summaryrefslogtreecommitdiff
path: root/spec/ruby/core/kernel/yield_self_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/kernel/yield_self_spec.rb')
-rw-r--r--spec/ruby/core/kernel/yield_self_spec.rb6
1 files changed, 2 insertions, 4 deletions
diff --git a/spec/ruby/core/kernel/yield_self_spec.rb b/spec/ruby/core/kernel/yield_self_spec.rb
index affedae144..e311dcee47 100644
--- a/spec/ruby/core/kernel/yield_self_spec.rb
+++ b/spec/ruby/core/kernel/yield_self_spec.rb
@@ -1,8 +1,6 @@
require_relative '../../spec_helper'
require_relative 'shared/then'
-ruby_version_is "2.5" do
- describe "Kernel#yield_self" do
- it_behaves_like :kernel_then, :yield_self
- end
+describe "Kernel#yield_self" do
+ it_behaves_like :kernel_then, :yield_self
end
ary='file diffstat' width='100%'> -rw-r--r--NEWS638
-rw-r--r--README26
-rw-r--r--README.EXT227
-rw-r--r--README.EXT.ja141
-rw-r--r--README.ja23
-rw-r--r--array.c2247
-rw-r--r--bcc32/Makefile.sub564
-rw-r--r--bcc32/README.bcc3226
-rwxr-xr-x[-rw-r--r--]bcc32/configure.bat132
-rwxr-xr-x[-rw-r--r--]bcc32/mkexports.rb2
-rw-r--r--bcc32/setup.mak104
-rw-r--r--bignum.c865
-rwxr-xr-xbin/erb156
-rw-r--r--bin/irb4
-rwxr-xr-xbin/ri49
-rw-r--r--class.c222
-rw-r--r--common.mk468
-rw-r--r--compar.c94
-rw-r--r--config.guess269
-rw-r--r--config.sub104
-rw-r--r--configure.in784
-rw-r--r--cygwin/GNUmakefile.in17
-rw-r--r--defines.h127
-rw-r--r--dir.c1829
-rw-r--r--distruby.rb59
-rwxr-xr-x[-rw-r--r--]djgpp/configure.bat0
-rw-r--r--dln.c217
-rw-r--r--dmydln.c2
-rw-r--r--doc/NEWS-1.8.0 (renamed from doc/NEWS)0
-rw-r--r--doc/irb/irb.rd.ja8
-rw-r--r--enum.c1609
-rw-r--r--enumerator.c450
-rw-r--r--env.h6
-rw-r--r--error.c428
-rw-r--r--eval.c5691
-rw-r--r--ext/.document11
-rw-r--r--ext/Setup1
-rw-r--r--ext/Setup.atheos1
-rw-r--r--ext/Setup.dj1
-rw-r--r--ext/Setup.emx1
-rw-r--r--ext/Setup.nt1
-rw-r--r--ext/Setup.x681
-rw-r--r--ext/Win32API/MANIFEST8
-rw-r--r--ext/Win32API/Win32API.c13
-rw-r--r--ext/Win32API/extconf.rb1
-rw-r--r--ext/Win32API/lib/win32/registry.rb2
-rw-r--r--ext/Win32API/lib/win32/resolv.rb6
-rw-r--r--ext/bigdecimal/MANIFEST18
-rw-r--r--ext/bigdecimal/bigdecimal.c863
-rw-r--r--ext/bigdecimal/bigdecimal.h12
-rw-r--r--ext/bigdecimal/bigdecimal_en.html9
-rw-r--r--ext/bigdecimal/bigdecimal_ja.html7
-rw-r--r--ext/bigdecimal/extconf.rb8
-rw-r--r--ext/bigdecimal/lib/bigdecimal/jacobian.rb26
-rw-r--r--ext/bigdecimal/lib/bigdecimal/ludcmp.rb9
-rw-r--r--ext/bigdecimal/lib/bigdecimal/math.rb45
-rw-r--r--ext/bigdecimal/lib/bigdecimal/newton.rb36
-rw-r--r--ext/bigdecimal/lib/bigdecimal/nlsolve.rb38
-rw-r--r--ext/bigdecimal/lib/bigdecimal/util.rb31
-rw-r--r--ext/bigdecimal/sample/linear.rb2
-rw-r--r--ext/bigdecimal/sample/nlsolve.rb2
-rw-r--r--ext/curses/MANIFEST9
-rw-r--r--ext/curses/curses.c132
-rw-r--r--ext/curses/extconf.rb4
-rw-r--r--ext/curses/view.rb2
-rw-r--r--ext/dbm/MANIFEST5
-rw-r--r--ext/dbm/dbm.c165
-rw-r--r--ext/dbm/extconf.rb60
-rw-r--r--ext/dbm/testdbm.rb593
-rw-r--r--ext/digest/MANIFEST11
-rw-r--r--ext/digest/bubblebabble/.cvsignore3
-rw-r--r--ext/digest/bubblebabble/bubblebabble.c142
-rw-r--r--ext/digest/bubblebabble/depend3
-rw-r--r--ext/digest/bubblebabble/extconf.rb6
-rw-r--r--ext/digest/defs.h8
-rw-r--r--ext/digest/digest.c702
-rw-r--r--ext/digest/digest.h26
-rw-r--r--ext/digest/digest.txt113
-rw-r--r--ext/digest/digest.txt.ja111
-rw-r--r--ext/digest/extconf.rb4
-rw-r--r--ext/digest/lib/digest.rb50
-rw-r--r--ext/digest/lib/md5.rb17
-rw-r--r--ext/digest/lib/sha1.rb17
-rw-r--r--ext/digest/md5/MANIFEST8
-rw-r--r--ext/digest/md5/extconf.rb6
-rw-r--r--ext/digest/md5/md5.c26
-rw-r--r--ext/digest/md5/md5.h9
-rw-r--r--ext/digest/md5/md5init.c23
-rw-r--r--ext/digest/md5/md5ossl.c23
-rw-r--r--ext/digest/md5/md5ossl.h6
-rw-r--r--ext/digest/rmd160/MANIFEST9
-rw-r--r--ext/digest/rmd160/depend2
-rw-r--r--ext/digest/rmd160/extconf.rb8
-rw-r--r--ext/digest/rmd160/rmd160.c9
-rw-r--r--ext/digest/rmd160/rmd160.h16
-rw-r--r--ext/digest/rmd160/rmd160hl.c96
-rw-r--r--ext/digest/rmd160/rmd160init.c26
-rw-r--r--ext/digest/rmd160/rmd160ossl.c43
-rw-r--r--ext/digest/rmd160/rmd160ossl.h5
-rw-r--r--ext/digest/sha1/MANIFEST9
-rw-r--r--ext/digest/sha1/depend2
-rw-r--r--ext/digest/sha1/extconf.rb7
-rw-r--r--ext/digest/sha1/sha1.c22
-rw-r--r--ext/digest/sha1/sha1.h17
-rw-r--r--ext/digest/sha1/sha1hl.c102
-rw-r--r--ext/digest/sha1/sha1init.c30
-rw-r--r--ext/digest/sha1/sha1ossl.c43
-rw-r--r--ext/digest/sha1/sha1ossl.h8
-rw-r--r--ext/digest/sha2/MANIFEST7
-rw-r--r--ext/digest/sha2/depend2
-rw-r--r--ext/digest/sha2/extconf.rb14
-rw-r--r--ext/digest/sha2/lib/sha2.rb73
-rw-r--r--ext/digest/sha2/sha2.c26
-rw-r--r--ext/digest/sha2/sha2.h36
-rw-r--r--ext/digest/sha2/sha2hl.c252
-rw-r--r--ext/digest/sha2/sha2init.c23
-rw-r--r--ext/digest/test.sh5
-rw-r--r--ext/dl/MANIFEST31
-rw-r--r--ext/dl/dl.c38
-rw-r--r--ext/dl/handle.c10
-rw-r--r--ext/dl/lib/dl/import.rb44
-rw-r--r--ext/dl/lib/dl/struct.rb9
-rw-r--r--ext/dl/lib/dl/types.rb262
-rw-r--r--ext/dl/lib/dl/win32.rb2
-rw-r--r--ext/dl/mkcallback.rb3
-rw-r--r--ext/dl/ptr.c145
-rw-r--r--ext/dl/sym.c13
-rw-r--r--ext/dl/test/test.rb13
-rw-r--r--ext/enumerator/.cvsignore2
-rw-r--r--ext/enumerator/MANIFEST3
-rw-r--r--ext/enumerator/enumerator.c201
-rw-r--r--ext/enumerator/enumerator.txt102
-rw-r--r--ext/etc/MANIFEST6
-rw-r--r--ext/etc/etc.c171
-rw-r--r--ext/etc/extconf.rb27
-rw-r--r--ext/extmk.rb479
-rw-r--r--ext/fcntl/MANIFEST3
-rw-r--r--ext/fcntl/extconf.rb2
-rw-r--r--ext/fcntl/fcntl.c75
-rw-r--r--ext/gdbm/MANIFEST6
-rw-r--r--ext/gdbm/gdbm.c612
-rw-r--r--ext/gdbm/testgdbm.rb663
-rw-r--r--ext/iconv/.cvsignore2
-rw-r--r--ext/iconv/MANIFEST5
-rw-r--r--ext/iconv/charset_alias.rb94
-rw-r--r--ext/iconv/extconf.rb44
-rw-r--r--ext/iconv/iconv.c489
-rw-r--r--ext/io/wait/MANIFEST4
-rw-r--r--ext/io/wait/extconf.rb7
-rw-r--r--ext/io/wait/lib/nonblock.rb2
-rw-r--r--ext/io/wait/wait.c30
-rw-r--r--ext/nkf/MANIFEST7
-rw-r--r--ext/nkf/depend2
-rw-r--r--ext/nkf/lib/kconv.rb336
-rw-r--r--ext/nkf/nkf-utf8/config.h88
-rw-r--r--ext/nkf/nkf-utf8/nkf.c6040
-rw-r--r--ext/nkf/nkf-utf8/utf8tbl.c8500
-rw-r--r--ext/nkf/nkf-utf8/utf8tbl.h34
-rw-r--r--ext/nkf/nkf.c554
-rw-r--r--ext/nkf/nkf1.7/nkf.c1900
-rw-r--r--ext/nkf/test.rb318
-rw-r--r--ext/openssl/.cvsignore1
-rw-r--r--ext/openssl/MANIFEST60
-rw-r--r--ext/openssl/extconf.rb96
-rw-r--r--ext/openssl/lib/net/ftptls.rb10
-rw-r--r--ext/openssl/lib/net/https.rb188
-rw-r--r--ext/openssl/lib/net/protocols.rb56
-rw-r--r--ext/openssl/lib/net/telnets.rb5
-rw-r--r--ext/openssl/lib/openssl.rb1
-rw-r--r--ext/openssl/lib/openssl/buffering.rb85
-rw-r--r--ext/openssl/lib/openssl/cipher.rb65
-rw-r--r--ext/openssl/lib/openssl/digest.rb51
-rw-r--r--ext/openssl/lib/openssl/pkcs7.rb25
-rw-r--r--ext/openssl/lib/openssl/ssl.rb101
-rw-r--r--ext/openssl/lib/openssl/x509.rb104
-rw-r--r--ext/openssl/openssl_missing.c44
-rw-r--r--ext/openssl/openssl_missing.h96
-rw-r--r--ext/openssl/ossl.c72
-rw-r--r--ext/openssl/ossl.h49
-rw-r--r--ext/openssl/ossl_asn1.c142
-rw-r--r--ext/openssl/ossl_asn1.h5
-rw-r--r--ext/openssl/ossl_bio.c26
-rw-r--r--ext/openssl/ossl_bn.c189
-rw-r--r--ext/openssl/ossl_bn.h5
-rw-r--r--ext/openssl/ossl_cipher.c437
-rw-r--r--ext/openssl/ossl_cipher.h1
-rw-r--r--ext/openssl/ossl_config.c94
-rw-r--r--ext/openssl/ossl_digest.c208
-rw-r--r--ext/openssl/ossl_digest.h1
-rw-r--r--ext/openssl/ossl_engine.c90
-rw-r--r--ext/openssl/ossl_hmac.c84
-rw-r--r--ext/openssl/ossl_ns_spki.c41
-rw-r--r--ext/openssl/ossl_ocsp.c56
-rw-r--r--ext/openssl/ossl_pkcs12.c210
-rw-r--r--ext/openssl/ossl_pkcs12.h15
-rw-r--r--ext/openssl/ossl_pkcs5.c96
-rw-r--r--ext/openssl/ossl_pkcs5.h6
-rw-r--r--ext/openssl/ossl_pkcs7.c243
-rw-r--r--ext/openssl/ossl_pkcs7.h4
-rw-r--r--ext/openssl/ossl_pkey.c68
-rw-r--r--ext/openssl/ossl_pkey.h36
-rw-r--r--ext/openssl/ossl_pkey_dh.c214
-rw-r--r--ext/openssl/ossl_pkey_dsa.c158
-rw-r--r--ext/openssl/ossl_pkey_ec.c1582
-rw-r--r--ext/openssl/ossl_pkey_rsa.c234
-rw-r--r--ext/openssl/ossl_rand.c92
-rw-r--r--ext/openssl/ossl_ssl.c937
-rw-r--r--ext/openssl/ossl_ssl.h15
-rw-r--r--ext/openssl/ossl_ssl_session.c298
-rw-r--r--ext/openssl/ossl_x509attr.c43
-rw-r--r--ext/openssl/ossl_x509cert.c124
-rw-r--r--ext/openssl/ossl_x509crl.c28
-rw-r--r--ext/openssl/ossl_x509ext.c55
-rw-r--r--ext/openssl/ossl_x509name.c185
-rw-r--r--ext/openssl/ossl_x509req.c14
-rw-r--r--ext/openssl/ossl_x509revoked.c12
-rw-r--r--ext/openssl/ossl_x509store.c97
-rw-r--r--ext/openssl/ruby_missing.h27
-rw-r--r--ext/pty/MANIFEST12
-rw-r--r--ext/pty/expect_sample.rb15
-rw-r--r--ext/pty/lib/expect.rb2
-rw-r--r--ext/pty/pty.c161
-rw-r--r--ext/purelib.rb10
-rw-r--r--ext/racc/cparse/MANIFEST4
-rw-r--r--ext/racc/cparse/cparse.c218
-rw-r--r--ext/readline/MANIFEST6
-rw-r--r--ext/readline/extconf.rb73
-rw-r--r--ext/readline/readline.c352
-rw-r--r--ext/sdbm/MANIFEST7
-rw-r--r--ext/sdbm/_sdbm.c4
-rw-r--r--ext/sdbm/init.c126
-rw-r--r--ext/sdbm/testsdbm.rb556
-rw-r--r--ext/socket/MANIFEST8
-rw-r--r--ext/socket/addrinfo.h5
-rw-r--r--ext/socket/extconf.rb324
-rw-r--r--ext/socket/getaddrinfo.c10
-rw-r--r--ext/socket/getnameinfo.c2
-rw-r--r--ext/socket/socket.c2147
-rw-r--r--ext/stringio/MANIFEST4
-rw-r--r--ext/stringio/extconf.rb2
-rw-r--r--ext/stringio/stringio.c560
-rw-r--r--ext/strscan/MANIFEST4
-rw-r--r--ext/strscan/strscan.c887
-rw-r--r--ext/syck/MANIFEST15
-rw-r--r--ext/syck/bytecode.c361
-rw-r--r--ext/syck/depend12
-rw-r--r--ext/syck/emitter.c1074
-rw-r--r--ext/syck/gram.c1210
-rw-r--r--ext/syck/gram.h24
-rw-r--r--ext/syck/handler.c20
-rw-r--r--ext/syck/implicit.c1466
-rw-r--r--ext/syck/node.c104
-rw-r--r--ext/syck/rubyext.c2167
-rw-r--r--ext/syck/syck.c33
-rw-r--r--ext/syck/syck.h120
-rw-r--r--ext/syck/token.c1577
-rw-r--r--ext/syck/yaml2byte.c20
-rw-r--r--ext/syslog/MANIFEST6
-rw-r--r--ext/syslog/syslog.c5
-rw-r--r--ext/syslog/syslog.txt5
-rw-r--r--ext/tcltklib/MANIFEST19
-rw-r--r--ext/tcltklib/MANUAL.eng264
-rw-r--r--ext/tcltklib/MANUAL.euc408
-rw-r--r--ext/tcltklib/README.1st41
-rw-r--r--ext/tcltklib/depend2
-rw-r--r--ext/tcltklib/extconf.rb58
-rw-r--r--ext/tcltklib/lib/tcltk.rb367
-rw-r--r--ext/tcltklib/sample/sample1.rb634
-rw-r--r--ext/tcltklib/sample/sample2.rb449
-rw-r--r--ext/tcltklib/stubs.c97
-rw-r--r--ext/tcltklib/tcltklib.c2396
-rw-r--r--ext/thread/extconf.rb9
-rw-r--r--ext/thread/lib/thread.rb5
-rw-r--r--ext/thread/thread.c1182
-rw-r--r--ext/tk/ChangeLog.tkextlib924
-rw-r--r--ext/tk/MANIFEST202
-rw-r--r--ext/tk/MANUAL_tcltklib.eng469
-rw-r--r--ext/tk/MANUAL_tcltklib.eucj579
-rw-r--r--ext/tk/README.1st26
-rw-r--r--ext/tk/README.ActiveTcl49
-rw-r--r--ext/tk/README.fork34
-rw-r--r--ext/tk/README.macosx-aqua67
-rw-r--r--ext/tk/README.tcltklib85
-rw-r--r--ext/tk/depend3
-rw-r--r--ext/tk/extconf.rb412
-rw-r--r--ext/tk/lib/README11
-rw-r--r--ext/tk/lib/multi-tk.rb2632
-rw-r--r--ext/tk/lib/remote-tk.rb526
-rw-r--r--ext/tk/lib/tcltk.rb367
-rw-r--r--ext/tk/lib/tk.rb8496
-rw-r--r--ext/tk/lib/tk/after.rb6
-rw-r--r--ext/tk/lib/tk/autoload.rb414
-rw-r--r--ext/tk/lib/tk/bgerror.rb29
-rw-r--r--ext/tk/lib/tk/bindtag.rb138
-rw-r--r--ext/tk/lib/tk/button.rb30
-rw-r--r--ext/tk/lib/tk/canvas.rb789
-rw-r--r--ext/tk/lib/tk/canvastag.rb434
-rw-r--r--ext/tk/lib/tk/checkbutton.rb30
-rw-r--r--ext/tk/lib/tk/clipboard.rb75
-rw-r--r--ext/tk/lib/tk/clock.rb71
-rw-r--r--ext/tk/lib/tk/composite.rb458
-rw-r--r--ext/tk/lib/tk/console.rb52
-rw-r--r--ext/tk/lib/tk/dialog.rb326
-rw-r--r--ext/tk/lib/tk/encodedstr.rb187
-rw-r--r--ext/tk/lib/tk/entry.rb119
-rw-r--r--ext/tk/lib/tk/event.rb542
-rw-r--r--ext/tk/lib/tk/font.rb2344
-rw-r--r--ext/tk/lib/tk/frame.rb131
-rw-r--r--ext/tk/lib/tk/grid.rb265
-rw-r--r--ext/tk/lib/tk/image.rb275
-rw-r--r--ext/tk/lib/tk/itemconfig.rb1215
-rw-r--r--ext/tk/lib/tk/itemfont.rb327
-rw-r--r--ext/tk/lib/tk/kinput.rb71
-rw-r--r--ext/tk/lib/tk/label.rb21
-rw-r--r--ext/tk/lib/tk/labelframe.rb29
-rw-r--r--ext/tk/lib/tk/listbox.rb282
-rw-r--r--ext/tk/lib/tk/macpkg.rb78
-rw-r--r--ext/tk/lib/tk/menu.rb681
-rw-r--r--ext/tk/lib/tk/menubar.rb131
-rw-r--r--ext/tk/lib/tk/menuspec.rb275
-rw-r--r--ext/tk/lib/tk/message.rb22
-rw-r--r--ext/tk/lib/tk/mngfocus.rb33
-rw-r--r--ext/tk/lib/tk/msgcat.rb296
-rw-r--r--ext/tk/lib/tk/namespace.rb551
-rw-r--r--ext/tk/lib/tk/optiondb.rb377
-rw-r--r--ext/tk/lib/tk/optionobj.rb212
-rw-r--r--ext/tk/lib/tk/pack.rb107
-rw-r--r--ext/tk/lib/tk/package.rb143
-rw-r--r--ext/tk/lib/tk/palette.rb55
-rw-r--r--ext/tk/lib/tk/panedwindow.rb258
-rw-r--r--ext/tk/lib/tk/place.rb128
-rw-r--r--ext/tk/lib/tk/radiobutton.rb71
-rw-r--r--ext/tk/lib/tk/root.rb95
-rw-r--r--ext/tk/lib/tk/scale.rb111
-rw-r--r--ext/tk/lib/tk/scrollable.rb82
-rw-r--r--ext/tk/lib/tk/scrollbar.rb177
-rw-r--r--ext/tk/lib/tk/scrollbox.rb39
-rw-r--r--ext/tk/lib/tk/selection.rb86
-rw-r--r--ext/tk/lib/tk/spinbox.rb119
-rw-r--r--ext/tk/lib/tk/tagfont.rb43
-rw-r--r--ext/tk/lib/tk/text.rb1596
-rw-r--r--ext/tk/lib/tk/textimage.rb88
-rw-r--r--ext/tk/lib/tk/textmark.rb204
-rw-r--r--ext/tk/lib/tk/texttag.rb318
-rw-r--r--ext/tk/lib/tk/textwindow.rb154
-rw-r--r--ext/tk/lib/tk/timer.rb669
-rw-r--r--ext/tk/lib/tk/toplevel.rb262
-rw-r--r--ext/tk/lib/tk/ttk_selector.rb76
-rw-r--r--ext/tk/lib/tk/txtwin_abst.rb39
-rw-r--r--ext/tk/lib/tk/validation.rb397
-rw-r--r--ext/tk/lib/tk/variable.rb1765
-rw-r--r--ext/tk/lib/tk/virtevent.rb139
-rw-r--r--ext/tk/lib/tk/winfo.rb392
-rw-r--r--ext/tk/lib/tk/winpkg.rb153
-rw-r--r--ext/tk/lib/tk/wm.rb552
-rw-r--r--ext/tk/lib/tk/xim.rb122
-rw-r--r--ext/tk/lib/tkafter.rb414
-rw-r--r--ext/tk/lib/tkbgerror.rb29
-rw-r--r--ext/tk/lib/tkcanvas.rb994
-rw-r--r--ext/tk/lib/tkclass.rb8
-rw-r--r--ext/tk/lib/tkconsole.rb28
-rw-r--r--ext/tk/lib/tkdialog.rb275
-rw-r--r--ext/tk/lib/tkentry.rb292
-rw-r--r--ext/tk/lib/tkextlib/ICONS.rb13
-rw-r--r--ext/tk/lib/tkextlib/ICONS/icons.rb129
-rw-r--r--ext/tk/lib/tkextlib/ICONS/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/SUPPORT_STATUS196
-rw-r--r--ext/tk/lib/tkextlib/blt.rb187
-rw-r--r--ext/tk/lib/tkextlib/blt/barchart.rb79
-rw-r--r--ext/tk/lib/tkextlib/blt/bitmap.rb112
-rw-r--r--ext/tk/lib/tkextlib/blt/busy.rb82
-rw-r--r--ext/tk/lib/tkextlib/blt/component.rb2145
-rw-r--r--ext/tk/lib/tkextlib/blt/container.rb28
-rw-r--r--ext/tk/lib/tkextlib/blt/cutbuffer.rb23
-rw-r--r--ext/tk/lib/tkextlib/blt/dragdrop.rb268
-rw-r--r--ext/tk/lib/tkextlib/blt/eps.rb32
-rw-r--r--ext/tk/lib/tkextlib/blt/graph.rb67
-rw-r--r--ext/tk/lib/tkextlib/blt/htext.rb111
-rw-r--r--ext/tk/lib/tkextlib/blt/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/blt/spline.rb23
-rw-r--r--ext/tk/lib/tkextlib/blt/stripchart.rb74
-rw-r--r--ext/tk/lib/tkextlib/blt/table.rb399
-rw-r--r--ext/tk/lib/tkextlib/blt/tabnotebook.rb21
-rw-r--r--ext/tk/lib/tkextlib/blt/tabset.rb430
-rw-r--r--ext/tk/lib/tkextlib/blt/ted.rb65
-rw-r--r--ext/tk/lib/tkextlib/blt/tile.rb21
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/button.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/checkbutton.rb17
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/frame.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/label.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/radiobutton.rb17
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/scrollbar.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/toplevel.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/tree.rb1058
-rw-r--r--ext/tk/lib/tkextlib/blt/treeview.rb1272
-rw-r--r--ext/tk/lib/tkextlib/blt/unix_dnd.rb135
-rw-r--r--ext/tk/lib/tkextlib/blt/vector.rb256
-rw-r--r--ext/tk/lib/tkextlib/blt/watch.rb175
-rw-r--r--ext/tk/lib/tkextlib/blt/win_printer.rb61
-rw-r--r--ext/tk/lib/tkextlib/blt/winop.rb107
-rw-r--r--ext/tk/lib/tkextlib/bwidget.rb151
-rw-r--r--ext/tk/lib/tkextlib/bwidget/arrowbutton.rb21
-rw-r--r--ext/tk/lib/tkextlib/bwidget/bitmap.rb21
-rw-r--r--ext/tk/lib/tkextlib/bwidget/button.rb31
-rw-r--r--ext/tk/lib/tkextlib/bwidget/buttonbox.rb90
-rw-r--r--ext/tk/lib/tkextlib/bwidget/combobox.rb51
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dialog.rb182
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dragsite.rb31
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dropsite.rb39
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dynamichelp.rb63
-rw-r--r--ext/tk/lib/tkextlib/bwidget/entry.rb43
-rw-r--r--ext/tk/lib/tkextlib/bwidget/label.rb41
-rw-r--r--ext/tk/lib/tkextlib/bwidget/labelentry.rb80
-rw-r--r--ext/tk/lib/tkextlib/bwidget/labelframe.rb52
-rw-r--r--ext/tk/lib/tkextlib/bwidget/listbox.rb358
-rw-r--r--ext/tk/lib/tkextlib/bwidget/mainframe.rb128
-rw-r--r--ext/tk/lib/tkextlib/bwidget/messagedlg.rb192
-rw-r--r--ext/tk/lib/tkextlib/bwidget/notebook.rb166
-rw-r--r--ext/tk/lib/tkextlib/bwidget/pagesmanager.rb73
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panedwindow.rb37
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panelframe.rb57
-rw-r--r--ext/tk/lib/tkextlib/bwidget/passwddlg.rb44
-rw-r--r--ext/tk/lib/tkextlib/bwidget/progressbar.rb20
-rw-r--r--ext/tk/lib/tkextlib/bwidget/progressdlg.rb58
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrollableframe.rb40
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb38
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrollview.rb25
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectcolor.rb73
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectfont.rb86
-rw-r--r--ext/tk/lib/tkextlib/bwidget/separator.rb20
-rw-r--r--ext/tk/lib/tkextlib/bwidget/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/spinbox.rb98
-rw-r--r--ext/tk/lib/tkextlib/bwidget/statusbar.rb52
-rw-r--r--ext/tk/lib/tkextlib/bwidget/titleframe.rb33
-rw-r--r--ext/tk/lib/tkextlib/bwidget/tree.rb453
-rw-r--r--ext/tk/lib/tkextlib/bwidget/widget.rb129
-rw-r--r--ext/tk/lib/tkextlib/itcl.rb13
-rw-r--r--ext/tk/lib/tkextlib/itcl/incr_tcl.rb178
-rw-r--r--ext/tk/lib/tkextlib/itcl/setup.rb13
-rw-r--r--ext/tk/lib/tkextlib/itk.rb13
-rw-r--r--ext/tk/lib/tkextlib/itk/incr_tk.rb446
-rw-r--r--ext/tk/lib/tkextlib/itk/setup.rb13
-rw-r--r--ext/tk/lib/tkextlib/iwidgets.rb94
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/buttonbox.rb120
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/calendar.rb125
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb53
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb38
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/checkbox.rb129
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/combobox.rb104
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/dateentry.rb20
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/datefield.rb58
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/dialog.rb20
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/dialogshell.rb120
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb50
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/entryfield.rb185
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/extbutton.rb40
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb46
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb33
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/feedback.rb35
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb46
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb33
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/finddialog.rb42
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/hierarchy.rb365
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb50
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/labeledframe.rb39
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb45
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/mainwindow.rb67
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/menubar.rb211
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/messagebox.rb92
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/messagedialog.rb20
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/notebook.rb174
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/optionmenu.rb92
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/panedwindow.rb133
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/promptdialog.rb131
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/pushbutton.rb35
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/radiobox.rb120
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scopedobject.rb24
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb353
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb59
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb58
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb207
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb564
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb20
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/selectionbox.rb102
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb92
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/shell.rb38
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spindate.rb48
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spinint.rb30
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spinner.rb169
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spintime.rb48
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb180
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/tabset.rb144
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/timeentry.rb25
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/timefield.rb58
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/toolbar.rb112
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/watch.rb56
-rwxr-xr-xext/tk/lib/tkextlib/pkg_checker.rb184
-rw-r--r--ext/tk/lib/tkextlib/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tcllib.rb90
-rw-r--r--ext/tk/lib/tkextlib/tcllib/README135
-rw-r--r--ext/tk/lib/tkextlib/tcllib/autoscroll.rb158
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ctext.rb160
-rw-r--r--ext/tk/lib/tkextlib/tcllib/cursor.rb97
-rw-r--r--ext/tk/lib/tkextlib/tcllib/datefield.rb57
-rw-r--r--ext/tk/lib/tkextlib/tcllib/dialog.rb84
-rw-r--r--ext/tk/lib/tkextlib/tcllib/getstring.rb134
-rw-r--r--ext/tk/lib/tkextlib/tcllib/history.rb73
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ico.rb116
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ip_entry.rb66
-rw-r--r--ext/tk/lib/tkextlib/tcllib/panelframe.rb72
-rw-r--r--ext/tk/lib/tkextlib/tcllib/plotchart.rb886
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ruler.rb65
-rw-r--r--ext/tk/lib/tkextlib/tcllib/screenruler.rb68
-rw-r--r--ext/tk/lib/tkextlib/tcllib/scrollwin.rb61
-rw-r--r--ext/tk/lib/tkextlib/tcllib/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tcllib/style.rb61
-rw-r--r--ext/tk/lib/tkextlib/tcllib/superframe.rb51
-rw-r--r--ext/tk/lib/tkextlib/tcllib/swaplist.rb150
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tablelist.rb27
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tablelist_core.rb782
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb25
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tkpiechart.rb314
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tooltip.rb95
-rw-r--r--ext/tk/lib/tkextlib/tcllib/widget.rb48
-rw-r--r--ext/tk/lib/tkextlib/tclx.rb13
-rw-r--r--ext/tk/lib/tkextlib/tclx/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tclx/tclx.rb74
-rw-r--r--ext/tk/lib/tkextlib/tile.rb419
-rw-r--r--ext/tk/lib/tkextlib/tile/dialog.rb96
-rw-r--r--ext/tk/lib/tkextlib/tile/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tile/sizegrip.rb29
-rw-r--r--ext/tk/lib/tkextlib/tile/style.rb316
-rw-r--r--ext/tk/lib/tkextlib/tile/tbutton.rb33
-rw-r--r--ext/tk/lib/tkextlib/tile/tcheckbutton.rb36
-rw-r--r--ext/tk/lib/tkextlib/tile/tcombobox.rb54
-rw-r--r--ext/tk/lib/tkextlib/tile/tentry.rb48
-rw-r--r--ext/tk/lib/tkextlib/tile/tframe.rb33
-rw-r--r--ext/tk/lib/tkextlib/tile/tlabel.rb33
-rw-r--r--ext/tk/lib/tkextlib/tile/tlabelframe.rb36
-rw-r--r--ext/tk/lib/tkextlib/tile/tmenubutton.rb36
-rw-r--r--ext/tk/lib/tkextlib/tile/tnotebook.rb139
-rw-r--r--ext/tk/lib/tkextlib/tile/tpaned.rb231
-rw-r--r--ext/tk/lib/tkextlib/tile/tprogressbar.rb56
-rw-r--r--ext/tk/lib/tkextlib/tile/tradiobutton.rb36
-rw-r--r--ext/tk/lib/tkextlib/tile/treeview.rb1238
-rw-r--r--ext/tk/lib/tkextlib/tile/tscale.rb53
-rw-r--r--ext/tk/lib/tkextlib/tile/tscrollbar.rb54
-rw-r--r--ext/tk/lib/tkextlib/tile/tseparator.rb33
-rw-r--r--ext/tk/lib/tkextlib/tile/tsquare.rb30
-rw-r--r--ext/tk/lib/tkextlib/tkDND.rb18
-rw-r--r--ext/tk/lib/tkextlib/tkDND/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tkDND/shape.rb125
-rw-r--r--ext/tk/lib/tkextlib/tkDND/tkdnd.rb182
-rw-r--r--ext/tk/lib/tkextlib/tkHTML.rb13
-rw-r--r--ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb453
-rw-r--r--ext/tk/lib/tkextlib/tkHTML/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tkimg.rb36
-rw-r--r--ext/tk/lib/tkextlib/tkimg/README26
-rw-r--r--ext/tk/lib/tkextlib/tkimg/bmp.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/gif.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/ico.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/jpeg.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/pcx.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/pixmap.rb44
-rw-r--r--ext/tk/lib/tkextlib/tkimg/png.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/ppm.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/ps.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tkimg/sgi.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/sun.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/tga.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/tiff.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/window.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/xbm.rb33
-rw-r--r--ext/tk/lib/tkextlib/tkimg/xpm.rb33
-rw-r--r--ext/tk/lib/tkextlib/tktable.rb14
-rw-r--r--ext/tk/lib/tkextlib/tktable/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tktable/tktable.rb957
-rw-r--r--ext/tk/lib/tkextlib/tktrans.rb14
-rw-r--r--ext/tk/lib/tkextlib/tktrans/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/tktrans/tktrans.rb64
-rw-r--r--ext/tk/lib/tkextlib/treectrl.rb13
-rw-r--r--ext/tk/lib/tkextlib/treectrl/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/treectrl/tktreectrl.rb2461
-rw-r--r--ext/tk/lib/tkextlib/trofs.rb13
-rw-r--r--ext/tk/lib/tkextlib/trofs/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/trofs/trofs.rb51
-rw-r--r--ext/tk/lib/tkextlib/version.rb6
-rw-r--r--ext/tk/lib/tkextlib/vu.rb48
-rw-r--r--ext/tk/lib/tkextlib/vu/bargraph.rb61
-rw-r--r--ext/tk/lib/tkextlib/vu/charts.rb53
-rw-r--r--ext/tk/lib/tkextlib/vu/dial.rb102
-rw-r--r--ext/tk/lib/tkextlib/vu/pie.rb282
-rw-r--r--ext/tk/lib/tkextlib/vu/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/vu/spinbox.rb22
-rw-r--r--ext/tk/lib/tkextlib/winico.rb14
-rw-r--r--ext/tk/lib/tkextlib/winico/setup.rb8
-rw-r--r--ext/tk/lib/tkextlib/winico/winico.rb224
-rw-r--r--ext/tk/lib/tkfont.rb1390
-rw-r--r--ext/tk/lib/tkmacpkg.rb56
-rw-r--r--ext/tk/lib/tkmenubar.rb143
-rw-r--r--ext/tk/lib/tkmngfocus.rb33
-rw-r--r--ext/tk/lib/tkpalette.rb54
-rw-r--r--ext/tk/lib/tkscrollbox.rb31
-rw-r--r--ext/tk/lib/tktext.rb1301
-rw-r--r--ext/tk/lib/tkvirtevent.rb85
-rw-r--r--ext/tk/lib/tkwinpkg.rb84
-rw-r--r--ext/tk/old-README.tcltklib.eucj (renamed from ext/tcltklib/README.euc)0
-rw-r--r--ext/tk/sample/24hr_clock.rb286
-rw-r--r--ext/tk/sample/binding_sample.rb87
-rw-r--r--ext/tk/sample/bindtag_sample.rb127
-rw-r--r--ext/tk/sample/binstr_usage.rb45
-rw-r--r--ext/tk/sample/btn_with_frame.rb20
-rw-r--r--ext/tk/sample/cd_timer.rb81
-rw-r--r--ext/tk/sample/cmd_res_test.rb17
-rw-r--r--ext/tk/sample/cmd_resource5
-rw-r--r--ext/tk/sample/demos-en/README.1st18
-rw-r--r--ext/tk/sample/demos-en/README.tkencoding5
-rw-r--r--ext/tk/sample/demos-en/anilabel.rb174
-rw-r--r--ext/tk/sample/demos-en/aniwave.rb118
-rw-r--r--ext/tk/sample/demos-en/arrow.rb96
-rw-r--r--ext/tk/sample/demos-en/bind.rb51
-rw-r--r--ext/tk/sample/demos-en/bitmap.rb24
-rw-r--r--ext/tk/sample/demos-en/browse28
-rw-r--r--ext/tk/sample/demos-en/button.rb2
-rw-r--r--ext/tk/sample/demos-en/check.rb16
-rw-r--r--ext/tk/sample/demos-en/check2.rb109
-rw-r--r--ext/tk/sample/demos-en/clrpick.rb28
-rw-r--r--ext/tk/sample/demos-en/colors.rb18
-rw-r--r--ext/tk/sample/demos-en/combo.rb96
-rw-r--r--ext/tk/sample/demos-en/cscroll.rb38
-rw-r--r--ext/tk/sample/demos-en/ctext.rb77
-rw-r--r--ext/tk/sample/demos-en/dialog1.rb5
-rw-r--r--ext/tk/sample/demos-en/dialog2.rb9
-rw-r--r--ext/tk/sample/demos-en/entry1.rb12
-rw-r--r--ext/tk/sample/demos-en/entry2.rb8
-rw-r--r--ext/tk/sample/demos-en/entry3.rb116
-rw-r--r--ext/tk/sample/demos-en/filebox.rb29
-rw-r--r--ext/tk/sample/demos-en/floor.rb742
-rw-r--r--ext/tk/sample/demos-en/floor2.rb1722
-rw-r--r--ext/tk/sample/demos-en/form.rb8
-rw-r--r--ext/tk/sample/demos-en/goldberg.rb2006
-rw-r--r--ext/tk/sample/demos-en/hello6
-rw-r--r--ext/tk/sample/demos-en/hscale.rb29
-rw-r--r--ext/tk/sample/demos-en/icon.rb44
-rw-r--r--ext/tk/sample/demos-en/image1.rb17
-rw-r--r--ext/tk/sample/demos-en/image2.rb26
-rw-r--r--ext/tk/sample/demos-en/image3.rb44
-rw-r--r--ext/tk/sample/demos-en/images/earth.gifbin51709 -> 0 bytes-rw-r--r--ext/tk/sample/demos-en/images/earthris.gifbin6343 -> 0 bytes-rw-r--r--ext/tk/sample/demos-en/images/tcllogo.gifbin2341 -> 0 bytes-rw-r--r--ext/tk/sample/demos-en/images/teapot.ppm56
-rw-r--r--ext/tk/sample/demos-en/items.rb167
-rw-r--r--ext/tk/sample/demos-en/knightstour.rb271
-rw-r--r--ext/tk/sample/demos-en/label.rb19
-rw-r--r--ext/tk/sample/demos-en/labelframe.rb30
-rw-r--r--ext/tk/sample/demos-en/mclist.rb117
-rw-r--r--ext/tk/sample/demos-en/menu.rb75
-rw-r--r--ext/tk/sample/demos-en/menu84.rb89
-rw-r--r--ext/tk/sample/demos-en/menubu.rb14
-rw-r--r--ext/tk/sample/demos-en/msgbox.rb34
-rw-r--r--ext/tk/sample/demos-en/msgbox2.rb91
-rw-r--r--ext/tk/sample/demos-en/paned1.rb28
-rw-r--r--ext/tk/sample/demos-en/paned2.rb64
-rw-r--r--ext/tk/sample/demos-en/patch_1.1c193
-rw-r--r--ext/tk/sample/demos-en/pendulum.rb240
-rw-r--r--ext/tk/sample/demos-en/plot.rb36
-rw-r--r--ext/tk/sample/demos-en/puzzle.rb40
-rw-r--r--ext/tk/sample/demos-en/radio.rb12
-rw-r--r--ext/tk/sample/demos-en/radio2.rb39
-rw-r--r--ext/tk/sample/demos-en/radio3.rb117
-rw-r--r--ext/tk/sample/demos-en/rolodex-j323
-rw-r--r--ext/tk/sample/demos-en/ruler.rb64
-rw-r--r--ext/tk/sample/demos-en/sayings.rb14
-rw-r--r--ext/tk/sample/demos-en/search.rb125
-rw-r--r--ext/tk/sample/demos-en/spin.rb34
-rw-r--r--ext/tk/sample/demos-en/states.rb8
-rw-r--r--ext/tk/sample/demos-en/style.rb74
-rw-r--r--ext/tk/sample/demos-en/tcolor73
-rw-r--r--ext/tk/sample/demos-en/tcolor.bak513
-rw-r--r--ext/tk/sample/demos-en/text.rb26
-rw-r--r--ext/tk/sample/demos-en/textpeer.rb76
-rw-r--r--ext/tk/sample/demos-en/toolbar.rb130
-rw-r--r--ext/tk/sample/demos-en/tree.rb119
-rw-r--r--ext/tk/sample/demos-en/ttkbut.rb139
-rw-r--r--ext/tk/sample/demos-en/ttkmenu.rb85
-rw-r--r--ext/tk/sample/demos-en/ttknote.rb89
-rw-r--r--ext/tk/sample/demos-en/ttkpane.rb213
-rw-r--r--ext/tk/sample/demos-en/ttkprogress.rb66
-rw-r--r--ext/tk/sample/demos-en/twind.rb152
-rw-r--r--ext/tk/sample/demos-en/twind2.rb384
-rw-r--r--ext/tk/sample/demos-en/unicodeout.rb56
-rw-r--r--ext/tk/sample/demos-en/vscale.rb29
-rw-r--r--ext/tk/sample/demos-en/widget829
-rw-r--r--ext/tk/sample/demos-jp/README.1st20
-rw-r--r--ext/tk/sample/demos-jp/anilabel.rb177
-rw-r--r--ext/tk/sample/demos-jp/aniwave.rb120
-rw-r--r--ext/tk/sample/demos-jp/arrow.rb100
-rw-r--r--ext/tk/sample/demos-jp/bind.rb53
-rw-r--r--ext/tk/sample/demos-jp/bitmap.rb28
-rw-r--r--ext/tk/sample/demos-jp/browse28
-rw-r--r--ext/tk/sample/demos-jp/button.rb7
-rw-r--r--ext/tk/sample/demos-jp/check.rb22
-rw-r--r--ext/tk/sample/demos-jp/check2.rb110
-rw-r--r--ext/tk/sample/demos-jp/clrpick.rb30
-rw-r--r--ext/tk/sample/demos-jp/colors.rb22
-rw-r--r--ext/tk/sample/demos-jp/combo.rb98
-rw-r--r--ext/tk/sample/demos-jp/cscroll.rb40
-rw-r--r--ext/tk/sample/demos-jp/ctext.rb81
-rw-r--r--ext/tk/sample/demos-jp/dialog1.rb6
-rw-r--r--ext/tk/sample/demos-jp/dialog2.rb12
-rw-r--r--ext/tk/sample/demos-jp/entry1.rb16
-rw-r--r--ext/tk/sample/demos-jp/entry2.rb12
-rw-r--r--ext/tk/sample/demos-jp/entry3.rb117
-rw-r--r--ext/tk/sample/demos-jp/filebox.rb33
-rw-r--r--ext/tk/sample/demos-jp/floor.rb746
-rw-r--r--ext/tk/sample/demos-jp/floor2.rb1719
-rw-r--r--ext/tk/sample/demos-jp/form.rb12
-rw-r--r--ext/tk/sample/demos-jp/goldberg.rb2011
-rw-r--r--ext/tk/sample/demos-jp/hello1
-rw-r--r--ext/tk/sample/demos-jp/hscale.rb32
-rw-r--r--ext/tk/sample/demos-jp/icon.rb50
-rw-r--r--ext/tk/sample/demos-jp/image1.rb21
-rw-r--r--ext/tk/sample/demos-jp/image2.rb29
-rw-r--r--ext/tk/sample/demos-jp/image3.rb52
-rw-r--r--ext/tk/sample/demos-jp/images/earth.gifbin51709 -> 0 bytes-rw-r--r--ext/tk/sample/demos-jp/images/earthris.gifbin6343 -> 0 bytes-rw-r--r--ext/tk/sample/demos-jp/images/face.bmp173
-rw-r--r--ext/tk/sample/demos-jp/images/flagdown.bmp27
-rw-r--r--ext/tk/sample/demos-jp/images/flagup.bmp27
-rw-r--r--ext/tk/sample/demos-jp/images/gray25.bmp6
-rw-r--r--ext/tk/sample/demos-jp/images/grey.256
-rw-r--r--ext/tk/sample/demos-jp/images/grey.56
-rw-r--r--ext/tk/sample/demos-jp/images/letters.bmp27
-rw-r--r--ext/tk/sample/demos-jp/images/noletter.bmp27
-rw-r--r--ext/tk/sample/demos-jp/images/pattern.bmp6
-rw-r--r--ext/tk/sample/demos-jp/images/tcllogo.gifbin2341 -> 0 bytes-rw-r--r--ext/tk/sample/demos-jp/images/teapot.ppm56
-rw-r--r--ext/tk/sample/demos-jp/items.rb181
-rw-r--r--ext/tk/sample/demos-jp/ixset21
-rw-r--r--ext/tk/sample/demos-jp/knightstour.rb273
-rw-r--r--ext/tk/sample/demos-jp/label.rb23
-rw-r--r--ext/tk/sample/demos-jp/labelframe.rb34
-rw-r--r--ext/tk/sample/demos-jp/mclist.rb121
-rw-r--r--ext/tk/sample/demos-jp/menu.rb79
-rw-r--r--ext/tk/sample/demos-jp/menu84.rb89
-rw-r--r--ext/tk/sample/demos-jp/menu8x.rb106
-rw-r--r--ext/tk/sample/demos-jp/menubu.rb21
-rw-r--r--ext/tk/sample/demos-jp/msgbox.rb38
-rw-r--r--ext/tk/sample/demos-jp/msgbox2.rb90
-rw-r--r--ext/tk/sample/demos-jp/paned1.rb32
-rw-r--r--ext/tk/sample/demos-jp/paned2.rb70
-rw-r--r--ext/tk/sample/demos-jp/pendulum.rb242
-rw-r--r--ext/tk/sample/demos-jp/plot.rb46
-rw-r--r--ext/tk/sample/demos-jp/puzzle.rb44
-rw-r--r--ext/tk/sample/demos-jp/radio.rb16
-rw-r--r--ext/tk/sample/demos-jp/radio2.rb46
-rw-r--r--ext/tk/sample/demos-jp/radio3.rb119
-rw-r--r--ext/tk/sample/demos-jp/rolodex-j3
-rw-r--r--ext/tk/sample/demos-jp/ruler.rb68
-rw-r--r--ext/tk/sample/demos-jp/sayings.rb18
-rw-r--r--ext/tk/sample/demos-jp/search.rb127
-rw-r--r--ext/tk/sample/demos-jp/spin.rb40
-rw-r--r--ext/tk/sample/demos-jp/states.rb12
-rw-r--r--ext/tk/sample/demos-jp/style.rb87
-rw-r--r--ext/tk/sample/demos-jp/tcolor41
-rw-r--r--ext/tk/sample/demos-jp/text.rb30
-rw-r--r--ext/tk/sample/demos-jp/textpeer.rb82
-rw-r--r--ext/tk/sample/demos-jp/toolbar.rb136
-rw-r--r--ext/tk/sample/demos-jp/tree.rb120
-rw-r--r--ext/tk/sample/demos-jp/ttkbut.rb145
-rw-r--r--ext/tk/sample/demos-jp/ttkmenu.rb91
-rw-r--r--ext/tk/sample/demos-jp/ttknote.rb97
-rw-r--r--ext/tk/sample/demos-jp/ttkpane.rb216
-rw-r--r--ext/tk/sample/demos-jp/ttkprogress.rb71
-rw-r--r--ext/tk/sample/demos-jp/twind.rb162
-rw-r--r--ext/tk/sample/demos-jp/twind2.rb384
-rw-r--r--ext/tk/sample/demos-jp/unicodeout.rb62
-rw-r--r--ext/tk/sample/demos-jp/vscale.rb33
-rw-r--r--ext/tk/sample/demos-jp/widget959
-rw-r--r--ext/tk/sample/editable_listbox.rb69
-rw-r--r--ext/tk/sample/encstr_usage.rb30
-rw-r--r--ext/tk/sample/figmemo_sample.rb456
-rw-r--r--ext/tk/sample/images/earth.gifbin0 -> 51712 bytes-rw-r--r--ext/tk/sample/images/earthris.gifbin0 -> 6343 bytes-rw-r--r--ext/tk/sample/images/face.xbm (renamed from ext/tk/sample/demos-en/images/face.xbm)0
-rw-r--r--ext/tk/sample/images/flagdown.xbm (renamed from ext/tk/sample/demos-en/images/flagdown.xbm)0
-rw-r--r--ext/tk/sample/images/flagup.xbm (renamed from ext/tk/sample/demos-en/images/flagup.xbm)0
-rw-r--r--ext/tk/sample/images/gray25.xbm (renamed from ext/tk/sample/demos-en/images/gray25.xbm)0
-rw-r--r--ext/tk/sample/images/grey.25 (renamed from ext/tk/sample/demos-en/images/grey.25)0
-rw-r--r--ext/tk/sample/images/grey.5 (renamed from ext/tk/sample/demos-en/images/grey.5)0
-rw-r--r--ext/tk/sample/images/letters.xbm (renamed from ext/tk/sample/demos-en/images/letters.xbm)0
-rw-r--r--ext/tk/sample/images/noletter.xbm (renamed from ext/tk/sample/demos-en/images/noletter.xbm)0
-rw-r--r--ext/tk/sample/images/pattern.xbm (renamed from ext/tk/sample/demos-en/images/pattern.xbm)0
-rw-r--r--ext/tk/sample/images/tcllogo.gifbin0 -> 2341 bytes-rw-r--r--ext/tk/sample/images/teapot.ppm31
-rw-r--r--ext/tk/sample/irbtk.rb30
-rw-r--r--ext/tk/sample/irbtkw.rbw146
-rw-r--r--ext/tk/sample/iso2022-kr.txt2
-rw-r--r--ext/tk/sample/menubar1.rb51
-rw-r--r--ext/tk/sample/menubar2.rb56
-rw-r--r--ext/tk/sample/msgs_rb/README3
-rw-r--r--ext/tk/sample/msgs_rb/cs.msg84
-rw-r--r--ext/tk/sample/msgs_rb/de.msg88
-rw-r--r--ext/tk/sample/msgs_rb/el.msg98
-rw-r--r--ext/tk/sample/msgs_rb/en.msg83
-rw-r--r--ext/tk/sample/msgs_rb/en_gb.msg7
-rw-r--r--ext/tk/sample/msgs_rb/eo.msg87
-rw-r--r--ext/tk/sample/msgs_rb/es.msg84
-rw-r--r--ext/tk/sample/msgs_rb/fr.msg84
-rw-r--r--ext/tk/sample/msgs_rb/it.msg84
-rw-r--r--ext/tk/sample/msgs_rb/ja.msg13
-rw-r--r--ext/tk/sample/msgs_rb/nl.msg123
-rw-r--r--ext/tk/sample/msgs_rb/pl.msg87
-rw-r--r--ext/tk/sample/msgs_rb/ru.msg87
-rw-r--r--ext/tk/sample/msgs_rb2/README5
-rw-r--r--ext/tk/sample/msgs_rb2/de.msg88
-rw-r--r--ext/tk/sample/msgs_rb2/ja.msg85
-rw-r--r--ext/tk/sample/msgs_tk/README4
-rw-r--r--ext/tk/sample/msgs_tk/cs.msg84
-rw-r--r--ext/tk/sample/msgs_tk/de.msg88
-rw-r--r--ext/tk/sample/msgs_tk/el.msg103
-rw-r--r--ext/tk/sample/msgs_tk/en.msg83
-rw-r--r--ext/tk/sample/msgs_tk/en_gb.msg7
-rw-r--r--ext/tk/sample/msgs_tk/eo.msg87
-rw-r--r--ext/tk/sample/msgs_tk/es.msg84
-rw-r--r--ext/tk/sample/msgs_tk/fr.msg84
-rw-r--r--ext/tk/sample/msgs_tk/it.msg84
-rw-r--r--ext/tk/sample/msgs_tk/ja.msg13
-rw-r--r--ext/tk/sample/msgs_tk/license.terms39
-rw-r--r--ext/tk/sample/msgs_tk/nl.msg123
-rw-r--r--ext/tk/sample/msgs_tk/pl.msg87
-rw-r--r--ext/tk/sample/msgs_tk/ru.msg87
-rw-r--r--ext/tk/sample/multi-ip_sample.rb102
-rw-r--r--ext/tk/sample/multi-ip_sample2.rb29
-rw-r--r--ext/tk/sample/optobj_sample.rb67
-rw-r--r--ext/tk/sample/propagate.rb30
-rw-r--r--ext/tk/sample/remote-ip_sample.rb33
-rw-r--r--ext/tk/sample/remote-ip_sample2.rb56
-rw-r--r--ext/tk/sample/safe-tk.rb200
-rw-r--r--ext/tk/sample/scrollframe.rb237
-rw-r--r--ext/tk/sample/tcltklib/batsu.gif (renamed from ext/tcltklib/sample/batsu.gif)bin538 -> 538 bytes-rw-r--r--ext/tk/sample/tcltklib/lines0.tcl (renamed from ext/tcltklib/demo/lines0.tcl)0
-rw-r--r--ext/tk/sample/tcltklib/lines1.rb (renamed from ext/tcltklib/demo/lines2.rb)0
-rw-r--r--ext/tk/sample/tcltklib/lines2.rb (renamed from ext/tcltklib/demo/lines1.rb)0
-rw-r--r--ext/tk/sample/tcltklib/lines3.rb54
-rw-r--r--ext/tk/sample/tcltklib/lines4.rb54
-rw-r--r--ext/tk/sample/tcltklib/maru.gif (renamed from ext/tcltklib/sample/maru.gif)bin481 -> 481 bytes-rw-r--r--ext/tk/sample/tcltklib/safeTk.rb (renamed from ext/tcltklib/demo/safeTk.rb)0
-rw-r--r--ext/tk/sample/tcltklib/sample0.rb (renamed from ext/tcltklib/sample/sample0.rb)0
-rw-r--r--ext/tk/sample/tcltklib/sample1.rb634
-rw-r--r--ext/tk/sample/tcltklib/sample2.rb451
-rw-r--r--ext/tk/sample/tkalignbox.rb225
-rw-r--r--ext/tk/sample/tkballoonhelp.rb103
-rw-r--r--ext/tk/sample/tkbiff.rb12
-rw-r--r--ext/tk/sample/tkbrowse.rb8
-rw-r--r--ext/tk/sample/tkcombobox.rb52
-rw-r--r--ext/tk/sample/tkextlib/ICONS/Orig_LICENSE.txt61
-rw-r--r--ext/tk/sample/tkextlib/ICONS/tkIcons195
-rw-r--r--ext/tk/sample/tkextlib/ICONS/tkIcons-sample.kde658
-rw-r--r--ext/tk/sample/tkextlib/ICONS/tkIcons.kde195
-rw-r--r--ext/tk/sample/tkextlib/ICONS/viewIcons.rb329
-rw-r--r--ext/tk/sample/tkextlib/blt/barchart5.rb101
-rw-r--r--ext/tk/sample/tkextlib/blt/calendar.rb117
-rw-r--r--ext/tk/sample/tkextlib/blt/graph6.rb2222
-rw-r--r--ext/tk/sample/tkextlib/blt/graph7.rb40
-rw-r--r--ext/tk/sample/tkextlib/blt/graph7a.rb63
-rw-r--r--ext/tk/sample/tkextlib/blt/graph7b.rb41
-rw-r--r--ext/tk/sample/tkextlib/blt/graph7c.rb45
-rw-r--r--ext/tk/sample/tkextlib/blt/images/buckskin.gifbin0 -> 7561 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/images/chalk.gifbin0 -> 4378 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/images/qv100.t.gifbin0 -> 2694 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/images/rain.gifbin0 -> 3785 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/images/sample.gifbin0 -> 186103 bytes-rw-r--r--ext/tk/sample/tkextlib/blt/pareto.rb90
-rw-r--r--ext/tk/sample/tkextlib/blt/plot1.rb9
-rw-r--r--ext/tk/sample/tkextlib/blt/plot1b.rb10
-rw-r--r--ext/tk/sample/tkextlib/blt/readme.txt2
-rw-r--r--ext/tk/sample/tkextlib/blt/scripts/stipples.rb156
-rw-r--r--ext/tk/sample/tkextlib/blt/winop1.rb40
-rw-r--r--ext/tk/sample/tkextlib/blt/winop2.rb28
-rw-r--r--ext/tk/sample/tkextlib/bwidget/Orig_LICENSE.txt53
-rw-r--r--ext/tk/sample/tkextlib/bwidget/basic.rb198
-rw-r--r--ext/tk/sample/tkextlib/bwidget/bwidget.xbm46
-rw-r--r--ext/tk/sample/tkextlib/bwidget/demo.rb243
-rw-r--r--ext/tk/sample/tkextlib/bwidget/dnd.rb46
-rw-r--r--ext/tk/sample/tkextlib/bwidget/manager.rb150
-rw-r--r--ext/tk/sample/tkextlib/bwidget/select.rb82
-rw-r--r--ext/tk/sample/tkextlib/bwidget/tmpldlg.rb221
-rw-r--r--ext/tk/sample/tkextlib/bwidget/tree.rb289
-rw-r--r--ext/tk/sample/tkextlib/bwidget/x1.xbm2258
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/Orig_LICENSE.txt42
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/box.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/clear.gifbin0 -> 279 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/close.gifbin0 -> 249 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/copy.gifbin0 -> 269 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/cut.gifbin0 -> 179 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/exit.gifbin0 -> 396 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/find.gifbin0 -> 386 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/help.gifbin0 -> 591 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/line.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/mag.gifbin0 -> 183 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/new.gifbin0 -> 212 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/open.gifbin0 -> 258 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/oval.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/paste.gifbin0 -> 376 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/points.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/poly.gifbin0 -> 141 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/print.gifbin0 -> 263 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/ruler.gifbin0 -> 174 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/save.gifbin0 -> 270 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/select.gifbin0 -> 124 bytes-rw-r--r--ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/text.xbm14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/buttonbox.rb22
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/calendar.rb10
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/canvasprintbox.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/canvasprintdialog.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/checkbox.rb12
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/combobox.rb32
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/dateentry.rb7
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/datefield.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/dialog.rb20
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/dialogshell.rb14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/disjointlistbox.rb16
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/entryfield-1.rb39
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/entryfield-2.rb40
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/entryfield-3.rb40
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/extbutton.rb20
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/extfileselectionbox.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/extfileselectiondialog.rb29
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/feedback.rb10
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/fileselectionbox.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/fileselectiondialog.rb28
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/finddialog.rb15
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/hierarchy.rb25
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/hyperhelp.rb14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/labeledframe.rb14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/labeledwidget.rb13
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/mainwindow.rb64
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/menubar.rb124
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/menubar2.rb44
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/messagebox1.rb19
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/messagebox2.rb19
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/messagedialog.rb44
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/notebook.rb30
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/notebook2.rb30
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/optionmenu.rb14
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/panedwindow.rb22
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/panedwindow2.rb22
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/promptdialog.rb17
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/pushbutton.rb9
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/radiobox.rb13
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledcanvas.rb13
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledframe.rb18
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledhtml.rb15
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledlistbox.rb22
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/scrolledtext.rb11
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/selectionbox.rb19
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/selectiondialog.rb12
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/shell.rb17
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/spindate.rb7
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/spinint.rb10
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/spinner.rb33
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/spintime.rb7
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook.rb26
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook2.rb30
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/tabset.rb34
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/timeentry.rb7
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/timefield.rb8
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/toolbar.rb152
-rw-r--r--ext/tk/sample/tkextlib/iwidgets/sample/watch.rb18
-rw-r--r--ext/tk/sample/tkextlib/tcllib/Orig_LICENSE.txt46
-rw-r--r--ext/tk/sample/tkextlib/tcllib/datefield.rb29
-rw-r--r--ext/tk/sample/tkextlib/tcllib/plotdemos1.rb158
-rw-r--r--ext/tk/sample/tkextlib/tcllib/plotdemos2.rb71
-rw-r--r--ext/tk/sample/tkextlib/tcllib/plotdemos3.rb83
-rw-r--r--ext/tk/sample/tkextlib/tcllib/xyplot.rb17
-rw-r--r--ext/tk/sample/tkextlib/tile/Orig_LICENSE.txt30
-rw-r--r--ext/tk/sample/tkextlib/tile/demo.rb983
-rw-r--r--ext/tk/sample/tkextlib/tile/iconlib.tcl110
-rw-r--r--ext/tk/sample/tkextlib/tile/readme.txt2
-rw-r--r--ext/tk/sample/tkextlib/tile/repeater.tcl117
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue.tcl149
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-h.gifbin0 -> 315 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-p.gifbin0 -> 312 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown.gifbin0 -> 313 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-h.gifbin0 -> 329 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-p.gifbin0 -> 327 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft.gifbin0 -> 323 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-h.gifbin0 -> 330 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-p.gifbin0 -> 327 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright.gifbin0 -> 324 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-h.gifbin0 -> 309 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-p.gifbin0 -> 313 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup.gifbin0 -> 314 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/button-h.gifbin0 -> 696 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.gifbin0 -> 770 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.xcfbin0 -> 1942 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/button-p.gifbin0 -> 769 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hc.gifbin0 -> 254 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hu.gifbin0 -> 234 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nc.gifbin0 -> 249 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nu.gifbin0 -> 229 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hc.gifbin0 -> 1098 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hu.gifbin0 -> 626 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nc.gifbin0 -> 389 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nu.gifbin0 -> 401 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb-p.gifbin0 -> 343 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb.gifbin0 -> 316 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb-p.gifbin0 -> 333 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb.gifbin0 -> 308 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/slider-p.gifbin0 -> 182 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/slider.gifbin0 -> 182 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider-p.gifbin0 -> 183 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider.gifbin0 -> 283 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl6
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik.tcl194
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-n.gifbin0 -> 273 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-p.gifbin0 -> 258 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-n.gifbin0 -> 292 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-p.gifbin0 -> 272 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-n.gifbin0 -> 274 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-p.gifbin0 -> 258 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-n.gifbin0 -> 286 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-p.gifbin0 -> 271 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-d.gifbin0 -> 1266 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-h.gifbin0 -> 896 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-n.gifbin0 -> 881 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-p.gifbin0 -> 625 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-s.gifbin0 -> 859 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-c.gifbin0 -> 434 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-u.gifbin0 -> 423 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-n.gifbin0 -> 401 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-p.gifbin0 -> 395 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hslider-n.gifbin0 -> 592 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-a.gifbin0 -> 1116 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-arrow-n.gifbin0 -> 61 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-d.gifbin0 -> 1057 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-n.gifbin0 -> 1095 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-c.gifbin0 -> 695 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-u.gifbin0 -> 686 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-n.gifbin0 -> 383 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-p.gifbin0 -> 878 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-a.gifbin0 -> 907 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-n.gifbin0 -> 238 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-p.gifbin0 -> 927 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-n.gifbin0 -> 405 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-p.gifbin0 -> 399 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vslider-n.gifbin0 -> 587 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/pkgIndex.tcl15
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc.rb226
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc.tcl163
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-h.gifbin0 -> 522 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-n.gifbin0 -> 554 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-p.gifbin0 -> 548 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hc.gifbin0 -> 281 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hu.gifbin0 -> 273 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nc.gifbin0 -> 303 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nu.gifbin0 -> 294 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hc.gifbin0 -> 652 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hu.gifbin0 -> 644 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nc.gifbin0 -> 632 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nu.gifbin0 -> 621 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/pkgIndex.tcl15
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/pkgIndex.tcl16
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik.tcl125
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-n.gifbin0 -> 362 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-p.gifbin0 -> 250 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-n.gifbin0 -> 378 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-p.gifbin0 -> 267 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-n.gifbin0 -> 379 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-p.gifbin0 -> 266 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-n.gifbin0 -> 363 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-p.gifbin0 -> 251 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-h.gifbin0 -> 439 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-n.gifbin0 -> 443 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-p.gifbin0 -> 302 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hc.gifbin0 -> 169 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hu.gifbin0 -> 170 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nc.gifbin0 -> 235 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nu.gifbin0 -> 226 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-pc.gifbin0 -> 169 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hsb-n.gifbin0 -> 269 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hslider-n.gifbin0 -> 342 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hc.gifbin0 -> 178 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hu.gifbin0 -> 179 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nc.gifbin0 -> 236 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nu.gifbin0 -> 178 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-pc.gifbin0 -> 178 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vsb-n.gifbin0 -> 366 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vslider-n.gifbin0 -> 336 bytes-rw-r--r--ext/tk/sample/tkextlib/tile/toolbutton.tcl152
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/Orig_COPYRIGHT.txt12
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/README12
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/hv.rb313
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image1bin0 -> 8995 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image10bin0 -> 3095 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image11bin0 -> 1425 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image12bin0 -> 2468 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image13bin0 -> 4073 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image14bin0 -> 53 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image2bin0 -> 42 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image3bin0 -> 3473 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image4bin0 -> 1988 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image5bin0 -> 973 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image6bin0 -> 2184 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image7bin0 -> 2022 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image8bin0 -> 1186 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/image9bin0 -> 139 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page1/index.html115
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image1bin0 -> 1966 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image10bin0 -> 255 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image11bin0 -> 590 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image12bin0 -> 254 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image13bin0 -> 493 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image14bin0 -> 195 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image15bin0 -> 68 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image16bin0 -> 157 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image17bin0 -> 81 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image18bin0 -> 545 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image19bin0 -> 53 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image2bin0 -> 49 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image20bin0 -> 533 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image21bin0 -> 564 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image22bin0 -> 81 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image23bin0 -> 539 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image24bin0 -> 151 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image25bin0 -> 453 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image26bin0 -> 520 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image27bin0 -> 565 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image28bin0 -> 416 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image29bin0 -> 121 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image3bin0 -> 10835 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image30bin0 -> 663 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image31bin0 -> 78 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image32bin0 -> 556 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image33bin0 -> 598 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image34bin0 -> 496 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image35bin0 -> 724 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image36bin0 -> 404 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image37bin0 -> 124 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image38bin0 -> 8330 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image39bin0 -> 369 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image4bin0 -> 268 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image5bin0 -> 492 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image6bin0 -> 246 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image7bin0 -> 551 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image8bin0 -> 497 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/image9bin0 -> 492 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page2/index.html433
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image1bin0 -> 113 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image10bin0 -> 5088 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image11bin0 -> 4485 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image12bin0 -> 3579 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image13bin0 -> 5119 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image14bin0 -> 3603 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image2bin0 -> 74 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image3bin0 -> 681 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image4bin0 -> 3056 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image5bin0 -> 2297 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image6bin0 -> 79 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image7bin0 -> 1613 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image8bin0 -> 864 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/image9bin0 -> 2379 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/index.html2787
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image1bin0 -> 42 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image2bin0 -> 14343 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image3bin0 -> 17750 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image4bin0 -> 61 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image5bin0 -> 201 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image6bin0 -> 214 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image7bin0 -> 149 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image8bin0 -> 203 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/image9bin0 -> 1504 bytes-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page4/index.html768
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/ss.rb436
-rw-r--r--ext/tk/sample/tkextlib/tkimg/demo.rb1478
-rw-r--r--ext/tk/sample/tkextlib/tkimg/license_terms_of_Img_extension41
-rw-r--r--ext/tk/sample/tkextlib/tkimg/readme.txt3
-rw-r--r--ext/tk/sample/tkextlib/tktable/Orig_LICENSE.txt52
-rw-r--r--ext/tk/sample/tkextlib/tktable/basic.rb60
-rw-r--r--ext/tk/sample/tkextlib/tktable/buttons.rb76
-rw-r--r--ext/tk/sample/tkextlib/tktable/command.rb89
-rw-r--r--ext/tk/sample/tkextlib/tktable/debug.rb101
-rw-r--r--ext/tk/sample/tkextlib/tktable/dynarows.rb99
-rw-r--r--ext/tk/sample/tkextlib/tktable/maxsize.rb67
-rw-r--r--ext/tk/sample/tkextlib/tktable/spreadsheet.rb137
-rwxr-xr-xext/tk/sample/tkextlib/tktable/tcllogo.gifbin0 -> 2341 bytes-rw-r--r--ext/tk/sample/tkextlib/tktable/valid.rb88
-rw-r--r--ext/tk/sample/tkextlib/treectrl/bitmaps.rb76
-rw-r--r--ext/tk/sample/tkextlib/treectrl/demo.rb1311
-rw-r--r--ext/tk/sample/tkextlib/treectrl/explorer.rb430
-rw-r--r--ext/tk/sample/tkextlib/treectrl/help.rb404
-rw-r--r--ext/tk/sample/tkextlib/treectrl/imovie.rb130
-rw-r--r--ext/tk/sample/tkextlib/treectrl/layout.rb159
-rw-r--r--ext/tk/sample/tkextlib/treectrl/mailwasher.rb269
-rw-r--r--ext/tk/sample/tkextlib/treectrl/outlook-folders.rb124
-rw-r--r--ext/tk/sample/tkextlib/treectrl/outlook-newgroup.rb448
-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-dll.gifbin0 -> 437 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-exe.gifbin0 -> 368 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-file.gifbin0 -> 466 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-folder.gifbin0 -> 459 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/big-txt.gifbin0 -> 392 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/checked.gifbin0 -> 78 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/file.gifbin0 -> 279 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/folder-closed.gifbin0 -> 111 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/folder-open.gifbin0 -> 120 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/help-book-closed.gifbin0 -> 115 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/help-book-open.gifbin0 -> 128 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/help-page.gifbin0 -> 132 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-01.gifbin0 -> 5406 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-02.gifbin0 -> 5912 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-03.gifbin0 -> 4696 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-04.gifbin0 -> 5783 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-05.gifbin0 -> 3238 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-06.gifbin0 -> 3509 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/imovie-07.gifbin0 -> 2091 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-check-off.gifbin0 -> 70 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-check-on.gifbin0 -> 76 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-print.gifbin0 -> 124 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-radio-off.gifbin0 -> 68 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-radio-on.gifbin0 -> 71 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-search.gifbin0 -> 114 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/internet-security.gifbin0 -> 108 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/mac-collapse.gifbin0 -> 275 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/mac-expand.gifbin0 -> 277 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-arrow.gifbin0 -> 73 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-clip.gifbin0 -> 73 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-deleted.gifbin0 -> 138 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-draft.gifbin0 -> 134 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-folder.gifbin0 -> 133 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-group.gifbin0 -> 144 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-inbox.gifbin0 -> 133 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-local.gifbin0 -> 146 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-main.gifbin0 -> 174 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-outbox.gifbin0 -> 136 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-read-2.gifbin0 -> 343 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-read.gifbin0 -> 304 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-sent.gifbin0 -> 132 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-server.gifbin0 -> 163 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-unread.gifbin0 -> 303 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/outlook-watch.gifbin0 -> 98 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/sky.gifbin0 -> 6454 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-dll.gifbin0 -> 311 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-exe.gifbin0 -> 115 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-file.gifbin0 -> 338 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-folder.gifbin0 -> 307 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/small-txt.gifbin0 -> 302 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/pics/unchecked.gifbin0 -> 72 bytes-rw-r--r--ext/tk/sample/tkextlib/treectrl/random.rb508
-rw-r--r--ext/tk/sample/tkextlib/treectrl/readme.txt2
-rw-r--r--ext/tk/sample/tkextlib/treectrl/www-options.rb303
-rw-r--r--ext/tk/sample/tkextlib/vu/Orig_LICENSE.txt51
-rw-r--r--ext/tk/sample/tkextlib/vu/README.txt50
-rw-r--r--ext/tk/sample/tkextlib/vu/canvItems.rb90
-rw-r--r--ext/tk/sample/tkextlib/vu/canvSticker.rb82
-rw-r--r--ext/tk/sample/tkextlib/vu/canvSticker2.rb101
-rw-r--r--ext/tk/sample/tkextlib/vu/dial_demo.rb113
-rw-r--r--ext/tk/sample/tkextlib/vu/m128_000.xbm174
-rw-r--r--ext/tk/sample/tkextlib/vu/oscilloscope.rb68
-rw-r--r--ext/tk/sample/tkextlib/vu/pie.rb56
-rw-r--r--ext/tk/sample/tkextlib/vu/vu_demo.rb67
-rw-r--r--ext/tk/sample/tkfrom.rb12
-rw-r--r--ext/tk/sample/tkhello.rb8
-rw-r--r--ext/tk/sample/tkline.rb6
-rw-r--r--ext/tk/sample/tkmenubutton.rb38
-rw-r--r--ext/tk/sample/tkmsgcat-load_rb.rb102
-rw-r--r--ext/tk/sample/tkmsgcat-load_rb2.rb102
-rw-r--r--ext/tk/sample/tkmsgcat-load_tk.rb118
-rw-r--r--ext/tk/sample/tkmulticolumnlist.rb743
-rw-r--r--ext/tk/sample/tkmultilistbox.rb162
-rw-r--r--ext/tk/sample/tkmultilistframe.rb940
-rw-r--r--ext/tk/sample/tkoptdb-safeTk.rb58
-rw-r--r--ext/tk/sample/tkoptdb.rb43
-rw-r--r--ext/tk/sample/tkrttimer.rb77
-rw-r--r--ext/tk/sample/tksleep_sample.rb29
-rw-r--r--ext/tk/sample/tktextframe.rb75
-rw-r--r--ext/tk/sample/tktextio.rb1060
-rw-r--r--ext/tk/sample/tktree.rb103
-rw-r--r--ext/tk/sample/tktree.tcl305
-rw-r--r--ext/tk/sample/ttk_wrapper.rb154
-rw-r--r--ext/tk/stubs.c564
-rw-r--r--ext/tk/stubs.h33
-rw-r--r--ext/tk/tcltklib.c10258
-rw-r--r--ext/tk/tkutil.c45
-rw-r--r--ext/tk/tkutil/.cvsignore (renamed from ext/tcltklib/.cvsignore)0
-rw-r--r--ext/tk/tkutil/depend1
-rw-r--r--ext/tk/tkutil/extconf.rb13
-rw-r--r--ext/tk/tkutil/tkutil.c1799
-rw-r--r--ext/win32ole/.cvsignore1
-rw-r--r--ext/win32ole/MANIFEST24
-rw-r--r--ext/win32ole/extconf.rb16
-rw-r--r--ext/win32ole/tests/testNIL2VTEMPTY.rb28
-rw-r--r--ext/win32ole/tests/testOLEEVENT.rb33
-rw-r--r--ext/win32ole/tests/testOLEMETHOD.rb5
-rw-r--r--ext/win32ole/tests/testOLEPARAM.rb9
-rw-r--r--ext/win32ole/tests/testWIN32OLE.rb87
-rw-r--r--ext/win32ole/tests/test_ole_methods.rb36
-rw-r--r--ext/win32ole/tests/test_propertyputref.rb19
-rw-r--r--ext/win32ole/tests/test_win32ole_event.rb133
-rw-r--r--ext/win32ole/tests/test_word.rb37
-rw-r--r--ext/win32ole/tests/testall.rb5
-rw-r--r--ext/win32ole/win32ole.c2238
-rw-r--r--ext/zlib/MANIFEST4
-rw-r--r--ext/zlib/doc/zlib.rd2
-rw-r--r--ext/zlib/extconf.rb11
-rw-r--r--ext/zlib/zlib.c1026
-rw-r--r--file.c2108
-rw-r--r--gc.c965
-rw-r--r--hash.c1176
-rw-r--r--ia64.s33
-rw-r--r--inits.c4
-rwxr-xr-x[-rw-r--r--]instruby.rb418
-rw-r--r--intern.h86
-rw-r--r--io.c2722
-rw-r--r--keywords2
-rw-r--r--lex.c2
-rw-r--r--lib/.document106
-rw-r--r--lib/English.rb132
-rw-r--r--lib/README6
-rw-r--r--lib/abbrev.rb38
-rw-r--r--lib/base64.rb150
-rw-r--r--lib/benchmark.rb166
-rw-r--r--lib/cgi-lib.rb2
-rw-r--r--lib/cgi.rb228
-rw-r--r--lib/cgi/.document2
-rw-r--r--lib/cgi/session.rb178
-rw-r--r--lib/cgi/session/pstore.rb44
-rw-r--r--lib/complex.rb32
-rw-r--r--lib/csv.rb1406
-rw-r--r--lib/date.rb1066
-rw-r--r--lib/date/format.rb1555
-rw-r--r--lib/debug.rb26
-rw-r--r--lib/delegate.rb268
-rw-r--r--lib/drb/acl.rb2
-rw-r--r--lib/drb/drb.rb337
-rw-r--r--lib/drb/extserv.rb7
-rw-r--r--lib/drb/extservm.rb51
-rw-r--r--lib/drb/gw.rb74
-rw-r--r--lib/drb/ssl.rb9
-rw-r--r--lib/drb/unix.rb4
-rw-r--r--lib/erb.rb679
-rw-r--r--lib/fileutils.rb1456
-rw-r--r--lib/finalize.rb39
-rw-r--r--lib/find.rb7
-rw-r--r--lib/forwardable.rb174
-rw-r--r--lib/ftools.rb167
-rw-r--r--lib/generator.rb58
-rw-r--r--lib/getoptlong.rb195
-rw-r--r--lib/getopts.rb3
-rw-r--r--lib/gserver.rb82
-rw-r--r--lib/importenv.rb2
-rw-r--r--lib/ipaddr.rb256
-rw-r--r--lib/irb.rb30
-rw-r--r--lib/irb/cmd/chws.rb4
-rw-r--r--lib/irb/cmd/fork.rb16
-rw-r--r--lib/irb/cmd/help.rb34
-rw-r--r--lib/irb/cmd/load.rb4
-rw-r--r--lib/irb/cmd/nop.rb4
-rw-r--r--lib/irb/cmd/pushws.rb4
-rw-r--r--lib/irb/cmd/subirb.rb4
-rw-r--r--lib/irb/completion.rb29
-rw-r--r--lib/irb/context.rb41
-rw-r--r--lib/irb/ext/change-ws.rb4
-rw-r--r--lib/irb/ext/history.rb8
-rw-r--r--lib/irb/ext/loader.rb14
-rw-r--r--lib/irb/ext/math-mode.rb4
-rw-r--r--lib/irb/ext/multi-irb.rb4
-rw-r--r--lib/irb/ext/save-history.rb85
-rw-r--r--lib/irb/ext/tracer.rb4
-rw-r--r--lib/irb/ext/use-loader.rb4
-rw-r--r--lib/irb/ext/workspaces.rb4
-rw-r--r--lib/irb/extend-command.rb67
-rw-r--r--lib/irb/help.rb4
-rw-r--r--lib/irb/init.rb87
-rw-r--r--lib/irb/input-method.rb10
-rw-r--r--lib/irb/lc/error.rb4
-rw-r--r--lib/irb/lc/help-message5
-rw-r--r--lib/irb/lc/ja/error.rb6
-rw-r--r--lib/irb/lc/ja/help-message5
-rw-r--r--lib/irb/locale.rb26
-rw-r--r--lib/irb/notifier.rb145
-rw-r--r--lib/irb/output-method.rb85
-rw-r--r--lib/irb/ruby-lex.rb147
-rw-r--r--lib/irb/ruby-token.rb6
-rw-r--r--lib/irb/slex.rb363
-rw-r--r--lib/irb/version.rb6
-rw-r--r--lib/irb/workspace.rb6
-rw-r--r--lib/irb/ws-for-case-2.rb4
-rw-r--r--lib/jcode.rb7
-rw-r--r--lib/logger.rb726
-rw-r--r--lib/mailread.rb14
-rw-r--r--lib/mathn.rb8
-rw-r--r--lib/matrix.rb590
-rw-r--r--lib/mkmf.rb1301
-rw-r--r--lib/monitor.rb59
-rw-r--r--lib/mutex_m.rb34
-rw-r--r--lib/net/ftp.rb39
-rw-r--r--lib/net/http.rb1099
-rw-r--r--lib/net/https.rb173
-rw-r--r--lib/net/imap.rb2815
-rw-r--r--lib/net/pop.rb636
-rw-r--r--lib/net/protocol.rb401
-rw-r--r--lib/net/smtp.rb966
-rw-r--r--lib/net/telnet.rb216
-rw-r--r--lib/open-uri.rb452
-rw-r--r--lib/open3.rb53
-rw-r--r--lib/optparse.rb2237
-rw-r--r--lib/optparse/version.rb36
-rw-r--r--lib/ostruct.rb119
-rw-r--r--lib/parsearg.rb4
-rw-r--r--lib/parsedate.rb44
-rw-r--r--lib/pathname.rb1258
-rw-r--r--lib/ping.rb68
-rw-r--r--lib/pp.rb533
-rw-r--r--lib/prettyprint.rb409
-rw-r--r--lib/profiler.rb58
-rw-r--r--lib/pstore.rb330
-rw-r--r--lib/racc/parser.rb64
-rw-r--r--lib/rational.rb420
-rw-r--r--lib/rdoc/README56
-rw-r--r--lib/rdoc/code_objects.rb142
-rw-r--r--lib/rdoc/diagram.rb36
-rw-r--r--lib/rdoc/dot/dot.rb50
-rw-r--r--lib/rdoc/generators/chm_generator.rb4
-rw-r--r--lib/rdoc/generators/html_generator.rb333
-rw-r--r--lib/rdoc/generators/ri_generator.rb268
-rw-r--r--lib/rdoc/generators/template/chm/chm.rb1
-rw-r--r--lib/rdoc/generators/template/html/css2.rb631
-rw-r--r--lib/rdoc/generators/template/html/hefss.rb52
-rw-r--r--lib/rdoc/generators/template/html/html.rb1175
-rw-r--r--lib/rdoc/generators/template/html/kilmer.rb87
-rw-r--r--lib/rdoc/generators/template/html/old_html.rb728
-rw-r--r--lib/rdoc/generators/template/html/one_page_html.rb122
-rw-r--r--lib/rdoc/markup/.document2
-rw-r--r--lib/rdoc/markup/simple_markup.rb5
-rw-r--r--lib/rdoc/markup/simple_markup/fragments.rb2
-rw-r--r--lib/rdoc/markup/simple_markup/inline.rb28
-rw-r--r--lib/rdoc/markup/simple_markup/preprocess.rb13
-rw-r--r--lib/rdoc/markup/simple_markup/to_flow.rb188
-rw-r--r--lib/rdoc/markup/test/TestInline.rb3
-rw-r--r--lib/rdoc/options.rb90
-rw-r--r--lib/rdoc/parsers/parse_c.rb706
-rw-r--r--lib/rdoc/parsers/parse_f95.rb1845
-rw-r--r--lib/rdoc/parsers/parse_rb.rb317
-rw-r--r--lib/rdoc/parsers/parse_simple.rb8
-rw-r--r--lib/rdoc/parsers/parserfactory.rb19
-rw-r--r--lib/rdoc/rdoc.rb161
-rw-r--r--lib/rdoc/ri/ri_cache.rb187
-rw-r--r--lib/rdoc/ri/ri_descriptions.rb154
-rw-r--r--lib/rdoc/ri/ri_display.rb255
-rw-r--r--lib/rdoc/ri/ri_driver.rb143
-rw-r--r--lib/rdoc/ri/ri_formatter.rb672
-rw-r--r--lib/rdoc/ri/ri_options.rb319
-rw-r--r--lib/rdoc/ri/ri_paths.rb101
-rw-r--r--lib/rdoc/ri/ri_reader.rb100
-rw-r--r--lib/rdoc/ri/ri_util.rb75
-rw-r--r--lib/rdoc/ri/ri_writer.rb62
-rw-r--r--lib/rdoc/usage.rb210
-rw-r--r--lib/readbytes.rb15
-rw-r--r--lib/resolv-replace.rb45
-rw-r--r--lib/resolv.rb1438
-rw-r--r--lib/rexml/attlistdecl.rb2
-rw-r--r--lib/rexml/attribute.rb54
-rw-r--r--lib/rexml/cdata.rb23
-rw-r--r--lib/rexml/comment.rb27
-rw-r--r--lib/rexml/doctype.rb435
-rw-r--r--lib/rexml/document.rb221
-rw-r--r--lib/rexml/dtd/dtd.rb2
-rw-r--r--lib/rexml/dtd/entitydecl.rb2
-rw-r--r--lib/rexml/dtd/notationdecl.rb2
-rw-r--r--lib/rexml/element.rb2346
-rw-r--r--lib/rexml/encoding.rb111
-rw-r--r--lib/rexml/encodings/CP-1252.rb103
-rw-r--r--lib/rexml/encodings/EUC-JP.rb57
-rw-r--r--lib/rexml/encodings/ICONV.rb24
-rw-r--r--lib/rexml/encodings/ISO-8859-1.rb26
-rw-r--r--lib/rexml/encodings/ISO-8859-15.rb72
-rw-r--r--lib/rexml/encodings/SHIFT-JIS.rb38
-rw-r--r--lib/rexml/encodings/SHIFT_JIS.rb34
-rw-r--r--lib/rexml/encodings/UNILE.rb55
-rw-r--r--lib/rexml/encodings/US-ASCII.rb47
-rw-r--r--lib/rexml/encodings/UTF-16.rb56
-rw-r--r--lib/rexml/encodings/UTF-8.rb23
-rw-r--r--lib/rexml/entity.rb7
-rw-r--r--lib/rexml/formatters/default.rb109
-rw-r--r--lib/rexml/formatters/pretty.rb138
-rw-r--r--lib/rexml/formatters/transitive.rb56
-rw-r--r--lib/rexml/functions.rb736
-rw-r--r--lib/rexml/instruction.rb8
-rw-r--r--lib/rexml/light/node.rb4
-rw-r--r--lib/rexml/node.rb50
-rw-r--r--lib/rexml/output.rb10
-rw-r--r--lib/rexml/parent.rb319
-rw-r--r--lib/rexml/parseexception.rb84
-rw-r--r--lib/rexml/parsers/baseparser.rb857
-rw-r--r--lib/rexml/parsers/lightparser.rb4
-rw-r--r--lib/rexml/parsers/pullparser.rb327
-rw-r--r--lib/rexml/parsers/sax2parser.rb60
-rw-r--r--lib/rexml/parsers/streamparser.rb75
-rw-r--r--lib/rexml/parsers/treeparser.rb97
-rw-r--r--lib/rexml/parsers/ultralightparser.rb4
-rw-r--r--lib/rexml/parsers/xpathparser.rb1196
-rw-r--r--lib/rexml/rexml.rb50
-rw-r--r--lib/rexml/sax2listener.rb5
-rw-r--r--lib/rexml/source.rb450
-rw-r--r--lib/rexml/streamlistener.rb3
-rw-r--r--lib/rexml/syncenumerator.rb33
-rw-r--r--lib/rexml/text.rb561
-rw-r--r--lib/rexml/undefinednamespaceexception.rb8
-rw-r--r--lib/rexml/validation/relaxng.rb559
-rw-r--r--lib/rexml/validation/validation.rb155
-rw-r--r--lib/rexml/validation/validationexception.rb9
-rw-r--r--lib/rexml/xmldecl.rb61
-rw-r--r--lib/rexml/xpath.rb14
-rw-r--r--lib/rexml/xpath_parser.rb1287
-rw-r--r--lib/rinda/rinda.rb188
-rw-r--r--lib/rinda/ring.rb115
-rw-r--r--lib/rinda/tuplespace.rb578
-rw-r--r--lib/rss.rb19
-rw-r--r--lib/rss/0.9.rb428
-rw-r--r--lib/rss/1.0.rb452
-rw-r--r--lib/rss/2.0.rb111
-rw-r--r--lib/rss/atom.rb749
-rw-r--r--lib/rss/content.rb31
-rw-r--r--lib/rss/content/1.0.rb10
-rw-r--r--lib/rss/content/2.0.rb12
-rw-r--r--lib/rss/converter.rb162
-rw-r--r--lib/rss/dublincore.rb161
-rw-r--r--lib/rss/dublincore/1.0.rb13
-rw-r--r--lib/rss/dublincore/2.0.rb13
-rw-r--r--lib/rss/dublincore/atom.rb17
-rw-r--r--lib/rss/image.rb193
-rw-r--r--lib/rss/itunes.rb410
-rw-r--r--lib/rss/maker.rb44
-rw-r--r--lib/rss/maker/0.9.rb467
-rw-r--r--lib/rss/maker/1.0.rb434
-rw-r--r--lib/rss/maker/2.0.rb223
-rw-r--r--lib/rss/maker/atom.rb172
-rw-r--r--lib/rss/maker/base.rb868
-rw-r--r--lib/rss/maker/content.rb21
-rw-r--r--lib/rss/maker/dublincore.rb124
-rw-r--r--lib/rss/maker/entry.rb163
-rw-r--r--lib/rss/maker/feed.rb429
-rw-r--r--lib/rss/maker/image.rb111
-rw-r--r--lib/rss/maker/itunes.rb242
-rw-r--r--lib/rss/maker/slash.rb33
-rw-r--r--lib/rss/maker/syndication.rb18
-rw-r--r--lib/rss/maker/taxonomy.rb118
-rw-r--r--lib/rss/maker/trackback.rb61
-rw-r--r--lib/rss/parser.rb541
-rw-r--r--lib/rss/rexmlparser.rb54
-rw-r--r--lib/rss/rss.rb1312
-rw-r--r--lib/rss/slash.rb49
-rw-r--r--lib/rss/syndication.rb67
-rw-r--r--lib/rss/taxonomy.rb145
-rw-r--r--lib/rss/trackback.rb288
-rw-r--r--lib/rss/utils.rb111
-rw-r--r--lib/rss/xml-stylesheet.rb105
-rw-r--r--lib/rss/xml.rb71
-rw-r--r--lib/rss/xmlparser.rb93
-rw-r--r--lib/rss/xmlscanner.rb121
-rw-r--r--lib/runit/cui/testrunner.rb2
-rw-r--r--lib/scanf.rb31
-rw-r--r--lib/securerandom.rb137
-rw-r--r--lib/set.rb119
-rw-r--r--lib/shell/command-processor.rb27
-rw-r--r--lib/shell/filter.rb7
-rw-r--r--lib/shell/process-controller.rb8
-rw-r--r--lib/shell/system-command.rb2
-rw-r--r--lib/shellwords.rb150
-rw-r--r--lib/singleton.rb87
-rw-r--r--lib/soap/attachment.rb107
-rw-r--r--lib/soap/baseData.rb379
-rw-r--r--lib/soap/element.rb103
-rw-r--r--lib/soap/encodingstyle/aspDotNetHandler.rb45
-rw-r--r--lib/soap/encodingstyle/handler.rb12
-rw-r--r--lib/soap/encodingstyle/literalHandler.rb101
-rw-r--r--lib/soap/encodingstyle/soapHandler.rb146
-rw-r--r--lib/soap/generator.rb117
-rw-r--r--lib/soap/header/handler.rb57
-rw-r--r--lib/soap/header/handlerset.rb70
-rw-r--r--lib/soap/header/simplehandler.rb44
-rw-r--r--lib/soap/httpconfigloader.rb119
-rw-r--r--lib/soap/mapping/factory.rb162
-rw-r--r--lib/soap/mapping/mapping.rb301
-rw-r--r--lib/soap/mapping/registry.rb294
-rw-r--r--lib/soap/mapping/rubytypeFactory.rb128
-rw-r--r--lib/soap/mapping/typeMap.rb9
-rw-r--r--lib/soap/mapping/wsdlRegistry.rb135
-rw-r--r--lib/soap/mapping/wsdlencodedregistry.rb280
-rw-r--r--lib/soap/mapping/wsdlliteralregistry.rb418
-rw-r--r--lib/soap/marshal.rb14
-rw-r--r--lib/soap/mimemessage.rb240
-rw-r--r--lib/soap/netHttpClient.rb60
-rw-r--r--lib/soap/parser.rb26
-rw-r--r--lib/soap/processor.rb16
-rw-r--r--lib/soap/property.rb243
-rw-r--r--lib/soap/rpc/cgistub.rb232
-rw-r--r--lib/soap/rpc/driver.rb321
-rw-r--r--lib/soap/rpc/element.rb122
-rw-r--r--lib/soap/rpc/httpserver.rb129
-rw-r--r--lib/soap/rpc/proxy.rb482
-rw-r--r--lib/soap/rpc/router.rb601
-rw-r--r--lib/soap/rpc/rpc.rb2
-rw-r--r--lib/soap/rpc/soaplet.rb176
-rw-r--r--lib/soap/rpc/standaloneServer.rb90
-rw-r--r--lib/soap/soap.rb63
-rw-r--r--lib/soap/streamHandler.rb206
-rw-r--r--lib/soap/wsdlDriver.rb571
-rw-r--r--lib/sync.rb5
-rw-r--r--lib/tempfile.rb43
-rw-r--r--lib/test/unit.rb527
-rw-r--r--lib/test/unit/assertionfailederror.rb2
-rw-r--r--lib/test/unit/assertions.rb284
-rw-r--r--lib/test/unit/autorunner.rb101
-rw-r--r--lib/test/unit/collector/dir.rb44
-rw-r--r--lib/test/unit/error.rb2
-rw-r--r--lib/test/unit/failure.rb2
-rw-r--r--lib/test/unit/testcase.rb30
-rw-r--r--lib/test/unit/testresult.rb3
-rw-r--r--lib/test/unit/testsuite.rb4
-rw-r--r--lib/test/unit/ui/console/testrunner.rb24
-rw-r--r--lib/test/unit/ui/fox/testrunner.rb59
-rw-r--r--lib/test/unit/ui/gtk/testrunner.rb93
-rw-r--r--lib/test/unit/ui/gtk2/testrunner.rb92
-rw-r--r--lib/test/unit/ui/testrunnermediator.rb4
-rw-r--r--lib/test/unit/ui/testrunnerutilities.rb12
-rw-r--r--lib/test/unit/ui/tk/testrunner.rb39
-rw-r--r--lib/test/unit/util/observable.rb6
-rw-r--r--lib/test/unit/util/procwrapper.rb8
-rw-r--r--lib/thread.rb128
-rw-r--r--lib/thwait.rb9
-rw-r--r--lib/time.rb456
-rw-r--r--lib/timeout.rb94
-rw-r--r--lib/tmpdir.rb109
-rw-r--r--lib/tracer.rb23
-rw-r--r--lib/tsort.rb179
-rw-r--r--lib/un.rb52
-rw-r--r--lib/uri.rb38
-rw-r--r--lib/uri/common.rb437
-rw-r--r--lib/uri/ftp.rb182
-rw-r--r--lib/uri/generic.rb1033
-rw-r--r--lib/uri/http.rb102
-rw-r--r--lib/uri/https.rb22
-rw-r--r--lib/uri/ldap.rb108
-rw-r--r--lib/uri/ldaps.rb12
-rw-r--r--lib/uri/mailto.rb256
-rw-r--r--lib/weakref.rb71
-rw-r--r--lib/webrick/accesslog.rb7
-rw-r--r--lib/webrick/cgi.rb257
-rw-r--r--lib/webrick/config.rb12
-rw-r--r--lib/webrick/cookie.rb30
-rw-r--r--lib/webrick/httpauth.rb3
-rw-r--r--lib/webrick/httpauth/basicauth.rb3
-rw-r--r--lib/webrick/httpauth/digestauth.rb13
-rw-r--r--lib/webrick/httpauth/htpasswd.rb10
-rw-r--r--lib/webrick/httpproxy.rb23
-rw-r--r--lib/webrick/httprequest.rb38
-rw-r--r--lib/webrick/httpresponse.rb60
-rw-r--r--lib/webrick/https.rb7
-rw-r--r--lib/webrick/httpserver.rb42
-rw-r--r--lib/webrick/httpservlet/abstract.rb2
-rw-r--r--lib/webrick/httpservlet/cgi_runner.rb4
-rw-r--r--lib/webrick/httpservlet/cgihandler.rb19
-rw-r--r--lib/webrick/httpservlet/erbhandler.rb3
-rw-r--r--lib/webrick/httpservlet/filehandler.rb171
-rw-r--r--lib/webrick/httputils.rb66
-rw-r--r--lib/webrick/server.rb53
-rw-r--r--lib/webrick/ssl.rb2
-rw-r--r--lib/webrick/utils.rb16
-rw-r--r--lib/wsdl/binding.rb2
-rw-r--r--lib/wsdl/data.rb1
-rw-r--r--lib/wsdl/definitions.rb51
-rw-r--r--lib/wsdl/import.rb28
-rw-r--r--lib/wsdl/importer.rb60
-rw-r--r--lib/wsdl/info.rb10
-rw-r--r--lib/wsdl/message.rb2
-rw-r--r--lib/wsdl/operation.rb23
-rw-r--r--lib/wsdl/operationBinding.rb32
-rw-r--r--lib/wsdl/param.rb15
-rw-r--r--lib/wsdl/parser.rb60
-rw-r--r--lib/wsdl/part.rb2
-rw-r--r--lib/wsdl/port.rb4
-rw-r--r--lib/wsdl/portType.rb5
-rw-r--r--lib/wsdl/service.rb2
-rw-r--r--lib/wsdl/soap/address.rb2
-rw-r--r--lib/wsdl/soap/binding.rb9
-rw-r--r--lib/wsdl/soap/body.rb12
-rw-r--r--lib/wsdl/soap/cgiStubCreator.rb76
-rw-r--r--lib/wsdl/soap/classDefCreator.rb314
-rw-r--r--lib/wsdl/soap/classDefCreatorSupport.rb126
-rw-r--r--lib/wsdl/soap/clientSkeltonCreator.rb78
-rw-r--r--lib/wsdl/soap/complexType.rb82
-rw-r--r--lib/wsdl/soap/data.rb1
-rw-r--r--lib/wsdl/soap/definitions.rb55
-rw-r--r--lib/wsdl/soap/driverCreator.rb95
-rw-r--r--lib/wsdl/soap/element.rb28
-rw-r--r--lib/wsdl/soap/fault.rb12
-rw-r--r--lib/wsdl/soap/header.rb19
-rw-r--r--lib/wsdl/soap/headerfault.rb8
-rw-r--r--lib/wsdl/soap/mappingRegistryCreator.rb92
-rw-r--r--lib/wsdl/soap/methodDefCreator.rb228
-rw-r--r--lib/wsdl/soap/operation.rb20
-rw-r--r--lib/wsdl/soap/servantSkeltonCreator.rb67
-rw-r--r--lib/wsdl/soap/standaloneServerStubCreator.rb85
-rw-r--r--lib/wsdl/soap/wsdl2ruby.rb176
-rw-r--r--lib/wsdl/xmlSchema/all.rb12
-rw-r--r--lib/wsdl/xmlSchema/annotation.rb34
-rw-r--r--lib/wsdl/xmlSchema/any.rb12
-rw-r--r--lib/wsdl/xmlSchema/attribute.rb95
-rw-r--r--lib/wsdl/xmlSchema/choice.rb12
-rw-r--r--lib/wsdl/xmlSchema/complexContent.rb13
-rw-r--r--lib/wsdl/xmlSchema/complexType.rb54
-rw-r--r--lib/wsdl/xmlSchema/content.rb4
-rw-r--r--lib/wsdl/xmlSchema/data.rb21
-rw-r--r--lib/wsdl/xmlSchema/element.rb134
-rw-r--r--lib/wsdl/xmlSchema/enumeration.rb36
-rw-r--r--lib/wsdl/xmlSchema/import.rb27
-rw-r--r--lib/wsdl/xmlSchema/importer.rb87
-rw-r--r--lib/wsdl/xmlSchema/include.rb54
-rw-r--r--lib/wsdl/xmlSchema/length.rb35
-rw-r--r--lib/wsdl/xmlSchema/parser.rb67
-rw-r--r--lib/wsdl/xmlSchema/pattern.rb36
-rw-r--r--lib/wsdl/xmlSchema/schema.rb59
-rw-r--r--lib/wsdl/xmlSchema/sequence.rb12
-rw-r--r--lib/wsdl/xmlSchema/simpleContent.rb65
-rw-r--r--lib/wsdl/xmlSchema/simpleExtension.rb54
-rw-r--r--lib/wsdl/xmlSchema/simpleRestriction.rb73
-rw-r--r--lib/wsdl/xmlSchema/simpleType.rb73
-rw-r--r--lib/wsdl/xmlSchema/xsd2ruby.rb107
-rw-r--r--lib/xmlrpc/.document1
-rw-r--r--lib/xmlrpc/README.txt31
-rw-r--r--lib/xmlrpc/client.rb48
-rw-r--r--lib/xmlrpc/create.rb24
-rw-r--r--lib/xmlrpc/datetime.rb4
-rw-r--r--lib/xmlrpc/parser.rb83
-rw-r--r--lib/xmlrpc/server.rb171
-rw-r--r--lib/xmlrpc/utils.rb11
-rw-r--r--lib/xsd/charset.rb80
-rw-r--r--lib/xsd/codegen.rb12
-rw-r--r--lib/xsd/codegen/classdef.rb203
-rw-r--r--lib/xsd/codegen/commentdef.rb34
-rw-r--r--lib/xsd/codegen/gensupport.rb166
-rw-r--r--lib/xsd/codegen/methoddef.rb63
-rw-r--r--lib/xsd/codegen/moduledef.rb191
-rw-r--r--lib/xsd/datatypes.rb713
-rw-r--r--lib/xsd/iconvcharset.rb2
-rw-r--r--lib/xsd/mapping.rb42
-rw-r--r--lib/xsd/namedelements.rb18
-rw-r--r--lib/xsd/ns.rb38
-rw-r--r--lib/xsd/qname.rb24
-rw-r--r--lib/xsd/xmlparser.rb2
-rw-r--r--lib/xsd/xmlparser/xmlscanner.rb6
-rw-r--r--lib/yaml.rb410
-rw-r--r--lib/yaml/baseemitter.rb102
-rw-r--r--lib/yaml/basenode.rb20
-rw-r--r--lib/yaml/emitter.rb107
-rw-r--r--lib/yaml/encoding.rb10
-rw-r--r--lib/yaml/error.rb1
-rw-r--r--lib/yaml/rubytypes.rb669
-rw-r--r--lib/yaml/store.rb98
-rw-r--r--lib/yaml/stream.rb18
-rw-r--r--lib/yaml/syck.rb8
-rw-r--r--lib/yaml/tag.rb91
-rw-r--r--lib/yaml/types.rb218
-rw-r--r--main.c13
-rw-r--r--marshal.c308
-rw-r--r--math.c231
-rw-r--r--misc/README13
-rw-r--r--misc/inf-ruby.el20
-rw-r--r--misc/ruby-electric.el200
-rw-r--r--misc/ruby-mode.el449
-rw-r--r--misc/ruby-style.el66
-rw-r--r--missing.h17
-rw-r--r--missing/crypt.c1184
-rw-r--r--missing/erf.c3
-rw-r--r--missing/flock.c5
-rw-r--r--missing/isinf.c36
-rw-r--r--missing/isnan.c24
-rw-r--r--missing/mkdir.c104
-rw-r--r--missing/os2.c2
-rw-r--r--missing/strchr.c4
-rw-r--r--missing/strftime.c58
-rw-r--r--missing/vsnprintf.c19
-rw-r--r--missing/x68.c4
-rwxr-xr-x[-rw-r--r--]mkconfig.rb137
-rw-r--r--node.h148
-rw-r--r--numeric.c1458
-rw-r--r--object.c1578
-rw-r--r--pack.c480
-rw-r--r--parse.y656
-rw-r--r--prec.c60
-rw-r--r--process.c1568
-rw-r--r--random.c325
-rw-r--r--range.c405
-rw-r--r--re.c621
-rw-r--r--regex.c178
-rw-r--r--regex.h4
-rw-r--r--ruby.17
-rw-r--r--ruby.c453
-rw-r--r--ruby.h154
-rw-r--r--rubyio.h34
-rw-r--r--rubysig.h32
-rwxr-xr-x[-rw-r--r--]rubytest.rb11
-rwxr-xr-xrunruby.rb71
-rw-r--r--sample/README3
-rw-r--r--sample/cal.rb237
-rw-r--r--sample/cbreak.rb4
-rw-r--r--sample/drb/README.rd56
-rw-r--r--sample/drb/README.rd.ja59
-rw-r--r--sample/drb/darray.rb12
-rw-r--r--sample/drb/darrayc.rb59
-rw-r--r--sample/drb/dbiff.rb51
-rw-r--r--sample/drb/dcdbiff.rb43
-rw-r--r--sample/drb/dchatc.rb41
-rw-r--r--sample/drb/dchats.rb70
-rw-r--r--sample/drb/dhasen.rb42
-rw-r--r--sample/drb/dhasenc.rb13
-rw-r--r--sample/drb/dlogc.rb16
-rw-r--r--sample/drb/dlogd.rb39
-rw-r--r--sample/drb/dqin.rb13
-rw-r--r--sample/drb/dqlib.rb14
-rw-r--r--sample/drb/dqout.rb14
-rw-r--r--sample/drb/dqueue.rb12
-rw-r--r--sample/drb/drbc.rb45
-rw-r--r--sample/drb/drbch.rb48
-rw-r--r--sample/drb/drbm.rb60
-rw-r--r--sample/drb/drbmc.rb22
-rw-r--r--sample/drb/drbs-acl.rb51
-rw-r--r--sample/drb/drbs.rb64
-rw-r--r--sample/drb/drbssl_c.rb19
-rw-r--r--sample/drb/drbssl_s.rb31
-rw-r--r--sample/drb/extserv_test.rb80
-rw-r--r--sample/drb/gw_ct.rb29
-rw-r--r--sample/drb/gw_cu.rb28
-rw-r--r--sample/drb/gw_s.rb10
-rw-r--r--sample/drb/holderc.rb22
-rw-r--r--sample/drb/holders.rb63
-rw-r--r--sample/drb/http0.rb77
-rw-r--r--sample/drb/http0serv.rb119
-rw-r--r--sample/drb/name.rb117
-rw-r--r--sample/drb/namec.rb36
-rw-r--r--sample/drb/old_tuplespace.rb214
-rw-r--r--sample/drb/rinda_ts.rb7
-rw-r--r--sample/drb/rindac.rb17
-rw-r--r--sample/drb/rindas.rb18
-rw-r--r--sample/drb/ring_echo.rb30
-rw-r--r--sample/drb/ring_inspect.rb30
-rw-r--r--sample/drb/ring_place.rb25
-rw-r--r--sample/drb/simpletuple.rb91
-rw-r--r--sample/drb/speedc.rb21
-rw-r--r--sample/drb/speeds.rb31
-rw-r--r--sample/dualstack-httpd.rb2
-rw-r--r--sample/erb/erb4html.rb60
-rw-r--r--sample/eval.rb2
-rw-r--r--sample/exyacc.rb4
-rw-r--r--sample/from.rb2
-rw-r--r--sample/goodfriday.rb48
-rw-r--r--sample/openssl/c_rehash.rb4
-rw-r--r--sample/openssl/cipher.rb12
-rw-r--r--sample/openssl/gen_csr.rb13
-rwxr-xr-xsample/optparse/subcommand.rb19
-rw-r--r--sample/philos.rb2
-rw-r--r--sample/regx.rb2
-rwxr-xr-xsample/rss/blend.rb79
-rwxr-xr-xsample/rss/convert.rb69
-rwxr-xr-xsample/rss/list_description.rb91
-rwxr-xr-xsample/rss/re_read.rb64
-rwxr-xr-xsample/rss/rss_recent.rb85
-rw-r--r--sample/soap/babelfish.rb16
-rw-r--r--sample/soap/calc/calc.rb17
-rw-r--r--sample/soap/calc/calc2.rb29
-rw-r--r--sample/soap/calc/client.rb26
-rw-r--r--sample/soap/calc/client2.rb29
-rw-r--r--sample/soap/calc/httpd.rb15
-rw-r--r--sample/soap/calc/server.cgi15
-rw-r--r--sample/soap/calc/server.rb17
-rw-r--r--sample/soap/calc/server2.rb20
-rw-r--r--sample/soap/digraph.rb43
-rw-r--r--sample/soap/exchange/client.rb19
-rw-r--r--sample/soap/exchange/exchange.rb17
-rw-r--r--sample/soap/exchange/httpd.rb15
-rw-r--r--sample/soap/exchange/server.cgi14
-rw-r--r--sample/soap/exchange/server.rb16
-rw-r--r--sample/soap/helloworld/hw_c.rb6
-rw-r--r--sample/soap/helloworld/hw_s.rb17
-rw-r--r--sample/soap/icd/IICD.rb17
-rw-r--r--sample/soap/icd/icd.rb46
-rw-r--r--sample/soap/raa/iRAA.rb154
-rw-r--r--sample/soap/raa/soap4r.rb30
-rw-r--r--sample/soap/sampleStruct/client.rb16
-rw-r--r--sample/soap/sampleStruct/httpd.rb15
-rw-r--r--sample/soap/sampleStruct/iSampleStruct.rb22
-rw-r--r--sample/soap/sampleStruct/sampleStruct.rb13
-rw-r--r--sample/soap/sampleStruct/server.cgi14
-rw-r--r--sample/soap/sampleStruct/server.rb16
-rw-r--r--sample/svr.rb8
-rw-r--r--sample/test.rb73
-rw-r--r--sample/time.rb16
-rw-r--r--sample/webrick/demo-app.rb66
-rw-r--r--sample/webrick/demo-multipart.cgi12
-rw-r--r--sample/webrick/demo-servlet.rb6
-rw-r--r--sample/webrick/demo-urlencoded.cgi12
-rw-r--r--sample/webrick/hello.cgi11
-rw-r--r--sample/webrick/hello.rb8
-rw-r--r--sample/webrick/httpd.rb23
-rw-r--r--sample/webrick/httpproxy.rb26
-rw-r--r--sample/webrick/httpsd.rb33
-rw-r--r--sample/wsdl/amazon/AmazonSearch.rb4693
-rw-r--r--sample/wsdl/amazon/AmazonSearchDriver.rb511
-rw-r--r--sample/wsdl/amazon/sampleClient.rb37
-rw-r--r--sample/wsdl/amazon/wsdlDriver.rb52
-rw-r--r--sample/wsdl/googleSearch/GoogleSearch.rb258
-rw-r--r--sample/wsdl/googleSearch/GoogleSearchDriver.rb101
-rw-r--r--sample/wsdl/googleSearch/README6
-rw-r--r--sample/wsdl/googleSearch/httpd.rb15
-rw-r--r--sample/wsdl/googleSearch/sampleClient.rb56
-rw-r--r--sample/wsdl/googleSearch/sjissearch.sh3
-rw-r--r--sample/wsdl/googleSearch/wsdlDriver.rb23
-rw-r--r--sample/wsdl/raa/raa.wsdl264
-rw-r--r--sample/wsdl/raa/soap4r.rb31
-rw-r--r--signal.c431
-rw-r--r--sprintf.c341
-rw-r--r--st.c45
-rw-r--r--st.h52
-rw-r--r--string.c2236
-rw-r--r--struct.c451
-rw-r--r--test/csv/bom.csv2
-rw-r--r--test/csv/mac.csv2
-rw-r--r--test/csv/test_csv.rb663
-rw-r--r--test/dbm/test_dbm.rb545
-rw-r--r--test/digest/test_digest.rb145
-rw-r--r--test/drb/drbtest.rb82
-rw-r--r--test/drb/ignore_test_drb.rb24
-rw-r--r--test/drb/test_drb.rb58
-rw-r--r--test/drb/test_drbssl.rb33
-rw-r--r--test/drb/test_drbunix.rb32
-rw-r--r--test/drb/ut_drb.rb21
-rw-r--r--test/drb/ut_drb_drbssl.rb2
-rw-r--r--test/drb/ut_eval.rb10
-rw-r--r--test/drb/ut_large.rb2
-rw-r--r--test/drb/ut_safe1.rb5
-rw-r--r--test/erb/hello.erb4
-rw-r--r--test/erb/test_erb.rb426
-rw-r--r--test/fileutils/fileasserts.rb34
-rw-r--r--test/fileutils/test_dryrun.rb25
-rw-r--r--test/fileutils/test_fileutils.rb615
-rw-r--r--test/fileutils/test_nowrite.rb28
-rw-r--r--test/fileutils/test_verbose.rb25
-rw-r--r--test/gdbm/test_gdbm.rb692
-rw-r--r--test/iconv/test_basic.rb49
-rw-r--r--test/iconv/test_option.rb31
-rw-r--r--test/iconv/test_partial.rb41
-rw-r--r--test/iconv/utils.rb26
-rw-r--r--test/io/nonblock/test_flush.rb28
-rw-r--r--test/logger/test_logger.rb108
-rw-r--r--test/matrix/test_matrix.rb43
-rw-r--r--test/matrix/test_vector.rb43
-rw-r--r--test/monitor/test_monitor.rb4
-rw-r--r--test/net/http/test_httpheader.rb317
-rw-r--r--test/net/http/test_https_proxy.rb37
-rw-r--r--test/net/imap/test_imap.rb11
-rw-r--r--test/net/pop/test_pop.rb132
-rw-r--r--test/nkf/test_kconv.rb71
-rw-r--r--test/nkf/test_nkf.rb16
-rw-r--r--test/openssl/ssl_server.rb81
-rw-r--r--test/openssl/test_asn1.rb197
-rw-r--r--test/openssl/test_cipher.rb95
-rw-r--r--test/openssl/test_digest.rb88
-rw-r--r--test/openssl/test_ec.rb113
-rw-r--r--test/openssl/test_hmac.rb34
-rw-r--r--test/openssl/test_ns_spki.rb59
-rw-r--r--test/openssl/test_pair.rb144
-rw-r--r--test/openssl/test_pkcs7.rb154
-rw-r--r--test/openssl/test_pkey_rsa.rb49
-rw-r--r--test/openssl/test_ssl.rb534
-rw-r--r--test/openssl/test_x509cert.rb175
-rw-r--r--test/openssl/test_x509crl.rb218
-rw-r--r--test/openssl/test_x509ext.rb74
-rw-r--r--test/openssl/test_x509name.rb266
-rw-r--r--test/openssl/test_x509req.rb140
-rw-r--r--test/openssl/test_x509store.rb218
-rw-r--r--test/openssl/utils.rb135
-rw-r--r--test/optparse/test_getopts.rb31
-rw-r--r--test/optparse/test_noarg.rb4
-rw-r--r--test/optparse/test_summary.rb23
-rw-r--r--test/pathname/test_pathname.rb478
-rw-r--r--test/rdoc/parsers/test_parse_c.rb261
-rw-r--r--test/readline/test_readline.rb84
-rw-r--r--test/rexml/test_document.rb66
-rw-r--r--test/rinda/test_rinda.rb544
-rw-r--r--test/rss/dot.pngbin0 -> 111 bytes-rw-r--r--test/rss/rss-assertions.rb2068
-rw-r--r--test/rss/rss-testcase.rb478
-rw-r--r--test/rss/test_1.0.rb296
-rw-r--r--test/rss/test_2.0.rb410
-rw-r--r--test/rss/test_accessor.rb103
-rw-r--r--test/rss/test_atom.rb681
-rw-r--r--test/rss/test_content.rb104
-rw-r--r--test/rss/test_dublincore.rb279
-rw-r--r--test/rss/test_image.rb214
-rw-r--r--test/rss/test_inherit.rb40
-rw-r--r--test/rss/test_itunes.rb347
-rw-r--r--test/rss/test_maker_0.9.rb438
-rw-r--r--test/rss/test_maker_1.0.rb484
-rw-r--r--test/rss/test_maker_2.0.rb705
-rw-r--r--test/rss/test_maker_atom_entry.rb367
-rw-r--r--test/rss/test_maker_atom_feed.rb389
-rw-r--r--test/rss/test_maker_content.rb47
-rw-r--r--test/rss/test_maker_dc.rb150
-rw-r--r--test/rss/test_maker_image.rb62
-rw-r--r--test/rss/test_maker_itunes.rb471
-rw-r--r--test/rss/test_maker_slash.rb37
-rw-r--r--test/rss/test_maker_sy.rb44
-rw-r--r--test/rss/test_maker_taxo.rb81
-rw-r--r--test/rss/test_maker_trackback.rb41
-rw-r--r--test/rss/test_maker_xml-stylesheet.rb83
-rw-r--r--test/rss/test_parser.rb62
-rw-r--r--test/rss/test_parser_1.0.rb511
-rw-r--r--test/rss/test_parser_2.0.rb122
-rw-r--r--test/rss/test_parser_atom_entry.rb163
-rw-r--r--test/rss/test_parser_atom_feed.rb276
-rw-r--r--test/rss/test_setup_maker_0.9.rb246
-rw-r--r--test/rss/test_setup_maker_1.0.rb550
-rw-r--r--test/rss/test_setup_maker_2.0.rb308
-rw-r--r--test/rss/test_setup_maker_atom_entry.rb409
-rw-r--r--test/rss/test_setup_maker_atom_feed.rb445
-rw-r--r--test/rss/test_setup_maker_itunes.rb144
-rw-r--r--test/rss/test_setup_maker_slash.rb38
-rw-r--r--test/rss/test_slash.rb64
-rw-r--r--test/rss/test_syndication.rb125
-rw-r--r--test/rss/test_taxonomy.rb172
-rw-r--r--test/rss/test_to_s.rb670
-rw-r--r--test/rss/test_trackback.rb135
-rw-r--r--test/rss/test_version.rb9
-rw-r--r--test/rss/test_xml-stylesheet.rb108
-rw-r--r--test/ruby/beginmainend.rb5
-rw-r--r--test/ruby/envutil.rb15
-rw-r--r--test/ruby/marshaltestlib.rb500
-rw-r--r--test/ruby/suicide.rb2
-rw-r--r--test/ruby/test_alias.rb2
-rw-r--r--test/ruby/test_array.rb1291
-rw-r--r--test/ruby/test_assignment.rb2
-rw-r--r--test/ruby/test_beginendblock.rb47
-rw-r--r--test/ruby/test_bignum.rb21
-rw-r--r--test/ruby/test_call.rb2
-rw-r--r--test/ruby/test_case.rb2
-rw-r--r--test/ruby/test_clone.rb2
-rw-r--r--test/ruby/test_condition.rb2
-rw-r--r--test/ruby/test_const.rb2
-rw-r--r--test/ruby/test_defined.rb2
-rw-r--r--test/ruby/test_dir.rb42
-rw-r--r--test/ruby/test_enum.rb258
-rw-r--r--test/ruby/test_enumerator.rb105
-rw-r--r--test/ruby/test_env.rb12
-rw-r--r--test/ruby/test_eval.rb37
-rw-r--r--test/ruby/test_exception.rb2
-rw-r--r--test/ruby/test_file.rb69
-rw-r--r--test/ruby/test_fixnum.rb26
-rw-r--r--test/ruby/test_float.rb109
-rw-r--r--test/ruby/test_gc.rb2
-rw-r--r--test/ruby/test_hash.rb569
-rw-r--r--test/ruby/test_ifunless.rb2
-rw-r--r--test/ruby/test_integer.rb653
-rw-r--r--test/ruby/test_io.rb11
-rw-r--r--test/ruby/test_iterator.rb28
-rw-r--r--test/ruby/test_marshal.rb323
-rw-r--r--test/ruby/test_math.rb2
-rw-r--r--test/ruby/test_method.rb53
-rw-r--r--test/ruby/test_objectspace.rb36
-rw-r--r--test/ruby/test_pack.rb83
-rw-r--r--test/ruby/test_path.rb180
-rw-r--r--test/ruby/test_pipe.rb2
-rw-r--r--test/ruby/test_proc.rb27
-rw-r--r--test/ruby/test_process.rb41
-rw-r--r--test/ruby/test_rand.rb131
-rw-r--r--test/ruby/test_range.rb8
-rw-r--r--test/ruby/test_readpartial.rb74
-rw-r--r--test/ruby/test_settracefunc.rb138
-rw-r--r--test/ruby/test_signal.rb45
-rw-r--r--test/ruby/test_sleep.rb10
-rw-r--r--test/ruby/test_string.rb19
-rw-r--r--test/ruby/test_stringchar.rb52
-rw-r--r--test/ruby/test_struct.rb2
-rw-r--r--test/ruby/test_super.rb134
-rw-r--r--test/ruby/test_symbol.rb92
-rw-r--r--test/ruby/test_system.rb19
-rw-r--r--test/ruby/test_time.rb95
-rw-r--r--test/ruby/test_trace.rb2
-rw-r--r--test/ruby/test_variable.rb2
-rw-r--r--test/ruby/test_whileuntil.rb2
-rw-r--r--test/ruby/ut_eof.rb110
-rw-r--r--test/runner.rb2
-rw-r--r--test/sdbm/test_sdbm.rb534
-rw-r--r--test/soap/asp.net/hello.wsdl96
-rw-r--r--test/soap/asp.net/test_aspdotnet.rb111
-rw-r--r--test/soap/calc/calc2.rb4
-rw-r--r--test/soap/calc/server2.rb4
-rw-r--r--test/soap/calc/test_calc.rb13
-rw-r--r--test/soap/calc/test_calc2.rb20
-rw-r--r--test/soap/calc/test_calc_cgi.rb8
-rw-r--r--test/soap/fault/test_customfault.rb58
-rw-r--r--test/soap/header/server.cgi119
-rw-r--r--test/soap/header/test_authheader.rb240
-rw-r--r--test/soap/header/test_authheader_cgi.rb121
-rw-r--r--test/soap/header/test_simplehandler.rb116
-rw-r--r--test/soap/helloworld/test_helloworld.rb13
-rw-r--r--test/soap/marshal/cmarshal.rb142
-rw-r--r--test/soap/marshal/test_marshal.rb496
-rw-r--r--test/soap/marshal/test_struct.rb4
-rw-r--r--test/soap/ssl/README1
-rw-r--r--test/soap/ssl/ca.cert23
-rw-r--r--test/soap/ssl/client.cert19
-rw-r--r--test/soap/ssl/client.key15
-rw-r--r--test/soap/ssl/server.cert19
-rw-r--r--test/soap/ssl/server.key15
-rw-r--r--test/soap/ssl/sslsvr.rb57
-rw-r--r--test/soap/ssl/subca.cert21
-rw-r--r--test/soap/ssl/test_ssl.rb204
-rw-r--r--test/soap/struct/test_struct.rb77
-rw-r--r--test/soap/swa/test_file.rb73
-rw-r--r--test/soap/test_basetype.rb52
-rw-r--r--test/soap/test_envelopenamespace.rb92
-rw-r--r--test/soap/test_httpconfigloader.rb39
-rw-r--r--test/soap/test_mapping.rb59
-rw-r--r--test/soap/test_no_indent.rb86
-rw-r--r--test/soap/test_property.rb424
-rw-r--r--test/soap/test_soapelement.rb5
-rw-r--r--test/soap/test_streamhandler.rb209
-rw-r--r--test/soap/test_styleuse.rb333
-rw-r--r--test/soap/wsdlDriver/README.txt2
-rw-r--r--test/soap/wsdlDriver/calc.wsdl126
-rw-r--r--test/soap/wsdlDriver/document.wsdl54
-rw-r--r--test/soap/wsdlDriver/echo_version.rb20
-rw-r--r--test/soap/wsdlDriver/simpletype.wsdl63
-rw-r--r--test/soap/wsdlDriver/test_calc.rb100
-rw-r--r--test/soap/wsdlDriver/test_document.rb78
-rw-r--r--test/soap/wsdlDriver/test_simpletype.rb87
-rw-r--r--test/socket/test_nonblock.rb179
-rw-r--r--test/socket/test_socket.rb83
-rw-r--r--test/socket/test_unix.rb141
-rw-r--r--test/stringio/test_stringio.rb29
-rw-r--r--test/strscan/test_stringscanner.rb219
-rw-r--r--test/testunit/collector/test_dir.rb37
-rw-r--r--test/testunit/test_assertions.rb70
-rw-r--r--test/testunit/util/test_procwrapper.rb2
-rwxr-xr-xtest/thread/lbtest.rb51
-rw-r--r--test/thread/test_thread.rb81
-rw-r--r--test/uri/test_common.rb26
-rw-r--r--test/uri/test_ftp.rb22
-rw-r--r--test/uri/test_generic.rb145
-rw-r--r--test/webrick/.htaccess1
-rw-r--r--test/webrick/test_cgi.rb71
-rw-r--r--test/webrick/test_cookie.rb104
-rw-r--r--test/webrick/test_filehandler.rb200
-rw-r--r--test/webrick/test_httpauth.rb82
-rw-r--r--test/webrick/test_httprequest.rb272
-rw-r--r--test/webrick/test_httpserver.rb260
-rw-r--r--test/webrick/test_httputils.rb96
-rw-r--r--test/webrick/test_httpversion.rb40
-rw-r--r--test/webrick/test_server.rb64
-rw-r--r--test/webrick/utils.rb52
-rw-r--r--test/webrick/webrick.cgi36
-rw-r--r--test/webrick/webrick_long_filename.cgi36
-rw-r--r--test/wsdl/any/any.wsdl50
-rw-r--r--test/wsdl/any/expectedDriver.rb54
-rw-r--r--test/wsdl/any/expectedEcho.rb14
-rw-r--r--test/wsdl/any/expectedService.rb52
-rw-r--r--test/wsdl/any/test_any.rb58
-rw-r--r--test/wsdl/axisArray/test_axisarray.rb5
-rw-r--r--test/wsdl/datetime/DatetimeService.rb42
-rw-r--r--test/wsdl/datetime/test_datetime.rb52
-rw-r--r--test/wsdl/document/document.wsdl74
-rw-r--r--test/wsdl/document/echo.rb92
-rw-r--r--test/wsdl/document/number.wsdl54
-rw-r--r--test/wsdl/document/ping_nosoapaction.wsdl66
-rw-r--r--test/wsdl/document/test_nosoapaction.rb109
-rw-r--r--test/wsdl/document/test_number.rb99
-rw-r--r--test/wsdl/document/test_rpc.rb177
-rw-r--r--test/wsdl/map/map.wsdl50
-rw-r--r--test/wsdl/map/test_map.rb70
-rw-r--r--test/wsdl/marshal/person.wsdl21
-rw-r--r--test/wsdl/marshal/person_org.rb22
-rw-r--r--test/wsdl/marshal/test_wsdlmarshal.rb80
-rw-r--r--test/wsdl/multiplefault.wsdl68
-rw-r--r--test/wsdl/qualified/lp.rb0
-rw-r--r--test/wsdl/qualified/lp.wsdl47
-rw-r--r--test/wsdl/qualified/lp.xsd26
-rw-r--r--test/wsdl/qualified/np.wsdl50
-rw-r--r--test/wsdl/qualified/test_qualified.rb154
-rw-r--r--test/wsdl/qualified/test_unqualified.rb143
-rw-r--r--test/wsdl/raa/RAAService.rb3
-rw-r--r--test/wsdl/raa/server.rb103
-rw-r--r--test/wsdl/raa/test_raa.rb19
-rw-r--r--test/wsdl/ref/expectedProduct.rb90
-rw-r--r--test/wsdl/ref/product.wsdl86
-rw-r--r--test/wsdl/ref/test_ref.rb54
-rw-r--r--test/wsdl/rpc/echoDriver.rb55
-rw-r--r--test/wsdl/rpc/echo_serviceClient.rb23
-rw-r--r--test/wsdl/rpc/rpc.wsdl75
-rw-r--r--test/wsdl/rpc/test-rpc-lit.wsdl364
-rw-r--r--test/wsdl/rpc/test-rpc-lit12.wsdl455
-rw-r--r--test/wsdl/rpc/test_rpc.rb118
-rw-r--r--test/wsdl/rpc/test_rpc_lit.rb399
-rw-r--r--test/wsdl/simpletype/rpc/expectedClient.rb34
-rw-r--r--test/wsdl/simpletype/rpc/expectedDriver.rb62
-rw-r--r--test/wsdl/simpletype/rpc/expectedEchoVersion.rb23
-rw-r--r--test/wsdl/simpletype/rpc/expectedServant.rb32
-rw-r--r--test/wsdl/simpletype/rpc/expectedService.rb60
-rw-r--r--test/wsdl/simpletype/rpc/rpc.wsdl80
-rw-r--r--test/wsdl/simpletype/rpc/test_rpc.rb62
-rw-r--r--test/wsdl/simpletype/simpletype.wsdl95
-rw-r--r--test/wsdl/simpletype/test_simpletype.rb99
-rw-r--r--test/wsdl/soap/soapbodyparts.wsdl103
-rw-r--r--test/wsdl/soap/test_soapbodyparts.rb79
-rw-r--r--test/wsdl/test_emptycomplextype.rb4
-rw-r--r--test/wsdl/test_multiplefault.rb39
-rw-r--r--test/xmlrpc/data/bug_bool.expected3
-rw-r--r--test/xmlrpc/data/bug_bool.xml8
-rw-r--r--test/xmlrpc/data/bug_cdata.expected3
-rw-r--r--test/xmlrpc/data/bug_cdata.xml8
-rw-r--r--test/xmlrpc/data/bug_covert.expected10
-rw-r--r--test/xmlrpc/data/bug_covert.xml6
-rw-r--r--test/xmlrpc/data/datetime_iso8601.xml8
-rw-r--r--test/xmlrpc/data/fault.xml16
-rw-r--r--test/xmlrpc/data/value.expected7
-rw-r--r--test/xmlrpc/data/value.xml22
-rw-r--r--test/xmlrpc/data/xml1.expected243
-rw-r--r--test/xmlrpc/data/xml1.xml1
-rw-r--r--test/xmlrpc/test_cookie.rb96
-rw-r--r--test/xmlrpc/test_datetime.rb159
-rw-r--r--test/xmlrpc/test_features.rb48
-rw-r--r--test/xmlrpc/test_marshal.rb93
-rw-r--r--test/xmlrpc/test_parser.rb85
-rw-r--r--test/xmlrpc/test_webrick_server.rb98
-rw-r--r--test/xmlrpc/webrick_testing.rb37
-rw-r--r--test/xsd/codegen/test_classdef.rb214
-rw-r--r--test/xsd/test_noencoding.rb13
-rw-r--r--test/xsd/test_xmlschemaparser.rb2
-rw-r--r--test/xsd/test_xsd.rb546
-rw-r--r--test/yaml/test_yaml.rb194
-rw-r--r--test/yaml/test_yamlstore.rb74
-rw-r--r--test/zlib/test_zlib.rb57
-rw-r--r--time.c819
-rw-r--r--util.c3478
-rw-r--r--util.h5
-rw-r--r--variable.c352
-rw-r--r--version.c38
-rw-r--r--version.h39
-rw-r--r--vms/config.h102
-rw-r--r--vms/config.h_in61
-rw-r--r--vms/vms.h6
-rw-r--r--vms/vmsruby_private.c52
-rw-r--r--vms/vmsruby_private.h7
-rw-r--r--win32/Makefile.sub720
-rwxr-xr-xwin32/configure.bat68
-rw-r--r--win32/dir.h4
-rwxr-xr-xwin32/ifchange.bat32
-rwxr-xr-x[-rw-r--r--]win32/mkexports.rb17
-rwxr-xr-x[-rw-r--r--]win32/resource.rb33
-rwxr-xr-xwin32/rm.bat8
-rw-r--r--win32/setup.mak124
-rw-r--r--win32/win32.c1613
-rw-r--r--win32/win32.h132
-rw-r--r--wince/Makefile.sub737
-rwxr-xr-x[-rw-r--r--]wince/configure.bat161
-rw-r--r--wince/mkconfig_wce.rb7
-rw-r--r--wince/mkexports.rb35
-rw-r--r--wince/resource.rb96
-rw-r--r--wince/setup.mak14
-rw-r--r--wince/sys/types.h7
2280 files changed, 319134 insertions, 73288 deletions
diff --git a/.cvsignore b/.cvsignore
index 52a5620133..a72211d03f 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -3,8 +3,14 @@
*.rej
*.sav
*~
+.*.list
+.*.time
.ccmalloc
.ppack
+.ext
+.git
+.svn
+.pc
COPYING.LIB
ChangeLog.pre-alpha
ChangeLog.pre1_1
@@ -22,32 +28,20 @@ config.h.in
config.log
config.status
configure
-foo.rb
libruby.so.*
miniruby
-miniruby.elhash
-miniruby.elhash2
-miniruby.orig2
-miniruby.plhash
-miniruby.plhash2
-modex.rb
newdate.rb
newver.rb
parse.c
-parse.y.try
-pitest.rb
+patches
ppack
preview
rbconfig.rb
-rename2.h
repack
riscos
rubicon
ruby
ruby-man.rd.gz
-rubyunit
-st.c.power
-this that
tmp
web
y.output
diff --git a/.document b/.document
new file mode 100644
index 0000000000..230c50e387
--- /dev/null
+++ b/.document
@@ -0,0 +1,16 @@
+# This file determines which files in the
+# Ruby hierarchy will be processed by the RDoc
+# tool when it is given the top-level directory
+# as an argument
+
+# Process all the C source files
+*.c
+
+# the lib/ directory (which has its own .document file)
+
+lib
+
+
+# and some of the ext/ directory (which has its own .document file)
+
+ext
diff --git a/COPYING b/COPYING
index 870a5f22d6..9043404a83 100644
--- a/COPYING
+++ b/COPYING
@@ -1,6 +1,6 @@
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
You can redistribute it and/or modify it under either the terms of the GPL
-(see the file GPL), or the conditions below:
+version 2 (see the file GPL), or the conditions below:
1. You may make and give away verbatim copies of the source form of the
software without restriction, provided that you duplicate all of the
diff --git a/ChangeLog b/ChangeLog
index a2cb2ff8db..917ed9da0f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19794 @@
+Sun Feb 22 22:08:45 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (stack_extend): streamlined rb_thread_restore_context()
+ to ensure O(1) time. based on a patch by Brent Roman <brent AT
+ mbari.org>.
+
+Sun Feb 22 22:03:40 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (cc_mark): frees the continuation's stack if its thread
+ is dead to avoid recursive gc that segfaults. [ruby-core:13889]
+ a patch by Brent Roman <brent AT mbari.org>.
+
+ * eval.c (rb_cont_check): checks for valid continuation instance.
+
+ * eval.c (rb_callcc): assigns th->thread before scope_dup() to
+ avoid segfaults if this scope_dup() triggers a gc pass.
+ a patch by Brent Roman <brent AT mbari.org>.
+
+Sun Feb 22 21:43:34 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (ruby_float_step): extracted from num_step().
+
+ * range.c (range_step): uses ruby_float_step() for float range.
+ [ruby-dev:37691]
+
+Sun Feb 22 00:49:36 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake): does not use both of makefile.rb and
+ extconf.rb at the same time.
+
+ * lib/mkmf.rb (DLLIB): depends on Makefile. [ruby-core:21096]
+
+Sun Feb 22 00:19:05 2009 Tanaka Akira <akr@fsij.org>
+
+ * eval.c (rb_thread_schedule): Don't change status of threads which
+ don't run next even if select notify readability/writability.
+ [ruby-core:20446]
+
+Fri Feb 20 20:43:13 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::List#summarize): gives priority
+ to latter switches. [ruby-dev:36692]
+
+ * lib/optparse.rb (OptionParser#summarize): do not append
+ unnecessary line terminator.
+
+Fri Feb 20 19:35:08 2009 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/session.rb: ignore session_id options fixed.[Bug #605]
+
+Fri Feb 20 18:06:40 2009 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 20854 from trunk.
+
+ * lib/xmlrpc/server.rb: Restricting method inspection to show only
+ non-inherited public methods. [ruby-core:20603]
+
+ * lib/xmlrpc/server.rb: Fixing method inspection so it doesn't
+ trigger XMLRPC::FaultException when used. [ruby-core:20604]
+
+Fri Feb 20 01:41:08 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/sync.rb (Sync_m#sync_try_lock): wrong variable name fixed.
+ a patch from [ruby-core:20561]
+
+ * lib/sync.rb (Sync_m::Err.Fail): turn off Thread.critical before
+ exit.
+
+Thu Feb 19 18:02:10 2009 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * pack.c (pack_pack): fixed odd act of 'm*', 'M*', and 'P*'.
+ just ignores '*' in these cases.
+ [ruby-dev:37289]
+
+Thu Feb 19 17:26:11 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * pack.c (pack_pack): fixed length for odd length string.
+ [ruby-dev:37283]
+
+Thu Feb 19 17:13:13 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_yield_0): Qundef means no argument. [ruby-Bugs-22525]
+
+Wed Feb 18 22:28:00 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_isatty): check whether fd is valid.
+
+Wed Feb 18 22:24:23 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (waitpid): fix bug of checking child slot.
+
+ * win32/win32.c (FindChildSlotByHandle): new.
+
+Wed Feb 18 22:17:04 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_pack): propagate taint status from format string to
+ result string.
+
+Wed Feb 18 22:07:44 2009 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * ext/gdbm/gdbm.c: do not set members of RSTRING(str) directly.
+ [ruby-dev:37182]
+
+ * ext/gdbm/gdbm.c (rb_gdbm_nextkey): fix memory leak.
+
+Tue Feb 17 11:58:58 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (str_independent): no independent string points null_str.
+ [ruby-core:20082]
+
+Mon Feb 16 23:30:24 2009 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/blt.rb, ext/tk/lib/tkextlib/blt/vector.rb:
+ fix NameError bug.
+
+Mon Feb 16 23:08:22 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_s_alloc, rb_str_replace): use null_str as well as
+ rb_string_value so that extension libraries do not segfault.
+ [ruby-core:19971]
+
+ * string.c (rb_str_replace): reduced unnecessary malloc and copy.
+
+Mon Feb 16 22:45:41 2009 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/rinda/test_rinda.rb: fixed fails occasionally [ruby-dev:37119].
+ thanks, shinichiro.h.
+
+Mon Feb 16 22:36:37 2009 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (DRbConn::alive?): fixed NoMethodError problem
+ from NaHi [ruby-dev:37110].
+
+Sun Feb 15 04:21:42 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/net/ftp.rb (Net::FTP#open_socket): SOCKSsocket is obsolete.
+ a patch from Alan Johnson <alan.wayne.johnson at gmail.com> in
+ [ruby-core:19982].
+
+Fri Feb 13 19:18:42 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/logger.rb (ProgName): fixed for svn, based on a patch from
+ Nobuhiro IMAI at [ruby-dev:37108].
+
+Sun Feb 15 04:17:40 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/webrick/httprequest.rb (WEBrick::HTTPRequest#read_request_line):
+ use non-greedy match for path retrieval to avoid huge recursion
+ for insanely long path.
+
+Fri Feb 13 19:04:54 2009 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * shell/command-processor.rb: undefined method `top_level_test' in
+ Shell#test. [ruby-list:45634]
+
+Tue Feb 10 20:00:52 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (load_lock): makes circular require deadlock.
+ [ruby-core:19821]
+
+Tue Feb 10 19:40:58 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_feature_p): returns found feature name if loading.
+ [ruby-core:19798]
+
+ * eval.c (search_required): ditto.
+
+Wed Feb 11 23:37:35 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c (VpMidRound): Round method bug
+ pointed by Ryan Platte fixed(Patch to the patch from "NATORI
+ Shin"). [ruby-talk:273360]
+ back ported from 1.9. fix [ruby-core:19791]
+
+Mon Feb 9 17:35:38 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_accept): secure fd before accept because if
+ error causes in securing, cannot restore the state of accepted
+ socket.
+ fixed [ruby-core:19728]
+
+Mon Feb 9 13:42:15 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (ifs_open_socket): should retry without proto_buffer
+ if cannot find the suitable protocol. a patch from Heesob Park.
+ fixed [ruby-core:19713]
+
+Mon Feb 9 13:40:21 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_ungetc): should allow ungetc at
+ the top of the buffer. ref #701
+
+Thu Feb 5 09:38:48 2009 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c (h_conv): can't guess UTF-8 input in
+ conversion. [ruby-list:45609]
+
+Thu Feb 5 09:03:21 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/rexml/entity.rb (unnormalized): do not call
+ document.record_entity_expansion if document is nil.
+ see <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=502535>.
+ Thanks, Naohisa Goto. backported from trunk.
+
+ * test/rexml/test_document.rb: ditto.
+
+Thu Feb 5 08:55:24 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_join): do not repeat self in a recursive array.
+ [ruby-dev:37019]
+
+Wed Feb 4 14:26:58 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (dir_globs): need taint check. reported by steve
+ <oksteev at gmail.com>
+
+Tue Feb 3 14:35:26 2009 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/net/pop.rb: check for invalid APOP timestamp. (CVE-2007-1558)
+ [ruby-dev:36631]
+
+ * test/net/pop/test_pop.rb: ditto.
+
+Mon Feb 2 20:03:58 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (time_mdump, time_mload): preserves GMT status.
+ [ruby-core:19252]
+
+Mon Feb 2 11:34:51 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * variable.c (autoload_delete, autoload_file): should not delete
+ autoload table, since it may be shared with duplicated modules.
+ [ruby-core:19181]
+
+Thu Jan 29 11:54:22 2009 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (today,now): should produce own instances.
+ [ruby-talk:317020]
+
+Wed Jan 28 22:51:55 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_mod_modfunc): method undefined in included module
+ may not have nd_body. [ruby-core:18738]
+
+Wed Jan 28 20:53:27 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (marshal_dump): fixed for check_dump_arg.
+
+Tue Jan 27 17:30:11 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (marshal_dump): initializes dump_arg before any funcall.
+ [ruby-dev:36648]
+
+Tue Jan 27 15:17:35 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/socket/socket.c (host_str): numeric address should be unsigned.
+ [ruby-core:18971]
+
+Mon Jan 26 11:12:03 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/tmpdir.rb: setup buffer with nul characters instead of spaces.
+ fixed [ruby-dev:36493]
+
+Sun Jan 25 00:07:23 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rexml/formatters/pretty.rb (REXML::Formatters::Pretty#wrap):
+ abandon wrapping if the line contains no space. [ruby-dev:36045]
+ fix: #342
+
+Sun Jan 25 00:02:23 2009 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * lib/matrix.rb (Vector#eql?): typo of the method name as "eqn?".
+ (Vector#eqn?): removed. Defined by mistake.
+ Fixes [ruby-dev:36294]. Reported by weda <weda AT
+ issp.u-tokyo.ac.jp> and an anonymous user.
+
+ * test/matrix/test_matrix.rb: added.
+
+ * test/matrix/test_vector.rb: added.
+
+Fri Jan 23 11:49:45 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * NEWS: added an entry for REXML.
+
+ * lib/rexml/document.rb: fixed typo.
+
+Fri Jan 23 11:49:45 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/rexml/document.rb: limit entity expansion. Thanks, Luka
+ Treiber, Mitja Kolsek, and Michael Koziarski. backported from
+ trunk r19033, r19317, r19318.
+
+ * lib/rexml/entity.rb: ditto.
+
+ * test/rexml/test_document.rb: ditto.
+
+Thu Jan 22 15:19:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (marshal_load): arg.data is no longer a VALUE but a
+ st_table, and freed in load_ensure. pointed out by pegacorn.
+ [ruby-dev:37008]
+
+Thu Jan 22 15:19:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (rb_mark_set): new function to mark keys.
+
+ * marshal.c (struct dump_arg, struct load_arg): added wrappers to mark
+ data entries. backport from trunk r13527,r13528,r13961,r16533.
+ [ruby-dev:36082]
+
+Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (filetime_to_timeval): new function, split from
+ gettimeofday().
+
+ * win32/win32.c (gettimeofday): use above function.
+
+ * win32/win32.c (filetime_to_unixtime): ditto. [ruby-dev:36135]
+
+Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (gettimeofday): tv_usec is usec, not msec.
+ [ruby-dev:36094]
+
+Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (gettimeofday): calc tv_sec and tv_usec from system
+ time by myself. [ruby-dev:36084]
+
+Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (gettimeofday): shouldn't use mktime(2) because it's
+ buggy about handling summer time.
+ reported by Yoshikawa <yoshixool AT gmail.com> at [ruby-dev:36071]
+
+Tue Jan 20 12:23:38 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/scanf.rb (Scanf::FormatSpecifier#initialize): %i should accept
+ single digit decimal. [ruby-core:18355]
+
+Mon Jan 19 18:25:28 2009 Tanaka Akira <akr@fsij.org>
+
+ * configure.in (rb_cv_broken_glibc_ia64_erfc): renamed from
+ rb_broken_glibc_ia64_erfc.
+ [ruby-core:18228]
+
+Sat Jan 17 12:16:10 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * random.c (Init_Random): always initialize seed.
+
+Fri Jan 16 10:59:31 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (clone_method): should copy cbase in cref as well.
+ [ruby-dev:35116]
+
+ * node.h (NEW_CREF): new NEW_ macro.
+
+ * eval.c (PUSH_CREF): use NEW_CREF().
+
+Thu Jan 15 14:34:32 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (STACK_LEVEL_MAX, ruby_stack_length): returns size_t.
+ [ruby-core:18207]
+Wed Jan 14 10:39:56 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * stable/ext/socket/socket.c (NI_MAXHOST, NI_MAXSERV): fixed invalid
+ preprocessor directives. a patch from Peter Bowen at
+ [ruby-core:18211].
+
+Tue Jan 13 04:40:30 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/ftp.rb (login): raise FTPReplyError if passwd or acct
+ is not supplied. backported from trunk. fixed [ruby-core:18058].
+
+Mon Jan 12 00:23:37 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (gc_sweep, obj_free, run_final): defer finalizers of IO and
+ Data. [ruby-dev:35578]
+
+ * gc.c (rb_gc_call_finalizer_at_exit): self-referencing finalizers
+ cannot be invoked. [ruby-dev:35681]
+
+Sun Jan 11 11:33:27 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/ftp.rb (chdir): handle 5xx errors correctly.
+ backported from trunk. fixed [ruby-core:18057].
+
+Fri Jan 9 19:25:25 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (disconnect): do not refer SSL::SSLSocket for
+ environments without OpenSSL. backported from trunk.
+ fixed [ruby-dev:35755].
+
+Thu Jan 8 13:24:23 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (deferred_nodes, compstmt, arg, fixup_nodes, range_op): fix
+ up fixnum range literal in conditional as automagical line number
+ comparison. [ruby-core:12124], [ruby-dev:35731]
+
+Wed Jan 7 10:09:46 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (timeofday): use monotonic clock. based on a patch
+ from zimbatm <zimbatm@oree.ch> in [ruby-core:16627].
+
+Tue Jan 6 09:03:35 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yylex): 8 and 9 in octal integer should cause compile
+ error. [ruby-dev:35729]
+
+Mon Jan 5 11:14:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_schedule): runs deferred finalizers.
+
+ * gc.c (gc_sweep): sets rb_thread_pending to run deferred finalizers.
+
+ * rubysig.h (CHECK_INTS): now checks rb_thread_pending even on
+ platforms where setitimer is not available. [ruby-core:18045]
+
+Mon Jan 5 11:14:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * rubysig.h (CHECK_INTS): gives the chance to perform to deferred
+ finalizers before explicit GC.start or the process termination.
+ [ruby-core:18045]
+
+Sun Jan 4 04:49:01 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_telldir): just returns loc.
+
+ * win32/win32.c (rb_w32_rewinddir): needs to intialize loc.
+ [ruby-core:18041]
+
+Sun Jan 4 04:45:26 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_select): recalc the rest of timeout for each
+ iterations. [ruby-core:18015]
+
+Fri Jan 2 03:08:47 2009 Kouhei Sutou <kou@cozmixng.org>
+
+ * test/rss/: use PNG instead of zlib as binary data. [ruby-dev:35666]
+
+Tue Nov 11 01:07:32 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * configure.in: fix SEGV on Mac OS X 10.5.3 with --enable-pthread.
+ a patch from Wataru Kimura in Bug #193 [ruby-core:17333].
+
+Mon Aug 11 09:37:17 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dl/dl.c (rb_str_to_ptr): should propagate taint to dlptr.
+
+ * ext/dl/dl.c (rb_ary_to_ptr): ditto.
+
+ * ext/dl/sym.c (rb_dlsym_call): should check taint of DLPtrData as
+ well.
+
+Fri Aug 8 10:53:52 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/resolv.rb: randomize source port and transaction id.
+ CVE-2008-1447.
+
+ * lib/resolv-replace.rb (UDPSocket#bind): don't resolv host if host is
+ "".
+
+Mon Aug 4 14:49:35 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * lib/net/smtp.rb (Net::SMTP::rcptto): fix a typo. a patch from
+ Masao Takaku <masao at nii.ac.jp>
+ fix [ruby-dev:35489].
+
+Mon Aug 4 14:13:15 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * regex.c (xmalloc, xrealloc, xfree): not to use ruby managed memory.
+
+ * regex.c (DOUBLE_STACK, re_compile_fastmap0, re_adjust_startpos),
+ (re_search, re_match_exec): check if failed to allocate memory.
+
+Mon Aug 4 13:53:42 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big2str0, bigsqr): made interruptible. [ruby-Bugs-20622]
+
+Mon Aug 4 13:31:41 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * numeric.c (check_uint, rb_num2uint, rb_fix2uint): fixed wrong check
+ about 64bit positive value.
+Mon Aug 4 13:31:41 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * numeric.c (check_uint, rb_num2uint, rb_fix2uint): strict check.
+ fixed [ruby-dev:33683]
+
+Thu Jul 17 21:42:07 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * lib/net/smtp.rb (Net::SMTP::start): revert to avoid RFC2821
+ violation. [ruby-dev:35487]
+
+Thu Jul 17 21:32:49 2008 Tanaka Akira <akr@fsij.org>
+
+ * string.c (rb_str_format_m): make tmp volatile to avoid possible GC
+ problem.
+
+Thu Jul 17 21:30:55 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#environment): requires shellwords.
+ [ruby-dev:35466]
+
+Thu Jul 17 02:05:10 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/xmlrpc/client.rb (XMLRPC::Client#do_rpc): requires
+ webrick/cookie. [ ruby-Bugs-21139 ]
+
+Thu Jul 17 01:38:31 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * ext/zlib/zlib.c (rb_gzfile_set_mtime): fix typo. [ruby-core:17713]
+
+Sun Jul 13 00:08:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/ipaddr.rb (IPAddr#initialize): get rid of ArgumentError in
+ IPAddr#to_range. a patch from okkez <okkez000 AT gmail.com> in
+ [ruby-dev:35091].
+
+Sun Jul 13 00:04:38 2008 Tanaka Akira <akr@fsij.org>
+
+ * configure.in (erfc): erfc of glibc comes with Debian GNU/Linux Etch
+ on IA64 is broken. erfc(10000.0) aborts.
+ use missing/erf.c instead.
+ http://sources.redhat.com/ml/libc-hacker/2005-08/msg00008.html
+
+Thu Jul 10 18:50:48 2008 Tanaka Akira <akr@fsij.org>
+
+ * common.mk (SPEC_GIT_BASE): update RubySpec GIT URL.
+
+Thu Jul 10 18:46:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_extname): fix for file name with spaces.
+ [ruby-talk:307404]
+
+Thu Jul 10 18:42:37 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb (PercentScanner#scan): fix %% line bug. [ruby-core:17491]
+
+ * test/erb/test_erb.rb (test_percent): ditto.
+
+Thu Jul 10 18:40:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/net/ftp.rb (Net::FTP#sendport): use divmod. [ruby-core:17557]
+
+Thu Jul 10 18:36:53 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * ruby.c: Mac OS X needs origargc times of '\0' in
+ origargv. [ruby-dev:35308]
+
+Thu Jul 10 13:53:08 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/ruby.h (POSFIXABLE): use FIXNUM_MAX+1 instead of
+ FIXNUM_MAX to make it possible to convert to double accurately.
+ It assumes FLT_RADIX is 2.
+ fix RubyForge bug #14102.
+ backported from 1.9.
+
+Mon Jul 7 16:21:38 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/net/smtp.rb (Net::SMTP::start): use 'localhost' instead of
+ 'localhost.localdomain'. [ruby-dev:35333]
+
+ * lib/net/smtp.rb (Net::SMTP::SMTP.start): ditto.
+
+Mon Jul 7 15:02:13 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_longjmp): duplicate the thrown exception to set backtrace
+ if it was frozen. clear all raised flags.
+
+ * eval.c (stack_check): leave clearing flag to rb_longjmp.
+
+ * eval.c (rb_thread_set_raised, rb_thread_reset_raised): use generic
+ flags.
+
+ * eval.c (Init_Proc), gc.c (Init_GC): freeze preallocated special exceptions.
+
+ * gc.c (rb_memerror): use thread raised flag instead of static flag,
+ and raise nomem_error without backtrace if failed to make backtrace.
+ [ruby-dev:34724]
+
+ * gc.c (ruby_xmalloc): increase malloc_increase only if malloc
+ succeeds. failed malloc size can be huge. it may increase
+ malloc_limit too big which cause less GC and memory full.
+ (ruby_xrealloc): ditto.
+
+Mon Jul 7 12:23:05 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c: avoid creating Ruby object during
+ GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313]
+
+ * ext/win32ole/tests: add test_win32ole_event.rb, remove
+ testOLEEVENT.rb
+
+ * ext/win32ole/tests/testWIN32OLE.rb(test_convert_bignum):
+ fix test.
+
+Mon Jul 7 12:23:05 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * gc.c: add rb_during_gc(). based on a patch from arton <artonx AT
+ yahoo.co.jp> at [ruby-dev:35313].
+
+ * intern.h: ditto.
+
+Thu Jul 3 20:13:20 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (w_object, marshal_dump, r_object0, marshal_load): search
+ public methods only. [ruby-core:17283]
+
+ * object.c (convert_type): ditto.
+
+ * lib/singleton.rb (Singleton#_dump): conversion method should be
+ public.
+
+Wed Jul 2 19:06:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::QueryExtension.read_multipart): blanks inside
+ double quotes are allowed. [ruby-list:45140]
+
+Wed Jul 2 19:03:37 2008 Tanaka Akira <akr@fsij.org>
+
+ * numeric.c (num_coerce): call rb_Float(x) first. don't depend on
+ evaluation order of function arguments.
+
+Wed Jul 2 18:57:19 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/syslog/syslog.c (syslog_write): syslog operations should be
+ protected from $SAFE level 4. a patch from Keita Yamaguchi
+ <keita.yamaguchi at gmail.com>.
+
+ * ext/syslog/syslog.c (mSyslog_close): ditto.
+
+ * ext/syslog/syslog.c (mSyslog_set_mask): ditto.
+
+Wed Jul 2 18:26:20 2008 Tanaka Akira <akr@fsij.org>
+
+ * math.c (domain_check): fix preprocess condition.
+
+Wed Jul 2 18:22:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/tmpdir.rb (@@systmpdir): prior LOCAL_APPDATA if possible, and
+ should be clean. based on a patch from arton <artonx AT
+ yahoo.co.jp> at [ruby-dev:35269]
+
+Wed Jul 2 18:16:19 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (date2time_str): fix the overflow in
+ some situation. [ruby-bugs-20793]
+
+Tue Jul 1 15:11:14 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_fill): check if beg is too big.
+
+Mon Jun 30 20:35:32 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (str_buf_cat): check for self concatenation.
+
+Sun Jun 29 21:39:54 2008 Tanaka Akira <akr@fsij.org>
+
+ * eval.c (rb_obj_respond_to): use RTEST to test the result of
+ respond_to? method.
+
+Sun Jun 29 21:20:17 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * array.c (rb_ary_fill): (compatibility) do not raise
+ ArgumentError on negative length. This behaviour shall change
+ in a future release.
+
+Sun Jun 29 20:08:11 2008 Tanaka Akira <akr@fsij.org>
+
+ * time.c (time_timeval): fix rounding negative float.
+
+Sun Jun 29 19:19:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/inlinetest.rb (InlineTest.in_progname): workaround for frozen
+ $0. [ruby-dev:35261]
+
+ * lib/test/unit/ui/console/testrunner.rb (TestRunner#finished): ditto.
+
+Sun Jun 29 19:19:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (set_arg0, ruby_prog_init): freeze $0. a patch from Keita
+ Yamaguchi <keita.yamaguchi at gmail.com>.
+
+Sun Jun 29 18:33:33 2008 Tanaka Akira <akr@fsij.org>
+
+ * process.c: include sys/resource.h if HAVE_SYS_RESOURCE_H is defined.
+ pointed by TOYOFUKU Chikanobu. [ruby-dev:35258]
+
+Sun Jun 29 18:26:01 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_f_trace_var): should not be allowed at safe level 4.
+ a patch from Keita Yamaguchi <keita.yamaguchi at gmail.com>.
+
+ * eval.c (rb_call0): wrong condition to check insecure method.
+ a patch from Keita Yamaguchi <keita.yamaguchi at gmail.com>.
+
+Sun Jun 29 18:22:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_fill): not depend on unspecified behavior at integer
+ overflow. reported by Vincenzo Iozzo <snagg AT openssl.it>.
+
+Sun Jun 29 18:22:06 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c(ole_invoke): fix memory leak.
+ [ruby-bugs-20792]
+
+Sun Jun 29 18:19:11 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (PUSH_FRAME, PUSH_CLASS): Add volatile to avoid a
+ possible optimization bug on OS X/PPC. This at least makes
+ build with gcc -O1 and `make test' pass.
+
+Sun Jun 29 17:24:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc#collect_first_comment): skip
+ magic comment.
+
+Sun Jun 29 17:22:09 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_each, strio_readlines): IO#each and
+ IO#readlines do not affect $_. [ruby-core:17277]
+
+Sun Jun 29 17:19:59 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_readline, strio_each)
+ (strio_readlines): set lastline. [ruby-core:17257]
+
+Sun Jun 29 17:15:49 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/openssl/ossl.h: include winsock.h if USE_WINSOCK2 is not defined.
+ a patch from arton <artonx at yahoo.co.jp> in [ruby-dev:35078]
+
+Sun Jun 29 17:09:48 2008 wanabe <s.wanabe@gmail.com>
+
+ * util.c (ruby_strtod): ruby_strtod don't allow a trailing
+ decimal point like "7.". [ruby-dev:34835] [ruby-dev:35009]
+
+Sat Jun 28 19:23:40 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * class.c (clone_method): use rb_copy_node_scope.
+ fixed [ruby-list:45102]
+ fixed [ruby-core:17393]
+
+Sat Jun 28 18:49:50 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * class.c: revert to r15855.
+
+Fri Jun 20 18:25:18 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_buf_append): should infect.
+
+Fri Jun 20 16:33:09 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_store, rb_ary_splice): not depend on unspecified
+ behavior at integer overflow.
+
+ * string.c (str_buf_cat): ditto.
+
+Wed Jun 18 22:24:46 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * array.c (ary_new, rb_ary_initialize, rb_ary_store,
+ rb_ary_aplice, rb_ary_times): integer overflows should be
+ checked. based on patches from Drew Yao <ayao at apple.com>
+ fixed CVE-2008-2726
+
+ * string.c (rb_str_buf_append): fixed unsafe use of alloca,
+ which led memory corruption. based on a patch from Drew Yao
+ <ayao at apple.com> fixed CVE-2008-2726
+
+ * sprintf.c (rb_str_format): backported from trunk.
+
+ * intern.h: ditto.
+
+Tue Jun 17 15:09:46 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (file_expand_path): no need to expand root path which has no
+ short file name. [ruby-dev:35095]
+
+Sun Jun 15 19:27:40 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * configure.in: Fix $LOAD_PATH. Properly expand vendor_ruby
+ directories; submitted by Takahiro Kambe <taca at
+ back-street.net> in [ruby-dev:35099].
+
+Mon Jun 9 17:56:30 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/set.rb (Set#delete_if): Call to_a.
+ (SortedSet#delete_if, TC_SortedSet#test_sortedset): Use super to
+ yield elements in sorted order; [ruby-core:17144] by Arthur
+ Schreiber.
+ (SortedSet#each, SortedSet#each, TC_Set#test_each)
+ (TC_SortedSet#test_sortedset): Return self; [ruby-dev:35002] by
+ Arthur Schreiber.
+
+Mon Jun 9 03:28:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/zlib/zlib.c (rb_deflate_initialize, Init_zlib): Fix up
+ initialize_copy; [ruby-list:45016], [ruby-list:45018].
+
+Mon Jun 9 03:26:03 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * NEWS: Mention new constants.
+
+Mon Jun 9 03:24:18 2008 Tanaka Akira <akr@fsij.org>
+
+ * hash.c (hash_i): make Hash#hash order insensitive.
+
+Mon Jun 9 03:22:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (VENDOR_DIR): use LIBDIR instead of PREFIX as well as
+ SITE_DIR. a patch from Richard Brown <rbrown AT exherbo.org> in
+ [ruby-core:17129].
+
+Mon Jun 9 03:21:20 2008 Tanaka Akira <akr@fsij.org>
+
+ * gc.c (os_obj_of): assure to not free the scanning heap.
+
+Mon Jun 9 03:20:12 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * io.c (rb_open_file, rb_io_s_sysopen): fmode should be unsigned int.
+ fixed [ruby-dev:34979]
+
+Fri Jun 6 21:16:55 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub (COMMON_HEADERS): include ws2tcpip.h.
+
+ * ext/socket/addrinfo.h (addrinfo, getaddrinfo, getnameinfo,
+ freehostent, freeaddrinfo): undef before define because these are
+ macros in some versions of Windows SDK.
+
+ * win32/setup.mak: maybe commit miss.
+
+Fri Jun 6 19:34:22 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * mkconfig.rb: hide build path from rbconfig.rb.
+
+ * util.c (ruby_strtod, dtoa): initialize more variables for error
+ handling.
+
+ * io.c (rscheck), marshal.c (w_nbyte, w_bytes, w_unique),
+ (path2class, path2module): constified.
+
+ * pack.c (pack_unpack), process.c (rb_syswait): suppress warnings.
+
+ * suppress warnings on cygwin, mingw and mswin.
+
+Fri Jun 6 19:23:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (file_expand_path): fix for non-existent files and SFN of
+ symlinks. [ruby-talk:303736]
+
+Fri Jun 6 18:25:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/iconv: Tests fixed.
+
+Fri Jun 6 17:04:56 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * win32/win32.h: include ws2tcpip.h. fixed [ruby-Bugs-20528]
+
+ * lib/time.rb (Time.xmlschema): don't use float. fix
+ http://rubyforge.org/tracker/index.php?func=detail&group_id=426&atid=1698&aid=20504
+
+ * object.c (rb_obj_alloc): RDoc updated. a patch from Gaston
+ Ramos <ramos.gaston at gmail.com> in [ruby-core:17073].
+
+ * lib/rdoc.rb: massive spelling correction patch from Evan Farrar
+ <evanfarrar at gmail.com> in [ruby-doc:1382] applied.
+
+ * ext/openssl/ossl_ssl_session.c (ossl_ssl_session_initialize):
+ Add a null check for ssl; submitted by akira yamada
+ in [ruby-dev:34950].
+
+ * ext/openssl/ossl_ssl.c (Init_ossl_ssl): Define OP_NO_TICKET if
+ SSL_OP_NO_TICKET is present; submitted by akira yamada
+ in [ruby-dev:34944].
+
+ * test/openssl/test_ssl.rb (OpenSSL#test_server_session): Add a
+ workaround for the case where OpenSSL is configured with
+ --enable-tlsext; submitted by akira yamada in [ruby-dev:34944].
+
+Fri Jun 6 16:58:23 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (iconv_iconv): fix for length argument and now
+ allows range. [ruby-core:17092] [ruby-core:17115]
+
+Wed Jun 4 17:22:30 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Fix typos and move misplaced entries.
+ NEWS: Somehow optflags and warnflags were not actually included
+ in this release.
+
+Tue Jun 3 19:33:22 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (enumerator_init_copy): Take care of
+ initialize_copy as well as initialize.
+
+ * test/ruby/test_enumerator.rb: Pull in the test suite for
+ enumerator from trunk.
+
+Tue Jun 3 12:51:57 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (enumerator_allocate, enumerator_ptr): Properly
+ detect if the object is initialized and raise error when
+ appropriate.
+ (enumerator_initialize): Fix a typo in rdoc. [ruby-core:17052]
+
+Tue Jun 3 10:16:40 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/erb.rb (ERB::Compiler::TrimScanner#scan_line): Fix a bug
+ where tokens are not yilelded one by one.
+ (ERB::Compiler::TrimScanner#explicit_trim_line): Fix without-
+ strscan problems. [ruby_core:17028].
+
+ * test/erb/test_erb.rb (TestERBCore#_test_01)
+ (TestERBCore#test_02_safe_04): The expected value should come
+ first for assert_equal().
+ (TestERBCoreWOStrScan): Add test class for without-strscan.
+
+Mon Jun 2 19:47:16 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/delegate.rb (DelegateClass, Delegator#respond_to?):
+ respond_to? must take optional second argument. This was a
+ latent bug exposed by a recent internal change of marshal.c to
+ call respond_to? with a second argument; submitted by Jeremy
+ Kemper <jeremy at bitsweat.net> in [ruby-core:17045].
+
+Sat May 31 23:53:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7.
+
+Sat May 31 23:33:34 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * README, README.ja: Add a note about default C flags.
+
+Sat May 31 22:11:15 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * version.c (ruby_description, ruby_copyright): backported from
+ 1.9. bug#19002, [ruby-dev:34883]
+
+ * error.c (report_bug): uses ruby_description.
+
+Sat May 31 20:56:04 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_delete_if): should return enumerator if no block
+ is given. [ruby-dev:34901]
+
+Sat May 31 18:28:17 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * suppress warnings with -Wwrite-string.
+
+Sat May 31 15:58:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, configure.in (warnflags): defaulted to -Wall
+ -Wno-parentheses with gcc. [ruby-dev:34810]
+
+Fri May 30 05:28:18 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enum.c (count_i, count_iter_i, count_all_i): add prototypes for VC.
+
+Fri May 30 04:32:07 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (count_i, count_iter_i): Sync with trunk.
+ enum.c (enum_count, count_all_i, Init_Enumerable),
+ array.c (rb_ary_count): Sync with trunk. If no argument or
+ block is given, count the number of all elements.
+
+Fri May 30 03:12:18 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/openssl/ossl_bn.c (ossl_bn_s_rand, ossl_bn_s_pseudo_rand):
+ Int should be enough here.
+
+Fri May 30 02:35:00 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/openssl/ossl_bn.c (ossl_bn_s_rand, ossl_bn_s_pseudo_rand),
+ ext/openssl/ossl_pkey_dh.c (ossl_dh_s_generate)
+ (ossl_dh_initialize),
+ ext/openssl/ossl_pkey_dsa.c (ossl_dsa_s_generate),
+ ext/openssl/ossl_rand.c (ossl_rand_bytes)
+ (ossl_rand_pseudo_bytes, ossl_rand_egd_bytes),
+ ext/openssl/ossl_x509store.c (ossl_x509stctx_set_error): Do not
+ use FIX2INT() without checking the value type. Use NUM2INT()
+ instead; found by akr in [ruby-dev:34890].
+
+Thu May 29 20:07:45 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * configure.in, win32/Makefile.sub, mkconfig.rb, instruby.rb,
+ ruby.c, lib/mkmf.rb, README.EXT, README.EXT.ja: Backport the
+ vendor_ruby directory support.
+
+Thu May 29 17:52:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/zlib/extconf.rb: search zlib1, and regard mswin32 later than VC6
+ as WIN32. [ruby-core:16984]
+
+Wed May 28 17:54:29 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (rb_str_start_with): Remove an unused variable.
+ (rb_str_upto_m): Fix a prototype.
+
+Wed May 28 17:48:28 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * range.c (range_step): Fix brokenness when a non-integer numeric
+ value is specified as step. [rubyspec]
+ (range_step): Make use of String#step internally if a string (or
+ string-alike) range is given.
+
+ * string.c (rb_str_upto_m, Init_String): Add an optional second
+ argument to specify if the last value should be included.
+
+Wed May 28 16:53:39 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_slice_bang): Call rb_ary_modify_check() at the
+ beginning. [rubyspec]
+
+Wed May 28 16:12:44 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/webrick/httpservlet/cgihandler.rb (WEBrick::HTTPServlet::CGIHandler#do_GET):
+ Set the HTTP status code to 302 if a Location header field is
+ present and the status code is not valid as a client
+ redirection. cf. RFC 3875 6.2.3, 6.2.4.
+
+Wed May 28 15:18:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/singleton.rb (SingletonClassMethods): _load should be public.
+
+Wed May 28 12:52:41 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (w_object, marshal_dump, r_object0, marshal_load): search
+ private methods too. [ruby-dev:34671]
+
+ * object.c (convert_type): ditto.
+
+Tue May 27 23:26:49 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (rb_bug): description from rb_bug() should include
+ patchlevel. [ruby-dev:34826]
+
+Tue May 27 20:19:22 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_slice_bang): Return an empty array instead of
+ nil when pos is valid and len is adjusted from a valid value to
+ zero; caught by RubySpec.
+
+Tue May 27 19:45:20 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * numeric.c (flo_divmod): Revert the behavior change; do not
+ suppress an exception when div is NaN or Inf. [ruby-dev:34857]
+
+Tue May 27 19:24:40 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (enum_to_a): Pass arguments through to #each().
+ (enum_sort): Follow the enum_to_a signature change.
+ (enum_reverse_each): Add #reverse_each().
+
+Tue May 27 18:54:02 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/stringio/stringio.c (strio_each_char, Init_stringio): Add
+ StringIO#{each_char,chars}.
+
+Tue May 27 17:59:34 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/stringio/stringio.c (strio_each): Return an enumerator if no
+ block is given.
+ (strio_each_byte): Return an enumerator if no block is given,
+ and return self if one is given as the rdoc says.
+
+ * io.c (rb_io_each_byte): Fix rdoc. IO#each_byte returns self,
+ not nil.
+
+Tue May 27 16:02:58 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_mod_module_exec, Init_eval): Add
+ Module#{module_exec,class_exec}.
+
+Tue May 27 15:36:37 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * io.c (rb_io_each_char, argf_each_char, Init_IO):
+ Add {IO#,ARGF.}{each_char,chars}.
+
+Tue May 27 13:46:52 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/stringio/stringio.c (Init_stringio): Define
+ StringIO#{getbyte,readbyte}.
+
+Tue May 27 13:38:51 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * io.c (Init_IO): Define {IO#,ARGF.}{getbyte,readbyte}.
+
+Tue May 27 13:26:15 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/stringio/stringio.c (Init_stringio): Define #bytes and
+ #lines.
+
+Tue May 27 13:20:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * io.c: (rb_io_lines, rb_io_bytes, Init_IO): Define
+ IO#{lines,bytes} and ARGF.{lines,bytes}.
+
+Tue May 27 12:13:17 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (BUFCHECK): wrong condition. [ruby-core:16921]
+
+ * file.c (file_expand_buf): shouldn't use buflen for length of string.
+
+Mon May 26 18:24:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (BUFCHECK): no resize if enough room.
+
+ * file.c (file_expand_path): use BUFCHECK.
+
+Mon May 26 16:46:19 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (ntfs_tail): filename which starts with '.' is valid.
+
+ * file.c (file_expand_path): cygwin symlink support.
+
+Mon May 26 12:16:43 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7-preview4.
+
+Mon May 26 12:12:26 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * marshal.c (dump_ensure, load_ensure): should return values.
+
+ * eval.c (yield_under, yield_under_i, yield_args_under_i)
+ (specific_eval, rb_obj_instance_exec, Init_eval): Implement
+ Object#instance_exec(), a 1.9 feature.
+
+Mon May 26 11:53:21 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_yield_0, proc_invoke, proc_arity): allow passing a
+ block to a Proc. [ruby-dev:23533]; by nobu; backported from
+ 1.9. This implementation in current shape is known to be
+ buggy/broken, especially with nested block invocation. Take
+ this as an experimental feature.
+
+ * parse.y (block_par, block_var): ditto.
+
+Mon May 26 08:00:52 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * marshal.c (r_object0, Init_marshal): Fix the garbled s_call
+ definition; fixes [ruby-dev:34843].
+
+Mon May 26 03:16:20 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * hash.c (rb_hash_default): Fix rdoc.
+ (rb_hash_each, env_each_value, env_each_pair): Return an
+ enumerator if no block is given.
+ (rb_hash_update): Update rdoc.
+ (envix): Conditionalize the definition itself.
+ (rb_f_getenv, env_fetch, env_keys, env_values, env_values_at)
+ (env_select, env_inspect, env_to_a, env_empty_p, env_has_key)
+ (env_has_value, env_index, env_indexes, env_to_hash, env_shift)
+ (env_update): Require secure level 4.
+ (env_each_value, env_each_i): Delay variable initialization.
+ (env_each_key, env_each_value, env_reject_bang)
+ (env_clear, env_replace): Omit duplicated secure level check.
+ (env_has_value): Do to_str conversion.
+
+Sun May 25 19:48:12 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * hash.c (env_delete_if): Return an enumerator if no block is
+ given.
+ (env_each_key): Delay a variable initialization after
+ RETURN_ENUMERATOR().
+
+Sun May 25 05:07:19 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_slice_bang): Be consistent with Array#slice()
+ and String#slice!(). Just return nil when a negative length or
+ out of boundary index is given instead of raising an exception
+ via internal functions.
+ (rb_ary_slice_bang): should not use rb_ary_subseq() which shares
+ internal pointer. splice modifies the receiver right after
+ subseq. [ruby-dev:34005]
+ (rb_ary_slice_bang): should adjust length before making
+ sub-array.
+
+ * enumerator.c (Init_Enumerator): Override
+ Enumerable::Enumerator#each_with_index with #with_index.
+
+Sun May 25 03:13:09 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (Init_Thread): Initialize recursive_key.
+
+Sun May 25 02:45:49 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * error.c (syserr_eqq): Use en.
+
+Sat May 24 22:32:49 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_cstr_to_dbl): should clear errno before calling
+ strtod(3). [ruby-dev:34834]
+
+Sat May 24 22:27:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (marshal_load): should initialize arg.data used for
+ reentrant check. [ruby-dev:34837]
+
+Sat May 24 00:34:59 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/rational.rb (Rational#to_i): fix rdoc. Rational(-7,4).to_i
+ should be -1.
+
+Fri May 23 20:22:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (reentrant_check): check reentrance via callcc.
+ [ruby-dev:34802]
+
+Fri May 23 16:46:28 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (proc_call): Remove an unused static function.
+
+Fri May 23 13:46:09 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (cflags): commit miss.
+
+Fri May 23 09:52:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (MINIRUBY), common.mk (RUBYOPT): add purelib.rb.
+ [ruby-core:16642]
+
+ * ext/extmk.rb: load purelib.rb only when not cross compiling.
+
+Fri May 23 08:47:02 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (syserr_eqq): === should be able to handle delegated
+ objects as well.
+
+Fri May 23 04:22:19 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c, ext/tk/tkutil/tkutil.c: fix memory leak.
+
+ * ext/tk/lib/tk.rb: avoid trouble when finalize TclTkIp.
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/*: help to fix troubles when
+ use Ttk widgets on old Tk scripts.
+
+ * ext/tk/sample/*: update and add demo scripts. some of them are
+ introduction about new features of Tcl/Tk8.5.
+
+Fri May 23 03:48:10 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * class.c (clone_method): Just use ruby_cref as cref.
+
+Fri May 23 01:03:23 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * class.c (rb_singleton_class_clone): Pass Qnil, not 0.
+
+Fri May 23 00:51:48 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * class.c (clone_method): Totally revamp the previous fix which
+ was incorrect.
+ (rb_mod_init_copy): Ditto.
+ (singleton_class_clone_int): Ditto.
+
+Fri May 23 00:48:10 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_copy_node_scope), node.h: Rename from copy_node_scope
+ and export.
+
+Thu May 22 21:24:15 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (top_local_setup): fixed memory leak bug based on a
+ patch from Roger Pack <rogerpack2005 at gmail.com> in
+ [ruby-core:16610].
+
+Thu May 22 14:20:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (flatten): check if reentered. [ruby-dev:34798]
+
+Thu May 22 08:28:49 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (flatten): free memo hash table before raising exception.
+ [ruby-dev:34789]
+
+Thu May 22 06:30:10 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * array.c (flatten): fix memory leak.
+
+Thu May 22 05:45:30 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * proc.c (proc_dup): should copy safe_level from src proc
+ properly. a patch from Keita Yamaguchi
+ <keita.yamaguchi at gmail.com>
+
+Wed May 21 23:31:44 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_get_method_body, rb_alias, rb_eval): should not cache
+ uninitialized value, since search_method doesn't set origin if the
+ method wasn't found.
+
+ * eval.c (search_method, remove_method, error_print, rb_alias)
+ (rb_eval, rb_rescue2, search_required, Init_eval, rb_thread_create),
+ gc.c (rb_source_filename, Init_stack), io.c (rb_io_getline),
+ parse.y (rb_id2name, rb_parser_free): suppress warnings.
+
+Wed May 21 12:34:51 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_hash_delete): rdoc fix based on a patch from Gaston Ramos
+ <ramos.gaston AT gmail.com>. [ruby-core:16825]
+
+Tue May 20 13:15:46 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * file.c (lchmod_internal): Remove a compiler warning.
+
+Mon May 19 18:22:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/openssl/ossl_pkcs5.c (ossl_pkcs5_pbkdf2_hmac): Fix the type
+ of md; pointed out by Takahiro Kambe <taca at back-street.net>
+ in [ruby-dev:34748].
+
+Mon May 19 14:20:13 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): fixed SEGV on win32 with "% 0e" % 1.0/0.0.
+
+Mon May 19 13:29:58 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * process.c (rb_f_system): set last_status when status == -1 because
+ there is no path to set it on win32. this patch is derived from
+ [ruby-core:16787], submitted by Luis Lavena <luislavena at gmail.com>
+
+Mon May 19 13:01:05 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk ({MSPEC,RUBYSPEC}_GIT_URL): moved from Makefine.in.
+
+ * {win32,bcc32}/Makefile.sub (update-rubyspec): added.
+
+Mon May 19 11:53:45 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/openssl/openssl_missing.c (HMAC_CTX_copy): adopted
+ prototype change in openssl bundled with newer OpenBSD.
+ a patch from Takahiro Kambe <taca at back-street.net> in
+ [ruby-dev:34691].
+
+Mon May 19 06:36:37 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7-preview3.
+
+Sun May 18 22:26:51 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpservlet/filehandler.rb: should normalize path
+ name in path_info to prevent script disclosure vulnerability on
+ DOSISH filesystems. (fix: CVE-2008-1891)
+ Note: NTFS/FAT filesystem should not be published by the platforms
+ other than Windows. Pathname interpretation (including short
+ filename) is less than perfect.
+
+ * lib/webrick/httpservlet/abstract.rb
+ (WEBrick::HTTPServlet::AbstracServlet#redirect_to_directory_uri):
+ should escape the value of Location: header.
+
+ * lib/webrick/httpservlet/cgi_runner.rb: accept interpreter
+ command line arguments.
+
+Sat May 17 23:53:57 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (file_expand_path): fix for short file name on Cygwin.
+
+Sat May 17 11:29:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_extname): first dot is not an extension name.
+
+Sat May 17 10:18:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_search): need to free allocated buffer in re_register.
+
+Fri May 16 17:01:44 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub (test-rubyspec): added.
+
+Fri May 16 16:22:40 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c: sometimes freeze when receive Interrupt signal.
+
+Fri May 16 14:54:56 2008 Tanaka Akira <akr@fsij.org>
+
+ * Makefile.in (update-rubyspec): move rubyspec to srcdir.
+ (test-rubyspec): ditto.
+
+Fri May 16 14:25:22 2008 Tanaka Akira <akr@fsij.org>
+
+ * Makefile.in (test-rubyspec): use RUNRUBY. suggested by nobu.
+
+Fri May 16 13:01:43 2008 Tanaka Akira <akr@fsij.org>
+
+ * Makefile.in (update-rubyspec): new target to download rubyspec.
+ (test-rubyspec): new target to run rubyspec. this doesn't work
+ before install.
+
+Fri May 16 08:15:52 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: fix memory (object) leak bug.
+
+ * ext/tk/sample/demos-jp/aniwave.rb, ext/tk/sample/demos-en/aniwave.rb:
+ bug fix.
+
+Thu May 15 17:00:22 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (Init_String): Define #bytesize as an alias for #size
+ for compatibility with 1.9.
+
+Thu May 15 15:33:59 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (file_expand_path): support for alternative data stream
+ and ignored trailing garbages of NTFS.
+
+ * file.c (rb_file_s_basename): ditto.
+
+ * file.c (rb_file_s_extname): ditto.
+
+Wed May 14 19:24:59 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_count): Override Enumerable#count for better
+ performance.
+ (rb_ary_nitems): Undo the backport. Use #count {} instead.
+
+ * enumerator.c (enumerator_iter_i): Remove an unused function.
+ (enumerator_with_index, enumerator_each): Remove unused
+ variables.
+
+Wed May 14 17:15:11 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/tk/tkutil/extronf.rb: check stdndup() because it's not standard
+ function of C.
+
+ * ext/tk/tkutil/tkutil.c (cbsubst_table_setup): use malloc() and
+ strncpy() instead of strndup() if not available.
+
+Wed May 14 09:52:02 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil/tkutil.c: improve handling callback-subst-keys.
+ Now, support longnam-keys (e.g. '%CTT' on tkdnd-2.0; however, still
+ not support tkdnd-2.0 on tkextlib), and symbols of parameters (e.g.
+ :widget=>'%W', :keycode=>'%k', '%x'=>:x, '%X'=>:root_x, and so on;
+ those are attributes of event object). It means that Ruby/Tk accepts
+ not only "widget.bind(ev, '%W', '%k', ...){|w, k, ...| ... }", but
+ also "widget.bind(ev, :widget, :keycode, ...){|w, k, ...| ... }".
+ It is potentially incompatible, when user passes symbols to the
+ arguments of the callback block (the block receives the symbols as
+ strings). I think that is very rare case (probably, used by Ruby/Tk
+ experts only). When causes such trouble, please give strings instead
+ of such symbol parameters (e.g. call Symbol#to_s method).
+
+ * ext/tk/lib/tk/event.rb, ext/tk/lib/tk/validation.rb,
+ ext/tk/lib/tkextlib/blt/treeview.rb,
+ ext/tk/lib/tkextlib/winico/winico.rb: ditto.
+
+ * ext/tk/tkutil/tkutil.c: strings are available on subst_tables on
+ TkUtil::CallbackSubst class (it is useful on Ruby 1.9).
+
+ * ext/tk/lib/tk/spinbox.rb, ext/tk/lib/tkextlib/iwidgets/hierarchy.rb,
+ ext/tk/lib/tkextlib/iwidgets/spinner.rb,
+ ext/tk/lib/tkextlib/iwidgets/entryfield.rb,
+ ext/tk/lib/tkextlib/iwidgets/calendar.rb,
+ ext/tk/lib/tkextlib/blt/dragdrop.rb,
+ ext/tk/lib/tkextlib/tkDND/tkdnd.rb,
+ ext/tk/lib/tkextlib/treectrl/tktreectrl.rb,
+ ext/tk/lib/tkextlib/tktable/tktable.rb: disable code piece became
+ unnecessary by reason of the changes of ext/tk/tkutil/tkutil.c.
+
+Tue May 13 15:10:50 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c: Update rdoc.
+ (enumerator_initialize): Discourage the use.
+ (enum_each_slice, enum_each_cons, enumerator_each)
+ (enumerator_with_index): Add a note about a call without a block.
+
+ * NEWS: Intentionally omit enum_slice and enum_cons, which are
+ removed in 1.9.
+
+Tue May 13 07:56:36 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_cat): fixed buffer overrun reported by
+ Christopher Thompson <cthompson at nexopia.com> in [ruby-core:16746]
+
+Mon May 12 13:57:19 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (is_defined): add NODE_OP_ASGN_{OR,AND}. "defined?(a||=1)"
+ should not operate assignment. [ruby-dev:34645]
+
+Mon May 12 12:59:23 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/wm.rb: Wm#overrideredirect overwrites arguemnt to
+ an invalid value.
+
+ * ext/tk/sample/ttk_wrapper.rb: support "if __FILE__ == $0" idiom.
+
+Mon May 12 12:36:55 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_select): backport from trunk.
+ [ruby-talk:300743]
+
+Mon May 12 12:33:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (RUBYLIB, RUBYOPT): clear.
+
+Mon May 12 10:41:10 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/delegate.rb (SimpleDelegator::dup): removed needless argument.
+ [ruby-list:44910]
+
+ * lib/delegate.rb (clone, dup): keep relationship with the target
+ object.
+
+Sun May 11 23:19:39 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (all_iter_i, any_iter_i): reduced duplicated code.
+
+Sun May 11 17:57:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (MINIRUBY): should not include extension library path.
+
+Sun May 11 10:36:10 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * eval.c (method_name, method_owner): New methods; backported
+ from 1.9. (UnboundMethod#name, UnboundMethod#owner)
+
+Sun May 11 02:48:13 2008 <nagai@orca16.orcabay.ddo.jp>
+
+ * ext/tk/lib/tk/pack.rb, ext/tk/lib/tk/grid.rb: fail to do pack/grid
+ without options.
+
+ * ext/tk/lib/tk.rb: add TkWindow#grid_anchor, grid_column, grid_row.
+
+Sat May 10 18:19:16 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_each_line): RDoc updated. [ruby-dev:34586]
+
+Sat May 10 13:17:56 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/pack.rb, ext/tk/lib/tk/grid.rb: increase supported
+ parameter patterns of configure method.
+
+Sat May 10 09:16:13 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * util.c (ruby_strtod): backported from 1.9. a patch from Satoshi
+ Nakagawa <psychs at limechat.net> in [ruby-dev:34625].
+ fixed: [ruby-dev:34623]
+
+Fri May 9 23:33:25 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/wm.rb: methods of Tk::Wm_for_General module cannot
+ pass the given block to methods of Tk::Wm module.
+
+ * ext/tk/lib/tk/grid.rb: lack of module-method definitions.
+
+ * ext/tk/lib/tkextlib/tile.rb: lack of autoload definitions.
+
+ * ext/tk/lib/tkextlib/tile/tnotebook.rb: cannot use kanji (not UTF-8)
+ characters for headings.
+
+ * ext/tk/tcltklib.c: maybe a little more stable about @encoding value
+ of TclTkIp object.
+
+Wed May 7 08:46:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (rb_struct_s_def): to_str should be called only once.
+ [ruby-core:16647]
+
+Wed May 7 00:54:25 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/zlib/zlib.c (gzreader_gets): may cause infinite loop.
+ a patch from Kouya <kouyataifu4 at gmail.com> in
+ [ruby-reference-manual:762].
+
+Sun May 4 09:35:51 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * sample/erb/erb4html.rb (ERB4Html) : add example of ERB#set_eoutvar.
+ ERB4Html is an auto-quote ERB.
+
+Sat May 3 22:52:48 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tile.rb, ext/tk/lib/tkextlib/tile/style.rb,
+ ext/tk/sample/ttk_wrapper.rb: improve treating and control themes.
+ add Tk::Tile.themes and Tk::Tile.set_theme(theme).
+
+Fri May 2 14:52:33 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el: move fontifying code from hook. a patch from
+ Phil Hagelberg <phil at hagelb.org> in [ruby-core:16636].
+
+Fri May 2 13:47:51 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (match_select): restore previous behavior of MatchData#select.
+ RDoc updated as well, mentioning the plan to remove this method
+ in the future. [ruby-dev:34556]
+
+Fri May 2 13:04:04 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dbm/dbm.c (Init_dbm): defines DBM::VERSION even when
+ DB_VERSION_STRING is not available. [ruby-dev:34569]
+
+Thu May 1 23:57:06 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 16257 from trunk.
+
+ * lib/net/telnet.rb: This patch from Brian Candler adds a FailEOF mode which
+ can be activated to have net/telnet raise EOFError exceptions when the
+ remote connection is closed. The default behavior remains unchanged though.
+
+Thu May 1 23:43:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * range.c (range_step): check if step can be converted to an integer.
+ [ruby-dev:34558]
+
+ * range.c (range_step): allow float step bigger than zero but less
+ than one. [ruby-dev:34557]
+
+Wed Apr 30 20:22:40 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 16241 from trunk.
+
+ * lib/net/telnet.rb: Fixing a bug where line endings would not be properly
+ escaped when the two character ending was broken up into separate TCP
+ packets. Issue reported and patched by Brian Candler.
+
+Wed Apr 30 17:47:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * re.c (rb_reg_search): use local variable. a patch from wanabe
+ <s.wanabe AT gmail.com> in [ruby-dev:34537]. [ruby-dev:34492]
+
+Sat Apr 26 19:40:34 2008 Guy Decoux <decoux@moulon.inra.fr>
+
+ * class.c (struct clone_method_data): Add cref.
+ (clone_method): Properly handle NODE_BMETHOD and NODE_DMETHOD.
+ (rb_singleton_class_clone, singleton_class_clone_int): Set a
+ proper value to klass and propagate cref. [ruby-core:16238]
+
+ * eval.c (rb_block_dup, rb_method_dup), intern.h: Add duplicator
+ methods for use from class.c#clone_method().
+
+Fri Apr 25 15:46:37 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/scrollbar.rb, ext/tk/lib/tk/scale.rb:
+ improve unknonw-option check when create a widget.
+
+ * ext/tk/lib/tkextlib/blt/unix_dnd.rb, ext/tk/lib/tkextlib/blt/ted.rb,
+ ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: bug fix on 'cget'.
+
+ * ext/tk/lib/tk/menuspec.rb: option check will fail when
+ TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ is true.
+
+ * ext/tk/lib/tk/palette.rb: bug fix.
+
+Fri Apr 25 12:37:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (flatten): returns an instance of same class.
+ [ruby-core:16554]
+
+Thu Apr 24 23:47:50 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/net/pop.rb: backported from 1.9. bug#19003
+
+ * ext/openssl/lib/openssl/ssl.rb: set_params; backported from 1.9.
+ bug#19552, [ruby-dev:34402]
+
+ * ext/openssl/ossl_ssl.c: ditto.
+
+ * test/openssl/test_ssl.rb: ditto.
+
+Thu Apr 24 17:06:34 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (THREAD_SAVE_CONTEXT): remove unnecessary
+ FLUSH_REGISTER_WINDOWS before calling setjmp(). [ruby-core:16285]
+
+Thu Apr 24 14:15:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dln.c (dln_find_1): prior files with extensions to files sans
+ extensions. [ruby-core:16517]
+
+Wed Apr 23 15:39:31 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (bind_eval): Add Binding#eval, a shorthand method for
+ eval(str, binding, ..); backported from 1.9.
+
+Wed Apr 23 15:28:52 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/gdbm/test_gdbm.rb (TestGDBM#test_s_open_no_create): failed
+ notice moved from comment to assertion message. [ruby-dev:29127]
+
+Wed Apr 23 14:00:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/mkmf.rb (create_makefile): Add a missing dependency on the
+ target directory for each .rb file. This will hopefully fix
+ parallel make (-jN). Tested on FreeBSD.
+
+Wed Apr 23 11:49:54 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/set.rb (Set#each, SortedSet#each, TC_Set#test_each): Return
+ an enumerator if no block is given.
+
+Wed Apr 23 00:42:49 2008 Tanaka Akira <akr@fsij.org>
+
+ * eval.c (error_print): show full stack grace except SystemStackError.
+ backport from 1.9. [ruby-dev:31014]
+
+Wed Apr 23 00:18:45 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/ruby/test_symbol.rb (TestSymbol#test_to_proc): Improve
+ tests of Symbol#to_proc.
+
+Tue Apr 22 22:43:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_proc_new, YIELD_FUNC_LAMBDA): Add a new nd_state
+ YIELD_FUNC_LAMBDA which avoids automatic `avalue' conversion for
+ arguments. This fixes a bug where [1,[2,3]].map(&:object_id)
+ fails.
+
+ * intern.h, object.c: Hide rb_proc_new() from intern.h. It should
+ not be considered an official API function yet.
+
+Tue Apr 22 21:24:32 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_proc_new): Turn the BLOCK_LAMBDA flag on.
+
+ * object.c (sym_to_proc), test/ruby/test_symbol.rb: Add back
+ Symbol#to_proc, now that it passes the tests.
+
+Tue Apr 22 19:35:03 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (enumerator_initialize): Remove an undocumented
+ feature (passing a block to the constructor) that's broken.
+ This is not what I intended.
+
+Tue Apr 22 17:49:46 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): should protect temporary string from
+ GC. [ruby-dev:34480]
+
+Tue Apr 22 17:12:05 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (re_search): string might be NULL. [ruby-core:16478]
+
+Tue Apr 22 16:44:00 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * object.c (rb_obj_tap): Correct documentation; pointed out by
+ okkez in [ruby-dev:34472].
+
+Tue Apr 22 10:05:51 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (eaccess): workaround for recent msvcrt's behavior.
+ [ruby-core:16460]
+
+Mon Apr 21 16:06:47 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * enumerator.c (enumerator_init): preserve the method name in ID.
+
+ * enumerator.c (enumerator_each): need not to call rb_to_id().
+
+ * enumerator.c (enumerator_with_index): ditto.
+
+Mon Apr 21 17:19:52 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_f_method_name): New gloval function: __method__;
+ backported from matzruby / 1.9.
+
+ * eval.c (rb_frame_this_func), intern.h: New internal function.
+
+ * intern.h (RETURN_ENUMERATOR): Use rb_frame_this_func() instead
+ of rb_frame_last_func(), to accommodate the behavior to that of
+ 1.9.
+
+Mon Apr 21 15:54:48 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/tempfile.rb (Tempfile::_close): check @data before modifying
+ it; backported from 1.9. [ruby-dev:34094]
+
+ * lib/tempfile.rb (Tempfile::close): clear @data and @tmpname.
+
+Mon Apr 21 10:17:17 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * time.c: should include <errno.h> to refer errno.
+
+Mon Apr 21 10:02:43 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * hash.c (recursive_hash): prototype.
+
+Mon Apr 21 10:00:51 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * time.c (rb_strftime): check errno to detect strftime(3)'s error.
+ this is workaround for recent version of MSVCRT.
+ [ruby-dev:34456]
+
+Sun Apr 20 21:10:04 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7-preview2.
+
+Sun Apr 20 21:02:06 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c: Resolve the method every time an enumeration
+ method is run, not once when the enumerator is initialized as it
+ was before, so that method_missing() and method (re)definition
+ afterwards are both in effect; pointed out in: [ruby-core:16441]
+
+Sun Apr 20 17:59:25 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * object.c, NEWS, test/ruby/test_symbol.rb: Revert Symbol#to_proc
+ since it does not pass the tests.
+
+Sun Apr 20 14:29:35 2008 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/ossl_ssl.c: initialize session class.
+
+Sat Apr 19 20:54:42 2008 akira yamada <akira@arika.org>
+
+ * lib/uri/ftp.rb, lib/uri/generic.rb, test/uri/test_common.rb,
+ test/uri/test_ftp.rb, test/uri/test_generic.rb: backported from 1.9.
+ [ruby-dev:31318]
+
+Sat Apr 19 20:35:02 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/yaml/baseemitter.rb, lib/yaml/encoding.rb: performance
+ tuning around String#gsub.
+
+ * lib/yaml/tag.rb: Replace nodoc with stopdoc so Module methods get
+ documented.
+
+ * lib/yaml/store.rb (YAML::load): modified to support empty
+ database.
+
+ * lib/yaml/store.rb (YAML::Store::marshal_dump_supports_canonical_option?):
+ add a method to support faster PStore.
+
+Sat Apr 19 20:16:52 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/yaml/types.rb: Likewise, pass self to YAML::quick_emit;
+ merged from 1.9.
+
+ * lib/yaml.rb (quick_emit): use combination of object_id and hash to
+ identify repeated object references, since GC will reuse memory of
+ objects during output of YAML. [ruby-Bugs-8548] [ruby-Bugs-3698];
+ merged from 1.9.
+
+Sat Apr 19 20:05:39 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_equal, rb_ary_eql, rb_ary_hash, rb_ary_cmp):
+ Make Array#eql?, #hash, #== and #<=> use rb_exec_recursive() and
+ handle recursive data properly.
+
+ * hash.c (hash_equal, rb_hash_hash): Make Hash#eql?, #hash and #==
+ use rb_exec_recursive() and handle recursive data properly.
+
+Sat Apr 19 19:26:09 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * intern.h, eval.c (rb_exec_recursive): New internal function to
+ help perform recursive operation; backported from 1.9.
+
+Sat Apr 19 18:42:04 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * intern.h, hash.c (rb_hash_lookup): New internal function to
+ check if a key exists in a hash, ignoring #default; backported
+ from 1.9.
+
+Fri Apr 18 18:56:57 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/syck/rubyext.c (syck_genericresolver_node_import): should
+ not set instance variable "@kind" before initializing it.
+ [ruby-dev:32677]
+
+ * ext/syck/rubyext.c (syck_resolver_initialize,
+ syck_resolver_detect_implicit, syck_emitter_emit): remove unused
+ variables.
+
+Fri Apr 18 18:54:57 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/syck/rubyext.c: Node#value defined twice.
+
+ * lib/yaml/: several method redefinitions causing warnings.
+
+Fri Apr 18 16:36:16 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/rexml/node.rb (REXML::Node::indent): should initialize rv
+ variable. a patch from Tadayoshi Funaba <tadf AT dotrb.org> in
+ [ruby-dev:32783].
+
+Fri Apr 18 16:01:37 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/rexml: Merge fixes since 1.8.6 made solely on the ruby_1_8_6
+ branch.
+
+Wed Apr 16 06:11:49 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * test/ruby/test_settracefunc.rb (TestSetTraceFunc#test_event):
+ Fix tests to reflect the following changes: r15833, r15759.
+
+Wed Apr 16 05:03:48 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7-preview1.
+
+Wed Apr 16 02:09:14 2008 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/xmlrpc/client.rb: fix cookie handling. [ruby-dev:34403]
+
+ * test/xmlrpc/test_cookie.rb: add a test for the above fix.
+
+Tue Apr 15 23:48:28 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * version.h: Branch off ruby_1_8_7 from ruby_1_8 in preparation
+ for the forthcoming 1.8.7 release.
+
+Tue Apr 15 23:40:39 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/syck/rubyext.c (rb_syck_mktime): Avoid buffer overflow.
+
+Tue Apr 15 20:32:03 2008 Tanaka Akira <akr@fsij.org>
+
+ * re.c (match_inspect): backported from 1.9.
+
+Tue Apr 15 19:03:28 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * eval.c (method_receiver, method_name, method_owner): New
+ methods; backported from 1.9. bug#19007
+
+Tue Apr 15 18:39:14 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/uri.rb, lib/uri/ldaps.rb: added LDAPS
+ scheme; backported from 1.9. bug#19015, [ruby-dev:31896]
+
+Tue Apr 15 17:45:43 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/net/smtp.rb: backported from 1.9. bug#19003
+
+Tue Apr 15 17:06:12 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/ruby/test_symbol.rb (TestSymbol#test_to_proc): add tests.
+
+Tue Apr 15 16:58:55 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/menuspec.rb: option check will fail when
+ TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ is true.
+
+ * ext/tk/lib/tk/palette.rb: bug fix.
+
+Tue Apr 15 16:47:48 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * signal.c, gc.c: New methods: GC.stress, GC.stress=;
+ backported from 1.9. a patch from Tadashi Saito
+ in [ruby-dev:34394] and bug#19000
+
+Tue Apr 15 12:35:44 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * rubyio.h (rb_io_t): renamed from OpenFile.
+
+ * ruby.h (struct RHash), file.c, gc.c, io.c, ext/dl/dl.c,
+ ext/io/wait/wait.c, ext/pty/pty.c, ext/readline/readline.c,
+ ext/socket/socket.c: ditto.
+
+ * win32/win32.h: removed workaround for OpenFile.
+
+Tue Apr 15 00:15:29 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/text.rb: typo. call a wrong method.
+
+ * ext/tk/lib/tk/itemconfig.rb: ditto.
+
+ * ext/tk/sample/ttk_wrapper.rb: bug fix.
+
+ * ext/tk/sample/tktextio.rb: add binding for 'Ctrl-u' at console mode.
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/itemfont.rb, ext/tk/lib/font.rb:
+ support __IGNORE_UNKNOWN_CONFIGURE_OPTION__ about font options.
+
+ * ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb,
+ ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb,
+ ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb: bug fix.
+
+ * ext/tk/lib/tkextlib/tile/tpaned.rb: improve TPaned#add.
+
+ * ext/tk/lib/tk/timer.rb: add TkTimer#at_end(proc) to register the
+ procedure which called at end of the timer.
+
+Mon Apr 14 19:54:21 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_flatten, rb_ary_flatten_bang): Take an optional
+ argument that determines the level of recursion to flatten;
+ backported from 1.9.
+
+ * array.c (rb_ary_shuffle_bang, rb_ary_shuffle, rb_ary_choice,
+ rb_ary_cycle, rb_ary_permutation, rb_ary_combination,
+ rb_ary_product, rb_ary_take, rb_ary_take_while, rb_ary_drop,
+ rb_ary_drop_while): New methods: Array#shuffle, #shuffle!,
+ #choice, #cycle, #permutation, #combination, #product, #take,
+ #take_while, #drop, #drop_while; backported from 1.9.
+
+Mon Apr 14 19:52:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ruby.h: New macro: RB_GC_GUARD().
+
+Mon Apr 14 19:49:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * random.c (rb_genrand_int32, rb_genrand_real), intern.h: Export.
+
+ * string.c (rb_str_tmp_new), intern.h: New function.
+
+Mon Apr 14 19:18:55 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enum.c (inject_i, inject_op_i): prototype.
+
+Mon Apr 14 19:10:47 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c New methods: Enumerable#take, #take_while, #drop and
+ #drop_while; backported from 1.9.
+
+Mon Apr 14 18:50:15 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c: New methods: Enumerable#one?, #none?, #minmax, #min_by,
+ #max_by, #minmax_by and #cycle; backported from 1.9.
+
+ * enum.c (enum_find_index): Add support for find_index(obj);
+ [ruby-dev:34313]; backported from 1.9.
+
+ * enum.c (enum_inject): Add support for Enumerable#inject(:binop);
+ backported from 1.9.
+
+ * enum.c: Alias Enumerable#reject to #inject; backported from 1.9.
+
+Mon Apr 14 18:14:19 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (enum_find, enum_reject): Return an enumerator if no
+ block is given; backported from 1.9.
+
+ * io.c (rb_io_each_line, rb_io_each_byte, rb_io_s_foreach,
+ argf_each_line, argf_each_byte): Ditto.
+
+ * string.c (str_gsub): Ditto.
+
+Mon Apr 14 18:10:05 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enum.c (find_index_i, find_index_iter_i): add prototype for VC.
+
+Mon Apr 14 17:55:30 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_collect_bang, rb_ary_select): Return an
+ enumerator if no block is given; backported from 1.9.
+
+ * dir.c (dir_each, dir_foreach): Ditto.
+
+ * enum.c (enum_partition, enum_sort_by): Ditto.
+
+ * gc.c (os_each_obj): Ditto.
+
+ * hash.c (rb_hash_delete_if, rb_hash_reject_bang, rb_hash_select,
+ rb_hash_each_value, rb_hash_each_key, rb_hash_each_pair,
+ env_each_key, env_each_value, env_each, env_each_pair,
+ env_reject_bang, env_delete_if, env_select): Ditto.
+
+ * numeric.c (num_step, int_upto, int_downto, int_dotimes): Ditto.
+
+Mon Apr 14 16:42:53 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ruby.h (rb_block_call_func): Fix prototype.
+
+ * enumerator.c (enumerator_iter_i, enumerator_each_i): Ditto.
+
+Mon Apr 14 15:49:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (enum_count, enum_find_index): New methods:
+ Enumerable#count and #find_index; backported from 1.9.
+
+Mon Apr 14 14:16:08 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enumerator.c (enumerator_mark, enumerator_iter_i, enumerator_each_i,
+ enumerator_allocate): add prototype.
+
+ * enumerator.c (enumerator_each_i): declare unused two arguments.
+
+Mon Apr 14 13:58:32 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (rb_str_each_char): New methods: String#chars and
+ #each_char; backported from 1.9.
+
+Mon Apr 14 13:42:20 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (rb_str_each_line, rb_str_each_byte): Reflect
+ enumerator integration. #lines and #bytes are now aliases to
+ #each_line and #each_byte, respectively.
+
+Mon Apr 14 13:19:36 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * range.c (range_each, range_step): Return an enumerator if no
+ block is given; backported from 1.9.
+
+ * struct.c (rb_struct_each, rb_struct_each_pair): Ditto.
+
+Mon Apr 14 13:07:59 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (rb_str_partition, rb_str_rpartition,
+ rb_str_start_with, rb_str_end_with): New methods:
+ String#partition, #rpartition, #start_with? and #end_with?;
+ backported from 1.9. These methods are $KCODE aware unlike
+ #index, #rindex and #include?.
+
+Sun Apr 13 15:55:52 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * object.c (sym_to_proc): new method Symbol#to_proc; backported
+ from 1.9. bug#19012
+
+Fri Apr 11 19:14:30 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * object.c (rb_obj_tap): new method Object#tap; backported from
+ 1.9. bug#19008
+
+Fri Apr 11 18:58:09 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * process.c: new method Process.exec; backported from 1.9. bug#19006
+
+Fri Apr 11 12:43:56 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tile.rb, ext/tk/lib/tkextlib/tile/style.rb,
+ ext/tk/sample/tkextlib/tile/demo.rb: previous patch is not complete.
+
+Fri Apr 11 10:22:54 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tile.rb:
+ __define_LoadImages_proc_for_compatibility__! do nothing when the
+ Tcl command exists.
+
+ * ext/tk/lib/tkextlib/tile/style.rb:
+ __define_wrapper_proc_for_compatibility__! do nothing when the Tcl
+ command exists.
+
+ * ext/tk/sample/tkextlib/tile/demo.rb: don't create 'step' theme if
+ it already exists.
+
+Fri Apr 11 08:05:12 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_object): add volatile to avoid potential GC bug. a
+ patch from Tomoyuki Chikanaga <chikanag at nippon-control-system.co.jp>
+ in [ruby-dev:34311].
+
+Thu Apr 10 20:29:13 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * misc/rdebug.el, misc/README: Remove rdebug.el as per request
+ from the maintainer and mention the ruby-debug project at
+ RubyForge in README; bug#19043.
+
+Thu Apr 10 20:08:37 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (enum_first, enum_group_by): New methods:
+ Enumerable#first and #group_by; backported from 1.9.
+
+Thu Apr 10 19:49:10 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (rb_eStopIteration), eval.c (rb_f_loop), ruby.h:
+ Add a new exception class StopIteration, which breaks Kernel#loop
+ iteration when raised; backported from 1.9.
+
+ * enumerator.c (enumerator_next, enumerator_rewind): Implement
+ #next and #rewind using the "generator" library.
+
+ * lib/generator.rb: Implement Enumerable::Enumerator#next and
+ #rewind.
+
+Thu Apr 10 19:29:48 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_first, rb_ary_last): Return a shared array when
+ possible.
+
+ * array.c (rb_ary_pop, rb_ary_pop_m, rb_ary_shift, rb_ary_shift_m):
+ Array#pop and Array#shift can take an optional argument
+ specifying the number of elements to remove and return;
+ backported from 1.9.
+
+Thu Apr 10 14:00:44 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/resolv.rb (Resolv::DNS#each_address): backport from 1.9 for
+ CNAME. [ruby-dev:34200]
+
+Thu Apr 10 01:42:25 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enum.c (iterate_method): add prototype to avoid warning on VC++.
+
+Wed Apr 9 23:12:41 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c: SEGV when tcltk-stubs is enabled.
+
+ * ext/tk/tcltklib.c: avoid error on a shared object.
+
+ * ext/tk/extconf.rb: support --with-tcltkversion
+
+ * ext/tk/README.tcltklib: add document about --with-tcltkversion
+
+ * ext/tk/sample/demos-jp/widget, ext/tk/sample/demos-en/widget,
+ ext/tk/sample/demos-jp/style.rb, ext/tk/sample/demos-en/style.rb,
+ ext/tk/sample/demos-jp/bind.rb, ext/tk/sample/demos-en/bind.rb:
+ bug fix.
+
+Wed Apr 9 21:54:45 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_pop): Do not reallocate too often; backported
+ from 1.9.
+
+Wed Apr 9 21:13:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_each, rb_ary_each_index, rb_ary_reverse_each,
+ rb_ary_reject, rb_ary_reject_bang): Array#each, #each_index,
+ #reverse_each, #reject, #reject! and #delete_if return an
+ enumerator if no block is given; backported from 1.9.
+
+Wed Apr 9 20:47:16 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_index, rb_ary_index): Array#index and #rindex
+ can take a block instead of an argument; backported from 1.9.
+
+Wed Apr 9 19:58:31 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c, inits.c (rb_call_inits), ruby.h, intern.h,
+ ext/enumerator, common.mk (OBJS, enumerator.$(OBJEXT)): Make the
+ enumerator module built-in.
+
+ * enumerator.c: New method: Enumerable::Enumerator#with_index.
+
+ * enum.c (enum_each_with_index): Enumerable#each_with_index now
+ returns an enumerator instead of raising an exception if no
+ block is given. Enumerable#enum_with_index, formerly defined in
+ the enumerator module, is kept as an alias to each_with_index
+ for backward compatibility.
+
+Wed Apr 9 19:43:51 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_obj_method, rb_proc_call), intern.h: Export.
+
+Tue Apr 8 11:11:28 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (EXEC_TAG): remove unnecessary FLUSH_REGISTER_WINDOWS for
+ better performance on SPARC. [ruby-core:16159]
+
+Tue Apr 8 10:49:54 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_quote): should always copy the quoting string.
+ [ruby-core:16235]
+
+Mon Apr 7 21:35:08 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_nitems): Backport Array#nitems with a block;
+ suggested by Bertram Scharpf <lists@bertram-scharpf.de> in
+ [ruby-talk:134083].
+
+Sun Apr 6 09:45:00 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (dir_tell): check if closed. [ruby-core:16223]
+
+Sat Apr 5 10:05:00 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_check_to_integer): backported for range_step.
+
+Fri Apr 4 05:57:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/net/pop.rb (Net::POP3::do_finish): clear @n_mails and
+ @n_bytes as well. [ruby-core:16144]
+
+Fri Apr 4 02:17:06 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * range.c (range_step): should not round step into integer if
+ begin and end are numeric. [ruby-core:15990]
+
+Tue Apr 1 14:43:38 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: get rid of empty expansion.
+
+ * {bcc,win}32/Makefile (config.h): need to define RUBY_SETJMP, etc.
+
+Tue Apr 1 11:36:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: _setjmp is available but _longjmp is not on mingw.
+
+Tue Apr 1 03:20:40 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_SETJMP, RUBY_LONGJMP, RUBY_JMP_BUF): prefers
+ _setjmp over setjmp and sigsetjmp. [ruby-core:16023]
+ __builtin_setjmp cannot handle a variable.
+
+ * configure.in (--with-setjmp-type): new option to override the
+ default rule in the above.
+
+ * eval_intern.h (ruby_setjmp, ruby_longjmp), gc.c (rb_setjmp),
+ vm_core.h (rb_jmpbuf_t): use RUBY_SETJMP, RUBY_LONGJMP and
+ RUBY_JMP_BUF.
+
+Tue Apr 1 01:55:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/resolv.rb (Resolv::Config.default_config_hash): requires
+ win32/resolv to use Win32::Resolv. [ruby-dev:34138]
+
+Mon Mar 31 14:51:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_div): Bignum#div should return integer for
+ floating number operand.
+
+Sun Mar 30 07:00:32 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/tk/tcltklib.c: rb_hash_lookup has not been backported yet.
+
+Sat Mar 29 14:18:41 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/*: full update Ruby/Tk to support Ruby(1.9|1.8) and Tc/Tk8.5.
+
+ * ext/tk/lib/tkextlib/tile.rb: [incompatible] remove TileWidgets'
+ instate/state/identify method to avoid the conflict with standard
+ widget options. Those methods are renamed to ttk_instate/ttk_state/
+ ttk_identify (tile_instate/tile_state/tile_identify are available
+ too). Although I don't recommend, if you realy need old methods,
+ please define "Tk::USE_OBSOLETE_TILE_STATE_METHOD = true" before
+ "require 'tkextlib/tile'".
+
+ * ext/tk/lib/tkextlib/tile.rb: "Tk::Tile::__Import_Tile_Widgets__!"
+ is obsolete. It outputs warning. To control default widget set,
+ use "Tk.default_widget_set = :Ttk".
+
+ * ext/tk/lib/tk.rb: __IGNORE_UNKNOWN_CONFIGURE_OPTION__ method and
+ __set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) method are defind
+ as module methods of TkConfigMethod. It may help users to wrap old
+ Ruby/Tk scripts (use standard widgets) to force to use Ttk widgets.
+ Ttk widgets don't have some options of standard widgets which are
+ control the view of widgets. When set ignore-mode true, configure
+ method tries to ignoure such unknown options with no exception.
+ Of course, it may raise other troubles on the GUI design.
+ So, those are a little danger methods.
+
+ * ext/tk/lib/tk/itemconfig.rb: __IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ method and __set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) method
+ are defind as module methods of TkItemConfigMethod as the same
+ purpose as TkConfigMethod's ones.
+
+ * ext/tk/sample/ttk_wrapper.rb: A new example. This is a tool for
+ wrapping old Ruby/Tk scripts (which use standard widgets) to use
+ Ttk (Tile) widgets as default.
+
+ * ext/tk/sample/tkextlib/tile/demo.rb: use ttk_instate/ttk_state
+ method instead of instate/state method.
+
+ * ext/tk/lib/tk/root, ext/tk/lib/tk/namespace.rb,
+ ext/tk/lib/tk/text.rb, ext/tk/lib/tkextlib/*: some 'instance_eval's
+ are replaced to "instance_exec(self)".
+
+ * ext/tk/lib/tk/event.rb: bug fix on KEY_TBL and PROC_TBL (?x is not
+ a character code on Ruby1.9).
+
+ * ext/tk/lib/tk/variable.rb: support new style of operation argument
+ on Tcl/Tk's 'trace' command for variables.
+
+ * ext/tk/sample/demos-jp/widget, ext/tk/sample/demos-en/widget: bug fix
+
+ * ext/tk/sammple/demos-jp/textpeer.rb,
+ ext/tk/sammple/demos-en/textpeer.rb: new widget demo.
+
+ * ext/tk/tcltklib.c: decrase SEGV troubles (probably)
+
+ * ext/tk/lib/tk.rb: remove Thread.critical access if Ruby1.9
+
+ * ext/tk/lib/tk/multi-tk.rb: support Ruby1.9 (probably)
+
+ * ext/tk/lib/tkextlib/tile.rb: add method to define Tcl/Tk command
+ to make Tcl/Tk theme sources (based on different version of Tile
+ extension) available.
+ (Tk::Tile::__define_LoadImages_proc_for_comaptibility__)
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/wm.rb: support dockable frames
+ (Tcl/Tk8.5 feature). 'wm' command can treat many kinds of widgets
+ as toplevel widgets.
+
+ * ext/tk/lib/tkextlib/tile/style.rb: ditto.
+ (Tk::Tile::Style.__define_wrapper_proc_for_compatibility__)
+
+ * ext/tk/lib/tk/font.rb: add actual_hash and metrics_hash to get
+ properties as a hash. metrics_hash method returns a boolean value
+ for 'fixed' option. But metrics method returns numeric value
+ (0 or 1) for 'fixed' option, because of backward compatibility.
+
+ * ext/tk/lib/tk/timer.rb: somtimes fail to set callback procedure.
+
+ * ext/tk/lib/tk.rb: add Tk.sleep and Tk.wakeup method. Tk.sleep
+ doesn't block the eventloop. It will be better to use the method
+ in event callbacks.
+
+ * ext/tk/sample/tksleep_sample.rb: sample script about Tk.sleep.
+
+Sat Mar 29 04:08:59 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (clone_method): should copy cref as well.
+ [ruby-core:15833]
+
+Mon Mar 24 20:07:42 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_eval): Call trace hook for if expression after the
+ condition has been evaluated, not before; submitted by Rocky
+ Bernstein in #18722.
+
+Mon Mar 24 19:44:53 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * parse.y (yycompile): Always prepare a new array for each file's
+ SCRIPT_LINES__ storage, instead of appending source lines every
+ time a file is re-loaded; submitted by Rocky Bernstein in
+ #18517.
+
+Mon Mar 24 10:25:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: sitearch should use target_cpu. [ruby-core:15986]
+
+Mon Mar 24 01:24:24 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb (result): use proc instead of Thread. [ruby-dev:33692]
+
+Fri Mar 21 21:26:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/resolv.rb (Resolv::Hosts): should not use win32/resolv on cygwin.
+ [ruby-dev:29945], [ruby-dev:34095]
+
+ * lib/win32/registry.rb (Win32::Registry.expand_environ): try upcased
+ name too for cygwin. [ruby-dev:29945]
+
+ * lib/win32/resolv.rb (Win32::Resolv.get_hosts_path): use expand_path.
+
+Fri Mar 21 21:10:00 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/ipaddr.rb: Say that I am the current maintainer.
+
+ * lib/set.rb: Ditto.
+
+ * lib/shellwords.rb: Ditto.
+
+ * ext/syslog/syslog.txt: Ditto.
+
+Fri Mar 21 09:24:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb (open_for_install): write block result and rewrite only
+ if changed from existing file.
+
+Wed Mar 19 21:01:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (dir_inspect, dir_path, dir_tell): check for frozen and closed
+ is not needed. [ruby-dev:32640]
+
+Wed Mar 19 20:25:40 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (Init_Dir): define inspect method. [ruby-core:15960]
+
+Wed Mar 19 14:59:12 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-style.el (ruby-style-{case,label}-indent): fix for labels
+ inside blocks in switch and function top level.
+
+Wed Mar 19 14:36:40 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_cstr_to_inum): treat successive underscores as
+ nondigit. [ruby-dev:34089]
+
+Wed Mar 19 00:01:23 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb (ERB::Compiler): Make some minor code optimization.
+
+Mon Mar 17 17:11:13 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-mode): should use `run-mode-hooks' instead
+ of calling `run-hooks' directly to run the mode hook. patch from
+ Chiyuan Zhang <pluskid AT gmail.com> in [ruby-core:15915]
+
+Mon Mar 17 16:41:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: unset GREP_OPTIONS. [ruby-core:15918]
+
+Fri Mar 14 16:59:23 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_LIB_PREFIX): fix for prefix.
+
+Fri Mar 14 16:35:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::Cookie::initialize): performance patch from
+ Makoto Kuwata <kwa@kuwata-lab.com> in [ruby-dev:34048].
+
+Fri Mar 14 15:49:05 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_LIB_PREFIX): use libdir.
+
+Fri Mar 14 10:12:29 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_CHECK_VARTYPE): should not indent preprocessor
+ directives.
+
+Thu Mar 13 00:37:20 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_call0): yields the last executed node line number at
+ return event. [ruby-core:15855]
+
+Wed Mar 12 02:12:20 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/delegate.rb: check $@ to avoid NoMethodError.
+
+Tue Mar 11 19:48:09 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (fix_coerce): try conversion before type check.
+ [ruby-core:15838]
+
+Tue Mar 11 17:03:23 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/delegate.rb (Delegator#initialize, DelegateClass): skip correct
+ backtrace. [ruby-dev:34019]
+
+Tue Mar 11 16:43:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_cmdvector): terminate shrunken command line.
+
+Tue Mar 11 12:39:03 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (clean-local): removes MINOBJS.
+
+Sat Mar 8 18:50:57 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (isdirsep): backslash is valid path separator on cygwin too.
+
+Fri Mar 7 19:56:10 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb: rdoc added. [ruby-Patches-9762]
+
+Thu Mar 6 15:10:21 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32}/Makefile.sub (RUNRUBY): use $(PROGRAM) instead of
+ ruby$(EXEEXT).
+ suggested by KIMURA Koichi <kimura.koichi at canon.co.jp>.
+ [ruby-dev:34000]
+
+Thu Mar 6 12:15:06 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (opt_block_param): command can start just after block param
+ definition. [ruby-list:44479]
+
+Thu Mar 6 00:34:11 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb: update RDoc. Thanks Makoto Kuwata [ruby-dev:33702]
+
+Mon Mar 3 23:28:34 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpservlet/filehandler.rb: should normalize path
+ separators in path_info to prevent directory traversal attacks
+ on DOSISH platforms.
+ reported by Digital Security Research Group [DSECRG-08-026].
+
+ * lib/webrick/httpservlet/filehandler.rb: pathnames which have
+ not to be published should be checked case-insensitively.
+
+Mon Mar 3 16:14:24 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_any_hash): shrinks all results in Fixnum range.
+ [ruby-core:15713]
+
+Sat Mar 1 02:35:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (big2str_find_n1): check integer overflow.
+
+Tue Feb 26 16:06:00 2008 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/ossl_pkey_{ec,dh,dsa,rsa}.c: Remove useless warnings.
+
+ * ext/openssl/ossl_asn1.c: Simplify code.
+
+ * ext/openssl/ossl_ssl_session.c Fix compiler warnings.
+ Undefine #id if SSL_SESSION_get_id is not supported.
+
+Tue Feb 26 15:43:42 2008 Tanaka Akira <akr@fsij.org>
+
+ * parse.y (tokadd_escape): refactored. [ruby-core:15657]
+
+Mon Feb 25 17:30:29 2008 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/digest.c ext/openssl/lib/openssl/digest.rb:
+ Commit patch #9280 from Akinori MUSHA.
+ Simplify the OpenSSL::Digest class and make use of the
+ existing Digest framework.
+ Enhance performance.
+
+Mon Feb 25 13:40:03 2008 Tanaka Akira <akr@fsij.org>
+
+ * process.c (Init_process): share bignum objects for RLIM_INFINITY,
+ RLIM_SAVED_MAX and RLIM_SAVED_CUR if they are equal.
+
+Sun Feb 24 23:29:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk, {bcc,win}32/Makefile.sub (clean-local): remove
+ intermediate files.
+
+Sun Feb 24 03:52:58 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * util.c (valid_filename): use O_EXCL to get rid of clobbering
+ existing files in race conditions.
+
+Fri Feb 22 19:50:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (BIGZEROP): fix for longer Bignum zeros. [ruby-Bugs-17454]
+
+Fri Feb 22 16:09:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_lshift, rb_big_rshift, rb_big_aref): removed excess
+ arguments.
+
+Thu Feb 21 00:01:34 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RPATHFLAG): -R option of HP-UX ld is not for runtime
+ load path. [ruby-list:44600]
+
+Wed Feb 20 23:55:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_map_errno): exported.
+
+Wed Feb 20 13:08:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb (parse_args): added --dir-mode, --script-mode and
+ --cmd-type options. [ruby-dev:33816]
+
+ * instruby.rb (parse_args): added bin-arch and bin-comm to install
+ type, for compiled files and script files.
+
+ * instruby.rb (parse_args): deal with make style command line macros,
+ and count as long syle options if prefixed with INSTALL_.
+
+ * instruby.rb (makedirs): use $dir_mode. [ruby-dev:33805]
+
+ * instruby.rb (open_for_install): set file mode, which is now
+ permission mode instead of access mode.
+
+ * instruby.rb (bin-comm): installs scripts with replacing shebang
+ lines.
+
+Tue Feb 19 18:34:32 2008 Tanaka Akira <akr@fsij.org>
+
+ * gc.c (STACK_LENGTH) [SPARC] : 0x80 offset removed. [ruby-dev:33857]
+
+Tue Feb 19 14:27:32 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/readline/readline.c (readline_event): prevent polling. based on
+ a patch from error errorsson in [ruby-Bugs-17675].
+
+Tue Feb 19 12:08:29 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yycompile): clear ruby_eval_tree_begin if parse failed.
+
+Mon Feb 18 16:23:45 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yycompile): clear ruby_eval_tree_begin too before parse.
+
+Mon Feb 18 10:17:42 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/pty/lib/expect.rb (IO#expect): check if peer is closed.
+ [ruby-Bugs-17940]
+
+Fri Feb 15 20:37:06 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/rational.rb (floor, ceil, truncate, round): do not use
+ definitions of Numeric.
+
+ * lib/rational.rb (to_i): should returns truncated self.
+
+ * lib/complex.rb (numerator): requires
+ Integer#{numerator,denominator}.
+
+ * lib/complex.rb (quo): do not use definition of Numeric.
+
+ * lib/complex.rb (div, divmod, floor, ceil, truncate, round):
+ undef'ed.
+
+Fri Feb 15 15:23:12 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (iconv_convert): check upper bound. a patch from
+ Daniel Luz at [ruby-Bugs-17910].
+
+Fri Feb 15 02:42:25 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (ftruncate): check if available.
+
+ * file.c (rb_file_truncate): check if ftruncate instead of truncate.
+
+Fri Feb 15 02:40:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (sigsetmask): check when signal semantics is not POSIX.
+
+ * signal.c (USE_TRAP_MASK): set true if sigprocmask or sigsetmask is
+ available.
+
+Thu Feb 14 17:44:32 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dl/ptr.c (dlmem_each_i): typo fixed. a patch from IKOMA
+ Yoshiki <ikoma AT mb.i-chubu.ne.jp> in [ruby-dev:33776].
+
+Thu Feb 14 16:02:51 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_utime): inhibits with secure level 2 or higher.
+
+Thu Feb 14 01:43:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/timeout.rb (Timeout::timeout): made sensitive to location on the
+ stack. [ruby-core:15458]
+
+Thu Feb 14 00:49:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (INSTRUBY_ARGS): pass mode to install. [ruby-dev:33766]
+
+ * instruby.rb (parse_args): added --data-mode and --prog-mode options.
+
+Tue Feb 12 11:33:26 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/erb/test_erb.rb(TestERBCore): import from erb-2.0.4.
+
+ * test/erb/hello.erb: ditto
+
+Mon Feb 11 17:25:21 2008 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb (RSS::VERSION), test/rss/test_version.rb, NEWS:
+ 0.2.3 -> 0.2.4.
+
+ * lib/rss/maker.rb, lib/rss/maker/, test/rss/test_maker_2.0.rb:
+ fixed a bug that RSS::Maker.make("0.9")'s item doesn't make some
+ elements if description is missed.
+ Reported by Michael Auzenne. Thanks!!!
+
+ * lib/rss/maker/0.9.rb, test/rss/test_maker_0.9.rb:
+ RSS::Maker.make("0.9") generates RSS 0.92 not RSS 0.91.
+
+Mon Feb 11 16:57:00 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * ChangeLog: format-time-string under C locale. [ruby-dev:33261]
+
+Mon Feb 11 16:31:47 2008 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
+
+ * gc.c (rb_newobj): prohibit call of rb_newobj() during gc.
+ Submitted by Sylvain Joyeux [ruby-core:12099].
+
+ * ext/dl/ptr.c: do not use LONG2NUM() inside dlptr_free().
+ Slightly modified fix bassed on a patch by Sylvain Joyeux
+ [ruby-core:12099] [ ruby-bugs-11859 ] [ ruby-bugs-11882 ]
+ [ ruby-patches-13151 ].
+
+Mon Feb 11 00:22:55 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/benchmark.rb (Job::Benchmark#item): fix typo.
+
+Sat Feb 9 23:22:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/bigdecimal/extconf.rb: simplified the condition.
+
+Sat Feb 9 17:51:24 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_to_f): use strtod() for more
+ precision. [ruby-talk:290296]
+
+ * ext/bigdecimal/bigdecimal.c (BASE_FIG): made constant.
+
+ * ext/bigdecimal/extconf.rb: ditto. [ruby-dev:33658]
+
+Sat Feb 9 00:44:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/irb.rb (IRB::Irb::eval_input): rescues Interrupt and other than
+ SystemExit and SignalException. [ruby-core:15359]
+
+Fri Feb 8 15:09:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (xsystem): expand macros like as make.
+
+Tue Feb 5 11:14:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (INSTALL_DIRS, install_dirs): added BINDIR.
+
+ * lib/mkmf.rb (install_files): rejects files matching to
+ $NONINSTALLFILES.
+
+ * lib/mkmf.rb (init_mkmf): defaults $NONINSTALLFILES to backup and
+ temporary filse.
+
+Mon Feb 4 16:44:24 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (darwin): NSIG is not defined if _XOPEN_SOURCE > 500L.
+ [ruby-dev:33584]
+
+Sat Feb 2 20:06:42 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/benchmark.rb (Benchmark::realtime): make Benchmark#realtime
+ a bit faster. a patch from Alexander Dymo <dymo AT ukrpost.ua> in
+ [ruby-core:15337].
+
+Sat Feb 2 09:53:39 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (darwin): disabled fat-binary support which confuses
+ configure much, since ``universal'' implies hidden cross-compiling.
+ TODO: ruby and libruby.bundle might be possible to bound with `lipo'
+ after builds for each archs. Anyway, config.h and rbconfig.rb must
+ be separated definitely at least.
+
+Fri Feb 1 21:42:37 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (darwin): _XOPEN_SOURCE is necessary to make ucontext_t
+ consistent with the library implementation of MacOS X 10.5.
+ [ruby-dev:33461]
+
+ * configure.in (darwin): ucontext on PowerPC MacOS X 10.5 is broken.
+
+Thu Jan 31 08:31:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (ext/extmk.rb, instruby.rb): inlined $(MAKE) so that can
+ be executed even with -n.
+
+Thu Jan 31 07:00:19 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (bin_for_find): should find a symbol by
+ Symbol class.
+
+ * test/rinda/test_rinda.rb (test_symbol_tuple): ditto.
+
+Wed Jan 30 22:07:58 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: refined deprecated methods.
+
+Wed Jan 30 22:06:54 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * bignum.c (rb_cstr_to_inum): '0_2' is a valid representation.
+
+Tue Jan 29 22:40:12 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * range.c (step_i): rb_funcall receives VALUE as an argument.
+
+Tue Jan 29 11:53:05 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: rm largefile.h.
+
+Mon Jan 28 01:21:15 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_open_file): should check NUL in path.
+ <http://www.rubyist.net/~matz/20080125.html#c01>.
+
+ * io.c (rb_io_s_popen): ditto.
+
+ * io.c (rb_io_reopen): ditto.
+
+ * io.c (next_argv): ditto.
+
+ * io.c (rb_io_s_foreach): ditto.
+
+ * io.c (rb_io_s_readlines): ditto.
+
+ * io.c (rb_io_s_read): ditto.
+
+Fri Jan 25 22:33:38 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * math.c: fix comment. [ruby-dev:33276]
+
+Fri Jan 25 10:31:58 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * */*.bat: set svn:mime-type to text/batch.
+
+Thu Jan 24 19:36:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/uri/generic.rb (URI::Generic::inspect): use Kernel#to_s instead
+ object_id with printf. [ruby-dev:33347]
+
+Tue Jan 22 11:22:47 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/setup.mak ($(ARCH)): if a macro is appended by $(APPEND),
+ a space will be inserted on the top of the line.
+
+ * win32/Makefile.sub (MKFILES): stop make process if Makefile is
+ updated.
+
+Mon Jan 21 17:34:41 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * io.c (rb_io_mode_flags, rb_io_mode_modenum): Ignore encoding
+ options for forward compatibility.
+
+Mon Jan 21 12:50:02 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c, gc.c (setjmp): sigsetjmp is a macro on cygwin.
+
+Sat Jan 19 11:21:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (sigsetjmp): check if available.
+
+ * eval.c, gc.c (setjmp): do not use _setjmp if sigsetjmp is available.
+
+Sat Jan 19 11:10:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: Remove wrong assumptions about Cygwin. a patch from
+ Corinna Vinschen in [ruby-Bugs-17018].
+
+Thu Jan 17 21:06:01 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (Date::Infinity#<=>): didn't work. A patch from
+ Dirkjan Bussink <d.bussink AT gmail.com> [ruby-core:15098].
+ This is a bug obviously. However it didn't affect the library's
+ functions.
+
+ * lib/date.rb, lib/date/format.rb: some trivial changes.
+
+Tue Jan 15 15:09:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/setup.mak: strip out empty lines from CPP output.
+
+Tue Jan 15 03:41:42 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (eval): check if backtrace is empty. [ruby-core:15040]
+
+Tue Jan 15 01:28:47 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk: simplified dummy objects dependencies.
+
+Mon Jan 14 16:12:58 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/shellwords.rb: scape should be an alias to shellescape. a
+ patch from Masahiro Kawato <m-kawato AT mwb.biglobe.ne.jp> in
+ [ruby-dev:33060].
+
+Mon Jan 14 09:32:40 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/time.rb: do not reference Time directly from the inside of
+ definitions. [ruby-dev:33059]
+
+Sat Jan 12 18:27:41 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_define_alloc_func, rb_undef_alloc_func): should
+ define/undef on a signleton class. [ruby-core:09959]
+
+Sat Jan 12 12:04:14 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: tuning for performance.
+
+Fri Jan 11 12:35:56 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: moved broken syscall checks from process.c etc.
+
+ * defines.h (WORDS_BIGENDIAN): honor __BIG_ENDIAN__ than the result of
+ configure.
+
+ * dln.c: use dlopen on Mac OS X 10.3 or later. backport from trunk.
+
+ * lib/rdoc/options.rb (check_diagram): more precise check, darwin
+ is not Windows but minwg is on it.
+
+Thu Jan 10 10:53:50 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_open_osfhandle): reverted to old definition.
+ [ ruby-Bugs-16948 ]
+
+Tue Jan 8 20:02:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win{32,ce}/Makefile.sub: merged.
+
+Sun Jan 6 09:39:02 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: introduced some constants
+ (for internal use).
+
+ * sample/cal.rb: trivial adjustments.
+
+Fri Jan 4 23:08:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (time_arg): use converted object. [ruby-core:14759]
+
+Fri Jan 4 01:20:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32.h: only VC6 needs extern "C++" for math.h. [ruby-talk:285660]
+
+Thu Jan 3 11:28:58 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (fptr_finalize): clear errno first. [ruby-talk:284492]
+
+Wed Jan 2 10:18:56 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * sample/time.rb: use Process.times instead of Time.times.
+
+Wed Jan 2 09:18:11 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * sample/goodfriday.rb: examples for date are enough. retired.
+
+Wed Jan 2 09:06:55 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * sample/cal.rb: just updated with the newest version.
+
+Mon Dec 31 06:50:38 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * trunk/common.mk: not use -I$(srcdir)/lib with $(MINIRUBY) for cross
+ compiling.
+
+ * configure.in, {win,bcc}32/Makefile.sub (MINIRUBY): -I$(srcdir)/lib
+ moved.
+
+Sun Dec 30 22:48:37 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (_valid_time?): I'm not sure to recommend such an
+ expression. but anyway it is acceptable now. [ruby-core:14580]
+
+Fri Dec 28 16:36:33 2007 NARUSE, Yui <naruse@airemix.com>
+
+ * lib/resolv.rb (Resolv::DNS#each_address): now returns IPv6 address.
+
+Fri Dec 28 13:21:32 2007 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb, test/rss/test_version.rb, NEWS: 0.2.2 -> 0.2.3.
+
+ * lib/rss/parser.rb, test/rss/test_parser.rb: supported "-" in tag name.
+ Reported by Ray Chen. Thanks.
+
+Thu Dec 27 23:56:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * mkconfig.rb: should not use the libraries under the source directory
+ at cross compiling.
+
+Thu Dec 27 11:02:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * intern.h, string.c (rb_str_set_len): added for upgrading path from
+ 1.8 to 1.9. [ruby-dev:32807]
+
+ * string.c (rb_str_lines, rb_str_bytes): ditto.
+
+Thu Dec 27 10:47:32 2007 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/ossl_ssl.c: Only show a warning if the default
+ DH callback is actually used.
+
+ * ext/openssl/ossl_rand.c: New method: random_add().
+
+Wed Dec 26 22:27:45 2007 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/resolv.rb (Resolv::DNS::Name.==): fix for other is array of
+ Resolv::DNS::Label::Str.
+
+ * lib/resolv.rb (Resolv::DNS::MessageEncoder#put_label): String#string
+ is not defined, so replace to_s.
+
+ * lib/resolv.rb (Resolv::IPv6#to_name): ip6.int is obsoleted by
+ int.arpa.
+
+Mon Dec 24 16:18:57 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/ri/ri_options.rb: Fix ri --help listing of gem ri paths.
+ Merge of r14567 and r14569 from trunk.
+
+ * lib/rdoc/ri/ri_paths.rb: Fix duplication of ri data for multiple
+ gems. Merge of r14567 from trunk
+
+Mon Dec 24 12:35:03 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win{32,ce}/Makefile.sub (MFLAGS): defaulted to -l.
+
+Mon Dec 24 11:56:31 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * {bcc32,win{32,ce}}/Makefile.sub (SET_MAKE): set MFLAGS which is not
+ set by default, to get rid of chaotic situation of MFLAGS/MAKEFLAGS.
+
+Sat Dec 22 14:49:46 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: don't freeze nil even if 1.8 will not be aware of
+ the issue. [ruby-dev:32677]
+
+Wed Dec 19 13:57:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (TIMEZONE_VOID): check whether timezone requires zero
+ arguments. [ruby-dev:32631]
+
+Wed Dec 19 12:01:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (f_rest_arg): check if duplicated. [ruby-core:14140]
+
+Wed Dec 19 10:52:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_cstr_to_inum): an underscore succeeding after octal
+ prefix is allowed. [ruby-core:14139]
+
+Mon Dec 17 13:43:15 2007 Tanaka Akira <akr@fsij.org>
+
+ * gc.c (stack_end_address): use local variable address instead of
+ __builtin_frame_address(0) to avoid SEGV on SunOS 5.11 on x86 with
+ gcc (GCC) 3.4.3 (csl-sol210-3_4-20050802).
+ stack_end_address returned a frame address of garbage_collect
+ since stack_end_address doesn't create its own frame.
+ So a VALUE stored in a callee saved register, %edi, pushed into
+ the stack at the beginning of garbage_collect was not marked.
+
+Mon Dec 17 12:21:25 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in (RUNRUBY): added RUNRUBYOPT.
+
+Fri Dec 14 12:36:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_CHECK_VARTYPE): check if a variable is defined
+ and its type.
+
+ * configure.in (timezone, altzone): check for recent cygwin.
+
+ * missing/strftime.c (strftime): fix for timezone. [ruby-dev:32536]
+
+ * lib/mkmf.rb (try_var): should fail for functions.
+
+ * ext/readline/extconf.rb: should use have_func for functions instead
+ of have_var.
+
+Tue Dec 11 00:04:05 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_slice_bang): If an invalid negative index (<
+ -size) is given, do not raise an exception but return nil just
+ like slice() does.
+
+ * test/ruby/test_array.rb (TestArray::test_slice,
+ TestArray::test_slice!): Pull in test cases from trunk.
+
+Mon Dec 10 21:47:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * transcode.c (str_transcode): allow non-registered encodings.
+ [ruby-dev:32520]
+
+Mon Dec 10 21:00:30 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_slice_bang): should return nil if position out
+ of range. a patch from Akinori MUSHA <knu AT iDaemons.org>.
+ [ruby-dev:32518]
+
+Mon Dec 10 18:28:06 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/uri/common.rb (URI::REGEXP::PATTERN): typo in REG_NAME
+ regular expression. a patch from Ueda Satoshi
+ <s-ueda AT livedoor.jp>. [ruby-dev:32514]
+
+Sun Dec 9 12:39:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/cgi.rb (read_multipart): exclude blanks from header values.
+ [ruby-list:44327]
+
+Wed Dec 5 23:38:50 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * range.c (range_each): followed step_i change.
+
+Wed Dec 5 18:08:45 2007 Tanaka Akira <akr@fsij.org>
+
+ * numeric.c (int_odd_p): new method Integer#odd?.
+ (int_even_p): new method Integer#even?.
+ (int_pred): new method Integer#pred.
+ (fix_odd_p): new method Fixnum#odd?.
+ (fix_even_p): new method Fixnum#even?.
+
+Wed Dec 5 15:15:21 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * range.c (step_i, range_step): support non-fixnum steps.
+ [ruby-talk:282100]
+
+Tue Dec 4 11:23:50 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_cstr_to_inum): trailing spaces may exist at sqeezing
+ preceeding 0s. [ruby-core:13873]
+
+Sun Dec 2 22:43:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (error_print): put newline unless multiple line message ends
+ with a newline. [ruby-dev:32429]
+
+Sun Dec 2 15:49:20 2007 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb, test/rss/test_version.rb, NEWS: 0.2.1 -> 0.2.2.
+
+ * lib/rss/maker/itunes.rb: fixed new_itunes_category.
+ * lib/rss/maker/taxonomy.rb: new_taxo_topic -> new_topic because
+ of consistency.
+
+ * test/rss/test_maker_itunes.rb, test/rss/test_itunes.rb: removed
+ needless UTF-8 characters.
+
+Sun Dec 2 01:12:15 2007 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 14070 from trunk.
+
+ * lib/xmlrpc/server.rb (XMLRPC::Server#server): Improve signal handling so
+ pressing control-c in the controlling terminal or sending SIGTERM stops
+ the XML-RPC server.
+
+Sat Dec 1 15:13:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/resolv.rb: documentation update. backported from 1.9.
+ [ruby-core:13273]
+
+Sat Dec 1 03:30:47 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (newline_node): set line from outermost node before removing
+ NODE_BEGIN. [ruby-dev:32406]
+
+Fri Nov 30 21:53:28 2007 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb, test/rss/test_version.rb: 0.2.0 -> 0.2.1.
+
+ * lib/rss/content.rb, lib/rss/content/1.0.rb,
+ lib/rss/content/2.0.rb, lib/rss/maker/content.rb,
+ test/rss/rss-testcase.rb, test/rss/test_content.rb,
+ test/rss/test_maker_content.rb: supported content:encoded with RSS
+ 2.0.
+ Suggested by Sam Lown. Thanks.
+
+ * NEWS: added the above changes.
+
+Thu Nov 29 16:59:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (stmt): remove unnecessary NODE_BEGIN. [ruby-core:13814]
+
+Wed Nov 28 14:43:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extract_makefile): use dldflags instead of DLDFLAGS to
+ get rid of mixing $LDFLAGS and $ARCH_FLAG.
+
+ * lib/mkmf.rb (configuration): ditto.
+
+ * lib/mkmf.rb (create_makefile): support for extensions which has no
+ shared object.
+
+Wed Nov 28 09:51:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): do not clobber space for sign.
+
+ * sprintf.c (remove_sign_bits): extends sign bit first.
+
+Wed Nov 21 01:04:12 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (nil_plus): remove unused function. [ruby-core:13737]
+
+Sun Nov 18 14:03:44 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_alias): do not call hook functions until initialization
+ finishes. [ruby-talk:279538]
+
+Sun Nov 18 09:09:48 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (String#tr_cpp): make preprocessor identifiers.
+
+Sat Nov 17 13:58:11 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_invoke): bug fix. [ruby-talk:279100]
+
+Fri Nov 16 17:41:34 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (Document-class): moved the simplest example to
+ the top.
+
+ * ext/iconv/iconv.c (iconv_s_iconv): Document-method: needs class
+ prefix for class method. [ruby-core:13542]
+
+ * ext/iconv/iconv.c (iconv_iconv): also instance method needs to be
+ qualified.
+
+Fri Nov 16 11:16:41 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/yaml/rubytypes.rb (String#is_binary_data?): use Integer#fdiv.
+
+Thu Nov 15 19:50:46 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/curses/extconf.rb: check macro if cannot find func.
+ [ruby-list:44224]
+
+Thu Nov 15 12:19:14 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi/session.rb (CGI::Session::FileStore::restore): use
+ lockfile for exclusive locks. a patch from <tommy AT tmtm.org>.
+ [ruby-dev:32296]
+
+Wed Nov 14 01:52:59 2007 Tanaka Akira <akr@fsij.org>
+
+ * missing/isinf.c (isinf): don't define if the macro is defined.
+
+Wed Nov 14 01:34:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (round): fallback definition.
+
+ * numeric.c (flo_divmod, flo_round): use round() always.
+ [ruby-dev:32269]
+
+Tue Nov 13 22:02:23 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: remove Thread.exclusive.
+
+ * lib/drb/extservm.rb: ditto.
+
+Tue Nov 13 16:33:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (flodivmod): work around for infinity.
+
+ * numeric.c (flo_divmod): work around for platforms have no round().
+ [ruby-dev:32247]
+
+Tue Nov 13 13:58:51 2007 Tanaka Akira <akr@fsij.org>
+
+ * numeric.c (numeric.c): Integer#ord implemented. [ruby-dev:32206]
+
+Tue Nov 13 02:57:04 2007 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
+
+ * numeric.c (flo_divmod): round to the nearest integer.
+ [ ruby-Bugs-14540 ]
+
+Mon Nov 12 16:52:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): rdoc about srcprefix. a patch from
+ Daniel Berger <djberg96 AT gmail.com> in [ruby-core:13378].
+
+Mon Nov 12 13:53:06 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-parse-partial): handle stringified
+ symbols properly using ruby-forward-string.
+
+Mon Nov 12 12:38:31 2007 Tanaka Akira <akr@fsij.org>
+
+ * Makefile.in (lex.c): don't remove lex.c at first.
+
+Fri Nov 9 07:26:04 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * random.c: update MT URL.[ruby-core:13305].
+
+Wed Nov 7 03:32:38 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rexml/encodings/SHIFT-JIS.rb (REXML::Encoding): place -x for
+ nkf conversion. a patch from <moonwolf AT moonwolf.com>.
+ [ruby-dev:32183]
+
+Mon Nov 5 05:17:04 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::Switch::summarize): fix for long form
+ option with very long argument. a patch from Kobayashi Noritada
+ <nori1 AT dolphin.c.u-tokyo.ac.jp> in [ruby-list:44179].
+
+Mon Nov 5 01:20:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (call_args): remove "parenthesize argument(s) for future
+ version" warning. when I added this warning, I had a plan to
+ reimplement the parser that is simpler than the current one.
+ since we abandoned the plan, warning no longer required.
+
+Fri Nov 2 00:13:51 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_assoc): check and convert inner arrays (assocs)
+ using #to_ary.
+
+ * hash.c (rb_hash_s_create): check and convert argument hash
+ using #to_hash.
+
+ * hash.c (rb_hash_s_create): Hash#[] now takes assocs as source of
+ hash conversion.
+
+Thu Nov 1 23:47:43 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (DRbTCPSocket): Improving with multiple network
+ interface.
+
+ * test/drb/drbtest.rb: ditto.
+
+Fri Oct 26 17:14:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (fix_pow): returns 1.0 for 0**0.0.
+
+ * numeric.c (fix_pow): returns infinity for 0**-1. [ruby-dev:32084]
+
+Wed Oct 25 07:18:09 2007 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 13781 from trunk.
+
+ * lib/net/telnet.rb (Net::Telnet#login): Allowing "passphrase" in
+ addition to "password" for Telnet login prompts. [ruby-Bugs-10746]
+
+Wed Oct 25 06:46:21 2007 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 13779 from trunk.
+
+ * lib/net/telnet.rb (Net::Telnet#login): Making the password prompt
+ pattern case insensitive. [ruby-Bugs-10746]
+
+Thu Oct 25 14:19:33 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_tell, rb_io_seek): check errno too. [ruby-dev:32093]
+
+Wed Oct 25 08:03:53 2007 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 13767, 13768, 13769, and 13770 from trunk.
+
+ * lib/xmlrpc/parser.rb (XMLRPC::Convert::dateTime): Fixing a bug that
+ caused time zone conversion to fail for some ISO 8601 date formats.
+ [ruby-Bugs-12677]
+
+ * lib/xmlrpc/client.rb (XMLRPC::Client#do_rpc): Explicitly start
+ the HTTP connection to support keepalive requests. [ruby-Bugs-9353]
+
+ * lib/xmlrpc/client.rb (XMLRPC::Client#do_rpc): Improving the error
+ message for Content-Type check failures. [ruby-core:12163]
+
+ * lib/xmlrpc/utils.rb (XMLRPC::ParseContentType#parse_content_type):
+ Making Content-Type checks case insensitive. [ruby-Bugs-3367]
+
+Sun Oct 21 21:16:43 2007 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss.rb, lib/rss/, test/rss/, sample/rss/: merged from trunk.
+ - 0.1.6 -> 2.0.0.
+ - fixed image module URI. Thanks to Dmitry Borodaenko.
+ - supported Atom.
+ - supported ITunes module.
+ - supported Slash module.
+
+ * NEWS: added an entry for RSS Parser.
+
+Thu Oct 18 10:57:06 2007 Tanaka Akira <akr@fsij.org>
+
+ * ruby.h (RCLASS_IV_TBL): defined.
+ (RCLASS_M_TBL): ditto.
+ (RCLASS_SUPER): ditto.
+ (RMODULE_IV_TBL): ditto.
+ (RMODULE_M_TBL): ditto.
+ (RMODULE_SUPER): ditto.
+
+Mon Oct 15 22:08:55 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Merge some of the sub-sections, as the differences were
+ unclear.
+
+Mon Oct 15 21:57:07 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Mention ipaddr enhancements.
+
+ * lib/ipaddr.rb (in_addr, in6_addr, addr_mask): Make some minor
+ code optimization.
+
+ * lib/ipaddr.rb (<=>): Implement IPAddr#<=> and make IPAddr
+ comparable.
+
+ * lib/ipaddr.rb (succ): Implement IPAddr#succ. You can now create
+ a range between two IPAddr's, which (Range) object is
+ enumerable.
+
+ * lib/ipaddr.rb (to_range): A new method to create a Range object
+ for the (network) address.
+
+ * lib/ipaddr.rb (coerce_other): Support type coercion and make &,
+ |, == and include? accept a string or an integer instead of an
+ IPAddr object as the argument.
+
+ * lib/ipaddr.rb (initialize): Give better error messages.
+
+ * lib/ipaddr.rb: Improve documentation.
+
+Mon Oct 15 21:24:25 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Mention shellwords and tempfile enhancements.
+
+ * NEWS: Move the entry about Tk::X_Scrollable to a better section.
+
+Mon Oct 15 17:28:20 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/openssl/lib/openssl/buffering.rb (read, readpartial): revert
+ r12496. handling EOF is a little differnt in ruby 1.8 and ruby 1.9.
+ [ruby-dev:31979]
+
+Mon Oct 15 11:45:12 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (r_bytes0): refined length check. [ruby-dev:32059]
+
+Mon Oct 15 09:58:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (r_bytes0): check if source has enough data.
+ [ruby-dev:32054]
+
+Mon Oct 15 01:15:09 2007 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/socket.c (s_accept_nonblock): make accepted fd
+ nonblocking. [ruby-talk:274079]
+
+Sun Oct 14 04:08:34 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (AC_SYS_LARGEFILE): keep results also in command
+ options, to vail out of mismatch. [ruby-list:44114]
+
+ * mkconfig.rb, lib/mkmf.rb (configuration): add DEFS.
+
+Sun Oct 14 03:55:52 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/mkexports.rb: deal with __fastcall name decorations.
+ [ruby-list:44111]
+
+Sat Oct 13 09:02:16 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * {bcc,win}32/mkexports.rb: explicit data. [ruby-list:44108]
+
+Sat Oct 13 00:35:03 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rexml/source.rb (REXML::SourceFactory::SourceFactory): typo
+ fixed. [ruby-list:44099]
+
+Fri Oct 12 11:22:15 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (match_values_at): make #select to be alias to #values_at
+ to adapt RDoc description. [ruby-core:12588]
+
+Thu Oct 11 14:32:46 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32}/Makefile.sub (COMMON_MACROS): workaround for old SDK's
+ bug. [ruby-core:12584]
+
+Wed Oct 10 23:34:45 2007 Tanaka Akira <akr@fsij.org>
+
+ * lib/securerandom.rb: new file. [ruby-dev:31928]
+
+ * lib/cgi/session.rb (create_new_id): use securerandom if available.
+
+Tue Oct 9 01:01:55 2007 Tanaka Akira <akr@fsij.org>
+
+ * re.c (rb_reg_s_union_m): Regexp.union accepts single
+ argument which is an array of patterns. [ruby-list:44084]
+
+Mon Oct 8 20:06:23 2007 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/net/http.rb, lib/open-uri.rb: remove
+ Net::HTTP#enable_post_connection_check. [ruby-dev:31960]
+
+ * lib/net/imap.rb: hostname should be verified against server's
+ indentity as persented in the server's certificate. [ruby-dev:31960]
+
+ * ext/openssl/lib/net/telnets.rb, ext/openssl/lib/net/ftptls.rb: ditto.
+
+Sat Oct 6 23:14:54 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_to_i): update RDoc since base can be any value
+ between 2 and 36. [ruby-talk:272879]
+
+Fri Oct 5 15:44:50 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/shellwords.rb: Add shellescape() and shelljoin().
+
+ * lib/shellwords.rb: Rename shellwords() to shellsplit() and make
+ the former an alias to the latter.
+
+ * lib/shellwords.rb: Add escape(), split(), join() as class
+ methods, which are aliases to their respective long names
+ prefixed with `shell'.
+
+ * lib/shellwords.rb: Add String#shellescape(), String#shellsplit()
+ and Array#shelljoin() for convenience.
+
+Fri Oct 5 15:40:04 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/tempfile.rb (Tempfile::make_tmpname): Allow to specify a
+ suffix for a temporary file name.
+
+ * lib/tempfile.rb (Tempfile::make_tmpname): Make temporary file
+ names less predictable by including a random string.
+ [inspired by: akr]
+
+Tue Oct 2 21:20:14 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (make_cmdvector): adjust escaped successive
+ double-quote handling. (merge from trunk)
+
+Tue Oct 2 20:35:24 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (init_env): initialize HOME and USER environment
+ variables unless set. [ruby-core:12328] (merge from trunk)
+
+ * win32/win32.c (NtInitialize, getlogin): ditto.
+
+ * configure.in, win32/Makefile.sub (LIBS): need to link shell32
+ library for SH* functions on mswin32 and mingw32.
+
+Mon Oct 1 12:50:59 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (id2ref): valid id should not refer T_VALUE nor T_ICLASS.
+ [ruby-dev:31911]
+
+Wed Sep 26 23:54:37 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake), lib/mkmf.rb (configuration): top_srcdir
+ should not prefixed with DESTDIR.
+
+Wed Sep 26 08:36:31 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in (ext/extinit.o): use $(OUTFLAG) as well as other
+ objects. [ruby-Bugs-14228]
+
+Wed Sep 26 05:12:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yyerror): limit error message length. [ruby-dev:31848]
+
+ * regex.c (re_mbc_startpos): separated from re_adjust_startpos.
+
+Tue Sep 25 13:47:38 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (remove_method): should not remove undef place holder.
+ [ruby-dev:31817]
+
+Mon Sep 24 16:52:11 2007 Urabe Shyouhei <shyouhei@ruby-lang.org>
+
+ * lib/net/http.rb: fix typo.
+
+Sun Sep 23 21:57:25 2007 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/net/http.rb: an SSL verification (the server hostname should
+ be matched with its certificate's commonName) is added.
+ this verification can be skipped by
+ "Net::HTTP#enable_post_connection_check=(false)".
+ suggested by Chris Clark <cclark at isecpartners.com>
+
+ * lib/net/open-uri.rb: use Net::HTTP#enable_post_connection_check to
+ perform SSL post connection check.
+
+ * ext/openssl/lib/openssl/ssl.c
+ (OpenSSL::SSL::SSLSocket#post_connection_check): refine error message.
+
+Sun Sep 23 09:05:05 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (os_obj_of, os_each_obj): hide objects to be finalized.
+ [ruby-dev:31810]
+
+Sun Sep 23 08:58:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval_method.ci (rb_attr): should not use alloca for unknowen size
+ input. [ruby-dev:31816]
+
+ * parse.y (rb_intern_str): prevent str from optimization.
+
+Sun Sep 23 05:42:35 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * lib/rdoc/options.rb (Options::check_diagram): dot -V output
+ changed. [ ruby-Bugs-11978 ], Thanks Florian Frank.
+
+Sat Sep 22 06:02:11 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::List::summarize): use each_line if
+ defined rather than each. [ruby-Patches-14096]
+
+Sat Sep 22 05:19:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_init): separate from strio_initialize
+ to share with strio_reopen properly. [ruby-Bugs-13919]
+
+Fri Sep 21 15:46:20 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (struct rb_exec_arg): proc should be a VALUE.
+
+ * process.c (rb_f_exec): suppress a warning.
+
+Fri Sep 21 03:05:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c, intern.h, ext/thread/thread.c: should not free queue while
+ any live threads are waiting. [ruby-dev:30653]
+
+Thu Sep 20 17:24:59 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (rb_detach_process): cast for the platforms where size of
+ pointer differs from size of int.
+
+ * process.c (rb_f_exec, rb_f_system): should not exceptions after
+ fork. [ruby-core:08262]
+
+Fri Sep 14 00:34:25 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/extservm.rb (invoke_service): use Thread.exclusive instead of
+ Thread.critical
+
+Wed Sep 12 23:12:22 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (proc_options): -W should be allowed in RUBYOPT
+ environment variable. [ruby-core:12118]
+
+Mon Sep 10 01:05:25 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * range.c (range_step): fixed integer overflow. [ruby-dev:31763]
+
+Sun Sep 9 09:14:45 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (_strptime): now also attaches an element
+ which denotes leftover substring if exists.
+
+Sat Sep 8 10:22:20 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (rb_struct_s_members): should raise TypeError instead
+ of call rb_bug(). [ruby-dev:31709]
+
+ * marshal.c (r_object0): no nil check require any more.
+
+Sat Sep 8 09:38:19 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (str[fp]time): now check specifications more
+ strictly.
+
+Fri Sep 7 05:36:19 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/rinda/test_rinda.rb (MockClock): correct synchronous problems
+ of the MultiThreading. [ruby-dev:31692]
+
+Wed Sep 5 22:02:27 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_subseq): need integer overflow check.
+ [ruby-dev:31736]
+
+ * array.c (rb_ary_splice): ditto. [ruby-dev:31737]
+
+ * array.c (rb_ary_fill): ditto. [ruby-dev:31738]
+
+ * string.c (rb_str_splice): integer overflow for length.
+ [ruby-dev:31739]
+
+Sun Sep 2 00:48:15 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (_parse): improved parsing of ordinal dates.
+
+ * lib/date/format.rb (_parse): use named character classes in some
+ regular expressions.
+
+Sat Sep 1 08:13:36 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c: add WIN32OLE#ole_activex_initialize.
+
+Thu Aug 30 13:13:13 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (try_const, have_const): check for a const is defined.
+ [ruby-core:04422]
+
+Thu Aug 30 13:10:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (group_member): check if presents.
+
+ * configure.in (XCFLAGS): add _GNU_SOURCE on linux.
+
+ * file.c (group_member): use system routine if available.
+
+Thu Aug 30 08:24:18 2007 Tanaka Akira <akr@fsij.org>
+
+ * ruby.h (RHASH_TBL): defined for compatibility to 1.9.
+ * (RHASH_ITER_LEV): ditto.
+ * (RHASH_IFNONE): ditto.
+ * (RHASH_SIZE): ditto.
+ * (RHASH_EMPTY_P): ditto.
+
+Wed Aug 29 13:05:59 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * include/ruby/defines.h (flush_register_windows): call "ta 0x03"
+ even on Linux/Sparc. [ruby-dev:31674]
+
+Tue Aug 28 23:26:12 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_type_progid, reg_enum_key,
+ reg_get_val, ole_wc2mb): fix the bug. Thanks, arton.
+ [ruby-dev:31576]
+
+Mon Aug 27 19:10:50 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/etc/etc.c (etc_getlogin): update documentation to note
+ security issue. [ruby-Bugs-11821]
+
+Tue Aug 21 21:09:48 2007 Tanaka Akira <akr@fsij.org>
+
+ * lib/tmpdir.rb (Dir.mktmpdir): make directory suffix specifiable.
+
+Tue Aug 21 13:57:04 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (st_foreach_func, rb_foreach_func): typedefed.
+
+Mon Aug 20 17:25:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (mnew): should preserve noex as safe_level.
+
+ * eval.c (rb_call0): tighten security check condition..
+
+Sat Aug 18 21:32:20 2007 Tanaka Akira <akr@fsij.org>
+
+ * lib/tmpdir.rb (Dir.mktmpdir): new method.
+ [ruby-dev:31462]
+
+Sat Aug 18 17:44:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/tk/tcltklib.c (Init_tcltklib): use rb_set_end_proc().
+
+Sat Aug 18 15:59:52 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (detach_process_watcher): should not pass the pointer
+ to an auto variable to the thread to be created. pointed and
+ fix by KUBO Takehiro <kubo at jiubao.org> [ruby-dev:30618]
+
+Sat Aug 18 12:24:30 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sample/test.rb, test/ruby/test_system.rb(valid_syntax?): keep
+ comment lines first.
+
+Thu Aug 16 20:40:50 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (bigtrunc): RBIGNUM(x)->len may be zero. out of bound
+ access. [ruby-dev:31404]
+
+Thu Aug 16 16:46:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (aix): enable shared by default.
+
+ * configure.in (aix): for 64bit-mode AIX. [ruby-dev:31401]
+ + use CC for LDSHARED if non-gcc,
+ + moved -G option from *LDFLAGS to LDSHARED,
+ + set -brtl only in XLDFLAGS.
+
+Thu Aug 16 13:06:08 2007 Tanaka Akira <akr@fsij.org>
+
+ * bignum.c (big_lshift): make shift offset long type.
+ (big_rshift): ditto.
+ (rb_big_lshift): ditto.
+ (big_rshift): ditto.
+ [ruby-dev:31434]
+
+Thu Aug 16 04:09:19 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (Rinda::TupleSpace#start_keeper): improve
+ keeper thread.
+
+Wed Aug 15 13:50:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_hash_delete_key): delete the entry without calling block.
+
+ * hash.c (rb_hash_shift): should consider iter_lev too.
+
+ * hash.c (delete_if_i): use rb_hash_delete_key() so that the block
+ isn't called twice. [ruby-core:11556]
+
+Sun Arg 12 03:56:30 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb: fix Rinda::TupleSpace keeper thread bug.
+ the thread is started too early. [ruby-talk:264062]
+
+ * test/rinda/test_rinda.rb: ditto.
+
+Sat Aug 11 07:34:10 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: reverted some wrongly erased "o" options
+ (pointed out by nobu).
+
+Tue Aug 7 14:58:39 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/pty/pty.c (establishShell): handshaking before close slave
+ device. [ruby-talk:263410]
+
+ * ext/pty/pty.c (MasterDevice, SlaveDevice, deviceNo): constified.
+
+ * ext/pty/pty.c (SlaveName): removed static buffer.
+
+ * ext/pty/expect_sample.rb: support for autologin.
+
+Tue Aug 7 12:45:13 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (ac_cv_func_isinf): set yes also on OpenSolaris.
+ [ruby-Bugs-12859]
+
+Mon Aug 6 17:36:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rexml/encodings/{ISO-8859-15,CP-1252}.rb: fixed invalid syntax.
+
+Fri Aug 3 11:05:54 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake): save all CONFIG values.
+
+ * ext/extmk.rb (extmake): remove mkmf.log at clean, and extconf.h at
+ distclean, respectively.
+
+ * ext/extmk.rb: remove rdoc at clean, and installed list file at
+ distclean, respectively.
+
+Fri Aug 3 07:09:05 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb: more verbose message. [ruby-Bugs-12766]
+
+ * lib/mkmf.rb (have_type): suppress a warning with -Wall.
+
+ * lib/mkmf.rb (find_type): new method.
+
+Thu Aug 2 13:46:39 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): should not check positional number as
+ width. [ruby-core:11838]
+
+Mon Jul 30 11:16:40 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_aref): check for Bignum index range.
+ [ruby-dev:31271]
+
+Sat Jul 28 09:35:41 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/digest/lib/digest.rb (Digest::self.const_missing): avoid
+ infinite recursive const_missing call. [ruby-talk:262193]
+
+Thu Jul 26 13:57:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dln.c (load_1, dln_find_1): constified.
+
+ * dln.c (conv_to_posix_path): removed.
+
+ * ruby.c (usage): constified.
+
+ * ruby.c (rubylib_mangled_path, rubylib_mangled_path2): return
+ VALUE instead of a pointer to static buffer.
+
+ * ruby.c (push_include_cygwin): fixed buffer overflow.
+ [ruby-dev:31297]
+
+ * ruby.c (ruby_init_loadpath): not convert built-in paths.
+
+Sun Jul 22 16:07:12 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * intern.h (is_ruby_native_thread): removed since declared as an int
+ function in ruby.h already.
+
+Sun Jul 22 14:33:40 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_rename): deleted code to get rid of a bug of
+ old Cygwin.
+
+ * file.c (rb_file_truncate): added prototype of GetLastError()
+ on cygwin. [ruby-dev:31239]
+
+ * intern.h (is_ruby_native_thread): prototype.
+
+ * missing/strftime.c (strftime): fix printf format and actual
+ arguments.
+
+ * ext/Win32API/Win32API.c (Win32API_initialize): ditto.
+
+ * ext/tk/tcltklib.c (ip_finalize): ditto.
+
+ * ext/dl/ptr.c (rb_dlptr_inspect): ditto. [ruby-dev:31268]
+
+ * ext/dl/sym.c (rb_dlsym_inspect): ditto.
+
+ * ext/socket/getnameinfo.c: include stdio.h always.
+
+ * ext/win32ole/win32ole.c (ole_hresult2msg, folevariable_name,
+ folevariable_ole_type, folevariable_ole_type_detail,
+ folevariable_value, folemethod_visible): missing return value.
+
+Sat Jul 21 17:48:26 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): make OBJS depend on RUBY_EXTCONF_H
+ only if extconf.h is created.
+
+ * bcc32/{Makefile.sub,configure.bat,setup.mak: configure_args
+ support.
+
+ * bcc32/setup.mak: check runtime version.
+
+ * win32/win32.c (rb_w32_open_osfhandle): prototype has changed
+ in bcc 5.82.
+
+ * {win32,wince,bcc32}/setup.mak (-version-): no RUBY_EXTERN magic.
+
+ * win32/resource.rb: include patchlevel number.
+
+Sat Jul 21 12:06:48 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (init_mkmf): should remove mkmf.log too.
+
+Sat Jul 21 01:53:17 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (Date._parse): completes calendar week based year.
+
+ * lib/date/format.rb (Date._parse): detects year of ordinal date in
+ extended format.
+
+Fri Jul 20 15:22:51 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/openssl/ossl_config.c (ossl_config_set_section): do not
+ initialize aggregations with dynamic values. [ruby-talk:259306]
+
+Thu Jul 19 19:24:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (get_backtrace): check the result more.
+ [ruby-dev:31261] [ruby-bugs-12398]
+
+Thu Jul 19 14:38:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_lshift, rb_big_rshift): separated functions
+ to get rid of infinite recursion. fixed calculation in edge
+ cases. [ruby-dev:31244]
+
+ * numeric.c (rb_fix_lshift, rb_fix_rshift): ditto.
+
+Wed Jul 18 16:57:41 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_pow): refine overflow check. [ruby-dev:31242]
+
+Wed Jul 18 08:47:09 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_succ): Time#succ should return a time object in the
+ same timezone mode to the original. [ruby-talk:260256]
+
+Tue Jul 17 00:50:53 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (fix_pow): integer power calculation: 0**n => 0,
+ 1**n => 1, -1**n => 1 (n: even) / -1 (n: odd).
+
+ * test/ruby/test_fixnum.rb (TestFixnum::test_pow): update test
+ suite. pow(-3, 2^64) gives NaN when pow(3, 2^64) gives Inf.
+
+Mon Jul 16 23:07:51 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/base64.rb (Base64::b64encode): should not specify /o option
+ for regular expression. [ruby-dev:31221]
+
+Mon Jul 16 18:29:33 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_rindex_m): accept string-like object convertible
+ with #to_str method, as well as rb_str_index_m. [ruby-core:11692]
+
+Mon Jul 16 05:45:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): more checks for format argument.
+ [ruby-core:11569], [ruby-core:11570], [ruby-core:11571],
+ [ruby-core:11573]
+
+Mon Jul 16 00:26:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_pow): removed invariant variable. [ruby-dev:31236]
+
+Sun Jul 15 23:59:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_neg): SIGNED_VALUE isn't in 1.8.
+
+Sun Jul 15 22:24:49 2007 pegacorn <subscriber.jp AT gmail.com>
+
+ * ext/digest/digest.c (rb_digest_instance_update,
+ rb_digest_instance_finish, rb_digest_instance_reset,
+ rb_digest_instance_block_length): %s in rb_raise() expects char*.
+ [ruby-dev:31222]
+
+ * ext/openssl/ossl.h: include ossl_pkcs5.h. [ruby-dev:31231]
+
+ * ext/openssl/ossl_pkcs5.h: new file for PKCS5. [ruby-dev:31231]
+
+ * ext/openssl/ossl_x509name.c (ossl_x509name_to_s): use ossl_raise()
+ instead of rb_raise(). [ruby-dev:31222]
+
+ * ext/sdbm/_sdbm.c: DOSISH platforms need io.h. [ruby-dev:31232]
+
+ * ext/syck/syck.h: include stdlib.h for malloc() and free().
+ [ruby-dev:31232]
+
+ * ext/syck/syck.h (syck_parser_set_input_type): prototype added.
+ [ruby-dev:31231]
+
+ * win32/win32.c: include mbstring.h for _mbspbrk(). [ruby-dev:31232]
+
+ * win32.h (rb_w32_getcwd): prototype added. [ruby-dev:31232]
+
+Sun Jul 15 21:07:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (bigtrunc): do not empty Bignum. [ruby-dev:31229]
+
+Sun Jul 15 19:05:28 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_cstr_to_inum): check leading non-digits.
+ [ruby-core:11691]
+
+Sun Jul 15 04:42:20 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (get2comp): do nothing for empty Bignum. [ruby-dev:31225]
+
+Sat Jul 14 14:04:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (sort_by_cmp): check if reentered. [ruby-dev:24291]
+
+Sat Jul 14 12:44:14 2007 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/openssl/test_pkcs7.rb: reverted the previous patch. it should
+ be as it was to check interface compatibility. sorry for bothering
+ with this.
+
+Sat Jul 14 12:16:17 2007 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/openssl/test_pkcs7.rb: follow the library change. applied a
+ patch from <zn at mbf.nifty.com> [ruby-dev:31214].
+ NOTE: r12496 imports the latest openssl libs from trunk to ruby_1_8
+ though its's not ChangeLog-ed. maintainer should aware that.
+
+Sat Jul 14 02:51:52 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (fix_pow): 0**2 should not raise floating point
+ exception. [ruby-dev:31216]
+
+Sat Jul 14 02:25:48 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (int_pow): wrong overflow detection. [ruby-dev:31213]
+
+ * numeric.c (int_pow): wrong overflow detection. [ruby-dev:31215]
+
+Fri Jul 13 16:10:00 2007 Tanaka Akira <akr@fsij.org>
+
+ * lib/open-uri.rb (URI::Generic#find_proxy): use ENV.to_hash to access
+ http_proxy environment variable to avoid case insensitive
+ environment search.
+
+Fri Jul 13 15:02:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (CreateChild): enclose command line except for
+ command.com which can not handle quotes. [ruby-talk:258939]
+
+Fri Jul 13 10:10:46 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (link_command, cc_command, cpp_command): do not expand
+ ::CONFIG which is an alias of MAKEFILE_CONFIG.
+
+Thu Jul 12 17:03:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * struct.c (rb_struct_init_copy): disallow changing the size.
+ [ruby-dev:31168]
+
+Wed Jul 11 23:38:14 2007 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * random.c: documentation fix. srand(0) initializes PRNG with '0',
+ not with random_seed.
+
+Tue Jul 10 14:50:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bcc32/{Makefile.sub,setup.mak}: remove surplus slash from srcdir.
+
+Fri Jul 6 15:22:58 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_interrupt): suppress a gcc's officious warning.
+
+Thu Jul 5 16:44:28 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * numeric.c (int_pow): fix previous nubu's commit.
+
+ * test/ruby/test_fixnum.rb: new test.
+
+Thu Jul 5 15:56:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (int_pow): even number multiplication never be negative.
+
+Mon Jul 2 14:34:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): sign bit extension should not be done
+ if FPLUS flag is specified. [ruby-list:39224]
+
+Sat Jun 30 16:05:41 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_initialize): should call rb_ary_modify() first.
+ [ruby-core:11562]
+
+Sat Jun 30 00:17:00 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yylex): return non-valid token for an invalid
+ instance/class variable name. a patch from Yusuke ENDOH
+ <mame AT tsg.ne.jp>. [ruby-dev:31095]
+
+Fri Jun 29 11:23:09 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (dsym): return non-null NODE even if yyerror(). based on a
+ patch from Yusuke ENDOH <mame AT tsg.ne.jp>. [ruby-dev:31085]
+
+Tue Jun 26 16:35:21 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (ruby_setreuid, ruby_setregid): rename to get rid of name
+ clash.
+
+ * process.c (proc_exec_v, rb_proc_exec): preserve errno.
+
+Sat Jun 23 00:37:46 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (rb_hash_select): remove unnecessary varargs for
+ rb_hash_select. a patch from Daniel Berger
+ <Daniel.Berger at qwest.com>. [ruby-core:11527]
+
+ * hash.c: ditto.
+
+Mon Jun 18 08:47:54 2007 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/{extconf.rb,ossl_ssl_session.c}:
+ Fix ruby-Bugs-11513.
+
+ * ext/openssl/ossl_pkey_ec.c
+ New methods EC::Point.[eql,make_affine!,invert!,on_curve?,infinity?]
+ By default output the same key form as the openssl command.
+
+ * ext/openssl/ossl_rand.c
+ New method Random.status?
+
+Mon Jun 18 13:54:36 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ruby_cleanup): return EXIT_FAILURE if any exceptions occured
+ in at_exit blocks. [ruby-core:11263]
+
+Mon Jun 18 01:14:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * variable.c (rb_path2class): get rid of dangling pointer caused by
+ optimized out value.
+
+ * variable.c (rb_global_entry, rb_f_untrace_var, rb_alias_variable,
+ rb_generic_ivar_table, generic_ivar_get, generic_ivar_set,
+ generic_ivar_defined, generic_ivar_remove, rb_mark_generic_ivar,
+ rb_free_generic_ivar, rb_copy_generic_ivar,
+ rb_obj_instance_variables): suppress warnings.
+
+Fri Jun 15 22:33:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (realclean): separate local and ext.
+
+ * ext/extmk.rb: not remove unrelated directories.
+
+Fri Jun 15 17:01:20 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/dl/lib/dl/win32.rb: seems that dl doesn't accept void argument.
+ fixed [ruby-bugs:PR#5489].
+
+Thu Jun 14 17:09:48 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser): handle more
+ extensions. [ruby-dev:30972]
+
+Wed Jun 13 06:05:12 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (darwin): prohibit loading extension libraries to
+ miniruby.
+
+Wed Jun 13 05:47:58 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_kill_thread): renamed in order to get rid of conflict
+ with a BeOS system function. [ruby-core:10830]
+
+Tue Jun 12 14:53:51 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (Logging.quiet, Logging.message): added quiet flag and
+ use it. [ruby-core:10909]
+
+ * lib/mkmf.rb (find_header): use header names in the message.
+
+Sun Jun 10 13:47:36 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/ruby/test_beginendblock.rb (test_should_propagate_signaled):
+ get rid of invoking shell. [ruby-dev:30942]
+
+Thu Jun 7 19:02:48 2007 Tanaka Akira <akr@fsij.org>
+
+ * lib/pp.rb: call original "method" method instead of redefined one.
+
+Mon Jun 4 11:11:12 2007 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (ResponseParser#next_token): fixed
+ error message. (backported from HEAD)
+
+ * lib/net/imap.rb (ResponseParser#parse_error): fixed
+ the condition not to refer @token.symbol unexpectedly.
+ Thanks, Dick Monahan. (backported from HEAD)
+
+Thu May 31 17:27:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/benchmark.rb (Benchmark::Job::item): avoid modifying the
+ argument unintentionally. [ruby-talk:253676]
+
+Thu May 31 02:12:32 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (Rinda::TupleBag): create index on tuple bag
+ by first column.
+
+Wed May 30 13:27:40 2007 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/ftp.rb (Net::FTP#transfercmd): skip 2XX
+ responses for some FTP servers. (backported from HEAD)
+
+Wed May 30 05:17:55 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_eval): get rid of SEGV at ZSUPER in a block
+ [ruby-dev:30836]
+
+Wed May 30 04:29:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (thread_timer): timer thread should not receive any
+ signals. submitted by Sylvain Joyeux. [ruby-core:08546]
+
+Wed May 30 04:18:37 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_eval_cmd): just return if no exceptions.
+ [ruby-dev:30820]
+
+Tue May 29 11:01:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_opendir): store attributes of the second
+ entries or later too.
+
+ * win32/win32.c (rb_w32_opendir, rb_w32_readdir): eliminate magic
+ numbers.
+
+Mon May 28 02:54:05 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (Rinda::TupleBag#delete): use rindex and
+ delete_at instead of delete for little improvement.
+
+Sat May 26 00:05:22 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/ruby/test_beginendblock.rb (test_should_propagate_signaled):
+ skip tests for exitstatus and termsig on the platforms where
+ signals not supported.
+
+Wed May 23 06:51:46 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * lib/cgi.rb (CGI#[]): get rid of exceptions being raised.
+ [ruby-dev:30740], Thanks Kentaro KAWAMOTO.
+
+Wed May 23 05:49:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb, ext/purelib.rb, lib/mkmf.rb, runruby.rb: clear default
+ load path to get rid of load pre-installed extensions/libraries.
+ [ruby-core:11017]
+
+Sat May 19 10:29:18 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (Date._parse): detects some OFX dates
+ (Of course not fully).
+
+Fri May 18 23:07:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_first): call rb_ary_subseq() instead of pushing
+ values by itself. [ruby-talk:252062]
+
+ * array.c (rb_ary_first): add negative length check.
+
+Fri May 18 17:10:31 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (move_to_next_entry): loc also must move forward.
+ [ruby-talk:251987]
+
+Fri May 18 03:02:40 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/mkexports.rb: preserve prefixed underscores for WINAPI
+ symbols.
+
+ * wince/mkconfig_wce.rb, wince/mkexports.rb: obsolete.
+
+Thu May 17 17:03:11 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-style.el (ruby-style-label-indent): for yacc rules.
+
+Tue May 15 14:54:07 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (init_stdhandle): stderr should be without buffering,
+ but mswin32 use buffering when stderr is not connected to tty.
+
+Mon May 14 13:28:03 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/thread/thread.c (wait_list): supress a warning.
+
+Thu May 10 15:21:51 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/iconv/iconv.c (iconv_s_conv): rdoc fix.
+
+Thu May 10 10:14:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_priority): rdoc fix; the initial value is
+ inherited from the creating thread. [ruby-core:10607]
+
+Wed May 9 12:28:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (Init_Bignum), numeric.c (Init_Numeric): added fdiv as
+ aliases of quo. [ruby-dev:30771]
+
+Wed May 9 11:55:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_quo): now calculate in integer. [ruby-dev:30753]
+
+Wed May 9 11:51:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_pow): reduce multiplying for even number.
+
+ * bignum.c (rb_big_pow): truncate all zero BDIGITs. [ruby-dev:30733]
+
+ * bignum.c (rb_big_pow): improvement by calculating from MSB and using
+ factorization. <http://yowaken.dip.jp/tdiary/20070426.html#p01>
+
+ * numeric.c (int_pow): calculate power in Fixnum as possible.
+ [ruby-dev:30726]
+
+Tue May 8 23:42:51 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (Date._parse): revised treatment of
+ hyphened/separatorless dates.
+
+ * lib/date/format.rb: some trivial adjustments.
+
+Tue May 8 20:25:05 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: reverted.
+
+Sat May 5 16:26:33 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/date/format.rb (Format::Bag#method_missing): get rid of
+ modifying orginal argument. [ruby-core:11090]
+
+Mon Apr 30 01:17:51 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (TupleSpace#create_entry, TupleBag#push,
+ delete): extract method, and rename parameter.
+
+Fri Apr 27 02:00:17 2007 Ryan Davis <ryand-ruby@zenspider.com>
+
+ * signal.c: Fixed backwards compatibility for 'raise Interrupt'.
+
+ * lib/yaml/tag.rb: Running rdoc over the 1.8.6 tree skips
+ Module. Patch from James Britt
+
+Thu Apr 26 13:54:51 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-style.el: new file. C/C++ style for ruby source code.
+
+Wed Apr 25 19:49:16 2007 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/socket.c (unix_send_io, unix_recv_io): use CMSG_DATA to
+ align file descriptor appropriately.
+
+Tue Apr 24 09:33:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (do_stat, do_lstat, do_opendir): should not warn ENOTDIR.
+ [ruby-talk:248288]
+
+Mon Apr 23 22:14:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb ($ruby): add extout directory to include path.
+ [ruby-core:11003]
+
+ * lib/mkmf.rb (libpathflag): not to append RPATHFLAG to current
+ directory.
+
+ * lib/mkmf.rb (init_mkmf): add current directory to default
+ library path with highest priority. [ruby-core:10960]
+
+ * lib/mkmf.rb (LINK_SO): LIBPATH to be placed before DLDFLAGS.
+
+Fri Apr 20 16:05:22 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (LIBPATHFLAG, RPATHFLAG): no needs to be quoted,
+ it is done by libpathflag in mkmf.rb.
+
+Fri Apr 20 12:27:04 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb: fix to override conv proc.
+
+Fri Apr 20 12:17:05 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ruby_cleanup): inversed the order of errinfos.
+
+Thu Apr 19 14:53:32 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/monitor.rb (ConditionVariable#wait, mon_enter, mon_exit_for_cond):
+ ensures Thread.critical to be false. [ruby-talk:248300]
+
+Wed Apr 18 10:41:21 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * util.c (ruby_strtod): exponent is radix 10. [ruby-talk:248272]
+
+Wed Apr 18 02:30:24 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (LDFLAGS): prepend -L. instead appending it to
+ XLDFLAGS. [ruby-core:10933]
+
+ * configure.in (Makefile): remove $U for automake from MISSING.
+ [ruby-talk:248171]
+
+Tue Apr 17 16:46:46 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): should not clear state on TAG_NEXT when
+ it's invoked from within lambda body. [ruby-talk:248136]
+
+ * eval.c (proc_invoke): handle TAG_NEXT which would be caused by
+ next in the lambda body as well.
+
+Mon Apr 16 22:56:01 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/pty/expect_sample.rb: avoid symbolic link representation for
+ expect. a patch from Kazuhiro NISHIYAMA <zn at mbf.nifty.com>.
+ [ruby-dev:30714]
+
+Mon Apr 16 22:51:11 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sample: replace TRUE, FALSE with true, false respectively.
+ a patch from Kazuhiro NISHIYAMA <zn at mbf.nifty.com>.
+ [ruby-dev:30713]
+
+Mon Apr 16 17:08:02 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (make_switch): do not clobber converter if pattern
+ has no convert method. reported by sheepman in [ruby-dev:30709].
+
+Mon Apr 16 16:49:32 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_seek): consistent behavior with
+ IO#seek. patch by sheepman in [ruby-dev:30710].
+
+Mon Apr 16 16:34:08 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (parser_yylex): should set command_start after block
+ starting "do"s and braces. [ruby-core:10916]
+
+Sun Apr 15 09:19:57 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: added some zone names.
+
+ * lib/date/format.rb (_parse): now interprets doted numerical
+ dates as a big endian (except dd.mm.yyyy).
+
+Tue Apr 10 17:37:36 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_fclose, rb_w32_close): need to save errno
+ before calling original fclose()/close().
+
+Mon Apr 9 09:30:44 2007 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (disconnect): call shutdown for
+ SSLSocket. Thanks, Technorama Ltd.
+
+Thu Apr 5 00:42:48 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * error.c (rb_notimplement), io.c (pipe_open): removed definite
+ articles and UNIX manual section from messages. [ruby-dev:30690]
+
+Wed Apr 4 17:09:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (pipe_open): refined the message of NotImplementedError.
+ [ruby-dev:30685]
+
+Wed Apr 4 10:18:04 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (pipe_open): raise NotImplementedError for command "-" on
+ platforms where fork(2) is not available. [ruby-dev:30681]
+
+Tue Apr 3 15:45:41 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/socket/socket.c (s_recv, s_recvfrom): some systems (such as
+ windows) doesn't set fromlen if the socket is connection-oriented.
+ reported by Bram Whillock in [ruby-core:10512] [ruby-Bugs#9061]
+
+Sat Mar 24 23:40:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * node.h (struct rb_thread.locals): explicit as struct.
+ [ruby-core:10585]
+
+ * eval.c, node.h (enum rb_thread_status, struct rb_thread,
+ rb_curr_thread, rb_main_thread): prefixed. [ruby-core:10586]
+
+ * file.c (chompdirsep): made an unprefixed name static.
+
+ * io.c (io_fread): ditto.
+
+Sat Mar 24 01:54:03 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ruby_cleanup): exit by SystemExit and SignalException in END
+ block. [ruby-core:10609]
+
+ * test/ruby/test_beginendblock.rb (test_should_propagate_exit_code):
+ test for exit in END block. [ruby-core:10760]
+
+ * test/ruby/test_beginendblock.rb (test_should_propagate_signaled):
+ test for signal in END block.
+
+Thu Mar 22 23:13:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_provided): check for extension library if SOEXT is
+ explicitly given. [ruby-dev:30657]
+
+Thu Mar 22 10:29:25 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/ruby/test_bignum.rb (test_to_s): add tests for Bignum#to_s.
+
+Wed Mar 21 17:04:30 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): round up for the most significant digit.
+ [ruby-core:10686]
+
+Wed Mar 21 07:21:24 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (remove_one): Preserve List invariants;
+ submitted by: MenTaLguY <mental AT rydia.net>
+ in [ruby-core:10598] and [ruby-bugs:PR#9388].
+
+Tue Mar 20 22:54:50 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_extended): erroneous check condition when dump
+ method is defined. [ruby-core:10646]
+
+Tue Mar 20 15:37:24 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * distruby.rb: Add zip generation.
+
+Tue Mar 20 11:28:41 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/matrix.rb (Matrix::inverse_from): adding partial pivoting to
+ the Gauss-Jordan algorithm, making it stable. a patch from
+ Peter Vanbroekhoven. [ruby-core:10641]
+
+Mon Mar 19 11:39:29 2007 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/protocol.rb (rbuf_read): extend buffer size for speed.
+
+Sun Mar 18 04:23:52 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Add a note about the new `date' library defining
+ Time#to_date and Time#to_datetime private methods.
+
+ * NEWS: Inform that the old `thread' library is considered to be
+ stable.
+
+ * NEWS: Sort library entries in alphabetical order.
+
+Fri Mar 16 21:48:11 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/dl/dl.c (rb_ary2cary): Fix a bug in type validation;
+ submitted by sheepman <sheepman AT sheepman.sakura.ne.jp>
+ in [ruby-dev:30554].
+
+Fri Mar 16 18:28:06 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/etc/etc.c (etc_getgrgid): Fix a bug in Etc::getgrgid()
+ always returning the (real) group entry of the running process;
+ reported by: UEDA Hiroyuki <ueda AT netforest.ad.jp>
+ in [ruby-dev:30586].
+
+Fri Mar 16 16:33:58 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (unlock_mutex_inner): Make sure that the
+ given mutex is actually owned by the caller; submitted by:
+ Sylvain Joyeux <sylvain.joyeux AT m4x.org> in [ruby-core:10598].
+
+Fri Mar 16 16:21:35 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (wait_condvar, lock_mutex): Fix a problem in
+ ConditionVariable#wait that occurs when two threads that are
+ trying to access the condition variable are also in concurrence
+ for the given mutex; submitted by: Sylvain Joyeux
+ <sylvain.joyeux AT m4x.org> and MenTaLguY <mental AT rydia.net>
+ in [ruby-core:10598].
+
+Fri Mar 16 16:17:27 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * test/thread/test_thread.rb: Add a test script for the `thread'
+ library. This should result in failure as of now with
+ ext/thread; submitted by: Sylvain Joyeux <sylvain.joyeux AT
+ m4x.org> in [ruby-core:10598].
+
+Wed Mar 14 12:30:00 2007 Shigeo Kobayashi <shigeo@tinyforest.jp>
+
+ * ext/bigdecimal/bigdecimal.c: BigDecimal("-.31") is now
+ treated as ("-0.31") not as ("0.31").
+
+Tue Mar 13 09:25:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (clear-installed-list): separated from install-prereq.
+
+Tue Mar 13 06:38:43 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Reword and improve entries.
+
+Tue Mar 13 06:03:46 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * stable version 1.8.6 released from the ruby_1_8_6 branch.
+
+Tue Mar 13 03:24:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * runruby.rb: added --pure (turned on by default) and --debugger
+ options.
+
+Tue Mar 13 02:50:28 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/cgi.rb (CGI::header): IIS >= 5.0 does not need the nph
+ assumption any more; submitted by MIYASAKA Masaru <alkaid AT
+ coral.ocn.ne.jp> in [ruby-dev:30537].
+
+Mon Mar 12 11:07:44 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/openssl/ossl_asn1.c (Init_ossl_asn1): Let rdoc know about
+ externally defined modules; submitted by Technorama
+ Ltd. <oss-ruby AT technorama.net> in [ruby-bugs:PR#4704].
+
+ * ext/openssl/ossl_bn.c (Init_ossl_bn): Ditto.
+
+ * ext/openssl/ossl_cipher.c (Init_ossl_cipher): Ditto.
+
+ * ext/openssl/ossl_digest.c (Init_ossl_digest): Ditto.
+
+ * ext/openssl/ossl_hmac.c (Init_ossl_hmac): Ditto.
+
+ * ext/openssl/ossl_pkey.c (Init_ossl_pkey): Ditto.
+
+ * ext/openssl/ossl_pkey_dh.c (Init_ossl_dh): Ditto.
+
+ * ext/openssl/ossl_pkey_dsa.c (Init_ossl_dsa): Ditto.
+
+ * ext/openssl/ossl_pkey_rsa.c (Init_ossl_rsa): Ditto.
+
+ * ext/openssl/ossl_rand.c (Init_ossl_rand): Ditto.
+
+ * ext/openssl/ossl_ssl.c (Init_ossl_ssl): Ditto.
+
+Mon Mar 12 01:05:17 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/dl/sym.c (rb_dlsym_inspect): Use "0x%x" rather for pointers.
+ This might not be very right but it is commonly used in other
+ parts of the code; submitted by sheepman <sheepman AT
+ sheepman.sakura.ne.jp> in [ruby-dev:30532].
+
+ * ext/dl/ptr.c (rb_dlptr_inspect): Ditto.
+
+Mon Mar 12 00:59:19 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/dl/lib/dl/import.rb (DL::Importable::Internal::import,
+ DL::Importable::Internal::callback): Avoid race condition for an
+ instance variable; submitted by sheepman <sheepman AT
+ sheepman.sakura.ne.jp> in [ruby-dev:30530].
+
+Sun Mar 11 18:57:50 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * misc/README: Add a note about ruby-electric.el.
+
+ * misc/ruby-mode.el (ruby-non-block-do-re): Fix
+ ruby-non-block-do-re. [ruby-core:03719]
+
+ * misc/inf-ruby.el: Synchronize the comment section with trunk.
+
+ * misc/README, misc/rdebug.el: Add rdebug.el, Emacs ruby-debug
+ interface based on rubydb3x.el; submitted by Martin Nordholts
+ <enselic AT gmail.com> in [ruby-bugs:PR#9023].
+
+Sun Mar 11 17:45:51 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/dl/mkcallback.rb (mkfunc): Make sure that a callback
+ function is found in the function table before trying to call
+ it; submitted by sheepman <sheepman AT sheepman.sakura.ne.jp>
+ in [ruby-dev:30524].
+
+Sun Mar 11 12:09:37 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (error_handle): no message when exiting by signal.
+
+ * eval.c (ruby_cleanup): re-send signal. [ruby-dev:30516]
+
+ * eval.c (rb_thread_interrupt): instantiate SignalException.
+
+ * eval.c (rb_thread_signal_raise): now takes signal number instead
+ of signal name.
+
+ * intern.h (rb_thread_signal_raise, ruby_default_signal): prototypes.
+
+ * signal.c (esignal_init): takes a signal number and an optional
+ signal name.
+
+ * signal.c (interrupt_init): pass SIGINT always.
+
+ * signal.c (ruby_default_signal): invoke system default signal
+ handler.
+
+ * signal.c (rb_signal_exec, trap): handle SIGTERM. [ruby-dev:30505]
+
+Tue Mar 6 19:08:46 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/md5.rb (MD5::new, MD5::md5): Do not modify
+ Digest::MD5.
+
+ * ext/digest/lib/sha1.rb (SHA1::new, SHA1::sha1): Ditto.
+
+Tue Mar 6 18:58:37 2007 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * lib/shell/process-controller.rb: fix thread synchronization
+ problem for [ruby-dev:30477].
+
+Tue Mar 6 18:44:26 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/md5.rb (MD5::new, MD5::md5): Catch up with
+ Digest's API changes; noted by: Kazuhiro Yoshida <moriq AT
+ moriq.com> in [ruby-dev:30500].
+
+ * ext/digest/lib/sha1.rb (SHA1::new, SHA1::sha1): Ditto.
+
+Tue Mar 6 18:24:19 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * time.c (time_to_s): Back out the format changes; discussed
+ in [ruby-dev:30495].
+
+Tue Mar 6 11:53:25 2007 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/irbtkw.rbw: fails to exit process.
+
+Mon Mar 5 20:14:49 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * time.c (time_to_s): Correct the wrong format which did not
+ really conform to RFC 2822; pointed out by: OHARA Shigeki <os at
+ iij.ad.jp> in [ruby-dev:30487].
+
+Sun Mar 4 23:38:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_stat_s_utime): fixed a commit miss for the platforms
+ where utimes() does not exist.
+
+ * lib/fileutils.rb (touch): ditto.
+
+Sun Mar 4 14:46:56 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * util.c (push_element): should return a int value.
+
+Sun Mar 4 01:05:57 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/set.rb (Set#^, Set#&): Correct documentation. Those methods
+ return sets, not arrays; noted by Oliver Frank Wittich <nietz AT
+ mangabrain.de>.
+
+Sat Mar 3 23:01:07 2007 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (mv): could not move a directory between
+ different filesystems. [ruby-dev:30411]
+
+Sat Mar 3 22:57:11 2007 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (touch): last commit causes error if :mtime
+ option was not given.
+
+Sat Mar 3 22:37:02 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_utime): allow nil to set the current time.
+
+ * lib/fileutils.rb (touch): ditto, and added :mtime and :nocreate
+ options. fixed: [ruby-talk:219037]
+
+Sat Mar 3 21:17:35 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (stack_check): Unset inline to fix build with GCC 3.4.6;
+ submitted by: NISHIMATSU Takeshi <t_nissie AT yahoo.co.jp> in
+ [ruby-list:43218].
+ cf. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24556
+
+Sat Mar 3 19:05:31 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (push_list): Use ALLOC().
+
+ * ext/thread/thread.c (rb_mutex_alloc): Ditto.
+
+ * ext/thread/thread.c (rb_condvar_alloc): Ditto.
+
+Sat Mar 3 18:53:11 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Add a note for String#intern.
+
+Sat Mar 3 16:23:13 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * env.h (SCOPE_CLONE): Introduce a new scope flag to prevent a
+ local_tbl region from getting freed many times; submitted by
+ Chikanaga Tomoyuki <chikanag AT nippon-control-system.co.jp> in
+ [ruby-dev:30460].
+
+ * eval.c (proc_invoke): Ditto.
+
+ * gc.c (obj_free): Ditto.
+
+ * parse.y (top_local_setup_gen): Ditto.
+
+Sat Mar 3 16:07:02 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * object.c (rb_obj_ivar_set): RDoc updated according to a
+ suggestion from Brian Candler <B.Candler AT pobox.com>.
+ [ruby-core:10469]
+
+Thu Mar 1 21:38:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (stmt, arg): should not omit lhs of OP_ASGN1 even if
+ empty. [ruby-dev:30455]
+
+Thu Mar 1 08:55:38 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_feature_p): check loading_tbl if the given ext is
+ empty. [ruby-dev:30452]
+
+ * eval.c (rb_feature_p): fix possible buffer overrun.
+
+Thu Mar 1 03:30:21 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/digest.c (get_digest_base_metadata): Allow inheriting
+ Digest::Base subclasses, which was unintentionally made
+ impossible while restructuring Digest classes.
+
+Thu Mar 1 02:05:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * mkconfig.rb (patchlevel): read from version.h.
+
+Thu Mar 1 00:09:39 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_provided): return true only for features loaded from
+ .rb files, and not search actual library type. [ruby-dev:30414]
+
+Wed Feb 28 21:15:00 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (ac_cv_func_fcntl): fcntl support for MinGW.
+
+ * missing/flock.c: workaround for MinGW.
+
+Wed Feb 28 20:51:32 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * pack.c (pack_unpack): properly ignore non-base64 octets such as
+ UTF-8 encoded BOMs; submitted by SOUMA Yutaka <holon@radastery.jp>
+ to fix [ruby-core:10437]
+
+Wed Feb 28 18:59:57 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Add NEWS, a document file to keep user visible feature
+ changes between releases.
+
+Wed Feb 28 18:35:50 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/openssl/extconf.rb: no need to check unistd.h and sys/time.h.
+ they are already checked at configure.
+ reported by KOBAYASHI Yasuhiro [ruby-list:43225]
+
+Wed Feb 28 18:34:48 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/mkmf.rb ($DEFLIBPATH): default library paths ($(topdir), etc)
+ should be the first elements of library paths list.
+ reported by KOBAYASHI Yasuhiro [ruby-list:43225]
+
+Wed Feb 28 18:31:32 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * doc/NEWS-1.8.0: Rename NEWS to NEWS-1.8.0. This is way too old
+ NEWS.
+
+Wed Feb 28 01:22:58 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/{dbm,gdbm}/test_{dbm,gdbm}.rb: shouldn't use host_os. use
+ target_os instead. reported by KOBAYASHI Yasuhiro [ruby-list:43225]
+
+Wed Feb 28 00:08:11 2007 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
+
+ * mkconfig.rb (RbConfig): add CONFIG['PATCHLEVEL']
+
+ * common.mk: new target dist
+
+ * distruby.rb: new file
+
+Tue Feb 27 22:18:45 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (--enable-auto-image-base): avoid the neccessity to
+ rebase the shared libs as much as possible;
+ submitted by Corinna Vinschen <spam at vinschen.de> in
+ [ruby-talk:240964].
+
+Tue Feb 27 21:36:47 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * util.c (__crt0_glob_function): use ruby_glob() instead of rb_globi().
+
+Tue Feb 27 21:33:04 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (ac_cv_func_setrlimit): workaround for djgpp.
+
+Tue Feb 27 19:38:52 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/base64.rb (Base64::b64encode): Fix documentation; submitted
+ by David Symonds <dsymonds@gmail.com> in [ruby-core:10432].
+
+Tue Feb 27 19:36:57 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * regex.c (calculate_must_string, slow_search, re_search): Silence
+ warnings regarding char * vs. unsigned char * mismatch;
+ submitted by Lyle Johnson <lyle.johnson@gmail.com>
+ in [ruby-core:10416].
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_load): Ditto.
+
+ * ext/digest/sha1/sha1ossl.c (SHA1_Finish): Ditto.
+
+ * ext/digest/rmd160/rmd160ossl.c (RMD160_Finish): Ditto.
+
+ * ext/digest/digest.c (rb_digest_base_finish,
+ rb_digest_base_update): Ditto.
+
+ * ext/nkf/nkf.c (rb_str_resize, rb_nkf_kconv, rb_nkf_guess1,
+ rb_nkf_guess2): Ditto.
+
+Tue Feb 27 03:40:09 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (wait_list_cleanup, rb_mutex_try_lock):
+ Eliminate rb_thread_critical switching where unnecessary;
+ implied by shugo in [ruby-dev:30412].
+
+ * ext/thread/thread.c (set_critical): Merge in
+ thread_exclusive_ensure().
+
+ * ext/thread/thread.c: Consistently use 0 and 1 for
+ rb_thread_critical values.
+
+Mon Feb 26 15:18:23 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c: Use xmalloc()/xfree() instead of
+ malloc()/free(); pointed out by shugo in [ruby-dev:30412].
+
+Sun Feb 25 23:02:55 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/test/unit/autorunner.rb (Test::Unit::AutoRunner::initialize):
+ Initialize @workdir properly to silence a warning under -w.
+ Submitted by <tommy at tmtm.org> in [ruby-dev:30400].
+
+Sun Feb 25 02:47:43 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * defines.h: Pull the RUBY_MBCHAR_MAXSIZE definition from trunk,
+ which is necessary for dir.c to compile on djgpp and emx.
+
+Sat Feb 24 10:42:01 2007 Minero Aoki <aamine@loveruby.net>
+
+ * ext/racc/cparse/cparse.c (cparse_params_mark): remove useless
+ rb_gc_mark. Thanks Tomoyuki Chikanaga. [ruby-dev:30405]
+
+Fri Feb 23 15:10:46 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (set_pioinfo_extra): new function for VC++8 SP1
+ workaround. [ruby-core:10259]
+
+ * win32/win32.c (NtInitialize): call above function.
+
+Fri Feb 23 14:19:40 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * signal.c (sighandler): need to tell to be interrupted to main
+ context when handler is installed.
+
+ * win32/win32.[ch] (rb_win32_interrupted): new function to listen
+ interrupt.
+
+Fri Feb 23 13:02:17 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * numeric.c (fix_cmp, fix_equal): Remove FIX2LONG() to optimize.
+ suggested in
+ http://t-a-w.blogspot.com/2007/02/making-ruby-faster.html.
+ [ruby-talk:240223]
+
+Fri Feb 23 12:43:17 2007 James Edward Gray II <james@grayproductions.net>
+
+ * lib/xmlrpc/client.rb (XMLRPC::Client::do_rpc): Make the
+ Content-Length parameter optional for responses in
+ xmlrpc/client.rb; suggested by Daniel Berger
+ <Daniel.Berger@qwest.com> and approved by the maintainer.
+
+ * lib/xmlrpc/create.rb (XMLRPC::Create::conv2value): Add DateTime
+ support to xmlrpc; approved by the maintainer.
+
+Mon Feb 19 18:22:52 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in, defines.h, eval.c (rb_feature_p, rb_provided,
+ load_wait, search_required, rb_require_safe), ext/extmk.rb: Fix
+ a bug where a statically linked extension cannot be autoloaded.
+ [ruby-dev:30023] / [ruby-dev:30239]
+
+Mon Feb 19 17:14:28 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (unix_peeraddr): wrong syscall name in error
+ message for #peeraddr. a patch from Sam Roberts
+ <sroberts at uniserve.com>. [ruby-core:10366]
+
+Sun Feb 18 19:35:21 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: updated based on date2 4.0.3.
+
+Fri Feb 16 11:18:21 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/.document: Apply patch for irb, e2mmap and README by Hugh Sasse
+ <hgs at dmu.ac.uk> from [ruby-core:10135]
+
+ * lib/prettyprint.rb: Suppress RDoc for PrettyPrint test suite.
+
+Thu Feb 15 20:26:30 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/uri/ftp.rb: Revert the previous change pending discussion.
+
+Thu Feb 15 18:08:17 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * dir.c (glob_helper): Fix the function declaration.
+
+Thu Feb 15 17:13:32 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * version.h: Welcome to the post-1.8.6 world. Radical changes are
+ inhibited in the ruby_1_8 branch until the 1.8.6 final release
+ goes out of the door.
+
+Thu Feb 15 16:44:14 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/uri/generic.rb (URI::Generic::userinfo): Considering how
+ `scheme://user:@...', `scheme://:password@...' and
+ `scheme://:@...' are parsed, an empty user name or password
+ should be allowed and represented as it is.
+
+Thu Feb 15 11:46:05 2007 KIMURA Koichi <hogemuta@gmail.com>
+
+ * dir.c, win32/win32.c, win32/dir.h, ruby.h, intern.h: Bring
+ encoding aware globbing support in from trunk. Dir.[] and
+ Dir.glob() can now take many patterns in an array. Minor fixes
+ will follow.
+
+Thu Feb 15 11:00:26 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/uri/generic.rb (URI::Generic::userinfo): should support
+ empty password. [ruby-core:10290]
+
+ * lib/uri/generic.rb (URI::Generic::set_password): password can be
+ cleared by nil. [ruby-core:10290]
+
+ * lib/uri/common.rb (escape): regard second string argument as a
+ character set properly. [ruby-dev:27692]
+
+ * lib/uri/ftp.rb: Attempt to conform to RFC 1738 with regard to
+ relative/absolute paths.
+
+ * lib/uri: Lovely RDOC patches from mathew (metaATpoboxDOTcom).
+
+Thu Feb 15 10:57:38 2007 Tietew <tietew@tietew.net>>
+
+ * lib/cgi.rb (CGI::unescapeHTML): invalid decoding for single
+ unescaped ampersand. a patch from Tietew
+ <tietew+ruby-dev at tietew.net> in [ruby-dev:30292].
+ fixed: [ruby-dev:30289]
+
+Thu Feb 15 10:48:40 2007 MenTaLguY <mental@rydia.net>
+
+ * ext/thread/thread.c: Handle interrupted waits correctly.
+ [ruby-bugs:PR#8663]
+
+Wed Feb 14 19:22:15 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/digest.rb (Digest::self.const_missing): Drop
+ autoloads for sha2 classes in favor of handling in
+ const_missing(), to work around a problem exposed on OS X.
+
+Tue Feb 13 02:21:12 2007 Sam Roberts <sroberts@uniserve.com>
+
+ * io.c (rb_f_syscall): Fix buffer overflow with syscall
+ arguments. [ruby-bugs:PR#8541]
+
+Sun Feb 11 07:46:45 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/cgi.rb (CGI::QueryExtension::read_multipart): Properly parse
+ a quoted-string in a Content-Disposition value.
+
+Sun Feb 11 06:27:54 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * configure.in, ext/thread/extconf.rb, lib/thread.rb: Add a
+ configure option `--disable-fastthread', to choose the original,
+ pure ruby version of the "thread" library instead of the new,
+ much faster implementation in ext/thread.
+
+Sun Feb 11 06:22:20 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/Setup: Add thread except for platforms without threads
+ support.
+
+Sun Feb 11 06:15:16 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/lib/thread.rb: Add a replacement of thread.rb that
+ loads this extension.
+
+Sun Feb 11 05:39:47 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/thread.rb: Remove an ineffective part of the code.
+
+Sun Feb 11 05:32:54 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (rb_thread_exclusive): Implement
+ Thread.exclusive.
+
+Sun Feb 11 05:26:51 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c: Get rid of use of a dummy function.
+
+Sun Feb 11 01:45:31 2007 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/thread/thread.c (Init_thread): Define missing aliases:
+ Queue#enq and SizedQueue#enq.
+
+Sat Feb 10 09:27:35 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_variant2val): fix compile error
+ on VC++.
+
+Sat Feb 10 07:41:52 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_variant2val): fix the bug when
+ SAFEARRAY pointer is NULL.
+
+Sat Feb 10 00:13:11 2007 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: fix typo (TkConfigMethod::__confinfo_cmd,
+ __conv_keyonly_opts).
+
+Fri Feb 9 20:44:53 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread: Make style fixes (mostly de-K&R'ism) to match the
+ rest of the source code.
+
+ * ext/thread: Make USE_MEM_POOLS an extconf option.
+
+Fri Feb 9 20:43:01 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread: Import the "fastthread" implementation by MenTaLguY
+ in the original form. This module is not hooked into the build
+ yet since it needs some style fixes and adjustments.
+
+Fri Feb 9 15:46:09 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/bigdecimal: Synchronize with trunk. Better function
+ prototypes, removal of a useless method `!=', and document
+ updates.
+
+Tue Feb 06 22:06:45 2007 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/{nkf.c,utf8tbl.c}:
+ imported nkf 2007-01-28.
+ * Fixed: can't decode MIME encode JIS string.
+ * Fixed: Fullwitdh-halfwidth conversion.
+ * Support DoCoMo's and Softbank's EMOJI
+ * Support CP932, CP5022x, eucJP-ms UDC
+ * Support UTF-32 encoding
+ * Support beyond BMP
+ [ruby-dev:29700] [ruby-dev:29922] [ruby-dev:30144]
+
+Wed Jan 31 14:52:09 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_iterate): need to PUSH_ITER in proper order.
+ [ruby-core:10125]
+
+ * test/ruby/test_iterator.rb (TestIterator::test_block_given_within_iterator):
+ add new test. [ruby-core:10125]
+
+Tue Jan 30 14:58:51 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * string.c (rb_str_sub_bang): calling rb_str_modify() should be just
+ before actually modifying the string.
+ fixed: [ruby-dev:30211] (originally reported by zunda)
+
+Tue Jan 30 12:05:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * mkconfig.rb: autoconf 2.61 support. [ruby-core:10016]
+
+Sat Jan 27 15:20:11 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (dyna_var_lookup): should not alter dvar->val not to
+ destroy living value. [ruby-core:10076]
+
+ * parse.y (dyna_init): ditto.
+
+Fri Jan 26 12:03:39 2007 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb (TkConfigMethod#__confinfo_cmd,
+ __conv_keyonly_optkeys): make them private [ruby-dev:30074].
+
+ * ext/tk/lib/tk/txtwin_abst.rb: fix typo [ruby-dev:30073].
+
+ * ext/tk/lib/tk/canvas.rb (TkCanvas#scan_dragto): lack of an argument.
+
+ * ext/tk/lib/tk/canvas.rb: clarify the including module name
+ [ruby-dev:30080].
+
+ * ext/tk/lib/tk/scrollable.rb: change primary name of modules
+ [ruby-dev:30080].
+
+Wed Jan 24 18:05:39 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-font-lock-syntactic-keywords): fix
+ regexp font-lock bug. [ruby-talk:235758]
+
+Tue Jan 23 11:02:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/webrick/httprequest.rb (WEBrick::HTTPRequest::read_line):
+
+Tue Jan 23 18:26:12 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::QueryExtension::read_multipart): use == instead
+ of ===. [ruby-dev:30176]
+
+Tue Jan 23 10:48:17 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c: added documentation for Hash about how it uses eql? and
+ hash methods for the keys. [ruby-core:09995]
+
+Mon Jan 22 14:57:25 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c: fix errors in socket sample code.
+ [ruby-core:09992]
+
+Sat Jan 13 23:54:48 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_free, ole_type_free,
+ olemethod_free, olevariable_free, oleparam_free,
+ ole_event_free): fix memory leak. [ruby-core:09846]
+
+Fri Jan 12 11:13:55 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/etc/etc.c (etc_getpwuid, etc_getgrgid): fix to correctly
+ convert uid/gid from VALUE. (backport of r11521)
+
+Wed Jan 10 18:57:57 2007 Minero Aoki <aamine@loveruby.net>
+
+ * ext/strscan/strscan.c (strscan_do_scan): should set kcode option
+ before match. [ruby-dev:29914]
+
+ * test/strscan/test_stringscanner.rb: test it.
+
+ * re.c: export kcode_set_option and kcode_reset_option (with "rb_"
+ prefix).
+
+ * intern.h: ditto.
+
+Tue Jan 9 17:45:17 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (rb_find_file): should not call fpath_check() with NULL.
+ fixed: [ruby-core:09867]
+
+Tue Jan 9 03:54:38 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_upto): String#upto from empty string makes
+ inifinite loop. [ruby-core:09864]
+
+Sun Jan 7 12:13:26 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#find_class_comment):
+ Look for class and module comments above rb_define_class and
+ rb_define_module. Patch by Daniel Berger <djberg96 at gmail.com>
+
+Sun Jan 7 10:32:12 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#handle_constants):
+ Properly handle escaping of : in comments.
+ * test/rdoc/parsers/test_parse_c.rb:
+ Test RDoc::C_Parser#do_classes and Rdoc::C_Parser#find_class_comment.
+
+Sun Jan 7 09:33:02 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: updated based on date2 4.0.1.
+
+Wed Jan 3 11:36:51 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (ruby_dup): start GC on ENOMEM as well.
+
+Mon Jan 1 06:13:11 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/c_parser.rb: Make Rdoc accessible. Update constant
+ value information.
+
+Mon Jan 1 06:13:11 2007 Eric Hodel <drbrain@segment7.net>
+
+ * ext/bigdecimal/bigdecimal.c: Update constant comments to provide
+ values for RDoc.
+
+Mon Jan 1 06:05:55 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#handle_constansts):
+ Allow RDoc comment to give friendly value for rb_define_const. Patch
+ by Daniel Berger <djberg96 at gmail.com>, [ruby-patches-7499].
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#handle_constansts): Fix
+ whitespace handling in constant comments.
+
+Sun Dec 31 00:31:16 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 4.0.
+
+Thu Dec 14 18:29:13 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/readline/readline.c: NetBSD editline does not have
+ rl_username_completion_function() and rl_completion_matches().
+ a patch from Takahiro Kambe <taca at back-street.net>.
+ [ruby-dev:30008]
+
+Thu Dec 14 18:20:43 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/locale.rb (IRB::Locale::puts): typo fixed. a patch from
+ NAKAMURA Usaku <usa@ruby-lang.org>. [ruby-dev:30012]
+
+Mon Dec 11 11:58:36 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/sha2/lib/sha2.rb: Moved one level up from under
+ the superfluous subdirectory digest/.
+
+Mon Dec 11 11:46:18 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_define_const): typo fixed.
+
+Mon Dec 11 09:36:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_aset): index double decode problem.
+ [ruby-core:09695]
+
+Sat Dec 9 21:39:24 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ruby_cleanup): keep the exception till after END blocks.
+ [ruby-core:09675]
+
+Sat Dec 9 11:22:00 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/locale.rb (IRB::Locale::search_file): ues File.exist?
+ instead of File.exists?. a patch from Yutaka Kanemoto
+ <kinpoco at gmail.com> in [ruby-dev:30000].
+
+Thu Dec 7 09:29:02 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/weakref.rb (WeakRef::__setobj__): should support
+ marshaling. [ruby-talk:228508]
+
+ * lib/delegate.rb (Delegator::marshal_load): need to call
+ __setobj__.
+
+Wed Dec 6 23:56:14 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, common.mk (NULLCMD): moved for platforms that empty
+ command does not run. fixed: [ruby-dev:29994]
+
+Wed Dec 6 17:17:26 2006 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (SITE_DIR): fixed to emtpy RUBY_SITE_LIB in config.h on
+ NetBSD. fixed: [ruby-dev:29358]
+
+Tue Dec 5 00:59:05 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-parse-partial): need to parse "/=" as
+ self assignment operator, not regex. [ruby-talk:227324]
+
+Mon Dec 4 10:48:03 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h (OFFT2NUM): use LONG2NUM() if sizeof(long) equals to
+ sizeof(off_t).
+
+Mon Dec 4 10:43:46 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (dyna_init_gen): dvar initialization only if dvar is
+ assigned inner block. [ruby-talk:227402]
+
+Mon Dec 4 08:32:49 2006 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::QueryExtension::read_multipart): should quote
+ boundary. JVN#84798830
+
+Sat Dec 2 07:09:04 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ocsp.c: OpenSSL::OCSP::OSCPError should be
+ subclass of OpenSSL::OpenSSLError. [ruby-dev:29980]
+
+Fri Dec 1 17:01:49 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * gc.c (ruby_init_stack): decrease "stack level too deep" in Windows.
+ merge from trunk.
+
+Fri Dec 1 16:31:53 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c: shouldn't run the killed thread at callback.
+ [ruby-talk: 227408]
+
+Mon Nov 27 17:18:27 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): need not to truncate string if no
+ width specifier given for %s. [ruby-dev:29952]
+
+Sun Nov 26 16:36:46 2006 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * version.h: addition of RUBY_PATCHLEVEL.
+ * version.c: ditto.
+
+Fri Nov 24 10:17:51 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (bignorm): avoid segmentation. a patch from Hiroyuki
+ Ito <ZXB01226@nifty.com>. [ruby-list:43012]
+
+Thu Nov 23 10:38:40 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_mod_define_method): set implicit visibility only when
+ it's called for the target class (ruby_cbase).
+
+Wed Nov 22 16:00:49 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/extconf.rb: support --with-X11/--without-X11 option.
+
+ * ext/tk/README.tcltklib: add description about --with-X11-* option
+ [ruby-talk:225166] and --with-X11/--without-X11 option.
+
+ * ext/tk/tkutil/extconf.rb: able to be called manually
+ [ruby-talk:225950].
+
+Wed Nov 15 23:22:54 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (test_grpowned, rb_stat_grpowned): should honor
+ supplementary group IDs. [ruby-core:09546]
+
+Thu Nov 9 03:15:22 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (BEGIN_CALLARGS): ruby_block may be NULL even when
+ ITER_PRE.
+
+Tue Nov 7 18:34:34 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/digest/hmac.rb: Keep this out of the 1.8 tree
+ until we reach a consensus that HMAC should be put under Digest.
+
+Tue Nov 7 18:05:01 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/itemconfig.rb: minor bug fix.
+
+Mon Nov 6 20:11:20 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/0.9.rb (RSS::Rss): removed needless include.
+
+Mon Nov 6 15:41:55 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/itemconfig.rb: ext/tk/lib/tk/itemconfig.rb: bug
+ fix on 'itemconfiginfo' method, and modify to make it easy to
+ override 'itemconfiginfo' method.
+
+ * ext/tk/lib/tkextlib/tile/treeview.rb : support Tile 0.7.8.
+
+ * ext/tk/lib/tkextlib/version.rb : [new] add Tk::Tkextlib_RELEASE_DATE
+ to get the information from scripts.
+
+ * ext/tk/lib/tk.rb: load 'tkextlib/version.rb', and update RELEASE_DATE
+
+ * ext/tk/lib/tkextlib/SUPPORT_STATUS: update.
+
+ * ext/tk/sample/editable_listbox.rb: [new] the listbox with editable
+ items. It's one of the example about usage of Place geometry manager.
+
+ * ext/tk/sample/tktextio.rb: improve the functions of TkTextIO class.
+ Those are required by 'irbtkw.rbw'.
+
+ * ext/tk/sample/irbtkw.rbw: [new] IRB on Ruby/Tk. It doesn't need any
+ real console. IRB works on a text widget without I/O blocking. That
+ is, thread switching on IRB will work properly, even if on Windows.
+
+Sun Nov 5 19:53:49 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: updated based on date2 3.9.7.
+
+Sat Nov 4 13:13:57 2006 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: accept NOMODSEQ. [ruby-core:9002]
+ (backported from HEAD)
+
+Fri Nov 3 00:16:37 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (ruby_getnameinfo__aix): AF_INET6 workaround
+ for AIX. a patch from Yutaka Kanemoto <kinpoco AT gmail.com>.
+ [ruby-dev:29744]
+
+Thu Nov 2 15:43:39 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * parse.y (primary): should set NODE even when compstmt is NULL.
+ merge from trunk. fixed: [ruby-dev:29732]
+
+Thu Nov 2 14:48:30 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/set.rb (Set#^): Fix XOR operation against a container that
+ holds duplicate values. [issue: #6444]
+
+Wed Nov 1 02:41:38 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/digest/hmac.rb (Digest::HMAC::update): Minor
+ optimization.
+
+ * ext/digest/digest.c (rb_digest_instance_equal): Allow comparing
+ a digest instance with another of a different class.
+
+Wed Nov 1 01:05:13 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * eval.c (rb_call0): fixed bug of zsuper with both of opt and rest.
+ fixed: [ruby-list:42928]
+
+ * test/ruby/test_super.rb: add tests to check above bug.
+
+Tue Oct 31 17:03:21 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_dup): duplicate the class of original time.
+ [ruby-core:09357]
+
+ * lib/time.rb (Time::make_time, Time::rfc2822, Time::httpdate):
+ should respect subclasses. [ruby-core:09357]
+
+Mon Oct 30 23:40:52 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in (miniruby): add XLDFLAGS.
+
+ * configure.in (aix): use -bE option for miniruby. [ruby-dev:29698]
+
+ * dir.c (glob_helper): get rid of possible memory leak.
+
+ * win32/win32.c (cmdglob, rb_w32_cmdvector, rb_w32_opendir,
+ rb_w32_get_environ): not to use GC before initialization.
+
+Mon Oct 30 19:29:20 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): use better approximation.
+
+Mon Oct 30 18:35:33 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): wrong allocation length. a patch from
+ U.Nakamura <usa at garbagecollect.jp> [ruby-dev:29710]
+
+Mon Oct 30 12:34:02 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): fix commit miss. [ruby-dev:29707]
+
+Mon Oct 30 12:20:58 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): a bug in length adjustment.
+
+Mon Oct 30 11:15:40 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_str_format): should preserve leading zero
+ information for negative %b and %x. [ruby-talk:221347]
+
+Thu Oct 26 21:05:58 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_pkcs7.c (ossl_pkcs7_verify): should clear error.
+ (fix http://bugs.debian.org/394336)
+
+ * ext/openssl/ossl_ns_spki.c (ossl_spki_initialize): ditto.
+
+Thu Oct 26 15:21:10 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/digest/digest.c (Init_digest): typo.
+
+Wed Oct 25 17:23:28 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest, test/digest/test_digest.rb: Merge from trunk:
+ - Introduce versioning in Digest::Base API, and prefix C
+ constants with RUBY_ and C type names with rb_ to avoid name
+ clash in writing extensions.
+ - Introduce Digest::Class and Digest::Instance for ease of
+ implementing subclasses and add-ons.
+ - Digest::Instance module requires and assumes that any instance
+ be resettable and clonable. An instance method #new() is
+ added so digest instances work just like digest classes.
+ - The constructor does no longer take an initial string to feed;
+ digest() and hexdigest() now do, instead. This allows digest
+ classes to take their own hashing parameters.
+ - Make some changes to digest() and hexdigest() class methods,
+ which now take extra arguments, which are passed through to
+ the constructor in an internal call.
+ - Add #digest_length/size/length() and #block_length(),
+ - Add the Digest::SHA2 class to wrap up SHA2 variants: SHA256,
+ SHA384 and SHA512, hoping this module would make a decent
+ example of a digest subclass written in Ruby.
+ - Rip BubbleBabble support out of the base class and have a
+ separate module named digest/bubblebabble.
+ - Remove RD documents in favor of newly written and embedded
+ RDoc documentation.
+
+Wed Oct 25 08:03:23 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: updated based on date2 3.9.6.
+ [ruby-core:09323]
+
+Sun Oct 22 14:48:31 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * signal.c (ruby_signal): don't set SA_RESTART. a backport from
+ the HEAD. [ruby-talk:220937] [ruby-talk:147220]
+
+ * signal.c (Init_signal): avoid duplicated installation of SIGCHLD
+ handler.
+
+Sun Oct 22 16:47:56 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_substr): should be infected with only original
+ string, but not the shared string. fixed: [ruby-core:09152]
+
+ * string.c (rb_str_new4): keep shared string untainted when orignal
+ string is tainted. fixed: [ruby-dev:29672]
+
+Sun Oct 22 05:20:34 2006 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
+
+ * configure.in: alloca is broken; use C_ALLOCA instead.
+ [ruby-dev:29416]
+
+Fri Oct 20 10:47:43 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/mkmf.rb: fixed the bug of handling COMMON_MACROS.
+
+Fri Oct 20 08:42:38 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (NULLCMD): dummy command.
+
+ * bcc32/Makefile.sub (post-install-*): Borland make cannot ignore
+ command-less double-colon rules. [ruby-dev:29676]
+
+Fri Oct 20 00:37:07 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bcc32/Makefile.sub ($(LIBRUBY_SO)): execute pre-link hook.
+
+ * ext/extmk.rb: workaround for Borland make.
+
+Wed Oct 18 23:02:40 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_shift): shorten copy size. fixed: [ruby-list:42907]
+
+ * signal.c (Init_signal): handle SIGTERM. fixed: [ruby-list:42895]
+
+ * win32/win32.c (rb_w32_utime): allow NULL to set the current time.
+ [ruby-talk:219248]
+
+Wed Oct 18 00:55:33 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (parser_yylex): use particular enums. [ruby-core:09221]
+
+Mon Oct 16 08:30:43 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * mkconfig.rb: *OBJS are not needed for extension libraries.
+
+ * {bcc32,wince,win32}/Makefile.sub (config.status): fixed typo,
+ missing comma.
+
+Sun Oct 15 01:03:08 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/collector/dir.rb (Collector::Dir#collect): append base
+ directory but not prepend.
+
+ * lib/test/unit/collector/dir.rb (Collector::Dir#collect_file): do not
+ join with dot. fixed: [ruby-core:09179]
+
+Sat Oct 14 23:39:50 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (singleton): no need to re-create NODE_SELF() again.
+ [ruby-core:09177]
+
+Sat Oct 14 23:25:31 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (parser_warning, parser_warn): some error message may
+ contain format specifiers. a patch from Akinori MUSHA <knu at
+ iDaemons.org>. [ruby-dev:29657]
+
+ * ext/bigdecimal/bigdecimal.c (VpException): ditto.
+
+ * ext/dl/handle.c (rb_dlhandle_initialize): ditto.
+
+ * ext/gdbm/gdbm.c (rb_gdbm_fatal): ditto.
+
+Sat Oct 14 08:24:45 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/digest/hmac: Back out the addition of digest/hmac
+ for now because the API is too premature for a stable branch.
+
+Sat Oct 14 00:55:08 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bcc32/Makefile.sub (post-install-ext): no longer needed.
+
+ * bcc32/configure.bat: get rid of a quirk of Borland make, which
+ sets empty macro in command line to "1".
+
+Fri Oct 13 22:50:43 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: updated based on date2 3.9.5.
+
+Fri Oct 13 22:33:28 2006 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (FileUtils.cp_r): dereference_root=true is
+ default in Ruby 1.8. This line is wrongly removed in last commit.
+
+Fri Oct 13 18:19:31 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c: Class#inherited RDoc added. a patch from Daniel
+ Berger <djberg96 at gmail.com> [ruby-core:08942]
+
+Fri Oct 13 02:30:12 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/collector/dir.rb (Collector::Dir#collect): prepend
+ base directory to load path.
+
+ * lib/test/unit/collector/dir.rb (Collector::Dir#collect_file): should
+ use the given File-like interface, but not File directly.
+
+ * test/testunit/collector/test_dir.rb (TestDir::FileSystem): implement
+ File-like methods correctly.
+
+Fri Oct 13 01:48:42 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/date.rb (Date::self.complete_hash): need to check if g is
+ nil before dereference. [ruby-core:09116]
+
+Fri Oct 13 00:34:26 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_mod_cvar_defined): wrong id check. a patch from
+ Mauricio Fernandez <mfp at acm.org>. [ruby-core:09158]
+
+ * object.c (rb_mod_cvar_get): typo fixed. [ruby-core:09168]
+
+ * object.c (rb_mod_cvar_set): ditto.
+
+Wed Oct 11 22:21:41 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest: Merge from trunk; metadata location changed,
+ Digest::Base#reset() added, Digest::Base#equal() changed, and
+ digest/hmac added with some modifications made for ruby 1.8.
+
+Tue Oct 10 17:24:12 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32,wince}/Makefile.sub (config.status): shouldn't use
+ copy command instead of install. use -run install.
+
+Tue Oct 10 16:49:16 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/digest.c (hexdigest_str_new, bubblebabble_str_new):
+ Perform StringValue() checks properly.
+
+ * ext/digest/digest.c: Use RSTRING_{PTR,LEN} macros.
+
+Tue Oct 10 13:49:53 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest: Merge from trunk; apply all changes since the
+ initial import, except for the removal of compatibility stub
+ libraries (md5.rb and sha1.rb).
+
+Mon Oct 9 23:46:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/parsedate.rb: documentation patch from Konrad Meyer
+ <konrad.meyer@gmail.com>. [ruby-doc:1238]
+
+ * lib/open3.rb, lib/ping.rb: ditto.
+
+Mon Oct 9 22:56:12 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rexml/encoding.rb (REXML::Encoding::check_encoding): spaces
+ are allowed around equal sign. [ruby-core:09032]
+
+ * lib/rexml/parsers/baseparser.rb (REXML::Parsers::BaseParser): ditto.
+
+Sat Oct 7 23:53:08 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_scan): small documentation fix.
+ [ruby-core:09007]
+
+Sat Oct 7 23:44:33 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_rshift): a bug in right shift of negative
+ bignums. [ruby-core:09020]
+
+Sat Oct 7 00:27:58 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_include_module): remove unnecessary check.
+ [ruby-talk:218402]
+
+Fri Oct 6 04:30:30 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * sample/openssl/c_rehash.rb: Use digest/md5 instead of obsolete md5.
+
+Wed Oct 4 18:47:25 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/*: bugfix and update
+ (see ext/tk/ChangeLog.tkextlib).
+
+Wed Oct 4 17:25:14 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call): check protected visibility based on real self,
+ not ruby_frame->self. [ruby-talk:217822]
+
+Wed Oct 4 08:52:30 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/optparse/test_getopts.rb: changed the class name of test case
+ to get rid of conflict with test_optparse.rb.
+
+Tue Oct 3 23:32:27 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/testcase.rb (Test::Unit::TestCase.suite): test name
+ must be string. fixed: [ruby-core:08978]
+
+Mon Oct 2 23:47:55 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/autorunner.rb (Test::Unit::AutoRunner::COLLECTORS):
+ base directory should be lower precedence. fixed: [ruby-dev:29622]
+
+ * lib/test/unit/autorunner.rb (Test::Unit::AutoRunner#options): typo.
+
+ * lib/test/unit/collector/dir.rb (Test::Unit::Collector::Dir#collect_file):
+ load expanded path. fixed: [ruby-dev:29621]
+
+Mon Oct 2 15:49:19 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * instruby.rb: batfile should be CRLF'ed.
+
+Mon Oct 2 01:24:26 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (test-all): separate directory where running test cases
+ from source tree.
+
+ * lib/test/unit/autorunner.rb (options): added --basedir, --workdir
+ and --load-path options.
+
+ * lib/test/unit/collector/dir.rb (recursive_collect, collect_file):
+ base directory support.
+
+Sun Oct 1 23:56:52 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, common.mk, ext/extmk.rb, win{32,ce}/Makefile.in: keep
+ LIBRUBY_SO unless need to be removed.
+
+Sun Oct 1 23:12:19 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#make_switch): pass arguments directly.
+
+Sat Sep 30 15:12:25 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.4.
+
+Fri Sep 29 12:11:04 2006 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * jcode.rb (succ!): call original succ! if $KCODE == 'n'.
+ fixed: [ruby-talk:216845]
+
+Fri Sep 29 11:43:40 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (try_func): revert fallback checking undeclared function.
+ fixed: [ruby-core:08949]
+
+Fri Sep 29 09:56:56 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: extout is needed for also clean.
+ fixed: [ruby-core:08944]
+
+ * lib/optparse.rb (OptionParser::Switch#conv_arg): unsplat by
+ Proc#call if no conversion is given.
+
+Thu Sep 28 23:59:31 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * node.h (struct thread): declare win32_exception_list on cygwin and
+ win32 regardless if it is implemented. Provisional fix for
+ [ruby-core:08917].
+
+Thu Sep 28 20:53:16 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/tmpdir.rb: use return value of getdir.call for length.
+
+Wed Sep 27 01:04:49 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (try_func): check function pointer first and macro next.
+
+ * lib/mkmf.rb (have_type): simplified with typedef and sizeof.
+
+Tue Sep 26 23:57:03 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#getopts): use strings as key.
+ fixed: [ruby-dev:29614]
+
+Tue Sep 26 15:31:26 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {win32,wince}/Makefile.sub (CPP): check predefined value.
+
+Tue Sep 26 07:55:16 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_shift): should not move memory region if array
+ body is shared. a patch from Kent Sibilev <ksruby at gmail.com>.
+ [ruby-core:08922]
+
+Mon Sep 25 22:26:26 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_path_end): skip root directory. fixed: [ruby-core:08913]
+
+ * lib/mkmf.rb (init_mkmf): set default $LDFLAGS. Patch by Michal
+ Suchanek <hramrach at centrum.cz>. [ruby-talk:216256]
+
+Mon Sep 25 08:14:43 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_shift): should clear shifting top element.
+ [ruby-talk:216055]
+
+ * array.c (rb_ary_shift): avoid creating shared object if array
+ size is small.
+
+Mon Sep 25 08:11:35 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * random.c (rb_f_rand): RDoc typo fix. a patch from Frederick
+ Cheung <fred at 82ask.com>. [ruby-talk:216047]
+
+Sun Sep 24 22:28:20 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * runruby.rb: extension library scripts moved into common directory.
+
+Sun Sep 24 14:59:50 2006 Tanaka Akira <akr@fsij.org>
+
+ * node.h (struct thread): ia64 support is broken by sandbox patch.
+
+Sun Sep 24 12:11:16 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.3.
+
+Sat Sep 23 23:24:57 2006 why the lucky stiff <why@ruby-lang.org>
+
+ * eval.c (rb_thread_save_context, rb_thread_restore_context):
+ sandbox hook to save and restore sandbox state.
+
+ * eval.c (thread_no_ensure): added THREAD_NO_ENSURE thread flag.
+
+ * eval.c (rb_thread_kill_bang): Thread#kill! uses the above flag
+ to circumvent ensure, in order to prevent endless loops.
+ [ruby-core:08768]
+
+ * eval.c (rb_thread_kill): fix Thread#kill docs, which returns
+ the thread object in all cases.
+
+ * node.h: expose the rb_jmpbuf_t and rb_thread_t structs, along
+ with the thread flags. used by the sandbox extension.
+
+ * ruby.h: extern rb_eThreadError, so sandbox can swap it.
+
+Sat Sep 23 21:34:15 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::QueryExtension::read_multipart): CGI content
+ may be empty. a patch from Jamis Buck <jamis at 37signals.com>.
+
+Sat Sep 23 08:35:53 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rdoc/ri/ri_options.rb: prevent NameError. [ruby-dev:29597]
+
+Sat Sep 23 01:04:20 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.2.
+
+Fri Sep 22 02:06:26 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * .cvsignore: ignore timestamp files and installed list file.
+
+Fri Sep 22 01:36:34 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb: include FileUtils unconditionally.
+
+Thu Sep 21 22:56:20 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (no-install): not install rdoc actually.
+
+ * common.mk (install-doc, no-install-doc): use instruby.rb.
+
+ * instruby.rb: rdoc installation.
+
+ * ext/extmk.rb: expand ruby executable names.
+
+Thu Sep 21 13:55:07 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/etc/etc.c (etc_getpwuid): uid integer should be wraped in
+ uid_t value. [ruby-core:08897]
+
+ * ext/etc/etc.c (etc_getpwuid): uid_t may be bigger than plain
+ 'int' type.
+
+Wed Sep 20 23:17:41 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (pre-install-doc): create data directory before install.
+
+ * lib/mkmf.rb (dir_re): fixed typo.
+
+ * lib/mkmf.rb (install_dirs): remove extra slash.
+
+Wed Sep 20 09:53:38 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32,wince}/Makefile.sub (INSTALLED_LIST): need to define
+ this macro to install.
+
+Wed Sep 20 09:43:10 2006 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: allow extra spaces in responses.
+ Thanks, Tom Soderlund. (backported from HEAD)
+
+Wed Sep 20 09:25:39 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/gdbm/gdbm.c: add RDoc documentation. a patch from Peter
+ Adolphs <futzilogik at users dot sourceforge dot net>.
+ [ruby-doc:1223]
+
+Tue Sep 19 01:28:00 2006 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb: backport from HEAD (rev 1.71).
+
+ * lib/fileutils.rb (FileUtils.cp_r): new option
+ :remove_destination.
+
+Tue Sep 19 00:42:15 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_obj_ivar_defined, rb_mod_cvar_defined): new methods,
+ Kernel#instance_variable_defined? and Module#class_variable_defined?.
+ [ruby-dev:29587]
+
+ * lib/date/format.rb (Date::Bag#method_missing): use new method,
+ instance_variable_defined? to check if an instance variable is
+ defined. fixed: [ruby-dev:29554]
+ -- This didn't fix anything.
+
+Sun Sep 17 23:44:58 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rdoc/rdoc.rb (RDoc::RDoc#document): scan only files modified
+ after the previous generation.
+
+Sun Sep 17 17:42:13 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (install-doc): reverted.
+
+ * instruby.rb: stores file name list without destdir prefix.
+
+ * lib/rdoc/generators/ri_generator.rb: do not chdir twice.
+
+Sat Sep 16 23:14:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/pty/pty.c (establishShell): remove remaining unused line.
+
+Sat Sep 16 16:40:44 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, common.in, instruby.rb, ext/extmk.rb, lib/mkmf.rb:
+ use instruby.rb to install extensions instead of ext/extmk.rb.
+
+ * instruby.rb: store installed list into the file.
+
+ * ext/dbm/extconf.rb: allow multiple candidates for dbm-type.
+
+ * ext/io/wait/extconf.rb: suspicious checking_for.
+
+ * ext/pty/pty.c (establishShell): parent pid is not used.
+
+ * ext/pty/pty.c (freeDevice): not used.
+
+ * ext/pty/pty.c (get_device_once): removed garbage right brace.
+
+ * lib/mkmf.rb (checking_for): improved the messages.
+
+Thu Sep 14 16:11:15 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_intern): raise SecurityError only when $SAFE
+ level is greater than zero. [ruby-core:08862]
+
+ * parse.y (rb_interned_p): new function to check if a string is
+ already interned.
+
+ * object.c (str_to_id): use rb_str_intern().
+
+Wed Sep 13 18:43:05 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * README.EXT: English adjustment. [ruby-core:08851] and
+ [ruby-core:08852]
+
+Wed Sep 13 18:25:18 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-parse-partial): better here-doc support.
+ a patch from Marshall T. Vandegrift <llasram at gmail.com>.
+ [ruby-core:08804]
+
+Wed Sep 13 16:43:36 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_intern): prohibit interning tainted string.
+
+Wed Sep 13 01:14:21 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#getopts): works with pre-registered
+ options. [ruby-core:08826]
+
+Sun Sep 10 20:27:13 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.1.
+
+Tue Jan 10 09:18:03 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (stack_extend): fixed prototype.
+
+ * eval.c (rb_require_safe): prevent extension from loading twice.
+ fixed: [ruby-dev:29523]
+
+Sat Sep 9 23:50:38 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_mul0): bignum multiplication without
+ normalization.
+
+ * bignum.c (rb_big_pow): use rb_big_mul0(). [ruby-dev:29547]
+
+Sat Sep 9 14:08:38 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/test/unit/testcase.rb (Test::Unit::TestCase#run): Rescue
+ Exception in Test::Unit::TestCase#run. [ruby-core:08783]
+
+Sat Sep 9 04:55:59 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/pstore.rb: open all in binary mode, and get rid of the quirk of
+ msvcrt. fixed: [ruby-dev:29518]
+
+Sat Sep 9 04:54:42 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, win32/Makefile.sub (MINIRUBY): append MINIRUBYOPT.
+
+ * mkconfig.rb, ext/extmk.rb, lib/mkmf.rb, win32/mkexports.rb: suppress
+ warnings with $VERBOSE.
+
+ * ext/extmk.rb: Proc#call does not pass the block in 1.8.
+
+ * win32/resource.rb: add more info.
+
+Fri Sep 8 10:03:59 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cookie.rb (WEBrick::Cookie.parse_set_cookies): new
+ method to parse multiple cookies per Set-Cookie header.
+ Thanks to Aaron Patterson <aaron_patterson at speakeasy.net>.
+ [ruby-core:08802]
+
+Fri Sep 8 08:59:30 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/Makefile.sub, win32/configure.bat win32/setup.mak: program
+ name transform.
+
+Fri Sep 8 01:33:08 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h (RSTRING_PTR): add migration macro.
+
+ * ruby.h (RARRAY_PTR): ditto.
+
+Thu Sep 7 23:27:05 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (path_check_0, fpath_check): disable path check on cygwin.
+ [ruby-talk:213074]
+
+Wed Sep 06 12:05:19 2006 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/lib/kconv.rb (Kconv::RegexpEucjp): fix regexp for euc-jp
+ [ruby-dev:29344]
+
+ * ext/nkf/lib/kconv.rb (Kconv::toeuc): remove -m0 [ruby-dev:29505]
+
+Tue Sep 5 06:47:22 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (time_to_s): variable declaration after an execution
+ statement.
+
+Tue Sep 5 05:56:51 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (flo_hash): improve collision. fixed: [ruby-dev:29352]
+
+Tue Sep 5 05:49:41 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (path_check_0): check if sticky bit is set on parent
+ directories for executable path. fixed: [ruby-dev:29415]
+
+Tue Sep 5 05:03:46 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (fix_plus): addition in Fixnum will never overflow
+ long. a patch from Ondrej Bilka <neleai at seznam.cz>.
+ [ruby-core:08794]
+
+ * numeric.c (fix_minus): ditto.
+
+ * bignum.c (rb_big_pow): eagerly truncate resulting bignum.
+ [ruby-core:08794]
+
+Mon Sep 4 23:15:34 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_to_s): make it conform to RFC2822 date format.
+ [ruby-dev:29467]
+
+Mon Sep 4 21:43:57 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/dbm/extconf.rb: create makefile according to the result of check
+ for dbm header. fixed: [ruby-dev:29445]
+
+Mon Sep 4 21:42:35 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.
+
+Mon Sep 4 21:14:20 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (time_strftime): include nul character. fixed: [ruby-dev:29422]
+
+Mon Sep 4 16:29:33 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::out): specify -m0 -x option for nkf.
+ [ruby-dev:29284]
+
+Mon Sep 4 16:13:23 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (pipe_open): command name should not contain null bytes.
+ [ruby-dev:29421]
+
+ * process.c (proc_spawn): ditto.
+
+ * process.c (proc_spawn_n): ditto.
+
+ * process.c (rb_f_system): ditto.
+
+Sun Sep 3 15:32:44 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb: get rid of nil.to_s.
+
+Sun Sep 3 06:24:38 2006 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/socket.c (ruby_connect): sockerrlen should be socklen_t.
+
+Sun Sep 3 04:40:42 2006 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/extconf.rb: check arpa/inet.h for ntohs.
+
+ * ext/socket/socket.c: include arpa/inet.h if available.
+
+Sun Sep 3 02:34:55 2006 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/unix.rb (DRbUNIXSocket#close): don't get path if client mode.
+ [ruby-dev:29417]
+
+Sun Sep 3 01:45:17 2006 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/acl.rb (ACLEntry#initialize): examine whether '*' is
+ included before IPAddr.new. [ruby-dev:29406]
+
+Sat Sep 2 13:23:01 2006 Tanaka Akira <akr@fsij.org>
+
+ * common.mk (ia64.o): use the compiler driver to assemble ia64.s
+ to use appropriate ABI.
+
+Sat Sep 2 03:36:22 2006 Tanaka Akira <akr@fsij.org>
+
+ * common.mk, configure.in, defines.h, eval.c, gc.c, main.c,
+ numeric.c, ruby.h, ia64.s: backport IA64 HP-UX support.
+
+Fri Sep 1 13:52:57 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/font.rb: TkFont#current_configinfo() doesn't work
+ on Tcl/Tk8.x.
+
+Thu Aug 31 12:46:55 2006 why the lucky stiff <why@ruby-lang.org>
+
+ * eval.c (ruby_init): rename top_cref to ruby_top_cref and export,
+ along with ruby_cref, for use by the sandbox. [ruby-core:08762]
+
+ * node.h: ditto.
+
+Tue Aug 29 19:10:10 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_hash_s_create): fixed memory leak, based on the patch
+ by Kent Sibilev <ksruby at gmail.com>. fixed: [ruby-talk:211233]
+
+Mon Aug 28 11:36:02 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_rb.rb: Fix typo. Submitted by
+ <calamitas at gmail.com>. [ruby-core:08724]
+
+Mon Aug 28 07:53:44 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/ri/ri_formatter.rb: Don't unescape HTML in HtmlFormatter.
+ Submitted by Kent Sibilev <ksruby at gmail.com>. [ruby-core:08392].
+
+Mon Aug 28 07:25:45 2006 Eric Hodel <drbrain@segment7.net>
+
+ * file.c (File#size?): Fix documentation submitted by Rick Ohnemus.
+ ruby-Bugs-5529. [ruby-core:08725]
+
+Sat Aug 26 08:07:13 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.8.2.
+
+Fri Aug 25 22:32:04 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rexml/source.rb (REXML::IOSource#initialize): encoding have to
+ be set with the accessor. fixed: [ruby-list:42737]
+
+Fri Aug 25 17:15:17 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.8.5 released.
+
+Fri Aug 25 17:02:06 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (gc_sweep): typo fixed.
+
+Tue Aug 22 18:47:51 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::handle_method):
+ rdoc documents C module methods as instance methods. a patch in
+ [ruby-core:08536].
+
+Sat Aug 19 14:15:02 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub (config.status): include winsock2.h instead of
+ winsock.h when --with-winsock2 is specified.
+ fixed: [ruby-dev:29296]
+
+Sat Aug 19 11:28:08 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_rename): use errno if set properly.
+ fixed: [ruby-dev:29293]
+
+Sat Aug 19 11:09:23 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (then): remove semicolon warning. [ruby-dev:29299]
+
+Thu Aug 17 19:15:16 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_stat_[rRwWxX]): check for super user.
+ fixed: [ruby-core:08616]
+
+Thu Aug 17 14:47:06 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb: added rdoc by Daniel Berger. [ruby-core:08177]
+
+Thu Aug 17 00:39:05 2006 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/ring.rb (do_reply): Fix for RingServer fails to find a
+ TupleSpace when TupleSpace resides in the same ruby process with
+ RingServer. a patch from Kent Sibilev. [ruby-core:08453]
+
+Wed Aug 16 11:45:36 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (proc_setuid, proc_setgid, proc_seteuid, proc_setegid):
+ get rid of bogus implementations on Mac OS X.
+
+Tue Aug 15 19:10:18 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#find_class_comment): Fix
+ broken class-level documentation.
+
+Wed Aug 16 11:09:26 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (set_arg0): fill argv other than the first with an empty
+ string instead of NULL.
+
+Wed Aug 16 11:08:00 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.h: removed an excess macro. fixed: [ruby-dev:29258]
+
+Tue Aug 8 23:49:06 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/extend-command.rb (IRB::ExtendCommandBundle): pacify
+ RDoc. a patch from Eric Hodel <drbrain at segment7.net>.
+ [ruby-core:08522]
+
+Tue Aug 8 11:32:54 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * Makefile.in, common.mk, configure.in: fix for platforms without
+ rm. patches from Yutaka kanemoto <kinpoco at gmail.com>.
+ [ruby-dev:29215]
+
+Mon Aug 7 17:56:59 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c, ext/digest/rmd160/rmd160ossl.c,
+ ext/digest/sha1/sha1ossl.c, ext/readline/readline.c: move
+ incluion of config.h to pacify AIX. a patch from Yutaka
+ Kanemoto <kinpoco at gmail.com>. [ruby-dev:29197]
+
+Mon Aug 7 15:55:08 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/syck/syck.c (syck_move_tokens): should avoid negative
+ memmove. [ruby-list:42625]
+
+Mon Aug 7 14:37:48 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in, common.mk: AIX link issue. a patch from Yutaka
+ Kanemoto <kinpoco at gmail.com>. [ruby-dev:29190]
+
+ * ext/socket/socket.c: AIX socket support. [ruby-dev:29190]
+
+Mon Aug 7 12:05:28 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dln.c, eval.c, gc.c, regex.c, ruby.h: shut up AIX alloca
+ warning. a patch from Yutaka Kanemoto <kinpoco at gmail.com>.
+ [ruby-dev:29191]
+
+Sun Aug 6 20:40:41 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (str[fp]time): %[EO]U didn't denote %U.
+
+Sat Aug 5 17:07:43 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (top_local_setup): local_vars[-1] should point
+ ruby_scope itself to protect local_tbl from garbage collection.
+ [ruby-dev:29049]
+
+Sat Aug 5 13:54:03 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (str[fp]time): "%\n" means "\n".
+
+Fri Aug 4 15:21:00 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib: Merge RDoc and .document from HEAD.
+ * lib/drb/ssl.rb: Close socket on SSLError [ruby-core:7197]
+
+Fri Aug 4 19:13:41 2006 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * lib/irb/{init.rb,ruby-lex.rb,slex.rb}: can't input '\c' for
+ [ruby-core: 7122].
+
+Fri Aug 4 14:02:14 2006 James Edward Gray II <james@grayproductions.net>
+
+ * lib/date/format.rb (__strptime, strftime): allow multi-line patterns
+ in Date#strftime the same as Time#strftime accepts.
+ fixed: [ruby-core:08466]
+
+Fri Aug 4 13:56:51 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * pack.c (pack_pack): check argument overrun for 'P'. based on a
+ patch by rucila <rucila at yahoo.cojp>. fixed: [ruby-dev:29182]
+
+Tue Aug 1 17:44:03 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (init_stdhandle): assign standard file handles.
+
+Tue Aug 1 12:24:58 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (Init_Binding): fix old commit miss.
+
+Mon Jul 31 17:08:20 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (exit_handler): new function; release winsock and
+ environment work area.
+
+ * win32/win32.c (NTInitialize): setup exit_handler.
+
+ * win32/win32.c (StartSockets): use exit_handler.
+
+ * win32/win32.c (rb_w32_getenv): use GetEnvironmentStrings() instead
+ of GetEnvironmentVariable(), because the latter cannot distinguish
+ wheather a null environment variable exists or not.
+ fixed: [ruby-talk:205123]
+
+Mon Jul 31 16:15:13 2006 Tanaka Akira <akr@fsij.org>
+
+ * test/ruby/test_process.rb (TestProcess#test_rlimit_nofile):
+ setrlimit may fail with EINVAL.
+ reported by MIYAMUKO Katsuyuki. [ruby-dev:29174]
+
+Mon Jul 31 13:38:22 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httprequest.rb (WEBrick::HTTPReuqest#parse_uri): improve
+ for the value of IPv6 address in the Host: header field.
+
+Mon Jul 31 09:22:12 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h: use ifdef (or defined) for macro constants that may or
+ may not be defined to shut up gcc's -Wundef warnings.
+ [ruby-core:08447]
+
+Sun Jul 30 23:26:22 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_call0): trace call/return of method defined from block.
+ fixed: [ruby-core:08329]
+
+ * eval.c (rb_trap_eval): make the current thread runnable to deal with
+ exceptions which occurred within the trap. fixed: [ruby-dev:27729]
+
+ * lib/cgi/session.rb, lib/cgi/session/pstore.rb: suppress warnings.
+ fixed: [ruby-talk:204896]
+
+Sat Jul 29 06:12:06 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: freeze ip_name for security reason.
+
+Sat Jul 29 01:23:52 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/logger.rb: improves the amount of documentation that Rdoc
+ picks up when processing logger.rb by moving the require
+ statement back before the comment block. a patch from Hugh
+ Sasse <hgs at dmu.ac.uk>. [ruby-core:08422]
+
+Thu Jul 27 22:21:52 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (time_to_s): fixed format mismatch.
+
+Thu Jul 27 21:19:54 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * math.c (domain_check): a new function to check domain error
+ explicitly for systems that return NaN like FreeBSD.
+ [ruby-core:07019]
+
+ * math.c (math_acos, math_asin, math_acosh, math_atanh, math_log,
+ math_log10, math_sqrt): use domain_check().
+
+ * math.c (math_sqrt): fix documentation flaw.
+
+Thu Jul 27 18:12:12 2006 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * time.c: need to declare time_utc_offset.
+
+Thu Jul 27 17:01:01 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_close): always calls "close" method of the receiver.
+ [ruby-core:6911] [ruby-core:8112]
+
+Thu Jul 27 16:49:01 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_to_s): use +0900 style timezone string for local time.
+ [ruby-dev:29143]
+
+Thu Jul 27 16:41:15 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/openssl/ossl.h: move <ruby.h> inclusion point to shut up
+ Solaris compiler. [ruby-core:08114]
+
+Wed Jul 26 22:20:59 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in: add support for as and ASFLAGS. [ruby-dev:29138]
+
+Wed Jul 26 22:13:45 2006 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/http.rb: sync with HEAD (rev 1.132).
+
+ * lib/net/http.rb (Net::HTTP#post, request_post, request): should
+ set Content-Type: x-www-form-urlencoded by default.
+
+ * lib/net/http.rb (Net::HTTPHeader#content_type): should return
+ nil when there's no Content-Type.
+
+ * lib/net/http.rb (Net::HTTPHeader#sub_type): should return nil
+ when there's no sub Content-Type (e.g. "Content-Type: text").
+
+ * lib/net/http.rb (Net::HTTPHeader#type_params): wrongly failed
+ when there's no Content-Type.
+
+Wed Jul 26 18:35:38 2006 Minero Aoki <aamine@loveruby.net>
+
+ * ext/strscan/strscan.c: sync with HEAD (rev 1.25).
+
+ * ext/strscan/strscan.c (strscan_do_scan):
+ StringScanner.new("").scan(//) should return "". [ruby-Bugs:4361]
+
+Wed Jul 26 18:14:19 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/pty/pty.c (getDevice): retry once after GC on failure.
+ [ruby-core:08282]
+
+Wed Jul 26 17:28:16 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): prepend ".." to %u for negative bignum,
+ but not "-". fixed: [ruby-core:08167]
+
+Wed Jul 26 16:39:07 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_scan): add string modification check.
+ [ruby-core:7216]
+
+Wed Jul 26 16:06:03 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::QueryExtension::read_multipart): check
+ multipart boundary end. a patch from Fujioka <fuj at rabbix.jp>
+ [ruby-dev:28470]
+
+Wed Jul 26 01:02:59 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: suppress warnings by automake 1.8 or later.
+
+Tue Jul 25 00:30:06 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/prettyprint.rb: RD to RDoc conversion by Hugh Sasse.
+
+Tue Jul 25 14:49:51 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/mkmf.rb (configuration): typo.
+
+Tue Jul 25 13:14:32 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * process.c (rb_proc_times): rename hz to hertz to avoid name
+ crash on AIX. [ruby-dev:29126]
+
+Mon Jul 24 22:03:40 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (backtrace): skip frames successive on node and method name.
+
+Mon Jul 24 17:55:55 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * process.c (rb_f_system): add security check. [ruby-talk:202947]
+
+ * process.c (rb_f_system): move signal right before fork to avoid
+ signal handler intervention.
+
+Mon Jul 24 15:51:52 2006 Tanaka Akira <akr@fsij.org>
+
+ * ext/readline/readline.c (readline_readline): rl_deprep_term_function
+ may be NULL with libedit. reported by Ryan Davis. [ruby-dev:29070]
+
+Mon Jul 24 15:19:55 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call0): revert last change. [ruby-dev:29112]
+ [ruby-core:08374]
+
+Sun Jul 23 22:59:49 2006 Tanaka Akira <akr@fsij.org>
+
+ * test/socket/test_unix.rb: disabled on cygwin.
+ reported by Kouhei Yanagita. [ruby-dev:29080]
+
+Fri Jul 21 21:21:08 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_call0): include funcalled methods in caller list.
+ fixed: [ruby-core:08290]
+
+Fri Jul 21 12:11:00 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb, lib/mkmf.rb (with_destdir): remove drive letter before
+ prepending destdir on DOSISH.
+
+Thu Jul 20 15:07:14 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h: export classes/modules to implement sandbox.
+ [ruby-core:08283]
+
+Thu Jul 20 00:06:29 2006 Keiju Ishitsuka <keiju@ishitsuka.com>
+
+ * lib/irb/completion.rb: support for completion of numeric
+ number. [ruby-dev: 29038]
+
+Wed Jul 19 23:53:05 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/parser.rb, lib/rss/utils.rb: added documents.
+
+Tue Jul 18 22:10:13 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * process.c (rb_f_system): block SIGCHLD during the process
+ execution, like glibc system(3) does. [ruby-talk:202361]
+
+Tue Jul 18 23:12:14 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (open_ifs_socket): should not use plain malloc.
+
+ * win32/win32.c (rb_w32_opendir): should not use plain realloc.
+
+Tue Jul 18 18:05:49 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/ruby/test_float.rb (TestFloat::test_strtod): update test to
+ conform strtod change.
+
+Tue Jul 18 15:49:42 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_unpack): propagate association array to copied
+ string. [ruby-core:08223]
+
+ * pack.c (pack_unpack): return referenced string itself if it has
+ same length as specified. a patch from <nobu at ruby-lang.org>
+ in [ruby-core:08225].
+
+ * pack.c (pack_pack): taint 'p' packed strings.
+
+Tue Jul 18 14:03:02 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/webrick/httpserver.rb (WEBrick::HTTPServer::unmount): remove
+ inpect argument from sprintf. [ruby-dev:29039]
+
+Tue Jul 18 10:53:37 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_cstr_to_dbl): limit out-of-range message.
+
+ * util.c (ruby_strtod): return end pointer even if ERANGE occurred.
+ fixed: [ruby-dev:29041]
+
+Mon Jul 18 00:43:05 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * util.c (ruby_strtod): stop at dot not followed by digits.
+ fixed: [ruby-dev:29035]
+
+Tue Jul 18 00:01:27 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: remove LIBRUBY_SO if static linked extensions exist.
+
+Mon Jul 17 23:30:46 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (rb_cv_msvcrt): defaulted to msvcrt. Workaround for a
+ bug of cygwin 1.5.20.
+
+Mon Jul 17 13:43:05 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (define_swapx): should not use plain malloc.
+
+Mon Jul 17 12:58:41 2006 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: should use ac_cv_lib_dl_dlopen=no on MinGW.
+
+Sat Jul 15 23:50:12 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_require_safe): wait for another thread requiring the same
+ feature. fixed: [ruby-core:08229]
+
+Sat Jul 15 01:27:13 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (has_magic): glob names contain alphabets to enable case fold
+ search also for directories. fixed: [ruby-talk:201917]
+
+Sat Jul 15 01:09:22 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * st.c (malloc): use xmalloc/xcalloc instead of plain
+ malloc/calloc, to detect memory allocation failure. see
+ <http://www.nongnu.org/failmalloc/>.
+
+ * gc.c (rb_memerror): should not raise empty nomem_error.
+
+Fri Jul 14 13:08:13 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: add methods for new features of latest Tcl/Tk8.5.
+
+ * ext/tk/lib/tk/namespace.rb: ditto.
+
+Fri Jul 14 02:30:12 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/monitor.rb: document patch from Hugh Sasse <hgs at dmu.ac.uk>.
+ [ruby-core:08205]
+
+Fri Jul 14 01:09:46 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (then): error in warning action.
+
+Fri Jul 14 00:10:15 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_pop): may cause realloc oscillation. a patch
+ from MORITA Naoyuki <mlgetter at kidou.sakura.ne.jp>.
+ [ruby-dev:29028]
+
+Thu Jul 13 22:23:56 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/composite.rb: improve handling of the classname on the
+ option database for the widget class which includes TkComposite.
+
+Thu Jul 13 20:32:19 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/parser.rb: updated documents by a patch from
+ Hugh Sasse <hgs at dmu.ac.uk>. [ruby-core:8194]
+
+Wed Jul 12 13:54:09 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (then): we'd like to reserve colon here for the future.
+ warning added.
+
+Tue Jul 11 20:58:18 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h: export rb_cMethod. [ruby-talk:201259]
+
+Tue Jul 11 19:13:33 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: remove restriction on the class of
+ pseudo-toplevel.
+
+Tue Jul 11 18:00:57 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: security fix.
+
+Tue Jul 11 17:33:39 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * string.c (rb_str_dump): need to extend len for \b.
+
+Mon Jul 10 22:00:00 2006 Shigeo Kobayashi <shigek@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c: Allows '_' to appear within
+ digits. [ruby-dev:28872]
+
+ * ext/bigdecimal/lib/bigdecimal/util.rb: Bug in to_r reported by
+ [ruby-list:42533] fixed.
+
+Mon Jul 10 19:22:19 2006 Tanaka Akira <akr@fsij.org>
+
+ * gc.c (gc_sweep): expand heap earlier.
+ reported by MORITA Naoyuki. [ruby-dev:28960]
+
+Mon Jul 10 18:59:34 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/font.rb: sorry. mistaken to patch.
+
+Mon Jul 10 18:46:52 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c: make SEGV risk lower at exit.
+
+ * ext/tk/lib/tk.rb: ditto.
+
+ * ext/tk/lib/multi-tk.rb: fail to call function-style methods on slave
+ interpreters. The strategy (MultiTkIp_PseudoToplevel_Evaluable) to
+ fix the problem is a little tricky. You may have to take care of
+ conflicting with it.
+
+ * ext/tk/lib/tk.rb: a little change for the pseudo-toplevel strategy.
+
+ * ext/tk/lib/tk/font.rb: ditto.
+
+ * ext/tk/lib/tk/msgcat.rb: ditto.
+
+ * ext/tk/lib/tkextlib/itk/incr_tk.rb: ditto.
+
+ * ext/tk/sample/demos-en/widget: fail to call function-style methods
+ on sample scripts. To fix it, a strategy which similar to the way
+ on MultiTiIp is used. Please take care when re-write and re-run a
+ demo script on the Widget-Demo code viewer.
+
+ * ext/tk/sample/demos-jp/widget: ditto.
+
+Mon Jul 10 13:58:40 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * signal.c (ruby_nativethread_signal, posix_nativethread_signal,
+ sigsend_to_ruby_thread, install_nativethread_sighandler):
+ nativethread-support on signal handler. RE-backport from 1.9.
+
+ * ruby.h (HAVE_NATIVETHREAD_KILL): ditto.
+
+ * eval.c (ruby_native_thread_kill): ditto.
+
+Mon Jul 10 10:54:14 2006 Ryan Davis <ryand@zenspider.com>
+
+ * lib/rdoc/parsers/parse_f95.rb: massive overhaul from Yasuhiro
+ Morikawa including new file suffixes, function support, public
+ variables and constants, derived-types, defined operators and
+ assignments, namelists, and subroutine and function
+ arguments. Truly massive.
+
+ * lib/rdoc/diagram.rb: diagrams are now cached.
+
+ * lib/irb/completion.rb: fixed a crasher when completing against
+ an unnamed class/module.
+
+ * lib/rdoc/parsers/parse_c.rb: private comment (--/++) support in
+ C-file rdoc.
+
+ * lib/debug.rb: minor clarification in help.
+
+ * lib/pp.rb: minor clarification on exception.
+
+Mon Jul 10 09:29:12 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_clear_cache_for_undef): clear entries for included
+ module. fixed: [ruby-core:08180]
+
+Mon Jul 10 01:48:38 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * st.h (st_data_t): use pointer sized integer for st_data_t.
+ [ruby-dev:28988]
+
+Sun Jul 9 18:06:47 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (try_constant): fix for value 1 at cross compiling.
+
+ * lib/mkmf.rb (create_makefile): prevent substitution of macro
+ definition. fixed: http://www.yotabanana.com/lab/20060624.html#p02
+
+Sun Jul 9 00:54:34 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (next_jump): deal with destination of next.
+ fixed: [ruby-core:08169]
+
+Fri Jul 7 00:38:49 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (rb_hash_default): should not call default procedure if
+ no key is given. [ruby-list:42541]
+
+Fri Jul 7 00:29:10 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_mload): a patch from Daniel Berger
+ <Daniel.Berger at qwest.com>. [ruby-core:08128]
+
+Thu Jul 6 22:21:57 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (rb_proc_times): use sysconf(_SC_CLK_TCK) value prior to
+ HZ and CLK_TCK. fixed: [ruby-talk:200293]
+
+Thu Jul 6 22:17:21 2006 Minero Aoki <aamine@loveruby.net>
+
+ * ext/racc/cparse/cparse.c: sync with original code, rev 1.8.
+
+ * ext/racc/cparse/cparse.c: should mark CparseParams objects.
+
+ * lib/racc/parser.rb: sync with original code, rev 1.8.
+
+ * lib/racc/parser.rb: update coding style.
+
+Mon Jul 3 19:04:38 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c (ip_make_menu_embeddable): help to make a menu
+ widget embeddable (pack, grid, and so on) like as a general widget.
+ However, an embeddable menu may require to be definied some event
+ bindings for general use.
+
+ * ext/tk/lib/tk/event.rb: [bug fix] Tk.callback_break and
+ Tk.callback_continue don't work on MultiTkIp.
+
+ * ext/tk/lib/multi-tk.rb: ditto.
+
+ * ext/tk/lib/tk.rb: lack of Tk.callback_return.
+
+ * ext/tk/lib/tk/menu.rb: improve creating clone menus.
+
+Mon Jul 3 14:42:06 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/etc/extconf.rb (PW_UID2VAL, PW_GID2VAL): defaulted to conversion
+ from int, and sys/types.h needs to be included before grp.h.
+ fixed: [ruby-dev:28938]
+
+Mon Jul 3 01:14:15 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_inspect): encode \b (\010) for escape.
+ [ruby-dev:28927]
+
+ * string.c (rb_str_dump): ditto.
+
+Sun Jul 2 19:17:56 2006 Minero Aoki <aamine@loveruby.net>
+
+ * ext/racc/cparse/cparse.c: sync with original code (rev 1.7).
+
+ * ext/racc/cparse/cparse.c: use rb_catch instead of rb_iterate.
+ Giving a block to a Ruby-level method by rb_iterate is obsolete on
+ Ruby 1.9. Note that current cparse.c still includes one
+ rb_iterate call on Ruby 1.8, but it is not a problem (at least
+ just now).
+
+Sat Jul 1 15:15:49 2006 Tanaka Akira <akr@m17n.org>
+
+ * test/socket/test_nonblock.rb: add timeout to send/receive
+ an empty UDP packet.
+ [ruby-dev:28820]
+
+Fri Jun 30 23:46:23 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in: should test isinf for Solaris with GCC compiler.
+ a patch from <ville.mattila at stonesoft.com>. [ruby-core:07791]
+
+ * configure.in: -shared patch from Andrew Morrow
+ <andrew.c.morrow at gmail.com>. [ruby-core:08100]
+
+Thu Jun 29 18:58:51 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_version): fix patch
+ failure.
+
+Thu Jun 29 18:00:51 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c: add RDoc document. a patch from
+ mathew <meta at pobox.com>. [ruby-core:07050]
+
+Wed Jun 28 15:47:14 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/optparse.rb: RDoc patch from Robin Stocker <robin@nibor.org>
+ [ruby-core:08087]
+
+Wed Jun 28 19:04:34 2006 Tanaka Akira <akr@m17n.org>
+
+ * test/socket/test_unix.rb: test_seqpacket_pair removed.
+ [ruby-dev:28846]
+
+Tue Jun 27 23:03:49 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c: RDoc update for =~ method. a patch from Alex Young
+ <alex at blackkettle.org>. [ruby-core:08068]
+
+Tue Jun 27 22:47:18 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c: forgot to update TCLTKLIB_RELEASE_DATE.
+
+ * ext/tk/lib/tk.rb (tk_tcl2ruby): [bug fix] sometimes fail to convert
+ a tcl string to a ruby object if the tcl string includes "\n".
+
+Tue Jun 27 16:04:05 2006 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.h: define isascii on MinGW for msvcrt compatibility.
+
+ * configure.in: set ac_cv_header_sys_time_h=no on MinGW
+ for msvcrt compatibility.
+
+Tue Jun 27 11:36:02 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/etc/etc.c (setup_passwd, setup_group): allow bignum uid, gid and
+ so on. [ruby-talk:199102]
+
+Mon Jun 26 13:37:27 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc: Merge from HEAD.
+ Add options to limit the ri search path.
+
+Tue Jun 27 00:54:08 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * util.c (powersOf10): constified.
+
+Mon Jun 26 18:37:44 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c (ip_delete): fix SEGV when a slave-ip is
+ deleted on callback.
+
+Mon Jun 26 10:47:42 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (pipe_open): avoid closing uninitialized file descriptors.
+ a patch from <tommy at tmtm.org> [ruby-dev:28600]
+
+Mon Jun 26 09:56:22 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.[ch] (rb_w32_send, rb_w32_sendto): constified.
+
+Sun Jun 25 23:02:12 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, mkconfig.rb: catch-up for latest autoconf.
+
+Sat Jun 24 06:35:00 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * signal.c: revert last change.
+
+ * ruby.h: ditto.
+
+ * eval.c: ditto.
+
+Thu Jun 22 11:52:02 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/net/http.rb (Net::HTTPResponse): duplicated error 501;
+ HTTPInternalServerError should be error 500. [ruby-core:08037]
+
+Thu Jun 22 05:15:58 2006 Tanaka Akira <akr@m17n.org>
+
+ * ext/socket/socket.c (sock_s_socketpair): try GC only once.
+ [ruby-dev:28778]
+
+Wed Jun 21 21:28:32 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (jd_to_commercial): now works fine even if in
+ mathn-ized context.
+
+Wed Jun 21 17:32:31 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * signal.c (ruby_nativethread_signal, posix_nativethread_signal,
+ sigsend_to_ruby_thread, install_nativethread_sighandler):
+ nativethread-support on signal handler (backport from 1.9).
+
+ * ruby.h (HAVE_NATIVETHREAD_KILL): ditto.
+
+ * eval.c (ruby_native_thread_kill): ditto.
+
+Wed Jun 21 08:39:54 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/xmlrpc/create.rb (XMLRPC::Create::conv2value): merge Date
+ and Time processing. [ruby-core:08033]
+
+Wed Jun 21 01:40:25 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yylex, reswords): modifier token is no longer returned in
+ fname state. [ruby-dev:28775]
+
+Wed Jun 21 01:12:46 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: RSS::Element.def_corresponded_attr_writer
+ supported date type.
+
+Tue Jun 20 22:08:36 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * test/rss/test_parser.rb: split parser tests into ...
+ * test/rss/test_parser_1.0.rb: ... RSS 1.0 parsing tests and ...
+ * test/rss/test_parser_2.0.rb: ... RSS 2.0 parsing tests.
+
+Tue Jun 20 21:19:06 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: provided default RSS::Element#children.
+
+ * lib/rss/0.9.rb: used default RSS::Element#children.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/2.0.rb: ditto.
+ * lib/rss/taxonomy.rb: ditto.
+
+Tue Jun 20 21:04:33 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: provided default RSS::Element#_tags.
+
+ * lib/rss/0.9.rb: used default RSS::Element#_tags.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/2.0.rb: ditto.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/taxonomy.rb: ditto.
+
+Tue Jun 20 20:47:07 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: hide RSS::Element.install_model.
+ (RSS::Element.install_have_child_element,
+ RSS::Element.install_have_children_element,
+ RSS::Element.install_text_element,
+ RSS::Element.install_date_element): call
+ RSS::Element.install_model internally.
+
+ * lib/rss/0.9.rb: followed new API.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/2.0.rb: ditto.
+ * lib/rss/content.rb: ditto.
+ * lib/rss/dublincore.rb: ditto.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/syndication.rb: ditto.
+ * lib/rss/taxonomy.rb: ditto.
+ * lib/rss/trackback.rb: ditto.
+
+Tue Jun 20 20:18:05 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/extconf.rb: add check for OBJ_NAME_do_all_sorted.
+
+ * ext/openssl/ossl_cipher.c (ossl_s_ciphers): new method
+ OpenSSL::Cipher.ciphers. it returns all the cipher names.
+
+ * ext/openssl/lib/openssl/cipher.rb:
+ - add constants AES128, AES192, AES256. [ruby-dev:28610]
+ - reimplement without eval()
+
+ * ext/openssl/lib/openssl/digest.rb: reimplement without eval().
+
+ * test/openssl/test_cipher.rb, test_digest: fix about reimplemented
+ features.
+
+ * sample/openssl/cipher.rb: rewrite all.
+
+Sat Jun 19 11:21:46 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/test/unit/assertions.rb: Merge RDoc from HEAD.
+
+Tue Jun 20 01:06:57 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb:
+ - cleanup validation mechanism. Now, #XXX_validation is
+ needless.
+ - changed internal variable name RSS::Element::MODEL to
+ RSS::Element::MODELS.
+ - RSS::Element.install_model requires uri.
+
+ * lib/rss/0.9.rb: followed new validation API.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/2.0.rb: ditto.
+ * lib/rss/content.rb: ditto.
+ * lib/rss/dublincore.rb: ditto.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/syndication.rb: ditto.
+ * lib/rss/taxonomy.rb: ditto.
+ * lib/rss/trackback.rb: ditto.
+
+Mon Jun 19 23:40:59 2006 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/lib/kconv.rb: remove default -m0 and fix document.
+
+ * ext/nkf/nkf-8/{nkf.c, config.h, utf8tbl.c, utf8tbl.h}:
+ imported nkf 2.0.7.
+
+Mon Jun 19 22:31:59 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb:
+ - provided default #to_s as RSS::Element#to_s.
+ - removed RSS::Element#other_element.
+ - RSS::Element#tag requires attributes as Hash instead of Array.
+
+ * lib/rss/0.9.rb: removed #to_s to use RSS::Element#to_s.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/taxonomy.rb: ditto.
+ * lib/rss/trackback.rb: ditto.
+
+ * lib/rss/2.0.rb: removed #other_element.
+
+Mon Jun 19 22:09:16 2006 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c(ole_invoke): support some kind of
+ method of word. [ruby-Bugs#3237]
+
+ * ext/win32ole/tests/test_word.rb: ditto.
+
+ * ext/win32ole/tests/testall.rb: ditto.
+
+Mon Jun 19 00:02:17 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: automatically detected attributes.
+
+ * lib/rss/0.9.rb: removed #_attrs.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/2.0.rb: ditto.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/taxonomy.rb: ditto.
+ * lib/rss/trackback.rb: ditto.
+
+ * lib/rss/parser.rb: followed new internal API.
+
+Mon Jun 19 00:00:17 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: fix bug: initialize improper tables.
+
+Sun Jun 18 22:36:13 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: RSS::Element#initialize accepts initial
+ attributes.
+ * lib/rss/0.9.rb: ditto.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/2.0.rb: ditto.
+ * lib/rss/dublincore.rb: ditto.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/taxonomy.rb: ditto.
+ * lib/rss/trackback.rb: ditto.
+
+ * lib/rss/utils.rb: added Utils.element_initialize_arguments? to
+ detect backward compatibility initial arguments.
+
+ * lib/rss/parser.rb: user initial attributes to initialize
+ RSS::Element.
+
+Sun Jun 18 18:24:42 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/converter.rb: use NKF for Uconv fallback.
+
+Sun Jun 18 18:22:04 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * test/rss/test_image.rb: shared name space configuration.
+
+Sun Jun 18 18:13:25 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: improved ignore_unknown_element
+ handling. RSS::NotExpectedTagError provides tag URI.
+ * lib/rss/parser.rb: ditto.
+ * lib/rss/0.9.rb: ditto.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/content.rb: ditto.
+ * lib/rss/dublincore.rb: ditto.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/syndication.rb: ditto.
+ * lib/rss/taxonomy.rb: ditto.
+ * lib/rss/trackback.rb: ditto.
+
+ * test/rss/rss-assertions.rb: checked URI of not expected tag too.
+ * test/rss/test_parser.rb: ditto.
+
+Sun Jun 18 18:08:36 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: changed empty namespace URI representation to ""
+ from nil.
+ * lib/rss/parser.rb: ditto.
+ * lib/rss/0.9.rb: ditto.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/2.0.rb: ditto.
+
+Sun Jun 18 18:03:50 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/parser.rb: removed a guard for requiring open-uri.
+
+Sun Jun 18 18:01:26 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: fixed typo: except -> expect
+ * lib/rss/parser.rb: ditto.
+ * test/rss/rss-assertions.rb: ditto.
+ * test/rss/test_parser.rb: ditto.
+
+Sun Jun 18 17:52:39 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: RSS::Element#calc_indent became to be deprecated.
+ * lib/rss/0.9.rb: ditto.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/taxonomy.rb: ditto.
+ * lib/rss/trackback.rb: ditto.
+
+ * test/rss/test_1.0.rb: removed RSS::Element.indent_size tests.
+ * test/rss/test_2.0.rb: ditto.
+
+Sun Jun 18 00:49:11 2006 Tanaka Akira <akr@m17n.org>
+
+ * ext/socket/socket.c (bsock_recv_nonblock): new method
+ BasicSocket#recv_nonblock.
+ (udp_recvfrom_nonblock): renamed from ip_recvfrom_nonblock.
+ IPSocket#recvfrom_nonblock is moved to UDPSocket#recvfrom_nonblock.
+ (unix_recvfrom_nonblock): removed.
+ UNIXSocket#recvfrom_nonblock is removed.
+
+Sat Jun 17 22:17:17 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/mathn.rb (Integer::prime_division): raise ZeroDivisionError
+ on zeros. [ruby-dev:28739]
+
+Sat Jun 17 14:53:32 2006 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb: backport from 1.9.
+ (Kernel#Pathname): new method.
+
+Sat Jun 17 10:30:41 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb (Hash#merge, Enumerable#sort_by): removed.
+
+ * lib/rss/rss.rb (RSS::RootElementMixin#to_xml): added.
+ [ruby-talk:197284]
+
+ We can convert RSS version easily like the following:
+ rss10 = RSS::Parser.parse(File.read("1.0.rdf"))
+ File.open("2.0.rss", "w") {|f| f.print(rss10.to_xml("2.0"))}
+
+ * test/rss/test_1.0.rb: added #to_xml test.
+ * test/rss/test_2.0.rb: ditto.
+
+ * test/rss/rss-testcase.rb: added some helper methods that
+ generates sample RSS 2.0.
+
+ * sample/rss/convert.rb: added a sample script to convert RSS format.
+
+Sat Jun 17 10:23:22 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb (Kernel#funcall): removed.
+ * lib/rss/parser.rb (Kernel.URI): removed.
+
+ * lib/rss/maker/: supported
+ xxx.new_yyy do |yyy|
+ yyy.zzz = zzz
+ ...
+ end
+ style and this style became the style of the recommendation.
+
+ Old style
+ yyy = xxx.new_yyy
+ yyy.zzz = zzz
+ ...
+ is supported too but this style isn't recommended.
+ [ruby-talk:197284]
+
+ * test/rss/test_*maker*.rb: used new recommended style.
+
+Sat Jun 17 09:03:47 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss, test/rss: backported from trunk. (2005-11-16 - now)
+
+ * lib/rss/rss.rb (RSS::VERSION): 0.1.5 -> 0.1.6.
+ * test/rss/test_version.rb (RSS::TestVersion#test_version): ditto.
+
+ * lib/rss/trackback.rb: added TrackBack prefix.
+ * lib/rss/maker/trackback.rb: ditto.
+
+ * lib/rss/rss.rb : removed needless argument 'prefix'.
+ * lib/rss/parser.rb: ditto.
+
+ * lib/rss/1.0.rb: added rdf:Bag.
+
+ * lib/rss/taxonomy.rb: implemented taxonomy module.
+ * test/rss/test_taxonomy.rb: added tests for taxonomy support.
+
+ * lib/rss/1.0.rb: added convenience method 'resources'.
+ * lib/rss/taxonomy.rb: ditto.
+ * test/rss/rss-assertions.rb: added test for 'resources'.
+ * test/rss/test_taxonomy.rb: ditto.
+
+ * lib/rss/rss.rb: fixed a indentation bug.
+ * lib/rss/taxonomy.rb: fixed <taxo:topic> #to_s bug.
+ * test/rss/test_taxonomy.rb: added a #to_s test.
+
+ * lib/rss/maker/taxonomy.rb: implemented taxonomy module for RSS
+ Maker.
+ * lib/rss/taxonomy.rb: supported RSS Maker.
+ * lib/rss/maker.rb: added taxonomy module support.
+
+ * lib/rss/rss.rb: adjusted to other element API.
+ * lib/rss/1.0.rb: adjusted to other element API but backward
+ compatibility is reserved.
+ * lib/rss/0.9.rb: ditto.
+
+ * test/rss/test_maker_taxo.rb: added test case for taxonomy module
+ for RSS Maker.
+ * test/rss/test_setup_maker_1.0.rb: added tests for taxo:topic.
+
+ * test/rss/test_setup_maker_1.0.rb: added backward compatibility
+ test.
+ * test/rss/test_setup_maker_0.9.rb: ditto.
+ * test/rss/test_setup_maker_2.0.rb: ditto.
+
+ * test/rss/rss-testcase.rb: added convenience method for setting
+ up taxo:topic.
+ * test/rss/rss-assertions.rb: added assertion for taxo:topic.
+
+ * sample/rss/blend.rb: followed new API.
+
+ * lib/rss/taxonomy.rb: changed class or module prefix to
+ Taxonomy from Taxo.
+ * lib/rss/maker/taxonomy.rb: ditto.
+
+ * test/rss/test_taxonomy.rb: use #reject directory.
+
+ * lib/rss/: use #__send__ instead of #send.
+ * test/rss/: ditto.
+
+ * lib/rss/parser.rb: added entity handling type predicate.
+ * lib/rss/rexmlparser.rb: ditto.
+ * lib/rss/xmlparser.rb: ditto.
+ * lib/rss/xmlscanner.rb: ditto.
+
+ * lib/rss/xmlscanner.rb: more robust entity handling.
+
+ * test/rss/test_parser.rb: added an entity handling test.
+
+ * test/rss/test_2.0.rb: added RSS 2.0 tests.
+ * test/rss/rss-assertions.rb: extended XML stylesheet assertion.
+ * lib/rss/0.9.rb: added initialize method.
+ * test/rss/test_1.0.rb: cleanup.
+
+ * lib/rss/image.rb: added Image prefix.
+ * lib/rss/maker/image.rb: ditto.
+
+ * lib/rss/rss.rb: improved type conversion.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/0.9.rb: ditto.
+ * lib/rss/2.0.rb: ditto.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/syndication.rb: ditto.
+
+ * test/rss/test_2.0.rb: added type conversion tests.
+ * test/rss/test_accessor.rb: ditto.
+ * test/rss/test_to_s.rb: ditto.
+ * test/rss/test_syndication.rb: ditto.
+ * test/rss/test_setup_maker_2.0.rb: ditto.
+ * test/rss/test_setup_maker_1.0.rb: ditto.
+ * test/rss/test_setup_maker_0.9.rb: ditto.
+ * test/rss/test_maker_sy.rb: ditto.
+ * test/rss/test_maker_image.rb: ditto.
+ * test/rss/test_maker_2.0.rb: ditto.
+ * test/rss/test_maker_0.9.rb: ditto.
+ * test/rss/test_image.rb: ditto.
+
+ * test/rss/test_maker_1.0.rb: use assert instead of assert_equal.
+
+ * test/rss/rss-assertions.rb: improved type conversion assertions.
+
+ * lib/rss/rss.rb: added backward compatibility codes.
+ * lib/rss/parser.rb: ditto.
+ * test/rss/test_parser.rb: ditto.
+ * test/rss/test_2.0.rb: ditto.
+
+Sat Jun 17 02:01:00 2006 Tanaka Akira <akr@m17n.org>
+
+ * lib/pp.rb (Kernel#pretty_inspect): defined for pretty printed
+ string.
+
+Sat Jun 17 00:23:58 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (reswords): kDO_BLOCK was missing. fixed: [ruby-core:7995]
+
+Sat Jun 17 00:02:15 2006 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_propertyput): support
+ PROPERTYPUTREF. [ruby-talk:183042]
+
+ * ext/win32ole/tests/test_propertyputref.rb: ditto.
+
+Thu Jun 15 23:02:47 2006 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (fole_methods): The return value
+ of WIN32OLE#ole_methods should include PROPERTYPUTREF methods.
+
+ * ext/win32ole/win32ole.c (fole_put_methods): The return value
+ of WIN32OLE#ole_put_methods should include PROPERTYPUTREF methods.
+
+ * ext/win32ole/tests/test_ole_methods.rb: ditto.
+
+ * ext/win32ole/tests/testall.rb : ditto.
+
+Wed Jun 14 18:23:28 2006 Eric Hodel <drbrain@segment7.net>
+
+ * enum.c (enum_any): Documentation typo.
+
+Wed Jun 14 15:01:09 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser#warn): Don't print
+ warnings when -q is set.
+
+Wed Jun 14 23:03:53 2006 Tanaka Akira <akr@m17n.org>
+
+ * configure.in: check sizeof(rlim_t).
+ check setrlimit.
+
+ * process.c (proc_getrlimit): new method Process.getrlimit.
+ (proc_setrlimit): new method Process.setrlimit.
+
+ * ruby.h (NUM2ULL): new macro.
+
+Mon Jun 12 22:25:09 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): adjust precision length to prevent
+ splitting multi-byte characters. [ruby-list:42389]
+
+Sun Jun 11 23:20:07 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::Arguable#getopts): pass self to the
+ parser.
+
+Sun Jun 11 10:00:57 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.h (write): not need to define on bcc.
+
+Sun Jun 11 08:30:33 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#getopts): new methods.
+
+Sat Jun 10 18:02:40 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/bigdecimal/lib/bigdecimal/newton.rb (Newton::nlsolve): typo
+ fixed: raize -> raise. [ruby-talk:196608]
+
+Thu Jun 8 14:19:17 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.[ch] (rb_w32_read, rb_w32_write): new functions.
+ use recv() and send() when fd is socket. fixed: [ruby-dev:28694]
+
+Wed Jun 7 16:22:51 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/tempfile.rb (Tempfile::make_tmpname): put dot between
+ basename and pid. [ruby-talk:196272]
+
+Wed Jun 7 14:53:04 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (errmap): add some winsock errors.
+
+Wed Jun 7 11:34:38 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * configure.in: add new configure option `--with-winsock2' for mingw.
+
+ * win32/Makefile.sub (config.h): define USE_WINSOCK2 in config.h
+ instead of in CPPFLAGS.
+
+ * ext/socket/extconf.rb: determine whether to use winsock2 or not
+ by using with_config.
+
+Wed Jun 7 10:45:10 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/{configure.bat, setup.mak, Makefile.sub, win32.h}: add
+ new configure option `--with-winsock2'.
+
+ * win32/win32.c (StartSockets): ditto.
+
+ * ext/socket/extconf.rb: ditto.
+
+ * win32/win32.c (open_ifs_socket): new function.
+
+ * win32/win32.c (StartSockets, rb_w32_socket): use open_ifs_socket()
+ instead of socket().
+ ifs socket support is backported from trunk.
+
+Wed Jun 7 09:14:44 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call0): binding for the return event hook should have
+ consistent scope. [ruby-core:07928]
+
+ * eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
+ event_hooks. no guarantee for arbitrary hook deletion.
+ [ruby-dev:28632]
+
+Mon Jun 5 18:12:12 2006 Tanaka Akira <akr@m17n.org>
+
+ * ext/socket/socket.c (sock_s_unpack_sockaddr_in): reject
+ non-AF_INET/AF_INET6 sockaddr.
+ (sock_s_unpack_sockaddr_un): reject non-AF_UNIX sockaddr.
+ [ruby-dev:28691]
+
+Sun Jun 4 20:40:19 2006 Tanaka Akira <akr@m17n.org>
+
+ * ext/socket/socket.c: fix sockaddr_un handling.
+ [ruby-dev:28677]
+
+Fri Jun 2 22:08:17 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/forwardable.rb: RDoc typo fix from Jan Svitok
+ <jan.svitok at gmail.com>. [ruby-core:07943]
+
+Fri Jun 2 19:02:09 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/extconf.rb: use create_header.
+
+ * ext/openssl/ossl.h, ext/openssl/openssl_missing.h:
+ include RUBY_EXTCONF_H.
+
+Fri Jun 2 17:16:52 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (CLEANINGS): remove extconf.h by distclean if created.
+
+Fri Jun 2 00:11:19 2006 Tanaka Akira <akr@m17n.org>
+
+ * ext/socket/socket.c (s_recvfrom): alen may be zero with UNIXSocket
+ too. (tested on NetBSD 3.0)
+ (s_recvfrom_nonblock): extracted from sock_recvfrom_nonblock.
+ (sock_recvfrom_nonblock): use s_recvfrom_nonblock.
+ (ip_recvfrom_nonblock): new method: IPSocket#recvfrom_nonblock
+ (unix_recvfrom_nonblock): new method: UNIXSocket#recvfrom_nonblock
+ (s_accept_nonblock): extracted from sock_accept_nonblock.
+ (sock_accept_nonblock): use s_accept_nonblock.
+ (tcp_accept_nonblock): new method: TCPServer#accept_nonblock
+ (unix_accept_nonblock): new method: UNIXServer#accept_nonblock
+
+Thu Jun 1 19:12:37 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_cmdvector): backslashes inside single-quotes
+ no longer has special meanings. fixed: [ruby-list:42311]
+
+Thu Jun 1 16:14:41 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_getcwd): runtime's getcwd() will not success
+ if the length of the cwd is longer than MAX_PATH.
+ fixed [ruby-list:42335]
+
+Thu Jun 1 11:29:14 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_getcwd): set errno if not set.
+ fixed [ruby-list:42346]
+
+Sat May 27 11:29:46 2006 nobuyoshi nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake): remove extinit files if no statically linked
+ extensions.
+
+Fri May 26 09:05:11 2006 nobuyoshi nakada <nobu@ruby-lang.org>
+
+ * ruby.h, lib/mkmf.rb (create_header): clear command line options for
+ macros moved to extconf.h.
+
+ * ext/extmk.rb (extract_makefile, extmk): made RUBY_EXTCONF_H and
+ EXTSTATIC permanent.
+
+ * ext/{dbm,digest/*,socket,zlib}/extconf.rb: used $defs and $INCFLAGS.
+
+ * {bcc32,win32,wince}/Makefile.sub (COMPILE_C, COMPILE_CXX): added
+ $(INCFLAGS).
+
+ * lib/mkmf.rb (configuration): add $defs unless extconf.h was created.
+
+Thu May 25 01:52:07 2006 nobuyoshi nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (pkg_config): particular config commands support.
+
+ * ext/extmk.rb: deal with $static set in extconf.rb.
+
+ * mkconfig.rb: merge multiple entries to an entry with multiple lines.
+
+ * lib/mkmf.rb: allow a series of commands to link.
+
+ * win32/Makefile.sub: embed manifests.
+
+ * win32/setup.mak: suffix OS name by runtime version.
+
+Wed May 24 23:52:11 2006 nobuyoshi nakada <nobu@ruby-lang.org>
+
+ * configure.in (ac_install_sh): ignore dummy install-sh.
+ [ruby-talk:193876]
+
+Wed May 24 03:10:48 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/lib/openssl/ssl.rb
+ (OpenSSL::SSL::SocketForwarder#setsockopt,getsockopt): typo fixed.
+
+Mon May 22 17:54:12 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/socket/socket.c (sock_recvfrom_nonblock): use rb_read_pending
+ instead of rb_io_read_pending.
+ [ruby-dev:28663]
+
+Mon May 22 17:30:04 2006 Tanaka Akira <akr@m17n.org>
+
+ * rubyio.h (rb_io_set_nonblock): declared.
+
+ * io.c (rb_io_set_nonblock): new function.
+ (io_getpartial): nonblocking read support.
+ (io_read_nonblock): new method: IO#read_nonblock.
+ (io_write_nonblock): new method: IO#write_nonblock.
+
+ * ext/socket/socket.c
+ (sock_connect_nonblock): new method: Socket#connect_nonblock.
+ (sock_accept_nonblock): new method: Socket#accept_nonblock.
+ (sock_recvfrom_nonblock): new method: Socket#recvfrom_nonblock.
+
+ [ruby-core:7917]
+
+Mon May 22 15:57:39 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (umethod_bind): should not update original class.
+ [ruby-dev:28636]
+
+Mon May 22 13:38:57 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ev_const_get): should support constant access from
+ within instance_eval(). [ruby-dev:28327]
+
+Thu May 18 17:51:32 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_timeval): should round for usec floating
+ number. [ruby-core:07896]
+
+ * time.c (time_add): ditto.
+
+Thu May 18 17:11:45 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::out): support utf-8. a patch from Fujioka
+ <fuj at rabbix.jp>. [ruby-dev:28649]
+
+Thu May 18 00:42:12 2006 nobuyoshi nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb, lib/mkmf.rb: use BUILD_FILE_SEPARATOR in Makefiles.
+
+Wed May 17 17:55:26 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (sys_warning): should not call a vararg function
+ rb_sys_warning() indirectly. [ruby-core:07886]
+
+Wed May 17 08:17:15 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * util.c (ruby_strtod): try to reduce errors using powersOf10
+ table. [ruby-dev:28644]
+
+Tue May 16 15:34:18 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_initialize): should not allow modifying literal
+ regexps. frozen check moved from rb_reg_initialize_m as well.
+
+Tue May 16 09:20:16 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_initialize): should not modify untainted objects in
+ safe levels higher than 3.
+
+ * re.c (rb_memcmp): type change from char* to const void*.
+
+ * dir.c (dir_close): should not close untainted dir stream.
+
+ * dir.c (GetDIR): add tainted/frozen check for each dir operation.
+
+Mon May 15 17:42:39 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
+ typo fixed. a patch from Florian Gross <florg at florg.net>.
+
+Sat May 13 16:14:05 2006 Tanaka Akira <akr@m17n.org>
+
+ * lib/pp.rb (PP.mcall): new method.
+ (Struct#pretty_print): call Kernel#class and Struct#members even if
+ overridden.
+ (Struct#pretty_print_cycle): ditto.
+ [ruby-core:7865]
+
+Thu May 11 19:57:00 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * util.c (ruby_strtod): differ addition to minimize error.
+ [ruby-dev:28619]
+
+Fri Aug 11 15:39:25 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/yaml/tag.rb: Replace nodoc with stopdoc so Module methods get
+ documented.
+
+Thu May 11 18:10:43 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * util.c (ruby_strtod): should not raise ERANGE when the input
+ string does not have any digits. [ruby-dev:28629]
+
+Sun May 7 03:09:51 2006 Stephan Maka <stephan@spaceboyz.net>
+
+ * lib/resolv.rb (Resolv::DNS::Requester::ConnectedUDP#initialize):
+ Use AF_INET6 for nameservers containing colons.
+
+Sat May 6 00:38:42 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * signal.c (trap): sig should be less then NSIG. Coverity found
+ this bug. a patch from Kevin Tew <tewk at tewk.com>.
+ [ruby-core:07823]
+
+Thu May 4 02:24:16 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/syck/emitter.c (syck_scan_scalar): avoid accessing
+ uninitialized array element. a patch from Pat Eyler
+ <rubypate at gmail.com>. [ruby-core:07809]
+
+ * array.c (rb_ary_fill): initialize local variables first. a
+ patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
+
+ * ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
+ type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
+ [ruby-core:07808]
+
+Wed May 3 02:12:07 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (make_hostent_internal): accept ai_family
+ check from Sam Roberts <sroberts at uniserve.com>.
+ [ruby-core:07691]
+
+Mon May 1 12:23:19 2006 <sinara@blade.nagaokaut.ac.jp>
+
+ * numeric.c (num_div): use floor rather than rb_Integer().
+ [ruby-dev:28589]
+
+ * numeric.c (flo_divmod): the first element of Float#divmod should
+ be an integer. [ruby-dev:28589]
+
+ * test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
+
+Sat Apr 29 22:42:08 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_asn1.c (ossl_asn1_decode0): should initialize
+ flag. [ruby-core:07785]
+
+Fri Apr 28 10:53:16 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * util.c (ruby_strtod): should not cut off 18 digits for no
+ reason. [ruby-core:07796]
+
+ * util.c (ruby_strtod): fixed wrong conversion.
+
+Thu Apr 27 01:38:10 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_fill): internalize local variable "beg" to
+ pacify Coverity. [ruby-core:07770]
+
+Wed Apr 26 16:59:24 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_unpack): now supports CRLF newlines. a patch from
+ <tommy at tmtm.org>. [ruby-dev:28601]
+
+Tue Apr 25 18:00:05 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c (delete_slaves): maybe increment the reference
+ count of a NULL Tcl_Obj [ruby-core:07759].
+
+Tue Apr 25 07:55:31 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/jcode.rb (String::tr_s): should have translated non
+ squeezing character sequence (i.e. a character) as well. thanks
+ to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
+
+Tue Apr 25 00:08:24 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (re_compile_pattern): should check if c is not a
+ multibyte character. a patch from KIMURA Koichi
+ <kimura.koichi at canon.co.jp>. [ruby-dev:28598]
+
+Fri Apr 21 15:19:13 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c (lib_eventloop_ensure): refer freed pointer
+ [ruby-core:07744] and memory leak.
+
+Fri Apr 21 12:14:52 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c: document update patch from Sam Roberts
+ <sroberts at uniserve.com>. [ruby-core:07701]
+
+Wed Apr 19 13:55:27 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (arg): too much NEW_LIST()
+
+ * eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
+
+Wed Apr 19 11:57:04 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
+ [ruby-dev:28585]
+
+ * parse.y (list_concat): revert last change.
+
+ * parse.y (arg): use NODE_ARGSCAT for placeholder.
+
+Wed Apr 19 11:13:17 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
+ mathew <meta at pobox.com>. [ruby-core:07738]
+
+Wed Apr 19 10:13:27 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_const_set): raise error when no target klass is
+ supplied. [ruby-dev:28582]
+
+Wed Apr 19 09:49:36 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (list_concat): should not modify nodes other than
+ NODE_ARRAY. [ruby-dev:28583]
+
+Tue Apr 18 17:40:37 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: add a binding to a container for a slave IP.
+
+ * ext/tk/lib/tk.rb: update RELEASE_DATE.
+
+ * ext/tk/tcltklib.c: forget to reset a Tcl interpreter.
+
+ * ext/tk/stubs.c: fix potential bugs about handling rb_argv0.
+
+Tue Apr 18 00:11:21 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c: block_unique should be 1, not frame_unique.
+ [ruby-dev:28577]
+
+Fri Aug 11 15:39:25 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#find_body): Make RDoc
+ ignore C function prototypes. Patch by Tilman Sauerbeck
+ <tilman at code-monkey.de>. [ruby-core:8574]
+ * lib/yaml/tag.rb: Replace nodoc with stopdoc so Module methods get
+ documented.
+
+Mon Apr 10 01:03:10 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * prec.c (prec_prec_f): documentation patch from
+ <gerardo.santana at gmail.com>. [ruby-core:07689]
+
+Sat Apr 8 02:34:34 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_pow): second operand may be too big even if
+ it's a Fixnum. [ruby-talk:187984]
+
+Sat Apr 8 02:12:38 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * README.EXT: update symbol description. [ruby-talk:188104]
+
+Thu Apr 6 23:28:47 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * COPYING: explicitly note GPLv2. [ruby-talk:187922]
+
+Thu Apr 6 11:18:37 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/panedwindow.rb: lack of arguments. [ruby-core:7681]
+
+Thu Apr 6 01:04:47 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c: fix SEGV when embedding to an application.
+ [ruby-core:7600]
+
+ * ext/tk/tcltklib.c: fix SEGV at exit. [ruby-talk:186489]
+
+ * ext/tk/tkutil/tkutil.c: follow to changing specification of
+ instance_eval on ruby-1.9.x.
+
+ * ext/tk/lib/tk.rb: ditto.
+
+ * ext/tk/lib/multi-tk.rb: ditto.
+
+ * ext/tk/lib/tk.rb: remove warning about redefinition of methods.
+
+ * ext/tk/lib/tk/variable.rb: remove warning about unseting Tcl
+ variables.
+
+Wed Mar 29 20:54:44 2006 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (fole_getproperty): WIN32OLE#[] should accept
+ multi arguments.
+
+ * ext/win32ole/tests/testWIN32OLE.rb (test_setproperty_bracket): ditto.
+
+Wed Mar 29 10:07:44 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c (nkf_each_char_to_hex, encode_fallback_subchar,
+ e2w_conv): support C90 compiler.
+
+Wed Mar 29 06:48:40 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (backtrace): reports aliased method names in a generated
+ backtrace. a patch from "U.Nakamura" <usa at garbagecollect.jp>.
+ [ruby-dev:28471]
+
+Mon Mar 27 22:19:09 2006 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/{nkf.c, utf8tbl.c, config.h}: imported nkf 2.0.6.
+ * Add --ic / --oc option and mapping tables.
+ * Add fallback option.
+ * Add --no-best-fit-chars option.
+ * Fix some bugs.
+
+ * ext/nkf/nkf.c (nkf_split_options): added for parse option string.
+
+ * ext/nkf/lib/kconv.rb (Kconv.to*): add -m0.
+ Note that Kconv.to* still imply -X.
+
+Mon Mar 27 03:17:21 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call0): insecure calling should be checked for non
+ NODE_SCOPE method invocations too.
+
+ * eval.c (rb_alias): should preserve the current safe level as
+ well as method definition.
+
+Fri Mar 24 23:14:30 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (yield_under_i): pass self again for instance_eval().
+ [ruby-dev:28466]
+
+Fri Mar 24 17:20:03 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * process.c (rb_f_sleep): remove description about SIGALRM which
+ is not valid on the current implementation. [ruby-dev:28464]
+
+Thu Mar 23 10:47:03 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (method_missing): should support argument splat in
+ super. [ruby-talk:185438]
+
+Mon Mar 20 12:05:18 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in: Solaris SunPro compiler -rapth patch from
+ <kuwa at labs.fujitsu.com>. [ruby-dev:28443]
+
+Mon Mar 20 09:40:23 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in: remove enable_rpath=no for Solaris.
+ [ruby-dev:28440]
+
+Fri Mar 17 19:08:49 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ssl.c, ext/openssl/ossl_nsspki.c: fix typo.
+ [ruby-core:07571]
+
+Wed Mar 15 16:54:21 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): support libraries without *.so.
+
+Wed Mar 15 16:35:43 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ssl.c, ext/openssl/ossl_nsspki.c: should use
+ "rb_str_new(0, 0)" to make empty string.
+
+Sat Mar 11 14:24:06 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rdoc/ri/ri_formatter.rb (RI::TextFormatter::wrap): removed
+ space before argument parenthesis. [ruby-talk:183630]
+
+ * ruby.1: a clarification patch from David Lutterkort
+ <dlutter at redhat.com>. [ruby-core:7508]
+
+Sat Mar 4 15:26:40 2006 Tanaka Akira <akr@m17n.org>
+
+ * gc.c (id2ref): fix symbol test.
+
+Sat Mar 4 01:08:07 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
+ directories. a patch from Eric Hodel <drbrain at segment7.net>.
+ [ruby-core:07423]
+
+Thu Mar 2 19:44:18 2006 Tanaka Akira <akr@m17n.org>
+
+ * gc.c: align VALUE with sizeof(RVALUE) globally.
+ (is_pointer_to_heap): check alignment out of loop.
+ (id2ref): avoid collision between symbols and objects.
+ (rb_obj_id): ditto. moved from object.c.
+ [ruby-talk:178364] [ruby-core:7305]
+
+Thu Mar 2 18:58:18 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_fd_writable): should not re-schedule output
+ from KILLED thread (must be error printing).
+
+Thu Mar 2 17:57:49 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * gc.c: commited magic for reducing RVALUE size on windows. (24->20byte)
+ [ruby-core:7474]
+
+Thu Mar 2 12:59:14 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.c (filetime_to_unixtime): should set tm_isdst to -1.
+ stat() didn't treat daylight saving time property on WinNT.
+ [ruby-talk:182100]
+
+Thu Mar 2 08:02:42 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (add_heap): heap_slots may overflow. a patch from Stefan
+ Weil <weil at mail.berlios.de>.
+
+Wed Mar 1 00:24:31 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/rdoc/parsers/parse_rb.rb (read_escape): could not handle /\^/.
+ merged Mr. Ishizuka's lib/irb/ruby-lex.rb 's patch rev 1.29.
+ [ruby-talk:181631] [ruby-dev:28404]
+
+Tue Feb 28 09:32:17 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/drb/extservm.rb (invoke_service_command): cannot invoke command
+ if command name is quoted on mswin32. [ruby-dev:28400]
+
+Mon Feb 27 00:19:16 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h (SYM2ID): should not cast to signed long.
+ [ruby-core:07414]
+
+Fri Feb 24 20:07:23 2006 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/drb/drbtest.rb (add_service_command): quote pathnames in the
+ server's command line for space contained directory names.
+ Thanks, arton. [ruby-dev:28386]
+
+Fri Feb 24 12:11:08 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * instruby.rb: install *.exe.manifest and *.dll.manifest if exist.
+ It's for VC++8.
+
+Fri Feb 24 11:33:52 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub (HAVE_HYPOT): bcc32 has hypot().
+
+Fri Feb 24 11:19:58 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * time.c (time_new_internal): add prototype to tell the compiler
+ arugments types.
+
+ * win32/win32.c (NtInitialize): need to set a handler for VC++8.
+
+Fri Feb 24 08:19:16 2006 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * test.rb: Removed. Obsolete by test/nkf.
+
+ * ext/.document: enabled documents in nkf and kconv
+
+ * ext/nkf/nkf.c ext/nkf/lib/kconv.rb: Add rdoc.
+
+Thu Feb 23 22:39:59 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub: use borlndmm.dll if possible. bcc32's RTL internal
+ memory manager cannot handle large memory block properly.
+ ex: 10000.times { "" << "." * 529671; GC.start } # crash
+ [ruby-dev:28230]
+
+Thu Feb 23 13:20:28 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * eval.c (SETUP_ARGS0): fixed memory corruption. [ruby-dev:28360]
+
+Tue Feb 21 02:18:46 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * configure.in (mingw): have link. [ruby-list:41838]
+
+ * win32/Makefile.sub (config.h): ditto.
+
+Tue Feb 21 02:07:39 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (f_arglist): should set command_start = Qtrue for
+ command body. [ruby-talk:180648]
+
+Mon Feb 20 17:37:26 2006 Tanaka Akira <akr@m17n.org>
+
+ * mkconfig.rb: alias RbConfig for Config.
+
+Mon Feb 20 12:27:53 2006 Kent Sibilev <ksruby@gmail.com>
+
+ * lib/rational.rb (Integer::gcd): small typo fix.
+ [ruby-core:07395]
+
+Mon Feb 20 01:05:27 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rational.rb (Integer::gcd): replaced by gcd4 in
+ [ruby-core:07390]. [ruby-core:07377]
+
+Mon Feb 20 00:57:02 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl.h (OSSL_Debug): should not use __func__.
+ [ruby-dev:28339]
+
+Sun Feb 19 04:46:29 2006 Guy Decoux <ts@moulon.inra.fr>
+
+ * eval.c: initial value for block_unique must be 1.
+ [ruby-talk:180420]
+
+Sat Feb 18 23:58:26 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/tracer.rb (Tracer::Tracer.add_filter): turn on tracer mode
+ only when caller() level size is one. [ruby-core:07389]
+
+ * lib/rdoc/parsers/parse_rb.rb: need not to require "tracer".
+ [ruby-core:07389]
+
+ * sample/rtags.rb: ditto.
+
+Sat Feb 18 12:18:26 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/fileutils.rb (FileUtils::fu_world_writable): make it
+ private. [ruby-core:07383]
+
+Sat Feb 18 00:22:39 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/tracer.rb: merged a minor clarification patch from Daniel
+ Berger <Daniel.Berger at qwest.com>. [ruby-core:07376]
+
+Fri Feb 17 11:18:42 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * util.c (ruby_strtod): Float("1e") should fail. [ruby-core:7330]
+
+ * pack.c (EXTEND32): unpack("l") did not work where sizeof(long) != 4.
+ [ruby-talk:180024]
+
+ * pack.c (pack_unpack): fixed integer overflow on template "w".
+ [ruby-talk:180126]
+
+Fri Feb 17 09:39:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_wait_for): sleep should always sleep for
+ specified amount of time. [ruby-talk:180067]
+
+Thu Feb 16 01:10:48 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (backtrace): frame->orig_func may not be initialized.
+ [ruby-core:07367]
+
+Wed Feb 15 16:52:52 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): NODE_OP_ASGN1 should allow splat in its
+ argument list. [ruby-core:07366]
+
+ * parse.y (arg): avoid unnecessary extra argument.
+ [ruby-core:07366]
+
+ * eval.c (rb_eval): honor visibility on OP_ASGN1 and
+ OP_ASGN2. [ruby-core:07366]
+
+Wed Feb 15 10:09:51 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (yield_under_i): should not pass self as an argument to
+ the block for instance_eval. [ruby-core:07364]
+
+Wed Feb 15 09:20:35 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_obj_instance_eval): should be no singleton classes for
+ true, false, and nil. [ruby-dev:28186]
+
+Tue Feb 14 18:48:33 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (DMETHOD_P): accessing wrong frame. [ruby-dev:28181]
+
+ * eval.c (proc_invoke): preserve FRAME_DMETH flag.
+
+Tue Feb 14 15:13:51 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/zlib/zlib.c: supress warning on test/zlib. [ruby-dev:28323]
+
+Tue Feb 14 14:01:17 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * time.c (search_time_t): support non 32bit time_t environments.
+
+ * win32/Makefile.sub (config.h): VC++8 has ``long long'' type.
+
+ * win32/Makefile.sub (config.h): VC++8's time_t is 64bit value.
+
+ * win32/win32.c (rb_w32_utime): drop read-only attribute before
+ changing file time.
+
+ all changes are backported from CVS HEAD.
+
+Tue Feb 14 11:21:38 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (argf_forward): should not use frame->argv.
+ [ruby-core:07358]
+
+Mon Feb 13 18:08:12 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call0): argument update propagation. [ruby-dev:28044]
+
+ * env.h: remove argv member from struct FRAME.
+
+Mon Feb 13 13:27:00 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (eval): should push class from binding if supplied.
+ [ruby-core:07347]
+
+Mon Feb 13 00:04:00 2006 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb (ERB::Compiler): add instance variable @insert_cmd to
+ change <%='s behavior. (backported 1.15 - 1.16)
+
+Sat Feb 11 02:04:11 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (eval): no need to push ruby_class. [ruby-dev:28176]
+
+Sat Feb 11 01:57:44 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_f_autoload): check if ruby_cbase is nil (during
+ instance_eval for objects cannot have singleton classes,
+ e.g. fixnums and symbols). [ruby-dev:28178]
+
+Tue Feb 7 23:03:24 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/zlib/zlib.c: should not access ruby objects in finalizer.
+ [ruby-dev:28286]
+
+Mon Feb 6 16:02:51 2006 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * file.c (rb_thread_flock): ERROR_NOT_LOCKED is not an error on Cygwin.
+ In such situation, flock() should return 0.
+
+Mon Feb 6 00:41:08 2006 Tanaka Akira <akr@m17n.org>
+
+ * ruby.h (RSTRUCT_LEN, RSTRUCT_PTR): defined for source level
+ compatibility with ruby 1.9.
+
+Sun Feb 5 21:05:34 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * numeric.c (fix_to_s): removed workaround for radix 2. Historically,
+ rb_fix2str could only handle radix 8, 10, 16. (Rev1.37) But for now,
+ it can handle radix 2..36. [ruby-Bugs#3438] [ruby-core:7300]
+
+Sun Feb 5 18:55:08 2006 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/http.rb: imported from trunk, rev 1.129
+
+ * lib/net/http.rb (add_field, get_fields): keep 1.8.2 backward
+ compatibility.
+
+ * lib/net/https.rb: imported from trunk, rev 1.3.
+
+ * lib/net/https.rb: #use_ssl? definition moved from net/http.rb.
+
+Sun Feb 5 14:22:15 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/pstore.rb: should return default value if name is not found.
+ [ruby-core:7304]
+
+ * lib/pstore.rb: should raise PStore::Error if not in transaction.
+
+Sat Feb 4 22:51:43 2006 Tanaka Akira <akr@m17n.org>
+
+ * eval.c: apply the FreeBSD getcontext/setcontext workaround
+ only before FreeBSD 7-CURRENT.
+
+Sat Feb 4 21:19:23 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (LK_ERR): ERROR_NOT_LOCKED is not an error.
+ In such situation, flock() should return 0.
+
+Sat Feb 4 15:56:37 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * numeric.c (fix_to_s): (2**32).to_s(2) fails with exception where
+ sizeof(int) == 4 < sizeof(long). [ruby-core:7300]
+
+Fri Feb 3 15:06:50 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/syck/syck.c (syck_move_tokens): should reset p->cursor or etc
+ even if skip == 0. This causes buffer overrun.
+ (ex: YAML.load('--- "..' + '\x82\xA0' * 511 + '"'))
+
+Thu Feb 2 23:51:18 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/syck/emitter.c (syck_emitter_write): should not set '\0' on
+ emitter's marker. if marker points to the end of buffer, this causes
+ buffer overrun. (ex: YAML.dump("." * 12288))
+
+Thu Feb 2 16:01:24 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (eval): need not to protect $SAFE value.
+ [ruby-core:07177]
+
+Thu Feb 2 14:45:53 2006 Ville Mattila <ville.mattila@stonesoft.com>
+
+ * configure.in: The isinf is not regognized by autoconf
+ library guesser on solaris 10. [ruby-core:7138]
+
+Wed Feb 1 22:01:47 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * configure.in, hash.c (ruby_setenv): use setenv(3) and unsetenv(3)
+ where they are supported. modifing environ variable seems to
+ segfault solaris 10. [ruby-core:7276] [ruby-dev:28270]
+
+ * ruby.c (set_arg0): if use setenv(3), environ space cannot be used
+ for altering argv[0].
+
+Tue Jan 31 14:46:28 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (rb_struct_select): update RDoc description.
+ [ruby-core:7254]
+
+Tue Jan 31 11:58:51 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: add MultiTkIp#eval and bg_eval.
+
+ * ext/tk/lib/tk/namespace.rb: TkNamespace#eval was enbugged at the
+ last commit. Now it will return a proper object.
+
+Tue Jan 31 00:10:26 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/syck/rubyext.c (syck_resolver_transfer): workaround for SEGV.
+ ex: ruby -ryaml -e 'YAML.load("!map:B {}")' [ruby-core:7217]
+
+Sat Jan 28 07:56:57 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/rdoc/usage.rb: support "a:0:33" style caller[-1]. In this case
+ file name is "a:0". I don't know this really happens though...
+ [ruby-Bugs:3344]
+
+Wed Jan 25 22:29:04 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in, dln.c, file.c, intern.h, missing.h (eaccess): use
+ system routine if provided. fixed: [ruby-core:07195]
+
+Sun Jan 22 23:27:13 2006 Go Noguchi <gonoguti@yahoo.co.jp>
+
+ * lib/test/unit/autorunner.rb (process_args): ignore arguments after
+ '--' so that test scripts can handle them. fixed: [ruby-dev:28258]
+
+Sun Jan 22 22:09:52 2006 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (POST_GETCONTEXT): define separately from PRE_GETCONTEXT on
+ IA64 to avoid reusing variable address.
+
+Sun Jan 22 20:03:35 2006 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (ruby_setjmp): define PRE_GETCONTEXT and POST_GETCONTEXT
+ instead of FUNCTION_CALL_MAY_RETURN_TWICE.
+ define PRE_GETCONTEXT to clear carry flag for workaround of
+ FreeBSD/i386 getcontext/setcontext bug.
+ [ruby-dev:28263]
+
+Sat Jan 21 00:36:47 2006 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (FUNCTION_CALL_MAY_RETURN_TWICE): use only on SPARC and IA64
+ before gcc 4.0.3.
+ [ruby-dev:28247]
+
+Thu Jan 19 22:21:23 2006 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (mv): should remove file after copying.
+ [ruby-dev:28223]
+
+Wed Jan 18 23:37:06 2006 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (FUNCTION_CALL_MAY_RETURN_TWICE): don't clobber %l7 of SPARC
+ if enable-shared.
+ (ruby_setjmp): call FUNCTION_CALL_MAY_RETURN_TWICE after getcontext
+ too.
+ reported by Pav Lucistnik and Marius Strobl.
+ http://lists.freebsd.org/pipermail/freebsd-sparc64/2006-January/003739.html
+
+Tue Jan 17 11:32:46 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/setup.mak (MAKE): workaround for nmake 8.
+
+Tue Jan 17 11:10:21 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/{Makefile.sub,setup.mak}: invoke .bat via shell. workaround
+ for nmake 8.
+
+Mon Jan 16 10:26:23 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/syck/emitter.c (syck_emit_seq, syck_emit_map, syck_emit_item):
+ should output complex key mark even if map's key is empty seq/map.
+ [ruby-core:7129]
+
+Sat Jan 14 05:37:06 2006 Tanaka Akira <akr@m17n.org>
+
+ * io.c (READ_DATA_PENDING, READ_DATA_PENDING_COUNT): defined
+ for DragonFly BSD 1.4.0.
+
+Sat Jan 14 03:43:24 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * file.c (rb_file_s_chmod): avoid warning where sizeof(int) !=
+ sizeof(void*).
+
+Fri Jan 13 19:14:56 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/rdoc/diagram.rb:
+ - properly quote bare element attributes
+ - terminates dangling elements (e.g. <img>, <br>, <link>, etc)
+ - converts "CVS" to the more HTML-friendly acronym element
+ - adds missing type attributes to style elements
+
+ based on Paul Duncan's patch <pabs@pablotron.org> [ruby-core:7028]
+
+ * lib/rdoc/generators/html_generator.rb: ditto.
+ * lib/rdoc/generators/template/html/hefss.rb: ditto.
+ * lib/rdoc/generators/template/html/html.rb: ditto.
+ * lib/rdoc/generators/template/html/kilmer.rb: ditto.
+
+Thu Jan 12 11:53:08 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/tkballoonhelp.rb: [bug fix] couldn't add to a widget
+ which is constructed with TkComposite module.
+ [new feature] support 'command' option which is called just before
+ popping up the balloon help.
+
+Wed Jan 11 15:00:00 2006 Ville Mattila <mulperi@iki.fi>
+
+ * io.c (READ_PENDING*): Support solaris 64-bit environments.
+ Solaris defines a opaque FILE struct when compiling 64 bit
+ binaries. This means that we dont have access to _ptr etc.
+ members anymore. The solution by Steven Lumos is to define
+ FILE64 that has needed members available. I've modified
+ the origanal patch a bit so that it compiles both with gcc
+ and now free sun studio 11 compiler and both amd64 and sparc.
+ NOTE! We have to 64 bit solaris FILE structure time to time
+ otherwise we'll get breakage.
+ [ruby-core:7106]
+
+Tue Jan 10 19:42:33 2006 Tanaka Akira <akr@m17n.org>
+
+ * gc.c (garbage_collect): mark ruby_current_node.
+ if an exception is raised in a finalizer called written in C by
+ rb_gc_call_finalizer_at_exit, ruby_set_current_source may use
+ collected ruby_current_node and mark_source_filename may corrupt
+ memory.
+
+Tue Jan 10 13:30:34 2006 akira yamada <akira@ruby-lang.org>
+
+ * ext/syck/rubyext.c (syck_resolver_transfer): should be able to load
+ !ruby/object:Bignum syntax 1.8.3 dumped. [ruby-core:6159]
+
+Tue Jan 10 12:47:41 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/yaml/rubytypes.rb (Fixnum): Bignum could not be loaded in
+ ruby 1.8.3/1.8.4. [ruby-core:6115]
+
+ * lib/yaml/rubytypes.rb (Numeric): Subclass of Numeric could not
+ be dumped properly. [ruby-core:7047]
+
+Tue Jan 10 12:00:48 2006 Aaron Schrab <aaron @nospam@ schrab.com>
+
+ * lib/yaml/rubytypes.rb (Symbol#yaml_new): YAML loading of quoted
+ Symbols broken. [ruby-Bugs:2535]
+
+Mon Jan 9 19:54:35 2006 arton <artonx@yahoo.co.jp>
+
+ * ext/zlib/extconf.rb: zlib compiled DLL version 1.2.3 distributed by
+ http://www.zlib.net/ has zdll.lib. [ruby-dev:28209]
+
+Mon Jan 9 14:17:12 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/Makefile.sub (OPTFLAGS): I have experienced trouble on y- flag,
+ (VisualC++6) so use -O2b2xg- if $(MSC_VER) < 1400. [ruby-core:7040]
+
+Mon Jan 9 14:17:12 2006 Kero van Gelder <rubyforge @nospam@ kero.tmfweb.nl>
+
+ * lib/webrick/httpservlet/filehandler.rb: fixed typo. [ruby-core:7075]
+
+Sat Jan 7 15:40:07 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (singleton): get rid of segfault on syntax error.
+ fixed: [ruby-core:07070]
+
+Fri Jan 6 10:16:20 2006 Steven Lumos <steven@lumos.us>
+
+ * io.c (READ_DATA_PENDING): defined for 64bit Solaris on SPARC.
+ [ruby-core:7057]
+ (READ_DATA_PENDING_COUNT): ditto.
+ (READ_DATA_PENDING_PTR): ditto.
+
+Sun Jan 1 17:07:59 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.c (rb_w32_seekdir): should not segfault even if passed
+ the location which rb_w32_telldir didn't return. [ruby-core:7035]
+ (I think HEAD implementation is better. but binary compatibility)
+
+ * test/ruby/test_dir.rb: added.
+
+Sat Dec 31 22:57:00 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_save_context): should not recycle scope object used
+ in a thread. fixed: [ruby-dev:28177]
+
+Fri Dec 30 18:22:42 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (garbage_collect): mark objects refered from aborting threads.
+ [ruby-dev:28190]
+
+ * win32/Makefile.sub: VC++8 support.
+
+Fri Dec 30 14:24:53 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dir.c (glob_helper): do not use TRUE for djgpp.
+
+Fri Dec 30 04:54:40 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (eaccess): workaround for VC++8 runtime.
+
+ * win32/win32.c (ioinfo): VC++8 support.
+
+Thu Dec 29 23:59:37 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_gc_mark_threads): leave unmarked threads which won't wake
+ up alone, and mark threads in the loading table. [ruby-dev:28154]
+
+ * eval.c (rb_gc_abort_threads), gc.c (gc_sweep): kill unmarked
+ threads. [ruby-dev:28172]
+
+Thu Dec 29 17:02:07 2005 Tanaka Akira <akr@m17n.org>
+
+ * test/ruby/envutil.rb (EnvUtil.rubybin): search "ruby" instead of
+ "miniruby". [ruby-dev:28140]
+
+Tue Dec 27 16:59:52 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/drb/drbtest.rb (DRbService::self.ext_service): increase
+ timeout limit. a patch from Kazuhiro NISHIYAMA
+ <zn at mbf.nifty.com>. [ruby-dev:28132]
+
+Tue Dec 27 08:29:18 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/lib/openssl/ssl.rb (OpenSSL::SSL::SSLSocket#post_connection_chech):
+ treat wildcard character in commonName. [ruby-dev:28121]
+
+Mon Dec 26 22:32:47 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_eval), gc.c (gc_mark_children), node.h (NEW_ALIAS,
+ NEW_VALIAS), parse.y (fitem): allow dynamic symbols to
+ NODE_UNDEF and NODE_ALIAS.
+ backported from trunk. fixed: [ruby-dev:28105]
+
+Mon Dec 26 08:50:36 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ev_const_get): fixed a bug in constant reference during
+ instance_eval. [yarv-dev:707]
+
+ * eval.c (ev_const_defined): ditto.
+
+ * lib/yaml.rb (YAML::add_domain_type): typo fixed. a patch from
+ Joel VanderWerf <vjoel at path.berkeley.edu>.
+ [ruby-talk:165285] [ruby-core:6995]
+
+Sat Dec 24 18:58:14 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.8.4 released.
+
+Fri Dec 23 10:30:23 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/digest/sha2/sha2.c (ULL): support AIX C. a patch from
+ Kailden <kailden at gmail.com>. [ruby-core:06984]
+
+Wed Dec 21 16:53:06 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * file.c (w32_io_info): should return handle because FileIndex is
+ valid only while file is open. [ruby-dev:28088]
+
+Wed Dec 21 14:53:26 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb (test_kernel_open): use File.identical?.
+ [ruby-talk:171804]
+
+Tue Dec 20 22:41:17 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (eval_under_i): evaluate source in caller's frame.
+ [ruby-dev:28076]
+
+ * eval.c (rb_call_super): use original method name on exception.
+ [ruby-dev:28078]
+
+Tue Dec 20 13:11:59 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/syck/rubyext.c: fixed GC problem (backported HEAD 1.55 - 1.62)
+ [ruby-dev:27839]
+
+ * ext/syck/syck.h (S_FREE): small hack. no need to check if pointer is
+ NULL or not before S_FREE.
+
+ * st.c: uses malloc instead of xmalloc to avoid GC. syck uses st_insert
+ in gram.c to insert node from rb_syck_bad_anchor_handler into
+ SyckParser's hash table. if GC occurs in st_insert, it's not under
+ SyckParser's mark system yet. so RString can be released wrongly.
+ [ruby-dev:28057]
+
+Tue Dec 20 12:53:23 2005 why the lucky stiff <why@ruby-lang.org>
+
+ * ext/syck/rubyext.c (syck_emitter_reset): to ensure compatibility
+ with previous Ruby versions, documents are no longer headless.
+
+Tue Dec 20 01:46:48 2005 Tanaka Akira <akr@m17n.org>
+
+ * io.c (rb_f_backquote): fix a GC problem on
+ IA64 with gcc 4.0.3 20051216 (prerelease) -O3.
+
+Mon Dec 19 23:32:39 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (rb_symname_p): fixed wrong validation. [ruby-dev:28047]
+
+Sat Dec 17 03:57:01 2005 Tanaka Akira <akr@m17n.org>
+
+ * bignum.c (rb_big_rshift): fix a GC problem on
+ IA64 with gcc 4.0.3 20051216 (prerelease).
+
+Sat Dec 17 03:30:23 2005 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (bmcall): fix a GC problem by tail call on
+ IA64 with gcc 4.0.3 20051216 (prerelease).
+
+Fri Dec 16 00:54:06 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * signal.c (Init_signal): revert C++ style comment.
+ [ruby-dev:28041]
+
+Thu Dec 15 12:35:14 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/tmpdir.rb: merged RDoc patch from Eric Hodel <drbrain at
+ segment7.net>. [ruby-core:06894]
+
+Thu Dec 15 01:33:31 2005 Tanaka Akira <akr@m17n.org>
+
+ * ext/zlib/zlib.c (zstream_run): fix a GC problem by tail call on
+ x86_64 with gcc 4.0.3 20051111 (prerelease) (Debian 4.0.2-4)
+
+Wed Dec 14 12:11:46 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * test/gdbm/test_gdbm.rb: specify pid for the argument of
+ Process.wait. workaround for Cygwin.
+
+Wed Dec 14 12:01:26 2005 Tanaka Akira <akr@m17n.org>
+
+ * marshal.c (r_object0): fix a GC problem for reading a bignum on
+ IA64 with gcc 3.3.5 (Debian 1:3.3.5-13).
+
+Tue Dec 13 12:23:47 2005 Tanaka Akira <akr@m17n.org>
+
+ * re.c (rb_reg_regcomp): fix a GC problem on x86_64 with
+ gcc 3.3.5 (Debian 1:3.3.5-13).
+
+Tue Dec 13 01:44:16 2005 Tanaka Akira <akr@m17n.org>
+
+ * array.c (rb_ary_diff): fix a GC problem on IA64 with
+ gcc 3.3.5 (Debian 1:3.3.5-13).
+ When rb_ary_push is called, there was no register which contains
+ `hash' but `&RHASH(hash)->tbl' instead.
+
+Tue Dec 13 00:08:09 2005 Tanaka Akira <akr@m17n.org>
+
+ * sprintf.c (rb_str_format): fix a GC problem.
+ [ruby-dev:28001]
+
+Mon Dec 12 15:54:56 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * test/openssl/test_ssl.rb (test_parallel): call GC.start to close
+ unused files. [ruby-dev:27981]
+
+Mon Dec 12 00:33:56 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/digest/digest.c (rb_digest_base_s_digest): add volatile to
+ protect temporary context object. [ruby-dev:27979]
+
+ * ext/iconv/iconv.c (Init_iconv): rb_gc_register_address() should
+ be called before actual variable initialization.
+ [ruby-dev:27986]
+
+Fri Dec 9 23:31:02 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rexml/encoding.rb (encoding=): give priority to particular
+ conversion to iconv. [ruby-core:06520]
+
+Thu Dec 8 02:07:19 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (umethod_bind): adjust invoking class for module method.
+ [ruby-dev:27964]
+
+Thu Dec 8 00:40:52 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (call_trace_func): klass parameter should be a
+ class/module that defines calling method. [ruby-talk:169307]
+
+Wed Dec 7 17:10:27 2005 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * sprintf.c (rb_f_sprintf): [ruby-dev:27967]
+
+Wed Dec 7 15:31:35 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_str_format): integer overflow check added.
+
+ * sprintf.c (GETASTER): ditto.
+
+Wed Dec 7 01:02:04 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/README.macosx-aqua: [new document] tips to avoid the known
+ bug on platform specific dialogs of Tcl/Tk Aqua on MacOS X.
+
+ * ext/tk/tcltklib.c: fix bug on switching threads and waiting on the
+ deleted interpreter on vwait and tkwait command.
+
+ * ext/tk/lib/multi-tk.rb: kill the meaningless loop for the deleted Tk
+ interpreter.
+
+ * ext/tk/sample/demos-jp/image3.rb: [bug fix] wrong argument.
+
+ * ext/tk/sample/demos-en/image3.rb: ditto.
+
+ * ext/tk/sample/demos-jp/menu.rb: fix message for MacOS X.
+
+ * ext/tk/sample/demos-jp/menu8x.rb: ditto.
+
+ * ext/tk/sample/demos-en/menu.rb: ditto.
+
+Tue Dec 6 16:37:57 2005 Yuya Nishida <yuya@j96.org>
+
+ * eval.c (exec_under): avoid accessing ruby_frame->prev.
+ [ruby-dev:27948]
+
+Thu Dec 1 00:50:33 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_funcall2): allow to call protected methods.
+ fixed: [ruby-dev:27890]
+
+Wed Nov 30 23:52:17 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (NEWHEAP, ADD2HEAP): set count after pointer was set.
+ fixed: [ruby-dev:27896]
+
+Wed Nov 30 13:43:07 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-expr-beg): support $! at the end of
+ expression. [ruby-dev:27868]
+
+Mon Nov 28 18:55:43 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/socket/socket.c (init_inetsock_internal): remove setting
+ SO_REUSEADDR option on server socket on Cygwin.
+ fixed: [ruby-core:6765] ([ ruby-Bugs-2872 ])
+
+Mon Nov 28 13:08:54 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.c (rb_w32_strerror): remove all CR and LF. (avoid broken
+ error message on bccwin32 + winsock)
+
+Mon Nov 28 09:21:49 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/mkmf.rb (create_makefile): should not change sodir with
+ dir.gsub!. (bccwin32 failed to install third party exntesions)
+ [ruby-dev:27834]
+
+Sun Nov 27 00:56:13 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/wsdl/xmlSchema/complexContent.rb: missing
+ ComplexContent#elementformdefault method.
+
+Sat Nov 26 19:57:45 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dln.c (conv_to_posix_path): should initialize posix.
+
+Thu Nov 24 21:05:58 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * configure.in (AC_CHECK_FUNCS): need to check link().
+ fixed: [ruby-dev:27814]
+
+Thu Nov 24 01:22:25 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * file.c (w32_io_info): CreateFile failed on Win9x if file was already
+ opened. (FILE_SHARE_READ was needed, but actually I don't understand
+ the flags of CreateFile well...)
+
+Wed Nov 23 20:59:01 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: add Tk.pkgconfig_list and Tk.pkgconfig_get
+ [Tk8.5 feature].
+
+ * ext/tk/lib/tk/text.rb: supports new indices modifires on a Text
+ widget [Tk8.5 feature].
+
+ * ext/tk/lib/tk/virtevent.rb: add TkNamedVirtualEvent.
+
+ * ext/tk/lib/tk/autoload.rb: ditto.
+
+ * ext/tk/lib/tk/event.rb: add :data key for virtual events [Tk8.5
+ feature].
+
+Wed Nov 23 18:55:31 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * file.c (w32_io_info): should not call GetFileInformationByHandle
+ for pipe.
+
+ * file.c (w32_io_info): checks return value from rb_w32_get_osfhandle.
+
+ * file.c (w32_io_info): now can identify directory on WinNT.
+
+Wed Nov 23 03:40:49 2005 Guy Decoux <ts@moulon.inra.fr>
+
+ * re.c (KR_REHASH): should cast to unsigned for 64bit CPU.
+ [ruby-core:06721]
+
+Wed Nov 23 11:01:33 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * intern.h, file.c: failed to compile on windows.
+
+Wed Nov 23 07:26:44 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/extconf.rb: check for X509V3_EXT_nconf_nid.
+
+ * ext/openssl/ossl_x509ext.c (MakeX509ExtFactory): should use
+ OPENSSL_malloc to allocate X509V3_CTX.
+
+ * ext/openssl/ossl_x509ext.c (ossl_x509extfactory_create_ext): use
+ X509V3_EXT_nconf_nid to avoid SEGV (and to build extensions which
+ values are placed in separate section).
+
+ * test/openssl/test_x509ext.rb: new file.
+
+Wed Nov 23 01:22:57 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (test_identical): test if two files are identical.
+
+ * file.c (rb_f_test): support DOSISH systems where st_ino is not
+ reliable. fixed: [ruby-core:06672]
+
+ * win32.h, win32.c (rb_w32_osid): check the running platform.
+
+Tue Nov 22 23:52:06 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb: match incomplete (in current enconding) multibyte
+ string. http://inamode6.tokuhirom.dnsalias.org/show/1551
+
+Tue Nov 22 18:36:11 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.c (winnt_stat): set mapped errno instead of ENOENT.
+
+Tue Nov 22 14:46:57 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (rb_file_s_basename): skip slashes just after UNC top slashes.
+
+ * test/ruby/test_path.rb (test_dirname, test_basename): follow new
+ spec. and add new tests.
+
+Tue Nov 22 13:18:32 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.c (rb_w32_stat): Dir.chdir('//server/shared');
+ p Dir.glob('*') should work on WinNT. (implemented our own
+ stat(2) on WinNT) [ruby-list:41552] [ruby-dev:27711]
+
+Tue Nov 22 02:31:53 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tile.rb: bug fix (Tk::Tile::USE_TTK_NAMESPACE
+ is not defined).
+
+Tue Nov 22 01:45:21 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_basename): DOSISH_UNC is defined on cygwin but
+ DOSISH is not. fixed: [ruby-dev:27797]
+
+Mon Nov 21 22:50:48 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_path_skip_prefix, rb_file_s_basename): UNC without path
+ should not be splitted. fixed: [ruby-dev:27776] [ruby-dev:27786]
+
+ * parse.y (dsym): prohibit empty symbol literal by interpolation.
+ fixed: [ruby-talk:166529]
+
+Mon Nov 21 16:03:48 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/setup.mk: findstr doesn't exist on win9x.
+ fixed: [ruby-dev:27756]
+
+Sun Nov 20 22:34:06 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (rb_symname_p): [ not followed by ] is not valid symbol.
+ fixed: [ruby-talk:166520]
+
+Sat Nov 19 19:57:54 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/fileutils.rb (FileUtils::ln): ln documentation fix.
+ [ruby-core:06661]
+
+Sat Nov 19 07:34:32 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/font.rb: remove dependency on Ruby's version (1.8
+ or 1.9).
+
+ * ext/tk/lib/tkextlib/ICONS/icons.rb: ditto.
+
+ * ext/tk/sample/tkextlib/treectrl/demo.rb: ditto.
+
+Fri Nov 18 17:57:08 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (rb_file_s_dirname): should use skipprefix for UNC path.
+ pointed out by nobu ([ruby-dev:27744]). fixed: [ruby-core:5076]
+
+Fri Nov 18 17:35:09 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: add restriction to access the entried
+ command table and manipulate other IPs (for reason of security).
+ Now, a IP object can be controlled by only its master IP or the
+ default IP.
+
+ * ext/tk/lib/remote-tk.rb: add restriction to manipulate.
+
+ * ext/tk/tcltklib.c (ip_is_slave_of_p): add TclTkIp#slave_of?(ip)
+ to check manipulability.
+
+ * ext/tk/lib/tk.rb: bug fix on handling of Tcl's namespaces.
+
+ * ext/tk/lib/tk/namespace.rb: ditto.
+
+Fri Nov 18 17:26:06 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (rb_file_s_dirname): added checks for some patterns with drive
+ letter. fixed: [ruby-dev:27738]
+
+ * test/ruby/test_path.rb (test_dirname): added tests for above
+ patterns.
+
+Fri Nov 18 12:18:02 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.h (S_IFIFO): r,w = IO.pipe; r.stat.pipe? now
+ returns true on VisualC++6.
+
+Wed Nov 16 23:24:17 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (static-ruby): overridable.
+
+ * ext/extmk.rb (parse_args): force to link extensions statically only
+ if static is given for extstatic.
+
+ * ext/extmk.rb (RUBY, RUBYW): overridable.
+
+Tue Nov 15 23:46:35 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/find.rb (Find::find): should not ignore symbolic links to
+ non-existing files. [ruby-talk:165866]
+
+Tue Nov 15 16:23:26 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * array.c (rb_ary_fill): previous commit disabled this usage:
+
+ a = [0,1,2,3,4,5,6,7,8,9]
+ a.fill {|i| a[i] * 10} #=> [nil, nil, ...., nil]
+
+ previous commit has the advantage of early garbage collection, but
+ potensially this would break some script. so I reverted behavior.
+
+Tue Nov 15 16:04:10 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * array.c (rb_ary_fill): tail elements were vanished when the middle
+ part of array was filled. (ie: [0,1,2,3,4].fill(-1,2,1) => [0,1,-1])
+
+ * test/ruby/test_array.rb (test_fill): added.
+
+Tue Nov 15 14:39:16 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_fill): should adjust array length correctly when
+ an array is expanded in the fill process. [ruby-core:06625]
+
+Mon Nov 14 23:49:57 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_readlink): ERANGE will occur only on GPFS.
+ [ruby-dev:27699]
+
+Mon Nov 14 17:36:22 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_first): RDoc update from Daniel Berger
+ <djberg96@yahoo.com>. [ruby-core:06577].
+
+Fri Nov 11 10:31:44 2005 Zach Dennis <zdennis@mktec.com>
+
+ * ext/socket/socket.c: Socket Documentation. [ruby-core:6552]
+
+Fri Nov 11 08:20:56 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in (OUTFLAG): keep trailing spaces. [ruby-dev:27666]
+
+ * mkconfig.rb: substitution refereces added.
+
+Fri Nov 11 07:44:18 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * configure.in: undef HAVE_LINK on BeOS. (link(2) always returns
+ EINVAL, and this causes error in test/fileutils.)
+
+ * file.c: overwride chown(2) and fchown(2) on BeOS. (these functions
+ should not change user/group id if -1 is passed as corresponding
+ argument, and this causes error in test/fileutils too)
+ [ruby-dev:27672]
+
+ * file.c (rb_file_s_link): checks HAVE_LINK.
+
+Tue Nov 8 15:32:27 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/drb/ssl.rb (DRb::SSLConfig#accept): fixed typo.
+ [ruby-dev:27560] [ruby-core:4627]
+
+Mon Nov 7 13:43:51 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/stubs.c (_nativethread_consistency_check): use simpler
+ (low cost) way to check whether the Tcl interpreter was compiled
+ with threads enabled of not.
+
+ * ext/tk/tcltklib.c: reduce warnings.
+
+ * ext/tk/tkutil/tkutil.c: ditto.
+
+Mon Nov 7 00:06:58 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/yaml.rb: removed :nodoc: to generate Kernel doc. [ruby-core:6324]
+
+Sun Nov 6 23:39:13 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (Iconv::BrokenLibrary): exception when detected a
+ bug of underlying library.
+
+Sun Nov 6 21:46:59 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tk/stubs.c (ruby_tcl_create_ip_and_stubs_init): should touch
+ interpreter after initialization is done. [ruby-dev:27638]
+
+Sun Nov 6 20:13:27 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_readlink): readlink(2) on AIX fails with ERANGE if
+ buffer size is less than required. fixed: [ruby-dev:27634]
+
+Wed Nov 2 20:25:28 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/extconf.rb: ext/tk/extconf.rb: change the check parameter
+ for Win32.
+
+Wed Nov 2 20:14:53 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib: merge into ext/tk and remove.
+
+Wed Nov 2 19:03:06 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_rbUpdateObjCmd,
+ ip_rb_threadUpdateObjCmd): passed improper flags to DoOneEvent().
+
+ * ext/tk/tkutil.c: use rb_obj_respond_to() instead of rb_respond_to().
+
+Tue Nov 1 14:20:11 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call_super): should call method_missing if super is
+ called from Kernel method.
+
+ * eval.c (exec_under): frame during eval should preserve external
+ information.
+
+Tue Nov 1 10:50:17 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/extconf.rb: should check ERR_peek_last_error().
+ [ruby-dev:27597]
+
+ * ext/openssl/ossl.c (ossl_raise): ditto.
+
+Mon Oct 31 17:34:46 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in: use proper option for Sun linker. A patch from
+ Shinya Kuwamura <kuwa at labs.fujitsu.com>. [ruby-dev:27603]
+
+Mon Oct 31 11:27:22 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/gdbm/test_gdbm.rb, test/sdbm/test_sdbm.rb (test_s_open_error):
+ skip on Win32/DOS platforms.
+
+Mon Oct 31 05:49:23 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_cipher.c (ossl_cipher_update): input data must
+ not be empty. [ruby-talk:161220]
+
+ * test/openssl/test_cipher.rb: add test for Cipher#update("").
+
+Mon Oct 31 05:37:20 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpservlet/cgihandler.rb
+ (WEBrick::HTTPServlet::CGIHandler#do_GET): the value of Set-Cookie:
+ header field should be splited into each cookie. [ruby-Bugs:2199]
+
+ * lib/webrick/cookie.rb (WEBrick::Cookie.parse_set_cookie): new method
+ to parse the value of Set-Cookie: header field.
+
+ * test/webrick/test_cookie.rb, test/webrick/test_cgi.rb,
+ test/webrick/webrick.cgi: add some test for cookie.
+
+Mon Oct 31 03:19:36 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/readline/readline.c (readline_readline): type check.
+ [ruby-core:6089]
+
+ * numeric.c (fix_rshift): RDoc fix. [ruby-core:6351]
+
+ * util.h (strtod): add #undef for platforms defines strtod()
+ macro. [ruby-dev:27563]
+
+Mon Oct 31 02:35:59 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * test/ruby/test_float.rb (test_precision): test by assert_in_delta.
+ [ruby-dev:27575]
+
+Sat Oct 29 01:58:25 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/etc/etc.c: document update from mathew <meta@pobox.com>.
+ [ruby-core:06473]
+
+ * ext/fcntl/fcntl.c: ditto.
+
+Thu Oct 27 16:45:31 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (scan_once): wrong condition to use mbclen2().
+ [ruby-dev:27535]
+
+Wed Oct 26 09:27:27 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/syck/implicit.c (syck_type_id_to_uri): should return
+ newly allocated memory. otherwise, type_id will be freed
+ twice. [ruby-dev:27384] [ruby-core:6385]
+
+Wed Oct 26 09:04:51 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ruby.h (Qfalse, Qtrue, Qnil, Qundef): make sure these immediate
+ values have VALUE type. there is an environment where sizeof(VALUE)
+ != sizeof(int) like IA64. if 32bit integer (Qtrue) is passed to ANYARGS
+ and received by 64bit integer (VALUE), upper bits may have garbage value.
+ [ruby-dev:27513]
+
+Wed Oct 26 01:58:19 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_EXTERN): macro to export symbols in shared
+ library. [ruby-core:05528]
+
+ * defines.h, {bcc32,win32,wince}/Makefile.sub (RUBY_EXTERN): moved to
+ configuration pass.
+
+ * ext/extmk.rb (extmake): RUBY_EXTERN for static linked extensions.
+
+Tue Oct 25 15:32:00 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rational.rb: applied documentation patch from Gavin Sinclair
+ <gsinclair@gmail.com>. [ruby-core:06364]
+
+ * lib/irb.rb (IRB::Irb::eval_input): handle prompts with newlines
+ in irb auto-indentation mode. [ruby-core:06358]
+
+Tue Oct 25 02:12:08 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rdoc/markup/simple_markup.rb (SM::SimpleMarkup::LABEL_LIST_RE):
+ reduce redundant backtrack. [ruby-talk:161771]
+
+Tue Oct 25 00:27:35 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/*: RDoc documentation from Eric Hodel
+ <drbrain@segment7.net> added.
+
+Mon Oct 24 21:14:29 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in, io.c: use sys/syscall.h if syscall.h is not available.
+ [ruby-core:06247]
+
+Mon Oct 24 20:49:45 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/Win32API/lib/win32/resolv.rb (get_info): support multiple DNS.
+ fixed: [ruby-list:40058], [ruby-dev:27479]
+
+Mon Oct 24 07:57:56 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/tk/lib/tk/canvas.rb (TkCanvasItemConfig::__item_val2ruby_optkeys):
+ typo fixed. [ruby-talk:162187]
+
+ * ext/tk/lib/tk/menu.rb (TkMenuEntryConfig::__item_val2ruby_optkeys):
+ ditto. [ruby-core:06359]
+
+Sun Oct 23 21:50:15 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/enumerator/enumerator.c: applied documentation patch from
+ James Edward Gray II <james@grayproductions.net>.
+ [ruby-core:06348]
+
+Sun Oct 23 07:11:11 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/extconf.rb: improve messages [ruby-core:06325].
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/canvas.rb, ext/tk/lib/tk/entry.rb,
+ ext/tk/lib/tk/frame.rb, ext/tk/lib/tk/image.rb,
+ ext/tk/lib/tk/itemconfig.rb, ext/tk/lib/tk/labelframe.rb,
+ ext/tk/lib/tk/listbox.rb, ext/tk/lib/tk/menu.rb,
+ ext/tk/lib/tk/radiobutton.rb, ext/tk/lib/tk/scale.rb,
+ ext/tk/lib/tk/spinbox.rb, ext/tk/lib/tk/text.rb,
+ ext/tk/lib/tk/toplevel.rb: improve conversion of option values.
+
+ * ext/tk/lib/tkextlib/*: ditto.
+
+ * ext/tk/lib/tkextlib/*: update to support ActiveTcl8.4.11.2.
+
+ * ext/tk/lib/tkextlib/trofs/*: support Trofs 0.4.3.
+
+ * ext/tk/lib/tkextlib/tile/*: support Tile 0.7.2.
+
+ * ext/tk/lib/tkextlib/vu/*: support vu 2.3.0.
+
+ * ext/tk/lib/tkextlib/tcllib/*: support Tcllib 1.8 (Tklib 0.3).
+
+Sat Oct 22 23:54:07 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb, lib/mkmf.rb (with_config): support --with-extension
+ options. [ruby-dev:27449]
+
+Sat Oct 22 13:26:57 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (sym_inspect), parse.y (parser_yylex, rb_symname_p): check
+ if valid as a symbol name more strictly. [ruby-dev:27478]
+
+ * test/ruby/test_symbol.rb: tests for [ruby-core:03573].
+
+ * time.c (rb_strftime): removed meaningless volatile modifiers, and
+ concatenate successive nul characters at once. [ruby-dev:27472]
+
+Fri Oct 21 19:21:56 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * rubysig.h (CHECK_INTS): fixed typo. (I believe bit-or is improper)
+
+Fri Oct 21 17:49:32 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bin/erb (ERB::Main::run): typo fixed. [ruby-core:06337]
+
+Fri Oct 21 15:27:17 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bignum.c (bignew_1): convertion from `int' to `char' discards
+ upper bits, (ie. (char)0xff00 -> 0) so it's better to test if
+ nonzero and set 0 or 1 instead of simply casting ... as a flag usage.
+ (but I believe this won't cause actual bug in current implementation)
+ [ruby-dev:27055]
+
+ * time.c: should use LONG_LONG instead of `long long'.
+
+Thu Oct 20 09:37:15 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/mkmf.rb (create_makefile): Borland make seems not to allow
+ empty dependency list. If this change is not good, please correct
+ it.
+
+Thu Oct 20 07:55:09 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): get rid of a restriction
+ of Borland make. fixed: [ruby-dev:27460]
+
+Thu Oct 20 00:13:18 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * rubysig.h (CHECK_INTS): fix typo.
+
+Wed Oct 19 23:58:03 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): do not create unnecessary empty
+ directories. fixed: [ruby-dev:27451]
+
+Wed Oct 19 19:26:15 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (rb_gc_mark_parser): get rid of segfault with old yacc.
+ fixed: [ruby-dev:27439]
+
+Wed Oct 19 08:28:32 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_join): elements may contain null pointer strings.
+ report and fixed by Lloyd Zusman (hippoman): [ruby-core:06326]
+
+Wed Oct 19 02:34:33 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c, gc.c, time.c: made internal symbols static. [ruby-dev:27435]
+
+Wed Oct 19 01:27:07 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * regex.c (re_compile_pattern): numeric literal inside character class
+ disabled succeeding backtrack. fixed: [ruby-list:41328]
+
+Mon Oct 17 21:18:50 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (parser_heap): byacc never free parser stack.
+ fixed: [ruby-dev:27428]
+
+Mon Oct 17 16:04:47 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (chmod_internal, lchmod_internal): fixed type of 2nd argument.
+
+Sun Oct 16 22:16:51 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: omit non-existing directories.
+
+Sun Oct 16 14:30:05 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/rinda.rb (Rinda::Tuple#initialize): check remote hash
+ tuple. fixed: [ruby-list:41227]
+
+ * test/rinda/test_rinda.rb: test it.
+
+Sun Oct 16 03:38:07 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * rubysig.h (CHECK_INTS): prevent signal handler to run during
+ critical section. [ruby-core:04039]
+
+ * eval.c (load_wait): need not to call rb_thread_schedule()
+ explicitly. [ruby-core:04039]
+
+ * eval.c (rb_thread_schedule): clear rb_thread_critical.
+ [ruby-core:04039]
+
+Sat Oct 15 19:56:38 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * bin/erb: typo fixed, again. thanks, Doug Kearns.
+
+Fri Oct 14 22:08:26 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (ioctl): should set errno.
+
+Fri Oct 14 16:57:32 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/config.rb (Config::FileHandler): :UserDir should be nil.
+ It is harmful to permit the access to ~/public_html by default.
+ suggested by Hiroyuki Iwatsuki.
+
+Thu Oct 13 23:29:51 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (HEAPCNT): bison allocates indivisible size.
+ fixed: [ruby-core:06261]
+
+ * io.c, pack.c, ext/syck/rubyext.c, ext/syck/syck.h, missing/isinf.c:
+ get rid of warnings. fixed: [ruby-core:06247]
+
+Wed Oct 12 12:52:57 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl.c (Init_openssl): should call
+ OpenSSL_add_ssl_algorithms().
+
+Wed Oct 12 11:08:54 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * file.c (rb_f_test): typo in RDoc comments.
+
+Tue Oct 11 21:41:58 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_obj_respond_to): check if obj responds to the given
+ method with the given visibility. [ruby-dev:27408]
+
+ * eval.c (rb_respond_to): conform to Object#respond_to?. [ruby-dev:27411]
+
+Tue Oct 11 00:01:21 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * st.c (st_free_table): do not call free() but xfree().
+ [ruby-core:06205]
+
+Sat Oct 8 20:04:40 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (Init_Binding): add Binding#dup method. [yarv-dev:666]
+
+ * parse.y (rb_parser_malloc, rb_parser_free): manage parser stack on
+ heap. [ruby-list:41199]
+
+ * ext/iconv/charset_alias.rb: parse config.charset_alias file directly.
+
+Fri Oct 7 09:54:00 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::Cookie::parse): Cookies from Nokia devices may
+ not be parsed correctly. A patch from August Z. Flatby
+ (augustzf) in [ruby-Patches-2595]. [ruby-core:06183]
+
+Thu Oct 6 20:12:16 2005 Minero Aoki <aamine@loveruby.net>
+
+ * ext/strscan/strscan.c (strscan_free): remove useless code.
+ [ruby-dev:26368] [ruby-dev:27389]
+ (backported from trunk, rev 1.22)
+
+Wed Oct 5 04:42:38 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/xmlrpc/server.rb (XMLRPC::Server#initialize): should mount the
+ servlet on "/".
+
+Wed Oct 5 03:59:09 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/xmlrpc/server.rb (XMLRPC::Server#serve): delete wrong call
+ of "join".
+
+Mon Oct 3 00:04:00 2005 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * pack.c (EXTEND16): [ruby-dev:27383]
+
+Thu Sep 29 10:26:18 2005 Tanaka Akira <akr@m17n.org>
+
+ * ext/dl/dl.c (rb_io_to_ptr): abolish sizeof(FILE).
+ [ruby-dev:27317]
+
+Thu Sep 29 07:22:05 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * evalc. (rb_f_send): underscores need to be escaped.
+ fixed by Doug Kearns. [ruby-core:06053]
+
+Thu Sep 29 00:57:35 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ev_const_get), variable.c (rb_const_get_0): retry only when
+ autoload succeeded.
+
+ * variable.c (rb_autoload_load): now return true if autoload
+ succeeded. fixed: [ruby-dev:27331]
+
+Wed Sep 28 23:42:15 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (apply2files): add prototype.
+
+ * file.c (rb_stat_inspect): constified.
+
+ * class.c (rb_mod_init_copy, rb_class_init_copy), file.c (rb_stat_init_copy),
+ numeric.c (num_init_copy), object.c (rb_obj_init_copy, Init_Object),
+ re.c (match_init_copy, rb_reg_init_copy), time.c (time_init_copy):
+ undocumented.
+
+Wed Sep 28 23:09:23 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb: document update from James Edward Gray II
+ <james@grayproductions.net>. [ruby-core:06027]
+
+Wed Sep 28 15:14:19 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb (WEBrick::CGI#start): req.query_string should
+ refer the value of QUERY_STRING. [ruby-list:41186]
+
+ * lib/webrick/httprequest.rb (WEBrick::HTTPRequest#query_string=):
+ add new method.
+
+Wed Sep 28 10:45:44 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: cannot compile with Tcl/Tk8.0.x
+ [ruby-dev:27335].
+
+Wed Sep 28 08:12:18 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (read_buffered_data): check if reached EOF. fixed: [ruby-dev:27334]
+
+Wed Sep 28 07:56:52 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/yaml/basenode.rb (YAML::BaseNode::match_segment): fix typo.
+ [ruby-dev:27237], [ruby-core:05854]
+
+ * lib/yaml/tag.rb (Module#yaml_as): suppress warnings.
+
+ * lib/yaml/types.rb (YAML::PrivateType, YAML::DomainType): ditto.
+
+Wed Sep 28 03:23:35 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * rubysig.h: fixed build problem with --enable-pthread on platforms
+ which don't have setitimer().
+
+Mon Sep 26 22:32:13 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (set_trace_func): add rb_secure(4) to prevent adding
+ tracing function.
+
+Sun Sep 25 12:05:10 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * bin/erb: typo fixed.
+
+Sun Sep 25 01:46:43 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-calculate-indent): arrange deep-indent
+ closing parenthesis at same column as the opening.
+
+Sun Sep 25 00:42:11 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-expr-beg): deal with heredoc separately.
+ fixed: [ruby-list:41168]
+
+ * misc/ruby-mode.el (ruby-calculate-indent): not to deepen indent
+ level for continuous line inside parentheses.
+ http://nabeken.tdiary.net/20050915.html#p02
+
+Sun Sep 25 00:18:11 2005 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (unknown_node): show more information. [ruby-dev:26196]
+
+Sat Sep 24 08:56:01 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (cd): no longer accept :noop option, related
+ code is useless (backported from trunk, rev 1.67).
+ [ruby-core:05858] [ruby-Bugs:2494]
+
+Sat Sep 24 08:38:07 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb: fix visibility of FileUtils::NoWrite, Verbose,
+ DryRun (backported from trunk, rev 1.66). [ruby-core:05954]
+
+ * test/fileutils/test_nowrite.rb: test it.
+
+ * test/fileutils/test_dryrun.rb: new file.
+
+ * test/fileutils/test_verbose.rb: new file.
+
+Sat Sep 24 02:40:20 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb: document update from James Edward Gray II
+ <james@grayproductions.net>. [ruby-core:05942]
+
+Thu Sep 22 23:36:24 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (find_executable0): default path if environment is not
+ set. [ruby-dev:27281]
+
+Thu Sep 22 16:33:12 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * test/readline/test_readline.rb (TestReadline::replace_stdio):
+ merged the patch of [ruby-dev:25232] instead of [ruby-dev:25223].
+
+Wed Sep 21 23:30:44 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (configuration): generalized nmake dependent code.
+
+Wed Sep 21 09:07:55 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.8.3 released.
+
+Wed Sep 21 08:52:25 2005 why the lucky stiff <why@ruby-lang.org>
+
+ * ext/syck/token.c: correctly compute identation of a block
+ scalar's parent node. [ruby-talk:150620]
+
+Wed Sep 21 08:20:24 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * README.EXT, README.EXT.ja: add new features.
+
+Wed Sep 21 07:43:58 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (default_argv, Arguable#options): defaults strings
+ to be parsed to Arguable instance.
+
+Wed Sep 21 02:44:09 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * file.c (path_check_0): disallow sticky world writable directory
+ in PATH (and $LOAD_PATH). [ruby-dev:27226]
+
+ * file.c (fpath_check): typo fixed.
+
+Tue Sep 20 22:29:49 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/wsdl/simpletype/rpc/test_rpc.rb, test/wsdl/ref/test_ref.rb,
+ test/wsdl/any/test_any.rb test/soap/wsdlDriver/test_calc.rb:
+ suppress deliberate warnings with $VERBOSE = nil.
+
+Tue Sep 20 21:26:23 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/io/wait/lib/nonblock.rb: disable on platforms non-blocking flag
+ is not available. fixed: [ruby-dev:27187]
+
+Tue Sep 20 18:23:04 2005 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (thread_mark): mark th->last_status. [ruby-dev:27179]
+
+Tue Sep 20 18:20:33 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/yaml.rb: require 'yaml/constants'. [ruby-core:5776]
+
+Tue Sep 20 17:48:34 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/xmlrpc/client.rb (XMLRPC::Client::do_rpc): add charset
+ information to content-type header.[ruby-core:5127]
+
+ * lib/xmlrpc/server.rb (CGIServer::serve): ditto.
+
+ * lib/xmlrpc/server.rb (ModRubyServer::serve): ditto.
+
+ * lib/xmlrpc/server.rb (WEBrickServlet::service): ditto.
+
+Tue Sep 20 17:34:46 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * test/webrick/test_cgi.rb: set ENV["PATH"] to CGIEnvPath on
+ windows. bcc32's runtime is not installed into system directory,
+ so it cannot be found without this setting. [ruby-dev:27166]
+
+Tue Sep 20 17:10:38 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/dbm/test_dbm.rb (TestDBM::test_s_open_error): remove
+ test_s_open_error test to detect duplicate open.
+ [ruby-dev:27202]
+
+Tue Sep 20 17:08:31 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * io.c: PIPE_BUF is not defined on BeOS. use _POSIX_PIPE_BUF instead.
+ [ruby-dev:27185]
+
+Tue Sep 20 16:53:53 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/readline/test_readline.rb (TestReadline::replace_stdio):
+ BSD seek support from [ruby-dev:25223]. fixed: [ruby-dev:27150]
+
+Tue Sep 20 15:39:40 2005 why the lucky stiff <why@ruby-lang.org>
+
+ * ext/syck/emitter.c (syck_scan_scalar): prevent indicators from
+ appearing alone or at the end of plain scalars. [ruby-core:5826]
+
+ * ext/syck/emitter.c (syck_emit_scalar): treat typed scalar nodes
+ as complex keys.
+
+ * lib/syck.h: version 0.60.
+
+ * lib/yaml/basenode.rb (YAML::BaseNode#at): transform keys during
+ key searches.
+
+ * ext/syck/rubyext.c: loading of binary-typed nodes. prevent
+ emission of plain strings that look like symbols, but which aren't.
+
+Tue Sep 20 05:50:22 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * test/xmlrpc/test_webrick_server.rb (setup_http_server):
+ should not include 'webrick/https' unless 'use_ssl' because
+ it fails where openssl is not installed.
+
+Tue Sep 20 00:34:07 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_close): call rb_io_close() directly if io is a T_FILE
+ object. [ruby-dev:27156]
+
+Mon Sep 19 19:09:08 2005 Minero Aoki <aamine@loveruby.net>
+
+ * file.c (rb_file_chown): should accept nil. [ruby-dev:27171]
+ (backport from trunk, rev 1.208)
+
+Mon Sep 19 18:35:13 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dl/dl.c (rb_io_to_ptr): fix DragonFlyBSD support.
+ [ruby-dev:27151]
+
+Mon Sep 19 14:17:04 2005 Minero Aoki <aamine@loveruby.net>
+
+ * ext/syck/emitter.c (syck_emit): passing an int* value to the
+ long* parameter causes unaligned access on LP64 systems.
+ [ruby-dev:27161]
+
+Mon Sep 19 13:44:03 2005 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c: avoid core dump with WIN32OLE_EVENT.
+ [ruby-dev:27133]
+
+Mon Sep 19 10:36:06 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (cp_r): default is :dereference_root=>true for
+ backward compatibility. [ruby-dev:27145]
+
+ * test/fileutils/test_fileutils.rb (test_cp_r): test it.
+
+Mon Sep 19 09:57:39 2005 Minero Aoki <aamine@loveruby.net>
+
+ * test/fileutils/test_fileutils.rb: backported from trunk (1.36).
+ (again) [ruby-dev:27145]
+
+Mon Sep 19 07:45:37 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_pkey.h, ossl_pkey_rsa.c, ossl_pkey_dsa.c:
+ an instance variable "private" is added to OpenSSL::PKey class.
+ this ivar is a flag that shows whether there is a private key
+ in the instance.
+
+ * ext/openssl/ossl_engine.c: (ossl_engine_load_privkey): set private
+ key flag.
+
+Mon Sep 19 06:41:32 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb: backported from trunk (rev 1.65):
+
+ * lib/fileutils.rb (rm_r): new option :secure.
+
+ * lib/fileutils.rb (rm_rf): new option :secure.
+
+ * lib/fileutils.rb: new method #remove_entry_secure.
+
+ * lib/fileutils.rb (cd): remove option :noop.
+
+ * lib/fileutils.rb (cp_r): new option :dereference_root.
+
+ * lib/fileutils.rb (cp_r): new option :dereference_root.
+
+ * lib/fileutils.rb: new method #remove_entry.
+
+ * lib/fileutils.rb: new method #chmod_R.
+
+ * lib/fileutils.rb: new method #chown.
+
+ * lib/fileutils.rb: new method #chown_R.
+
+ * lib/fileutils.rb: new method .commands.
+
+ * lib/fileutils.rb: new method .options.
+
+ * lib/fileutils.rb: new method .have_option?.
+
+ * lib/fileutils.rb: new method .options_of.
+
+ * lib/fileutils.rb: new method .collect_method.
+
+ * lib/fileutils.rb: use module_function instead of single extend.
+
+ * test/fileutils/test_fileutils.rb: backported from trunk (1.36).
+
+Mon Sep 19 03:17:48 2005 Tanaka Akira <akr@m17n.org>
+
+ * file.c (rb_thread_flock): wrap the flock system call by
+ TRAP_BEG/TRAP_END to enable signals. [ruby-dev:27122]
+
+ * ext/socket/socket.c (bsock_send): wrap the sendto and send system
+ call by TRAP_BEG/TRAP_END to enable signals when writing to a socket
+ which is full. [ruby-dev:27132]
+
+ * io.c (rb_io_syswrite): wrap the write system call by
+ TRAP_BEG/TRAP_END to enable signals when writing to a pipe which is
+ full. [ruby-dev:27134]
+
+Mon Sep 19 03:02:08 2005 Tanaka Akira <akr@m17n.org>
+
+ * io.c (io_fwrite): wrap the write system call by TRAP_BEG/TRAP_END to
+ enable signals when writing to a pipe which is full.
+
+Sun Sep 18 02:10:47 2005 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/yaml/rubytypes.rb: remove comments that are bungling up
+ the rdoc and ri output. output symbols as plain scalars.
+
+ * ext/syck/rubyext.c (syck_emitter_reset): emit headless
+ documents always.
+
+ * ext/syck/emitter.c (syck_scan_scalar): quote scalars with any
+ kind of surrounding line space, tabs or spaces alike.
+
+ * ext/syck/token.c: accept tabs as whitespace, not for indentation,
+ but strip from plain scalars.
+
+ * test/yaml/test_yaml.rb: remove outdated tests.
+
+Sat Sep 17 23:25:04 2005 sheepman <sheepman@sheepman.sakura.ne.jp>
+
+ * lib/mathn.rb (Rational::inspect): should preserve original
+ operand. [ruby-core:05806]
+
+Sat Sep 17 23:20:27 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::Cookie): should handle multiple values for a
+ cookie name. [ruby-talk:156140]
+
+Sat Sep 17 10:42:13 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: MultiTkIp#eval_string and bg_eval_string
+ should call Kernel.eval on caller's safe-level instead of slave's
+ safe-level (Of course, the given script should be evaluated on
+ slave's safe-level).
+
+Sat Sep 17 09:45:26 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_substr): should propagate taintness even for
+ empty strings. [ruby-dev:27121]
+
+ * string.c (rb_str_aref): should infect result if range argument
+ is tainted. [ruby-dev:27121]
+
+Sat Sep 17 08:35:39 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/maker/base.rb (RSS::Maker::ItemsBase#normalize): fixed
+ strange RSS::Maker::Item#max_size behavior.
+ Thanks to Kazuhiko <kazuhiko@fdiary.net>.
+
+ * test/rss/test_maker_1.0.rb (RSS::TestMaker10#test_items): ditto.
+
+Fri Sep 16 23:09:20 2005 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_search_event_at): bug fix
+ in ext/win32ole/sample/ienavi.rb.
+
+ * ext/win32ole/win32ole/tests/testOLEEVENT.rb: ditto.
+
+Fri Sep 16 22:41:18 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_extname): empty string for path name ending with a
+ period. fixed: [ruby-core:05651]
+
+ * file.c (rb_file_join): smarter behavior at edge cases.
+ fixed: [ruby-core:05706]
+
+Fri Sep 16 18:34:01 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/syck/node.c (syck_replace_str): was using return from the
+ void function. a patch from MIYAMUKO Katsuyuki
+ <miyamuko at mtb.biglobe.ne.jp>. [ruby-dev:27111]
+
+Fri Sep 16 14:48:48 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: fix typo on MultiTkIp#bg_eval_string
+
+Fri Sep 16 12:02:12 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/syck/rubyext.c (syck_resolver_transfer): remove C++ style
+ comment (//). [ruby-core:05793]
+
+Fri Sep 16 00:14:14 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/logger/test_logger.rb: unintentionally overwritten changes by
+ Usa. reverted.
+
+Fri Sep 16 00:06:18 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb (WEBrick::CGI::Socket#initialize): should set
+ $stdout.binmode.
+
+Thu Sep 15 23:25:21 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/{soap,wsdl,xsd}, test/{soap,wsdl,xsd}: imported soap4r/1.5.5.
+
+ #nnn is a ticket number at http://dev.ctor.org/soap4r
+
+ * SOAP
+
+ * allow to configure an envelope namespace of SOAP request. (#124)
+ TemporaryNamespace = 'http://www.w3.org/2003/05/soap-envelope'
+ @client.options["soap.envelope.requestnamespace"] =
+ TemporaryNamespace
+ @client.options["soap.envelope.responsenamespace"] =
+ TemporaryNamespace
+ @client.do_proc(...)
+
+ * let SOAP request XML indent space configuable. see
+ "soap.envelope.no_indent" option. (#130)
+
+ * let external CES configuable.
+ ex. client["soap.mapping.external_ces"] = 'SJIS'. $KCODE is used
+ by default. (#133)
+ external CES ::= CES used in Ruby object of client and server
+ internal CES ::= CES used in SOAP/OM
+
+ * add iso-8859-1 external CES support. (#106)
+
+ * fixed illegal 'qualified' handling of elements. it caused
+ ASP.NET inteoperability problem. (#144)
+
+ * added 'soap.envelope.use_numeric_character_reference' (boolean)
+ option to let query XML use numeric character reference in XML,
+ not plain UTF-8 character. !GoogleSearch server seems to not
+ allow plain UTF-8 character since 2005-08-15 update. (#147)
+
+ * SOAP::Header::SimpleHeader (de)serialization throws an exception
+ on !SimpleHeader.on_(in|out)bound when header is a String. so we
+ could not use a simple single element headerItem. fixed. thanks
+ to emil. (#129)
+
+ * out parameter of rpc operation did not work. (#132)
+
+ * follow HTTP redirect only if using http-access2. (#125) (#145)
+
+ * add a workaround for importing an WSDL whose path begins with
+ drive letter. (#115)
+
+ * WSDL
+
+ * SOAP Data which is defined as a simpletype was not mapped
+ correctly to Ruby obj when using wsdl2ruby.rb generated classdef
+ file. (#123)
+
+ * rpc/literal support. (#118)
+
+ * re-implemented local element qualify/unqualify control. handles
+ elementFormDefault and form in WSDL. (#119)
+
+ * Array of an element which has simpleType causes a crash. (#128)
+
+ * prarmeterOrder may not contain return part so it can be shorter
+ than parts size. Thanks to Hugh. (#139)
+
+ * Samples
+
+ * added !BasicAuth client sample. (#117)
+
+ * added Base64 client/server sample.
+
+ * added Flickr SOAP interface client sample. (#122)
+
+ * added !SalesForce client sample. (#135)
+
+ * updated Thawte CA certificate for !GoogleAdWords sample.
+
+ * updated a client script with the newer version made by Johan.
+ thanks!
+
+ * shortened long file names. (#120)
+
+ * fixed typo in authheader sample. (#129)
+
+ * updated deprecated method usage. (#138)
+
+Thu Sep 15 23:02:57 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.h (rb_w32_stat): added prototype.
+
+Thu Sep 15 22:35:55 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/ruby/test_signal.rb (test_exit_action): skip the test using
+ fork on fork-less platforms.
+
+Thu Sep 15 11:39:18 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/dialog.rb: If a dialog does not show up yet,
+ TkDialogObj#name raises an exception. [ruby-talk:156109]
+
+Thu Sep 15 01:39:19 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (Rinda::TemplateEntry::initialize): pull
+ up method. Tabs converted to spaces.
+
+Thu Sep 15 00:18:24 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/net/telnet.rb (Net::Telnet::waitfor): replace sysread with
+ readpartial. [ruby-talk:127641]
+
+Wed Sep 14 22:40:26 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (ruby_glob): glob function not using ruby exception system.
+
+Wed Sep 14 01:26:03 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/https.rb: backported from trunk, rev 1.3.
+ [ruby-dev:25673] (again), [ruby-dev:26617] (again),
+ [ruby-dev:27062]
+
+ * ext/openssl/lib/net/https.rb: removed.
+
+ * ext/openssl/lib/net/protocols.rb: removed.
+
+ * lib/net/http.rb: #use_ssl?, #use_ssl are moved from net/https.
+
+Tue Sep 13 22:09:40 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/logger.rb (Logger): added formatter accessor to logger for
+ dictating the way in which the logger should format the messages it
+ displays. Thanks to Nicholas Seckar (cf. [ruby-talk:153391]) and
+ Daniel Berger.
+
+ * lib/logger.rb (Logger): added VERSION constant.
+
+ * lib/logger.rb: removed document for LogDevice. It is an
+ implementation detail and is not a public interface.
+
+ * test/logger/test_logger.rb: added tests.
+
+Tue Sep 13 21:47:17 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (BEGIN_CALLARGS): pop halfly pushed status.
+ fixed: [ruby-dev:26881]
+
+Tue Sep 13 16:26:45 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/http.rb: backported from trunk, rev 1.128.
+ [ruby-dev:25673] [ruby-dev:26617]
+
+ * lib/net/protocol.rb: backported from trunk, rev 1.78.
+
+ * lib/net/protocol.rb: new method #old_open to support net/smtp
+ and net/pop.
+
+ * lib/net/smtp.rb: use #old_open.
+
+ * lib/net/pop.rb: ditto.
+
+Tue Sep 13 12:33:05 2005 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/yaml.rb: reworking YAML::Stream to use the new
+ emitter.
+
+ * lib/yaml/stream.rb: ditto.
+
+ * lib/yaml/rubytypes.rb: added Object#yaml_new.
+
+ * lib/yaml/tag.rb: the tag_subclasses? method now
+ shows up in the class. allow taguri to be set using an accessor.
+ continue support of Object#to_yaml_type.
+
+ * ext/syck/rubyext.c: new emitter code. yaml_new and yaml_initialize
+ get called, should they be present. consolidated all the diaspora of internal
+ node types into the family below YAML::Syck::Node -- Map,
+ Seq, Scalar -- all of whom are SyckNode structs pointing to
+ Ruby data. moved Object#yaml_new into the node_import and made it the
+ default behavior. the target_class is always called wih yaml_new, prepended
+ a parameter, which is the klass. loaded nodes through GenericResolver show their style.
+ new Resolver#tagurize converts type ids to taguris.
+
+ * ext/syck/implicit.re: were 'y' and 'n' seriously omitted??
+
+ * ext/syck/emitter.c: renovated emitter, walks the tree in advance.
+ consolidated redundant block_styles struct into
+ the scalar_style struct. (this means loaded nodes can now
+ be sent back to emitter and preserve at least its very basic
+ formatting.)
+
+ * ext/syck/gram.c: headless documents of any kind allowed.
+
+ * ext/syck/node.c: new syck_replace_str methods and syck_empty_*
+ methods for rewriting node contents, while keeping the ID
+ and other setup info. added syck_seq_assign.
+
+ * ext/syck/syck.h: reflect block_styles and new node functions.
+
+Mon Sep 12 20:53:06 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * test/openssl/test_pkcs7.rb (test_enveloped): skip this test
+ to avoid a bug of PKCS7_enctypt() (only if ext/openssl is
+ compiled with OpenSSL-0.9.7d or earlier versions).
+ http://www.mail-archive.com/openssl-dev@openssl.org/msg17376.html
+
+Mon Sep 12 14:03:33 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/dbm/test_dbm.rb: remove locking test, which may not be
+ supported on some platforms. [ruby-dev:27030]
+
+Mon Sep 12 10:45:58 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dl/dl.c (rb_io_to_ptr): merged a patch for DragonFly BSD
+ from Takahiro Kambe <taca at back-street.net>. [ruby-dev:27023]
+
+Sun Sep 11 22:05:51 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * bin/erb (ERB::Main#run): set ERB#filename so that it is used
+ when reporting syntax/runtime errors. Tabs converted to spaces.
+
+Sat Sep 10 10:17:03 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_engine.c (ossl_engine_s_by_id):
+ OpenSSL::Engine.by_id calls given block before calling
+ ENGINE_init (block parameter is the return value of this method
+ itself). this functionality is useful to load dynamic shared
+ engines. the following code is a sample of loading a key using
+ OpenSC PKCS #11 module.
+
+ require "openssl"
+ pkcs11 = OpenSSL::Engine.by_id("dynamic"){|e|
+ e.ctrl_cmd("SO_PATH", "/usr/lib/opensc/engine_pkcs11.so")
+ e.ctrl_cmd("LIST_ADD", "1")
+ e.ctrl_cmd("LOAD")
+ }
+ pkcs11.ctrl_cmd("PIN", "secret")
+ key = pkcs11.load_private_key
+
+ * ext/openssl/ossl_engine.c (ossl_engine_ctrl_cmd): new method
+ OpenSSL::Engine#ctrl_cmd. it wraps ENGINE_ctrl_cmd_string.
+
+ * ext/openssl/ossl_engine.c (ossl_engine_get_cmds): new method
+ OpenSSL::Engine#cmds. it returms engine command definitions.
+
+Sat Sep 10 10:09:47 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_asn1.c (asn1str_to_str): new function.
+
+ * ext/openssl/ossl_pkcs7.c: new class OpenSSL::PKCS7::RecipientInfo.
+ this class wraps PKCS7_RECIP_INFO struct.
+
+ * ext/openssl/ossl_pkcs7.c: OpenSSL::PKCS7::Signer is renamed to
+ OpenSSL::PKCS7::SignerInfo. ("Signer" remains as an alias of
+ SignerInfo.)
+
+ * test/openssl/test_pkcs7.rb: new file.
+
+Sat Sep 10 10:05:51 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ns_spki.c (ossl_spki_initialize): assume that
+ the argument is a DER string if Base64 decoding failed.
+
+ * ext/openssl/ossl_ns_pki.c (ossl_spki_to_der): new method.
+
+ * test/openssl/test_ns_spki.rb: add new file.
+
+Sat Sep 10 09:56:24 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/lib/digest.rb: added SHA224, SHA256, SHA384 and SHA512.
+ these features are enabled if this library is compiled with
+ OpenSSL 0.9.8 or later.
+
+ * test/openssl/test_digest.rb: add test for new digests.
+
+Sat Sep 10 09:51:30 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl.c (ossl_raise): should use ERR_peek_last_error
+ to get last error on the current thread. And should report
+ errors on the stack while OpenSSL.debug is true.
+
+ * ext/openssl/ossl.c (ossl_get_errors): new method for debugging
+ this library.
+
+ * ext/openssl/ossl_ssl.c (ossl_sslctx_set_ciphers): fix error message.
+
+ * ext/openssl/ossl_x509req.c (ossl_x509req_set_attributes): get rid
+ of unused variable.
+
+ * ext/openssl/ossl_x509store.c (ossl_x509store_initialize): should
+ set @time to avoid warning.
+
+ * ext/openssl/ossl_x509store.c (ossl_x509store_set_default_paths,
+ X509_STORE_add_cert, X509_STORE_add_crl): should raise error if
+ wrapped functions failed.
+
+ * test/openssl/test_x509store.rb: add test for errors.
+
+Fri Sep 9 22:13:19 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call0): prohibit calling tainted method (>2) when
+ $SAFE == 0.
+
+Fri Sep 9 16:45:25 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_times): make empty strings to keep taintness,
+ and a little improvement. [ruby-dev:26900]
+
+ * ext/iconv/iconv.c (iconv_try), ext/iconv/extconf.rb: get rid of meta
+ characters in command line option. fixed: [ruby-talk:155369]
+
+Thu Sep 8 14:58:11 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * merged a patch from Takahiro Kambe <taca at back-street.net> to
+ support DragonFly BSD. [ruby-dev:26984]
+
+Wed Sep 7 12:55:08 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb: abolish mod === tempfile to avoid a problem
+ [ruby-dev:26967].
+
+Wed Sep 7 10:45:15 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_switch): convert all exceptions to
+ SystemExit. fixed: [ruby-core:05724]
+
+ * eval.c (rb_thread_terminated): show backtrace before propagate
+ exceptions to main thread.
+
+Wed Sep 7 08:35:04 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, configure.in (MINIOBJS): miniruby on HP-UX can not load
+ extension libraries.
+
+ * bignum.c (bignew_1, bigadd): K&R style argument actually can't be
+ defined as char.
+
+ * missing/vsnprintf.c: ANSI compiler supports const keyword.
+
+ * ext/digest/sha2/extconf.rb: reject platforms which has inttypes.h
+ but no 64bit integer.
+
+ * lib/mkmf.rb (what_type?): guesstimate type.
+
+ * ext/etc/etc.c (setup_passwd), ext/etc/extconf.rb: pw_age might be
+ char*. fixed: [ruby-core:05470]
+
+Wed Sep 7 08:32:47 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_mod_cvar_get, rb_mod_cvar_set): document fix from
+ sheepman <sheepman@sheepman.sakura.ne.jp>; a bug in visibility
+ description. [ruby-dev:26965]
+
+ * sprintf.c (rb_f_sprintf): warn "too many argument" on verbose
+ mode (-v/-w); backported from 1.9. [ruby-dev:26963]
+
+Mon Sep 5 17:03:07 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/ostruct.rb: a patch from Florian Gross <florgro at gmail.com>
+ merged to allow recursive inspect (and to_s) for OpenStruct.
+ [ruby-core:05532]
+
+Mon Sep 5 07:01:12 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/openssl/lib/openssl/buffering.rb (Buffering#do_write):
+ should clear data from the buffer which already been output.
+
+Fri Sep 2 23:51:54 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib: do not use __send__ to access private methods. [ruby-dev:26935]
+
+Fri Sep 2 03:29:00 2005 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * lib/irb/init.rb: make IRB -I option that is same befavior for ruby.
+ [ruby-dev:26872], [ruby-dev: 26920]
+
+ * lib/irb/locale.rb: support to print help message when OS locale is
+ ja_JP.utf-8. [ruby-dev:26872]
+
+Thu Sep 1 17:11:25 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call0): wrong condition for $SAFE restoration.
+
+Thu Sep 1 14:12:45 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: On Tcl8.5, MultiTkIp#invoke_hidden doesn't
+ work (gives wrong order of arguments).
+
+ * ext/tk/lib/multi-tk.rb: add MultiTkIp#invoke_hidden_on_namespace
+ to support '-namespace' option of 'interp invokehidden' command
+ on Tcl8.5.
+
+Wed Aug 31 14:43:15 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub (OPTFLAGS): default global optimization to
+ disabled for all VC++ versions. fixed: [ruby-dev:26897]
+
+Wed Aug 31 11:35:43 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/gdbm/test_gdbm.rb (teardown): should remove GDBM temporary
+ file.
+
+Wed Aug 31 10:30:56 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * process.c (proc_detach, proc_setmaxgroups): missing argument type
+ declaration. (I recommend ANSI-style function)
+
+Tue Aug 30 23:20:19 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_rescue2): initialization miss. fixed: [ruby-dev:26917]
+
+ * lib/mkmf.rb (xsystem, xpopen): no longer expand by Config.
+
+ * lib/mkmf.rb (link_command, cc_command, cpp_command): expand
+ variables at once, and quote hdrdir. fixed: [ruby-core:05680]
+
+ * lib/mkmf.rb (libpathflag): quote paths.
+
+Tue Aug 30 19:34:27 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/digest/md5/md5ossl.h, ext/digest/rmd160/rmd160ossl.h,
+ ext/digest/sha1/sha1ossl.h: include <stddef.h> to avoid
+ error in compilation with OpenSSL-0.9.8. [ruby-list:41068]
+
+Mon Aug 29 19:54:21 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/rdoc/usage.rb: improper exceptions. [ruby-dev:26870]
+
+ * lib/rdoc/usage.rb: support the case when non-ruby code exists before
+ shebang. (this is needed when ri.bat is executed on windows)
+
+Mon Aug 29 17:48:17 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (method_arity): should return proper arity value.
+ [ruby-dev:26390]
+
+Mon Aug 29 01:19:57 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/time.rb (Time.parse): extract fractional seconds using
+ Date._parse. [ruby-talk:153859]
+
+Sat Aug 27 20:20:01 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/curses/curses.c ({curses,window}_clrtoeol): added. suggested
+ by Reyn Vlietstra.
+
+ * ext/curses/curses.c: chtype in curses is not `char', rahter `long'.
+ [ruby-Bugs:2298]
+
+ * ext/curses/view.rb: String =~ String is deprecated.
+
+Wed Aug 24 10:53:28 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/logger/test_logger.rb (test_shifting_size): should close log
+ device before unlink, since some platform cannot unlink opened
+ file.
+
+Sun Aug 21 00:13:27 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/wsdl/xmlSchema/importer.rb (WSDL::XMLSchema::Importer#fetch): add
+ a workaround for importing an WSDL whose path begins with drive
+ letter. [ruby-dev:26242]
+
+Sat Aug 20 22:37:13 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/logger.rb (write, shift_log?, shift_log): file shifting race
+ condition bug fixed. [ruby-dev:26764]
+
+ * test/logger/test_logger.rb: tests.
+
+Fri Aug 19 18:13:39 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/time.rb (Time.apply_offset): fix a problem with last day of
+ month. reported by Lucas Nussbaum. [ruby-talk:152866]
+
+Thu Aug 18 12:46:28 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub (COMMON_HEADERS): reverted 1.42.2.24.
+ I misunderstood, bccwin32 on ruby_1_8 uses winsock2 originally.
+ [ruby-dev:26806]
+
+ * win32/win32.h: include winsock2.h instead of winsock.h. (bcc32)
+
+Wed Aug 17 23:58:05 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_to_integer): argument constified.
+
+ * eval.c (terminate_process): take String message.
+
+ * eval.c (rb_thread_switch): propagate the exception caused thread
+ termination directly. fixed: [ruby-core:05552]
+
+Wed Aug 17 00:05:46 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_add_method): preserve safe level in the environment
+ where a method is defined .
+
+ * eval.c (rb_call0): restore preserved safe level in the method
+ execution.
+
+Mon Aug 15 00:38:51 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_rescue2): reduce PUSH_TAG() as well as NODE_RESCUE.
+ [ruby-dev:26800]
+
+ * range.c (range_check, range_init): reduce useless exceptions.
+
+Sat Aug 13 18:51:26 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_block_pass): distinguish current block from others.
+ fixed: [ruby-dev:26274]
+
+ * ext/stringio/stringio.c (strio_set_string): disallow nil.
+ http://www.rubyist.net/~nobu/t/20050811.html#c05
+
+Thu Aug 11 23:29:03 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c: keep holding string after closed.
+
+Thu Aug 11 13:01:48 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss: fixed sort bug. [ruby-list:41018]
+
+ * lib/rss/1.0.rb (RSS::RDF::Channel#setup_maker_attributes):
+ removed self.
+
+ * lib/rss/maker/base.rb (RSS::Maker::ItemsBase#<=>): use #date
+ instead of @date.
+ (RSS::Maker::Base::self.def_array_element): added #size.
+
+ * lib/rss/maker/1.0.rb
+ (RSS::Maker::RSS10::Channel#to_rss,
+ RSS::Maker::RSS10::Items::Item#to_rss): cleared dc_dates set
+ upped by using #date.
+
+ * lib/rss/maker/dublincore.rb
+ (RSS::Maker::ChannelBase, RSS::Maker::ItemsBase::ItemBase):
+ fixed opposite alias.
+
+ * test/rss/test_setup_maker_1.0.rb
+ (RSS::TestSetupMaker10::test_setup_maker_items_sort): added some
+ tests for RSS::Maker::ItemsBase#do_sort.
+
+Wed Aug 10 10:29:40 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: fix bug on handling __ruby2val_optkeys().
+
+ * ext/tk/lib/tk/itemconfig.rb: fix bug on handling
+ __item_ruby2val_optkeys().
+
+ * ext/tk/lib/tk/canvas.rb: didn't check __item_ruby2val_optkeys().
+
+ * ext/tk/lib/tkextlib/blt/component.rb: ditto.
+
+Tue Aug 9 15:12:04 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: remove dangerous 'rb_jump_tag's.
+
+ * ext/tk/lib/tk.rb: add __val2ruby_optkeys and __ruby2val_optkeys to
+ help to convert option values between ruby and tcl.
+
+ * ext/tk/lib/tk/itemconfig.rb: add __item_val2ruby_optkeys and
+ __item_ruby2val_optkeys to help to convert option values between
+ ruby and tcl.
+
+ * ext/tk/lib/tk/radiobutton.rb: use __ruby2val_optkeys for 'variable'
+ option (for the reason of backward compatibility).
+
+ * ext/tk/lib/tk/composite.rb: clarify the arguments of super().
+
+ * ext/tk/lib/tk/spinbox.rb: ditto.
+
+ * ext/tk/lib/tk/text.rb: ditto.
+
+ * ext/tk/lib/tk/validation.rb: ditto.
+
+ * ext/tk/lib/tkextlib/*: support to treat tkvariable-type
+ configure options.
+
+Tue Aug 9 20:30:19 2005 Tadashi Saito <shiba@mail2.accsnet.ne.jp>
+
+ * bignum.c (rb_big_coerce): allow bignum x bignum coercing.
+ [ruby-dev:26778]
+
+Mon Aug 8 20:43:02 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/ruby/test_method.rb: added. [ruby-dev:26761]
+
+Sun Aug 7 23:50:14 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/ruby/test_super.rb: added from HEAD. [ruby-dev:26743]
+
+Sun Aug 7 01:31:15 2005 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (WIN32OLE_EVENT#on_event): should set
+ only one event handler.
+
+ * ext/win32ole/tests/testOLEEVENT.rb: ditto.
+
+ * ext/win32ole/tests/testOLEPARAM.rb: remove re-defined
+ test_ole_type_detail method.
+
+Sat Aug 6 12:35:24 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/{tk.rb,tk/itemconfig.rb}: configure creates
+ TkVariable if key name is 'variable' or 'textvariable'
+ by default. [ruby-dev:26749]
+
+ * ext/tk/lib/tk/{label,radiobutton}.rb: removed its own
+ {variable,textvariable} function.
+
+ * ext/tk/lib/tk/variable.rb: retains backward conpatibility.
+
+Fri Aug 5 12:50:32 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c: fixed memory leak when tk_funcall raised
+ exception. (copies argv into heap in tk_funcall instead of
+ caller)
+
+Fri Aug 5 12:42:57 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): need to convert path separetor
+ before invoking install command.
+
+Fri Aug 5 00:27:04 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c: refactoring - extract ruby string <->
+ tcl object conversion as get_str_from_obj and get_obj_from_str.
+
+Fri Aug 5 00:19:33 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * extmk.rb (extmake): needs to be wrapped in an Array.
+
+Thu Aug 4 18:38:36 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: cannot compile for Tcl7.6/Tk4.2.
+
+ * ext/tcltklib/tcltklib.c: add nativethread consistency check.
+
+ * ext/tcltklib/stubs.c: ditto.
+
+ * ext/tk/lib/tk.rb: forgot to define TclTkIp.encoding and encoding=
+ when Tcl is 7.6 or 8.0.
+
+ * ext/tk/lib/tk/wm.rb: support to make some methods as options of
+ root or toplevel widget. [ruby-talk:150336]
+
+ * ext/tk/lib/tk/root.rb: ditto.
+
+ * ext/tk/lib/tk/toplevel.rb: ditto.
+
+ * ext/tk/lib/tkextlib/SUPPRT_STATUS: update RELEASE_DATE
+
+Thu Aug 4 08:03:39 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake): should not modify $mflags for each
+ extentions.
+
+Thu Aug 4 00:25:48 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk, Makefile.in, {bcc32,win32,wince}/Makefile.sub: integrated
+ macro definitions.
+
+ * bcc32/Makefile.sub: LIBRUBY_SO should use DLDOBJS, not EXTOBJS.
+
+ * {win32,wince}/Makefile.sub: separate config.h for compiler versions.
+
+Wed Aug 3 21:59:16 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/variable.rb: TkVariable#trace didn't work on
+ TkVariable retrived from TkVariable.new_hash.ref. [ruby-dev:26721]
+
+Wed Aug 3 08:22:13 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (ruby_connect): revert [ruby-talk:111654]
+ changes at 2004-09-07. [ruby-dev:26656]
+
+Tue Aug 2 10:20:54 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c: use Tcl_[GS]etVar2Ex instead of
+ Tcl_Obj[GS]etVar2. (avoid Tcl_NewStringObj on supported platforms)
+
+ * ext/tcltklib/tcltklib.c: use ip_{get,set,unset}_variable2_core from
+ ip_{get,set,unset}_variable.
+
+ * ext/tcltklib/tcltklib.c: replaced Tcl_Panic with rb_bug.
+
+Tue Aug 2 01:41:28 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/ping.rb (Ping.pingecho): should rescue StandardError.
+ [ruby-dev:26677]
+
+Mon Aug 1 19:09:41 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c: refactoring - replaced rb_ivar_defined &
+ rb_ivar_get with single rb_attr_get call.
+
+Mon Aug 1 18:45:07 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c (Tcl_GetStringResult): refactoring - define
+ alternative macro on Tcl7.x or earlier.
+
+Mon Aug 1 13:57:35 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c (deleted_ip): refactoring - interpreter
+ deletion check. [ruby-dev:26664]
+
+Mon Aug 1 01:17:40 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (check_insecure_method): use private_methods and
+ protected_methods instead of respond_to? to check method visibility.
+ [ruby-dev:26616]
+
+ * test/drb/drbtest.rb: ditto.
+
+ * test/drb/ut_drb.rb: ditto.
+
+Mon Aug 1 00:07:32 2005 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * lib/irb/context.rb: fix `irb --readline` option. [ruby-list:40955]
+
+Fri Jul 29 09:59:38 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_yield_0): push yielded node instead of yielding.
+ fixed: [yarv-dev:549]
+
+Thu Jul 28 18:09:55 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/stubs.c: When --enable-tcltk-stubs, the initialize
+ routine creates a Tcl/Tk interpreter and deletes it. However,
+ init cost of Tk's MainWindow is not so small. And that makes it
+ impossible to use libraries written with Tcl functions only on
+ an environment without a graphical display. This changes support
+ delaying initalization of Tk_Stubs until the script needs Tk.
+
+ * ext/tcltklib/stubs.h: New file. Define prototypes and return
+ codes of functions on stubs.c.
+
+ * ext/tcltklib/tcltklib.c: Support delaying initalization of
+ Tk_Stubs until the script needs Tk.
+
+ * ext/tcltklib/tcltklib.c: Show friendly error messages for errors
+ on initialization.
+
+ * ext/tcltklib/tcltklib.c: Avoid SEGV on ip_finalize() when ruby is
+ exiting and $DEBUG is true. (Not fix. If you know the reason of
+ why, please fix it.)
+
+ * ext/tk/tkutil.c (ary2list, ary2list2): bug fix on handling of
+ encoding.
+
+ * ext/tk/lib/multi-tk.rb: MultiTkIp#eval_string and bg_eval_string
+ don't work propery.
+
+ * ext/tk/lib/tk.rb: Forget extending Tk::Encoding module to Tk.
+ * ext/tk/lib/tk/variable.rb: TkVarAccess fails to initialize the
+ object for an element of a Tcl's array variable.
+
+Wed Jul 27 23:23:54 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (obj_free): make message format consistent with one from
+ gc_mark(). [ruby-talk:149668]
+
+Wed Jul 27 22:11:37 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * sample/rss/tdiary_plugin: removed. because the plugin
+ is imported in the tDiary plugin packages.
+
+Wed Jul 27 10:59:02 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (dir_each): rewinddir(3) before iteration.
+ [ruby-talk:149628]
+
+Tue Jul 26 12:57:49 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/openssl_missin.c: include <openssl/engine.h> before
+ <openssl/x509_vfy.h> to avoid compilation error of mswin32.
+ suggested by NAKAMURA Usaku.
+
+Mon Jul 25 21:30:46 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * {bcc32,win32,wince}/Makefile.sub: moved CPPFLAGS only for ruby
+ source to XCFLAGS.
+
+Mon Jul 25 13:45:18 2005 NAJIMA Hiroki <najima@mickey.ai.kyutech.ac.jp>
+
+ * io.c: check HAVE_SYS_IOCTL_H before including the header.
+ [ruby-dev:26610]
+
+Mon Jul 25 14:10:02 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: fix en-bugged part in the last commit.
+
+Sat Jul 23 16:49:04 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_engine.c (ossl_engine_s_load): should check
+ OPENSSL_NO_STATIC_ENGINE.
+
+Fri Jul 22 21:06:08 2005 Tadashi Saito <shiba@mail2.accsnet.ne.jp>
+
+ * bignum.c (rb_big_eq): reduce isnan(). [ruby-dev:26600]
+
+ * numeric.c (flo_eq, flo_gt, flo_ge, flo_lt, flo_le): ditto.
+
+Fri Jul 22 15:02:39 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: moved copyright description to lib/rss.rb.
+
+ * lib/rss.rb: added for convenience.
+
+ * sample/rss/re_read.rb: added #to_s sample.
+
+ * sample/rss/blend.rb: use 'require "rss"' instead of
+ 'require "rss/*"'.
+ * sample/rss/list_description.rb: ditto.
+ * sample/rss/rss_recent.rb: ditto.
+ * sample/rss/tdiary-plugin/rss-recent.rb: ditto.
+
+ * sample/rss/tdiary-plugin/rss-recent.rb: 0.0.6 -> 0.0.7.
+
+Fri Jul 22 14:37:43 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/parser.rb (RSS::Parser#initialize): accept HTTP/FTP
+ URI and local file path too.
+
+ * test/rss/test_parser.rb (RSS::TestParser#test_parse): test
+ for the above.
+
+Fri Jul 22 07:01:42 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil.c (tk_conv_args): forget to revert thread_critical
+ and gc_disable when raise ArgumentError.
+
+ * ext/tk/lib/remote-tk.rb: RemoteTkIp doesn't need to include TkUtil.
+
+ * ext/tcltklib/tcltklib.c: add TclTkIp#has_mainwindow? method.
+
+ * ext/tk/lib/tk.rb: add Tk.has_mainwindow? method.
+
+ * ext/tk/lib/multi-tk.rb: add MultiTkIp#has_mainwindow? method.
+
+ * ext/tk/lib/remote-tk.rb: add RemoteTkIp#has_mainwindow? method.
+
+ * ext/tk/lib/multi-tk.rb: slave IP fail to exit itself when $SAFE==4.
+
+ * ext/tk/lib/multi-tk.rb: remove constants from MultiTkIp module to
+ avoid access from external.
+
+ * ext/tk/lib/multi-tk.rb: check_root flag is ignored on slave IPs'
+ mainloop.
+
+ * ext/tk/lib/multi-tk.rb: hang-up Tk.mainloop called on a slave IP
+ with $SAFE==4.
+
+ * ext/tk/lib/multi-tk.rb: MultiTkIp#bg_eval_proc doesn't work
+ properly.
+
+ * ext/tk/lib/multi-tk.rb: add MultiTkIp#set_cb_error(proc) and
+ cb_error(exc) to log errors at callbacks on safe slave IPs.
+
+ * ext/tk/lib/multi-tk.rb: fail to get an available slave IP object
+ when call Tk.mainloop in the block which is given to new_* method,
+ because cannot finish initialize while the root widget is alive.
+
+ * ext/tk/lib/multi-tk.rb: fail to control a slave IP when Tk.mainloop
+ runs on the IP.
+
+Wed Jul 20 19:20:37 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * io.c (S_ISREG): need to define S_ISREG before it is used first.
+
+Wed Jul 20 18:40:50 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * io.c (wsplit_p): patch for the environment where
+ fcntl(F_GETFL, O_NONBLOCK) is not supported. in that case,
+ set FMODE_WSPLIT without fcntl check. [ruby-dev:26566]
+
+Wed Jul 20 18:07:11 2005 Tanaka Akira <akr@m17n.org>
+
+ * io.c (rb_io_ctl): update FMODE_WSPLIT_INITIALIZED and FMODE_WSPLIT
+ by F_SETFL.
+
+Wed Jul 20 10:04:51 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_class_path): need to adjust snprintf() len for
+ teminating NUL. [ruby-dev:26581]
+
+Wed Jul 20 04:01:55 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/socket/socket.c: sorry, BeOS also uses HAVE_CLOSESOCKET,
+ so reverted.
+
+ * ext/socket/extconf.rb: should not define HAVE_CLOSESOCKET
+ on windows.
+
+Wed Jul 20 03:16:43 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/socket/socket.c: should not undef close() on win32.
+ it's defined to rb_w32_close(), otherwise handle leaks.
+ [ruby-Bugs-2131]
+
+Wed Jul 20 00:48:16 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (syserr_initialize): don't use str before StringValue()
+ check. [ruby-dev:26579]
+
+Tue Jul 19 22:47:29 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (syserr_initialize): add 1 byte for snprintf() size for
+ NUL at the end. [ruby-dev:26574]
+
+Tue Jul 19 16:39:46 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_inspect): replace sprintf() with "%s" format all
+ over the place by snprintf() to avoid integer overflow.
+
+Tue Jul 19 14:08:22 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c: rbtk_eventloop_depth is used as int.
+
+ * ext/tcltklib/tcltklib.c: rbtk_pending_exception is tested with
+ NIL_P, so should assign Qnil instead of 0 (Qfalse).
+
+ * ext/tcltklib/tcltklib.c (ip_invoke_real): fixed memory leak when
+ ip is deleted.
+
+Tue Jul 19 13:19:46 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/variable.rb: For symmetry, add TkVariable#string. It
+ returns a string even if the default value type of the TkVariable
+ object is not "string".
+
+Mon Jul 18 21:40:20 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * eval.c (rb_call0): make the pointer to NODE volatile
+ instead of NODE itself.
+
+Mon Jul 18 14:32:21 2005 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (rb_call0): make body volatile to avoid optimization problem.
+ [ruby-dev:26195]
+
+Mon Jul 18 12:23:27 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/io/wait/wait.c: wrong backport from trunk. fixed: [ruby-dev:26562]
+
+Mon Jul 18 09:36:25 2005 Tanaka Akira <akr@m17n.org>
+
+ * rubyio.h (FMODE_WSPLIT, FMODE_WSPLIT_INITIALIZED): new constant.
+
+ * io.c (wsplit_p): new function.
+ (io_fwrite): split writing data by PIPE_BUF if wsplit_p is true in
+ multi-threaded mode.
+ [ruby-dev:26540]
+
+Sun Jul 17 13:46:54 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/io/wait/extconf.rb, ext/io/wait/wait.c: Win32 platforms support.
+
+Fri Jul 15 23:59:03 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rdoc/parsers/parse_c.rb (handle_class_module): handle a
+ module enclosed in a built-in module. fixed: [ruby-talk:148239]
+
+ * lib/rdoc/parsers/parse_c.rb (find_body): allow macros as methods.
+
+ * lib/rdoc/parsers/parse_c.rb (find_call_seq): allow :nodoc: modifier
+ in C. [ruby-core:04572]
+
+Fri Jul 15 18:00:01 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub (COMMON_HEADERS): ruby_1_8 is using winsock.h.
+ failed to compile ext/socket on bcc5.6.4. [ruby-dev:26193]
+
+Fri Jul 15 07:58:56 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/server.rb (WEBrick::GenericServer#accept_client):
+ sockets should be non-blocking mode. [ruby-dev:26405]
+
+ * lib/webrick/utils.rb (WEBrick::Utils.set_non_blocking): new method.
+
+ * lib/webrick/httprequest.rb (WEBrick::HTTPRequest#read_chunked):
+ should call sock.read repeatedly until the preferred size data
+ is obtained.
+
+Thu Jul 14 18:27:16 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.c (rb_w32_strerror): should return correct message
+ for ENAMETOOLONG and ENOTEMPTY. (bcc32) [ruby-dev:26533]
+
+ * win32/win32.c (rb_w32_strerror): stripped CR LF on the tail.
+ (bcc32) [ruby-dev:26533]
+
+Thu Jul 14 00:45:42 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * LEGAL (ext/nkf/nkf-utf8): updated from nkf1.7 to nkf-utf8.
+
+Wed Jul 13 19:37:47 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.c (rb_w32_mkdir): should set EEXIST (not EACCES)
+ if file or directory already exists. (bcc32) [ruby-dev:26508]
+
+ * win32/win32.c (rb_w32_rmdir): should set ENOTDIR (not EINVAL)
+ if it is not directory. (bcc32, win32)
+
+ * win32/win32.c (rb_w32_rmdir, rb_w32_unlink): restore
+ FILE_ATTRIBUTE_READONLY flag on function failure.
+
+Wed Jul 13 12:40:00 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: TclTkLib.do_one_event doesn't work.
+
+ * ext/tk/lib/tk.rb: Tk.thread_update is available.
+
+Tue Jul 12 23:32:11 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb: keep curdir unexpanded.
+
+Mon Jul 11 08:31:29 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * regex.c (read_special): fix parsing backslashes following \c in
+ regexp. fixed: [ruby-dev:26500]
+
+Mon Jul 11 02:53:00 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb (WEBrick::CGI::Socket#request_line):
+ mistook in merging the patch of [ruby-dev:26235] at
+ revision 1.4.2.6.
+
+Sun Jul 10 23:58:04 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb (Pathname#unlink): try Dir.unlink first to
+ avoid unlink a directory by root.
+ cf. [ruby-dev:26237]
+
+Sun Jul 11 05:18:17 2005 Michael Neumann <mneumann@ruby-lang.org>
+
+ * lib/xmlrpc/server.rb (XMLRPC::Server): Switch from GServer over to
+ WEBrick. This makes file lib/xmlrpc/httpserver.rb obsolete (at least it is
+ no further used by the XML-RPC library).
+
+Sun Jul 10 12:47:01 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/debug.rb (debug_command): added a deficient format specifier.
+ fixed: [ruby-core:05419]
+
+Sat Jul 9 21:28:46 2005 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_method_dispid): convert dispid
+ in Ruby and C by INT2NUM and NUM2INT.
+
+ * ext/win32ole/win32ole.c (ole_invoke2): ditto.
+
+ * ext/win32ole/test/testWIN32OLE.rb: ditto.
+
+ * ext/win32ole/test/testOLEMETHOD.rb: ditto.
+
+Fri Jul 8 15:45:04 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb (RSS::VERSION): 0.1.4 -> 0.1.5.
+
+ * test/rss/test_version.rb (RSS::TestVersion#test_version):
+ ditto.
+
+ * lib/rss/0.9.rb (RSS::Rss::Channel::Item::Category):
+ domain attribute of <category> is optional. Thanks to
+ Chris Lee <clee@kde.org>.
+
+ * test/rss/test_parser.rb (RSS::TestParser#test_category20):
+ adjusted test case.
+
+Tue Jul 5 23:44:06 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb: expand source library path.
+
+Tue Jul 5 23:27:14 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (sort_2): get rid of yet another bcc's bug.
+ fixed: [ruby-core:05152]
+
+ * eval.c (rb_thread_save_context): must not switch contexts during
+ re-allocating stack. fixed: [ruby-core:05219]
+
+Tue Jul 5 15:15:10 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil.c: fix typo.
+
+Tue Jul 5 14:51:35 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: bug fix on treating Unicode strings.
+
+ * ext/tcltklib/tcltklib.c: add methods to treat encoding mode.
+
+ * ext/tcltklib/MANUAL.eng: add description of TclTkLib#encoding,
+ encoding_system, and so on.
+
+ * ext/tcltklib/MANUAL.euc: ditto.
+
+ * ext/tk/tkutil.c: fail to create a Tcl's list string from an
+ array including multiple kind of encoded strings.
+
+ * ext/tk/lib/tk.rb: ditto.
+
+ * ext/tk/lib/multi-tk.rb: 2nd arg of _{to|from}UTF8 is omissible.
+
+ * ext/tk/lib/remote-tk.rb: ditto.
+
+ * ext/tk/lib/tk.rb: override TclTkLib#encoding and encoding= to
+ use TkCore::INTERP.encoding and encoding=.
+
+ * ext/tk/lib/tk.rb: when "require 'tk'" and $KCODE=='NONE', check
+ DEFAULT_TK_ENCODING to decide Ruby/Tk's system encoding mode.
+
+ * ext/tk/lib/tk/encodedstr.rb: check both of Tk.encoding and
+ Tk.encoding_system. Tk.encoding has higher priority.
+
+ * ext/tk/lib/tk/optiondb.rb: ditto.
+
+ * ext/tk/lib/tk/spinbox.rb: ditto.
+
+ * ext/tk/lib/tk/validation.rb: ditto.
+
+ * ext/tk/lib/tk/namespace.rb: arguemnts for TclTkIp#_merge_tklist
+ should be UTF-8 strings.
+
+Mon Jul 4 14:35:52 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sample/svr.rb: service can be stopped by ill-behaved client; use
+ tsvr.rb instead.
+
+Mon Jul 4 13:25:21 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * missing/erf.c: original erf.c by prof. Okumura is confirmed to
+ be public domain. reverted BSD implementation.
+
+Mon Jul 4 11:15:37 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/{dbm,gdbm,sdbm}/test_{dbm,gdbm,sdbm}.rb: skip some tests
+ which using fork on fork-less platforms.
+
+Sun Jul 3 23:26:30 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/wsdl/document/test_rpc.rb: compare formatted time string of
+ Time objects instead of comparing Time objects itself to avoid
+ unintended conflict of usec part. [ruby-dev:26220]
+
+Sat Jul 2 22:41:04 2005 Tanaka Akira <akr@m17n.org>
+
+ * ext/socket/socket.c (unix_send_io, unix_recv_io): support x86-64 and
+ IA64.
+
+Sat Jul 2 17:06:23 2005 Tanaka Akira <akr@m17n.org>
+
+ * defines.h (FLUSH_REGISTER_WINDOWS): defined for IA64.
+ (flush_register_windows): declare flush_register_windows.
+
+ * eval.c (flush_register_windows): new function.
+
+Fri Jul 1 17:48:52 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (get2comp): revert all prior changes, and calculate
+ proper 2's complement for negative numbers. backported from
+ HEAD.
+
+Fri Jul 1 15:50:12 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * missing/erf.c: need to include some headers for some platforms.
+
+ * win32/win32.h (copysign, scalb): define for compatibility with
+ other platforms. [ruby-dev:26430]
+
+Fri Jul 1 15:37:42 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * missing/crypt.c: modified to make it compilable on platforms
+ other than BSD. [ruby-dev:26430]
+
+ * missing/erf.c: ditto. code from <exp.c> merged.
+
+Fri Jul 1 12:44:56 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb (OpenURI.open_http): refine post_connection_check
+ call.
+
+Fri Jul 1 11:34:08 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * missing/crypt.c: replaced with 4.4BSD version.
+
+ * missing/erf.c: ditto.
+
+ * missing/vsnprintf.c: removed the third provision from the old
+ BSD license. [ruby-core:05177]
+
+Fri Jul 1 01:45:21 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (enum_min, enum_max): must not return Qundef.
+ fixed: [ruby-core:05299]
+
+Fri Jul 1 00:18:40 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb (Delegator::respond_to): respond_to? must check
+ destination object. [ruby-talk:146894]
+
+Thu Jun 30 19:00:21 2005 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * lib/irb/ruby-lex.rb (RubyLex::identify_number): alternative implements
+ for [ruby-dev:26410]. And support a numeric form of 0d99999.
+
+Thu Jun 30 17:28:10 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/ruby-lex.rb (RubyLex::identify_number): should not treat
+ plain zero as an octal number. [ruby-dev:26410]
+
+Thu Jun 30 15:13:16 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): pre-evaluate argument for unambiguous
+ evaluation order. [ruby-dev:26383]
+
+Thu Jun 30 09:53:56 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb (Delegator::method_missing): forward unknown
+ method to the destination. suggested by
+ <christophe.poucet@gmail.com>. [ruby-talk:146776]
+
+Tue Jun 28 21:59:29 2005 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * dir.c, eval.c, hash.c, process.c, ruby.c: avoid warning "unused
+ variable" [ruby-dev:26387]
+
+Sat Jun 25 17:15:23 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httputils.rb (WEBrick::HTTPUtils.parse_query): should
+ discard if key=val pair is empty. patch from Gary Wright.
+
+Sat Jun 25 23:30:51 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * process.c (detach_process_watcher): terminate process watcher
+ thread right after rb_waitpid() succeed. [ruby-talk:146430]
+
+Sat Jun 25 15:49:18 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (enum_min, enum_max): do not ignore nil as the first element.
+
+Sat Jun 25 14:40:17 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/sdbm/init.c (fsdbm_select): SDBM#select had returned the array
+ which contained each elements twice. [ruby-dev:26358]
+
+Fri Jun 25 05:06:47 2005 Michael Neumann <mneumann@ruby-lang.org>
+
+ * lib/xmlrpc/*, test/xmlrpc/*: backported changes from HEAD into 1.8
+
+Fri Jun 24 17:00:00 2005 Shigeo Kobayashi <shigeo@tinyforest.jp>
+
+ * ext/bigdecimal/bigdecimal.c: patch from "NATORI Shin"
+ (u-tokyo.ac.jp) applied to fix rounding bug.
+
+Fri Jun 24 13:06:45 2005 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/common.rb, lib/uri/generic.rb: fixed typo in documents and
+ replaced some existent domain name with "example.com".
+
+Fri Jun 24 12:23:19 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: fix typo on Tk.grid_propagate.
+
+ * ext/tk/lib/tk.rb: Tk.event_generate and TkWindow#event_generate
+ accept TkEvent::Event object as context argument.
+
+ * ext/tk/lib/tk/event.rb: add TkEvent::Event#valid_fields and
+ valid_for_generate to get field parameters of event_generate.
+
+Thu Jun 23 23:55:59 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * runruby.rb: should load built rbconfig.rb.
+
+Thu Jun 23 16:53:15 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/canvastag.rb: TkcGroup.new cannot include given items.
+ TkcGroup#exclude calls wrong method.
+ Add alias TkcGroup#add [ruby-talk:146049].
+
+ * ext/tk/lib/tk/canvas.rb: TkCanvas#dtag and some subcommands of
+ TkCanvas#addtag fail to treat a TkcTag argument.
+
+ * ext/tk/lib/tk/event.rb: add TkEvent::Event#generate to help to send
+ current event to other widgets.
+
+Mon Jun 20 18:44:04 2005 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (FUNCTION_CALL_MAY_RETURN_TWICE): DUMMY_SETJMP is replaced
+ because setjmp is not enough to fix getcontext and SPARC register
+ window problem.
+
+Mon Jun 20 16:48:36 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/dbm/dbm.c (fdbm_closed): new method DBM#closed?
+
+ * ext/gdbm/gdbm.c (fgdbm_closed): new method GDBM#closed?
+
+ * ext/sdbm/init.c (fsdbm_closed): new method SDBM#closed?
+
+ * test/dbm/test_dbm.rb, test/gdbm/test_gdbm.rb, test/sdbm/test_sdbm.rb
+ (teardown): close all db objects before deleting data files.
+
+ * win32/win32.{ch} (unlink): hook runtime function to change
+ file attribute before unlinking.
+ fixed: [ruby-dev:26360]
+
+Mon Jun 20 02:15:35 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (define_final): document fix: finalizers never get called
+ before target object is destroyed.
+
+Mon Jun 20 01:26:49 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/openssl_missing.c, ext/openssl/ossl.h,
+ ext/openssl/ossl_asn1.c, ext/openssl/ossl_bio.c,
+ ext/openssl/ossl_pkcs12.h, ext/openssl/ossl_x509req.c: avoid
+ compiler warnings. suggested by Michal Rokos.
+
+Sun Jun 19 14:09:07 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (run_final): reduce unnecessary object allocation during
+ finalization.
+
+ * gc.c (rb_gc_call_finalizer_at_exit): deferred finalizers list should
+ be cleared before calling them. fixed: [ruby-talk:145790]
+
+Fri Jun 17 13:01:40 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/time.rb (Time.parse): fix previous leap seconds support.
+ (Time.rfc2822): ditto.
+ (Time.xmlschema): ditto.
+
+Thu Jun 16 15:06:55 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_rb_threadVwaitCommand): Tcl_Release
+ was missing.
+
+Thu Jun 16 13:34:48 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: add Tk.getMultiple{Open|Save}File() which return
+ an Array of selected files.
+
+Thu Jun 16 12:53:24 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/time.rb (Time.parse): "Fri Jan 1 08:59:60 +0900 1999" was
+ parsed as "Fri Jan 01 09:00:00 JST 1999" even on an environment
+ which supports leap seconds.
+ (Time.rfc2822): ditto.
+ (Time.xmlschema): ditto.
+
+Thu Jun 16 08:29:22 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/dl/sym.c (rb_dlsym_call): needs FREE_ARGS before return.
+ fixed memory leak. [ruby-Bugs-2034]
+
+Wed Jun 15 18:26:39 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: support "tk inactive" sub-command [for Tcl/Tk8.5a3]
+
+ * ext/tk/lib/tk/namespace.rb: support "namespace path" sub-command and
+ 'namespace ensemble' sub-command [for Tcl/Tk8.5a3]
+
+Tue Jun 14 02:02:43 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil.c: add TkUtil::CallbackSubst.subst_arg(m, ...) &
+ _define_attribute_aliases(hash) to get substitution-argument from
+ attributes (e.g. subst_arg(:x,:y,:num,:button) --> "%x %y %b %b ").
+
+ * ext/tk/lib/tk/event.rb: use _define_attribute_aliases().
+
+Mon Jun 13 13:01:05 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * hash.c (ruby_setenv): fixed SEGV. [ruby-dev:26186]
+
+Mon Jun 13 01:54:20 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * signal.c (sigexit): call rb_thread_signal_exit() instead of
+ rb_exit(). [ruby-dev:26347]
+
+ * eval.c (rb_thread_signal_exit): a new function to exit on main
+ thread.
+
+ * eval.c (rb_thread_switch): exit status should be retrieved from
+ ruby_errinfo.
+
+ * eval.c (rb_f_exit): ensure exit(0) should call
+ exit(EXIT_SUCCESS).
+
+Mon Jun 13 01:20:02 2005 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (rb_gc_mark_threads): curr_thread may not be part of the
+ thread list. [ruby-dev:26312]
+
+Fri Jun 10 23:35:34 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * missing/mkdir.c: remove. [ruby-core:05177]
+
+Fri Jun 10 22:54:26 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * missing.h: fd_set stuffs need sys/types.h. fixed: [ruby-core:05179]
+
+Thu Jun 9 23:58:12 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/Win32API/Win32API.c (Win32API_Call): disable global
+ optimization. fixed: [ruby-core:05143]
+
+Thu Jun 9 23:35:22 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (enum_inject): default the result value to Qundef to use
+ first element as initial value if not given.
+
+Thu Jun 9 19:55:41 2005 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (ruby_longjmp): new macro to call longjmp, setcontext, etc.
+ (ruby_setjmp): new macro to call setjmp, getcontext, etc.
+ (ruby_setjmp): call setjmp before getcontext to avoid IA64 register
+ stack problem.
+ [ruby-talk:144939]
+
+ * gc.c (Init_stack): remove IA64_MAGIC_STACK_LIMIT.
+
+Thu Jun 9 11:55:34 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb (SimpleDelegator::__setobj__): need check for
+ recursive delegation. [ruby-core:04940]
+
+Wed Jun 8 18:47:10 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-expr-beg): fix looking point drift.
+
+Wed Jun 8 11:11:34 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (get2comp): calculate proper 2's complement for
+ negative numbers. a bug in normalizing negative numbers
+ reported from Honda Hiroki <hhonda@ipflex.com>.
+
+Wed Jun 8 08:33:10 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (enum_min_by, enum_max_by): return nil if no iteration.
+ fixed: [ruby-dev:26245]
+
+ * eval.c (rb_need_block): ensure a block is given.
+
+ * eval.c (backtrace): skip successive frames sharing same node.
+
+Wed Jun 8 00:15:08 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (ruby_getaddrinfo__aix): merged a patch from
+ KUBO Takehiro <kubo at jiubao.org> to support AIX. [ruby-list:40832]
+
+Wed Jun 8 00:09:01 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/yaml/rubytypes.rb (Array::to_yaml): merged a patch from
+ Tilman Sauerbeck <tilman at code-monkey.de>. [ruby-core:05055]
+
+ * lib/yaml/rubytypes.rb (Hash::to_yaml): ditto.
+
+Wed Jun 8 00:00:01 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/curses/curses.c (curses_insertln): merged a patch from
+ TAKAHASHI Tamotsu <ttakah at lapis.plala.or.jp>. [ruby-ext:02305]
+
+Tue Jun 7 19:34:15 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/init.rb (IRB::IRB.rc_file_generators): more flexible
+ IRB.rc_file_generators. [ruby-core:05163]
+
+Tue Jun 7 18:39:31 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/thread.rb: RDoc documentation from Eric Hodel
+ <drbrain at segment7.net> added. [ruby-core:05148]
+
+Tue Jun 7 18:30:04 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): add .SUFFIXES from depend file.
+ fixed: [ruby-dev:26294]
+
+Tue Jun 7 17:39:54 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_mod_cvar_get): Module#class_variable_get(): back
+ ported from CVS HEAD. [ruby-talk:144741]
+
+ * object.c (rb_mod_cvar_set): Module#class_variable_set().
+ [ruby-talk:144741]
+
+Tue Jun 7 16:32:53 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): raise exception on debug mode (-d),
+ not verbose mode (-v/-w). [ruby-core:05123]
+
+Tue Jun 7 10:30:49 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: slave-ip fails to call procedures
+ delegated by master-ip.
+
+Sun Jun 5 23:00:35 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/console.rb: create console when required
+
+ * ext/tk/sample/tkextlib/tile/demo.rb: fix TypeError & create Console
+
+Sat Jun 4 14:55:18 2005 Tanaka Akira <akr@m17n.org>
+
+ * test/dbm/test_dbm.rb: merged from ext/dbm/testdbm.rb.
+
+ * test/gdbm/test_gdbm.rb: merged from ext/gdbm/testgdbm.rb.
+
+ * test/sdbm/test_sdbm.rb: renamed from ext/sdbm/testsdbm.rb with
+ modification to use test/unit.
+
+Fri Jun 3 14:06:12 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: fix typo.
+
+Wed Jun 1 11:32:42 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub: can use single quote character in DESTDIR.
+ [ruby-dev:26205]
+
+Mon May 30 23:48:29 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/macpkg.rb: add PACKAGE_NAME information of Tcl/Tk
+ Extension.
+
+ * ext/tk/lib/tk/msgcat.rb: ditto.
+
+ * ext/tk/lib/tk/winpkg.rb: ditto.
+
+ * ext/tk/lib/tkextlib/*: ditto.
+
+Sat May 28 16:40:15 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * test/openssl/test_x509store.rb: add test for expired CRL
+ and refine some assertions.
+
+Sat May 28 05:15:51 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_x509store.c (ossl_x509stctx_set_time): should
+ not set internal flag directry.
+
+Sat May 28 02:00:11 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb (WEBrick::CGI::Socket#request_line):
+ ENV["REQUEST_URI"] is better to get correct Request-URI
+ than ENV["SCRIPT_NAME"] + ENV["PATH_INFO"]. [ruby-dev:26235]
+
+Fri May 27 16:32:04 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/mkmf.rb: use the semicolon as the path separator
+ in the environment of MSYS. fixed: [ruby-dev:26232]
+
+Thu May 26 06:08:11 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: add shortcut-methods of tk_call + tk_split_list
+
+Wed May 25 22:52:42 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/irb/input-method.rb: do not use Readline::HISTORY.pop.
+ (backported from HEAD)
+
+Wed May 25 21:55:40 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * ext/readline/readline.c: supported libedit. (backported from HEAD)
+
+ * ext/readline/extconf.rb: ditto.
+
+ * test/readline/test_readline.rb: ditto.
+
+Wed May 25 20:06:27 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: TkComm#tk_split_*list fail to split a kind of SJIS
+ strings. To avoid the trouble, add arguments to control converting
+ encoding, and do split on a UTF8 string.
+
+ * ext/tk/lib/multi-tk.rb: modify to attend encoding.
+
+ * ext/tk/lib/remote-tk.rb: ditto.
+
+ * ext/tk/lib/tk/itemconfig.rb: ditto.
+
+ * ext/tk/lib/tk/listbox.rb: ditto.
+
+ * ext/tk/lib/tk/namespace.rb: ditto.
+
+ * ext/tk/lib/tk/panedwindow.rb: ditto.
+
+ * ext/tk/lib/tk/text.rb: ditto.
+
+ * ext/tk/lib/tk/textmark.rb: ditto.
+
+ * ext/tk/lib/tk/texttag.rb: ditto.
+
+ * ext/tk/lib/tk/variable.rb: ditto.
+
+ * ext/tk/lib/tk/winfo.rb: ditto.
+
+ * ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb: ditto.
+
+ * ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb: ditto.
+
+ * ext/tk/lib/tk.rb: add TkWindow#lower_window/raise_window and
+ Tk#lower_window/raise_window by reason of method-name conflict
+
+ * ext/tk/lib/tk/canvas.rb: bug fix on TkCanvas#delete when given
+ non-TkcItem arguments.
+
+ * ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb: ditto.
+
+Wed May 25 12:59:48 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb (OpenURI::Meta::RE_QUOTED_STRING): a content of
+ quoted-string should be zero or more characters.
+
+Tue May 24 23:42:16 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (fix_pow): support Fixnum ** Float case directly
+ without coercing. [ruby-talk:142697] [ruby-talk:143054]
+
+Tue May 24 16:57:24 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (require_libraries): caused SEGV when continuation jumped
+ in to the required library code.
+
+Tue May 24 11:56:25 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/getopts.rb: should warn only if verbose mode.
+ fixed: [ruby-dev:26201]
+
+Tue May 24 06:45:31 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-font-lock-syntactic-keywords): string
+ literals to be matched non-greedy.
+
+Tue May 24 00:34:32 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/soap/calc: method name 'set' was able to crash with a class Set.
+ [ruby-dev:26210]
+
+ * test/wsdl/document/test_rpc.rb: dateTime comparison failed under
+ TZ=right/Asia/Tokyo (with leap second.) [ruby-dev:26208]
+
+Mon May 23 16:24:05 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/extconf.rb: Framework support on MacOS X Tiger.
+
+ * ext/tcltklib/README.1st: add description of Framework support options.
+
+Mon May 23 12:21:37 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (make_regexp): should not return junk address during
+ compile time. [ruby-dev:26206]
+
+Sun May 22 21:54:06 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/{soap,wsdl,xsd}, test/{soap,wsdl,xsd}: imported soap4r/1.5.4.
+
+ == SOAP client and server ==
+
+ === for both client side and server side ===
+
+ * improved document/literal service support.
+ style(rpc,document)/use(encoding, literal) combination are all
+ supported. for the detail about combination, see
+ test/soap/test_style.rb.
+
+ * let WSDLEncodedRegistry#soap2obj map SOAP/OM to Ruby according to
+ WSDL as well as obj2soap. closes #70.
+
+ * let SOAP::Mapping::Object handle XML attribute for doc/lit service.
+ you can set/get XML attribute via accessor methods which as a name
+ 'xmlattr_' prefixed (<foo name="bar"/> -> Foo#xmlattr_name).
+
+ === client side ===
+
+ * WSDLDriver capitalized name operation bug fixed. from
+ 1.5.3-ruby1.8.2, operation which has capitalized name (such as
+ KeywordSearchRequest in AWS) is defined as a method having
+ uncapitalized name. (converted with GenSupport.safemethodname
+ to handle operation name 'foo-bar'). it introduced serious
+ incompatibility; in the past, it was defined as a capitalized.
+ define capitalized method as well under that circumstance.
+
+ * added new factory interface 'WSDLDriverFactory#create_rpc_driver'
+ to create RPC::Driver, not WSDLDriver (RPC::Driver and WSDLDriver
+ are merged). 'WSDLDriverFactory#create_driver' still creates
+ WSDLDriver for compatibility but it warns that the method is
+ deprecated. please use create_rpc_driver instead of create_driver.
+
+ * allow to use an URI object as an endpoint_url even with net/http,
+ not http-access2.
+
+ === server side ===
+
+ * added mod_ruby support to SOAP::CGIStub. rename a CGI script
+ server.cgi to server.rb and let mod_ruby's RubyHandler handles the
+ script. CGIStub detects if it's running under mod_ruby environment
+ or not.
+
+ * added fcgi support to SOAP::CGIStub. see the sample at
+ sample/soap/calc/server.fcgi. (almost same as server.cgi but has
+ fcgi handler at the bottom.)
+
+ * allow to return a SOAPFault object to respond customized SOAP fault.
+
+ * added the interface 'generate_explicit_type' for server side
+ (CGIStub, HTTPServer). call 'self.generate_explicit_type = true'
+ if you want to return simplified XML even if it's rpc/encoded
+ service.
+
+ == WSDL ==
+
+ === WSDL definition ===
+
+ * improved XML Schema support such as extension, restriction,
+ simpleType, complexType + simpleContent, ref, length, import,
+ include.
+
+ * reduced "unknown element/attribute" warnings (warn only 1 time for
+ each QName).
+
+ * importing XSD file at schemaLocation with xsd:import.
+
+ === code generation from WSDL ===
+
+ * generator crashed when there's '-' in defined element/attribute
+ name.
+
+ * added ApacheMap WSDL definition.
+
+ * sample/{soap,wsdl}: removed.
+
+Sun May 22 19:11:35 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/lib/openssl/ssl.rb (OpenSSL::SSL::SSLServer#intialize):
+ should initialize session id context. [ruby-core:4663]
+
+ * ext/openssl/ossl_ssl.c (ossl_sslctx_setup): add session id support.
+
+Sat May 21 10:24:21 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub: tds files were not deleted when DESTDIR
+ included '\' path delimiter. [ruby-dev:26193]
+
+Thu May 19 19:04:29 2005 speakillof <speakillof@yahoo.co.jp>
+
+ * lib/rexml/encodings/SHIFT-JIS.rb: encoding and decoding were
+ swapped. [ruby-core:4772]
+
+Wed May 18 23:42:25 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * error.c (exc_exception): reverted to call Exception#initialize
+ directly. fixed: [ruby-dev:26177]
+
+Wed May 18 23:39:09 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (glob_helper): get rid of using String. [ruby-dev:26180]
+
+ * dir.c (push_braces): should skip balanced braces.
+
+ * eval.c (ruby_options), win32/win32.c (NtInitialize): move argument
+ intialization back. [ruby-dev:26180]
+
+Tue May 17 15:31:31 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpserver.rb (WEBrick::HTTPServer#run): should
+ break the loop if the socket reached to EOF. [ruby-talk:142285]
+
+Tue May 17 11:52:18 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (unixtime_to_filetime): use localtime() instead of
+ gmtime() when using FileLocalTimeToFileTime().
+
+Mon May 16 22:28:43 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.h, {bcc32,win32,wince}/Makefile.sub: moved rb_[ugp]id_t
+ to get rid of redefinition warnings on mingw.
+
+ * class.c (rb_class_init_copy): singleton class is disallowed to copy,
+ from its definition. fixed: [ruby-talk:142749]
+
+Mon May 16 08:52:29 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.{h,c}: define rb_[pgu]id_t.
+
+Mon May 16 00:21:02 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb (Pathname#unlink): use SystemCallError instead of
+ Errno::EISDIR because EISDIR is not portable.
+ [ruby-core:5001]
+
+Sun May 15 22:11:33 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (DRbObject#method_missing): use raise(exception).
+ [ruby-dev:26164]
+
+Sun May 15 18:56:35 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in, ruby.h: define rb_[pgu]id_t macros instead of typedefs
+ to get rid of types which might not be defined yet. [ruby-dev:26165]
+
+Sun May 15 14:35:46 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb (Pathname#unlink): unlink a symlink to a directory
+ was failed. [ruby-core:4992]
+
+Sun May 15 09:57:30 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (unixtime_to_filetime): deal with DST.
+ [ruby-talk:141817]
+
+Sat May 14 23:59:11 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * error.c (exc_exception, {exit,name_err,syserr}_initialize): call
+ Execption#initialize. fixed: [ruby-talk:142593]
+
+Sat May 14 23:57:26 2005 Erik Huelsmann <ehuels@gmail.com>
+
+ * configure.in: Check for the availability of pid_t, gid_t and uid_t and
+ remove AC_TYPE_UID_T. fixed: [ruby-core:04745]
+
+ * defines.h: Remove pid_t typedef.
+
+ * ruby.h: Define rb_pid_t, rb_gid_t and rb_uid_t in accordance with
+ the available system types.
+
+ * process.c: Change instances of pid_t and gid_t to their rb_*
+ counterparts.
+
+ * ext/pty/pty.c: Change pid_t to rb_pid_t.
+
+ * vms/config.h: Define HAVE_{P,G,U}ID_T to 1.
+
+ * win32/Makefile.sub: Remove #define for {g,u}id_t.
+
+ * win32/win32.c: Change pid_t to rb_pid_t.
+
+ * wince/Makefile.sub: Remove #define for {g,u}id_t.
+
+ * wince/sys/types.h: Remove definitions of {p,g,u}id_t.
+
+Fri May 13 23:44:22 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: keep srcdir unexpanded.
+
+ * lib/mkmf.rb (create_makefile): quote topdir and hdrdir if necessary.
+ fixed: [ruby-core:04932]
+
+ * lib/mkmf.rb (configuration), {bcc32,win32,wince}/Makefile.sub: make
+ also INSTALL_PROG and INSTALL_DATA system dependent.
+ fixed: [ruby-core:04931]
+
+Fri May 13 17:54:39 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * variable.c (generic_ivar_get): rb_attr_get should not warn.
+ [ruby-dev:26010]
+
+Fri May 13 12:28:43 2005 Daniel Berger <djberge@qwest.com>
+
+ * array.c (rb_ary_select): can remove argc check. [ruby-core:4911]
+
+ * test/ruby/test_array.rb: add test for find_all.
+
+Fri May 13 11:29:00 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * eval.c (unknown_node): add volatile directive to prototype.
+
+Thu May 12 17:08:48 2005 Tanaka Akira <akr@m17n.org>
+
+ * io.c (rb_io_eof, remain_size, read_all, io_read, appendline)
+ (swallow, rb_io_each_byte, rb_io_getc): revert previous change.
+
+ * io.c (rb_io_eof, io_fread, appendline, swallow, rb_io_each_byte)
+ (rb_io_getc, rb_getc): call clearerr before getc to avoid
+ stdio incompatibility.
+
+Thu May 12 16:52:20 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/rdoc/parsers/parse_c.rb: more readability for mixing
+ progress "c..." and warning message.
+
+Thu May 12 16:31:00 2005 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c: follow nkf 2.0.5
+
+Thu May 12 16:15:01 2005 Tanaka Akira <akr@m17n.org>
+
+ * io.c (rb_io_eof, remain_size, read_all, io_read, appendline)
+ (swallow, rb_io_each_byte, rb_io_getc): don't rely EOF flag.
+ [ruby-talk:141527]
+
+Thu May 12 15:56:20 2005 Tilman Sauerbeck <tilman@code-monkey.de>
+
+ * lib/rdoc/parsers/parse_c.rb: show parsing progress for C files.
+ [ruby-core:4341]
+
+Thu May 12 13:47:56 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * test/drb/test_drb{ssl,unix}.rb: can test drb
+ before install. (backported from HEAD) [ruby-dev:26146]
+
+Thu May 12 09:53:57 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * version.c (ruby_show_version): flush for non-tty stdout.
+
+Thu May 12 09:07:07 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * test/ruby/envutil.rb, test/drb/drbtest.rb: can test drb
+ before install. (backported from HEAD) [ruby-Bugs-1672]
+
+Thu May 12 01:23:55 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_eval), parse.y (arg): reduce fixnum range literal at
+ parser. fixed: [ruby-dev:26113]
+
+ * eval.c (unknown_node): ignore broken NODE to get rid of accessing
+ possibly inaccessible address. fixed: [ruby-dev:26122]
+ should emit more useful information like [ruby-dev:26126], though.
+
+Wed May 11 16:20:01 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb: new methods WEBrick::CGI#[], WEBrick::CGI#logger
+ and WEBrick::CGI#config. (backported from HEAD)
+
+ * lib/webrick/httputils.rb (WEBrick::HTTPUtils.escape_path): should
+ not use String#split("/"). (backported from HEAD)
+
+Wed May 11 15:58:39 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (break_jump): break should not cross functions.
+ [ruby-list:40818]
+
+Wed May 11 10:39:37 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/tempfile.rb (Tempfile#unlink): fixed typo.
+
+Wed May 11 01:03:36 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (TMP_ALLOC): use macro NEW_NODE() to get rid of warnings on
+ platforms which have no alloca(). fixed: [ruby-talk:141301]
+
+Sun May 8 23:17:47 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/timer.rb: fix typo.
+
+Sun May 8 16:52:56 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/profiler.rb: fixed "undefined method `[]' for nil:NilClass"
+ [ruby-core:4775] [ruby-talk:140401] [ruby-dev:26118]
+
+Sat May 7 22:58:00 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (have_var): no libs argument is given.
+
+Sun May 1 09:58:11 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (process_sflag): replace '-' in variable names with '_'.
+ [ruby-dev:26107]
+
+ * ruby.c (set_arg0): use also environment variable space for setting
+ $0. [ruby-core:04774]
+
+Wed Apr 27 23:42:22 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/Makefile.sub (OPTFLAGS): default global optimization to
+ disabled only for VC++6.
+
+Tue Apr 26 22:58:00 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_invoke_core): call Tcl's "::unknown"
+ command when can't get information of target command.
+
+Mon Apr 25 01:18:43 2005 Tanaka Akira <akr@m17n.org>
+
+ * regex.c: declare rb_warn to have variadic argument. [ruby-core:4751]
+
+Sat Apr 23 19:45:59 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_RubyExitCommand): exit with status code
+ via TclTkIp#_eval didn't work. [ruby-talk:139390]
+
+Fri Apr 22 16:41:50 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_set_exc_message): fixed memory leak.
+
+ * ext/tcltklib/tcltklib.c: eTkCallbackReturn was not initialized.
+
+Thu Apr 21 00:07:50 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): support platforms have file separator
+ other than /.
+
+ * {bcc32,win32,wince}/Makefile.sub (BUILD_FILE_SEPARATOR): separator
+ of building platform.
+
+ * {bcc32,win32,wince}/Makefile.sub (CP, INSTALL): use COPY command.
+
+Wed Apr 20 23:22:39 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, common.mk: miniruby depens on MINIOBJS.
+
+ * dmydln.c (dln_load): dummy function to raise LoadError.
+
+ * cygwin/GNUmakefile.in, {bcc32,win32,wince}/Makefile.sub: miniruby
+ can't load extensions on Windows.
+
+Wed Apr 20 23:01:35 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/ifchange.bat: delete testing files.
+
+Wed Apr 20 07:27:18 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * {bcc32,win32,wince}/configure.bat, {bcc32,win32,wince}/setup.mak:
+ add extout option.
+
+ * bcc32/setup.mak: make configuration variables overridable.
+
+Wed Apr 20 04:15:27 2005 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * lib/irb.rb lib/irb/* doc/irb: IRB 0.9.5
+
+Tue Apr 19 23:37:09 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/ftools.rb (File.safe_unlink): do not modify a symlinked file.
+
+Tue Apr 19 00:06:20 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: expand path for ext/**/extconf.rb.
+
+Mon Apr 18 11:25:14 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/zlib/zlib.c (zstream_run): fixed SEGV. [ruby-core:4712]
+
+Sun Apr 17 23:57:49 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake, parse_args): do not expand destdir.
+
+ * ext/extmk.rb (relative_from): treat mere drive letter as an absolute
+ path.
+
+Sat Apr 16 17:01:16 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * sample/rss/tdiary_plugin/rss-recent.rb (rss_recent_cache_rss):
+ use the first date information of items as site date information
+ if channel doesn't have date information.
+
+Sat Apr 16 15:27:03 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_PROG_INSTALL): not add -p option to INSTALL.
+ files need timestamps to be kept are only ar-archive on a few
+ platforms, and be installed by instruby.rb but not INSTALL.
+ fixed: [ruby-core:04721]
+
+ * mkconfig.rb: purge autoconf value variables.
+
+Sat Apr 16 10:36:01 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub: quick hack... prepend DESTDIR.
+ still have restriction on DESTDIR ("", "/", "e:")
+
+Sat Apr 16 03:59:42 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/extconf.rb: check for OPENSSL_cleanse.
+
+ * ext/openssl/openssl_missing.h: ditto.
+
+Thu Apr 14 19:18:30 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (remove_file): ignore exceptions caused by
+ chmod.
+
+ * lib/fileutils.rb (remove_dir): try to get rights to rmdir.
+ [ruby-Bugs:1502] (2 items backportted from HEAD, rev 1.53-54)
+
+Thu Apr 14 16:57:40 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bcc32/Makefile.sub: failed to remove debug information files.
+ fixed: [ruby-dev:26034]
+
+Wed Apr 13 23:40:21 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb (RSS::VERSION): 0.1.3 -> 0.1.4.
+
+ * lib/rss/rss.rb (RSS::Element#converter): fixed converter
+ transmission bug.
+
+Wed Apr 13 21:20:35 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (mingw32): extract msvcr*.dll from objdump result.
+
+Wed Apr 13 20:24:30 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (mingw32): use actual runtime DLL name as ruby DLL
+ name and default load path.
+
+ * win32/Makefile.sub, win32/setup.mak: ditto.
+
+Tue Apr 12 15:33:09 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_finalize): better modification than the
+ previous commit [ruby-dev:26029].
+
+Tue Apr 12 12:38:06 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_finalize): fix SEGV when Tcl_GlobalEval()
+ modifies the argument string to eval.
+
+Tue Apr 12 02:21:55 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_finalize): add existence check of
+ Tcl commands before calling Tcl_GlobalEval().
+
+Mon Apr 11 23:47:21 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: [druby-ja:123] fix: When reference of my object is
+ loaded, the object is tainted.
+
+ * test/drb/test_drb.rb: ditto.
+
+Mon Apr 11 22:18:23 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dir.c, file.c (lstat): avoid warnings for mingw.
+
+Mon Apr 11 20:11:06 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_finalize): adhoc patch to avoid SEGV
+ when exit on Tcl/Tk8.3.x.
+
+Mon Apr 11 15:26:25 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/mkmf.rb (configuration): shouldn't output hdrdir twice.
+
+Mon Apr 11 12:09:05 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * {bcc32,win32,wince}/Makefile.sub: ri data was not installed
+ into correct path. [ruby-dev:26011]
+
+ * bcc32/Makefile.sub: defaulted install-nodoc. [ruby-dev:26011]
+
+Sun Apr 10 10:12:42 2005 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c(ole_invoke): retry after converting Qnil
+ to VT_EMPTY.
+
+ * ext/win32ole/win32ole/tests/testWIN32OLE.rb: correct error
+ message string "Unknown" => "unknown".
+
+Sat Apr 9 18:20:31 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/image.rb: support to create TkImage object without
+ creating a new image object on Tk.
+
+ * ext/tk/lib/tk/menu.rb: use TkCommandNames on create_self()
+
+ * ext/tk/lib/tk/root.rb: TkRoot.to_eval() returns '.'.
+
+ * ext/tk/lib/tk/text.rb: add methods to create a TkText::IndexString
+ from (x, y) coords.
+
+ * ext/tk/lib/tkextlib/tile/: add demo and update support status.
+
+Sat Apr 9 14:42:29 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * sample/rss/tdiary_plugin/rss-recent.rb: supported configuration
+ via Web browser.
+
+Sat Apr 9 11:59:57 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss: backoported from HEAD.
+
+ * lib/rss: refactored.
+ - gave a name to 'x'.
+ - undef_method -> remove_method for avoiding a warning in ruby 1.6.
+
+ * lib/rss/parser.rb: @@setter -> @@setters.
+
+ * lib/rss/parser.rb
+ (RSS::BaseListener.register_uri)
+ (RSS::BaseListener.uri_registered?)
+ (RSS::BaseListener.install_get_text_element):
+ swapped the first argument and the second argument.
+
+ * lib/rss/taxonomy.rb: swapped the first argument and the second
+ argument for RSS::BaseListener.install_get_text_element.
+ * lib/rss/image.rb: ditto.
+ * lib/rss/syndication.rb: ditto.
+ * lib/rss/dublincore.rb: ditto.
+ * lib/rss/parser.rb: ditto.
+ * lib/rss/1.0.rb: ditto.
+ * lib/rss/2.0.rb: ditto.
+ * lib/rss/0.9.rb: ditto.
+ * lib/rss/content.rb: ditto.
+
+ * lib/rss/parser.rb
+ (RSS::BaseListener.install_setter)
+ (RSS::BaseListener.register_uri): changed fallback way.
+
+ * lib/rss/parser.rb: added class name registry for complex model
+ elements. (ex. have childlen elements, have some attributes and
+ a child element and so on.)
+
+ * lib/rss/dublincore.rb: supported multiple Dublin Core items.
+ * lib/rss/maker/dublincore.rb: ditto.
+
+ * lib/rss/maker/image.rb: supproted new Dublin Core API.
+
+ * lib/rss/maker/base.rb: added default current_element implementation.
+
+ * lib/rss/trackback.rb (RSS::TrackBackUtils.new_with_value_if_need):
+ moved to RSS::Utils.
+
+ * lib/rss/utils.rb (RSS::Utils.new_with_value_if_need):
+ moved from RSS::TrackBackUtils.
+
+ * lib/rss/maker/image.rb: fixed invalid argument of
+ add_need_initialize_variable bug.
+ * lib/rss/maker/trackback.rb: ditto.
+
+ * lib/rss/rss.rb (Hash#merge): added for ruby 1.6.
+
+ * lib/rss/rss.rb (RSS::BaseModel.date_writer): changed to accept nil
+ for date value.
+
+ * test/test_dublincore.rb: added tests for plural accessor and
+ multiple Dublin Core items.
+
+ * test/test_setup_maker_1.0.rb: fixed swapped actual and expected
+ values.
+
+ * test/rss/rss-assertions.rb (assert_multiple_dublin_core): added
+ an assertion for testing multiple Dublin Core items.
+
+ * test/rss/test_maker_dc.rb (test_rss10_multiple): added a test
+ for making multiple Dublin Core items.
+
+ * test/rss/test_maker_dc.rb (test_date): added a test for #date=
+ and #dc_date=.
+
+ * sample/rss/tdiary_plugin/rss-recent.rb:
+ new option: @options['rss-recent.use-image-link']:
+ use image as link instread of text if available.
+
+ * sample/rss/tdiary_plugin/rss-recent.rb (RSS_RECENT_VERSION):
+ 0.0.5 -> 0.0.6.
+
+Fri Apr 8 20:17:48 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake): hdrdir needs to be defined also in
+ Config::CONFIG.
+
+ * lib/mkmf.rb (configuration, create_makefile): get rid of recursive
+ macro reference.
+
+Fri Apr 8 18:26:56 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ssl.c: add callbacks to OpenSSL::SSL::SSLContexts.
+ - SSLContext#client_cert_cb=(aProc). it is called when a client
+ certificate is requested by a server and no certificate was not
+ set for the SSLContext. it must return an Array which includes
+ OpenSSL::X509::Certificate and OpenSSL::PKey::RSA/DSA objects.
+ - SSLContext#tmp_dh_callback=(aProc). it is called in key
+ exchange with DH algorithm. it must return an OpenSSL::PKey::DH
+ object.
+
+ * ext/openssl/ossl_ssl.c (ossl_sslctx_set_ciphers): ignore the
+ argument if it's nil.
+
+ * ext/openssl/ossl_pkey.c
+ (GetPrivPKeyPtr, ossl_pkey_sign): should call rb_funcall first.
+ (DupPrivPKeyPtr): new function.
+
+ * ext/openssl/ossl_pkey_dh.c: add default DH parameters.
+
+ * ext/openssl/ossl_pkey.h: ditto.
+
+Fri Apr 8 01:55:20 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/demos-{en,jp}/goldberg.rb: reduced window size.
+ [ruby-dev:25992]
+
+Thu Apr 7 23:58:40 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake): keep directory names in Makefile as macros.
+
+ * lib/mkmf.rb (configuration, create_makefile): ditto.
+
+ * lib/mkmf.rb (CXX_EXT): separate C++ extensions.
+
+Thu Apr 7 17:43:25 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * eval.c (rb_call0): "return" event hook should be always executed
+ if event_hooks is set. fixed: [ruby-core:04662]
+ (backported from HEAD)
+
+Mon Apr 4 23:17:52 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb (TkComm#array2tk_list): accept enc-mode argument to
+ decide whether convert encoding of each element or not.
+
+ * ext/tk/lib/tk/variable.rb (TkVariable#value=): fail to convert the
+ encoding of array elements when assign an array to an TkVariable
+ object.
+
+Mon Apr 4 10:26:48 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tk/lib/tk/dialog.rb: fixed typo.
+
+Sun Apr 3 17:16:33 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.{h,c} (rb_w32_fdopen): avoid warning on bcc32.
+ (backported from HEAD)
+
+Sat Apr 2 23:38:54 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (CP, INSTALL): get rid of less portable options.
+
+ * lib/mkmf.rb (configuration, create_makefile): correct configuration
+ variable.
+
+ * {bcc32,win32,wince}/{Makefile.sub,setup.mak}: leave prefix empty in
+ config.status for backward compatibility. fixed: [ruby-core:04649]
+
+ * lib/mkmf.rb (create_makefile): ensure library directories get made
+ before copying libraries there.
+
+Sat Apr 2 16:59:46 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: forgot to update RELEASE_DATE
+
+ * ext/tk/lib/tk/variable.rb: fix namespace trouble when autoloading
+
+ * ext/tk/lib/tk/palette.rb: define Tcl variable 'tkPalette' as global
+
+ * ext/tk/lib/tk/dialog.rb: use array2tk_list method when calling
+ Tk.ip_eval.
+
+ * ext/tk/lib/tk/autoload.rb: add autoload entry 'TkDialogObj' and
+ 'TkWarningObj'
+
+Sat Apr 2 02:19:11 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb (TkWindow.initialize): accept 'without_creating'
+ option without 'widgetname' option to allow creating a widget object
+ which is used as an argument of Tcl/Tk's widget allocation commands.
+
+ * ext/tk/lib/tk/image.rb (TkImage.initialize): accept 'imagename'
+ option to create a image object by the given name.
+
+Thu Mar 31 22:23:51 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (SRC_EXT): exclude just case different suffixes on case
+ insensitive file system platforms.
+
+ * README.EXT, README.EXT.ja (Appendix C): utility functions.
+
+Thu Mar 31 14:15:44 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_engine.c (ossl_engine_s_load): should return
+ value. [ruby-dev:25971]
+
+Thu Mar 31 08:25:50 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (RUBYOPT): clear for the environment RubyGems installed.
+
+ * common.mk (clean-local): keep $(PREP) files till distclean.
+
+ * common.mk (check): do all tests.
+
+Thu Mar 31 06:00:20 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_engine.c (ossl_engine_s_load): should not raise
+ error even if the specified engine could not be loaded. (Dynamic
+ engines don't have fixed name to load.)
+
+Thu Mar 31 00:18:27 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/ifchange.bat, win32/rm.bat: backported from HEAD.
+
+Wed Mar 30 23:44:50 2005 Nobuyoshi Nakada <nobu.nokada@softhome.net>
+
+ * Makefile.in, */Makefile.sub, */configure.bat,
+ cygwin/GNUmakefile.in, common.mk, configure.in, ext/extmk.rb,
+ lib/mkmf.rb, instruby.rb, runruby.rb: backport extout.
+ [ruby-dev:25963]
+
+Wed Mar 30 17:41:48 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: add TclTkIp#_create_console() method to
+ create a Tcl/Tk's console window.
+
+ * ext/tk/lib/multi-tk.rb: support TclTkIp#_create_console() method.
+
+ * ext/tk/lib/remote-tk.rb: ditto.
+
+ * ext/tk/lib/tk/console.rb: ditto.
+
+ * ext/tk/lib/tk.rb: update RELEASE_DATE
+
+ * ext/tk/sample/demo-*/check2.rb: use 'return' in the Proc object.
+
+ * ext/tk/sample/tkextlib/**: ditto.
+
+Tue Mar 29 22:11:56 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/rinda/test_rinda.rb: use DRbObject.new_with instead of reinit.
+ [ruby-dev:25961]
+
+Mon Mar 28 23:40:40 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: move method DRbObject#reinit to DRbObject.new_with.
+ extract method DRbObject.prepare_backtrace. add DRb.regist_server,
+ remove_server, fetch_server. change server in thread variable if
+ in-proc server. [druby-ja:113]
+
+ * lib/drb/gw.rb: ditto.
+
+Mon Mar 28 20:43:34 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/syck/rubyext.c: get rid of warnings caused by a bug of VC.
+
+Mon Mar 28 08:39:49 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (iconv_create): Iconv::Failure requires 3
+ arguments. (pointed out by NaHi)
+
+Sat Mar 26 22:51:33 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb (_callback_entry_class?): add for checking whether
+ a class is available for a callback entry.
+
+ * ext/tk/lib/tk.rb (after_cancel): add Tk.after_cancel(afterID) method.
+
+ * ext/tk/lib/tk.rb (array2tk_list): change from private module method
+ of TkComm to public module method.
+
+ * ext/tk/lib/tk.rb (cget): add check that slot argument is not
+ empty string.
+
+ * ext/tk/lib/tk.rb (configinfo): ditto.
+
+ * ext/tk/lib/tk/itemconfig.rb (itemcget): add check that slot argument
+ is not empty string.
+
+ * ext/tk/lib/tk/itemconfig.rb (itemconfiginfo): ditto.
+
+ * ext/tk/lib/tk/entry.rb: add TkEntry#icursor and icursor= (alias of
+ cursor and cursor= method).
+
+ * ext/tk/lib/tk/font.rb: improve font treatment when the font name is
+ empty string.
+
+ * ext/tk/lib/tk/variable.rb: add :variable, :window and :procedure
+ type.
+
+ * ext/tk/lib/tk/variable.rb: improve treatment of array-type
+ tkvariable.
+
+ * ext/tk/lib/tkextlib/blt.rb: add commands for zooming.
+
+ * ext/tk/lib/tkextlib/blt/*: bug fix.
+
+ * ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: bug fix and add methods
+ to call TreeCtrl commands for bindings.
+
+ * ext/tk/sample/tkextlib/blt/*: new sample scripts.
+
+ * ext/tk/sample/tkextlib/treectrl/*: ditto.
+
+Fri Mar 25 10:53:16 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (WIN32_LEAN_AND_MEAN): removed because a lot of
+ troubles. [ruby-list:40721]
+
+Thu Mar 24 23:10:44 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (macro_defined?): try to compile for an old compiler
+ which doesn't bail out at #error directive. [ruby-dev:25818]
+
+ * lib/mkmf.rb (check_sizeof): refine logging messages.
+
+Thu Mar 24 03:57:48 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/utils.rb (WEBrick::Utils.create_listeners):
+ - should raise ArgumentError if no port is specified.
+ - even if the specified port is 0, all TCPServers should be
+ initialized with the port given to the first one.
+
+ * lib/webrick/server.rb (WEBrick::GenericServer#initialize): if :Port
+ parameter is 0, it should be updated with the port number which
+ actually listened.
+
+Wed Mar 23 00:35:10 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * test/ruby/test_settracefunc.rb (test_event): added tests for
+ "class" and "end" and "raise".
+
+Tue Mar 22 22:40:18 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * eval.c (rb_call0): check event_hooks instead of trace_func.
+
+Tue Mar 22 17:30:44 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * eval.c (rb_add_event_hook): new function to add a hook function for
+ interpreter events. (backported form HEAD)
+
+Sun Mar 20 22:51:19 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (mkmf_failed): check if Makefile is created without
+ create_makefile.
+
+Sat Mar 19 23:48:10 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-expr-beg): returned true always.
+ fixed: [ruby-list:40683]
+
+Sat Mar 19 00:41:02 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/font.rb: add some TkFont class methods to get font
+ information without creating a TkFont object.
+
+ * ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: bug fix and define some
+ classes for components of Tk::TreeCtrl
+
+Thu Mar 17 17:42:13 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (make_struct): allow non local-id field
+ names. [ruby-core:04575]
+
+ * struct.c (inspect_struct): ditto.
+
+Wed Mar 16 23:36:02 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * eval.c (rb_call0): call_cfunc() should be protected.
+
+ * test/ruby/test_settracefunc.rb: added test for c-return.
+
+Wed Mar 16 22:20:25 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * object.c (str_to_id): fixed typo.
+
+Wed Mar 16 18:08:32 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call0): reorganize "return" event post.
+
+Tue Mar 15 23:49:19 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (Init_iconv): InvalidEncoding also should include
+ Iconv::Failure.
+
+Tue Mar 15 16:38:11 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil.c (ary2list): give wrong arguments to hash2kv()
+
+Mon Mar 14 19:39:33 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/timer.rb (TkTimer): forgot to clear @return_value
+ when restarting
+
+ * ext/tk/lib/tk/sample/cd_timer.rb: new sample of TkRTTimer
+
+Mon Mar 14 12:21:03 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/timer.rb (TkRTTimer): forgot to reset the callback
+ time. So, 'continue' do all callbacks between 'stop' and 'continue'.
+
+Mon Mar 14 08:14:56 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (str_to_id): warn for NUL containing strings.
+
+Mon Mar 14 00:13:49 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/timer.rb (TkRTTimer): correct calculation of offset
+ value. get a little better accuracy.
+
+ * ext/tk/sample/demos-en/widget: use a binding with no local variables
+ when eval a sample script.
+
+ * ext/tk/sample/demos-en/bind.rb: ditto.
+
+ * ext/tk/sample/demos-en/tcolor: ditto.
+
+ * ext/tk/sample/demos-jp/widget: ditto.
+
+ * ext/tk/sample/demos-jp/bind.rb: ditto.
+
+ * ext/tk/sample/demos-jp/tcolor: ditto.
+
+Sun Mar 13 10:04:17 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/rinda/test_rinda.rb: remove test_gc. [ruby-dev:25871]
+
+Thu Mar 10 19:12:06 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (lib_eventloop_ensure): mis-delete a timer
+ handler when exit from a recursive called eventloop
+
+ * ext/tk/lib/tk/timer.rb: new TkRTTimer class, which can works for a
+ realtime operation
+
+ * ext/tk/sample/tkrttimer.rb: sample of TkRTTimer class
+
+ * ext/tk/lib/tk/textmark.rb: move TkTextMark#+ and TkTextMark#- to
+ TkText::IndexModMethods
+
+ * ext/tk/lib/tk/text.rb: improve TkTextMark#+ and TkTextMark#-, and
+ add them to TkText::IndexModMethods module
+
+ * ext/tk/sample/tktextio.rb: add test part of "seek by text index
+ modifiers"
+
+Thu Mar 10 08:10:11 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (make_regexp): need to free internal regexp structure when
+ compilation fails. [ruby-talk:133228]
+
+Wed Mar 9 20:25:58 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ssl.c (ossl_start_ssl, ossl_ssl_write): call
+ rb_sys_fail if errno isn't 0. [ruby-dev:25831]
+
+ * ext/openssl/lib/openssl/cipher.rb: fix typo. [ruby-dev:24285]
+
+Wed Mar 9 15:46:35 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/server.rb (WEBrick::GenericServer#start): should
+ restore @token if accept failure. suggested by Dominique Brezinski.
+ [ruby-core:04518]
+
+Wed Mar 9 13:37:57 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/tktextio.rb: fix bug of handling 'end' position.
+ support initial text, overwrite setting and pos_gravity control.
+
+Tue Mar 8 18:16:55 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/tktextio.rb: New sample script. TkTextIO class in this
+ sample supports to use a text widget as if it is a I/O stream (such
+ like as StringIO class).
+
+Tue Mar 8 13:54:40 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/socket/socket.c: workaround for some of 4.4BSD-Lite derived OSs.
+
+Tue Mar 8 12:36:17 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c: document from Sam Roberts
+ <sroberts@uniserve.com> for getsockopt and setsockopt is merged.
+ [ruby-doc:824]
+
+Tue Mar 8 01:27:00 2005 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c: follow nkf 1.66
+ fixed: [ruby-dev:25828]
+
+Mon Mar 7 21:35:02 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * sample/webrick/httpsd.rb: fix typo in comment. suggested by
+ Kazuhiko Shiozaki.
+
+Mon Mar 7 14:55:43 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (block_pass): should not push unique number if a block is
+ not an orphan. [ruby-dev:25808]
+
+Wed Feb 16 02:55:21 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ssl.c (ossl_start_ssl, ossl_ssl_read,
+ ossl_ssl_write):
+ - need to set errno on Win32 platform.
+ - should call rb_sys_fail instead of rasing SSLError if
+ SSL_ERROR_SYSCALL occured.
+ - should wait for that the underlying IO become readable or
+ writable if the error was SSL_ERROR_WANT_READ or
+ SSL_ERROR_WANT_WRITE. [ruby-dev:25795]
+
+ * ext/openssl/lib/openssl/buffering.rb
+ (Buffering#initialize): should set @eof and @rbuffer.
+ (Buffering#fill_rbuff): should rescue Errno::EAGAIN.
+ (Buffering#consume_rbuf): pointless eof flag resetting is deleted.
+ (Buffering#read): should return an empty string if the specified
+ size is zero.
+ (Buffering#readpartial): new method.
+ (Buffering#readline): fix typo.
+ (Buffering#getc): return the first character of string correctly.
+ (Buffering#each): fix typo. suggested by Brian Ollenberger.
+ (Buffering#readchar): fix typo.
+ (Buffering#eof?): should read again it the input buffer is empty.
+ (Buffering#do_write): should rescue Errno::EAGAIN.
+ (Buffering#puts): use "\n" as the output field separator.
+
+ * ext/openssl/lib/openssl/ssl.rb: set non-blocking flag to the
+ underlying IO.
+
+ * ext/openssl/extconf.rb: get rid of GNUmakefile generation.
+
+ * text/openssl/test_pair.rb: test for IO like methods.
+
+ * test/ruby/ut_eof.rb: test about empty file.
+
+Mon Mar 7 10:22:06 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/un.rb: should use OptionParser. (backported form HEAD)
+
+Mon Mar 7 09:18:42 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_cmp_m): should not return false but nil.
+ fixed: [ruby-dev:25811]
+
+Mon Mar 7 01:22:14 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil.c: remove the some codes which depend on the
+ difference between Ruby1.8 and 1.9, because st.c on Ruby1.9
+ was changed.
+
+Mon Mar 7 00:01:04 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: fail to call TclTkLib.mainloop when $SAFE==4
+
+Sun Mar 6 16:41:33 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/http.rb: HTTPHeader holds its header fields as an array
+ (backport from CVS HEAD rev 1.112-1.123). [ruby-list:40629]
+
+ * test/net/http/test_httpheader.rb: new file.
+
+Sun Mar 6 11:47:10 2005 Sam Roberts <sroberts@uniserve.com>
+
+ * lib/pp.rb: rdoced. [ruby-core:4490]
+
+Sun Mar 6 11:36:37 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/pp.rb (File::Stat#pretty_print): Etc.getpwuid and Etc.getgrgid
+ may return nil. [ruby-talk:129826]
+ reported by Daniel Berger.
+
+Sat Mar 5 18:06:21 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * dir.c (fnmatch): removed unnecessary code. (ruby_1_8 didn't have
+ String#clear, so [ruby-dev:24749] didn't affect it)
+
+ * win32/win32.c (NtInitialize): ditto. (by numeric.c 1.101.2.14)
+
+Sat Mar 5 16:29:26 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: freeze callback-entry objects
+
+ * ext/tk/lib/tkextlib/tile.rb: support tile-0.6
+
+Fri Mar 4 19:39:28 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#do_includes): replace
+ also locally defined modules.
+
+ * ext/iconv/iconv.c: backport Iconv::InvalidEncoding from CVS HEAD.
+
+ * ext/strscan/strscan.c: moved misplaced rdoc.
+
+Fri Mar 4 15:58:12 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi-lib.rb: add deprecation warning. [ruby-dev:25499]
+ getopts.rb, parsearg.rb, importenv.rb as well.
+
+Fri Mar 4 11:17:06 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_rbUpdateCommand): get rid of
+ warnings with Tcl/Tk 8.3 or former (backport from CVS_HEAD).
+
+ * ext/tcltklib/tcltklib.c (ip_rb_threadUpdateCommand): ditto.
+
+Fri Mar 4 10:15:30 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/set.rb (SortedSet::setup): a hack to shut up warning.
+ [ruby-talk:132866]
+
+Fri Mar 4 07:07:00 2005 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c: follow nkf 1.63
+
+Thu Mar 3 23:49:00 2005 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c: follow nkf 1.62
+
+Thu Mar 3 11:49:51 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * sample/rss/tdiary_plugin/rss-recent.rb: added site information.
+
+Wed Mar 2 19:53:07 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (parse_args): add DESTDIR only when not directed
+ already. fixed: [ruby-dev:25781]
+
+Wed Mar 2 17:14:18 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (lib_eventloop_core): fix typo
+
+Wed Mar 2 16:00:02 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: enforce thread-check and exception-handling
+ to avoid SEGV trouble.
+ [KNOWN BUG] When supports pthread and running multiple Tk
+ interpreters, an interrupt signal causes SEGV frequently. That
+ may be a trouble of Ruby's signal handler.
+
+ * ext/tk/tkutil/tkutil.c; fix a bug on converting a SJIS string array
+ to a Tcl's list string.
+
+ * ext/tk/tcltklib.c: wrap Tcl's original "namespace" command to
+ protect from namespace crash.
+
+ * ext/tk/lib/multi-tk.rb: enforce exception-handling.
+
+ * ext/tk/lib/multi-tk.rb: catch IRB_EXIT to work on irb.
+
+ * ext/tk/lib/tk.rb: ditto.
+
+ * ext/tk/tcltklib.c: add TclTkLib.mainloop_thread?
+
+ * ext/tk/lib/multi-tk.rb: (bug fix) callback returns a value.
+
+ * ext/tk/lib/tk/canvas.rb (delete): bug fix when multiple arguments.
+
+ * ext/tk/lib/clock.rb: fix 'no method error'.
+
+ * ext/tk/lib/clock.rb (self.clicks): accept a Symbol argument.
+
+ * ext/tk/lib/variable.rb: be able to set default_value_type; :numeric,
+ :bool, :string, :symbol, :list, :numlist or nil (default; same to
+ :string). If set a type, TkVariable#value returns a value of the
+ type.
+
+ * ext/tk/lib/tkextlib/tclx/tclx.rb: add Tk::TclX.signal to warn the
+ risk of using TclX extension's 'signal' command.
+
+ * ext/tk/sample/irbtk.rb: irb with Ruby/Tk.
+
+ * ext/tk/sample/demos-*/anilabel.rb: bug fix on 'show code'
+
+ * ext/tk/sample/demos-*/aniwave.rb: new Ruby/Tk animation demo.
+
+ * ext/tk/sample/demos-*/pendulum.rb: ditto.
+
+ * ext/tk/sample/demos-*/goldberg.rb: ditto.
+
+ * ext/tk/sample/demos-*/widget: add entries of animation demos.
+
+Tue Mar 1 00:47:43 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/rinda/test_rinda.rb: backport from CVS_HEAD. use
+ MockClock.sleep instead of Kernel.sleep [ruby-dev:25387]
+
+Tue Mar 1 00:34:24 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (Rinda::TupleSpace): improved keeper thread.
+
+ * test/rinda/test_rinda.rb: ditto.
+
+Mon Feb 28 11:42:23 2005 Ian Macdonald <ian@caliban.org>
+
+ * exception error messages updated. [ruby-core:04497]
+
+Mon Feb 28 09:03:09 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (Init_socket): add bunch of Socket
+ constants. Patch from Sam Roberts <sroberts@uniserve.com>.
+ [ruby-core:04409]
+
+Wed Feb 23 15:04:32 2005 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/generic.rb (split_userinfo): should split ":pass" into ""
+ and "pass". [ruby-dev:25667]
+
+Wed Feb 23 08:00:18 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_s_create): no need for negative argc check.
+ [ruby-core:04463]
+
+ * array.c (rb_ary_unshift_m): ditto.
+
+Wed Feb 23 01:57:46 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (initialize): handle certs correctly. Thanks,
+ NABEYA Kenichi. (backported from CVS HEAD)
+
+Tue Feb 22 07:25:18 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (parser_yylex): identfier after dot must not be a variable.
+
+Mon Feb 21 10:04:49 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32,wince}/Makefile.sub (config.h): add fcntl.
+
+ * win32/win32.[ch] (fcntl): ditto.
+
+ * win32/win32.c (rb_w32_connect): support nonblocking mode.
+
+ * ext/socket/socket.c (wait_connectable, ruby_connect): support
+ nonblocking connect on various platforms.
+ all changes are backported from CVS HEAD. [ruby-core:3154],
+ [ruby-core:4364].
+
+Sun Feb 20 00:48:48 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb (URI::FTP#buffer_open): access mechanism
+ re-implemented according to RFC 1738.
+ reported by Guillaume Marcais. [ruby-talk:131650]
+
+Sat Feb 19 18:11:47 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (DRbObject#respond_to?): take two arguments.
+ [ruby-dev:25722]
+
+ * test/drb/drbtest.rb: ditto.
+
+Sat Feb 19 13:52:02 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb: call OpenSSL::SSL::SSLSocket#post_connection_check
+ after connection is made.
+
+Sat Feb 19 01:32:03 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/bigdecimal/lib/bigdecimal/newton.rb: resolved LoadError.
+ [ruby-dev:25685]
+
+ * ext/bigdecimal/sample/linear.rb: ditto.
+
+ * ext/bigdecimal/sample/nlsolve.rb: ditto.
+
+ * ext/bigdecimal/lib/bigdecimal/nlsolve.rb: removed because this file
+ is sample script and same file exists in ext/bigdecimal/sample.
+
+Fri Feb 18 17:14:00 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
+ of StandardError class, not Exception class. [ruby-core:04429]
+
+Thu Feb 17 20:11:18 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/drb/drb.rb (DRbServer.default_safe_level): fix typo.
+
+Thu Feb 17 20:11:18 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/digest/test_digest.rb: separate test case for each algorithms.
+ [ruby-dev:25412]
+
+Thu Feb 17 11:54:00 2005 Nathaniel Talbott <ntalbott@ruby-lang.org>
+
+ * lib/test/unit/collector.rb (collect_file): now deletes paths added
+ to $LOAD_PATH instead of restoring it verbatim.
+
+ * lib/test/unit/autorunner.rb (AutoRunner.run): fixed so that
+ 'ruby -rtest/unit -rtest1 -rtest2 -e0' will use the objectspace
+ collector again. Also tried to simplify the calling convention.
+
+ * test/runner.rb: adjusted for new AutoRunner semantics.
+
+ * lib/test/unit.rb: ditto.
+
+Thu Feb 17 04:21:47 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
+ fixed: [ruby-core:04444]
+
+Thu Feb 17 00:09:45 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/drb/ignore_test_drb.rb: move TestDRbReusePort to new file
+ [ruby-dev:25238]
+
+ * test/drb/test_drb.rb: add method DRbService.ext_service, move
+ TestDRbReusePort to new file [ruby-dev:25238]
+
+ * test/drb/test_drb.rb: ditto.
+
+ * test/drb/test_drbssl.rb: ditto.
+
+ * test/drb/test_drbunix.rb: ditto.
+
+ * test/drb/ut_drb.rb: reduce sleep.
+
+Thu Feb 17 00:02:27 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (is_defined): NODE_IASGN is an assignment.
+
+Wed Feb 16 23:34:30 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: add lazy stop_service. ([druby-ja:109])
+
+ * lib/drb/extserv.rb: ditto.
+
+Wed Feb 16 17:07:57 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil.c: Follow the change of st.c (st_foreach)
+ [ruby-list:40623].
+ Sometimes mis-convert from a Ruby's Array of SJIS Strings, which
+ includes some kind of SJIS characters, to a Tcl's UTF8 list string.
+
+Mon Feb 14 23:58:17 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/parser.rb (RSS::ListenerMixin::tag_end):
+ fixed invalid namespace handling bug.
+
+Mon Feb 14 13:12:38 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/lib/openssl/ssl.rb
+ (OpenSSL::SSL::SSLSocket#post_connection_check): new method.
+
+Mon Feb 14 00:40:49 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (InvokeMethod.perform): pass DRb info to sub thread.
+
+ * test/drb/test_drb.rb (test_01_safe1_safe4_eval): fix test case.
+
+Sun Feb 13 23:13:46 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/dublincore.rb (RSS::DublicCoreModel#date{,=}): added
+ convenient methods.
+
+ * lib/rss/0.9.rb (RSS::Rss::Channel#date{,=}): ditto.
+
+ * lib/rss/2.0.rb (RSS::Rss::Channel::Item#date{,=}): ditto.
+
+ * test/rss/: added tests for the convenient methods.
+
+Sun Feb 13 22:43:03 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (DRbServer): add default_safe_level, safe_level,
+ config[:safe_level] ([druby-ja:120])
+
+ * test/drb/test_drb.rb, ut_eval.rb, ut_safe1.rb: ditto.
+
+Sun Feb 13 16:56:52 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb (WEBrick::CGI.start): should set reason-phrase
+ to the value of status header field. ([ruby-dev:40617])
+
+Sun Feb 13 00:52:33 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb (ERB::Util.h, u): make it module_function.
+
+Sat Feb 12 17:29:19 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb (OpenURI.open_loop): send authentication only for
+ the URI directly specified.
+
+Sat Feb 12 15:07:23 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * random.c (rand_init): suppress warning.
+
+Sat Feb 12 13:54:03 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb: support https if the platform provides CA
+ certificates.
+
+Sat Feb 12 06:18:28 2005 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
+
+ * ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check.
+ [ruby-dev:25675]
+
+Fri Feb 11 17:40:42 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_x509store.c (ossl_x509store_set_default_paths):
+ new method OpenSSL::X509::Store#set_default_paths.
+
+Fri Feb 11 11:33:53 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb (URI::HTTP#proxy_open): new option supported:
+ :http_basic_authentication.
+ suggested by Kent Sibilev. [ruby-core:4392]
+
+Fri Feb 11 06:30:07 2005 George Ogata <g_ogata@optushome.com.au>
+
+ * misc/ruby-mode.el: ignore parenthesis inside heredoc.
+ [ruby-core:04415]
+
+Fri Feb 11 04:54:13 2005 Tilman Sauerbeck <tilman@code-monkey.de>
+
+ * lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
+
+ * lib/rdoc/generators/ri_generator.rb: ditto.
+
+Thu Feb 10 11:14:17 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub (COMMON_HEADERS): shouldn't include winsock2.h.
+
+ * ext/socket/extconf.rb (sockaddr_storage): remove workaround for
+ mswin32.
+
+Thu Feb 10 10:29:16 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/curses/curses.c: don't need to check HAVE_WCOLOR_SET excluding
+ window_color_set().
+
+Thu Feb 10 00:47:25 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (make_struct): fixed: [ruby-core:04402]
+
+Wed Feb 9 08:07:08 2005 Paul Duncan <pabs@pablotron.org>
+
+ * ext/curses/curses.c (window_color_set): [ruby-core:04393]
+
+Tue Feb 8 23:51:47 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: reject :instance_eval, :class_eval, :module_eval
+ [druby-ja:117]
+
+Tue Feb 8 13:06:12 2005 Sam Roberts <sroberts@uniserve.com>
+
+ * ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
+ [ruby-talk:130092]
+
+Tue Feb 8 09:30:01 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::Cookie): [ruby-talk:130040]
+
+Tue Feb 8 00:19:02 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/resolv.rb (Resolv::DNS::Name#subdomain_of?): new method.
+ (Resolv::DNS::Name#inspect): ditto.
+ Suggested by Sam Roberts. [ruby-talk:129086]
+
+Mon Feb 7 10:06:30 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c: [ruby-doc:818]
+
+Mon Feb 7 01:56:20 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * instruby.rb, rubytest.rb (srcdir): no longer embed srcdir into
+ rbconfig.rb. (backported from CVS HEAD)
+
+ * ext/socket/extconf.rb (sockaddr_storage): winsock2.h have the
+ definition of struct sockaddr_storage, but socket.c doesn't
+ include it because this version of ruby still has binary level
+ compatibility with winsock1.
+
+ * lib/mkmf.rb (create_makefile): should support header files in
+ depend file.
+
+Mon Feb 7 01:21:50 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/socket/extconf.rb: check if getaddrinfo() works fine only when
+ wide-getaddrinfo option is not given. fixed: [ruby-dev:25422]
+
+ * lib/mkmf.rb ($extmk): check if under ext directory.
+
+ * lib/mkmf.rb (Logging.postpone): allow recursive operation.
+
+ * lib/mkmf.rb (try_constant): make sure if really a constant, reduce
+ the number of times of compile.
+
+ * lib/mkmf.rb (have_macro, have_var, byte_order): new functions.
+
+ * lib/mkmf.rb (find_library): allow directory list with separators.
+
+ * lib/mkmf.rb (arg_config): manage provided configuration options.
+
+ * lib/mkmf.rb (dir_config): accept arrays of directory names as
+ default values.
+
+ * mkconfig.rb: no longer embed srcdir and compile_dir into
+ rbconfig.rb.
+
+ * lib/mkmf.rb (create_makefile): fix unbalanced parens.
+
+Sun Feb 6 19:23:01 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * eval.c (stack_extend): add prototype because VC++8 doesn't
+ accept __declspec(noinline) with K&R style function definitions.
+ (backported from CVS HEAD)
+
+Sun Feb 6 14:14:26 2005 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (new_with_hash): changed messages of exception.
+
+ * lib/date/format.rb (str[fp]time): undocumented conversion
+ specifications %[1-3] are now deprecated.
+
+Sun Feb 6 12:20:11 2005 Akinori MUSHA <knu@iDaemons.org>
+
+ * bignum.c (rb_big2ulong_pack): One too many arguments are passed
+ to big2ulong().
+
+ * re.c (rb_reg_init_copy, rb_reg_initialize_m): One too many
+ arguments are passed to rb_reg_initialize().
+
+Sun Feb 6 03:24:20 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/resolv.rb (Resolv::DNS::Resource::TXT): multiple strings was not
+ handled.
+ (Resolv::DNS::Resource::TXT#strings): new method to return all
+ strings.
+ (Resolv::DNS::Message::MessageEncoder#put_string_list): new method.
+ (Resolv::DNS::Message::MessageDecoder#get_string_list): ditto.
+ based on [ruby-talk:129732] by Sam Roberts.
+
+Fri Feb 4 00:30:45 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss: supported Image module.
+ http://web.resource.org/rss/1.0/modules/image/
+
+Thu Feb 3 23:42:36 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_close, strio_close_read, strio_close_write):
+ should return nil instead of self as well as IO. [ruby-dev:25623]
+
+ * ext/stringio/stringio.c (strio_extend, strio_putc): fill with zero
+ extended portion. [ruby-dev:25626]
+
+Wed Feb 2 23:52:53 2005 sheepman <sheepman@tcn.zaq.ne.jp>
+
+ * ext/stringio/stringio.c (strio_truncate): should MEMZERO an extended
+ part. [ruby-dev:25618]
+
+Wed Feb 2 21:56:01 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb (RSS::Element#convert): added.
+
+ * lib/rss/rss.rb: convert -> need_convert.
+
+ * lib/rss/1.0.rb: ditto.
+
+ * lib/rss/0.9.rb: ditto.
+
+ * lib/rss/2.0.rb: ditto.
+
+ * lib/rss/trackback.rb: ditto.
+
+Tue Feb 1 22:48:48 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (DRb::DRbObject#respond_to?): check marshal_dump and
+ _dump.
+
+Tue Feb 1 00:20:23 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (aix): fix linker flags on AIX. [ruby-talk:125460]
+
+Mon Jan 31 13:33:21 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: add invalid namespace check
+
+ * ext/tk/lib/multi-tk.rb: add invalid_namespace? method
+
+ * ext/tk/lib/remote-tk.rb: ditto
+
+Mon Jan 31 10:29:18 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
+
+Sat Jan 29 09:42:12 2005 Sam Roberts <sroberts@uniserve.com>
+
+ * lib/resolv.rb (Resolv::DNS::Resource::IN::SRV): Added RFC2782 SRV
+ resource record for specifying location of services.
+
+Fri Jan 28 17:16:55 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/resolv.rb (Resolv::DNS::Config.parse_resolv_conf):
+ parse options line for ndots option.
+ (Resolv::Hosts#lazy_initialize): return self.
+ (Resolv::DNS#lazy_initialize): ditto.
+ (Resolv::DNS::Config#lazy_initialize): ditto.
+ Suggested by Sam Roberts.
+
+Thu Jan 27 13:18:03 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * st.c (st_foreach): report success/failure by return value.
+ [ruby-Bugs-1396]
+
+Thu Jan 27 00:15:29 2005 Minero Aoki <aamine@loveruby.net>
+
+ * test/fileutils/test_fileutils.rb (setup): support BSD-style
+ directory group inheritance. (backport from HEAD, rev 1.32)
+
+ * test/fileutils/fileasserts.rb (assert_same_entry): show entry
+ difference. (backport from HEAD, rev 1.4)
+
+Wed Jan 26 23:09:11 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/protocol.rb (WriteAdapter#puts): should append \n, not
+ prepend. [ruby-talk:128302] (backport from HEAD, rev 1.75)
+
+Wed Jan 26 10:51:50 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (flock_winnt, flock_win95): unlock file even if
+ LOCK_NB is specified. (backported from CVS HEAD)
+
+Tue Jan 25 17:11:51 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ruby.c (proc_options): correct -T option in RUBYOPT. (backported
+ from CVS HEAD)
+
+Tue Jan 25 14:05:52 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: fix SEGV bug; trouble on canceling remained
+ after scripts [ruby-dev:25479]: NULL current namespace when deleting
+ Tk interpreter [ruby-talk:126225]
+
+ * ext/tcltklib/extconf.rb: bug fix; TCL_ENABLE_THREAD flag is inverted
+ [ruby-talk:126360]
+
+ * ext/tcltklib/extconf.rb: add yet another native-thread check
+
+ * ext/tk/tkutil.c: fix SEGV bug; NULL string pointer when finalize
+ Ruby interpreter
+
+ * ext/tk/lib/multi-tk.rb: avoid warning for deleted safeTk ip frame
+
+ * ext/tk/lib/tk/bindtag.rb: bug fix; new method of named bindtag
+ doesn't return the created object [ruby-dev:25479]
+
+ * ext/tk/lib/tk/menu.rb: bug on treating arguments [ruby-dev:25479]
+
+ * ext/tk/lib/tk.rb: bug fix; cannot accept a callback ID string for
+ a command argument [ruby-dev:25479]
+
+ * ext/tk/lib/multi-tk.rb: ditto
+
+ * ext/tk/lib/tk/*.rb: ditto
+
+ * ext/tk/lib/tkextlib/*.rb: ditto
+
+ * ext/tk/sample/demos-jp/anilabel.rb: new demo script
+
+ * ext/tk/sample/demos-en/anilabel.rb: ditto
+
+ * ext/tk/sample/tkHTML/ss.rb: local variable scope bug fix
+ [ruby-dev:25479]
+
+Mon Jan 24 15:44:25 2005 Tilman Sauerbeck <tilman@code-monkey.de>
+
+ * lib/rdoc/parsers/parse_c.rb: allow whitespace after function names.
+ [ruby-core:4296]
+
+ * lib/rdoc/parsers/parse_simple.rb: adds support for private comments
+ in the "simple" parser. [ruby-core:4301]
+
+Mon Jan 24 15:44:25 2005 Charles Mills <cmills@freeshell.org>
+
+ * lib/rdoc/parsers/parse_c.rb: adds support for constants
+ (rb_define_const), accessors (rb_define_attr), and makes a
+ couple fixes. [ruby-core:4307]
+
+Mon Jan 24 15:44:25 2005 Florian Gro <florgro@gmail.com>
+
+ * lib/rdoc/parsers/parse_rb.rb: Logic for def Builtin.method() end
+ [ruby-core:4302]
+
+Mon Jan 24 15:44:25 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * document updates - [ruby-core:04296], [ruby-core:04301],
+ [ruby-core:04302], [ruby-core:04307]
+
+Sun Jan 23 12:41:16 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/soap/wsdlDriver.rb: from 1.5.3-ruby1.8.2, operation which has
+ capitalized name (such as KeywordSearchRequest in AWS) is defined as
+ a method having uncapitalized name. (converted with
+ GenSupport.safemethodname to handle operation name 'foo-bar'). it
+ introduced serious incompatibility; in the past, it was defined as a
+ capitalized.
+
+ define capitalized method as well under that circumstance.
+
+Sun Jan 23 05:24:42 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ocsp.c (ossl_ocspreq_to_der): should call
+ GetOCSPReq at first.
+
+Sat Jan 22 23:09:47 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/ssl.rb (accept): rescue SSLError. [druby-ja:110]
+
+Sat Jan 22 22:35:03 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/unix.rb: fail if UNIXFileOwner is set. [druby-ja:111]
+
+Fri Jan 21 23:58:42 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_set_pos): clear EOF flag.
+ [ruby-talk:127511]
+
+Fri Jan 21 20:07:02 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/resolv.rb (Resolv::DNS::Config.resolv): don't raise ResolvError.
+ reported by Sam Roberts. [ruby-talk:127133]
+
+Fri Jan 21 16:58:10 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (rb_push_glob): should work for NUL delimited patterns.
+
+Fri Jan 21 13:58:37 2005 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (u8tou16): fixed typo. fixed: [ruby-list:40546]
+ (backported from CVS HEAD)
+
+Fri Jan 21 09:30:16 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * rubyio.h (rb_eof_error): should mark as NORETURN. (backported
+ from CVS HEAD)
+
+Fri Jan 21 00:31:36 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/syck/rubyext.c (syck_parser_bufsize_set): avoid VC++ warning
+ "local variable 'size' used without having been initialized".
+
+Thu Jan 20 19:03:24 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/extmk.rb (extmake): shouldn't set $extflags on mswin32.
+
+ * win32/Makefile.sub (LIBRUBY_SO): should use $DLDOBJS instead of
+ $EXTOBJS.
+ fixed: [ruby-core:04290] (backported from CVS HEAD)
+
+Thu Jan 20 11:42:02 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_new4): should propagate taintedness.
+
+ * struct.c (rb_struct_set): use original method name, not callee
+ name, to retrieve member slot. [ruby-core:04268]
+
+ * time.c (time_strftime): protect from format modification from GC
+ finalizers.
+
+Wed Jan 19 18:06:40 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/ipaddr.rb (to_s, test_to_s): too many colons with some cases.
+ (backported from CVS HEAD)
+
+Wed Jan 19 01:16:30 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/resolv.rb (Resolv::DNS::Config.parse_resolv_conf): ignore
+ domain and search directive without an argument.
+ reported by Sam Roberts. [ruby-talk:126781]
+
+Tue Jan 18 15:03:05 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/ssl.rb (WEBrick::Config::SSL): the default value
+ of :SSLEnable is false.
+
+ * lib/webrick/server.rb (WEBrick::Daemon.start): prepared stdio
+ don't allow changing its mode.
+
+ * lib/webrick/httpproxy.rb (WEBrick::HTTPProxyServer#proxy_service):
+ should delete trailing LF from the result of pack("m*").
+
+ * lib/webrick/httpproxy.rb (WEBrick::HTTPProxyServer#proxy_connect):
+ - should delete trailing LF from the result of pack("m*").
+ - clear Request-Line not to send the response by HTTPServer#run.
+
+ * lib/webrick/httputils (WEBrick::HTTPUtils.parse_qvalues):
+ refine regexp (and change the name of a local variable).
+
+ * lib/webrick/httputils.rb (WEBrick::HTTPUtils#escape_path): add
+ new method to escape URI path component.
+
+ * lib/webrick/cgi.rb (WEBrick::CGI::Socket#request_line): should
+ escape SCRIPT_NAME and PATH_INFO before being parsed as a URI.
+
+ * test/webrick/*, sample/webrick/httpproxy.rb: add new file.
+
+Mon Jan 17 23:33:46 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (aix): fix typo. [ruby-talk:126401]
+
+Mon Jan 17 07:08:51 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/readline/readline.c: suppress warnings.
+
+ * lib/irb/extend-command.rb (IRB::ContextExtender.def_extend_command):
+ ditto.
+
+ * lib/irb/ext/history.rb (IRB::Context::set_last_value): ditto.
+
+ * lib/irb/ext/history.rb (IRB::Context::eval_history): ditto.
+
+ * lib/irb/locale.rb (IRB::Locale::real_load): ditto.
+
+ * lib/irb/slex.rb (SLex::Node::create_subnode): remove garbage.
+
+Mon Jan 17 00:09:42 2005 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/uri/common.rb (PORT): typo fix. fixed: [ruby-core:04256]
+
+Sat Jan 15 14:57:22 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (proc_options): ignore trailing CRs at the end of short
+ options as well as long options. fixed: [ruby-core:04232]
+
+Sat Jan 15 13:35:16 2005 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb (RSS::VERSION): 0.1.2 -> 0.1.3.
+
+ * lib/rss/rss.rb: accept inheritance. [ruby-talk:126104]
+
+Thu Jan 13 04:48:53 2005 Tanaka Akira <akr@m17n.org>
+
+ * io.c (io_fread): don't warn nonblocking behavior by default.
+
+Wed Jan 12 00:36:29 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_class_superclass): superclass of singleton class also
+ should be a singleton class. fixed: [ruby-list:40519]
+
+Tue Jan 11 09:44:40 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * numeric.c (Init_Numeric): turn off floating point exceptions
+ on bcc32. "1e300".to_f had crashed by overflow.
+
+Tue Jan 11 03:10:10 2005 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (copy_entry): could not copy symbolic link.
+ [ruby-talk:125733]
+
+ * lib/fileutils.rb (copy_stream): use read/write instead of
+ sysread/syswrite.
+
+Mon Jan 10 23:08:15 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * variable.c (rb_autoload): hide internal data from ruby level.
+ fixed: [ruby-dev:25435], [ruby-list:40498]
+
+Mon Jan 10 01:22:55 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (rb_data_object_alloc): klass may be NULL.
+ [ruby-list:40498]
+
+Sun Jan 9 03:12:58 2005 Tanaka Akira <akr@m17n.org>
+
+ * io.c (io_fread): warn nonblocking behavior.
+ (io_readpartial): new method IO#readpartial.
+
+Sat Jan 8 04:38:47 2005 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/yaml.rb: Kernel#y requires an argument.
+
+Fri Jan 7 21:12:29 2005 TAMURA Takashi <sheepman@tcn.zaq.ne.jp>
+
+ * random.c (rand_init): use ALLOC_N instead of ALLOCA_N
+ [ruby-dev:25426]
+
+Fri Jan 7 18:03:35 2005 Tanaka Akira <akr@m17n.org>
+
+ * gc.c (mark_locations_array): avoid core dump with -O3.
+ [ruby-dev:25424]
+
+Thu Jan 6 20:31:07 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/zlib/zlib.c (zstream_end): should return value. (backported
+ from CVS HEAD)
+
+Thu Jan 6 19:55:13 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.c (rb_w32_close): didn't close socket handle.
+ [ruby-dev:25414]
+
+ * win32/win32.c (rb_w32_open_osfhandle): bcc32's _open_osfhandle
+ never set EMFILE.
+
+Thu Jan 6 17:14:31 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * random.c (random_seed): O_NONBLOCK isn't defined on some
+ platforms. [ruby-dev:25417]
+
+Thu Jan 6 13:45:35 2005 Tanaka Akira <akr@m17n.org>
+
+ * lib/time.rb: recognize +00:00 and GMT as a localtime.
+
+Thu Jan 6 07:58:28 2005 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/usage.rb (RDoc::RDoc.usage_no_exit): Allow for colons
+ in path names on DOS machines. (thanks to Johan Nilsson)
+
+Wed Jan 5 20:16:32 2005 Tanaka Akira <akr@m17n.org>
+
+ * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
+ [ruby-dev:25408]
+
+ * random.c (random_seed): refined.
+
+Wed Jan 5 12:49:39 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_initialize): Thread objects cannot be initialized
+ again. fixed: [ruby-core:04067]
+
+Wed Jan 5 10:48:16 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * dir.c (dir_s_mkdir): win32 special processing doesn't need any
+ longer. (backported from CVS HEAD)
+
+ * win32/win32.[ch] (rb_w32_mkdir): new function. POSIX.1 compatible
+ interface. (backported from CVS HEAD)
+
+ * win32/win32.[ch] (rb_w32_rmdir): new function. (backported from CVS
+ HEAD)
+
+Wed Jan 5 02:30:11 2005 Tanaka Akira <akr@m17n.org>
+
+ * random.c (init_by_array): imported from mt19937ar-cok.tgz.
+ (genrand_int32): ditto.
+ (genrand_real): replaced with genrand_res53 in mt19937ar-cok.
+ (rand_init): support bignum for longer seed.
+ (random_seed): generate longer seed.
+ (make_mask): new function.
+ (limited_rand): ditto.
+ (limited_big_rand): ditto.
+ (rb_f_rand): call limited_rand and limited_big_rand.
+ [ruby-dev:25403]
+
+Tue Jan 4 23:25:29 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_rand): should return positive random number.
+ [ruby-dev:25401]
+
+Tue Jan 4 11:15:29 2005 TAMURA Takashi <sheepman@tcn.zaq.ne.jp>
+
+ * bignum.c (rb_big_rand): do not use rb_big_modulo to generate
+ random bignums. [ruby-dev:25396]
+
+Mon Jan 3 14:01:54 2005 Tanaka Akira <akr@m17n.org>
+
+ * random.c (random_seed): don't use /dev/urandom if it is not
+ character device.
+
+Mon Jan 3 11:37:42 2005 Tanaka Akira <akr@m17n.org>
+
+ * random.c (random_seed): use /dev/urandom if available.
+ [ruby-dev:25392]
+
+Mon Jan 3 07:46:42 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpauth/htpasswd.rb (WEBrick::Htpasswd#reload):
+ raise NotImplementedError if password is encrypted by digest
+ algorithms. This patch is contributed by sheepman. [ruby-list:40467]
+
+ * lib/webrick/httpauth/digestauth.rb
+ (WEBrick::HTTPAuth::DigestAuth#_authenticate): fix digest calculation.
+ This patch is contributed by sheepman. [ruby-list:40482]
+
+ * lib/webrick/{httpauth.rb,httpauth/basicauth.rb,httpproxy.rb}: use
+ pack/unpack-template char "m" instead of lib/base64.rb to do base64
+ encoding/decoding. fixed: [ruby-dev:25336]
+
+ * test/webrick/test_httpauth.rb: new file.
+
+Sat Jan 1 04:20:23 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ns_spki.c (ossl_spki_set_challenge): should call
+ StringValue before GetSPKI. fixed: [ruby-dev:25359].
+
+Sat Jan 1 01:13:28 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_autoload): [ruby-dev:25373]
+
+Fri Dec 31 14:10:43 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_formatter.rb (RI::TextFormatter::display_flow_item): Fix problem
+ if heading contains formatting.
+
+Thu Dec 30 00:41:42 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (svalue_to_avalue): [ruby-dev:25366]
+
+ * string.c (rb_str_justify): [ruby-dev:25367]
+
+Wed Dec 29 11:07:07 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/template/html/kilmer.rb: Update to use new
+ sections.
+
+Tue Dec 28 22:31:46 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_justify): create buffer string after argument type
+ conversion. fixed: [ruby-dev:25341]
+
+Tue Dec 28 15:41:48 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c (reinit): should initialize all static
+ variables. fixed: [ruby-list:40445]
+
+Tue Dec 28 15:25:20 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/nkf/lib/kconv.rb (Kconv::RegexpEucjp): second byte is up to
+ 0xfe.
+
+ * ext/nkf/lib/kconv.rb (Kconv#kconv): should handle UTF8 and UTF16
+ properly.
+
+Tue Dec 28 13:35:20 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/zlib/zlib.c (rb_deflate_s_deflate, rb_inflate_s_inflate): ensure
+ freeing internal zstreams. fixed: [ruby-dev:25309]
+
+ * ext/zlib/zlib.c (rb_deflate_init_copy): replace rb_deflate_clone.
+
+Tue Dec 28 12:26:45 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub, win32/setup.mak (RDOCTARGET, install,
+ install-nodoc, install-doc): rdoc support for mswin32.
+
+ * win32/configure.bat (--enable-install-doc, --disable-install-doc):
+ ditto.
+
+Mon Dec 27 20:02:14 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: fix SEGV bug when deleting Tk interp
+
+ * ext/tk/lib/multi-tk.rb: ditto
+
+Mon Dec 27 16:55:17 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_x509name.c (Init_ossl_x509name): should use
+ rb_hash_new to get exactly a Hash. fix [ruby-dev:25325].
+
+Mon Dec 27 16:29:56 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_justify): [ruby-dev:25341]
+
+Mon Dec 27 15:47:48 2004 Minero Aoki <aamine@loveruby.net>
+
+ * test/fileutils/fileasserts.rb: sync with HEAD.
+
+ * test/fileutils/test_fileutils.rb: ditto.
+
+ * test/fileutils/test_nowrite.rb: ditto.
+
+Mon Dec 27 15:21:07 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (mv): should raise error when moving a
+ directory to the (empty) directory. [ruby-talk:124368]
+ (backport from HEAD 1.48)
+
+ * lib/fileutils.rb (mv): wrongly did not overwrite file on Win32
+ platforms. (backport from HEAD 1.48)
+
+Sat Dec 25 11:11:48 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.8.2 released.
+
+Sat Dec 25 04:23:49 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (mkdir, mkdir_p): should ensure directory
+ permission. (backportted from HEAD, 1.47)
+
+ * lib/fileutils.rb (traverse, remove_dir): untaint trasted
+ objects. (backportted from HEAD, 1.46)
+
+Sat Dec 25 01:28:23 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c: cancel io_reopen() change on Dec. 24th.
+
+ * dln.c: use <dlfcn.h> for NetBSD. [ruby-dev:25313]
+
+ * io.c (rb_f_select): IO list could be altered. [ruby-dev:25312]
+
+Fri Dec 24 23:51:48 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub: bcc32 should use RTL dll (backport from HEAD)
+ [ruby-dev:25306]
+
+ * win32/win32.[ch]: ditto.
+
+Fri Dec 24 23:27:18 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/image.rb: TkPhotoImage#cget bug fix
+
+Fri Dec 24 18:39:25 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.[ch]: failed to compile on bcc32 (and probably wince)
+ [ruby-dev:25306]
+
+Fri Dec 24 02:52:52 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (io_reopen, rb_io_reopen): prohibit to change access mode for
+ special IO ports. [ruby-dev:25225]
+
+Fri Dec 24 02:22:53 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/syck/rubyext.c (rb_syck_io_str_read): [ruby-core:03973]
+
+ * ext/syck/rubyext.c (syck_loader_transfer): check type conversion.
+
+ * ext/syck/rubyext.c (syck_parser_assign_io, rb_new_syck_node): duck
+ typing.
+
+ * ext/syck/rubyext.c (syck_parser_s_alloc, syck_parser_initialize):
+ allocation framework.
+
+ * ext/syck/rubyext.c (syck_emitter_s_alloc, syck_emitter_initialize):
+ ditto.
+
+Fri Dec 24 01:21:00 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/blt.rb: add BLT extension support
+
+ * ext/tk/lib/tkextlib/blt/*.rb: ditto
+
+ * ext/tk/lib/tkextlib/blt/tile/*.rb: ditto
+
+Thu Dec 23 23:36:28 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (proc_setgroups): check if the argument lenght is
+ modified. fixed: [ruby-dev:25285]
+
+Thu Dec 23 13:13:33 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: define TclTkLib::COMPILE_INFO and
+ RELEASE_DATE
+
+ * ext/tcltklib/extconf.rb: ditto
+
+ * ext/tk/tkutil.c: define TkUtil::RELEASE_DATE
+
+ * ext/tk/lib/tk.rb: define Tk::RELEASE_DATE
+
+Thu Dec 23 09:38:31 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (io_reopen): restore exact mode. fixed: [ruby-core:04003]
+
+Thu Dec 23 00:16:32 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (bsdi): use $(CC) for LDSHARED. fixed [ruby-dev:25270]
+
+Wed Dec 22 11:14:55 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_mode_modenum): replace O_ACCMODE with O_RDWR.
+ fixed: [ruby-dev:25273]
+
+Wed Dec 22 08:34:32 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/dl/sym.c (rb_dlsym_initialize): extract internal pointers after
+ all argument conversion. fixed: [ruby-dev:25271]
+
+Wed Dec 22 00:08:01 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/soap/*, test/soap/*, sample/soap/authheader/*: eval cleanup.
+
+Tue Dec 21 22:07:33 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_asn1.c (ossl_asn1_traverse, ossl_asn1_decode,
+ ossl_asn1_decode_all): temporary value should be marked volatile.
+
+Tue Dec 21 14:40:02 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_asn1.c (ossl_asn1_traverse, ossl_asn1_decode,
+ ossl_asn1_decode_all): use rb_str_new4 to avoid SEGV.
+ fix [ruby-dev:25261]
+
+ * test/openssl/test_asn1.rb: add tests for OpenSSL::ASN1.
+
+Tue Dec 21 12:22:40 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (io_reopen): keep duplex pipe in correct mode for exception
+ safeness. fixed: [ruby-dev:25152]
+
+Tue Dec 21 12:10:04 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/grid.rb: rescue bug of 'grid configure' on Tcl/Tk8.3-
+
+Tue Dec 21 00:53:01 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/openssl/ossl_asn1.c (ossl_asn1_traverse): [ruby-dev:25261]
+
+ * ext/openssl/ossl_asn1.c (ossl_asn1_decode): ditto.
+
+ * ext/openssl/ossl_asn1.c (ossl_asn1_decode_all): ditto.
+
+Mon Dec 20 23:22:26 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * added files:
+ * lib/soap/mapping/wsdl*.rb
+ * lib/wsdl/soap/element.rb
+ * lib/wsdl/xmlSchema/simpleContent.rb
+
+ * modified files:
+ * lib/soap/*
+ * lib/wsdl/*
+ * lib/xsd/*
+ * test/soap/*
+ * test/wsdl/*
+ * test/xsd/*
+ * sample/soap/*
+ * sample/sdl/*
+
+ * summary
+ * imported from the soap4r repository. Version: 1.5.3-ruby1.8.2
+
+ * added several XSD basetype support: nonPositiveInteger,
+ negativeInteger, nonNegativeInteger, unsignedLong, unsignedInt,
+ unsignedShort, unsignedByte, positiveInteger
+
+ * HTTP client connection/send/receive timeout support.
+
+ * HTTP client/server gzipped content encoding support.
+
+ * improved WSDL schema definition support; still is far from
+ complete, but is making step by step improovement.
+
+Mon Dec 20 22:56:39 2004 Tanaka Akira <akr@m17n.org>
+
+ * gc.c (stack_end_address): gcc noinline attribute is available since
+ gcc-3.1.
+
+Mon Dec 20 14:07:02 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: supports new features of Tcl/Tk8.5a2
+
+ * ext/tk/lib/tk/clock.rb: ditto
+
+ * ext/tk/lib/tk/text.rb: ditto
+
+ * ext/tk/lib/tk/panedwindow.rb: ditto
+
+Mon Dec 20 12:47:13 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/lib/net/https.rb,protocols.rb,telnets.rb: delete
+ doc and code about SSLContext#{key_file,cert_file}.
+ fixed: [ruby-dev:25243]
+
+Mon Dec 20 12:42:17 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * io.c (io_fwrite): workaround for MSVCRT's bug.
+ fixed: [ruby-core:03982]
+
+Mon Dec 20 11:21:04 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_eof): check if closed before clearerr().
+ fixed: [ruby-dev:25251]
+
+Mon Dec 20 03:30:40 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/cgi/session.rb (CGI::Session#initialize): empty session id was
+ used if request had no session key. fixed: [ruby-core:03981]
+
+Mon Dec 20 01:51:01 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (make_struct): [ruby-dev:25249]
+
+Mon Dec 20 00:28:20 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rexml/encodings/SHIFT-JIS.rb: backported from CVS HEAD.
+
+ * lib/rexml/encodings/SHIFT_JIS.rb: ditto.
+
+Sun Dec 19 17:19:48 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_x509store.c
+ (ossl_x509store_set_time): add OpenSSL::X509::Store#time=.
+ (ossl_x509stctx_set_time): add OpenSSL::X509::StoreContext#time=.
+
+ * test/openssl/ossl_x509store.rb: test certificate validity times.
+
+ * ext/openssl/ossl_x509name.c (ossl_x509name_to_s): add optional
+ second argument to specify the output format (see also
+ X509_NAME_print_ex).
+
+ * ext/openssl/ossl_x509name.c (ossl_x509name_init): new constants:
+ OpenSSL::X509::Name::COMPAT, OpenSSL::X509::Name::RFC2253,
+ OpenSSL::X509::ONELINE, OpenSSL::X509::MULTILINE.
+
+ * ext/openssl/lib/openssl/x509.rb (OpenSSL::X509::Name::RFC2253DN):
+ new module to provide the parse for RFC2253 DN format.
+
+ * ext/openssl/lib/openssl/x509.rb (OpenSSL::X509::Name.parse_rfc2253):
+ new method to parse RFC2253 DN format.
+
+ * test/openssl/ossl_x509name.rb: add tests about RFC2253 DN.
+
+ * text/openssl/ssl_server.rb: try to listen ports from 20443 to 20542
+ while EADDRINUSE is raised.
+
+ * all changes in this entry are backport from 1.9.
+
+Sun Dec 19 17:24:59 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (enable_rpath): use rpath flag to embed the library
+ path into extensions on ELF environment. [ruby-dev:25035]
+
+Sun Dec 19 11:01:25 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit.rb: use standalone runner for -e.
+
+ * lib/test/unit/autorunner.rb (Test::Unit::AutoRunner#options): accept
+ multiple -p and -x options.
+
+ * lib/test/unit/collector/dir.rb (Test::Unit::Collector::Dir#recursive_collect):
+ ditto.
+
+Sat Dec 18 16:36:23 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/zlib/zlib.c (rb_deflate_s_deflate, rb_inflate_s_inflate):
+ disallow interrupt by type conversion. fixed: [ruby-dev:25226]
+
+Sat Dec 18 15:16:41 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/webrick/httpauth.rb,
+ lib/webrick/httpauth/{basicauth.rb,digestauth.rb}: use
+ pack/unpack-template char "m" instead of lib/base64.rb to do base64
+ encoding/decoding.
+
+Sat Dec 18 10:51:01 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (dir_open_dir): new function. [ruby-dev:25242]
+
+Fri Dec 17 18:07:01 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * test/readline/test_readline.rb: fix for BSD. Thanks, GOTOU Yuuzou.
+ fixed: [ruby-dev:25218]
+
+Fri Dec 17 16:28:12 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: fix bug on setting up system encoding
+
+ * ext/tk/lib/tk/event.rb: fix error on require process
+
+ * ext/tk/lib/tk/font.rb: fix abnormal termination error on Windows
+
+ * ext/tk/lib/tk/virtevent.rb: TkVirtualEvent::PreDefVirtEvent.new()
+ accepts event-sequence arguments
+
+ * ext/tk/lib/tk/text.rb: fail to dump embedded images
+
+ * ext/tk/lib/tk/text.rb: tag_nextrange and tag_prevrange returns wrong
+ types of values
+
+ * ext/tk/lib/tk/texttag.rb: nextrange and prevrange returns wrong
+ types of values
+
+ * ext/tk/lib/tk/text.rb: add TkText::IndexModMethods module and
+ TkText::IndexString class to treat text index modifiers
+
+ * ext/tk/lib/tk/texttag.rb: use TkText::IndexModMethods module
+
+ * ext/tk/lib/tk/textmark.rb: ditto
+
+ * ext/tk/lib/tk/textimage.rb: ditto
+
+ * ext/tk/lib/tk/textwindow.rb: ditto
+
+ * ext/tk/lib/tk/textimage.rb: wrong gravity of text mark for embedded
+ image
+
+ * ext/tk/lib/tk/textwindow.rb: wrong gravity of text mark for
+ embedded window
+
+Fri Dec 17 13:50:00 2004 Akiyoshi, Masamichi <akiyoshi@hp.com>
+
+ * vms/vmsruby_private.c, vms/vmsruby_private.h: private routines
+ for VMS port are added.
+
+ * eval.c (ruby_init): change to call VMS private intialization routine.
+
+Fri Dec 17 13:33:58 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/cgi/session.rb (CGI::Session#initialize): control adding
+ session_id hidden fields. fixed: [ruby-talk:123850]
+
+Thu Dec 16 23:25:25 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb, lib/drb/ssl.rb: backported from CVS HEAD.
+ [druby-ja:101]
+
+ * test/drb/test_drb.rb: adjust and reduce sleep (backported from
+ CVS HEAD.)
+
+Thu Dec 16 18:44:58 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpserver.rb (WEBrick::HTTPServer#run): should wait
+ for reading request till data arrive. [ruby-talk:121068]
+
+ * lib/webrick/server.rb (WEBrick::GenericServer#start_thread):
+ should log about all accepted socket. [ruby-core:03962]
+
+ * lib/webrick/accesslog.rb (WEBrick::AccessLog#setup_params):
+ "%%" and "%u" are supported. [webricken:135]
+
+ * lib/webrick/httpservlet/filehandler.rb
+ (WEBrick::HTTPServlet::FileHandler#check_filename):
+ :NondisclosureName is acceptable if it is Enumerable.
+
+ * lib/webrick/config.rb (WEBrick::Config::FileHandler):
+ default value of :NondisclosureName is [".ht*", "*~"].
+
+Thu Dec 16 18:36:52 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl.c (ossl_raise): refine message format.
+
+Thu Dec 16 16:29:44 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/demos-en/widget: modify version check for
+ supporting features
+
+Thu Dec 16 16:03:50 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/bindtag.rb: bug fix [ruby-talk: 123667]
+
+ * ext/tk/lib/tk/timer.rb: accept :idle for the interval argument
+
+ * ext/tk/lib/tk.rb: add TkComm._callback_entry?()
+
+ * ext/tk/lib/multi-tk.rb: add MultiTkIp.cb_entry_class
+
+ * ext/tk/lib/tk/canvas.rb: use TkComm._callback_entry?()
+
+ * ext/tk/lib/tk/canvastag.rb: ditto
+
+ * ext/tk/lib/tk/dialog.rb: ditto
+
+ * ext/tk/lib/tk/optiondb.rb: ditto
+
+ * ext/tk/lib/tk/text.rb: ditto
+
+ * ext/tk/lib/tk/texttag.rb: ditto
+
+ * ext/tk/lib/tk/textwindow.rb: ditto
+
+ * ext/tk/lib/tk/timer.rb: ditto
+
+ * ext/tk/lib/tk/validation.rb: ditto
+
+ * ext/tk/lib/tkextlib/*: ditto
+
+Thu Dec 16 03:14:28 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/http.rb (basic_encode): return value of pack('m') may
+ include multiple CR/LFs. Backported from main trunk (rev 1.112).
+ [ruby-dev:25212]
+
+Thu Dec 16 00:33:37 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (Init_Hash): remove custom "hash" and "eql?".
+
+Wed Dec 15 18:57:01 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/set.rb (Set::eql): wrong definition. [ruby-dev:25207]
+
+Wed Dec 15 18:48:42 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * ext/curses/curses.c (window_subwin): call NUM2INT() before
+ GetWINDOW(). (backported from CVS HEAD)
+
+Wed Dec 15 17:03:50 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.[ch] (rb_w32_isatty): new function to replace MSVCRT's
+ isatty because it never sets errno. (backported from CVS HEAD)
+
+Wed Dec 15 15:39:32 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_x509name.c (ossl_x509name_to_a): avoid SEGV
+ (rollback the previous commit).
+
+Wed Dec 15 16:10:23 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_obj_id_obsolete): warn always.
+
+ * eval.c (rb_enable_super): ditto.
+
+Wed Dec 15 15:31:02 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/set.rb (Set#==): [ruby-dev:25206]
+
+Wed Dec 15 14:22:10 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_fdisset): check whether the handle is valid.
+ fixed: [ruby-core:03959]
+
+Wed Dec 15 10:30:37 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/openssl/ossl_digest.c (ossl_digest_initialize): [ruby-dev:25198]
+
+Tue Dec 14 17:10:09 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_close): need to reset osfhnd().
+
+Tue Dec 14 14:03:57 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl.c (ossl_raise): avoid buffer overrun.
+ [ruby-dev:25187]
+
+Tue Dec 14 12:36:04 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi/session.rb (CGI::Session::initialize): generate new
+ session if given session_id does not exist. [ruby-list:40368]
+
+Mon Dec 13 18:13:52 2004 Tanaka Akira <akr@m17n.org>
+
+ * gc.c (stack_end_address): new function to obtain stack end address.
+ stack_end_address calls __builtin_frame_address(0) to obtain the
+ frame pointer of a stack frame of stack_end_address. The address
+ is the stack pointer of the caller's stack frame.
+ (SET_STACK_END): use stack_end_address.
+ This makes the conservative garbage collector to scan a stack frame
+ of the garbage_collect function itself. This is required because
+ callee-save registers may be stored in the frame.
+ [ruby-dev:25158]
+
+Mon Dec 13 00:58:02 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb (cleanpath_aggressive): make it private.
+ (cleanpath_conservative): ditto.
+ Suggested by Daniel Berger. [ruby-core:3914]
+
+Sun Dec 12 20:06:38 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: backported from CVS HEAD.
+
+Sun Dec 12 10:35:10 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/template/html/html.rb (RDoc::Page): Don't
+ show an accessor's r/w flag if none was specified
+
+Sun Dec 12 10:14:03 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/rdoc.rb (RDoc::RDoc::parse_files): Never exclude files
+ explicitly given on the command line.
+
+Sun Dec 11 23:54:07 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/*: update to support libraries in ActiveTcl8.4.12.0
+ (see ext/tk/ChangeLog.tkextlib).
+
+ * ext/tk/sample/scrollframe.rb: add a new sample.
+
+Sat Dec 11 20:12:21 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: add DRbRemoteError. [ruby-list:40348],
+ [ruby-list:40390]
+
+ * test/drb/drbtest.rb: ditto.
+
+ * test/drb/ut_drb.rb: ditto.
+
+Sat Dec 11 15:38:14 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/jcode.rb (String::succ): [ruby-dev:25156]
+
+Sat Dec 11 12:41:55 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * eval.c (run_trap_eval): prototype; avoid VC++ warnings.
+
+ * ext/socket/getaddrinfo.c: fix typo. fixed: [ruby-core:03947]
+
+ * win32/win32.c: need to include dln.h.
+
+Sat Dec 11 00:10:18 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_reopen): [ruby-dev:25150]
+
+Fri Dec 10 08:39:27 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/socket/socket.c (sock_listen): get OpenFile just before calling
+ listen(2). fixed: [ruby-dev:25149]
+
+Thu Dec 9 17:00:00 2004 Akiyoshi, Masamichi <akiyoshi@hp.com>
+
+ * ext/socket/socket.c, ext/socket/getaddrinfo.c: port to VMS
+
+Thu Dec 9 16:31:02 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/sdbm/init.c (GetDBM): typo.
+
+Thu Dec 9 16:05:00 2004 Akiyoshi, Masamichi <akiyoshi@hp.com>
+
+ * defines.h: change path of vms.h
+ * vms/vms.h: delete reference for snprintf()
+ * vms/config.h: new file
+ * vms/config.h_in: deleted
+
+Thu Dec 9 14:38:35 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_inspect): escape # which starts an expression
+ substitution. fixed: [ruby-core:03922]
+
+ * string.c (rb_str_dump): not escape # which isn't a substitution.
+
+Thu Dec 9 10:54:36 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dbm/dbm.c (fdbm_select): [ruby-dev:25132]
+
+ * ext/sdbm/init.c: ditto.
+
+ * ext/gdbm/gdbm.c: ditto.
+
+Thu Dec 9 03:08:36 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_init): set root-win title to "ruby" when
+ the running script is '-e one-liner' or '-' (stdin).
+
+ * ext/tcltklib/extconf.rb: add find_library("#{lib}#{ver}",..) for
+ stub libs
+
+ * ext/tk/lib/tk/textmark.rb: TkTextMarkCurrent and TkTextMarkAnchor
+ have a wrong parent class.
+
+ * ext/tk/lib/tk/dialog.rb: rename TkDialog2 --> TkDialogObj and
+ TkWarning2 --> TkWarningObj (old names are changed to alias names)
+
+ * ext/tk/lib/tk/dialog.rb: bug fix of treatment of 'prev_command'
+ option and hashes for configuration
+
+ * ext/tk/lib/tk/dialog.rb: add TkDialogObj#name to return the
+ button name
+
+ * ext/tk/lib/tk/radiobutton.rb: rename enbugged method value() ==>
+ get_value() and value=(val) ==> set_value(val).
+
+ * ext/tk/lib/tk/menu.rb: add TkMenu.new_menuspec
+
+ * ext/tk/lib/tk/menu.rb: add alias (TkMenuButton = TkMenubutton,
+ TkOptionMenuButton = TkOptionMenubutton)
+
+ * ext/tk/lib/tk/event.rb: new method aliases (same as option keys of
+ event_generate) for Event object
+
+ * ext/tk/lib/tk/font.rb: configinfo returns proper types of values
+
+ * ext/tk/lib/tk.rb: bind methods accept subst_args + block
+
+ * ext/tk/lib/tk/canvas.rb: ditto
+
+ * ext/tk/lib/tk/canvastag.rb: ditto
+
+ * ext/tk/lib/tk/frame.rb: ditto
+
+ * ext/tk/lib/tk/text.rb: ditto
+
+ * ext/tk/lib/tk/texttag.rb: ditto
+
+ * ext/tk/lib/tk/toplevel.rb: ditto
+
+ * ext/tk/lib/tkextlib/*: ditto and bug fix
+
+Wed Dec 8 23:54:29 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/template/html/html.rb (RDoc::Page): Typo
+ meant that h2 tag was invisible.
+
+Wed Dec 8 21:56:31 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss, test/rss, sample/rss: backported from CVS HEAD.
+
+Wed Dec 8 14:31:36 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_fwrite): change dereference for cosmetic reason.
+
+ * sprintf.c (rb_f_sprintf): [ruby-dev:25104]
+
+Tue Dec 7 19:08:00 2004 Akiyoshi, Masamichi <akiyoshi@hp.com>
+
+ * io.c (io_fwrite): fix offset incrementation (for VMS and Human68k)
+
+Tue Dec 7 00:27:37 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * process.c (proc_setgroups): [ruby-dev:25081]
+
+Mon Dec 6 18:08:10 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_eqq): document fix. [ruby-talk:122541]
+
+Mon Dec 6 17:19:13 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * rubysig.h (TRAP_BEG, TRAP_END): safe errno around CHECK_INTS.
+ (backported from CVS HEAD) [ruby-dev:24993]
+
+Mon Dec 6 10:18:17 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::look_for_directives_in):
+ Oops - 1.8 doesn't have String#clear
+
+Mon Dec 6 09:59:23 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (sock_connect): use rb_str_new4().
+ [ruby-dev:25052]
+
+Mon Dec 6 01:42:08 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_pkey_rsa.c (ossl_rsa_public_encrypt,
+ ossl_rsa_public_decrypt, ossl_rsa_private_encrypt,
+ ossl_rsa_private_decrypt): should take an optional argument
+ to specify padding mode. [ruby-talk:122539]
+
+ * ext/openssl/ossl_pkey_rsa.c (Init_ossl_rsa): add new constants
+ PKCS1_PADDING, SSLV23_PADDING, NO_PADDING and PKCS1_OAEP_PADDING
+ under OpenSSL::PKey::RSA.
+
+ * test/openssl/test_pkey_rsa.rb: new file.
+
+Sun Dec 5 19:39:17 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::Completion#complete): new parameter
+ to direct case insensitiveness.
+
+ * lib/optparse.rb (OptionParser#order!): ignore case only for long
+ option. [ruby-dev:25048]
+
+Sat Dec 4 22:54:15 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_write): remove rb_str_locktmp(). [ruby-dev:25050]
+
+ * io.c (io_fwrite): takes VALUE string as an argument.
+ [ruby-dev:25050]
+
+ * ext/socket/socket.c (sock_connect): remove rb_str_locktmp().
+ [ruby-dev:25050]
+
+ * ext/socket/socket.c (udp_connect): [ruby-dev:25045]
+
+ * ext/socket/socket.c (udp_bind): ditto.
+
+ * ext/socket/socket.c (udp_send): ditto.
+
+ * ext/socket/socket.c (bsock_send): ditto.
+
+ * ext/socket/socket.c (s_recvfrom): ditto.
+
+ * hash.c (rb_hash_hash): should provide "hash" method where "eql?"
+ is redefined. [ruby-talk:122482]
+
+Sat Dec 4 14:54:52 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * eval.c (proc_invoke): use volatile `tmp' rather than `args'.
+ [ruby-core:03882]
+
+Sat Dec 4 14:28:56 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/code_objects.rb (RDoc::Context::Section::set_comment):
+ Section comments may now be bracketed by lines which are
+ ignored. You can now write
+ # -----------
+ # :section: Dave's Section
+ # comment material
+ # -----------
+ The lines before :section: are removed, and identical lines at the end are
+ also removed if present.
+
+Sat Dec 4 03:33:45 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * ext/readline/readline.c: check $SAFE. (backported from CVS HEAD)
+
+ * test/readline/test_readline.rb: added tests for readline.
+ (backported from CVS HEAD)
+
+Sat Dec 4 02:24:00 2004 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf.c: add constant NKF::VERSION
+
+ * ext/nkf/nkf.c(guess): this becomes an alias of guess2
+
+ * ext/nkf/test.rb(mime_out2): add --no-cp932
+
+ * ext/nkf/nkf-utf8/nkf.c: original nkf2 revision 1.47
+
+Sat Dec 4 00:35:08 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (bsock_setsockopt): [ruby-dev:25039]
+
+Fri Dec 3 18:57:03 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/ostruct.rb: 1.9 marshaling support back-ported.
+ [ruby-core:03871]
+
+Fri Dec 3 13:45:20 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_invoke): copy arguments to frame.argv.
+ [ruby-core:03861]
+
+Fri Dec 3 12:25:41 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * st.h: fix prototypes.
+
+Fri Dec 3 00:21:05 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (convert_type): use rb_respond_to() again.
+ [ruby-dev:25021]
+
+ * eval.c (rb_respond_to): funcall respond_to? if it's redefined.
+ [ruby-dev:25021]
+
+Fri Dec 3 01:55:24 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: widget configuration by TkWindow#method_missing
+ returns proper object. "widget.option = val" returns val, and
+ "widget.option(val)" returns self.
+
+ * ext/tk/lib/tk/font.rb: TkFont#replace accepts only one font argument.
+
+ * ext/tk/lib/tk/radiobutton.rb: add TkRadiobutton#value and
+ TkRadiobutton#value=(val).
+
+ * ext/tk/lib/tk/spinbox.rb: callback substitution support on
+ command option.
+
+ * ext/tk/sample/demos-en/widget: bug fix (wrong image height)
+
+ * ext/tk/sample/demos-jp/widget: ditto.
+
+Fri Dec 3 00:11:48 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_file_initialize): [ruby-dev:25032]
+
+Thu Dec 2 16:41:03 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_protect): prevent continuations created inside from being
+ called from the outside. [ruby-dev:25003]
+
+ * eval.c (rb_callcc, rb_cont_call): prohibit calling from different
+ signal contexts. [ruby-dev:25022]
+
+Thu Dec 2 09:57:24 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/ostruct.rb (OpenStruct::Marshaler): OpenStruct can be
+ marshaled again. [ruby-core:03862]
+
+Thu Dec 2 09:30:06 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (thread_mark): mark thread group. [ruby-dev:25020]
+
+ * eval.c (thgroup_add): check whether the argument is really a Thread.
+
+Thu Dec 2 07:57:16 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_ctl): [ruby-dev:25019]
+
+Wed Dec 1 02:21:02 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * signal.c (sighandler): call handler immediately only for default
+ handlers. [ruby-dev:25003]
+
+Tue Nov 30 23:38:18 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (io_fread): need not to null terminate. [ruby-dev:24998]
+
+ * io.c (read_all): remove unnecessary rb_str_resize().
+ [ruby-dev:24996] (backported from CVS HEAD)
+
+ * io.c (io_readpartial): ditto.
+
+ * io.c (io_read): ditto.
+
+Tue Nov 30 16:18:50 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_fread): need not to null terminate. [ruby-dev:24998]
+
+ * io.c (read_all): remove unnecessary rb_str_resize().
+ [ruby-dev:24996]
+
+ * io.c (io_read): ditto.
+
+Tue Nov 30 00:49:08 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_sysread): use temporary lock. [ruby-dev:24992]
+
+Mon Nov 29 16:06:04 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_write): insufficiently filled string
+ being extended when overwriting. [ruby-core:03836]
+
+Mon Nov 29 15:59:05 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/ostruct.rb (OpenStruct::method_missing): check method
+ duplication for -d.
+
+ * lib/ostruct.rb (OpenStruct::initialize): ditto.
+
+Mon Nov 29 15:22:28 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/io/nonblock/test_flush.rb: abandon tests when io/nonblock is
+ not supported.
+
+Mon Nov 29 03:08:30 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (convert_type): direct call conversion methods for the
+ performance. [ruby-core:03845]
+
+ * eval.c (rb_funcall_rescue): new function.
+
+ * object.c (rb_Array): avoid using rb_respond_to().
+
+ * object.c (rb_Integer): ditto.
+
+ * parse.y (reduce_nodes): empty body should return nil.
+
+ * string.c (rb_str_aset): the original string should not be
+ affected by modifying duplicated string. [ruby-dev:24981]
+
+Mon Nov 29 13:57:38 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (CreateChild): search executable file if no program
+ name given. (backported from CVS HEAD)
+
+Mon Nov 29 13:37:54 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (fptr_finalize): must not use FILE after fclose().
+ [ruby-dev:24985]
+
+Mon Nov 29 13:16:31 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (CreateChild): push back the last space before next
+ loop because CharNext() eats it.
+
+Mon Nov 29 01:18:18 2004 Tanaka Akira <akr@m17n.org>
+
+ * io.c (rb_io_check_writable): call io_seek regardless of
+ NEED_IO_SEEK_BETWEEN_RW. [ruby-dev:24986]
+
+Sat Nov 27 21:43:39 2004 Tanaka Akira <akr@m17n.org>
+
+ * io.c: avoid data lost with nonblocking fd and
+ stdio buffering in sync mode. [ruby-dev:24966]
+ based on matz's patch [ruby-dev:24967]
+ (io_fwrite): new primitive writing function which writes
+ directly if sync mode.
+ (rb_io_fwrite): wrapper for io_fwrite now.
+ (io_write): call io_fwrite instead of rb_io_fwrite.
+
+Sat Nov 27 14:44:15 2004 Kent Sibilev <ksibilev@bellsouth.net>
+
+ * lib/cgi/session.rb (CGI::Session::initialize): create_new_id is
+ now a instance method. [ruby-core:03832]
+
+Sat Nov 27 09:41:21 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_fread): old rb_io_fread with file closing checking.
+ (rb_io_fread): wrapper for io_fread now.
+ [ruby-dev:24964]
+
+Fri Nov 26 18:02:44 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: Tk.destroy uses TkWindow#epath
+
+ * ext/tk/lib/tk/image.rb: bug fix
+
+ * ext/tk/lib/tk/wm.rb: add 'iconphoto' method(Windows only)
+
+ * ext/tk/lib/tkextlib/*: some methods uses TkWindow#epath
+
+Fri Nov 26 13:49:06 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (method_missing): raise TypeError for classes do not
+ have allocators. [ruby-core:03752]
+
+ * lib/erb.rb: add RDoc by James Edward Gray II. [ruby-core:03786]
+
+Fri Nov 26 13:29:02 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::look_for_directives_in): Break
+ out of preprocessing when we find a :section: directive (previously cleared out the
+ comment, but this apparently now generates an error in gsub!)
+
+Fri Nov 26 00:17:40 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_read): move StringValue() check before GetOpenFile().
+ [ruby-dev:24959]
+
+Thu Nov 25 20:14:57 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/thwait.rb (ThreadsWait#join_nowait): abnormally terminated
+ threads should be also processed. [ruby-talk:121320]
+
+Thu Nov 25 10:14:26 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (push_braces): do not reuse buffer strings. [ruby-core:03806]
+
+Thu Nov 25 07:59:41 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (read_all): stringify non-nil buffer argument, and always
+ taint the result. [ruby-dev:24955]
+
+Wed Nov 24 01:01:31 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_read): integer conversion should be prior to
+ GetOpenFile(). [ruby-dev:24952]
+
+ * configure.in, io.c: cancel [ ruby-Patches-1074 ].
+
+Tue Nov 23 08:09:50 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/menu.rb: improve usability of TkOptionMenubutton
+
+Tue Nov 23 02:00:21 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * file.c (rb_file_chown): integer conversion should be prior to
+ GetOpenFile(). [ruby-dev:24949]
+
+Tue Nov 23 00:10:48 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * file.c (rb_file_chown): integer conversion should be prior to
+ GetOpenFile(). [ruby-dev:24947]
+
+ * file.c (rb_file_truncate): ditto.
+
+ * file.c (rb_file_s_truncate): ditto.
+
+ * dir.c (dir_seek): use NUM2OFFT().
+
+ * misc/ruby-mode.el (ruby-non-block-do-re): should not match words
+ start with block keyword and underscore. [ruby-core:03719]
+
+Mon Nov 22 22:33:02 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::parse_require): Don't use names
+ of variables or constants when oarsing 'require'
+
+Mon Nov 22 00:13:35 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (dir_seek): should retrieve dir_data after NUM2INT().
+ [ruby-dev:24941]
+
+Sat Nov 20 23:57:33 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/README (et al): Add a new directive, :section:, and
+ change the output format to accomodate. :section: allows to to
+ group together methods, attributes, constants, etc under
+ headings in the output. If used, a table of contents is
+ generated.
+
+Sat Nov 20 23:56:54 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/options.rb (Options::parse): Force --inline-source if
+ --one-file option given
+
+Sat Nov 20 23:55:19 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_splice): should place index wrapping after
+ possible modification. [ruby-dev:24940]
+
+Sat Nov 20 13:26:03 2004 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/utf8tbl.c: original revision 1.7
+
+Sat Nov 20 05:34:24 2004 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c: original nkf.c rev:1.40
+
+ * ext/nkf/test.rb: add test for mime encode/decode
+
+Sat Nov 20 01:37:34 2004 Johan Holmberg <holmberg@iar.se>
+
+ * eval.c (error_print): nicer traceback at interrupt.
+ [ruby-core:03774]
+
+Sat Nov 20 00:07:16 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_gsub): internal buffer should not be listed by
+ ObjectSpace.each_object() by String#gsub. [ruby-dev:24931]
+
+Fri Nov 19 01:20:22 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi/session.rb (CGI::Session::FileStore::initialize): raise
+ exception if data corresponding to session specified from the
+ client does not exist.
+
+Fri Nov 19 00:59:31 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_gsub): internal buffer should not be listed by
+ ObjectSpace.each_object(). [ruby-dev:24919]
+
+Thu Nov 18 18:41:08 2004 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/ruby/test_stringchar.rb (test_bang): added.
+
+ * string.c (rb_str_upcase_bang, rb_str_capitalize_bang)
+ (rb_str_swapcase_bang): missing rb_str_modify(). [ruby-dev:24915]
+
+Thu Nov 18 00:21:15 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * process.c (proc_getpgrp): prohibit for $SAFE=2.
+ [ruby-dev:24899]
+
+ * process.c (get_pid): ditto. [ruby-dev:24904]
+
+ * process.c (get_ppid): ditto.
+
+ * array.c (rb_ary_delete): defer rb_ary_modify() until actual
+ modification. [ruby-dev:24901]
+
+Thu Nov 18 10:10:14 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c, rubyio.h (rb_io_modenum_flags): exported.
+
+ * ext/stringio/stringio.c (strio_initialize): allow Fixnum as mode as
+ well as IO.new does. [ruby-dev:24896]
+
+Wed Nov 17 23:42:40 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/ruby/test_settracefunc.rb: added. [ruby-dev:24884]
+
+Wed Nov 17 13:56:57 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (newline_node): should not use FL_SET. [ruby-dev:24874]
+
+ * parse.y (string_content): should not use FL_UNSET.
+
+ * node.h (NODE_NEWLINE): remove unused bit to utilize flag field
+ in nodes.
+
+Wed Nov 17 13:09:40 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32,wince}/Makefile.sub (test): should build ruby.exe
+ before running test. [ruby-core:03756]
+
+Wed Nov 17 04:33:01 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * pack.c: all features are backport from 1.9. [ruby-dev:24826]
+
+ * bignum.c (rb_big2ulong_pack): new function to pack Bignums.
+
+Wed Nov 17 03:42:45 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_splice): move rb_str_modify() after
+ StringValue(), which may alter the receiver. [ruby-dev:24878]
+
+Tue Nov 16 23:45:07 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (flo_divmod): protect float values from GC by
+ assignment to local variables. [ruby-dev:24873]
+
+Tue Nov 16 16:30:21 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32,wince}/setup.mak (-epilogue-): remove config.h and
+ config.status to force updating them.
+
+Tue Nov 16 16:20:45 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_read): position was ignored when a
+ buffer was passed. http://www.yo.rim.or.jp/~nov/d/?date=20041116#p03
+
+Tue Nov 16 11:19:07 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/autorunner.rb (Test::Unit::AutoRunner::options): use
+ Regexp conversion.
+
+Tue Nov 16 01:41:31 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_mod_check): frozen check should be separated.
+ [ruby-core:3742]
+
+ * array.c (rb_ary_update): pedantic check to detect
+ rb_ary_to_ary() to modify the receiver. [ruby-dev:24861]
+
+Mon Nov 15 13:50:52 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_justify): typo fixed. [ruby-dev:24851]
+
+Mon Nov 15 11:50:32 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-special-char-p, ruby-parse-partial): handle
+ operator symbols. [ruby-talk:120177]
+
+Sun Nov 14 13:27:03 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/pp.rb (PP#object_address_group): remove odd number of 'f'
+ prefixed to negative address.
+
+Sun Nov 14 08:51:04 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/logger/test_logger.rb: Logger just expects
+ Logger#datetime_format to be used for Time#strftime independently of
+ locale. [ruby-dev:24828]
+
+Fri Nov 12 15:03:26 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * eval.c (ruby_options): now we cannot call rb_glob() before
+ ruby_init(), so call rb_w32_cmdvector() at ruby_options().
+
+ * win32.{c,h} (rb_w32_cmdvector): rename make_cmdvector() and
+ export it.
+
+Fri Nov 12 14:08:01 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/event.rb: remove $LOADED_FEATURES trick
+
+ * ext/tk/lib/tk.rb: ditto
+
+Fri Nov 12 00:31:05 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/gdbm/gdbm.c (fgdbm_store): StringValue() may alter string
+ pointer. [ruby-dev:24783]
+
+Thu Nov 11 17:36:12 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (rb_globi): also should call back via rb_glob_caller().
+ [ruby-dev:24775]
+
+Thu Nov 11 16:47:21 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/ruby/test_file.rb (test_truncate_wbuf): we want to test
+ only File#truncate, not behaviour of seek(2).
+
+Thu Nov 11 09:41:01 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (push_braces): was confusing VALUE and char*.
+
+ * dir.c (rb_push_glob): Dir.glob should have called its block.
+
+Thu Nov 11 01:52:52 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * error.c (syserr_initialize): use stringified object.
+ [ruby-dev:24768]
+
+Wed Nov 10 22:49:01 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb (SimpleDelegator::dup): wrong number of
+ arguments.
+
+ * lib/delegate.rb (DelegateClass::dup): ditto.
+
+Wed Nov 10 12:31:21 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * README.EXT (Example): extconf.rb is indispensable now.
+
+Wed Nov 10 03:33:36 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: fix SEGV when compiled with Tcl/Tk8.3.x
+ or older
+
+ * ext/tk/lib/tkextlib/tile/style.rb: bug fix
+
+Tue Nov 9 14:27:18 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::Officious): moved from DefaultList.
+
+Tue Nov 9 01:05:04 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (rb_glob2): do not allocate buffer from heap to avoid
+ memory leaks. use string object for buffering instead.
+ [ruby-dev:24738]
+
+ * dir.c (join_path): ditto.
+
+ * io.c (io_read): external input buffer may be modified even after
+ rb_str_locktmp(). [ruby-dev:24735]
+
+ * dir.c (fnmatch): p or s may be NULL. [ruby-dev:24749]
+
+Tue Nov 9 00:53:53 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * regex.c (slow_match): avoid GCC 3.4.x warnings.
+
+Tue Nov 9 00:50:06 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/rdoc.rb: Change version numbering of RDoc and ri
+
+Mon Nov 8 23:38:35 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/extservm.rb: add DRb::ExtServManager#uri=.
+ [ruby-dev:24743]
+
+Mon Nov 8 22:20:19 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_class):
+ Fix bug where parent class wasn't being detected if the
+ child class was defined using the A::B notation.
+
+Mon Nov 8 00:14:13 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: add setup for mignw32 cross compiling.
+ [ruby-talk:119413]
+
+Sun Nov 7 23:49:26 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: bind-event methods accept multi substitution
+ arguments.
+
+ * ext/tk/lib/tk/canvas.rb: ditto.
+
+ * ext/tk/lib/tk/canvastag.rb: ditto.
+
+ * ext/tk/lib/tk/text.rb: ditto.
+
+ * ext/tk/lib/tk/texttag.rb: ditto.
+
+ * ext/tk/lib/tkextlib: ditto.
+
+Sat Nov 6 14:58:44 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/server.rb (WEBrick::HTTPServer#start): remove
+ :DoNotReverseLookup option. (Socket#do_not_reverse_lookup is a
+ ruby 1.9 feature)
+
+Sat Nov 6 11:31:04 2004 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (_parse): checks whether zone was given.
+
+Sat Nov 6 00:46:27 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_locktmp): check STR_TMPLOCK flag before
+ locking. [ruby-dev:24727]
+
+Fri Nov 5 18:12:42 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/scrollable.rb: divide Scrollable module into
+ X_Scrollable and Y_Scrollable
+
+ * ext/tk/lib/tk/entry.rb: include X_Scrollable instead of Scrollable
+
+ * ext/tk/lib/tk/autoload.rb: define autoload for X_Scrollable and
+ Y_Scrollable
+
+Fri Nov 5 16:05:32 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: TkComm._at() supprts both of "@x,y" and "@x"
+
+Fri Nov 5 13:22:58 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/text.rb: sorry. bug fix again.
+
+Fri Nov 5 13:17:54 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/text.rb: bug fix
+
+Fri Nov 5 08:52:48 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (gc_mark): stricter GC stack check.
+
+Fri Nov 5 08:52:48 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (gc_mark): stricter GC stack check.
+
+Fri Nov 5 08:34:43 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_gsub): should have removed rb_str_unlocktmp(str).
+ [ruby-dev:24708]
+
+Thu Nov 4 21:25:38 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_gsub): string modify check no longer based on
+ tmplock. [ruby-dev:24706]
+
+Thu Nov 4 19:27:46 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * io.c (rb_f_open): fix typo.
+
+Thu Nov 4 15:02:14 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/variable.rb: forget to initialize instance_variables
+ of TkVarAccess objects
+
+Thu Nov 4 09:11:35 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (gc_mark): enable GC stack checking.
+
+Thu Nov 4 03:11:33 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_gsub): lock strings temporarily. [ruby-dev:24687]
+
+ * ext/socket/socket.c (s_recvfrom): tmplock input buffer.
+ [ruby-dev:24705]
+
+Wed Nov 3 22:32:12 2004 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * process.c: On NetBSD don't use setruid() and setrgid().
+
+Wed Nov 3 22:24:17 2004 Daigo Moriwaki <techml@sgtpepper.net>
+
+ * lib/webrick/httpauth/digestauth.rb: use Base64.encode64 to
+ avoid warnings.
+
+Wed Nov 3 17:19:59 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_uniq_bang): do not push frozen string from hash
+ table. [ruby-dev:24695]
+
+ * array.c (rb_ary_and): ditto.
+
+ * array.c (rb_ary_or): ditto.
+
+Wed Nov 3 17:13:02 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * io.c (pipe_open): fix compile error
+
+Wed Nov 3 16:58:07 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: support to use different Tcl commands between
+ configure and configinfo
+
+ * ext/tk/lib/font.rb: ditto.
+
+ * ext/tk/lib/itemconfig.rb: support to use different Tcl commands
+ between item_configure and item_configinfo
+
+ * ext/tk/lib/itemfont.rb: ditto.
+
+ * ext/tk/extconf.rb: install SUPPORT_STATUS
+
+ * ext/tk/lib/tkextlib: some bug fixes (see ext/tk/ChangeLog.tkextlib)
+
+Wed Nov 3 16:30:41 2004 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf: follow nkf 2.0.4
+
+Wed Nov 3 15:53:34 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * test/rss/test_maker_*.rb: added tests for RSS Maker.
+
+ * lib/rss/maker.rb: added RSS Maker.
+
+ * lib/rss/maker/*.rb: ditto.
+
+Tue Nov 2 16:35:57 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/enumerator/enumerator.c (each_cons_i): pass copy of an
+ internal consequent array. [ruby-talk:118691]
+
+Tue Nov 2 16:05:21 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * process.c (rb_f_fork): need to flush stdout and stderr before
+ fork(2). [ruby-talk:117715]
+
+Tue Nov 2 01:20:09 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_invoke): nail down dyna_var node when Proc object
+ or continuation is created. [ruby-dev:24671]
+
+Mon Nov 1 13:59:28 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/extmk.rb (MANIFEST): do not use anymore, use extconf.rb instead.
+
+ * ext/enumerator/extconf.rb, ext/fcntl/extconf.rb,
+ ext/stringio/extconf.rb: added.
+
+ * MANIFEST, ext/**/MANIFEST: removed.
+
+ * README.EXT, README.EXT.ja: remove MANIFEST stuff.
+
+Mon Nov 1 01:14:52 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_f_open): create copy of popen specifier. [ruby-dev:24656]
+
+Mon Nov 1 00:36:48 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * main.c (_stklen): move to gc.c.
+
+Sun Oct 31 00:22:28 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_locktmp): lock string temporarily.
+
+ * string.c (str_independent): add tmplock check.
+
+ * io.c (io_write): lock output string temporarily.
+ [ruby-dev:24649]
+
+ * io.c (io_write): use rb_str_locktmp().
+
+ * io.c (read_all): ditto.
+
+Sat Oct 30 06:53:24 2004 Peter Vanbroekhoven <peter.vanbroekhoven@cs.kuleuven.ac.be>
+
+ * eval.c (rb_eval): NODE_XSTR should pass copy of literal string.
+
+Sat Oct 30 00:19:40 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * enum.c (enum_sort_by): protect continuation jump in.
+ [ruby-dev:24642]
+
+Fri Oct 29 21:27:51 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_check_initialized): new function to check uninitialized
+ object. [ruby-talk:118234]
+
+ * file.c (rb_file_path), io.c (rb_io_closed): check if initialized.
+
+Fri Oct 29 10:00:30 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_start_0): forget to free some memory chunks.
+ [ruby-core:03611]
+
+ * eval.c (ruby_cleanup): ruby_finalize_1 may cause exception,
+ should be wrapped by PUSH_TAG/POP_TAG(). [ruby-dev:24627]
+
+Thu Oct 28 08:42:02 2004 Tanaka Akira <akr@m17n.org>
+
+ * io.c (argf_forward): use ANSI style.
+ (argf_read): call argf_forward with argv argument.
+ [ruby-dev:24624]
+
+Thu Oct 28 23:32:54 2004 akira yamada <akira@ruby-lang.org>
+
+ * ext/zlib/zlib.c (zstream_detach_input): resets klass of z->input if
+ z->input isn't nil.
+
+Thu Oct 28 23:19:31 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: prefer relative path. [ruby-talk:93037]
+
+Wed Oct 27 18:49:11 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * gc.c: prototype; rb_io_fptr_finalize() doesn't return any value
+ at this version.
+
+Wed Oct 27 17:27:45 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (gc_sweep): recover ruby_in_compile variable.
+
+Wed Oct 27 09:17:30 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (str_gsub): use a string object for exception safeness.
+ [ruby-dev:24601]
+
+Tue Oct 26 23:52:32 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_getline): rs modification check should not interfere in the loop.
+
+Tue Oct 26 23:30:39 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/code_objects.rb (RDoc::Context::add_class_or_module):
+ Restore correct :nopdoc: behavior with nested classes and modules.
+
+Tue Oct 26 18:21:29 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (RESIZE_CAPA): check string attribute before modifying
+ capacity member of string structure. [ruby-dev:24594]
+
+Tue Oct 26 11:33:26 2004 David G. Andersen <dga@lcs.mit.edu>
+
+ * ext/zlib/zlib.c (gzreader_gets): use memchr() to to gain
+ performance. [ruby-talk:117701]
+
+Tue Oct 26 10:56:55 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): raise ArgumentError for extra
+ arguments, unless (digit)$ style used.
+
+Tue Oct 26 11:33:26 2004 David G. Andersen <dga@lcs.mit.edu>
+
+ * ext/zlib/zlib.c (gzreader_gets): use memchr() to to gain
+ performance. [ruby-talk:117701]
+
+Tue Oct 26 10:56:55 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): raise ArgumentError for extra
+ arguments, unless (digit)$ style used.
+
+Mon Oct 25 18:35:39 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c (isUNCRoot): should check NUL after '.'.
+ [ruby-dev:24590]
+
+ * win32/win32.c (isUNCRoot): fixed buffer overrun.
+
+Mon Oct 25 08:03:26 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (get_backtrace): ignore illegal backtrace. [ruby-dev:24587]
+
+Sun Oct 24 00:41:09 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_load, search_required, rb_require_safe, rb_require): use
+ frozen shared string to avoid outside modification. [ruby-dev:24580]
+
+Sat Oct 23 22:18:32 2004 Guy Decoux <ts@moulon.inra.fr>
+
+ * eval.c (frame_free): Guy Decoux solved the leak problem.
+ Thanks. [ruby-core:03549]
+
+Sat Oct 23 00:20:55 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/zlib/zlib.c (zstream_append_input): clear klass for z->input
+ to avoid potential vulnerability.
+
+ * ext/zlib/zlib.c (zstream_run): always use zstream_append_input()
+ to avoid SEGV. [ruby-dev:24568]
+
+Fri Oct 22 12:02:28 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_alias): was warning for wrong condition.
+ [ruby-dev:24565]
+
+Fri Oct 22 10:36:37 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httprequest.rb (WEBrick::HTTPRequest#meta_vars):
+ should check if path_info is not nil.
+
+Fri Oct 22 00:22:31 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/zlib/zlib.c (zstream_shift_buffer): should restore class
+ field of a buffer. [ruby-dev:24562]
+
+Fri Oct 22 00:20:33 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_include): should not treat char as negative value.
+ [ruby-dev:24558]
+
+Thu Oct 21 21:32:30 2004 IWATSUKI Hiroyuki <don@na.rim.or.jp>
+
+ * lib/pstore.rb (PStore#transaction): Use the empty content when a
+ file is not found. [ruby-dev:24561]
+
+Thu Oct 21 19:06:15 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpresponse.rb (WEBrick::HTTPResponse#send_body_io):
+ ensure to close @body. (http://bugs.debian.org/277520)
+
+Thu Oct 21 00:36:41 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_alias): should warn on method discarding.
+ [ruby-dev:24546]
+
+ * ext/zlib/zlib.c (zstream_expand_buffer_into): hide internal
+ string buffer by clearing klass. [ruby-dev:24548]
+
+Wed Oct 20 19:45:13 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_gsub): reentrant check. [ruby-dev:24432]
+
+ * backport all SEGV bug fixes from CVS HEAD. [ruby-dev:24536]
+
+Wed Oct 20 04:17:55 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dbm/dbm.c (fdbm_delete_if): should check if deleting element
+ is a string. [ruby-dev:24490]
+
+ * ext/sdbm/init.c (fsdbm_delete_if): ditto.
+
+Wed Oct 20 01:37:18 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_times): Array#* should return an instance of
+ the class of right operand. [ruby-dev:24526]
+
+ * ext/zlib/zlib.c (zstream_detach_buffer): should not expose
+ class-less object to Ruby world. [ruby-dev:24530]
+
+ * eval.c (proc_dup): provide Proc#dup as well. [ruby-talk:116915]
+
+ * eval.c (ruby_exec): stack marking position may be higher than
+ expected. thanks to Guy Decoux. [ruby-core:03527]
+
+Tue Oct 19 22:43:12 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_attr): If
+ we come across 'attr' in a context where it isn't
+ followed by a symbol, just issue a warning.
+
+Tue Oct 19 20:41:37 2004 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole.c(ole_invoke): retrieve the result value when
+ retrying the IDispatch::invoke.
+
+Tue Oct 19 17:24:11 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (read_all): block string buffer modification during
+ rb_io_fread() by freezing it temporarily. [ruby-dev:24479]
+
+ * dir.c (rb_push_glob): block call at once the end of method.
+ [ruby-dev:24487]
+
+ * ext/enumerator/enumerator.c (enum_each_slice): remove
+ rb_gc_force_recycle() to prevent potential SEGV.
+ [ruby-dev:24499]
+
+ * ext/zlib/zlib.c (zstream_expand_buffer): hide internal string
+ buffer by clearing klass. [ruby-dev:24510]
+
+Tue Oct 19 16:12:18 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil.c: backport from CVS HEAD
+
+Tue Oct 19 08:54:26 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * intern.h, object.c (rb_class_inherited_p): export.
+
+Tue Oct 19 08:46:57 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_upto): method result must be checked. [ruby-dev:24504]
+
+ * eval.c (error_print): ditto. [ruby-dev:24519]
+
+Mon Oct 18 23:37:05 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (r_object0): check inheritance by the internal function.
+ [ruby-dev:24515]
+
+Mon Oct 18 15:58:01 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * range.c (range_step, range_each): need cast.
+
+Fri Oct 29 16:34:19 2004 Daiki Ueno <ueno@unixuser.org>
+
+ * misc/ruby-mode.el (ruby-parse-partial): Parse the rest of the
+ line after opening heredoc identifier. [ruby-dev:24635]
+
+Mon Oct 18 07:26:21 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_truncate): discard read buffer before truncation.
+ [ruby-dev:24197]
+
+Mon Oct 18 02:11:21 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/config.rb (WEBrick::Config::General): add default values:
+ - WEBrick::Config[:DoNotReverseLookup]
+ - WEBrick::Config[:RequestCallback] (it used as an alias of
+ :RequestHandler in WEBrick::HTTPServer#run)
+ - WEBrick::Config::FileHandler[:AcceptableLanguages]
+
+ * lib/webrick/httpservlet/filehandler.rb
+ (WEBrick::HTTPServlet::FileHandler#set_filename): search files
+ having suffix of language-name which Accept-Language header field
+ includes if :AcceptableLanguages options is present.
+
+ * lib/webrick/httpservlet/filehandler.rb
+ (WEBrick::HTTPServlet::FileHandler#get_servlet): new method to
+ search servlet correspond to the suffix of filename.
+
+ * lib/webrick/httprequest.rb: add attributes access methods: accept,
+ accept_charset, accept_encoding, accept_language, content_length
+ and content_type.
+
+ * lib/webrick/httpresponse.rb: add attribute access methods:
+ content_length, content_length=, content_type and content_type=.
+
+ * lib/webrick/httputils.rb (WEBrick::HTTPUtils.mime_types):
+ use the second suffix to detect media type. (the first suffix
+ may be a language name.)
+
+ * lib/webrick/httputils.rb (WEBrick::HTTPUtils.parse_qvalues):
+ add method to parse Accept header field. it returns an Array of
+ values sorted by the qvalues.
+
+Mon Oct 18 02:04:11 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpserver.rb (WEBrick::HTTPServer#virtual_host): new
+ method to register virtual hosting servers.
+
+ * lib/webrick/server.rb (WEBrick::GenericServer#accept): call
+ do_not_reverse_lookup for each socket if :DoNotReverseLookup
+ is set. [ruby-core:02357]
+
+Mon Oct 18 00:42:45 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (sock_s_getservbyaname): protocol string
+ might be altered. [ruby-dev:24503]
+
+ * string.c (rb_str_upto): check if return value from succ is a
+ string. [ruby-dev:24504]
+
+Sun Oct 17 23:03:48 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/timer.rb: TkTimer#start and restart accept a block
+
+Sun Oct 17 13:05:04 2004 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (fole_func_methods): correct argument mismatch.
+ * ext/win32ole/win32ole.c (fole_get_methods): ditto.
+ * ext/win32ole/win32ole.c (fole_put_methods): ditto.
+ * ext/win32ole/tests/testWIN32OLE.rb: add test for WIN32OLE#ole_func_methods
+ WIN32OLE#ole_get_methods, WIN32OLE#ole_put_methods
+
+Sat Oct 16 14:45:28 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/0.9.rb (RSS::Rss#to_s): removed garbage.
+
+Sat Oct 16 13:42:49 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/: untabified.
+ * test/rss/: untabified.
+ * lib/rss/0.9.rb (RSS::Rss#to_s): inent -> indent.
+
+Sat Oct 16 13:34:56 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss: supported prety print.
+ * test/rss/test_1.0.rb: added test for calculating default indent size.
+
+Fri Oct 15 18:04:35 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/timer.rb: TkTimer.new(interval, loop){ ... } is
+ acceptable. Add TkTimer.start ( == new + start ).
+
+Fri Oct 15 12:43:09 2004 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (Init_stack): make prototype declaration consistent with
+ the definition in gc.c.
+
+Thu Oct 14 14:34:01 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * io.c (MODE_BINMODE, MODE_BINARY): fixed reversed condition.
+
+Thu Oct 14 13:33:59 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: added link to Tutorial.
+
+Mon Oct 11 13:48:20 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/*: untabify
+
+Sun Oct 10 12:32:08 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::parse_require): Allow 'require'
+ to be used as a variable name
+
+Sat Oct 9 21:23:37 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/converter.rb: changed to try to use Iconv for default
+ conversion.
+
+ * lib/rss/rss.rb: 0.0.9 -> 0.1.0.
+
+Sat Oct 9 19:50:36 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_getline): should not treat char as negative value.
+ [ruby-dev:24460]
+
+Fri Oct 8 09:49:32 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_pack): pointer modification check before each
+ iteration. [ruby-dev:24445]
+
+Fri Oct 8 01:13:05 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/optiondb.rb: make it more secure
+
+Thu Oct 7 23:47:57 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/scrollbar.rb: When 'set' operation, a scrollbar
+ cannot propagate view port information from the source widget
+ (that calls 'set') to other assigned widgets.
+
+Thu Oct 7 17:36:25 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: When CHILDKILLED and so on, Tk.errorCode returns
+ a Fixnum for 2nd element (it's pid) of the return value.
+
+Thu Oct 7 12:55:04 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_read): should freeze buffer before thread context
+ switch. [ruby-dev:24442]
+
+ * pack.c (pack_unpack): string conversion should at the top of the
+ method. [ruby-dev:24439]
+
+ * io.c (io_read): buffer should be frozen only after the length
+ check. [ruby-dev:24440]
+
+Thu Oct 7 02:56:43 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c: use FMODE_APPEND.
+
+Thu Oct 7 01:05:33 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: add Tk.errorInfo and Tk.errorCode
+
+Thu Oct 7 00:08:37 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_s_sysopen): preserve path in the buffer allocated by
+ ALLOCA_N() to prevent modification. [ruby-dev:24438]
+
+Wed Oct 6 09:21:00 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_mode_flags): preserve append mode flag.
+ [ruby-dev:24436]
+
+ * io.c (rb_io_modenum_mode): do not use external output buffer.
+
+ * string.c (rb_str_justify): differ pointer retrieval to prevent
+ padding string modification. [ruby-dev:24434]
+
+ * range.c (range_each_func): allow func to terminate loop by
+ returning RANGE_EACH_BREAK.
+
+ * range.c (member_i): use RANGE_EACH_BREAK. [ruby-talk:114959]
+
+Mon Oct 4 14:04:14 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_file_open_internal, rb_io_reopen): fname might be altered
+ while GC. [ruby-dev:24408]
+
+Mon Oct 4 12:53:45 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/optiondb.rb: support definition of command
+ resources on widgets
+
+ * ext/tk/lib/tk/image.rb: bug fix
+
+Sun Oct 3 21:20:03 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (TEXT_REGEXP): allow 8-bit characters for the german
+ version of Microsoft Exchange Server. (backported from HEAD)
+
+ * lib/net/imap.rb (RTEXT_REGEXP): ditto.
+
+ * lib/net/imap.rb (CTEXT_REGEXP): ditto.
+
+Sat Oct 2 20:34:22 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * node.h (NEW_DVAR): extra semicolon.
+
+Sat Oct 2 00:42:20 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (r_byte): retrieve pointer from string value for each
+ time. [ruby-dev:24404]
+
+ * marshal.c (r_bytes0): ditto.
+
+ * enum.c (sort_by_i): re-entrance check added. [ruby-dev:24399]
+
+ * io.c (io_read): should freeze all reading buffer.
+ [ruby-dev:24400]
+
+ * string.c (rb_str_sum): should use bignums when bits is greater
+ than or equals to sizeof(long)*CHAR_BITS. [ruby-dev:24395]
+
+ * eval.c (specific_eval): defer pointer retrieval to prevent
+ unsafe sourcefile string modification. [ruby-dev:24382]
+
+ * eval.c (specific_eval): defer pointer retrieval to prevent
+ unsafe sourcefile string modification. [ruby-dev:24382]
+
+ * string.c (rb_str_sum): wrong cast caused wrong result.
+ [ruby-dev:24385]
+
+ * enum.c (enum_sort_by): hide temporary array from
+ ObjectSpace.each_object. [ruby-dev:24386]
+
+ * string.c (rb_str_sum): check was done with false pointer.
+ [ruby-dev:24383]
+
+ * string.c (rb_str_sum): string may be altered. [ruby-dev:24381]
+
+Mon Oct 11 17:51:34 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_popen): get mode string via rb_io_flags_mode() to
+ avoid mode string modification. [ruby-dev:24454]
+
+ * io.c (rb_io_getline_fast): should take delim as unsigned char to
+ distinguish EOF and '\377'. [ruby-dev:24460]
+
+ * io.c (rb_io_getline): add check for RS modification.
+ [ruby-dev:24461]
+
+ * enum.c (enum_sort_by): use qsort() directly instead using
+ rb_iterate(). [ruby-dev:24462]
+
+ * enum.c (enum_each_with_index): remove rb_gc_force_recycle() to
+ prevent access to recycled object (via continuation for
+ example). [ruby-dev:24463]
+
+Fri Oct 1 11:40:14 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_f_eval): defer pointer retrieval to prevent unsafe
+ sourcefile string modification. [ruby-dev:24373]
+
+ * io.c (io_read): block string buffer modification during
+ rb_io_fread() by freezing it temporarily. [ruby-dev:24366]
+
+ * io.c (rb_io_s_popen): mode argument may be altered.
+ [ruby-dev:24375]
+
+ * file.c (rb_file_s_basename): ext argument may be altered.
+ [ruby-dev:24377]
+
+ * enum.c (enum_sort_by): use NODE instead of 2 element arrays.
+ [ruby-dev:24378]
+
+ * string.c (rb_str_chomp_bang): StringValue() may change the
+ receiver. [ruby-dev:24371]
+
+Fri Oct 1 11:25:20 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/grid.rb: revive TkGrid.grid
+
+ * ext/tk/lib/tk/pack.rb: revive TkPack.pack
+
+ * ext/tk/lib/tk/place.rb: revive TkPlace.place
+
+Thu Sep 30 00:50:44 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_init): bug fix
+
+ * ext/tk/tkutil.c (get_eval_string_core): accept a Regexp object
+
+ * ext/tk/lib/multi-tk.rb: fix bug on 'exit' operation
+
+ * ext/tk/lib/tk/text.rb: 'tksearch' accepts a Regexp object as a
+ matting pattern argument
+
+Wed Sep 29 10:58:07 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (sort_by_i): internally used object must not be changed
+ outside. [ruby-dev:24368]
+
+Mon Sep 27 13:46:45 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * intern.h, struct.c (rb_struct_s_members, rb_struct_members): public
+ accessors. [ruby-dev:24342]
+
+ * marshal.c (w_object, r_object0): use accessors.
+
+Mon Sep 27 09:14:03 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (s_accept): don't retry for EWOULDBLOCK.
+ [ruby-talk:113807]
+
+Fri Sep 24 16:09:42 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_invoke): propagate DVAR_DONT_RECYCLE on termination
+ to avoid double call to rb_gc_force_recycle(). [ruby-dev:24311]
+
+Fri Sep 24 08:29:45 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_subseq): original object might be modified after
+ sharing data creation. [ruby-dev:24327]
+
+ * array.c (rb_ary_replace): ditto.
+
+ * array.c (ary_make_shared): freeze shared array. [ruby-dev:24325]
+
+ * struct.c (struct_members): always check struct size and size of
+ members list in the class. [ruby-dev:24320]
+
+Thu Sep 23 09:29:14 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_sub_bang): check if string is not modified
+ during iteration. [ruby-dev:24315]
+
+ * hash.c (rb_hash_rehash): replace st_foreach() by its deep
+ checking counterpart. [ruby-dev:24310]
+
+Wed Sep 22 13:38:12 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (rb_hash_rehash): add iteration check. [ruby-dev:24301]
+
+ * st.c (st_foreach): add deep check.
+
+Wed Sep 22 13:06:14 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_call_handler): workaround for Ctrl-C.
+ merge from HEAD.
+
+Wed Sep 22 00:11:12 2004 Dave Thomas <dave@pragprog.com>
+
+ * process.c: Add documentation for fork()
+
+Wed Sep 22 09:04:41 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_collect_bang): element size might change during
+ comparison. [ruby-dev:24300]
+
+ * array.c (rb_ary_reject_bang): ditto. [ruby-dev:24300]
+
+ * array.c (rb_ary_eql): ditto. [ruby-dev:24300]
+
+Tue Sep 21 18:29:49 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_equal): merge miss.
+
+ * array.c (rb_ary_uniq_bang): element size might change during
+ comparison. [ruby-dev:24298]
+
+Mon Sep 20 00:24:19 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * enum.c (enum_sort_by): do not use qsort directly. use
+ rb_ary_sort_bang() instead. [ruby-dev:24291]
+
+ * enum.c (enum_sort_by): pedantic type check added.
+ [ruby-dev:24291]
+
+ * hash.c (rb_hash_foreach_iter): check iter_lev after each
+ iteration. [ruby-dev:24289]
+
+ * array.c (rb_ary_and): element size might change during
+ comparison. [ruby-dev:24290]
+
+ * array.c (rb_ary_or): ditto. [ruby-dev:24292]
+
+ * array.c (rb_ary_equal): wrong fix. [ruby-dev:24286]
+
+Sat Sep 18 15:02:22 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_equal): element size might change during
+ comparison. [ruby-dev:24254]
+
+ * array.c (rb_ary_diff): ditto. [ruby-dev:24274]
+
+ * array.c (rb_ary_select): ditto. [ruby-dev:24278]
+
+ * array.c (rb_ary_delete): ditto. [ruby-dev:24283]
+
+ * array.c (rb_ary_rindex): ditto. [ruby-dev:24275]
+
+ * array.c (rb_ary_initialize): element size might change during
+ initializing block. [ruby-dev:24284]
+
+Sat Sep 18 14:10:23 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (dir_s_chdir): avoid memory leak and unnecessary chdir to
+ the original directory when exception has caused in changing
+ direcotry or within block. thanks to Johan Holmberg
+ <holmberg@iar.se> [ruby-core:03446]
+
+Fri Sep 17 20:20:27 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (mkdir_p): backport from CVS HEAD 1.45. [ruby-core:03420]
+
+Fri Sep 17 17:11:08 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_delete): element comparison might change array
+ size. [ruby-dev:24273]
+
+ * file.c (rb_file_truncate): clear stdio buffer before truncating
+ the file. [ruby-dev:24191]
+
+ * ext/digest/digest.c: use rb_obj_class() instead of CLASS_OF
+ which might return singleton class. [ruby-dev:24202]
+
+Fri Sep 17 16:07:09 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: improve exit operation
+
+Fri Sep 17 15:01:57 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: fix SEGV when (thread_)vwait or
+ (thread_)tkwait
+
+ * ext/tk/lib/tk.rb: add alias wait_window to wait_destroy
+
+ * ext/tk/lib/multi-tk.rb: support calling 'mainloop' on slave
+ interpreters (however, the 'real' eventloop must be run on the
+ Default Master IP)
+
+ * ext/tk/lib/remote-tk.rb: follow the changes of ext/tk/lib/multi-tk.rb
+
+ * ext/tk/sample/remote-ip_sample2.rb: ditto
+
+ * ext/tk/sample/tkoptdb-safeTk.rb: ditto
+
+Thu Sep 16 18:12:32 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb (WEBrick::CGI#start): should set REMOTE_USER
+ to request.user attribute.
+
+ * lib/webrick/httpservlet/filehandler.rb
+ (WEBrick::HTTPServlet::FileHandler#initialize): should expand
+ the pathname of document root directory.
+
+Thu Sep 16 15:49:28 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_intern): protect string argument from GC.
+ [ruby-core:03411]
+
+Wed Sep 15 20:22:23 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/tkoptdb-safeTk.rb: fix a bug depend on the changes
+ of MultiTkIp
+
+Tue Sep 14 23:54:11 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: MultiTkIp#eval_string was en-bugged by
+ the previous changes.
+
+Tue Sep 14 23:45:44 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_formatter.rb (RI::TextFormatter::TextFormatter.for):
+ Add Eric Hodel's simpleformatter.
+
+Tue Sep 14 16:59:37 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: fix SEGV
+
+ * ext/tk/lib/multi-tk.rb: improve safe-level handling of argument proc
+
+ * ext/tk/sample/multi-ip_sample.rb: rename of old 'safe-tk.rb'
+
+ * ext/tk/sample/safe-tk.rb: new sample script
+
+Tue Sep 14 00:15:15 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/zlib/zlib.c: backported from HEAD.
+
+Mon Sep 13 19:16:33 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * eval.c (blk_copy_prev): need frame_dup(). [ruby-dev:24103]
+
+Mon Sep 13 16:23:27 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: MultiTkIp.new_master and new_slave accept
+ safe-level value argument
+
+Mon Sep 13 10:20:45 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * object.c (nil_inspect): fix typo.
+
+Mon Sep 13 01:03:02 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: improve control of preserv/release tcltkip
+
+ * ext/tcltklib/tcltklib.c: store original 'exit' command
+
+ * ext/tk/tkutil.c: fix(?) SEGV
+
+Sun Sep 12 23:46:23 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * util.c (ruby_strdup): remove unnecessary code. (xmalloc never
+ returns NULL.)
+
+ * util.c (ruby_getcwd): fix memory leak on failure.
+
+Sun Sep 12 02:41:58 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: add TclTkIp#allow_ruby_exit? and
+ allow_ruby_exit=
+
+ * ext/tk/lib/multi-tk.rb: ditto.
+
+ * ext/tk/lib/remote-tk.rb: ditto.
+
+ * ext/tcltklib/MANUAL.euc: ditto.
+
+ * ext/tcltklib/MANUAL.eng: ditto.
+
+ * ext/tcltklib/tcltklib.c: fix some reasons of SEGV
+
+ * ext/tk/tkutil.c: ditto.
+
+ * ext/tk/lib/multi-tk.rb: ditto.
+
+ * ext/tk/lib/tk/timer.rb: ditto.
+
+Sat Sep 11 16:09:46 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb: Fix up cross-file class merging.
+
+Fri Sep 10 20:20:53 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tcltklib/tcltklib.c (lib_merge_tklist): fix suspicious
+ pointer conversion.
+
+Fri Sep 10 02:43:54 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/template/kilmer.rb: James Buck's
+ patch for call-seq.
+
+Thu Sep 9 13:58:56 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_init): change flag value for setting
+ 'argv' and 'argv0' variable
+
+ * ext/tk/lib/remote-tk.rb: follow changes of multi-tk.rb
+
+Thu Sep 9 11:46:18 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::do_classes): Allow
+ spaces aroun parameter to define_method_under (James Buck)
+
+Wed Sep 8 18:44:03 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_write): zero fill a gap if exsts.
+ [ruby-dev:24190]
+
+Wed Sep 8 15:19:49 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_init): cannot create a IP at level 4
+
+ * ext/tk/lib/multi-tk.rb: improve 'exit' operation, security check,
+ and error treatment
+
+ * ext/tk/lib/multi-tk.rb: allow a trusted slave IP to create slave IPs
+
+ * ext/tk/lib/tk/listbox.rb: add TkListbox#value, value=, clear, and
+ erase
+
+ * ext/tk/lib/tk/text.rb: add TkText#clear and erase
+
+Tue Sep 7 15:17:49 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/socket/socket.c (ruby_connect): break immediately if a
+ socket is non-blocking. [ruby-talk:111654]
+
+Mon Sep 6 11:08:50 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tk/lib/tk/menu.rb(TkOptionMenubutton#insert): call correct method
+
+Mon Sep 6 11:00:47 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (dir_s_chdir): the patch to shut up false warning when
+ exception occurred within a block. a patch was given from Johan
+ Holmberg <holmberg at iar.se>. [ruby-core:03292]
+
+Mon Sep 6 07:51:42 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (cvar_cbase): singletons should refer outer cvar scope.
+ [ruby-dev:24223]
+
+ * eval.c (rb_load): should preserve previous ruby_wrapper value.
+ [ruby-dev:24226]
+
+Sat Sep 4 01:14:57 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (cvar_cbase): class variables cause SEGV in
+ instance_eval() for fixnums and symbols. [ruby-dev:24213]
+
+Fri Sep 3 17:47:58 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (make_struct): remove redefining constant when
+ conflict. [ruby-dev:24210]
+
+Fri Sep 3 11:31:44 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: Tk.after makes TkCore::INTERP.tk_cmd_tbl grow
+ [ruby-dev:24207]
+
+Fri Sep 3 02:12:48 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: fix typo [ruby-talk:111266]
+
+ * ext/tk/lib/tk/text.rb: fix typo
+
+ * ext/tk/lib/multi-tk.rb: improve safe-level treatment on slave IPs
+
+Fri Sep 3 01:54:20 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: already built-in libraries satisfy dependencies.
+ [ruby-dev:24028]
+
+Thu Sep 2 11:36:20 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * eval.c (rb_obj_instance_eval): backported from HEAD.
+
+Wed Sep 1 21:18:25 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tk/lib/tk/spinbox.rb: fix typo
+
+Tue Aug 31 18:24:04 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/tk/tkutil.c (cbsubst_init): fix memory leak
+
+ * ext/tk/tkutil.c (cbsubst_get_all_subst_keys): fix SEGV
+
+Tue Aug 31 16:04:22 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_delete): when a tcltkip is deleted,
+ destroy its root widget
+
+Tue Aug 31 12:30:36 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (del_root): fix SEGV
+
+Mon Aug 30 23:11:06 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_driver.rb (and others): ri now merges documentation
+ if it finds the same class in multiple places.
+
+Mon Aug 30 22:40:30 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/multi-tk.rb: 'restart' method accepts arguments
+
+Mon Aug 30 21:50:14 2004 Dave Thomas <dave@pragprog.com>
+
+ * object.c: Add RDoc for Module.included.
+
+Mon Aug 30 15:10:46 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (GNU/k*BSD): fixed FTBFS on GNU/k*BSD. [ruby-dev:24051]
+
+Mon Aug 30 11:29:35 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (CreateChild): strip trailing spaces. [ruby-dev:24143]
+ merge from HEAD.
+
+Sun Aug 29 14:08:56 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: compile error on bcc32 [ruby-dev:24081]
+
+ * ext/tk/lib/multi-tk.rb: MultiTkIp#eval_string does not work
+
+Sat Aug 28 23:04:41 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_and): protect parameters from GC.
+ [ruby-talk:110664]
+
+Thu Aug 26 04:38:29 2004 Dave Thomas <dave@pragprog.com>
+
+ * eval.c (return_jump): Minor typo in error message. Now reads
+ "return can't jump across threads".
+
+Tue Aug 24 17:30:00 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/cgi/session.rb (CGI::Session::FileStore#initialize): do not
+ use a session id as a filename. (backported from HEAD)
+
+ * lib/cgi/session/pstore.rb (CGI::Session::PStore#initialize): ditto.
+
+ * lib/cgi/session/pstore.rb (CGI::Session::PStore#initialize): use
+ Dir::tmpdir. (backported from HEAD)
+
+Tue Aug 24 14:40:16 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/cgi/session.rb (CGI::Session::FileStore#initialize): untaint
+ session id after check. (backported from HEAD)
+
+Tue Aug 24 09:09:01 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_x509attr.c (ossl_x509attr_initialize): d2i
+ functions may replace the pointer indicated by the first argument.
+
+ * ext/openssl/ossl_x509ext.c (ossl_x509ext_initialize): ditto.
+
+ * ext/openssl/ossl_x509name.c (ossl_x509name_initialize): ditto.
+
+Mon Aug 23 14:04:51 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ssl.c (ossl_ssl_read):
+ - should return an empty string if specified length to read is 0.
+ - should check for pending data and wait for fd before reading.
+ - call underlying IO's sysread if SSL session is not started.
+ [ruby-dev:24072], [ruby-dev:24075]
+
+ * ext/openssl/ossl_ssl.c (ossl_ssl_write):
+ - call underlying IO's syswrite if SSL session is not started.
+
+ * ext/openssl/ossl_ssl.c (ossl_ssl_pending): new method
+ OpenSSL::SSL#pending.
+
+ * ext/openssl/lib/openssl/buffering.rb: should not use select.
+
+Mon Aug 23 12:40:56 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/resolv.rb (Config.default_config_hash): when multiple domains
+ are set, Win32::Resolv.get_resolv_info returns Array.
+
+Sun Aug 22 01:15:31 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpproxy.rb (WEBrick::HTTPProxyServer#proxy_connect):
+ should call :ProxyContentHandler before finishing CONNECT.
+
+Sat Aug 21 06:41:16 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/tcltklib/extconf.rb (find_tcl, find_tk): find stub library.
+
+ * lib/mkmf.rb (arg_config, with_config): deal with '-' and '_'
+ uniformly. [ruby-dev:24118]
+
+Thu Aug 19 16:29:45 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: Fail to treat a hash value of 'font' option.
+
+ * ext/tk/lib/tk.rb: bindinfo cannot return '%' substiturion infomation.
+
+ * ext/tk/lib/menu.rb: typo bug.
+
+Thu Aug 19 15:15:24 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (free_dir): fix memory leak. reported by yamamoto
+ madoka.
+
+Thu Aug 19 11:00:00 2004 Akiyoshi, Masamichi <masamichi.akiyoshi@hp.com>
+
+ * dln.c (dln_load): Modify to call lib$find_image_symbol for VMS.
+ * io.c (rb_io_fwrite): Use fputc() for VMS non-stream file.
+
+Thu Aug 19 06:07:45 2004 why the lucky stiff <why@ruby-lang.org>
+
+ * ext/syck/token.c: re2c no longer compiled with bit vectors. caused
+ problems for non-ascii characters. [ruby-core:03280]
+ * ext/syck/implicit.c: ditto.
+ * ext/syck/bytecode.c: ditto.
+
+ * lib/yaml/baseemitter.rb: folding now handles double-quoted strings,
+ fixed problem with extra line feeds at end of folding, whitespace
+ opening scalar blocks.
+
+ * lib/yaml/rubytypes.rb: subtelties in handling strings with
+ non-printable characters and odd whitespace patterns.
+
+Wed Aug 18 23:41:33 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/protocol.rb (rbuf_fill): OpenSSL::SSL::SSLSocket has its own
+ buffer, select(2) might not work. [ruby-dev:24072]
+
+Wed Aug 18 17:10:12 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/tcltklib/stubs.c (ruby_tcltk_stubs): need to call
+ Tcl_FindExecutable() for Tcl/Tk 8.4.
+
+Wed Aug 18 12:52:55 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_obj_instance_eval): evaluates under special singleton
+ classes as for special constants.
+
+Tue Aug 17 17:20:59 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_reopen): should clear allocated OpenFile. pointed
+ out by Guy Decoux. [ruby-core:03288]
+
+Tue Aug 17 01:36:32 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/usage.rb: Remove extra indent. Tidy 'ri' option
+ parsing so RDoc::usage plays better with OptionParser.
+
+Sat Aug 14 13:09:10 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb: backport from CVS HEAD (rev1.44).
+
+ * lib/fileutils.rb: cp_r should copy symlink itself, except cp_r
+ root.
+
+ * lib/fileutils.rb: new option mv :force.
+
+ * lib/fileutils.rb: new module FileUtils::DryRun.
+
+Sat Aug 14 02:48:16 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/usage.rb: Added. Allows command line programs
+ to report usage using their initial RDoc comment.
+
+Fri Aug 13 13:23:17 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httputils.rb (WEBrick::HTTPUtils.parse_range_header):
+ fix regex for range-spec.
+
+ * lib/webrick/httpservlet/filehandler.rb
+ (WEBrick::HTTPServlet::DefaultFileHandler#make_partial_content):
+ multipart/byteranges response was broken.
+
+ * lib/webrick/httpservlet/erbhandler.rb
+ (WEBrick::HTTPServlet::ERBHandler#do_GET): should select media type
+ by suffix of script filename.
+
+ * lib/xmlrpc/server.rb: refine example code.
+
+Wed Aug 11 17:17:50 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (RPATHFLAG): stop setting RPATHFLAG on Interix.
+
+Sun Aug 8 00:43:31 2004 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/implicit.c: added sexagecimal float#base60.
+
+ * ext/syck/rubyext.c (yaml_org_handler): ditto.
+
+ * lib/token.c: indentation absolutely ignored when processing flow
+ collections. plain scalars are trimmed if indentation follows in
+ an ambiguous flow collection.
+
+Sat Aug 7 00:50:01 2004 Tanaka Akira <akr@m17n.org>
+
+ * ext/zlib/zlib.c: Zlib::GzipReader#read(0) returns "" instead of nil.
+
+Tue Aug 3 13:49:20 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/namespace.rb: bug fix
+
+ * ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: add Tk::TreeCtrl.loupe
+
+Mon Aug 2 18:04:21 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/msgcat.rb (set_translation): bug fix (fail to set
+ trans_str to the same as src_str when trans_str is not given.)
+
+Mon Aug 2 11:53:06 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/code_objects.rb (RDoc::Context::find_symbol): Fix infinite recursion
+ looking up some top level symbols (batsman)
+
+Mon Aug 2 11:48:29 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::do_methods): Allow '.'s in
+ variable names to support SWIG generated files (Hans Fugal)
+
+Sat Jul 31 17:40:16 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-expr-beg, ruby-parse-partial,
+ ruby-calculate-indent, ruby-move-to-block, ruby-forward-sexp,
+ ruby-backward-sexp): keywords must match word-wise.
+
+Sat Jul 31 05:47:37 2004 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/yaml.rb (YAML::load_file, YAML::parse_file): added.
+
+ * lib/yaml/rubytypes.rb: exceptions were using an older
+ YAML.object_maker. [ruby-core:03080]
+
+ * ext/syck/token.c (sycklex_yaml_utf8): using newline_len to
+ handline CR-LFs. "\000" was showing up on folded blocks which
+ stopped at EOF.
+
+ * ext/syck/token.c: re2c compiled with bit vectors now.
+ * ext/syck/implicit.c: ditto.
+ * ext/syck/bytecode.c: ditto.
+
+Fri Jul 30 16:10:54 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (lib_fromUTF8_core): raise ArgumentError when
+ the unknown encoding name is given.
+
+ * ext/tcltklib/tcltklib.c (lib_toUTF8_core): ditto.
+
+ * ext/tk/lib/tk.rb (Tk::Encoding.encoding_convertfrom): bug fix.
+
+ * ext/tk/lib/tk.rb (Tk::Encoding.encoding_convertto): ditto.
+
+Wed Jul 28 18:59:17 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::initialize): remove at_exit code for CGI_PARAMS
+ and CGI_COOKIES. they will no longer be used.
+
+Wed Jul 28 01:04:44 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (run_final): wrong order of data. [ruby-dev:23984]
+
+Tue Jul 27 07:05:04 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): copy on write for argument local variable
+ assignment.
+
+ * eval.c (assign): ditto.
+
+ * eval.c (rb_call0): update ruby_frame->argv with the default
+ value used for the optional arguments.
+
+ * object.c (Init_Object): "===" calls rb_obj_equal() directly.
+ [ruby-list:39937]
+
+Mon Jul 26 11:22:55 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httputils.rb (WEBrick::HTTPUtils.escape): should
+ escape space.
+
+Sun Jul 25 11:05:21 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * win32/win32.{h,c} (rb_w32_{f,fd,fs}open): workaround for bcc32's
+ {f,fd,fs}open bug. set errno EMFILE and EBADF. [ruby-dev:23963]
+
+Sat Jul 24 13:32:47 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * range.c (rb_range_beg_len): returns Qnil only when "beg" points
+ outside of a range. No boundary check for "end".
+
+Fri Jul 23 16:40:25 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (define_final): should not disclose NODE* to Ruby world.
+ [ruby-dev:23957]
+
+Fri Jul 23 09:03:16 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (disconnected?): new method. (backported from HEAD)
+
+Thu Jul 22 16:41:54 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi/session.rb (CGI::Session::FileStore#update): sets the
+ permission of the session data file to 0600.
+
+ * lib/cgi/session/pstore.rb (CGI::Session::Pstore#initialize):
+ ditto.
+
+Thu Jul 22 00:02:21 2004 Masahiro Kitajima <katonbo@katontech.com>
+
+ * process.c (rb_f_system): not need to call last_status_set() any
+ longer on _WIN32.
+
+Tue Jul 20 09:15:17 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * test/fileutils/test_fileutils.rb: File.link raises EINVAL on BeOS.
+
+Mon Jul 19 01:15:07 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpservlet/cgihandler.rb
+ (WEBrick::HTTPServlet::CGIhandler#do_GET): set SystemRoot environment
+ variable to CGI process on Windows native platforms. [ruby-dev:23936]
+
+ * lib/webrick/httpservlet/cgihandler.rb
+ (WEBrick::HTTPServlet::CGIhandler#do_GET): use $?.exitstatus and
+ refine log message.
+
+Sun Jul 18 16:14:29 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/msgcat.rb (TkMsgCatalog.callback): bug fix
+ ( wrong number of argument )
+
+Sun Jul 18 08:13:58 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): remove extra sign digit.
+
+Sun Jul 18 03:21:42 2004 Akinori MUSHA <knu@iDaemons.org>
+
+ * dir.c (range): use NULL instead of 0.
+
+ * dir.c (range): get rid of a gcc 3.4 warning.
+
+Sun Jul 18 03:12:11 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (receive_responses): return if a LOGOUT response
+ received. (backported from HEAD)
+ * lib/net/imap.rb (send_string_data): wait command continuation
+ requests before sending octet data of literals. (backported from HEAD)
+
+Sat Jul 17 23:54:59 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/variable.rb: TkVariable#ref returns a TkVariable object
+
+Sat Jul 17 22:04:44 2004 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/ldap.rb: method hierarchical? should be in URI::LDAP.
+
+Sat Jul 17 18:29:07 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (stmt): not to show same error messages twice.
+
+Sat Jul 17 13:13:32 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/ruby-lex.rb (RubyLex::identify_string): %s string do not
+ process expression interpolation. [ruby-talk:106691]
+
+Sat Jul 17 05:26:27 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/diagram.rb: Incorporate Micheal Neuman's
+ client-side imagemao patch
+
+Sat Jul 17 01:57:03 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (THREAD_ALLOC): th->thread should be initialized to NULL.
+ [ruby-talk:106657] The solution was found by Guy Decoux.
+
+Fri Jul 16 22:30:28 2004 Michael Neumann <mneumann@ntecs.de>
+
+ * file.c (rb_stat_dev_major): new methods File::Stat#dev_major and
+ #dev_minor. [ruby-core:03195]
+
+Fri Jul 16 15:23:53 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (return_jump, break_jump): raise unexpceted local jump
+ exception directly. [ruby-dev:23740]
+
+ * lib/base64.rb (Deprecated): super in bound method calls original
+ name method in stable version. [ruby-dev:23916]
+
+Fri Jul 16 11:31:49 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/test/unit/ui/{fox,gtk,gtk2}/testrunner.rb: remove
+ garbage (patch from akira yamada) [ruby-dev:23911]
+
+Fri Jul 16 11:20:00 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): fix output of NaN, Inf and -Inf with
+ "%f" or etc on MSVCRT platforms. (backported from HEAD)
+
+Fri Jul 16 11:17:38 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * error.c (exit_initialize): use EXIT_SUCCESS instead of 0.
+ [ruby-dev:23913]
+
+ * error.c (exit_success_p): new method SystemExit#success?.
+ [ruby-dev:23912]
+
+ * error.c (syserr_initialize): initialization for subclasses.
+ [ruby-dev:23912]
+
+Thu Jul 15 23:53:38 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#warn, OptionParser#abort): Exception
+ no longer has to_str method.
+
+Thu Jul 15 22:59:48 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * ext/readline/extconf.rb: added dir_config for curses, ncurses,
+ termcap. (backported from HEAD)
+
+Thu Jul 15 20:29:15 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * class.c, error.c, eval.c, intern.h, object.c, variable.c:
+ do not set path if it is a singleton class. [ruby-dev:22588]
+ (backport from 1.9)
+
+Thu Jul 15 10:15:04 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/, ext/tcltklib/: bug fix
+
+ * ext/tk/lib/tk.rb: better operation for SIGINT when processing
+ callbacks.
+ * ext/tk/lib/tk/msgcat.rb: ditto.
+ * ext/tk/lib/tk/variable.rb: ditto.
+ * ext/tk/lib/tk/timer.rb: ditto.
+
+ * ext/tk/lib/tk/validation.rb: add Tk::ValidateConfigure.__def_validcmd
+ to define validatecommand methods easier
+
+ * ext/tk/lib/tk.rb (_genobj_for_tkwidget): support autoload Tk ext
+ classes
+
+ * ext/tk/lib/tk/canvas.rb and so on: remove the parent widget type
+ check for items (e.g. canvas items; depends on the class) to
+ avoid some troubles on Tk extension widget class definition.
+
+ * ext/tk/lib/tkextlib/: add Iwidget and TkTable extension support
+
+ * ext/tk/sample/tkextlib/: add samples of Iwidget and TkTable
+
+Wed Jul 14 18:08:37 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_asn1.c (ossl_asn1cons_to_der): fix type of
+ argument. [ruby-dev:23891]
+
+ * test/openssl/test_x509store.rb: prune tests for CRL checking
+ unless X509::V_FLAG_CRL_CHECK is defined.
+
+Wed Jul 14 12:29:07 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * util.c (ruby_strtod): should not convert string in the form of
+ "-I.FE-X" which both "I" and "F" are ommitted. [ruby-dev:23883]
+
+ * test/ruby/test_float.rb (test_strtod): add test for bug fix.
+
+Wed Jul 14 00:31:15 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * array.c: rdoc patch. merged patch from Johan Holmberg
+ <holmberg@iar.se> [ruby-core:3170]
+
+Tue Jul 13 19:39:12 2004 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/generic.rb (URI::Generic#merge_path):
+ "URI('http://www.example.com/foo/..') + './'" should return
+ "URI('http://www.example.com/')". [ruby-list:39838]
+ "URI('http://www.example.com/') + './foo/bar/..'" should return
+ "URI('http://www.example.com/foo/')". [ruby-list:39844]
+
+ * test/uri/test_generic.rb (TestGeneric#test_merge): added tests.
+
+Tue Jul 13 15:51:45 2004 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/mkmf.rb (init_mkmf): Do not add $(libdir) to $LIBPATH in
+ extmk mode.
+
+ * lib/mkmf.rb (dir_config): Prepend a new library path instead of
+ appending so it is tried first.
+
+Tue Jul 13 00:50:48 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb: Support call-seq: for Ruby files.
+
+Mon Jul 12 21:20:36 2004 Dave Thomas <dave@pragprog.com>
+
+ * html_generator.rb: Support hyperlinks of the form {any text}[xxx]
+ as well as stuff[xxx]
+
+Sat Jul 10 09:30:24 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/soap/marshal/test_struct.rb: use qualified build-tin class name
+ (::Struct) to avoid name crash.
+
+Sat Jul 10 04:21:56 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: better operation for SIGINT when processing
+ callbacks.
+ * ext/tk/lib/tk/msgcat.rb: ditto.
+ * ext/tk/lib/tk/variable.rb: ditto.
+ * ext/tk/lib/tk/timer.rb: ditto.
+
+ * ext/tk/lib/tk/validation.rb (__def_validcmd): add a module
+ function of Tk::ValidateConfigure to define validatecommand
+ methods easier
+
+Fri Jul 9 22:36:36 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * array.c, enum.c, pack.c: rdoc patch from Johan Holmberg
+ <holmberg@iar.se> [ruby-core:3132] [ruby-core:3136]
+
+ * numeric.c: rdoc patch.
+
+Fri Jul 9 19:26:39 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb (URI::HTTPS#proxy_open): raise ArgumentError to
+ notice https is not supported.
+
+Fri Jul 9 14:28:54 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_raise): accept third argument as well as
+ Kernel#raise, and evaluate the arguments to create an exception in
+ the caller's context. [ruby-talk:105507]
+
+Fri Jul 9 01:47:08 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib : bug fix
+ * ext/tk/lib/tkextlib/itcl : add [incr Tcl] support
+ * ext/tk/lib/tkextlib/itk : add [incr Tk] support
+ * ext/tk/lib/tkextlib/iwidgets : midway point of [incr Widgets] support
+ * ext/tk/sample/tkextlib/iwidgets : very simple examples of
+ [incr Widgets]
+
+Thu Jul 8 22:52:19 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/{rss,parser,0.9,1.0,2.0}.rb: supported RSS 0.9x/2.0
+ validation and validation which disregard order of elements.
+ * test/rss/test_parser.rb: added tests for RSS 0.9x/2.0
+ validation.
+ * test/rss/{test_trackback,rss-testcase}.rb: fixed no good method
+ name.
+
+Thu Jul 8 00:05:23 2004 akira yamada <akira@ruby-lang.org>
+
+ * lib/tempfile.rb (Tempfile::initialize): got out code of
+ generating tmpname. [ruby-dev:23832][ruby-dev:23837]
+
+Wed Jul 7 15:53:14 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * string.c (rb_str_match): raise TypeError when both arguments are
+ strings. [ruby-dev:22869] (backported from HEAD)
+
+ * string.c (rb_str_match2): removed.
+
+ * Makefile.in, bcc32/Makefile.sub, win32/Makefile.sub,
+ wince/Makefile.sub (string.c): now not depend on version.h.
+
+Wed Jul 7 00:48:34 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/tk/lib/tkextlib/tktrans.rb,
+ ext/tk/lib/tkextlib/treectrl.rb: fix syntax errors.
+
+Tue Jul 6 18:38:45 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib : improve framework of developping Tcl/Tk extension
+ wrappers
+
+Mon Jul 5 23:56:42 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/{trackback,syndication,dublincore,content}.rb: worked
+ with ruby 1.6 again.
+
+ * test/rss/rss-assertions.rb: ditto.
+
+Mon Jul 5 22:54:39 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/uri/common.rb (Kernel#URI): new global method for parsing URIs.
+
+Mon Jul 5 09:02:52 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_yield, rb_f_catch): 4th argument to rb_yield_0()
+ is a set of bit flags. [ruby-dev:23859]
+
+Mon Jul 5 01:27:32 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/drb/drb.rb(DRbConn self.open): If socket pool is full, close
+ the socket whose last-access-time is oldest. (and add new one)
+ [ruby-dev:23860]
+
+Sun Jul 4 12:24:50 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb: added copyright header.
+
+Sun Jul 4 00:24:40 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * added files
+ * lib/soap/attachment.rb
+ * lib/soap/header
+ * lib/soap/mimemessage.rb
+ * lib/soap/rpc/httpserver.rb
+ * lib/wsdl/soap/cgiStubCreator.rb
+ * lib/wsdl/soap/classDefCreator.rb
+ * lib/wsdl/soap/classDefCreatorSupport.rb
+ * lib/wsdl/soap/clientSkeltonCreator.rb
+ * lib/wsdl/soap/driverCreator.rb
+ * lib/wsdl/soap/mappingRegistryCreator.rb
+ * lib/wsdl/soap/methodDefCreator.rb
+ * lib/wsdl/soap/servantSkeltonCreator.rb
+ * lib/wsdl/soap/standaloneServerStubCreator.rb
+ * lib/wsdl/xmlSchema/enumeration.rb
+ * lib/wsdl/xmlSchema/simpleRestriction.rb
+ * lib/wsdl/xmlSchema/simpleType.rb
+ * lib/xsd/codegen
+ * lib/xsd/codegen.rb
+ * sample/soap/authheader
+ * sample/soap/raa2.4
+ * sample/soap/ssl
+ * sample/soap/swa
+ * sample/soap/whois.rb
+ * sample/soap/calc/samplehttpd.conf
+ * sample/soap/exchange/samplehttpd.conf
+ * sample/soap/sampleStruct/samplehttpd.conf
+ * sample/wsdl/raa2.4
+ * sample/wsdl/googleSearch/samplehttpd.conf
+ * test/openssl/_test_ssl.rb
+ * test/soap/header
+ * test/soap/ssl
+ * test/soap/struct
+ * test/soap/swa
+ * test/soap/wsdlDriver
+ * test/wsdl/multiplefault.wsdl
+ * test/wsdl/simpletype
+ * test/wsdl/test_multiplefault.rb
+
+ * modified files
+ * lib/soap/baseData.rb
+ * lib/soap/element.rb
+ * lib/soap/generator.rb
+ * lib/soap/marshal.rb
+ * lib/soap/netHttpClient.rb
+ * lib/soap/parser.rb
+ * lib/soap/processor.rb
+ * lib/soap/property.rb
+ * lib/soap/soap.rb
+ * lib/soap/streamHandler.rb
+ * lib/soap/wsdlDriver.rb
+ * lib/soap/encodingstyle/handler.rb
+ * lib/soap/encodingstyle/literalHandler.rb
+ * lib/soap/encodingstyle/soapHandler.rb
+ * lib/soap/mapping/factory.rb
+ * lib/soap/mapping/mapping.rb
+ * lib/soap/mapping/registry.rb
+ * lib/soap/mapping/rubytypeFactory.rb
+ * lib/soap/mapping/wsdlRegistry.rb
+ * lib/soap/rpc/cgistub.rb
+ * lib/soap/rpc/driver.rb
+ * lib/soap/rpc/element.rb
+ * lib/soap/rpc/proxy.rb
+ * lib/soap/rpc/router.rb
+ * lib/soap/rpc/soaplet.rb
+ * lib/soap/rpc/standaloneServer.rb
+ * lib/wsdl/data.rb
+ * lib/wsdl/definitions.rb
+ * lib/wsdl/operation.rb
+ * lib/wsdl/parser.rb
+ * lib/wsdl/soap/definitions.rb
+ * lib/wsdl/xmlSchema/complexContent.rb
+ * lib/wsdl/xmlSchema/complexType.rb
+ * lib/wsdl/xmlSchema/data.rb
+ * lib/wsdl/xmlSchema/parser.rb
+ * lib/wsdl/xmlSchema/schema.rb
+ * lib/xsd/datatypes.rb
+ * lib/xsd/qname.rb
+ * sample/soap/calc/httpd.rb
+ * sample/soap/exchange/httpd.rb
+ * sample/soap/sampleStruct/httpd.rb
+ * sample/soap/sampleStruct/server.rb
+ * sample/wsdl/amazon/AmazonSearch.rb
+ * sample/wsdl/amazon/AmazonSearchDriver.rb
+ * sample/wsdl/googleSearch/httpd.rb
+ * test/soap/test_basetype.rb
+ * test/soap/test_property.rb
+ * test/soap/test_streamhandler.rb
+ * test/soap/calc/test_calc.rb
+ * test/soap/calc/test_calc2.rb
+ * test/soap/calc/test_calc_cgi.rb
+ * test/soap/helloworld/test_helloworld.rb
+ * test/wsdl/test_emptycomplextype.rb
+ * test/wsdl/axisArray/test_axisarray.rb
+ * test/wsdl/datetime/test_datetime.rb
+ * test/wsdl/raa/test_raa.rb
+ * test/xsd/test_xmlschemaparser.rb
+ * test/xsd/test_xsd.rb
+
+ * summary
+ * add SOAP Header mustUnderstand support.
+
+ * add HTTP client SSL configuration and Cookies support (works
+ completely with http-access2).
+
+ * add header handler for handling sending/receiving SOAP Header.
+
+ * map Ruby's anonymous Struct to common SOAP Struct in SOAP Object
+ Model. it caused error.
+
+ * add WSDL simpleType support to restrict lexical value space.
+
+ * add SOAP with Attachment support.
+
+Sat Jul 3 17:19:44 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/tk/lib/tkextlib/tkDND.rb: fix syntax error.
+
+Thu Jul 1 23:15:29 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/pstore.rb (transaction): safer backup scheme. [ruby-list:39102]
+
+ * lib/pstore.rb (commit_new): use FileUtils.copy_stream for Cygwin.
+ [ruby-dev:23157]
+
+ * lib/pstore.rb (transaction): allow overriding dump and load.
+ [ruby-dev:23567]
+
+ * lib/pstore.rb (PStore#transaction): get rid of opening in write mode
+ when read only transaction. [ruby-dev:23842]
+
+ * lib/yaml/store.rb: follow lib/pstore.rb's change.
+
+Thu Jul 1 18:36:08 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tcltklib : bug fix
+
+ * ext/tk/lib/tk : bug fix and add Tcl/Tk extension support libraries
+
+Thu Jul 1 11:59:45 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/extconf.rb: check for EVP_CIPHER_CTX_copy, ENGINE_add,
+ EVP_CIPHER_CTX_set_padding, EVP_CipherFinal_ex, EVP_CipherInit_ex,
+ EVP_DigestFinal_ex and EVP_DigestInit_ex.
+
+ * ext/openssl/openssl_missing.c (EVP_CIPHER_CTX_copy): new function.
+
+ * ext/openssl/openssl_missing.h (EVP_DigestInit_ex, EVP_DigestFinal_ex,
+ EVP_CipherInit_ex, EVP_CipherFinal_ex, HMAC_Init_ex): new macro for
+ OpenSSL 0.9.6.
+
+ * ext/openssl/ossl_cipher.c (ossl_cipher_encrypt, ossl_cipher_decrypt):
+ re-implemnt (the arguments for this method is ).
+
+ * ext/openssl/ossl_cipher.c (ossl_cipher_pkcs5_keyivgen): new method
+ OpenSSL::Cipher::Cipher#pkcs5_keyivgen. it calls EVP_BytesToKey().
+
+ * ext/openssl/ossl_cipher.c (ossl_cipher_alloc, ossl_cipher_initialize,
+ ossl_cipher_copy, ossl_cipher_reset ossl_cipher_final,
+ ossl_cipher_set_key, ossl_cipher_set_iv): replace all EVP_CipherInit
+ and EVP_CipherFinal into EVP_CipherInit_ex and EVP_CipherFinal_ex.
+ and EVP_CIPHER_CTX_init should only be called once.
+
+ * ext/openssl/ossl_cipher.c (ossl_cipher_set_key_length): new method
+ OpenSSL::Cipher::Cipher#key_len=.
+
+ * ext/openssl/ossl_cipher.c (ossl_cipher_init_deprecated): new
+ finction; print warning for Cipher#<<.
+
+ * ext/openssl/ossl_digest.c: replace all EVP_DigestInit and
+ EVP_DigestFinal into EVP_DigestInit_ex and EVP_DigestFinal_ex.
+ and EVP_MD_CTX_init should only be called once.
+
+ * ext/openssl/ossl_digest.c (digest_final): should call
+ EVP_MD_CTX_cleanup to avoid memory leak.
+
+ * ext/openssl/ossl_hmac.c (ossl_hmac_initialize): repalce HMAC_init
+ into HMAC_init_ex. and HMAC_CTX_init is moved to ossl_hmac_alloc.
+
+ * ext/openssl/ossl_hmac.c (hmac_final): should call
+ HMAC_CTX_cleanup to avoid memory leak.
+
+ * test/openssl/test_cipher.rb, test/openssl/test_digest.rb,
+ test/openssl/test_hmac.rb: new file.
+
+Thu Jul 1 04:08:30 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_asn1.c (ossl_i2d_ASN1_TYPE, ossl_ASN1_TYPE_free):
+ workaround for the versions earlier than OpenSSL-0.9.7.
+
+Thu Jul 1 03:33:55 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_pkey_dh.c (ossl_dh_initialize): should create
+ empty pkey object if no argument is passed. [ruby-talk:103328]
+
+ * ext/openssl/ossl_pkey_dsa.c (ossl_dsa_initialize): ditto.
+
+ * ext/openssl/ossl_pkey_rsa.c (ossl_rsa_initialize): ditto.
+
+ * ext/openssl/ossl_pkey_dh.c: add new methods: OpenSSL::PKey::DH#p,
+ OpenSSL::PKey::DH#p=, OpenSSL::PKey::DH#g, OpenSSL::PKey::DH#g=,
+ OpenSSL::PKey::DH#pub_key, OpenSSL::PKey::DH#pub_key=,
+ OpenSSL::PKey::DH#priv_key and OpenSSL::PKey::DH#priv_key=.
+
+ * ext/openssl/ossl_pkey_dsa.c: add new methods: OpenSSL::PKey::DSA#p,
+ OpenSSL::PKey::DSA#p=, OpenSSL::PKey::DSA#q, OpenSSL::PKey::DSA#q=,
+ OpenSSL::PKey::DSA#g, OpenSSL::PKey::DSA#g=,
+ OpenSSL::PKey::DSA#pub_key, OpenSSL::PKey::DSA#pub_key=,
+ OpenSSL::PKey::DSA#priv_key and OpenSSL::PKey::DSA#priv_key=.
+
+Thu Jul 1 03:16:09 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ssl.c (ossl_ssl_read): take optional second argument
+ to specify a string to be written.
+
+ * ext/openssl/lib/openssl/buffering.rb (OpenSSL::Buffering#read):
+ take optional second argument to specify a string to be written.
+
+ * ext/openssl/lib/openssl/buffering.rb (OpenSSL::Buffering#gets):
+ refine regexp for end-of-line.
+
+ * ext/opnessl/lib/openssl/ssl.rb
+ (OpenSSL::SSL::SocketForwarder#listen): fix typo.
+
+Wed Jun 30 11:38:51 2004 Mikael Brockman <phubuh@phubuh.org>
+
+ * parse.y (primary): should not be NULL. [ruby-core:03098]
+
+Wed Jun 30 02:53:24 2004 why the lucky stiff <why@ruby-lang.org>
+
+ * ext/syck/rubyext.c (syck_emitter_new): set buffer after
+ Data_Wrap_Struct to avoid possible GC. [ruby-talk:104835]
+
+Tue Jun 29 10:31:19 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_eval_cmd, rb_thread_trap_eval): restore safe level.
+
+ * gc.c (define_final, run_final): preserve and restore safe level for
+ finalizers. [ruby-core:03058]
+
+ * signal.c (signal_exec, rb_trap_exit, trap): preserve and restore
+ safe level for signal handlers. [ruby-dev:23829]
+
+Mon Jun 28 14:57:56 2004 Jeff Mitchell <quixoticsycophant@yahoo.com>
+
+ * configure.in, lib/mkmf.rb (LIBPATHFLAG): use double quotes due to
+ DOSISH compilers. [ruby-core:03107]
+
+Mon Jun 28 00:30:19 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * sample/drb/*.rb: using 'DRb.thread.join' instead of 'gets'
+
+Sun Jun 27 22:39:51 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * sample/rss/tdiary_plugin/rss-recent.rb: supported Hiki.
+
+Sun Jun 27 12:19:46 2004 Kouhei Sutou <kou@cozmixng.org>
+
+ * {lib,sample,test}/rss: added RSS Parser. [ruby-dev:23780]
+
+Sat Jun 26 11:07:30 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (aix): -b must come at the start of the command line,
+ and -e must not appear while testing libraries. [ruby-talk:104501]
+
+ * lib/mkmf.rb (dir_config): quote directory names if necessary.
+ [ruby-talk:104505]
+
+Fri Jun 25 15:33:19 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/extconf.rb: check stricter. [ruby-talk:104501]
+
+ * ext/iconv/extconf.rb: include iconv.h for libiconv. [ruby-dev:22715]
+
+Fri Jun 25 08:31:29 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_atfork): remove "fork terminates thread"
+ warning. [ruby-dev:23768]
+
+ * object.c (rb_obj_clone): backport FL_FINALIZE patch from 1.9.
+ [ruby-core:02786][ruby-core:03067]
+
+ * ext/socket/socket.c (sock_sockaddr): Socket#gethostbyname()
+ should give us packed address, not struct sockaddr.
+ [ruby-core:03053]
+
+Fri Jun 25 02:04:23 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32,wince}/setup.mak: remove RUBY_EXTERN lines when
+ including version.h. [ruby-talk:104456] (backported from HEAD)
+
+Thu Jun 24 14:23:29 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_fread): return already read data when system call is
+ interrupted. [ruby-talk:97206]
+
+Thu Jun 24 01:32:43 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * version.h: added declarations of ruby_version,
+ ruby_release_date, ruby_platform.
+ (backported from HEAD)
+
+Wed Jun 23 22:23:37 2004 Dave Thomas <dave@pragprog.com>
+
+ * ext/socket/socket.c (sock_s_gethostbyaddr): Work around problem
+ with OS X not returning 'from' parameter to recvfrom for
+ connection-oriented sockets.
+
+Wed Jun 23 01:45:27 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RubyLex::identify_quotation):
+ Fix problem with the 'r' being dropped from %r{xxx}
+
+Wed Jun 23 00:20:20 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_hresult2msg): remove trailing
+ CRs and LFs. (doesn't depend on CR+LF) [ruby-dev:23749]
+
+Wed Jun 23 00:00:25 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_initialize): should check fcntl result. [ruby-dev:23742]
+
+Tue Jun 22 21:11:36 2004 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (OLE_FREE): should not call CoFreeUnuse-
+ dLibraries().
+
+ * ext/win32ole/win32ole.c (ole_event_free): ditto.
+
+ * ext/win32ole/win32ole.c (ole_hresult2msg): truncate error message
+ before CR.
+
+Tue Jun 22 16:47:42 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/ftp.rb (MDTM_REGEXP): fix for demon's ftp server.
+ Thanks, Rutger Nijlunsing.
+
+Mon Jun 21 10:19:23 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_opendir): use FindFirstFile()/FindNextFile()/
+ FindClose() instead of _findfirst()/_findnext()/_findclose().
+ merge from HEAD.
+
+Sat Jun 19 13:24:15 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (method_call): allow changing $SAFE. [ruby-dev:23713]
+
+Fri Jun 18 23:12:22 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (proc_save_safe_level, rb_set_safe_level, safe_setter): limit
+ safe level.
+
+Wed Jun 16 23:05:57 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_mod_freeze): prepare string representation before
+ freezing. [ruby-talk:103646]
+
+Wed Jun 16 16:04:40 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_mod_le): singleton class inherits Class rather than its
+ object's class. [ruby-dev:23690]
+
+Wed Jun 16 16:01:17 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (stack_grow_direction): memoize the direction.
+
+ * gc.c (Init_stack): should always move to end of VALUE.
+
+Tue Jun 15 12:10:04 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: bug fix (TkWindow#grab)
+
+Mon Jun 14 18:23:27 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/remote-tk.rb: bug fix
+
+Sun Jun 13 00:23:04 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/extconf.rb: [EXPERIMENTAL] MacOS X (darwin) support
+
+ * ext/tcltklib/tcltklib.c: fix thread trouble on callback proc, and
+ eliminate warning about instance variable access
+
+ * ext/tk/lib/tk/menubar.rb: improve supported menu_spec
+
+ * ext/tk/lib/tk/menuspec.rb: [add] menu_spec support library
+
+ * ext/tk/lib/tk/root.rb: add menu_spec support
+
+ * ext/tk/lib/tk/text.rb: bug fix
+
+ * ext/tk/lib/tk/toplevel.rb: add menu_spec support
+
+ * ext/tk/sample/menubar?.rb: [add] sample of menu_spec usage
+
+Sat Jun 12 11:15:53 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (target_os): strip -gnu suffix on Linux.
+
+Fri Jun 11 17:08:21 2004 Akinori MUSHA <knu@iDaemons.org>
+
+ * config.guess: Restore a wrongly removed hyphen.
+
+Fri Jun 11 14:30:08 2004 Akinori MUSHA <knu@iDaemons.org>
+
+ * config.guess: Attempt to avoid system name change on
+ Darwin platforms also.
+
+Fri Jun 11 14:22:45 2004 Akinori MUSHA <knu@iDaemons.org>
+
+ * config.guess, config.sub: Attempt to avoid system name change on
+ Linux platforms. We have been using "linux" instead of
+ "linux-gnu" on this branch.
+
+Thu Jun 10 19:19:41 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/sdbm/init.c (fsdbm_store): sdbm should use StringValue().
+ [ruby-talk:103062]
+
+Wed Jun 9 18:04:14 2004 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/generic.rb (URI::Generic::merge,
+ URI::Generic::route_from): accepts non-hierarchical URI.
+ [ruby-dev:23631]
+
+ * test/uri/test_generic.rb (TestGeneric::test_route,
+ TestGeneric::test_merge): added tests for above changes.
+
+Wed Jun 9 17:39:37 2004 Akinori MUSHA <knu@iDaemons.org>
+
+ * config.guess, config.sub: Update to a more recent version as of
+ 2004-01-20.
+
+ * configure.in: Add support for DragonFly BSD.
+
+Wed Jun 2 20:16:03 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (str_new4): should share shared instance if it already
+ exists. [ruby-dev:23665]
+
+Wed Jun 2 12:41:53 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_gets_m): set lastline ($_) even when read line is
+ nil. [ruby-dev:23663]
+
+Fri May 28 11:20:31 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_eval): bad influence on frame node.
+
+ * eval.c (eval): reverted wrongly removed condition. [ruby-dev:23638]
+
+Thu May 27 23:15:18 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/logger.rb: leading 0 padding of timestamp usec part.
+
+ * lib/csv.rb (CSV.parse): [CAUTION] behavior changed. in the past,
+ CSV.parse accepts a filename to be read-opened (it was just a
+ shortcut of CSV.open(filename, 'r')). now CSV.parse accepts a
+ string or a stream to be parsed e.g.
+ CSV.parse("1,2\n3,r") #=> [['1', '2'], ['3', '4']]
+
+ * lib/csv.rb: CSV::Row and CSV::Cell are deprecated. these classes
+ are removed in the future. in the new csv.rb, row is represented
+ as just an Array. since CSV::Row was a subclass of Array, it won't
+ hurt almost all programs except one which depended CSV::Row#match.
+ and a cell is represented as just a String or nil(NULL). this
+ change will cause widespread destruction.
+
+ CSV.open("foo.csv", "r") do |row|
+ row.each do |cell|
+ if cell.is_null # using Cell#is_null
+ p "(NULL)"
+ else
+ p cell.data # using Cell#data
+ end
+ end
+ end
+
+ must be just;
+
+ CSV.open("foo.csv", "r") do |row|
+ row.each do |cell|
+ if cell.nil?
+ p "(NULL)"
+ else
+ p cell
+ end
+ end
+ end
+
+ * lib/csv.rb: [CAUTION] record separator(CR, LF, CR+LF) behavior
+ change. CSV.open, CSV.parse, and CSV,generate now do not force
+ opened file binmode. formerly it set binmode explicitly.
+
+ with CSV.open, binmode of opened file depends the given mode
+ parameter "r", "w", "rb", and "wb". CSV.parse and CSV.generate open
+ file with "r" and "w".
+
+ setting mode properly is user's responsibility now.
+
+ * lib/csv.rb: accepts String as a fs (field separator/column separator)
+ and rs (record separator/row separator)
+
+ * lib/csv.rb (CSV.read, CSV.readlines): added. works as IO.read and
+ IO.readlines in CSV format.
+
+ * lib/csv.rb: added CSV.foreach(path, rs = nil, &block). CSV.foreach
+ now does not handle "| cmd" as a path different from IO.foreach.
+ needed?
+
+ * test/csv/test_csv.rb: updated.
+
+ * test/ruby/test_float.rb: added test_strtod to test Float("0").
+
+Thu May 27 21:37:50 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb (Pathname#initialize): refine pathname initialization
+ by pathname.
+
+Thu May 27 20:22:05 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * io.c (rb_io_fwrite): check all case errno != 0 [ruby-dev:23648]
+
+Thu May 27 14:53:13 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * io.c (rb_io_fwrite): workaround for bcc32's fwrite bug.
+ add errno checking. [ruby-dev:23627]
+
+Wed May 26 14:19:42 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_eval, eval): make line number consistent on eval with
+ Proc. [ruby-talk:101253]
+
+Wed May 26 13:59:17 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::skip_for_variable): Allow for
+ 'do' after for statement
+
+Wed May 26 13:56:03 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb (Generators::MarkUp::style_url): Fix
+ relative path to code CSS file
+
+Wed May 26 13:14:52 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_init_copy): copy also positions. [ruby-talk:100910]
+
+Wed May 26 00:00:00 2004 why the lucky stiff <why@ruby-lang.org>
+
+ * ext/syck/syck.c (syck_new_parser): clear parser on init.
+ thanks, ts. [ruby-core:02931]
+
+ * ext/syck/token.c (sycklex_yaml_utf8): buffer underflow.
+ thanks, ts. [ruby-core:02929]
+
+ * lib/yaml/baseemitter.rb (indent_text): simpler flow block code.
+
+ * lib/yaml.rb: added rdoc to beginning of lib.
+
+Mon May 24 10:46:26 2004 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/rdoc/generators/template/html/html.rb: SYSTEM identifiers
+ must be absolute URIs
+
+Sat May 22 12:00:04 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * MANIFEST: add new encodings in rexml.
+
+ * ext/tk/MANIFEST: add recent files.
+
+Sat May 22 05:37:11 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/remote-tk.rb: (NEW library) controll Tk interpreters
+ on the other processes by Tcl/Tk's 'send' command
+
+Fri May 21 09:22:05 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method_parameters):
+ Add ()'s around parameters that don't have them
+
+Thu May 20 17:02:03 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (check_sizeof): define result size. [ruby-core:02911]
+
+ * lib/mkmf.rb (create_header): macro name should not include equal
+ sign.
+
+Thu May 20 15:59:50 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * ext/socket/socket.c: fix SEGV. [ruby-dev:23550]
+
+Thu May 20 14:35:52 2004 Tanaka Akira <akr@m17n.org>
+
+ * ext/socket/socket.c: check SCM_RIGHTS macro addition to
+ the msg_control field to test existence of file descriptor passing
+ by msg_control.
+
+Thu May 20 12:38:06 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (flo_eq): always check if operands are NaN.
+ [ruby-list:39685]
+
+Thu May 20 12:34:39 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_visibility):
+ At Ryan Davis' suggestion, honor visibility modifers if guarded by a
+ statement modifier
+
+Thu May 20 12:22:13 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (have_type): do not check pointer to incomplete type,
+ which always get compiled. [ruby-list:39683]
+
+Wed May 19 11:09:00 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: change permition of TkObject#tk_send from
+ private to public
+
+Tue May 18 14:00:46 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * node.h (NEW_DSTR): adjust list length.
+
+ * parse.y (literal_concat): ditto.
+
+Mon May 17 16:14:25 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * numeric.c (flo_to_s): it's preferable that "p 0.0" outputs "0.0"
+ instead of "0.0e+00". [ruby-dev:23480]
+
+ * numeric.c (flo_to_s): it's preferable that "p 0.00000000000000000001"
+ outputs "1.0e-20" instead of "9.999999999999999e-21". (the precision
+ is considered, but there is assumption DBL_DIG == 15 in current
+ implementation)
+
+Mon May 17 10:13:33 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (setup_domain_and_type): honor duck typing.
+ [ruby-dev:23522]
+
+ * ext/socket/socket.c (sock_s_getnameinfo): ditto.
+
+Mon May 17 01:15:23 2004 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/yaml.rb: removed fallback to pure Ruby parser.
+
+ * lib/yaml/baseemitter.rb (indent_text): was forcing a mod value
+ of zero at times, which kept some blocks from getting indentation.
+
+ * lib/yaml/baseemitter.rb (node_text): rewriting folded scalars.
+
+ * ext/syck/syck.h: reports style of scalars now, be they plain, block
+ single-, or double-quoted.
+
+ * ext/syck/syck.c: ditto.
+
+ * ext/syck/gram.c: ditto.
+
+ * ext/syck/node.c: ditto.
+
+ * ext/syck/token.c: ditto.
+
+ * ext/syck/rubyext.c (yaml_org_handler): symbols loaded only
+ if scalar style is plain.
+
+ * ext/syck/rubyext.c (yaml_org_handler): some empty strings were
+ loaded as symbols.
+
+ * test/yaml/test_yaml.rb (test_perl_regexp): updated test to
+ match new regexp serialization.
+
+Mon May 17 00:03:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/drb/drb.rb: Cosmetic documentation changes.
+
+Sun May 16 22:36:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/test/unit.rb: Removed :nodoc: directive (it prevented effective
+ RDoc operation), and added file-level comment.
+
+Sun May 16 20:55:49 2004 Tanaka Akira <akr@m17n.org>
+
+ * ext/dbm/dbm.c (fdbm_initialize): accept optional 3rd argument to
+ specify an open flag.
+ (Init_dbm): define open flags: DBM::READER, DBM::WRITER, DBM::WRCREAT
+ and DBM::NEWDB.
+
+Sun May 16 13:10:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/test/unit/**/*.rb: Removed :nodoc: directives (many were
+ generating warnings, many were on private methods).
+
+Sat May 15 01:41:34 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (eval): forgot to restore $SAFE value before evaluating
+ compiled node. [ruby-core:02872]
+
+Sat May 15 01:33:12 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * range.c (range_each_func): terminates loop if generating value
+ is same to @end. [ruby-talk:100269]
+
+Fri May 14 22:08:38 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_new4): should not reuse frozen shared string if
+ the original is not an instance of String. [ruby-talk:100193]
+
+Fri May 14 18:39:25 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/canvas.rb: improve coords support for canvas items.
+ Now, supports all of the followings.
+ TkcLine.new(c, 0, 0, 100, 100, :fill=>'red')
+ TkcLine.new(c, [0, 0, 100, 100], :fill=>'red')
+ TkcLine.new(c, [0, 0], [100, 100], :fill=>'red')
+ TkcLine.new(c, [[0, 0], [100, 100]], :fill=>'red')
+ TkcLine.new(c, :coords=>[0, 0, 100, 100], :fill=>'red')
+ TkcLine.new(c, :coords=>[[0, 0], [100, 100]], :fill=>'red')
+
+Fri May 14 12:11:43 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * util.c (ruby_strtod): strtod("0", &end); => end should point '\0'.
+ [ruby-dev:23498]
+
+Thu May 13 15:47:30 2004 akira yamada <akira@ruby-lang.org>
+
+ * lib/net/telnet.rb (Net::Telnet::login): "options" can specify
+ regexps for login prompt and/or password prompt.
+
+Thu May 13 14:23:45 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * hash.c (delete_if_i): use st_delete_safe() (via
+ rb_hash_delete()) instead of returning ST_DELETE.
+ backport from HEAD. [ruby-dev:23487]
+
+Thu May 13 13:01:30 2004 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/mailto.rb (URI::MailTo::to_s): should include fragment.
+
+Thu May 13 11:04:08 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * pack.c (pack_pack): always add with null for 'Z'.
+
+ * pack.c (pack_unpack): terminated by null for 'Z'. [ruby-talk:98281]
+
+Wed May 12 19:59:43 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (have_type, check_sizeof): replace unusable characters.
+ [ruby-talk:99788]
+
+Wed May 12 17:41:42 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/resolv.rb (Resolv::DNS::Config): make it configurable without
+ external file such as /etc/resolv.conf.
+
+Wed May 12 14:37:27 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_x509name.c: attribute value of DC (short name of
+ domainComponent) should be IA5String.
+
+Wed May 12 13:20:19 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/composite.rb: improve configure methods (based on
+ the proposal of [ruby-talk:99671]).
+
+Wed May 12 11:51:08 2004 Dave Thomas <dave@pragprog.com>
+
+ * class.c (rb_obj_singleton_methods): fix rdoc
+
+Mon May 10 21:44:42 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb: Change scheme for
+ looking up symbols in HTML generator.
+
+Mon May 10 16:45:21 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (eval): warning during eval should not cause deadlock.
+ [ruby-talk:98651]
+
+ * eval.c (rb_eval): raise TypeError exception for superclass
+ mismatch. [ruby-list:39567]
+
+Mon May 10 12:11:37 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb: Hack to search parents
+ for unqualified constant names.
+
+Mon May 10 12:11:37 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb: Hack to search parents
+ for unqualified constant names.
+
+Sun May 9 22:37:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/net/ftp.rb: improved documentation
+ * lib/net/imap.rb: ditto
+ * lib/net/pop.rb: ditto
+ * lib/net/smtp.rb: ditto
+ * lib/net/telnet.rb: ditto
+
+Fri May 7 21:50:21 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::parse_include): Allow
+ multiple arguments to 'include'
+
+Fri May 7 21:31:56 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (fu_list): Array() breaks pathes including "\n".
+ [ruby-core:02843]
+
+Fri May 7 11:25:53 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * util.c (ruby_strtod): "0.0000000000000000001" should be converted
+ to 1.0e-19 instead of 0.0. (leading zeros aren't significant digits)
+ [ruby-talk:99318] [ruby-dev:23465]
+
+Fri May 7 10:00:05 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil.c (get_eval_string_core): bug fix. [ruby-dev:23466]
+
+Thu May 6 22:13:17 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * ext/socket/socket.c (ippaddr): use NUMERICHOST if can not resolve
+ hostname.
+
+Thu May 6 14:22:29 2004 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/yaml/rubytypes.rb (to_yaml): added instance variable handling
+ for Ranges, Strings, Structs, Regexps.
+
+ * lib/yaml/rubytypes.rb (to_yaml_fold): new method for setting a
+ String's flow style.
+
+ * lib/yaml.rb (YAML::object_maker): now uses Object.allocate.
+
+ * ext/syck/gram.c: fixed transfer methods on structs, broke it
+ last commit.
+
+Thu May 6 11:40:28 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (string): accept NIL.
+
+ * lib/net/imap.rb (body_type_basic): allow body-fields omissions.
+
+Thu May 6 01:59:04 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb (Generators::HtmlMethod::params):
+ Don't include the &block parameter if we have explicit
+ yield parameters.
+
+Wed May 5 03:40:29 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/ring.rb: use recv instead of recvfrom.
+
+Tue May 4 23:52:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/gserver.rb: documented
+
+Tue May 4 23:46:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/xmlrpc/README.txt: introduced for documentation purposes
+
+Mon May 3 09:47:24 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method_or_yield_parameters):
+ Fix parsing bug if yield called within 1 line block
+
+Sun May 2 01:04:38 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib, ext/tk: renewal Ruby/Tk
+
+Fri Apr 30 20:08:41 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * time.c (SIZEOF_TIME_T): support SIZEOF_TIME_T == SIZEOF_INT.
+
+Tue Apr 27 13:12:42 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): too many line trace call. (ruby-bugs PR#1320)
+
+Tue Apr 27 08:41:28 2004 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/yaml/rubytypes.rb: passing Range tests.
+
+ * ext/syck/syck.h: version 0.44.
+
+ * ext/syck/gram.c: transfers no longer open an indentation.
+ fixed transfers which precede blocks.
+
+ * ext/syck/token.c: ditto.
+
+ * ext/syck/syck.c: fixed segfault if an anchor has been released already.
+
+ * ext/syck/node.c (syck_free_members): organized order of free'd nodes.
+
+ * ext/syck/rubyext.c (syck_emitter_write_m): test for proper string with
+ StringValue.
+
+Mon Apr 26 23:56:54 2004 Daniel Kelley <news-1082945587@dkelley.gmp.san-jose.ca.us>
+
+ * README.EXT, README.EXT.ja: fixed wrong function signature.
+ [ruby-talk:98349]
+
+Mon Apr 26 21:40:09 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/code_objects.rb (RDoc::Context::add_alias): Only alias
+ to instance methods.
+
+Sat Apr 24 10:38:31 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/markup/simple_markup.rb (SM::SimpleMarkup::group_lines):
+ Fix bug where consecutive headings are merged.
+
+Fri Apr 23 23:26:13 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb: $hdrdir should not contain macros for backward
+ compatibility. [bruby-dev:28]
+
+ * version.c (ruby_show_copyright): obtain copyright year from
+ RUBY_RELEASE_YEAR.
+
+ * win32/resource.rb: ditto.
+
+ * win32/resource.rb: default rubyw icon to ruby.ico, and let DLL also
+ include them.
+
+ * win32/resource.rb: include winver.h for older WindowsCE.
+
+Fri Apr 23 16:38:46 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb: sync taint/freeze flag between
+ a pathname object and its internal string object.
+
+Fri Apr 23 14:52:08 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (stmt, arg, aref_args): should not make sole splat into
+ array, in aref_args other than aref with op_asgn.
+
+Fri Apr 23 14:14:38 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/resolv.rb: don't use Regexp#source to embed regexps.
+ [ruby-dev:23432]
+
+Thu Apr 22 04:15:36 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (aref_args): should pass expanded list. [ruby-core:02793]
+
+Thu Apr 22 01:12:57 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (flo_to_s): tweak output string based to preserve
+ decimal point and to remove trailing zeros. [ruby-talk:97891]
+
+ * string.c (rb_str_index_m): use unsigned comparison for T_FIXNUM
+ search. [ruby-talk:97342]
+
+Wed Apr 21 22:57:27 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/rinda.rb, test/rinda/test_rinda.rb: check Hash tuple size.
+
+Wed Apr 21 20:05:00 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb (URI::HTTP#proxy_open): set Host: field explicitly.
+ [ruby-list:39542]
+
+Mon Apr 19 18:11:15 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (rb_hash_equal): returns true if two hashes have same set
+ of key-value set. [ruby-talk:97559]
+
+ * hash.c (rb_hash_eql): returns true if two hashes are equal and
+ have same default values.
+
+Mon Apr 19 08:19:58 2004 Doug Kearns <djkea2@mugca.its.monash.edu.au>
+
+ * dln.c, io.c, lib/benchmark.rb, lib/cgi.rb, lib/csv.rb, lib/date.rb,
+ lib/ftools.rb, lib/getoptlong.rb, lib/logger.rb, lib/matrix.rb,
+ lib/monitor.rb, lib/set.rb, lib/thwait.rb, lib/timeout.rb,
+ lib/yaml.rb, lib/drb/drb.rb, lib/irb/workspace.rb, lib/net/ftp.rb,
+ lib/net/http.rb, lib/net/imap.rb, lib/net/telnet.rb,
+ lib/racc/parser.rb, lib/rinda/rinda.rb, lib/rinda/tuplespace.rb,
+ lib/shell/command-processor.rb, lib/soap/rpc/soaplet.rb,
+ lib/test/unit/testcase.rb, lib/test/unit/testsuite.rb: typo fix.
+
+Mon Apr 19 08:14:18 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::find_body): Allow for
+ #ifdef HAVE_PROTOTYPES
+
+Fri Apr 16 22:33:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * ext/iconv/iconv.c: nearly finished RDoc comments.
+
+Fri Apr 16 17:04:07 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_equal): always returns true or false, never
+ returns nil. [ruby-dev:23404]
+
+Fri Apr 16 08:27:02 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: skip linking when libraries to be preloaded not
+ compiled. [ruby-list:39561]
+
+Thu Apr 15 23:21:52 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (pst_success_p): new method Process::Status#success?.
+ [ruby-dev:23385]
+
+Thu Apr 15 17:12:13 2004 Tanaka Akira <akr@m17n.org>
+
+ * ext/gdbm/gdbm.c (Init_gdbm): define GDBM::READER, GDBM::WRITER,
+ GDBM::WRCREAT and GDBM::NEWDB.
+ (fgdbm_initialize): use specified read/write flag.
+
+Wed Apr 14 11:29:56 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * numeric.c (flo_eq): workaround for bcc32's bug.
+ (ruby-bugs-ja:PR#594)
+
+Wed Apr 14 13:06:35 2004 Doug Kearns <djkea2@mugca.its.monash.edu.au>
+
+ * array.c, enum.c, eval.c, file.c, io.c, numeric.c, object.c, prec.c,
+ process.c, re.c, string.c: typos in RDoc comments. [ruby-core:02783]
+
+Wed Apr 14 11:06:38 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::scan): Changed
+ behavior of :enddoc: -- it now unconditionally terminates
+ processing of the current file.
+
+Wed Apr 14 11:03:22 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * defines.h: include <net/socket.h> to get fd_set definition in BeOS.
+
+Tue Apr 13 23:06:30 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/rinda.rb: change pattern matching.
+ a === b -> a == b || a === b. [druby-ja:98]
+
+ * test/rinda/test_rinda.rb: ditto.
+
+Tue Apr 13 19:54:29 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/http.rb: should not overwrite HTTP request header.
+ [ruby-list:39543]
+
+Tue Apr 13 01:30:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * ext/iconv/iconv.c: RDoc documentation (from RD; nearly finished).
+ * ext/iconv/charset_alias.rb: Prevent from RDoc'ing.
+
+Mon Apr 12 19:11:29 2004 Eric Hodel <drbrain@segment7.net>
+
+ * gc.c (rb_gc_copy_finalizer): typo. [ruby-core:02774]
+
+Mon Apr 12 18:52:32 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_x509name.c (ossl_x509name_init_i): should return
+ a value.
+
+Mon Apr 12 10:43:47 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * dir.c (rb_glob2, rb_glob, rb_globi, push_globs, push_braces,
+ rb_push_glob): fix memory leak. (leaked when block was interrupted)
+
+Mon Apr 12 10:27:37 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub: backport SIZEOF_TIME_T definition from 1.9.
+
+ * win32/Makefile.sub: ditto.
+
+ * wince/Makefile.sub: ditto.
+
+Sun Apr 11 19:12:35 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (require_libraries): restore source file/line after
+ statically linked extensions initialized. [ruby-dev:23357]
+
+Sun Apr 11 10:47:04 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/code_objects.rb (RDoc::TopLevel::add_class_or_module): Toplevel
+ classes and modules are a special case too... (handle extending existing
+ classes with or without :enddoc:)
+
+Sat Apr 10 23:51:13 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/code_objects.rb (RDoc::Context::add_to): Implementation of :enddoc:
+ made one too many assumptions...
+
+Sat Apr 10 00:00:19 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/markup/simple_markup/inline.rb: Fix problem
+ with \_cat_<b>dog</b>
+
+Wed Apr 7 00:19:50 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/rinda.rb: fix hash tuple bug.
+
+ * lib/rinda/tuplespace.rb: ditto.
+
+ * test/rinda/test_rinda.rb
+
+Tue Apr 6 18:24:18 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_reopen): should use rb_io_check_io().
+
+Tue Apr 6 16:46:09 2004 Tanaka Akira <akr@m17n.org>
+
+ * configure.in: check the size of time_t.
+
+ * time.c (time_add): new function.
+ (time_plus): use time_add.
+ (time_minus): use time_add.
+
+Tue Apr 6 13:21:30 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/socket/socket.c (make_hostent): must return value.
+
+Tue Apr 6 00:05:30 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/rinda.rb: add require 'drb/drb'
+
+Mon Apr 5 08:18:23 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/rdoc.rb: Remove leading ./ from file names so that cross
+ references work properly.
+
+Sun Apr 4 20:33:42 2004 Minero Aoki <aamine@loveruby.net>
+
+ * eval.c (Init_load): make $LOADED_FEATURES built-in.
+ [ruby-dev:23299]
+
+ * ruby.c (ruby_prog_init): make $PROGRAM_NAME built-in.
+
+ * lib/English.rb: remove $LOADED_FEATURES and $PROGRAM_NAME.
+
+Sun Apr 4 14:01:20 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/options.rb (Options::parse): Allow multiple -x options to RDoc.
+ Fix bug where files weren't being excluded properly
+
+Sat Apr 3 17:11:05 2004 why the lucky stiff <why@ruby-lang.org>
+
+ * ext/syck/syck.h: version 0.43.
+
+ * ext/syck/lib/gram.c: allow root-level inline collections.
+ [ruby-talk:94922]
+
+ * lib/yaml/rubytypes.rb (Symbol#to_yaml): emit symbols as implicits.
+ [ruby-talk:94930]
+
+ * ext/syck/bytecode.c: turn off default implicit typing.
+
+ * ext/syck/implicit.c: detect base60 integers.
+
+ * ext/syck/rubyext.c: handle base60, as well as hex and octal
+ with commas. implicit typing of ruby symbols.
+
+Fri Apr 2 17:27:17 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (top_include): include in the wrapped load is done for
+ the wrapper, not for a singleton class for wrapped main.
+ [ruby-dev:23305]
+
+Fri Apr 2 15:13:44 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_eq): use temporary double variable to save the
+ result (internal float register may be bigger than 64 bits, for
+ example, 80 bits on x86). [ruby-dev:23311]
+
+Fri Apr 2 14:35:26 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (block_pass): should generate unique identifier of the
+ pushing block. [ruby-talk:96363]
+
+Fri Apr 2 07:31:38 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (make_hostent): fix memory leak, based on
+ the patch from HORIKAWA Hisashi <vzw00011@nifty.ne.jp>.
+
+Thu Apr 1 22:55:33 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb: Allow rdoc comments in
+ =begin rdoc/=end
+
+ * lib/rdoc/parsers/parse_rb.rb: Fix problem with comment in
+ top-level method being taken as file comment.
+
+Thu Apr 1 22:55:04 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_options.rb: Fix undefined variable warning.
+
+Thu Apr 1 19:58:37 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/soap/mapping/{factory.rb,registry.rb}: fixed illegal mapped URI
+ object with soap/marshal.
+ added URIFactory class for URI mapping. BasetypeFactory checks
+ instance_variables when original mapping is not allowed (ivar must
+ be empty). Instance of URI have instance_variables but it must be
+ llowed whenever original mapping is allowed or not.
+
+ * lib/xsd/datatypes.rb: check the smallest positive non-zero
+ single-precision float exactly instead of packing with "f".
+ [ruby-talk:88822]
+
+ * lib/soap/mapping/rubytypeFactory.rb: should not dump singleton class.
+ [ruby-dev:22588]
+ c = class << Object.new; class C; self; end; end; SOAPMarshal.dump(c)
+
+Wed Mar 31 19:06:23 2004 Tanaka Akira <akr@m17n.org>
+
+ * time.c (year_leap_p): new function.
+ (timegm_noleapsecond): ditto.
+ (search_time_t): use timegm_noleapsecond instead of
+ mktime for first guess.
+
+Wed Mar 31 12:04:04 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/delegate.rb (DelegateClass): define internal methods of the
+ result class, but not metaclass of the caller. [ruby-talk:96156]
+
+ * intern.h: provide proper prototypes. [ruby-core:02724]
+
+ * ruby.h: missing.h is now prerequisite to intern.h.
+
+Tue Mar 30 20:25:34 2004 Tanaka Akira <akr@m17n.org>
+
+ * time.c (search_time_t): limit guess range by mktime if it is
+ available. [ruby-dev:23274]
+
+Sun Mar 28 14:16:59 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/pop.rb (auth): failed when account/password include "%".
+ [ruby-talk:95933]
+
+Sat Mar 27 21:40:41 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb: permit extra semicolon in content-type field.
+
+Sat Mar 27 10:40:48 2004 Tanaka Akira <akr@m17n.org>
+
+ * (lib/pp.rb, lib/prettyprint.rb): define seplist in PP::PPMethods
+ instead of PrettyPrint.
+
+Thu Mar 25 23:28:52 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_overflow_p): backport 1.9 usec overflow function.
+ (ruby-bugs PR#1307)
+
+Thu Mar 25 23:15:24 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_options.rb (RI::Options::show_version):
+ Add --version option
+
+Thu Mar 25 04:16:18 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_options.rb (RI::Options): Add the --list-names option,
+ which dumps our all known names
+
+Thu Mar 25 03:57:47 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_util.rb (NameDescriptor::initialize): No longer
+ allow nested classes to be designated using "."--you must
+ now use "::"
+
+Thu Mar 25 02:00:18 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/template/html/one_page_html.rb (Page):
+ Fix to work with C modules.
+
+Wed Mar 24 21:17:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/uri.rb: Documented (thanks Dmitry V. Sabanin).
+ * lib/uri/common.rb: Ditto.
+ * lib/uri/ftp.rb: Ditto.
+ * lib/uri/generic.rb: Ditto.
+ * lib/uri/http.rb: Ditto.
+ * lib/uri/https.rb: Ditto.
+ * lib/uri/ldap.rb: Ditto.
+ * lib/uri/mailto.rb: Ditto.
+ (All backported from 1.9)
+
+Wed Mar 24 18:48:26 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb ($ruby, $topdir, $hdrdir): should not be affected by
+ DESTDIR after installed.
+
+ * lib/mkmf.rb (RUBY): / is not recognized as path separator on
+ nmake/bmake. [ruby-list:39388]
+
+ * lib/mkmf.rb (init_mkmf): $INCFLAGS also should be lazy-evaluated.
+
+Wed Mar 24 12:32:56 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::handle_class_module):
+ Don't document methods if we don't know for sure the
+ class or module.
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_class):
+ Don't store documentation for singleton classes if we
+ don't know the real class.
+
+Wed Mar 24 11:11:26 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb (Generators::HTMLGenerator::load_html_template):
+ Allow non-RDoc templates by putting a slash in the template name
+
+Mon Mar 22 16:19:57 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ruby.1: add -width option to .Bl for old groff.
+
+Sun Mar 21 21:11:16 2004 Keiju Ishitsuka <keiju@ishitsuka.com>
+
+ * lib/shell/*: bug fix for Shell#system(command_line_string).
+
+Sat Mar 20 20:57:10 2004 David Black <dblack@wobblini.net>
+
+ * lib/scanf.rb: Backported 1.9 branch
+ modifications/corrections to 1.8 branch
+
+Sat Mar 20 23:51:03 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * eval.c (rb_require_safe): preserve old ruby_errinfo.
+ [ruby-talk:95409]
+
+ * eval.c (rb_f_raise): should not clear backtrace information if
+ exception object already have one.
+
+Sat Mar 20 15:25:36 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/template/html/html.rb (RDoc::Page): Force
+ page background to white.
+
+Sat Mar 20 09:52:33 2004 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: _parse() now accepts fractional
+ part of second minute that follows a comma or a full stop.
+
+Fri Mar 19 01:55:57 2004 Mauricio Fernandez <batsman.geo@yahoo.com>
+
+ * io.c (rb_io_sync): need not to check writable. [ruby-core:02674]
+
+Thu Mar 18 21:44:38 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: backport drb.rb 1.16.
+
+Fri Mar 18 17:49:51 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (make_struct): allow const_id for accessor names.
+ [ruby-core:04585]
+
+ * eval.c (rb_attr): check if attribute name is local_id or
+ const_id.
+
+Thu Mar 18 16:22:38 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_eq): avoid false positive by using scope and
+ dyna_vars. no longer use frame.uniq.
+
+Wed Mar 17 14:44:43 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * dir.c (range): fix possible "\0" overrun. (in case of "\0-")
+
+Mon Mar 15 07:39:13 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): should not re-submit TAG_BREAK if this
+ yield is not break destination. [ruby-dev:23197]
+
+Sat Mar 13 14:28:16 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/drb/test_drbssl.rb: rescue LoadError. (Barkport from main
+ trunk)
+
+ * test/drb/test_drbunix.rb: ditto.
+
+Wed Mar 10 22:28:09 2004 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (remove_dir): should handle symlink correctly.
+ This patch is contributed by Christian Loew. [ruby-talk:94635]
+ (Backport from main trunk)
+
+Wed Mar 10 16:28:42 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (return_jump): set return value to the return
+ destination. separated from localjump_destination().
+
+ * eval.c (break_jump): break innermost loop (or thread or proc).
+
+ * eval.c (rb_yield_0): set exit_value for block break.
+
+Wed Mar 10 15:58:43 2004 Ryan Davis <ryand@zenspider.com>
+
+ * eval.c (eval): Only print backtrace if generating the backtrace
+ doesn't generate an exception. [ruby-core:02621]
+
+Tue Mar 9 13:04:26 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_ungetc): raise IOError instead of calling
+ rb_sys_fail(). [ruby-talk:23181]
+
+Mon Mar 8 19:32:28 2004 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/common.rb (URI::REGEXP::PATTERN::HOSTPORT): (?:#{PORT})
+ -> (?::#{PORT}). [ruby-dev:23170]
+
+Mon Mar 8 15:31:41 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * dir.c (range): treat incomplete '[' as ordinary character (like
+ has_magic does).
+
+ * dir.c (range): Cancel above change. More discussion is needed.
+
+Sun Mar 7 22:37:46 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/drb/ut_drb.rb: use 'druby://localhost:0'. [ruby-dev:23078]
+
+ * test/drb/ut_eval.rb: ditto.
+
+ * test/drb/ut_large.rb: ditto.
+
+ * test/drb/ut_safe1.rb: ditto.
+
+ * test/drb/ut_drb_drbssl.rb: use 'drbssl://localhost:0'.
+
+Sun Mar 7 16:22:26 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * Makefile.in (lex.c): use $? instead of $<.
+
+Fri Mar 5 00:54:14 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/test/unit.rb: MOve RDoc documentation so that you can
+ now say 'ri Test::Unit'
+
+Tue Mar 2 12:32:59 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub, wince/Makefile.sub (config.h): shouldn't check
+ defined? NORETURN. [ruby-dev:23100]
+
+Mon Mar 1 12:24:10 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_alias):
+ Allow aliases to have parentheses
+
+Sun Feb 29 23:14:53 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_class):
+ Handle :nodoc: on singleton classes.
+
+Sat Feb 28 10:58:49 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * MANIFEST: add test_erb.rb
+
+ * lib/erb.rb, test/erb/test_erb.rb: don't forget filename,
+ if both filename and safe_level given. [ruby-dev:23050]
+
+Fri Feb 27 01:00:09 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb, test/drb/drbtest.rb: require drb/eq.rb by default
+
+Wed Feb 25 21:16:25 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb (with_destdir): should return the given argument if no
+ DESTDIR is given.
+
+ * instruby.rb: use path name expansion of cmd.exe.
+
+Wed Feb 25 09:35:22 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * error.c (NameError::Message): new class for lazy evaluation of
+ message to ensure replaced before marshalling. merge from HEAD.
+ (ruby-bugs-ja:PR#588)
+
+ * eval.c (rb_method_missing): use NameError::Message. merge from
+ HEAD. (ruby-bugs-ja:PR#588)
+
+Tue Feb 24 18:59:37 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * dir.c (glob_helper): '**/' should not match leading period
+ unless File::FNM_DOTMATCH is set. (like '*/') [ruby-dev:23014]
+
+Tue Feb 24 13:22:21 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/rdoc.rb (RDoc::RDoc::normalized_file_list): Attempt to get better
+ heuristics on which files to include and exclude. Now only include
+ non-standard files if they are explicitly named in ARGV.
+
+Tue Feb 24 07:23:30 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb: Deal with :stopdoc: when
+ choosing a default main page to display (ie. don't select a page
+ if we don't have documentation for it).
+
+Tue Feb 24 06:40:14 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RubyLex::identify_identifier): Handle
+ class variables in code listings
+
+Tue Feb 24 06:40:14 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RubyLex::identify_identifier): Handle
+ class variables in code listings
+
+Tue Feb 24 06:32:27 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::do_aliases): Handle
+ aliases in C files.
+
+Tue Feb 24 06:16:22 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/rdoc.rb (RDoc::RDoc::document): Now create op dir _before_
+ parsing files.
+
+Tue Feb 24 06:08:47 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_constant):
+ Start collecting text of constant values earlier: was missing
+ values in output if there was no space after '='
+
+Tue Feb 24 06:08:25 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb: Escape contant values.
+
+Tue Feb 24 03:45:06 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_config.c (ossl_config_each): add new method
+ OpenSSL::Config#each. it iterates with section name, field name
+ and value.
+
+ * ext/openssl/ossl_config.c (Init_ossl_config): include Enumerable.
+
+Mon Feb 23 09:16:35 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb (DOSISH): embedded path in batch files should not be
+ prefixed by DESTDIR. [ruby-core:02186]
+
+Sun Feb 22 09:54:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * re.c: corrected documentation format (again)
+
+Sun Feb 22 09:43:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * re.c: corrected documentation format (rb_reg_initialize_m)
+
+Sat Feb 21 22:36:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * ext/zlib/zlib.c: documented, but needs more effort.
+
+Sat Feb 21 11:12:15 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * missing/os2.c, missing/x68.c: typo fix. pointed out by greentea.
+
+Fri Feb 20 18:59:47 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/init.rb (IRB::IRB.parse_opts): add -I option to
+ irb. [ruby-dev:39243]
+
+Thu Feb 19 23:24:16 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb (Generators::HtmlClass::build_attribute_list):
+ Support visibility modifiers for attributes
+
+Thu Feb 19 23:24:16 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb (Generators::HtmlClass::build_attribute_list):
+ Support visibility modifiers for attributes
+
+Thu Feb 19 22:39:04 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/rinda/test_rinda.rb: DRb.start_service only once in testsuites.
+ DRb.start_service could handle this.
+
+Thu Feb 19 22:19:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/ostruct.rb: documented
+
+Thu Feb 19 21:28:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * ext/strscan/strscan.c: improved documentation
+
+Thu Feb 19 03:10:52 2004 Minero Aoki <aamine@loveruby.net>
+
+ * ext/strscan/strscan.c: synchronized with main trunk (rev 1.11).
+
+Thu Feb 19 02:30:34 2004 Minero Aoki <aamine@loveruby.net>
+
+ * ext/strscan/strscan.c: documentation checked.
+
+Thu Feb 19 00:11:05 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/markup/simple_markup/preprocess.rb (SM::PreProcess::handle):
+ Strip extraneous space from filenames in :include:
+
+Wed Feb 18 22:52:00 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/unix.rb: remove O_NONBLOCK, thanks \ay
+
+Wed Feb 18 22:47:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * ext/strscan/strscan.c: documented
+
+Wed Feb 18 22:03:11 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/*: should not depend on $KCODE.
+
+Wed Feb 18 17:18:01 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/win32ole/win32ole.c: need to include <olectl.h> on Cygwin.
+
+Wed Feb 18 10:40:38 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): do not prepend dots for negative
+ numbers if FZERO is specified. [ruby-list:39218]
+
+Tue Feb 17 23:40:34 2004 Guy Decoux <ts@moulon.inra.fr>
+
+ * sprintf.c (rb_f_sprintf): preserve original val for
+ format_integer. [ruby-talk:92975]
+
+Tue Feb 17 23:28:45 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/ruby/marshaltestlib.rb: common marshal testcase added.
+
+ * test/ruby/test_marshal.rb: use above testsuite.
+
+ * test/soap/marshal/test_marshal.rb: ditto.
+
+ * test/soap/marshal/cmarshal.rb: removed (not used).
+
+Tue Feb 17 10:51:23 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/syck/rubyext.c (syck_emitter_end_object): takes only one arg.
+
+Tue Feb 17 01:35:28 2004 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (rb_eval): care that another thread replace NODE_DREGX_ONCE
+ to NODE_LIT. [ruby-dev:22920]
+
+Tue Feb 17 01:24:35 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bcc32/Makefile.sub, win32/Makefile.sub (config.h): define
+ STACK_GROW_DIRECTION. [ruby-dev:22910]
+
+ * bcc32/Makefile.sub (config.h): add newer checks.
+
+ * wince/Makefile.sub (config.h): define NEED_IO_SEEK_BETWEEN_RW.
+
+Tue Feb 17 00:38:10 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb: TupleSpace#initialize, stop doubling timeout
+
+Tue Feb 17 00:18:03 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/rinda/test_rinda.rb: import test_rinda.rb
+
+Tue Feb 17 00:14:30 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub: avoid warning "Redefinition of macro
+ 'HAVE_GETLOGIN'".
+
+ * vms/config.h_in: ditto.
+
+Mon Feb 16 23:28:14 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/csv.rb: document reduction. [ruby-core:02429]
+
+Mon Feb 16 22:08:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/generator.rb: corrected doc format
+ * lib/rinda/rinda.rb: added documentation (from Hugh Sasse)
+ * lib/rinda/tuplespace.rb: ditto
+
+Mon Feb 16 20:41:32 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub: show more warnings. (refering to mingw)
+
+ * bcc32/setup.mak: ditto.
+
+Mon Feb 16 13:39:44 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * dir.c (rb_glob, rb_globi): add const.
+
+ * ruby.h: ditto.
+
+Mon Feb 16 02:16:33 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * bcc32/Makefile.sub: should warn suspicious pointer conversion.
+
+ * bcc32/setup.mak: ditto.
+
+Sun Feb 15 19:06:42 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb: TupleSpace#read(tpl, 0), raise
+ RequestExpiredError if not found.
+
+Sun Feb 15 15:56:46 2004 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c: add IDispatch wrapper in val2variant.
+ Thanks, arton.
+
+Sun Feb 15 01:46:05 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/mkmf.rb: absolute path of ruby is assigned to $(RUBY).
+ [ruby-dev:22870]
+
+Sat Feb 14 11:29:41 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * sample/drb/*: import lib/drb/sample
+
+Sat Feb 14 11:08:23 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: add pretty_print, thanks gotoken.
+
+Fri Feb 13 12:35:08 2004 Minero Aoki <aamine@loveruby.net>
+
+ * test/fileutils/test_fileutils.rb: File.link may raise EINVAL and
+ EACCES on Windows.
+
+Thu Feb 12 21:45:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/ftools.rb: documented
+
+Thu Feb 12 21:25:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/base64.rb: backported from HEAD (modularised and documented)
+
+Thu Feb 12 20:31:48 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_tmpsrc): cpp32 of Borland C++ ignores #error
+ directives in DOS line-ending files at all.
+
+Thu Feb 12 02:23:56 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb: use assert_raise instead of assert_raises.
+
+ * lib/pp.rb: ditto.
+
+ * lib/time.rb: ditto.
+
+ * lib/tsort.rb: ditto.
+ use TSortHash and TSortArray instead of Hash and Array in test.
+
+Wed Feb 11 20:01:12 2004 akira yamada <akira@ruby-lang.org>
+
+ * test/ruby/test_file.rb (TestFile::test_fnmatch): added tests for
+ File.fnmatch. [ruby-dev:22815][ruby-dev:22819]
+
+ * test/ruby/test_proc.rb (TestProc::test_eq): added a
+ test. [ruby-dev:22599]
+
+ * test/ruby/test_proc.rb (TestProc::test_eq): added tests for
+ Proc#==. [ruby-dev:22592], [ruby-dev:22601]
+
+Tue Feb 10 16:43:56 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (umethod_bind): purge unused check. [ruby-dev:22850]
+
+Mon Feb 9 17:16:00 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/rdoc/parsers/parse_c.rb: escape '{' and '}' to avoid warnings.
+
+Mon Feb 9 13:00:55 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * dir.c (fnmatch): File.fnmatch('*?', 'a') should return true.
+ [ruby-dev:22815]
+
+ * dir.c (fnmatch): File.fnmatch('\[1\]' , '[1]') should return true.
+ [ruby-dev:22819]
+
+Sun Feb 8 16:46:13 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/pp.rb (PP::PPMethods::object_address_group): suppress negative
+ sign for higher heap areas.
+
+Fri Feb 6 22:48:16 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb (gen_url): Support
+ https in RDoc hyperlinks
+
+Fri Feb 6 22:41:22 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/pp.rb (PPInspectTest#test_to_s_with_iv): rollback the previous
+ commit. [ruby-dev:22813]
+
+Fri Feb 6 22:22:50 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/pp.rb (PPInspectTest#test_to_s_with_iv): remove instance
+ variable which is defined in the test.
+
+Fri Feb 6 00:48:37 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/prettyprint.rb (PrettyPrint#first?): obsoleted.
+
+Thu Feb 5 23:56:55 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/prettyprint.rb (PrettyPrint#seplist): added.
+
+ * lib/pp.rb (PPMethods#pp_object): use seplist.
+ (PPMethods#pp_hash): ditto.
+ (Array#pretty_print): ditto.
+ (Struct#pretty_print): ditto.
+ (MatchData#pretty_print): ditto.
+
+ * lib/set.rb (Set#pretty_print): use seplist.
+
+Wed Feb 4 02:12:06 2004 Tanaka Akira <akr@m17n.org>
+
+ * file.c (test_l): fix wrong method name in document.
+ (test_S): ditto.
+ (test_b): ditto.
+ (test_c): ditto.
+ (test_suid): ditto.
+ (test_sgid): ditto.
+ (test_sticky): ditto.
+
+Tue Feb 3 08:04:57 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/pp.rb (Struct#pretty_print_cycle): follow 1.8 style.
+
+Mon Feb 2 19:33:49 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: backport from 1.9 for Interix.
+
+ * dln.c (dln_load): ditto.
+
+Mon Feb 2 13:31:51 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/net/http.rb (canonical_each): fix merge miss.
+
+Mon Feb 2 01:54:00 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/pp.rb (Struct#pretty_print): make it 1.8 style.
+ (Numeric#pretty_print, FalseClass#pretty_print)
+ (TrueClass#pretty_print, Module#pretty_print): fix pp for objects
+ with instance variables. [ruby-talk:91157]
+
+ * lib/open-uri.rb (URI::Generic#find_proxy): return nil on loopback
+ address.
+
+ * lib/resolv-replace.rb (BasicSocket#send): don't replace because
+ it has no hostname argument.
+ (IPSocket.getaddress): raise SocketError instead of
+ Resolv::ResolvError for errors.
+ (TCPSocket#initialize, UDPSocket#bind, UDPSocket#connect)
+ (SOCKSSocket#initialize): use IPSocket.getaddress instead of
+ Resolv.getaddress.
+ (UDPSocket#send): recognize 3 arguments form. try all addresses on
+ 4 arguments form.
+
+Sun Feb 1 18:17:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/net/http.rb: merged coding style changes from HEAD.
+
+Sun Feb 1 16:15:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/test/unit.rb: rearranged documentation for RDoc's sake.
+ * lib/matrix.rb: improved documentation.
+ * lib/net/http.rb: slight documentation formatting improvement.
+
+Sun Feb 1 05:30:06 2004 Tanaka Akira <akr@m17n.org>
+
+ * lib/open-uri.rb (URI::Generic#find_proxy): warn HTTP_PROXY.
+ raise an errror on non-http proxy URI.
+ (OpenURI::Buffer#<<): make a tempfile binmode. [ruby-talk:90793]
+
+Sat Jan 31 09:20:32 2004 NAKAMURA, Hiroshi <nakahiro@sairon.co.jp>
+
+ * sample/openssl/gen_csr.rb: wrong usage string.
+
+Sat Jan 31 01:00:32 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/soap/wsdlDriver.rb, lib/wsdl/soap/operation.rb: add support of
+ "parts" attribute of soap:body element in WSDL.
+
+ * lib/wsdl/xmlSchema/schema.rb: friendly warning message for
+ simpleType element which is not supported for now.
+
+ * lib/soap/mapping/factory.rb: deleted unused methods.
+
+ * lib/soap/mapping/rubytypeFactory.rb: do no ignore case while xsi:type
+ string <-> Ruby class name matching.
+
+ * test/wsdl/soap/{soapbodyparts.wsdl,test_soapbodyparts.wsdl}: new
+ files.
+
+Thu Jan 29 23:56:00 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * util.c (mblen): fix overrun. [ruby-dev:22672]
+
+Thu Jan 29 22:41:53 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb: Allow 'link:' in Tidylinks.
+ THis means you can write "see f1[link:files/f1_rb.html]".
+
+Thu Jan 29 15:33:23 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_x509hame.c (ossl_x509name_initialize): change
+ second argument. it expected to be a Hash not an Integer.
+
+ * ext/openssl/ossl_x509name.c (ossl_x509name_add_entry): add new
+ function for OpenSSL::X509::Name#add_entry.
+
+ * ext/openssl/ossl_x509name.c (ossl_x509name_to_a): append ASN.1
+ tag number to each element of return value.
+
+ * ext/openssl/ossl_x509name.c (Init_ossl_x509name): add constants
+ OpenSSL::X509::Name::DEFAULT_OBJECT_TYPE and OBJECT_TYPE_TEMPLATE.
+
+ * ext/openssl/lib/openssl/x509.rb (OpenSSL::X509::Name#initialize):
+ second argument takes OBJECT_TYPE_TEMPLATE by default.
+
+ * sample/openssl/gen_csr.rb: use OpenSSL::X509::Name.parse.
+
+Wed Jan 28 04:29:41 2004 Eric Schwartz <emschwar@fc.hp.com>
+
+ * lib/cgi/session.rb: use LOCK_SH to read, and a few other
+ improvements. [ruby-core:02328]
+
+Tue Jan 27 11:09:29 2004 FUKUMOTO Atsushi <fukumoto@nospam.imasy.or.jp>
+
+ * ext/socket/socket.c (s_recvfrom): sending length should be an
+ invariant while retrying on EAGAIN. [ruby-talk:89962]
+
+Tue Jan 27 10:35:18 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/win32ole/win32ole.c (set_argv): fix condition.
+
+Tue Jan 27 02:26:31 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httputils.rb (WEBrick:HTTPUtils::parse_header):
+ refine regex for header-name.
+
+Tue Jan 27 00:30:11 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub: rollback.
+
+Mon Jan 26 22:53:04 2004 Dave Thomas <dave@pragprog.com>
+
+ * io.c: Remove documentation references to $defout.
+
+Mon Jan 26 15:11:47 2004 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * sample/exyacc.rb: escape '}' to avoid warning.
+
+Mon Jan 26 14:41:46 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb (Delegator::initialize): preserve
+ singleton_method_added method [ruby-dev:22685]
+
+ * lib/delegate.rb (Delegator::initialize): use Kernel::raise
+ instead of mere raise. [ruby-dev:22681]
+
+Mon Jan 26 12:47:17 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: define CONST84 when TCL_MAJOR_VERSION == 7
+
+Mon Jan 26 11:35:23 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: Makefiles should depend on also rbconfig.rb.
+ (ruby-bugs:PR#1256)
+
+ * ext/win32ole/win32ole.c (set_argv): set real arguments to
+ WIN32OLE::ARGV. [ruby-list:39073]
+
+Thu Jan 22 22:54:53 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (BEG_REGEXP): allow 8-bit characters in quoted
+ strings for Novell GroupWise Internet Agent.
+ * lib/net/imap.rb (DATA_REGEXP): ditto.
+
+Thu Jan 22 16:21:33 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (string_content): reset lexical states at the beginning of
+ string contents. [ruby-list:39061]
+
+Wed Jan 21 21:55:51 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: remove O_NONBLOCK, thanks \ay
+ * lib/drb/extserv.rb: typo
+
+Wed Jan 21 17:57:56 2004 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (envelope): allow NIL.
+ * lib/net/imap.rb (body): ditto.
+ * lib/net/imap.rb (number): ditto.
+ * lib/net/imap.rb (ensure_nz_number): show a detailed error
+ message.
+
+Wed Jan 21 16:44:20 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (merge_libs): squeeze successive same libraries.
+ [ruby-dev:22652]
+
+Wed Jan 21 16:01:37 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/digest/rmd160/extconf.rb: have_library appends found library.
+
+Wed Jan 21 11:36:00 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (block_append): update nd_end for "real" head node.
+ [ruby-list:39058]
+
+Tue Jan 20 14:48:13 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/extconf.rb: should check <openssl/conf_api.h> instead
+ of OPENSSL_VERSION_NUMBER. [ruby-list:39056]
+
+Tue Jan 20 14:43:17 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/base64.rb: Add RDoc
+
+Tue Jan 20 14:25:51 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/abbrev.rb: Add RDoc
+
+Tue Jan 20 13:22:39 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb: Document aliases at
+ top-most level.
+
+ * lib/English.rb: Document English.rb.
+
+Tue Jan 20 02:49:22 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/extconf.rb: add check for OpenSSL version.
+ [ruby-list:39054]
+
+Tue Jan 20 02:38:13 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_class): should not dump singleton class.
+ [ruby-dev:22631]
+
+Tue Jan 20 01:31:36 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * io.c (lineno): typo fix(FIX2INT -> INT2FIX).
+
+Mon Jan 19 21:53:38 2004 akira yamada <akira@ruby-lang.org>
+
+ * io.c, re.c, string.c, time.c: fixed up positions of RDocs.
+
+Mon Jan 19 07:09:20 2004 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: zone was wrong when it was behind UTC.
+ Thanks Mark J. Reed.
+
+ * lib/date/format.rb: %z is now always replaced by four digits
+ with a leading plus or minus sign.
+
+ * sample/cal.rb: added a class, anyway.
+
+Sun Jan 18 20:47:35 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ruby.c: use translate_char() on Cygwin.
+
+Sun Jan 18 02:33:26 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * defines.h (_WIN32): undef _WIN32 on Cygwin before defining DOSISH.
+
+Sun Jan 18 00:23:55 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (class2path): check anonymous class/module before
+ checking referable, and allow singleton classes.
+
+Fri Jan 16 14:33:35 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (class2path): get class path and check referable.
+ [ruby-dev:22588]
+
+Fri Jan 16 09:52:23 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_eq): Proc with empty body may not be equal.
+ [ruby-dev:22590]
+
+Thu Jan 15 13:03:10 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (argf_read): do not append EOF. (ruby-bugs-ja:PR#585)
+
+ * io.c (rb_io_fwrite): ad-hockery hack to get rid of HP-UX stdio
+ weird behavior. [ruby-dev:22424]
+
+Wed Jan 14 13:31:06 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/extconf.rb: wrapper iconv.rb is dependent on platform.
+
+Tue Jan 13 18:54:28 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/logger.rb(Logger#msg2str): no special treatment for the object
+ which responds to :to_str. commited at 2004-01-11T21:46:27 by
+ gsinclair.
+
+ * lib/logger.rb(LogDevice#initialize): remove type checking if the
+ given object is a String. Kernel.open handles it correctly.
+ commited at 2004-01-11T21:46:27 by gsinclair.
+
+ * test/logger/test_logger.rb: follow above change (ArgumentError ->
+ TypeError.) follow above commit.
+
+Tue Jan 13 14:27:13 2004 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/test/unit/ui/testrunnerutilities.rb (TestRunnerUtilities):
+ moved run method which allows output level. [ruby-dev:22554]
+
+Tue Jan 13 04:29:52 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_driver.rb (RiDriver::report_method_stuff):
+ Show fully-qualified class names in class list.
+
+Tue Jan 13 01:04:37 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_paths.rb (RI::Paths): First attempt at
+ incorporating DESTDIR in the rdoc installation.
+
+Mon Jan 12 23:27:19 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (primary): fix position after FCALL. [ruby-dev:22574]
+
+Mon Jan 12 12:07:22 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::do_methods):
+ Someone changed the "// in eval.c" comments to "/*...*/" style,
+ so the parsing of the source file name broke.
+
+ * object.c: Remove spurious space in TrueClass documentation.
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::find_body): Fix
+ bad regexp: if the code before a documented method contained
+ a comment that wasn't terminated by whitespace, that comment
+ and all intervening code was included in the following
+ method's documentation.
+
+ * lib/rdoc/ri/ri_formatter.rb (RI::HtmlFormatter::break_to_newline):
+ HTML formats need explicit line breaks.
+
+Mon Jan 12 11:46:30 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (LIBPATHFLAG, RPATHFLAG): enclose paths with single
+ quotes. [ruby-dev:22564]
+
+ * lib/mkmf.rb (libpathflag): do not enclose with quotes always.
+
+ * {bcc32,win32,wince}/Makefile.sub (LIBPATHFLAG): quoted.
+
+Mon Jan 12 02:24:07 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_formatter.rb (RI::HtmlFormatter): Add HTML
+ generation support to ri (Elliot Hughes)
+
+Mon Jan 12 02:24:07 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_formatter.rb (RI::HtmlFormatter): Add HTML
+ generation support to ri (Elliot Hughes)
+
+Sun Jan 11 02:07:47 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_options.rb (RI::Options::OptionList::OptionList):
+ Also accept command line options via the 'RI' environment variable.
+
+Sun Jan 11 02:07:47 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_options.rb (RI::Options::OptionList::OptionList):
+ Also accept command line options via the 'RI' environment variable.
+
+Sat Jan 10 21:27:41 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (eval): need to add message delimiter. [ruby-dev:22561]
+
+Sat Jan 10 01:54:50 2004 Eric Sunshine <sunshine@sunshineco.com>
+
+ * defines.h (__NeXT__): Ensure that all standard S_IRUSR, S_IWGRP,
+ S_IRWXO, etc. macros are defined since future code might require
+ them (even though present code only requires a subset).
+
+ * defines.h (__NeXT__): Bug fix: WORDS_BIGENDIAN was not being set
+ correctly on Rhapsody when -arch compiler flag was used (via
+ configure's --enable-fat-binary option).
+
+Fri Jan 9 10:05:14 2004 Siena. <siena@faculty.chiba-u.jp>
+
+ * lib/mkmf.rb (libpathflag): use single quotes. [ruby-dev:22440]
+
+Thu Jan 8 23:49:21 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (RDOCTARGET): new macro. if you want to install
+ rdoc documentation, you need to run configure with
+ --enable-install-doc.
+
+Thu Jan 8 21:29:43 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_pkey.c (ossl_pkey_to_der): removed; it returns
+ public key only.
+
+ * ext/openssl/ossl_pkey_dh.c (ossl_dh_to_der): new function for
+ OpenSSL::PKey::DH#to_der.
+
+ * ext/openssl/ossl_pkey_dsa.c (ossl_dsa_to_der): new function for
+ OpenSSL::PKey::DSA#to_der.
+
+ * ext/openssl/ossl_pkey_rsa.c (ossl_rsa_to_der): new function for
+ OpenSSL::PKey::RSA#to_der.
+
+Thu Jan 8 16:51:04 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/wsdl/datetime/test_datetime.rb: fixed a stupid testcase which
+ dumps "E" at month-end.
+
+Thu Jan 8 11:20:01 2004 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * eval.c, object.c, process.c, re.c: don't use C++ style comments.
+
+Thu Jan 8 04:36:21 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb (WEBrick::CGI#initialize): should create
+ @config[:Logger] if it was not given.
+
+ * sample/webrick/*: new files.
+
+ * MANIFEST: add sample/webrick/*
+
+Wed Jan 7 13:00:18 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_driver.rb: Fix problem where ri was
+ being too eager to find matches of ambiguous method
+ names (such as "ri Thread.join" would return both
+ Thread.join and ThreadsWait.join)
+
+Wed Jan 7 12:35:41 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/debug.rb: revert command parse regexps. [ruby-list:39014] by
+ Shirai,Kaoru.
+
+Wed Jan 7 08:21:04 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parserfactory.rb: Check for shebang
+ line in files that would otherwise be treated as
+ plain text.
+
+Tue Jan 6 22:13:34 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_mod_modfunc): should break if m has no super class.
+ [ruby-dev:22498]
+
+Tue Jan 6 21:55:02 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (fptr_finalize): should save errno just after failure.
+ [ruby-dev:22492]
+
+Tue Jan 6 14:53:14 2004 Dave Thomas <dave@pragprog.com>
+
+ * bin/ri: split out the display side, making it pluggable. Added
+ new ri_driver and ri_display files in lib/rdoc/ri.
+
+Tue Jan 6 06:37:53 2004 Dave Thomas <dave@pragprog.com>
+
+ * bin/rdoc: Add --ri-system switch
+
+ * lib/.document: Update with list of files that seem to have
+ documentation
+
+ * lib/test/unit.rb: Reorder comment to make it RDoc friendly.
+
+ * Makefile.in: add install-nodoc target, and make it
+ generate RDoc on default install.
+
+ * lib/rdoc/ri/ri_options.rb (RI::Options::parse): Add
+ --doc-dir option to ri.
+
+Tue Jan 6 00:04:40 2004 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method_or_yield_parameters):
+ fix parsing if there are braces in a method parameter list
+
+Fri Jan 2 14:54:11 2004 Dave Thomas <dave@pragprog.com>
+
+ * bin/ri: Add new --classes option, and arrange for
+ help messages to be paged too.
+
+ * bin/rdoc: Add statistics.
+
+ * process.c: (MG) Added Process documentation
+
+ * lib/rdoc/ri/ri_formatter.rb (RI::AttributeFormatter::wrap):
+ Fix problem with labels not displaying in RI labeled
+ lists using BS and ANSI modes.
+
+Fri Jan 2 01:50:13 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (argf_eof): ARGF.eof? should not have any side effect.
+ [ruby-dev:22469]
+
+Wed Dec 31 17:25:17 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (argf_each_byte): should return self. [ruby-dev:22465]
+
+Wed Dec 31 11:20:34 2003 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::do_methods): Make
+ file referenced in "// in sss.c" relative to current file.
+
+Wed Dec 31 11:17:37 2003 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/generators/html_generator.rb: Fix problem when
+ a public method was aliased, but the alias is then
+ made private, and hence doesn't appear in RDoc output.
+
+Wed Dec 31 01:33:05 2003 Dave Thomas <dave@pragprog.com>
+
+ * array.c, error.c, eval.c, io.c, prec.c, range.c, re.c,
+ string.c, time.c: Add RDoc for Kernel functions, and tidy.
+
+Tue Dec 30 19:39:14 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_f_readline): should raise EOFError at the end of
+ files. [ruby-dev:22458]
+
+ * io.c (argf_read): should concatenate input files when length
+ argument is nil. [ruby-dev:22450]
+
+ * io.c (argf_read): should update supplied string buffer (2nd
+ argument) even when IO#read is called multiple times.
+
+ * io.c: should initialize lineno by zero. [ruby-dev:22460]
+
+Tue Dec 30 12:30:30 2003 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/code_objects.rb (RDoc::Context::find_symbol): If a
+ class and a method have the same name, finding Xxx.abc was trying
+ to find 'abc' in method 'Xxx', not class 'Xxx'.
+
+Tue Dec 30 08:32:32 2003 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method):
+ Handle undoing nesting of yield parameters correctly for:
+
+ def each_entry(&b) Dir.foreach(@path) {|f| yield P.new(f) } end
+
+Tue Dec 30 08:32:32 2003 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method):
+ Handle undoing nesting of yield parameters correctly for:
+
+ def each_entry(&block) Dir.foreach(@path) {|f| yield Pathname.new(f) } end
+
+Mon Dec 29 12:51:02 2003 Dave Thomas <dave@pragprog.com>
+
+ * eval.c: Add RDoc for Kernel global functions.
+
+Mon Dec 29 11:00:16 2003 Dave Thomas <dave@pragprog.com>
+
+ * array.c: Tidy up RDoc loose ends.
+
+Mon Dec 29 05:05:51 2003 Dave Thomas <dave@pragprog.com>
+
+ * struct.c, random: Add RDoc comments
+
+Mon Dec 29 02:20:54 2003 Dave Thomas <dave@pragprog.com>
+
+ * eval.c: Add RDoc for class Proc, Method, UnboundMethod
+
+Mon Dec 29 00:41:44 2003 Dave Thomas <dave@pragprog.com>
+
+ * math.c: Add RDoc comments
+
+Sun Dec 28 20:19:11 2003 Tanaka Akira <akr@m17n.org>
+
+ * ext/stringio/stringio.c (strio_sysread): StringIO.new.sysread didn't
+ raise EOFError.
+
+ * ext/zlib/zlib.c (gzreader_gets): don't increment lineno when
+ gzfile_read_all returns "".
+
+Sun Dec 28 15:25:08 2003 Dave Thomas <dave@pragprog.com>
+
+ * class.c,object.c,parse.y,sprintf.c,variable.c: Document classes
+ Object, Module, etc...
+
+Sun Dec 28 11:55:29 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/csv/test_csv.rb: generate bom.csv and mac.csv files on the fly.
+ [ruby-talk:88852]
+
+ * test/csv/{bom.csv,mac.csv}: removed.
+
+Sun Dec 28 08:56:51 2003 Dave Thomas <dave@pragprog.com>
+
+ * eval.c: Thead[Group] RDoc (thanks to MG)
+
+Sun Dec 28 03:50:05 2003 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::find_override_comment):
+ Escape method names used in regexp
+
+Sun Dec 28 01:46:02 2003 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/ri/ri_formatter.rb (RI::TextFormatter::display_flow_item):
+ Add support for rules in 'ri' output.
+
+Sun Dec 28 01:35:35 2003 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::find_body):
+ Sometimes the Ruby source aliases two otherwise
+ unrelated methods (for example Kernel#object_id and
+ Kernel#hash are both the same C function). Provide a
+ facility to allow the methods to be documented
+ separately.
+
+Sun Dec 28 01:05:31 2003 Dave Thomas <dave@pragprog.com>
+
+ * marshal.c, signal.c: RDoc collemts added by Elliott Hughes
+
+Sun Dec 28 00:48:47 2003 Dave Thomas <dave@pragprog.com>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::find_class_comment):
+ Some source files use lower case class or module names
+ when naming the Init_XXX function in C.
+
+Sat Dec 27 23:41:46 2003 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: fix "test: too many arguments" error.
+
+Sat Dec 27 15:32:19 2003 Dave Thomas <dave@wireless_3.local.thomases.com>
+
+ * time.c: RDoc comments added
+
+Sat Dec 27 15:07:57 2003 Dave Thomas <dave@pragprog.com>
+
+ * object.c: Add RDoc comments for Symbol class.
+
+Sat Dec 27 14:42:30 2003 Dave Thomas <dave@pragprog.com>
+
+ * numeric.c: Add RDoc comments.
+
+Sat Dec 27 00:44:00 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (next_argv): warn always for stdin on inplace edit mode.
+
+ * io.c (read_all): need to check string value.
+
+ * io.c (argf_read): allow ARGF.read(nil). [ruby-dev:22433]
+
+Fri Dec 26 23:02:09 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_f_backquote): need not to check nil result.
+ [ruby-core:02078]
+
+ * io.c (rb_io_getline): should return nil when read_all gives
+ empty string, even when nil rs is specified. [ruby-core:02077]
+
+Fri Dec 26 18:50:59 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: check if getcontext and setcontext are available.
+
+ * eval.c: use presence of getcontext/setcontext.
+
+Fri Dec 26 16:40:53 2003 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb (PathnameTest#test_plus): add 2 assertions.
+
+Fri Dec 26 09:26:58 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_pack): add sign check for 'i', and 'l'.
+ [ruby-dev:22427]
+
+ * bignum.c (rb_quad_pack): add range check for 'quad int'.
+
+Thu Dec 25 22:39:59 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * string.c (rb_str_update): don't return any value.
+
+Thu Dec 25 15:30:17 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_update): call rb_str_modify().
+
+Thu Dec 25 05:08:09 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (search_required): search actual file name once when no
+ extension specified.
+
+Thu Dec 25 04:00:44 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.8.1 released.
+
+Thu Dec 25 00:17:53 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in: check for nanosleep, -lrt if required.
+ [ruby-core:02059]
+
+ * eval.c (thread_timer): use select(2) if nanosleep(2) is not
+ available.
+
+ * eval.c: check __stub_getcontext for glibc on some platforms.
+ [ruby-list:38984]
+
+Wed Dec 24 23:48:04 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/soap/test_basetype.rb, test/soap/marshal/test_marshal.rb
+ test/xsd/test_xsd.rb: use "(-1.0 / (1.0 / 0.0))" instead of "-0.0"
+ to express -0.0. [ruby-talk:88786]
+
+Wed Dec 24 23:29:30 2003 Tanaka Akira <akr@m17n.org>
+
+ * lib/tsort.rb (test_orphaned_break): removed.
+
+Wed Dec 24 20:53:06 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/tkmulticolumnlist.rb: new sample
+
+ * ext/tk/sample/tkmultilistframe.rb: bug fix
+
+Wed Dec 24 20:37:37 2003 Eric Sunshine <sunshine@sunshineco.com>
+
+ * configure.in (LDSHARED): Fixed typographical error in assignment of
+ LDSHARED for Rhapsody which caused linking of extension modules to
+ fail.
+
+Wed Dec 24 17:51:18 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * file.c (rb_thread_flock): enable thread support again.
+
+Wed Dec 24 16:46:08 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (catch_timer): do not call rb_thread_schedule() inside to
+ avoid pthread_mutex_lock() deadlock. interrupts to system calls
+ are detected by TRAP_END via EINTR error.
+
+ * eval.c (thread_timer): do not post signal unless it is
+ absolutely necessary.
+
+ * rubysig.h (TRAP_END): add CHECK_INTS to switch thread.
+
+ * regex.c (re_compile_pattern): check if nextp is smaller than
+ pend. [ruby-dev:22372]
+
+ * eval.c (umethod_bind): remove method overridden check.
+ [ruby-dev:22366]
+
+Wed Dec 24 16:13:05 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ssl.c (ossl_ssl_read): should check for error
+ status by SSL_get_error().
+
+ * ext/openssl/ossl_ssl.c (ossl_ssl_write): ditto.
+
+Wed Dec 24 14:23:27 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_read): clear the buffer argument
+ when returning nil. [ruby-dev:22363]
+
+ * test/ruby/ut_eof.rb (TestEOF::test_eof_0, TestEOF::test_eof_1):
+ add buffer argument tests.
+
+Wed Dec 24 14:07:55 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/assertions.rb: Modules are allowed to rescue.
+
+ * lib/test/unit/autorunner.rb: show output_level in order.
+
+ * lib/test/unit/collector/dir.rb: get rid of successive same
+ directories in load path.
+
+ * test/testunit/test_assertions.rb (test_assert_nothing_raised,
+ test_assert_raise): test for modules.
+
+Wed Dec 24 13:43:34 2003 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (authenticate): remove "\n" from base64 encoded
+ strings.
+
+Wed Dec 24 11:26:41 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/fileutils/test_fileutils.rb: should not create any
+ files or directories in current directory. [ruby-talk:88724]
+
+Wed Dec 24 10:29:53 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_read): never return nil at
+ unlimited read. [ruby-dev:22334]
+
+ * ext/stringio/stringio.c (strio_read): support second
+ argument. [ruby-dev:22350]
+
+Wed Dec 24 09:38:49 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (arg): should return 0 after error. [ruby-dev:22360]
+
+Wed Dec 24 00:56:54 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (read_all): do not return nil at the end of file.
+ [ruby-dev:22334]
+
+ * io.c (argf_read): do not depend on nil at eof behavior of
+ IO#read().
+
+ * eval.c (rb_thread_join): dup exception before re-raising it.
+
+ * io.c (rb_io_eof): call clearerr() to prevent side effect. this
+ patch is supplied by Masahiro Sakai <sakai@tom.sfc.keio.ac.jp>.
+ [ruby-dev:22234]
+
+ * pack.c (OFF16): get offset for big endian machines.
+
+ * pack.c (pack_pack): use OFF16 instead of OFF16B.
+ [ruby-dev:22344]
+
+ * pack.c (pack_unpack): ditto.
+
+Tue Dec 23 22:47:14 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_check_readable): set FMODE_RBUF always, even if
+ NEED_IO_SEEK_BETWEEN_RW is not defined. [ruby-dev:22340]
+
+ * io.c (rb_io_check_writable): clear FMODE_RBUF before writing
+ something.
+
+Tue Dec 23 22:25:00 2003 Gavin Sinclair <gsinclair@soyabean.com.au>
+
+ * lib/optparse.rb: incomplete RDoc documentation added in place of
+ existing RD comments. Tabs converted to spaces.
+
+Tue Dec 23 19:44:47 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/soap/test_streamhandler.rb (test_basic_auth): removed.
+ soap4r + basic_auth is not officially supported in ruby/1.8.1 even
+ though soap4r + basic_auth + http-access2 should run fine.
+
+Tue Dec 23 19:42:59 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_ungetc): raise an exception at unread stream to
+ avoid unspecified behavior. [ruby-dev:22330]
+
+ * test/ruby/test_system.rb (test_syntax): glob relatively from
+ __FILE__.
+
+Tue Dec 23 18:09:40 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_pack): remove unnecessary negative value check.
+ [ruby-dev:22329]
+
+Tue Dec 23 17:26:55 2003 KONISHI Hiromasa <konishih@fd6.so-net.ne.jp>
+
+ * bcc32/Makefile.sub (config.h): bcc has finite(). [ruby-list:38940]
+
+Tue Dec 23 16:08:16 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/rexml/encodings/US-ASCII.rb: typo. [ruby-talk:88650]
+
+ * test/ruby/test_system.rb: num of asserts depended on running dir.
+
+ * test/xsd/test_noencoding.rb: rexml + without iconv/uconv cannot
+ handle euc-jp. install iconv, uconv or xmlscan.
+
+Tue Dec 23 14:13:51 2003 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/generic.rb (URI::Generic::check_userinfo,
+ URI::Generic::check_user, URI::Generic::check_password): tests
+ conflicts/depends with other components closely.
+
+ * test/uri/test_generic.rb (TestGeneric::test_set_component):
+ added tets.
+
+Tue Dec 23 11:08:34 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/xsd/test_noencoding.rb: rescue Errno::EINVAL and do not test.
+ "euc-jp" might not be in supported encoding name list.
+ [ruby-talk:88650]
+
+Tue Dec 23 06:10:31 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb (CGI): add support for mod_ruby.
+
+ * lib/webrick/cgi.rb (CGI::Socket): add check for existence of
+ OpenSSL module in all HTTPS related methods.
+
+ * lib/webrick/cgi.rb (CGI::Socket#cipher): should create similar
+ value to OpenSSL::SSLSocket#cipher.
+
+ * lib/webrick/httpresponse.rb (HTTPResponse#setup_header): should
+ set "connection: close" if @keep_alive is false.
+
+ * lib/webrick/https.rb (HTTPrequest#meta_vars): add supprt for
+ SSL_PROTOCOL, SSL_CIPHER_USEKEYSIZE and SSL_CIPHER_ALGKEYSIZE.
+
+Mon Dec 22 23:00:05 2003 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/generic.rb (URI::Generic::check_opaque): fixed typo.
+
+Mon Dec 22 21:59:24 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (map_charset): always ensure code is a String.
+
+Mon Dec 22 21:15:29 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * class.c (rb_mod_init_copy): always copy singleton class.
+ [ruby-dev:22325]
+
+Mon Dec 22 20:44:36 2003 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/generic.rb (URI::Generic#route_from): accepts urls which
+ has no host-part.
+
+ * test/uri/test_generic.rb (TestGeneric::test_route): added a test.
+
+Mon Dec 22 20:38:44 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/cgi.rb: reduce eval.
+
+ * lib/cgi.rb (CGI::QueryExtension::read_multipart): alias path to
+ local_path. [ruby-list:38883]
+
+Mon Dec 22 20:09:31 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/soap/test_property.rb: remove duplicated test method.
+
+Mon Dec 22 18:22:04 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * bcc32/Makefile.sub, win32/Makefile.sub (config.h): remove
+ HAVE_ISINF definition to follow previous commits of missing.h
+ and win32/win32.h.
+
+Mon Dec 22 17:23:42 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (ac_cv_func_setitimer): moved from defines.h
+
+ * defines.h, rubysig.h, signal.c: removed macro handling which
+ should be done in configure.
+
+ * configure.in (intrinsics.h): check if present.
+
+ * ruby.h: include intrinsics.h if available.
+
+ * bignum.c, marshal.c: include ieeefp.h if available.
+
+ * missing.h (isinf): define as a macro if finite() and isnan()
+ are available. [ruby-core:02032]
+
+Mon Dec 22 17:07:31 2003 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (mingw): set isnan, finite and isinf to yes.
+
+Mon Dec 22 13:40:19 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/soap/property.rb: passing block by reference.
+
+Mon Dec 22 00:32:43 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_with_disable_interrupt): use ENABLE_INTS instead of
+ ALLOW_INTS which may switch context. [ruby-dev:22319]
+
+ * ext/syck/emitter.c (syck_emitter_write): str bigger than
+ e->bufsize causes buffer overflow. [ruby-dev:22307]
+
+Sun Dec 21 17:29:00 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * class.c (rb_check_inheritable): new function. [ruby-dev:22316]
+
+ * intern.h: add prototype.
+
+ * eval.c (superclass): use rb_check_inheritable().
+
+ * object.c (rb_class_initialize): check argument validity.
+
+Sun Dec 21 16:25:10 2003 Tanaka Akira <akr@m17n.org>
+
+ * lib/pathname.rb (Pathname#+): re-implemented to resolve ".." in
+ beginning of the argument.
+ (Pathname#join): concatenate from the last argument.
+ (Pathname#parent): just use Pathname#+.
+
+Sun Dec 21 00:12:37 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: add new methods (TkScrollbar#assign, assign_list)
+
+ * ext/tk/sample/tkmultilistframe.rb: use TkScrollbar#assign method
+
+Sat Dec 20 21:59:03 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httprequest.rb (HTTPRequest#meta_vars): refine regexp.
+
+ * lib/webrick/cgi.rb (CGI#start): NPH scripts return status line
+ instead of Status: header field.
+
+ * lib/webrick/cgi.rb (CGI::Socket): refine some coditions.
+
+Sat Dec 20 16:07:14 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::Completion::complete): wrong
+ Regexp for word boundary. pointed out by Gavin Sinclair.
+
+ * lib/optparse.rb (OptionParser::make_switch): [no-] prefix was
+ missing.
+
+Sat Dec 20 11:40:10 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/yaml.rb (YAML::YAML): adjust Marshal version.
+
+Sat Dec 20 03:56:02 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_with_disable_interrupt): prohibit thread context
+ switch during proc execution. [ruby-dev:21899]
+
+Sat Dec 20 02:41:02 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cgi.rb: add file. (yet another CGI library)
+
+ * MANIFEST: add lib/webrick/cgi.rb.
+
+Sat Dec 20 02:18:31 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-calculate-indent): proper indentation
+ inside of parentheses. [ruby-dev:22308]
+
+Fri Dec 19 21:24:22 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httprequest.rb (HTTPRequest#meta_vars): should not set
+ HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH.
+
+ * lib/webrick/https.rb (HTTPRequest#parse): should check presence
+ of cert() method to detect SSLSocket.
+
+Fri Dec 19 22:56:46 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/soap/property.rb (SOAP::Property#load): new method for loading
+ property value into existing property tree.
+
+ * test/soap/test_property.rb: add test.
+
+Fri Dec 19 19:21:49 2003 akira yamada <akira@ruby-lang.org>
+
+ * lib/runit/cui/testrunner.rb (RUNIT::CUI::TestRunner::run):
+ should use Test::Unit::UI::{PROGRESS_ONLY,VERBOSE}.
+
+Fri Dec 19 17:36:49 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/tkmultilistbox.rb: bug fix
+
+ * ext/tk/sample/tkmultilistframe.rb: new sample script
+
+Fri Dec 19 03:44:27 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httputils.rb (parse_form_data): should return an
+ empty Hash if the body is empty.
+
+Thu Dec 18 21:47:35 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): should remove deffile if it's
+ made by miniruby. based on nobu's patch.
+
+Thu Dec 18 21:44:21 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * eval.c (stack_extend): ignore inline optimization on VC7.
+
+ * win32/Makefile.sub (OS, RT): can override.
+
+ * win32/Makefile.sub (LDFLAGS): ditto. shouldn't use pdb:none
+ option. based on Tietew's patch [ruby-dev:22289]
+
+Thu Dec 18 16:38:44 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (fnmatch): unlike find_dirsep(), rb_path_next() never
+ return NULL.
+
+Thu Dec 18 15:27:59 2003 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/ipaddr.rb (IPSocket::getaddress): merge usa's patch.
+ [ruby-dev:21678]
+
+Wed Dec 17 15:15:30 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::QueryExtension::Value::[]): should work like
+ String#[] if more than one arguments are specified.
+
+ * lib/delegate.rb: avoid using common instance name as "@obj".
+
+ * lib/cgi.rb (CGI::QueryExtension::Value): Value is no longer
+ subclass of String, but DelegateClass(String).
+
+ * ext/curses/extconf.rb: restore function check for init_color.
+ [ruby-list:38905]
+
+ * Makefile.in: need to specify $(MAINLIBS) for the miniruby
+ generation rule.
+
+ * configure.in: better FreeBSD -lc_r support.
+
+Wed Dec 17 00:16:14 2003 Minero Aoki <aamine@loveruby.net>
+
+ * ext/strscan/strscan.c: new method
+ StringScanner#beginning_of_line? (alias #bol?)
+
+ * ext/strscan/strscan.c: new method StringScanner#concat and #<<.
+
+ * ext/strscan/strscan.c: StringScanner#new(str) does not duplicate
+ nor freeze STR (allow destructive modification).
+
+ * test/strscan/test_stringscanner.rb: test new methods above.
+
+ * test/strscan/test_stringscanner.rb: test destructive string
+ modification.
+
+Tue Dec 16 21:20:47 2003 Tanaka Akira <akr@m17n.org>
+
+ * lib/pp.rb: don't use local variable `pp'.
+
+ * lib/prettyprint.rb: ditto.
+
+Tue Dec 16 13:20:43 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: condition bug of if statement on
+ {pack,grid}_propagate methods
+
+Tue Dec 16 03:17:29 2003 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/yaml/rubytypes.rb: comments in strings. [ruby-talk:88012]
+
+ * test/yaml/test_yaml.rb: add test.
+
+Tue Dec 16 01:14:44 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (catch_timer): check rb_thread_crtical in main native
+ thread.
+
+ * eval.c (thread_timer): just sends signals periodically, to
+ prevent main native thread from receiving them in critical
+ section. [ruby-core:01959]
+
+Mon Dec 15 13:32:22 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (check_dirname): check string safety and remove extraneous
+ trailing directory separators. [ruby-dev:22279]
+
+ * file.c: renamed and externalized rb_path_next,
+ rb_path_skip_prefix, rb_path_last_separator, rb_path_end.
+
+ * intern.h: prototypes for rb_path_next, rb_path_skip_prefix,
+ rb_path_last_separator, rb_path_end.
+
+Mon Dec 15 09:27:46 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/openssl/ossl_pkcs12.c (ossl_pkcs12_initialize): first argument
+ of rb_protect should take an argument of VALUE.
+
+Sun Dec 14 18:46:48 2003 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/socket/socket.c (Init_socket): IPv6 is not supported although
+ AF_INET6 is defined on MinGW.
+
+ * lib/ipaddr.rb (AF_INET6): workaround in the environment which does
+ not support IPv6.
+
+Sat Dec 13 18:55:16 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/charset_alias.rb: preserve original order.
+
+ * ext/iconv/extconf.rb: remove wrapper file at clean.
+
+Sat Dec 13 18:09:42 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (thread_timer): use timer by sub-thread and nanosleep.
+ [ruby-talk:87519]
+
+ * gc.c (Init_stack): no stack adjustment for THREAD_SAFE.
+
+Sat Dec 13 17:17:59 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (proc_alloc): cache the created object at first time.
+ [ruby-talk:61288], [ruby-dev:22240]
+
+Sat Dec 13 09:01:23 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: check ucontext.h.
+
+ * eval.c: use getcontext/setcontext() instead of setjmp/longjmp()
+ on ia64 or with native thread enabled. [ruby-core:01932]
+
+Sat Dec 13 03:09:14 2003 why the lucky stiff <why@ruby-lang.org>
+
+ * lib/yaml/rubytypes.rb: anonymous struct fix. [ruby-core:01946]
+
+ * test/yaml/test_yaml.rb: add test.
+
+Fri Dec 12 22:36:44 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/csv.rb: add Cell#to_str and Cell#to_s for /.../ =~ aCell,
+ "#{aCell}" and so on.
+
+ * test/csv/test_csv.rb: add tests.
+
+Fri Dec 12 19:33:06 2003 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (mkdir): remove trailing `/' from pathes.
+
+ * lib/fileutils.rb (rmdir): ditto. [ruby-dev:22238]
+
+ * lib/fileutils.rb (rmdir_r): ditto.
+
+ * lib/fileutils.rb (fu_copy_dir): check if it is a directory after
+ mkdir(2).
+
+Fri Dec 12 06:06:09 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (proc_invoke): fix class name in warning message for
+ define_method. [ruby-dev:22235]
+
+Thu Dec 11 21:24:43 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_pkcs12.[ch]: new files. add OpenSSL::PKCS12.
+
+ * ext/openssl/ossl.[ch]: ditto.
+
+ * ext/openssl/MANIFEST: add ossl_pkcs12.[ch].
+
+Thu Dec 11 20:54:28 2003 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (mkdir_p): remove trailing `/' befere mkdir(2).
+ mkdir("nonexistdir/") does not work on NetBSD/Alpha 1.6.1.
+
+ * lib/fileutils.rb (fu_list): call to_str for all arguments.
+
+Thu Dec 11 20:07:01 2003 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/ftools.rb (makedirs): sync with fileutils.
+
+Thu Dec 11 19:53:03 2003 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (mkdir_p): catch all SystemCallErrors.
+ (mkdir("C:\") causes EACCESS on Windows 2000/NTFS)
+
+Thu Dec 11 19:08:02 2003 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (mkdir_p): check if it is a directory after
+ mkdir(2) instead of before mkdir(2), to avoid race condition.
+ [ruby-talk:87730]
+ Refer: mkinstalldirs sh script, GNU mkdir(1) (coreutils 5.0)
+
+Thu Dec 11 18:49:30 2003 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb: def m( arg ) -> def m(arg).
+
+Thu Dec 11 11:39:43 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (ieeefp.h), numeric.c: needed for finite() on
+ Solaris. [ruby-core:01921]
+
+ * file.c (rb_stat_inspect): adjust format specifier.
+
+ * parse.c (arg_prepend): nodetype() is for debug use.
+
+ * ruby.h (ISASCII, etc): cast to int to get rid of warning.
+
+ * ruby.h (alloca.h): include even in GCC. [ruby-core:01925]
+
+ * ext/bigdecimal/bigdecimal.c (GetVpValue): adjust format
+ specifier.
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_prec, BigDecimal_coerce,
+ BigDecimal_divmod): use rb_assoc_new() to suppress memory usage.
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_split): ditto.
+
+ * ext/dl/sym.c (rb_dlsym_guardcall): guard itself should be
+ volatile.
+
+ * ext/iconv/iconv.c (iconv_convert): ensure actual parameter with
+ format specifier.
+
+ * ext/pty/pty.c (MasterDevice, SlaveDevice, deviceNo): do not
+ define unless used.
+
+ * ext/pty/pty.c (getDevice): get rid of warning.
+
+ * ext/socket/socket.c (port_str, sock_s_getaddrinfo,
+ sock_s_getnameinfo): FIX2INT() now returns long.
+
+ * ext/socket/socket.c (init_inetsock_internal): uninitialized
+ variable.
+
+ * ext/syck/rubyext.c (syck_parser_assign_io): add prototype.
+
+ * ext/syck/rubyext.c (rb_syck_mktime, yaml_org_handler): use
+ ISDIGIT() instead of isdigit() to avoid warnings and for
+ platforms which don't support non-ascii charater.
+
+Wed Dec 10 19:28:56 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_read): set EOF flag at short read.
+ [ruby-dev:22223], [ruby-dev:22224]
+
+Wed Dec 10 18:07:25 2003 Minero Aoki <aamine@loveruby.net>
+
+ * lib/erb.rb: new method ERB#filename(=). [ruby-dev:22208]
+
+Wed Dec 10 17:54:51 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_read): do not set EOF flag when
+ requested length is zero. [ruby-dev:22214]
+
+Wed Dec 10 17:17:18 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (read_all): should return given string even if data read is
+ empty. [ruby-dev:22207]
+
+Wed Dec 10 17:16:06 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_read): adjust behavior at reading
+ beyond EOF to IO. [ruby-dev:22205]
+
+ * test/ruby/ut_eof.rb (TestEOF::Seek): test behaviors at reading
+ beyond EOF.
+
+ * test/ruby/test_file.rb, test/stringio/test_stringio.rb: include
+ TestEOF::Seek test case.
+
+Wed Dec 10 15:01:19 2003 Shugo Maeda <shugo@ruby-lang.org>
+
+ * test/monitor/test_monitor.rb (test_cond): use Queue#deq
+ instead of sleep.
+
+Wed Dec 10 14:45:39 2003 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/pty/pty.c (HAVE_SYS_IOCTL_H): need to include <sys/ioctl.h>
+ for TIOCSCTTY on *BSD. based on gotoyuzo's patch.
+ (ruby-bugs:PR#1211)
+
+ * ext/pty/pty.c (establishShell): should close descriptors if fork
+ failed.
+
+Wed Dec 10 12:53:05 2003 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.h: define execv() using do_aspawn().
+
+ * process.c (proc_exec_v): remove #ifdef's which stopped needing.
+
+Tue Dec 9 23:32:23 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tkcanvas.rb, ext/tk/lib/tkdialog.rb,
+ ext/tk/lib/tkentry.rb, ext/tk/lib/tkscrollbox.rb, ext/tk/lib/tktext.rb,
+ ext/tk/sample/tkalignbox.rb, ext/tk/sample/tkcombobox.rb,
+ ext/tk/sample/tkmultilistbox.rb, ext/tk/sample/tkoptdb.rb, ext/tk/sample/tktextframe.rb,
+ ext/tk/sample/demos-en/dialog1.rb, ext/tk/sample/demos-en/dialog2.rb,
+ ext/tk/sample/demos-jp/dialog1.rb, ext/tk/sample/demos-jp/dialog2.rb:
+ overrided instance methods, which are private methods on the super
+ class, are changed to 'private'
+
+Tue Dec 9 19:53:02 2003 akira yamada <akira@ruby-lang.org>
+
+ * lib/uri/generic.rb (URI::Generic#route_from0): make case insensitive
+ for host-part.
+
+ * test/uri/test_generic.rb (test_route): added tests for the above
+ change.
+
+Tue Dec 9 14:10:48 2003 Tanaka Akira <akr@m17n.org>
+
+ * io.c (rb_io_check_readable): don't call io_seek if EOF flag is set,
+ to avoid clearing EOF flag.
+ (rb_io_check_writable): ditto.
+
+Tue Dec 9 02:53:55 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/tkalignbox.rb: new sample script
+
+Tue Dec 9 00:45:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
+
+ * lib/test/unit/assertions.rb: renamed #assert_raises to #assert_raise
+ and made the former call the latter. [ruby-core:01890]
+
+ * test/testunit/test_assertions.rb: ditto.
+
+Tue Dec 9 00:07:35 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/soap/rpc/standaloneServer.rb: add 'shutdown' and 'status'
+ methods as delegates to WEBrick.
+
+ * test/soap/calc/{test_calc.rb,test_calc2.rb},
+ test/soap/helloworld/test_helloworld.rb,
+ test/wsdl/datetime/test_datetime.rb, test/wsdl/raa/test_raa.rb:
+ follow the change.
+
+Mon Dec 8 22:48:03 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/autorunner.rb: remove dependency to a particular
+ runner. [ruby-core:01901], [ruby-list:38869]
+
+ * lib/test/unit/ui/testrunnerutilities.rb: moved output level
+ constants from Console.
+
+ * lib/test/unit/ui/console/testrunner.rb: ditto.
+
+ * lib/test/unit/ui/{fox,gtk,gtk2,tk}/testrunner.rb (initialize):
+ accept output_level.
+
+Mon Dec 8 15:03:30 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/syck/syck.c (syck_io_str_read): get rid of buffer overflow.
+
+Mon Dec 8 13:02:11 2003 Minero Aoki <aamine@loveruby.net>
+
+ * lib/uri/common.rb: new method URI.regexp. [ruby-dev:22121]
+
+ * test/uri/test_common.rb: add test for URI.regexp.
+
+Mon Dec 8 12:44:14 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c: define swap16 and swap32 only if they are not
+ defined. OpenBSD defines these macros. [ruby-dev:22181]
+
+Sun Dec 7 20:54:17 2003 Tanaka Akira <akr@m17n.org>
+
+ * ext/iconv/iconv.c (map_charset): make case sensitive.
+ ext/iconv/charset_alias.rb (charset_alias): don't ignore
+ config.charset's information. sort aliases.
+
+Sat Dec 6 22:58:03 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ssl.c (ossl_start_ssl): new function to wrap
+ SSL_connect and SSL_accept; if SSL_connect (or SSL_accept) returned
+ but not finished the handshake process, we should retry it.
+
+ * ext/openssl/ossl_ssl.c (ossl_ssl_connect): call ossl_start_ssl.
+
+ * ext/openssl/ossl_ssl.c (ossl_ssl_accept): ditto.
+
+ * ext/openssl/ossl_ssl.c (ossl_ssl_read): allow signal traps.
+
+Sat Dec 6 21:45:10 2003 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * io.c (flush_before_seek): flush before seek on any platform.
+
+ * configure.in: ditto.
+
+Sat Dec 6 17:23:00 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/soap/soap.rb(SOAP::Env.getenv): allow upcase environment variable
+ as well as downcase one.
+
+ * lib/soap/netHttpClient.rb(SOAP::NetHttpClient#proxy=): check URI.
+
+Fri Dec 5 23:22:30 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/assertions.rb (Test::Unit::Assertions::assert_raises,
+ Test::Unit::Assertions::assert_nothing_raised): use the last
+ argument as message unless class object.
+
+ * test/testunit/test_assertions.rb (test_assert_raises): test for
+ multiple exception list. [ruby-core:01891]
+
+ * test/testunit/test_assertions.rb (test_assert_nothing_raised): test
+ for non-exception classes.
+
+Fri Dec 5 22:23:04 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * lib/soap/netHttpClient.rb: proxy support did not work. fixed.
+
+ * lib/soap/property.rb: add class methods for loading property from
+ stream/file/propertyfile. propertyfile is a file which is located at
+ somedir in $:.
+
+ * lib/soap/soap.rb, lib/soap/wsdlDriver.rb, lib/soap/rpc/driver.rb,
+ lib/wsdl/importer.rb: load property from propertyfile 'soap/property'
+ e.g. /usr/local/lib/ruby/site_ruby/1.8/soap/property.
+
+ * test/soap/test_property.rb, test/soap/test_streamhandler.rb: new file.
+
Fri Dec 5 17:26:23 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (rb_exec_end_proc): maintain tmp_end_procs.
@@ -176,7 +19967,7 @@ Tue Dec 2 21:31:42 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* test/runner.rb: exit with the test result.
-Tue Dec 2 20:18:48 2003 Eric Sunshine <sunshine@sunshineco.com>
+Tue Dec 2 20:18:48 2003 Eric Sunshine <sunshine@sunshineco.com>
* configure.in (AC_PROG_YACC): AC_DEFINE(OLD_YACC) if Yacc is found
instead of Bison or byacc.
@@ -239,7 +20030,7 @@ Mon Dec 1 14:17:49 2003 Minero Aoki <aamine@loveruby.net>
* test/fileutils/test_fileutils.rb: does much strict test on
"same" files detecting.
-Mon Dec 1 09:28:14 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Mon Dec 1 09:28:14 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub
(XCFLAGS): re-export $(XCFLAGS).
@@ -323,7 +20114,7 @@ Fri Nov 28 19:37:56 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* test/ruby/test_env.rb (test_has_value, test_index): condition for
aboves.
-Fri Nov 28 17:59:20 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Fri Nov 28 17:59:20 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* test/ruby/test_env.rb: add tests for ENV.
@@ -409,7 +20200,7 @@ Wed Nov 26 00:55:30 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* lib/webrick/httpserver.rb (HTTPServer#run): should pass the
request's keep_alive flag to the response.
-Tue Nov 25 21:41:35 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Tue Nov 25 21:41:35 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* defines.h (ENV_IGNORECASE): should define when DOSISH without
human68k. [ruby-dev:22047]
@@ -550,7 +20341,7 @@ Mon Nov 24 17:00:00 2003 Tanaka Akira <akr@m17n.org>
* lib/open-uri.rb: validate option names.
:content_length_proc and :progress_proc option implemented.
-Mon Nov 24 14:53:10 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Mon Nov 24 14:53:10 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub
(XCFLAGS): output empty value instead of `-DRUBY_EXPORT'.
@@ -573,12 +20364,12 @@ Sat Nov 22 22:48:46 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tcltklib/tcltklib.c: add native thread check
-Sat Nov 22 18:49:47 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Sat Nov 22 18:49:47 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/curses/curses.c (window_nodelay): nodelay() of NetBSD's
libcruses returns no value, just like keypad().
-Sat Nov 22 17:36:36 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Sat Nov 22 17:36:36 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub
(HAVE_GETCWD): output to config.h.
@@ -687,7 +20478,7 @@ Wed Nov 19 14:32:08 2003 Minero Aoki <aamine@loveruby.net>
* lib/fileutils.rb (cannot_overwrite_file?): add wince.
-Wed Nov 19 11:04:47 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Wed Nov 19 11:04:47 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* lib/fileutils.rb (cannot_overwrite_file?, have_st_ino?): bccwin32
is same as mswin32.
@@ -788,7 +20579,7 @@ Sun Nov 16 13:26:07 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* marshal.c (w_object): LINK check earlier than anything else,
i.e. do not dump TYPE_IVAR for already dumped objects.
- (ruby-bugs PR#1220)
+ (ruby-bugs:PR#1220)
* eval.c (rb_eval): call "inherited" only when a new class is
generated; not on reopening.
@@ -802,7 +20593,7 @@ Sun Nov 16 12:16:10 2003 Minero Aoki <aamine@loveruby.net>
* lib/net/protocol.rb: logging response body. [experimental]
[ruby-list:38800]
-Sun Nov 16 10:49:38 2003 Gavin Sinclair <gsinclair@soyabean.com.au>
+Sun Nov 16 10:49:38 2003 Gavin Sinclair <gsinclair@soyabean.com.au>
* lib/thread.rb (Thread.exclusive): wrap method definition in
class Thread to enable rdoc to process.
@@ -975,7 +20766,8 @@ Sat Nov 8 13:49:50 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* configure.in: improvement of pthread check
-Sat Nov 8 13:28:46 2003 Takaaki Tateishi <ttate@ttsky.net>
+Sat Nov 8 13:28:46 2003 Takaaki Tateishi <ttate@ttsky.net>
+
* ext/dl/sym.c: Add DL.win32_last_error and DL.last_error.
Thanks, Kaoru Shirai.
@@ -1078,7 +20870,7 @@ Wed Nov 5 17:05:18 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/test/unit/ui/gtk/testrunner.rb: typo.
-Wed Nov 5 11:13:32 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Wed Nov 5 11:13:32 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* string.c: add #include "version.h". this file still depends on it.
@@ -1099,7 +20891,7 @@ Wed Nov 5 08:39:51 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_ssl.c (ossl_ssl_get_peer_cert_chain): return nil
if no cert-chain was given.
-Tue Nov 4 23:44:48 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Tue Nov 4 23:44:48 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* bcc32/Makefile.sub, win32/Makefile.sub, wince/Makefile.sub:
remove needless version.h dependency.
@@ -1205,10 +20997,10 @@ Fri Oct 31 12:55:24 2003 WATANABE Hirofumi <eban@ruby-lang.org>
* bcc32/Makefile.sub, win32/Makefile.sub, win32/Makefile.sub: ditto.
-Fri Oct 31 01:38:14 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Fri Oct 31 01:38:14 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* wince/Makefile.sub, win32/Makefile.sub (.y.c): allow white spaces
- at the beginning of line to remove by sed. (ruby-bugs-ja PR#580)
+ at the beginning of line to remove by sed. (ruby-bugs-ja:PR#580)
Fri Oct 31 01:02:24 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -1217,7 +21009,7 @@ Fri Oct 31 01:02:24 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
comparison.
* eval.c (search_required): should update *featurep when DLEXT2 is
- defined. (ruby-bugs-ja PR#581)
+ defined. (ruby-bugs-ja:PR#581)
Thu Oct 30 23:41:04 2003 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
@@ -1264,7 +21056,7 @@ Thu Oct 30 10:14:51 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* lib/test/unit/autorunner.rb: make fox runner work.
-Thu Oct 30 09:32:26 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Thu Oct 30 09:32:26 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* process.c (rb_f_system): fixed lack of security check before
calling do_spawn() on win32. [ruby-talk:84555]
@@ -1293,7 +21085,7 @@ Wed Oct 29 22:02:04 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* test/drb/drbtest.rb: use rbconfig.rb to make the path of ruby
interpreter to exec, instead of test/ruby/envutil.rb,
-Wed Oct 29 19:58:59 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Wed Oct 29 19:58:59 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/tcltklib/tcltklib.c (CONST84): define CONST84 when it is not
defined and TCL_MAJOR_VERSION >= 8.
@@ -1325,7 +21117,7 @@ Wed Oct 29 11:27:39 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* parse.y (ret_args): node may be NULL. [ruby-talk:84530]
-Tue Oct 28 15:20:12 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Tue Oct 28 15:20:12 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/tcltklib/tcltklib.c (VwaitVarProc, ip_rbVwaitObjCmd,
WaitVariableProc, WaitVisibilityProc, WaitWindowProc,
@@ -1347,7 +21139,7 @@ Mon Oct 27 00:23:50 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
Sat Oct 25 09:18:04 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (rb_method_missing): protect exception from within
- "inspect". (ruby-bugs PR#1204)
+ "inspect". (ruby-bugs:PR#1204)
Fri Oct 24 23:26:34 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -1407,7 +21199,7 @@ Tue Oct 21 15:57:11 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/test/unit/collector/dir.rb (Test::Unit::Collector::Dir#collect_file):
prepend the directory of target file to the load path.
-Tue Oct 21 15:08:53 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Tue Oct 21 15:08:53 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (do_spawn, do_aspawn): should wait child process even
if callded with P_OVERLAY.
@@ -1460,10 +21252,15 @@ Mon Oct 20 11:00:46 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* gc.c (gc_sweep): do not update malloc_limit when malloc_increase
is smaller than malloc_limit.
-Mon Oct 20 09:45:12 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Mon Oct 20 09:45:12 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* lib/debug.rb (debug_command): remove debug print.
+Wed Oct 20 00:25:41 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (search_required): required name must not be changed before
+ loading. [ruby-dev:24492]
+
Sun Oct 19 13:12:30 2003 Tanaka Akira <akr@m17n.org>
* lib/pathname.rb (foreachline, dir_foreach): add obsolete warning.
@@ -1509,7 +21306,7 @@ Fri Oct 17 22:16:42 2003 Akinori MUSHA <knu@iDaemons.org>
* lib/set.rb: It is not necessary to require
'test/unit/ui/console/testrunner'.
-Fri Oct 17 11:15:22 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Fri Oct 17 11:15:22 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* test/ruby/test_range.rb: added.
@@ -1518,7 +21315,7 @@ Fri Oct 17 11:15:22 2003 NAKAMURA Usaku <usa@ruby-lang.org>
Fri Oct 17 03:21:23 2003 William Sobel <will.sobel@barra.com>
* ext/socket/socket.c (make_hostent): h_aliases may be NULL.
- (ruby-bugs PR#1195)
+ (ruby-bugs:PR#1195)
* ext/socket/socket.c (sock_s_gethostbyaddr): ditto.
@@ -1536,7 +21333,7 @@ Thu Oct 16 23:51:04 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
Thu Oct 16 17:09:19 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* lib/debug.rb (DEBUGGER__::Context::debug_command): do not call
- debug_silent_eval() when $1 is not set. (ruby-bugs PR#1194)
+ debug_silent_eval() when $1 is not set. (ruby-bugs:PR#1194)
Thu Oct 16 16:54:57 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -1576,7 +21373,7 @@ Wed Oct 15 15:00:54 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (ruby_run): just return FAILURE instead of parse error
count. [ruby-list:38569]
-Wed Oct 15 13:17:02 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Wed Oct 15 13:17:02 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/digest/digest.c (rb_digest_base_alloc): need to initialize
buffer. [ruby-dev:21622]
@@ -1589,7 +21386,7 @@ Wed Oct 15 11:23:05 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
modules before invoking marshal_load. these two fixes are done
by Masatoshi Seki <m_seki@mva.biglobe.ne.jp>.
-Wed Oct 15 09:30:34 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Wed Oct 15 09:30:34 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/enumerator/enumerator.c (enumerator_each): avoid VC++ warning.
@@ -1856,6 +21653,92 @@ Thu Oct 9 06:43:33 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (rb_thread_start_0, rb_thread_raise, rb_callcc): save
variables across THREAD_SAVE_CONTEXT.
+Thu Oct 9 12:05:46 2003 Eric Sunshine <sunshine@sunshineco.com>
+
+ * configure.in: revived NextStep, OpenStep, and Rhapsody ports which
+ had become unbuildable; enhanced --enable-fat-binary option so that
+ it accepts a list of desired architectures (rather than assuming a
+ fixed list), or defaults to a platform-appropriate list if user does
+ not provide an explicit list; made the default list of architectures
+ for MAB (fat binary) more comprehensive; now uses -fno-common even
+ when building the interpreter (in addition to using it for
+ extensions), thus allowing the interpreter to be embedded into a
+ plugin module of an external project (in addition to allowing
+ embedding directly into an application); added checks for
+ <netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now
+ ensures that -I/usr/local/include is employed when extensions'
+ extconf.rb scripts invoke have_header() since extension checks on
+ NextStep and OpenStep will fail without it if the desired resource
+ resides in the /usr/local tree; fixed formatting of --help message.
+
+ * Makefile.in: $(LIBRUBY_A) rule now deletes the archive before
+ invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives
+ (see configure's --enable-fat-binary option); added rule for new
+ missing/getcwd.c.
+
+ * defines.h: fixed endian handling during MAB build (see configure's
+ --enable-fat-binary option) to ensure that all portions of the
+ project see the correct WORDS_BIGENDIAN value (some extension modules
+ were getting the wrong endian setting); added missing constants
+ GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep
+ and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H
+ define in NeXT section.
+
+ * dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on
+ NextStep since, on some installations, this value always resolves
+ uselessly to zero.
+
+ * dln.c: added error reporting to NextStep extension loader since the
+ previous behavior of failing silently was not useful; now ensures
+ that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined
+ for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice
+ on Rhapsody since this header lacks multiple-include protection,
+ which resulted in "redefinition" compilation errors.
+
+ * main.c: also create hard reference to objc_msgSend() on NeXT
+ platforms (in addition to Apple platforms).
+
+ * lib/mkmf.rb: now exports XCFLAGS from configure script to extension
+ makefiles so that extensions can be built MAB (see configure's
+ --enable-fat-binary option); also utilize XCFLAGS in cc_command()
+ (but not cpp_command() because MAB flags are incompatible with
+ direct invocation of `cpp').
+
+ * ext/curses/extconf.rb: now additionally checks for presence of these
+ curses functions which are not present on NextStep or Openstep:
+ bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(),
+ setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(),
+ wscrl(), wsetscrreg()
+
+ * ext/curses/curses.c: added appropriate #ifdef's for additional set of
+ curses functions now checked by extconf.rb; fixed curses_bkgd() and
+ window_bkgd() to correctly return boolean result rather than numeric
+ result; fixed window_getbkgd() to correctly signal an error by
+ returning nil rather than -1.
+
+ * ext/etc/etc.c: setup_passwd() and setup_group() now check for null
+ pointers before invoking rb_tainted_str_new2() upon fields extracted
+ from `struct passwd' and `struct group' since null pointers in some
+ fields are common on NextStep/OpenStep (especially so for the
+ `pw_comment' field) and rb_tainted_str_new2() throws an exception
+ when it receives a null pointer.
+
+ * ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for
+ platforms such as NextStep and OpenStep which lack strdup().
+
+ * ext/socket/getaddrinfo.c: cast first argument of getservbyname(),
+ gethostbyaddr(), and gethostbyname() from (const char*) to non-const
+ (char*) for older platforms such as NextStep and OpenStep.
+
+ * ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for
+ platforms such as NextStep and OpenStep which lack strdup(); include
+ <netinet/in_systm.h> if present for NextStep and OpenStep; cast first
+ argument of gethostbyaddr() and getservbyname() from (const char*) to
+ non-const (char*) for older platforms.
+
+ * ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for
+ platforms such as NextStep and OpenStep which lack strdup().
+
Wed Oct 8 22:19:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
* lib/test/unit.rb: removed installation instructions.
@@ -2189,7 +22072,7 @@ Fri Oct 3 16:13:19 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_x509attr.c (ossl_x509attr_get_value): return
DER encoded data in OpenSSL::ASN1 types.
-Fri Oct 3 13:02:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
+Fri Oct 3 13:02:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
* lib/test/unit.rb: refactored to use optparse.
@@ -2212,7 +22095,7 @@ Fri Oct 3 08:14:32 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* lib/irb/ruby-lex.rb (RubyLex::identify_identifier): support
'class ::Foo' syntax. [ruby-talk:83514]
-Fri Oct 3 08:01:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
+Fri Oct 3 08:01:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
* lib/test/unit/assertions.rb: added a default message for #assert,
#assert_block, and #flunk.
@@ -2308,7 +22191,7 @@ Thu Oct 2 11:17:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
* lib/test/unit/collector/objectspace.rb: ditto.
-Thu Oct 2 03:25:01 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Thu Oct 2 03:25:01 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* eval.c (rb_thread_raise): prototype; avoid VC++ warning.
@@ -2361,6 +22244,35 @@ Thu Oct 2 00:21:11 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* test/soap/calc/*: give httpd config param "CGIInterpreter".
"/usr/bin/env ruby" thing does not work under non-Unix boxes.
+Sat Oct 2 00:42:20 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (r_byte): retrieve pointer from string value for each
+ time. [ruby-dev:24404]
+
+ * marshal.c (r_bytes0): ditto.
+
+ * enum.c (sort_by_i): re-entrance check added. [ruby-dev:24399]
+
+ * io.c (io_read): should freeze all reading buffer.
+ [ruby-dev:24400]
+
+ * string.c (rb_str_sum): should use bignums when bits is greater
+ than or equals to sizeof(long)*CHAR_BITS. [ruby-dev:24395]
+
+ * eval.c (specific_eval): defer pointer retrieval to prevent
+ unsafe sourcefile string modification. [ruby-dev:24382]
+
+ * string.c (rb_str_sum): wrong cast caused wrong result.
+ [ruby-dev:24385]
+
+ * enum.c (enum_sort_by): hide temporary array from
+ ObjectSpace.each_object. [ruby-dev:24386]
+
+ * string.c (rb_str_sum): check was done with false pointer.
+ [ruby-dev:24383]
+
+ * string.c (rb_str_sum): string may be altered. [ruby-dev:24381]
+
Thu Oct 2 00:25:21 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* signal.c (ruby_signal_name): adjust to the prototype.
@@ -2392,11 +22304,11 @@ Wed Oct 1 17:01:30 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (rb_load): Object scope had priority over required file
scope. [ruby-dev:21415]
-Wed Oct 01 14:09:53 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp>
+Wed Oct 1 14:09:53 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp>
* wince/mkconfig_wce.rb: sorry, forget to commit.
-Wed Oct 01 10:08:42 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp>
+Wed Oct 1 10:08:42 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp>
* wince/setup.mak: add sigmarionIII SDK support.
@@ -2406,7 +22318,7 @@ Wed Oct 01 10:08:42 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp>
* wince/mkconfig_wce.rb: camouflage RUBY_PLATFORM for compiling ext.
-Wed Oct 01 08:02:52 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp>
+Wed Oct 1 08:02:52 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp>
* wince/time_wce.c (time): add zero check.
@@ -2463,7 +22375,7 @@ Mon Sep 29 23:39:13 2003 Minero Aoki <aamine@loveruby.net>
Mon Sep 29 19:06:51 2003 WATANABE Hirofumi <eban@ruby-lang.org>
* ext/win32ole/extconf.rb: add windows.h checking.
- (ruby-bugs PR#1185)
+ (ruby-bugs:PR#1185)
Mon Sep 29 16:18:30 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
@@ -2524,6 +22436,20 @@ Sat Sep 27 09:44:18 2003 Minero Aoki <aamine@loveruby.net>
* test/fileutils/test_nowrite.rb: ditto.
+Mon Sep 27 09:14:03 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_delete): comparison may change the capacity.
+ [ruby-dev:24348]
+
+ * array.c (rb_ary_fill): fill should honor length argument.
+ [ruby-dev:24346]
+
+ * array.c (rb_ary_replace): should not use ptr from shared array.
+ [ruby-dev:24345]
+
+ * ext/socket/socket.c (s_accept): don't retry for EWOULDBLOCK.
+ [ruby-talk:113807]
+
Sat Sep 27 04:57:07 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* test/ruby/test_file.rb: new file. only asserts unlink-before-close
@@ -2539,7 +22465,7 @@ Sat Sep 27 03:32:37 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
test/soap/marshal/test_marshal.rb crashed with
test/ruby/test_marshal.rb.
-Sat Sep 27 01:30:59 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Sat Sep 27 01:30:59 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/socket/socket.c (ruby_connect): on win32, type of the 4th
argument of getsockopt is char *.
@@ -2564,7 +22490,7 @@ Fri Sep 26 00:10:13 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* lib/README: updated.
-Thu Sep 25 17:48:10 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Thu Sep 25 17:48:10 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/openssl/ossl.c (ossl_buf2str): fix type of 1st argument for
rb_protect.
@@ -2572,7 +22498,7 @@ Thu Sep 25 17:48:10 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/openssl/ossl_hmac.c (ossl_hmac_digest): should return meaningful
value.
-Thu Sep 25 09:00:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
+Thu Sep 25 09:00:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
* lib/ostruct.rb: Added OpenStruct#==.
@@ -2634,7 +22560,7 @@ Mon Sep 22 19:22:26 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
Mon Sep 22 12:34:55 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* util.c (ruby_strtod): skip preceding zeros before counting
- digits in the mantissa. (ruby-bugs PR#1181)
+ digits in the mantissa. (ruby-bugs:PR#1181)
Sun Sep 21 04:12:36 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
@@ -2655,7 +22581,7 @@ Sat Sep 20 11:49:05 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* test/logger/test_logger.rb: new file.
-Fri Sep 19 11:39:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
+Fri Sep 19 11:39:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
* test/testunit/*: Added.
@@ -2796,7 +22722,7 @@ Mon Sep 15 19:02:52 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* test/csv/mac.csv: added. Sample CR separated CSV file.
-Fri Sep 12 22:41:48 2003 Michal Rokos <m.rokos@sh.cvut.cz>
+Fri Sep 12 22:41:48 2003 Michal Rokos <m.rokos@sh.cvut.cz>
* ext/openssl/ossl.c: move ASN.1 stuff to ossl_asn1.[ch]
@@ -2820,7 +22746,7 @@ Fri Sep 12 12:09:54 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* bignum.c (rb_big_xor): ditto.
-Fri Sep 11 22:06:14 2003 David Black <dblack@superlink.net>
+Fri Sep 12 07:06:14 2003 David Black <dblack@superlink.net>
* lib/scanf.rb: Took out useless @matched_item variable; some small
refactoring.
@@ -2845,97 +22771,11 @@ Wed Sep 10 22:47:30 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_config.c (set_conf_section_i): should check
if the argument is Array.
-Wed Sep 10 22:41:54 2003 Tietew <tietew@tietew.net>
+Wed Sep 10 22:41:54 2003 Tietew <tietew@tietew.net>
* eval.c (win32_get_exception_list): avoid VC7 warning.
[ruby-win32:577]
-Thu Oct 9 12:05:46 2003 Eric Sunshine <sunshine@sunshineco.com>
-
- * configure.in: revived NextStep, OpenStep, and Rhapsody ports which
- had become unbuildable; enhanced --enable-fat-binary option so that
- it accepts a list of desired architectures (rather than assuming a
- fixed list), or defaults to a platform-appropriate list if user does
- not provide an explicit list; made the default list of architectures
- for MAB (fat binary) more comprehensive; now uses -fno-common even
- when building the interpreter (in addition to using it for
- extensions), thus allowing the interpreter to be embedded into a
- plugin module of an external project (in addition to allowing
- embedding directly into an application); added checks for
- <netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now
- ensures that -I/usr/local/include is employed when extensions'
- extconf.rb scripts invoke have_header() since extension checks on
- NextStep and OpenStep will fail without it if the desired resource
- resides in the /usr/local tree; fixed formatting of --help message.
-
- * Makefile.in: $(LIBRUBY_A) rule now deletes the archive before
- invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives
- (see configure's --enable-fat-binary option); added rule for new
- missing/getcwd.c.
-
- * defines.h: fixed endian handling during MAB build (see configure's
- --enable-fat-binary option) to ensure that all portions of the
- project see the correct WORDS_BIGENDIAN value (some extension modules
- were getting the wrong endian setting); added missing constants
- GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep
- and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H
- define in NeXT section.
-
- * dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on
- NextStep since, on some installations, this value always resolves
- uselessly to zero.
-
- * dln.c: added error reporting to NextStep extension loader since the
- previous behavior of failing silently was not useful; now ensures
- that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined
- for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice
- on Rhapsody since this header lacks multiple-include protection,
- which resulted in "redefinition" compilation errors.
-
- * main.c: also create hard reference to objc_msgSend() on NeXT
- platforms (in addition to Apple platforms).
-
- * lib/mkmf.rb: now exports XCFLAGS from configure script to extension
- makefiles so that extensions can be built MAB (see configure's
- --enable-fat-binary option); also utilize XCFLAGS in cc_command()
- (but not cpp_command() because MAB flags are incompatible with
- direct invocation of `cpp').
-
- * ext/curses/extconf.rb: now additionally checks for presence of these
- curses functions which are not present on NextStep or Openstep:
- bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(),
- setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(),
- wscrl(), wsetscrreg()
-
- * ext/curses/curses.c: added appropriate #ifdef's for additional set of
- curses functions now checked by extconf.rb; fixed curses_bkgd() and
- window_bkgd() to correctly return boolean result rather than numeric
- result; fixed window_getbkgd() to correctly signal an error by
- returning nil rather than -1.
-
- * ext/etc/etc.c: setup_passwd() and setup_group() now check for null
- pointers before invoking rb_tainted_str_new2() upon fields extracted
- from `struct passwd' and `struct group' since null pointers in some
- fields are common on NextStep/OpenStep (especially so for the
- `pw_comment' field) and rb_tainted_str_new2() throws an exception
- when it receives a null pointer.
-
- * ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for
- platforms such as NextStep and OpenStep which lack strdup().
-
- * ext/socket/getaddrinfo.c: cast first argument of getservbyname(),
- gethostbyaddr(), and gethostbyname() from (const char*) to non-const
- (char*) for older platforms such as NextStep and OpenStep.
-
- * ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for
- platforms such as NextStep and OpenStep which lack strdup(); include
- <netinet/in_systm.h> if present for NextStep and OpenStep; cast first
- argument of gethostbyaddr() and getservbyname() from (const char*) to
- non-const (char*) for older platforms.
-
- * ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for
- platforms such as NextStep and OpenStep which lack strdup().
-
Tue Sep 9 10:39:51 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (struct tag): dst should be VALUE.
@@ -2949,7 +22789,7 @@ Tue Sep 9 05:17:04 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_config.rb: avoid compile error in OpenSSL-0.9.6.
-Tue Sep 9 02:41:35 2003 Michal Rokos <m.rokos@sh.cvut.cz>
+Tue Sep 9 02:41:35 2003 Michal Rokos <m.rokos@sh.cvut.cz>
* ext/openssl/ossl_config.c: Refine compatibility.
@@ -3019,7 +22859,7 @@ Sat Sep 6 02:26:34 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* test/ruby/test_*.rb: assert_same, assert_match, and so on.
-Sat Sep 6 18:45:46 2003 Mauricio Fernandez <batsman.geo@yahoo.com>
+Sat Sep 6 18:45:46 2003 Mauricio Fernandez <batsman.geo@yahoo.com>
* parse.y (assignable): call rb_compile_error(), not rb_bug().
[ruby-core:01523]
@@ -3038,7 +22878,7 @@ Sat Sep 6 17:40:41 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_x509ext.c (X509::Extension#critical=): new method.
-Sat Sep 6 01:23:22 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Sat Sep 6 01:23:22 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (CreateChild): need to quote cmd if RUBYSHELL is set.
@@ -3319,12 +23159,12 @@ Sat Aug 30 03:58:21 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (rb_yield_0): stop TAG_RETURN/TAG_BREAK escaping.
-Fri Aug 29 22:35:00 2003 Shigeo Kobayashi <shigek@ruby-lang.org>
+Fri Aug 29 22:35:00 2003 Shigeo Kobayashi <shigek@ruby-lang.org>
* bigdecimal.c *.html: The 2nd arg. for add,sub,mult, and div is 0,
then result will be the same as +,-,*,/ respectively.
-Fri Aug 29 17:30:15 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+Fri Aug 29 17:30:15 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* process.c: bug fix
@@ -3376,7 +23216,7 @@ Thu Aug 28 17:30:24 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
Thu Aug 28 05:02:52 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
- * parse.y (singleton): typo fixed (ruby-bugs-ja PR#562)
+ * parse.y (singleton): typo fixed (ruby-bugs-ja:PR#562)
Thu Aug 28 02:37:45 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -3399,7 +23239,7 @@ Wed Aug 27 15:07:57 2003 Minero Aoki <aamine@loveruby.net>
* lib/net/smtp.rb (check_response): AUTH CRAM-MD5 returns 334
response. [ruby-list:38279]
-Wed Aug 27 05:10:15 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Wed Aug 27 05:10:15 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (map_errno): support winsock error.
@@ -3448,7 +23288,7 @@ Sat Aug 23 18:56:53 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/nkf/nkf.c (rb_nkf_putchar): should use rb_str_resize() to just
resize a string, rb_str_cat() disallows NULL. [ruby-dev:21237]
-Sat Aug 23 16:48:41 2003 Keiju Ishitsuka <keiju@ishitsuka.com>
+Sat Aug 23 16:48:41 2003 Keiju Ishitsuka <keiju@ishitsuka.com>
* lib/irb/ruby-lex.rb: bug fix for "foo" !~ /bar/. [ruby-talk:79942]
@@ -3473,7 +23313,7 @@ Fri Aug 22 17:07:05 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* string.c (rb_str_scan): use rb_yield_splat().
-Fri Aug 22 06:13:22 2003 why the lucky stiff <why@ruby-lang.org>
+Fri Aug 22 06:13:22 2003 why the lucky stiff <why@ruby-lang.org>
* ext/syck/rubyext.c: refactoring of the transfer method
dispatch. added yaml_org_handler for faster dispatch of
@@ -3490,7 +23330,7 @@ Fri Aug 22 01:00:31 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (block_pass): improve passing current block.
-Tue Aug 21 00:13:00 2003 Shigeo Kobayashi <shigek@ruby-lang.org>
+Fri Aug 22 00:13:00 2003 Shigeo Kobayashi <shigek@ruby-lang.org>
* ext/bigdecimal/bigdecimal.c: Int. overflow bug in multiplication
fixed, and VpNmlz() speed up.
@@ -3661,7 +23501,7 @@ Fri Aug 15 02:08:53 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* gc.c (id2ref): recycle check should be done by klass == 0.
[ruby-core:01408]
-Fri Aug 15 01:34:23 2003 Michal Rokos <m.rokos@sh.cvut.cz>
+Fri Aug 15 01:34:23 2003 Michal Rokos <m.rokos@sh.cvut.cz>
* ext/openssl/ossl_pkey.c: move generate_cb here
@@ -3693,7 +23533,7 @@ Thu Aug 14 20:03:34 2003 Masaki Suketa <masaki.suketa@nifty.ne.jp>
* ext/win32ole/win32ole.c (ole_initialize): stop calling
OleUninitialize at exit.
-Thu Aug 14 11:27:37 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Thu Aug 14 11:27:37 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* gc.c (rb_data_object_alloc): check type of 1st argument.
[ruby-dev:21192]
@@ -3732,10 +23572,10 @@ Wed Aug 13 15:58:31 2003 WATANABE Hirofumi <eban@ruby-lang.org>
* object.c (rb_class_s_alloc): add function prototype to avoid VC++
warning.
-Wed Aug 13 13:50:59 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Wed Aug 13 13:50:59 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/Win32API/Win32API.c (Win32API_initialize): should pass some
- class to first argument of Data_Wrap_Struct(). (ruby-bugs PR#1109)
+ class to first argument of Data_Wrap_Struct(). (ruby-bugs:PR#1109)
Tue Aug 12 16:55:11 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
@@ -3765,6 +23605,7 @@ Tue Aug 12 02:48:56 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (THREAD_ALLOC): initialize IA64 members.
Mon Aug 11 22:31:50 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
* lib/debug.rb(debug_command): inspection command should inspect
resulting value even if it's nil. [ruby-dev:21180] by OMAE, jun
<jun66j5@ybb.ne.jp>.
@@ -3826,7 +23667,7 @@ Thu Aug 7 14:40:37 2003 WATANABE Hirofumi <eban@ruby-lang.org>
Thu Aug 7 14:21:05 2003 Corinna Vinschen <vinschen@redhat.com>
* configure.in: Fix Cygwin specific naming of libraries to
- be net distribution compliant. (ruby-bugs PR#1077)
+ be net distribution compliant. (ruby-bugs:PR#1077)
cygwin-ruby18.dll -> cygruby18.dll
Thu Aug 7 12:51:38 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -3839,7 +23680,7 @@ Thu Aug 7 06:46:06 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (rb_call0): forgot to pop ruby_class.
* eval.c (rb_call0): update ruby_class as well as ruby_cref.
- (ruby-bugs-ja PR#540)
+ (ruby-bugs-ja:PR#540)
Thu Aug 7 04:52:50 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -3852,7 +23693,7 @@ Thu Aug 7 04:19:15 2003 Akinori MUSHA <knu@iDaemons.org>
Linux/ia64. This makes gc.c compile but miniruby coredumps for
the moment.
-Wed Aug 7 00:15:00 2003 Shigeo Kobayashi <shigek@ruby-lang.org>
+Thu Aug 7 00:15:00 2003 Shigeo Kobayashi <shigek@ruby-lang.org>
* ext/bigdecimal.c: Comparison results adjusted to Float's.
* ext/bigdecimal.c: Use rb_num_coerce_????(x,y) instead of own.
@@ -3891,7 +23732,7 @@ Wed Aug 6 17:23:57 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c: initialize /* OK */ variables by Qnil to stop warnings.
-Wed Aug 6 04:58:32 2003 NAKAMURA Usaku <usa@ruby-lang.org>
+Wed Aug 6 04:58:32 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/Setup*: add io/wait and openssl.
@@ -3965,9 +23806,10 @@ For the changes before 1.8.0, see doc/ChangeLog-1.8.0
Local variables:
add-log-time-format: (lambda ()
(let* ((time (current-time))
+ (system-time-locale "C")
(diff (+ (cadr time) 32400))
(lo (% diff 65536))
- (hi (+ (car time) (/ diff 65536))))
+ (hi (+ (car time) (/ diff 65536))))
(format-time-string "%a %b %e %H:%M:%S %Y" (list hi lo) t)))
indent-tabs-mode: t
tab-width: 8
diff --git a/LEGAL b/LEGAL
index dce7c1acbf..908eb270f5 100644
--- a/LEGAL
+++ b/LEGAL
@@ -134,14 +134,12 @@ st.[ch]:
x68/*:
missing/alloca.c:
missing/dup2.c:
-missing/erf.c:
missing/finite.c:
missing/hypot.c:
missing/isinf.c:
missing/isnan.c:
missing/memcmp.c:
missing/memmove.c:
-missing/mkdir.c:
missing/strcasecmp.c:
missing/strchr.c:
missing/streror.c:
@@ -186,6 +184,8 @@ missing/strtoul.c:
software for any purpose. It is provided "as is" without
express or implied warranty.
+missing/erf.c:
+missing/crypt.c:
missing/vsnprintf.c:
This file is under the old-style BSD license. Note that the
@@ -205,11 +205,7 @@ missing/vsnprintf.c:
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- 3. All advertising materials mentioning features or use of this software
- must display the following acknowledgement:
- This product includes software developed by the University of
- California, Berkeley and its contributors.
- 4. Neither the name of the University nor the names of its contributors
+ 3. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
@@ -309,17 +305,20 @@ ext/digest/sha2/sha2hl.c:
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-ext/nkf/nkf1.7/nkf.c:
+ext/nkf/nkf-utf8/config.h:
+ext/nkf/nkf-utf8/nkf.c:
+ext/nkf/nkf-utf8/utf8tbl.c:
- This file is under the following license. So to speak, it is
+ These files are under the following license. So to speak, it is
copyrighted semi-public-domain software.
Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
Everyone is permitted to do anything on this program
- including copying, modifying, improving.
+ including copying, modifying, improving,
as long as you don't try to pretend that you wrote it.
i.e., the above copyright notice has to appear in all copies.
- You don't have to ask before copying or publishing.
+ Binary distribution requires original version messages.
+ You don't have to ask before copying, redistribution or publishing.
THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
ext/socket/addrinfo.h:
diff --git a/MANIFEST b/MANIFEST
deleted file mode 100644
index 41555142be..0000000000
--- a/MANIFEST
+++ /dev/null
@@ -1,850 +0,0 @@
-COPYING
-COPYING.ja
-ChangeLog
-GPL
-LEGAL
-LGPL
-MANIFEST
-Makefile.in
-README
-README.EXT
-README.EXT.ja
-README.ja
-ToDo
-array.c
-bignum.c
-class.c
-compar.c
-config.guess
-config.sub
-configure
-configure.in
-defines.h
-dir.c
-dln.c
-dln.h
-dmyext.c
-enum.c
-env.h
-error.c
-eval.c
-file.c
-gc.c
-hash.c
-inits.c
-install-sh
-instruby.rb
-intern.h
-io.c
-keywords
-lex.c
-main.c
-marshal.c
-math.c
-mdoc2man.rb
-missing.h
-mkconfig.rb
-node.h
-numeric.c
-object.c
-pack.c
-parse.c
-parse.y
-prec.c
-process.c
-random.c
-range.c
-re.c
-re.h
-regex.c
-regex.h
-ruby.1
-ruby.c
-ruby.h
-rubyio.h
-rubysig.h
-rubytest.rb
-signal.c
-sprintf.c
-st.c
-st.h
-string.c
-struct.c
-time.c
-util.c
-util.h
-variable.c
-version.c
-version.h
-bcc32/Makefile.sub
-bcc32/README.bcc32
-bcc32/configure.bat
-bcc32/mkexports.rb
-bcc32/setup.mak
-bin/erb
-bin/irb
-bin/rdoc
-bin/testrb
-cygwin/GNUmakefile.in
-djgpp/GNUmakefile.in
-djgpp/README.djgpp
-djgpp/config.hin
-djgpp/config.sed
-djgpp/configure.bat
-djgpp/mkver.sed
-doc/ChangeLog-1.8.0
-doc/NEWS
-doc/forwardable.rd
-doc/forwardable.rd.ja
-doc/irb/irb-tools.rd.ja
-doc/irb/irb.rd
-doc/irb/irb.rd.ja
-doc/shell.rd
-doc/shell.rd.ja
-ext/Setup
-ext/Setup.atheos
-ext/Setup.dj
-ext/Setup.emx
-ext/Setup.nt
-ext/Setup.x68
-ext/extmk.rb
-lib/English.rb
-lib/Env.rb
-lib/README
-lib/abbrev.rb
-lib/base64.rb
-lib/benchmark.rb
-lib/cgi-lib.rb
-lib/cgi.rb
-lib/cgi/session.rb
-lib/cgi/session/pstore.rb
-lib/complex.rb
-lib/csv.rb
-lib/date.rb
-lib/date/format.rb
-lib/date2.rb
-lib/debug.rb
-lib/delegate.rb
-lib/drb.rb
-lib/drb/acl.rb
-lib/drb/drb.rb
-lib/drb/eq.rb
-lib/drb/extserv.rb
-lib/drb/extservm.rb
-lib/drb/gw.rb
-lib/drb/invokemethod.rb
-lib/drb/observer.rb
-lib/drb/ssl.rb
-lib/drb/timeridconv.rb
-lib/drb/unix.rb
-lib/e2mmap.rb
-lib/erb.rb
-lib/eregex.rb
-lib/fileutils.rb
-lib/finalize.rb
-lib/find.rb
-lib/forwardable.rb
-lib/ftools.rb
-lib/generator.rb
-lib/getoptlong.rb
-lib/getopts.rb
-lib/gserver.rb
-lib/importenv.rb
-lib/ipaddr.rb
-lib/irb.rb
-lib/irb/cmd/chws.rb
-lib/irb/cmd/fork.rb
-lib/irb/cmd/load.rb
-lib/irb/cmd/nop.rb
-lib/irb/cmd/pushws.rb
-lib/irb/cmd/subirb.rb
-lib/irb/completion.rb
-lib/irb/context.rb
-lib/irb/ext/change-ws.rb
-lib/irb/ext/history.rb
-lib/irb/ext/loader.rb
-lib/irb/ext/math-mode.rb
-lib/irb/ext/multi-irb.rb
-lib/irb/ext/tracer.rb
-lib/irb/ext/use-loader.rb
-lib/irb/ext/workspaces.rb
-lib/irb/extend-command.rb
-lib/irb/frame.rb
-lib/irb/help.rb
-lib/irb/init.rb
-lib/irb/input-method.rb
-lib/irb/lc/error.rb
-lib/irb/lc/help-message
-lib/irb/lc/ja/error.rb
-lib/irb/lc/ja/help-message
-lib/irb/locale.rb
-lib/irb/ruby-lex.rb
-lib/irb/ruby-token.rb
-lib/irb/slex.rb
-lib/irb/version.rb
-lib/irb/workspace.rb
-lib/irb/ws-for-case-2.rb
-lib/irb/xmp.rb
-lib/jcode.rb
-lib/logger.rb
-lib/mailread.rb
-lib/mathn.rb
-lib/matrix.rb
-lib/mkmf.rb
-lib/monitor.rb
-lib/mutex_m.rb
-lib/net/ftp.rb
-lib/net/http.rb
-lib/net/imap.rb
-lib/net/pop.rb
-lib/net/protocol.rb
-lib/net/smtp.rb
-lib/net/telnet.rb
-lib/observer.rb
-lib/open-uri.rb
-lib/open3.rb
-lib/optparse.rb
-lib/optparse/date.rb
-lib/optparse/shellwords.rb
-lib/optparse/time.rb
-lib/optparse/uri.rb
-lib/optparse/version.rb
-lib/ostruct.rb
-lib/parsearg.rb
-lib/parsedate.rb
-lib/pathname.rb
-lib/ping.rb
-lib/pp.rb
-lib/prettyprint.rb
-lib/profile.rb
-lib/profiler.rb
-lib/pstore.rb
-lib/racc/parser.rb
-lib/rational.rb
-lib/rdoc/README
-lib/rdoc/code_objects.rb
-lib/rdoc/diagram.rb
-lib/rdoc/options.rb
-lib/rdoc/rdoc.rb
-lib/rdoc/template.rb
-lib/rdoc/tokenstream.rb
-lib/rdoc/dot/dot.rb
-lib/rdoc/generators/chm_generator.rb
-lib/rdoc/generators/html_generator.rb
-lib/rdoc/generators/xml_generator.rb
-lib/rdoc/generators/template/chm/chm.rb
-lib/rdoc/generators/template/html/css2.rb
-lib/rdoc/generators/template/html/hefss.rb
-lib/rdoc/generators/template/html/html.rb
-lib/rdoc/generators/template/html/kilmer.rb
-lib/rdoc/generators/template/xml/rdf.rb
-lib/rdoc/generators/template/xml/xml.rb
-lib/rdoc/markup/sample/rdoc2latex.rb
-lib/rdoc/markup/sample/sample.rb
-lib/rdoc/markup/simple_markup.rb
-lib/rdoc/markup/simple_markup/fragments.rb
-lib/rdoc/markup/simple_markup/inline.rb
-lib/rdoc/markup/simple_markup/lines.rb
-lib/rdoc/markup/simple_markup/preprocess.rb
-lib/rdoc/markup/simple_markup/to_html.rb
-lib/rdoc/markup/simple_markup/to_latex.rb
-lib/rdoc/markup/test/AllTests.rb
-lib/rdoc/markup/test/TestInline.rb
-lib/rdoc/markup/test/TestParse.rb
-lib/rdoc/parsers/parse_c.rb
-lib/rdoc/parsers/parse_f95.rb
-lib/rdoc/parsers/parse_rb.rb
-lib/rdoc/parsers/parse_simple.rb
-lib/rdoc/parsers/parserfactory.rb
-lib/readbytes.rb
-lib/resolv-replace.rb
-lib/resolv.rb
-lib/rexml/attlistdecl.rb
-lib/rexml/attribute.rb
-lib/rexml/cdata.rb
-lib/rexml/child.rb
-lib/rexml/comment.rb
-lib/rexml/doctype.rb
-lib/rexml/document.rb
-lib/rexml/dtd/attlistdecl.rb
-lib/rexml/dtd/dtd.rb
-lib/rexml/dtd/elementdecl.rb
-lib/rexml/dtd/entitydecl.rb
-lib/rexml/dtd/notationdecl.rb
-lib/rexml/element.rb
-lib/rexml/encoding.rb
-lib/rexml/encodings/EUC-JP.rb
-lib/rexml/encodings/ICONV.rb
-lib/rexml/encodings/ISO-8859-1.rb
-lib/rexml/encodings/SHIFT-JIS.rb
-lib/rexml/encodings/SHIFT_JIS.rb
-lib/rexml/encodings/UNILE.rb
-lib/rexml/encodings/US-ASCII.rb
-lib/rexml/encodings/UTF-16.rb
-lib/rexml/encodings/UTF-8.rb
-lib/rexml/entity.rb
-lib/rexml/functions.rb
-lib/rexml/instruction.rb
-lib/rexml/light/node.rb
-lib/rexml/namespace.rb
-lib/rexml/node.rb
-lib/rexml/output.rb
-lib/rexml/parent.rb
-lib/rexml/parseexception.rb
-lib/rexml/parsers/baseparser.rb
-lib/rexml/parsers/lightparser.rb
-lib/rexml/parsers/pullparser.rb
-lib/rexml/parsers/sax2parser.rb
-lib/rexml/parsers/streamparser.rb
-lib/rexml/parsers/ultralightparser.rb
-lib/rexml/parsers/xpathparser.rb
-lib/rexml/quickpath.rb
-lib/rexml/rexml.rb
-lib/rexml/sax2listener.rb
-lib/rexml/source.rb
-lib/rexml/streamlistener.rb
-lib/rexml/text.rb
-lib/rexml/xmldecl.rb
-lib/rexml/xmltokens.rb
-lib/rexml/xpath.rb
-lib/rexml/xpath_parser.rb
-lib/rinda/rinda.rb
-lib/rinda/ring.rb
-lib/rinda/tuplespace.rb
-lib/rubyunit.rb
-lib/runit/assert.rb
-lib/runit/cui/testrunner.rb
-lib/runit/error.rb
-lib/runit/testcase.rb
-lib/runit/testresult.rb
-lib/runit/testsuite.rb
-lib/runit/topublic.rb
-lib/scanf.rb
-lib/set.rb
-lib/shell.rb
-lib/shell/builtin-command.rb
-lib/shell/command-processor.rb
-lib/shell/error.rb
-lib/shell/filter.rb
-lib/shell/process-controller.rb
-lib/shell/system-command.rb
-lib/shell/version.rb
-lib/shellwords.rb
-lib/singleton.rb
-lib/soap/baseData.rb
-lib/soap/element.rb
-lib/soap/encodingstyle/aspDotNetHandler.rb
-lib/soap/encodingstyle/handler.rb
-lib/soap/encodingstyle/literalHandler.rb
-lib/soap/encodingstyle/soapHandler.rb
-lib/soap/generator.rb
-lib/soap/mapping.rb
-lib/soap/mapping/factory.rb
-lib/soap/mapping/mapping.rb
-lib/soap/mapping/registry.rb
-lib/soap/mapping/rubytypeFactory.rb
-lib/soap/mapping/typeMap.rb
-lib/soap/mapping/wsdlRegistry.rb
-lib/soap/marshal.rb
-lib/soap/netHttpClient.rb
-lib/soap/parser.rb
-lib/soap/processor.rb
-lib/soap/property.rb
-lib/soap/rpc/cgistub.rb
-lib/soap/rpc/driver.rb
-lib/soap/rpc/element.rb
-lib/soap/rpc/proxy.rb
-lib/soap/rpc/router.rb
-lib/soap/rpc/rpc.rb
-lib/soap/rpc/soaplet.rb
-lib/soap/rpc/standaloneServer.rb
-lib/soap/soap.rb
-lib/soap/streamHandler.rb
-lib/soap/wsdlDriver.rb
-lib/sync.rb
-lib/tempfile.rb
-lib/test/unit.rb
-lib/test/unit/assertionfailederror.rb
-lib/test/unit/assertions.rb
-lib/test/unit/autorunner.rb
-lib/test/unit/collector.rb
-lib/test/unit/collector/dir.rb
-lib/test/unit/collector/objectspace.rb
-lib/test/unit/error.rb
-lib/test/unit/failure.rb
-lib/test/unit/testcase.rb
-lib/test/unit/testresult.rb
-lib/test/unit/testsuite.rb
-lib/test/unit/ui/console/testrunner.rb
-lib/test/unit/ui/fox/testrunner.rb
-lib/test/unit/ui/gtk/testrunner.rb
-lib/test/unit/ui/gtk2/testrunner.rb
-lib/test/unit/ui/testrunnermediator.rb
-lib/test/unit/ui/testrunnerutilities.rb
-lib/test/unit/ui/tk/testrunner.rb
-lib/test/unit/util/backtracefilter.rb
-lib/test/unit/util/observable.rb
-lib/test/unit/util/procwrapper.rb
-lib/thread.rb
-lib/thwait.rb
-lib/time.rb
-lib/timeout.rb
-lib/tmpdir.rb
-lib/tracer.rb
-lib/tsort.rb
-lib/un.rb
-lib/uri.rb
-lib/uri/common.rb
-lib/uri/ftp.rb
-lib/uri/generic.rb
-lib/uri/http.rb
-lib/uri/https.rb
-lib/uri/ldap.rb
-lib/uri/mailto.rb
-lib/weakref.rb
-lib/webrick.rb
-lib/webrick/accesslog.rb
-lib/webrick/compat.rb
-lib/webrick/config.rb
-lib/webrick/cookie.rb
-lib/webrick/htmlutils.rb
-lib/webrick/httpauth.rb
-lib/webrick/httpauth/authenticator.rb
-lib/webrick/httpauth/basicauth.rb
-lib/webrick/httpauth/digestauth.rb
-lib/webrick/httpauth/htdigest.rb
-lib/webrick/httpauth/htgroup.rb
-lib/webrick/httpauth/htpasswd.rb
-lib/webrick/httpauth/userdb.rb
-lib/webrick/httpproxy.rb
-lib/webrick/httprequest.rb
-lib/webrick/httpresponse.rb
-lib/webrick/https.rb
-lib/webrick/httpserver.rb
-lib/webrick/httpservlet.rb
-lib/webrick/httpservlet/abstract.rb
-lib/webrick/httpservlet/cgi_runner.rb
-lib/webrick/httpservlet/cgihandler.rb
-lib/webrick/httpservlet/erbhandler.rb
-lib/webrick/httpservlet/filehandler.rb
-lib/webrick/httpservlet/prochandler.rb
-lib/webrick/httpstatus.rb
-lib/webrick/httputils.rb
-lib/webrick/httpversion.rb
-lib/webrick/log.rb
-lib/webrick/server.rb
-lib/webrick/ssl.rb
-lib/webrick/utils.rb
-lib/webrick/version.rb
-lib/wsdl/binding.rb
-lib/wsdl/data.rb
-lib/wsdl/definitions.rb
-lib/wsdl/documentation.rb
-lib/wsdl/import.rb
-lib/wsdl/importer.rb
-lib/wsdl/info.rb
-lib/wsdl/message.rb
-lib/wsdl/operation.rb
-lib/wsdl/operationBinding.rb
-lib/wsdl/param.rb
-lib/wsdl/parser.rb
-lib/wsdl/part.rb
-lib/wsdl/port.rb
-lib/wsdl/portType.rb
-lib/wsdl/service.rb
-lib/wsdl/soap/address.rb
-lib/wsdl/soap/binding.rb
-lib/wsdl/soap/body.rb
-lib/wsdl/soap/complexType.rb
-lib/wsdl/soap/data.rb
-lib/wsdl/soap/definitions.rb
-lib/wsdl/soap/fault.rb
-lib/wsdl/soap/header.rb
-lib/wsdl/soap/headerfault.rb
-lib/wsdl/soap/operation.rb
-lib/wsdl/types.rb
-lib/wsdl/wsdl.rb
-lib/wsdl/xmlSchema/all.rb
-lib/wsdl/xmlSchema/any.rb
-lib/wsdl/xmlSchema/attribute.rb
-lib/wsdl/xmlSchema/choice.rb
-lib/wsdl/xmlSchema/complexContent.rb
-lib/wsdl/xmlSchema/complexType.rb
-lib/wsdl/xmlSchema/content.rb
-lib/wsdl/xmlSchema/data.rb
-lib/wsdl/xmlSchema/element.rb
-lib/wsdl/xmlSchema/import.rb
-lib/wsdl/xmlSchema/parser.rb
-lib/wsdl/xmlSchema/schema.rb
-lib/wsdl/xmlSchema/sequence.rb
-lib/wsdl/xmlSchema/unique.rb
-lib/xmlrpc/base64.rb
-lib/xmlrpc/client.rb
-lib/xmlrpc/config.rb
-lib/xmlrpc/create.rb
-lib/xmlrpc/datetime.rb
-lib/xmlrpc/httpserver.rb
-lib/xmlrpc/marshal.rb
-lib/xmlrpc/parser.rb
-lib/xmlrpc/server.rb
-lib/xmlrpc/utils.rb
-lib/xsd/charset.rb
-lib/xsd/datatypes.rb
-lib/xsd/datatypes1999.rb
-lib/xsd/iconvcharset.rb
-lib/xsd/namedelements.rb
-lib/xsd/ns.rb
-lib/xsd/qname.rb
-lib/xsd/xmlparser.rb
-lib/xsd/xmlparser/parser.rb
-lib/xsd/xmlparser/rexmlparser.rb
-lib/xsd/xmlparser/xmlparser.rb
-lib/xsd/xmlparser/xmlscanner.rb
-lib/yaml.rb
-lib/yaml/baseemitter.rb
-lib/yaml/basenode.rb
-lib/yaml/constants.rb
-lib/yaml/dbm.rb
-lib/yaml/emitter.rb
-lib/yaml/encoding.rb
-lib/yaml/error.rb
-lib/yaml/loader.rb
-lib/yaml/rubytypes.rb
-lib/yaml/store.rb
-lib/yaml/stream.rb
-lib/yaml/stringio.rb
-lib/yaml/syck.rb
-lib/yaml/types.rb
-lib/yaml/yamlnode.rb
-lib/yaml/ypath.rb
-misc/README
-misc/inf-ruby.el
-misc/ruby-mode.el
-misc/rubydb2x.el
-misc/rubydb3x.el
-missing/acosh.c
-missing/alloca.c
-missing/crypt.c
-missing/dup2.c
-missing/erf.c
-missing/file.h
-missing/fileblocks.c
-missing/finite.c
-missing/flock.c
-missing/hypot.c
-missing/isinf.c
-missing/isnan.c
-missing/memcmp.c
-missing/memmove.c
-missing/mkdir.c
-missing/os2.c
-missing/strcasecmp.c
-missing/strchr.c
-missing/strerror.c
-missing/strftime.c
-missing/strncasecmp.c
-missing/strstr.c
-missing/strtod.c
-missing/strtol.c
-missing/strtoul.c
-missing/vsnprintf.c
-missing/x68.c
-sample/README
-sample/biorhythm.rb
-sample/cal.rb
-sample/cbreak.rb
-sample/clnt.rb
-sample/dbmtest.rb
-sample/dir.rb
-sample/dualstack-fetch.rb
-sample/dualstack-httpd.rb
-sample/eval.rb
-sample/export.rb
-sample/exyacc.rb
-sample/fact.rb
-sample/fib.awk
-sample/fib.pl
-sample/fib.py
-sample/fib.rb
-sample/fib.scm
-sample/freq.rb
-sample/from.rb
-sample/fullpath.rb
-sample/getopts.test
-sample/goodfriday.rb
-sample/less.rb
-sample/list.rb
-sample/list2.rb
-sample/list3.rb
-sample/logger/app.rb
-sample/logger/log.rb
-sample/logger/shifting.rb
-sample/mine.rb
-sample/mkproto.rb
-sample/mpart.rb
-sample/mrshtest.rb
-sample/observ.rb
-sample/occur.pl
-sample/occur.rb
-sample/occur2.rb
-sample/openssl/c_rehash.rb
-sample/openssl/cert2text.rb
-sample/openssl/cert_store_view.rb
-sample/openssl/certstore.rb
-sample/openssl/cipher.rb
-sample/openssl/crlstore.rb
-sample/openssl/echo_cli.rb
-sample/openssl/echo_svr.rb
-sample/openssl/gen_csr.rb
-sample/openssl/smime_read.rb
-sample/openssl/smime_write.rb
-sample/openssl/wget.rb
-sample/optparse/opttest.rb
-sample/philos.rb
-sample/pi.rb
-sample/rcs.awk
-sample/rcs.dat
-sample/rcs.rb
-sample/regx.rb
-sample/sieve.rb
-sample/soap/babelfish.rb
-sample/soap/calc/calc.rb
-sample/soap/calc/calc2.rb
-sample/soap/calc/client.rb
-sample/soap/calc/client2.rb
-sample/soap/calc/httpd.rb
-sample/soap/calc/server.cgi
-sample/soap/calc/server.rb
-sample/soap/calc/server2.rb
-sample/soap/digraph.rb
-sample/soap/exchange/client.rb
-sample/soap/exchange/exchange.rb
-sample/soap/exchange/httpd.rb
-sample/soap/exchange/server.cgi
-sample/soap/exchange/server.rb
-sample/soap/helloworld/hw_c.rb
-sample/soap/helloworld/hw_s.rb
-sample/soap/icd/IICD.rb
-sample/soap/icd/icd.rb
-sample/soap/raa/iRAA.rb
-sample/soap/raa/soap4r.rb
-sample/soap/sampleStruct/client.rb
-sample/soap/sampleStruct/httpd.rb
-sample/soap/sampleStruct/iSampleStruct.rb
-sample/soap/sampleStruct/sampleStruct.rb
-sample/soap/sampleStruct/server.cgi
-sample/soap/sampleStruct/server.rb
-sample/svr.rb
-sample/test.rb
-sample/testunit/adder.rb
-sample/testunit/subtracter.rb
-sample/testunit/tc_adder.rb
-sample/testunit/tc_subtracter.rb
-sample/testunit/ts_examples.rb
-sample/time.rb
-sample/trojan.rb
-sample/tsvr.rb
-sample/uumerge.rb
-sample/wsdl/amazon/AmazonSearch.rb
-sample/wsdl/amazon/AmazonSearchDriver.rb
-sample/wsdl/amazon/sampleClient.rb
-sample/wsdl/amazon/wsdlDriver.rb
-sample/wsdl/googleSearch/GoogleSearch.rb
-sample/wsdl/googleSearch/GoogleSearchDriver.rb
-sample/wsdl/googleSearch/README
-sample/wsdl/googleSearch/httpd.rb
-sample/wsdl/googleSearch/sampleClient.rb
-sample/wsdl/googleSearch/sjissearch.sh
-sample/wsdl/googleSearch/wsdlDriver.rb
-sample/wsdl/raa/raa.wsdl
-sample/wsdl/raa/soap4r.rb
-test/csv/bom.csv
-test/csv/mac.csv
-test/csv/test_csv.rb
-test/digest/test_digest.rb
-test/drb/drbtest.rb
-test/drb/test_acl.rb
-test/drb/test_drb.rb
-test/drb/test_drbssl.rb
-test/drb/test_drbunix.rb
-test/drb/ut_array.rb
-test/drb/ut_array_drbssl.rb
-test/drb/ut_array_drbunix.rb
-test/drb/ut_drb.rb
-test/drb/ut_drb_drbssl.rb
-test/drb/ut_drb_drbunix.rb
-test/drb/ut_eval.rb
-test/drb/ut_large.rb
-test/drb/ut_port.rb
-test/drb/ut_safe1.rb
-test/drb/ut_timerholder.rb
-test/fileutils/fileasserts.rb
-test/fileutils/test_fileutils.rb
-test/fileutils/test_nowrite.rb
-test/logger/test_logger.rb
-test/monitor/test_monitor.rb
-test/optparse/test_noarg.rb
-test/optparse/test_optarg.rb
-test/optparse/test_optparse.rb
-test/optparse/test_placearg.rb
-test/optparse/test_reqarg.rb
-test/ostruct/test_ostruct.rb
-test/ruby/beginmainend.rb
-test/ruby/endblockwarn.rb
-test/ruby/envutil.rb
-test/ruby/test_alias.rb
-test/ruby/test_array.rb
-test/ruby/test_assignment.rb
-test/ruby/test_beginendblock.rb
-test/ruby/test_bignum.rb
-test/ruby/test_call.rb
-test/ruby/test_case.rb
-test/ruby/test_clone.rb
-test/ruby/test_condition.rb
-test/ruby/test_const.rb
-test/ruby/test_defined.rb
-test/ruby/test_env.rb
-test/ruby/test_eval.rb
-test/ruby/test_exception.rb
-test/ruby/test_file.rb
-test/ruby/test_float.rb
-test/ruby/test_gc.rb
-test/ruby/test_hash.rb
-test/ruby/test_ifunless.rb
-test/ruby/test_iterator.rb
-test/ruby/test_marshal.rb
-test/ruby/test_math.rb
-test/ruby/test_pack.rb
-test/ruby/test_path.rb
-test/ruby/test_pipe.rb
-test/ruby/test_proc.rb
-test/ruby/test_range.rb
-test/ruby/test_signal.rb
-test/ruby/test_stringchar.rb
-test/ruby/test_struct.rb
-test/ruby/test_system.rb
-test/ruby/test_trace.rb
-test/ruby/test_variable.rb
-test/ruby/test_whileuntil.rb
-test/ruby/ut_eof.rb
-test/runner.rb
-test/soap/calc/calc.rb
-test/soap/calc/calc2.rb
-test/soap/calc/server.cgi
-test/soap/calc/server.rb
-test/soap/calc/server2.rb
-test/soap/calc/test_calc.rb
-test/soap/calc/test_calc2.rb
-test/soap/calc/test_calc_cgi.rb
-test/soap/helloworld/hw_s.rb
-test/soap/helloworld/test_helloworld.rb
-test/soap/marshal/cmarshal.rb
-test/soap/marshal/test_digraph.rb
-test/soap/marshal/test_marshal.rb
-test/soap/marshal/test_struct.rb
-test/soap/test_basetype.rb
-test/soap/test_soapelement.rb
-test/stringio/test_stringio.rb
-test/strscan/test_stringscanner.rb
-test/testunit/collector/test_dir.rb
-test/testunit/collector/test_objectspace.rb
-test/testunit/runit/test_assert.rb
-test/testunit/runit/test_testcase.rb
-test/testunit/runit/test_testresult.rb
-test/testunit/runit/test_testsuite.rb
-test/testunit/test_assertions.rb
-test/testunit/test_error.rb
-test/testunit/test_failure.rb
-test/testunit/test_testcase.rb
-test/testunit/test_testresult.rb
-test/testunit/test_testsuite.rb
-test/testunit/util/test_backtracefilter.rb
-test/testunit/util/test_observable.rb
-test/testunit/util/test_procwrapper.rb
-test/uri/test_common.rb
-test/uri/test_ftp.rb
-test/uri/test_generic.rb
-test/uri/test_http.rb
-test/uri/test_ldap.rb
-test/uri/test_mailto.rb
-test/wsdl/axisArray/axisArray.wsdl
-test/wsdl/axisArray/itemList.rb
-test/wsdl/axisArray/test_axisarray.rb
-test/wsdl/datetime/DatetimeService.rb
-test/wsdl/datetime/datetime.rb
-test/wsdl/datetime/datetime.wsdl
-test/wsdl/datetime/datetimeServant.rb
-test/wsdl/datetime/test_datetime.rb
-test/wsdl/emptycomplextype.wsdl
-test/wsdl/map/map.wsdl
-test/wsdl/map/map.xml
-test/wsdl/map/test_map.rb
-test/wsdl/raa/RAA.rb
-test/wsdl/raa/README.txt
-test/wsdl/raa/RAAServant.rb
-test/wsdl/raa/RAAService.rb
-test/wsdl/raa/raa.wsdl
-test/wsdl/raa/test_raa.rb
-test/wsdl/test_emptycomplextype.rb
-test/wsdl/test_fault.rb
-test/xsd/noencoding.xml
-test/xsd/test_noencoding.rb
-test/xsd/test_xmlschemaparser.rb
-test/xsd/test_xsd.rb
-test/xsd/xmlschema.xml
-test/yaml/test_yaml.rb
-vms/config.h_in
-vms/vms.h
-win32/Makefile.sub
-win32/README.win32
-win32/configure.bat
-win32/dir.h
-win32/mkexports.rb
-win32/resource.rb
-win32/setup.mak
-win32/win32.c
-win32/win32.h
-win32/winmain.c
-wince/Makefile.sub
-wince/README.wince
-wince/assert.c
-wince/assert.h
-wince/configure.bat
-wince/direct.c
-wince/direct.h
-wince/errno.c
-wince/errno.h
-wince/fcntl.h
-wince/io.h
-wince/io_wce.c
-wince/mkconfig_wce.rb
-wince/mkexports.rb
-wince/process.h
-wince/process_wce.c
-wince/resource.rb
-wince/setup.mak
-wince/signal.h
-wince/signal_wce.c
-wince/stddef.h
-wince/stdio.c
-wince/stdlib.c
-wince/string_wce.c
-wince/sys/stat.c
-wince/sys/stat.h
-wince/sys/timeb.c
-wince/sys/timeb.h
-wince/sys/types.h
-wince/sys/utime.c
-wince/sys/utime.h
-wince/time.h
-wince/time_wce.c
-wince/varargs.h
-wince/wince.c
-wince/wince.h
-wince/wincemain.c
-wince/wincon.h
-wince/winsock2.c
-x68/_dtos18.c
-x68/_round.c
-x68/fconvert.c
-x68/select.c
diff --git a/Makefile.in b/Makefile.in
index 64110b8761..a37bcf65fb 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,5 @@
SHELL = /bin/sh
+NULLCMD = :
#### Start of system configuration section. ####
@@ -10,6 +11,7 @@ YACC = @YACC@
PURIFY =
AUTOCONF = autoconf
@SET_MAKE@
+MKFILES = @MAKEFILES@
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -17,11 +19,25 @@ bindir = @bindir@
sbindir = @sbindir@
libdir = @libdir@
libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+datadir = @datadir@
arch = @arch@
sitearch = @sitearch@
sitedir = @sitedir@
+TESTUI = console
+TESTS =
+RDOCTARGET = @RDOCTARGET@
+
+EXTOUT = @EXTOUT@
+RIDATADIR = $(DESTDIR)$(datadir)/ri/$(MAJOR).$(MINOR)/system
+
+empty =
+OUTFLAG = @OUTFLAG@$(empty)
CFLAGS = @CFLAGS@ @XCFLAGS@ @ARCH_FLAG@
+cflags = @cflags@
+optflags = @optflags@
+debugflags = @debugflags@
CPPFLAGS = -I. -I$(srcdir) @CPPFLAGS@
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
EXTLDFLAGS =
@@ -33,13 +49,15 @@ LDSHARED = @LIBRUBY_LDSHARED@
DLDFLAGS = @LIBRUBY_DLDFLAGS@ $(EXTLDFLAGS) @ARCH_FLAG@
SOLIBS = @SOLIBS@
MAINLIBS = @MAINLIBS@
+MINIOBJS = @MINIOBJS@
RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
RUBY_SO_NAME=@RUBY_SO_NAME@
EXEEXT = @EXEEXT@
PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
RUBY = $(RUBY_INSTALL_NAME)
-MINIRUBY = @MINIRUBY@
+MINIRUBY = @MINIRUBY@ $(MINIRUBYOPT)
+RUNRUBY = @RUNRUBY@ $(RUNRUBYOPT) --
#### End of system configuration section. ####
@@ -55,129 +73,56 @@ LIBRUBYARG = @LIBRUBYARG@
LIBRUBYARG_STATIC = @LIBRUBYARG_STATIC@
LIBRUBYARG_SHARED = @LIBRUBYARG_SHARED@
-PREP = @PREP@ @ARCHFILE@
+PREP = @PREP@
+ARCHFILE = @ARCHFILE@
SETUP =
EXTSTATIC = @EXTSTATIC@
-EXTOBJS =
-DLDOBJS = $(DMYEXT)
-DMYEXT = dmyext.@OBJEXT@
-
-MAINOBJ = main.@OBJEXT@
-
-OBJS = array.@OBJEXT@ \
- bignum.@OBJEXT@ \
- class.@OBJEXT@ \
- compar.@OBJEXT@ \
- dir.@OBJEXT@ \
- dln.@OBJEXT@ \
- enum.@OBJEXT@ \
- error.@OBJEXT@ \
- eval.@OBJEXT@ \
- file.@OBJEXT@ \
- gc.@OBJEXT@ \
- hash.@OBJEXT@ \
- inits.@OBJEXT@ \
- io.@OBJEXT@ \
- marshal.@OBJEXT@ \
- math.@OBJEXT@ \
- numeric.@OBJEXT@ \
- object.@OBJEXT@ \
- pack.@OBJEXT@ \
- parse.@OBJEXT@ \
- process.@OBJEXT@ \
- prec.@OBJEXT@ \
- random.@OBJEXT@ \
- range.@OBJEXT@ \
- re.@OBJEXT@ \
- regex.@OBJEXT@ \
- ruby.@OBJEXT@ \
- signal.@OBJEXT@ \
- sprintf.@OBJEXT@ \
- st.@OBJEXT@ \
- string.@OBJEXT@ \
- struct.@OBJEXT@ \
- time.@OBJEXT@ \
- util.@OBJEXT@ \
- variable.@OBJEXT@ \
- version.@OBJEXT@ \
- $(MISSING)
+RM = rm -f
+NM = @NM@
+AR = @AR@
+ARFLAGS = rcu
+RANLIB = @RANLIB@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+OBJEXT = @OBJEXT@
MANTYPE = @MANTYPE@
-SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \
- --make="$(MAKE)" \
- --mflags="$(MFLAGS)" \
- --make-flags="$(MAKEFLAGS)"
+INSTALLED_LIST= .installed.list
+#### End of variables
-all: @MAKEFILES@ miniruby$(EXEEXT) rbconfig.rb $(LIBRUBY)
- @$(MINIRUBY) $(srcdir)/ext/extmk.rb --extstatic="$(EXTSTATIC)" $(SCRIPT_ARGS)
+all:
-miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) $(DMYEXT)
- @rm -f $@
- $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(DMYEXT) $(LIBRUBY_A) $(LIBS) -o $@
+.DEFAULT: all
-$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(EXTOBJS) $(SETUP) miniruby$(EXEEXT)
- @rm -f $@
- $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
+# Prevent GNU make v3 from overflowing arg limit on SysV.
+.NOEXPORT:
+
+miniruby$(EXEEXT):
+ @$(RM) $@
+ $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(MINIOBJS) $(LIBRUBY_A) $(LIBS) $(OUTFLAG)$@
+
+$(PROGRAM):
+ @$(RM) $@
+ $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) $(OUTFLAG)$@
# We must `rm' the library each time this rule is invoked because "updating" a
# MAB library on Apple/NeXT (see --enable-fat-binary in configure) is not
# supported.
-$(LIBRUBY_A): $(OBJS) $(DMYEXT)
- @rm -f $@
- @AR@ rcu $@ $(OBJS) $(DMYEXT)
- @-@RANLIB@ $@ 2> /dev/null || true
-
-$(LIBRUBY_SO): $(OBJS) $(DLDOBJS) miniruby$(EXEEXT) $(PREP)
- $(LDSHARED) $(DLDFLAGS) $(OBJS) $(DLDOBJS) $(SOLIBS) -o $@
+$(LIBRUBY_A):
+ @$(RM) $@
+ $(AR) $(ARFLAGS) $@ $(OBJS) $(DMYEXT)
+ @-$(RANLIB) $@ 2> /dev/null || true
+
+$(LIBRUBY_SO):
+ @-$(PRE_LIBRUBY_UPDATE)
+ $(LDSHARED) $(DLDFLAGS) $(OBJS) $(DLDOBJS) $(SOLIBS) $(OUTFLAG)$@
@-$(MINIRUBY) -e 'ARGV.each{|link| File.delete link if File.exist? link; \
File.symlink "$(LIBRUBY_SO)", link}' \
$(LIBRUBY_ALIASES) || true
-ruby.imp: $(LIBRUBY_A)
- @@NM@ -Pgp $(LIBRUBY_A) | awk 'BEGIN{print "#!"}; $$2~/^[BD]$$/{print $$1}' | sort -u -o $@
-# $(MINIRUBY) $< $@
-
-install: rbconfig.rb
- $(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --mantype="$(MANTYPE)"
- $(MINIRUBY) $(srcdir)/ext/extmk.rb $(SCRIPT_ARGS) install
-
-what-where no-install: rbconfig.rb
- $(MINIRUBY) $(srcdir)/instruby.rb -n $(SCRIPT_ARGS) --mantype="$(MANTYPE)"
- $(MINIRUBY) $(srcdir)/ext/extmk.rb -n $(SCRIPT_ARGS) install
-
-clean-ext:
- @-$(MINIRUBY) $(srcdir)/ext/extmk.rb $(SCRIPT_ARGS) clean 2> /dev/null || true
-
-clean-local:
- @rm -f $(OBJS) $(MAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY_ALIASES)
- @rm -f ext/extinit.c ext/extinit.@OBJEXT@ dmyext.@OBJEXT@
- @rm -f $(PROGRAM) miniruby$(EXEEXT)
-
-clean: clean-ext clean-local
-
-distclean-ext:
- @-$(MINIRUBY) $(srcdir)/ext/extmk.rb $(SCRIPT_ARGS) distclean 2> /dev/null || true
-
-distclean-local: clean-local
- @rm -f @MAKEFILES@ config.h rbconfig.rb
- @rm -f ext/config.cache config.cache config.log config.status
- @rm -f *~ core *.core gmon.out y.tab.c y.output ruby.imp
-
-distclean: distclean-ext distclean-local
-
-realclean: distclean
- @rm -f parse.c
- @rm -f lex.c
-
-test: miniruby$(EXEEXT) rbconfig.rb $(PROGRAM) PHONY
- @./miniruby$(EXEEXT) $(srcdir)/rubytest.rb
-
-rbconfig.rb: miniruby$(EXEEXT) $(srcdir)/mkconfig.rb config.status $(PREP)
- @$(MINIRUBY) $(srcdir)/mkconfig.rb rbconfig.rb
-
-fake.rb: miniruby$(EXEEXT) Makefile
+fake.rb: Makefile
@echo ' \
class Object; \
CROSS_COMPILING = RUBY_PLATFORM; \
@@ -196,13 +141,7 @@ fake.rb: miniruby$(EXEEXT) Makefile
Makefile: $(srcdir)/Makefile.in
-.PRECIOUS: @MAKEFILES@
-
-.PHONY: test
-
-PHONY:
-
-@MAKEFILES@: config.status
+$(MKFILES): config.status $(srcdir)/common.mk
MAKE=$(MAKE) $(SHELL) ./config.status
@{ \
echo "all:; -@rm -f conftest.mk"; \
@@ -218,157 +157,46 @@ config.status: $(srcdir)/configure
$(srcdir)/configure: $(srcdir)/configure.in
cd $(srcdir) && $(AUTOCONF)
-.c.@OBJEXT@:
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
-
lex.c: keywords
- @-rm -f $@
- gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$$ $> > $@ || \
- cp "$(srcdir)/$@" .
+ ( gperf -C -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$$ $? > $@.tmp && mv $@.tmp $@ ) || \
+ if test -f $@; then \
+ touch $@ && echo $@ touched.; \
+ else \
+ cp $(srcdir)/lex.c $@ && echo $@ copied.; \
+ fi
.y.c:
$(YACC) $<
sed '/^#/s|y\.tab\.c|$@|' y.tab.c > $@
rm -f y.tab.c
-ext/extinit.@OBJEXT@: ext/extinit.c $(SETUP)
- $(CC) $(CFLAGS) $(CPPFLAGS) @OUTFLAG@$@ -c ext/extinit.c
-
-acosh.@OBJEXT@: $(srcdir)/missing/acosh.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/acosh.c
-
-alloca.@OBJEXT@: $(srcdir)/missing/alloca.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/alloca.c
-
-crypt.@OBJEXT@: $(srcdir)/missing/crypt.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/crypt.c
-
-dup2.@OBJEXT@: $(srcdir)/missing/dup2.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/dup2.c
-
-fileblocks.@OBJEXT@: $(srcdir)/missing/fileblocks.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/fileblocks.c
-
-finite.@OBJEXT@: $(srcdir)/missing/finite.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/finite.c
-
-flock.@OBJEXT@: $(srcdir)/missing/flock.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/flock.c
-
-isinf.@OBJEXT@: $(srcdir)/missing/isinf.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/isinf.c
-
-isnan.@OBJEXT@: $(srcdir)/missing/isnan.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/isnan.c
-
-fnmatch.@OBJEXT@: $(srcdir)/missing/fnmatch.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/fnmatch.c
-
-memcmp.@OBJEXT@: $(srcdir)/missing/memcmp.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/memcmp.c
-
-memmove.@OBJEXT@: $(srcdir)/missing/memmove.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/memmove.c
-
-mkdir.@OBJEXT@: $(srcdir)/missing/mkdir.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/mkdir.c
-
-vsnprintf.@OBJEXT@: $(srcdir)/missing/vsnprintf.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/vsnprintf.c
-
-strcasecmp.@OBJEXT@: $(srcdir)/missing/strcasecmp.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strcasecmp.c
-
-strncasecmp.@OBJEXT@: $(srcdir)/missing/strncasecmp.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strncasecmp.c
-
-strchr.@OBJEXT@: $(srcdir)/missing/strchr.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strchr.c
-
-strerror.@OBJEXT@: $(srcdir)/missing/strerror.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strerror.c
-
-strftime.@OBJEXT@: $(srcdir)/missing/strftime.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strftime.c
-
-strstr.@OBJEXT@: $(srcdir)/missing/strstr.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strstr.c
+.c.@OBJEXT@:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
-strtol.@OBJEXT@: $(srcdir)/missing/strtol.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strtol.c
+.s.@OBJEXT@:
+ $(AS) $(ASFLAGS) -o $@ $<
-strtoul.@OBJEXT@: $(srcdir)/missing/strtoul.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strtoul.c
+clean-local::
+ @$(RM) ext/extinit.c ext/extinit.$(OBJEXT)
-x68.@OBJEXT@: $(srcdir)/missing/x68.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/x68.c
+distclean-local::
+ @$(RM) ext/config.cache $(RBCONFIG)
-os2.@OBJEXT@: $(srcdir)/missing/os2.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/os2.c
+ext/extinit.$(OBJEXT): ext/extinit.c $(SETUP)
+ $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ -c ext/extinit.c
-dl_os2.@OBJEXT@: $(srcdir)/missing/dl_os2.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/dl_os2.c
+update-rubyspec:
+ if [ -d $(srcdir)/rubyspec ]; then \
+ cd $(srcdir)/rubyspec/mspec; \
+ git pull; \
+ cd ../spec/rubyspec; \
+ git pull; \
+ else \
+ git clone $(MSPEC_GIT_URL) $(srcdir)/rubyspec/mspec; \
+ git clone $(RUBYSPEC_GIT_URL) $(srcdir)/rubyspec/spec/rubyspec; \
+ fi
-win32.@OBJEXT@: $(srcdir)/win32/win32.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -I$(srcdir)/win32 -c $(srcdir)/win32/win32.c
+test-rubyspec:
+ @if [ ! -d $(srcdir)/rubyspec ]; then echo No rubyspec here. make update-rubyspec first.; exit 1; fi
+ $(RUNRUBY) $(srcdir)/rubyspec/mspec/bin/mspec -r$(srcdir)/ext/purelib.rb $(srcdir)/rubyspec/spec/rubyspec/$(MAJOR).$(MINOR)
-# Prevent GNU make v3 from overflowing arg limit on SysV.
-.NOEXPORT:
-###
-array.@OBJEXT@: array.c ruby.h config.h defines.h intern.h missing.h \
- util.h st.h
-bignum.@OBJEXT@: bignum.c ruby.h config.h defines.h intern.h missing.h
-class.@OBJEXT@: class.c ruby.h config.h defines.h intern.h missing.h \
- rubysig.h node.h st.h
-compar.@OBJEXT@: compar.c ruby.h config.h defines.h intern.h missing.h
-dir.@OBJEXT@: dir.c ruby.h config.h defines.h intern.h missing.h util.h
-dln.@OBJEXT@: dln.c ruby.h config.h defines.h intern.h missing.h dln.h
-dmyext.@OBJEXT@: dmyext.c
-enum.@OBJEXT@: enum.c ruby.h config.h defines.h intern.h missing.h node.h \
- util.h
-error.@OBJEXT@: error.c ruby.h config.h defines.h intern.h missing.h \
- env.h version.h st.h
-eval.@OBJEXT@: eval.c ruby.h config.h defines.h intern.h missing.h node.h \
- env.h util.h rubysig.h st.h dln.h
-file.@OBJEXT@: file.c ruby.h config.h defines.h intern.h missing.h \
- rubyio.h rubysig.h util.h dln.h
-gc.@OBJEXT@: gc.c ruby.h config.h defines.h intern.h missing.h rubysig.h \
- st.h node.h env.h re.h regex.h
-hash.@OBJEXT@: hash.c ruby.h config.h defines.h intern.h missing.h st.h \
- util.h rubysig.h
-inits.@OBJEXT@: inits.c ruby.h config.h defines.h intern.h missing.h
-io.@OBJEXT@: io.c ruby.h config.h defines.h intern.h missing.h rubyio.h \
- rubysig.h env.h util.h
-main.@OBJEXT@: main.c ruby.h config.h defines.h intern.h missing.h
-marshal.@OBJEXT@: marshal.c ruby.h config.h defines.h intern.h missing.h \
- rubyio.h st.h util.h
-math.@OBJEXT@: math.c ruby.h config.h defines.h intern.h missing.h
-numeric.@OBJEXT@: numeric.c ruby.h config.h defines.h intern.h missing.h
-object.@OBJEXT@: object.c ruby.h config.h defines.h intern.h missing.h \
- st.h util.h
-pack.@OBJEXT@: pack.c ruby.h config.h defines.h intern.h missing.h
-parse.@OBJEXT@: parse.c ruby.h config.h defines.h intern.h missing.h \
- env.h node.h st.h regex.h util.h lex.c
-prec.@OBJEXT@: prec.c ruby.h config.h defines.h intern.h missing.h
-process.@OBJEXT@: process.c ruby.h config.h defines.h intern.h missing.h \
- rubysig.h st.h
-random.@OBJEXT@: random.c ruby.h config.h defines.h intern.h missing.h
-range.@OBJEXT@: range.c ruby.h config.h defines.h intern.h missing.h
-re.@OBJEXT@: re.c ruby.h config.h defines.h intern.h missing.h re.h \
- regex.h
-regex.@OBJEXT@: regex.c config.h regex.h
-ruby.@OBJEXT@: ruby.c ruby.h config.h defines.h intern.h missing.h dln.h \
- node.h util.h
-signal.@OBJEXT@: signal.c ruby.h config.h defines.h intern.h missing.h \
- rubysig.h
-sprintf.@OBJEXT@: sprintf.c ruby.h config.h defines.h intern.h missing.h
-st.@OBJEXT@: st.c config.h st.h
-string.@OBJEXT@: string.c ruby.h config.h defines.h intern.h missing.h \
- re.h regex.h version.h
-struct.@OBJEXT@: struct.c ruby.h config.h defines.h intern.h missing.h
-time.@OBJEXT@: time.c ruby.h config.h defines.h intern.h missing.h
-util.@OBJEXT@: util.c ruby.h config.h defines.h intern.h missing.h util.h
-variable.@OBJEXT@: variable.c ruby.h config.h defines.h intern.h \
- missing.h env.h node.h st.h util.h
-version.@OBJEXT@: version.c ruby.h config.h defines.h intern.h missing.h \
- version.h
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000000..965ce6de5a
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,638 @@
+= NEWS
+
+This document is a list of user visible feature changes made between
+releases except for bug fixes.
+
+Note that each entry is kept so brief that no reason behind or
+reference information is supplied with. For a full list of changes
+with all sufficient information, see the ChangeLog file.
+
+* REXML
+
+ * REXML::Document.entity_expansion_limit=
+
+ New method to set the entity expansion limit. By default the limit is
+ set to 10000. See the following URL for details.
+
+ http://www.ruby-lang.org/en/news/2008/08/23/dos-vulnerability-in-rexml/
+
+== Changes since the 1.8.6 release
+
+=== Configuration changes
+
+* vendor_ruby directory
+
+ A new library directory named `vendor_ruby' is introduced in
+ addition to `site_ruby'. The idea is to separate libraries
+ installed by the package system (`vendor') from manually (`site')
+ installed libraries preventing the former from getting overwritten
+ by the latter, while preserving the user option to override vendor
+ libraries with site libraries. (`site_ruby' takes precedence over
+ `vendor_ruby')
+
+ If you are a package maintainer, make each library package configure
+ the library passing the `--vendor' option to `extconf.rb' so that
+ the library files will get installed under `vendor_ruby'.
+
+ You can change the directory locations using configure options such
+ as `--with-sitedir=DIR' and `--with-vendordir=DIR'.
+
+=== Global constants
+
+* new constants
+
+ * RUBY_COPYRIGHT
+ * RUBY_DESCRIPTION
+
+=== Library updates (outstanding ones only)
+
+* new library
+
+ * securerandom
+
+* builtin classes
+
+ * Array#flatten
+ * Array#flatten!
+
+ Takes an optional argument that determines the level of recursion
+ to flatten.
+
+ * Array#eql?
+ * Array#hash
+ * Array#==
+ * Array#<=>
+
+ Handle recursive data properly.
+
+ * Array#index
+ * Array#rindex
+
+ Take a block instead of an argument.
+
+ * Array#collect!
+ * Array#map!
+ * Array#each
+ * Array#each_index
+ * Array#reverse_each
+ * Array#reject
+ * Array#reject!
+ * Array#delete_if
+
+ Return an enumerator if no block is given.
+
+ Note that #map and #collect still return an array unlike Ruby 1.9
+ to keep compatibility.
+
+ * Array#pop
+ * Array#shift
+
+ Take an optional argument specifying the number of elements to
+ remove.
+
+ * Array#choice
+ * Array#combination
+ * Array#cycle
+ * Array#drop
+ * Array#drop_while
+ * Array#permutation
+ * Array#product
+ * Array#shuffle
+ * Array#shuffle!
+ * Array#take,
+ * Array#take_while
+
+ New methods.
+
+ * Binding#eval
+
+ New method.
+
+ * Dir#each
+ * Dir#foreach
+
+ Return an enumerator if no block is given.
+
+ * Enumerable::Enumerator
+
+ New class for various enumeration defined by the enumerator library.
+
+ * Enumerable#each_slice
+ * Enumerable#each_cons
+ * Object#to_enum
+ * Object#enum_for
+
+ New methods for various enumeration defined by the enumerator library.
+
+ * Enumerable#count
+ * Enumerable#cycle
+ * Enumerable#drop
+ * Enumerable#drop_while
+ * Enumerable#find_index
+ * Enumerable#first
+ * Enumerable#group_by
+ * Enumerable#max_by
+ * Enumerable#min_by
+ * Enumerable#minmax
+ * Enumerable#minmax_by
+ * Enumerable#none?
+ * Enumerable#one?
+ * Enumerable#take
+ * Enumerable#take_while
+
+ New methods.
+
+ * Enumerable#find
+ * Enumerable#find_all
+ * Enumerable#partition
+ * Enumerable#reject
+ * Enumerable#select
+ * Enumerable#sort_by
+
+ Return an enumerator if no block is given.
+
+ Note that #map and #collect still return an array unlike Ruby 1.9
+ to keep compatibility.
+
+ * Enumerable#inject
+
+ Accepts a binary operator instead of a block.
+
+ * Enumerable#reduce
+
+ New alias to #inject.
+
+ * Hash#eql?
+ * Hash#hash
+ * Hash#==
+
+ Handle recursive data properly.
+
+ * Hash#delete_if
+ * Hash#each
+ * Hash#each_key
+ * Hash#each_pair
+ * Hash#each_value
+ * Hash#reject!
+ * Hash#select
+ * ENV.delete_if
+ * ENV.each
+ * ENV.each_key
+ * ENV.each_pair
+ * ENV.each_value
+ * ENV.reject!
+ * ENV.select
+
+ Return an enumerator if no block is given.
+
+ * GC.stress
+ * GC.stress=
+
+ New methods.
+
+ * Integer#ord
+ * Integer#odd?
+ * Integer#even?
+ * Integer#pred
+
+ New methods.
+
+ * Integer#downto
+ * Integer#times
+ * Integer#upto
+
+ Return an enumerator if no block is given.
+
+ * IO#each
+ * IO#each_line
+ * IO#each_byte
+ * IO.foreach
+ * ARGF.each
+ * ARGF.each_line
+ * ARGF.each_byte
+
+ Return an enumerator if no block is given.
+
+ * IO#bytes
+ * IO#chars
+ * IO#each_char
+ * IO#getbyte
+ * IO#lines
+ * IO#readbyte
+ * ARGF.bytes
+ * ARGF.chars
+ * ARGF.each_char
+ * ARGF.getbyte
+ * ARGF.lines
+ * ARGF.readbyte
+
+ New methods.
+
+ * Method#name
+ * Method#owner
+ * Method#receiver
+ * UnboundMethod#name
+ * UnboundMethod#owner
+
+ New methods.
+
+ * Module#class_exec
+ * Module#module_exec
+
+ New methods.
+
+ * Numeric#step
+
+ Return an enumerator if no block is given.
+
+ * Object#instance_exec
+ * Object#tap
+
+ New methods.
+
+ * ObjectSpace.each_object
+
+ Return an enumerator if no block is given.
+
+ * Process.exec implemented.
+
+ * Range#each
+ * Range#step
+
+ Return an enumerator if no block is given.
+
+ * Regexp.union accepts an array of patterns.
+
+ * String#bytesize
+
+ New method, returning the size in bytes. (alias length and size)
+
+ * String#chars
+ * String#each_char
+ * String#partition
+ * String#rpartition
+ * String#start_with?
+ * String#end_with?
+
+ New methods. These are $KCODE aware unlike #index, #rindex and
+ #include?.
+
+ * String#each_byte
+ * String#each
+ * String#each_line
+ * String#gsub(pattern)
+
+ Return an enumerator if no block is given.
+
+ * String#upto
+
+ An optional second argument is added to specify if the last value
+ should be included.
+
+ * StopIteration
+
+ New exception class that causes Kernel#loop to stop iteration when
+ raised.
+
+ * Struct#each
+ * Struct#each_pair
+
+ Return an enumerator if no block is given.
+
+ * Symbol#to_proc
+
+ New method.
+
+ * __method__
+
+ New global function that returns the name of the current method as
+ a Symbol.
+
+* enumerator
+
+ * Enumerator is now a built-in module. The #next and #rewind
+ methods are implemented using the "generator" library. Use with
+ care and be aware of the performance loss.
+
+* ipaddr
+
+ * New methods
+ * IPAddr#<=>
+ * IPAddr#succ
+
+ IPAddr objects are now comparable and enumerable having these
+ methods. This also means that it is possible to have a Range
+ object between two IPAddr objects.
+
+ * IPAddr#to_range
+
+ A new method to create a Range object for the (network) address.
+
+ * Type coercion support
+ * IPAddr#&
+ * IPAddr#|
+ * IPAddr#==
+ * IPAddr#include?
+
+ These methods now accept a string or an integer instead of an
+ IPAddr object as the argument.
+
+* net/smtp
+
+ * Support SSL/TLS.
+
+* openssl
+
+ * New classes
+ * OpenSSL::PKey::EC
+ * OpenSSL::PKey::EC::Group
+ * OpenSSL::PKey::EC::Point
+ * OpenSSL::PKey::PKCS5
+ * OpenSSL::SSL::Session
+
+ * Documentation!
+
+ * Various new methods (see documentation).
+
+ * Remove redundant module namespace in Cipher, Digest, PKCS7, PKCS12.
+ Compatibility classes are provided which will be removed in Ruby 1.9.
+
+* shellwords
+
+ * Add methods for escaping shell-unsafe characters:
+ * Shellwords.join
+ * Shellwords.escape
+ * Array#shelljoin
+ * String#shellescape
+
+ * Add shorthand methods:
+ * Shellwords.split (alias shellwords)
+ * String#shellsplit
+
+* stringio
+
+ * StringIO#getbyte
+ * StringIO#readbyte
+
+ New methods. (aliases for compatibility with 1.9)
+
+ * StringIO#each_char
+ * StringIO#chars
+
+ New methods.
+
+ * StringIO#each
+ * StringIO#each_line
+ * StringIO#each_byte
+
+ Return an enumerator if no block is given.
+
+* tempfile
+
+ * Tempfile.open and Tempfile.new now accept a suffix for the
+ temporary file to be created. To specify a suffix, pass an array
+ of [basename, suffix] as the first argument.
+
+ Tempfile.open(['image', 'jpg']) { |tempfile| ... }
+
+* tmpdir
+
+ * New method:
+
+ * Dir.mktmpdir
+
+* uri
+
+ * added LDAPS scheme.
+ * Change for RFC3986:
+ * FTP
+ * URI('ftp://example.com/foo').path #=> 'foo'
+ * URI('ftp://example.com/%2Ffoo').path #=> '/foo'
+ * URI::FTP.build([nil, 'example.com', nil, '/foo', 'i').to_s #=> 'ftp://example.com/%2Ffoo;type=i'
+ * URI merge
+ * URI('http://a/b/c/d;p?q').merge('?y') == URI('http://a/b/c/d;p?y')
+ * URI('http://a/b/c/d;p?q').merge('/./g') == URI('http://a/g')
+ * URI('http://a/b/c/d;p?q').merge('/../g') == URI('http://a/g')
+ * URI('http://a/b/c/d;p?q').merge('../../../g') == URI('http://a/g')
+ * URI('http://a/b/c/d;p?q').merge('../../../../g') == URI('http://a/g')
+
+* rss
+
+ * 0.1.6 -> 0.2.4
+
+ * Fix image module URI
+
+ * Atom support
+
+ * ITunes module support
+
+ * Slash module support
+
+ * content:encoded with RSS 2.0 support
+
+=== Interpreter Implementation
+
+* passing a block to a Proc [experimental]
+
+ This implementation in current shape is known to be buggy/broken,
+ especially with nested block invocation. Take this as an
+ experimental feature.
+
+* stack trace
+
+ On non-SystemStackError exception, full stack trace is shown.
+
+=== Compatibility issues (excluding feature bug fixes)
+
+* String#slice! had some unintentional bugs and they have been fixed
+ because either they disagreed with documentation or their respective
+ behavior of #slice. Unfortunately, this causes some
+ incompatibilities in the following (somewhat rare) cases.
+
+ * #slice! no longer expands the array when an out-of-boundary value
+ is given.
+
+ # Ruby 1.8.6
+ a = [1,2]
+ a.slice!(4,0) #=> nil
+ a #=> [1,2,nil,nil]
+
+ # Ruby 1.8.7
+ a = [1,2]
+ a.slice!(4,0) #=> nil
+ a #=> [1,2]
+
+ * #slice! no longer raises an exception but returns nil when a
+ negative length or out-of-boundary negative position is given.
+
+ # Ruby 1.8.6
+ a = [1,2]
+ a.slice!(1,-1) #=> (raises IndexError)
+ a.slice!(-5,1) #=> (raises IndexError)
+
+ # Ruby 1.8.7
+ a = [1,2]
+ a.slice!(1,-1) #=> nil
+ a.slice!(-5,1) #=> nil
+
+* String#to_i, String#hex and String#oct no longer accept a sequence
+ of underscores (`__') as part of a number.
+
+ # Ruby 1.8.6
+ '1__0'.to_i #=> 10
+ '1__0'.to_i(2) #=> 2 # 0b10
+ '1__0'.oct #=> 8 # 010
+ '1__0'.hex #=> 16 # 0x10
+
+ # Ruby 1.8.7
+ '1__0'.to_i #=> 1
+ '1__0'.to_i(2) #=> 1
+ '1__0'.oct #=> 1
+ '1__0'.hex #=> 1
+
+ The old behavior was inconsistent with Ruby syntax and considered as
+ a bug.
+
+* date
+
+ * Date.parse
+
+ '##.##.##' (where each '#' is a digit) is now taken as 'YY.MM.DD'
+ instead of 'MM.DD.YY'. While the change may confuse you, you can
+ always use Date.strptime() when you know what you are dealing
+ with.
+
+* stringio
+
+ * StringIO#each_byte
+
+ The return value changed from nil to self. This is what the
+ document says and the same as each_line() does.
+
+* tempfile
+
+ * The file name format has changed. No dots are included by default
+ in temporary file names any more. See above for how to specify a
+ suffix.
+
+* uri
+
+ * See above for details.
+
+== Changes since the 1.8.5 release
+
+=== New platforms/build tools support
+
+* IA64 HP-UX
+
+* Visual C++ 8 SP1
+
+* autoconf 2.6x
+
+=== Global constants
+
+* RUBY_PATCHLEVEL
+
+ New constant since 1.8.5-p1.
+
+=== Library updates (outstanding ones only)
+
+* builtin classes
+
+ * New method: Kernel#instance_variable_defined?
+
+ * New method: Module#class_variable_defined?
+
+ * New feature: Dir::glob() can now take an array of glob patterns.
+
+* date
+
+ * Updated based on date2 4.0.3.
+
+* digest
+
+ * New internal APIs for C and Ruby.
+
+ * Support for autoloading.
+
+ require 'digest'
+
+ # autoloads digest/md5
+ md = Digest::MD5.digest("string")
+
+ * New digest class methods: file
+
+ * New digest instance methods: clone, reset, new, inspect,
+ digest_length (alias size or length), block_length()
+
+ * New library: digest/bubblebabble
+
+ * New function: Digest(name)
+
+* fileutils
+
+ * New option for FileUtils.cp_r(): :remove_destination
+
+* nkf
+
+ * Updated based on nkf as of 2007-01-28.
+
+* thread
+
+ * Replaced with much faster mutex implementation in C. The former
+ implementation, which is slow but considered to be stable, is
+ available with a configure option `--disable-fastthread'.
+
+* tk
+
+ * Updated Tile extension support based on Tile 0.7.8.
+
+ * Support --without-X11 configure option for non-X11 versions of
+ Tcl/Tk (e.g. Tcl/Tk Aqua).
+
+ * New sample script: irbtkw.rbw -- IRB on Ruby/Tk. It has no trouble
+ about STDIN blocking on Windows.
+
+* webrick
+
+ * New method: WEBrick::Cookie.parse_set_cookies()
+
+=== Compatibility issues (excluding feature bug fixes)
+
+* builtin classes
+
+ * String#intern now raises SecurityError when $SAFE level is greater
+ than zero.
+
+* date
+
+ * Time#to_date and Time#to_datetime are added as private methods.
+ They cause name conflict error in ActiveSupport 1.4.1 and prior,
+ which comes with Rails 1.2.2 and prior. Updating ActiveSupport
+ and/or Rails to the latest versions fixes the problem.
+
+* digest
+
+ * The constructor does no longer take an initial string to feed.
+ The following examples show how to migrate:
+
+ # Before
+ md = Digest::MD5.new("string")
+ # After (works with any version)
+ md = Digest::MD5.new.update("string")
+
+ # Before
+ hd = Digest::MD5.new("string").hexdigest
+ # After (works with any version)
+ hd = Digest::MD5.hexdigest("string")
+
+* fileutils
+
+ * A minor implementation change breaks Rake <=0.7.1.
+ Updating Rake to 0.7.2 or higher fixes the problem.
+
+* tk
+
+ * Tk::X_Scrollable (Y_Scrollable) is renamed to Tk::XScrollable
+ (YScrollable). Tk::X_Scrollable (Y_Scrollable) is still available,
+ but it is an alias name.
diff --git a/README b/README
index bde22dff78..1b79781367 100644
--- a/README
+++ b/README
@@ -22,16 +22,24 @@ Perl). It is simple, straight-forward, and extensible.
* How to get Ruby
-The Ruby distribution can be found on:
+The Ruby distribution files can be found in the following FTP site:
ftp://ftp.ruby-lang.org/pub/ruby/
-You can get it by anonymous CVS. How to check out is:
+The latest source code of this version series can be checked out
+through SVN with the following command:
- $ cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login
- (Logging in to anonymous@cvs.ruby-lang.org)
- CVS password: anonymous
- $ cvs -z4 -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout ruby
+ $ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8/
+
+The trunk of the Ruby source tree can be checked out with the
+following command:
+
+ $ svn co http://svn.ruby-lang.org/repos/ruby/trunk/ ruby
+
+There are some other branches under development. Try the following
+command and see the list of branches:
+
+ $ svn ls http://svn.ruby-lang.org/repos/ruby/branches/
* Ruby home-page
@@ -62,7 +70,11 @@ This is what you need to do to compile and install Ruby:
2. Run ./configure, which will generate config.h and Makefile.
- 3. Edit defines.h if you need. Probably this step will not need.
+ Some C compiler flags may be added by default depending on your
+ environment. Specify optflags=.. and warnflags=.. as necessary
+ to override them.
+
+ 3. Edit defines.h if you need. Usually this step will not be needed.
4. Remove comment mark(#) before the module names from ext/Setup (or
add module names if not present), if you want to link modules
diff --git a/README.EXT b/README.EXT
index 3a37db4e11..637b19d25b 100644
--- a/README.EXT
+++ b/README.EXT
@@ -8,8 +8,8 @@ In C, variables have types and data do not have types. In contrast,
Ruby variables do not have a static type, and data themselves have
types, so data will need to be converted between the languages.
-Data in Ruby are represented by C type `VALUE'. Each VALUE data has
-its data-type.
+Data in Ruby are represented by the C type `VALUE'. Each VALUE data
+has its data-type.
To retrieve C data from a VALUE, you need to:
@@ -91,31 +91,31 @@ The data for type T_NIL, T_FALSE, T_TRUE are nil, true, false
respectively. They are singletons for the data type.
The T_FIXNUM data is a 31bit length fixed integer (63bit length on
-some machines), which can be convert to a C integer by using the
+some machines), which can be converted to a C integer by using the
FIX2INT() macro. There is also NUM2INT() which converts any Ruby
numbers into C integers. The NUM2INT() macro includes a type check, so
an exception will be raised if the conversion failed. NUM2DBL() can
-be used to retrieve the double float value in same way.
+be used to retrieve the double float value in the same way.
-To get char* from a VALUE, version 1.7 recommend to use new macros
-StringValue() and StringValuePtr(). StringValue(var) replaces var's
-value to the result of "var.to_str()". StringValuePtr(var) does same
-replacement and returns char* representation of var. These macros
-will skip the replacement if var is a String. Notice that the macros
-requires to take only lvalue as their argument, to change the value
-of var in the replacement.
+In version 1.7 or later it is recommended that you use the new macros
+StringValue() and StringValuePtr() to get a char* from a VALUE.
+StringValue(var) replaces var's value with the result of "var.to_str()".
+StringValuePtr(var) does same replacement and returns char*
+representation of var. These macros will skip the replacement if var is
+a String. Notice that the macros take only the lvalue as their
+argument, to change the value of var in place.
-In version 1.6 or earlier, STR2CSTR() was used to do same thing
-but now it is obsoleted in version 1.7 because of STR2CSTR() has
-a risk of dangling pointer problem in to_str() impliclit conversion.
+In version 1.6 or earlier, STR2CSTR() was used to do the same thing
+but now it is deprecated in version 1.7, because STR2CSTR() has a risk
+of a dangling pointer problem in the to_str() impliclit conversion.
Other data types have corresponding C structures, e.g. struct RArray
-for T_ARRAY etc. The VALUE of the type which has corresponding structure
+for T_ARRAY etc. The VALUE of the type which has the corresponding structure
can be cast to retrieve the pointer to the struct. The casting macro
will be of the form RXXXX for each data type; for instance, RARRAY(obj).
See "ruby.h".
-For example, `RSTRING(size)->len' is the way to get the size of the
+For example, `RSTRING(str)->len' is the way to get the size of the
Ruby String object. The allocated region can be accessed by
`RSTRING(str)->ptr'. For arrays, use `RARRAY(ary)->len' and
`RARRAY(ary)->ptr' respectively.
@@ -205,7 +205,7 @@ interpreter. Some (not all) of the useful functions are listed below:
rb_ary_unshift(VALUE ary, VALUE val)
Array operations. The first argument to each functions must be an
- array. They may dump core if other types given.
+ array. They may dump core if other types are given.
2. Extending Ruby with C
@@ -244,7 +244,7 @@ To define methods or singleton methods, use these functions:
VALUE (*func)(), int argc)
The `argc' represents the number of the arguments to the C function,
-which must be less than 17. But I believe you don't need that much. :-)
+which must be less than 17. But I doubt you'll need that many.
If `argc' is negative, it specifies the calling sequence, not number of
the arguments.
@@ -272,7 +272,7 @@ private methods:
The other is to define module functions, which are private AND singleton
methods of the module. For example, sqrt is the module function
-defined in Math module. It can be call in the form like:
+defined in Math module. It can be called in the following way:
Math.sqrt(4)
@@ -291,10 +291,19 @@ in the Kernel module, can be defined using:
void rb_define_global_function(const char *name, VALUE (*func)(), int argc)
-To define alias to the method,
+To define an alias for the method,
void rb_define_alias(VALUE module, const char* new, const char* old);
+To define and undefine the `allocate' class method,
+
+ void rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE klass));
+ void rb_undef_alloc_func(VALUE klass);
+
+func have to take the klass as the argument and return a newly
+allocated instance. This instance should be empty as possible,
+without any expensive (including external) resources.
+
2.1.3 Constant definition
We have 2 functions to define constants:
@@ -312,7 +321,7 @@ There are several ways to invoke Ruby's features from C code.
2.2.1 Evaluate Ruby Programs in a String
The easiest way to use Ruby's functionality from a C program is to
-evaluate the string as Ruby program. This function will do the job.
+evaluate the string as Ruby program. This function will do the job:
VALUE rb_eval_string(const char *str)
@@ -321,17 +330,30 @@ of the innermost method (which is defined by Ruby) can be accessed.
2.2.2 ID or Symbol
-You can invoke methods directly, without parsing the string. First I
-need to explain about symbols (whose data type is ID). ID is the
-integer number to represent Ruby's identifiers such as variable names.
-It can be accessed from Ruby in the form:
+You can invoke methods directly, without parsing the string. First I need
+to explain about ID. ID is the integer number to represent Ruby's
+identifiers such as variable names. The Ruby data type corresponding to ID
+is Symbol. It can be accessed from Ruby in the form:
:Identifier
-You can get the symbol value from a string within C code by using
+You can get the ID value from a string within C code by using
rb_intern(const char *name)
+You can retrieve ID from Ruby object (Symbol or String) given as an
+argument by using
+
+ rb_to_id(VALUE symbol)
+
+You can convert C ID to Ruby Symbol by using
+
+ VALUE ID2SYM(ID id)
+
+and to convert Ruby Symbol object to ID, use
+
+ ID SYM2ID(VALUE symbol)
+
2.2.3 Invoke Ruby method from C
To invoke methods directly, you can use the function below
@@ -412,7 +434,7 @@ The prototypes of the getter and setter functions are as follows:
(*getter)(ID id, void *data, struct global_entry* entry);
(*setter)(VALUE val, ID id, void *data, struct global_entry* entry);
-3.3 Encapsulate C data into Ruby object
+3.3 Encapsulate C data into a Ruby object
To wrap and objectify a C pointer as a Ruby object (so called
DATA), use Data_Wrap_Struct().
@@ -460,19 +482,11 @@ directory in the Ruby's source tree.
Make a directory for the extension library under ext directory.
-(2) create MANIFEST file
-
- % cd ext/dbm
- % touch MANIFEST
-
-There should be MANIFEST file in the directory for the extension
-library. Make an empty file for now.
-
-(3) design the library
+(2) design the library
You need to design the library features, before making it.
-(4) write C code.
+(3) write C code.
You need to write C code for your extension library. If your library
has only one source file, choosing ``LIBRARY.c'' as a file name is
@@ -600,13 +614,12 @@ are not exported to the Ruby world. You need to protect them by
void rb_global_variable(VALUE *var)
-(5) prepare extconf.rb
+(4) prepare extconf.rb
If the file named extconf.rb exists, it will be executed to generate
-Makefile. If not, the compilation scheme will try to generate Makefile
-anyway.
+Makefile.
-extconf.rb is the file for check compilation conditions etc. You
+extconf.rb is the file for checking compilation conditions etc. You
need to put
require 'mkmf'
@@ -621,57 +634,59 @@ various conditions.
The value of the variables below will affect the Makefile.
- $CFLAGS: included in CFLAGS make variable (such as -I)
+ $CFLAGS: included in CFLAGS make variable (such as -O)
+ $CPPFLAGS: included in CPPFLAGS make variable (such as -I, -D)
$LDFLAGS: included in LDFLAGS make variable (such as -L)
+ $objs: list of object file names
+
+Normally, the object files list is automatically generated by searching
+source files, but you must define them explicitly if any sources will
+be generated while building.
If a compilation condition is not fulfilled, you should not call
-``create_makefile''. The Makefile will not generated, compilation will
+``create_makefile''. The Makefile will not be generated, compilation will
not be done.
-(6) prepare depend (optional)
+(5) prepare depend (optional)
If the file named depend exists, Makefile will include that file to
check dependencies. You can make this file by invoking
% gcc -MM *.c > depend
-It's no harm. Prepare it.
-
-(7) put file names into MANIFEST (optional)
-
- % find * -type f -print > MANIFEST
- % vi MANIFEST
+It's harmless. Prepare it.
-Append file names into MANIFEST. The compilation scheme requires
-MANIFEST only to exist, but it's better to take this step in order
-to distinguish which files are required.
-
-(8) generate Makefile
+(6) generate Makefile
Try generating the Makefile by:
ruby extconf.rb
+If the library should be installed under vendor_ruby directory
+instead of site_ruby directory, use --vendor option as follows.
+
+ ruby extconf.rb --vendor
+
You don't need this step if you put the extension library under the ext
directory of the ruby source tree. In that case, compilation of the
interpreter will do this step for you.
-(9) make
+(7) make
Type
make
to compile your extension. You don't need this step either if you have
-put extension library under the ext directory of the ruby source tree.
+put the extension library under the ext directory of the ruby source tree.
-(9) debug
+(8) debug
You may need to rb_debug the extension. Extensions can be linked
-statically by the adding directory name in the ext/Setup file so that
+statically by adding the directory name in the ext/Setup file so that
you can inspect the extension with the debugger.
-(10) done, now you have the extension library
+(9) done, now you have the extension library
You can do anything you want with your library. The author of Ruby
will not claim any restrictions on your code depending on the Ruby API.
@@ -789,7 +804,9 @@ NUM2INT(value)
INT2NUM(i)
NUM2DBL(value)
rb_float_new(f)
-STR2CSTR(value)
+StringValue(value)
+StringValuePtr(value)
+StringValueCStr(value)
rb_str_new2(s)
** defining class/module
@@ -807,7 +824,7 @@ namespace.
Defines a new Ruby module.
- VALUE rb_define_module_under(VALUE module, const char *name, VALUE super)
+ VALUE rb_define_module_under(VALUE module, const char *name)
Defines a new Ruby module under the module's namespace.
@@ -831,15 +848,15 @@ it can't be seen from Ruby programs.
void rb_define_readonly_variable(const char *name, VALUE *var)
Defines a read-only global variable. Works just like
-rb_define_variable(), except defined variable is read-only.
+rb_define_variable(), except the defined variable is read-only.
void rb_define_virtual_variable(const char *name,
VALUE (*getter)(), VALUE (*setter)())
Defines a virtual variable, whose behavior is defined by a pair of C
functions. The getter function is called when the variable is
-referred. The setter function is called when the value is set to the
-variable. The prototype for getter/setter functions are:
+referenced. The setter function is called when the variable is set to a
+value. The prototype for getter/setter functions are:
VALUE getter(ID id)
void setter(VALUE val, ID id)
@@ -999,7 +1016,7 @@ Terminates the interpreter immediately. This function should be
called under the situation caused by the bug in the interpreter. No
exception handling nor ensure execution will be done.
-** Initialize and Starts the Interpreter
+** Initialize and Start the Interpreter
The embedding API functions are below (not needed for extension libraries):
@@ -1019,10 +1036,41 @@ Starts execution of the interpreter.
Specifies the name of the script ($0).
+** Hooks for the Interpreter Events
+
+ void rb_add_event_hook(rb_event_hook_func_t func, rb_event_t events)
+
+Adds a hook function for the specified interpreter events.
+events should be Or'ed value of:
+
+ RUBY_EVENT_LINE
+ RUBY_EVENT_CLASS
+ RUBY_EVENT_END
+ RUBY_EVENT_CALL
+ RUBY_EVENT_RETURN
+ RUBY_EVENT_C_CALL
+ RUBY_EVENT_C_RETURN
+ RUBY_EVENT_RAISE
+ RUBY_EVENT_ALL
+
+The definition of rb_event_hook_func_t is below:
+
+ typedef void (*rb_event_hook_func_t)(rb_event_t event, NODE *node,
+ VALUE self, ID id, VALUE klass)
+
+ int rb_remove_event_hook(rb_event_hook_func_t func)
+
+Removes the specified hook function.
+
Appendix C. Functions Available in extconf.rb
These functions are available in extconf.rb:
+ have_macro(macro, headers)
+
+Checks whether macro is defined with header. Returns true if the macro
+is defined.
+
have_library(lib, func)
Checks whether the library exists, containing the specified function.
@@ -1039,20 +1087,61 @@ Checks whether func exists with header. Returns true if the function
exists. To check functions in an additional library, you need to
check that library first using have_library().
+ have_var(var, header)
+
+Checks whether var exists with header. Returns true if the variable
+exists. To check variables in an additional library, you need to
+check that library first using have_library().
+
have_header(header)
Checks whether header exists. Returns true if the header file exists.
+ find_header(header, path...)
+
+Checks whether header exists in path. Returns true if the header file
+exists.
+
+ have_struct_member(type, member, header)
+
+Checks whether type has member with header. Returns true if the type
+is defined and has the member.
+
+ have_type(type, header, opt)
+
+Checks whether type is defined with header. Returns true if the type
+is defined.
+
+ check_sizeof(type, header)
+
+Checks the size of type in char with header. Returns the size if the
+type is defined, otherwise nil.
+
create_makefile(target)
Generates the Makefile for the extension library. If you don't invoke
this method, the compilation will not be done.
+ find_executable(bin, path)
+
+Finds command in path, which is File::PATH_SEPARATOR-separated list of
+directories. If path is nil or omitted, environment varialbe PATH
+will be used. Returns the path name of the command if it is found,
+otherwise nil.
+
with_config(withval[, default=nil])
Parses the command line options and returns the value specified by
--with-<withval>.
+ enable_config(config, *defaults)
+ disable_config(config, *defaults)
+
+Parses the command line options for boolean. Returns true if
+--enable-<config> is given, or false if --disable-<config> is given.
+Otherwise, yields defaults to the given block and returns the result
+if it is called with a block, or returns defaults.
+
dir_config(target[, default_dir])
dir_config(target[, default_include, default_lib])
@@ -1062,6 +1151,12 @@ to $CFLAGS and/or $LDFLAGS. --with-<target>-dir=/path is equivalent to
--with-<target>-include=/path/include --with-<target>-lib=/path/lib.
Returns an array of the added directories ([include_dir, lib_dir]).
+ pkg_config(pkg)
+
+Obtains the information for pkg by pkg-config command. The actual
+command name can be overriden by --with-pkg-config command line
+option.
+
/*
* Local variables:
* fill-column: 70
diff --git a/README.EXT.ja b/README.EXT.ja
index f49083e60e..73425c2cdb 100644
--- a/README.EXT.ja
+++ b/README.EXT.ja
@@ -331,6 +331,17 @@ private¥á¥½¥Ã¥É¤È¤Ï´Ø¿ô·Á¼°¤Ç¤·¤«¸Æ¤Ó½Ð¤¹¤³¤È¤Î½ÐÍè¤Ê¤¤¥á¥½¥Ã
void rb_define_alias(VALUE module, const char* new, const char* old);
+¥¯¥é¥¹¥á¥½¥Ã¥Éallocate¤òÄêµÁ¤·¤¿¤êºï½ü¤·¤¿¤ê¤¹¤ë¤¿¤á¤Î´Ø¿ô¤Ï
+°Ê²¼¤ÎÄ̤ê¤Ç¤¹¡£
+
+ void rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE klass));
+ void rb_undef_alloc_func(VALUE klass);
+
+func¤Ï¥¯¥é¥¹¤ò°ú¿ô¤È¤·¤Æ¼õ¤±¼è¤Ã¤Æ¡¢¿·¤·¤¯³ä¤êÅö¤Æ¤é¤ì¤¿¥¤¥ó
+¥¹¥¿¥ó¥¹¤òÊÖ¤µ¤Ê¤¯¤Æ¤Ï¤Ê¤ê¤Þ¤»¤ó¡£¤³¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Ï¡¢³°Éô¥ê
+¥½¡¼¥¹¤Ê¤É¤ò´Þ¤Þ¤Ê¤¤¡¢¤Ç¤­¤ë¤À¤±¡Ö¶õ¡×¤Î¤Þ¤Þ¤Ë¤·¤Æ¤ª¤¤¤¿¤Û¤¦
+¤¬¤è¤¤¤Ç¤·¤ç¤¦¡£
+
2.1.3 Äê¿ôÄêµÁ
³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤¬É¬ÍפÊÄê¿ô¤Ï¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤
@@ -369,7 +380,8 @@ C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤ËRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ
¤¹¡¥¤½¤ÎÁ°¤Ë¡¤Ruby¥¤¥ó¥¿¥×¥ê¥¿Æâ¤Ç¥á¥½¥Ã¥É¤äÊÑ¿ô̾¤ò»ØÄꤹ¤ë
»þ¤Ë»È¤ï¤ì¤Æ¤¤¤ëID¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤ª¤­¤Þ¤·¤ç¤¦¡¥
-ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥Ruby¤ÎÃæ¤Ç¤Ï
+ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥Ruby¤Ç¤ÏID¤ËÂбþ¤¹¤ë
+¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ¥·¥ó¥Ü¥ë(Symbol)¤¬¤¢¤ê¡¤
:¼±ÊÌ»Ò
@@ -382,6 +394,14 @@ ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥Ruby¤ÎÃæ¤Ç¤Ï
rb_to_id(VALUE symbol)
+ID¤«¤é¥·¥ó¥Ü¥ë¤òÆÀ¤ë¤¿¤á¤Ë¤Ï°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤¤¤Þ¤¹¡¥
+
+ VALUE ID2SYM(ID id)
+
+¥·¥ó¥Ü¥ë¤«¤éID¤òÆÀ¤ë¤¿¤á¤Ë¤Ï°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤¤¤Þ¤¹¡¥
+
+ ID SYM2ID(VALUE symbol)
+
2.2.3 C¤«¤éRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹
C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤ËRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼
@@ -542,28 +562,14 @@ Ruby 1.1¤«¤é¤ÏǤ°Õ¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî
¥é¥¤¥Ö¥é¥êÍѤΥǥ£¥ì¥¯¥È¥ê¤òºî¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥Ì¾Á°¤ÏŬÅö¤Ë
Áª¤ó¤Ç¹½¤¤¤Þ¤»¤ó¡¥
-(2) MANIFEST¥Õ¥¡¥¤¥ë¤òºî¤ë
-
- % cd ext/dbm
- % touch MANIFEST
-
-³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Ë¤ÏMANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬
-ɬÍפʤΤǡ¤¤È¤ê¤¢¤¨¤º¶õ¤Î¥Õ¥¡¥¤¥ë¤òºî¤Ã¤Æ¤ª¤­¤Þ¤¹¡¥¸å¤Ç¤³¤Î
-¥Õ¥¡¥¤¥ë¤Ë¤ÏɬÍפʥե¡¥¤¥ë°ìÍ÷¤¬Æþ¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
-
-MANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï¡¤ÀÅŪ¥ê¥ó¥¯¤Îmake¤Î»þ¤Ë¥Ç¥£¥ì¥¯¥È¥ê
-¤¬³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò´Þ¤ó¤Ç¤¤¤ë¤«¤É¤¦¤«È½Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ì¤Æ
-¤¤¤Þ¤¹¡¥¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî¤ë¾ì¹ç¤Ë¤Ïɬ¤º¤·¤âɬÍפǤÏ
-¤¢¤ê¤Þ¤»¤ó¡¥
-
-(3) À߷פ¹¤ë
+(2) À߷פ¹¤ë
¤Þ¤¢¡¤ÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¤¤É¤¦¤¤¤¦µ¡Ç½¤ò¼Â¸½¤¹¤ë¤«¤É¤¦¤«¤Þ¤ºÀß
·×¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¤É¤ó¤Ê¥¯¥é¥¹¤ò¤Ä¤¯¤ë¤«¡¤¤½¤Î¥¯¥é¥¹¤Ë¤Ï
¤É¤ó¤Ê¥á¥½¥Ã¥É¤¬¤¢¤ë¤«¡¤¥¯¥é¥¹¤¬Ä󶡤¹¤ëÄê¿ô¤Ê¤É¤Ë¤Ä¤¤¤ÆÀß·×
¤·¤Þ¤¹¡¥
-(4) C¥³¡¼¥É¤ò½ñ¤¯
+(3) C¥³¡¼¥É¤ò½ñ¤¯
³ÈÄ¥¥é¥¤¥Ö¥é¥êËÜÂΤȤʤëC¸À¸ì¤Î¥½¡¼¥¹¤ò½ñ¤­¤Þ¤¹¡¥C¸À¸ì¤Î¥½¡¼
¥¹¤¬¤Ò¤È¤Ä¤Î»þ¤Ë¤Ï¡Ö¥é¥¤¥Ö¥é¥ê̾.c¡×¤òÁª¤Ö¤ÈÎɤ¤¤Ç¤·¤ç¤¦¡¥C
@@ -706,7 +712,7 @@ C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤ÆRuby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß
void rb_global_variable(VALUE *var)
-(5) extconf.rb¤òÍѰդ¹¤ë
+(4) extconf.rb¤òÍѰդ¹¤ë
Makefile¤òºî¤ë¾ì¹ç¤Î¿÷·¿¤Ë¤Ê¤ëextconf.rb¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤òºî¤ê
¤Þ¤¹¡¥extconf.rb¤Ï¥é¥¤¥Ö¥é¥ê¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã
@@ -724,14 +730,20 @@ Makefile¤òºî¤ë¾ì¹ç¤Î¿÷·¿¤Ë¤Ê¤ëextconf.rb¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤òºî¤ê
°Ê²¼¤ÎÊÑ¿ô¤ò»È¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥
- $CFLAGS: ¥³¥ó¥Ñ¥¤¥ë»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-I¤Ê¤É)
+ $CFLAGS: ¥³¥ó¥Ñ¥¤¥ë»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-O¤Ê¤É)
+ $CPPFLAGS: ¥×¥ê¥×¥í¥»¥Ã¥µ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-I¤ä-D¤Ê¤É)
$LDFLAGS: ¥ê¥ó¥¯»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-L¤Ê¤É)
+ $objs: ¥ê¥ó¥¯¤µ¤ì¤ë¥ª¥Ö¥¸¥§¥¯¥È¥Õ¥¡¥¤¥ë̾¤Î¥ê¥¹¥È
+
+¥ª¥Ö¥¸¥§¥¯¥È¥Õ¥¡¥¤¥ë¤Î¥ê¥¹¥È¤Ï¡¢Ä̾ï¤Ï¥½¡¼¥¹¥Õ¥¡¥¤¥ë¤ò¸¡º÷¤·
+¤Æ¼«Æ°Åª¤ËÀ¸À®¤µ¤ì¤Þ¤¹¤¬¡¢make¤ÎÅÓÃæ¤Ç¥½¡¼¥¹¤òÀ¸À®¤¹¤ë¤è¤¦¤Ê
+¾ì¹ç¤ÏÌÀ¼¨Åª¤Ë»ØÄꤹ¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£
¥é¥¤¥Ö¥é¥ê¤ò¥³¥ó¥Ñ¥¤¥ë¤¹¤ë¾ò·ï¤¬Â·¤ï¤º¡¤¤½¤Î¥é¥¤¥Ö¥é¥ê¤ò¥³¥ó
¥Ñ¥¤¥ë¤·¤Ê¤¤»þ¤Ë¤Ïcreate_makefile¤ò¸Æ¤Ð¤Ê¤±¤ì¤ÐMakefile¤ÏÀ¸
À®¤µ¤ì¤º¡¤¥³¥ó¥Ñ¥¤¥ë¤â¹Ô¤ï¤ì¤Þ¤»¤ó¡¥
-(6) depend¤òÍѰդ¹¤ë
+(5) depend¤òÍѰդ¹¤ë
¤â¤·¡¤¥Ç¥£¥ì¥¯¥È¥ê¤Ëdepend¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ì¤Ð¡¤
Makefile¤¬°Í¸´Ø·¸¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
@@ -740,18 +752,7 @@ Makefile¤¬°Í¸´Ø·¸¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
¤Ê¤É¤Çºî¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤¢¤Ã¤ÆÂ»¤Ï̵¤¤¤Ç¤·¤ç¤¦¡¥
-(7) MANIFEST¥Õ¥¡¥¤¥ë¤Ë¥Õ¥¡¥¤¥ë̾¤òÆþ¤ì¤ë
-
- % find * -type f -print > MANIFEST
- % vi MANIFEST
-
-*.o, *~¤Ê¤ÉÉÔɬÍפʥե¡¥¤¥ë°Ê³°¤ÏMANIFEST¤ËÄɲ䷤Ƥª¤­¤Þ¤¹¡¥
-make»þ¤Ë¤ÏMANIFEST¤ÎÆâÍÆ¤Ï»²¾È¤·¤Þ¤»¤ó¤Î¤Ç¡¤¶õ¤Î¤Þ¤Þ¤Ç¤âÌäÂê
-¤Ïµ¯¤­¤Þ¤»¤ó¤¬¡¤¥Ñ¥Ã¥±¡¼¥¸¥ó¥°¤Î»þ¤Ë»²¾È¤¹¤ë¤³¤È¤¬¤¢¤ë¤Î¤È¡¤
-ɬÍפʥե¡¥¤¥ë¤ò¶èÊ̤Ǥ­¤ë¤Î¤Ç¡¤ÍѰդ·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤¤Ç¤·¤ç
-¤¦¡¥
-
-(8) Makefile¤òÀ¸À®¤¹¤ë
+(6) Makefile¤òÀ¸À®¤¹¤ë
Makefile¤ò¼ÂºÝ¤ËÀ¸À®¤¹¤ë¤¿¤á¤Ë¤Ï
@@ -764,10 +765,16 @@ Makefile¤ò¼ÂºÝ¤ËÀ¸À®¤¹¤ë¤¿¤á¤Ë¤Ï
¤È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+site_ruby ¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤Ê¤¯¡¢
+vendor_ruby ¥Ç¥£¥ì¥¯¥È¥ê¤Ë¥¤¥ó¥¹¥È¡¼¥ë¤¹¤ë¾ì¹ç¤Ë¤Ï
+°Ê²¼¤Î¤è¤¦¤Ë --vendor ¥ª¥×¥·¥ç¥ó¤ò²Ã¤¨¤Æ¤¯¤À¤µ¤¤¡¥
+
+ ruby extconf.rb --vendor
+
¥Ç¥£¥ì¥¯¥È¥ê¤òext°Ê²¼¤ËÍѰդ·¤¿¾ì¹ç¤Ë¤ÏRubyÁ´ÂΤÎmake¤Î»þ¤Ë
¼«Æ°Åª¤ËMakefile¤¬À¸À®¤µ¤ì¤Þ¤¹¤Î¤Ç¡¤¤³¤Î¥¹¥Æ¥Ã¥×¤ÏÉÔÍפǤ¹¡¥
-(9) make¤¹¤ë
+(7) make¤¹¤ë
ưŪ¥ê¥ó¥¯¥é¥¤¥Ö¥é¥ê¤òÀ¸À®¤¹¤ë¾ì¹ç¤Ë¤Ï¤½¤Î¾ì¤Çmake¤·¤Æ¤¯¤À¤µ
¤¤¡¥É¬ÍפǤ¢¤ì¤Ð make install ¤Ç¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡¥
@@ -785,13 +792,13 @@ extconf.rb¤ò½ñ¤­´¹¤¨¤ë¤Ê¤É¤·¤ÆMakefile¤ÎºÆÀ¸À®¤¬É¬Íפʻþ¤Ï¤Þ
¤òºî¤ê¡¤¤½¤³¤Ë ³ÈÄ¥»Ò .rb ¤Î¥Õ¥¡¥¤¥ë¤òÃÖ¤¤¤Æ¤ª¤±¤ÐƱ»þ¤Ë¥¤¥ó
¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡¥
-(10) ¥Ç¥Ð¥Ã¥°
+(8) ¥Ç¥Ð¥Ã¥°
¤Þ¤¢¡¤¥Ç¥Ð¥Ã¥°¤·¤Ê¤¤¤Èư¤«¤Ê¤¤¤Ç¤·¤ç¤¦¤Í¡¥ext/Setup¤Ë¥Ç¥£¥ì
¥¯¥È¥ê̾¤ò½ñ¤¯¤ÈÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¤Î¤Ç¥Ç¥Ð¥Ã¥¬¤¬»È¤¨¤ë¤è¤¦¤Ë¤Ê
¤ê¤Þ¤¹¡¥¤½¤Îʬ¥³¥ó¥Ñ¥¤¥ë¤¬ÃÙ¤¯¤Ê¤ê¤Þ¤¹¤±¤É¡¥
-(11) ¤Ç¤­¤¢¤¬¤ê
+(9) ¤Ç¤­¤¢¤¬¤ê
¸å¤Ï¤³¤Ã¤½¤ê»È¤¦¤Ê¤ê¡¤¹­¤¯¸ø³«¤¹¤ë¤Ê¤ê¡¤Çä¤ë¤Ê¤ê¡¤¤´¼«Í³¤Ë¤ª
»È¤¤¤¯¤À¤µ¤¤¡¥Ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò
@@ -916,7 +923,9 @@ NUM2INT(value)
INT2NUM(i)
NUM2DBL(value)
rb_float_new(f)
-STR2CSTR(value)
+StringValue(value)
+StringValuePtr(value)
+StringValueCStr(value)
rb_str_new2(s)
** ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ
@@ -934,7 +943,7 @@ VALUE rb_define_module(const char *name)
¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥
-VALUE rb_define_module_under(VALUE module, const char *name, VALUE super)
+VALUE rb_define_module_under(VALUE module, const char *name)
¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
@@ -1148,6 +1157,12 @@ Appendix C. extconf.rb¤Ç»È¤¨¤ë´Ø¿ô¤¿¤Á
extconf.rb¤ÎÃæ¤Ç¤ÏÍøÍѲÄǽ¤Ê¥³¥ó¥Ñ¥¤¥ë¾ò·ï¥Á¥§¥Ã¥¯¤Î´Ø¿ô¤Ï°Ê
²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+have_macro(macro, headers)
+
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ëheader¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ¥Þ¥¯¥ímacro¤¬ÄêµÁ¤µ
+ ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Þ¥¯¥í¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë»þtrue
+ ¤òÊÖ¤¹¡¥
+
have_library(lib, func)
´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥
@@ -1165,21 +1180,67 @@ have_func(func, header)
¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö¥é¥ê¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤ª¤¯
»ö¡¥´Ø¿ô¤¬Â¸ºß¤¹¤ë»þtrue¤òÊÖ¤¹¡¥
+have_var(var, header)
+
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ëheader¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤ÆÊÑ¿ôvar¤Î¸ºß¤ò¥Á¥§¥Ã
+ ¥¯¤¹¤ë¡¥var¤¬É¸½à¤Ç¤Ï¥ê¥ó¥¯¤µ¤ì¤Ê¤¤¥é¥¤¥Ö¥é¥êÆâ¤Î¤â¤Î¤Ç¤¢
+ ¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö¥é¥ê¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤ª¤¯
+ »ö¡¥ÊÑ¿ô¤¬Â¸ºß¤¹¤ë»þtrue¤òÊÖ¤¹¡¥
+
have_header(header)
¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹
¤ë»þtrue¤òÊÖ¤¹¡¥
+find_header(header, path...)
+
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ëheader¤Î¸ºß¤ò -Ipath ¤òÄɲ䷤ʤ¬¤é¥Á¥§¥Ã¥¯
+ ¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬¸«ÉÕ¤«¤Ã¤¿»þ¡¤true¤òÊÖ¤¹¡¥
+
+have_struct_member(type, member, header)
+
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ëheader¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ·¿type¤Ë¥á¥ó¥Ðmember
+ ¤¬Â¸ºß¤¹¤ë¤«¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥type¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Æ¡¤member¤ò
+ »ý¤Ä¤¹¤ë»þtrue¤òÊÖ¤¹¡¥
+
+have_type(type, header, opt)
+
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ëheader¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ·¿type¤¬Â¸ºß¤¹¤ë¤«¤ò
+ ¥Á¥§¥Ã¥¯¤¹¤ë¡¥type¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë»þtrue¤òÊÖ¤¹¡¥
+
+check_sizeof(type, header)
+
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ëheader¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ·¿type¤Îcharñ°Ì¥µ¥¤
+ ¥º¤òÄ´¤Ù¤ë¡¥type¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë»þ¤½¤Î¥µ¥¤¥º¤òÊÖ¤¹¡¥ÄêµÁ¤µ
+ ¤ì¤Æ¤¤¤Ê¤¤¤È¤­¤Ïnil¤òÊÖ¤¹¡¥
+
create_makefile(target)
³ÈÄ¥¥é¥¤¥Ö¥é¥êÍѤÎMakefile¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤ò¸Æ¤Ð¤Ê¤±¤ì
¤Ð¤½¤Î¥é¥¤¥Ö¥é¥ê¤Ï¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤Ê¤¤¡¥target¤Ï¥â¥¸¥å¡¼¥ë̾
¤òɽ¤¹¡¥
+find_executable(command, path)
+
+ ¥³¥Þ¥ó¥Écommand¤òFile::PATH_SEPARATOR¤Ç¶èÀÚ¤é¤ì¤¿¥Ñ¥¹Ì¾¤Î
+ ¥ê¥¹¥Èpath¤«¤éõ¤¹¡¥path¤¬nil¤Þ¤¿¤Ï¾Êά¤µ¤ì¤¿¾ì¹ç¤Ï¡¤´Ä¶­
+ ÊÑ¿ôPATH¤ÎÃͤò»ÈÍѤ¹¤ë¡¥¼Â¹Ô²Äǽ¤Ê¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤Ã¤¿¾ì¹ç
+ ¤Ï¥Ñ¥¹¤ò´Þ¤à¥Õ¥¡¥¤¥ë̾¡¤¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ïnil¤òÊÖ¤¹¡¥
+
with_config(withval[, default=nil])
¥³¥Þ¥ó¥É¥é¥¤¥ó¾å¤Î--with-<withval>¤Ç»ØÄꤵ¤ì¤¿¥ª¥×¥·¥ç¥óÃͤòÆÀ¤ë¡¥
+enable_config(config, *defaults)
+disable_config(config, *defaults)
+
+ ¥³¥Þ¥ó¥É¥é¥¤¥ó¾å¤Î--enable-<config>¤Þ¤¿¤Ï
+ --disable-<config>¤Ç»ØÄꤵ¤ì¤¿¿¿µ¶ÃͤòÆÀ¤ë¡¥
+ --enable-<config>¤¬»ØÄꤵ¤ì¤Æ¤¤¤¿¾ì¹ç¤Ïtrue¡¤
+ --disable-<config>¤¬»ØÄꤵ¤ì¤Æ¤¤¤¿¾ì¹ç¤Ïfalse¤òÊÖ¤¹¡¥
+ ¤É¤Á¤é¤â»ØÄꤵ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï¡¤¥Ö¥í¥Ã¥¯¤Ä¤­¤Ç¸Æ¤Ó½Ð¤µ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ï
+ *defaults¤òyield¤·¤¿·ë²Ì¡¤¥Ö¥í¥Ã¥¯¤Ê¤·¤Ê¤é*defaults¤òÊÖ¤¹¡¥
+
dir_config(target[, default_dir])
dir_config(target[, default_include, default_lib])
@@ -1190,6 +1251,12 @@ dir_config(target[, default_include, default_lib])
¤ÈÅù²Á¤Ç¤¢¤ë¡¥Äɲ䵤줿 include ¥Ç¥£¥ì¥¯¥È¥ê¤È lib ¥Ç¥£¥ì¥¯¥È¥ê¤Î
ÇÛÎó¤òÊÖ¤¹¡¥ ([include_dir, lib_dir])
+pkg_config(pkg)
+
+ pkg-config¥³¥Þ¥ó¥É¤«¤é¥Ñ¥Ã¥±¡¼¥¸pkg¤Î¾ðÊó¤òÆÀ¤ë¡¥
+ pkg-config¤Î¼ÂºÝ¤Î¥³¥Þ¥ó¥É̾¤Ï¡¤--with-pkg-config¥³¥Þ¥ó¥É
+ ¥é¥¤¥ó¥ª¥×¥·¥ç¥ó¤Ç»ØÄê²Äǽ¡¥
+
/*
* Local variables:
* fill-column: 60
diff --git a/README.ja b/README.ja
index fc502dd440..71ce4ee12c 100644
--- a/README.ja
+++ b/README.ja
@@ -26,18 +26,25 @@ Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤Perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
* Æþ¼êË¡
-** ftp¤Ç
+** FTP¤Ç
°Ê²¼¤Î¾ì½ê¤Ë¤ª¤¤¤Æ¤¢¤ê¤Þ¤¹¡¥
ftp://ftp.ruby-lang.org/pub/ruby/
-** CVS¤Ç
+** Subversion¤Ç
- $ cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login
- (Logging in to anonymous@cvs.ruby-lang.org)
- CVS password: anonymous
- $ cvs -z4 -d :pserver:anonymous@cvs.ruby-lang.org:src checkout ruby
+ËÜ¥Ö¥é¥ó¥Á¤ÎRuby¤ÎºÇ¿·¤Î¥½¡¼¥¹¥³¡¼¥É¤Ï¼¡¤Î¥³¥Þ¥ó¥É¤Ç¼èÆÀ¤Ç¤­¤Þ¤¹¡¥
+
+ $ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8/
+
+³«È¯Àèü¤Î¥½¡¼¥¹¥³¡¼¥É¤Ï¼¡¤Î¥³¥Þ¥ó¥É¤Ç¼èÆÀ¤Ç¤­¤Þ¤¹¡¥
+
+ $ svn co http://svn.ruby-lang.org/repos/ruby/trunk/ ruby
+
+¾¤Ë³«È¯Ãæ¤Î¥Ö¥é¥ó¥Á¤Î°ìÍ÷¤Ï¼¡¤Î¥³¥Þ¥ó¥É¤Ç¸«¤é¤ì¤Þ¤¹¡¥
+
+ $ svn ls http://svn.ruby-lang.org/repos/ruby/branches/
* ¥Û¡¼¥à¥Ú¡¼¥¸
@@ -85,6 +92,10 @@ Ruby³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤Ä¤¤¤ÆÏ䷹礦ruby-ext¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤È
2. configure¤ò¼Â¹Ô¤·¤ÆMakefile¤Ê¤É¤òÀ¸À®¤¹¤ë
+ ´Ä¶­¤Ë¤è¤Ã¤Æ¤Ï¥Ç¥Õ¥©¥ë¥È¤ÎC¥³¥ó¥Ñ¥¤¥éÍÑ¥ª¥×¥·¥ç¥ó¤¬ÉÕ¤­
+ ¤Þ¤¹¡¥configure¥ª¥×¥·¥ç¥ó¤Ç optflags=.. warnflags=.. Åù
+ ¤Ç¾å½ñ¤­¤Ç¤­¤Þ¤¹¡¥
+
3. (ɬÍפʤé¤Ð)defines.h¤òÊÔ½¸¤¹¤ë
¿ʬ¡¤É¬Í×̵¤¤¤È»×¤¤¤Þ¤¹¡¥
diff --git a/array.c b/array.c
index 5f41d26409..89f74d01ff 100644
--- a/array.c
+++ b/array.c
@@ -20,6 +20,7 @@ VALUE rb_cArray;
static ID id_cmp;
#define ARY_DEFAULT_SIZE 16
+#define ARY_MAX_SIZE (LONG_MAX / sizeof(VALUE))
void
rb_mem_clear(mem, size)
@@ -31,7 +32,7 @@ rb_mem_clear(mem, size)
}
}
-static void
+static inline void
memfill(mem, size, val)
register VALUE *mem;
register long size;
@@ -50,7 +51,7 @@ rb_ary_modify_check(ary)
{
if (OBJ_FROZEN(ary)) rb_error_frozen("array");
if (FL_TEST(ary, ARY_TMPLOCK))
- rb_raise(rb_eTypeError, "can't modify array during iteration");
+ rb_raise(rb_eRuntimeError, "can't modify array during iteration");
if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify array");
}
@@ -70,6 +71,7 @@ rb_ary_modify(ary)
RARRAY(ary)->ptr = ptr;
}
}
+
VALUE
rb_ary_freeze(ary)
VALUE ary;
@@ -77,6 +79,14 @@ rb_ary_freeze(ary)
return rb_obj_freeze(ary);
}
+/*
+ * call-seq:
+ * array.frozen? -> true or false
+ *
+ * Return <code>true</code> if this array is frozen (or temporarily frozen
+ * while being sorted).
+ */
+
static VALUE
rb_ary_frozen_p(ary)
VALUE ary;
@@ -111,7 +121,7 @@ ary_new(klass, len)
if (len < 0) {
rb_raise(rb_eArgError, "negative array size (or size too big)");
}
- if (len > 0 && len * sizeof(VALUE) <= len) {
+ if (len > ARY_MAX_SIZE) {
rb_raise(rb_eArgError, "array size too big");
}
if (len == 0) len++;
@@ -179,11 +189,34 @@ rb_ary_new4(n, elts)
if (n > 0 && elts) {
MEMCPY(RARRAY(ary)->ptr, elts, VALUE, n);
}
+
+ /* This assignment to len will be moved to the above "if" block in Ruby 1.9 */
RARRAY(ary)->len = n;
return ary;
}
+static VALUE
+ary_make_shared(ary)
+ VALUE ary;
+{
+ if (!FL_TEST(ary, ELTS_SHARED)) {
+ NEWOBJ(shared, struct RArray);
+ OBJSETUP(shared, rb_cArray, T_ARRAY);
+
+ shared->len = RARRAY(ary)->len;
+ shared->ptr = RARRAY(ary)->ptr;
+ shared->aux.capa = RARRAY(ary)->aux.capa;
+ RARRAY(ary)->aux.shared = (VALUE)shared;
+ FL_SET(ary, ELTS_SHARED);
+ OBJ_FREEZE(shared);
+ return (VALUE)shared;
+ }
+ else {
+ return RARRAY(ary)->aux.shared;
+ }
+}
+
VALUE
rb_assoc_new(car, cdr)
VALUE car, cdr;
@@ -214,6 +247,44 @@ rb_check_array_type(ary)
static VALUE rb_ary_replace _((VALUE, VALUE));
+/*
+ * call-seq:
+ * Array.new(size=0, obj=nil)
+ * Array.new(array)
+ * Array.new(size) {|index| block }
+ *
+ * Returns a new array. In the first form, the new array is
+ * empty. In the second it is created with _size_ copies of _obj_
+ * (that is, _size_ references to the same
+ * _obj_). The third form creates a copy of the array
+ * passed as a parameter (the array is generated by calling
+ * to_ary on the parameter). In the last form, an array
+ * of the given size is created. Each element in this array is
+ * calculated by passing the element's index to the given block and
+ * storing the return value.
+ *
+ * Array.new
+ * Array.new(2)
+ * Array.new(5, "A")
+ *
+ * # only one copy of the object is created
+ * a = Array.new(2, Hash.new)
+ * a[0]['cat'] = 'feline'
+ * a
+ * a[1]['cat'] = 'Felix'
+ * a
+ *
+ * # here multiple copies are created
+ * a = Array.new(2) { Hash.new }
+ * a[0]['cat'] = 'feline'
+ * a
+ *
+ * squares = Array.new(5) {|i| i*i}
+ * squares
+ *
+ * copy = Array.new(squares)
+ */
+
static VALUE
rb_ary_initialize(argc, argv, ary)
int argc;
@@ -244,7 +315,7 @@ rb_ary_initialize(argc, argv, ary)
if (len < 0) {
rb_raise(rb_eArgError, "negative array size");
}
- if (len > 0 && len * (long)sizeof(VALUE) <= len) {
+ if (len > ARY_MAX_SIZE) {
rb_raise(rb_eArgError, "array size too big");
}
if (len > RARRAY(ary)->aux.capa) {
@@ -258,7 +329,7 @@ rb_ary_initialize(argc, argv, ary)
rb_warn("block supersedes default value argument");
}
for (i=0; i<len; i++) {
- RARRAY(ary)->ptr[i] = rb_yield(LONG2NUM(i));
+ rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
RARRAY(ary)->len = i + 1;
}
}
@@ -270,6 +341,15 @@ rb_ary_initialize(argc, argv, ary)
return ary;
}
+
+/*
+* Returns a new array populated with the given objects.
+*
+* Array.[]( 1, 'a', /^A/ )
+* Array[ 1, 'a', /^A/ ]
+* [ 1, 'a', /^A/ ]
+*/
+
static VALUE
rb_ary_s_create(argc, argv, klass)
int argc;
@@ -278,9 +358,6 @@ rb_ary_s_create(argc, argv, klass)
{
VALUE ary = ary_alloc(klass);
- if (argc < 0) {
- rb_raise(rb_eArgError, "negative number of arguments");
- }
if (argc > 0) {
RARRAY(ary)->ptr = ALLOC_N(VALUE, argc);
MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
@@ -296,7 +373,6 @@ rb_ary_store(ary, idx, val)
long idx;
VALUE val;
{
- rb_ary_modify(ary);
if (idx < 0) {
idx += RARRAY(ary)->len;
if (idx < 0) {
@@ -304,17 +380,21 @@ rb_ary_store(ary, idx, val)
idx - RARRAY(ary)->len);
}
}
+ else if (idx >= ARY_MAX_SIZE) {
+ rb_raise(rb_eIndexError, "index %ld too big", idx);
+ }
+ rb_ary_modify(ary);
if (idx >= RARRAY(ary)->aux.capa) {
long new_capa = RARRAY(ary)->aux.capa / 2;
if (new_capa < ARY_DEFAULT_SIZE) {
new_capa = ARY_DEFAULT_SIZE;
}
- new_capa += idx;
- if (new_capa * (long)sizeof(VALUE) <= new_capa) {
- rb_raise(rb_eArgError, "index too big");
+ if (new_capa >= ARY_MAX_SIZE - idx) {
+ new_capa = (ARY_MAX_SIZE - idx) / 2;
}
+ new_capa += idx;
REALLOC_N(RARRAY(ary)->ptr, VALUE, new_capa);
RARRAY(ary)->aux.capa = new_capa;
}
@@ -329,6 +409,63 @@ rb_ary_store(ary, idx, val)
RARRAY(ary)->ptr[idx] = val;
}
+static VALUE
+ary_shared_array(klass, ary)
+ VALUE klass;
+ VALUE ary;
+{
+ VALUE val = ary_alloc(klass);
+
+ ary_make_shared(ary);
+ RARRAY(val)->ptr = RARRAY(ary)->ptr;
+ RARRAY(val)->len = RARRAY(ary)->len;
+ RARRAY(val)->aux.shared = RARRAY(ary)->aux.shared;
+ FL_SET(val, ELTS_SHARED);
+ return val;
+}
+
+static VALUE
+ary_shared_first(argc, argv, ary, last)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+ int last;
+{
+ VALUE nv, result;
+ long n;
+ long offset = 0;
+
+ rb_scan_args(argc, argv, "1", &nv);
+ n = NUM2LONG(nv);
+ if (n > RARRAY(ary)->len) {
+ n = RARRAY(ary)->len;
+ }
+ else if (n < 0) {
+ rb_raise(rb_eArgError, "negative array size");
+ }
+ if (last) {
+ offset = RARRAY(ary)->len - n;
+ }
+ result = ary_shared_array(rb_cArray, ary);
+ RARRAY(result)->ptr += offset;
+ RARRAY(result)->len = n;
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * array << obj -> array
+ *
+ * Append---Pushes the given object on to the end of this array. This
+ * expression returns the array itself, so several appends
+ * may be chained together.
+ *
+ * [ 1, 2 ] << "c" << "d" << [ 3, 4 ]
+ * #=> [ 1, 2, "c", "d", [ 3, 4 ] ]
+ *
+ */
+
VALUE
rb_ary_push(ary, item)
VALUE ary;
@@ -338,6 +475,19 @@ rb_ary_push(ary, item)
return ary;
}
+/*
+ * call-seq:
+ * array.push(obj, ... ) -> array
+ *
+ * Append---Pushes the given object(s) on to the end of this array. This
+ * expression returns the array itself, so several appends
+ * may be chained together.
+ *
+ * a = [ "a", "b", "c" ]
+ * a.push("d", "e", "f")
+ * #=> ["a", "b", "c", "d", "e", "f"]
+ */
+
static VALUE
rb_ary_push_m(argc, argv, ary)
int argc;
@@ -357,7 +507,7 @@ rb_ary_pop(ary)
rb_ary_modify_check(ary);
if (RARRAY(ary)->len == 0) return Qnil;
if (!FL_TEST(ary, ELTS_SHARED) &&
- RARRAY(ary)->len * 2 < RARRAY(ary)->aux.capa &&
+ RARRAY(ary)->len * 3 < RARRAY(ary)->aux.capa &&
RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
RARRAY(ary)->aux.capa = RARRAY(ary)->len * 2;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
@@ -365,20 +515,39 @@ rb_ary_pop(ary)
return RARRAY(ary)->ptr[--RARRAY(ary)->len];
}
-static void
-ary_make_shared(ary)
+/*
+ * call-seq:
+ * array.pop -> obj or nil
+ * array.pop(n) -> array
+ *
+ * Removes the last element from <i>self</i> and returns it, or
+ * <code>nil</code> if the array is empty.
+ *
+ * If a number _n_ is given, returns an array of the last n elements
+ * (or less) just like <code>array.slice!(-n, n)</code> does.
+ *
+ * a = [ "a", "b", "c", "d" ]
+ * a.pop #=> "d"
+ * a.pop(2) #=> ["b", "c"]
+ * a #=> ["a"]
+ */
+
+static VALUE
+rb_ary_pop_m(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
{
- if (!FL_TEST(ary, ELTS_SHARED)) {
- NEWOBJ(shared, struct RArray);
- OBJSETUP(shared, rb_cArray, T_ARRAY);
+ VALUE result;
- shared->len = RARRAY(ary)->len;
- shared->ptr = RARRAY(ary)->ptr;
- shared->aux.capa = RARRAY(ary)->aux.capa;
- RARRAY(ary)->aux.shared = (VALUE)shared;
- FL_SET(ary, ELTS_SHARED);
+ if (argc == 0) {
+ return rb_ary_pop(ary);
}
+
+ rb_ary_modify_check(ary);
+ result = ary_shared_first(argc, argv, ary, Qtrue);
+ RARRAY(ary)->len -= RARRAY(result)->len;
+ return result;
}
VALUE
@@ -390,13 +559,70 @@ rb_ary_shift(ary)
rb_ary_modify_check(ary);
if (RARRAY(ary)->len == 0) return Qnil;
top = RARRAY(ary)->ptr[0];
- ary_make_shared(ary);
+ if (!FL_TEST(ary, ELTS_SHARED)) {
+ if (RARRAY(ary)->len < ARY_DEFAULT_SIZE) {
+ MEMMOVE(RARRAY(ary)->ptr, RARRAY(ary)->ptr+1, VALUE, RARRAY(ary)->len-1);
+ RARRAY(ary)->len--;
+ return top;
+ }
+ RARRAY(ary)->ptr[0] = Qnil;
+ ary_make_shared(ary);
+ }
RARRAY(ary)->ptr++; /* shift ptr */
RARRAY(ary)->len--;
return top;
}
+/*
+ * call-seq:
+ * array.shift -> obj or nil
+ * array.shift(n) -> array
+ *
+ * Returns the first element of <i>self</i> and removes it (shifting all
+ * other elements down by one). Returns <code>nil</code> if the array
+ * is empty.
+ *
+ * If a number _n_ is given, returns an array of the first n elements
+ * (or less) just like <code>array.slice!(0, n)</code> does.
+ *
+ * args = [ "-m", "-q", "filename" ]
+ * args.shift #=> "-m"
+ * args #=> ["-q", "filename"]
+ *
+ * args = [ "-m", "-q", "filename" ]
+ * args.shift(2) #=> ["-m", "-q"]
+ * args #=> ["filename"]
+ */
+
+static VALUE
+rb_ary_shift_m(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ VALUE result;
+ long n;
+
+ if (argc == 0) {
+ return rb_ary_shift(ary);
+ }
+
+ rb_ary_modify_check(ary);
+ result = ary_shared_first(argc, argv, ary, Qfalse);
+ n = RARRAY(result)->len;
+ if (FL_TEST(ary, ELTS_SHARED)) {
+ RARRAY(ary)->ptr += n;
+ RARRAY(ary)->len -= n;
+ }
+ else {
+ MEMMOVE(RARRAY(ary)->ptr, RARRAY(ary)->ptr+n, VALUE, RARRAY(ary)->len-n);
+ RARRAY(ary)->len -= n;
+ }
+
+ return result;
+}
+
VALUE
rb_ary_unshift(ary, item)
VALUE ary, item;
@@ -420,6 +646,18 @@ rb_ary_unshift(ary, item)
return ary;
}
+/*
+ * call-seq:
+ * array.unshift(obj, ...) -> array
+ *
+ * Prepends objects to the front of <i>array</i>.
+ * other elements up one.
+ *
+ * a = [ "b", "c", "d" ]
+ * a.unshift("a") #=> ["a", "b", "c", "d"]
+ * a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"]
+ */
+
static VALUE
rb_ary_unshift_m(argc, argv, ary)
int argc;
@@ -428,9 +666,6 @@ rb_ary_unshift_m(argc, argv, ary)
{
long len = RARRAY(ary)->len;
- if (argc < 0) {
- rb_raise(rb_eArgError, "negative number of arguments");
- }
if (argc == 0) return ary;
/* make rooms by setting the last item */
@@ -443,34 +678,42 @@ rb_ary_unshift_m(argc, argv, ary)
return ary;
}
-VALUE
-rb_ary_entry(ary, offset)
+/* faster version - use this if you don't need to treat negative offset */
+static inline VALUE
+rb_ary_elt(ary, offset)
VALUE ary;
long offset;
{
if (RARRAY(ary)->len == 0) return Qnil;
-
- if (offset < 0) {
- offset += RARRAY(ary)->len;
- }
if (offset < 0 || RARRAY(ary)->len <= offset) {
return Qnil;
}
-
return RARRAY(ary)->ptr[offset];
}
+VALUE
+rb_ary_entry(ary, offset)
+ VALUE ary;
+ long offset;
+{
+ if (offset < 0) {
+ offset += RARRAY(ary)->len;
+ }
+ return rb_ary_elt(ary, offset);
+}
+
static VALUE
rb_ary_subseq(ary, beg, len)
VALUE ary;
long beg, len;
{
- VALUE klass, ary2;
+ VALUE klass, ary2, shared;
+ VALUE *ptr;
if (beg > RARRAY(ary)->len) return Qnil;
if (beg < 0 || len < 0) return Qnil;
- if (beg + len > RARRAY(ary)->len) {
+ if (RARRAY(ary)->len < len || RARRAY(ary)->len < beg + len) {
len = RARRAY(ary)->len - beg;
if (len < 0)
len = 0;
@@ -478,16 +721,49 @@ rb_ary_subseq(ary, beg, len)
klass = rb_obj_class(ary);
if (len == 0) return ary_new(klass, 0);
- ary_make_shared(ary);
+ shared = ary_make_shared(ary);
+ ptr = RARRAY(ary)->ptr;
ary2 = ary_alloc(klass);
- RARRAY(ary2)->ptr = RARRAY(ary)->ptr + beg;
+ RARRAY(ary2)->ptr = ptr + beg;
RARRAY(ary2)->len = len;
- RARRAY(ary2)->aux.shared = RARRAY(ary)->aux.shared;
+ RARRAY(ary2)->aux.shared = shared;
FL_SET(ary2, ELTS_SHARED);
return ary2;
}
+/*
+ * call-seq:
+ * array[index] -> obj or nil
+ * array[start, length] -> an_array or nil
+ * array[range] -> an_array or nil
+ * array.slice(index) -> obj or nil
+ * array.slice(start, length) -> an_array or nil
+ * array.slice(range) -> an_array or nil
+ *
+ * Element Reference---Returns the element at _index_,
+ * or returns a subarray starting at _start_ and
+ * continuing for _length_ elements, or returns a subarray
+ * specified by _range_.
+ * Negative indices count backward from the end of the
+ * array (-1 is the last element). Returns nil if the index
+ * (or starting index) are out of range.
+ *
+ * a = [ "a", "b", "c", "d", "e" ]
+ * a[2] + a[0] + a[1] #=> "cab"
+ * a[6] #=> nil
+ * a[1, 2] #=> [ "b", "c" ]
+ * a[1..3] #=> [ "b", "c", "d" ]
+ * a[4..7] #=> [ "e" ]
+ * a[6..10] #=> nil
+ * a[-3, 3] #=> [ "c", "d", "e" ]
+ * # special cases
+ * a[5] #=> nil
+ * a[5, 1] #=> []
+ * a[5..10] #=> []
+ *
+ */
+
VALUE
rb_ary_aref(argc, argv, ary)
int argc;
@@ -531,6 +807,21 @@ rb_ary_aref(argc, argv, ary)
return rb_ary_entry(ary, NUM2LONG(arg));
}
+/*
+ * call-seq:
+ * array.at(index) -> obj or nil
+ *
+ * Returns the element at _index_. A
+ * negative index counts from the end of _self_. Returns +nil+
+ * if the index is out of range. See also <code>Array#[]</code>.
+ * (<code>Array#at</code> is slightly faster than <code>Array#[]</code>,
+ * as it does not accept ranges and so on.)
+ *
+ * a = [ "a", "b", "c", "d", "e" ]
+ * a.at(0) #=> "a"
+ * a.at(-1) #=> "e"
+ */
+
static VALUE
rb_ary_at(ary, pos)
VALUE ary, pos;
@@ -538,6 +829,21 @@ rb_ary_at(ary, pos)
return rb_ary_entry(ary, NUM2LONG(pos));
}
+/*
+ * call-seq:
+ * array.first -> obj or nil
+ * array.first(n) -> an_array
+ *
+ * Returns the first element, or the first +n+ elements, of the array.
+ * If the array is empty, the first form returns <code>nil</code>, and the
+ * second form returns an empty array.
+ *
+ * a = [ "q", "r", "s", "t" ]
+ * a.first #=> "q"
+ * a.first(1) #=> ["q"]
+ * a.first(3) #=> ["q", "r", "s"]
+ */
+
static VALUE
rb_ary_first(argc, argv, ary)
int argc;
@@ -549,20 +855,21 @@ rb_ary_first(argc, argv, ary)
return RARRAY(ary)->ptr[0];
}
else {
- VALUE nv, result;
- long n, i;
-
- rb_scan_args(argc, argv, "01", &nv);
- n = NUM2LONG(nv);
- if (n > RARRAY(ary)->len) n = RARRAY(ary)->len;
- result = rb_ary_new2(n);
- for (i=0; i<n; i++) {
- rb_ary_push(result, RARRAY(ary)->ptr[i]);
- }
- return result;
+ return ary_shared_first(argc, argv, ary, Qfalse);
}
}
+/*
+ * call-seq:
+ * array.last -> obj or nil
+ * array.last(n) -> an_array
+ *
+ * Returns the last element(s) of <i>self</i>. If the array is empty,
+ * the first form returns <code>nil</code>.
+ *
+ * [ "w", "x", "y", "z" ].last #=> "z"
+ */
+
static VALUE
rb_ary_last(argc, argv, ary)
int argc;
@@ -574,19 +881,29 @@ rb_ary_last(argc, argv, ary)
return RARRAY(ary)->ptr[RARRAY(ary)->len-1];
}
else {
- VALUE nv, result;
- long n, i;
-
- rb_scan_args(argc, argv, "01", &nv);
- n = NUM2LONG(nv);
- if (n > RARRAY(ary)->len) n = RARRAY(ary)->len;
- result = rb_ary_new2(n);
- for (i=RARRAY(ary)->len-n; n--; i++) {
- rb_ary_push(result, RARRAY(ary)->ptr[i]);
- }
- return result;
- }
-}
+ return ary_shared_first(argc, argv, ary, Qtrue);
+ }
+}
+
+/*
+ * call-seq:
+ * array.fetch(index) -> obj
+ * array.fetch(index, default ) -> obj
+ * array.fetch(index) {|index| block } -> obj
+ *
+ * Tries to return the element at position <i>index</i>. If the index
+ * lies outside the array, the first form throws an
+ * <code>IndexError</code> exception, the second form returns
+ * <i>default</i>, and the third form returns the value of invoking
+ * the block, passing in the index. Negative values of <i>index</i>
+ * count from the end of the array.
+ *
+ * a = [ 11, 22, 33, 44 ]
+ * a.fetch(1) #=> 22
+ * a.fetch(-1) #=> 44
+ * a.fetch(4, 'cat') #=> "cat"
+ * a.fetch(4) { |i| i*i } #=> 16
+ */
static VALUE
rb_ary_fetch(argc, argv, ary)
@@ -618,13 +935,43 @@ rb_ary_fetch(argc, argv, ary)
return RARRAY(ary)->ptr[idx];
}
+/*
+ * call-seq:
+ * array.index(obj) -> int or nil
+ * array.index {|item| block} -> int or nil
+ *
+ * Returns the index of the first object in <i>self</i> such that is
+ * <code>==</code> to <i>obj</i>. If a block is given instead of an
+ * argument, returns first object for which <em>block</em> is true.
+ * Returns <code>nil</code> if no match is found.
+ *
+ * a = [ "a", "b", "c" ]
+ * a.index("b") #=> 1
+ * a.index("z") #=> nil
+ * a.index{|x|x=="b"} #=> 1
+ *
+ * This is an alias of <code>#find_index</code>.
+ */
+
static VALUE
-rb_ary_index(ary, val)
+rb_ary_index(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
- VALUE val;
{
+ VALUE val;
long i;
+ if (argc == 0) {
+ RETURN_ENUMERATOR(ary, 0, 0);
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) {
+ return LONG2NUM(i);
+ }
+ }
+ return Qnil;
+ }
+ rb_scan_args(argc, argv, "01", &val);
for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], val))
return LONG2NUM(i);
@@ -632,20 +979,60 @@ rb_ary_index(ary, val)
return Qnil;
}
+/*
+ * call-seq:
+ * array.rindex(obj) -> int or nil
+ *
+ * Returns the index of the last object in <i>array</i>
+ * <code>==</code> to <i>obj</i>. If a block is given instead of an
+ * argument, returns first object for which <em>block</em> is
+ * true. Returns <code>nil</code> if no match is found.
+ *
+ * a = [ "a", "b", "b", "b", "c" ]
+ * a.rindex("b") #=> 3
+ * a.rindex("z") #=> nil
+ * a.rindex{|x|x=="b"} #=> 3
+ */
+
static VALUE
-rb_ary_rindex(ary, val)
+rb_ary_rindex(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
- VALUE val;
{
+ VALUE val;
long i = RARRAY(ary)->len;
+ if (argc == 0) {
+ RETURN_ENUMERATOR(ary, 0, 0);
+ while (i--) {
+ if (RTEST(rb_yield(RARRAY(ary)->ptr[i])))
+ return LONG2NUM(i);
+ if (i > RARRAY(ary)->len) {
+ i = RARRAY(ary)->len;
+ }
+ }
+ return Qnil;
+ }
+ rb_scan_args(argc, argv, "01", &val);
while (i--) {
if (rb_equal(RARRAY(ary)->ptr[i], val))
return LONG2NUM(i);
+ if (i > RARRAY(ary)->len) {
+ i = RARRAY(ary)->len;
+ }
}
return Qnil;
}
+/*
+ * call-seq:
+ * array.indexes( i1, i2, ... iN ) -> an_array
+ * array.indices( i1, i2, ... iN ) -> an_array
+ *
+ * Deprecated; use <code>Array#values_at</code>.
+ */
+
static VALUE
rb_ary_indexes(argc, argv, ary)
int argc;
@@ -678,7 +1065,7 @@ rb_ary_to_ary(obj)
}
static void
-rb_ary_update(ary, beg, len, rpl)
+rb_ary_splice(ary, beg, len, rpl)
VALUE ary;
long beg, len;
VALUE rpl;
@@ -693,11 +1080,10 @@ rb_ary_update(ary, beg, len, rpl)
rb_raise(rb_eIndexError, "index %ld out of array", beg);
}
}
- if (beg + len > RARRAY(ary)->len) {
+ if (RARRAY(ary)->len < len || RARRAY(ary)->len < beg + len) {
len = RARRAY(ary)->len - beg;
}
- rb_ary_modify(ary);
if (NIL_P(rpl)) {
rlen = 0;
}
@@ -705,8 +1091,12 @@ rb_ary_update(ary, beg, len, rpl)
rpl = rb_ary_to_ary(rpl);
rlen = RARRAY(rpl)->len;
}
+ rb_ary_modify(ary);
if (beg >= RARRAY(ary)->len) {
+ if (beg > ARY_MAX_SIZE - rlen) {
+ rb_raise(rb_eIndexError, "index %ld too big", beg);
+ }
len = beg + rlen;
if (len >= RARRAY(ary)->aux.capa) {
REALLOC_N(RARRAY(ary)->ptr, VALUE, len);
@@ -742,6 +1132,34 @@ rb_ary_update(ary, beg, len, rpl)
}
}
+/*
+ * call-seq:
+ * array[index] = obj -> obj
+ * array[start, length] = obj or an_array or nil -> obj or an_array or nil
+ * array[range] = obj or an_array or nil -> obj or an_array or nil
+ *
+ * Element Assignment---Sets the element at _index_,
+ * or replaces a subarray starting at _start_ and
+ * continuing for _length_ elements, or replaces a subarray
+ * specified by _range_. If indices are greater than
+ * the current capacity of the array, the array grows
+ * automatically. A negative indices will count backward
+ * from the end of the array. Inserts elements if _length_ is
+ * zero. If +nil+ is used in the second and third form,
+ * deletes elements from _self_. An +IndexError+ is raised if a
+ * negative index points past the beginning of the array. See also
+ * <code>Array#push</code>, and <code>Array#unshift</code>.
+ *
+ * a = Array.new
+ * a[4] = "4"; #=> [nil, nil, nil, nil, "4"]
+ * a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
+ * a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"]
+ * a[0, 2] = "?" #=> ["?", 2, nil, "4"]
+ * a[0..2] = "A" #=> ["A", "4"]
+ * a[-1] = "Z" #=> ["A", "Z"]
+ * a[1..-1] = nil #=> ["A"]
+ */
+
static VALUE
rb_ary_aset(argc, argv, ary)
int argc;
@@ -757,7 +1175,7 @@ rb_ary_aset(argc, argv, ary)
if (SYMBOL_P(argv[1])) {
rb_raise(rb_eTypeError, "Symbol as subarray length");
}
- rb_ary_update(ary, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
+ rb_ary_splice(ary, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
return argv[2];
}
if (argc != 2) {
@@ -772,7 +1190,7 @@ rb_ary_aset(argc, argv, ary)
}
if (rb_range_beg_len(argv[0], &beg, &len, RARRAY(ary)->len, 1)) {
/* check if idx is Range */
- rb_ary_update(ary, beg, len, argv[1]);
+ rb_ary_splice(ary, beg, len, argv[1]);
return argv[1];
}
@@ -782,6 +1200,18 @@ fixnum:
return argv[1];
}
+/*
+ * call-seq:
+ * array.insert(index, obj...) -> array
+ *
+ * Inserts the given values before the element with the given index
+ * (which may be negative).
+ *
+ * a = %w{ a b c d }
+ * a.insert(2, 99) #=> ["a", "b", 99, "c", "d"]
+ * a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
+ */
+
static VALUE
rb_ary_insert(argc, argv, ary)
int argc;
@@ -790,6 +1220,7 @@ rb_ary_insert(argc, argv, ary)
{
long pos;
+ if (argc == 1) return ary;
if (argc < 1) {
rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
}
@@ -797,45 +1228,92 @@ rb_ary_insert(argc, argv, ary)
if (pos == -1) {
pos = RARRAY(ary)->len;
}
- else if (pos < 0) {
+ if (pos < 0) {
pos++;
}
-
- if (argc == 1) return ary;
- rb_ary_update(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
+ rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
return ary;
}
+/*
+ * call-seq:
+ * array.each {|item| block } -> array
+ *
+ * Calls <i>block</i> once for each element in <i>self</i>, passing that
+ * element as a parameter.
+ *
+ * a = [ "a", "b", "c" ]
+ * a.each {|x| print x, " -- " }
+ *
+ * produces:
+ *
+ * a -- b -- c --
+ */
+
VALUE
rb_ary_each(ary)
VALUE ary;
{
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(RARRAY(ary)->ptr[i]);
}
return ary;
}
+/*
+ * call-seq:
+ * array.each_index {|index| block } -> array
+ *
+ * Same as <code>Array#each</code>, but passes the index of the element
+ * instead of the element itself.
+ *
+ * a = [ "a", "b", "c" ]
+ * a.each_index {|x| print x, " -- " }
+ *
+ * produces:
+ *
+ * 0 -- 1 -- 2 --
+ */
+
static VALUE
rb_ary_each_index(ary)
VALUE ary;
{
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(LONG2NUM(i));
}
return ary;
}
+/*
+ * call-seq:
+ * array.reverse_each {|item| block }
+ *
+ * Same as <code>Array#each</code>, but traverses <i>self</i> in reverse
+ * order.
+ *
+ * a = [ "a", "b", "c" ]
+ * a.reverse_each {|x| print x, " " }
+ *
+ * produces:
+ *
+ * c b a
+ */
+
static VALUE
rb_ary_reverse_each(ary)
VALUE ary;
{
- long len = RARRAY(ary)->len;
+ long len;
+ RETURN_ENUMERATOR(ary, 0, 0);
+ len = RARRAY(ary)->len;
while (len--) {
rb_yield(RARRAY(ary)->ptr[len]);
if (RARRAY(ary)->len < len) {
@@ -845,6 +1323,15 @@ rb_ary_reverse_each(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.length -> int
+ *
+ * Returns the number of elements in <i>self</i>. May be zero.
+ *
+ * [ 1, 2, 3, 4, 5 ].length #=> 5
+ */
+
static VALUE
rb_ary_length(ary)
VALUE ary;
@@ -852,6 +1339,15 @@ rb_ary_length(ary)
return LONG2NUM(RARRAY(ary)->len);
}
+/*
+ * call-seq:
+ * array.empty? -> true or false
+ *
+ * Returns <code>true</code> if <i>self</i> array contains no elements.
+ *
+ * [].empty? #=> true
+ */
+
static VALUE
rb_ary_empty_p(ary)
VALUE ary;
@@ -909,7 +1405,7 @@ rb_ary_join(ary, sep)
case T_STRING:
break;
case T_ARRAY:
- if (rb_inspecting_p(tmp)) {
+ if (tmp == ary || rb_inspecting_p(tmp)) {
tmp = rb_str_new2("[...]");
}
else {
@@ -933,6 +1429,17 @@ rb_ary_join(ary, sep)
return result;
}
+/*
+ * call-seq:
+ * array.join(sep=$,) -> str
+ *
+ * Returns a string created by converting each element of the array to
+ * a string, separated by <i>sep</i>.
+ *
+ * [ "a", "b", "c" ].join #=> "abc"
+ * [ "a", "b", "c" ].join("-") #=> "a-b-c"
+ */
+
static VALUE
rb_ary_join_m(argc, argv, ary)
int argc;
@@ -947,6 +1454,16 @@ rb_ary_join_m(argc, argv, ary)
return rb_ary_join(ary, sep);
}
+/*
+ * call-seq:
+ * array.to_s -> string
+ *
+ * Returns _self_<code>.join</code>.
+ *
+ * [ "a", "e", "i", "o" ].to_s #=> "aeio"
+ *
+ */
+
VALUE
rb_ary_to_s(ary)
VALUE ary;
@@ -1058,6 +1575,13 @@ inspect_ary(ary)
return str;
}
+/*
+ * call-seq:
+ * array.inspect -> string
+ *
+ * Create a printable version of <i>array</i>.
+ */
+
static VALUE
rb_ary_inspect(ary)
VALUE ary;
@@ -1067,6 +1591,14 @@ rb_ary_inspect(ary)
return rb_protect_inspect(inspect_ary, ary, 0);
}
+/*
+ * call-seq:
+ * array.to_a -> array
+ *
+ * Returns _self_. If called on a subclass of Array, converts
+ * the receiver to an Array object.
+ */
+
static VALUE
rb_ary_to_a(ary)
VALUE ary;
@@ -1079,6 +1611,13 @@ rb_ary_to_a(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.to_ary -> array
+ *
+ * Returns _self_.
+ */
+
static VALUE
rb_ary_to_ary_m(ary)
VALUE ary;
@@ -1107,6 +1646,17 @@ rb_ary_reverse(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.reverse! -> array
+ *
+ * Reverses _self_ in place.
+ *
+ * a = [ "a", "b", "c" ]
+ * a.reverse! #=> ["c", "b", "a"]
+ * a #=> ["c", "b", "a"]
+ */
+
static VALUE
rb_ary_reverse_bang(ary)
VALUE ary;
@@ -1114,6 +1664,16 @@ rb_ary_reverse_bang(ary)
return rb_ary_reverse(ary);
}
+/*
+ * call-seq:
+ * array.reverse -> an_array
+ *
+ * Returns a new array containing <i>self</i>'s elements in reverse order.
+ *
+ * [ "a", "b", "c" ].reverse #=> ["c", "b", "a"]
+ * [ 1 ].reverse #=> [1]
+ */
+
static VALUE
rb_ary_reverse_m(ary)
VALUE ary;
@@ -1121,40 +1681,69 @@ rb_ary_reverse_m(ary)
return rb_ary_reverse(rb_ary_dup(ary));
}
+struct ary_sort_data {
+ VALUE ary;
+ VALUE *ptr;
+ long len;
+};
+
+static void
+ary_sort_check(data)
+ struct ary_sort_data *data;
+{
+ if (RARRAY(data->ary)->ptr != data->ptr || RARRAY(data->ary)->len != data->len) {
+ rb_raise(rb_eArgError, "array modified during sort");
+ }
+}
+
static int
-sort_1(a, b)
+sort_1(a, b, data)
VALUE *a, *b;
+ struct ary_sort_data *data;
{
VALUE retval = rb_yield_values(2, *a, *b);
- return rb_cmpint(retval, *a, *b);
+ int n;
+
+ n = rb_cmpint(retval, *a, *b);
+ ary_sort_check(data);
+ return n;
}
static int
-sort_2(ap, bp)
+sort_2(ap, bp, data)
VALUE *ap, *bp;
+ struct ary_sort_data *data;
{
VALUE retval;
- long a = (long)*ap, b = (long)*bp;
+ VALUE a = *ap, b = *bp;
+ int n;
if (FIXNUM_P(a) && FIXNUM_P(b)) {
- if (a > b) return 1;
- if (a < b) return -1;
+ if ((long)a > (long)b) return 1;
+ if ((long)a < (long)b) return -1;
return 0;
}
- if (TYPE(a) == T_STRING && TYPE(b) == T_STRING) {
- return rb_str_cmp(a, b);
+ if (TYPE(a) == T_STRING) {
+ if (TYPE(b) == T_STRING) return rb_str_cmp(a, b);
}
retval = rb_funcall(a, id_cmp, 1, b);
- return rb_cmpint(retval, a, b);
+ n = rb_cmpint(retval, a, b);
+ ary_sort_check(data);
+
+ return n;
}
static VALUE
sort_internal(ary)
VALUE ary;
{
+ struct ary_sort_data data;
+
+ data.ary = ary;
+ data.ptr = RARRAY(ary)->ptr; data.len = RARRAY(ary)->len;
qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
- rb_block_given_p()?sort_1:sort_2);
+ rb_block_given_p()?sort_1:sort_2, &data);
return ary;
}
@@ -1166,6 +1755,22 @@ sort_unlock(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.sort! -> array
+ * array.sort! {| a,b | block } -> array
+ *
+ * Sorts _self_. Comparisons for
+ * the sort will be done using the <code><=></code> operator or using
+ * an optional code block. The block implements a comparison between
+ * <i>a</i> and <i>b</i>, returning -1, 0, or +1. See also
+ * <code>Enumerable#sort_by</code>.
+ *
+ * a = [ "d", "a", "e", "c", "b" ]
+ * a.sort #=> ["a", "b", "c", "d", "e"]
+ * a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
+ */
+
VALUE
rb_ary_sort_bang(ary)
VALUE ary;
@@ -1178,6 +1783,22 @@ rb_ary_sort_bang(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.sort -> an_array
+ * array.sort {| a,b | block } -> an_array
+ *
+ * Returns a new array created by sorting <i>self</i>. Comparisons for
+ * the sort will be done using the <code><=></code> operator or using
+ * an optional code block. The block implements a comparison between
+ * <i>a</i> and <i>b</i>, returning -1, 0, or +1. See also
+ * <code>Enumerable#sort_by</code>.
+ *
+ * a = [ "d", "a", "e", "c", "b" ]
+ * a.sort #=> ["a", "b", "c", "d", "e"]
+ * a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
+ */
+
VALUE
rb_ary_sort(ary)
VALUE ary;
@@ -1187,6 +1808,20 @@ rb_ary_sort(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.collect {|item| block } -> an_array
+ * array.map {|item| block } -> an_array
+ *
+ * Invokes <i>block</i> once for each element of <i>self</i>. Creates a
+ * new array containing the values returned by the block.
+ * See also <code>Enumerable#collect</code>.
+ *
+ * a = [ "a", "b", "c", "d" ]
+ * a.collect {|x| x + "!" } #=> ["a!", "b!", "c!", "d!"]
+ * a #=> ["a", "b", "c", "d"]
+ */
+
static VALUE
rb_ary_collect(ary)
VALUE ary;
@@ -1205,15 +1840,30 @@ rb_ary_collect(ary)
return collect;
}
+/*
+ * call-seq:
+ * array.collect! {|item| block } -> array
+ * array.map! {|item| block } -> array
+ *
+ * Invokes the block once for each element of _self_, replacing the
+ * element with the value returned by _block_.
+ * See also <code>Enumerable#collect</code>.
+ *
+ * a = [ "a", "b", "c", "d" ]
+ * a.collect! {|x| x + "!" }
+ * a #=> [ "a!", "b!", "c!", "d!" ]
+ */
+
static VALUE
rb_ary_collect_bang(ary)
VALUE ary;
{
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_modify(ary);
for (i = 0; i < RARRAY(ary)->len; i++) {
- RARRAY(ary)->ptr[i] = rb_yield(RARRAY(ary)->ptr[i]);
+ rb_ary_store(ary, i, rb_yield(RARRAY(ary)->ptr[i]));
}
return ary;
}
@@ -1251,6 +1901,22 @@ rb_values_at(obj, olen, argc, argv, func)
return result;
}
+/*
+ * call-seq:
+ * array.values_at(selector,... ) -> an_array
+ *
+ * Returns an array containing the elements in
+ * _self_ corresponding to the given selector(s). The selectors
+ * may be either integer indices or ranges.
+ * See also <code>Array#select</code>.
+ *
+ * a = %w{ a b c d e f }
+ * a.values_at(1, 3, 5)
+ * a.values_at(1, 3, 5, 7)
+ * a.values_at(-1, -3, -5, -7)
+ * a.values_at(1..3, 2...5)
+ */
+
static VALUE
rb_ary_values_at(argc, argv, ary)
int argc;
@@ -1260,27 +1926,52 @@ rb_ary_values_at(argc, argv, ary)
return rb_values_at(ary, RARRAY(ary)->len, argc, argv, rb_ary_entry);
}
+/*
+ * call-seq:
+ * array.select {|item| block } -> an_array
+ *
+ * Invokes the block passing in successive elements from <i>array</i>,
+ * returning an array containing those elements for which the block
+ * returns a true value (equivalent to <code>Enumerable#select</code>).
+ *
+ * a = %w{ a b c d e f }
+ * a.select {|v| v =~ /[aeiou]/} #=> ["a", "e"]
+ */
+
static VALUE
-rb_ary_select(argc, argv, ary)
- int argc;
- VALUE *argv;
+rb_ary_select(ary)
VALUE ary;
{
VALUE result;
long i;
- if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number arguments (%d for 0)", argc);
- }
+ RETURN_ENUMERATOR(ary, 0, 0);
result = rb_ary_new2(RARRAY(ary)->len);
for (i = 0; i < RARRAY(ary)->len; i++) {
if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) {
- rb_ary_push(result, RARRAY(ary)->ptr[i]);
+ rb_ary_push(result, rb_ary_elt(ary, i));
}
}
return result;
}
+/*
+ * call-seq:
+ * array.delete(obj) -> obj or nil
+ * array.delete(obj) { block } -> obj or nil
+ *
+ * Deletes items from <i>self</i> that are equal to <i>obj</i>. If
+ * the item is not found, returns <code>nil</code>. If the optional
+ * code block is given, returns the result of <i>block</i> if the item
+ * is not found.
+ *
+ * a = [ "a", "b", "b", "b", "c" ]
+ * a.delete("b") #=> "b"
+ * a #=> ["a", "c"]
+ * a.delete("z") #=> nil
+ * a.delete("z") { "not found" } #=> "not found"
+ */
+
VALUE
rb_ary_delete(ary, item)
VALUE ary;
@@ -1288,11 +1979,12 @@ rb_ary_delete(ary, item)
{
long i1, i2;
- rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
- if (rb_equal(RARRAY(ary)->ptr[i1], item)) continue;
+ VALUE e = RARRAY(ary)->ptr[i1];
+
+ if (rb_equal(e, item)) continue;
if (i1 != i2) {
- RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1];
+ rb_ary_store(ary, i2, e);
}
i2++;
}
@@ -1303,11 +1995,14 @@ rb_ary_delete(ary, item)
return Qnil;
}
- RARRAY(ary)->len = i2;
- if (i2 * 2 < RARRAY(ary)->aux.capa &&
+ rb_ary_modify(ary);
+ if (RARRAY(ary)->len > i2) {
+ RARRAY(ary)->len = i2;
+ if (i2 * 2 < RARRAY(ary)->aux.capa &&
RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
- REALLOC_N(RARRAY(ary)->ptr, VALUE, i2 * 2);
- RARRAY(ary)->aux.capa = i2 * 2;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, i2 * 2);
+ RARRAY(ary)->aux.capa = i2 * 2;
+ }
}
return item;
@@ -1321,13 +2016,13 @@ rb_ary_delete_at(ary, pos)
long i, len = RARRAY(ary)->len;
VALUE del;
- rb_ary_modify(ary);
if (pos >= len) return Qnil;
if (pos < 0) {
pos += len;
if (pos < 0) return Qnil;
}
+ rb_ary_modify(ary);
del = RARRAY(ary)->ptr[pos];
for (i = pos + 1; i < len; i++, pos++) {
RARRAY(ary)->ptr[pos] = RARRAY(ary)->ptr[i];
@@ -1337,6 +2032,20 @@ rb_ary_delete_at(ary, pos)
return del;
}
+/*
+ * call-seq:
+ * array.delete_at(index) -> obj or nil
+ *
+ * Deletes the element at the specified index, returning that element,
+ * or <code>nil</code> if the index is out of range. See also
+ * <code>Array#slice!</code>.
+ *
+ * a = %w( ant bat cat dog )
+ * a.delete_at(2) #=> "cat"
+ * a #=> ["ant", "bat", "dog"]
+ * a.delete_at(99) #=> nil
+ */
+
static VALUE
rb_ary_delete_at_m(ary, pos)
VALUE ary, pos;
@@ -1344,6 +2053,31 @@ rb_ary_delete_at_m(ary, pos)
return rb_ary_delete_at(ary, NUM2LONG(pos));
}
+/*
+ * call-seq:
+ * array.slice!(index) -> obj or nil
+ * array.slice!(start, length) -> sub_array or nil
+ * array.slice!(range) -> sub_array or nil
+ *
+ * Deletes the element(s) given by an index (optionally with a length)
+ * or by a range. Returns the deleted object, subarray, or
+ * <code>nil</code> if the index is out of range. Equivalent to:
+ *
+ * def slice!(*args)
+ * result = self[*args]
+ * self[*args] = nil
+ * result
+ * end
+ *
+ * a = [ "a", "b", "c" ]
+ * a.slice!(1) #=> "b"
+ * a #=> ["a", "c"]
+ * a.slice!(-1) #=> "c"
+ * a #=> ["a"]
+ * a.slice!(100) #=> nil
+ * a #=> ["a"]
+ */
+
static VALUE
rb_ary_slice_bang(argc, argv, ary)
int argc;
@@ -1351,65 +2085,140 @@ rb_ary_slice_bang(argc, argv, ary)
VALUE ary;
{
VALUE arg1, arg2;
- long pos, len;
+ long pos, len, orig_len;
- rb_ary_modify(ary);
+ rb_ary_modify_check(ary);
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
pos = NUM2LONG(arg1);
len = NUM2LONG(arg2);
delete_pos_len:
+ if (len < 0) return Qnil;
+ orig_len = RARRAY_LEN(ary);
if (pos < 0) {
- pos = RARRAY(ary)->len + pos;
+ pos += orig_len;
+ if (pos < 0) return Qnil;
+ }
+ else if (orig_len < pos) return Qnil;
+ if (orig_len < pos + len) {
+ len = orig_len - pos;
}
- arg2 = rb_ary_subseq(ary, pos, len);
- rb_ary_update(ary, pos, len, Qnil); /* Qnil/rb_ary_new2(0) */
+ if (len == 0) return rb_ary_new2(0);
+ arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
+ RBASIC(arg2)->klass = rb_obj_class(ary);
+ rb_ary_splice(ary, pos, len, Qnil); /* Qundef in 1.9 */
return arg2;
}
- if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, RARRAY(ary)->len, 1)) {
- goto delete_pos_len;
+ if (!FIXNUM_P(arg1)) {
+ switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
+ case Qtrue:
+ /* valid range */
+ goto delete_pos_len;
+ case Qnil:
+ /* invalid range */
+ return Qnil;
+ default:
+ /* not a range */
+ break;
+ }
}
return rb_ary_delete_at(ary, NUM2LONG(arg1));
}
+/*
+ * call-seq:
+ * array.reject! {|item| block } -> array or nil
+ *
+ * Equivalent to <code>Array#delete_if</code>, deleting elements from
+ * _self_ for which the block evaluates to true, but returns
+ * <code>nil</code> if no changes were made. Also see
+ * <code>Enumerable#reject</code>.
+ */
+
static VALUE
rb_ary_reject_bang(ary)
VALUE ary;
{
long i1, i2;
+ RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
- if (RTEST(rb_yield(RARRAY(ary)->ptr[i1]))) continue;
+ VALUE v = RARRAY(ary)->ptr[i1];
+ if (RTEST(rb_yield(v))) continue;
if (i1 != i2) {
- RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1];
+ rb_ary_store(ary, i2, v);
}
i2++;
}
if (RARRAY(ary)->len == i2) return Qnil;
- RARRAY(ary)->len = i2;
+ if (i2 < RARRAY(ary)->len)
+ RARRAY(ary)->len = i2;
return ary;
}
+/*
+ * call-seq:
+ * array.reject {|item| block } -> an_array
+ *
+ * Returns a new array containing the items in _self_
+ * for which the block is not true.
+ */
+
static VALUE
rb_ary_reject(ary)
VALUE ary;
{
+ RETURN_ENUMERATOR(ary, 0, 0);
ary = rb_ary_dup(ary);
rb_ary_reject_bang(ary);
return ary;
}
+/*
+ * call-seq:
+ * array.delete_if {|item| block } -> array
+ *
+ * Deletes every element of <i>self</i> for which <i>block</i> evaluates
+ * to <code>true</code>.
+ *
+ * a = [ "a", "b", "c" ]
+ * a.delete_if {|x| x >= "b" } #=> ["a"]
+ */
+
static VALUE
rb_ary_delete_if(ary)
VALUE ary;
{
+ RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_reject_bang(ary);
return ary;
}
+/*
+ * call-seq:
+ * array.zip(arg, ...) -> an_array
+ * array.zip(arg, ...) {| arr | block } -> nil
+ *
+ * Converts any arguments to arrays, then merges elements of
+ * <i>self</i> with corresponding elements from each argument. This
+ * generates a sequence of <code>self.size</code> <em>n</em>-element
+ * arrays, where <em>n</em> is one more that the count of arguments. If
+ * the size of any argument is less than <code>enumObj.size</code>,
+ * <code>nil</code> values are supplied. If a block given, it is
+ * invoked for each output array, otherwise an array of arrays is
+ * returned.
+ *
+ * a = [ 4, 5, 6 ]
+ * b = [ 7, 8, 9 ]
+ *
+ * [1,2,3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
+ * [1,2].zip(a,b) #=> [[1, 4, 7], [2, 5, 8]]
+ * a.zip([1,2],[8]) #=> [[4,1,8], [5,2,nil], [6,nil,nil]]
+ */
+
static VALUE
rb_ary_zip(argc, argv, ary)
int argc;
@@ -1427,9 +2236,9 @@ rb_ary_zip(argc, argv, ary)
for (i=0; i<RARRAY(ary)->len; i++) {
VALUE tmp = rb_ary_new2(argc+1);
- rb_ary_push(tmp, rb_ary_entry(ary, i));
+ rb_ary_push(tmp, rb_ary_elt(ary, i));
for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_entry(argv[j], i));
+ rb_ary_push(tmp, rb_ary_elt(argv[j], i));
}
rb_yield(tmp);
}
@@ -1440,15 +2249,26 @@ rb_ary_zip(argc, argv, ary)
for (i=0; i<len; i++) {
VALUE tmp = rb_ary_new2(argc+1);
- rb_ary_push(tmp, rb_ary_entry(ary, i));
+ rb_ary_push(tmp, rb_ary_elt(ary, i));
for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_entry(argv[j], i));
+ rb_ary_push(tmp, rb_ary_elt(argv[j], i));
}
rb_ary_push(result, tmp);
}
return result;
}
+/*
+ * call-seq:
+ * array.transpose -> an_array
+ *
+ * Assumes that <i>self</i> is an array of arrays and transposes the
+ * rows and columns.
+ *
+ * a = [[1,2], [3,4], [5,6]]
+ * a.transpose #=> [[1, 3, 5], [2, 4, 6]]
+ */
+
static VALUE
rb_ary_transpose(ary)
VALUE ary;
@@ -1459,7 +2279,7 @@ rb_ary_transpose(ary)
alen = RARRAY(ary)->len;
if (alen == 0) return rb_ary_dup(ary);
for (i=0; i<alen; i++) {
- tmp = to_ary(RARRAY(ary)->ptr[i]);
+ tmp = to_ary(rb_ary_elt(ary, i));
if (elen < 0) { /* first element */
elen = RARRAY(tmp)->len;
result = rb_ary_new2(elen);
@@ -1468,34 +2288,58 @@ rb_ary_transpose(ary)
}
}
else if (elen != RARRAY(tmp)->len) {
- rb_raise(rb_eIndexError, "element size differ (%d should be %d)",
+ rb_raise(rb_eIndexError, "element size differs (%d should be %d)",
RARRAY(tmp)->len, elen);
}
for (j=0; j<elen; j++) {
- rb_ary_store(RARRAY(result)->ptr[j], i, RARRAY(tmp)->ptr[j]);
+ rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
}
}
return result;
}
+/*
+ * call-seq:
+ * array.replace(other_array) -> array
+ *
+ * Replaces the contents of <i>self</i> with the contents of
+ * <i>other_array</i>, truncating or expanding if necessary.
+ *
+ * a = [ "a", "b", "c", "d", "e" ]
+ * a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"]
+ * a #=> ["x", "y", "z"]
+ */
+
static VALUE
rb_ary_replace(copy, orig)
VALUE copy, orig;
{
+ VALUE shared;
+
rb_ary_modify(copy);
orig = to_ary(orig);
if (copy == orig) return copy;
- ary_make_shared(orig);
+ shared = ary_make_shared(orig);
if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED))
free(RARRAY(copy)->ptr);
RARRAY(copy)->ptr = RARRAY(orig)->ptr;
RARRAY(copy)->len = RARRAY(orig)->len;
- RARRAY(copy)->aux.shared = RARRAY(orig)->aux.shared;
+ RARRAY(copy)->aux.shared = shared;
FL_SET(copy, ELTS_SHARED);
return copy;
}
+/*
+ * call-seq:
+ * array.clear -> array
+ *
+ * Removes all elements from _self_.
+ *
+ * a = [ "a", "b", "c", "d", "e" ]
+ * a.clear #=> [ ]
+ */
+
VALUE
rb_ary_clear(ary)
VALUE ary;
@@ -1509,6 +2353,30 @@ rb_ary_clear(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.fill(obj) -> array
+ * array.fill(obj, start [, length]) -> array
+ * array.fill(obj, range ) -> array
+ * array.fill {|index| block } -> array
+ * array.fill(start [, length] ) {|index| block } -> array
+ * array.fill(range) {|index| block } -> array
+ *
+ * The first three forms set the selected elements of <i>self</i> (which
+ * may be the entire array) to <i>obj</i>. A <i>start</i> of
+ * <code>nil</code> is equivalent to zero. A <i>length</i> of
+ * <code>nil</code> is equivalent to <i>self.length</i>. The last three
+ * forms fill the array with the value of the block. The block is
+ * passed the absolute index of each element to be filled.
+ *
+ * a = [ "a", "b", "c", "d" ]
+ * a.fill("x") #=> ["x", "x", "x", "x"]
+ * a.fill("z", 2, 2) #=> ["x", "x", "z", "z"]
+ * a.fill("y", 0..1) #=> ["y", "y", "z", "z"]
+ * a.fill {|i| i*i} #=> [0, 1, 4, 9]
+ * a.fill(-2) {|i| i*i*i} #=> [0, 1, 8, 27]
+ */
+
static VALUE
rb_ary_fill(argc, argv, ary)
int argc;
@@ -1516,7 +2384,7 @@ rb_ary_fill(argc, argv, ary)
VALUE ary;
{
VALUE item, arg1, arg2;
- long beg, end, len;
+ long beg = 0, end = 0, len = 0;
VALUE *p, *pend;
int block_p = Qfalse;
@@ -1548,15 +2416,19 @@ rb_ary_fill(argc, argv, ary)
break;
}
rb_ary_modify(ary);
+ if (len < 0) {
+ return ary;
+ }
+ if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
+ rb_raise(rb_eArgError, "argument too big");
+ }
end = beg + len;
if (end > RARRAY(ary)->len) {
if (end >= RARRAY(ary)->aux.capa) {
REALLOC_N(RARRAY(ary)->ptr, VALUE, end);
RARRAY(ary)->aux.capa = end;
}
- if (beg > RARRAY(ary)->len) {
- rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len, end - RARRAY(ary)->len);
- }
+ rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len, end - RARRAY(ary)->len);
RARRAY(ary)->len = end;
}
@@ -1564,7 +2436,7 @@ rb_ary_fill(argc, argv, ary)
VALUE v;
long i;
- for (i=beg; i<RARRAY(ary)->len; i++) {
+ for (i=beg; i<end; i++) {
v = rb_yield(LONG2NUM(i));
if (i>=RARRAY(ary)->len) break;
RARRAY(ary)->ptr[i] = v;
@@ -1580,6 +2452,16 @@ rb_ary_fill(argc, argv, ary)
return ary;
}
+/*
+ * call-seq:
+ * array + other_array -> an_array
+ *
+ * Concatenation---Returns a new array built by concatenating the
+ * two arrays together to produce a third array.
+ *
+ * [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]
+ */
+
VALUE
rb_ary_plus(x, y)
VALUE x, y;
@@ -1596,17 +2478,43 @@ rb_ary_plus(x, y)
return z;
}
+/*
+ * call-seq:
+ * array.concat(other_array) -> array
+ *
+ * Appends the elements in other_array to _self_.
+ *
+ * [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
+ */
+
+
VALUE
rb_ary_concat(x, y)
VALUE x, y;
{
y = to_ary(y);
if (RARRAY(y)->len > 0) {
- rb_ary_update(x, RARRAY(x)->len, 0, y);
+ rb_ary_splice(x, RARRAY(x)->len, 0, y);
}
return x;
}
+
+/*
+ * call-seq:
+ * array * int -> an_array
+ * array * str -> a_string
+ *
+ * Repetition---With a String argument, equivalent to
+ * self.join(str). Otherwise, returns a new array
+ * built by concatenating the _int_ copies of _self_.
+ *
+ *
+ * [ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
+ * [ 1, 2, 3 ] * "," #=> "1,2,3"
+ *
+ */
+
static VALUE
rb_ary_times(ary, times)
VALUE ary, times;
@@ -1620,11 +2528,11 @@ rb_ary_times(ary, times)
}
len = NUM2LONG(times);
- if (len == 0) return rb_ary_new2(0);
+ if (len == 0) return ary_new(rb_obj_class(ary), 0);
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
- if (LONG_MAX/len < RARRAY(ary)->len) {
+ if (ARY_MAX_SIZE/len < RARRAY(ary)->len) {
rb_raise(rb_eArgError, "argument too big");
}
len *= RARRAY(ary)->len;
@@ -1640,50 +2548,107 @@ rb_ary_times(ary, times)
return ary2;
}
+/*
+ * call-seq:
+ * array.assoc(obj) -> an_array or nil
+ *
+ * Searches through an array whose elements are also arrays
+ * comparing _obj_ with the first element of each contained array
+ * using obj.==.
+ * Returns the first contained array that matches (that
+ * is, the first associated array),
+ * or +nil+ if no match is found.
+ * See also <code>Array#rassoc</code>.
+ *
+ * s1 = [ "colors", "red", "blue", "green" ]
+ * s2 = [ "letters", "a", "b", "c" ]
+ * s3 = "foo"
+ * a = [ s1, s2, s3 ]
+ * a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
+ * a.assoc("foo") #=> nil
+ */
+
VALUE
rb_ary_assoc(ary, key)
VALUE ary, key;
{
- VALUE *p, *pend;
+ long i;
+ VALUE v;
- p = RARRAY(ary)->ptr;
- pend = p + RARRAY(ary)->len;
-
- while (p < pend) {
- if (TYPE(*p) == T_ARRAY &&
- RARRAY(*p)->len > 0 &&
- rb_equal(RARRAY(*p)->ptr[0], key))
- return *p;
- p++;
+ for (i = 0; i < RARRAY(ary)->len; ++i) {
+ v = rb_check_array_type(RARRAY(ary)->ptr[i]);
+ if (!NIL_P(v) && RARRAY(v)->len > 0 &&
+ rb_equal(RARRAY(v)->ptr[0], key))
+ return v;
}
return Qnil;
}
+/*
+ * call-seq:
+ * array.rassoc(key) -> an_array or nil
+ *
+ * Searches through the array whose elements are also arrays. Compares
+ * <em>key</em> with the second element of each contained array using
+ * <code>==</code>. Returns the first contained array that matches. See
+ * also <code>Array#assoc</code>.
+ *
+ * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
+ * a.rassoc("two") #=> [2, "two"]
+ * a.rassoc("four") #=> nil
+ */
+
VALUE
rb_ary_rassoc(ary, value)
VALUE ary, value;
{
- VALUE *p, *pend;
-
- p = RARRAY(ary)->ptr;
- pend = p + RARRAY(ary)->len;
+ long i;
+ VALUE v;
- while (p < pend) {
- if (TYPE(*p) == T_ARRAY
- && RARRAY(*p)->len > 1
- && rb_equal(RARRAY(*p)->ptr[1], value))
- return *p;
- p++;
+ for (i = 0; i < RARRAY(ary)->len; ++i) {
+ v = RARRAY(ary)->ptr[i];
+ if (TYPE(v) == T_ARRAY &&
+ RARRAY(v)->len > 1 &&
+ rb_equal(RARRAY(v)->ptr[1], value))
+ return v;
}
return Qnil;
}
+static VALUE recursive_equal _((VALUE, VALUE, int));
static VALUE
-rb_ary_equal(ary1, ary2)
+recursive_equal(ary1, ary2, recur)
VALUE ary1, ary2;
+ int recur;
{
long i;
+ if (recur) return Qfalse;
+ for (i=0; i<RARRAY(ary1)->len; i++) {
+ if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+ return Qfalse;
+ }
+ return Qtrue;
+}
+
+/*
+ * call-seq:
+ * array == other_array -> bool
+ *
+ * Equality---Two arrays are equal if they contain the same number
+ * of elements and if each element is equal to (according to
+ * Object.==) the corresponding element in the other array.
+ *
+ * [ "a", "c" ] == [ "a", "c", 7 ] #=> false
+ * [ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true
+ * [ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false
+ *
+ */
+
+static VALUE
+rb_ary_equal(ary1, ary2)
+ VALUE ary1, ary2;
+{
if (ary1 == ary2) return Qtrue;
if (TYPE(ary2) != T_ARRAY) {
if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
@@ -1692,36 +2657,57 @@ rb_ary_equal(ary1, ary2)
return rb_equal(ary2, ary1);
}
if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
+ return rb_exec_recursive(recursive_equal, ary1, ary2);
+}
+
+static VALUE recursive_eql _((VALUE, VALUE, int));
+static VALUE
+recursive_eql(ary1, ary2, recur)
+ VALUE ary1, ary2;
+ int recur;
+{
+ long i;
+
+ if (recur) return Qfalse;
for (i=0; i<RARRAY(ary1)->len; i++) {
- if (!rb_equal(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i]))
+ if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
return Qfalse;
}
return Qtrue;
}
+/*
+ * call-seq:
+ * array.eql?(other) -> true or false
+ *
+ * Returns <code>true</code> if _array_ and _other_ are the same object,
+ * or are both arrays with the same content.
+ */
+
static VALUE
rb_ary_eql(ary1, ary2)
VALUE ary1, ary2;
{
- long i;
-
if (ary1 == ary2) return Qtrue;
if (TYPE(ary2) != T_ARRAY) return Qfalse;
if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
- for (i=0; i<RARRAY(ary1)->len; i++) {
- if (!rb_eql(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i]))
- return Qfalse;
- }
- return Qtrue;
+ return rb_exec_recursive(recursive_eql, ary1, ary2);
}
+static VALUE recursive_hash _((VALUE, VALUE, int));
static VALUE
-rb_ary_hash(ary)
+recursive_hash(ary, dummy, recur)
VALUE ary;
+ VALUE dummy;
+ int recur;
{
long i, h;
VALUE n;
+ if (recur) {
+ return LONG2FIX(0);
+ }
+
h = RARRAY(ary)->len;
for (i=0; i<RARRAY(ary)->len; i++) {
h = (h << 1) | (h<0 ? 1 : 0);
@@ -1731,6 +2717,34 @@ rb_ary_hash(ary)
return LONG2FIX(h);
}
+/*
+ * call-seq:
+ * array.hash -> fixnum
+ *
+ * Compute a hash-code for this array. Two arrays with the same content
+ * will have the same hash code (and will compare using <code>eql?</code>).
+ */
+
+static VALUE
+rb_ary_hash(ary)
+ VALUE ary;
+{
+ return rb_exec_recursive(recursive_hash, ary, 0);
+}
+
+/*
+ * call-seq:
+ * array.include?(obj) -> true or false
+ *
+ * Returns <code>true</code> if the given object is present in
+ * <i>self</i> (that is, if any object <code>==</code> <i>anObject</i>),
+ * <code>false</code> otherwise.
+ *
+ * a = [ "a", "b", "c" ]
+ * a.include?("b") #=> true
+ * a.include?("z") #=> false
+ */
+
VALUE
rb_ary_includes(ary, item)
VALUE ary;
@@ -1746,23 +2760,61 @@ rb_ary_includes(ary, item)
return Qfalse;
}
-VALUE
-rb_ary_cmp(ary1, ary2)
- VALUE ary1, ary2;
+
+static VALUE recursive_cmp _((VALUE, VALUE, int));
+static VALUE
+recursive_cmp(ary1, ary2, recur)
+ VALUE ary1;
+ VALUE ary2;
+ int recur;
{
long i, len;
- ary2 = to_ary(ary2);
+ if (recur) return Qnil;
len = RARRAY(ary1)->len;
if (len > RARRAY(ary2)->len) {
len = RARRAY(ary2)->len;
}
for (i=0; i<len; i++) {
- VALUE v = rb_funcall(RARRAY(ary1)->ptr[i], id_cmp, 1, RARRAY(ary2)->ptr[i]);
+ VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
if (v != INT2FIX(0)) {
return v;
}
}
+ return Qundef;
+}
+
+/*
+ * call-seq:
+ * array <=> other_array -> -1, 0, +1
+ *
+ * Comparison---Returns an integer (-1, 0,
+ * or +1) if this array is less than, equal to, or greater than
+ * other_array. Each object in each array is compared
+ * (using <=>). If any value isn't
+ * equal, then that inequality is the return value. If all the
+ * values found are equal, then the return is based on a
+ * comparison of the array lengths. Thus, two arrays are
+ * ``equal'' according to <code>Array#<=></code> if and only if they have
+ * the same length and the value of each element is equal to the
+ * value of the corresponding element in the other array.
+ *
+ * [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1
+ * [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1
+ *
+ */
+
+VALUE
+rb_ary_cmp(ary1, ary2)
+ VALUE ary1, ary2;
+{
+ long len;
+ VALUE v;
+
+ ary2 = to_ary(ary2);
+ if (ary1 == ary2) return INT2FIX(0);
+ v = rb_exec_recursive(recursive_cmp, ary1, ary2);
+ if (v != Qundef) return v;
len = RARRAY(ary1)->len - RARRAY(ary2)->len;
if (len == 0) return INT2FIX(0);
if (len > 0) return INT2FIX(1);
@@ -1787,11 +2839,24 @@ ary_make_hash(ary1, ary2)
return hash;
}
+/*
+ * call-seq:
+ * array - other_array -> an_array
+ *
+ * Array Difference---Returns a new array that is a copy of
+ * the original array, removing any items that also appear in
+ * other_array. (If you need set-like behavior, see the
+ * library class Set.)
+ *
+ * [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
+ */
+
static VALUE
rb_ary_diff(ary1, ary2)
VALUE ary1, ary2;
{
- VALUE ary3, hash;
+ VALUE ary3;
+ volatile VALUE hash;
long i;
hash = ary_make_hash(to_ary(ary2), 0);
@@ -1799,16 +2864,27 @@ rb_ary_diff(ary1, ary2)
for (i=0; i<RARRAY(ary1)->len; i++) {
if (st_lookup(RHASH(hash)->tbl, RARRAY(ary1)->ptr[i], 0)) continue;
- rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ rb_ary_push(ary3, rb_ary_elt(ary1, i));
}
return ary3;
}
+/*
+ * call-seq:
+ * array & other_array
+ *
+ * Set Intersection---Returns a new array
+ * containing elements common to the two arrays, with no duplicates.
+ *
+ * [ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ]
+ */
+
+
static VALUE
rb_ary_and(ary1, ary2)
VALUE ary1, ary2;
{
- VALUE hash, ary3;
+ VALUE hash, ary3, v, vv;
long i;
ary2 = to_ary(ary2);
@@ -1817,21 +2893,32 @@ rb_ary_and(ary1, ary2)
hash = ary_make_hash(ary2, 0);
for (i=0; i<RARRAY(ary1)->len; i++) {
- VALUE v = RARRAY(ary1)->ptr[i];
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
- rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ v = vv = rb_ary_elt(ary1, i);
+ if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
+ rb_ary_push(ary3, v);
}
}
return ary3;
}
+/*
+ * call-seq:
+ * array | other_array -> an_array
+ *
+ * Set Union---Returns a new array by joining this array with
+ * other_array, removing duplicates.
+ *
+ * [ "a", "b", "c" ] | [ "c", "d", "a" ]
+ * #=> [ "a", "b", "c", "d" ]
+ */
+
static VALUE
rb_ary_or(ary1, ary2)
VALUE ary1, ary2;
{
VALUE hash, ary3;
- VALUE v;
+ VALUE v, vv;
long i;
ary2 = to_ary(ary2);
@@ -1839,48 +2926,67 @@ rb_ary_or(ary1, ary2)
hash = ary_make_hash(ary1, ary2);
for (i=0; i<RARRAY(ary1)->len; i++) {
- v = RARRAY(ary1)->ptr[i];
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
- rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ v = vv = rb_ary_elt(ary1, i);
+ if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
+ rb_ary_push(ary3, v);
}
}
for (i=0; i<RARRAY(ary2)->len; i++) {
- v = RARRAY(ary2)->ptr[i];
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
- rb_ary_push(ary3, RARRAY(ary2)->ptr[i]);
+ v = vv = rb_ary_elt(ary2, i);
+ if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
+ rb_ary_push(ary3, v);
}
}
return ary3;
}
+/*
+ * call-seq:
+ * array.uniq! -> array or nil
+ *
+ * Removes duplicate elements from _self_.
+ * Returns <code>nil</code> if no changes are made (that is, no
+ * duplicates are found).
+ *
+ * a = [ "a", "a", "b", "b", "c" ]
+ * a.uniq! #=> ["a", "b", "c"]
+ * b = [ "a", "b", "c" ]
+ * b.uniq! #=> nil
+ */
+
static VALUE
rb_ary_uniq_bang(ary)
VALUE ary;
{
- VALUE hash;
- VALUE *p, *q, *end;
-
- rb_ary_modify(ary);
+ VALUE hash, v, vv;
+ long i, j;
hash = ary_make_hash(ary, 0);
if (RARRAY(ary)->len == RHASH(hash)->tbl->num_entries) {
return Qnil;
}
- p = q = RARRAY(ary)->ptr;
- end = p + RARRAY(ary)->len;
- while (p < end) {
- VALUE v = *p;
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) {
- *q++ = *p;
+ for (i=j=0; i<RARRAY(ary)->len; i++) {
+ v = vv = rb_ary_elt(ary, i);
+ if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
+ rb_ary_store(ary, j++, v);
}
- p++;
}
- RARRAY(ary)->len = (q - RARRAY(ary)->ptr);
+ RARRAY(ary)->len = j;
return ary;
}
+/*
+ * call-seq:
+ * array.uniq -> an_array
+ *
+ * Returns a new array by removing duplicate values in <i>self</i>.
+ *
+ * a = [ "a", "a", "b", "b", "c" ]
+ * a.uniq #=> ["a", "b", "c"]
+ */
+
static VALUE
rb_ary_uniq(ary)
VALUE ary;
@@ -1890,6 +2996,17 @@ rb_ary_uniq(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.compact! -> array or nil
+ *
+ * Removes +nil+ elements from array.
+ * Returns +nil+ if no changes were made.
+ *
+ * [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
+ * [ "a", "b", "c" ].compact! #=> nil
+ */
+
static VALUE
rb_ary_compact_bang(ary)
VALUE ary;
@@ -1913,6 +3030,16 @@ rb_ary_compact_bang(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.compact -> an_array
+ *
+ * Returns a copy of _self_ with all +nil+ elements removed.
+ *
+ * [ "a", nil, "b", nil, "c", nil ].compact
+ * #=> [ "a", "b", "c" ]
+ */
+
static VALUE
rb_ary_compact(ary)
VALUE ary;
@@ -1922,6 +3049,17 @@ rb_ary_compact(ary)
return ary;
}
+/*
+ * call-seq:
+ * array.nitems -> int
+ *
+ * Returns the number of non-<code>nil</code> elements in _self_.
+ *
+ * May be zero.
+ *
+ * [ 1, nil, 3, nil, 5 ].nitems #=> 3
+ */
+
static VALUE
rb_ary_nitems(ary)
VALUE ary;
@@ -1929,78 +3067,699 @@ rb_ary_nitems(ary)
long n = 0;
VALUE *p, *pend;
- p = RARRAY(ary)->ptr;
- pend = p + RARRAY(ary)->len;
-
- while (p < pend) {
+ for (p = RARRAY(ary)->ptr, pend = p + RARRAY(ary)->len; p < pend; p++) {
if (!NIL_P(*p)) n++;
- p++;
}
return LONG2NUM(n);
}
-static long
-flatten(ary, idx, ary2, memo)
+/*
+ * call-seq:
+ * array.count -> int
+ * array.count(obj) -> int
+ * array.count { |item| block } -> int
+ *
+ * Returns the number of elements. If an argument is given, counts
+ * the number of elements which equals to <i>obj</i>. If a block is
+ * given, counts the number of elements yielding a true value.
+ *
+ * ary = [1, 2, 4, 2]
+ * ary.count # => 4
+ * ary.count(2) # => 2
+ * ary.count{|x|x%2==0} # => 3
+ *
+ */
+
+static VALUE
+rb_ary_count(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
- long idx;
- VALUE ary2, memo;
{
- VALUE id;
- long i = idx;
- long n, lim = idx + RARRAY(ary2)->len;
+ long n = 0;
+
+ if (argc == 0) {
+ VALUE *p, *pend;
+
+ if (!rb_block_given_p())
+ return LONG2NUM(RARRAY_LEN(ary));
- id = rb_obj_id(ary2);
- if (rb_ary_includes(memo, id)) {
- rb_raise(rb_eArgError, "tried to flatten recursive array");
+ for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
+ if (RTEST(rb_yield(*p))) n++;
+ }
}
- rb_ary_push(memo, id);
- rb_ary_update(ary, idx, 1, ary2);
- while (i < lim) {
- if (TYPE(RARRAY(ary)->ptr[i]) == T_ARRAY) {
- n = flatten(ary, i, RARRAY(ary)->ptr[i], memo);
- i += n; lim += n;
+ else {
+ VALUE obj, *p, *pend;
+
+ rb_scan_args(argc, argv, "1", &obj);
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
+ for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
+ if (rb_equal(*p, obj)) n++;
}
- i++;
}
- rb_ary_pop(memo);
- return lim - idx - 1; /* returns number of increased items */
+ return LONG2NUM(n);
}
static VALUE
-rb_ary_flatten_bang(ary)
+flatten(ary, level, modified)
VALUE ary;
+ int level;
+ int *modified;
{
long i = 0;
- int mod = 0;
- VALUE memo = Qnil;
+ VALUE stack, result, tmp, elt;
+ st_table *memo;
+ st_data_t id;
+
+ stack = ary_new(0, ARY_DEFAULT_SIZE);
+ result = ary_new(0, RARRAY_LEN(ary));
+ memo = st_init_numtable();
+ st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
+ *modified = 0;
+
+ while (1) {
+ while (i < RARRAY(ary)->len) {
+ elt = RARRAY(ary)->ptr[i++];
+ tmp = rb_check_array_type(elt);
+ if (RBASIC(result)->klass) {
+ rb_raise(rb_eRuntimeError, "flatten reentered");
+ }
+ if (NIL_P(tmp) || (level >= 0 && RARRAY(stack)->len / 2 >= level)) {
+ rb_ary_push(result, elt);
+ }
+ else {
+ *modified = 1;
+ id = (st_data_t)tmp;
+ if (st_lookup(memo, id, 0)) {
+ st_free_table(memo);
+ rb_raise(rb_eArgError, "tried to flatten recursive array");
+ }
+ st_insert(memo, id, (st_data_t)Qtrue);
+ rb_ary_push(stack, ary);
+ rb_ary_push(stack, LONG2NUM(i));
+ ary = tmp;
+ i = 0;
+ }
+ }
+ if (RARRAY(stack)->len == 0) {
+ break;
+ }
+ id = (st_data_t)ary;
+ st_delete(memo, &id, 0);
+ tmp = rb_ary_pop(stack);
+ i = NUM2LONG(tmp);
+ ary = rb_ary_pop(stack);
+ }
+
+ st_free_table(memo);
+
+ RBASIC(result)->klass = rb_class_of(ary);
+ return result;
+}
+
+/*
+ * call-seq:
+ * array.flatten! -> array or nil
+ * array.flatten!(level) -> array or nil
+ *
+ * Flattens _self_ in place.
+ * Returns <code>nil</code> if no modifications were made (i.e.,
+ * <i>array</i> contains no subarrays.) If the optional <i>level</i>
+ * argument determines the level of recursion to flatten.
+ *
+ * a = [ 1, 2, [3, [4, 5] ] ]
+ * a.flatten! #=> [1, 2, 3, 4, 5]
+ * a.flatten! #=> nil
+ * a #=> [1, 2, 3, 4, 5]
+ * a = [ 1, 2, [3, [4, 5] ] ]
+ * a.flatten!(1) #=> [1, 2, 3, [4, 5]]
+ */
+
+static VALUE
+rb_ary_flatten_bang(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ int mod = 0, level = -1;
+ VALUE result, lv;
+
+ rb_scan_args(argc, argv, "01", &lv);
+ if (!NIL_P(lv)) level = NUM2INT(lv);
+ if (level == 0) return ary;
+
+ result = flatten(ary, level, &mod);
+ if (mod == 0) return Qnil;
+ rb_ary_replace(ary, result);
+
+ return ary;
+}
+
+/*
+ * call-seq:
+ * array.flatten -> an_array
+ * array.flatten(level) -> an_array
+ *
+ * Returns a new array that is a one-dimensional flattening of this
+ * array (recursively). That is, for every element that is an array,
+ * extract its elements into the new array. If the optional
+ * <i>level</i> argument determines the level of recursion to flatten.
+ *
+ * s = [ 1, 2, 3 ] #=> [1, 2, 3]
+ * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
+ * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
+ * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ * a = [ 1, 2, [3, [4, 5] ] ]
+ * a.flatten(1) #=> [1, 2, 3, [4, 5]]
+ */
+
+static VALUE
+rb_ary_flatten(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ int mod = 0, level = -1;
+ VALUE result, lv;
+
+ rb_scan_args(argc, argv, "01", &lv);
+ if (!NIL_P(lv)) level = NUM2INT(lv);
+ if (level == 0) return ary;
+
+ result = flatten(ary, level, &mod);
+ if (OBJ_TAINTED(ary)) OBJ_TAINT(result);
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * array.shuffle! -> array or nil
+ *
+ * Shuffles elements in _self_ in place.
+ */
+
+
+static VALUE
+rb_ary_shuffle_bang(ary)
+ VALUE ary;
+{
+ long i = RARRAY(ary)->len;
rb_ary_modify(ary);
- while (i<RARRAY(ary)->len) {
- VALUE ary2 = RARRAY(ary)->ptr[i];
+ while (i) {
+ long j = rb_genrand_real()*i;
+ VALUE tmp = RARRAY(ary)->ptr[--i];
+ RARRAY(ary)->ptr[i] = RARRAY(ary)->ptr[j];
+ RARRAY(ary)->ptr[j] = tmp;
+ }
+ return ary;
+}
+
- if (TYPE(ary2) == T_ARRAY) {
- if (NIL_P(memo)) {
- memo = rb_ary_new();
+/*
+ * call-seq:
+ * array.shuffle -> an_array
+ *
+ * Returns a new array with elements of this array shuffled.
+ *
+ * a = [ 1, 2, 3 ] #=> [1, 2, 3]
+ * a.shuffle #=> [2, 3, 1]
+ */
+
+static VALUE
+rb_ary_shuffle(VALUE ary)
+{
+ ary = rb_ary_dup(ary);
+ rb_ary_shuffle_bang(ary);
+ return ary;
+}
+
+
+/*
+ * call-seq:
+ * array.choice -> obj
+ *
+ * Choose a random element from an array.
+ */
+
+
+static VALUE
+rb_ary_choice(ary)
+ VALUE ary;
+{
+ long i, j;
+
+ i = RARRAY(ary)->len;
+ if (i == 0) return Qnil;
+ j = rb_genrand_real()*i;
+ return RARRAY(ary)->ptr[j];
+}
+
+
+/*
+ * call-seq:
+ * ary.cycle {|obj| block }
+ * ary.cycle(n) {|obj| block }
+ *
+ * Calls <i>block</i> for each element repeatedly _n_ times or
+ * forever if none or nil is given. If a non-positive number is
+ * given or the array is empty, does nothing. Returns nil if the
+ * loop has finished without getting interrupted.
+ *
+ * a = ["a", "b", "c"]
+ * a.cycle {|x| puts x } # print, a, b, c, a, b, c,.. forever.
+ * a.cycle(2) {|x| puts x } # print, a, b, c, a, b, c.
+ *
+ */
+
+static VALUE
+rb_ary_cycle(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ long n, i;
+ VALUE nv = Qnil;
+
+ rb_scan_args(argc, argv, "01", &nv);
+
+ RETURN_ENUMERATOR(ary, argc, argv);
+ if (NIL_P(nv)) {
+ n = -1;
+ }
+ else {
+ n = NUM2LONG(nv);
+ if (n <= 0) return Qnil;
+ }
+
+ while (RARRAY(ary)->len > 0 && (n < 0 || 0 < n--)) {
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ rb_yield(RARRAY(ary)->ptr[i]);
+ }
+ }
+ return Qnil;
+}
+
+#define tmpbuf(n, size) rb_str_tmp_new((n)*(size))
+
+/*
+ * Recursively compute permutations of r elements of the set [0..n-1].
+ * When we have a complete permutation of array indexes, copy the values
+ * at those indexes into a new array and yield that array.
+ *
+ * n: the size of the set
+ * r: the number of elements in each permutation
+ * p: the array (of size r) that we're filling in
+ * index: what index we're filling in now
+ * used: an array of booleans: whether a given index is already used
+ * values: the Ruby array that holds the actual values to permute
+ */
+static void
+permute0(n, r, p, index, used, values)
+ long n, r, *p, index;
+ int *used;
+ VALUE values;
+{
+ long i,j;
+ for (i = 0; i < n; i++) {
+ if (used[i] == 0) {
+ p[index] = i;
+ if (index < r-1) { /* if not done yet */
+ used[i] = 1; /* mark index used */
+ permute0(n, r, p, index+1, /* recurse */
+ used, values);
+ used[i] = 0; /* index unused */
+ }
+ else {
+ /* We have a complete permutation of array indexes */
+ /* Build a ruby array of the corresponding values */
+ /* And yield it to the associated block */
+ VALUE result = rb_ary_new2(r);
+ VALUE *result_array = RARRAY(result)->ptr;
+ const VALUE *values_array = RARRAY(values)->ptr;
+
+ for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
+ RARRAY(result)->len = r;
+ rb_yield(result);
}
- i += flatten(ary, i, ary2, memo);
- mod = 1;
}
- i++;
}
- if (mod == 0) return Qnil;
+}
+
+/*
+ * call-seq:
+ * ary.permutation { |p| block } -> array
+ * ary.permutation -> enumerator
+ * ary.permutation(n) { |p| block } -> array
+ * ary.permutation(n) -> enumerator
+ *
+ * When invoked with a block, yield all permutations of length <i>n</i>
+ * of the elements of <i>ary</i>, then return the array itself.
+ * If <i>n</i> is not specified, yield all permutations of all elements.
+ * The implementation makes no guarantees about the order in which
+ * the permutations are yielded.
+ *
+ * When invoked without a block, return an enumerator object instead.
+ *
+ * Examples:
+ *
+ * a = [1, 2, 3]
+ * a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
+ * a.permutation(1).to_a #=> [[1],[2],[3]]
+ * a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
+ * a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
+ * a.permutation(0).to_a #=> [[]] # one permutation of length 0
+ * a.permutation(4).to_a #=> [] # no permutations of length 4
+ */
+
+static VALUE
+rb_ary_permutation(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ VALUE num;
+ long r, n, i;
+
+ n = RARRAY(ary)->len; /* Array length */
+ RETURN_ENUMERATOR(ary, argc, argv); /* Return enumerator if no block */
+ rb_scan_args(argc, argv, "01", &num);
+ r = NIL_P(num) ? n : NUM2LONG(num); /* Permutation size from argument */
+
+ if (r < 0 || n < r) {
+ /* no permutations: yield nothing */
+ }
+ else if (r == 0) { /* exactly one permutation: the zero-length array */
+ rb_yield(rb_ary_new2(0));
+ }
+ else if (r == 1) { /* this is a special, easy case */
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ rb_yield(rb_ary_new3(1, RARRAY(ary)->ptr[i]));
+ }
+ }
+ else { /* this is the general case */
+ volatile VALUE t0 = tmpbuf(n,sizeof(long));
+ long *p = (long*)RSTRING(t0)->ptr;
+ volatile VALUE t1 = tmpbuf(n,sizeof(int));
+ int *used = (int*)RSTRING(t1)->ptr;
+ VALUE ary0 = ary_make_shared(ary); /* private defensive copy of ary */
+
+ for (i = 0; i < n; i++) used[i] = 0; /* initialize array */
+
+ permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
+ RB_GC_GUARD(t0);
+ RB_GC_GUARD(t1);
+ }
return ary;
}
+static long
+combi_len(n, k)
+ long n, k;
+{
+ long i, val = 1;
+
+ if (k*2 > n) k = n-k;
+ if (k == 0) return 1;
+ if (k < 0) return 0;
+ val = 1;
+ for (i=1; i <= k; i++,n--) {
+ long m = val;
+ val *= n;
+ if (val < m) {
+ rb_raise(rb_eRangeError, "too big for combination");
+ }
+ val /= i;
+ }
+ return val;
+}
+
+/*
+ * call-seq:
+ * ary.combination(n) { |c| block } -> ary
+ * ary.combination(n) -> enumerator
+ *
+ * When invoked with a block, yields all combinations of length <i>n</i>
+ * of elements from <i>ary</i> and then returns <i>ary</i> itself.
+ * The implementation makes no guarantees about the order in which
+ * the combinations are yielded.
+ *
+ * When invoked without a block, returns an enumerator object instead.
+ *
+ * Examples:
+ *
+ * a = [1, 2, 3, 4]
+ * a.combination(1).to_a #=> [[1],[2],[3],[4]]
+ * a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
+ * a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
+ * a.combination(4).to_a #=> [[1,2,3,4]]
+ * a.combination(0).to_a #=> [[]] # one combination of length 0
+ * a.combination(5).to_a #=> [] # no combinations of length 5
+ *
+ */
+
static VALUE
-rb_ary_flatten(ary)
+rb_ary_combination(ary, num)
VALUE ary;
+ VALUE num;
{
- ary = rb_ary_dup(ary);
- rb_ary_flatten_bang(ary);
+ long n, i, len;
+
+ n = NUM2LONG(num);
+ RETURN_ENUMERATOR(ary, 1, &num);
+ len = RARRAY(ary)->len;
+ if (n < 0 || len < n) {
+ /* yield nothing */
+ }
+ else if (n == 0) {
+ rb_yield(rb_ary_new2(0));
+ }
+ else if (n == 1) {
+ for (i = 0; i < len; i++) {
+ rb_yield(rb_ary_new3(1, RARRAY(ary)->ptr[i]));
+ }
+ }
+ else {
+ volatile VALUE t0 = tmpbuf(n+1, sizeof(long));
+ long *stack = (long*)RSTRING(t0)->ptr;
+ long nlen = combi_len(len, n);
+ volatile VALUE cc = rb_ary_new2(n);
+ VALUE *chosen = RARRAY(cc)->ptr;
+ long lev = 0;
+
+ RBASIC(cc)->klass = 0;
+ MEMZERO(stack, long, n);
+ stack[0] = -1;
+ for (i = 0; i < nlen; i++) {
+ chosen[lev] = RARRAY(ary)->ptr[stack[lev+1]];
+ for (lev++; lev < n; lev++) {
+ chosen[lev] = RARRAY(ary)->ptr[stack[lev+1] = stack[lev]+1];
+ }
+ rb_yield(rb_ary_new4(n, chosen));
+ do {
+ stack[lev--]++;
+ } while (lev && (stack[lev+1]+n == len+lev+1));
+ }
+ }
return ary;
}
+/*
+ * call-seq:
+ * ary.product(other_ary, ...)
+ *
+ * Returns an array of all combinations of elements from all arrays.
+ * The length of the returned array is the product of the length
+ * of ary and the argument arrays
+ *
+ * [1,2,3].product([4,5]) # => [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
+ * [1,2].product([1,2]) # => [[1,1],[1,2],[2,1],[2,2]]
+ * [1,2].product([3,4],[5,6]) # => [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
+ * # [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
+ * [1,2].product() # => [[1],[2]]
+ * [1,2].product([]) # => []
+ */
+
+static VALUE
+rb_ary_product(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ int n = argc+1; /* How many arrays we're operating on */
+ volatile VALUE t0 = tmpbuf(n, sizeof(VALUE));
+ volatile VALUE t1 = tmpbuf(n, sizeof(int));
+ VALUE *arrays = (VALUE*)RSTRING(t0)->ptr; /* The arrays we're computing the product of */
+ int *counters = (int*)RSTRING(t1)->ptr; /* The current position in each one */
+ VALUE result; /* The array we'll be returning */
+ long i,j;
+ long resultlen = 1;
+
+ RBASIC(t0)->klass = 0;
+ RBASIC(t1)->klass = 0;
+
+ /* initialize the arrays of arrays */
+ arrays[0] = ary;
+ for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
+
+ /* initialize the counters for the arrays */
+ for (i = 0; i < n; i++) counters[i] = 0;
+
+ /* Compute the length of the result array; return [] if any is empty */
+ for (i = 0; i < n; i++) {
+ long k = RARRAY(arrays[i])->len, l = resultlen;
+ if (k == 0) return rb_ary_new2(0);
+ resultlen *= k;
+ if (resultlen < k || resultlen < l || resultlen / k != l) {
+ rb_raise(rb_eRangeError, "too big to product");
+ }
+ }
+
+ /* Otherwise, allocate and fill in an array of results */
+ result = rb_ary_new2(resultlen);
+ for (i = 0; i < resultlen; i++) {
+ int m;
+ /* fill in one subarray */
+ VALUE subarray = rb_ary_new2(n);
+ for (j = 0; j < n; j++) {
+ rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
+ }
+
+ /* put it on the result array */
+ rb_ary_push(result, subarray);
+
+ /*
+ * Increment the last counter. If it overflows, reset to 0
+ * and increment the one before it.
+ */
+ m = n-1;
+ counters[m]++;
+ while (m > 0 && counters[m] == RARRAY(arrays[m])->len) {
+ counters[m] = 0;
+ m--;
+ counters[m]++;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * ary.take(n) => array
+ *
+ * Returns first n elements from <i>ary</i>.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.take(3) # => [1, 2, 3]
+ *
+ */
+
+static VALUE
+rb_ary_take(obj, n)
+ VALUE obj;
+ VALUE n;
+{
+ long len = NUM2LONG(n);
+ if (len < 0) {
+ rb_raise(rb_eArgError, "attempt to take negative size");
+ }
+
+ return rb_ary_subseq(obj, 0, len);
+}
+
+/*
+ * call-seq:
+ * ary.take_while {|arr| block } => array
+ *
+ * Passes elements to the block until the block returns nil or false,
+ * then stops iterating and returns an array of all prior elements.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.take_while {|i| i < 3 } # => [1, 2]
+ *
+ */
+
+static VALUE
+rb_ary_take_while(ary)
+ VALUE ary;
+{
+ long i;
+
+ RETURN_ENUMERATOR(ary, 0, 0);
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ if (!RTEST(rb_yield(RARRAY(ary)->ptr[i]))) break;
+ }
+ return rb_ary_take(ary, LONG2FIX(i));
+}
+
+/*
+ * call-seq:
+ * ary.drop(n) => array
+ *
+ * Drops first n elements from <i>ary</i>, and returns rest elements
+ * in an array.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.drop(3) # => [4, 5, 0]
+ *
+ */
+
+static VALUE
+rb_ary_drop(ary, n)
+ VALUE ary;
+ VALUE n;
+{
+ VALUE result;
+ long pos = NUM2LONG(n);
+ if (pos < 0) {
+ rb_raise(rb_eArgError, "attempt to drop negative size");
+ }
+
+ result = rb_ary_subseq(ary, pos, RARRAY(ary)->len);
+ if (result == Qnil) result = rb_ary_new();
+ return result;
+}
+
+/*
+ * call-seq:
+ * ary.drop_while {|arr| block } => array
+ *
+ * Drops elements up to, but not including, the first element for
+ * which the block returns nil or false and returns an array
+ * containing the remaining elements.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.drop_while {|i| i < 3 } # => [3, 4, 5, 0]
+ *
+ */
+
+static VALUE
+rb_ary_drop_while(ary)
+ VALUE ary;
+{
+ long i;
+
+ RETURN_ENUMERATOR(ary, 0, 0);
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ if (!RTEST(rb_yield(RARRAY(ary)->ptr[i]))) break;
+ }
+ return rb_ary_drop(ary, LONG2FIX(i));
+}
+
+
+
+/* Arrays are ordered, integer-indexed collections of any object.
+ * Array indexing starts at 0, as in C or Java. A negative index is
+ * assumed to be relative to the end of the array---that is, an index of -1
+ * indicates the last element of the array, -2 is the next to last
+ * element in the array, and so on.
+ */
+
void
Init_Array()
{
@@ -2031,8 +3790,8 @@ Init_Array()
rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
- rb_define_method(rb_cArray, "pop", rb_ary_pop, 0);
- rb_define_method(rb_cArray, "shift", rb_ary_shift, 0);
+ rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
+ rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
rb_define_method(rb_cArray, "each", rb_ary_each, 0);
@@ -2041,8 +3800,9 @@ Init_Array()
rb_define_method(rb_cArray, "length", rb_ary_length, 0);
rb_define_alias(rb_cArray, "size", "length");
rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
- rb_define_method(rb_cArray, "index", rb_ary_index, 1);
- rb_define_method(rb_cArray, "rindex", rb_ary_rindex, 1);
+ rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
+ rb_define_method(rb_cArray, "index", rb_ary_index, -1);
+ rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
rb_define_method(rb_cArray, "indexes", rb_ary_indexes, -1);
rb_define_method(rb_cArray, "indices", rb_ary_indexes, -1);
rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
@@ -2054,7 +3814,7 @@ Init_Array()
rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
- rb_define_method(rb_cArray, "select", rb_ary_select, -1);
+ rb_define_method(rb_cArray, "select", rb_ary_select, 0);
rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
@@ -2086,9 +3846,22 @@ Init_Array()
rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
- rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
- rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, 0);
+ rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
+ rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0);
+ rb_define_method(rb_cArray, "count", rb_ary_count, -1);
+ rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, 0);
+ rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, 0);
+ rb_define_method(rb_cArray, "choice", rb_ary_choice, 0);
+ rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
+ rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
+ rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
+ rb_define_method(rb_cArray, "product", rb_ary_product, -1);
+
+ rb_define_method(rb_cArray, "take", rb_ary_take, 1);
+ rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
+ rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
+ rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
id_cmp = rb_intern("<=>");
inspect_key = rb_intern("__inspect_key__");
diff --git a/bcc32/Makefile.sub b/bcc32/Makefile.sub
index 99305ab068..713b5c69df 100644
--- a/bcc32/Makefile.sub
+++ b/bcc32/Makefile.sub
@@ -1,10 +1,15 @@
# -*- makefile -*-
SHELL = $(COMSPEC)
+MKFILES = Makefile
#### Start of system configuration section. ####
+!ifndef OS
OS = bccwin32
-RT = $(OS)
+!endif
+!if !defined(RT)
+!error RT not defined. Retry from configure pass.
+!endif
## variables may be overridden by $(compile_dir)/Makefile
!ifndef srcdir
@@ -56,6 +61,7 @@ AR = tlib
PURIFY =
AUTOCONF = autoconf
+RM = $(srcdir:/=\)\win32\rm.bat
!if !defined(PROCESSOR_ARCHITECTURE)
PROCESSOR_ARCHITECTURE = x86
@@ -91,14 +97,28 @@ exec_prefix = $(prefix)
!ifndef libdir
libdir = $(exec_prefix)/lib
!endif
-!ifndef DESTDIR
-DESTDIR = $(prefix)
+!if !defined(datadir)
+datadir = /share
!endif
-!ifndef CFLAGS
-CFLAGS = -q $(DEBUGFLAGS) $(OPTFLAGS) $(PROCESSOR_FLAG) -w-
+!ifndef EXTOUT
+EXTOUT = .ext
+!endif
+!ifndef RIDATADIR
+RIDATADIR = $(DESTDIR)$(datadir)/ri/$(MAJOR).$(MINOR)/system
+!endif
+!ifndef TESTUI
+TESTUI = console
!endif
-!ifndef CPPFLAGS
-CPPFLAGS = -I. -I$(srcdir) -I$(srcdir)missing
+!ifndef TESTS
+TESTS =
+!endif
+!ifndef RDOCTARGET
+RDOCTARGET = install-nodoc
+!endif
+
+OUTFLAG = -o
+!ifndef CFLAGS
+CFLAGS = -q -tWR -tWC $(DEBUGFLAGS) $(OPTFLAGS) $(PROCESSOR_FLAG) -w- -wsus -wcpt -wdup -wext -wrng -wrpt -wzdi
!endif
!ifndef LDFLAGS
LDFLAGS = -S:$(STACK)
@@ -109,16 +129,19 @@ RFLAGS = $(iconinc)
!ifndef EXTLIBS
EXTLIBS =
!endif
-LIBS = cw32.lib import32.lib ws2_32.lib $(EXTLIBS)
+!ifndef MEMLIB
+MEMLIB =
+!endif
+LIBS = $(MEMLIB) cw32i.lib import32.lib ws2_32.lib $(EXTLIBS)
MISSING = acosh.obj crypt.obj erf.obj win32.obj
!ifndef STACK
STACK = 0x2000000
!endif
-XCFLAGS = -DRUBY_EXPORT
+XCFLAGS = -DRUBY_EXPORT -I. -I$(srcdir) -I$(srcdir)/missing
-ARFLAGS = /a
+ARFLAGS = /a /p32
LD = ilink32 -q -Gn
LDSHARED = $(LD)
XLDFLAGS = -Tpe c0x32.obj
@@ -134,7 +157,8 @@ EXEEXT = .exe
PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
WPROGRAM=$(RUBYW_INSTALL_NAME)$(EXEEXT)
RUBYDEF = $(RUBY_SO_NAME).def
-MINIRUBY = .\miniruby$(EXEEXT)
+MINIRUBY = .\miniruby$(EXEEXT) -I$(srcdir)/lib $(MINIRUBYOPT)
+RUNRUBY = .\$(PROGRAM) "$(srcdir)/runruby.rb" --extout="$(EXTOUT)" --
ORGLIBPATH = $(LIB)
@@ -145,160 +169,147 @@ LIBRUBY_SO = $(RUBY_SO_NAME).dll
LIBRUBY = $(RUBY_SO_NAME).lib
LIBRUBYARG = $(LIBRUBY)
-!ifndef EXTOBJS
-EXTOBJS = dmyext.obj
-!endif
-
-MAINOBJ = main.obj
-WINMAINOBJ = winmain.obj
-
-OBJS = array.obj \
- bignum.obj \
- class.obj \
- compar.obj \
- dir.obj \
- dln.obj \
- enum.obj \
- error.obj \
- eval.obj \
- file.obj \
- gc.obj \
- hash.obj \
- inits.obj \
- io.obj \
- marshal.obj \
- math.obj \
- numeric.obj \
- object.obj \
- pack.obj \
- parse.obj \
- prec.obj \
- process.obj \
- random.obj \
- range.obj \
- re.obj \
- regex.obj \
- ruby.obj \
- signal.obj \
- sprintf.obj \
- st.obj \
- string.obj \
- struct.obj \
- time.obj \
- util.obj \
- variable.obj \
- version.obj \
- $(MISSING)
-
-SCRIPT_ARGS = "--dest-dir=$(DESTDIR)" \
- "--make=$(MAKE)" \
- "--mflags=$(MFLAGS)" \
- "--make-flags=$(MAKEFLAGS)"
-
-all: miniruby$(EXEEXT) rbconfig.rb \
- $(LIBRUBY) $(MISCLIBS)
- .\miniruby$(EXEEXT) $(srcdir)ext/extmk.rb --extstatic=$(EXTSTATIC) $(SCRIPT_ARGS)
+PREP = miniruby$(EXEEXT)
+
+OBJEXT = obj
+
+INSTALLED_LIST= .installed.list
+
+WINMAINOBJ = winmain.$(OBJEXT)
+MINIOBJS = dmydln.$(OBJEXT)
+
+.path.c = .;$(srcdir);$(srcdir)/win32;$(srcdir)/missing
+.path.h = .;$(srcdir);$(srcdir)/win32;$(srcdir)/missing
+.path.y = $(srcdir)
+.path. = $(srcdir)
+
+.c.obj:
+ $(CC) $(CFLAGS) $(XCFLAGS) -I. $(CPPFLAGS) -c $(<:/=\)
+
+.rc.res:
+ $(RC) $(RFLAGS) -I. -I$(<D). $(iconinc) -I$(srcdir)/win32 $(RFLAGS) -fo$@ $(<:/=\)
+
+.y.c:
+ $(YACC) $(YFLAGS) $(<:\=/)
+ sed -e "s!^ *extern char \*getenv();!/* & */!;s/^\(#.*\)y\.tab/\1parse/" y.tab.c > $(@F)
+ @del y.tab.c
+
+all: $(srcdir)/bcc32/Makefile.sub $(srcdir)/common.mk
ruby: $(PROGRAM)
rubyw: $(WPROGRAM)
-lib: $(LIBRUBY)
-dll: $(LIBRUBY_SO)
-config: config.h config.status
+!include $(srcdir)/common.mk
-config.h:
- @echo Creating $(@:.\=)
- @type > $@ &&|
+$(MKFILES): $(srcdir)/bcc32/Makefile.sub $(srcdir)/bcc32/configure.bat $(srcdir)/bcc32/setup.mak
+ $(COMSPEC) /C $(srcdir:/=\)\bcc32\configure.bat $(configure_args)
+ @echo $(MKFILES) should be updated, re-run $(MAKE).
+ @$(MAKE) > nul -q -f &&|
+PHONY: nul
+ @exit
+|
+
+CONFIG_H = ./.config.h.time
+
+config: config.status
+
+config.status: $(CONFIG_H)
+
+$(CONFIG_H): $(MKFILES) $(srcdir)/bcc32/Makefile.sub
+ @$(srcdir:/=\)\win32\ifchange.bat config.h &&|
+\#define HAVE_SYS_TYPES_H 1
+\#define HAVE_SYS_STAT_H 1
+\#define HAVE_STDLIB_H 1
+\#define HAVE_STRING_H 1
+\#define HAVE_MEMORY_H 1
+\#define HAVE_OFF_T 1
+\#define SIZEOF_INT 4
+\#define SIZEOF_SHORT 2
+\#define SIZEOF_LONG 4
+\#define SIZEOF_LONG_LONG 0
+\#define SIZEOF___INT64 8
+\#define SIZEOF_OFF_T 4
+\#define SIZEOF_VOIDP 4
+\#define SIZEOF_FLOAT 4
+\#define SIZEOF_DOUBLE 8
+\#define SIZEOF_TIME_T 4
\#define HAVE_PROTOTYPES 1
+\#define TOKEN_PASTE(x,y) x\#\#y
\#define HAVE_STDARG_PROTOTYPES 1
-/* \#define HAVE_ATTR_NORETURN 1 */
\#define NORETURN(x) x
-\#define TOKEN_PASTE(x,y) x\#\#y
-\#define inline __inline
-/* \#define HAVE_DIRENT_H 1 */
-/* \#define HAVE_UNISTD_H 1 */
-\#define HAVE_STDLIB_H 1
+\#define RUBY_EXTERN extern __declspec(dllimport)
+\#define HAVE_DECL_SYS_NERR 1
\#define HAVE_LIMITS_H 1
-/* \#define HAVE_SYS_FILE_H 1 */
\#define HAVE_FCNTL_H 1
-/* \#define HAVE_PWD_H 1 */
-/* \#define HAVE_SYS_TIME_H 1 */
-/* \#define HAVE_SYS_TIMES_H 1 */
-/* \#define HAVE_SYS_PARAM_H 1 */
-/* \#define HAVE_SYS_WAIT_H 1 */
-\#define HAVE_STRING_H 1
\#define HAVE_UTIME_H 1
-\#define HAVE_MEMORY_H 1
-/* \#define HAVE_ST_BLKSIZE 1 */
+\#define HAVE_FLOAT_H 1
+\#define rb_uid_t uid_t
+\#define rb_gid_t gid_t
+\#define rb_pid_t int
+\#define HAVE_STRUCT_STAT_ST_RDEV 1
\#define HAVE_ST_RDEV 1
-/* \#define GETGROUPS_T gid_t */
\#define GETGROUPS_T int
\#define RETSIGTYPE void
\#define HAVE_ALLOCA 1
-\#define vfork fork
+\#define HAVE_DUP2 1
+\#define HAVE_MEMMOVE 1
+\#define HAVE_MKDIR 1
+\#define HAVE_STRCASECMP 1
+\#define HAVE_STRNCASECMP 1
+\#define HAVE_STRERROR 1
+\#define HAVE_STRFTIME 1
+\#define HAVE_STRCHR 1
+\#define HAVE_STRSTR 1
+\#define HAVE_STRTOD 1
+\#define HAVE_STRTOL 1
+\#define HAVE_STRTOUL 1
+\#define HAVE_VSNPRINTF 1
+\#define HAVE_ISNAN 1
+\#define HAVE_FINITE 1
+\#define HAVE_HYPOT 1
\#define HAVE_FMOD 1
-/* \#define HAVE_RANDOM 1 */
\#define HAVE_WAITPID 1
-\#define HAVE_GETCWD 1
\#define HAVE_FSYNC 1
-/* \#define HAVE_TRUNCATE 1 */
+\#define HAVE_GETCWD 1
\#define HAVE_CHSIZE 1
\#define HAVE_TIMES 1
-/* \#define HAVE_UTIMES 1 */
-/* \#define HAVE_FCNTL 1 */
-/* \#define HAVE_SETITIMER 1 */
-/* \#define HAVE_GETGROUPS 1 */
-/* \#define HAVE_SIGPROCMASK 1 */
-\#define HAVE_GETLOGIN 1
+\#define HAVE_FCNTL 1
+\#define HAVE_LINK 1
\#define HAVE_TELLDIR 1
\#define HAVE_SEEKDIR 1
\#define HAVE_COSH 1
\#define HAVE_SINH 1
\#define HAVE_TANH 1
-
-\#define NEED_IO_SEEK_BETWEEN_RW 1
-\#define RSHIFT(x,y) ((x)>>y)
+\#define RSHIFT(x,y) ((x)>>(int)y)
\#define FILE_COUNT level
\#define FILE_READPTR curp
+\#define RUBY_SETJMP(env) _setjmp(env)
+\#define RUBY_LONGJMP(env,val) longjmp(env,val)
+\#define RUBY_JMP_BUF jmp_buf
+\#define inline __inline
+\#define NEED_IO_SEEK_BETWEEN_RW 1
+\#define STACK_GROW_DIRECTION -1
\#define DEFAULT_KCODE KCODE_NONE
\#define DLEXT ".so"
-\#define DLEXT2 ".dll"
\#define RUBY_LIB "/lib/ruby/$(MAJOR).$(MINOR)"
\#define RUBY_SITE_LIB "/lib/ruby/site_ruby"
\#define RUBY_SITE_LIB2 "/lib/ruby/site_ruby/$(MAJOR).$(MINOR)"
+\#define RUBY_VENDOR_LIB "/lib/ruby/vendor_ruby"
+\#define RUBY_VENDOR_LIB2 "/lib/ruby/vendor_ruby/$(MAJOR).$(MINOR)"
\#define RUBY_PLATFORM "$(ARCH)-$(OS)"
\#define RUBY_ARCHLIB "/lib/ruby/$(MAJOR).$(MINOR)/$(ARCH)-$(OS)"
\#define RUBY_SITE_ARCHLIB "/lib/ruby/site_ruby/$(MAJOR).$(MINOR)/$(ARCH)-$(OS)"
-
-\#define SIZEOF_INT 4
-\#define SIZEOF_SHORT 2
-\#define SIZEOF_LONG 4
-\#define SIZEOF___INT64 8
-\#define SIZEOF_VOIDP 4
-\#define SIZEOF_FLOAT 4
-\#define SIZEOF_DOUBLE 8
-
-\#define HAVE_DECL_SYS_NERR 1
-\#define HAVE_ISINF 1
-\#define HAVE_ISNAN 1
-\#define HAVE_MEMMOVE 1
-\#define HAVE_MKDIR 1
-\#define HAVE_STRCASECMP 1
-\#define HAVE_STRNCASECMP 1
-\#define HAVE_STRCHR 1
-\#define HAVE_STRERROR 1
-\#define HAVE_STRFTIME 1
-\#define HAVE_STRSTR 1
-\#define HAVE_STRTOD 1
-\#define HAVE_STRTOUL 1
-\#define HAVE_GETCWD 1
+\#define RUBY_VENDOR_ARCHLIB "/lib/ruby/vendor_ruby/$(MAJOR).$(MINOR)/$(ARCH)-$(OS)"
|
+ @exit > $@
-config.status: Makefile $(srcdir)bcc32/Makefile.sub
+config.status: $(MKFILES) $(srcdir)/bcc32/Makefile.sub $(srcdir)/common.mk
@echo Creating $@
@type > $@ &&|
# Generated automatically by Makefile.sub.
s,@SHELL@,$$(COMSPEC),;t t
+s,@BUILD_FILE_SEPARATOR@,\,;t t
+s,@PATH_SEPARATOR@,;,;t t
s,@CFLAGS@,$(CFLAGS),;t t
s,@CPPFLAGS@,$(CPPFLAGS),;t t
s,@CXXFLAGS@,$(CXXFLAGS),;t t
@@ -342,7 +353,8 @@ s,@RANLIB@,,;t t
s,@AR@,$(AR),;t t
s,@ARFLAGS@,$(ARFLAGS) ,;t t
s,@LN_S@,$(LN_S),;t t
-s,@SET_MAKE@,$(SET_MAKE),;t t
+s,@SET_MAKE@,MFLAGS = -$$(MAKEFLAGS),;t t
+s,@CP@,copy > nul,;t t
s,@LIBOBJS@, acosh.obj crypt.obj erf.obj win32.obj,;t t
s,@ALLOCA@,$(ALLOCA),;t t
s,@DEFAULT_KCODE@,$(DEFAULT_KCODE),;t t
@@ -356,12 +368,16 @@ s,@STATIC@,$(STATIC),;t t
s,@CCDLFLAGS@,,;t t
s,@LDSHARED@,$(LDSHARED),;t t
s,@DLEXT@,so,;t t
-s,@DLEXT2@,dll,;t t
s,@LIBEXT@,lib,;t t
s,@STRIP@,$(STRIP),;t t
s,@EXTSTATIC@,$(EXTSTATIC),;t t
s,@setup@,Setup,;t t
s,@MINIRUBY@,$(MINIRUBY),;t t
+s,@PREP@,miniruby$(EXEEXT),;t t
+s,@RUNRUBY@,$(RUNRUBY),;t t
+s,@EXTOUT@,$(EXTOUT),;t t
+s,@ARCHFILE@,,;t t
+s,@RDOCTARGET@,,;t t
s,@LIBRUBY_LDSHARED@,$$(LDSHARED),;t t
s,@LIBRUBY_DLDFLAGS@,-Gi $$(DLDFLAGS),;t t
s,@RUBY_INSTALL_NAME@,$(RUBY_INSTALL_NAME),;t t
@@ -378,32 +394,34 @@ s,@LIBRUBYARG_SHARED@,$$(LIBRUBY),;t t
s,@SOLIBS@,$(SOLIBS),;t t
s,@DLDLIBS@,$(DLDLIBS),;t t
s,@ENABLE_SHARED@,yes,;t t
-s,@OUTFLAG@,-o,;t t
+s,@OUTFLAG@,$(OUTFLAG),;t t
s,@CPPOUTFILE@,,;t t
-s,@LIBPATHFLAG@, -L%s,;t t
+s,@LIBPATHFLAG@, -L"%s",;t t
s,@RPATHFLAG@,,;t t
s,@LIBARG@,%s.lib,;t t
-s,@LINK_SO@,$$(LDSHARED) $$(DLDFLAGS) $$(LIBPATH) $$(OBJS), $$@, nul, $$(LIBS) $$(LOCAL_LIBS), $$(DEFFILE), $$(RESFILE),;t t
-s,@COMPILE_C@,$$(CC) $$(CFLAGS) $$(CPPFLAGS) -c $$(<:/=\),;t t
-s,@COMPILE_CXX@,$$(CXX) $$(CXXFLAGS) $$(CPPFLAGS) -P -c $$(<:/=\),;t t
-s,@COMPILE_RULES@,{$$(srcdir)}.%s{}.%s: .%s.%s:,;t t
-s,@COMMON_LIBS@,m,;t t
-s,@COMMON_MACROS@,WIN32_LEAN_AND_MEAN;t t
+s,@LINK_SO@,$$(LDSHARED) $$(DLDFLAGS) $$(LIBPATH) $$(OBJS), $$(@:/=\), nul, $$(LIBS) $$(LOCAL_LIBS), $$(DEFFILE), $$(RESFILE),;t t
+s,@COMPILE_C@,$$(CC) $$(INCFLAGS) $$(CFLAGS) $$(CPPFLAGS) -c $$(<:/=\),;t t
+s,@COMPILE_CXX@,$$(CXX) $$(INCFLAGS) $$(CXXFLAGS) $$(CPPFLAGS) -P -c $$(<:/=\),;t t
+s,@COMPILE_RULES@,{$$(srcdir)}.%s{}.%s: {$$(topdir)}.%s{}.%s: {$$(hdrdir)}.%s{}.%s: .%s.%s:,;t t
+s,@RULE_SUBST@,{.;$$(VPATH)}%s,;t t
+s,@COMMON_LIBS@,m advapi32 avicap32 avifil32 cap comctl32 comdlg32 dlcapi gdi32 glu32 imagehlp imm32 inetmib1 kernel32 loadperf lsapi32 lz32 mapi32 mgmtapi mpr msacm32 msvfw32 nddeapi netapi32 ole32 oleaut32 oledlg olepro32 opengl32 pdh pkpd32 rasapi32 rasdlg rassapi rpcrt4 setupapi shell32 shfolder snmpapi sporder tapi32 url user32 vdmdbg version win32spl winmm wintrust wsock32,;t t
+s,@COMMON_MACROS@,WIN32_LEAN_AND_MEAN WIN32,;t t
s,@COMMON_HEADERS@,winsock2.h windows.h,;t t
s,@TRY_LINK@,$$(CC) -oconftest $$(INCFLAGS) -I$$(hdrdir) $$(CPPFLAGS) $$(CFLAGS) $$(LIBPATH) $$(LDFLAGS) $$(src) $$(LOCAL_LIBS) $$(LIBS),;t t
s,@EXPORT_PREFIX@,_,;t t
s,@arch@,$(ARCH)-$(OS),;t t
s,@sitearch@,$(ARCH)-$(OS),;t t
s,@sitedir@,$${prefix}/lib/ruby/site_ruby,;t t
+s,@vendordir@,$${prefix}/lib/ruby/vendor_ruby,;t t
s,@configure_args@,--enable-shared $(configure_args),;t t
s,@configure_input@,$$configure_input,;t t
s,@srcdir@,$(srcdir),;t t
s,@top_srcdir@,$(srcdir),;t t
|
-miniruby$(EXEEXT): $(LIBRUBY_A) $(MAINOBJ) dmyext.obj
+miniruby$(EXEEXT):
@echo $(LIBS)
- $(LD) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) dmyext.obj,$@,nul,$(LIBRUBY_A) $(LIBS)
+ $(LD) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(MINIOBJS),$@,nul,$(LIBRUBY_A) $(LIBS)
$(PROGRAM): $(MAINOBJ) $(LIBRUBY_SO) $(RUBY_INSTALL_NAME).res
$(LD) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ),$@,nul,$(LIBRUBYARG) $(LIBS),,$(RUBY_INSTALL_NAME).res
@@ -411,187 +429,121 @@ $(PROGRAM): $(MAINOBJ) $(LIBRUBY_SO) $(RUBY_INSTALL_NAME).res
$(WPROGRAM): $(MAINOBJ) $(WINMAINOBJ) $(LIBRUBY_SO) $(RUBYW_INSTALL_NAME).res
$(LD) $(LDFLAGS) $(WLDFLAGS) $(MAINOBJ) $(WINMAINOBJ),$@,nul,$(LIBRUBYARG) $(LIBS),,$(RUBYW_INSTALL_NAME).res
-$(LIBRUBY_A): $(OBJS) dmyext.obj
+$(LIBRUBY_A): $(OBJS) $(DMYEXT)
@-if exist $@ del $@
- $(AR) $(ARFLAGS) "$@" $(OBJS) dmyext.obj
+ $(AR) $(ARFLAGS) "$@" $(OBJS) $(DMYEXT)
# $(LIBRUBY): $(LIBRUBY_SO)
# implib $@ $(LIBRUBY_SO)
-$(LIBRUBY_SO) $(LIBRUBY): $(LIBRUBY_A) $(EXTOBJS) $(RUBYDEF) $(RUBY_SO_NAME).res
- @echo $(EXTOBJS)
- $(LIBRUBY_LDSHARED) $(LIBRUBY_DLDFLAGS) $(EXTOBJS:/=\),$(LIBRUBY_SO),nul,$(LIBRUBY_A) $(LIBS),$(RUBYDEF),$(RUBY_SO_NAME).res
-
-$(RUBYDEF): $(LIBRUBY_A) miniruby$(EXEEXT)
- $(MINIRUBY) $(srcdir)bcc32/mkexports.rb -output=$@ $(LIBRUBY_A)
-
-install: rbconfig.rb
- $(MINIRUBY) $(srcdir)instruby.rb $(SCRIPT_ARGS)
- $(MINIRUBY) $(srcdir)ext/extmk.rb $(SCRIPT_ARGS) install
-
-what-where no-install: rbconfig.rb
- $(MINIRUBY) $(srcdir)instruby.rb -n $(SCRIPT_ARGS)
- $(MINIRUBY) $(srcdir)ext/extmk.rb -n $(SCRIPT_ARGS) install
-
-clean: clean-ext clean-local
-
-clean-local:
- @if exist $(LIBRUBY_A) del $(LIBRUBY_A)
- @if exist $(MAINOBJ) del $(MAINOBJ)
- @if exist rbconfig.rb del rbconfig.rb
- @if exist ext\extinit.c del ext\extinit.c
- @if exist ext\extinit.obj del ext\extinit.obj
- @if exist ext\vc*.pdb del ext\vc*.pdb
- @if exist *.obj del *.obj
- @if exist *.res del *.res
- @if exist *.tds del *.tds
- @if exist *.il? del *.il?
-
-clean-ext:
- @-$(MINIRUBY) $(srcdir)ext/extmk.rb $(SCRIPT_ARGS) clean
-
-distclean: distclean-ext distclean-local
-
-distclean-local: clean-local
- @if exist Makefile del Makefile
- @if exist config.h del config.h
- @if exist ext\config.cache del ext\config.cache
- @if exist config.cache del config.cache
- @if exist config.log del config.log
- @if exist config.status del config.status
- @if exist *~ del *~
- @if exist *.bak del *.bak
- @if exist *.stackdump del *.stackdump
- @if exist *.core del *.core
- @if exist gmon.out del gmon.out
- @if exist y.tab.c del y.tab.c
- @if exist y.output del y.output
- @if exist *.map del *.map
- @if exist *.pdb del *.pdb
- @if exist *.ilk del *.ilk
- @if exist *.exp del *.exp
- @if exist $(RUBYDEF) del $(RUBYDEF)
- @if exist $(RUBY_INSTALL_NAME).rc del $(RUBY_INSTALL_NAME).rc
- @if exist $(RUBYW_INSTALL_NAME).rc del $(RUBYW_INSTALL_NAME).rc
- @if exist $(RUBY_SO_NAME).rc del $(RUBY_SO_NAME).rc
- @if exist $(PROGRAM) del $(PROGRAM)
- @if exist $(WPROGRAM) del $(WPROGRAM)
- @if exist $(LIBRUBY_SO) del $(LIBRUBY_SO)
- @if exist $(LIBRUBY) del $(LIBRUBY)
- @if exist ext\nul if not exist ext\* rmdir ext
- @if exist miniruby$(EXEEXT) del miniruby$(EXEEXT)
-
-distclean-ext:
- @-$(MINIRUBY) $(srcdir)ext/extmk.rb $(SCRIPT_ARGS) distclean
-
-realclean: distclean
- @if exist parse.c del parse.c
- @if exist lex.c del lex.c
-
-test: miniruby$(EXEEXT) NUL
- @$(MINIRUBY) $(srcdir)rubytest.rb
-
-rbconfig.rb: miniruby$(EXEEXT) config.status
- @$(MINIRUBY) $(srcdir)mkconfig.rb -srcdir=$(srcdir) \
- -install_name=$(RUBY_INSTALL_NAME) \
- -so_name=$(RUBY_SO_NAME) rbconfig.rb
+$(LIBRUBY_SO): $(LIBRUBY_A) $(DLDOBJS) $(RUBYDEF) $(RUBY_SO_NAME).res
+ @echo $(DLDOBJS)
+ @$(PRE_LIBRUBY_UPDATE)
+ $(LIBRUBY_LDSHARED) $(LIBRUBY_DLDFLAGS) $(DLDOBJS:/=\),$(LIBRUBY_SO),nul,$(LIBRUBY_A) $(LIBS),$(RUBYDEF),$(RUBY_SO_NAME).res
+
+$(LIBRUBY): $(LIBRUBY_SO)
+
+$(RUBYDEF): $(LIBRUBY_A) $(PREP)
+ $(MINIRUBY) $(srcdir)/bcc32/mkexports.rb -output=$@ -base=$(RUBY_SO_NAME) $(LIBRUBY_A)
$(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(RUBY_SO_NAME).rc: rbconfig.rb
- @$(MINIRUBY) $(srcdir)win32/resource.rb \
+ @$(MINIRUBY) $(srcdir)/win32/resource.rb \
-ruby_name=$(RUBY_INSTALL_NAME) \
-rubyw_name=$(RUBYW_INSTALL_NAME) \
-so_name=$(RUBY_SO_NAME) \
- . $(icondirs) $(srcdir)win32
-
-#config.status: $(srcdir)configure
-# $(SHELL) .config.status --recheck
-
-.path.c = .;$(srcdir);$(srcdir)win32;$(srcdir)missing
-.path.h = .;$(srcdir);$(srcdir)win32;$(srcdir)missing
-.path.y = $(srcdir)
-
-.c.obj:
- $(CC) $(CFLAGS) $(XCFLAGS) -I. $(CPPFLAGS) -c $(<:/=\)
-
-.rc.res:
- $(RC) $(RFLAGS) -I. -I$(<D). $(iconinc) -I$(srcdir)win32 $(RFLAGS) -fo$@ $(<:/=\)
-
-.y.c:
- $(YACC) $(YFLAGS) $(<:\=/)
- sed -e "s!^ *extern char \*getenv();!/* & */!;s/^\(#.*\)y\.tab/\1parse/" y.tab.c > $(@F)
- @del y.tab.c
-
-parse.c: parse.y
+ . $(icondirs) $(srcdir)/win32
+
+post-install-bin::
+ @$(NULLCMD)
+post-install-lib::
+ @$(NULLCMD)
+post-install-ext-comm::
+ @$(NULLCMD)
+post-install-ext-arch::
+ @$(NULLCMD)
+post-install-man::
+ @$(NULLCMD)
+post-install-doc::
+ @$(NULLCMD)
+
+clean-local::
+ @$(RM) $(WINMAINOBJ) ext\extinit.c ext\extinit.$(OBJEXT) *.tds *.il? $(RUBY_SO_NAME).lib
+ @$(RM) $(RUBY_INSTALL_NAME).res $(RUBYW_INSTALL_NAME).res $(RUBY_SO_NAME).res
+ @$(RM) *.map *.pdb *.ilk *.exp $(RUBYDEF)
+
+distclean-local::
+ @$(RM) ext\config.cache $(RBCONFIG:/=\)
+ @$(RM) $(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(RUBY_SO_NAME).rc
+
+update-rubyspec:
+ @echo SPEC_EXISTS=0 > $@.mk
+ @if exist $(srcdir:/=\)\rubyspec\nul echo SPEC_EXISTS=1 >> $@.mk
+ @type >> $@.mk &&|
+$()update-rubyspec:
+$() @del $@.mk
+$()!if $$(SPEC_EXISTS)
+$() cd $(srcdir:/=\)\rubyspec\mspec
+$() git pull
+$() cd ..\spec\rubyspec
+$() git pull
+$()!else
+$() git clone $(MSPEC_GIT_URL) $(srcdir)/rubyspec/mspec
+$() git clone $(RUBYSPEC_GIT_URL) $(srcdir)/rubyspec/spec/rubyspec
+$()!endif
+|
+ @$(MAKE) -$(MAKEFLAGS)$(MFLAGS) -f $@.mk
+
+test-rubyspec:
+ @echo SPEC_EXISTS=0 > $@.mk
+ @if exist $(srcdir:/=\)\rubyspec\nul echo SPEC_EXISTS=1 >> $@.mk
+ @type >> $@.mk &&|
+$()test-rubyspec:
+$()!if $$(SPEC_EXISTS)
+$() $(RUNRUBY) $(srcdir)/rubyspec/mspec/bin/mspec -r$(srcdir)/ext/purelib.rb $(srcdir)/rubyspec/spec/rubyspec/$(MAJOR).$(MINOR)
+$()!else
+$() @echo No rubyspec here. put rubyspec to srcdir first.
+$() @cd $(srcdir:/=\)\rubyspec
+$()!endif
+|
+ @$(MAKE) -$(MAKEFLAGS) -f $@.mk
ext/extinit.obj: ext/extinit.c $(SETUP)
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -o$@ -c ext/extinit.c
-acosh.obj: acosh.c win32.h
-alloca.obj: alloca.c win32.h
-crypt.obj: crypt.c win32.h
-dup2.obj: dup2.c win32.h
-erf.obj: erf.c win32.h
-finite.obj: finite.c win32.h
-flock.obj: flock.c win32.h
-memcmp.obj: memcmp.c win32.h
-memmove.obj: memmove.c win32.h
-mkdir.obj: mkdir.c win32.h
-vsnprintf.obj: vsnprintf.c win32.h
-strcasecmp.obj: strcasecmp.c win32.h
-strncasecmp.obj: strncasecmp.c win32.h
-strchr.obj: strchr.c win32.h
-strdup.obj: strdup.c win32.h
-strerror.obj: strerror.c win32.h
-strftime.obj: strftime.c win32.h
-strstr.obj: strstr.c win32.h
-strtod.obj: strtod.c win32.h
-strtol.obj: strtol.c win32.h
-strtoul.obj: strtoul.c win32.h
-nt.obj: nt.c win32.h
-x68.obj: x68.c win32.h
-os2.obj: os2.c win32.h
-dl_os2.obj: dl_os2.c win32.h
-
-# when I use -I., there is confliction at "OpenFile"
-# so, set . into environment varible "include"
-win32.obj: win32.c win32.h
-
-###
-array.obj: array.c ruby.h config.h defines.h intern.h missing.h util.h st.h win32.h
-bignum.obj: bignum.c ruby.h config.h defines.h intern.h missing.h win32.h
-class.obj: class.c ruby.h config.h defines.h intern.h missing.h rubysig.h node.h st.h win32.h
-compar.obj: compar.c ruby.h config.h defines.h intern.h missing.h win32.h
-dir.obj: dir.c ruby.h config.h defines.h intern.h missing.h util.h win32.h
-dln.obj: dln.c ruby.h config.h defines.h intern.h missing.h dln.h win32.h
-dmyext.obj: dmyext.c
-enum.obj: enum.c ruby.h config.h defines.h intern.h missing.h node.h util.h win32.h
-error.obj: error.c ruby.h config.h defines.h intern.h missing.h env.h version.h st.h win32.h
-eval.obj: eval.c ruby.h config.h defines.h intern.h missing.h node.h env.h util.h rubysig.h st.h dln.h win32.h
-file.obj: file.c ruby.h config.h defines.h intern.h missing.h rubyio.h rubysig.h util.h dln.h win32.h
-gc.obj: gc.c ruby.h config.h defines.h intern.h missing.h rubysig.h st.h node.h env.h re.h regex.h win32.h
-hash.obj: hash.c ruby.h config.h defines.h intern.h missing.h st.h util.h rubysig.h win32.h
-inits.obj: inits.c ruby.h config.h defines.h intern.h missing.h win32.h
-io.obj: io.c ruby.h config.h defines.h intern.h missing.h rubyio.h rubysig.h env.h util.h win32.h
-main.obj: main.c ruby.h config.h defines.h intern.h missing.h win32.h
-marshal.obj: marshal.c ruby.h config.h defines.h intern.h missing.h rubyio.h st.h util.h win32.h
-math.obj: math.c ruby.h config.h defines.h intern.h missing.h win32.h
-numeric.obj: numeric.c ruby.h config.h defines.h intern.h missing.h win32.h
-object.obj: object.c ruby.h config.h defines.h intern.h missing.h st.h util.h win32.h
-pack.obj: pack.c ruby.h config.h defines.h intern.h missing.h win32.h
-parse.obj: parse.c ruby.h config.h defines.h intern.h missing.h env.h node.h st.h regex.h util.h lex.c win32.h
-prec.obj: prec.c ruby.h config.h defines.h intern.h missing.h win32.h
-process.obj: process.c ruby.h config.h defines.h intern.h missing.h rubysig.h st.h win32.h
-random.obj: random.c ruby.h config.h defines.h intern.h missing.h win32.h
-range.obj: range.c ruby.h config.h defines.h intern.h missing.h win32.h
-re.obj: re.c ruby.h config.h defines.h intern.h missing.h re.h regex.h win32.h
-regex.obj: regex.c config.h regex.h win32.h
-ruby.obj: ruby.c ruby.h config.h defines.h intern.h missing.h dln.h node.h util.h win32.h
-signal.obj: signal.c ruby.h config.h defines.h intern.h missing.h rubysig.h win32.h
-sprintf.obj: sprintf.c ruby.h config.h defines.h intern.h missing.h win32.h
-st.obj: st.c config.h st.h
-string.obj: string.c ruby.h config.h defines.h intern.h missing.h re.h regex.h version.h win32.h
-struct.obj: struct.c ruby.h config.h defines.h intern.h missing.h win32.h
-time.obj: time.c ruby.h config.h defines.h intern.h missing.h win32.h
-util.obj: util.c ruby.h config.h defines.h intern.h missing.h util.h win32.h
-variable.obj: variable.c ruby.h config.h defines.h intern.h missing.h env.h node.h st.h util.h win32.h
-version.obj: version.c ruby.h config.h defines.h intern.h missing.h version.h win32.h
+main.$(OBJEXT): win32.h
+array.$(OBJEXT): win32.h
+bignum.$(OBJEXT): win32.h
+class.$(OBJEXT): win32.h
+compar.$(OBJEXT): win32.h
+dir.$(OBJEXT): dir.h win32.h
+dln.$(OBJEXT): win32.h
+enum.$(OBJEXT): win32.h
+error.$(OBJEXT): win32.h
+eval.$(OBJEXT): win32.h
+file.$(OBJEXT): win32.h
+gc.$(OBJEXT): win32.h
+hash.$(OBJEXT): win32.h
+inits.$(OBJEXT): win32.h
+io.$(OBJEXT): win32.h
+marshal.$(OBJEXT): win32.h
+math.$(OBJEXT): win32.h
+numeric.$(OBJEXT): win32.h
+object.$(OBJEXT): win32.h
+pack.$(OBJEXT): win32.h
+parse.$(OBJEXT): win32.h
+process.$(OBJEXT): win32.h
+prec.$(OBJEXT): win32.h
+random.$(OBJEXT): win32.h
+range.$(OBJEXT): win32.h
+re.$(OBJEXT): win32.h
+regex.$(OBJEXT): win32.h
+ruby.$(OBJEXT): win32.h
+signal.$(OBJEXT): win32.h
+sprintf.$(OBJEXT): win32.h
+st.$(OBJEXT): win32.h
+string.$(OBJEXT): win32.h
+struct.$(OBJEXT): win32.h
+time.$(OBJEXT): win32.h
+util.$(OBJEXT): win32.h
+variable.$(OBJEXT): win32.h
+version.$(OBJEXT): win32.h
diff --git a/bcc32/README.bcc32 b/bcc32/README.bcc32
index a699d34a4e..c27a1261f1 100644
--- a/bcc32/README.bcc32
+++ b/bcc32/README.bcc32
@@ -6,18 +6,26 @@
(1) Borland C++ 5.0 or later.
-(2) If you want to run `((%make clean%))' or `((%make distclean%))'
- properly, you must install UNIX compatible `((%rm%))' command on
- your ((|PATH|)).
-
-(3) Please set environment variable (({INCLUDE})), (({LIB})), (({PATH}))
+(2) Please set environment variable (({PATH}))
to run required commands properly from the command line.
Note: building ruby requires following commands.
* make
- * bcc
+ * bcc32
* tlib
- * ilink
+ * ilink32
+
+(3) If you want to build from CVS source, following commands are required.
+ * byacc ((<URL:http://gnuwin32.sourceforge.net/packages/byacc.htm>))
+ * sed ((<URL:http://gnuwin32.sourceforge.net/packages/sed.htm>))
+
+(4) We strongly recommend to build ruby on C++Builder, to link following files.
+ * usebormm.lib
+ * memmgr.lib
+
+ RTL's internal memory manager cannot handle large memory block properly,
+ so we should use borlndmm.dll instead.
+ 10000.times { "" << "." * 529671; GC.start } # crash
== How to compile and install
@@ -48,6 +56,10 @@
If Ruby's version is `x.y.z', the ((|<MAJOR>|)) is `x' and the ((|<MINOR>|)) is `y'.
The ((|<PLATFORM>|)) is usually `(({i586-bccwin32}))'.
+(6) Requires dynamic RTL (cc3250.dll on C++Builder5) and borlndmm.dll (If built with
+ usebormm.lib) to use installed binary. These files are ordinary in bcc32's bin
+ directory.
+
== Icons
Any icon files(*.ico) in the build directory, directories specified with
diff --git a/bcc32/configure.bat b/bcc32/configure.bat
index 449b6e25b5..95575cbc60 100644..100755
--- a/bcc32/configure.bat
+++ b/bcc32/configure.bat
@@ -6,27 +6,147 @@
echo> ~tmp~.mak ####
echo>> ~tmp~.mak conf = %0
echo>> ~tmp~.mak $(conf:\=/): nul
-echo>> ~tmp~.mak @del ~tmp~.mak
+echo>> ~tmp~.mak @del ~setup~.mak
echo>> ~tmp~.mak @-$(MAKE) -l$(MAKEFLAGS) -f $(@D)setup.mak \
-echo>> ~tmp~.mak bcc32dir="$(@D)" \
+if exist pathlist.tmp del pathlist.tmp
+if exist confargs.mk del confargs.mk
:loop
if "%1" == "" goto :end
+if "%1" == "--prefix" goto :prefix
+if "%1" == "prefix" goto :prefix
if "%1" == "--srcdir" goto :srcdir
if "%1" == "srcdir" goto :srcdir
if "%1" == "--target" goto :target
if "%1" == "target" goto :target
- echo>> ~tmp~.mak "%1"
+if "%1" == "--with-static-linked-ext" goto :extstatic
+if "%1" == "--program-suffix" goto :suffix
+if "%1" == "RUBY_SUFFIX" goto :suffix
+if "%1" == "--program-name" goto :installname
+if "%1" == "--install-name" goto :installname
+if "%1" == "RUBY_INSTALL_NAME" goto :installname
+if "%1" == "--so-name" goto :soname
+if "%1" == "RUBY_SO_NAME" goto :soname
+if "%1" == "--enable-install-doc" goto :enable-rdoc
+if "%1" == "--disable-install-doc" goto :disable-rdoc
+if "%1" == "--extout" goto :extout
+if "%1" == "EXTOUT" goto :extout
+if "%1" == "--path" goto :path
+if "%1" == "-h" goto :help
+if "%1" == "--help" goto :help
+ echo>>confargs.tmp %1 \
shift
goto :loop
:srcdir
- echo>> ~tmp~.mak "srcdir=%2"
+ echo>> ~tmp~.mak -Dsrcdir=%2 \
+ echo>>confargs.tmp --srcdir=%2 \
+ shift
+ shift
+goto :loop
+:prefix
+ echo>> ~tmp~.mak -Dprefix=%2 \
+ echo>>confargs.tmp %1=%2 \
+ shift
+ shift
+goto :loop
+:suffix
+ echo>>confargs.mk !ifndef RUBY_SUFFIX
+ echo>>confargs.mk RUBY_SUFFIX = %2
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1=%2 \
+ shift
+ shift
+goto :loop
+:installname
+ echo>>confargs.mk !ifndef RUBY_INSTALL_NAME
+ echo>>confargs.mk RUBY_INSTALL_NAME = %2
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1=%2 \
+ shift
+ shift
+goto :loop
+:soname
+ echo>>confargs.mk !ifndef RUBY_SO_NAME
+ echo>>confargs.mk RUBY_SO_NAME = %2
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:target
- echo>> ~tmp~.mak %2
+ echo>> ~tmp~.mak %2 \
+ echo>>confargs.tmp --target=%2 \
+ shift
+ shift
+goto :loop
+:extstatic
+ echo>>confargs.mk !ifndef EXTSTATIC
+ echo>>confargs.mk EXTSTATIC = static
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1 \
+ shift
+goto :loop
+:enable-rdoc
+ echo>>confargs.mk !ifndef RDOCTARGET
+ echo>>confargs.mk RDOCTARGET = install-doc
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1 \
+ shift
+goto :loop
+:disable-rdoc
+ echo>>confargs.mk !ifndef RDOCTARGET
+ echo>>confargs.mk RDOCTARGET = install-nodoc
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1 \
+ shift
+goto :loop
+:extout
+ echo>>confargs.mk !ifndef EXTOUT
+ echo>>confargs.mk EXTOUT = %2
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1=%2 \
+ shift
+ shift
+goto :loop
+:path
+ echo>>pathlist.tmp %2;\
+ echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
+:help
+ echo Configuration:
+ echo --help display this help
+ echo --srcdir=DIR find the sources in DIR [configure dir or `..']
+ echo Installation directories:
+ echo --prefix=PREFIX install files in PREFIX (ignored currently)
+ echo System types:
+ echo --target=TARGET configure for TARGET [i386-bccwin32]
+ echo Optional Package:
+ echo --with-static-linked-ext link external modules statically
+ echo --disable-install-doc install rdoc indexes during install
+ del *.tmp
+ del ~tmp~.mak
+goto :exit
:end
-make -s -f ~tmp~.mak
+echo>> ~tmp~.mak -Dbcc32dir=$(@D)
+if not exist confargs.tmp goto :noconfargs
+ echo>>confargs.mk configure_args = \
+ type>>confargs.mk confargs.tmp
+ echo.>>confargs.mk
+ echo>>confargs.mk ####
+:noconfargs
+if not exist pathlist.tmp goto :nopathlist
+ echo>>confargs.mk pathlist = \
+ type>>confargs.mk pathlist.tmp
+ echo.>>confargs.mk
+ echo>>confargs.mk ####
+ echo>>confargs.mk PATH = $(pathlist:;=/bin;)$(PATH)
+ echo>>confargs.mk INCLUDE = $(pathlist:;=/include;)
+ echo>>confargs.mk LIB = $(pathlist:;=/lib;)
+:nopathlist
+if exist confargs.mk copy confargs.mk ~setup~.mak > nul
+type>>~setup~.mak ~tmp~.mak
+del *.tmp > nul
+del ~tmp~.mak > nul
+make -s -f ~setup~.mak
+:exit
diff --git a/bcc32/mkexports.rb b/bcc32/mkexports.rb
index e34b441e2f..dc523e2541 100644..100755
--- a/bcc32/mkexports.rb
+++ b/bcc32/mkexports.rb
@@ -1,5 +1,7 @@
#!./miniruby -s
+$name = $library = $description = nil
+
SYM = {}
STDIN.reopen(open("nul"))
ARGV.each do |obj|
diff --git a/bcc32/setup.mak b/bcc32/setup.mak
index c81eaf2020..483292ed51 100644
--- a/bcc32/setup.mak
+++ b/bcc32/setup.mak
@@ -1,18 +1,20 @@
# -*- makefile -*-
!if "$(srcdir)" != ""
-bcc32dir = $(srcdir)bcc32/
+bcc32dir = $(srcdir)/bcc32
!elseif "$(bcc32dir)" == "bcc32/"
-srcdir = ./
+srcdir = .
!elseif "$(bcc32dir:/bcc32/=)/bcc32/" == "$(bcc32dir)"
-srcdir = $(bcc32dir:/bcc32/=/)
+srcdir = $(bcc32dir:/bcc32/=)
!else
-srcdir = $(bcc32dir)../
+srcdir = $(bcc32dir)/..
+!endif
+!ifndef prefix
+prefix = /usr
!endif
-
OS = bccwin32
RT = $(OS)
-INCLUDE = !include
+BANG = !
APPEND = echo>>$(MAKEFILE)
!ifdef MAKEFILE
MAKE = $(MAKE) -f $(MAKEFILE)
@@ -28,62 +30,134 @@ i586-$(OS): -prologue- -i586- -epilogue-
i686-$(OS): -prologue- -i686- -epilogue-
alpha-$(OS): -prologue- -alpha- -epilogue-
--prologue-: nul
+-prologue-: -basic-vars- -version- -system-vars-
+
+-basic-vars-: nul
@echo Creating $(MAKEFILE)
@type > $(MAKEFILE) &&|
\#\#\# Makefile for ruby $(OS) \#\#\#
+$(BANG)ifndef srcdir
srcdir = $(srcdir:\=/)
+$(BANG)endif
+$(BANG)ifndef prefix
+prefix = $(prefix:\=/)
+$(BANG)endif
|
+!if exist(confargs.mk)
+ @type confargs.mk >> $(MAKEFILE)
+ @del confargs.mk
+!endif
+
+-system-vars-: -runtime- -bormm-
+
+-bormm-: nul
+ @-ilink32 -q -Gn -x usebormm.lib > nul
+ @-if exist usebormm.tds $(APPEND) MEMLIB = usebormm.lib
+ @if exist usebormm.* del usebormm.*
+
+-osname-: nul
+ @echo OS = >>$(MAKEFILE)
+
+-runtime-: nul
+ type > conftest.c &&|
+\#include <stdio.h>
+int main(){printf("");return 0;}
+|
+ bcc32 conftest.c cw32i.lib > nul
+ tdump conftest.exe < nul > conftest.i
+ grep "^Imports from CC" conftest.i > conftest.c
+ cpp32 -P- -DFile=\# -DImports=RTNAME -Dfrom== conftest.c > nul
+ $(MAKE) > nul -DBANG=$(BANG) -f &&|
+-runtime-: nul
+$(BANG)include conftest.i
+RT = $$(RTNAME:.DLL=)
+OS = $$(RT:CC32=)
+-runtime-:
+ del conftest.*
+$(BANG)if "$$(OS)" == "50"
+ echo OS = bccwin32 >> $(MAKEFILE)
+$(BANG)else
+ echo OS = bccwin32_$$(OS) >> $(MAKEFILE)
+$(BANG)endif
+|
+ @echo RT = $$(OS) >> $(MAKEFILE)
+
+-version-: nul
@cpp32 -I$(srcdir) -P- -o$(MAKEFILE) > nul &&|
\#include "version.h"
MAJOR = RUBY_VERSION_MAJOR
MINOR = RUBY_VERSION_MINOR
TEENY = RUBY_VERSION_TEENY
+
+BORLANDC = __BORLANDC__
|
- @type $(MAKEFILE).i >> $(MAKEFILE)
+ @$(MAKE) > nul -DBANG=$(BANG) -f &&,
+-version-: nul
+$(BANG)include $(MAKEFILE)
+$(BANG)include $(MAKEFILE).i
+-version-:
@del $(MAKEFILE).i
+ @type >> $(MAKEFILE) &&|
+MAJOR = $$(MAJOR)
+MINOR = $$(MINOR)
+TEENY = $$(TEENY)
+BORLANDC = $$(BORLANDC)
+|
+,
-generic-: nul
!if defined(PROCESSOR_ARCHITECTURE) || defined(PROCESSOR_LEVEL)
@type >> $(MAKEFILE) &&|
!if defined(PROCESSOR_ARCHITECTURE)
+$(BANG)ifndef PROCESSOR_ARCHITECTURE
PROCESSOR_ARCHITECTURE = $(PROCESSOR_ARCHITECTURE)
+$(BANG)endif
!endif
!if defined(PROCESSOR_LEVEL)
+$(BANG)ifndef PROCESSOR_LEVEL
PROCESSOR_LEVEL = $(PROCESSOR_LEVEL)
+$(BANG)endif
!endif
-
|
!endif
-alpha-: nul
+ @$(APPEND) !ifndef PROCESSOR_ARCHITECTURE
@$(APPEND) PROCESSOR_ARCHITECTURE = alpha
+ @$(APPEND) !endif
-ix86-: nul
+ @$(APPEND) !ifndef PROCESSOR_ARCHITECTURE
@$(APPEND) PROCESSOR_ARCHITECTURE = x86
+ @$(APPEND) !endif
-i386-: -ix86-
+ @$(APPEND) !ifndef PROCESSOR_LEVEL
@$(APPEND) PROCESSOR_LEVEL = 3
+ @$(APPEND) !endif
-i486-: -ix86-
+ @$(APPEND) !ifndef PROCESSOR_LEVEL
@$(APPEND) PROCESSOR_LEVEL = 4
+ @$(APPEND) !endif
-i586-: -ix86-
+ @$(APPEND) !ifndef PROCESSOR_LEVEL
@$(APPEND) PROCESSOR_LEVEL = 5
+ @$(APPEND) !endif
-i686-: -ix86-
+ @$(APPEND) !ifndef PROCESSOR_LEVEL
@$(APPEND) PROCESSOR_LEVEL = 6
+ @$(APPEND) !endif
-epilogue-: nul
@type >> $(MAKEFILE) &&|
-\# OS = $(OS)
-\# RT = $(RT)
\# RUBY_INSTALL_NAME = ruby
\# RUBY_SO_NAME = $$(RT)-$$(RUBY_INSTALL_NAME)$$(MAJOR)$$(MINOR)
-\# prefix = /usr
-\# CFLAGS = -q $$(DEBUGFLAGS) $$(OPTFLAGS) $$(PROCESSOR_FLAG) -w-
-\# CPPFLAGS = -I. -I$$(srcdir) -I$$(srcdir)missing -DLIBRUBY_SO=\"$$(LIBRUBY_SO)\"
+\# CFLAGS = -q $$(DEBUGFLAGS) $$(OPTFLAGS) $$(PROCESSOR_FLAG) -w- -wsus -wcpt -wdup -wext -wrng -wrpt -wzdi
+\# CPPFLAGS = -I. -I$$(srcdir) -I$$(srcdir)/missing -DLIBRUBY_SO=\"$$(LIBRUBY_SO)\"
\# STACK = 0x2000000
\# LDFLAGS = -S:$$(STACK)
\# RFLAGS = $$(iconinc)
\# EXTLIBS = cw32.lib import32.lib user32.lib kernel32.lib
-$(INCLUDE) $$(srcdir)bcc32/Makefile.sub
+$(BANG)include $$(srcdir)/bcc32/Makefile.sub
|
@echo type "`$(MAKE)'" to make ruby for $(OS).
diff --git a/bignum.c b/bignum.c
index 7c3e029d57..7f14aee709 100644
--- a/bignum.c
+++ b/bignum.c
@@ -11,9 +11,14 @@
**********************************************************************/
#include "ruby.h"
+#include "rubysig.h"
#include <math.h>
+#include <float.h>
#include <ctype.h>
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
VALUE rb_cBignum;
@@ -33,17 +38,31 @@ VALUE rb_cBignum;
#define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
#define BDIGMAX ((BDIGIT)-1)
-#define BIGZEROP(x) (RBIGNUM(x)->len == 0 || (RBIGNUM(x)->len == 1 && BDIGITS(x)[0] == 0))
+#define BIGZEROP(x) (RBIGNUM(x)->len == 0 || \
+ (BDIGITS(x)[0] == 0 && \
+ (RBIGNUM(x)->len == 1 || bigzero_p(x))))
+
+static int bigzero_p(VALUE);
+static int
+bigzero_p(x)
+ VALUE x;
+{
+ long i;
+ for (i = 0; i < RBIGNUM(x)->len; ++i) {
+ if (BDIGITS(x)[i]) return 0;
+ }
+ return 1;
+}
static VALUE
bignew_1(klass, len, sign)
VALUE klass;
long len;
- char sign;
+ int sign;
{
NEWOBJ(big, struct RBignum);
OBJSETUP(big, klass, T_BIGNUM);
- big->sign = sign;
+ big->sign = sign?1:0;
big->len = len;
big->digits = ALLOC_N(BDIGIT, len);
@@ -62,15 +81,16 @@ rb_big_clone(x)
return z;
}
+/* modify a bignum by 2's complement */
static void
-get2comp(x, carry) /* get 2's complement */
+get2comp(x)
VALUE x;
- int carry;
{
long i = RBIGNUM(x)->len;
BDIGIT *ds = BDIGITS(x);
BDIGIT_DBL num;
+ if (!i) return;
while (i--) ds[i] = ~ds[i];
i = 0; num = 1;
do {
@@ -78,11 +98,10 @@ get2comp(x, carry) /* get 2's complement */
ds[i++] = BIGLO(num);
num = BIGDN(num);
} while (i < RBIGNUM(x)->len);
- if (!carry) return;
- if ((ds[RBIGNUM(x)->len-1] & (1<<(BITSPERDIG-1))) == 0) {
+ if (num != 0) {
REALLOC_N(RBIGNUM(x)->digits, BDIGIT, ++RBIGNUM(x)->len);
ds = BDIGITS(x);
- ds[RBIGNUM(x)->len-1] = ~0;
+ ds[RBIGNUM(x)->len-1] = RBIGNUM(x)->sign ? ~0 : 1;
}
}
@@ -90,36 +109,56 @@ void
rb_big_2comp(x) /* get 2's complement */
VALUE x;
{
- get2comp(x, Qtrue);
+ get2comp(x);
}
static VALUE
-bignorm(x)
+bigtrunc(x)
VALUE x;
{
- if (!FIXNUM_P(x)) {
- long len = RBIGNUM(x)->len;
- BDIGIT *ds = BDIGITS(x);
+ long len = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
- while (len-- && !ds[len]) ;
- RBIGNUM(x)->len = ++len;
+ if (len == 0) return x;
+ while (--len && !ds[len]);
+ RBIGNUM(x)->len = ++len;
+ return x;
+}
- if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) {
- long num = 0;
- while (len--) {
- num = BIGUP(num) + ds[len];
+static VALUE
+bigfixize(x)
+ VALUE x;
+{
+ long len = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
+
+ if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) {
+ long num = 0;
+ while (len--) {
+ num = BIGUP(num) + ds[len];
+ }
+ if (num >= 0) {
+ if (RBIGNUM(x)->sign) {
+ if (POSFIXABLE(num)) return LONG2FIX(num);
}
- if (num >= 0) {
- if (RBIGNUM(x)->sign) {
- if (POSFIXABLE(num)) return LONG2FIX(num);
- }
- else if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num);
+ else {
+ if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num);
}
}
}
return x;
}
+static VALUE
+bignorm(x)
+ VALUE x;
+{
+ if (!FIXNUM_P(x) && TYPE(x) == T_BIGNUM) {
+ x = bigfixize(bigtrunc(x));
+ }
+ return x;
+}
+
VALUE
rb_big_norm(x)
VALUE x;
@@ -200,6 +239,8 @@ rb_quad_pack(buf, val)
long len = RBIGNUM(val)->len;
BDIGIT *ds;
+ if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS)
+ rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
ds = BDIGITS(val);
q = 0;
while (len--) {
@@ -269,7 +310,9 @@ rb_quad_pack(buf, val)
val = rb_int2big(FIX2LONG(val));
}
len = RBIGNUM(val)->len * SIZEOF_BDIGITS;
- if (len > QUAD_SIZE) len = QUAD_SIZE;
+ if (len > QUAD_SIZE) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
+ }
memcpy(buf, (char*)BDIGITS(val), len);
if (!RBIGNUM(val)->sign) {
len = QUAD_SIZE;
@@ -322,6 +365,13 @@ rb_cstr_to_inum(str, base, badcheck)
VALUE z;
BDIGIT *zds;
+#define conv_digit(c) \
+ (!ISASCII(c) ? -1 : \
+ isdigit(c) ? ((c) - '0') : \
+ islower(c) ? ((c) - 'a' + 10) : \
+ isupper(c) ? ((c) - 'A' + 10) : \
+ -1)
+
if (!str) {
if (badcheck) goto bad;
return INT2FIX(0);
@@ -413,8 +463,21 @@ rb_cstr_to_inum(str, base, badcheck)
break;
}
if (*str == '0') { /* squeeze preceeding 0s */
- while (*++str == '0');
- --str;
+ int us = 0;
+ while ((c = *++str) == '0' || c == '_') {
+ if (c == '_') {
+ if (++us >= 2)
+ break;
+ } else
+ us = 0;
+ }
+ if (!(c = *str) || ISSPACE(c)) --str;
+ }
+ c = *str;
+ c = conv_digit(c);
+ if (c < 0 || c >= base) {
+ if (badcheck) goto bad;
+ return INT2FIX(0);
}
len *= strlen(str)*sizeof(char);
@@ -448,24 +511,16 @@ rb_cstr_to_inum(str, base, badcheck)
z = bignew(len, sign);
zds = BDIGITS(z);
for (i=len;i--;) zds[i]=0;
- while (c = *str++) {
+ while ((c = *str++) != 0) {
if (c == '_') {
- if (badcheck) {
- if (nondigit) goto bad;
- nondigit = c;
+ if (nondigit) {
+ if (badcheck) goto bad;
+ break;
}
+ nondigit = c;
continue;
}
- else if (isdigit(c)) {
- c -= '0';
- }
- else if (islower(c)) {
- c -= 'a' - 10;
- }
- else if (isupper(c)) {
- c -= 'A' - 10;
- }
- else {
+ else if ((c = conv_digit(c)) < 0) {
break;
}
if (c >= base) break;
@@ -524,7 +579,7 @@ rb_str_to_inum(str, base, badcheck)
s = p;
}
}
- return rb_cstr_to_inum(s, base, badcheck);
+ return rb_cstr_to_inum(s, base, badcheck);
}
#if HAVE_LONG_LONG
@@ -586,7 +641,7 @@ rb_ll2inum(n)
}
#endif /* HAVE_LONG_LONG */
-
+
VALUE
rb_cstr2inum(str, base)
const char *str;
@@ -605,15 +660,16 @@ rb_str2inum(str, base)
const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
VALUE
-rb_big2str(x, base)
+rb_big2str0(x, base, trim)
VALUE x;
int base;
+ int trim;
{
volatile VALUE t;
BDIGIT *ds;
long i, j, hbase;
VALUE ss;
- char *s, c;
+ char *s;
if (FIXNUM_P(x)) {
return rb_fix2str(x, base);
@@ -622,34 +678,37 @@ rb_big2str(x, base)
if (BIGZEROP(x)) {
return rb_str_new2("0");
}
+ if (i >= LONG_MAX/SIZEOF_BDIGITS/CHAR_BIT) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
+ }
j = SIZEOF_BDIGITS*CHAR_BIT*i;
switch (base) {
case 2: break;
case 3:
- j = j * 647L / 1024;
+ j = j * 53L / 84 + 1;
break;
case 4: case 5: case 6: case 7:
- j /= 2;
+ j = (j + 1) / 2;
break;
case 8: case 9:
- j /= 3;
+ j = (j + 2) / 3;
break;
case 10: case 11: case 12: case 13: case 14: case 15:
- j = j * 241L / 800;
+ j = j * 28L / 93 + 1;
break;
case 16: case 17: case 18: case 19: case 20: case 21:
case 22: case 23: case 24: case 25: case 26: case 27:
case 28: case 29: case 30: case 31:
- j /= 4;
+ j = (j + 3) / 4;
break;
case 32: case 33: case 34: case 35: case 36:
- j /= 5;
+ j = (j + 4) / 5;
break;
default:
rb_raise(rb_eArgError, "illegal radix %d", base);
break;
}
- j += 2;
+ j++; /* space for sign */
hbase = base * base;
#if SIZEOF_BDIGITS > 2
@@ -658,11 +717,12 @@ rb_big2str(x, base)
t = rb_big_clone(x);
ds = BDIGITS(t);
- ss = rb_str_new(0, j);
+ ss = rb_str_new(0, j+1);
s = RSTRING(ss)->ptr;
s[0] = RBIGNUM(x)->sign ? '+' : '-';
- while (i && j) {
+ TRAP_BEG;
+ while (i && j > 1) {
long k = i;
BDIGIT_DBL num = 0;
@@ -671,23 +731,51 @@ rb_big2str(x, base)
ds[k] = (BDIGIT)(num / hbase);
num %= hbase;
}
- if (ds[i-1] == 0) i--;
+ if (trim && ds[i-1] == 0) i--;
k = SIZEOF_BDIGITS;
while (k--) {
- c = (char)(num % base);
- s[--j] = ruby_digitmap[(int)c];
+ s[--j] = ruby_digitmap[num % base];
num /= base;
- if (i == 0 && num == 0) break;
+ if (!trim && j <= 1) break;
+ if (trim && i == 0 && num == 0) break;
}
}
- while (s[j] == '0') j++;
- RSTRING(ss)->len -= RBIGNUM(x)->sign?j:j-1;
- memmove(RBIGNUM(x)->sign?s:s+1, s+j, RSTRING(ss)->len);
+ if (trim) {while (s[j] == '0') j++;}
+ i = RSTRING(ss)->len - j;
+ if (RBIGNUM(x)->sign) {
+ memmove(s, s+j, i);
+ RSTRING(ss)->len = i-1;
+ }
+ else {
+ memmove(s+1, s+j, i);
+ RSTRING(ss)->len = i;
+ }
s[RSTRING(ss)->len] = '\0';
+ TRAP_END;
return ss;
}
+VALUE
+rb_big2str(VALUE x, int base)
+{
+ return rb_big2str0(x, base, Qtrue);
+}
+
+/*
+ * call-seq:
+ * big.to_s(base=10) => string
+ *
+ * Returns a string containing the representation of <i>big</i> radix
+ * <i>base</i> (2 through 36).
+ *
+ * 12345654321.to_s #=> "12345654321"
+ * 12345654321.to_s(2) #=> "1011011111110110111011110000110001"
+ * 12345654321.to_s(8) #=> "133766736061"
+ * 12345654321.to_s(16) #=> "2dfdbbc31"
+ * 78546939656932.to_s(36) #=> "rubyrules"
+ */
+
static VALUE
rb_big_to_s(argc, argv, x)
int argc;
@@ -724,6 +812,17 @@ big2ulong(x, type)
}
unsigned long
+rb_big2ulong_pack(x)
+ VALUE x;
+{
+ unsigned long num = big2ulong(x, "unsigned long");
+ if (!RBIGNUM(x)->sign) {
+ return -num;
+ }
+ return num;
+}
+
+unsigned long
rb_big2ulong(x)
VALUE x;
{
@@ -742,10 +841,10 @@ long
rb_big2long(x)
VALUE x;
{
- unsigned long num = big2ulong(x, "int");
+ unsigned long num = big2ulong(x, "long");
if ((long)num < 0 && (RBIGNUM(x)->sign || (long)num != LONG_MIN)) {
- rb_raise(rb_eRangeError, "bignum too big to convert into `int'");
+ rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
}
if (!RBIGNUM(x)->sign) return -(long)num;
return num;
@@ -839,8 +938,8 @@ rb_dbl2big(d)
return bignorm(dbl2big(d));
}
-double
-rb_big2dbl(x)
+static double
+big2dbl(x)
VALUE x;
{
double d = 0.0;
@@ -850,14 +949,32 @@ rb_big2dbl(x)
while (i--) {
d = ds[i] + BIGRAD*d;
}
+ if (!RBIGNUM(x)->sign) d = -d;
+ return d;
+}
+
+double
+rb_big2dbl(x)
+ VALUE x;
+{
+ double d = big2dbl(x);
+
if (isinf(d)) {
rb_warn("Bignum out of Float range");
d = HUGE_VAL;
}
- if (!RBIGNUM(x)->sign) d = -d;
return d;
}
+/*
+ * call-seq:
+ * big.to_f -> float
+ *
+ * Converts <i>big</i> to a <code>Float</code>. If <i>big</i> doesn't
+ * fit in a <code>Float</code>, the result is infinity.
+ *
+ */
+
static VALUE
rb_big_to_f(x)
VALUE x;
@@ -865,6 +982,16 @@ rb_big_to_f(x)
return rb_float_new(rb_big2dbl(x));
}
+/*
+ * call-seq:
+ * big <=> numeric => -1, 0, +1
+ *
+ * Comparison---Returns -1, 0, or +1 depending on whether <i>big</i> is
+ * less than, equal to, or greater than <i>numeric</i>. This is the
+ * basis for the tests in <code>Comparable</code>.
+ *
+ */
+
static VALUE
rb_big_cmp(x, y)
VALUE x, y;
@@ -900,6 +1027,17 @@ rb_big_cmp(x, y)
(RBIGNUM(x)->sign ? INT2FIX(-1) : INT2FIX(1));
}
+/*
+ * call-seq:
+ * big == obj => true or false
+ *
+ * Returns <code>true</code> only if <i>obj</i> has the same value
+ * as <i>big</i>. Contrast this with <code>Bignum#eql?</code>, which
+ * requires <i>obj</i> to be a <code>Bignum</code>.
+ *
+ * 68719476736 == 68719476736.0 #=> true
+ */
+
static VALUE
rb_big_eq(x, y)
VALUE x, y;
@@ -911,10 +1049,14 @@ rb_big_eq(x, y)
case T_BIGNUM:
break;
case T_FLOAT:
- if (rb_big2dbl(x) == RFLOAT(y)->value)
- return Qtrue;
- else
- return Qfalse;
+ {
+ volatile double a, b;
+
+ a = RFLOAT(y)->value;
+ if (isnan(a)) return Qfalse;
+ b = rb_big2dbl(x);
+ return (a == b)?Qtrue:Qfalse;
+ }
default:
return rb_equal(y, x);
}
@@ -924,6 +1066,17 @@ rb_big_eq(x, y)
return Qtrue;
}
+/*
+ * call-seq:
+ * big.eql?(obj) => true or false
+ *
+ * Returns <code>true</code> only if <i>obj</i> is a
+ * <code>Bignum</code> with the same value as <i>big</i>. Contrast this
+ * with <code>Bignum#==</code>, which performs type conversions.
+ *
+ * 68719476736.eql?(68719476736.0) #=> false
+ */
+
static VALUE
rb_big_eql(x, y)
VALUE x, y;
@@ -935,6 +1088,13 @@ rb_big_eql(x, y)
return Qtrue;
}
+/*
+ * call-seq:
+ * -big => other_big
+ *
+ * Unary minus (returns a new Bignum whose value is 0-big)
+ */
+
static VALUE
rb_big_uminus(x)
VALUE x;
@@ -946,18 +1106,33 @@ rb_big_uminus(x)
return bignorm(z);
}
+/*
+ * call-seq:
+ * ~big => integer
+ *
+ * Inverts the bits in big. As Bignums are conceptually infinite
+ * length, the result acts as if it had an infinite number of one
+ * bits to the left. In hex representations, this is displayed
+ * as two periods to the left of the digits.
+ *
+ * sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA"
+ */
+
static VALUE
rb_big_neg(x)
VALUE x;
{
VALUE z = rb_big_clone(x);
- long i = RBIGNUM(x)->len;
- BDIGIT *ds = BDIGITS(z);
+ long i;
+ BDIGIT *ds;
- if (!RBIGNUM(x)->sign) get2comp(z, Qtrue);
+ if (!RBIGNUM(x)->sign) get2comp(z);
+ ds = BDIGITS(z);
+ i = RBIGNUM(x)->len;
+ if (!i) return INT2FIX(~0);
while (i--) ds[i] = ~ds[i];
- if (RBIGNUM(x)->sign) get2comp(z, Qfalse);
RBIGNUM(z)->sign = !RBIGNUM(z)->sign;
+ if (RBIGNUM(x)->sign) get2comp(z);
return bignorm(z);
}
@@ -970,7 +1145,7 @@ bigsub(x, y)
BDIGIT *zds;
BDIGIT_DBL_SIGNED num;
long i = RBIGNUM(x)->len;
-
+
/* if x is larger than y, swap */
if (RBIGNUM(x)->len < RBIGNUM(y)->len) {
z = x; x = y; y = z; /* swap x y */
@@ -988,14 +1163,14 @@ bigsub(x, y)
}
}
- z = bignew(RBIGNUM(x)->len, (z == 0)?1:0);
+ z = bignew(RBIGNUM(x)->len, z==0);
zds = BDIGITS(z);
- for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) {
+ for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) {
num += (BDIGIT_DBL_SIGNED)BDIGITS(x)[i] - BDIGITS(y)[i];
zds[i] = BIGLO(num);
num = BIGDN(num);
- }
+ }
while (num && i < RBIGNUM(x)->len) {
num += BDIGITS(x)[i];
zds[i++] = BIGLO(num);
@@ -1005,14 +1180,14 @@ bigsub(x, y)
zds[i] = BDIGITS(x)[i];
i++;
}
-
+
return z;
}
static VALUE
bigadd(x, y, sign)
VALUE x, y;
- char sign;
+ int sign;
{
VALUE z;
BDIGIT_DBL num;
@@ -1054,6 +1229,13 @@ bigadd(x, y, sign)
return z;
}
+/*
+ * call-seq:
+ * big + other => Numeric
+ *
+ * Adds big and other, returning the result.
+ */
+
VALUE
rb_big_plus(x, y)
VALUE x, y;
@@ -1073,6 +1255,13 @@ rb_big_plus(x, y)
}
}
+/*
+ * call-seq:
+ * big - other => Numeric
+ *
+ * Subtracts other from big, returning the result.
+ */
+
VALUE
rb_big_minus(x, y)
VALUE x, y;
@@ -1093,7 +1282,7 @@ rb_big_minus(x, y)
}
VALUE
-rb_big_mul(x, y)
+rb_big_mul0(x, y)
VALUE x, y;
{
long i, j;
@@ -1122,7 +1311,7 @@ rb_big_mul(x, y)
zds = BDIGITS(z);
while (j--) zds[j] = 0;
for (i = 0; i < RBIGNUM(x)->len; i++) {
- BDIGIT_DBL dd = BDIGITS(x)[i];
+ BDIGIT_DBL dd = BDIGITS(x)[i];
if (dd == 0) continue;
n = 0;
for (j = 0; j < RBIGNUM(y)->len; j++) {
@@ -1136,7 +1325,21 @@ rb_big_mul(x, y)
}
}
- return bignorm(z);
+ return z;
+}
+
+/*
+ * call-seq:
+ * big * other => Numeric
+ *
+ * Multiplies big and other, returning the result.
+ */
+
+VALUE
+rb_big_mul(x, y)
+ VALUE x, y;
+{
+ return bignorm(rb_big_mul0(x, y));
}
static void
@@ -1185,7 +1388,7 @@ bigdivrem(x, y, divp, modp)
dd = 0;
q = yds[ny-1];
- while ((q & (1<<(BITSPERDIG-1))) == 0) {
+ while ((q & (1U<<(BITSPERDIG-1))) == 0) {
q <<= 1;
dd++;
}
@@ -1287,6 +1490,14 @@ bigdivmod(x, y, divp, modp)
}
}
+/*
+ * call-seq:
+ * big / other => Numeric
+ * big.div(other) => Numeric
+ *
+ * Divides big by other, returning the result.
+ */
+
static VALUE
rb_big_div(x, y)
VALUE x, y;
@@ -1301,9 +1512,6 @@ rb_big_div(x, y)
case T_BIGNUM:
break;
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) / RFLOAT(y)->value);
-
default:
return rb_num_coerce_bin(x, y);
}
@@ -1312,6 +1520,15 @@ rb_big_div(x, y)
return bignorm(z);
}
+/*
+ * call-seq:
+ * big % other => Numeric
+ * big.modulo(other) => Numeric
+ *
+ * Returns big modulo other. See Numeric.divmod for more
+ * information.
+ */
+
static VALUE
rb_big_modulo(x, y)
VALUE x, y;
@@ -1334,6 +1551,15 @@ rb_big_modulo(x, y)
return bignorm(z);
}
+/*
+ * call-seq:
+ * big.remainder(numeric) => number
+ *
+ * Returns the remainder after dividing <i>big</i> by <i>numeric</i>.
+ *
+ * -1234567890987654321.remainder(13731) #=> -6966
+ * -1234567890987654321.remainder(13731.24) #=> -9906.22531493148
+ */
static VALUE
rb_big_remainder(x, y)
VALUE x, y;
@@ -1356,6 +1582,48 @@ rb_big_remainder(x, y)
return bignorm(z);
}
+static int
+bdigbitsize(BDIGIT x)
+{
+ int size = 1;
+ int nb = BITSPERDIG / 2;
+ BDIGIT bits = (~0 << nb);
+
+ if (!x) return 0;
+ while (x > 1) {
+ if (x & bits) {
+ size += nb;
+ x >>= nb;
+ }
+ x &= ~bits;
+ nb /= 2;
+ bits >>= nb;
+ }
+
+ return size;
+}
+
+static VALUE big_lshift _((VALUE, unsigned long));
+static VALUE big_rshift _((VALUE, unsigned long));
+
+static VALUE big_shift(x, n)
+ VALUE x;
+ int n;
+{
+ if (n < 0)
+ return big_lshift(x, (unsigned int)n);
+ else if (n > 0)
+ return big_rshift(x, (unsigned int)n);
+ return x;
+}
+
+/*
+ * call-seq:
+ * big.divmod(numeric) => array
+ *
+ * See <code>Numeric#divmod</code>.
+ *
+ */
VALUE
rb_big_divmod(x, y)
VALUE x, y;
@@ -1378,13 +1646,54 @@ rb_big_divmod(x, y)
return rb_assoc_new(bignorm(div), bignorm(mod));
}
+/*
+ * call-seq:
+ * big.quo(numeric) -> float
+ * big.fdiv(numeric) -> float
+ *
+ * Returns the floating point result of dividing <i>big</i> by
+ * <i>numeric</i>.
+ *
+ * -1234567890987654321.quo(13731) #=> -89910996357705.5
+ * -1234567890987654321.quo(13731.24) #=> -89909424858035.7
+ *
+ */
+
static VALUE
rb_big_quo(x, y)
VALUE x, y;
{
- double dx = rb_big2dbl(x);
+ double dx = big2dbl(x);
double dy;
+ if (isinf(dx)) {
+#define DBL_BIGDIG ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)
+ VALUE z;
+ int ex, ey;
+
+ ex = (RBIGNUM(bigtrunc(x))->len - 1) * BITSPERDIG;
+ ex += bdigbitsize(BDIGITS(x)[RBIGNUM(x)->len - 1]);
+ ex -= 2 * DBL_BIGDIG * BITSPERDIG;
+ if (ex) x = big_shift(x, ex);
+
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = rb_int2big(FIX2LONG(y));
+ case T_BIGNUM: {
+ ey = (RBIGNUM(bigtrunc(y))->len - 1) * BITSPERDIG;
+ ey += bdigbitsize(BDIGITS(y)[RBIGNUM(y)->len - 1]);
+ ey -= DBL_BIGDIG * BITSPERDIG;
+ if (ey) y = big_shift(y, ey);
+ bignum:
+ bigdivrem(x, y, &z, 0);
+ return rb_float_new(ldexp(big2dbl(z), ex - ey));
+ }
+ case T_FLOAT:
+ y = dbl2big(ldexp(frexp(RFLOAT(y)->value, &ey), DBL_MANT_DIG));
+ ey -= DBL_MANT_DIG;
+ goto bignum;
+ }
+ }
switch (TYPE(y)) {
case T_FIXNUM:
dy = (double)FIX2LONG(y);
@@ -1404,13 +1713,72 @@ rb_big_quo(x, y)
return rb_float_new(dx / dy);
}
+static VALUE
+bigsqr(x)
+ VALUE x;
+{
+ long len = RBIGNUM(x)->len, k = len / 2, i;
+ VALUE a, b, a2, z;
+ BDIGIT_DBL num;
+
+ if (len < 4000 / BITSPERDIG) {
+ return rb_big_mul0(x, x);
+ }
+
+ a = bignew(len - k, 1);
+ MEMCPY(BDIGITS(a), BDIGITS(x) + k, BDIGIT, len - k);
+ b = bignew(k, 1);
+ MEMCPY(BDIGITS(b), BDIGITS(x), BDIGIT, k);
+
+ a2 = bigtrunc(bigsqr(a));
+ z = bigsqr(b);
+ REALLOC_N(RBIGNUM(z)->digits, BDIGIT, (len = 2 * k + RBIGNUM(a2)->len) + 1);
+ while (RBIGNUM(z)->len < 2 * k) BDIGITS(z)[RBIGNUM(z)->len++] = 0;
+ MEMCPY(BDIGITS(z) + 2 * k, BDIGITS(a2), BDIGIT, RBIGNUM(a2)->len);
+ RBIGNUM(z)->len = len;
+ a2 = bigtrunc(rb_big_mul0(a, b));
+ len = RBIGNUM(a2)->len;
+ TRAP_BEG;
+ for (i = 0, num = 0; i < len; i++) {
+ num += (BDIGIT_DBL)BDIGITS(z)[i + k] + ((BDIGIT_DBL)BDIGITS(a2)[i] << 1);
+ BDIGITS(z)[i + k] = BIGLO(num);
+ num = BIGDN(num);
+ }
+ TRAP_END;
+ if (num) {
+ len = RBIGNUM(z)->len;
+ for (i += k; i < len && num; ++i) {
+ num += (BDIGIT_DBL)BDIGITS(z)[i];
+ BDIGITS(z)[i] = BIGLO(num);
+ num = BIGDN(num);
+ }
+ if (num) {
+ BDIGITS(z)[RBIGNUM(z)->len++] = BIGLO(num);
+ }
+ }
+ return bigtrunc(z);
+}
+
+/*
+ * call-seq:
+ * big ** exponent #=> numeric
+ *
+ * Raises _big_ to the _exponent_ power (which may be an integer, float,
+ * or anything that will coerce to a number). The result may be
+ * a Fixnum, Bignum, or Float
+ *
+ * 123456789 ** 2 #=> 15241578750190521
+ * 123456789 ** 1.2 #=> 5126464716.09932
+ * 123456789 ** -2 #=> 6.5610001194102e-17
+ */
+
VALUE
rb_big_pow(x, y)
VALUE x, y;
{
double d;
long yy;
-
+
if (y == INT2FIX(0)) return INT2FIX(1);
switch (TYPE(y)) {
case T_FLOAT:
@@ -1423,18 +1791,23 @@ rb_big_pow(x, y)
break;
case T_FIXNUM:
- yy = NUM2LONG(y);
+ yy = FIX2LONG(y);
if (yy > 0) {
- VALUE z = x;
-
- for (;;) {
- yy -= 1;
- if (yy == 0) break;
- while (yy % 2 == 0) {
- yy /= 2;
- x = rb_big_mul(x, x);
+ VALUE z = 0;
+ long mask;
+ const long BIGLEN_LIMIT = 1024*1024 / SIZEOF_BDIGITS;
+
+ if ((RBIGNUM(x)->len > BIGLEN_LIMIT) ||
+ (RBIGNUM(x)->len > BIGLEN_LIMIT / yy)) {
+ rb_warn("in a**b, b may be too big");
+ d = (double)yy;
+ break;
+ }
+ for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
+ if (z) z = bigtrunc(bigsqr(z));
+ if (yy & mask) {
+ z = z ? bigtrunc(rb_big_mul0(z, x)) : x;
}
- z = rb_big_mul(z, x);
}
return bignorm(z);
}
@@ -1447,26 +1820,34 @@ rb_big_pow(x, y)
return rb_float_new(pow(rb_big2dbl(x), d));
}
+/*
+ * call-seq:
+ * big & numeric => integer
+ *
+ * Performs bitwise +and+ between _big_ and _numeric_.
+ */
+
VALUE
-rb_big_and(x, y)
- VALUE x, y;
+rb_big_and(xx, yy)
+ VALUE xx, yy;
{
- VALUE z;
+ volatile VALUE x, y, z;
BDIGIT *ds1, *ds2, *zds;
long i, l1, l2;
char sign;
- y = rb_to_int(y);
+ x = xx;
+ y = rb_to_int(yy);
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
if (!RBIGNUM(y)->sign) {
y = rb_big_clone(y);
- get2comp(y, Qtrue);
+ get2comp(y);
}
if (!RBIGNUM(x)->sign) {
x = rb_big_clone(x);
- get2comp(x, Qtrue);
+ get2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
@@ -1491,31 +1872,38 @@ rb_big_and(x, y)
for (; i<l2; i++) {
zds[i] = sign?0:ds2[i];
}
- if (!RBIGNUM(z)->sign) get2comp(z, Qfalse);
+ if (!RBIGNUM(z)->sign) get2comp(z);
return bignorm(z);
}
+/*
+ * call-seq:
+ * big | numeric => integer
+ *
+ * Performs bitwise +or+ between _big_ and _numeric_.
+ */
+
VALUE
-rb_big_or(x, y)
- VALUE x, y;
+rb_big_or(xx, yy)
+ VALUE xx, yy;
{
- VALUE z;
+ volatile VALUE x, y, z;
BDIGIT *ds1, *ds2, *zds;
long i, l1, l2;
char sign;
- y = rb_to_int(y);
+ x = xx;
+ y = rb_to_int(yy);
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
-
if (!RBIGNUM(y)->sign) {
y = rb_big_clone(y);
- get2comp(y, Qtrue);
+ get2comp(y);
}
if (!RBIGNUM(x)->sign) {
x = rb_big_clone(x);
- get2comp(x, Qtrue);
+ get2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
@@ -1540,32 +1928,40 @@ rb_big_or(x, y)
for (; i<l2; i++) {
zds[i] = sign?ds2[i]:(BIGRAD-1);
}
- if (!RBIGNUM(z)->sign) get2comp(z, Qfalse);
+ if (!RBIGNUM(z)->sign) get2comp(z);
return bignorm(z);
}
+/*
+ * call-seq:
+ * big ^ numeric => integer
+ *
+ * Performs bitwise +exclusive or+ between _big_ and _numeric_.
+ */
+
VALUE
-rb_big_xor(x, y)
- VALUE x, y;
+rb_big_xor(xx, yy)
+ VALUE xx, yy;
{
+ volatile VALUE x, y;
VALUE z;
BDIGIT *ds1, *ds2, *zds;
long i, l1, l2;
char sign;
- y = rb_to_int(y);
+ x = xx;
+ y = rb_to_int(yy);
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
-
if (!RBIGNUM(y)->sign) {
y = rb_big_clone(y);
- get2comp(y, Qtrue);
+ get2comp(y);
}
if (!RBIGNUM(x)->sign) {
x = rb_big_clone(x);
- get2comp(x, Qtrue);
+ get2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
@@ -1592,26 +1988,72 @@ rb_big_xor(x, y)
for (; i<l2; i++) {
zds[i] = sign?ds2[i]:~ds2[i];
}
- if (!RBIGNUM(z)->sign) get2comp(z, Qfalse);
+ if (!RBIGNUM(z)->sign) get2comp(z);
return bignorm(z);
}
-static VALUE rb_big_rshift _((VALUE,VALUE));
+static VALUE
+check_shiftdown(VALUE y, VALUE x)
+{
+ if (!RBIGNUM(x)->len) return INT2FIX(0);
+ if (RBIGNUM(y)->len > SIZEOF_LONG / SIZEOF_BDIGITS) {
+ return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(-1);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * big << numeric => integer
+ *
+ * Shifts big left _numeric_ positions (right if _numeric_ is negative).
+ */
VALUE
rb_big_lshift(x, y)
VALUE x, y;
{
+ long shift;
+ int neg = 0;
+
+ for (;;) {
+ if (FIXNUM_P(y)) {
+ shift = FIX2LONG(y);
+ if (shift < 0) {
+ neg = 1;
+ shift = -shift;
+ }
+ break;
+ }
+ else if (TYPE(y) == T_BIGNUM) {
+ if (!RBIGNUM(y)->sign) {
+ VALUE t = check_shiftdown(y, x);
+ if (!NIL_P(t)) return t;
+ neg = 1;
+ }
+ shift = big2ulong(y, "long");
+ break;
+ }
+ y = rb_to_int(y);
+ }
+
+ if (neg) return big_rshift(x, shift);
+ return big_lshift(x, shift);
+}
+
+static VALUE
+big_lshift(x, shift)
+ VALUE x;
+ unsigned long shift;
+{
BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
- int s1 = shift/BITSPERDIG;
+ long s1 = shift/BITSPERDIG;
int s2 = shift%BITSPERDIG;
VALUE z;
BDIGIT_DBL num = 0;
long len, i;
- if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
len = RBIGNUM(x)->len;
z = bignew(len+s1+1, RBIGNUM(x)->sign);
zds = BDIGITS(z);
@@ -1628,19 +2070,59 @@ rb_big_lshift(x, y)
return bignorm(z);
}
-static VALUE
+/*
+ * call-seq:
+ * big >> numeric => integer
+ *
+ * Shifts big right _numeric_ positions (left if _numeric_ is negative).
+ */
+
+VALUE
rb_big_rshift(x, y)
VALUE x, y;
{
+ long shift;
+ int neg = 0;
+
+ for (;;) {
+ if (FIXNUM_P(y)) {
+ shift = FIX2LONG(y);
+ if (shift < 0) {
+ neg = 1;
+ shift = -shift;
+ }
+ break;
+ }
+ else if (TYPE(y) == T_BIGNUM) {
+ if (RBIGNUM(y)->sign) {
+ VALUE t = check_shiftdown(y, x);
+ if (!NIL_P(t)) return t;
+ }
+ else {
+ neg = 1;
+ }
+ shift = big2ulong(y, "long");
+ break;
+ }
+ y = rb_to_int(y);
+ }
+
+ if (neg) return big_lshift(x, shift);
+ return big_rshift(x, shift);
+}
+
+static VALUE
+big_rshift(x, shift)
+ VALUE x;
+ unsigned long shift;
+{
BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
long s1 = shift/BITSPERDIG;
- long s2 = shift%BITSPERDIG;
+ int s2 = shift%BITSPERDIG;
VALUE z;
BDIGIT_DBL num = 0;
long i, j;
-
- if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));
+ volatile VALUE save_x;
if (s1 > RBIGNUM(x)->len) {
if (RBIGNUM(x)->sign)
@@ -1649,11 +2131,15 @@ rb_big_rshift(x, y)
return INT2FIX(-1);
}
if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
+ save_x = x = rb_big_clone(x);
+ get2comp(x);
}
xds = BDIGITS(x);
i = RBIGNUM(x)->len; j = i - s1;
+ if (j == 0) {
+ if (RBIGNUM(x)->sign) return INT2FIX(0);
+ else return INT2FIX(-1);
+ }
z = bignew(j, RBIGNUM(x)->sign);
if (!RBIGNUM(x)->sign) {
num = ((BDIGIT_DBL)~0) << BITSPERDIG;
@@ -1665,43 +2151,79 @@ rb_big_rshift(x, y)
num = BIGUP(xds[i]);
}
if (!RBIGNUM(x)->sign) {
- get2comp(z, Qfalse);
+ get2comp(z);
}
return bignorm(z);
}
+/*
+ * call-seq:
+ * big[n] -> 0, 1
+ *
+ * Bit Reference---Returns the <em>n</em>th bit in the (assumed) binary
+ * representation of <i>big</i>, where <i>big</i>[0] is the least
+ * significant bit.
+ *
+ * a = 9**15
+ * 50.downto(0) do |n|
+ * print a[n]
+ * end
+ *
+ * <em>produces:</em>
+ *
+ * 000101110110100000111000011110010100111100010111001
+ *
+ */
+
static VALUE
rb_big_aref(x, y)
VALUE x, y;
{
BDIGIT *xds;
- int shift;
- long s1, s2;
+ BDIGIT_DBL num;
+ unsigned long shift;
+ long i, s1, s2;
if (TYPE(y) == T_BIGNUM) {
- if (!RBIGNUM(y)->sign || RBIGNUM(x)->sign)
+ if (!RBIGNUM(y)->sign)
return INT2FIX(0);
- return INT2FIX(1);
+ if (RBIGNUM(bigtrunc(y))->len > SIZEOF_LONG/SIZEOF_BDIGITS) {
+ out_of_range:
+ return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(1);
+ }
+ shift = big2ulong(y, "long");
+ }
+ else {
+ i = NUM2LONG(y);
+ if (i < 0) return INT2FIX(0);
+ shift = (VALUE)i;
}
- shift = NUM2INT(y);
- if (shift < 0) return INT2FIX(0);
s1 = shift/BITSPERDIG;
s2 = shift%BITSPERDIG;
+ if (s1 >= RBIGNUM(x)->len) goto out_of_range;
if (!RBIGNUM(x)->sign) {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(1);
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
+ xds = BDIGITS(x);
+ i = 0; num = 1;
+ while (num += ~xds[i], ++i <= s1) {
+ num = BIGDN(num);
+ }
}
else {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(0);
+ num = BDIGITS(x)[s1];
}
- xds = BDIGITS(x);
- if (xds[s1] & (1<<s2))
+ if (num & ((BDIGIT_DBL)1<<s2))
return INT2FIX(1);
return INT2FIX(0);
}
+/*
+ * call-seq:
+ * big.hash => fixnum
+ *
+ * Compute a hash based on the value of _big_.
+ */
+
static VALUE
rb_big_hash(x)
VALUE x;
@@ -1716,6 +2238,10 @@ rb_big_hash(x)
return LONG2FIX(key);
}
+/*
+ * MISSING: documentation
+ */
+
static VALUE
rb_big_coerce(x, y)
VALUE x, y;
@@ -1723,14 +2249,26 @@ rb_big_coerce(x, y)
if (FIXNUM_P(y)) {
return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
}
+ else if (TYPE(y) == T_BIGNUM) {
+ return rb_assoc_new(y, x);
+ }
else {
- rb_raise(rb_eTypeError, "Can't coerce %s to Bignum",
+ rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
rb_obj_classname(y));
}
/* not reached */
return Qnil;
}
+/*
+ * call-seq:
+ * big.abs -> aBignum
+ *
+ * Returns the absolute value of <i>big</i>.
+ *
+ * -1234567890987654321.abs #=> 1234567890987654321
+ */
+
static VALUE
rb_big_abs(x)
VALUE x;
@@ -1754,13 +2292,27 @@ rb_big_rand(max, rand_buf)
return rb_float_new(rand_buf[0]);
}
v = bignew(len,1);
+ len--;
+ BDIGITS(v)[len] = BDIGITS(max)[len] * rand_buf[len];
while (len--) {
BDIGITS(v)[len] = ((BDIGIT)~0) * rand_buf[len];
}
- return rb_big_modulo((VALUE)v, max);
+ return v;
}
+/*
+ * call-seq:
+ * big.size -> integer
+ *
+ * Returns the number of bytes in the machine representation of
+ * <i>big</i>.
+ *
+ * (256**10 - 1).size #=> 12
+ * (256**20 - 1).size #=> 20
+ * (256**40 - 1).size #=> 40
+ */
+
static VALUE
rb_big_size(big)
VALUE big;
@@ -1768,6 +2320,24 @@ rb_big_size(big)
return LONG2FIX(RBIGNUM(big)->len*SIZEOF_BDIGITS);
}
+/*
+ * Bignum objects hold integers outside the range of
+ * Fixnum. Bignum objects are created
+ * automatically when integer calculations would otherwise overflow a
+ * Fixnum. When a calculation involving
+ * Bignum objects returns a result that will fit in a
+ * Fixnum, the result is automatically converted.
+ *
+ * For the purposes of the bitwise operations and <code>[]</code>, a
+ * Bignum is treated as if it were an infinite-length
+ * bitstring with 2's complement representation.
+ *
+ * While Fixnum values are immediate, Bignum
+ * objects are not---assignment and parameter passing work with
+ * references to objects, not the objects themselves.
+ *
+ */
+
void
Init_Bignum()
{
@@ -1786,6 +2356,7 @@ Init_Bignum()
rb_define_method(rb_cBignum, "modulo", rb_big_modulo, 1);
rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
rb_define_method(rb_cBignum, "quo", rb_big_quo, 1);
+ rb_define_method(rb_cBignum, "fdiv", rb_big_quo, 1);
rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
rb_define_method(rb_cBignum, "&", rb_big_and, 1);
rb_define_method(rb_cBignum, "|", rb_big_or, 1);
diff --git a/bin/erb b/bin/erb
index 2459d2562e..a6fcd5370c 100755
--- a/bin/erb
+++ b/bin/erb
@@ -12,13 +12,13 @@ class ERB
arg = self.shift
return nil if arg == '--'
if arg =~ /^-(.)(.*)/
- return arg if $1 == '-'
- raise 'unknown switch "-"' if $2.index('-')
- self.unshift "-#{$2}" if $2.size > 0
- "-#{$1}"
+ return arg if $1 == '-'
+ raise 'unknown switch "-"' if $2.index('-')
+ self.unshift "-#{$2}" if $2.size > 0
+ "-#{$1}"
else
- self.unshift arg
- nil
+ self.unshift arg
+ nil
end
end
@@ -30,13 +30,13 @@ class ERB
return trim_mode if disable_percent
case trim_mode
when 0
- return '%'
+ return '%'
when 1
- return '%>'
+ return '%>'
when 2
- return '%<>'
+ return '%<>'
when '-'
- return '%-'
+ return '%-'
end
end
module_function :trim_mode_opt
@@ -45,89 +45,91 @@ class ERB
trim_mode = 0
disable_percent = false
begin
- while switch = ARGV.switch
- case switch
- when '-x' # ruby source
- output = true
- when '-n' # line number
- number = true
- when '-v' # verbose
- $VERBOSE = true
- when '--version' # version
- STDERR.puts factory.version
- exit
- when '-d', '--debug' # debug
- $DEBUG = true
- when '-r' # require
- require ARGV.req_arg
- when '-S' # sacurity level
- arg = ARGV.req_arg
- raise "invalid safe_level #{arg.dump}" unless arg =~ /^[0-4]$/
- safe_level = arg.to_i
- when '-T' # trim mode
- arg = ARGV.req_arg
- if arg == '-'
- trim_mode = arg
- next
- end
- raise "invalid trim mode #{arg.dump}" unless arg =~ /^[0-2]$/
- trim_mode = arg.to_i
- when '-K' # KCODE
- arg = ARGV.req_arg
- case arg.downcase
- when 'e', '-e', 'euc'
- $KCODE = 'EUC'
- when 's', '-s', 'sjis'
- $KCODE = 'SJIS'
- when 'u', '-u', 'utf8'
- $KCODE = 'UTF8'
- when 'n', '-n', 'none'
- $KCODE = 'NONE'
- else
- raise "invalid KCODE #{arg.dump}"
- end
- when '-P'
- disable_percent = true
- when '--help'
- raise "print this help"
- else
- raise "unknown switch #{switch.dump}"
- end
- end
- rescue # usage
- STDERR.puts $!.to_s
- STDERR.puts File.basename($0) +
- " [switches] [inputfile]"
- STDERR.puts <<EOU
+ while switch = ARGV.switch
+ case switch
+ when '-x' # ruby source
+ output = true
+ when '-n' # line number
+ number = true
+ when '-v' # verbose
+ $VERBOSE = true
+ when '--version' # version
+ STDERR.puts factory.version
+ exit
+ when '-d', '--debug' # debug
+ $DEBUG = true
+ when '-r' # require
+ require ARGV.req_arg
+ when '-S' # security level
+ arg = ARGV.req_arg
+ raise "invalid safe_level #{arg.dump}" unless arg =~ /^[0-4]$/
+ safe_level = arg.to_i
+ when '-T' # trim mode
+ arg = ARGV.req_arg
+ if arg == '-'
+ trim_mode = arg
+ next
+ end
+ raise "invalid trim mode #{arg.dump}" unless arg =~ /^[0-2]$/
+ trim_mode = arg.to_i
+ when '-K' # KCODE
+ arg = ARGV.req_arg
+ case arg.downcase
+ when 'e', '-e', 'euc'
+ $KCODE = 'EUC'
+ when 's', '-s', 'sjis'
+ $KCODE = 'SJIS'
+ when 'u', '-u', 'utf8'
+ $KCODE = 'UTF8'
+ when 'n', '-n', 'none'
+ $KCODE = 'NONE'
+ else
+ raise "invalid KCODE #{arg.dump}"
+ end
+ when '-P'
+ disable_percent = true
+ when '--help'
+ raise "print this help"
+ else
+ raise "unknown switch #{switch.dump}"
+ end
+ end
+ rescue # usage
+ STDERR.puts $!.to_s
+ STDERR.puts File.basename($0) +
+ " [switches] [inputfile]"
+ STDERR.puts <<EOU
-x print ruby script
-n print ruby script with line number
-v enable verbose mode
- -d set $DBEUG to true
+ -d set $DEBUG to true
-r [library] load a library
-K [kcode] specify KANJI code-set
-S [safe_level] set $SAFE (0..4)
-T [trim_mode] specify trim_mode (0..2, -)
- -P disregard the lin which starts in "%"
+ -P ignore lines which start with "%"
EOU
- exit 1
+ exit 1
end
src = $<.read
+ filename = $FILENAME
exit 2 unless src
trim = trim_mode_opt(trim_mode, disable_percent)
erb = factory.new(src.untaint, safe_level, trim)
+ erb.filename = filename
if output
- if number
- l = 1
- for line in erb.src
- puts "%3d %s"%[l, line]
- l += 1
- end
- else
- puts erb.src
- end
+ if number
+ l = 1
+ for line in erb.src
+ puts "%3d %s"%[l, line]
+ l += 1
+ end
+ else
+ puts erb.src
+ end
else
- erb.run(TOPLEVEL_BINDING.taint)
+ erb.run(TOPLEVEL_BINDING.taint)
end
end
module_function :run
diff --git a/bin/irb b/bin/irb
index 309da52161..f277bc4b69 100644
--- a/bin/irb
+++ b/bin/irb
@@ -1,10 +1,10 @@
#!/usr/bin/env ruby
#
# irb.rb - intaractive ruby
-# $Release Version: 0.7.3 $
+# $Release Version: 0.9.5 $
# $Revision$
# $Date$
-# by Keiju ISHITSUKA(keiju@ishitsuka.com)
+# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
require "irb"
diff --git a/bin/ri b/bin/ri
new file mode 100755
index 0000000000..fb3e00eda3
--- /dev/null
+++ b/bin/ri
@@ -0,0 +1,49 @@
+#!/usr/bin/env ruby
+# usage:
+#
+# ri name...
+#
+# where name can be
+#
+# Class | Class::method | Class#method | Class.method | method
+#
+# All names may be abbreviated to their minimum unbiguous form. If a name
+# _is_ ambiguous, all valid options will be listed.
+#
+# The form '.' method matches either class or instance methods, while
+# #method matches only instance and ::method matches only class methods.
+#
+#
+# == Installing Documentation
+#
+# 'ri' uses a database of documentation built by the RDoc utility.
+#
+# So, how do you install this documentation on your system?
+# It depends on how you installed Ruby.
+#
+# <em>If you installed Ruby from source files</em> (that is, if it some point
+# you typed 'make' during the process :), you can install the RDoc
+# documentation yourself. Just go back to the place where you have
+# your Ruby source and type
+#
+# make install-doc
+#
+# You'll probably need to do this as a superuser, as the documentation
+# is installed in the Ruby target tree (normally somewhere under
+# <tt>/usr/local</tt>.
+#
+# <em>If you installed Ruby from a binary distribution</em> (perhaps
+# using a one-click installer, or using some other packaging system),
+# then the team that produced the package probably forgot to package
+# the documentation as well. Contact them, and see if they can add
+# it to the next release.
+#
+
+
+require 'rdoc/ri/ri_driver'
+
+######################################################################
+
+ri = RiDriver.new
+ri.process_args
+
diff --git a/class.c b/class.c
index 666548dde3..80f57a1622 100644
--- a/class.c
+++ b/class.c
@@ -48,21 +48,39 @@ rb_class_new(super)
return rb_class_boot(super);
}
+struct clone_method_data {
+ st_table *tbl;
+ VALUE klass;
+};
+
static int
-clone_method(mid, body, tbl)
+clone_method(mid, body, data)
ID mid;
NODE *body;
- st_table *tbl;
+ struct clone_method_data *data;
{
- st_insert(tbl, mid, (st_data_t)NEW_METHOD(body->nd_body, body->nd_noex));
+ NODE *fbody = body->nd_body;
+
+ if (fbody && nd_type(fbody) == NODE_SCOPE) {
+ NODE *cref = (NODE*)fbody->nd_rval;
+
+ if (cref) cref = cref->nd_next;
+ fbody = rb_copy_node_scope(fbody, NEW_CREF(data->klass, cref));
+ }
+ st_insert(data->tbl, mid, (st_data_t)NEW_METHOD(fbody, body->nd_noex));
return ST_CONTINUE;
}
+/* :nodoc: */
VALUE
rb_mod_init_copy(clone, orig)
VALUE clone, orig;
{
rb_obj_init_copy(clone, orig);
+ if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
+ RBASIC(clone)->klass = RBASIC(orig)->klass;
+ RBASIC(clone)->klass = rb_singleton_class_clone(clone);
+ }
RCLASS(clone)->super = RCLASS(orig)->super;
if (RCLASS(orig)->iv_tbl) {
ID id;
@@ -74,14 +92,18 @@ rb_mod_init_copy(clone, orig)
st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0);
}
if (RCLASS(orig)->m_tbl) {
- RCLASS(clone)->m_tbl = st_init_numtable();
- st_foreach(RCLASS(orig)->m_tbl, clone_method,
- (st_data_t)RCLASS(clone)->m_tbl);
+ struct clone_method_data data;
+
+ data.tbl = RCLASS(clone)->m_tbl = st_init_numtable();
+ data.klass = (VALUE)clone;
+
+ st_foreach(RCLASS(orig)->m_tbl, clone_method, (st_data_t)&data);
}
return clone;
}
+/* :nodoc: */
VALUE
rb_class_init_copy(clone, orig)
VALUE clone, orig;
@@ -89,6 +111,9 @@ rb_class_init_copy(clone, orig)
if (RCLASS(clone)->super != 0) {
rb_raise(rb_eTypeError, "already initialized class");
}
+ if (FL_TEST(orig, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError, "can't copy singleton class");
+ }
return rb_mod_init_copy(clone, orig);
}
@@ -118,9 +143,22 @@ rb_singleton_class_clone(obj)
if (RCLASS(klass)->iv_tbl) {
clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
}
- clone->m_tbl = st_init_numtable();
- st_foreach(RCLASS(klass)->m_tbl, clone_method,
- (st_data_t)clone->m_tbl);
+ {
+ struct clone_method_data data;
+
+ data.tbl = clone->m_tbl = st_init_numtable();
+ switch (TYPE(obj)) {
+ case T_CLASS:
+ case T_MODULE:
+ data.klass = obj;
+ break;
+ default:
+ data.klass = 0;
+ break;
+ }
+
+ st_foreach(RCLASS(klass)->m_tbl, clone_method, (st_data_t)&data);
+ }
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
FL_SET(clone, FL_SINGLETON);
return (VALUE)clone;
@@ -172,12 +210,24 @@ rb_define_class_id(id, super)
if (!super) super = rb_cObject;
klass = rb_class_new(super);
- rb_name_class(klass, id);
rb_make_metaclass(klass, RBASIC(super)->klass);
return klass;
}
+void
+rb_check_inheritable(super)
+ VALUE super;
+{
+ if (TYPE(super) != T_CLASS) {
+ rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
+ rb_obj_classname(super));
+ }
+ if (RBASIC(super)->flags & FL_SINGLETON) {
+ rb_raise(rb_eTypeError, "can't make subclass of virtual class");
+ }
+}
+
VALUE
rb_class_inherited(super, klass)
VALUE super, klass;
@@ -210,6 +260,7 @@ rb_define_class(name, super)
}
klass = rb_define_class_id(id, super);
st_add_direct(rb_class_tbl, id, klass);
+ rb_name_class(klass, id);
rb_const_set(rb_cObject, id, klass);
rb_class_inherited(super, klass);
@@ -358,9 +409,6 @@ rb_include_module(klass, module)
rb_secure(4);
}
- if (NIL_P(module)) return;
- if (klass == module) return;
-
if (TYPE(module) != T_MODULE) {
Check_Type(module, T_MODULE);
}
@@ -396,6 +444,23 @@ rb_include_module(klass, module)
if (changed) rb_clear_cache();
}
+/*
+ * call-seq:
+ * mod.included_modules -> array
+ *
+ * Returns the list of modules included in <i>mod</i>.
+ *
+ * module Mixin
+ * end
+ *
+ * module Outer
+ * include Mixin
+ * end
+ *
+ * Mixin.included_modules #=> []
+ * Outer.included_modules #=> [Mixin]
+ */
+
VALUE
rb_mod_included_modules(mod)
VALUE mod;
@@ -411,6 +476,25 @@ rb_mod_included_modules(mod)
return ary;
}
+/*
+ * call-seq:
+ * mod.include?(module) => true or false
+ *
+ * Returns <code>true</code> if <i>module</i> is included in
+ * <i>mod</i> or one of <i>mod</i>'s ancestors.
+ *
+ * module A
+ * end
+ * class B
+ * include A
+ * end
+ * class C < B
+ * end
+ * B.include?(A) #=> true
+ * C.include?(A) #=> true
+ * A.include?(A) #=> false
+ */
+
VALUE
rb_mod_include_p(mod, mod2)
VALUE mod;
@@ -427,6 +511,22 @@ rb_mod_include_p(mod, mod2)
return Qfalse;
}
+/*
+ * call-seq:
+ * mod.ancestors -> array
+ *
+ * Returns a list of modules included in <i>mod</i> (including
+ * <i>mod</i> itself).
+ *
+ * module Mod
+ * include Math
+ * include Comparable
+ * end
+ *
+ * Mod.ancestors #=> [Mod, Comparable, Math]
+ * Math.ancestors #=> [Math]
+ */
+
VALUE
rb_mod_ancestors(mod)
VALUE mod;
@@ -560,6 +660,33 @@ class_instance_method_list(argc, argv, mod, func)
return ary;
}
+/*
+ * call-seq:
+ * mod.instance_methods(include_super=true) => array
+ *
+ * Returns an array containing the names of public instance methods in
+ * the receiver. For a module, these are the public methods; for a
+ * class, they are the instance (not singleton) methods. With no
+ * argument, or with an argument that is <code>false</code>, the
+ * instance methods in <i>mod</i> are returned, otherwise the methods
+ * in <i>mod</i> and <i>mod</i>'s superclasses are returned.
+ *
+ * module A
+ * def method1() end
+ * end
+ * class B
+ * def method2() end
+ * end
+ * class C < B
+ * def method3() end
+ * end
+ *
+ * A.instance_methods #=> ["method1"]
+ * B.instance_methods(false) #=> ["method2"]
+ * C.instance_methods(false) #=> ["method3"]
+ * C.instance_methods(true).length #=> 43
+ */
+
VALUE
rb_class_instance_methods(argc, argv, mod)
int argc;
@@ -569,6 +696,15 @@ rb_class_instance_methods(argc, argv, mod)
return class_instance_method_list(argc, argv, mod, ins_methods_i);
}
+/*
+ * call-seq:
+ * mod.protected_instance_methods(include_super=true) => array
+ *
+ * Returns a list of the protected instance methods defined in
+ * <i>mod</i>. If the optional parameter is not <code>false</code>, the
+ * methods of any ancestors are included.
+ */
+
VALUE
rb_class_protected_instance_methods(argc, argv, mod)
int argc;
@@ -578,6 +714,23 @@ rb_class_protected_instance_methods(argc, argv, mod)
return class_instance_method_list(argc, argv, mod, ins_methods_prot_i);
}
+/*
+ * call-seq:
+ * mod.private_instance_methods(include_super=true) => array
+ *
+ * Returns a list of the private instance methods defined in
+ * <i>mod</i>. If the optional parameter is not <code>false</code>, the
+ * methods of any ancestors are included.
+ *
+ * module Mod
+ * def method1() end
+ * private :method1
+ * def method2() end
+ * end
+ * Mod.instance_methods #=> ["method2"]
+ * Mod.private_instance_methods #=> ["method1"]
+ */
+
VALUE
rb_class_private_instance_methods(argc, argv, mod)
int argc;
@@ -587,6 +740,15 @@ rb_class_private_instance_methods(argc, argv, mod)
return class_instance_method_list(argc, argv, mod, ins_methods_priv_i);
}
+/*
+ * call-seq:
+ * mod.public_instance_methods(include_super=true) => array
+ *
+ * Returns a list of the public instance methods defined in <i>mod</i>.
+ * If the optional parameter is not <code>false</code>, the methods of
+ * any ancestors are included.
+ */
+
VALUE
rb_class_public_instance_methods(argc, argv, mod)
int argc;
@@ -596,6 +758,38 @@ rb_class_public_instance_methods(argc, argv, mod)
return class_instance_method_list(argc, argv, mod, ins_methods_pub_i);
}
+/*
+ * call-seq:
+ * obj.singleton_methods(all=true) => array
+ *
+ * Returns an array of the names of singleton methods for <i>obj</i>.
+ * If the optional <i>all</i> parameter is true, the list will include
+ * methods in modules included in <i>obj</i>.
+ *
+ * module Other
+ * def three() end
+ * end
+ *
+ * class Single
+ * def Single.four() end
+ * end
+ *
+ * a = Single.new
+ *
+ * def a.one()
+ * end
+ *
+ * class << a
+ * include Other
+ * def two()
+ * end
+ * end
+ *
+ * Single.singleton_methods #=> ["four"]
+ * a.singleton_methods(false) #=> ["two", "one"]
+ * a.singleton_methods #=> ["two", "one", "three"]
+ */
+
VALUE
rb_obj_singleton_methods(argc, argv, obj)
int argc;
@@ -855,7 +1049,7 @@ rb_scan_args(argc, argv, fmt, va_alist)
}
if (argc > i) {
- rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)", argc, i);
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
}
return argc;
diff --git a/common.mk b/common.mk
new file mode 100644
index 0000000000..bf49aade4a
--- /dev/null
+++ b/common.mk
@@ -0,0 +1,468 @@
+bin: $(PROGRAM) $(WPROGRAM)
+lib: $(LIBRUBY)
+dll: $(LIBRUBY_SO)
+
+RUBYLIB = -
+RUBYOPT = -
+
+SPEC_GIT_BASE = git://github.com/rubyspec
+MSPEC_GIT_URL = $(SPEC_GIT_BASE)/mspec.git
+RUBYSPEC_GIT_URL = $(SPEC_GIT_BASE)/rubyspec.git
+
+STATIC_RUBY = static-ruby
+
+EXTCONF = extconf.rb
+RBCONFIG = ./.rbconfig.time
+LIBRUBY_EXTS = ./.libruby-with-ext.time
+RDOCOUT = $(EXTOUT)/rdoc
+
+DMYEXT = dmyext.$(OBJEXT)
+MAINOBJ = main.$(OBJEXT)
+EXTOBJS =
+DLDOBJS = $(DMYEXT)
+
+OBJS = array.$(OBJEXT) \
+ bignum.$(OBJEXT) \
+ class.$(OBJEXT) \
+ compar.$(OBJEXT) \
+ dir.$(OBJEXT) \
+ dln.$(OBJEXT) \
+ enum.$(OBJEXT) \
+ enumerator.$(OBJEXT) \
+ error.$(OBJEXT) \
+ eval.$(OBJEXT) \
+ file.$(OBJEXT) \
+ gc.$(OBJEXT) \
+ hash.$(OBJEXT) \
+ inits.$(OBJEXT) \
+ io.$(OBJEXT) \
+ marshal.$(OBJEXT) \
+ math.$(OBJEXT) \
+ numeric.$(OBJEXT) \
+ object.$(OBJEXT) \
+ pack.$(OBJEXT) \
+ parse.$(OBJEXT) \
+ process.$(OBJEXT) \
+ prec.$(OBJEXT) \
+ random.$(OBJEXT) \
+ range.$(OBJEXT) \
+ re.$(OBJEXT) \
+ regex.$(OBJEXT) \
+ ruby.$(OBJEXT) \
+ signal.$(OBJEXT) \
+ sprintf.$(OBJEXT) \
+ st.$(OBJEXT) \
+ string.$(OBJEXT) \
+ struct.$(OBJEXT) \
+ time.$(OBJEXT) \
+ util.$(OBJEXT) \
+ variable.$(OBJEXT) \
+ version.$(OBJEXT) \
+ $(MISSING)
+
+SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \
+ --extout="$(EXTOUT)" \
+ --mflags="$(MFLAGS)" \
+ --make-flags="$(MAKEFLAGS)"
+EXTMK_ARGS = $(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) --
+INSTRUBY_ARGS = $(SCRIPT_ARGS) \
+ --data-mode=$(INSTALL_DATA_MODE) \
+ --prog-mode=$(INSTALL_PROG_MODE) \
+ --installed-list $(INSTALLED_LIST)
+INSTALL_PROG_MODE = 0755
+INSTALL_DATA_MODE = 0644
+
+PRE_LIBRUBY_UPDATE = $(MINIRUBY) -e 'ARGV[1] or File.unlink(ARGV[0]) rescue nil' -- \
+ $(LIBRUBY_EXTS) $(LIBRUBY_SO_UPDATE)
+
+TESTSDIR = $(srcdir)/test
+TESTWORKDIR = testwork
+
+all: $(MKFILES) $(PREP) $(RBCONFIG) $(LIBRUBY)
+ @$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS)
+prog: $(PROGRAM) $(WPROGRAM)
+
+miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) $(MINIOBJS) $(OBJS) $(DMYEXT)
+
+$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP)
+
+$(LIBRUBY_A): $(OBJS) $(DMYEXT) $(ARCHFILE)
+
+$(LIBRUBY_SO): $(OBJS) $(DLDOBJS) $(LIBRUBY_A) $(PREP) $(LIBRUBY_SO_UPDATE)
+
+$(LIBRUBY_EXTS):
+ @exit > $@
+
+$(STATIC_RUBY)$(EXEEXT): $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A)
+ @$(RM) $@
+ $(PURIFY) $(CC) $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A) $(MAINLIBS) $(EXTLIBS) $(LIBS) $(OUTFLAG)$@ $(LDFLAGS) $(XLDFLAGS)
+
+ruby.imp: $(OBJS)
+ @$(NM) -Pgp $(OBJS) | awk 'BEGIN{print "#!"}; $$2~/^[BD]$$/{print $$1}' | sort -u -o $@
+
+install: install-nodoc $(RDOCTARGET)
+install-all: install-nodoc install-doc
+
+install-nodoc: pre-install-nodoc do-install-nodoc post-install-nodoc
+pre-install-nodoc:: pre-install-local pre-install-ext
+do-install-nodoc:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --mantype="$(MANTYPE)"
+post-install-nodoc:: post-install-local post-install-ext
+
+install-local: pre-install-local do-install-local post-install-local
+pre-install-local:: pre-install-bin pre-install-lib pre-install-man
+do-install-local:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=local --mantype="$(MANTYPE)"
+loadpath: $(PREP)
+ $(MINIRUBY) -e 'p $$:'
+
+post-install-local:: post-install-bin post-install-lib post-install-man
+
+install-ext: pre-install-ext do-install-ext post-install-ext
+pre-install-ext:: pre-install-ext-arch pre-install-ext-comm
+do-install-ext:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext
+post-install-ext:: post-install-ext-arch post-install-ext-comm
+
+install-arch: pre-install-arch do-install-arch post-install-arch
+pre-install-arch:: pre-install-bin pre-install-ext-arch
+do-install-arch:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin --install=ext-arch
+post-install-arch:: post-install-bin post-install-ext-arch
+
+install-comm: pre-install-comm do-install-comm post-install-comm
+pre-install-comm:: pre-install-lib pre-install-ext-comm pre-install-man
+do-install-comm:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=lib --install=ext-comm --install=man
+post-install-comm:: post-install-lib post-install-ext-comm post-install-man
+
+install-bin: pre-install-bin do-install-bin post-install-bin
+pre-install-bin:: install-prereq
+do-install-bin:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin
+post-install-bin::
+ @$(NULLCMD)
+
+install-lib: pre-install-lib do-install-lib post-install-lib
+pre-install-lib:: install-prereq
+do-install-lib:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=lib
+post-install-lib::
+ @$(NULLCMD)
+
+install-ext-comm: pre-install-ext-comm do-install-ext-comm post-install-ext-comm
+pre-install-ext-comm:: install-prereq
+do-install-ext-comm:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-comm
+post-install-ext-comm::
+ @$(NULLCMD)
+
+install-ext-arch: pre-install-ext-arch do-install-ext-arch post-install-ext-arch
+pre-install-ext-arch:: install-prereq
+do-install-ext-arch:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-arch
+post-install-ext-arch::
+ @$(NULLCMD)
+
+install-man: pre-install-man do-install-man post-install-man
+pre-install-man:: install-prereq
+do-install-man:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=man --mantype="$(MANTYPE)"
+post-install-man::
+ @$(NULLCMD)
+
+what-where: no-install
+no-install: no-install-nodoc no-install-doc
+what-where-all: no-install-all
+no-install-all: no-install-nodoc
+
+what-where-nodoc: no-install-nodoc
+no-install-nodoc: pre-no-install-nodoc dont-install-nodoc post-no-install-nodoc
+pre-no-install-nodoc:: pre-no-install-local pre-no-install-ext
+dont-install-nodoc:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --mantype="$(MANTYPE)"
+post-no-install-nodoc:: post-no-install-local post-no-install-ext
+
+what-where-local: no-install-local
+no-install-local: pre-no-install-local dont-install-local post-no-install-local
+pre-no-install-local:: pre-no-install-bin pre-no-install-lib pre-no-install-man
+dont-install-local:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=local --mantype="$(MANTYPE)"
+post-no-install-local:: post-no-install-bin post-no-install-lib post-no-install-man
+
+what-where-ext: no-install-ext
+no-install-ext: pre-no-install-ext dont-install-ext post-no-install-ext
+pre-no-install-ext:: pre-no-install-ext-arch pre-no-install-ext-comm
+dont-install-ext:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext
+post-no-install-ext:: post-no-install-ext-arch post-no-install-ext-comm
+
+what-where-arch: no-install-arch
+no-install-arch: pre-no-install-arch dont-install-arch post-no-install-arch
+pre-no-install-arch:: pre-no-install-bin pre-no-install-ext-arch
+dont-install-arch:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin --install=ext-arch
+post-no-install-arch:: post-no-install-lib post-no-install-man post-no-install-ext-arch
+
+what-where-comm: no-install-comm
+no-install-comm: pre-no-install-comm dont-install-comm post-no-install-comm
+pre-no-install-comm:: pre-no-install-lib pre-no-install-ext-comm pre-no-install-man
+dont-install-comm:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=lib --install=ext-comm --install=man
+post-no-install-comm:: post-no-install-lib post-no-install-ext-comm post-no-install-man
+
+what-where-bin: no-install-bin
+no-install-bin: pre-no-install-bin dont-install-bin post-no-install-bin
+pre-no-install-bin:: install-prereq
+dont-install-bin:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin
+post-no-install-bin::
+ @$(NULLCMD)
+
+what-where-lib: no-install-lib
+no-install-lib: pre-no-install-lib dont-install-lib post-no-install-lib
+pre-no-install-lib:: install-prereq
+dont-install-lib:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=lib
+post-no-install-lib::
+ @$(NULLCMD)
+
+what-where-ext-comm: no-install-ext-comm
+no-install-ext-comm: pre-no-install-ext-comm dont-install-ext-comm post-no-install-ext-comm
+pre-no-install-ext-comm:: install-prereq
+dont-install-ext-comm:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-comm
+post-no-install-ext-comm::
+ @$(NULLCMD)
+
+what-where-ext-arch: no-install-ext-arch
+no-install-ext-arch: pre-no-install-ext-arch dont-install-ext-arch post-no-install-ext-arch
+pre-no-install-ext-arch:: install-prereq
+dont-install-ext-arch:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-arch
+post-no-install-ext-arch::
+ @$(NULLCMD)
+
+what-where-man: no-install-man
+no-install-man: pre-no-install-man dont-install-man post-no-install-man
+pre-no-install-man:: install-prereq
+dont-install-man:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=man --mantype="$(MANTYPE)"
+post-no-install-man::
+ @$(NULLCMD)
+
+install-doc: rdoc pre-install-doc do-install-doc post-install-doc
+pre-install-doc:: install-prereq
+do-install-doc: $(PROGRAM)
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
+post-install-doc::
+ @$(NULLCMD)
+
+rdoc: $(PROGRAM) PHONY
+ @echo Generating RDoc documentation
+ $(RUNRUBY) "$(srcdir)/bin/rdoc" --all --ri --op "$(RDOCOUT)" "$(srcdir)"
+
+what-where-doc: no-install-doc
+no-install-doc: pre-no-install-doc dont-install-doc post-no-install-doc
+pre-no-install-doc:: install-prereq
+dont-install-doc::
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
+post-no-install-doc::
+ @$(NULLCMD)
+
+CLEAR_INSTALLED_LIST = clear-installed-list
+
+install-prereq: $(CLEAR_INSTALLED_LIST)
+
+clear-installed-list:
+ @exit > $(INSTALLED_LIST)
+
+clean: clean-ext clean-local
+clean-local::
+ @$(RM) $(OBJS) $(MINIOBJS) $(MAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
+ @$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) $(ARCHFILE) .*.time
+ @$(RM) y.tab.c y.output
+clean-ext:
+ @-$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS) clean
+
+distclean: distclean-ext distclean-local
+distclean-local:: clean-local
+ @$(RM) $(MKFILES) config.h rbconfig.rb
+ @$(RM) config.cache config.log config.status
+ @$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP)
+distclean-ext:
+ @-$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS) distclean
+
+realclean:: realclean-ext realclean-local
+realclean-local:: distclean-local
+ @$(RM) parse.c lex.c
+realclean-ext::
+ @-$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS) realclean
+
+check: test test-all
+
+test: miniruby$(EXEEXT) $(RBCONFIG) $(PROGRAM) PHONY
+ @$(MINIRUBY) $(srcdir)/rubytest.rb
+
+test-all:
+ $(RUNRUBY) "$(srcdir)/test/runner.rb" --basedir="$(TESTSDIR)" --runner=$(TESTUI) $(TESTS)
+
+extconf:
+ $(MINIRUBY) -run -e mkdir -- -p "$(EXTCONFDIR)"
+ $(RUNRUBY) -C "$(EXTCONFDIR)" $(EXTCONF) $(EXTCONFARGS)
+
+$(RBCONFIG): $(srcdir)/mkconfig.rb config.status $(PREP)
+ @$(MINIRUBY) $(srcdir)/mkconfig.rb -timestamp=$@ \
+ -install_name=$(RUBY_INSTALL_NAME) \
+ -so_name=$(RUBY_SO_NAME) rbconfig.rb
+
+.PRECIOUS: $(MKFILES)
+
+.PHONY: test install install-nodoc install-doc dist
+
+PHONY:
+
+{$(VPATH)}parse.c: parse.y
+
+acosh.$(OBJEXT): {$(VPATH)}acosh.c
+alloca.$(OBJEXT): {$(VPATH)}alloca.c
+crypt.$(OBJEXT): {$(VPATH)}crypt.c
+dup2.$(OBJEXT): {$(VPATH)}dup2.c
+erf.$(OBJEXT): {$(VPATH)}erf.c
+finite.$(OBJEXT): {$(VPATH)}finite.c
+flock.$(OBJEXT): {$(VPATH)}flock.c
+memcmp.$(OBJEXT): {$(VPATH)}memcmp.c
+memmove.$(OBJEXT): {$(VPATH)}memmove.c
+mkdir.$(OBJEXT): {$(VPATH)}mkdir.c
+vsnprintf.$(OBJEXT): {$(VPATH)}vsnprintf.c
+strcasecmp.$(OBJEXT): {$(VPATH)}strcasecmp.c
+strncasecmp.$(OBJEXT): {$(VPATH)}strncasecmp.c
+strchr.$(OBJEXT): {$(VPATH)}strchr.c
+strdup.$(OBJEXT): {$(VPATH)}strdup.c
+strerror.$(OBJEXT): {$(VPATH)}strerror.c
+strftime.$(OBJEXT): {$(VPATH)}strftime.c
+strstr.$(OBJEXT): {$(VPATH)}strstr.c
+strtod.$(OBJEXT): {$(VPATH)}strtod.c
+strtol.$(OBJEXT): {$(VPATH)}strtol.c
+strtoul.$(OBJEXT): {$(VPATH)}strtoul.c
+nt.$(OBJEXT): {$(VPATH)}nt.c
+x68.$(OBJEXT): {$(VPATH)}x68.c
+os2.$(OBJEXT): {$(VPATH)}os2.c
+dl_os2.$(OBJEXT): {$(VPATH)}dl_os2.c
+ia64.$(OBJEXT): {$(VPATH)}ia64.s
+ $(CC) $(CFLAGS) -c $<
+
+# when I use -I., there is confliction at "OpenFile"
+# so, set . into environment varible "include"
+win32.$(OBJEXT): {$(VPATH)}win32.c
+
+###
+
+array.$(OBJEXT): {$(VPATH)}array.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}util.h {$(VPATH)}st.h
+bignum.$(OBJEXT): {$(VPATH)}bignum.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}rubysig.h
+class.$(OBJEXT): {$(VPATH)}class.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}rubysig.h {$(VPATH)}node.h {$(VPATH)}st.h
+compar.$(OBJEXT): {$(VPATH)}compar.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+dir.$(OBJEXT): {$(VPATH)}dir.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}util.h
+dln.$(OBJEXT): {$(VPATH)}dln.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}dln.h
+dmydln.$(OBJEXT): {$(VPATH)}dmydln.c dln.$(OBJEXT)
+dmyext.$(OBJEXT): {$(VPATH)}dmyext.c
+enum.$(OBJEXT): {$(VPATH)}enum.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}node.h {$(VPATH)}util.h
+enumerator.$(OBJEXT): {$(VPATH)}enumerator.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}env.h {$(VPATH)}st.h
+eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}node.h {$(VPATH)}env.h {$(VPATH)}util.h \
+ {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.h
+file.$(OBJEXT): {$(VPATH)}file.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}rubyio.h {$(VPATH)}rubysig.h {$(VPATH)}util.h \
+ {$(VPATH)}dln.h
+gc.$(OBJEXT): {$(VPATH)}gc.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}node.h \
+ {$(VPATH)}env.h {$(VPATH)}re.h {$(VPATH)}regex.h
+hash.$(OBJEXT): {$(VPATH)}hash.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}st.h {$(VPATH)}util.h {$(VPATH)}rubysig.h
+inits.$(OBJEXT): {$(VPATH)}inits.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+io.$(OBJEXT): {$(VPATH)}io.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}rubyio.h {$(VPATH)}rubysig.h {$(VPATH)}util.h \
+ {$(VPATH)}env.h
+main.$(OBJEXT): {$(VPATH)}main.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+marshal.$(OBJEXT): {$(VPATH)}marshal.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}rubyio.h {$(VPATH)}st.h {$(VPATH)}util.h
+math.$(OBJEXT): {$(VPATH)}math.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+numeric.$(OBJEXT): {$(VPATH)}numeric.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}env.h {$(VPATH)}defines.h {$(VPATH)}intern.h \
+ {$(VPATH)}missing.h
+object.$(OBJEXT): {$(VPATH)}object.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}st.h {$(VPATH)}util.h
+pack.$(OBJEXT): {$(VPATH)}pack.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+parse.$(OBJEXT): {$(VPATH)}parse.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}env.h {$(VPATH)}node.h {$(VPATH)}st.h \
+ {$(VPATH)}regex.h {$(VPATH)}util.h {$(VPATH)}lex.c
+prec.$(OBJEXT): {$(VPATH)}prec.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+process.$(OBJEXT): {$(VPATH)}process.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}rubysig.h {$(VPATH)}st.h
+random.$(OBJEXT): {$(VPATH)}random.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+range.$(OBJEXT): {$(VPATH)}range.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+re.$(OBJEXT): {$(VPATH)}re.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}re.h {$(VPATH)}regex.h
+regex.$(OBJEXT): {$(VPATH)}regex.c config.h {$(VPATH)}regex.h
+ruby.$(OBJEXT): {$(VPATH)}ruby.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}dln.h {$(VPATH)}node.h {$(VPATH)}util.h
+signal.$(OBJEXT): {$(VPATH)}signal.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}rubysig.h
+sprintf.$(OBJEXT): {$(VPATH)}sprintf.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+st.$(OBJEXT): {$(VPATH)}st.c config.h {$(VPATH)}st.h
+string.$(OBJEXT): {$(VPATH)}string.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}re.h {$(VPATH)}regex.h
+struct.$(OBJEXT): {$(VPATH)}struct.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+time.$(OBJEXT): {$(VPATH)}time.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+util.$(OBJEXT): {$(VPATH)}util.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}util.h
+variable.$(OBJEXT): {$(VPATH)}variable.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}env.h {$(VPATH)}node.h {$(VPATH)}st.h {$(VPATH)}util.h
+version.$(OBJEXT): {$(VPATH)}version.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}version.h
+
+dist: $(PROGRAM)
+ $(RUNRUBY) $(srcdir)/distruby.rb
diff --git a/compar.c b/compar.c
index 5376ce4452..1488b2c65d 100644
--- a/compar.c
+++ b/compar.c
@@ -69,6 +69,15 @@ cmp_failed()
return Qnil;
}
+/*
+ * call-seq:
+ * obj == other => true or false
+ *
+ * Compares two objects based on the receiver's <code><=></code>
+ * method, returning true if it returns 0. Also returns true if
+ * _obj_ and _other_ are the same object.
+ */
+
static VALUE
cmp_equal(x, y)
VALUE x, y;
@@ -81,6 +90,14 @@ cmp_equal(x, y)
return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
}
+/*
+ * call-seq:
+ * obj > other => true or false
+ *
+ * Compares two objects based on the receiver's <code><=></code>
+ * method, returning true if it returns 1.
+ */
+
static VALUE
cmp_gt(x, y)
VALUE x, y;
@@ -92,6 +109,14 @@ cmp_gt(x, y)
return Qfalse;
}
+/*
+ * call-seq:
+ * obj >= other => true or false
+ *
+ * Compares two objects based on the receiver's <code><=></code>
+ * method, returning true if it returns 0 or 1.
+ */
+
static VALUE
cmp_ge(x, y)
VALUE x, y;
@@ -103,6 +128,14 @@ cmp_ge(x, y)
return Qfalse;
}
+/*
+ * call-seq:
+ * obj < other => true or false
+ *
+ * Compares two objects based on the receiver's <code><=></code>
+ * method, returning true if it returns -1.
+ */
+
static VALUE
cmp_lt(x, y)
VALUE x, y;
@@ -114,6 +147,15 @@ cmp_lt(x, y)
return Qfalse;
}
+
+/*
+ * call-seq:
+ * obj <= other => true or false
+ *
+ * Compares two objects based on the receiver's <code><=></code>
+ * method, returning true if it returns -1 or 0.
+ */
+
static VALUE
cmp_le(x, y)
VALUE x, y;
@@ -125,6 +167,21 @@ cmp_le(x, y)
return Qfalse;
}
+/*
+ * call-seq:
+ * obj.between?(min, max) => true or false
+ *
+ * Returns <code>false</code> if <i>obj</i> <code><=></code>
+ * <i>min</i> is less than zero or if <i>anObject</i> <code><=></code>
+ * <i>max</i> is greater than zero, <code>true</code> otherwise.
+ *
+ * 3.between?(1, 5) #=> true
+ * 6.between?(1, 5) #=> false
+ * 'cat'.between?('ant', 'dog') #=> true
+ * 'gnu'.between?('ant', 'dog') #=> false
+ *
+ */
+
static VALUE
cmp_between(x, min, max)
VALUE x, min, max;
@@ -134,6 +191,43 @@ cmp_between(x, min, max)
return Qtrue;
}
+/*
+ * The <code>Comparable</code> mixin is used by classes whose objects
+ * may be ordered. The class must define the <code><=></code> operator,
+ * which compares the receiver against another object, returning -1, 0,
+ * or +1 depending on whether the receiver is less than, equal to, or
+ * greater than the other object. <code>Comparable</code> uses
+ * <code><=></code> to implement the conventional comparison operators
+ * (<code><</code>, <code><=</code>, <code>==</code>, <code>>=</code>,
+ * and <code>></code>) and the method <code>between?</code>.
+ *
+ * class SizeMatters
+ * include Comparable
+ * attr :str
+ * def <=>(anOther)
+ * str.size <=> anOther.str.size
+ * end
+ * def initialize(str)
+ * @str = str
+ * end
+ * def inspect
+ * @str
+ * end
+ * end
+ *
+ * s1 = SizeMatters.new("Z")
+ * s2 = SizeMatters.new("YY")
+ * s3 = SizeMatters.new("XXX")
+ * s4 = SizeMatters.new("WWWW")
+ * s5 = SizeMatters.new("VVVVV")
+ *
+ * s1 < s2 #=> true
+ * s4.between?(s1, s3) #=> false
+ * s4.between?(s3, s5) #=> true
+ * [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
+ *
+ */
+
void
Init_Comparable()
{
diff --git a/config.guess b/config.guess
index 844739cdaf..dd1688b7b5 100644
--- a/config.guess
+++ b/config.guess
@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-timestamp='2003-01-10'
+timestamp='2004-06-11'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -106,6 +106,7 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
{ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
@@ -178,10 +179,26 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
os=netbsd
;;
esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}"
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amd64:OpenBSD:*:*)
+ echo x86_64-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
amiga:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
@@ -189,9 +206,15 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arc:OpenBSD:*:*)
echo mipsel-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
+ cats:OpenBSD:*:*)
+ echo arm-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
hp300:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
+ luna88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
mac68k:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
@@ -222,73 +245,70 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:OpenBSD:*:*)
echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
- *:MicroBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-microbsd${UNAME_RELEASE}
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
exit 0 ;;
alpha:OSF1:*:*)
- if test $UNAME_RELEASE = "V4.0"; then
+ case $UNAME_RELEASE in
+ *4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- fi
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- eval $set_cc_for_build
- cat <<EOF >$dummy.s
- .data
-\$Lformat:
- .byte 37,100,45,37,120,10,0 # "%d-%x\n"
-
- .text
- .globl main
- .align 4
- .ent main
-main:
- .frame \$30,16,\$26,0
- ldgp \$29,0(\$27)
- .prologue 1
- .long 0x47e03d80 # implver \$0
- lda \$2,-1
- .long 0x47e20c21 # amask \$2,\$1
- lda \$16,\$Lformat
- mov \$0,\$17
- not \$1,\$18
- jsr \$26,printf
- ldgp \$29,0(\$26)
- mov 0,\$16
- jsr \$26,exit
- .end main
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null
- if test "$?" = 0 ; then
- case `$dummy` in
- 0-0)
- UNAME_MACHINE="alpha"
- ;;
- 1-0)
- UNAME_MACHINE="alphaev5"
- ;;
- 1-1)
- UNAME_MACHINE="alphaev56"
- ;;
- 1-101)
- UNAME_MACHINE="alphapca56"
- ;;
- 2-303)
- UNAME_MACHINE="alphaev6"
- ;;
- 2-307)
- UNAME_MACHINE="alphaev67"
- ;;
- 2-1307)
- UNAME_MACHINE="alphaev68"
- ;;
- 3-1307)
- UNAME_MACHINE="alphaev7"
- ;;
- esac
- fi
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha*:OpenVMS:*:*)
+ echo alpha-hp-vms
exit 0 ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
@@ -311,6 +331,9 @@ EOF
*:OS/390:*:*)
echo i370-ibm-openedition
exit 0 ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit 0 ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit 0;;
@@ -328,6 +351,9 @@ EOF
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit 0 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
DRS?6000:UNIX_SV:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7 && exit 0 ;;
@@ -400,6 +426,9 @@ EOF
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
exit 0 ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit 0 ;;
@@ -735,7 +764,7 @@ EOF
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit 0 ;;
*:UNICOS/mp:*:*)
- echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit 0 ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
@@ -743,6 +772,11 @@ EOF
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit 0 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit 0 ;;
@@ -764,7 +798,10 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+ # GNU/KFreeBSD systems have a "k" prefix to indicate we are using
+ # FreeBSD's kernel, but not the complete OS.
+ case ${LIBC} in gnu) kernel_only='k' ;; esac
+ echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
exit 0 ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
@@ -775,8 +812,8 @@ EOF
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit 0 ;;
- x86:Interix*:3*)
- echo i586-pc-interix3
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
exit 0 ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
@@ -797,19 +834,30 @@ EOF
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
*:GNU:*:*)
+ # the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit 0 ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit 0 ;;
arm*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
exit 0 ;;
ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;;
m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;;
mips:Linux:*:*)
eval $set_cc_for_build
@@ -828,7 +876,7 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && echo "${CPU}-unknown-linux" && exit 0
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
;;
mips64:Linux:*:*)
eval $set_cc_for_build
@@ -847,13 +895,13 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && echo "${CPU}-unknown-linux" && exit 0
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux
+ echo powerpc-unknown-linux-gnu
exit 0 ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux
+ echo powerpc64-unknown-linux-gnu
exit 0 ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -866,31 +914,34 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
- if test "$?" = 0 ; then LIBC="-libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux${LIBC}
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
exit 0 ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux;;
- PA8*) echo hppa2.0-unknown-linux;;
- *) echo hppa-unknown-linux;;
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
esac
exit 0 ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux
+ echo hppa64-unknown-linux-gnu
exit 0 ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
exit 0 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;;
x86_64:Linux:*:*)
- echo x86_64-unknown-linux
+ echo x86_64-unknown-linux-gnu
exit 0 ;;
i*86:Linux:*:*)
# The BFD linker knows what the default object file format is, so
@@ -905,20 +956,47 @@ EOF
p'`
case "$ld_supported_targets" in
elf32-i386)
- TENTATIVE="${UNAME_MACHINE}-pc-linux"
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
;;
a.out-i386-linux)
- echo "${UNAME_MACHINE}-pc-linux-aout"
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
exit 0 ;;
coff-i386)
- echo "${UNAME_MACHINE}-pc-linux-coff"
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
exit 0 ;;
"")
- # Either a pre-BFD a.out linker (linux-oldld) or
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
# one that does not give us useful --help.
- echo "${UNAME_MACHINE}-pc-linux-oldld"
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
exit 0 ;;
esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
;;
i*86:DYNIX/ptx:4*:*)
@@ -946,6 +1024,9 @@ EOF
i*86:atheos:*:*)
echo ${UNAME_MACHINE}-unknown-atheos
exit 0 ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit 0 ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
@@ -1015,9 +1096,9 @@ EOF
M680?0:D-NIX:5.3:*)
echo m68k-diab-dnix
exit 0 ;;
- M68*:*:R3V[567]*:*)
+ M68*:*:R3V[5678]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
- 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0)
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
@@ -1119,7 +1200,7 @@ EOF
*86) UNAME_PROCESSOR=i686 ;;
powerpc) UNAME_PROCESSOR=powerpc ;;
esac
- echo ${UNAME_PROCESSOR}-apple-darwin
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit 0 ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
@@ -1132,7 +1213,7 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit 0 ;;
- NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+ NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit 0 ;;
*:NonStop-UX:*:*)
@@ -1173,6 +1254,12 @@ EOF
*:ITS:*:*)
echo pdp10-unknown-its
exit 0 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
diff --git a/config.sub b/config.sub
index d2c7af03c5..506d3ab77f 100644
--- a/config.sub
+++ b/config.sub
@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-timestamp='2003-01-03'
+timestamp='2004-06-11'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -118,7 +118,8 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
- nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@@ -228,13 +229,14 @@ case $basic_machine in
| a29k \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
- | clipper \
+ | c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
- | ip2k \
+ | ip2k | iq2000 \
| m32r | m68000 | m68k | m88k | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
@@ -247,6 +249,7 @@ case $basic_machine in
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
@@ -257,11 +260,11 @@ case $basic_machine in
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
- | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
| strongarm \
- | tahoe | thumb | tic80 | tron \
+ | tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
| x86 | xscale | xstormy16 | xtensa \
@@ -296,7 +299,7 @@ case $basic_machine in
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* \
| bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
@@ -304,7 +307,7 @@ case $basic_machine in
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* \
+ | ip2k-* | iq2000-* \
| m32r-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | mcore-* \
@@ -319,6 +322,7 @@ case $basic_machine in
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
@@ -329,11 +333,13 @@ case $basic_machine in
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
- | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
- | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
| v850-* | v850e-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
@@ -371,6 +377,12 @@ case $basic_machine in
basic_machine=a29k-none
os=-bsd
;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
amdahl)
basic_machine=580-amdahl
os=-sysv
@@ -735,6 +747,10 @@ case $basic_machine in
basic_machine=or32-unknown
os=-coff
;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
os=-ose
@@ -766,18 +782,24 @@ case $basic_machine in
pentiumpro | p6 | 6x86 | athlon | athlon_*)
basic_machine=i686-pc
;;
- pentiumii | pentium2)
+ pentiumii | pentium2 | pentiumiii | pentium3)
basic_machine=i686-pc
;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
- pentiumii-* | pentium2-*)
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
pn)
basic_machine=pn-gould
;;
@@ -836,6 +858,10 @@ case $basic_machine in
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
sequent)
basic_machine=i386-sequent
;;
@@ -843,6 +869,9 @@ case $basic_machine in
basic_machine=sh-hitachi
os=-hms
;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
sparclite-wrs | simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
@@ -917,14 +946,18 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
- tic4x | c4x*)
- basic_machine=tic4x-unknown
- os=-coff
- ;;
tic54x | c54x*)
basic_machine=tic54x-unknown
os=-coff
;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
tx39)
basic_machine=mipstx39-unknown
;;
@@ -938,6 +971,10 @@ case $basic_machine in
tower | tower-32)
basic_machine=m68k-ncr
;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
udi29k)
basic_machine=a29k-amd
os=-udi
@@ -1027,7 +1064,7 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
- sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
+ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sh64)
@@ -1106,19 +1143,19 @@ case $os in
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -microbsd*)
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1142,6 +1179,9 @@ case $os in
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
-linux*)
os=-linux
;;
@@ -1154,6 +1194,9 @@ case $os in
-opened*)
os=-openedition
;;
+ -os400*)
+ os=-os400
+ ;;
-wince*)
os=-wince
;;
@@ -1175,6 +1218,9 @@ case $os in
-atheos*)
os=-atheos
;;
+ -syllable*)
+ os=-syllable
+ ;;
-386bsd)
os=-bsd
;;
@@ -1197,6 +1243,9 @@ case $os in
-sinix*)
os=-sysv4
;;
+ -tpf*)
+ os=-tpf
+ ;;
-triton*)
os=-sysv3
;;
@@ -1227,6 +1276,12 @@ case $os in
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
-none)
;;
*)
@@ -1258,6 +1313,9 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
@@ -1436,9 +1494,15 @@ case $basic_machine in
-mvs* | -opened*)
vendor=ibm
;;
+ -os400*)
+ vendor=ibm
+ ;;
-ptx*)
vendor=sequent
;;
+ -tpf*)
+ vendor=ibm
+ ;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
diff --git a/configure.in b/configure.in
index 23149915e4..d922bd20da 100644
--- a/configure.in
+++ b/configure.in
@@ -1,9 +1,9 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT()
-AC_PREREQ(2.50)
+AC_PREREQ(2.58)
-AC_DEFUN(RUBY_MINGW32,
+AC_DEFUN([RUBY_MINGW32],
[case "$host_os" in
cygwin*)
AC_CACHE_CHECK(for mingw32 environment, rb_cv_mingw32,
@@ -17,7 +17,7 @@ test "$rb_cv_mingw32" = yes && target_os="mingw32"
;;
esac])
-AC_DEFUN(RUBY_CPPOUTFILE,
+AC_DEFUN([RUBY_CPPOUTFILE],
[AC_CACHE_CHECK(whether ${CPP} accepts -o, rb_cv_cppoutfile,
[cppflags=$CPPFLAGS
CPPFLAGS='-o conftest.i'
@@ -33,7 +33,7 @@ elif test -n "$rb_cv_cppoutfile"; then
fi
AC_SUBST(CPPOUTFILE)])
-AC_DEFUN(RUBY_PROG_GNU_LD,
+AC_DEFUN([RUBY_PROG_GNU_LD],
[AC_CACHE_CHECK(whether the linker is GNU ld, rb_cv_prog_gnu_ld,
[if `$CC $CFLAGS $CPPFLAGS $LDFLAGS --print-prog-name=ld 2>&1` -v 2>&1 | grep "GNU ld" > /dev/null; then
rb_cv_prog_gnu_ld=yes
@@ -44,10 +44,20 @@ fi
GNU_LD=$rb_cv_prog_gnu_ld
AC_SUBST(GNU_LD)])
+unset GREP_OPTIONS
rb_version=`grep RUBY_VERSION $srcdir/version.h`
MAJOR=`expr "$rb_version" : '#define RUBY_VERSION "\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*"'`
MINOR=`expr "$rb_version" : '#define RUBY_VERSION "[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*"'`
TEENY=`expr "$rb_version" : '#define RUBY_VERSION "[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\)"'`
+if test "$MAJOR" = ""; then
+ AC_MSG_ERROR(could not determine MAJOR number from version.h)
+fi
+if test "$MINOR" = ""; then
+ AC_MSG_ERROR(could not determine MINOR number from version.h)
+fi
+if test "$TEENY" = ""; then
+ AC_MSG_ERROR(could not determine TEENY number from version.h)
+fi
AC_SUBST(MAJOR)
AC_SUBST(MINOR)
AC_SUBST(TEENY)
@@ -72,7 +82,10 @@ if test "$program_prefix" = NONE; then
program_prefix=
fi
AC_CANONICAL_TARGET
+target_os=`echo $target_os | sed 's/linux-gnu$/linux/;s/linux-gnu/linux-/'`
+ac_install_sh='' # unusable for extension libraries.
+ifelse(currently,disabled, [
dnl checks for fat-binary
AC_ARG_ENABLE(fat-binary,
[ --enable-fat-binary=ARCHS
@@ -126,6 +139,7 @@ if test "$fat_binary" != no; then
done
AC_DEFINE(NEXT_FAT_BINARY)
fi
+], [fat_binary=no])
case $target_cpu in
i?86) frame_address=yes;;
@@ -147,6 +161,11 @@ if test x"${build}" != x"${host}"; then
fi
AC_PROG_CC
AC_PROG_GCC_TRADITIONAL
+if test "$GCC" = yes; then
+ linker_flag=-Wl,
+else
+ linker_flag=
+fi
RUBY_PROG_GNU_LD
RUBY_CPPOUTFILE
@@ -167,12 +186,38 @@ if test -z "$AR"; then
AC_CHECK_PROGS(AR, aal, ar)
fi
+AC_CHECK_TOOL(AS, as)
+ASFLAGS=$ASFLAGS
+AC_SUBST(ASFLAGS)
+
case "$target_os" in
cygwin*|mingw*)
AC_CHECK_TOOL(NM, nm)
AC_CHECK_TOOL(WINDRES, windres)
AC_CHECK_TOOL(DLLWRAP, dllwrap)
target_cpu=`echo $target_cpu | sed s/i.86/i386/`
+ case "$target_os" in
+ mingw*)
+ test "$rb_cv_msvcrt" = "" && unset rb_cv_msvcrt
+ AC_CHECK_TOOL(OBJDUMP, objdump)
+ AC_CACHE_CHECK(for mingw32 runtime DLL, rb_cv_msvcrt, [
+ AC_TRY_LINK([#include <stdio.h>],
+ [FILE* volatile f = stdin; return 0;],
+ [rb_cv_msvcrt=`$OBJDUMP -p conftest$ac_exeext |
+ tr A-Z a-z |
+ sed -n '/^[[ ]]*dll name: \(msvc.*\)\.dll$/{s//\1/p;q;}'`],
+ [rb_cv_msvcrt=msvcrt])
+ test "$rb_cv_msvcrt" = "" && rb_cv_msvcrt=msvcrt])
+ AC_ARG_WITH(winsock2,
+ [ --with-winsock2 link winsock2 (MinGW only)], [
+ case $withval in
+ yes) with_winsock2=yes;;
+ *) with_winsock2=no;;
+ esac], [with_winsock2=no])
+ if test "$with_winsock2" = yes; then
+ AC_DEFINE(USE_WINSOCK2)
+ fi
+ esac
: ${enable_shared=yes}
;;
aix*)
@@ -186,13 +231,27 @@ esac
AC_PROG_LN_S
AC_PROG_MAKE_SET
+AC_PROG_INSTALL
# checks for UNIX variants that set C preprocessor variables
AC_AIX
AC_MINIX
+AC_SUBST(RM, ['rm -f'])
+AC_SUBST(CP, ['cp'])
+if $as_mkdir_p; then
+ AC_SUBST(MAKEDIRS, ['mkdir -p'])
+else
+ AC_SUBST(MAKEDIRS, ['install -d'])
+fi
+
dnl check for large file stuff
+mv confdefs.h confdefs1.h
+: > confdefs.h
AC_SYS_LARGEFILE
+mv confdefs.h largefile.h
+mv confdefs1.h confdefs.h
+cat largefile.h >> confdefs.h
AC_CHECK_TYPES([long long, off_t])
@@ -205,6 +264,12 @@ AC_CHECK_SIZEOF(off_t, 0)
AC_CHECK_SIZEOF(void*, 4)
AC_CHECK_SIZEOF(float, 4)
AC_CHECK_SIZEOF(double, 8)
+AC_CHECK_SIZEOF(time_t, 0)
+
+for id in pid_t gid_t uid_t; do
+ AC_CHECK_TYPE($id, [typ=$id], [typ=int])
+ AC_DEFINE_UNQUOTED(rb_$id, $typ)
+done
AC_CACHE_CHECK(for prototypes, rb_cv_have_prototypes,
[AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);],
@@ -243,16 +308,53 @@ if test "$rb_cv_stdarg" = yes; then
AC_DEFINE(HAVE_STDARG_PROTOTYPES)
fi
-AC_CACHE_CHECK([for noreturn], rb_cv_noreturn,
-[rb_cv_noreturn=no
-for mac in "x __attribute__ ((noreturn))" "__declspec(noreturn) x" x; do
+AC_DEFUN([RUBY_FUNC_ATTRIBUTE], [dnl
+m4_ifval([$2], dnl
+ [AS_VAR_PUSHDEF([attrib],[$2])], dnl
+ [AS_VAR_PUSHDEF([attrib],[FUNC_]AS_TR_CPP($1))] dnl
+)dnl
+m4_ifval([$3], dnl
+ [AS_VAR_PUSHDEF([rbcv],[$3])], dnl
+ [AS_VAR_PUSHDEF([rbcv],[rb_cv_func_][$1])]dnl
+)dnl
+AC_CACHE_CHECK(for [$1] function attribute, rbcv,
+[rbcv=x
+if test "${ac_c_werror_flag+set}"; then
+ rb_c_werror_flag="$ac_c_werror_flag"
+else
+ unset rb_c_werror_flag
+fi
+ac_c_werror_flag=yes
+for mac in "__attribute__ (($1)) x" "x __attribute__ (($1))" "__declspec($1) x" x; do
AC_TRY_COMPILE(
- [#define NORETURN(x) $mac
-NORETURN(void exit(int x));],
- [],
- [rb_cv_noreturn="$mac"; break])
+ [#define ]attrib[(x) $mac
+ ]attrib[(void conftest_attribute_check(void));], [],
+ [rbcv="$mac"; break])
+done
+if test "${rb_c_werror_flag+set}"; then
+ ac_c_werror_flag="$rb_c_werror_flag"
+else
+ unset ac_c_werror_flag
+fi
+])
+AC_DEFINE_UNQUOTED(attrib[(x)], $rbcv)
+AS_VAR_POPDEF([attrib])
+AS_VAR_POPDEF([rbcv])
+])
+
+RUBY_FUNC_ATTRIBUTE(noreturn, NORETURN)
+RUBY_FUNC_ATTRIBUTE(noinline, NOINLINE)
+
+AC_CACHE_CHECK([for RUBY_EXTERN], rb_cv_ruby_extern,
+[rb_cv_ruby_extern=no
+for mac in "__attribute__((dllimport))" "__declspec(dllimport)"; do
+ AC_TRY_COMPILE(
+ [extern $mac void conftest(void);],
+ [rb_cv_ruby_extern="extern $mac"; break])
done])
-AC_DEFINE_UNQUOTED([NORETURN(x)], $rb_cv_noreturn)
+test "x$rb_cv_ruby_extern" = xno || AC_DEFINE_UNQUOTED(RUBY_EXTERN, $rb_cv_ruby_extern)
+
+XCFLAGS="$XCFLAGS -DRUBY_EXPORT"
dnl Check whether we need to define sys_nerr locally
AC_CHECK_DECLS([sys_nerr], [], [], [$ac_includes_default
@@ -270,22 +372,45 @@ AC_ARG_ENABLE(pthread,
[ --enable-pthread use pthread library.],
[enable_pthread=$enableval], [enable_pthread=no])
+AC_ARG_ENABLE(fastthread,
+ [ --disable-fastthread do not use the fastthread mutex], [
+ : handled by ext/thread/extconf.rb
+ ])
+
dnl Checks for libraries.
case "$target_os" in
nextstep*) ;;
openstep*) ;;
rhapsody*) ;;
-darwin*) LIBS="-lobjc $LIBS";;
+darwin*) LIBS="-lobjc $LIBS"
+ CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE"
+ AC_TRY_CPP([#include <AvailabilityMacros.h>
+ #if MAC_OS_X_VERSION_MAX_ALLOWED <= 1040
+ #error pre OS X 10.4
+ [!<===== pre OS X 10.4 =====>]
+ #endif
+ ],
+ [
+ test "x$target_cpu" = xpowerpc && ac_cv_header_ucontext_h=no
+ ],
+ [
+ AC_DEFINE(BROKEN_SETREUID, 1)
+ AC_DEFINE(BROKEN_SETREGID, 1)
+ ])
+ ;;
hpux*) LIBS="-lm $LIBS"
ac_cv_c_inline=no;;
-human*) ac_cv_func_getpgrp_void=yes;;
-beos*) ;;
-cygwin*) rb_cv_have_daylight=no
- ac_cv_var_tzname=no
- ac_cv_func__setjmp=no
+human*) ac_cv_func_getpgrp_void=yes
ac_cv_func_setitimer=no
;;
-mingw*) LIBS="-lwsock32 $LIBS"
+beos*) ac_cv_func_link=no;;
+cygwin*) ;;
+mingw*) if test "$with_winsock2" = yes; then
+ LIBS="-lws2_32 $LIBS"
+ else
+ LIBS="-lwsock32 $LIBS"
+ fi
+ LIBS="-lshell32 $LIBS"
ac_cv_header_a_out_h=no
ac_cv_header_pwd_h=no
ac_cv_header_utime_h=no
@@ -293,6 +418,7 @@ mingw*) LIBS="-lwsock32 $LIBS"
ac_cv_header_sys_param_h=no
ac_cv_header_sys_resource_h=no
ac_cv_header_sys_select_h=no
+ ac_cv_header_sys_time_h=no
ac_cv_header_sys_times_h=no
ac_cv_func_times=yes
ac_cv_func_waitpid=yes
@@ -300,13 +426,32 @@ mingw*) LIBS="-lwsock32 $LIBS"
ac_cv_func_vsnprintf=yes
ac_cv_func_seekdir=yes
ac_cv_func_telldir=yes
+ ac_cv_func_isinf=yes
+ ac_cv_func_isnan=yes
+ ac_cv_func_finite=yes
+ ac_cv_func_link=yes
ac_cv_lib_crypt_crypt=no
+ ac_cv_func_getpgrp_void=no
+ ac_cv_func_setpgrp_void=yes
+ ac_cv_func_memcmp_working=yes
+ ac_cv_lib_dl_dlopen=no
+ rb_cv_binary_elf=no
+ rb_cv_negative_time_t=no
enable_pthread=no
+ ac_cv_func_fcntl=yes
;;
os2-emx*) LIBS="-lm $LIBS"
ac_cv_lib_dir_opendir=no;;
msdosdjgpp*) LIBS="-lm $LIBS"
- ac_cv_func_getpgrp_void=yes;;
+ ac_cv_func_getpgrp_void=yes
+ ac_cv_func_setitimer=no
+ ac_cv_sizeof_rlim_t=4
+ ac_cv_func_setrlimit=no
+ ;;
+bsdi*) LIBS="-lm $LIBS"
+ AC_DEFINE(BROKEN_SETREUID, 1)
+ AC_DEFINE(BROKEN_SETREGID, 1)
+ ac_cv_sizeof_rlim_t=8;;
freebsd*) LIBS="-lm $LIBS"
AC_CACHE_CHECK([whether -lxpg4 has to be linked],
rb_cv_lib_xpg4_needed,
@@ -323,7 +468,7 @@ freebsd*) LIBS="-lm $LIBS"
if test "$rb_cv_lib_xpg4_needed" = yes; then
AC_CHECK_LIB(xpg4, setlocale)
fi
- if test "$with_libc_r" = yes -a "$enable_pthread" = 'yes'; then
+ if test "$with_libc_r" = yes; then
AC_CACHE_CHECK([whether libc_r is supplementary to libc],
rb_cv_supplementary_lib_c_r,
[AC_TRY_CPP([
@@ -336,19 +481,27 @@ freebsd*) LIBS="-lm $LIBS"
rb_cv_supplementary_lib_c_r=yes,
rb_cv_supplementary_lib_c_r=yes)])
if test "$rb_cv_supplementary_lib_c_r" = yes; then
- MAINLIBS="-lc_r $MAINLIBS"
- else
- AC_DEFINE(HAVE_LIBPTHREAD)
- MAINLIBS="-pthread $MAINLIBS"
- CFLAGS="-D_THREAD_SAFE -D_REENTRANT $CFLAGS"
+ MAINLIBS="-lc_r $MAINLIBS"
fi
fi
;;
+dragonfly*) LIBS="-lm $LIBS"
+ ;;
+bow) ac_cv_func_setitimer=no
+ ;;
+superux*) ac_cv_func_setitimer=no
+ ;;
+solaris*2.1*) if test -z "$GCC"; then
+ ac_cv_func_isinf=yes
+ fi
+ LIBS="-lm $LIBS"
+ ;;
*) LIBS="-lm $LIBS";;
esac
AC_CHECK_LIB(crypt, crypt)
AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV
AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX
+AC_CHECK_LIB(rt, clock_gettime) # GNU/Linux
case "$target_cpu" in
alpha*) case "$target_os"::"$GCC" in
@@ -361,13 +514,30 @@ dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS(stdlib.h string.h unistd.h limits.h sys/file.h sys/ioctl.h\
+AC_CHECK_HEADERS(stdlib.h string.h unistd.h limits.h sys/file.h sys/ioctl.h sys/syscall.h\
fcntl.h sys/fcntl.h sys/select.h sys/time.h sys/times.h sys/param.h\
syscall.h pwd.h grp.h a.out.h utime.h memory.h direct.h sys/resource.h \
- sys/mkdev.h sys/utime.h netinet/in_systm.h float.h pthread.h)
+ sys/mkdev.h sys/utime.h netinet/in_systm.h float.h ieeefp.h pthread.h \
+ ucontext.h intrinsics.h)
+
+dnl Check additional types.
+AC_CHECK_SIZEOF(rlim_t, 0, [
+ #ifdef HAVE_SYS_TYPES_H
+ # include <sys/types.h>
+ #endif
+ #ifdef HAVE_SYS_TIME_H
+ # include <sys/time.h>
+ #endif
+ #ifdef HAVE_SYS_RESOURCE_H
+ # include <sys/resource.h>
+ #endif
+ #ifdef HAVE_UNISTD_H
+ # include <unistd.h>
+ #endif
+ #include <stdio.h>
+])
dnl Checks for typedefs, structures, and compiler characteristics.
-AC_TYPE_UID_T
AC_TYPE_SIZE_T
AC_STRUCT_ST_BLKSIZE
AC_STRUCT_ST_BLOCKS
@@ -376,21 +546,104 @@ AC_STRUCT_ST_RDEV
dnl Checks for library functions.
AC_TYPE_GETGROUPS
AC_TYPE_SIGNAL
-AC_FUNC_ALLOCA
+case "${target_cpu}-${target_os}" in
+powerpc-darwin*)
+ AC_LIBSOURCES(alloca.c)
+ AC_SUBST([ALLOCA], [\${LIBOBJDIR}alloca.${ac_objext}])
+ AC_DEFINE(C_ALLOCA)
+ AC_DEFINE_UNQUOTED(alloca, alloca)
+ ;;
+*)
+ AC_FUNC_ALLOCA
+ ;;
+esac
AC_FUNC_MEMCMP
AC_FUNC_FSEEKO
AC_CHECK_FUNCS(ftello)
-AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strncasecmp strerror strftime\
+
+# http://sources.redhat.com/ml/libc-hacker/2005-08/msg00008.html
+# Debian GNU/Linux Etch's libc6.1 2.3.6.ds1-13etch5 has this problem.
+# Debian GNU/Linux Lenny's libc6.1 2.7-10 has no problem.
+AC_CACHE_CHECK(for broken erfc of glibc-2.3.6 on IA64, rb_cv_broken_glibc_ia64_erfc,
+ [AC_TRY_RUN([
+#include <math.h>
+int
+main()
+{
+ erfc(10000.0);
+ return 0;
+}
+],
+ rb_cv_broken_glibc_ia64_erfc=no,
+ rb_cv_broken_glibc_ia64_erfc=yes,
+ rb_cv_broken_glibc_ia64_erfc=no)])
+case $rb_cv_broken_glibc_ia64_erfc in
+ yes) ac_cv_func_erf=no;;
+esac
+
+AC_REPLACE_FUNCS(dup2 memmove strcasecmp strncasecmp strerror strftime\
strchr strstr strtoul crypt flock vsnprintf\
- isinf isnan finite hypot acosh erf)
-AC_CHECK_FUNCS(fmod killpg wait4 waitpid syscall chroot fsync getcwd\
- truncate chsize times utimes fcntl lockf lstat symlink readlink\
- setitimer setruid seteuid setreuid setresuid setproctitle\
- setrgid setegid setregid setresgid issetugid pause lchown lchmod\
- getpgrp setpgrp getpgid setpgid initgroups getgroups setgroups\
- getpriority getrlimit dlopen sigprocmask sigaction _setjmp\
- setsid telldir seekdir fchmod mktime timegm cosh sinh tanh\
- setuid setgid)
+ isnan finite isinf hypot acosh erf)
+AC_CHECK_FUNCS(fmod killpg wait4 waitpid syscall chroot fsync getcwd eaccess\
+ truncate ftruncate chsize times utimes fcntl lockf lstat symlink link\
+ readlink setitimer setruid seteuid setreuid setresuid\
+ setproctitle setrgid setegid setregid setresgid issetugid pause\
+ lchown lchmod getpgrp setpgrp getpgid setpgid initgroups\
+ getgroups setgroups getpriority getrlimit setrlimit sysconf\
+ group_member dlopen sigprocmask\
+ sigaction sigsetjmp _setjmp _longjmp setsid telldir seekdir fchmod\
+ mktime timegm gettimeofday\
+ cosh sinh tanh round setuid setgid setenv unsetenv)
+
+AC_CACHE_CHECK(for __builtin_setjmp, ac_cv_func___builtin_setjmp,
+[AC_TRY_LINK([@%:@include <setjmp.h>
+ jmp_buf jb; void t(v) int v; {__builtin_longjmp(jb, v);}],
+ [__builtin_setjmp(jb);],
+ [ac_cv_func___builtin_setjmp=yes],
+ [ac_cv_func___builtin_setjmp=no])
+])
+
+test x$ac_cv_func__longjmp = xno && ac_cv_func__setjmp=no
+
+AC_MSG_CHECKING(for setjmp type)
+AC_ARG_WITH(setjmp-type,
+ [ --with-setjmp-type select setjmp type], [
+ case $withval in
+ __builtin_setjmp) setjmp_prefix=__builtin_;;
+ _setjmp) setjmp_prefix=_;;
+ sigsetjmp) setjmp_prefix=sig;;
+ setjmp) setjmp_prefix=;;
+ '') unset setjmp_prefix;;
+ *) AC_MSG_ERROR(invalid setjmp type: $withval);;
+ esac], [unset setjmp_prefix])
+if test ${setjmp_prefix+set}; then
+ if test "${setjmp_prefix}" && eval test '$ac_cv_func_'${setjmp_prefix}setjmp = no; then
+ AC_MSG_ERROR(${setjmp_prefix}setjmp is not available)
+ fi
+elif test "$ac_cv_func___builtin_setjmp" = yes; then
+ setjmp_prefix=__builtin_
+elif test "$ac_cv_func__setjmp" = yes; then
+ setjmp_prefix=_
+elif test "$ac_cv_func_sigsetjmp" = yes; then
+ case $target_os in
+ solaris*|cygwin*)
+ setjmp_prefix=;;
+ *)
+ setjmp_prefix=sig;;
+ esac
+else
+ setjmp_prefix=
+fi
+if test x$setjmp_prefix = xsig; then
+ setjmp_sigmask=yes
+else
+ unset setjmp_sigmask
+fi
+AC_MSG_RESULT(${setjmp_prefix}setjmp)
+AC_DEFINE_UNQUOTED([RUBY_SETJMP(env)], [${setjmp_prefix}setjmp(env${setjmp_sigmask+,0})])
+AC_DEFINE_UNQUOTED([RUBY_LONGJMP(env,val)], [${setjmp_prefix}longjmp(env,val)])
+AC_DEFINE_UNQUOTED(RUBY_JMP_BUF, ${setjmp_sigmask+${setjmp_prefix}}jmp_buf)
+
AC_ARG_ENABLE(setreuid,
[ --enable-setreuid use setreuid()/setregid() according to need even if obsolete.],
[use_setreuid=$enableval])
@@ -416,6 +669,50 @@ AC_CACHE_CHECK(for external int daylight, rb_cv_have_daylight,
if test "$rb_cv_have_daylight" = yes; then
AC_DEFINE(HAVE_DAYLIGHT)
fi
+AC_DEFUN([RUBY_CHECK_VARTYPE], [dnl
+AC_CACHE_CHECK([for external $1], rb_cv_var_$1,
+ [rb_cv_var_$1=no
+ AC_TRY_COMPILE([
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 1
+#endif
+$2
+;
+const volatile void *volatile t;],
+ [t = &(&$1)[0];],
+ [for t in $3; do
+ AC_TRY_COMPILE([
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 1
+#endif
+$2
+;
+extern $t $1;
+const volatile void *volatile t;],
+ [t = &(&$1)[0];],
+ [rb_cv_var_$1=$t; break])
+ done])])
+if test "[$rb_cv_var_]$1" != no; then
+ AC_DEFINE([HAVE_VAR_]m4_toupper($1))
+ AC_DEFINE_UNQUOTED([TYPEOF_VAR_]m4_toupper($1), $rb_cv_var_$1)
+fi])
+RUBY_CHECK_VARTYPE(timezone, [@%:@include <time.h>], [long int])
+RUBY_CHECK_VARTYPE(altzone, [@%:@include <time.h>], [long int])
+if test "$rb_cv_var_timezone" = no; then
+ AC_CHECK_FUNCS(timezone)
+ if test "$ac_cv_func_timezone" = yes; then
+ AC_CACHE_CHECK([whether timezone requires zero arguments], rb_cv_func_timezone_void,
+ [AC_TRY_COMPILE([@%:@include <time.h>],
+ [(void)timezone(0, 0);],
+ [rb_cv_func_timezone_void=no],
+ [rb_cv_func_timezone_void=yes])]
+ )
+ if test $rb_cv_func_timezone_void = yes; then
+ AC_DEFINE(TIMEZONE_VOID)
+ fi
+ fi
+fi
+
AC_CACHE_CHECK(for negative time_t for gmtime(3), rb_cv_negative_time_t,
[AC_TRY_RUN([
#include <time.h>
@@ -457,6 +754,7 @@ fi
if test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = yes; then
AC_DEFINE(POSIX_SIGNAL)
else
+ AC_CHECK_FUNCS(sigsetmask)
AC_CACHE_CHECK(for BSD signal semantics, rb_cv_bsd_signal,
[AC_TRY_RUN([
#include <stdio.h>
@@ -479,7 +777,7 @@ main()
],
rb_cv_bsd_signal=yes,
rb_cv_bsd_signal=no,
- rb_cv_bsd_signal=no)])
+ rb_cv_bsd_signal=$ac_cv_func_sigsetmask)])
if test "$rb_cv_bsd_signal" = yes; then
AC_DEFINE(BSD_SIGNAL)
fi
@@ -494,6 +792,21 @@ AC_C_CHAR_UNSIGNED
AC_C_INLINE
AC_C_VOLATILE
+if test x"$target_cpu" = xia64; then
+ AC_LIBOBJ([ia64])
+ AC_CACHE_CHECK(for __libc_ia64_register_backing_store_base,
+ rb_cv___libc_ia64_register_backing_store_base,
+ [rb_cv___libc_ia64_register_backing_store_base=no
+ AC_TRY_LINK(
+ [extern unsigned long __libc_ia64_register_backing_store_base;],
+ [unsigned long p = __libc_ia64_register_backing_store_base;
+ printf("%ld\n", p);],
+ [rb_cv___libc_ia64_register_backing_store_base=yes])])
+ if test $rb_cv___libc_ia64_register_backing_store_base = yes; then
+ AC_DEFINE(HAVE___LIBC_IA64_REGISTER_BACKING_STORE_BASE)
+ fi
+fi
+
AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
[AC_TRY_RUN([
int
@@ -578,7 +891,7 @@ else
fi
fi
-AC_DEFUN(RUBY_CHECK_IO_NEED,
+AC_DEFUN([RUBY_CHECK_IO_NEED],
[AC_CACHE_CHECK(whether need to [$1], [$2],
[AC_TRY_RUN([
#include <stdio.h>
@@ -636,10 +949,10 @@ RUBY_CHECK_IO_NEED(seek between R/W, rb_cv_need_io_seek_between_rw, yes)
if test "$rb_cv_need_io_seek_between_rw" = yes; then
AC_DEFINE(NEED_IO_SEEK_BETWEEN_RW, 1)
fi
-RUBY_CHECK_IO_NEED(flush before seek, rb_cv_need_io_flush_before_seek, no)
-if test "$rb_cv_need_io_flush_before_seek" = yes; then
- AC_DEFINE(NEED_IO_FLUSH_BEFORE_SEEK, 1)
-fi
+dnl RUBY_CHECK_IO_NEED(flush before seek, rb_cv_need_io_flush_before_seek, no)
+dnl if test "$rb_cv_need_io_flush_before_seek" = yes; then
+dnl AC_DEFINE(NEED_IO_FLUSH_BEFORE_SEEK, 1)
+dnl fi
AC_CACHE_CHECK([whether st_ino is huge], rb_cv_huge_st_ino,
[AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([
@@ -653,8 +966,25 @@ if test $rb_cv_huge_st_ino = yes; then
AC_DEFINE(HUGE_ST_INO)
fi
+if test "$ac_cv_func_sysconf" = yes; then
+ AC_DEFUN([RUBY_CHECK_SYSCONF], [dnl
+ AC_CACHE_CHECK([whether _SC_$1 is supported], rb_cv_have_sc_[]m4_tolower($1),
+ [AC_TRY_COMPILE([#include <unistd.h>
+ ],
+ [_SC_$1 >= 0],
+ rb_cv_have_sc_[]m4_tolower($1)=yes,
+ rb_cv_have_sc_[]m4_tolower($1)=no)
+ ])
+ if test "$rb_cv_have_sc_[]m4_tolower($1)" = yes; then
+ AC_DEFINE(HAVE__SC_$1)
+ fi
+ ])
+ RUBY_CHECK_SYSCONF(CLK_TCK)
+fi
+
case "$target_cpu" in
-m68*|i?86|sparc) rb_cv_stack_grow_dir=-1;;
+m68*|i?86|ia64|sparc*|alpha*) rb_cv_stack_grow_dir=-1;;
+hppa*) rb_cv_stack_grow_dir=+1;;
esac
AC_CACHE_CHECK(stack growing direction, rb_cv_stack_grow_dir,
[AC_TRY_RUN([
@@ -677,56 +1007,41 @@ int main()
], rb_cv_stack_grow_dir=-1, rb_cv_stack_grow_dir=+1, rb_cv_stack_grow_dir=0)])
AC_DEFINE_UNQUOTED(STACK_GROW_DIRECTION, $rb_cv_stack_grow_dir)
-if test "$enable_pthread" = "yes"; then
- AC_CHECK_LIB(pthread, pthread_mutex_init,
- rb_with_pthread=yes, rb_with_pthread=no)
- if test "$rb_with_pthread" = "no"; then
- AC_CHECK_LIB(pthread, __pthread_mutex_init,
- rb_with_pthread=yes, rb_with_pthread=no)
- fi
- if test "$rb_with_pthread" = "yes"; then
- LIBS="-lpthread $LIBS"
- AC_DEFINE(_REENTRANT)
- AC_DEFINE(_THREAD_SAFE)
- AC_DEFINE(HAVE_LIBPTHREAD)
- else
- AC_CHECK_LIB(pthreads, pthread_mutex_init,
- rb_with_pthread=yes, rb_with_pthread=no)
- if test "$rb_with_pthread" = "yes"; then
- LIBS="-lpthreads $LIBS"
- AC_DEFINE(_REENTRANT)
- AC_DEFINE(_THREAD_SAFE)
- AC_DEFINE(HAVE_LIBPTHREAD)
- else
- AC_CHECK_LIB(c, pthread_mutex_init,
- rb_with_pthread=yes, rb_with_pthread=no)
- if test "$rb_with_pthread" = "yes"; then
- AC_DEFINE(_REENTRANT)
- AC_DEFINE(_THREAD_SAFE)
- AC_DEFINE(HAVE_LIBPTHREAD)
- else
- AC_CHECK_LIB(c_r, pthread_mutex_init,
- rb_with_pthread=yes, rb_with_pthread=no)
- if test "$rb_with_pthread" = "yes"; then
- if test "$with_libc_r" = "yes"; then
- if test "$rb_cv_supplementary_lib_c_r" = "yes"; then
- AC_DEFINE(_REENTRANT)
- AC_DEFINE(_THREAD_SAFE)
- AC_DEFINE(HAVE_LIBPTHREAD)
- MAINLIBS="-pthread $MAINLIBS"
- fi
- else
- MAINLIBS="-pthread $MAINLIBS"
- AC_DEFINE(_REENTRANT)
- AC_DEFINE(_THREAD_SAFE)
- AC_DEFINE(HAVE_LIBPTHREAD)
- fi
- else
- AC_MSG_WARN("Don't know how to find pthread library on your system -- thread support disabled")
- fi
- fi
- fi
- fi
+if test x"$enable_pthread" = xyes; then
+ for pthread_lib in pthread pthreads c c_r; do
+ AC_CHECK_LIB($pthread_lib, pthread_kill,
+ rb_with_pthread=yes, rb_with_pthread=no)
+ if test "$rb_with_pthread" = "yes"; then break; fi
+ done
+ if test x"$rb_with_pthread" = xyes; then
+ AC_DEFINE(_REENTRANT)
+ AC_DEFINE(_THREAD_SAFE)
+ AC_DEFINE(HAVE_LIBPTHREAD)
+ case $pthread_lib in
+ c)
+ ;;
+ c_r)
+ MAINLIBS="-pthread $MAINLIBS"
+ ;;
+ *)
+ LIBS="-l$pthread_lib $LIBS"
+ ;;
+ esac
+ else
+ AC_MSG_WARN("Don't know how to find pthread library on your system -- thread support disabled")
+ fi
+ AC_CHECK_FUNCS(nanosleep)
+ if test x"$ac_cv_func_nanosleep" = xno; then
+ AC_CHECK_LIB(rt, nanosleep)
+ if test x"$ac_cv_lib_rt_nanosleep" = xyes; then
+ AC_DEFINE(HAVE_NANOSLEEP)
+ fi
+ fi
+fi
+if test x"$ac_cv_header_ucontext_h" = xyes; then
+ if test x"$rb_with_pthread" = xyes; then
+ AC_CHECK_FUNCS(getcontext setcontext)
+ fi
fi
dnl default value for $KANJI
@@ -778,21 +1093,12 @@ if test "$rb_cv_binary_elf" = yes; then
fi
case "$target_os" in
-linux*)
+linux* | gnu* | k*bsd*-gnu | bsdi*)
if test "$rb_cv_binary_elf" = no; then
with_dln_a_out=yes
- target_os=${target_os}-a_out
else
LDFLAGS="$LDFLAGS -rdynamic"
fi;;
-netbsd*|openbsd*)
- if [[ "`$CC -dM -E - </dev/null | grep __ELF__`" != "" ]]
- then
- netbsd_elf=yes
- else
- netbsd_elf=no
- fi
- ;;
esac
LIBEXT=a
@@ -819,13 +1125,7 @@ if test "$with_dln_a_out" != yes; then
openstep*) CCDLFLAGS="$CCDLFLAGS -fno-common";;
rhapsody*) CCDLFLAGS="$CCDLFLAGS -fno-common";;
darwin*) CCDLFLAGS="$CCDLFLAGS -fno-common";;
- human*) ;;
- bsdi*) ;;
- beos*) ;;
- cygwin*) ;;
- mingw*) ;;
- aix*) ;;
- netbsd*) CCDLFLAGS="$CCDLFLAGS -fPIC";;
+ human*|bsdi*|beos*|cygwin*|mingw*|aix*|interix*) ;;
*) CCDLFLAGS="$CCDLFLAGS -fPIC";;
esac
else
@@ -838,16 +1138,28 @@ if test "$with_dln_a_out" != yes; then
esac
fi
+
+ AC_ARG_ENABLE(rpath,
+ [ --disable-rpath embed run path into extension libraries.],
+ [enable_rpath=$enableval], [enable_rpath="$rb_cv_binary_elf"])
+ if test "$enable_rpath" = yes; then
+ LIBPATHFLAG=" -L%1\$-s"
+ RPATHFLAG=" ${linker_flag}-R%1\$-s"
+ fi
+
case "$target_os" in
hpux*) DLDFLAGS="$DLDFLAGS -E"
: ${LDSHARED='ld -b'}
XLDFLAGS="$XLDFLAGS -Wl,-E"
+ : ${LIBPATHENV=SHLIB_PATH}
+ if test "$rb_cv_prog_gnu_ld" = no; then
+ RPATHFLAG=' +b %1$-s'
+ fi
rb_cv_dlopen=yes;;
solaris*) if test "$GCC" = yes; then
- : ${LDSHARED='$(CC) -Wl,-G'}
+ : ${LDSHARED='$(CC) -shared'}
if test "$rb_cv_prog_gnu_ld" = yes; then
LDFLAGS="$LDFLAGS -Wl,-E"
- LDSHARED="$LDSHARED -shared"
fi
else
: ${LDSHARED='ld -G'}
@@ -865,12 +1177,21 @@ if test "$with_dln_a_out" != yes; then
rb_cv_dlopen=yes ;;
osf*) : ${LDSHARED="ld -shared -expect_unresolved \"*\""}
rb_cv_dlopen=yes ;;
- linux*) : ${LDSHARED="$CC -shared"}
+ bsdi3*) case "$CC" in
+ *shlicc*) : ${LDSHARED="$CC -r"}
+ rb_cv_dlopen=yes ;;
+ esac ;;
+ linux* | gnu* | k*bsd*-gnu | netbsd* | bsdi*)
+ : ${LDSHARED='${CC} -shared'}
+ if test "$rb_cv_binary_elf" = yes; then
+ LDFLAGS="$LDFLAGS -Wl,-export-dynamic"
+ fi
rb_cv_dlopen=yes ;;
- gnu*) : ${LDSHARED="$CC -shared"}
- rb_cv_dlopen=yes
- LDFLAGS="$LDFLAGS -rdynamic" ;;
- freebsd*) : ${LDSHARED="$CC -shared"}
+ interix*) : ${LDSHARED="$CC -shared"}
+ XLDFLAGS="$XLDFLAGS -Wl,-E"
+ LIBPATHFLAG=" -L%1\$-s"
+ rb_cv_dlopen=yes ;;
+ freebsd*|dragonfly*) : ${LDSHARED="$CC -shared"}
if test "$rb_cv_binary_elf" = yes; then
LDFLAGS="$LDFLAGS -rdynamic"
DLDFLAGS="$DLDFLAGS "'-Wl,-soname,$(.TARGET)'
@@ -878,44 +1199,37 @@ if test "$with_dln_a_out" != yes; then
test "$GCC" = yes && test "$rb_cv_prog_gnu_ld" = yes || LDSHARED="ld -Bshareable"
fi
rb_cv_dlopen=yes ;;
- netbsd*) : ${LDSHARED='${CC} -shared'}
- if test "$rb_cv_binary_elf" = yes; then
- LDFLAGS="$LDFLAGS -Wl,-export-dynamic"
- LIBPATHFLAG=' -L%1$-s'
- RPATHFLAG=' -Wl,-R%1$-s'
- fi
- rb_cv_dlopen=yes ;;
openbsd*) : ${LDSHARED="\$(CC) -shared ${CCDLFLAGS}"}
if test "$rb_cv_binary_elf" = yes; then
LDFLAGS="$LDFLAGS -Wl,-E"
fi
rb_cv_dlopen=yes ;;
- bsdi3*) case "$CC" in
- *shlicc*) : ${LDSHARED="$CC -r"}
- rb_cv_dlopen=yes ;;
- esac ;;
- bsdi*) : ${LDSHARED="ld -shared"}
- LDFLAGS="$LDFLAGS "'-rdynamic -Wl,-rpath,$(libdir)/ruby/$(MAJOR).$(MINOR)/i386-bsdi4.0'
- rb_cv_dlopen=yes ;;
nextstep*) : ${LDSHARED='cc -r -nostdlib'}
LDFLAGS="$LDFLAGS -u libsys_s"
rb_cv_dlopen=yes ;;
openstep*) : ${LDSHARED='cc -dynamic -bundle -undefined suppress'}
: ${LDFLAGS=""}
rb_cv_dlopen=yes ;;
- rhapsody*) : $LDSHARED='cc -dynamic -bundle -undefined suppress'}
+ rhapsody*) : ${LDSHARED='cc -dynamic -bundle -undefined suppress'}
: ${LDFLAGS=""}
rb_cv_dlopen=yes ;;
darwin*) : ${LDSHARED='cc -dynamic -bundle -undefined suppress -flat_namespace'}
: ${LDFLAGS=""}
+ : ${LIBPATHENV=DYLD_LIBRARY_PATH}
rb_cv_dlopen=yes ;;
- aix*) : ${LDSHARED='/usr/ccs/bin/ld'}
- XLDFLAGS="$XLDFLAGS -Wl,-bE:ruby.imp"
- DLDFLAGS="$DLDFLAGS "'-brtl -eInit_$(TARGET) -bI:$(topdir)/ruby.imp -bM:SRE -T512 -H512 -lc'
- LDFLAGS="$LDFLAGS -brtl"
- : ${ARCHFILE="ruby.imp"}
- rb_cv_dlopen=yes ;;
-
+ aix*) if test "$GCC" = yes; then
+ : ${LDSHARED='$(CC) -shared'}
+ else
+ : ${LDSHARED='$(CC)'}
+ fi
+ LDSHARED="$LDSHARED ${linker_flag}-G"
+ DLDFLAGS='-eInit_$(TARGET)'
+ XLDFLAGS="${linker_flag}-bE:ruby.imp ${linker_flag}-brtl"
+ : ${ARCHFILE="ruby.imp"}
+ TRY_LINK='$(CC) $(LDFLAGS) -oconftest $(INCFLAGS) -I$(hdrdir) $(CPPFLAGS)'
+ TRY_LINK="$TRY_LINK"' $(CFLAGS) $(src) $(LIBPATH) $(LOCAL_LIBS) $(LIBS)'
+ : ${LIBPATHENV=SHLIB_PATH}
+ rb_cv_dlopen=yes ;;
human*) : ${DLDFLAGS=''}
: ${LDSHARED=''}
: ${LDFLAGS=''}
@@ -931,6 +1245,7 @@ if test "$with_dln_a_out" != yes; then
DLDFLAGS="$DLDFLAGS -L/boot/develop/lib/x86 -lbe -lroot"
;;
esac
+ : ${LIBPATHENV=LIBRARY_PATH}
rb_cv_dlopen=yes ;;
nto-qnx*) DLDFLAGS="$DLDFLAGS -L/lib -L/usr/lib -L/usr/local/lib"
: ${LDSHARED='ld -Bshareable -x'}
@@ -938,7 +1253,8 @@ if test "$with_dln_a_out" != yes; then
rb_cv_dlopen=yes;;
cygwin*|mingw*) : ${LDSHARED="${CC} -shared -s"}
XLDFLAGS="$XLDFLAGS -Wl,--stack,0x02000000"
- DLDFLAGS="${DLDFLAGS} -Wl,--enable-auto-import,--export-all"
+ DLDFLAGS="${DLDFLAGS} -Wl,--enable-auto-image-base,--enable-auto-import,--export-all"
+ : ${LIBPATHENV=""}
rb_cv_dlopen=yes ;;
hiuxmpp) : ${LDSHARED='ld -r'} ;;
atheos*) : ${LDSHARED="$CC -shared"}
@@ -952,6 +1268,8 @@ fi
AC_SUBST(LINK_SO)
AC_SUBST(LIBPATHFLAG)
AC_SUBST(RPATHFLAG)
+AC_SUBST(LIBPATHENV, "${LIBPATHENV-LD_LIBRARY_PATH}")
+AC_SUBST(TRY_LINK)
dln_a_out_works=no
if test "$ac_cv_header_a_out_h" = yes; then
@@ -979,30 +1297,24 @@ if test "$dln_a_out_works" = yes; then
STATIC=-Bstatic
fi
DLEXT=so
- AC_DEFINE(DLEXT, ".so")
CCDLFLAGS=
else
case "$target_os" in
- hpux*) DLEXT=sl
- AC_DEFINE(DLEXT, ".sl");;
- nextstep*) DLEXT=bundle
- AC_DEFINE(DLEXT, ".bundle");;
- openstep*) DLEXT=bundle
- AC_DEFINE(DLEXT, ".bundle");;
- rhapsody*) DLEXT=bundle
- AC_DEFINE(DLEXT, ".bundle");;
- darwin*) DLEXT=bundle
- AC_DEFINE(DLEXT, ".bundle");;
- os2-emx*) DLEXT=dll
- AC_DEFINE(DLEXT, ".dll");;
- cygwin*|mingw*) DLEXT=so
- AC_DEFINE(DLEXT, ".so")
- DLEXT2=dll
- AC_DEFINE(DLEXT2, ".dll");;
- *) DLEXT=so
- AC_DEFINE(DLEXT, ".so");;
+ hpux*) DLEXT=sl;;
+ nextstep*|openstep*|rhapsody*|darwin*)
+ DLEXT=bundle;;
+ os2-emx*) DLEXT=dll;;
+ cygwin*|mingw*)
+ DLEXT=so DLEXT2=dll;;
+ *) DLEXT=so;;
esac
fi
+len=2 # .rb
+n=`expr "$DLEXT" : '.*'`; test "$n" -gt "$len" && len=$n
+n=`expr "$DLEXT2" : '.*'`; test "$n" -gt "$len" && len=$n
+AC_DEFINE_UNQUOTED(DLEXT_MAXLEN, `expr $len + 1`)
+test ".$DLEXT" = "." || AC_DEFINE_UNQUOTED(DLEXT, ".$DLEXT")
+test ".$DLEXT2" = "." || AC_DEFINE_UNQUOTED(DLEXT2, ".$DLEXT2")
AC_SUBST(STRIP)dnl
if test "$with_dln_a_out" = yes; then
@@ -1012,9 +1324,7 @@ else
fi
case "$target_os" in
- linux*)
- STRIP='strip -S -x';;
- gnu*)
+ linux* | gnu* | k*bsd*-gnu)
STRIP='strip -S -x';;
nextstep*)
STRIP='strip -A -n';;
@@ -1040,7 +1350,7 @@ case "$target_os" in
human*)
AC_CHECK_LIB(signal, _harderr)
AC_CHECK_LIB(hmem, hmemset)
- AC_CHECK_FUNCS(select gettimeofday)
+ AC_CHECK_FUNCS(select)
AC_CACHE_CHECK(whether PD libc _dtos18 fail to convert big number,
rb_cv_missing__dtos18,
[AC_TRY_RUN(
@@ -1111,12 +1421,17 @@ fi
if test x"$cross_compiling" = xyes; then
test x"$MINIRUBY" = x && MINIRUBY="${RUBY-ruby} -I`pwd` -rfake"
PREP=fake.rb
+ RUNRUBY='$(MINIRUBY) -I`cd $(srcdir)/lib; pwd`'
else
- MINIRUBY='./miniruby$(EXEEXT)'
- PREP=''
+ MINIRUBY='./miniruby$(EXEEXT) -I$(srcdir)/lib'
+ MINIRUBY="$MINIRUBY"' -I$(EXTOUT)/common -I./- -r$(srcdir)/ext/purelib.rb'
+ PREP='miniruby$(EXEEXT)'
+ RUNRUBY='$(MINIRUBY) $(srcdir)/runruby.rb --extout=$(EXTOUT)'
fi
AC_SUBST(MINIRUBY)
AC_SUBST(PREP)
+AC_SUBST(RUNRUBY)
+AC_SUBST(EXTOUT, [${EXTOUT-.ext}])
FIRSTMAKEFILE=""
LIBRUBY_A='lib$(RUBY_SO_NAME)-static.a'
@@ -1157,15 +1472,11 @@ if test "$enable_shared" = 'yes'; then
sunos4*)
LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_SO_NAME).so'
;;
- linux*)
+ linux* | gnu* | k*bsd*-gnu | atheos*)
LIBRUBY_DLDFLAGS='-Wl,-soname,lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR)'
LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_SO_NAME).so'
;;
- gnu*)
- LIBRUBY_DLDFLAGS='-Wl,-soname,lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR)'
- LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_SO_NAME).so'
- ;;
- freebsd*)
+ freebsd*|dragonfly*)
SOLIBS='$(LIBS)'
LIBRUBY_SO='lib$(RUBY_SO_NAME).so.$(MAJOR)$(MINOR)'
if test "$rb_cv_binary_elf" != "yes" ; then
@@ -1177,7 +1488,6 @@ if test "$enable_shared" = 'yes'; then
SOLIBS='$(LIBS)'
LIBRUBY_SO='lib$(RUBY_SO_NAME).so.$(MAJOR)$(MINOR).$(TEENY)'
LIBRUBY_DLDFLAGS='-Wl,-soname,lib$(RUBY_SO_NAME).so.$(MAJOR)$(MINOR)'
- LIBRUBYARG_SHARED='-Wl,-R -Wl,${libdir} -L${libdir} -L. -l$(RUBY_SO_NAME)'
if test "$rb_cv_binary_elf" = yes; then # ELF platforms
LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).so.$(MAJOR)$(MINOR) lib$(RUBY_SO_NAME).so'
else # a.out platforms
@@ -1189,6 +1499,12 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).'`expr ${MINOR} \* 10 + ${TEENY}`
;;
solaris*)
+ SOLIBS='$(LIBS)'
+ LIBRUBY_SO='lib$(RUBY_SO_NAME).so.$(MAJOR)'
+ LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR).$(TEENY) lib$(RUBY_SO_NAME).so'
+ if test "$GCC" = yes; then
+ LIBRUBY_DLDFLAGS="$DLDFLAGS "'-Wl,-h,$(@F)'
+ fi
XLDFLAGS="$XLDFLAGS "'-R${libdir}'
;;
hpux*)
@@ -1197,14 +1513,8 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).sl.$(MAJOR).$(MINOR) lib$(RUBY_SO_NAME).sl'
;;
aix*)
- if test "$GCC" = yes; then
- LIBRUBY_LDSHARED='$(CC) -shared'
- LIBRUBY_DLDFLAGS='-Wl,-bE:ruby.imp'
- else
- LIBRUBY_LDSHARED='/usr/ccs/bin/ld'
- LIBRUBY_DLDFLAGS='-bE:ruby.imp -bM:SRE -bnoentry'
- fi
- LIBRUBYARG_SHARED='-L${libdir} -Wl,lib$(RUBY_SO_NAME).so'
+ LIBRUBY_DLDFLAGS="${linker_flag}-bnoentry $XLDFLAGS"
+ LIBRUBYARG_SHARED='-L${libdir} -l${RUBY_SO_NAME}'
SOLIBS='-lm -lc'
;;
beos*)
@@ -1220,18 +1530,34 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_DLDFLAGS='-install_name $(libdir)/lib$(RUBY_SO_NAME).dylib -current_version $(MAJOR).$(MINOR).$(TEENY) -compatibility_version $(MAJOR).$(MINOR)'
LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).$(MAJOR).$(MINOR).dylib lib$(RUBY_SO_NAME).dylib'
;;
- atheos*)
- LIBRUBY_DLDFLAGS='-Wl,-soname,lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR)'
- LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_SO_NAME).so'
+ interix*)
+ LIBRUBYARG_SHARED='-L. -L${libdir} -l$(RUBY_SO_NAME)'
;;
*)
;;
esac
fi
-XLDFLAGS="$XLDFLAGS -L."
+if test "$enable_rpath" = yes; then
+ LIBRUBYARG_SHARED="${linker_flag}-R ${linker_flag}\$(libdir) -L\$(libdir) $LIBRUBYARG_SHARED"
+fi
+
+LDFLAGS="-L. $LDFLAGS"
AC_SUBST(ARCHFILE)
+dnl build rdoc index if requested
+RDOCTARGET=""
+AC_ARG_ENABLE(install-doc,
+ [ --enable-install-doc build and install rdoc indexes during install ],
+ [install_doc=$enableval], [install_doc=no])
+if test "$install_doc" != no; then
+ RDOCTARGET="install-doc"
+fi
+AC_SUBST(RDOCTARGET)
+
case "$target_os" in
+ linux*)
+ XCFLAGS="$XCFLAGS -D_GNU_SOURCE=1"
+ ;;
netbsd*)
CFLAGS="$CFLAGS -pipe"
;;
@@ -1251,6 +1577,7 @@ case "$target_os" in
;;
darwin*)
CFLAGS="$CFLAGS -pipe -fno-common"
+ MINIOBJS=dmydln.o
;;
os2-emx)
CFLAGS="$CFLAGS -DOS2 -Zmts"
@@ -1273,7 +1600,7 @@ case "$target_os" in
rm -f /tmp/main.o
CFLAGS="$CFLAGS -std"
fi
- ;;
+ ;;
beos*)
case "$target_cpu" in
powerpc*)
@@ -1288,21 +1615,19 @@ case "$target_os" in
LIBRUBY_SO='cyg$(RUBY_SO_NAME)'${MAJOR}${MINOR}.dll
LIBRUBY='lib$(RUBY_SO_NAME).dll.a'
fi
- AC_LIBOBJ([strftime])
;;
mingw*)
- RUBY_SO_NAME=msvcrt-'$(RUBY_INSTALL_NAME)'${MAJOR}${MINOR}
+ RUBY_SO_NAME=${rb_cv_msvcrt}-'$(RUBY_INSTALL_NAME)'${MAJOR}${MINOR}
if test x"$enable_shared" = xyes; then
LIBRUBY_SO='$(RUBY_SO_NAME)'.dll
LIBRUBY='lib$(LIBRUBY_SO).a'
fi
AC_LIBOBJ([win32])
COMMON_LIBS=m
- COMMON_MACROS="WIN32_LEAN_AND_MEAN="
+# COMMON_MACROS="WIN32_LEAN_AND_MEAN="
COMMON_HEADERS="windows.h winsock.h"
;;
esac
- XCFLAGS="$XCFLAGS"
LIBRUBY_DLDFLAGS="${DLDFLAGS}"' -Wl,--out-implib=$(LIBRUBY)'
LIBRUBY_ALIASES=''
FIRSTMAKEFILE=GNUmakefile:cygwin/GNUmakefile.in
@@ -1312,6 +1637,7 @@ case "$target_os" in
LIBRUBY='lib$(RUBY_SO_NAME).a'
LIBRUBYARG='-l$(RUBY_SO_NAME)'
fi
+ MINIOBJS=dmydln.o
;;
hpux*)
case "$YACC" in
@@ -1320,6 +1646,7 @@ case "$target_os" in
YACC="$YACC -Nl40000 -Nm40000"
;;
esac
+ MINIOBJS=dmydln.o
;;
*)
;;
@@ -1329,6 +1656,13 @@ case "$build_os" in
*msdosdjgpp*) FIRSTMAKEFILE=GNUmakefile:djgpp/GNUmakefile.in;;
esac
+CPPFLAGS="$CPPFLAGS "'$(DEFS)'
+test -z "$CFLAGS" || CFLAGS="$CFLAGS "; CFLAGS="$CFLAGS"'${cflags}'
+test -z "$CPPFLAGS" || CPPFLAGS="$CPPFLAGS "; CPPFLAGS="$CPPFLAGS"'${cppflags}'
+AC_SUBST(cppflags, [])dnl
+AC_SUBST(cflags, ['${optflags} ${debugflags}'])dnl
+AC_SUBST(optflags)dnl
+AC_SUBST(debugflags)dnl
AC_SUBST(XCFLAGS)dnl
AC_SUBST(XLDFLAGS)dnl
AC_SUBST(LIBRUBY_LDSHARED)
@@ -1352,6 +1686,7 @@ AC_SUBST(COMMON_LIBS)
AC_SUBST(COMMON_MACROS)
AC_SUBST(COMMON_HEADERS)
AC_SUBST(EXPORT_PREFIX)
+AC_SUBST(MINIOBJS)
MAKEFILES="Makefile `echo $FIRSTMAKEFILE | sed 's/:.*//'`"
MAKEFILES="`echo $MAKEFILES`"
@@ -1372,37 +1707,53 @@ case "$target_os" in
rubyw_install_name="$RUBYW_INSTALL_NAME"
;;
esac
+RUBY_LIB_PREFIX=`eval echo \\"${libdir}/ruby\\"`
+
+AC_ARG_WITH(sitedir,
+ [ --with-sitedir=DIR site libraries in DIR [[LIBDIR/ruby/site_ruby]]],
+ [sitedir=$withval],
+ [sitedir='${libdir}/ruby/site_ruby'])
+SITE_DIR=`eval echo \\"${sitedir}\\"`
+
case "$target_os" in
cygwin*|mingw*|*djgpp*|os2-emx*)
- RUBY_LIB_PREFIX="/lib/ruby"
+ RUBY_LIB_PREFIX="`eval echo "$RUBY_LIB_PREFIX" | sed 's|^NONE/|/|;s|^'"$prefix"'/|/|'`"
+ RUBY_SITE_LIB_PATH="`eval echo "$SITE_DIR" | sed 's|^NONE/|/|;s|^'"$prefix"'/|/|'`"
;;
*)
- RUBY_LIB_PREFIX="${prefix}/lib/ruby"
+ RUBY_LIB_PREFIX="`eval echo \\"$RUBY_LIB_PREFIX\\" | sed 's|^NONE/|'"$prefix"'/|'`"
+ RUBY_SITE_LIB_PATH="`eval echo \\"$SITE_DIR\\" | sed 's|^NONE/|'"$prefix"'/|'`"
;;
esac
RUBY_LIB_PATH="${RUBY_LIB_PREFIX}/${MAJOR}.${MINOR}"
+RUBY_SITE_LIB_PATH2="${RUBY_SITE_LIB_PATH}/${MAJOR}.${MINOR}"
-AC_ARG_WITH(sitedir,
- [ --with-sitedir=DIR site libraries in DIR [PREFIX/lib/ruby/site_ruby]],
- [sitedir=$withval],
- [sitedir='${prefix}/lib/ruby/site_ruby'])
-SITE_DIR="`eval \"echo ${sitedir}\"`"
+AC_DEFINE_UNQUOTED(RUBY_LIB, "${RUBY_LIB_PATH}")
+AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${RUBY_SITE_LIB_PATH}")
+AC_DEFINE_UNQUOTED(RUBY_SITE_LIB2, "${RUBY_SITE_LIB_PATH2}")
+
+AC_ARG_WITH(vendordir,
+ [ --with-vendordir=DIR vendor libraries in DIR [[LIBDIR/ruby/vendor_ruby]]],
+ [vendordir=$withval],
+ [vendordir='${libdir}/ruby/vendor_ruby'])
+VENDOR_DIR=`eval echo \\"${vendordir}\\"`
case "$target_os" in
cygwin*|mingw*|*djgpp*|os2-emx*)
- RUBY_SITE_LIB_PATH="`expr "$SITE_DIR" : "$prefix\(/.*\)"`" ||
- RUBY_SITE_LIB_PATH="$SITE_DIR";;
+ RUBY_VENDOR_LIB_PATH="`eval echo "$VENDOR_DIR" | sed 's|^NONE/|/|;s|^'"$prefix"'/|/|'`"
+ ;;
*)
- RUBY_SITE_LIB_PATH="$SITE_DIR";;
+ RUBY_VENDOR_LIB_PATH="`eval echo \\"$VENDOR_DIR\\" | sed 's|^NONE/|'"$prefix"'/|'`"
+ ;;
esac
-RUBY_SITE_LIB_PATH2="${RUBY_SITE_LIB_PATH}/${MAJOR}.${MINOR}"
+RUBY_VENDOR_LIB_PATH2="${RUBY_VENDOR_LIB_PATH}/${MAJOR}.${MINOR}"
-AC_DEFINE_UNQUOTED(RUBY_LIB, "${RUBY_LIB_PATH}")
-AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${RUBY_SITE_LIB_PATH}")
-AC_DEFINE_UNQUOTED(RUBY_SITE_LIB2, "${RUBY_SITE_LIB_PATH2}")
+AC_DEFINE_UNQUOTED(RUBY_VENDOR_LIB, "${RUBY_VENDOR_LIB_PATH}")
+AC_DEFINE_UNQUOTED(RUBY_VENDOR_LIB2, "${RUBY_VENDOR_LIB_PATH2}")
AC_SUBST(arch)dnl
AC_SUBST(sitearch)dnl
AC_SUBST(sitedir)dnl
+AC_SUBST(vendordir)dnl
configure_args=$ac_configure_args
AC_SUBST(configure_args)dnl
@@ -1415,6 +1766,8 @@ if test "$fat_binary" != no ; then
AC_DEFINE_UNQUOTED(RUBY_SITE_THIN_ARCHLIB,
"${RUBY_SITE_LIB_PATH}/" __ARCHITECTURE__ "-${target_os}")
+ AC_DEFINE_UNQUOTED(RUBY_VENDOR_THIN_ARCHLIB,
+ "${RUBY_VENDOR_LIB_PATH}/" __ARCHITECTURE__ "-${target_os}")
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, __ARCHITECTURE__ "-${target_os}")
else
arch="${target_cpu}-${target_os}"
@@ -1422,12 +1775,13 @@ else
fi
case "$target_os" in
- mingw*) sitearch="i386-msvcrt" ;;
+ mingw*) sitearch="$target_cpu-$rb_cv_msvcrt" ;;
*) sitearch="${arch}" ;;
esac
AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${RUBY_LIB_PATH}/${arch}")
AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${RUBY_SITE_LIB_PATH2}/${sitearch}")
+AC_DEFINE_UNQUOTED(RUBY_VENDOR_ARCHLIB, "${RUBY_VENDOR_LIB_PATH2}/${sitearch}")
AC_ARG_WITH(search-path,
[ --with-search-path=DIR specify the additional search path],
@@ -1464,7 +1818,15 @@ else
echo "creating config.h"
tr -d '\015' < confdefs.h > config.h
fi
-: > confdefs.h
-
-AC_CONFIG_FILES([$FIRSTMAKEFILE Makefile])
+tr -d '\015' < largefile.h > confdefs.h
+rm largefile.h
+
+AC_CONFIG_FILES($FIRSTMAKEFILE)
+AC_CONFIG_FILES(Makefile, [{
+ sed '/^MISSING/s/\$U\././g' Makefile
+ echo; test x"$EXEEXT" = x || echo 'miniruby: miniruby$(EXEEXT)'
+ test "$RUBY_INSTALL_NAME$EXEEXT" = ruby || echo 'ruby: $(PROGRAM);'
+ sed ['s/{\$([^(){}]*)[^{}]*}//g'] ${srcdir}/common.mk
+ } >> confmk$$.tmp && mv -f confmk$$.tmp Makefile],
+[RUBY_INSTALL_NAME=$RUBY_INSTALL_NAME EXEEXT=$EXEEXT])
AC_OUTPUT
diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in
index da9efaab47..03208df11c 100644
--- a/cygwin/GNUmakefile.in
+++ b/cygwin/GNUmakefile.in
@@ -1,11 +1,14 @@
include Makefile
ENABLE_SHARED=@ENABLE_SHARED@
+DLLWRAP = @DLLWRAP@ --target=@target_os@
ifeq (@target_os@,cygwin)
DLL_BASE_NAME := $(subst .dll,,$(LIBRUBY_SO))
else
DLL_BASE_NAME := $(RUBY_SO_NAME)
+ DLLWRAP += -mno-cygwin
+ VPATH += $(srcdir)/win32
endif
ifneq ($(ENABLE_SHARED),yes)
@@ -24,6 +27,10 @@ endif
WPROGRAM = $(RUBYW_INSTALL_NAME)$(EXEEXT)
SOLIBS := $(DLL_BASE_NAME).res.@OBJEXT@ $(SOLIBS)
EXTOBJS += $(@:$(EXEEXT)=.res.@OBJEXT@)
+RCFILES = $(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(DLL_BASE_NAME).rc
+
+ruby: $(PROGRAM)
+rubyw: $(WPROGRAM)
$(LIBRUBY): $(RUBY_EXP) $(LIBRUBY_SO)
$(RUBY_EXP) $(LIBRUBY_SO): $(DLL_BASE_NAME).res.@OBJEXT@
@@ -31,7 +38,7 @@ $(RUBY_EXP) $(LIBRUBY_SO): $(DLL_BASE_NAME).res.@OBJEXT@
%.res.@OBJEXT@: %.rc
@WINDRES@ --include-dir . --include-dir $(<D) --include-dir $(srcdir)/win32 $< $@
-$(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(DLL_BASE_NAME).rc: rbconfig.rb
+$(RCFILES): $(RBCONFIG)
@$(MINIRUBY) $(srcdir)/win32/resource.rb \
-ruby_name=$(RUBY_INSTALL_NAME) -rubyw_name=$(RUBYW_INSTALL_NAME) \
-so_name=$(DLL_BASE_NAME) \
@@ -44,7 +51,7 @@ $(WPROGRAM): $(RUBYW_INSTALL_NAME).res.@OBJEXT@
$(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
$(RUBY_EXP): $(LIBRUBY_A)
- @DLLWRAP@ --target=@target_os@ --driver-name=$(CC) \
+ $(DLLWRAP) \
--output-exp=$(RUBY_EXP) \
--export-all $(LIBRUBY_A) $(LIBS) -o $(PROGRAM)
$(LDSHARED) $(DLDFLAGS) $(OBJS) dmyext.o $(SOLIBS) -o $(PROGRAM)
@@ -63,3 +70,9 @@ cygwin-$(RUBY_INSTALL_NAME)$(MAJOR)$(MINOR).dll: $(LIBRUBY_A)
@DLLWRAP@ -s --def=rubydll.def -o $@
@rm -f rubydll.def
endif
+
+clean-local::
+ @$(RM) $(RUBY_EXP) $(RCFILES:.rc=.res.@OBJEXT@)
+
+distclean-local::
+ @$(RM) $(RCFILES)
diff --git a/defines.h b/defines.h
index 6d9a7013c8..f39097fea4 100644
--- a/defines.h
+++ b/defines.h
@@ -82,6 +82,10 @@ void xfree _((void*));
# define BDIGIT_DBL_SIGNED long
#endif
+#ifdef __CYGWIN__
+#undef _WIN32
+#endif
+
#if defined(MSDOS) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__)
#define DOSISH 1
#ifndef _WIN32_WCE
@@ -98,41 +102,100 @@ void xfree _((void*));
#endif
#endif
+#if defined(__NeXT__) || defined(__APPLE__)
+/* Do not trust WORDS_BIGENDIAN from configure since -arch compiler flag may
+ result in a different endian. Instead trust __BIG_ENDIAN__ and
+ __LITTLE_ENDIAN__ which are set correctly by -arch. */
+#undef WORDS_BIGENDIAN
+#ifdef __BIG_ENDIAN__
+#define WORDS_BIGENDIAN
+#endif
+#endif
+
#ifdef __NeXT__
-#define S_IXGRP 0000010 /* execute/search permission, group */
-#define S_IXOTH 0000001 /* execute/search permission, other */
+/* NextStep, OpenStep, Rhapsody */
+#ifndef S_IRUSR
+#define S_IRUSR 0000400 /* read permission, owner */
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 0000040 /* read permission, group */
+#endif
+#ifndef S_IROTH
+#define S_IROTH 0000004 /* read permission, other */
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR 0000200 /* write permission, owner */
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 0000020 /* write permission, group */
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 0000002 /* write permission, other */
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR 0000100 /* execute/search permission, owner */
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0000010 /* execute/search permission, group */
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0000001 /* execute/search permission, other */
+#endif
+#ifndef S_IRWXU
+#define S_IRWXU 0000700 /* read, write, execute permissions, owner */
+#endif
+#ifndef S_IRWXG
+#define S_IRWXG 0000070 /* read, write, execute permissions, group */
+#endif
+#ifndef S_IRWXO
+#define S_IRWXO 0000007 /* read, write, execute permissions, other */
+#endif
+#ifndef S_ISBLK
+#define S_ISBLK(mode) (((mode) & (0170000)) == (0060000))
+#endif
+#ifndef S_ISCHR
+#define S_ISCHR(mode) (((mode) & (0170000)) == (0020000))
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(mode) (((mode) & (0170000)) == (0040000))
+#endif
+#ifndef S_ISFIFO
+#define S_ISFIFO(mode) (((mode) & (0170000)) == (0010000))
+#endif
+#ifndef S_ISREG
+#define S_ISREG(mode) (((mode) & (0170000)) == (0100000))
+#endif
#ifndef __APPLE__
-#define S_IXUSR _S_IXUSR /* execute/search permission, owner */
+/* NextStep, OpenStep (but not Rhapsody) */
+#ifndef GETPGRP_VOID
#define GETPGRP_VOID 1
+#endif
+#ifndef WNOHANG
#define WNOHANG 01
+#endif
+#ifndef WUNTRACED
#define WUNTRACED 02
-#define X_OK 1
-typedef int pid_t;
-/* Do not trust WORDS_BIGENDIAN from configure since -arch compiler flag may
- result in a different endian. */
-#undef WORDS_BIGENDIAN
-#ifdef __BIG_ENDIAN__
-#define WORDS_BIGENDIAN
#endif
+#ifndef X_OK
+#define X_OK 1
#endif
+#endif /* __APPLE__ */
#endif /* NeXT */
-#ifdef __CYGWIN__
-#undef _WIN32
-#endif
#ifdef _WIN32
#include "win32/win32.h"
#endif
#if defined(__VMS)
-#include "vms/vms.h"
+#include "vms.h"
#endif
+#if defined(__BEOS__)
+#include <net/socket.h> /* intern.h needs fd_set definition */
+#endif
+
+#ifdef RUBY_EXPORT
#undef RUBY_EXTERN
-#if defined _WIN32 && !defined __GNUC__
-# ifndef RUBY_EXPORT
-# define RUBY_EXTERN extern __declspec(dllimport)
-# endif
#endif
#ifndef RUBY_EXTERN
@@ -143,6 +206,11 @@ typedef int pid_t;
#define EXTERN RUBY_EXTERN /* deprecated */
#endif
+#ifndef RUBY_MBCHAR_MAXSIZE
+#define RUBY_MBCHAR_MAXSIZE INT_MAX
+ /* MB_CUR_MAX will not work well in C locale */
+#endif
+
#if defined(sparc) || defined(__sparc__)
static inline void
flush_register_windows(void)
@@ -153,17 +221,19 @@ flush_register_windows(void)
#endif
# if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
("flushw")
-# elif defined(linux) || defined(__linux__)
- ("ta 0x83")
-# else /* Solaris, OpenBSD, NetBSD, etc. */
+# else
("ta 0x03")
# endif /* trap always to flush register windows if we are on a Sparc system */
;
}
# define FLUSH_REGISTER_WINDOWS flush_register_windows()
+#elif defined(__ia64)
+void *rb_ia64_bsp(void);
+void rb_ia64_flushrs(void);
+# define FLUSH_REGISTER_WINDOWS rb_ia64_flushrs()
#else
# define FLUSH_REGISTER_WINDOWS ((void)0)
-#endif
+#endif
#if defined(DOSISH)
#define PATH_SEP ";"
@@ -184,13 +254,16 @@ flush_register_windows(void)
#define ENV_IGNORECASE
#endif
-#if defined(__human68k__)
-#undef HAVE_RANDOM
-#undef HAVE_SETITIMER
+#ifndef CASEFOLD_FILESYSTEM
+# if defined DOSISH || defined __VMS
+# define CASEFOLD_FILESYSTEM 1
+# else
+# define CASEFOLD_FILESYSTEM 0
+# endif
#endif
-#if defined(DJGPP) || defined(__BOW__)
-#undef HAVE_SETITIMER
+#ifndef DLEXT_MAXLEN
+#define DLEXT_MAXLEN 4
#endif
#ifndef RUBY_PLATFORM
diff --git a/dir.c b/dir.c
index d16e311a11..710299e7b6 100644
--- a/dir.c
+++ b/dir.c
@@ -63,178 +63,287 @@ char *strchr _((char*,char));
#include "util.h"
-#ifndef HAVE_LSTAT
-#define lstat(path,st) stat(path,st)
+#if !defined HAVE_LSTAT && !defined lstat
+#define lstat stat
+#endif
+
+#ifndef CASEFOLD_FILESYSTEM
+# if defined DOSISH || defined __VMS
+# define CASEFOLD_FILESYSTEM 1
+# else
+# define CASEFOLD_FILESYSTEM 0
+# endif
#endif
#define FNM_NOESCAPE 0x01
#define FNM_PATHNAME 0x02
#define FNM_DOTMATCH 0x04
#define FNM_CASEFOLD 0x08
+#if CASEFOLD_FILESYSTEM
+#define FNM_SYSCASE FNM_CASEFOLD
+#else
+#define FNM_SYSCASE 0
+#endif
#define FNM_NOMATCH 1
#define FNM_ERROR 2
#define downcase(c) (nocase && ISUPPER(c) ? tolower(c) : (c))
-
-#ifndef CharNext /* defined as CharNext[AW] on Windows. */
-# if defined(DJGPP)
-# define CharNext(p) ((p) + mblen(p, MB_CUR_MAX))
-# else
-# define CharNext(p) ((p) + 1)
-# endif
+#define compare(c1, c2) (((unsigned char)(c1)) - ((unsigned char)(c2)))
+
+/* caution: in case *p == '\0'
+ Next(p) == p + 1 in single byte environment
+ Next(p) == p in multi byte environment
+*/
+#if defined(CharNext)
+# define Next(p) CharNext(p)
+#elif defined(DJGPP)
+# define Next(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
+#elif defined(__EMX__)
+# define Next(p) ((p) + emx_mblen(p))
+static inline int
+emx_mblen(const char *p)
+{
+ int n = mblen(p, RUBY_MBCHAR_MAXSIZE);
+ return (n < 0) ? 1 : n;
+}
#endif
-#if defined DOSISH
-#define isdirsep(c) ((c) == '/' || (c) == '\\')
-static const char *
-find_dirsep(s)
- const char *s;
+#ifndef Next /* single byte environment */
+# define Next(p) ((p) + 1)
+# define Inc(p) (++(p))
+# define Compare(p1, p2) (compare(downcase(*(p1)), downcase(*(p2))))
+#else /* multi byte environment */
+# define Inc(p) ((p) = Next(p))
+# define Compare(p1, p2) (CompareImpl(p1, p2, nocase))
+static int
+CompareImpl(const char *p1, const char *p2, int nocase)
{
- while (*s) {
- if (isdirsep(*s))
- return s;
- s = CharNext(s);
+ const int len1 = Next(p1) - p1;
+ const int len2 = Next(p2) - p2;
+#ifdef _WIN32
+ char buf1[10], buf2[10]; /* large enough? */
+#endif
+
+ if (len1 < 0 || len2 < 0) {
+ rb_fatal("CompareImpl: negative len");
+ }
+
+ if (len1 == 0) return len2;
+ if (len2 == 0) return -len1;
+
+#ifdef _WIN32
+ if (nocase && rb_w32_iswinnt()) {
+ if (len1 > 1) {
+ if (len1 >= sizeof(buf1)) {
+ rb_fatal("CompareImpl: too large len");
+ }
+ memcpy(buf1, p1, len1);
+ buf1[len1] = '\0';
+ CharLower(buf1);
+ p1 = buf1; /* trick */
+ }
+ if (len2 > 1) {
+ if (len2 >= sizeof(buf2)) {
+ rb_fatal("CompareImpl: too large len");
+ }
+ memcpy(buf2, p2, len2);
+ buf2[len2] = '\0';
+ CharLower(buf2);
+ p2 = buf2; /* trick */
+ }
}
- return 0;
-}
-#else
-#define isdirsep(c) ((c) == '/')
-#define find_dirsep(s) strchr(s, '/')
#endif
+ if (len1 == 1)
+ if (len2 == 1)
+ return compare(downcase(*p1), downcase(*p2));
+ else {
+ const int ret = compare(downcase(*p1), *p2);
+ return ret ? ret : -1;
+ }
+ else
+ if (len2 == 1) {
+ const int ret = compare(*p1, downcase(*p2));
+ return ret ? ret : 1;
+ }
+ else {
+ const int ret = memcmp(p1, p2, len1 < len2 ? len1 : len2);
+ return ret ? ret : len1 - len2;
+ }
+}
+#endif /* environment */
static char *
-range(pat, test, flags)
- char *pat;
- char test;
+bracket(p, s, flags)
+ const char *p; /* pattern (next to '[') */
+ const char *s; /* string */
int flags;
{
- int not, ok = 0;
- int nocase = flags & FNM_CASEFOLD;
- int escape = !(flags & FNM_NOESCAPE);
+ const int nocase = flags & FNM_CASEFOLD;
+ const int escape = !(flags & FNM_NOESCAPE);
- not = *pat == '!' || *pat == '^';
- if (not)
- pat++;
-
- test = downcase(test);
-
- while (*pat) {
- int cstart, cend;
- cstart = cend = *pat++;
- if (cstart == ']')
- return ok == not ? 0 : pat;
- else if (escape && cstart == '\\')
- cstart = cend = *pat++;
- if (*pat == '-' && pat[1] != ']') {
- if (escape && pat[1] == '\\')
- pat++;
- cend = pat[1];
- if (!cend)
- return 0;
- pat += 2;
+ int ok = 0, not = 0;
+
+ if (*p == '!' || *p == '^') {
+ not = 1;
+ p++;
+ }
+
+ while (*p != ']') {
+ const char *t1 = p;
+ if (escape && *t1 == '\\')
+ t1++;
+ if (!*t1)
+ return NULL;
+ p = Next(t1);
+ if (p[0] == '-' && p[1] != ']') {
+ const char *t2 = p + 1;
+ if (escape && *t2 == '\\')
+ t2++;
+ if (!*t2)
+ return NULL;
+ p = Next(t2);
+ if (!ok && Compare(t1, s) <= 0 && Compare(s, t2) <= 0)
+ ok = 1;
}
- if (downcase(cstart) <= test && test <= downcase(cend))
- ok = 1;
+ else
+ if (!ok && Compare(t1, s) == 0)
+ ok = 1;
}
- return 0;
+
+ return ok == not ? NULL : (char *)p + 1;
}
-#define ISDIRSEP(c) (pathname && isdirsep(c))
-#define PERIOD(s) (period && *(s) == '.' && \
- ((s) == string || ISDIRSEP((s)[-1])))
+/* If FNM_PATHNAME is set, only path element will be matched. (upto '/' or '\0')
+ Otherwise, entire string will be matched.
+ End marker itself won't be compared.
+ And if function succeeds, *pcur reaches end marker.
+*/
+#define UNESCAPE(p) (escape && *(p) == '\\' ? (p) + 1 : (p))
+#define ISEND(p) (!*(p) || (pathname && *(p) == '/'))
+#define RETURN(val) return *pcur = p, *scur = s, (val);
+
static int
-fnmatch(pat, string, flags)
- const char *pat;
- const char *string;
+fnmatch_helper(pcur, scur, flags)
+ const char **pcur; /* pattern */
+ const char **scur; /* string */
int flags;
{
- int c;
- int test;
- const char *s = string;
- int escape = !(flags & FNM_NOESCAPE);
- int pathname = flags & FNM_PATHNAME;
- int period = !(flags & FNM_DOTMATCH);
- int nocase = flags & FNM_CASEFOLD;
+ const int period = !(flags & FNM_DOTMATCH);
+ const int pathname = flags & FNM_PATHNAME;
+ const int escape = !(flags & FNM_NOESCAPE);
+ const int nocase = flags & FNM_CASEFOLD;
- while (c = *pat++) {
- switch (c) {
- case '?':
- if (!*s || ISDIRSEP(*s) || PERIOD(s))
- return FNM_NOMATCH;
- s++;
- break;
- case '*':
- while ((c = *pat++) == '*')
- ;
+ const char *ptmp = 0;
+ const char *stmp = 0;
- if (PERIOD(s))
- return FNM_NOMATCH;
+ const char *p = *pcur;
+ const char *s = *scur;
- if (!c) {
- if (pathname && find_dirsep(s))
- return FNM_NOMATCH;
- else
- return 0;
+ if (period && *s == '.' && *UNESCAPE(p) != '.') /* leading period */
+ RETURN(FNM_NOMATCH);
+
+ while (1) {
+ switch (*p) {
+ case '*':
+ do { p++; } while (*p == '*');
+ if (ISEND(UNESCAPE(p))) {
+ p = UNESCAPE(p);
+ RETURN(0);
}
- else if (ISDIRSEP(c)) {
- s = find_dirsep(s);
- if (s) {
- s++;
- break;
- }
- return FNM_NOMATCH;
+ if (ISEND(s))
+ RETURN(FNM_NOMATCH);
+ ptmp = p;
+ stmp = s;
+ continue;
+
+ case '?':
+ if (ISEND(s))
+ RETURN(FNM_NOMATCH);
+ p++;
+ Inc(s);
+ continue;
+
+ case '[': {
+ const char *t;
+ if (ISEND(s))
+ RETURN(FNM_NOMATCH);
+ if ((t = bracket(p + 1, s, flags)) != 0) {
+ p = t;
+ Inc(s);
+ continue;
}
+ goto failed;
+ }
+ }
- test = escape && c == '\\' ? *pat : c;
- test = downcase(test);
- pat--;
- while (*s) {
- if ((c == '[' || downcase(*s) == test) &&
- !fnmatch(pat, s, flags | FNM_DOTMATCH))
+ /* ordinary */
+ p = UNESCAPE(p);
+ if (ISEND(s))
+ RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
+ if (ISEND(p))
+ goto failed;
+ if (Compare(p, s) != 0)
+ goto failed;
+ Inc(p);
+ Inc(s);
+ continue;
+
+ failed: /* try next '*' position */
+ if (ptmp && stmp) {
+ p = ptmp;
+ Inc(stmp); /* !ISEND(*stmp) */
+ s = stmp;
+ continue;
+ }
+ RETURN(FNM_NOMATCH);
+ }
+}
+
+static int
+fnmatch(p, s, flags)
+ const char *p; /* pattern */
+ const char *s; /* string */
+ int flags;
+{
+ const int period = !(flags & FNM_DOTMATCH);
+ const int pathname = flags & FNM_PATHNAME;
+
+ const char *ptmp = 0;
+ const char *stmp = 0;
+
+ if (pathname) {
+ while (1) {
+ if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
+ do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
+ ptmp = p;
+ stmp = s;
+ }
+ if (fnmatch_helper(&p, &s, flags) == 0) {
+ while (*s && *s != '/') Inc(s);
+ if (*p && *s) {
+ p++;
+ s++;
+ continue;
+ }
+ if (!*p && !*s)
return 0;
- else if (ISDIRSEP(*s))
- break;
- s++;
}
- return FNM_NOMATCH;
-
- case '[':
- if (!*s || ISDIRSEP(*s) || PERIOD(s))
- return FNM_NOMATCH;
- pat = range(pat, *s, flags);
- if (!pat)
- return FNM_NOMATCH;
- s++;
- break;
-
- case '\\':
- if (escape
-#if defined DOSISH
- && *pat && strchr("*?[\\", *pat)
-#endif
- ) {
- c = *pat;
- if (!c)
- c = '\\';
- else
- pat++;
+ /* failed : try next recursion */
+ if (ptmp && stmp && !(period && *stmp == '.')) {
+ while (*stmp && *stmp != '/') Inc(stmp);
+ if (*stmp) {
+ p = ptmp;
+ stmp++;
+ s = stmp;
+ continue;
+ }
}
- /* FALLTHROUGH */
-
- default:
-#if defined DOSISH
- if (ISDIRSEP(c) && isdirsep(*s))
- ;
- else
-#endif
- if(downcase(c) != downcase(*s))
- return FNM_NOMATCH;
- s++;
- break;
+ return FNM_NOMATCH;
}
}
- return !*s ? 0 : FNM_NOMATCH;
+ else
+ return fnmatch_helper(&p, &s, flags);
}
VALUE rb_cDir;
@@ -248,7 +357,11 @@ static void
free_dir(dir)
struct dir_data *dir;
{
- if (dir && dir->dir) closedir(dir->dir);
+ if (dir) {
+ if (dir->dir) closedir(dir->dir);
+ if (dir->path) free(dir->path);
+ }
+ free(dir);
}
static VALUE dir_close _((VALUE));
@@ -267,6 +380,12 @@ dir_s_alloc(klass)
return obj;
}
+/*
+ * call-seq:
+ * Dir.new( string ) -> aDir
+ *
+ * Returns a new directory object for the named directory.
+ */
static VALUE
dir_initialize(dir, dirname)
VALUE dir, dirname;
@@ -294,6 +413,18 @@ dir_initialize(dir, dirname)
return dir;
}
+/*
+ * call-seq:
+ * Dir.open( string ) => aDir
+ * Dir.open( string ) {| aDir | block } => anObject
+ *
+ * With no block, <code>open</code> is a synonym for
+ * <code>Dir::new</code>. If a block is present, it is passed
+ * <i>aDir</i> as a parameter. The directory is closed at the end of
+ * the block, and <code>Dir::open</code> returns the value of the
+ * block.
+ */
+
static VALUE
dir_s_open(klass, dirname)
VALUE klass, dirname;
@@ -315,22 +446,76 @@ dir_closed()
rb_raise(rb_eIOError, "closed directory");
}
+static void
+dir_check(dir)
+ VALUE dir;
+{
+ if (!OBJ_TAINTED(dir) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted Dir");
+ rb_check_frozen(dir);
+}
+
#define GetDIR(obj, dirp) do {\
+ dir_check(dir);\
Data_Get_Struct(obj, struct dir_data, dirp);\
if (dirp->dir == NULL) dir_closed();\
} while (0)
+/*
+ * call-seq:
+ * dir.inspect => string
+ *
+ * Return a string describing this Dir object.
+ */
+static VALUE
+dir_inspect(dir)
+ VALUE dir;
+{
+ struct dir_data *dirp;
+
+ Data_Get_Struct(dir, struct dir_data, dirp);
+ if (dirp->path) {
+ const char *c = rb_obj_classname(dir);
+ int len = strlen(c) + strlen(dirp->path) + 4;
+ VALUE s = rb_str_new(0, len);
+ snprintf(RSTRING_PTR(s), len+1, "#<%s:%s>", c, dirp->path);
+ return s;
+ }
+ return rb_funcall(dir, rb_intern("to_s"), 0, 0);
+}
+
+/*
+ * call-seq:
+ * dir.path => string or nil
+ *
+ * Returns the path parameter passed to <em>dir</em>'s constructor.
+ *
+ * d = Dir.new("..")
+ * d.path #=> ".."
+ */
static VALUE
dir_path(dir)
VALUE dir;
{
struct dir_data *dirp;
- GetDIR(dir, dirp);
+ Data_Get_Struct(dir, struct dir_data, dirp);
if (!dirp->path) return Qnil;
return rb_str_new2(dirp->path);
}
+/*
+ * call-seq:
+ * dir.read => string or nil
+ *
+ * Reads the next entry from <em>dir</em> and returns it as a string.
+ * Returns <code>nil</code> at the end of the stream.
+ *
+ * d = Dir.new("testdir")
+ * d.read #=> "."
+ * d.read #=> ".."
+ * d.read #=> "config.h"
+ */
static VALUE
dir_read(dir)
VALUE dir;
@@ -353,6 +538,23 @@ dir_read(dir)
return Qnil; /* not reached */
}
+/*
+ * call-seq:
+ * dir.each { |filename| block } => dir
+ *
+ * Calls the block once for each entry in this directory, passing the
+ * filename of each entry as a parameter to the block.
+ *
+ * d = Dir.new("testdir")
+ * d.each {|x| puts "Got #{x}" }
+ *
+ * <em>produces:</em>
+ *
+ * Got .
+ * Got ..
+ * Got config.h
+ * Got main.rb
+ */
static VALUE
dir_each(dir)
VALUE dir;
@@ -360,7 +562,9 @@ dir_each(dir)
struct dir_data *dirp;
struct dirent *dp;
+ RETURN_ENUMERATOR(dir, 0, 0);
GetDIR(dir, dirp);
+ rewinddir(dirp->dir);
for (dp = readdir(dirp->dir); dp != NULL; dp = readdir(dirp->dir)) {
rb_yield(rb_tainted_str_new(dp->d_name, NAMLEN(dp)));
if (dirp->dir == NULL) dir_closed();
@@ -368,6 +572,19 @@ dir_each(dir)
return dir;
}
+/*
+ * call-seq:
+ * dir.pos => integer
+ * dir.tell => integer
+ *
+ * Returns the current position in <em>dir</em>. See also
+ * <code>Dir#seek</code>.
+ *
+ * d = Dir.new("testdir")
+ * d.tell #=> 0
+ * d.read #=> "."
+ * d.tell #=> 12
+ */
static VALUE
dir_tell(dir)
VALUE dir;
@@ -384,21 +601,50 @@ dir_tell(dir)
#endif
}
+/*
+ * call-seq:
+ * dir.seek( integer ) => dir
+ *
+ * Seeks to a particular location in <em>dir</em>. <i>integer</i>
+ * must be a value returned by <code>Dir#tell</code>.
+ *
+ * d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
+ * d.read #=> "."
+ * i = d.tell #=> 12
+ * d.read #=> ".."
+ * d.seek(i) #=> #<Dir:0x401b3c40>
+ * d.read #=> ".."
+ */
static VALUE
dir_seek(dir, pos)
VALUE dir, pos;
{
struct dir_data *dirp;
+ off_t p = NUM2OFFT(pos);
-#ifdef HAVE_SEEKDIR
GetDIR(dir, dirp);
- seekdir(dirp->dir, NUM2INT(pos));
+#ifdef HAVE_SEEKDIR
+ seekdir(dirp->dir, p);
return dir;
#else
rb_notimplement();
#endif
}
+/*
+ * call-seq:
+ * dir.pos( integer ) => integer
+ *
+ * Synonym for <code>Dir#seek</code>, but returns the position
+ * parameter.
+ *
+ * d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
+ * d.read #=> "."
+ * i = d.pos #=> 12
+ * d.read #=> ".."
+ * d.pos = i #=> 12
+ * d.read #=> ".."
+ */
static VALUE
dir_set_pos(dir, pos)
VALUE dir, pos;
@@ -407,17 +653,41 @@ dir_set_pos(dir, pos)
return pos;
}
+/*
+ * call-seq:
+ * dir.rewind => dir
+ *
+ * Repositions <em>dir</em> to the first entry.
+ *
+ * d = Dir.new("testdir")
+ * d.read #=> "."
+ * d.rewind #=> #<Dir:0x401b3fb0>
+ * d.read #=> "."
+ */
static VALUE
dir_rewind(dir)
VALUE dir;
{
struct dir_data *dirp;
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(dir)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't close");
+ }
GetDIR(dir, dirp);
rewinddir(dirp->dir);
return dir;
}
+/*
+ * call-seq:
+ * dir.close => nil
+ *
+ * Closes the directory stream. Any further attempts to access
+ * <em>dir</em> will raise an <code>IOError</code>.
+ *
+ * d = Dir.new("testdir")
+ * d.close #=> nil
+ */
static VALUE
dir_close(dir)
VALUE dir;
@@ -433,27 +703,84 @@ dir_close(dir)
static void
dir_chdir(path)
- const char *path;
+ VALUE path;
{
- if (chdir(path) < 0)
- rb_sys_fail(path);
+ if (chdir(RSTRING(path)->ptr) < 0)
+ rb_sys_fail(RSTRING(path)->ptr);
}
static int chdir_blocking = 0;
static VALUE chdir_thread = Qnil;
+struct chdir_data {
+ VALUE old_path, new_path;
+ int done;
+};
+
static VALUE
-chdir_restore(path)
- char *path;
+chdir_yield(args)
+ struct chdir_data *args;
{
- chdir_blocking--;
- if (chdir_blocking == 0)
- chdir_thread = Qnil;
- dir_chdir(path);
- free(path);
+ dir_chdir(args->new_path);
+ args->done = Qtrue;
+ chdir_blocking++;
+ if (chdir_thread == Qnil)
+ chdir_thread = rb_thread_current();
+ return rb_yield(args->new_path);
+}
+
+static VALUE
+chdir_restore(args)
+ struct chdir_data *args;
+{
+ if (args->done) {
+ chdir_blocking--;
+ if (chdir_blocking == 0)
+ chdir_thread = Qnil;
+ dir_chdir(args->old_path);
+ }
return Qnil;
}
+/*
+ * call-seq:
+ * Dir.chdir( [ string] ) => 0
+ * Dir.chdir( [ string] ) {| path | block } => anObject
+ *
+ * Changes the current working directory of the process to the given
+ * string. When called without an argument, changes the directory to
+ * the value of the environment variable <code>HOME</code>, or
+ * <code>LOGDIR</code>. <code>SystemCallError</code> (probably
+ * <code>Errno::ENOENT</code>) if the target directory does not exist.
+ *
+ * If a block is given, it is passed the name of the new current
+ * directory, and the block is executed with that as the current
+ * directory. The original working directory is restored when the block
+ * exits. The return value of <code>chdir</code> is the value of the
+ * block. <code>chdir</code> blocks can be nested, but in a
+ * multi-threaded program an error will be raised if a thread attempts
+ * to open a <code>chdir</code> block while another thread has one
+ * open.
+ *
+ * Dir.chdir("/var/spool/mail")
+ * puts Dir.pwd
+ * Dir.chdir("/tmp") do
+ * puts Dir.pwd
+ * Dir.chdir("/usr") do
+ * puts Dir.pwd
+ * end
+ * puts Dir.pwd
+ * end
+ * puts Dir.pwd
+ *
+ * <em>produces:</em>
+ *
+ * /var/spool/mail
+ * /tmp
+ * /usr
+ * /tmp
+ * /var/spool/mail
+ */
static VALUE
dir_s_chdir(argc, argv, obj)
int argc;
@@ -461,19 +788,18 @@ dir_s_chdir(argc, argv, obj)
VALUE obj;
{
VALUE path = Qnil;
- char *dist = "";
rb_secure(2);
if (rb_scan_args(argc, argv, "01", &path) == 1) {
SafeStringValue(path);
- dist = RSTRING(path)->ptr;
}
else {
- dist = getenv("HOME");
+ const char *dist = getenv("HOME");
if (!dist) {
dist = getenv("LOGDIR");
if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
}
+ path = rb_str_new2(dist);
}
if (chdir_blocking > 0) {
@@ -482,18 +808,30 @@ dir_s_chdir(argc, argv, obj)
}
if (rb_block_given_p()) {
+ struct chdir_data args;
char *cwd = my_getcwd();
- chdir_blocking++;
- if (chdir_thread == Qnil)
- chdir_thread = rb_thread_current();
- dir_chdir(dist);
- return rb_ensure(rb_yield, path, chdir_restore, (VALUE)cwd);
+
+ args.old_path = rb_tainted_str_new2(cwd); free(cwd);
+ args.new_path = path;
+ args.done = Qfalse;
+ return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
}
- dir_chdir(dist);
+ dir_chdir(path);
return INT2FIX(0);
}
+/*
+ * call-seq:
+ * Dir.getwd => string
+ * Dir.pwd => string
+ *
+ * Returns the path to the current working directory of this process as
+ * a string.
+ *
+ * Dir.chdir("/tmp") #=> 0
+ * Dir.getwd #=> "/tmp"
+ */
static VALUE
dir_s_getwd(dir)
VALUE dir;
@@ -509,13 +847,36 @@ dir_s_getwd(dir)
return cwd;
}
+static void check_dirname _((volatile VALUE *));
+static void
+check_dirname(dir)
+ volatile VALUE *dir;
+{
+ char *path, *pend;
+
+ SafeStringValue(*dir);
+ rb_secure(2);
+ path = RSTRING(*dir)->ptr;
+ if (path && *(pend = rb_path_end(rb_path_skip_prefix(path)))) {
+ *dir = rb_str_new(path, pend - path);
+ }
+}
+
+/*
+ * call-seq:
+ * Dir.chroot( string ) => 0
+ *
+ * Changes this process's idea of the file system root. Only a
+ * privileged process may make this call. Not available on all
+ * platforms. On Unix systems, see <code>chroot(2)</code> for more
+ * information.
+ */
static VALUE
dir_s_chroot(dir, path)
VALUE dir, path;
{
#if defined(HAVE_CHROOT) && !defined(__CHECKER__)
- rb_secure(2);
- SafeStringValue(path);
+ check_dirname(&path);
if (chroot(RSTRING(path)->ptr) == -1)
rb_sys_fail(RSTRING(path)->ptr);
@@ -527,6 +888,19 @@ dir_s_chroot(dir, path)
#endif
}
+/*
+ * call-seq:
+ * Dir.mkdir( string [, integer] ) => 0
+ *
+ * Makes a new directory named by <i>string</i>, with permissions
+ * specified by the optional parameter <i>anInteger</i>. The
+ * permissions may be modified by the value of
+ * <code>File::umask</code>, and are ignored on NT. Raises a
+ * <code>SystemCallError</code> if the directory cannot be created. See
+ * also the discussion of permissions in the class documentation for
+ * <code>File</code>.
+ *
+ */
static VALUE
dir_s_mkdir(argc, argv, obj)
int argc;
@@ -543,118 +917,286 @@ dir_s_mkdir(argc, argv, obj)
mode = 0777;
}
- SafeStringValue(path);
- rb_secure(2);
-#ifndef _WIN32
+ check_dirname(&path);
if (mkdir(RSTRING(path)->ptr, mode) == -1)
rb_sys_fail(RSTRING(path)->ptr);
-#else
- if (mkdir(RSTRING(path)->ptr) == -1)
- rb_sys_fail(RSTRING(path)->ptr);
-#endif
return INT2FIX(0);
}
+/*
+ * call-seq:
+ * Dir.delete( string ) => 0
+ * Dir.rmdir( string ) => 0
+ * Dir.unlink( string ) => 0
+ *
+ * Deletes the named directory. Raises a subclass of
+ * <code>SystemCallError</code> if the directory isn't empty.
+ */
static VALUE
dir_s_rmdir(obj, dir)
VALUE obj, dir;
{
- SafeStringValue(dir);
- rb_secure(2);
+ check_dirname(&dir);
if (rmdir(RSTRING(dir)->ptr) < 0)
rb_sys_fail(RSTRING(dir)->ptr);
return INT2FIX(0);
}
+static void
+sys_warning_1(mesg)
+ const char* mesg;
+{
+ rb_sys_warning("%s", mesg);
+}
+
+#define GLOB_VERBOSE (1UL << (sizeof(int) * CHAR_BIT - 1))
+#define sys_warning(val) \
+ (void)((flags & GLOB_VERBOSE) && rb_protect((VALUE (*)_((VALUE)))sys_warning_1, (VALUE)(val), 0))
+
+#define GLOB_ALLOC(type) (type *)malloc(sizeof(type))
+#define GLOB_ALLOC_N(type, n) (type *)malloc(sizeof(type) * (n))
+#define GLOB_JUMP_TAG(status) ((status == -1) ? rb_memerror() : rb_jump_tag(status))
+
+/*
+ * ENOTDIR can be returned by stat(2) if a non-leaf element of the path
+ * is not a directory.
+ */
+#define to_be_ignored(e) ((e) == ENOENT || (e) == ENOTDIR)
+
+/* System call with warning */
+static int
+do_stat(const char *path, struct stat *pst, int flags)
+
+{
+ int ret = stat(path, pst);
+ if (ret < 0 && !to_be_ignored(errno))
+ sys_warning(path);
+
+ return ret;
+}
+
+static int
+do_lstat(const char *path, struct stat *pst, int flags)
+{
+ int ret = lstat(path, pst);
+ if (ret < 0 && !to_be_ignored(errno))
+ sys_warning(path);
+
+ return ret;
+}
+
+static DIR *
+do_opendir(const char *path, int flags)
+{
+ DIR *dirp = opendir(path);
+ if (dirp == NULL && !to_be_ignored(errno))
+ sys_warning(path);
+
+ return dirp;
+}
+
/* Return nonzero if S has any special globbing chars in it. */
static int
-has_magic(s, send, flags)
- char *s, *send;
- int flags;
+has_magic(s, flags)
+ const char *s;
+ int flags;
{
- register char *p = s;
+ const int escape = !(flags & FNM_NOESCAPE);
+ const int nocase = flags & FNM_CASEFOLD;
+
+ register const char *p = s;
register char c;
- int open = 0;
- int escape = !(flags & FNM_NOESCAPE);
- while ((c = *p++) != '\0') {
+ while ((c = *p++) != 0) {
switch (c) {
- case '?':
case '*':
- return Qtrue;
+ case '?':
+ case '[':
+ return 1;
- case '[': /* Only accept an open brace if there is a close */
- open++; /* brace to match it. Bracket expressions must be */
- continue; /* complete, according to Posix.2 */
- case ']':
- if (open)
- return Qtrue;
+ case '\\':
+ if (escape && !(c = *p++))
+ return 0;
continue;
- case '\\':
- if (escape && *p++ == '\0')
- return Qfalse;
+ default:
+ if (!FNM_SYSCASE && ISALPHA(c) && nocase)
+ return 1;
}
- if (send && p >= send) break;
+ p = Next(p-1);
}
- return Qfalse;
+
+ return 0;
}
-static char*
-extract_path(p, pend)
- char *p, *pend;
+/* Find separator in globbing pattern. */
+static char *
+find_dirsep(const char *s, int flags)
{
- char *alloc;
- int len;
-
- len = pend - p;
- alloc = ALLOC_N(char, len+1);
- memcpy(alloc, p, len);
- if (len > 1 && pend[-1] == '/'
-#if defined DOSISH_DRIVE_LETTER
- && pend[-2] != ':'
-#endif
- ) {
- alloc[len-1] = 0;
- }
- else {
- alloc[len] = 0;
- }
+ const int escape = !(flags & FNM_NOESCAPE);
- return alloc;
-}
+ register const char *p = s;
+ register char c;
+ int open = 0;
-static char*
-extract_elem(path)
- char *path;
-{
- char *pend;
+ while ((c = *p++) != 0) {
+ switch (c) {
+ case '[':
+ open = 1;
+ continue;
+ case ']':
+ open = 0;
+ continue;
- pend = strchr(path, '/');
- if (!pend) pend = path + strlen(path);
+ case '/':
+ if (!open)
+ return (char *)p-1;
+ continue;
- return extract_path(path, pend);
+ case '\\':
+ if (escape && !(c = *p++))
+ return (char *)p-1;
+ continue;
+ }
+
+ p = Next(p-1);
+ }
+
+ return (char *)p-1;
}
+/* Remove escaping backslashes */
static void
remove_backslashes(p)
char *p;
{
- char *pend = p + strlen(p);
char *t = p;
+ char *s = p;
- while (p < pend) {
+ while (*p) {
if (*p == '\\') {
- if (++p == pend) break;
+ if (t != s)
+ memmove(t, s, p - s);
+ t += p - s;
+ s = ++p;
+ if (!*p) break;
}
- *t++ = *p++;
+ Inc(p);
}
- *t = '\0';
+
+ while (*p++);
+
+ if (t != s)
+ memmove(t, s, p - s); /* move '\0' too */
}
+/* Globing pattern */
+enum glob_pattern_type { PLAIN, MAGICAL, RECURSIVE, MATCH_ALL, MATCH_DIR };
+
+struct glob_pattern {
+ char *str;
+ enum glob_pattern_type type;
+ struct glob_pattern *next;
+};
+
+static void glob_free_pattern(struct glob_pattern *list);
+
+static struct glob_pattern *
+glob_make_pattern(const char *p, int flags)
+{
+ struct glob_pattern *list, *tmp, **tail = &list;
+ int dirsep = 0; /* pattern is terminated with '/' */
+
+ while (*p) {
+ tmp = GLOB_ALLOC(struct glob_pattern);
+ if (!tmp) goto error;
+ if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
+ /* fold continuous RECURSIVEs (needed in glob_helper) */
+ do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
+ tmp->type = RECURSIVE;
+ tmp->str = 0;
+ dirsep = 1;
+ }
+ else {
+ const char *m = find_dirsep(p, flags);
+ char *buf = GLOB_ALLOC_N(char, m-p+1);
+ if (!buf) {
+ free(tmp);
+ goto error;
+ }
+ memcpy(buf, p, m-p);
+ buf[m-p] = '\0';
+ tmp->type = has_magic(buf, flags) ? MAGICAL : PLAIN;
+ tmp->str = buf;
+ if (*m) {
+ dirsep = 1;
+ p = m + 1;
+ }
+ else {
+ dirsep = 0;
+ p = m;
+ }
+ }
+ *tail = tmp;
+ tail = &tmp->next;
+ }
+
+ tmp = GLOB_ALLOC(struct glob_pattern);
+ if (!tmp) {
+ error:
+ *tail = 0;
+ glob_free_pattern(list);
+ return 0;
+ }
+ tmp->type = dirsep ? MATCH_DIR : MATCH_ALL;
+ tmp->str = 0;
+ *tail = tmp;
+ tmp->next = 0;
+
+ return list;
+}
+
+static void
+glob_free_pattern(struct glob_pattern *list)
+{
+ while (list) {
+ struct glob_pattern *tmp = list;
+ list = list->next;
+ if (tmp->str)
+ free(tmp->str);
+ free(tmp);
+ }
+}
+
+static char *
+join_path(const char *path, int dirsep, const char *name)
+{
+ long len = strlen(path);
+ char *buf = GLOB_ALLOC_N(char, len+strlen(name)+(dirsep?1:0)+1);
+
+ if (!buf) return 0;
+ memcpy(buf, path, len);
+ if (dirsep) {
+ strcpy(buf+len, "/");
+ len++;
+ }
+ strcpy(buf+len, name);
+ return buf;
+}
+
+enum answer { YES, NO, UNKNOWN };
+
+#ifndef S_ISLNK
+# ifndef S_IFLNK
+# define S_ISLNK(m) (0)
+# else
+# define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK)
+# endif
+#endif
+
#ifndef S_ISDIR
# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
#endif
@@ -672,358 +1214,546 @@ glob_func_caller(val)
VALUE val;
{
struct glob_args *args = (struct glob_args *)val;
+
(*args->func)(args->c, args->v);
return Qnil;
}
-static int
-glob_call_func(func, path, arg)
- void (*func) _((const char*, VALUE));
- const char *path;
- VALUE arg;
-{
- int status;
- struct glob_args args;
+#define glob_call_func(func, path, arg) (*func)(path, arg)
- args.func = func;
- args.c = path;
- args.v = arg;
-
- rb_protect(glob_func_caller, (VALUE)&args, &status);
- return status;
-}
+static int glob_helper _((const char *, int, enum answer, enum answer, struct glob_pattern **, struct glob_pattern **, int, ruby_glob_func *, VALUE));
static int
-glob_helper(path, sub, flags, func, arg)
- char *path;
- char *sub;
+glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
+ const char *path;
+ int dirsep; /* '/' should be placed before appending child entry's name to 'path'. */
+ enum answer exist; /* Does 'path' indicate an existing entry? */
+ enum answer isdir; /* Does 'path' indicate a directory or a symlink to a directory? */
+ struct glob_pattern **beg;
+ struct glob_pattern **end;
int flags;
- void (*func) _((const char*, VALUE));
+ ruby_glob_func *func;
VALUE arg;
{
struct stat st;
- char *p, *m;
int status = 0;
+ struct glob_pattern **cur, **new_beg, **new_end;
+ int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
+ int escape = !(flags & FNM_NOESCAPE);
- p = sub ? sub : path;
- if (!has_magic(p, 0, flags)) {
-#if defined DOSISH
- remove_backslashes(path);
-#else
- if (!(flags & FNM_NOESCAPE)) remove_backslashes(p);
-#endif
- if (lstat(path, &st) == 0) {
- status = glob_call_func(func, path, arg);
- if (status) return status;
+ for (cur = beg; cur < end; ++cur) {
+ struct glob_pattern *p = *cur;
+ if (p->type == RECURSIVE) {
+ recursive = 1;
+ p = p->next;
}
- else if (errno != ENOENT) {
- /* In case stat error is other than ENOENT and
- we may want to know what is wrong. */
- rb_sys_warning(path);
+ switch (p->type) {
+ case PLAIN:
+ plain = 1;
+ break;
+ case MAGICAL:
+ magical = 1;
+ break;
+ case MATCH_ALL:
+ match_all = 1;
+ break;
+ case MATCH_DIR:
+ match_dir = 1;
+ break;
+ case RECURSIVE:
+ rb_bug("continuous RECURSIVEs");
}
- return 0;
}
- while (p && !status) {
- if (*p == '/') p++;
- m = strchr(p, '/');
- if (has_magic(p, m, flags)) {
- char *dir, *base, *magic, *buf;
- DIR *dirp;
- struct dirent *dp;
- int recursive = 0;
-
- struct d_link {
- char *path;
- struct d_link *next;
- } *tmp, *link, **tail = &link;
-
- base = extract_path(path, p);
- if (path == p) dir = ".";
- else dir = base;
-
- magic = extract_elem(p);
- if (stat(dir, &st) < 0) {
- if (errno != ENOENT) rb_sys_warning(dir);
- free(base);
- free(magic);
- break;
+ if (*path) {
+ if (match_all && exist == UNKNOWN) {
+ if (do_lstat(path, &st, flags) == 0) {
+ exist = YES;
+ isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
}
- if (S_ISDIR(st.st_mode)) {
- if (m && strcmp(magic, "**") == 0) {
- int n = strlen(base);
- recursive = 1;
- buf = ALLOC_N(char, n+strlen(m)+3);
- sprintf(buf, "%s%s", base, *base ? m : m+1);
- status = glob_helper(buf, buf+n, flags, func, arg);
- free(buf);
- if (status) goto finalize;
- }
- dirp = opendir(dir);
- if (dirp == NULL) {
- rb_sys_warning(dir);
- free(base);
- free(magic);
- break;
- }
+ else {
+ exist = NO;
+ isdir = NO;
+ }
+ }
+ if (match_dir && isdir == UNKNOWN) {
+ if (do_stat(path, &st, flags) == 0) {
+ exist = YES;
+ isdir = S_ISDIR(st.st_mode) ? YES : NO;
}
else {
- free(base);
- free(magic);
- break;
+ exist = NO;
+ isdir = NO;
}
+ }
+ if (match_all && exist == YES) {
+ status = glob_call_func(func, path, arg);
+ if (status) return status;
+ }
+ if (match_dir && isdir == YES) {
+ char *tmp = join_path(path, dirsep, "");
+ if (!tmp) return -1;
+ status = glob_call_func(func, tmp, arg);
+ free(tmp);
+ if (status) return status;
+ }
+ }
-#if defined DOSISH_DRIVE_LETTER
-#define BASE (*base && !((isdirsep(*base) && !base[1]) || (base[1] == ':' && isdirsep(base[2]) && !base[3])))
+ if (exist == NO || isdir == NO) return 0;
+
+ if (magical || recursive) {
+ struct dirent *dp;
+ DIR *dirp = do_opendir(*path ? path : ".", flags);
+ if (dirp == NULL) return 0;
+
+ for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ char *buf = join_path(path, dirsep, dp->d_name);
+ enum answer new_isdir = UNKNOWN;
+
+ if (!buf) {
+ status = -1;
+ break;
+ }
+ if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0
+ && fnmatch("*", dp->d_name, flags) == 0) {
+#ifndef _WIN32
+ if (do_lstat(buf, &st, flags) == 0)
+ new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
+ else
+ new_isdir = NO;
#else
-#define BASE (*base && !(isdirsep(*base) && !base[1]))
+ new_isdir = dp->d_isdir ? (!dp->d_isrep ? YES : UNKNOWN) : NO;
#endif
+ }
- for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- if (recursive) {
- if (strcmp(".", dp->d_name) == 0 || strcmp("..", dp->d_name) == 0)
- continue;
- buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+strlen(m)+6);
- sprintf(buf, "%s%s%s", base, (BASE) ? "/" : "", dp->d_name);
- if (lstat(buf, &st) < 0) {
- if (errno != ENOENT) rb_sys_warning(buf);
- free(buf);
- continue;
- }
- if (S_ISDIR(st.st_mode)) {
- char *t = buf+strlen(buf);
- strcpy(t, "/**");
- strcpy(t+3, m);
- status = glob_helper(buf, t, flags, func, arg);
- free(buf);
- if (status) break;
- continue;
- }
- free(buf);
- continue;
+ new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, (end - beg) * 2);
+ if (!new_beg) {
+ status = -1;
+ break;
+ }
+
+ for (cur = beg; cur < end; ++cur) {
+ struct glob_pattern *p = *cur;
+ if (p->type == RECURSIVE) {
+ if (new_isdir == YES) /* not symlink but real directory */
+ *new_end++ = p; /* append recursive pattern */
+ p = p->next; /* 0 times recursion */
}
- if (fnmatch(magic, dp->d_name, flags) == 0) {
- buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+2);
- sprintf(buf, "%s%s%s", base, (BASE) ? "/" : "", dp->d_name);
- if (!m) {
- status = glob_call_func(func, buf, arg);
- free(buf);
- if (status) break;
- continue;
- }
- tmp = ALLOC(struct d_link);
- tmp->path = buf;
- *tail = tmp;
- tail = &tmp->next;
+ if (p->type == PLAIN || p->type == MAGICAL) {
+ if (fnmatch(p->str, dp->d_name, flags) == 0)
+ *new_end++ = p->next;
}
}
- closedir(dirp);
- finalize:
- *tail = 0;
- free(base);
- free(magic);
- if (link) {
- while (link) {
- if (status == 0) {
- if (stat(link->path, &st) == 0) {
- if (S_ISDIR(st.st_mode)) {
- int len = strlen(link->path);
- int mlen = strlen(m);
- char *t = ALLOC_N(char, len+mlen+1);
-
- sprintf(t, "%s%s", link->path, m);
- status = glob_helper(t, t+len, flags, func, arg);
- free(t);
- }
- }
- else {
- rb_sys_warning(link->path);
- }
+
+ status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end, flags, func, arg);
+ free(buf);
+ free(new_beg);
+ if (status) break;
+ }
+
+ closedir(dirp);
+ }
+ else if (plain) {
+ struct glob_pattern **copy_beg, **copy_end, **cur2;
+
+ copy_beg = copy_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
+ if (!copy_beg) return -1;
+ for (cur = beg; cur < end; ++cur)
+ *copy_end++ = (*cur)->type == PLAIN ? *cur : 0;
+
+ for (cur = copy_beg; cur < copy_end; ++cur) {
+ if (*cur) {
+ char *buf;
+ char *name;
+ name = GLOB_ALLOC_N(char, strlen((*cur)->str) + 1);
+ if (!name) {
+ status = -1;
+ break;
+ }
+ strcpy(name, (*cur)->str);
+ if (escape) remove_backslashes(name);
+
+ new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
+ if (!new_beg) {
+ free(name);
+ status = -1;
+ break;
+ }
+ *new_end++ = (*cur)->next;
+ for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
+ if (*cur2 && fnmatch((*cur2)->str, name, flags) == 0) {
+ *new_end++ = (*cur2)->next;
+ *cur2 = 0;
}
- tmp = link;
- link = link->next;
- free(tmp->path);
- free(tmp);
}
- break;
+
+ buf = join_path(path, dirsep, name);
+ free(name);
+ if (!buf) {
+ free(new_beg);
+ status = -1;
+ break;
+ }
+ status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg);
+ free(buf);
+ free(new_beg);
+ if (status) break;
}
}
- p = m;
+
+ free(copy_beg);
}
+
return status;
}
-static void
-rb_glob2(path, flags, func, arg)
- char *path;
+static int
+ruby_glob0(path, flags, func, arg)
+ const char *path;
int flags;
- void (*func) _((const char*, VALUE));
+ ruby_glob_func *func;
VALUE arg;
{
- int status = glob_helper(path, 0, flags, func, arg);
- if (status) rb_jump_tag(status);
+ struct glob_pattern *list;
+ const char *root, *start;
+ char *buf;
+ int n;
+ int status;
+
+ start = root = path;
+ flags |= FNM_SYSCASE;
+#if defined DOSISH
+ root = rb_path_skip_prefix(root);
+#endif
+
+ if (root && *root == '/') root++;
+
+ n = root - start;
+ buf = GLOB_ALLOC_N(char, n + 1);
+ if (!buf) return -1;
+ MEMCPY(buf, start, char, n);
+ buf[n] = '\0';
+
+ list = glob_make_pattern(root, flags);
+ if (!list) {
+ free(buf);
+ return -1;
+ }
+ status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg);
+ glob_free_pattern(list);
+ free(buf);
+
+ return status;
}
-void
-rb_glob(path, func, arg)
- char *path;
- void (*func) _((const char*, VALUE));
+int
+ruby_glob(path, flags, func, arg)
+ const char *path;
+ int flags;
+ ruby_glob_func *func;
VALUE arg;
{
- rb_glob2(path, 0, func, arg);
+ return ruby_glob0(path, flags & ~GLOB_VERBOSE, func, arg);
}
-void
-rb_globi(path, func, arg)
- char *path;
- void (*func) _((const char*, VALUE));
- VALUE arg;
+static int rb_glob_caller _((const char *, VALUE));
+
+static int
+rb_glob_caller(path, a)
+ const char *path;
+ VALUE a;
{
- rb_glob2(path, FNM_CASEFOLD, func, arg);
+ int status;
+ struct glob_args *args = (struct glob_args *)a;
+
+ args->c = path;
+ rb_protect(glob_func_caller, a, &status);
+ return status;
}
-static void
-push_pattern(path, ary)
+static int
+rb_glob2(path, flags, func, arg)
const char *path;
- VALUE ary;
+ int flags;
+ void (*func) _((const char *, VALUE));
+ VALUE arg;
{
- VALUE str = rb_tainted_str_new2(path);
+ struct glob_args args;
- if (ary) {
- rb_ary_push(ary, str);
- }
- else {
- rb_yield(str);
+ args.func = func;
+ args.v = arg;
+
+ if (flags & FNM_SYSCASE) {
+ rb_warning("Dir.glob() ignores File::FNM_CASEFOLD");
}
+
+ return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
}
-static void
-push_globs(ary, s, flags)
- VALUE ary;
- char *s;
- int flags;
+void
+rb_glob(path, func, arg)
+ const char *path;
+ void (*func) _((const char*, VALUE));
+ VALUE arg;
{
- rb_glob2(s, flags, push_pattern, ary);
+ int status = rb_glob2(path, 0, func, arg);
+ if (status) GLOB_JUMP_TAG(status);
}
+static void push_pattern _((const char* path, VALUE ary));
static void
-push_braces(ary, s, flags)
+push_pattern(path, ary)
+ const char *path;
VALUE ary;
- char *s;
+{
+ rb_ary_push(ary, rb_tainted_str_new2(path));
+}
+
+int
+ruby_brace_expand(str, flags, func, arg)
+ const char *str;
int flags;
+ ruby_glob_func *func;
+ VALUE arg;
{
- char *buf;
- char *p, *t, *b;
- char *lbrace, *rbrace;
- int nest = 0;
+ const int escape = !(flags & FNM_NOESCAPE);
+ const char *p = str;
+ const char *s = p;
+ const char *lbrace = 0, *rbrace = 0;
+ int nest = 0, status = 0;
- p = s;
- lbrace = rbrace = 0;
while (*p) {
- if (*p == '{') {
+ if (*p == '{' && nest++ == 0) {
lbrace = p;
- break;
}
- p++;
- }
- while (*p) {
- if (*p == '{') nest++;
- if (*p == '}' && --nest == 0) {
+ if (*p == '}' && --nest <= 0) {
rbrace = p;
break;
}
- p++;
+ if (*p == '\\' && escape) {
+ if (!*++p) break;
+ }
+ Inc(p);
}
if (lbrace && rbrace) {
- int len = strlen(s);
- buf = xmalloc(len + 1);
+ char *buf = GLOB_ALLOC_N(char, strlen(s) + 1);
+ long shift;
+
+ if (!buf) return -1;
memcpy(buf, s, lbrace-s);
- b = buf + (lbrace-s);
+ shift = (lbrace-s);
p = lbrace;
- while (*p != '}') {
- t = p + 1;
- for (p = t; *p!='}' && *p!=','; p++) {
- /* skip inner braces */
- if (*p == '{') while (*p!='}') p++;
+ while (p < rbrace) {
+ const char *t = ++p;
+ nest = 0;
+ while (p < rbrace && !(*p == ',' && nest == 0)) {
+ if (*p == '{') nest++;
+ if (*p == '}') nest--;
+ if (*p == '\\' && escape) {
+ if (++p == rbrace) break;
+ }
+ Inc(p);
}
- memcpy(b, t, p-t);
- strcpy(b+(p-t), rbrace+1);
- push_braces(ary, buf, flags);
+ memcpy(buf+shift, t, p-t);
+ strcpy(buf+shift+(p-t), rbrace+1);
+ status = ruby_brace_expand(buf, flags, func, arg);
+ if (status) break;
}
free(buf);
}
- else {
- push_globs(ary, s, flags);
+ else if (!lbrace && !rbrace) {
+ status = (*func)(s, arg);
}
+
+ return status;
+}
+
+struct brace_args {
+ ruby_glob_func *func;
+ VALUE value;
+ int flags;
+};
+
+static int glob_brace _((const char *, VALUE));
+static int
+glob_brace(path, val)
+ const char *path;
+ VALUE val;
+{
+ struct brace_args *arg = (struct brace_args *)val;
+
+ return ruby_glob0(path, arg->flags, arg->func, arg->value);
}
-#define isdelim(c) ((c)=='\0')
+static int
+ruby_brace_glob0(str, flags, func, arg)
+ const char *str;
+ int flags;
+ ruby_glob_func *func;
+ VALUE arg;
+{
+ struct brace_args args;
+
+ args.func = func;
+ args.value = arg;
+ args.flags = flags;
+ return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args);
+}
+
+int
+ruby_brace_glob(str, flags, func, arg)
+ const char *str;
+ int flags;
+ ruby_glob_func *func;
+ VALUE arg;
+{
+ return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg);
+}
+
+static int
+push_glob(VALUE ary, const char *str, int flags)
+{
+ struct glob_args args;
+
+ args.func = push_pattern;
+ args.v = ary;
+ return ruby_brace_glob0(str, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
+}
static VALUE
-rb_push_glob(str, flags)
+rb_push_glob(str, flags) /* '\0' is delimiter */
VALUE str;
int flags;
{
- char *p, *pend;
- char *buf;
- char *t;
- int nest, maxnest;
- int noescape = flags & FNM_NOESCAPE;
+ long offset = 0;
VALUE ary;
- if (rb_block_given_p())
- ary = 0;
- else
- ary = rb_ary_new();
-
+ ary = rb_ary_new();
SafeStringValue(str);
- buf = xmalloc(RSTRING(str)->len + 1);
-
- p = RSTRING(str)->ptr;
- pend = p + RSTRING(str)->len;
-
- while (p < pend) {
- t = buf;
- nest = maxnest = 0;
- while (p < pend && isdelim(*p)) p++;
- while (p < pend && !isdelim(*p)) {
- if (*p == '{') nest++, maxnest++;
- if (*p == '}') nest--;
- if (!noescape && *p == '\\') {
- *t++ = *p++;
- if (p == pend) break;
- }
- *t++ = *p++;
- }
- *t = '\0';
- if (maxnest == 0) {
- push_globs(ary, buf, flags);
- }
- else if (nest == 0) {
- push_braces(ary, buf, flags);
- }
- /* else unmatched braces */
+
+ while (offset < RSTRING_LEN(str)) {
+ int status = push_glob(ary, RSTRING(str)->ptr + offset, flags);
+ char *p, *pend;
+ if (status) GLOB_JUMP_TAG(status);
+ if (offset >= RSTRING_LEN(str)) break;
+ p = RSTRING(str)->ptr + offset;
+ p += strlen(p) + 1;
+ pend = RSTRING(str)->ptr + RSTRING_LEN(str);
+ while (p < pend && !*p)
+ p++;
+ offset = p - RSTRING(str)->ptr;
}
- free(buf);
return ary;
}
static VALUE
-dir_s_aref(obj, str)
- VALUE obj, str;
+dir_globs(argc, argv, flags)
+ long argc;
+ VALUE *argv;
+ int flags;
{
- return rb_push_glob(str, 0);
+ VALUE ary = rb_ary_new();
+ long i;
+
+ for (i = 0; i < argc; ++i) {
+ int status;
+ VALUE str = argv[i];
+ SafeStringValue(str);
+ status = push_glob(ary, RSTRING(str)->ptr, flags);
+ if (status) GLOB_JUMP_TAG(status);
+ }
+
+ return ary;
}
+/*
+ * call-seq:
+ * Dir[ array ] => array
+ * Dir[ string [, string ...] ] => array
+ *
+ * Equivalent to calling
+ * <code>Dir.glob(</code><i>array,</i><code>0)</code> and
+ * <code>Dir.glob([</code><i>string,...</i><code>],0)</code>.
+ *
+ */
+static VALUE
+dir_s_aref(int argc, VALUE *argv, VALUE obj)
+ {
+ if (argc == 1) {
+ return rb_push_glob(argv[0], 0);
+ }
+ return dir_globs(argc, argv, 0);
+ }
+
+/*
+ * call-seq:
+ * Dir.glob( pattern, [flags] ) => array
+ * Dir.glob( pattern, [flags] ) {| filename | block } => nil
+ *
+ * Returns the filenames found by expanding <i>pattern</i> which is
+ * an +Array+ of the patterns or the pattern +String+, either as an
+ * <i>array</i> or as parameters to the block. Note that this pattern
+ * is not a regexp (it's closer to a shell glob). See
+ * <code>File::fnmatch</code> for the meaning of the <i>flags</i>
+ * parameter. Note that case sensitivity depends on your system (so
+ * <code>File::FNM_CASEFOLD</code> is ignored)
+ *
+ * <code>*</code>:: Matches any file. Can be restricted by
+ * other values in the glob. <code>*</code>
+ * will match all files; <code>c*</code> will
+ * match all files beginning with
+ * <code>c</code>; <code>*c</code> will match
+ * all files ending with <code>c</code>; and
+ * <code>*c*</code> will match all files that
+ * have <code>c</code> in them (including at
+ * the beginning or end). Equivalent to
+ * <code>/ .* /x</code> in regexp.
+ * <code>**</code>:: Matches directories recursively.
+ * <code>?</code>:: Matches any one character. Equivalent to
+ * <code>/.{1}/</code> in regexp.
+ * <code>[set]</code>:: Matches any one character in +set+.
+ * Behaves exactly like character sets in
+ * Regexp, including set negation
+ * (<code>[^a-z]</code>).
+ * <code>{p,q}</code>:: Matches either literal <code>p</code> or
+ * literal <code>q</code>. Matching literals
+ * may be more than one character in length.
+ * More than two literals may be specified.
+ * Equivalent to pattern alternation in
+ * regexp.
+ * <code>\</code>:: Escapes the next metacharacter.
+ *
+ * Dir["config.?"] #=> ["config.h"]
+ * Dir.glob("config.?") #=> ["config.h"]
+ * Dir.glob("*.[a-z][a-z]") #=> ["main.rb"]
+ * Dir.glob("*.[^r]*") #=> ["config.h"]
+ * Dir.glob("*.{rb,h}") #=> ["main.rb", "config.h"]
+ * Dir.glob("*") #=> ["config.h", "main.rb"]
+ * Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "..", "config.h", "main.rb"]
+ *
+ * rbfiles = File.join("**", "*.rb")
+ * Dir.glob(rbfiles) #=> ["main.rb",
+ * "lib/song.rb",
+ * "lib/song/karaoke.rb"]
+ * libdirs = File.join("**", "lib")
+ * Dir.glob(libdirs) #=> ["lib"]
+ *
+ * librbfiles = File.join("**", "lib", "**", "*.rb")
+ * Dir.glob(librbfiles) #=> ["lib/song.rb",
+ * "lib/song/karaoke.rb"]
+ *
+ * librbfiles = File.join("**", "lib", "*.rb")
+ * Dir.glob(librbfiles) #=> ["lib/song.rb"]
+ */
static VALUE
dir_s_glob(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
- VALUE str, rflags;
+ VALUE str, rflags, ary;
int flags;
if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
@@ -1031,30 +1761,168 @@ dir_s_glob(argc, argv, obj)
else
flags = 0;
- return rb_push_glob(str, flags);
+ ary = rb_check_array_type(str);
+ if (NIL_P(ary)) {
+ ary = rb_push_glob(str, flags);
+ }
+ else {
+ volatile VALUE v = ary;
+ ary = dir_globs(RARRAY_LEN(v), RARRAY_PTR(v), flags);
+ }
+
+ if (rb_block_given_p()) {
+ rb_ary_each(ary);
+ return Qnil;
+ }
+ return ary;
}
static VALUE
+dir_open_dir(path)
+ VALUE path;
+{
+ VALUE dir = rb_funcall(rb_cDir, rb_intern("open"), 1, path);
+
+ if (TYPE(dir) != T_DATA ||
+ RDATA(dir)->dfree != (RUBY_DATA_FUNC)free_dir) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Dir)",
+ rb_obj_classname(dir));
+ }
+ return dir;
+}
+
+
+/*
+ * call-seq:
+ * Dir.foreach( dirname ) {| filename | block } => nil
+ *
+ * Calls the block once for each entry in the named directory, passing
+ * the filename of each entry as a parameter to the block.
+ *
+ * Dir.foreach("testdir") {|x| puts "Got #{x}" }
+ *
+ * <em>produces:</em>
+ *
+ * Got .
+ * Got ..
+ * Got config.h
+ * Got main.rb
+ *
+ */
+static VALUE
dir_foreach(io, dirname)
VALUE io, dirname;
{
VALUE dir;
- dir = rb_funcall(rb_cDir, rb_intern("open"), 1, dirname);
+ RETURN_ENUMERATOR(io, 1, &dirname);
+ dir = dir_open_dir(dirname);
rb_ensure(dir_each, dir, dir_close, dir);
return Qnil;
}
+/*
+ * call-seq:
+ * Dir.entries( dirname ) => array
+ *
+ * Returns an array containing all of the filenames in the given
+ * directory. Will raise a <code>SystemCallError</code> if the named
+ * directory doesn't exist.
+ *
+ * Dir.entries("testdir") #=> [".", "..", "config.h", "main.rb"]
+ *
+ */
static VALUE
dir_entries(io, dirname)
VALUE io, dirname;
{
VALUE dir;
- dir = rb_funcall(rb_cDir, rb_intern("open"), 1, dirname);
+ dir = dir_open_dir(dirname);
return rb_ensure(rb_Array, dir, dir_close, dir);
}
+/*
+ * call-seq:
+ * File.fnmatch( pattern, path, [flags] ) => (true or false)
+ * File.fnmatch?( pattern, path, [flags] ) => (true or false)
+ *
+ * Returns true if <i>path</i> matches against <i>pattern</i> The
+ * pattern is not a regular expression; instead it follows rules
+ * similar to shell filename globbing. It may contain the following
+ * metacharacters:
+ *
+ * <code>*</code>:: Matches any file. Can be restricted by
+ * other values in the glob. <code>*</code>
+ * will match all files; <code>c*</code> will
+ * match all files beginning with
+ * <code>c</code>; <code>*c</code> will match
+ * all files ending with <code>c</code>; and
+ * <code>*c*</code> will match all files that
+ * have <code>c</code> in them (including at
+ * the beginning or end). Equivalent to
+ * <code>/ .* /x</code> in regexp.
+ * <code>**</code>:: Matches directories recursively or files
+ * expansively.
+ * <code>?</code>:: Matches any one character. Equivalent to
+ * <code>/.{1}/</code> in regexp.
+ * <code>[set]</code>:: Matches any one character in +set+.
+ * Behaves exactly like character sets in
+ * Regexp, including set negation
+ * (<code>[^a-z]</code>).
+ * <code>\</code>:: Escapes the next metacharacter.
+ *
+ * <i>flags</i> is a bitwise OR of the <code>FNM_xxx</code>
+ * parameters. The same glob pattern and flags are used by
+ * <code>Dir::glob</code>.
+ *
+ * File.fnmatch('cat', 'cat') #=> true : match entire string
+ * File.fnmatch('cat', 'category') #=> false : only match partial string
+ * File.fnmatch('c{at,ub}s', 'cats') #=> false : { } isn't supported
+ *
+ * File.fnmatch('c?t', 'cat') #=> true : '?' match only 1 character
+ * File.fnmatch('c??t', 'cat') #=> false : ditto
+ * File.fnmatch('c*', 'cats') #=> true : '*' match 0 or more characters
+ * File.fnmatch('c*t', 'c/a/b/t') #=> true : ditto
+ * File.fnmatch('ca[a-z]', 'cat') #=> true : inclusive bracket expression
+ * File.fnmatch('ca[^t]', 'cat') #=> false : exclusive bracket expression ('^' or '!')
+ *
+ * File.fnmatch('cat', 'CAT') #=> false : case sensitive
+ * File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true : case insensitive
+ *
+ * File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false : wildcard doesn't match '/' on FNM_PATHNAME
+ * File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false : ditto
+ * File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false : ditto
+ *
+ * File.fnmatch('\?', '?') #=> true : escaped wildcard becomes ordinary
+ * File.fnmatch('\a', 'a') #=> true : escaped ordinary remains ordinary
+ * File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true : FNM_NOESACPE makes '\' ordinary
+ * File.fnmatch('[\?]', '?') #=> true : can escape inside bracket expression
+ *
+ * File.fnmatch('*', '.profile') #=> false : wildcard doesn't match leading
+ * File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true period by default.
+ * File.fnmatch('.*', '.profile') #=> true
+ *
+ * rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string.
+ * File.fnmatch(rbfiles, 'main.rb') #=> false
+ * File.fnmatch(rbfiles, './main.rb') #=> false
+ * File.fnmatch(rbfiles, 'lib/song.rb') #=> true
+ * File.fnmatch('**.rb', 'main.rb') #=> true
+ * File.fnmatch('**.rb', './main.rb') #=> false
+ * File.fnmatch('**.rb', 'lib/song.rb') #=> true
+ * File.fnmatch('*', 'dave/.profile') #=> true
+ *
+ * pattern = '*' '/' '*'
+ * File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME) #=> false
+ * File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
+ *
+ * pattern = '**' '/' 'foo'
+ * File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME) #=> true
+ * File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME) #=> true
+ * File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true
+ * File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME) #=> false
+ * File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
+ */
static VALUE
file_s_fnmatch(argc, argv, obj)
int argc;
@@ -1079,6 +1947,17 @@ file_s_fnmatch(argc, argv, obj)
return Qfalse;
}
+/*
+ * Objects of class <code>Dir</code> are directory streams representing
+ * directories in the underlying file system. They provide a variety of
+ * ways to list directories and their contents. See also
+ * <code>File</code>.
+ *
+ * The directory used in these examples contains the two regular files
+ * (<code>config.h</code> and <code>main.rb</code>), the parent
+ * directory (<code>..</code>), and the directory itself
+ * (<code>.</code>).
+ */
void
Init_Dir()
{
@@ -1093,6 +1972,7 @@ Init_Dir()
rb_define_method(rb_cDir,"initialize", dir_initialize, 1);
rb_define_method(rb_cDir,"path", dir_path, 0);
+ rb_define_method(rb_cDir,"inspect", dir_inspect, 0);
rb_define_method(rb_cDir,"read", dir_read, 0);
rb_define_method(rb_cDir,"each", dir_each, 0);
rb_define_method(rb_cDir,"rewind", dir_rewind, 0);
@@ -1112,7 +1992,7 @@ Init_Dir()
rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1);
- rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, 1);
+ rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, -1);
rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
@@ -1121,4 +2001,5 @@ Init_Dir()
rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
+ rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE));
}
diff --git a/distruby.rb b/distruby.rb
new file mode 100644
index 0000000000..613da0eb9c
--- /dev/null
+++ b/distruby.rb
@@ -0,0 +1,59 @@
+#!./miniruby
+
+if RUBY_PATCHLEVEL.zero?
+ dirname = sprintf 'ruby-%s', RUBY_VERSION
+ tagname = dirname.gsub /ruby-(\d)\.(\d)\.(\d)/, 'v\1_\2_\3'
+else
+ dirname = sprintf 'ruby-%s-p%u', RUBY_VERSION, RUBY_PATCHLEVEL
+ tagname = dirname.gsub /ruby-(\d)\.(\d)\.(\d)-p/, 'v\1_\2_\3_'
+end
+tgzname = dirname + '.tar.gz'
+tbzname = dirname + '.tar.bz2'
+zipname = dirname + '.zip'
+repos = 'http://svn.ruby-lang.org/repos/ruby/tags/' + tagname
+
+STDERR.puts 'exporting sources...'
+system 'svn', 'export', '-q', repos, dirname
+Dir.chdir dirname do
+ STDERR.puts 'generating configure...'
+ system 'autoconf'
+ system 'rm', '-rf', 'autom4te.cache'
+
+ STDERR.puts 'generating parse.c...'
+ system 'bison', '-y', '-o', 'parse.c', 'parse.y'
+end
+
+STDERR.puts 'generating tarballs...'
+ENV['GZIP'] = '-9'
+system 'tar', 'chofzp', tgzname, dirname
+system 'tar', 'chojfp', tbzname, dirname
+system 'zip', '-q9r', zipname, dirname
+
+require 'digest/md5'
+require 'digest/sha2'
+for name in [tgzname, tbzname, zipname] do
+ open name, 'rb' do |fp|
+ str = fp.read
+ md5 = Digest::MD5.hexdigest str
+ sha = Digest::SHA256.hexdigest str
+ printf "MD5(%s)= %s\nSHA256(%s)= %s\nSIZE(%s)= %s\n\n",
+ name, md5,
+ name, sha,
+ name, str.size
+ end
+end
+
+
+
+#
+# Local Variables:
+# mode: ruby
+# code: utf-8
+# indent-tabs-mode: t
+# tab-width: 3
+# ruby-indent-level: 3
+# fill-column: 79
+# default-justification: full
+# End:
+# vi: ts=3 sw=3
+
diff --git a/djgpp/configure.bat b/djgpp/configure.bat
index e6a5d79d4a..e6a5d79d4a 100644..100755
--- a/djgpp/configure.bat
+++ b/djgpp/configure.bat
diff --git a/dln.c b/dln.c
index be3e6c4b6b..5ba25b6415 100644
--- a/dln.c
+++ b/dln.c
@@ -27,10 +27,6 @@
char *dln_argv0;
#endif
-#ifdef _AIX
-#pragma alloca
-#endif
-
#if defined(HAVE_ALLOCA_H)
#include <alloca.h>
#endif
@@ -85,19 +81,28 @@ char *getenv();
# include "macruby_private.h"
#endif
+#if defined(__APPLE__) && defined(__MACH__) /* Mac OS X */
+# if defined(HAVE_DLOPEN)
+ /* Mac OS X with dlopen (10.3 or later) */
+# define MACOSX_DLOPEN
+# else
+# define MACOSX_DYLD
+# endif
+#endif
+
#ifdef __BEOS__
# include <image.h>
#endif
-int eaccess();
+#ifndef NO_DLN_LOAD
-#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(__APPLE__)
+#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(MACOSX_DYLD) && !defined(_UNICOSMP)
/* dynamic load with dlopen() */
# define USE_DLN_DLOPEN
#endif
#ifndef FUNCNAME_PATTERN
-# if defined(__hp9000s300) || (defined(__NetBSD__) && !defined(__ELF__)) || defined(__BORLANDC__) || (defined(__FreeBSD__) && !defined(__ELF__)) || (defined(__OpenBSD__) && !defined(__ELF__)) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__)
+# if defined(__hp9000s300) || (defined(__NetBSD__) && !defined(__ELF__)) || defined(__BORLANDC__) || (defined(__FreeBSD__) && !defined(__ELF__)) || (defined(__OpenBSD__) && !defined(__ELF__)) || defined(NeXT) || defined(__WATCOMC__) || defined(MACOSX_DYLD)
# define FUNCNAME_PATTERN "_Init_%s"
# else
# define FUNCNAME_PATTERN "Init_%s"
@@ -160,7 +165,7 @@ static int dln_errno;
#define DLN_ENOEXEC ENOEXEC /* Exec format error */
#define DLN_ECONFL 1201 /* Symbol name conflict */
-#define DLN_ENOINIT 1202 /* No inititalizer given */
+#define DLN_ENOINIT 1202 /* No initializer given */
#define DLN_EUNDEF 1203 /* Undefine symbol remains */
#define DLN_ENOTLIB 1204 /* Not a library file */
#define DLN_EBADLIB 1205 /* Malformed library file */
@@ -395,7 +400,7 @@ dln_init(prog)
if (c != '!') goto err_noexec;
p = buf;
- /* skip forwading spaces */
+ /* skip forwarding spaces */
while (read(fd, &c, 1) == 1) {
if (c == '\n') goto err_noexec;
if (c != '\t' && c != ' ') {
@@ -640,7 +645,7 @@ load_1(fd, disp, need_init)
long disp;
const char *need_init;
{
- static char *libc = LIBC_NAME;
+ static const char *libc = LIBC_NAME;
struct exec hdr;
struct relocation_info *reloc = NULL;
long block = 0;
@@ -960,8 +965,9 @@ load_lib(lib)
dln_errno = DLN_EBADLIB;
if (lib[0] == '-' && lib[1] == 'l') {
- char *p = alloca(strlen(lib) + 4);
- sprintf(p, "lib%s.a", lib+2);
+ long len = strlen(lib) + 4;
+ char *p = alloca(len);
+ snprintf(p, len, "lib%s.a", lib+2);
lib = p;
}
@@ -1115,7 +1121,7 @@ dln_sym(name)
#endif /* USE_DLN_A_OUT */
#ifdef USE_DLN_DLOPEN
-# ifdef __NetBSD__
+# if defined(__NetBSD__) && defined(__NetBSD_Version__) && __NetBSD_Version__ < 105000000
# include <nlist.h>
# include <link.h>
# else
@@ -1144,7 +1150,7 @@ dln_sym(name)
#endif
#endif
#else
-#ifdef __APPLE__
+#ifdef MACOSX_DYLD
#include <mach-o/dyld.h>
#endif
#endif
@@ -1172,7 +1178,7 @@ dln_strerror()
case DLN_ECONFL:
return "Symbol name conflict";
case DLN_ENOINIT:
- return "No inititalizer given";
+ return "No initializer given";
case DLN_EUNDEF:
return "Unresolved symbols";
case DLN_ENOTLIB:
@@ -1233,7 +1239,7 @@ aix_loaderror(const char *pathname)
{L_ERROR_MEMBER,
"file not an archive or does not contain requested member:"},
{L_ERROR_TYPE, "symbol table mismatch:"},
- {L_ERROR_ALIGN, "text allignment in file is wrong."},
+ {L_ERROR_ALIGN, "text alignment in file is wrong."},
{L_ERROR_SYSTEM, "System error:"},
{L_ERROR_ERRNO, NULL}
};
@@ -1261,10 +1267,29 @@ aix_loaderror(const char *pathname)
}
#endif
+#if defined(__VMS)
+#include <starlet.h>
+#include <rms.h>
+#include <stsdef.h>
+#include <unixlib.h>
+#include <descrip.h>
+#include <lib$routines.h>
+
+static char *vms_filespec;
+static int vms_fileact(char *filespec, int type);
+static long vms_fisexh(long *sigarr, long *mecarr);
+#endif
+
+#endif /* NO_DLN_LOAD */
+
void*
dln_load(file)
const char *file;
{
+#ifdef NO_DLN_LOAD
+ rb_raise(rb_eLoadError, "this executable file can't load extension libraries");
+#else
+
#if !defined(_AIX) && !defined(NeXT)
const char *error = 0;
#define DLN_ERROR() (error = dln_strerror(), strcpy(ALLOCA_N(char, strlen(error) + 1), error))
@@ -1318,6 +1343,9 @@ dln_load(file)
#ifndef RTLD_LAZY
# define RTLD_LAZY 1
#endif
+#ifdef __INTERIX
+# undef RTLD_GLOBAL
+#endif
#ifndef RTLD_GLOBAL
# define RTLD_GLOBAL 0
#endif
@@ -1384,7 +1412,7 @@ dln_load(file)
}
#endif /* _AIX */
-#if defined(NeXT) || defined(__APPLE__)
+#if defined(NeXT) || defined(MACOSX_DYLD)
#define DLN_DEFINED
/*----------------------------------------------------
By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
@@ -1508,7 +1536,7 @@ dln_load(file)
}
#endif /* __BEOS__*/
-#ifdef __MACOS__
+#ifdef __MACOS__ /* Mac OS 9 or before */
# define DLN_DEFINED
{
OSErr err;
@@ -1558,9 +1586,16 @@ dln_load(file)
#if defined(__VMS)
#define DLN_DEFINED
{
- void *handle, (*init_fct)();
+ long status;
+ void (*init_fct)();
char *fname, *p1, *p2;
+ $DESCRIPTOR(fname_d, "");
+ $DESCRIPTOR(image_d, "");
+ $DESCRIPTOR(buf_d, "");
+
+ decc$to_vms(file, vms_fileact, 0, 0);
+
fname = (char *)__alloca(strlen(file)+1);
strcpy(fname,file);
if (p1 = strrchr(fname,'/'))
@@ -1568,19 +1603,35 @@ dln_load(file)
if (p2 = strrchr(fname,'.'))
*p2 = '\0';
- if ((handle = (void*)dlopen(fname, 0)) == NULL) {
+ fname_d.dsc$w_length = strlen(fname);
+ fname_d.dsc$a_pointer = fname;
+ image_d.dsc$w_length = strlen(vms_filespec);
+ image_d.dsc$a_pointer = vms_filespec;
+ buf_d.dsc$w_length = strlen(buf);
+ buf_d.dsc$a_pointer = buf;
+
+ lib$establish(vms_fisexh);
+
+ status = lib$find_image_symbol (
+ &fname_d,
+ &buf_d,
+ &init_fct,
+ &image_d);
+
+ lib$establish(0);
+
+ if (status == RMS$_FNF) {
error = dln_strerror();
goto failed;
- }
-
- if ((init_fct = (void (*)())dlsym(handle, buf)) == NULL) {
+ } else if (!$VMS_STATUS_SUCCESS(status)) {
error = DLN_ERROR();
- dlclose(handle);
goto failed;
}
+
/* Call the init code */
(*init_fct)();
- return handle;
+
+ return 1;
}
#endif /* __VMS */
@@ -1594,6 +1645,8 @@ dln_load(file)
failed:
rb_loaderror("%s - %s", error, file);
#endif
+
+#endif /* NO_DLN_LOAD */
return 0; /* dummy return */
}
@@ -1632,63 +1685,35 @@ dln_find_file(fname, path)
#endif
}
-#if defined(__CYGWIN32__)
-const char *
-conv_to_posix_path(win32, posix, len)
- char *win32;
- char *posix;
- int len;
-{
- char *first = win32;
- char *p = win32;
- char *dst = posix;
-
- for (p = win32; *p; p++)
- if (*p == ';') {
- *p = 0;
- cygwin32_conv_to_posix_path(first, posix);
- posix += strlen(posix);
- *posix++ = ':';
- first = p + 1;
- *p = ';';
- }
- if (len < strlen(first))
- fprintf(stderr, "PATH length too long: %s\n", first);
- else
- cygwin32_conv_to_posix_path(first, posix);
- return dst;
-}
-#endif
-
static char fbuf[MAXPATHLEN];
static char *
dln_find_1(fname, path, exe_flag)
- char *fname;
- char *path;
+ const char *fname;
+ const char *path;
int exe_flag; /* non 0 if looking for executable. */
{
- register char *dp;
- register char *ep;
+ register const char *dp;
+ register const char *ep;
register char *bp;
struct stat st;
#ifdef __MACOS__
const char* mac_fullpath;
#endif
- if (!fname) return fname;
- if (fname[0] == '/') return fname;
+ if (!fname) return (char *)fname;
+ if (fname[0] == '/') return (char *)fname;
if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0)
- return fname;
- if (exe_flag && strchr(fname, '/')) return fname;
+ return (char *)fname;
+ if (exe_flag && strchr(fname, '/')) return (char *)fname;
#ifdef DOSISH
- if (fname[0] == '\\') return fname;
+ if (fname[0] == '\\') return (char *)fname;
# ifdef DOSISH_DRIVE_LETTER
- if (strlen(fname) > 2 && fname[1] == ':') return fname;
+ if (strlen(fname) > 2 && fname[1] == ':') return (char *)fname;
# endif
if (strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0)
- return fname;
- if (exe_flag && strchr(fname, '\\')) return fname;
+ return (char *)fname;
+ if (exe_flag && strchr(fname, '\\')) return (char *)fname;
#endif
for (dp = path;; dp = ++ep) {
@@ -1756,26 +1781,9 @@ dln_find_1(fname, path, exe_flag)
}
memcpy(bp, fname, i + 1);
-#ifndef __MACOS__
- if (stat(fbuf, &st) == 0) {
- if (exe_flag == 0) return fbuf;
- /* looking for executable */
- if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
- return fbuf;
- }
-#else
- if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) {
- if (exe_flag == 0) return mac_fullpath;
- /* looking for executable */
- if (stat(mac_fullpath, &st) == 0) {
- if (!S_ISDIR(st.st_mode) && eaccess(mac_fullpath, X_OK) == 0)
- return mac_fullpath;
- }
- }
-#endif
#if defined(DOSISH)
if (exe_flag) {
- static const char *extension[] = {
+ static const char extension[][5] = {
#if defined(MSDOS)
".com", ".exe", ".bat",
#if defined(DJGPP)
@@ -1788,11 +1796,10 @@ dln_find_1(fname, path, exe_flag)
".r", ".R", ".x", ".X", ".bat", ".BAT",
/* __human68k__ */
#endif
- (char *) NULL
};
int j;
- for (j = 0; extension[j]; j++) {
+ for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
if (fspace < strlen(extension[j])) {
fprintf(stderr, "openpath: pathname too long (ignored)\n");
fprintf(stderr, "\tDirectory \"%.*s\"\n", (int) (bp - fbuf), fbuf);
@@ -1809,9 +1816,28 @@ dln_find_1(fname, path, exe_flag)
#endif
}
+ goto next;
}
#endif /* MSDOS or _WIN32 or __human68k__ or __EMX__ */
+#ifndef __MACOS__
+ if (stat(fbuf, &st) == 0) {
+ if (exe_flag == 0) return fbuf;
+ /* looking for executable */
+ if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
+ return fbuf;
+ }
+#else
+ if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) {
+ if (exe_flag == 0) return mac_fullpath;
+ /* looking for executable */
+ if (stat(mac_fullpath, &st) == 0) {
+ if (!S_ISDIR(st.st_mode) && eaccess(mac_fullpath, X_OK) == 0)
+ return mac_fullpath;
+ }
+ }
+#endif
+
next:
/* if not, and no other alternatives, life is bleak */
if (*ep == '\0') {
@@ -1821,3 +1847,24 @@ dln_find_1(fname, path, exe_flag)
/* otherwise try the next component in the search path */
}
}
+
+#if defined(__VMS)
+
+/* action routine for decc$to_vms */
+static int vms_fileact(char *filespec, int type)
+{
+ if (vms_filespec)
+ free(vms_filespec);
+ vms_filespec = malloc(strlen(filespec)+1);
+ strcpy(vms_filespec, filespec);
+ return 1;
+}
+
+/* exception handler for LIB$FIND_IMAGE_SYMBOL */
+static long vms_fisexh(long *sigarr, long *mecarr)
+{
+ sys$unwind(1, 0);
+ return 1;
+}
+
+#endif /* __VMS */
diff --git a/dmydln.c b/dmydln.c
new file mode 100644
index 0000000000..09ea06806c
--- /dev/null
+++ b/dmydln.c
@@ -0,0 +1,2 @@
+#define NO_DLN_LOAD 1
+#include "dln.c"
diff --git a/doc/NEWS b/doc/NEWS-1.8.0
index b4445fa59f..b4445fa59f 100644
--- a/doc/NEWS
+++ b/doc/NEWS-1.8.0
diff --git a/doc/irb/irb.rd.ja b/doc/irb/irb.rd.ja
index bf8ac5d517..338dcc644e 100644
--- a/doc/irb/irb.rd.ja
+++ b/doc/irb/irb.rd.ja
@@ -1,8 +1,8 @@
irb -- interactive ruby
- $Release Version: 0.9 $
+ $Release Version: 0.9.5 $
$Revision$
$Date$
- by Keiju ISHITSUKA(keiju@ishitsuka.com)
+ by Keiju ISHITSUKA(keiju@ruby-lang.org)
=begin
= irb¤È¤Ï?
@@ -112,6 +112,7 @@ irbµ¯Æ°»þ¤Ë``~/.irbrc''¤òÆÉ¤ß¹þ¤ß¤Þ¤¹. ¤â¤·Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ï,
IRB.conf[:PROMPT][:MY_PROMPT] = { # ¥×¥í¥ó¥×¥È¥â¡¼¥É¤Î̾Á°
:PROMPT_I => nil, # Ä̾ï¤Î¥×¥í¥ó¥×¥È
+ :PROMPT_N => nil, # ·Ñ³¹Ô¤Î¥×¥í¥ó¥×¥È
:PROMPT_S => nil, # ʸ»úÎó¤Ê¤É¤Î·Ñ³¹Ô¤Î¥×¥í¥ó¥×¥È
:PROMPT_C => nil, # ¼°¤¬·Ñ³¤·¤Æ¤¤¤ë»þ¤Î¥×¥í¥ó¥×¥È
:RETURN => " ==>%s\n" # ¥ê¥¿¡¼¥ó»þ¤Î¥×¥í¥ó¥×¥È
@@ -126,7 +127,7 @@ OK¤Ç¤¹.
IRB.conf[:PROMPT_MODE] = :MY_PROMPT
-PROMPT_I, PROMPT_S, PROMPT_C¤Ï, ¥Õ¥©¡¼¥Þ¥Ã¥È¤ò»ØÄꤷ¤Þ¤¹.
+PROMPT_I, PROMPT_N, PROMPT_S, PROMPT_C¤Ï, ¥Õ¥©¡¼¥Þ¥Ã¥È¤ò»ØÄꤷ¤Þ¤¹.
%N µ¯Æ°¤·¤Æ¤¤¤ë¥³¥Þ¥ó¥É̾¤¬½ÐÎϤµ¤ì¤ë.
%m main¥ª¥Ö¥¸¥§¥¯¥È(self)¤¬to_s¤Ç½ÐÎϤµ¤ì¤ë.
@@ -141,6 +142,7 @@ PROMPT_I, PROMPT_S, PROMPT_C¤Ï, ¥Õ¥©¡¼¥Þ¥Ã¥È¤ò»ØÄꤷ¤Þ¤¹.
IRB.conf[:PROMPT_MODE][:DEFAULT] = {
:PROMPT_I => "%N(%m):%03n:%i> ",
+ :PROMPT_N => "%N(%m):%03n:%i> ",
:PROMPT_S => "%N(%m):%03n:%i%l ",
:PROMPT_C => "%N(%m):%03n:%i* ",
:RETURN => "%s\n"
diff --git a/enum.c b/enum.c
index ee0b05838f..df35c2fe03 100644
--- a/enum.c
+++ b/enum.c
@@ -15,7 +15,43 @@
#include "util.h"
VALUE rb_mEnumerable;
-static ID id_each, id_eqq, id_cmp;
+static ID id_each, id_eqq, id_cmp, id_size;
+
+struct iter_method_arg {
+ VALUE obj;
+ ID mid;
+ int argc;
+ VALUE *argv;
+};
+
+static VALUE iterate_method _((VALUE obj));
+static VALUE
+iterate_method(obj)
+ VALUE obj;
+{
+ struct iter_method_arg *arg;
+
+ arg = (struct iter_method_arg *)obj;
+ return rb_funcall2(arg->obj, arg->mid, arg->argc, arg->argv);
+}
+
+VALUE
+rb_block_call(obj, mid, argc, argv, bl_proc, data2)
+ VALUE obj;
+ ID mid;
+ int argc;
+ VALUE *argv;
+ VALUE (*bl_proc) (ANYARGS);
+ VALUE data2;
+{
+ struct iter_method_arg arg;
+
+ arg.obj = obj;
+ arg.mid = mid;
+ arg.argc = argc;
+ arg.argv = argv;
+ return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
+}
VALUE
rb_each(obj)
@@ -44,6 +80,24 @@ grep_iter_i(i, arg)
return Qnil;
}
+/*
+ * call-seq:
+ * enum.grep(pattern) => array
+ * enum.grep(pattern) {| obj | block } => array
+ *
+ * Returns an array of every element in <i>enum</i> for which
+ * <code>Pattern === element</code>. If the optional <em>block</em> is
+ * supplied, each matching element is passed to it, and the block's
+ * result is stored in the output array.
+ *
+ * (1..100).grep 38..44 #=> [38, 39, 40, 41, 42, 43, 44]
+ * c = IO.constants
+ * c.grep(/SEEK/) #=> ["SEEK_END", "SEEK_SET", "SEEK_CUR"]
+ * res = c.grep(/SEEK/) {|v| IO.const_get(v) }
+ * res #=> [2, 0, 1]
+ *
+ */
+
static VALUE
enum_grep(obj, pat)
VALUE obj, pat;
@@ -55,46 +109,222 @@ enum_grep(obj, pat)
arg[1] = ary;
rb_iterate(rb_each, obj, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
-
+
return ary;
}
+static VALUE count_i _((VALUE, VALUE));
+static VALUE
+count_i(i, memop)
+ VALUE i, memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ if (rb_equal(i, memo[1])) {
+ memo[0]++;
+ }
+ return Qnil;
+}
+
+static VALUE count_iter_i _((VALUE, VALUE));
+static VALUE
+count_iter_i(i, memop)
+ VALUE i, memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ if (RTEST(rb_yield(i))) {
+ memo[0]++;
+ }
+ return Qnil;
+}
+
+static VALUE count_all_i _((VALUE, VALUE));
+static VALUE
+count_all_i(i, memop)
+ VALUE i, memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ memo[0]++;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.count => int
+ * enum.count(item) => int
+ * enum.count {| obj | block } => int
+ *
+ * Returns the number of items in <i>enum</i>, where #size is called
+ * if it responds to it, otherwise the items are counted through
+ * enumeration. If an argument is given, counts the number of items
+ * in <i>enum</i>, for which equals to <i>item</i>. If a block is
+ * given, counts the number of elements yielding a true value.
+ *
+ * ary = [1, 2, 4, 2]
+ * ary.count # => 4
+ * ary.count(2) # => 2
+ * ary.count{|x|x%2==0} # => 3
+ *
+ */
+
+static VALUE
+enum_count(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE memo[2]; /* [count, condition value] */
+ rb_block_call_func *func;
+
+ if (argc == 0) {
+ if (rb_block_given_p()) {
+ func = count_iter_i;
+ }
+ else {
+ if (rb_respond_to(obj, id_size)) {
+ return rb_funcall(obj, id_size, 0, 0);
+ }
+ func = count_all_i;
+ }
+ }
+ else {
+ rb_scan_args(argc, argv, "1", &memo[1]);
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
+ func = count_i;
+ }
+
+ memo[0] = 0;
+ rb_block_call(obj, id_each, 0, 0, func, (VALUE)&memo);
+ return INT2NUM(memo[0]);
+}
+
static VALUE
find_i(i, memo)
VALUE i;
- NODE *memo;
+ VALUE *memo;
{
if (RTEST(rb_yield(i))) {
- memo->u2.value = Qtrue;
- memo->u1.value = i;
+ *memo = i;
rb_iter_break();
}
return Qnil;
}
+/*
+ * call-seq:
+ * enum.detect(ifnone = nil) {| obj | block } => obj or nil
+ * enum.find(ifnone = nil) {| obj | block } => obj or nil
+ *
+ * Passes each entry in <i>enum</i> to <em>block</em>. Returns the
+ * first for which <em>block</em> is not <code>false</code>. If no
+ * object matches, calls <i>ifnone</i> and returns its result when it
+ * is specified, or returns <code>nil</code>
+ *
+ * (1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
+ * (1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35
+ *
+ */
+
static VALUE
enum_find(argc, argv, obj)
int argc;
VALUE* argv;
VALUE obj;
{
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, Qfalse, 0);
+ VALUE memo = Qundef;
VALUE if_none;
rb_scan_args(argc, argv, "01", &if_none);
- rb_iterate(rb_each, obj, find_i, (VALUE)memo);
- if (memo->u2.value) {
- VALUE result = memo->u1.value;
- rb_gc_force_recycle((VALUE)memo);
- return result;
+ RETURN_ENUMERATOR(obj, argc, argv);
+ rb_iterate(rb_each, obj, find_i, (VALUE)&memo);
+ if (memo != Qundef) {
+ return memo;
}
- rb_gc_force_recycle((VALUE)memo);
if (!NIL_P(if_none)) {
return rb_funcall(if_none, rb_intern("call"), 0, 0);
}
return Qnil;
}
+static VALUE find_index_i _((VALUE, VALUE));
+static VALUE
+find_index_i(i, memop)
+ VALUE i;
+ VALUE memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ if (rb_equal(i, memo[2])) {
+ memo[0] = UINT2NUM(memo[1]);
+ rb_iter_break();
+ }
+ memo[1]++;
+ return Qnil;
+}
+
+static VALUE find_index_iter_i _((VALUE, VALUE));
+static VALUE
+find_index_iter_i(i, memop)
+ VALUE i;
+ VALUE memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ if (RTEST(rb_yield(i))) {
+ memo[0] = UINT2NUM(memo[1]);
+ rb_iter_break();
+ }
+ memo[1]++;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.find_index(value) => int or nil
+ * enum.find_index {| obj | block } => int or nil
+ *
+ * Compares each entry in <i>enum</i> with <em>value</em> or passes
+ * to <em>block</em>. Returns the index for the first for which the
+ * evaluated value is non-false. If no object matches, returns
+ * <code>nil</code>
+ *
+ * (1..10).find_index {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
+ * (1..100).find_index {|i| i % 5 == 0 and i % 7 == 0 } #=> 34
+ * (1..100).find_index(50) #=> 49
+ *
+ */
+
+static VALUE
+enum_find_index(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE memo[3]; /* [return value, current index, condition value] */
+ rb_block_call_func *func;
+
+ if (argc == 0) {
+ RETURN_ENUMERATOR(obj, 0, 0);
+ func = find_index_iter_i;
+ }
+ else {
+ rb_scan_args(argc, argv, "1", &memo[2]);
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
+ func = find_index_i;
+ }
+
+ memo[0] = Qnil;
+ memo[1] = 0;
+ rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
+ return memo[0];
+}
+
static VALUE
find_all_i(i, ary)
VALUE i, ary;
@@ -105,12 +335,26 @@ find_all_i(i, ary)
return Qnil;
}
+/*
+ * call-seq:
+ * enum.find_all {| obj | block } => array
+ * enum.select {| obj | block } => array
+ *
+ * Returns an array containing all elements of <i>enum</i> for which
+ * <em>block</em> is not <code>false</code> (see also
+ * <code>Enumerable#reject</code>).
+ *
+ * (1..10).find_all {|i| i % 3 == 0 } #=> [3, 6, 9]
+ *
+ */
+
static VALUE
enum_find_all(obj)
VALUE obj;
{
VALUE ary = rb_ary_new();
-
+
+ RETURN_ENUMERATOR(obj, 0, 0);
rb_iterate(rb_each, obj, find_all_i, ary);
return ary;
@@ -126,12 +370,24 @@ reject_i(i, ary)
return Qnil;
}
+/*
+ * call-seq:
+ * enum.reject {| obj | block } => array
+ *
+ * Returns an array for all elements of <i>enum</i> for which
+ * <em>block</em> is false (see also <code>Enumerable#find_all</code>).
+ *
+ * (1..10).reject {|i| i % 3 == 0 } #=> [1, 2, 4, 5, 7, 8, 10]
+ *
+ */
+
static VALUE
enum_reject(obj)
VALUE obj;
{
VALUE ary = rb_ary_new();
-
+
+ RETURN_ENUMERATOR(obj, 0, 0);
rb_iterate(rb_each, obj, reject_i, ary);
return ary;
@@ -142,7 +398,7 @@ collect_i(i, ary)
VALUE i, ary;
{
rb_ary_push(ary, rb_yield(i));
-
+
return Qnil;
}
@@ -151,65 +407,167 @@ collect_all(i, ary)
VALUE i, ary;
{
rb_ary_push(ary, i);
-
+
return Qnil;
}
+/*
+ * call-seq:
+ * enum.collect {| obj | block } => array
+ * enum.map {| obj | block } => array
+ *
+ * Returns a new array with the results of running <em>block</em> once
+ * for every element in <i>enum</i>.
+ *
+ * (1..4).collect {|i| i*i } #=> [1, 4, 9, 16]
+ * (1..4).collect { "cat" } #=> ["cat", "cat", "cat", "cat"]
+ *
+ */
+
static VALUE
enum_collect(obj)
VALUE obj;
{
VALUE ary = rb_ary_new();
-
+
rb_iterate(rb_each, obj, rb_block_given_p() ? collect_i : collect_all, ary);
return ary;
}
+/*
+ * call-seq:
+ * enum.to_a => array
+ * enum.entries => array
+ *
+ * Returns an array containing the items in <i>enum</i>.
+ *
+ * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
+ * { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a #=> [["a", 1], ["b", 2], ["c", 3]]
+ */
static VALUE
-enum_to_a(obj)
+enum_to_a(argc, argv, obj)
+ int argc;
+ VALUE *argv;
VALUE obj;
{
VALUE ary = rb_ary_new();
-
- rb_iterate(rb_each, obj, collect_all, ary);
+
+ rb_block_call(obj, id_each, argc, argv, collect_all, ary);
return ary;
}
+static VALUE inject_i _((VALUE, VALUE));
static VALUE
-inject_i(i, memo)
+inject_i(i, p)
VALUE i;
- NODE *memo;
+ VALUE p;
{
- if (memo->u2.value) {
- memo->u2.value = Qfalse;
- memo->u1.value = i;
+ VALUE *memo = (VALUE *)p;
+ if (memo[0] == Qundef) {
+ memo[0] = i;
}
else {
- memo->u1.value = rb_yield_values(2, memo->u1.value, i);
+ memo[0] = rb_yield_values(2, memo[0], i);
}
return Qnil;
}
+static VALUE inject_op_i _((VALUE, VALUE));
static VALUE
-enum_inject(argc, argv, obj)
- int argc;
- VALUE *argv, obj;
+inject_op_i(i, p)
+ VALUE i;
+ VALUE p;
{
- NODE *memo;
- VALUE n;
+ VALUE *memo = (VALUE *)p;
- if (rb_scan_args(argc, argv, "01", &n) == 1) {
- memo = rb_node_newnode(NODE_MEMO, n, Qfalse, 0);
+ if (memo[0] == Qundef) {
+ memo[0] = i;
}
else {
- memo = rb_node_newnode(NODE_MEMO, Qnil, Qtrue, 0);
+ memo[0] = rb_funcall(memo[0], (ID)memo[1], 1, i);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.inject(initial, sym) => obj
+ * enum.inject(sym) => obj
+ * enum.inject(initial) {| memo, obj | block } => obj
+ * enum.inject {| memo, obj | block } => obj
+ *
+ * enum.reduce(initial, sym) => obj
+ * enum.reduce(sym) => obj
+ * enum.reduce(initial) {| memo, obj | block } => obj
+ * enum.reduce {| memo, obj | block } => obj
+ *
+ * Combines all elements of <i>enum</i> by applying a binary
+ * operation, specified by a block or a symbol that names a
+ * method or operator.
+ *
+ * If you specify a block, then for each element in <i>enum<i>
+ * the block is passed an accumulator value (<i>memo</i>) and the element.
+ * If you specify a symbol instead, then each element in the collection
+ * will be passed to the named method of <i>memo</i>.
+ * In either case, the result becomes the new value for <i>memo</i>.
+ * At the end of the iteration, the final value of <i>memo</i> is the
+ * return value fo the method.
+ *
+ * If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
+ * then uses the first element of collection is used as the initial value
+ * of <i>memo</i>.
+ *
+ * Examples:
+ *
+ * # Sum some numbers
+ * (5..10).reduce(:+) #=> 45
+ * # Same using a block and inject
+ * (5..10).inject {|sum, n| sum + n } #=> 45
+ * # Multiply some numbers
+ * (5..10).reduce(1, :*) #=> 151200
+ * # Same using a block
+ * (5..10).inject(1) {|product, n| product * n } #=> 151200
+ * # find the longest word
+ * longest = %w{ cat sheep bear }.inject do |memo,word|
+ * memo.length > word.length ? memo : word
+ * end
+ * longest #=> "sheep"
+ *
+ */
+static VALUE
+enum_inject(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE memo[2];
+ rb_block_call_func *iter = inject_i;
+
+ switch (rb_scan_args(argc, argv, "02", &memo[0], &memo[1])) {
+ case 0:
+ memo[0] = Qundef;
+ break;
+ case 1:
+ if (rb_block_given_p()) {
+ break;
+ }
+ memo[1] = (VALUE)rb_to_id(memo[0]);
+ memo[0] = Qundef;
+ iter = inject_op_i;
+ break;
+ case 2:
+ if (rb_block_given_p()) {
+ rb_warning("given block not used");
+ }
+ memo[1] = (VALUE)rb_to_id(memo[1]);
+ iter = inject_op_i;
+ break;
}
- rb_iterate(rb_each, obj, inject_i, (VALUE)memo);
- n = memo->u1.value;
- rb_gc_force_recycle((VALUE)memo);
- return n;
+ rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
+ if (memo[0] == Qundef) return Qnil;
+ return memo[0];
}
static VALUE
@@ -225,12 +583,26 @@ partition_i(i, ary)
return Qnil;
}
+/*
+ * call-seq:
+ * enum.partition {| obj | block } => [ true_array, false_array ]
+ *
+ * Returns two arrays, the first containing the elements of
+ * <i>enum</i> for which the block evaluates to true, the second
+ * containing the rest.
+ *
+ * (1..6).partition {|i| (i&1).zero?} #=> [[2, 4, 6], [1, 3, 5]]
+ *
+ */
+
static VALUE
enum_partition(obj)
VALUE obj;
{
VALUE ary[2];
+ RETURN_ENUMERATOR(obj, 0, 0);
+
ary[0] = rb_ary_new();
ary[1] = rb_ary_new();
rb_iterate(rb_each, obj, partition_i, (VALUE)ary);
@@ -239,34 +611,229 @@ enum_partition(obj)
}
static VALUE
+group_by_i(i, hash)
+ VALUE i;
+ VALUE hash;
+{
+ VALUE group = rb_yield(i);
+ VALUE values;
+
+ values = rb_hash_aref(hash, group);
+ if (NIL_P(values)) {
+ values = rb_ary_new3(1, i);
+ rb_hash_aset(hash, group, values);
+ }
+ else {
+ rb_ary_push(values, i);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.group_by {| obj | block } => a_hash
+ *
+ * Returns a hash, which keys are evaluated result from the
+ * block, and values are arrays of elements in <i>enum</i>
+ * corresponding to the key.
+ *
+ * (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
+ *
+ */
+
+static VALUE
+enum_group_by(obj)
+ VALUE obj;
+{
+ VALUE hash;
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ hash = rb_hash_new();
+ rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
+
+ return hash;
+}
+
+static VALUE
+first_i(i, ary)
+ VALUE i;
+ VALUE *ary;
+{
+ if (NIL_P(ary[0])) {
+ ary[1] = i;
+ rb_iter_break();
+ }
+ else {
+ long n = NUM2LONG(ary[0]);
+
+ if (n <= 0) {
+ rb_iter_break();
+ }
+ rb_ary_push(ary[1], i);
+ n--;
+ ary[0] = INT2NUM(n);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.first -> obj or nil
+ * enum.first(n) -> an_array
+ *
+ * Returns the first element, or the first +n+ elements, of the enumerable.
+ * If the enumerable is empty, the first form returns <code>nil</code>, and the
+ * second form returns an empty array.
+ *
+ */
+
+static VALUE
+enum_first(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE n, ary[2];
+
+ if (argc == 0) {
+ ary[0] = ary[1] = Qnil;
+ }
+ else {
+ rb_scan_args(argc, argv, "01", &n);
+ ary[0] = n;
+ ary[1] = rb_ary_new2(NUM2LONG(n));
+ }
+ rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)ary);
+
+ return ary[1];
+}
+
+
+/*
+ * call-seq:
+ * enum.sort => array
+ * enum.sort {| a, b | block } => array
+ *
+ * Returns an array containing the items in <i>enum</i> sorted,
+ * either according to their own <code><=></code> method, or by using
+ * the results of the supplied block. The block should return -1, 0, or
+ * +1 depending on the comparison between <i>a</i> and <i>b</i>. As of
+ * Ruby 1.8, the method <code>Enumerable#sort_by</code> implements a
+ * built-in Schwartzian Transform, useful when key computation or
+ * comparison is expensive..
+ *
+ * %w(rhea kea flea).sort #=> ["flea", "kea", "rhea"]
+ * (1..10).sort {|a,b| b <=> a} #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
+ */
+
+static VALUE
enum_sort(obj)
VALUE obj;
{
- return rb_ary_sort(enum_to_a(obj));
+ return rb_ary_sort(enum_to_a(0, 0, obj));
}
static VALUE
sort_by_i(i, ary)
VALUE i, ary;
{
- VALUE v, e;
+ VALUE v;
+ NODE *memo;
v = rb_yield(i);
- e = rb_assoc_new(v, i);
- rb_ary_push(ary, e);
+ if (RBASIC(ary)->klass) {
+ rb_raise(rb_eRuntimeError, "sort_by reentered");
+ }
+ memo = rb_node_newnode(NODE_MEMO, v, i, 0);
+ rb_ary_push(ary, (VALUE)memo);
return Qnil;
}
static int
-sort_by_cmp(a, b)
- VALUE *a, *b;
+sort_by_cmp(aa, bb, data)
+ NODE **aa, **bb;
+ void *data;
{
- VALUE retval;
+ VALUE a = aa[0]->u1.value;
+ VALUE b = bb[0]->u1.value;
+ VALUE ary = (VALUE)data;
- retval = rb_funcall(RARRAY(*a)->ptr[0], id_cmp, 1, RARRAY(*b)->ptr[0]);
- return rb_cmpint(retval, *a, *b);
+ if (RBASIC(ary)->klass) {
+ rb_raise(rb_eRuntimeError, "sort_by reentered");
+ }
+ return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
}
+/*
+ * call-seq:
+ * enum.sort_by {| obj | block } => array
+ *
+ * Sorts <i>enum</i> using a set of keys generated by mapping the
+ * values in <i>enum</i> through the given block.
+ *
+ * %w{ apple pear fig }.sort_by {|word| word.length}
+ #=> ["fig", "pear", "apple"]
+ *
+ * The current implementation of <code>sort_by</code> generates an
+ * array of tuples containing the original collection element and the
+ * mapped value. This makes <code>sort_by</code> fairly expensive when
+ * the keysets are simple
+ *
+ * require 'benchmark'
+ * include Benchmark
+ *
+ * a = (1..100000).map {rand(100000)}
+ *
+ * bm(10) do |b|
+ * b.report("Sort") { a.sort }
+ * b.report("Sort by") { a.sort_by {|a| a} }
+ * end
+ *
+ * <em>produces:</em>
+ *
+ * user system total real
+ * Sort 0.180000 0.000000 0.180000 ( 0.175469)
+ * Sort by 1.980000 0.040000 2.020000 ( 2.013586)
+ *
+ * However, consider the case where comparing the keys is a non-trivial
+ * operation. The following code sorts some files on modification time
+ * using the basic <code>sort</code> method.
+ *
+ * files = Dir["*"]
+ * sorted = files.sort {|a,b| File.new(a).mtime <=> File.new(b).mtime}
+ * sorted #=> ["mon", "tues", "wed", "thurs"]
+ *
+ * This sort is inefficient: it generates two new <code>File</code>
+ * objects during every comparison. A slightly better technique is to
+ * use the <code>Kernel#test</code> method to generate the modification
+ * times directly.
+ *
+ * files = Dir["*"]
+ * sorted = files.sort { |a,b|
+ * test(?M, a) <=> test(?M, b)
+ * }
+ * sorted #=> ["mon", "tues", "wed", "thurs"]
+ *
+ * This still generates many unnecessary <code>Time</code> objects. A
+ * more efficient technique is to cache the sort keys (modification
+ * times in this case) before the sort. Perl users often call this
+ * approach a Schwartzian Transform, after Randal Schwartz. We
+ * construct a temporary array, where each element is an array
+ * containing our sort key along with the filename. We sort this array,
+ * and then extract the filename from the result.
+ *
+ * sorted = Dir["*"].collect { |f|
+ * [test(?M, f), f]
+ * }.sort.collect { |f| f[1] }
+ * sorted #=> ["mon", "tues", "wed", "thurs"]
+ *
+ * This is exactly what <code>sort_by</code> does internally.
+ *
+ * sorted = Dir["*"].sort_by {|f| test(?M, f)}
+ * sorted #=> ["mon", "tues", "wed", "thurs"]
+ */
+
static VALUE
enum_sort_by(obj)
VALUE obj;
@@ -274,113 +841,238 @@ enum_sort_by(obj)
VALUE ary;
long i;
+ RETURN_ENUMERATOR(obj, 0, 0);
+
if (TYPE(obj) == T_ARRAY) {
ary = rb_ary_new2(RARRAY(obj)->len);
}
else {
ary = rb_ary_new();
}
+ RBASIC(ary)->klass = 0;
rb_iterate(rb_each, obj, sort_by_i, ary);
if (RARRAY(ary)->len > 1) {
- qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp);
+ qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
+ sort_by_cmp, (void *)ary);
+ }
+ if (RBASIC(ary)->klass) {
+ rb_raise(rb_eRuntimeError, "sort_by reentered");
}
for (i=0; i<RARRAY(ary)->len; i++) {
- VALUE e = RARRAY(ary)->ptr[i];
- RARRAY(ary)->ptr[i] = RARRAY(e)->ptr[1];
+ RARRAY(ary)->ptr[i] = RNODE(RARRAY(ary)->ptr[i])->u2.value;
}
+ RBASIC(ary)->klass = rb_cArray;
return ary;
}
static VALUE
-all_iter_i(i, memo)
+all_i(i, memo)
VALUE i;
- NODE *memo;
+ VALUE *memo;
{
- if (!RTEST(rb_yield(i))) {
- memo->u1.value = Qfalse;
+ if (!RTEST(i)) {
+ *memo = Qfalse;
rb_iter_break();
}
return Qnil;
}
static VALUE
-all_i(i, memo)
+all_iter_i(i, memo)
VALUE i;
- NODE *memo;
+ VALUE *memo;
{
- if (!RTEST(i)) {
- memo->u1.value = Qfalse;
+ return all_i(rb_yield(i), memo);
+}
+
+/*
+ * call-seq:
+ * enum.all? [{|obj| block } ] => true or false
+ *
+ * Passes each element of the collection to the given block. The method
+ * returns <code>true</code> if the block never returns
+ * <code>false</code> or <code>nil</code>. If the block is not given,
+ * Ruby adds an implicit block of <code>{|obj| obj}</code> (that is
+ * <code>all?</code> will return <code>true</code> only if none of the
+ * collection members are <code>false</code> or <code>nil</code>.)
+ *
+ * %w{ ant bear cat}.all? {|word| word.length >= 3} #=> true
+ * %w{ ant bear cat}.all? {|word| word.length >= 4} #=> false
+ * [ nil, true, 99 ].all? #=> false
+ *
+ */
+
+static VALUE
+enum_all(obj)
+ VALUE obj;
+{
+ VALUE result = Qtrue;
+
+ rb_iterate(rb_each, obj, rb_block_given_p() ? all_iter_i : all_i, (VALUE)&result);
+ return result;
+}
+
+static VALUE
+any_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ if (RTEST(i)) {
+ *memo = Qtrue;
rb_iter_break();
}
return Qnil;
}
static VALUE
-enum_all(obj)
+any_iter_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ return any_i(rb_yield(i), memo);
+}
+
+/*
+ * call-seq:
+ * enum.any? [{|obj| block } ] => true or false
+ *
+ * Passes each element of the collection to the given block. The method
+ * returns <code>true</code> if the block ever returns a value other
+ * than <code>false</code> or <code>nil</code>. If the block is not
+ * given, Ruby adds an implicit block of <code>{|obj| obj}</code> (that
+ * is <code>any?</code> will return <code>true</code> if at least one
+ * of the collection members is not <code>false</code> or
+ * <code>nil</code>.
+ *
+ * %w{ ant bear cat}.any? {|word| word.length >= 3} #=> true
+ * %w{ ant bear cat}.any? {|word| word.length >= 4} #=> true
+ * [ nil, true, 99 ].any? #=> true
+ *
+ */
+
+static VALUE
+enum_any(obj)
VALUE obj;
{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
+ VALUE result = Qfalse;
- memo->u1.value = Qtrue;
- rb_iterate(rb_each, obj, rb_block_given_p() ? all_iter_i : all_i, (VALUE)memo);
- result = memo->u1.value;
- rb_gc_force_recycle((VALUE)memo);
+ rb_iterate(rb_each, obj, rb_block_given_p() ? any_iter_i : any_i, (VALUE)&result);
return result;
}
static VALUE
-any_iter_i(i, memo)
+one_i(i, memo)
VALUE i;
- NODE *memo;
+ VALUE *memo;
{
- if (RTEST(rb_yield(i))) {
- memo->u1.value = Qtrue;
- rb_iter_break();
+ if (RTEST(i)) {
+ if (*memo == Qundef) {
+ *memo = Qtrue;
+ }
+ else if (*memo == Qtrue) {
+ *memo = Qfalse;
+ rb_iter_break();
+ }
}
return Qnil;
}
static VALUE
-any_i(i, memo)
+one_iter_i(i, memo)
VALUE i;
- NODE *memo;
+ VALUE *memo;
+{
+ return one_i(rb_yield(i), memo);
+}
+
+/*
+ * call-seq:
+ * enum.one? [{|obj| block }] => true or false
+ *
+ * Passes each element of the collection to the given block. The method
+ * returns <code>true</code> if the block returns <code>true</code>
+ * exactly once. If the block is not given, <code>one?</code> will return
+ * <code>true</code> only if exactly one of the collection members is
+ * true.
+ *
+ * %w{ant bear cat}.one? {|word| word.length == 4} #=> true
+ * %w{ant bear cat}.one? {|word| word.length > 4} #=> false
+ * %w{ant bear cat}.one? {|word| word.length < 4} #=> false
+ * [ nil, true, 99 ].one? #=> false
+ * [ nil, true, false ].one? #=> true
+ *
+ */
+
+static VALUE
+enum_one(obj)
+ VALUE obj;
+{
+ VALUE result = Qundef;
+
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? one_iter_i : one_i, (VALUE)&result);
+ if (result == Qundef) return Qfalse;
+ return result;
+}
+
+static VALUE
+none_i(i, memo)
+ VALUE i;
+ VALUE *memo;
{
if (RTEST(i)) {
- memo->u1.value = Qtrue;
+ *memo = Qfalse;
rb_iter_break();
}
return Qnil;
}
static VALUE
-enum_any(obj)
+none_iter_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ return none_i(rb_yield(i), memo);
+}
+
+/*
+ * call-seq:
+ * enum.none? [{|obj| block }] => true or false
+ *
+ * Passes each element of the collection to the given block. The method
+ * returns <code>true</code> if the block never returns <code>true</code>
+ * for all elements. If the block is not given, <code>none?</code> will return
+ * <code>true</code> only if none of the collection members is true.
+ *
+ * %w{ant bear cat}.none? {|word| word.length == 5} #=> true
+ * %w{ant bear cat}.none? {|word| word.length >= 4} #=> false
+ * [].none? #=> true
+ * [nil].none? #=> true
+ * [nil,false].none? #=> true
+ */
+static VALUE
+enum_none(obj)
VALUE obj;
{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
+ VALUE result = Qtrue;
- memo->u1.value = Qfalse;
- rb_iterate(rb_each, obj, rb_block_given_p() ? any_iter_i : any_i, (VALUE)memo);
- result = memo->u1.value;
- rb_gc_force_recycle((VALUE)memo);
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? none_iter_i : none_i, (VALUE)&result);
return result;
}
static VALUE
min_i(i, memo)
VALUE i;
- NODE *memo;
+ VALUE *memo;
{
VALUE cmp;
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = i;
+ if (*memo == Qundef) {
+ *memo = i;
}
else {
- cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
- if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
- memo->u1.value = i;
+ cmp = rb_funcall(i, id_cmp, 1, *memo);
+ if (rb_cmpint(cmp, i, *memo) < 0) {
+ *memo = i;
}
}
return Qnil;
@@ -389,49 +1081,76 @@ min_i(i, memo)
static VALUE
min_ii(i, memo)
VALUE i;
- NODE *memo;
+ VALUE *memo;
{
VALUE cmp;
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = i;
+ if (*memo == Qundef) {
+ *memo = i;
}
else {
- cmp = rb_yield_values(2, i, memo->u1.value);
- if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
- memo->u1.value = i;
+ cmp = rb_yield_values(2, i, *memo);
+ if (rb_cmpint(cmp, i, *memo) < 0) {
+ *memo = i;
}
}
return Qnil;
}
+
+/*
+ * call-seq:
+ * enum.min => obj
+ * enum.min {| a,b | block } => obj
+ *
+ * Returns the object in <i>enum</i> with the minimum value. The
+ * first form assumes all objects implement <code>Comparable</code>;
+ * the second uses the block to return <em>a <=> b</em>.
+ *
+ * a = %w(albatross dog horse)
+ * a.min #=> "albatross"
+ * a.min {|a,b| a.length <=> b.length } #=> "dog"
+ */
+
static VALUE
enum_min(obj)
VALUE obj;
{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
+ VALUE result = Qundef;
- rb_iterate(rb_each, obj, rb_block_given_p() ? min_ii : min_i, (VALUE)memo);
- result = memo->u1.value;
- rb_gc_force_recycle((VALUE)memo);
+ rb_iterate(rb_each, obj, rb_block_given_p() ? min_ii : min_i, (VALUE)&result);
+ if (result == Qundef) return Qnil;
return result;
}
+/*
+ * call-seq:
+ * enum.max => obj
+ * enum.max {| a,b | block } => obj
+ *
+ * Returns the object in <i>enum</i> with the maximum value. The
+ * first form assumes all objects implement <code>Comparable</code>;
+ * the second uses the block to return <em>a <=> b</em>.
+ *
+ * a = %w(albatross dog horse)
+ * a.max #=> "horse"
+ * a.max {|a,b| a.length <=> b.length } #=> "albatross"
+ */
+
static VALUE
max_i(i, memo)
VALUE i;
- NODE *memo;
+ VALUE *memo;
{
VALUE cmp;
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = i;
+ if (*memo == Qundef) {
+ *memo = i;
}
else {
- cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
- if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
- memo->u1.value = i;
+ cmp = rb_funcall(i, id_cmp, 1, *memo);
+ if (rb_cmpint(cmp, i, *memo) > 0) {
+ *memo = i;
}
}
return Qnil;
@@ -440,89 +1159,389 @@ max_i(i, memo)
static VALUE
max_ii(i, memo)
VALUE i;
- NODE *memo;
+ VALUE *memo;
{
VALUE cmp;
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = i;
+ if (*memo == Qundef) {
+ *memo = i;
}
else {
- cmp = rb_yield_values(2, i, memo->u1.value);
- if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
- memo->u1.value = i;
+ cmp = rb_yield_values(2, i, *memo);
+ if (rb_cmpint(cmp, i, *memo) > 0) {
+ *memo = i;
}
}
return Qnil;
}
+/*
+ * call-seq:
+ * enum.max => obj
+ * enum.max {|a,b| block } => obj
+ *
+ * Returns the object in _enum_ with the maximum value. The
+ * first form assumes all objects implement <code>Comparable</code>;
+ * the second uses the block to return <em>a <=> b</em>.
+ *
+ * a = %w(albatross dog horse)
+ * a.max #=> "horse"
+ * a.max {|a,b| a.length <=> b.length } #=> "albatross"
+ */
+
static VALUE
enum_max(obj)
VALUE obj;
{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
+ VALUE result = Qundef;
- rb_iterate(rb_each, obj, rb_block_given_p() ? max_ii : max_i, (VALUE)memo);
- result = memo->u1.value;
- rb_gc_force_recycle((VALUE)memo);
+ rb_iterate(rb_each, obj, rb_block_given_p() ? max_ii : max_i, (VALUE)&result);
+ if (result == Qundef) return Qnil;
return result;
}
static VALUE
+minmax_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ int n;
+
+ if (memo[0] == Qundef) {
+ memo[0] = i;
+ memo[1] = i;
+ }
+ else {
+ n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo[0]), i, memo[0]);
+ if (n < 0) {
+ memo[0] = i;
+ }
+ n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo[1]), i, memo[1]);
+ if (n > 0) {
+ memo[1] = i;
+ }
+ }
+ return Qnil;
+}
+
+static VALUE
+minmax_ii(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ int n;
+
+ if (memo[0] == Qundef) {
+ memo[0] = i;
+ memo[1] = i;
+ }
+ else {
+ VALUE ary = memo[2];
+
+ RARRAY(ary)->ptr[0] = i;
+ RARRAY(ary)->ptr[1] = memo[0];
+ n = rb_cmpint(rb_yield(ary), i, memo[0]);
+ if (n < 0) {
+ memo[0] = i;
+ }
+ RARRAY(ary)->ptr[0] = i;
+ RARRAY(ary)->ptr[1] = memo[1];
+ n = rb_cmpint(rb_yield(ary), i, memo[1]);
+ if (n > 0) {
+ memo[1] = i;
+ }
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.minmax => [min,max]
+ * enum.minmax {|a,b| block } => [min,max]
+ *
+ * Returns two elements array which contains the minimum and the
+ * maximum value in the enumerable. The first form assumes all
+ * objects implement <code>Comparable</code>; the second uses the
+ * block to return <em>a <=> b</em>.
+ *
+ * a = %w(albatross dog horse)
+ * a.minmax #=> ["albatross", "horse"]
+ * a.minmax {|a,b| a.length <=> b.length } #=> ["dog", "albatross"]
+ */
+
+static VALUE
+enum_minmax(obj)
+ VALUE obj;
+{
+ VALUE result[3];
+ VALUE ary = rb_ary_new3(2, Qnil, Qnil);
+
+ result[0] = Qundef;
+ if (rb_block_given_p()) {
+ result[2] = ary;
+ rb_block_call(obj, id_each, 0, 0, minmax_ii, (VALUE)result);
+ }
+ else {
+ rb_block_call(obj, id_each, 0, 0, minmax_i, (VALUE)result);
+ }
+ if (result[0] != Qundef) {
+ RARRAY(ary)->ptr[0] = result[0];
+ RARRAY(ary)->ptr[1] = result[1];
+ }
+ return ary;
+}
+
+static VALUE
+min_by_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ VALUE v;
+
+ v = rb_yield(i);
+ if (memo[0] == Qundef) {
+ memo[0] = v;
+ memo[1] = i;
+ }
+ else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) < 0) {
+ memo[0] = v;
+ memo[1] = i;
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.min_by {| obj| block } => obj
+ *
+ * Returns the object in <i>enum</i> that gives the minimum
+ * value from the given block.
+ *
+ * a = %w(albatross dog horse)
+ * a.min_by {|x| x.length } #=> "dog"
+ */
+
+static VALUE
+enum_min_by(obj)
+ VALUE obj;
+{
+ VALUE memo[2];
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ memo[0] = Qundef;
+ memo[1] = Qnil;
+ rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
+ return memo[1];
+}
+
+static VALUE
+max_by_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ VALUE v;
+
+ v = rb_yield(i);
+ if (memo[0] == Qundef) {
+ memo[0] = v;
+ memo[1] = i;
+ }
+ else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) > 0) {
+ memo[0] = v;
+ memo[1] = i;
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.max_by {| obj| block } => obj
+ *
+ * Returns the object in <i>enum</i> that gives the maximum
+ * value from the given block.
+ *
+ * a = %w(albatross dog horse)
+ * a.max_by {|x| x.length } #=> "albatross"
+ */
+
+static VALUE
+enum_max_by(obj)
+ VALUE obj;
+{
+ VALUE memo[2];
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ memo[0] = Qundef;
+ memo[1] = Qnil;
+ rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
+ return memo[1];
+}
+
+static VALUE
+minmax_by_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ VALUE v;
+
+ v = rb_yield(i);
+ if (memo[0] == Qundef) {
+ memo[0] = v;
+ memo[1] = v;
+ memo[2] = i;
+ memo[3] = i;
+ }
+ else {
+ if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) < 0) {
+ memo[0] = v;
+ memo[2] = i;
+ }
+ if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[1]), v, memo[1]) > 0) {
+ memo[1] = v;
+ memo[3] = i;
+ }
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.minmax_by {| obj| block } => [min, max]
+ *
+ * Returns two elements array array containing the objects in
+ * <i>enum</i> that gives the minimum and maximum values respectively
+ * from the given block.
+ *
+ * a = %w(albatross dog horse)
+ * a.minmax_by {|x| x.length } #=> ["dog", "albatross"]
+ */
+
+static VALUE
+enum_minmax_by(obj)
+ VALUE obj;
+{
+ VALUE memo[4];
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ memo[0] = Qundef;
+ memo[1] = Qundef;
+ memo[2] = Qnil;
+ memo[3] = Qnil;
+ rb_block_call(obj, id_each, 0, 0, minmax_by_i, (VALUE)memo);
+ return rb_assoc_new(memo[2], memo[3]);
+}
+
+static VALUE
member_i(item, memo)
VALUE item;
- NODE *memo;
+ VALUE *memo;
{
- if (rb_equal(item, memo->u1.value)) {
- memo->u2.value = Qtrue;
+ if (rb_equal(item, memo[0])) {
+ memo[1] = Qtrue;
rb_iter_break();
}
return Qnil;
}
+/*
+ * call-seq:
+ * enum.include?(obj) => true or false
+ * enum.member?(obj) => true or false
+ *
+ * Returns <code>true</code> if any member of <i>enum</i> equals
+ * <i>obj</i>. Equality is tested using <code>==</code>.
+ *
+ * IO.constants.include? "SEEK_SET" #=> true
+ * IO.constants.include? "SEEK_NO_FURTHER" #=> false
+ *
+ */
+
static VALUE
enum_member(obj, val)
VALUE obj, val;
{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, val, Qfalse, 0);
+ VALUE memo[2];
+ memo[0] = val;
+ memo[1] = Qfalse;
rb_iterate(rb_each, obj, member_i, (VALUE)memo);
- result = memo->u2.value;
- rb_gc_force_recycle((VALUE)memo);
- return result;
+ return memo[1];
}
static VALUE
each_with_index_i(val, memo)
VALUE val;
- NODE *memo;
+ VALUE *memo;
{
- rb_yield_values(2, val, INT2FIX(memo->u3.cnt));
- memo->u3.cnt++;
+ rb_yield_values(2, val, INT2FIX(*memo));
+ ++*memo;
return Qnil;
}
+/*
+ * call-seq:
+ * enum.each_with_index {|obj, i| block } -> enum
+ *
+ * Calls <em>block</em> with two arguments, the item and its index, for
+ * each item in <i>enum</i>.
+ *
+ * hash = Hash.new
+ * %w(cat dog wombat).each_with_index {|item, index|
+ * hash[item] = index
+ * }
+ * hash #=> {"cat"=>0, "wombat"=>2, "dog"=>1}
+ *
+ */
+
static VALUE
enum_each_with_index(obj)
VALUE obj;
{
- NODE *memo = rb_node_newnode(NODE_MEMO, 0, 0, 0);
+ VALUE memo;
- rb_iterate(rb_each, obj, each_with_index_i, (VALUE)memo);
- rb_gc_force_recycle((VALUE)memo);
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ memo = 0;
+ rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&memo);
return obj;
}
+/*
+ * call-seq:
+ * enum.reverse_each {|item| block }
+ *
+ * Traverses <i>enum</i> in reverse order.
+ */
+
+static VALUE
+enum_reverse_each(int argc, VALUE *argv, VALUE obj)
+{
+ VALUE ary;
+ long i;
+
+ RETURN_ENUMERATOR(obj, argc, argv);
+
+ ary = enum_to_a(argc, argv, obj);
+
+ for (i = RARRAY_LEN(ary); --i >= 0; ) {
+ rb_yield(RARRAY_PTR(ary)[i]);
+ }
+
+ return obj;
+}
+
+
static VALUE
zip_i(val, memo)
VALUE val;
- NODE *memo;
+ VALUE *memo;
{
- VALUE result = memo->u1.value;
- VALUE args = memo->u2.value;
- int idx = memo->u3.cnt++;
+ VALUE result = memo[0];
+ VALUE args = memo[1];
+ int idx = memo[2]++;
VALUE tmp;
int i;
@@ -540,6 +1559,29 @@ zip_i(val, memo)
return Qnil;
}
+/*
+ * call-seq:
+ * enum.zip(arg, ...) => array
+ * enum.zip(arg, ...) {|arr| block } => nil
+ *
+ * Converts any arguments to arrays, then merges elements of
+ * <i>enum</i> with corresponding elements from each argument. This
+ * generates a sequence of <code>enum#size</code> <em>n</em>-element
+ * arrays, where <em>n</em> is one more that the count of arguments. If
+ * the size of any argument is less than <code>enum#size</code>,
+ * <code>nil</code> values are supplied. If a block given, it is
+ * invoked for each output array, otherwise an array of arrays is
+ * returned.
+ *
+ * a = [ 4, 5, 6 ]
+ * b = [ 7, 8, 9 ]
+ *
+ * (1..3).zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
+ * "cat\ndog".zip([1]) #=> [["cat\n", 1], ["dog", nil]]
+ * (1..3).zip #=> [[1], [2], [3]]
+ *
+ */
+
static VALUE
enum_zip(argc, argv, obj)
int argc;
@@ -548,49 +1590,302 @@ enum_zip(argc, argv, obj)
{
int i;
VALUE result;
- NODE *memo;
+ VALUE memo[3];
for (i=0; i<argc; i++) {
- argv[i] = rb_convert_type(argv[i], T_ARRAY, "Array", "to_ary");
+ argv[i] = rb_convert_type(argv[i], T_ARRAY, "Array", "to_a");
}
result = rb_block_given_p() ? Qnil : rb_ary_new();
- memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), 0);
+ memo[0] = result;
+ memo[1] = rb_ary_new4(argc, argv);
+ memo[2] = 0;
rb_iterate(rb_each, obj, zip_i, (VALUE)memo);
return result;
}
+static VALUE
+take_i(i, arg)
+ VALUE i;
+ VALUE *arg;
+{
+ if (arg[1]-- == 0) rb_iter_break();
+ rb_ary_push(arg[0], i);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.take(n) => array
+ *
+ * Returns first n elements from <i>enum</i>.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.take(3) # => [1, 2, 3]
+ *
+ */
+
+static VALUE
+enum_take(obj, n)
+ VALUE obj;
+ VALUE n;
+{
+ VALUE args[2];
+ long len = NUM2LONG(n);
+
+ if (len < 0) {
+ rb_raise(rb_eArgError, "attempt to take negative size");
+ }
+
+ args[1] = len;
+ args[0] = rb_ary_new();
+ rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)args);
+ return args[0];
+}
+
+
+static VALUE
+take_while_i(i, ary)
+ VALUE i;
+ VALUE *ary;
+{
+ if (!RTEST(rb_yield(i))) rb_iter_break();
+ rb_ary_push(*ary, i);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.take_while {|arr| block } => array
+ *
+ * Passes elements to the block until the block returns nil or false,
+ * then stops iterating and returns an array of all prior elements.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.take_while {|i| i < 3 } # => [1, 2]
+ *
+ */
+
+static VALUE
+enum_take_while(obj)
+ VALUE obj;
+{
+ VALUE ary;
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+ ary = rb_ary_new();
+ rb_block_call(obj, id_each, 0, 0, take_while_i, (VALUE)&ary);
+ return ary;
+}
+
+static VALUE
+drop_i(i, arg)
+ VALUE i;
+ VALUE *arg;
+{
+ if (arg[1] == 0) {
+ rb_ary_push(arg[0], i);
+ }
+ else {
+ arg[1]--;
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.drop(n) => array
+ *
+ * Drops first n elements from <i>enum</i>, and returns rest elements
+ * in an array.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.drop(3) # => [4, 5, 0]
+ *
+ */
+
+static VALUE
+enum_drop(obj, n)
+ VALUE obj;
+ VALUE n;
+{
+ VALUE args[2];
+ long len = NUM2LONG(n);
+
+ if (len < 0) {
+ rb_raise(rb_eArgError, "attempt to drop negative size");
+ }
+
+ args[1] = len;
+ args[0] = rb_ary_new();
+ rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)args);
+ return args[0];
+}
+
+
+static VALUE
+drop_while_i(i, args)
+ VALUE i;
+ VALUE *args;
+{
+ if (!args[1] && !RTEST(rb_yield(i))) {
+ args[1] = Qtrue;
+ }
+ if (args[1]) {
+ rb_ary_push(args[0], i);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.drop_while {|arr| block } => array
+ *
+ * Drops elements up to, but not including, the first element for
+ * which the block returns nil or false and returns an array
+ * containing the remaining elements.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.drop_while {|i| i < 3 } # => [3, 4, 5, 0]
+ *
+ */
+
+static VALUE
+enum_drop_while(obj)
+ VALUE obj;
+{
+ VALUE args[2];
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+ args[0] = rb_ary_new();
+ args[1] = Qfalse;
+ rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)args);
+ return args[0];
+}
+
+static VALUE
+cycle_i(i, ary)
+ VALUE i;
+ VALUE ary;
+{
+ rb_ary_push(ary, i);
+ rb_yield(i);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.cycle {|obj| block }
+ * enum.cycle(n) {|obj| block }
+ *
+ * Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
+ * times or forever if none or nil is given. If a non-positive
+ * number is given or the collection is empty, does nothing. Returns
+ * nil if the loop has finished without getting interrupted.
+ *
+ * Enumerable#cycle saves elements in an internal array so changes
+ * to <i>enum</i> after the first pass have no effect.
+ *
+ * a = ["a", "b", "c"]
+ * a.cycle {|x| puts x } # print, a, b, c, a, b, c,.. forever.
+ * a.cycle(2) {|x| puts x } # print, a, b, c, a, b, c.
+ *
+ */
+
+static VALUE
+enum_cycle(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE ary;
+ VALUE nv = Qnil;
+ long n, i, len;
+
+ rb_scan_args(argc, argv, "01", &nv);
+
+ RETURN_ENUMERATOR(obj, argc, argv);
+ if (NIL_P(nv)) {
+ n = -1;
+ }
+ else {
+ n = NUM2LONG(nv);
+ if (n <= 0) return Qnil;
+ }
+ ary = rb_ary_new();
+ RBASIC(ary)->klass = 0;
+ rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
+ len = RARRAY(ary)->len;
+ if (len == 0) return Qnil;
+ while (n < 0 || 0 < --n) {
+ for (i=0; i<len; i++) {
+ rb_yield(RARRAY(ary)->ptr[i]);
+ }
+ }
+ return Qnil; /* not reached */
+}
+
+/*
+ * The <code>Enumerable</code> mixin provides collection classes with
+ * several traversal and searching methods, and with the ability to
+ * sort. The class must provide a method <code>each</code>, which
+ * yields successive members of the collection. If
+ * <code>Enumerable#max</code>, <code>#min</code>, or
+ * <code>#sort</code> is used, the objects in the collection must also
+ * implement a meaningful <code><=></code> operator, as these methods
+ * rely on an ordering between members of the collection.
+ */
+
void
Init_Enumerable()
{
rb_mEnumerable = rb_define_module("Enumerable");
- rb_define_method(rb_mEnumerable,"to_a", enum_to_a, 0);
- rb_define_method(rb_mEnumerable,"entries", enum_to_a, 0);
-
- rb_define_method(rb_mEnumerable,"sort", enum_sort, 0);
- rb_define_method(rb_mEnumerable,"sort_by", enum_sort_by, 0);
- rb_define_method(rb_mEnumerable,"grep", enum_grep, 1);
- rb_define_method(rb_mEnumerable,"find", enum_find, -1);
- rb_define_method(rb_mEnumerable,"detect", enum_find, -1);
- rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0);
- rb_define_method(rb_mEnumerable,"select", enum_find_all, 0);
- rb_define_method(rb_mEnumerable,"reject", enum_reject, 0);
- rb_define_method(rb_mEnumerable,"collect", enum_collect, 0);
- rb_define_method(rb_mEnumerable,"map", enum_collect, 0);
- rb_define_method(rb_mEnumerable,"inject", enum_inject, -1);
- rb_define_method(rb_mEnumerable,"partition", enum_partition, 0);
- rb_define_method(rb_mEnumerable,"all?", enum_all, 0);
- rb_define_method(rb_mEnumerable,"any?", enum_any, 0);
- rb_define_method(rb_mEnumerable,"min", enum_min, 0);
- rb_define_method(rb_mEnumerable,"max", enum_max, 0);
- rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
- rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
- rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0);
+ rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
+ rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
+
+ rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
+ rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
+ rb_define_method(rb_mEnumerable, "grep", enum_grep, 1);
+ rb_define_method(rb_mEnumerable, "count", enum_count, -1);
+ rb_define_method(rb_mEnumerable, "find", enum_find, -1);
+ rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
+ rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
+ rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
+ rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
+ rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
+ rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
+ rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
+ rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
+ rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
+ rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
+ rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
+ rb_define_method(rb_mEnumerable, "first", enum_first, -1);
+ rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
+ rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
+ rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
+ rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
+ rb_define_method(rb_mEnumerable, "min", enum_min, 0);
+ rb_define_method(rb_mEnumerable, "max", enum_max, 0);
+ rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
+ rb_define_method(rb_mEnumerable, "min_by", enum_min_by, 0);
+ rb_define_method(rb_mEnumerable, "max_by", enum_max_by, 0);
+ rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
+ rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
+ rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
+ rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, 0);
+ rb_define_method(rb_mEnumerable, "enum_with_index", enum_each_with_index, 0);
+ rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
+ rb_define_method(rb_mEnumerable, "take", enum_take, 1);
+ rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
+ rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
+ rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
+ rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
id_eqq = rb_intern("===");
id_each = rb_intern("each");
id_cmp = rb_intern("<=>");
+ id_size = rb_intern("size");
}
diff --git a/enumerator.c b/enumerator.c
new file mode 100644
index 0000000000..f95d931b62
--- /dev/null
+++ b/enumerator.c
@@ -0,0 +1,450 @@
+/************************************************
+
+ enumerator.c - provides Enumerator class
+
+ $Author$
+
+ Copyright (C) 2001-2003 Akinori MUSHA
+
+ $Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
+ $RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
+ $Id$
+
+************************************************/
+
+#include "ruby.h"
+
+/*
+ * Document-class: Enumerable::Enumerator
+ *
+ * A class which provides a method `each' to be used as an Enumerable
+ * object.
+ */
+VALUE rb_cEnumerator;
+static VALUE sym_each;
+
+VALUE rb_eStopIteration;
+
+struct enumerator {
+ VALUE obj;
+ ID meth;
+ VALUE proc;
+ VALUE args;
+ rb_block_call_func *iter;
+};
+
+static void enumerator_mark _((void *));
+static void
+enumerator_mark(p)
+ void *p;
+{
+ struct enumerator *ptr = p;
+ rb_gc_mark(ptr->obj);
+ rb_gc_mark(ptr->args);
+}
+
+static struct enumerator *
+enumerator_ptr(obj)
+ VALUE obj;
+{
+ struct enumerator *ptr;
+
+ Data_Get_Struct(obj, struct enumerator, ptr);
+ if (RDATA(obj)->dmark != enumerator_mark) {
+ rb_raise(rb_eTypeError,
+ "wrong argument type %s (expected Enumerable::Enumerator)",
+ rb_obj_classname(obj));
+ }
+ if (!ptr || ptr->obj == Qundef) {
+ rb_raise(rb_eArgError, "uninitialized enumerator");
+ }
+ return ptr;
+}
+
+/*
+ * call-seq:
+ * obj.to_enum(method = :each, *args)
+ * obj.enum_for(method = :each, *args)
+ *
+ * Returns Enumerable::Enumerator.new(self, method, *args).
+ *
+ * e.g.:
+ *
+ * str = "xyz"
+ *
+ * enum = str.enum_for(:each_byte)
+ * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
+ *
+ * # protects an array from being modified
+ * a = [1, 2, 3]
+ * some_method(a.to_enum)
+ *
+ */
+static VALUE
+obj_to_enum(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE meth = sym_each;
+
+ if (argc > 0) {
+ --argc;
+ meth = *argv++;
+ }
+ return rb_enumeratorize(obj, meth, argc, argv);
+}
+
+static VALUE
+each_slice_i(val, memo)
+ VALUE val;
+ VALUE *memo;
+{
+ VALUE ary = memo[0];
+ VALUE v = Qnil;
+ long size = (long)memo[1];
+
+ rb_ary_push(ary, val);
+
+ if (RARRAY_LEN(ary) == size) {
+ v = rb_yield(ary);
+ memo[0] = rb_ary_new2(size);
+ }
+
+ return v;
+}
+
+/*
+ * call-seq:
+ * e.each_slice(n) {...}
+ * e.each_slice(n)
+ *
+ * Iterates the given block for each slice of <n> elements. If no
+ * block is given, returns an enumerator.
+ *
+ * e.g.:
+ * (1..10).each_slice(3) {|a| p a}
+ * # outputs below
+ * [1, 2, 3]
+ * [4, 5, 6]
+ * [7, 8, 9]
+ * [10]
+ *
+ */
+static VALUE
+enum_each_slice(obj, n)
+ VALUE obj, n;
+{
+ long size = NUM2LONG(n);
+ VALUE args[2], ary;
+
+ if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
+ RETURN_ENUMERATOR(obj, 1, &n);
+ args[0] = rb_ary_new2(size);
+ args[1] = (VALUE)size;
+
+ rb_block_call(obj, SYM2ID(sym_each), 0, 0, each_slice_i, (VALUE)args);
+
+ ary = args[0];
+ if (RARRAY_LEN(ary) > 0) rb_yield(ary);
+
+ return Qnil;
+}
+
+static VALUE
+each_cons_i(val, memo)
+ VALUE val;
+ VALUE *memo;
+{
+ VALUE ary = memo[0];
+ VALUE v = Qnil;
+ long size = (long)memo[1];
+
+ if (RARRAY_LEN(ary) == size) {
+ rb_ary_shift(ary);
+ }
+ rb_ary_push(ary, val);
+ if (RARRAY_LEN(ary) == size) {
+ v = rb_yield(rb_ary_dup(ary));
+ }
+ return v;
+}
+
+/*
+ * call-seq:
+ * each_cons(n) {...}
+ * each_cons(n)
+ *
+ * Iterates the given block for each array of consecutive <n>
+ * elements. If no block is given, returns an enumerator.a
+ *
+ * e.g.:
+ * (1..10).each_cons(3) {|a| p a}
+ * # outputs below
+ * [1, 2, 3]
+ * [2, 3, 4]
+ * [3, 4, 5]
+ * [4, 5, 6]
+ * [5, 6, 7]
+ * [6, 7, 8]
+ * [7, 8, 9]
+ * [8, 9, 10]
+ *
+ */
+static VALUE
+enum_each_cons(obj, n)
+ VALUE obj, n;
+{
+ long size = NUM2LONG(n);
+ VALUE args[2];
+
+ if (size <= 0) rb_raise(rb_eArgError, "invalid size");
+ RETURN_ENUMERATOR(obj, 1, &n);
+ args[0] = rb_ary_new2(size);
+ args[1] = (VALUE)size;
+
+ rb_block_call(obj, SYM2ID(sym_each), 0, 0, each_cons_i, (VALUE)args);
+
+ return Qnil;
+}
+
+static VALUE enumerator_allocate _((VALUE));
+static VALUE
+enumerator_allocate(klass)
+ VALUE klass;
+{
+ struct enumerator *ptr;
+ VALUE enum_obj;
+
+ enum_obj = Data_Make_Struct(klass, struct enumerator,
+ enumerator_mark, -1, ptr);
+ ptr->obj = Qundef;
+
+ return enum_obj;
+}
+
+static VALUE enumerator_each_i _((VALUE, VALUE));
+static VALUE
+enumerator_each_i(v, enum_obj)
+ VALUE v;
+ VALUE enum_obj;
+{
+ return rb_yield(v);
+}
+
+static VALUE
+enumerator_init(enum_obj, obj, meth, argc, argv)
+ VALUE enum_obj;
+ VALUE obj;
+ VALUE meth;
+ int argc;
+ VALUE *argv;
+{
+ struct enumerator *ptr;
+
+ Data_Get_Struct(enum_obj, struct enumerator, ptr);
+
+ if (!ptr) {
+ rb_raise(rb_eArgError, "unallocated enumerator");
+ }
+
+ ptr->obj = obj;
+ ptr->meth = rb_to_id(meth);
+ ptr->iter = enumerator_each_i;
+ if (argc) ptr->args = rb_ary_new4(argc, argv);
+
+ return enum_obj;
+}
+
+/*
+ * call-seq:
+ * Enumerable::Enumerator.new(obj, method = :each, *args)
+ *
+ * Creates a new Enumerable::Enumerator object, which is to be
+ * used as an Enumerable object using the given object's given
+ * method with the given arguments.
+ *
+ * Use of this method is discouraged. Use Kernel#enum_for() instead.
+ */
+static VALUE
+enumerator_initialize(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE recv, meth = sym_each;
+
+ if (argc == 0)
+ rb_raise(rb_eArgError, "wrong number of argument (0 for 1)");
+ recv = *argv++;
+ if (--argc) {
+ meth = *argv++;
+ --argc;
+ }
+ return enumerator_init(obj, recv, meth, argc, argv);
+}
+
+/* :nodoc: */
+static VALUE
+enumerator_init_copy(obj, orig)
+ VALUE obj;
+ VALUE orig;
+{
+ struct enumerator *ptr0, *ptr1;
+
+ ptr0 = enumerator_ptr(orig);
+
+ Data_Get_Struct(obj, struct enumerator, ptr1);
+
+ if (!ptr1) {
+ rb_raise(rb_eArgError, "unallocated enumerator");
+ }
+
+ ptr1->obj = ptr0->obj;
+ ptr1->meth = ptr0->meth;
+ ptr1->iter = ptr0->iter;
+ ptr1->args = ptr0->args;
+
+ return obj;
+}
+
+VALUE
+rb_enumeratorize(obj, meth, argc, argv)
+ VALUE obj;
+ VALUE meth;
+ int argc;
+ VALUE *argv;
+{
+ return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, meth, argc, argv);
+}
+
+/*
+ * call-seq:
+ * enum.each {...}
+ *
+ * Iterates the given block using the object and the method specified
+ * in the first place. If no block is given, returns self.
+ *
+ */
+static VALUE
+enumerator_each(obj)
+ VALUE obj;
+{
+ struct enumerator *e;
+ int argc = 0;
+ VALUE *argv = 0;
+
+ if (!rb_block_given_p()) return obj;
+ e = enumerator_ptr(obj);
+ if (e->args) {
+ argc = RARRAY_LEN(e->args);
+ argv = RARRAY_PTR(e->args);
+ }
+ return rb_block_call(e->obj, e->meth, argc, argv, e->iter, (VALUE)e);
+}
+
+static VALUE
+enumerator_with_index_i(val, memo)
+ VALUE val;
+ VALUE *memo;
+{
+ val = rb_yield_values(2, val, INT2FIX(*memo));
+ ++*memo;
+ return val;
+}
+
+/*
+ * call-seq:
+ * e.with_index {|(*args), idx| ... }
+ * e.with_index
+ *
+ * Iterates the given block for each elements with an index, which
+ * start from 0. If no block is given, returns an enumerator.
+ *
+ */
+static VALUE
+enumerator_with_index(obj)
+ VALUE obj;
+{
+ struct enumerator *e = enumerator_ptr(obj);
+ VALUE memo = 0;
+ int argc = 0;
+ VALUE *argv = 0;
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+ if (e->args) {
+ argc = RARRAY_LEN(e->args);
+ argv = RARRAY_PTR(e->args);
+ }
+ return rb_block_call(e->obj, e->meth, argc, argv,
+ enumerator_with_index_i, (VALUE)&memo);
+}
+
+/*
+ * call-seq:
+ * e.next => object
+ *
+ * Returns the next object in the enumerator, and move the internal
+ * position forward. When the position reached at the end, internal
+ * position is rewinded then StopIteration is raised.
+ *
+ * Note that enumeration sequence by next method does not affect other
+ * non-external enumeration methods, unless underlying iteration
+ * methods itself has side-effect, e.g. IO#each_line.
+ *
+ * Caution: Calling this method causes the "generator" library to be
+ * loaded.
+ */
+
+static VALUE
+enumerator_next(obj)
+ VALUE obj;
+{
+ rb_require("generator");
+ return rb_funcall(obj, rb_intern("next"), 0, 0);
+}
+
+/*
+ * call-seq:
+ * e.rewind => e
+ *
+ * Rewinds the enumeration sequence by the next method.
+ */
+
+static VALUE
+enumerator_rewind(obj)
+ VALUE obj;
+{
+ rb_require("generator");
+ return rb_funcall(obj, rb_intern("rewind"), 0, 0);
+}
+
+void
+Init_Enumerator()
+{
+ rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -1);
+ rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -1);
+
+ rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
+ rb_define_method(rb_mEnumerable, "enum_slice", enum_each_slice, 1);
+ rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
+ rb_define_method(rb_mEnumerable, "enum_cons", enum_each_cons, 1);
+
+ rb_cEnumerator = rb_define_class_under(rb_mEnumerable, "Enumerator", rb_cObject);
+ rb_include_module(rb_cEnumerator, rb_mEnumerable);
+
+ rb_define_alloc_func(rb_cEnumerator, enumerator_allocate);
+ rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
+ rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1);
+ rb_define_method(rb_cEnumerator, "each", enumerator_each, 0);
+ rb_define_method(rb_cEnumerator, "each_with_index", enumerator_with_index, 0);
+ rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, 0);
+ rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
+ rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
+
+ rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);
+
+ sym_each = ID2SYM(rb_intern("each"));
+
+ rb_provide("enumerator.so"); /* for backward compatibility */
+}
diff --git a/env.h b/env.h
index c47c01d9db..c50103f71e 100644
--- a/env.h
+++ b/env.h
@@ -16,7 +16,6 @@
extern struct FRAME {
VALUE self;
int argc;
- VALUE *argv;
ID last_func;
ID orig_func;
VALUE last_class;
@@ -30,8 +29,8 @@ extern struct FRAME {
void rb_gc_mark_frame _((struct FRAME *));
-#define FRAME_ALLOCA 0
-#define FRAME_MALLOC 1
+#define FRAME_DMETH 1
+#define FRAME_FUNC 2
extern struct SCOPE {
struct RBasic super;
@@ -44,6 +43,7 @@ extern struct SCOPE {
#define SCOPE_MALLOC 1
#define SCOPE_NOSTACK 2
#define SCOPE_DONT_RECYCLE 4
+#define SCOPE_CLONE 8
extern int ruby_in_eval;
diff --git a/error.c b/error.c
index d6b8be4c4d..a991f55e57 100644
--- a/error.c
+++ b/error.c
@@ -12,7 +12,6 @@
#include "ruby.h"
#include "env.h"
-#include "version.h"
#include "st.h"
#include <stdio.h>
@@ -23,6 +22,14 @@
#include <varargs.h>
#define va_init_list(a,b) va_start(a)
#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+
+extern const char *ruby_description;
int ruby_nerrs;
@@ -162,6 +169,14 @@ rb_warning(fmt, va_alist)
va_end(args);
}
+/*
+ * call-seq:
+ * warn(msg) => nil
+ *
+ * Display the given message (followed by a newline) on STDERR unless
+ * warnings are disabled (for example with the <code>-W0</code> flag).
+ */
+
static VALUE
rb_warn_m(self, mesg)
VALUE self, mesg;
@@ -193,8 +208,7 @@ rb_bug(fmt, va_alist)
va_init_list(args, fmt);
vfprintf(out, fmt, args);
va_end(args);
- fprintf(out, "\nruby %s (%s) [%s]\n\n",
- RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM);
+ fprintf(out, "\n%s\n\n", ruby_description);
}
abort();
}
@@ -243,7 +257,7 @@ rb_check_type(x, t)
if (TYPE(x) != t) {
while (type->type >= 0) {
if (type->type == t) {
- char *etype;
+ const char *etype;
if (NIL_P(x)) {
etype = "nil";
@@ -251,6 +265,9 @@ rb_check_type(x, t)
else if (FIXNUM_P(x)) {
etype = "Fixnum";
}
+ else if (SYMBOL_P(x)) {
+ etype = "Symbol";
+ }
else if (rb_special_const_p(x)) {
etype = RSTRING(rb_obj_as_string(x))->ptr;
}
@@ -285,6 +302,7 @@ VALUE rb_eNoMethodError;
VALUE rb_eSecurityError;
VALUE rb_eNotImpError;
VALUE rb_eNoMemError;
+VALUE rb_cNameErrorMesg;
VALUE rb_eScriptError;
VALUE rb_eSyntaxError;
@@ -315,9 +333,17 @@ rb_exc_new3(etype, str)
VALUE etype, str;
{
StringValue(str);
- return rb_exc_new(etype, RSTRING(str)->ptr, RSTRING(str)->len);
+ return rb_funcall(etype, rb_intern("new"), 1, str);
}
+/*
+ * call-seq:
+ * Exception.new(msg = nil) => exception
+ *
+ * Construct a new Exception object, optionally passing in
+ * a message.
+ */
+
static VALUE
exc_initialize(argc, argv, exc)
int argc;
@@ -326,16 +352,26 @@ exc_initialize(argc, argv, exc)
{
VALUE arg;
- if (rb_scan_args(argc, argv, "01", &arg) == 1) {
- VALUE mesg = arg;
- StringValue(mesg); /* ensure mesg can be converted to String */
- }
+ rb_scan_args(argc, argv, "01", &arg);
rb_iv_set(exc, "mesg", arg);
rb_iv_set(exc, "bt", Qnil);
return exc;
}
+/*
+ * Document-method: exception
+ *
+ * call-seq:
+ * exc.exception(string) -> an_exception or exc
+ *
+ * With no argument, or if the argument is the same as the receiver,
+ * return the receiver. Otherwise, create a new
+ * exception object of the same class as the receiver, but with a
+ * message equal to <code>string.to_str</code>.
+ *
+ */
+
static VALUE
exc_exception(argc, argv, self)
int argc;
@@ -352,17 +388,36 @@ exc_exception(argc, argv, self)
return exc;
}
+/*
+ * call-seq:
+ * exception.to_s => string
+ *
+ * Returns exception's message (or the name of the exception if
+ * no message is set).
+ */
+
static VALUE
exc_to_s(exc)
VALUE exc;
{
VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
- if (NIL_P(mesg)) return rb_class_path(CLASS_OF(exc));
+ if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
return mesg;
}
+/*
+ * call-seq:
+ * exception.message => string
+ * exception.to_str => string
+ *
+ * Returns the result of invoking <code>exception.to_s</code>.
+ * Normally this returns the exception's message or name. By
+ * supplying a to_str method, exceptions are agreeing to
+ * be used where Strings are expected.
+ */
+
static VALUE
exc_to_str(exc)
VALUE exc;
@@ -370,6 +425,13 @@ exc_to_str(exc)
return rb_funcall(exc, rb_intern("to_s"), 0, 0);
}
+/*
+ * call-seq:
+ * exception.inspect => string
+ *
+ * Return this exception's class name an message
+ */
+
static VALUE
exc_inspect(exc)
VALUE exc;
@@ -379,11 +441,11 @@ exc_inspect(exc)
klass = CLASS_OF(exc);
exc = rb_obj_as_string(exc);
if (RSTRING(exc)->len == 0) {
- return rb_str_dup(rb_class_path(klass));
+ return rb_str_dup(rb_class_name(klass));
}
str = rb_str_buf_new2("#<");
- klass = rb_class_path(klass);
+ klass = rb_class_name(klass);
rb_str_buf_append(str, klass);
rb_str_buf_cat(str, ": ", 2);
rb_str_buf_append(str, exc);
@@ -392,22 +454,51 @@ exc_inspect(exc)
return str;
}
+/*
+ * call-seq:
+ * exception.backtrace => array
+ *
+ * Returns any backtrace associated with the exception. The backtrace
+ * is an array of strings, each containing either ``filename:lineNo: in
+ * `method''' or ``filename:lineNo.''
+ *
+ * def a
+ * raise "boom"
+ * end
+ *
+ * def b
+ * a()
+ * end
+ *
+ * begin
+ * b()
+ * rescue => detail
+ * print detail.backtrace.join("\n")
+ * end
+ *
+ * <em>produces:</em>
+ *
+ * prog.rb:2:in `a'
+ * prog.rb:6:in `b'
+ * prog.rb:10
+*/
+
static VALUE
exc_backtrace(exc)
VALUE exc;
{
- ID bt = rb_intern("bt");
+ static ID bt;
- if (!rb_ivar_defined(exc, bt)) return Qnil;
- return rb_ivar_get(exc, bt);
+ if (!bt) bt = rb_intern("bt");
+ return rb_attr_get(exc, bt);
}
-static VALUE
-check_backtrace(bt)
+VALUE
+rb_check_backtrace(bt)
VALUE bt;
{
long i;
- static char *err = "backtrace must be Array of String";
+ static const char err[] = "backtrace must be Array of String";
if (!NIL_P(bt)) {
int t = TYPE(bt);
@@ -425,30 +516,55 @@ check_backtrace(bt)
return bt;
}
+/*
+ * call-seq:
+ * exc.set_backtrace(array) => array
+ *
+ * Sets the backtrace information associated with <i>exc</i>. The
+ * argument must be an array of <code>String</code> objects in the
+ * format described in <code>Exception#backtrace</code>.
+ *
+ */
+
static VALUE
exc_set_backtrace(exc, bt)
VALUE exc;
VALUE bt;
{
- return rb_iv_set(exc, "bt", check_backtrace(bt));
+ return rb_iv_set(exc, "bt", rb_check_backtrace(bt));
}
+/*
+ * call-seq:
+ * SystemExit.new(status=0) => system_exit
+ *
+ * Create a new +SystemExit+ exception with the given status.
+ */
+
static VALUE
exit_initialize(argc, argv, exc)
int argc;
VALUE *argv;
VALUE exc;
{
- VALUE status = INT2NUM(0);
+ VALUE status = INT2FIX(EXIT_SUCCESS);
if (argc > 0 && FIXNUM_P(argv[0])) {
status = *argv++;
--argc;
}
- exc_initialize(argc, argv, exc);
+ rb_call_super(argc, argv);
rb_iv_set(exc, "status", status);
return exc;
}
+
+/*
+ * call-seq:
+ * system_exit.status => fixnum
+ *
+ * Return the status value associated with this system exit.
+ */
+
static VALUE
exit_status(exc)
VALUE exc;
@@ -456,6 +572,24 @@ exit_status(exc)
return rb_attr_get(exc, rb_intern("status"));
}
+
+/*
+ * call-seq:
+ * system_exit.success? => true or false
+ *
+ * Returns +true+ if exiting successful, +false+ if not.
+ */
+
+static VALUE
+exit_success_p(exc)
+ VALUE exc;
+{
+ VALUE status = rb_attr_get(exc, rb_intern("status"));
+ if (NIL_P(status)) return Qtrue;
+ if (status == INT2FIX(EXIT_SUCCESS)) return Qtrue;
+ return Qfalse;
+}
+
void
#ifdef HAVE_STDARG_PROTOTYPES
rb_name_error(ID id, const char *fmt, ...)
@@ -480,6 +614,15 @@ rb_name_error(id, fmt, va_alist)
rb_exc_raise(exc);
}
+/*
+ * call-seq:
+ * NameError.new(msg [, name]) => name_error
+ *
+ * Construct a new NameError exception. If given the <i>name</i>
+ * parameter may subsequently be examined using the <code>NameError.name</code>
+ * method.
+ */
+
static VALUE
name_err_initialize(argc, argv, self)
int argc;
@@ -489,11 +632,18 @@ name_err_initialize(argc, argv, self)
VALUE name;
name = (argc > 1) ? argv[--argc] : Qnil;
- exc_initialize(argc, argv, self);
+ rb_call_super(argc, argv);
rb_iv_set(self, "name", name);
return self;
}
+/*
+ * call-seq:
+ * name_error.name => string or nil
+ *
+ * Return the name associated with this NameError exception.
+ */
+
static VALUE
name_err_name(self)
VALUE self;
@@ -501,6 +651,38 @@ name_err_name(self)
return rb_attr_get(self, rb_intern("name"));
}
+/*
+ * call-seq:
+ * name_error.to_s => string
+ *
+ * Produce a nicely-formated string representing the +NameError+.
+ */
+
+static VALUE
+name_err_to_s(exc)
+ VALUE exc;
+{
+ VALUE mesg = rb_attr_get(exc, rb_intern("mesg")), str = mesg;
+
+ if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
+ StringValue(str);
+ if (str != mesg) {
+ rb_iv_set(exc, "mesg", mesg = str);
+ }
+ if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
+ return mesg;
+}
+
+/*
+ * call-seq:
+ * NoMethodError.new(msg, name [, args]) => no_method_error
+ *
+ * Construct a NoMethodError exception for a method of the given name
+ * called with the given arguments. The name may be accessed using
+ * the <code>#name</code> method on the resulting object, and the
+ * arguments using the <code>#args</code> method.
+ */
+
static VALUE
nometh_err_initialize(argc, argv, self)
int argc;
@@ -513,6 +695,90 @@ nometh_err_initialize(argc, argv, self)
return self;
}
+/* :nodoc: */
+static void
+name_err_mesg_mark(ptr)
+ VALUE *ptr;
+{
+ rb_gc_mark_locations(ptr, ptr+3);
+}
+
+/* :nodoc: */
+static VALUE
+name_err_mesg_new(obj, mesg, recv, method)
+ VALUE obj, mesg, recv, method;
+{
+ VALUE *ptr = ALLOC_N(VALUE, 3);
+
+ ptr[0] = mesg;
+ ptr[1] = recv;
+ ptr[2] = method;
+ return Data_Wrap_Struct(rb_cNameErrorMesg, name_err_mesg_mark, -1, ptr);
+}
+
+/* :nodoc: */
+static VALUE
+name_err_mesg_to_str(obj)
+ VALUE obj;
+{
+ VALUE *ptr, mesg;
+ Data_Get_Struct(obj, VALUE, ptr);
+
+ mesg = ptr[0];
+ if (NIL_P(mesg)) return Qnil;
+ else {
+ const char *desc = 0;
+ VALUE d = 0, args[3];
+
+ obj = ptr[1];
+ switch (TYPE(obj)) {
+ case T_NIL:
+ desc = "nil";
+ break;
+ case T_TRUE:
+ desc = "true";
+ break;
+ case T_FALSE:
+ desc = "false";
+ break;
+ default:
+ d = rb_protect(rb_inspect, obj, 0);
+ if (NIL_P(d) || RSTRING(d)->len > 65) {
+ d = rb_any_to_s(obj);
+ }
+ desc = RSTRING(d)->ptr;
+ break;
+ }
+ if (desc && desc[0] != '#') {
+ d = rb_str_new2(desc);
+ rb_str_cat2(d, ":");
+ rb_str_cat2(d, rb_obj_classname(obj));
+ }
+ args[0] = mesg;
+ args[1] = ptr[2];
+ args[2] = d;
+ mesg = rb_f_sprintf(3, args);
+ }
+ if (OBJ_TAINTED(obj)) OBJ_TAINT(mesg);
+ return mesg;
+}
+
+/* :nodoc: */
+static VALUE
+name_err_mesg_load(klass, str)
+ VALUE klass, str;
+{
+ return str;
+}
+
+/*
+ * call-seq:
+ * no_method_error.args => obj
+ *
+ * Return the arguments passed in as the third parameter to
+ * the constructor.
+ */
+
static VALUE
nometh_err_args(self)
VALUE self;
@@ -529,6 +795,37 @@ rb_invalid_str(str, type)
rb_raise(rb_eArgError, "invalid value for %s: %s", type, RSTRING(s)->ptr);
}
+/*
+ * Document-module: Errno
+ *
+ * Ruby exception objects are subclasses of <code>Exception</code>.
+ * However, operating systems typically report errors using plain
+ * integers. Module <code>Errno</code> is created dynamically to map
+ * these operating system errors to Ruby classes, with each error
+ * number generating its own subclass of <code>SystemCallError</code>.
+ * As the subclass is created in module <code>Errno</code>, its name
+ * will start <code>Errno::</code>.
+ *
+ * The names of the <code>Errno::</code> classes depend on
+ * the environment in which Ruby runs. On a typical Unix or Windows
+ * platform, there are <code>Errno</code> classes such as
+ * <code>Errno::EACCES</code>, <code>Errno::EAGAIN</code>,
+ * <code>Errno::EINTR</code>, and so on.
+ *
+ * The integer operating system error number corresponding to a
+ * particular error is available as the class constant
+ * <code>Errno::</code><em>error</em><code>::Errno</code>.
+ *
+ * Errno::EACCES::Errno #=> 13
+ * Errno::EAGAIN::Errno #=> 11
+ * Errno::EINTR::Errno #=> 4
+ *
+ * The full list of operating system errors on your particular platform
+ * are available as the constants of <code>Errno</code>.
+ *
+ * Errno.constants #=> E2BIG, EACCES, EADDRINUSE, EADDRNOTAVAIL, ...
+ */
+
static st_table *syserr_tbl;
static VALUE
@@ -564,6 +861,17 @@ get_syserr(n)
return error;
}
+/*
+ * call-seq:
+ * SystemCallError.new(msg, errno) => system_call_error_subclass
+ *
+ * If _errno_ corresponds to a known system error code, constructs
+ * the appropriate <code>Errno</code> class for that error, otherwise
+ * constructs a generic <code>SystemCallError</code> object. The
+ * error number is subsequently available via the <code>errno</code>
+ * method.
+ */
+
static VALUE
syserr_initialize(argc, argv, self)
int argc;
@@ -573,8 +881,7 @@ syserr_initialize(argc, argv, self)
#if !defined(_WIN32) && !defined(__VMS)
char *strerror();
#endif
- char *err;
- char *buf;
+ const char *err;
VALUE mesg, error;
VALUE klass = rb_obj_class(self);
@@ -593,24 +900,36 @@ syserr_initialize(argc, argv, self)
}
else {
rb_scan_args(argc, argv, "01", &mesg);
- error = rb_const_get_at(klass, rb_intern("Errno"));
+ error = rb_const_get(klass, rb_intern("Errno"));
}
if (!NIL_P(error)) err = strerror(NUM2LONG(error));
else err = "unknown error";
if (!NIL_P(mesg)) {
- StringValue(mesg);
- buf = ALLOCA_N(char, strlen(err)+RSTRING(mesg)->len+4);
- sprintf(buf, "%s - %.*s", err, (int)RSTRING(mesg)->len, RSTRING(mesg)->ptr);
- mesg = rb_str_new2(buf);
+ VALUE str = mesg;
+ size_t len;
+
+ StringValue(str);
+ len = strlen(err)+RSTRING(str)->len+3;
+ mesg = rb_str_new(0, len);
+ snprintf(RSTRING(mesg)->ptr, len+1, "%s - %.*s", err,
+ (int)RSTRING(str)->len, RSTRING(str)->ptr);
+ rb_str_resize(mesg, strlen(RSTRING(mesg)->ptr));
}
else {
mesg = rb_str_new2(err);
}
- exc_initialize(1, &mesg, self);
+ rb_call_super(1, &mesg);
rb_iv_set(self, "errno", error);
return self;
}
+/*
+ * call-seq:
+ * system_call_error.errno => fixnum
+ *
+ * Return this SystemCallError's error number.
+ */
+
static VALUE
syserr_errno(self)
VALUE self;
@@ -618,23 +937,30 @@ syserr_errno(self)
return rb_attr_get(self, rb_intern("errno"));
}
+/*
+ * call-seq:
+ * system_call_error === other => true or false
+ *
+ * Return +true+ if the receiver is a generic +SystemCallError+, or
+ * if the error numbers _self_ and _other_ are the same.
+ */
+
+
static VALUE
syserr_eqq(self, exc)
VALUE self, exc;
{
VALUE num, e;
+ ID en = rb_intern("errno");
- if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) return Qfalse;
- if (self == rb_eSystemCallError) return Qtrue;
+ if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
+ if (!rb_respond_to(exc, en)) return Qfalse;
+ }
+ else if (self == rb_eSystemCallError) return Qtrue;
- num = rb_attr_get(exc, rb_intern("errno"));
+ num = rb_attr_get(exc, en);
if (NIL_P(num)) {
- VALUE klass = CLASS_OF(exc);
-
- while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) {
- klass = (VALUE)RCLASS(klass)->super;
- }
- num = rb_const_get(klass, rb_intern("Errno"));
+ num = rb_funcall(exc, en, 0, 0);
}
e = rb_const_get(self, rb_intern("Errno"));
if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
@@ -642,7 +968,15 @@ syserr_eqq(self, exc)
return Qfalse;
}
-static void init_syserr _((void));
+/*
+ * Descendents of class <code>Exception</code> are used to communicate
+ * between <code>raise</code> methods and <code>rescue</code>
+ * statements in <code>begin/end</code> blocks. <code>Exception</code>
+ * objects carry information about the exception---its type (the
+ * exception's class name), an optional descriptive string, and
+ * optional traceback information. Programs may subclass
+ * <code>Exception</code> to add additional information.
+ */
void
Init_Exception()
@@ -661,6 +995,7 @@ Init_Exception()
rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
rb_define_method(rb_eSystemExit, "status", exit_status, 0);
+ rb_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
rb_eFatal = rb_define_class("fatal", rb_eException);
rb_eSignal = rb_define_class("SignalException", rb_eException);
@@ -674,6 +1009,12 @@ Init_Exception()
rb_eNameError = rb_define_class("NameError", rb_eStandardError);
rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
rb_define_method(rb_eNameError, "name", name_err_name, 0);
+ rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
+ rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
+ rb_define_singleton_method(rb_cNameErrorMesg, "!", name_err_mesg_new, 3);
+ rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
+ rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_to_str, 1);
+ rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
@@ -739,7 +1080,7 @@ void
rb_notimplement()
{
rb_raise(rb_eNotImpError,
- "The %s() function is unimplemented on this machine",
+ "%s() function is unimplemented on this machine",
rb_id2name(ruby_frame->last_func));
}
@@ -767,7 +1108,6 @@ void
rb_sys_fail(mesg)
const char *mesg;
{
- extern int errno;
int n = errno;
VALUE arg;
@@ -808,14 +1148,14 @@ rb_sys_warning(fmt, va_alist)
void
rb_load_fail(path)
- char *path;
+ const char *path;
{
rb_loaderror("%s -- %s", strerror(errno), path);
}
void
rb_error_frozen(what)
- char *what;
+ const char *what;
{
rb_raise(rb_eTypeError, "can't modify frozen %s", what);
}
diff --git a/eval.c b/eval.c
index 5e88cf5176..e9c196d71f 100644
--- a/eval.c
+++ b/eval.c
@@ -29,7 +29,7 @@
#endif
#include <stdio.h>
-#include <setjmp.h>
+
#include "st.h"
#include "dln.h"
@@ -48,9 +48,7 @@
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
-# ifdef _AIX
- #pragma alloca
-# else
+# ifndef _AIX
# ifndef alloca /* predefined by HP cc +Olibcalls */
void *alloca ();
# endif
@@ -74,6 +72,8 @@ char *strrchr _((const char*,const char));
#include <unistd.h>
#endif
+#include <time.h>
+
#ifdef __BEOS__
#include <net/socket.h>
#endif
@@ -82,11 +82,125 @@ char *strrchr _((const char*,const char));
#include "macruby_private.h"
#endif
-#ifndef setjmp
-#ifdef HAVE__SETJMP
-#define setjmp(env) _setjmp(env)
-#define longjmp(env,val) _longjmp(env,val)
+#ifdef __VMS
+#include "vmsruby_private.h"
#endif
+
+#ifdef USE_CONTEXT
+
+NORETURN(static void rb_jump_context(rb_jmpbuf_t, int));
+static inline void
+rb_jump_context(env, val)
+ rb_jmpbuf_t env;
+ int val;
+{
+ env->status = val;
+ setcontext(&env->context);
+ abort(); /* ensure noreturn */
+}
+/*
+ * PRE_GETCONTEXT and POST_GETCONTEXT is a magic for getcontext, gcc,
+ * IA64 register stack and SPARC register window combination problem.
+ *
+ * Assume following code sequence.
+ *
+ * 1. set a register in the register stack/window such as r32/l0.
+ * 2. call getcontext.
+ * 3. use the register.
+ * 4. update the register for other use.
+ * 5. call setcontext indirectly (or directly).
+ *
+ * This code should be run as 1->2->3->4->5->3->4.
+ * But after second getcontext return (second 3),
+ * the register is broken (updated).
+ * It's because getcontext/setcontext doesn't preserve the content of the
+ * register stack/window.
+ *
+ * setjmp also doesn't preserve the content of the register stack/window.
+ * But it has not the problem because gcc knows setjmp may return twice.
+ * gcc detects setjmp and generates setjmp safe code.
+ *
+ * So setjmp calls before and after the getcontext call makes the code
+ * somewhat safe.
+ * It fix the problem on IA64.
+ * It is not required that setjmp is called at run time, since the problem is
+ * register usage.
+ *
+ * Since the magic setjmp is not enough for SPARC,
+ * inline asm is used to prohibit registers in register windows.
+ *
+ * Since the problem is fixed at gcc 4.0.3, the magic is applied only for
+ * prior versions of gcc.
+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21957
+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22127
+ */
+# define GCC_VERSION_BEFORE(major, minor, patchlevel) \
+ (defined(__GNUC__) && !defined(__INTEL_COMPILER) && \
+ ((__GNUC__ < (major)) || \
+ (__GNUC__ == (major) && __GNUC_MINOR__ < (minor)) || \
+ (__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ < (patchlevel))))
+# if GCC_VERSION_BEFORE(4,0,3) && (defined(sparc) || defined(__sparc__))
+# ifdef __pic__
+/*
+ * %l7 is excluded for PIC because it is PIC register.
+ * http://lists.freebsd.org/pipermail/freebsd-sparc64/2006-January/003739.html
+ */
+# define PRE_GETCONTEXT \
+ ({ __asm__ volatile ("" : : : \
+ "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7", \
+ "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", \
+ "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i7"); })
+# else
+# define PRE_GETCONTEXT \
+ ({ __asm__ volatile ("" : : : \
+ "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7", \
+ "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", \
+ "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i7"); })
+# endif
+# define POST_GETCONTEXT PRE_GETCONTEXT
+# elif GCC_VERSION_BEFORE(4,0,3) && defined(__ia64)
+static jmp_buf function_call_may_return_twice_jmp_buf;
+int function_call_may_return_twice_false_1 = 0;
+int function_call_may_return_twice_false_2 = 0;
+# define PRE_GETCONTEXT \
+ (function_call_may_return_twice_false_1 ? \
+ setjmp(function_call_may_return_twice_jmp_buf) : \
+ 0)
+# define POST_GETCONTEXT \
+ (function_call_may_return_twice_false_2 ? \
+ setjmp(function_call_may_return_twice_jmp_buf) : \
+ 0)
+# elif defined(__FreeBSD__) && __FreeBSD__ < 7
+/*
+ * workaround for FreeBSD/i386 getcontext/setcontext bug.
+ * clear the carry flag by (0 ? ... : ...).
+ * FreeBSD PR 92110 http://www.freebsd.org/cgi/query-pr.cgi?pr=92110
+ * [ruby-dev:28263]
+ */
+static int volatile freebsd_clear_carry_flag = 0;
+# define PRE_GETCONTEXT \
+ (freebsd_clear_carry_flag ? (freebsd_clear_carry_flag = 0) : 0)
+# endif
+# ifndef PRE_GETCONTEXT
+# define PRE_GETCONTEXT 0
+# endif
+# ifndef POST_GETCONTEXT
+# define POST_GETCONTEXT 0
+# endif
+# define ruby_longjmp(env, val) rb_jump_context(env, val)
+# define ruby_setjmp(just_before_setjmp, j) ((j)->status = 0, \
+ (just_before_setjmp), \
+ PRE_GETCONTEXT, \
+ getcontext(&(j)->context), \
+ POST_GETCONTEXT, \
+ (j)->status)
+#else
+# define ruby_setjmp(just_before_setjmp, env) \
+ ((just_before_setjmp), RUBY_SETJMP(env))
+# define ruby_longjmp(env,val) RUBY_LONGJMP(env,val)
+# ifdef __CYGWIN__
+int _setjmp(), _longjmp();
+# endif
#endif
#include <sys/types.h>
@@ -104,17 +218,20 @@ char *strrchr _((const char*,const char));
#include <sys/stat.h>
VALUE rb_cProc;
-static VALUE rb_cBinding;
+VALUE rb_cBinding;
static VALUE proc_invoke _((VALUE,VALUE,VALUE,VALUE));
static VALUE rb_f_binding _((VALUE));
static void rb_f_END _((void));
static VALUE rb_f_block_given_p _((void));
static VALUE block_pass _((VALUE,NODE*));
-static VALUE rb_cMethod;
+
+VALUE rb_cMethod;
static VALUE method_call _((int, VALUE*, VALUE));
-static VALUE rb_cUnboundMethod;
+VALUE rb_cUnboundMethod;
static VALUE umethod_bind _((VALUE, VALUE));
static VALUE rb_mod_define_method _((int, VALUE*, VALUE));
+NORETURN(static void rb_raise_jump _((VALUE)));
+static VALUE rb_make_exception _((int argc, VALUE *argv));
static int scope_vmode;
#define SCOPE_PUBLIC 0
@@ -125,6 +242,8 @@ static int scope_vmode;
#define SCOPE_SET(f) (scope_vmode=(f))
#define SCOPE_TEST(f) (scope_vmode&(f))
+VALUE (*ruby_sandbox_save)_((rb_thread_t));
+VALUE (*ruby_sandbox_restore)_((rb_thread_t));
NODE* ruby_current_node;
int ruby_safe_level = 0;
/* safe-level:
@@ -240,7 +359,8 @@ rb_clear_cache_for_undef(klass, id)
if (!ruby_running) return;
ent = cache; end = ent + CACHE_SIZE;
while (ent < end) {
- if (ent->origin == klass && ent->mid == id) {
+ if (ent->mid == id &&
+ RCLASS(ent->origin)->m_tbl == RCLASS(klass)->m_tbl) {
ent->mid = 0;
}
ent++;
@@ -281,7 +401,12 @@ rb_clear_cache_by_class(klass)
static ID init, eqq, each, aref, aset, match, missing;
static ID added, singleton_added;
-static ID __id__, __send__;
+static ID __id__, __send__, respond_to;
+
+#define NOEX_TAINTED 8
+#define NOEX_SAFE(n) ((n) >> 4)
+#define NOEX_WITH(n, v) ((n) | (v) << 4)
+#define NOEX_WITH_SAFE(n) NOEX_WITH(n, ruby_safe_level)
void
rb_add_method(klass, mid, node, noex)
@@ -309,7 +434,7 @@ rb_add_method(klass, mid, node, noex)
}
if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
rb_clear_cache_by_id(mid);
- body = NEW_METHOD(node, noex);
+ body = NEW_METHOD(node, NOEX_WITH_SAFE(noex));
st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t)body);
if (node && mid != ID_ALLOCATOR && ruby_running) {
if (FL_TEST(klass, FL_SINGLETON)) {
@@ -327,7 +452,8 @@ rb_define_alloc_func(klass, func)
VALUE (*func) _((VALUE));
{
Check_Type(klass, T_CLASS);
- rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), NOEX_PRIVATE);
+ rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
+ NOEX_PRIVATE);
}
void
@@ -335,7 +461,7 @@ rb_undef_alloc_func(klass)
VALUE klass;
{
Check_Type(klass, T_CLASS);
- rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
+ rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
}
static NODE*
@@ -343,16 +469,16 @@ search_method(klass, id, origin)
VALUE klass, *origin;
ID id;
{
- NODE *body;
+ st_data_t body;
if (!klass) return 0;
- while (!st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *)&body)) {
+ while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) {
klass = RCLASS(klass)->super;
if (!klass) return 0;
}
if (origin) *origin = klass;
- return body;
+ return (NODE *)body;
}
static NODE*
@@ -363,7 +489,7 @@ rb_get_method_body(klassp, idp, noexp)
{
ID id = *idp;
VALUE klass = *klassp;
- VALUE origin;
+ VALUE origin = 0;
NODE * volatile body;
struct cache_entry *ent;
@@ -381,7 +507,6 @@ rb_get_method_body(klassp, idp, noexp)
if (ruby_running) {
/* store in cache */
- if (BUILTIN_TYPE(origin) == T_ICLASS) origin = RBASIC(origin)->klass;
ent = cache + EXPR1(klass, id);
ent->klass = klass;
ent->noex = body->nd_noex;
@@ -432,7 +557,8 @@ remove_method(klass, mid)
VALUE klass;
ID mid;
{
- NODE *body;
+ st_data_t data;
+ NODE *body = 0;
if (klass == rb_cObject) {
rb_secure(4);
@@ -444,8 +570,14 @@ remove_method(klass, mid)
if (mid == __id__ || mid == __send__ || mid == init) {
rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
}
- if (!st_delete(RCLASS(klass)->m_tbl, &mid, (st_data_t *)&body) ||
- !body->nd_body) {
+ if (st_lookup(RCLASS(klass)->m_tbl, mid, &data)) {
+ body = (NODE *)data;
+ if (!body || !body->nd_body) body = 0;
+ else {
+ st_delete(RCLASS(klass)->m_tbl, &mid, &data);
+ }
+ }
+ if (!body) {
rb_name_error(mid, "method `%s' not defined in %s",
rb_id2name(mid), rb_class2name(klass));
}
@@ -466,6 +598,14 @@ rb_remove_method(klass, name)
remove_method(klass, rb_intern(name));
}
+/*
+ * call-seq:
+ * remove_method(symbol) => self
+ *
+ * Removes the method identified by _symbol_ from the current
+ * class. For an example, see <code>Module.undef_method</code>.
+ */
+
static VALUE
rb_mod_remove_method(argc, argv, mod)
int argc;
@@ -496,7 +636,7 @@ rb_enable_super(klass, name)
VALUE klass;
const char *name;
{
- rb_warning("rb_enable_super() is obsolete");
+ rb_warn("rb_enable_super() is obsolete");
}
static void
@@ -563,6 +703,7 @@ rb_attr(klass, id, read, write, ex)
char *buf;
ID attriv;
int noex;
+ size_t len;
if (!ex) noex = NOEX_PUBLIC;
else {
@@ -580,20 +721,22 @@ rb_attr(klass, id, read, write, ex)
}
}
+ if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
+ rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
+ }
name = rb_id2name(id);
if (!name) {
rb_raise(rb_eArgError, "argument needs to be symbol or string");
}
- buf = ALLOCA_N(char,strlen(name)+2);
- sprintf(buf, "@%s", name);
+ len = strlen(name)+2;
+ buf = ALLOCA_N(char,len);
+ snprintf(buf, len, "@%s", name);
attriv = rb_intern(buf);
if (read) {
rb_add_method(klass, id, NEW_IVAR(attriv), noex);
}
if (write) {
- sprintf(buf, "%s=", name);
- id = rb_intern(buf);
- rb_add_method(klass, id, NEW_ATTRSET(attriv), noex);
+ rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
}
}
@@ -604,8 +747,8 @@ extern NODE *ruby_eval_tree_begin;
extern NODE *ruby_eval_tree;
extern int ruby_nerrs;
-static VALUE rb_eLocalJumpError;
-static VALUE rb_eSysStackError;
+VALUE rb_eLocalJumpError;
+VALUE rb_eSysStackError;
extern VALUE ruby_top_self;
@@ -617,14 +760,13 @@ static struct SCOPE *top_scope;
static unsigned long frame_unique = 0;
#define PUSH_FRAME() do { \
- struct FRAME _frame; \
+ volatile struct FRAME _frame; \
_frame.prev = ruby_frame; \
_frame.tmp = 0; \
_frame.node = ruby_current_node; \
_frame.iter = ruby_iter->iter; \
_frame.argc = 0; \
- _frame.argv = 0; \
- _frame.flags = FRAME_ALLOCA; \
+ _frame.flags = 0; \
_frame.uniq = frame_unique++; \
ruby_frame = &_frame
@@ -644,6 +786,7 @@ struct BLOCK {
int iter;
int vmode;
int flags;
+ int uniq;
struct RVarmap *dyna_vars;
VALUE orig_thread;
VALUE wrapper;
@@ -656,11 +799,12 @@ struct BLOCK {
#define BLOCK_LAMBDA 2
static struct BLOCK *ruby_block;
+static unsigned long block_unique = 1;
#define PUSH_BLOCK(v,b) do { \
struct BLOCK _block; \
- _block.var = v; \
- _block.body = b; \
+ _block.var = (v); \
+ _block.body = (b); \
_block.self = self; \
_block.frame = *ruby_frame; \
_block.klass = ruby_class; \
@@ -675,6 +819,10 @@ static struct BLOCK *ruby_block;
_block.dyna_vars = ruby_dyna_vars; \
_block.wrapper = ruby_wrapper; \
_block.block_obj = 0; \
+ _block.uniq = (b)?block_unique++:0; \
+ if (b) { \
+ prot_tag->blkid = _block.uniq; \
+ } \
ruby_block = &_block
#define POP_BLOCK() \
@@ -688,15 +836,17 @@ struct RVarmap *ruby_dyna_vars;
ruby_dyna_vars = 0
#define POP_VARS() \
- if (_old && (ruby_scope->flags & SCOPE_DONT_RECYCLE)) {\
- if (RBASIC(_old)->flags) /* unless it's already recycled */ \
- FL_SET(_old, DVAR_DONT_RECYCLE); \
+ if (_old && (ruby_scope->flags & SCOPE_DONT_RECYCLE)) {\
+ if (RBASIC(_old)->flags) /* unless it's already recycled */ \
+ FL_SET(_old, DVAR_DONT_RECYCLE); \
}\
ruby_dyna_vars = _old; \
} while (0)
#define DVAR_DONT_RECYCLE FL_USER2
+#define DMETHOD_P() (ruby_frame->flags & FRAME_DMETH)
+
static struct RVarmap*
new_dvar(id, value, prev)
ID id;
@@ -835,6 +985,7 @@ static struct iter *ruby_iter;
#define ITER_NOT 0
#define ITER_PRE 1
#define ITER_CUR 2
+#define ITER_PAS 3
#define PUSH_ITER(i) do { \
struct iter _iter; \
@@ -847,7 +998,7 @@ static struct iter *ruby_iter;
} while (0)
struct tag {
- jmp_buf buf;
+ rb_jmpbuf_t buf;
struct FRAME *frame;
struct iter *iter;
VALUE tag;
@@ -855,6 +1006,7 @@ struct tag {
struct SCOPE *scope;
VALUE dst;
struct tag *prev;
+ int blkid;
};
static struct tag *prot_tag;
@@ -867,21 +1019,22 @@ static struct tag *prot_tag;
_tag.scope = ruby_scope; \
_tag.tag = ptag; \
_tag.dst = 0; \
+ _tag.blkid = 0; \
prot_tag = &_tag
#define PROT_NONE Qfalse /* 0 */
#define PROT_THREAD Qtrue /* 2 */
#define PROT_FUNC INT2FIX(0) /* 1 */
-#define PROT_ITER INT2FIX(1) /* 3 */
-#define PROT_CALL INT2FIX(2) /* 5 */
-#define PROT_PCALL INT2FIX(3) /* 7 */
+#define PROT_LOOP INT2FIX(1) /* 3 */
+#define PROT_LAMBDA INT2FIX(2) /* 5 */
+#define PROT_YIELD INT2FIX(3) /* 7 */
-#define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, setjmp(prot_tag->buf))
+#define EXEC_TAG() ruby_setjmp(((void)0), prot_tag->buf)
#define JUMP_TAG(st) do { \
ruby_frame = prot_tag->frame; \
ruby_iter = prot_tag->iter; \
- longjmp(prot_tag->buf,(st)); \
+ ruby_longjmp(prot_tag->buf,(st)); \
} while (0)
#define POP_TAG() \
@@ -904,15 +1057,15 @@ VALUE ruby_class;
static VALUE ruby_wrapper; /* security wrapper */
#define PUSH_CLASS(c) do { \
- VALUE _class = ruby_class; \
+ volatile VALUE _class = ruby_class; \
ruby_class = (c)
#define POP_CLASS() ruby_class = _class; \
} while (0)
-static NODE *ruby_cref = 0;
-static NODE *top_cref;
-#define PUSH_CREF(c) ruby_cref = NEW_NODE(NODE_CREF,(c),0,ruby_cref)
+NODE *ruby_cref = 0;
+NODE *ruby_top_cref;
+#define PUSH_CREF(c) ruby_cref = NEW_CREF(c,ruby_cref)
#define POP_CREF() ruby_cref = ruby_cref->nd_next
#define PUSH_SCOPE() do { \
@@ -927,22 +1080,24 @@ static NODE *top_cref;
ruby_scope = _scope; \
scope_vmode = SCOPE_PUBLIC
-typedef struct thread * rb_thread_t;
-static rb_thread_t curr_thread = 0;
-static rb_thread_t main_thread;
+rb_thread_t rb_curr_thread;
+rb_thread_t rb_main_thread;
+#define main_thread rb_main_thread
+#define curr_thread rb_curr_thread
+
static void scope_dup _((struct SCOPE *));
#define POP_SCOPE() \
if (ruby_scope->flags & SCOPE_DONT_RECYCLE) {\
- if (_old) scope_dup(_old); \
+ if (_old) scope_dup(_old); \
} \
if (!(ruby_scope->flags & SCOPE_MALLOC)) {\
ruby_scope->local_vars = 0; \
ruby_scope->local_tbl = 0; \
if (!(ruby_scope->flags & SCOPE_DONT_RECYCLE) && \
- ruby_scope != top_scope) { \
+ ruby_scope != top_scope) { \
rb_gc_force_recycle((VALUE)ruby_scope);\
- } \
+ } \
} \
ruby_scope->flags |= SCOPE_NOSTACK; \
ruby_scope = _old; \
@@ -950,25 +1105,50 @@ static void scope_dup _((struct SCOPE *));
} while (0)
static VALUE rb_eval _((VALUE,NODE*));
-static VALUE eval _((VALUE,VALUE,VALUE,char*,int));
-static NODE *compile _((VALUE, char*, int));
+static VALUE eval _((VALUE,VALUE,VALUE,const char*,int));
+static NODE *compile _((VALUE, const char*, int));
static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
-#define YIELD_PROC_CALL 1
-#define YIELD_PUBLIC_DEF 2
+#define YIELD_LAMBDA_CALL 1
+#define YIELD_PROC_CALL 2
+#define YIELD_PUBLIC_DEF 4
#define YIELD_FUNC_AVALUE 1
#define YIELD_FUNC_SVALUE 2
+#define YIELD_FUNC_LAMBDA 3
-static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int));
+static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int,VALUE));
static VALUE module_setup _((VALUE,NODE*));
static VALUE massign _((VALUE,NODE*,VALUE,int));
static void assign _((VALUE,NODE*,VALUE,int));
+typedef struct event_hook {
+ rb_event_hook_func_t func;
+ rb_event_t events;
+ struct event_hook *next;
+} rb_event_hook_t;
+
+static rb_event_hook_t *event_hooks;
+
+#define EXEC_EVENT_HOOK(event, node, self, id, klass) \
+ do { \
+ rb_event_hook_t *hook = event_hooks; \
+ rb_event_hook_func_t hook_func; \
+ rb_event_t events; \
+ \
+ while (hook) { \
+ hook_func = hook->func; \
+ events = hook->events; \
+ hook = hook->next; \
+ if (events & event) \
+ (*hook_func)(event, node, self, id, klass); \
+ } \
+ } while (0)
+
static VALUE trace_func = 0;
static int tracing = 0;
-static void call_trace_func _((char*,NODE*,VALUE,ID,VALUE));
+static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE));
#if 0
#define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \
@@ -981,7 +1161,7 @@ void
ruby_set_current_source()
{
if (ruby_current_node) {
- ruby_sourcefile = ruby_current_node->nd_file;
+ ruby_sourcefile = ruby_current_node->nd_file;
ruby_sourceline = nd_line(ruby_current_node);
}
}
@@ -1014,7 +1194,7 @@ error_pos()
if (ruby_sourcefile) {
if (ruby_frame->last_func) {
warn_printf("%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline,
- rb_id2name(ruby_frame->last_func));
+ rb_id2name(ruby_frame->orig_func));
}
else if (ruby_sourceline == 0) {
warn_printf("%s", ruby_sourcefile);
@@ -1025,12 +1205,16 @@ error_pos()
}
}
+VALUE rb_check_backtrace(VALUE);
+
static VALUE
get_backtrace(info)
VALUE info;
{
if (NIL_P(info)) return Qnil;
- return rb_funcall(info, rb_intern("backtrace"), 0);
+ info = rb_funcall(info, rb_intern("backtrace"), 0);
+ if (NIL_P(info)) return Qnil;
+ return rb_check_backtrace(info);
}
static void
@@ -1045,7 +1229,7 @@ error_print()
{
VALUE errat = Qnil; /* OK */
volatile VALUE eclass, e;
- char *einfo;
+ const char *einfo;
long elen;
if (NIL_P(ruby_errinfo)) return;
@@ -1079,7 +1263,8 @@ error_print()
eclass = CLASS_OF(ruby_errinfo);
if (EXEC_TAG() == 0) {
- e = rb_obj_as_string(ruby_errinfo);
+ e = rb_funcall(ruby_errinfo, rb_intern("message"), 0, 0);
+ StringValue(e);
einfo = RSTRING(e)->ptr;
elen = RSTRING(e)->len;
}
@@ -1094,17 +1279,18 @@ error_print()
else {
VALUE epath;
- epath = rb_class_path(eclass);
+ epath = rb_class_name(eclass);
if (elen == 0) {
warn_print(": ");
warn_print2(RSTRING(epath)->ptr, RSTRING(epath)->len);
+ warn_print("\n");
}
else {
char *tail = 0;
long len = elen;
if (RSTRING(epath)->ptr[0] == '#') epath = 0;
- if (tail = memchr(einfo, '\n', elen)) {
+ if ((tail = memchr(einfo, '\n', elen)) != 0) {
len = tail - einfo;
tail++; /* skip newline */
}
@@ -1115,8 +1301,9 @@ error_print()
warn_print2(RSTRING(epath)->ptr, RSTRING(epath)->len);
warn_print(")\n");
}
- if (tail) {
+ if (tail && elen>len+1) {
warn_print2(tail, elen-len-1);
+ if (einfo[elen-1] != '\n') warn_print2("\n", 1);
}
}
}
@@ -1124,6 +1311,7 @@ error_print()
if (!NIL_P(errat)) {
long i;
struct RArray *ep = RARRAY(errat);
+ int truncate = eclass == rb_eSysStackError;
#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
#define TRACE_HEAD 8
@@ -1134,7 +1322,7 @@ error_print()
if (TYPE(ep->ptr[i]) == T_STRING) {
warn_printf("\tfrom %s\n", RSTRING(ep->ptr[i])->ptr);
}
- if (i == TRACE_HEAD && ep->len > TRACE_MAX) {
+ if (truncate && i == TRACE_HEAD && ep->len > TRACE_MAX) {
warn_printf("\t ... %ld levels...\n",
ep->len - TRACE_HEAD - TRACE_TAIL);
i = ep->len - TRACE_TAIL;
@@ -1153,7 +1341,7 @@ extern char **environ;
char **rb_origenviron;
void rb_call_inits _((void));
-void Init_stack _((void*));
+void Init_stack _((VALUE*));
void Init_heap _((void));
void Init_ext _((void));
@@ -1163,6 +1351,15 @@ int
is_ruby_native_thread() {
return NATIVETHREAD_EQUAL(ruby_thid, NATIVETHREAD_CURRENT());
}
+
+# ifdef HAVE_NATIVETHREAD_KILL
+void
+ruby_native_thread_kill(sig)
+ int sig;
+{
+ NATIVETHREAD_KILL(ruby_thid, sig);
+}
+# endif
#endif
void
@@ -1203,11 +1400,13 @@ ruby_init()
rb_call_inits();
ruby_class = rb_cObject;
ruby_frame->self = ruby_top_self;
- top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
- ruby_cref = top_cref;
+ ruby_top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
+ ruby_cref = ruby_top_cref;
rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self));
#ifdef __MACOS__
_macruby_init();
+#elif defined(__VMS)
+ _vmsruby_init();
#endif
ruby_prog_init();
ALLOW_INTS;
@@ -1219,6 +1418,7 @@ ruby_init()
}
POP_SCOPE();
ruby_scope = top_scope;
+ top_scope->flags &= ~SCOPE_NOSTACK;
ruby_running = 1;
}
@@ -1240,22 +1440,33 @@ eval_node(self, node)
int ruby_in_eval;
+static int rb_thread_join _((rb_thread_t, double));
+
static void rb_thread_cleanup _((void));
static void rb_thread_wait_other_threads _((void));
-static int thread_set_raised();
-static int thread_reset_raised();
+static int thread_no_ensure _((void));
static VALUE exception_error;
static VALUE sysstack_error;
static int
+sysexit_status(err)
+ VALUE err;
+{
+ VALUE st = rb_iv_get(err, "status");
+ return NUM2INT(st);
+}
+
+static int
error_handle(ex)
int ex;
{
int status = EXIT_FAILURE;
+ rb_thread_t th = curr_thread;
- if (thread_set_raised()) return EXIT_FAILURE;
+ if (rb_thread_set_raised(th))
+ return EXIT_FAILURE;
switch (ex & TAG_MASK) {
case 0:
status = EXIT_SUCCESS;
@@ -1295,8 +1506,10 @@ error_handle(ex)
case TAG_RAISE:
case TAG_FATAL:
if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
- VALUE st = rb_iv_get(ruby_errinfo, "status");
- status = NUM2INT(st);
+ status = sysexit_status(ruby_errinfo);
+ }
+ else if (rb_obj_is_instance_of(ruby_errinfo, rb_eSignal)) {
+ /* no message when exiting by signal */
}
else {
error_print();
@@ -1306,7 +1519,7 @@ error_handle(ex)
rb_bug("Unknown longjmp status %d", ex);
break;
}
- thread_reset_raised();
+ rb_thread_reset_raised(th);
return status;
}
@@ -1346,6 +1559,7 @@ ruby_finalize_0()
static void
ruby_finalize_1()
{
+ signal(SIGINT, SIG_DFL);
ruby_errinfo = 0;
rb_gc_call_finalizer_at_exit();
trace_func = 0;
@@ -1364,12 +1578,14 @@ ruby_cleanup(ex)
int ex;
{
int state;
- volatile VALUE err = ruby_errinfo;
+ volatile VALUE errs[2];
+ int nerr;
+ errs[1] = ruby_errinfo;
ruby_safe_level = 0;
- Init_stack((void*)&state);
+ Init_stack((void *)&state);
ruby_finalize_0();
- if (ruby_errinfo) err = ruby_errinfo;
+ errs[0] = ruby_errinfo;
PUSH_TAG(PROT_NONE);
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
@@ -1380,25 +1596,47 @@ ruby_cleanup(ex)
ex = state;
}
POP_ITER();
- ruby_errinfo = err;
+ ruby_errinfo = errs[1];
ex = error_handle(ex);
+ ruby_finalize_1();
POP_TAG();
- ruby_finalize_1();
- if (err && rb_obj_is_kind_of(err, rb_eSystemExit)) {
- VALUE st = rb_iv_get(err, "status");
- return NUM2INT(st);
+ for (nerr = 0; nerr < sizeof(errs) / sizeof(errs[0]); ++nerr) {
+ VALUE err = errs[nerr];
+
+ if (!RTEST(err)) continue;
+
+ if (rb_obj_is_kind_of(err, rb_eSystemExit)) {
+ return sysexit_status(err);
+ }
+ else if (rb_obj_is_kind_of(err, rb_eSignal)) {
+ VALUE sig = rb_iv_get(err, "signo");
+ ruby_default_signal(NUM2INT(sig));
+ }
+ else if (ex == 0) {
+ ex = 1;
+ }
}
+
+#if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
+ switch (ex) {
+#if EXIT_SUCCESS != 0
+ case 0: return EXIT_SUCCESS;
+#endif
+#if EXIT_FAILURE != 1
+ case 1: return EXIT_FAILURE;
+#endif
+ }
+#endif
+
return ex;
}
-int
-ruby_exec()
+static int
+ruby_exec_internal()
{
int state;
- volatile NODE *tmp;
- Init_stack((void*)&tmp);
PUSH_TAG(PROT_NONE);
PUSH_ITER(ITER_NOT);
/* default visibility is private at toplevel */
@@ -1418,6 +1656,15 @@ ruby_stop(ex)
exit(ruby_cleanup(ex));
}
+int
+ruby_exec()
+{
+ volatile NODE *tmp;
+
+ Init_stack((void*)&tmp);
+ return ruby_exec_internal();
+}
+
void
ruby_run()
{
@@ -1469,22 +1716,7 @@ rb_eval_string_protect(str, state)
const char *str;
int *state;
{
- VALUE result = Qnil; /* OK */
- int status;
-
- PUSH_TAG(PROT_NONE);
- if ((status = EXEC_TAG()) == 0) {
- result = rb_eval_string(str);
- }
- POP_TAG();
- if (state) {
- *state = status;
- }
- if (status != 0) {
- return Qnil;
- }
-
- return result;
+ return rb_protect((VALUE (*)_((VALUE)))rb_eval_string, (VALUE)str, state);
}
VALUE
@@ -1502,7 +1734,6 @@ rb_eval_string_wrap(str, state)
rb_extend_object(ruby_top_self, ruby_wrapper);
PUSH_FRAME();
ruby_frame->last_func = 0;
- ruby_frame->orig_func = 0;
ruby_frame->last_class = 0;
ruby_frame->self = self;
PUSH_CREF(ruby_wrapper);
@@ -1524,6 +1755,7 @@ rb_eval_string_wrap(str, state)
return val;
}
+NORETURN(static void localjump_error(const char*, VALUE, int));
static void
localjump_error(mesg, value, reason)
const char *mesg;
@@ -1552,6 +1784,12 @@ localjump_error(mesg, value, reason)
rb_exc_raise(exc);
}
+/*
+ * call_seq:
+ * local_jump_error.exit_value => obj
+ *
+ * Returns the exit value associated with this +LocalJumpError+.
+ */
static VALUE
localjump_xvalue(exc)
VALUE exc;
@@ -1559,6 +1797,14 @@ localjump_xvalue(exc)
return rb_iv_get(exc, "@exit_value");
}
+/*
+ * call-seq:
+ * local_jump_error.reason => symbol
+ *
+ * The reason this block was terminated:
+ * :break, :redo, :retry, :next, :return, or :noreason.
+ */
+
static VALUE
localjump_reason(exc)
VALUE exc;
@@ -1566,15 +1812,14 @@ localjump_reason(exc)
return rb_iv_get(exc, "@reason");
}
-NORETURN(static void jump_tag_but_local_jump _((int)));
+NORETURN(static void jump_tag_but_local_jump _((int,VALUE)));
static void
-jump_tag_but_local_jump(state)
+jump_tag_but_local_jump(state, val)
int state;
-{
VALUE val;
+{
- if (prot_tag) val = prot_tag->retval;
- else val = Qnil;
+ if (val == Qundef) val = prot_tag->retval;
switch (state) {
case 0:
break;
@@ -1600,19 +1845,29 @@ jump_tag_but_local_jump(state)
}
VALUE
-rb_eval_cmd(cmd, arg, tcheck)
+rb_eval_cmd(cmd, arg, level)
VALUE cmd, arg;
- int tcheck;
+ int level;
{
int state;
VALUE val = Qnil; /* OK */
struct SCOPE *saved_scope;
volatile int safe = ruby_safe_level;
+ if (OBJ_TAINTED(cmd)) {
+ level = 4;
+ }
if (TYPE(cmd) != T_STRING) {
PUSH_ITER(ITER_NOT);
- val = rb_funcall2(cmd, rb_intern("call"), RARRAY(arg)->len, RARRAY(arg)->ptr);
+ PUSH_TAG(PROT_NONE);
+ ruby_safe_level = level;
+ if ((state = EXEC_TAG()) == 0) {
+ val = rb_funcall2(cmd, rb_intern("call"), RARRAY(arg)->len, RARRAY(arg)->ptr);
+ }
+ ruby_safe_level = safe;
+ POP_TAG();
POP_ITER();
+ if (state) JUMP_TAG(state);
return val;
}
@@ -1620,64 +1875,24 @@ rb_eval_cmd(cmd, arg, tcheck)
ruby_scope = top_scope;
PUSH_FRAME();
ruby_frame->last_func = 0;
- ruby_frame->orig_func = 0;
ruby_frame->last_class = 0;
ruby_frame->self = ruby_top_self;
PUSH_CREF(ruby_wrapper ? ruby_wrapper : rb_cObject);
- if (tcheck && OBJ_TAINTED(cmd)) {
- ruby_safe_level = 4;
- }
+ ruby_safe_level = level;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
val = eval(ruby_top_self, cmd, Qnil, 0, 0);
}
if (ruby_scope->flags & SCOPE_DONT_RECYCLE)
- scope_dup(saved_scope);
+ scope_dup(saved_scope);
ruby_scope = saved_scope;
ruby_safe_level = safe;
POP_TAG();
POP_FRAME();
- jump_tag_but_local_jump(state);
- return val;
-}
-
-static VALUE
-superclass(self, node)
- VALUE self;
- NODE *node;
-{
- VALUE val = Qnil; /* OK */
- int state;
-
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- val = rb_eval(self, node);
- }
- POP_TAG();
- if (state) {
- switch (nd_type(node)) {
- case NODE_COLON2:
- rb_raise(rb_eTypeError, "undefined superclass `%s'",
- rb_id2name(node->nd_mid));
- case NODE_CONST:
- rb_raise(rb_eTypeError, "undefined superclass `%s'",
- rb_id2name(node->nd_vid));
- default:
- break;
- }
- JUMP_TAG(state);
- }
- if (TYPE(val) != T_CLASS) {
- rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
- rb_obj_classname(val));
- }
- if (FL_TEST(val, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "can't make subclass of virtual class");
- }
-
+ if (state) jump_tag_but_local_jump(state, val);
return val;
}
@@ -1695,12 +1910,13 @@ ev_const_defined(cref, id, self)
while (cbase && cbase->nd_next) {
struct RClass *klass = RCLASS(cbase->nd_clss);
- if (NIL_P(klass)) return rb_const_defined(CLASS_OF(self), id);
- if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, &result)) {
- if (result == Qundef && NIL_P(rb_autoload_p((VALUE)klass, id))) {
- return Qfalse;
+ if (!NIL_P(klass)) {
+ if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, &result)) {
+ if (result == Qundef && NIL_P(rb_autoload_p((VALUE)klass, id))) {
+ return Qfalse;
+ }
+ return Qtrue;
}
- return Qtrue;
}
cbase = cbase->nd_next;
}
@@ -1719,17 +1935,19 @@ ev_const_get(cref, id, self)
while (cbase && cbase->nd_next) {
VALUE klass = cbase->nd_clss;
- if (NIL_P(klass)) return rb_const_get(CLASS_OF(self), id);
- while (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &result)) {
- if (result == Qundef) {
- rb_autoload_load(klass, id);
- continue;
+ if (!NIL_P(klass)) {
+ while (RCLASS(klass)->iv_tbl &&
+ st_lookup(RCLASS(klass)->iv_tbl, id, &result)) {
+ if (result == Qundef) {
+ if (!RTEST(rb_autoload_load(klass, id))) break;
+ continue;
+ }
+ return result;
}
- return result;
}
cbase = cbase->nd_next;
}
- return rb_const_get(cref->nd_clss, id);
+ return rb_const_get(NIL_P(cref->nd_clss) ? CLASS_OF(self): cref->nd_clss, id);
}
static VALUE
@@ -1737,15 +1955,33 @@ cvar_cbase()
{
NODE *cref = ruby_cref;
- while (cref && cref->nd_next && FL_TEST(cref->nd_clss, FL_SINGLETON)) {
+ while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) {
cref = cref->nd_next;
if (!cref->nd_next) {
rb_warn("class variable access from toplevel singleton method");
}
}
+ if (NIL_P(cref->nd_clss)) {
+ rb_raise(rb_eTypeError, "no class variables available");
+ }
return cref->nd_clss;
}
+/*
+ * call-seq:
+ * Module.nesting => array
+ *
+ * Returns the list of +Modules+ nested at the point of call.
+ *
+ * module M1
+ * module M2
+ * $a = Module.nesting
+ * end
+ * end
+ * $a #=> [M1::M2, M1]
+ * $a[0].name #=> "M1::M2"
+ */
+
static VALUE
rb_mod_nesting()
{
@@ -1762,6 +1998,20 @@ rb_mod_nesting()
return ary;
}
+/*
+ * call-seq:
+ * Module.constants => array
+ *
+ * Returns an array of the names of all constants defined in the
+ * system. This list includes the names of all modules and classes.
+ *
+ * p Module.constants.sort[1..5]
+ *
+ * <em>produces:</em>
+ *
+ * ["ARGV", "ArgumentError", "Array", "Bignum", "Binding"]
+ */
+
static VALUE
rb_mod_s_constants()
{
@@ -1785,7 +2035,7 @@ void
rb_frozen_class_p(klass)
VALUE klass;
{
- char *desc = "something(?!)";
+ const char *desc = "something(?!)";
if (OBJ_FROZEN(klass)) {
if (FL_TEST(klass, FL_SINGLETON))
@@ -1823,7 +2073,7 @@ rb_undef(klass, id)
}
body = search_method(klass, id, &origin);
if (!body || !body->nd_body) {
- char *s0 = " class";
+ const char *s0 = " class";
VALUE c = klass;
if (FL_TEST(c, FL_SINGLETON)) {
@@ -1852,6 +2102,49 @@ rb_undef(klass, id)
}
}
+/*
+ * call-seq:
+ * undef_method(symbol) => self
+ *
+ * Prevents the current class from responding to calls to the named
+ * method. Contrast this with <code>remove_method</code>, which deletes
+ * the method from the particular class; Ruby will still search
+ * superclasses and mixed-in modules for a possible receiver.
+ *
+ * class Parent
+ * def hello
+ * puts "In parent"
+ * end
+ * end
+ * class Child < Parent
+ * def hello
+ * puts "In child"
+ * end
+ * end
+ *
+ *
+ * c = Child.new
+ * c.hello
+ *
+ *
+ * class Child
+ * remove_method :hello # remove from child, still in parent
+ * end
+ * c.hello
+ *
+ *
+ * class Child
+ * undef_method :hello # prevent any calls to 'hello'
+ * end
+ * c.hello
+ *
+ * <em>produces:</em>
+ *
+ * In child
+ * In parent
+ * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
+ */
+
static VALUE
rb_mod_undef_method(argc, argv, mod)
int argc;
@@ -1871,9 +2164,10 @@ rb_alias(klass, name, def)
VALUE klass;
ID name, def;
{
- VALUE origin;
- NODE *orig, *body;
+ VALUE origin = 0;
+ NODE *orig, *body, *node;
VALUE singleton = 0;
+ st_data_t data;
rb_frozen_class_p(klass);
if (name == def) return;
@@ -1901,8 +2195,18 @@ rb_alias(klass, name, def)
}
rb_clear_cache_by_id(name);
+ if (RTEST(ruby_verbose) && st_lookup(RCLASS(klass)->m_tbl, name, &data)) {
+ node = (NODE *)data;
+ if (node->nd_cnt == 0 && node->nd_body) {
+ rb_warning("discarding old %s", rb_id2name(name));
+ }
+ }
st_insert(RCLASS(klass)->m_tbl, name,
- (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
+ (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin),
+ NOEX_WITH_SAFE(orig->nd_noex)));
+
+ if (!ruby_running) return;
+
if (singleton) {
rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
}
@@ -1911,6 +2215,28 @@ rb_alias(klass, name, def)
}
}
+/*
+ * call-seq:
+ * alias_method(new_name, old_name) => self
+ *
+ * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
+ * be used to retain access to methods that are overridden.
+ *
+ * module Mod
+ * alias_method :orig_exit, :exit
+ * def exit(code=0)
+ * puts "Exiting with code #{code}"
+ * orig_exit(code)
+ * end
+ * end
+ * include Mod
+ * exit(99)
+ *
+ * <em>produces:</em>
+ *
+ * Exiting with code 99
+ */
+
static VALUE
rb_mod_alias_method(mod, newname, oldname)
VALUE mod, newname, oldname;
@@ -1919,8 +2245,8 @@ rb_mod_alias_method(mod, newname, oldname)
return mod;
}
-static NODE*
-copy_node_scope(node, rval)
+NODE *
+rb_copy_node_scope(node, rval)
NODE *node;
NODE *rval;
{
@@ -1939,54 +2265,56 @@ copy_node_scope(node, rval)
#ifdef C_ALLOCA
# define TMP_PROTECT NODE * volatile tmp__protect_tmp=0
# define TMP_ALLOC(n) \
- (tmp__protect_tmp = rb_node_newnode(NODE_ALLOCA, \
- ALLOC_N(VALUE,n),tmp__protect_tmp,n), \
+ (tmp__protect_tmp = NEW_NODE(NODE_ALLOCA, \
+ ALLOC_N(VALUE,n),tmp__protect_tmp,n), \
(void*)tmp__protect_tmp->nd_head)
#else
# define TMP_PROTECT typedef int foobazzz
# define TMP_ALLOC(n) ALLOCA_N(VALUE,n)
#endif
-#define SETUP_ARGS0(anode,alen) do {\
+#define SETUP_ARGS0(anode,extra) do {\
NODE *n = anode;\
if (!n) {\
argc = 0;\
argv = 0;\
}\
else if (nd_type(n) == NODE_ARRAY) {\
- argc=alen;\
- if (argc > 0) {\
- int i;\
+ argc=anode->nd_alen;\
+ if (argc > 0) {\
+ int i;\
n = anode;\
- argv = TMP_ALLOC(argc);\
+ argv = TMP_ALLOC(argc+extra);\
for (i=0;i<argc;i++) {\
argv[i] = rb_eval(self,n->nd_head);\
n=n->nd_next;\
}\
- }\
- else {\
+ }\
+ else {\
argc = 0;\
argv = 0;\
- }\
+ }\
}\
else {\
- VALUE args = rb_eval(self,n);\
+ VALUE args = rb_eval(self,n);\
if (TYPE(args) != T_ARRAY)\
args = rb_ary_to_ary(args);\
- argc = RARRAY(args)->len;\
- argv = ALLOCA_N(VALUE, argc);\
+ argc = RARRAY(args)->len;\
+ argv = TMP_ALLOC(argc+extra);\
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\
}\
} while (0)
-#define SETUP_ARGS(anode) SETUP_ARGS0(anode, anode->nd_alen)
+#define SETUP_ARGS(anode) SETUP_ARGS0(anode,0)
#define BEGIN_CALLARGS do {\
struct BLOCK *tmp_block = ruby_block;\
int tmp_iter = ruby_iter->iter;\
- if (tmp_iter == ITER_PRE) {\
- ruby_block = ruby_block->outer;\
- tmp_iter = ITER_NOT;\
+ switch (tmp_iter) {\
+ case ITER_PRE:\
+ if (ruby_block) ruby_block = ruby_block->outer;\
+ case ITER_PAS:\
+ tmp_iter = ITER_NOT;\
}\
PUSH_ITER(tmp_iter)
@@ -1997,9 +2325,9 @@ copy_node_scope(node, rval)
#define MATCH_DATA *rb_svar(node->nd_cnt)
-static char* is_defined _((VALUE, NODE*, char*));
+static const char* is_defined _((VALUE, NODE*, char*));
-static char*
+static const char*
arg_defined(self, node, buf, type)
VALUE self;
NODE *node;
@@ -2012,13 +2340,13 @@ arg_defined(self, node, buf, type)
if (!node) return type; /* no args */
if (nd_type(node) == NODE_ARRAY) {
argc=node->nd_alen;
- if (argc > 0) {
+ if (argc > 0) {
for (i=0;i<argc;i++) {
if (!is_defined(self, node->nd_head, buf))
return 0;
node = node->nd_next;
}
- }
+ }
}
else if (!is_defined(self, node, buf)) {
return 0;
@@ -2026,19 +2354,7 @@ arg_defined(self, node, buf, type)
return type;
}
-static VALUE
-search_iclass(self, klass)
- VALUE self, klass;
-{
- VALUE k = CLASS_OF(self);
-
- while (k && !(BUILTIN_TYPE(k) == T_ICLASS && RBASIC(k)->klass == klass)) {
- k = RCLASS(k)->super;
- }
- return k;
-}
-
-static char*
+static const char*
is_defined(self, node, buf)
VALUE self;
NODE *node; /* OK */
@@ -2052,13 +2368,9 @@ is_defined(self, node, buf)
switch (nd_type(node)) {
case NODE_SUPER:
case NODE_ZSUPER:
- if (ruby_frame->orig_func == 0) return 0;
+ if (ruby_frame->last_func == 0) return 0;
else if (ruby_frame->last_class == 0) return 0;
val = ruby_frame->last_class;
- if (BUILTIN_TYPE(val) == T_MODULE) {
- val = search_iclass(self, val);
- if (!val) return 0;
- }
if (rb_method_boundp(RCLASS(val)->super, ruby_frame->orig_func, 0)) {
if (nd_type(node) == NODE_SUPER) {
return arg_defined(self, node->nd_args, buf, "super");
@@ -2135,11 +2447,14 @@ is_defined(self, node, buf)
case NODE_ATTRSET:
case NODE_OP_ASGN1:
case NODE_OP_ASGN2:
+ case NODE_OP_ASGN_OR:
+ case NODE_OP_ASGN_AND:
case NODE_MASGN:
case NODE_LASGN:
case NODE_DASGN:
case NODE_DASGN_CURR:
case NODE_GASGN:
+ case NODE_IASGN:
case NODE_CDECL:
case NODE_CVDECL:
case NODE_CVASGN:
@@ -2252,23 +2567,141 @@ rb_obj_is_proc(proc)
return Qfalse;
}
+void
+rb_add_event_hook(func, events)
+ rb_event_hook_func_t func;
+ rb_event_t events;
+{
+ rb_event_hook_t *hook;
+
+ hook = ALLOC(rb_event_hook_t);
+ hook->func = func;
+ hook->events = events;
+ hook->next = event_hooks;
+ event_hooks = hook;
+}
+
+int
+rb_remove_event_hook(func)
+ rb_event_hook_func_t func;
+{
+ rb_event_hook_t *prev, *hook;
+
+ prev = NULL;
+ hook = event_hooks;
+ while (hook) {
+ if (hook->func == func) {
+ if (prev) {
+ prev->next = hook->next;
+ }
+ else {
+ event_hooks = hook->next;
+ }
+ xfree(hook);
+ return 0;
+ }
+ prev = hook;
+ hook = hook->next;
+ }
+ return -1;
+}
+
+/*
+ * call-seq:
+ * set_trace_func(proc) => proc
+ * set_trace_func(nil) => nil
+ *
+ * Establishes _proc_ as the handler for tracing, or disables
+ * tracing if the parameter is +nil+. _proc_ takes up
+ * to six parameters: an event name, a filename, a line number, an
+ * object id, a binding, and the name of a class. _proc_ is
+ * invoked whenever an event occurs. Events are: <code>c-call</code>
+ * (call a C-language routine), <code>c-return</code> (return from a
+ * C-language routine), <code>call</code> (call a Ruby method),
+ * <code>class</code> (start a class or module definition),
+ * <code>end</code> (finish a class or module definition),
+ * <code>line</code> (execute code on a new line), <code>raise</code>
+ * (raise an exception), and <code>return</code> (return from a Ruby
+ * method). Tracing is disabled within the context of _proc_.
+ *
+ * class Test
+ * def test
+ * a = 1
+ * b = 2
+ * end
+ * end
+ *
+ * set_trace_func proc { |event, file, line, id, binding, classname|
+ * printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
+ * }
+ * t = Test.new
+ * t.test
+ *
+ * line prog.rb:11 false
+ * c-call prog.rb:11 new Class
+ * c-call prog.rb:11 initialize Object
+ * c-return prog.rb:11 initialize Object
+ * c-return prog.rb:11 new Class
+ * line prog.rb:12 false
+ * call prog.rb:2 test Test
+ * line prog.rb:3 test Test
+ * line prog.rb:4 test Test
+ * return prog.rb:4 test Test
+ */
+
+
static VALUE
set_trace_func(obj, trace)
VALUE obj, trace;
{
+ rb_event_hook_t *hook;
+
+ rb_secure(4);
if (NIL_P(trace)) {
trace_func = 0;
+ rb_remove_event_hook(call_trace_func);
return Qnil;
}
if (!rb_obj_is_proc(trace)) {
rb_raise(rb_eTypeError, "trace_func needs to be Proc");
}
- return trace_func = trace;
+ trace_func = trace;
+ for (hook = event_hooks; hook; hook = hook->next) {
+ if (hook->func == call_trace_func)
+ return trace;
+ }
+ rb_add_event_hook(call_trace_func, RUBY_EVENT_ALL);
+ return trace;
+}
+
+static const char *
+get_event_name(rb_event_t event)
+{
+ switch (event) {
+ case RUBY_EVENT_LINE:
+ return "line";
+ case RUBY_EVENT_CLASS:
+ return "class";
+ case RUBY_EVENT_END:
+ return "end";
+ case RUBY_EVENT_CALL:
+ return "call";
+ case RUBY_EVENT_RETURN:
+ return "return";
+ case RUBY_EVENT_C_CALL:
+ return "c-call";
+ case RUBY_EVENT_C_RETURN:
+ return "c-return";
+ case RUBY_EVENT_RAISE:
+ return "raise";
+ default:
+ return "unknown";
+ }
}
static void
call_trace_func(event, node, self, id, klass)
- char *event;
+ rb_event_t event;
NODE *node;
VALUE self;
ID id;
@@ -2278,6 +2711,8 @@ call_trace_func(event, node, self, id, klass)
struct FRAME *prev;
NODE *node_save;
VALUE srcfile;
+ const char *event_name;
+ rb_thread_t th = curr_thread;
if (!trace_func) return;
if (tracing) return;
@@ -2305,14 +2740,15 @@ call_trace_func(event, node, self, id, klass)
klass = RBASIC(klass)->klass;
}
else if (FL_TEST(klass, FL_SINGLETON)) {
- klass = self;
+ klass = rb_iv_get(klass, "__attached__");
}
}
PUSH_TAG(PROT_NONE);
- raised = thread_reset_raised();
+ raised = rb_thread_reset_raised(th);
if ((state = EXEC_TAG()) == 0) {
srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)");
- proc_invoke(trace_func, rb_ary_new3(6, rb_str_new2(event),
+ event_name = get_event_name(event);
+ proc_invoke(trace_func, rb_ary_new3(6, rb_str_new2(event_name),
srcfile,
INT2FIX(ruby_sourceline),
id?ID2SYM(id):Qnil,
@@ -2320,7 +2756,7 @@ call_trace_func(event, node, self, id, klass)
klass),
Qundef, 0);
}
- if (raised) thread_set_raised();
+ if (raised) rb_thread_set_raised(th);
POP_TAG();
POP_FRAME();
@@ -2370,7 +2806,7 @@ svalue_to_avalue(v)
if (RARRAY(tmp)->len == 1) {
top = rb_check_array_type(RARRAY(tmp)->ptr[0]);
if (!NIL_P(top) && RARRAY(top)->len > 1) {
- return v;
+ return tmp;
}
return rb_ary_new3(1, v);
}
@@ -2482,7 +2918,26 @@ class_prefix(self, cpath)
}\
} while (0)
-NORETURN(static void localjump_destination _((int, VALUE)));
+NORETURN(static void return_jump _((VALUE)));
+NORETURN(static void break_jump _((VALUE)));
+NORETURN(static void next_jump _((VALUE)));
+NORETURN(static void unknown_node _((NODE * volatile)));
+
+static void
+unknown_node(node)
+ NODE *volatile node;
+{
+ ruby_current_node = 0;
+ if (node->flags == 0) {
+ rb_bug("terminated node (0x%lx)", node);
+ }
+ else if (BUILTIN_TYPE(node) != T_NODE) {
+ rb_bug("not a node 0x%02lx (0x%lx)", BUILTIN_TYPE(node), node);
+ }
+ else {
+ rb_bug("unknown node type %d (0x%lx)", nd_type(node), node);
+ }
+}
static VALUE
rb_eval(self, n)
@@ -2493,6 +2948,7 @@ rb_eval(self, n)
NODE * volatile node = n;
int state;
volatile VALUE result = Qnil;
+ st_data_t data;
#define RETURN(v) do { \
result = (v); \
@@ -2540,7 +2996,7 @@ rb_eval(self, n)
/* nodes for speed-up(literal match) */
case NODE_MATCH3:
- {
+ {
VALUE r = rb_eval(self,node->nd_recv);
VALUE l = rb_eval(self,node->nd_value);
if (TYPE(l) == T_STRING) {
@@ -2554,7 +3010,7 @@ rb_eval(self, n)
/* node for speed-up(top-level loop for -n/-p) */
case NODE_OPT_N:
- PUSH_TAG(PROT_ITER);
+ PUSH_TAG(PROT_LOOP);
switch (state = EXEC_TAG()) {
case 0:
opt_n_next:
@@ -2592,15 +3048,16 @@ rb_eval(self, n)
RETURN(Qfalse);
case NODE_IF:
- if (trace_func) {
- call_trace_func("line", node, self,
+ if (RTEST(rb_eval(self, node->nd_cond))) {
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
ruby_frame->last_func,
ruby_frame->last_class);
- }
- if (RTEST(rb_eval(self, node->nd_cond))) {
node = node->nd_body;
}
else {
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
node = node->nd_else;
}
goto again;
@@ -2612,11 +3069,9 @@ rb_eval(self, n)
if (nd_type(node) != NODE_WHEN) goto again;
tag = node->nd_head;
while (tag) {
- if (trace_func) {
- call_trace_func("line", tag, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
- }
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
VALUE v = rb_eval(self, tag->nd_head->nd_head);
long i;
@@ -2655,11 +3110,9 @@ rb_eval(self, n)
}
tag = node->nd_head;
while (tag) {
- if (trace_func) {
- call_trace_func("line", tag, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
- }
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
VALUE v = rb_eval(self, tag->nd_head->nd_head);
long i;
@@ -2686,7 +3139,7 @@ rb_eval(self, n)
RETURN(Qnil);
case NODE_WHILE:
- PUSH_TAG(PROT_ITER);
+ PUSH_TAG(PROT_LOOP);
result = Qnil;
switch (state = EXEC_TAG()) {
case 0:
@@ -2721,7 +3174,7 @@ rb_eval(self, n)
RETURN(result);
case NODE_UNTIL:
- PUSH_TAG(PROT_ITER);
+ PUSH_TAG(PROT_LOOP);
result = Qnil;
switch (state = EXEC_TAG()) {
case 0:
@@ -2762,7 +3215,7 @@ rb_eval(self, n)
case NODE_ITER:
case NODE_FOR:
{
- PUSH_TAG(PROT_ITER);
+ PUSH_TAG(PROT_LOOP);
PUSH_BLOCK(node->nd_var, node->nd_body);
state = EXEC_TAG();
@@ -2781,7 +3234,7 @@ rb_eval(self, n)
END_CALLARGS;
ruby_current_node = node;
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
+ result = rb_call(CLASS_OF(recv),recv,each,0,0,0,self);
}
POP_ITER();
}
@@ -2805,13 +3258,12 @@ rb_eval(self, n)
break;
case NODE_BREAK:
- localjump_destination(TAG_BREAK, rb_eval(self, node->nd_stts));
+ break_jump(rb_eval(self, node->nd_stts));
break;
case NODE_NEXT:
CHECK_INTS;
- return_value(rb_eval(self, node->nd_stts));
- JUMP_TAG(TAG_NEXT);
+ next_jump(rb_eval(self, node->nd_stts));
break;
case NODE_REDO:
@@ -2850,7 +3302,7 @@ rb_eval(self, n)
break;
case NODE_RESCUE:
- {
+ {
volatile VALUE e_info = ruby_errinfo;
volatile int rescuing = 0;
@@ -2893,7 +3345,6 @@ rb_eval(self, n)
POP_TAG();
if (state != TAG_RAISE) ruby_errinfo = e_info;
if (state) {
- if (state == TAG_NEXT) prot_tag->retval = result;
JUMP_TAG(state);
}
/* no exception raised */
@@ -2901,7 +3352,7 @@ rb_eval(self, n)
goto again;
}
}
- break;
+ break;
case NODE_ENSURE:
PUSH_TAG(PROT_NONE);
@@ -2909,7 +3360,7 @@ rb_eval(self, n)
result = rb_eval(self, node->nd_head);
}
POP_TAG();
- if (node->nd_ensr) {
+ if (node->nd_ensr && !thread_no_ensure()) {
VALUE retval = prot_tag->retval; /* save retval */
VALUE errinfo = ruby_errinfo;
@@ -2939,19 +3390,11 @@ rb_eval(self, n)
case NODE_DOT2:
case NODE_DOT3:
- result = rb_range_new(rb_eval(self, node->nd_beg),
- rb_eval(self, node->nd_end),
- nd_type(node) == NODE_DOT3);
- if (node->nd_state) break;
- if (nd_type(node->nd_beg) == NODE_LIT && FIXNUM_P(node->nd_beg->nd_lit) &&
- nd_type(node->nd_end) == NODE_LIT && FIXNUM_P(node->nd_end->nd_lit))
- {
- nd_set_type(node, NODE_LIT);
- node->nd_lit = result;
- }
- else {
- node->nd_state = 1;
- }
+ {
+ VALUE beg = rb_eval(self, node->nd_beg);
+ VALUE end = rb_eval(self, node->nd_end);
+ result = rb_range_new(beg, end, nd_type(node) == NODE_DOT3);
+ }
break;
case NODE_FLIP2: /* like AWK */
@@ -2994,7 +3437,7 @@ rb_eval(self, n)
break;
case NODE_RETURN:
- localjump_destination(TAG_RETURN, rb_eval(self, node->nd_stts));
+ return_jump(rb_eval(self, node->nd_stts));
break;
case NODE_ARGSCAT:
@@ -3032,7 +3475,7 @@ rb_eval(self, n)
ruby_current_node = node;
SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope);
+ rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope,self);
result = argv[argc-1];
}
break;
@@ -3050,7 +3493,7 @@ rb_eval(self, n)
ruby_current_node = node;
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
+ result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0,self);
}
break;
@@ -3065,13 +3508,13 @@ rb_eval(self, n)
ruby_current_node = node;
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1);
+ result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1,self);
}
break;
case NODE_VCALL:
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,2);
+ result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,2,self);
break;
case NODE_SUPER:
@@ -3081,7 +3524,7 @@ rb_eval(self, n)
TMP_PROTECT;
if (ruby_frame->last_class == 0) {
- if (ruby_frame->orig_func) {
+ if (ruby_frame->last_func) {
rb_name_error(ruby_frame->last_func,
"superclass method `%s' disabled",
rb_id2name(ruby_frame->orig_func));
@@ -3092,7 +3535,21 @@ rb_eval(self, n)
}
if (nd_type(node) == NODE_ZSUPER) {
argc = ruby_frame->argc;
- argv = ruby_frame->argv;
+ if (argc && DMETHOD_P()) {
+ if (TYPE(RBASIC(ruby_scope)->klass) != T_ARRAY ||
+ RARRAY(RBASIC(ruby_scope)->klass)->len != argc) {
+ rb_raise(rb_eRuntimeError,
+ "super: specify arguments explicitly");
+ }
+ argv = RARRAY(RBASIC(ruby_scope)->klass)->ptr;
+ }
+ else if (!ruby_scope->local_vars) {
+ argc = 0;
+ argv = 0;
+ }
+ else {
+ argv = ruby_scope->local_vars + 2;
+ }
}
else {
BEGIN_CALLARGS;
@@ -3110,14 +3567,13 @@ rb_eval(self, n)
{
struct FRAME frame;
NODE *saved_cref = 0;
- int jump_chain = Qfalse;
frame = *ruby_frame;
frame.tmp = ruby_frame;
ruby_frame = &frame;
PUSH_SCOPE();
- PUSH_TAG(PROT_PCALL);
+ PUSH_TAG(PROT_NONE);
if (node->nd_rval) {
saved_cref = ruby_cref;
ruby_cref = (NODE*)node->nd_rval;
@@ -3136,52 +3592,41 @@ rb_eval(self, n)
if ((state = EXEC_TAG()) == 0) {
result = rb_eval(self, node->nd_next);
}
- else if (TAG_DST()) {
- result = prot_tag->retval;
- jump_chain = Qtrue;
- }
POP_TAG();
POP_SCOPE();
ruby_frame = frame.tmp;
if (saved_cref)
ruby_cref = saved_cref;
- switch (state) {
- case 0:
- break;
- case TAG_RETURN:
- case TAG_BREAK:
- localjump_destination(state, result);
- default:
- JUMP_TAG(state);
- }
+ if (state) JUMP_TAG(state);
}
break;
case NODE_OP_ASGN1:
{
int argc; VALUE *argv; /* used in SETUP_ARGS */
- VALUE recv, val;
+ VALUE recv, val, tmp;
NODE *rval;
TMP_PROTECT;
recv = rb_eval(self, node->nd_recv);
rval = node->nd_args->nd_head;
- SETUP_ARGS0(node->nd_args->nd_next, node->nd_args->nd_alen - 1);
- val = rb_funcall2(recv, aref, argc-1, argv);
+ SETUP_ARGS0(node->nd_args->nd_body, 1);
+ val = rb_funcall3(recv, aref, argc, argv);
switch (node->nd_mid) {
case 0: /* OR */
- if (RTEST(val)) RETURN(val);
- val = rb_eval(self, rval);
- break;
+ if (RTEST(val)) RETURN(val);
+ val = rb_eval(self, rval);
+ break;
case 1: /* AND */
- if (!RTEST(val)) RETURN(val);
- val = rb_eval(self, rval);
- break;
+ if (!RTEST(val)) RETURN(val);
+ val = rb_eval(self, rval);
+ break;
default:
- val = rb_funcall(val, node->nd_mid, 1, rb_eval(self, rval));
+ tmp = rb_eval(self, rval);
+ val = rb_funcall3(val, node->nd_mid, 1, &tmp);
}
- argv[argc-1] = val;
- rb_funcall2(recv, aset, argc, argv);
+ argv[argc] = val;
+ rb_funcall2(recv, aset, argc+1, argv);
result = val;
}
break;
@@ -3189,22 +3634,22 @@ rb_eval(self, n)
case NODE_OP_ASGN2:
{
ID id = node->nd_next->nd_vid;
- VALUE recv, val;
+ VALUE recv, val, tmp;
recv = rb_eval(self, node->nd_recv);
- val = rb_funcall(recv, id, 0);
+ val = rb_funcall3(recv, id, 0, 0);
switch (node->nd_next->nd_mid) {
case 0: /* OR */
- if (RTEST(val)) RETURN(val);
- val = rb_eval(self, node->nd_value);
- break;
+ if (RTEST(val)) RETURN(val);
+ val = rb_eval(self, node->nd_value);
+ break;
case 1: /* AND */
- if (!RTEST(val)) RETURN(val);
- val = rb_eval(self, node->nd_value);
- break;
+ if (!RTEST(val)) RETURN(val);
+ val = rb_eval(self, node->nd_value);
+ break;
default:
- val = rb_funcall(val, node->nd_next->nd_mid, 1,
- rb_eval(self, node->nd_value));
+ tmp = rb_eval(self, node->nd_value);
+ val = rb_funcall3(val, node->nd_next->nd_mid, 1, &tmp);
}
rb_funcall2(recv, node->nd_next->nd_aid, 1, &val);
@@ -3263,9 +3708,6 @@ rb_eval(self, n)
rb_const_set(class_prefix(self, node->nd_else), node->nd_else->nd_mid, result);
}
else {
- if (NIL_P(ruby_cbase)) {
- rb_raise(rb_eTypeError, "no class/module to define constant");
- }
rb_const_set(ruby_cbase, node->nd_vid, result);
}
break;
@@ -3456,6 +3898,9 @@ rb_eval(self, n)
nd_set_type(node, NODE_LIT);
node->nd_lit = result;
break;
+ case NODE_LIT:
+ /* other thread may replace NODE_DREGX_ONCE to NODE_LIT */
+ goto again;
case NODE_DXSTR:
result = rb_funcall(self, '`', 1, str);
break;
@@ -3470,24 +3915,17 @@ rb_eval(self, n)
break;
case NODE_XSTR:
- result = rb_funcall(self, '`', 1, node->nd_lit);
+ result = rb_funcall(self, '`', 1, rb_str_new3(node->nd_lit));
break;
case NODE_LIT:
result = node->nd_lit;
break;
- case NODE_ATTRSET:
- if (ruby_frame->argc != 1)
- rb_raise(rb_eArgError, "wrong number of arguments(%d for 1)",
- ruby_frame->argc);
- result = rb_ivar_set(self, node->nd_vid, ruby_frame->argv[0]);
- break;
-
case NODE_DEFN:
if (node->nd_defn) {
NODE *body, *defn;
- VALUE origin;
+ VALUE origin = 0;
int noex;
if (NIL_P(ruby_class)) {
@@ -3521,7 +3959,7 @@ rb_eval(self, n)
noex |= NOEX_NOSUPER;
}
- defn = copy_node_scope(node->nd_defn, ruby_cref);
+ defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
rb_add_method(ruby_class, node->nd_mid, defn, noex);
if (scope_vmode == SCOPE_MODFUNC) {
rb_add_method(rb_singleton_class(ruby_class),
@@ -3549,7 +3987,8 @@ rb_eval(self, n)
if (OBJ_FROZEN(recv)) rb_error_frozen("object");
klass = rb_singleton_class(recv);
- if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, (st_data_t *)&body)) {
+ if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &data)) {
+ body = (NODE *)data;
if (ruby_safe_level >= 4) {
rb_raise(rb_eSecurityError, "redefining method prohibited");
}
@@ -3557,7 +3996,7 @@ rb_eval(self, n)
rb_warning("redefine %s", rb_id2name(node->nd_mid));
}
}
- defn = copy_node_scope(node->nd_defn, ruby_cref);
+ defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
rb_add_method(klass, node->nd_mid, defn,
NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
result = Qnil;
@@ -3568,7 +4007,7 @@ rb_eval(self, n)
if (NIL_P(ruby_class)) {
rb_raise(rb_eTypeError, "no class to undef method");
}
- rb_undef(ruby_class, node->nd_mid);
+ rb_undef(ruby_class, rb_to_id(rb_eval(self, node->u2.node)));
result = Qnil;
break;
@@ -3576,12 +4015,13 @@ rb_eval(self, n)
if (NIL_P(ruby_class)) {
rb_raise(rb_eTypeError, "no class to make alias");
}
- rb_alias(ruby_class, node->nd_new, node->nd_old);
+ rb_alias(ruby_class, rb_to_id(rb_eval(self, node->u1.node)),
+ rb_to_id(rb_eval(self, node->u2.node)));
result = Qnil;
break;
case NODE_VALIAS:
- rb_alias_variable(node->nd_new, node->nd_old);
+ rb_alias_variable(node->u1.id, node->u2.id);
result = Qnil;
break;
@@ -3591,18 +4031,20 @@ rb_eval(self, n)
ID cname;
int gen = Qfalse;
+ cbase = class_prefix(self, node->nd_cpath);
+ cname = node->nd_cpath->nd_mid;
+
if (NIL_P(ruby_cbase)) {
rb_raise(rb_eTypeError, "no outer class/module");
}
if (node->nd_super) {
- super = superclass(self, node->nd_super);
+ super = rb_eval(self, node->nd_super);
+ rb_check_inheritable(super);
}
else {
super = 0;
}
- cbase = class_prefix(self, node->nd_cpath);
- cname = node->nd_cpath->nd_mid;
if (rb_const_defined_at(cbase, cname)) {
klass = rb_const_get_at(cbase, cname);
if (TYPE(klass) != T_CLASS) {
@@ -3612,7 +4054,8 @@ rb_eval(self, n)
if (super) {
tmp = rb_class_real(RCLASS(klass)->super);
if (tmp != super) {
- goto override_class;
+ rb_raise(rb_eTypeError, "superclass mismatch for class %s",
+ rb_id2name(cname));
}
super = 0;
}
@@ -3621,7 +4064,6 @@ rb_eval(self, n)
}
}
else {
- override_class:
if (!super) super = rb_cObject;
klass = rb_define_class_id(cname, super);
rb_set_class_path(klass, cbase, rb_id2name(cname));
@@ -3698,7 +4140,7 @@ rb_eval(self, n)
case NODE_DEFINED:
{
char buf[20];
- char *desc = is_defined(self, node->nd_head, buf);
+ const char *desc = is_defined(self, node->nd_head, buf);
if (desc) result = rb_str_new2(desc);
else result = Qnil;
@@ -3706,16 +4148,14 @@ rb_eval(self, n)
break;
case NODE_NEWLINE:
- if (trace_func) {
- call_trace_func("line", node, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
- }
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
node = node->nd_next;
goto again;
default:
- rb_bug("unknown node type %d", nd_type(node));
+ unknown_node(node);
}
finish:
CHECK_INTS;
@@ -3761,9 +4201,8 @@ module_setup(module, n)
PUSH_CREF(module);
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- if (trace_func) {
- call_trace_func("class", n, ruby_cbase, ruby_frame->last_func, ruby_frame->last_class);
- }
+ EXEC_EVENT_HOOK(RUBY_EVENT_CLASS, n, ruby_cbase,
+ ruby_frame->last_func, ruby_frame->last_class);
result = rb_eval(ruby_cbase, node->nd_next);
}
POP_TAG();
@@ -3773,27 +4212,54 @@ module_setup(module, n)
POP_CLASS();
ruby_frame = frame.tmp;
- if (trace_func) {
- call_trace_func("end", n, 0, ruby_frame->last_func, ruby_frame->last_class);
- }
+ EXEC_EVENT_HOOK(RUBY_EVENT_END, n, 0,
+ ruby_frame->last_func, ruby_frame->last_class);
if (state) JUMP_TAG(state);
return result;
}
+static NODE *basic_respond_to = 0;
+
int
-rb_respond_to(obj, id)
+rb_obj_respond_to(obj, id, priv)
VALUE obj;
ID id;
+ int priv;
{
- if (rb_method_boundp(CLASS_OF(obj), id, 0)) {
- return Qtrue;
+ VALUE klass = CLASS_OF(obj);
+
+ if (rb_method_node(klass, respond_to) == basic_respond_to) {
+ return rb_method_boundp(klass, id, !priv);
+ }
+ else {
+ VALUE args[2];
+ int n = 0;
+ args[n++] = ID2SYM(id);
+ if (priv) args[n++] = Qtrue;
+ return RTEST(rb_funcall2(obj, respond_to, n, args));
}
- return Qfalse;
}
+int
+rb_respond_to(obj, id)
+ VALUE obj;
+ ID id;
+{
+ return rb_obj_respond_to(obj, id, Qfalse);
+}
+
+/*
+ * call-seq:
+ * obj.respond_to?(symbol, include_private=false) => true or false
+ *
+ * Returns +true+> if _obj_ responds to the given
+ * method. Private methods are included in the search only if the
+ * optional second parameter evaluates to +true+.
+ */
+
static VALUE
-rb_obj_respond_to(argc, argv, obj)
+obj_respond_to(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -3809,6 +4275,32 @@ rb_obj_respond_to(argc, argv, obj)
return Qfalse;
}
+/*
+ * call-seq:
+ * mod.method_defined?(symbol) => true or false
+ *
+ * Returns +true+ if the named method is defined by
+ * _mod_ (or its included modules and, if _mod_ is a class,
+ * its ancestors). Public and protected methods are matched.
+ *
+ * module A
+ * def method1() end
+ * end
+ * class B
+ * def method2() end
+ * end
+ * class C < B
+ * include A
+ * def method3() end
+ * end
+ *
+ * A.method_defined? :method1 #=> true
+ * C.method_defined? "method1" #=> true
+ * C.method_defined? "method2" #=> true
+ * C.method_defined? "method3" #=> true
+ * C.method_defined? "method4" #=> false
+ */
+
static VALUE
rb_mod_method_defined(mod, mid)
VALUE mod, mid;
@@ -3818,6 +4310,32 @@ rb_mod_method_defined(mod, mid)
#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
+/*
+ * call-seq:
+ * mod.public_method_defined?(symbol) => true or false
+ *
+ * Returns +true+ if the named public method is defined by
+ * _mod_ (or its included modules and, if _mod_ is a class,
+ * its ancestors).
+ *
+ * module A
+ * def method1() end
+ * end
+ * class B
+ * protected
+ * def method2() end
+ * end
+ * class C < B
+ * include A
+ * def method3() end
+ * end
+ *
+ * A.method_defined? :method1 #=> true
+ * C.public_method_defined? "method1" #=> true
+ * C.public_method_defined? "method2" #=> false
+ * C.method_defined? "method2" #=> true
+ */
+
static VALUE
rb_mod_public_method_defined(mod, mid)
VALUE mod, mid;
@@ -3832,6 +4350,32 @@ rb_mod_public_method_defined(mod, mid)
return Qfalse;
}
+/*
+ * call-seq:
+ * mod.private_method_defined?(symbol) => true or false
+ *
+ * Returns +true+ if the named private method is defined by
+ * _ mod_ (or its included modules and, if _mod_ is a class,
+ * its ancestors).
+ *
+ * module A
+ * def method1() end
+ * end
+ * class B
+ * private
+ * def method2() end
+ * end
+ * class C < B
+ * include A
+ * def method3() end
+ * end
+ *
+ * A.method_defined? :method1 #=> true
+ * C.private_method_defined? "method1" #=> false
+ * C.private_method_defined? "method2" #=> true
+ * C.method_defined? "method2" #=> false
+ */
+
static VALUE
rb_mod_private_method_defined(mod, mid)
VALUE mod, mid;
@@ -3846,6 +4390,32 @@ rb_mod_private_method_defined(mod, mid)
return Qfalse;
}
+/*
+ * call-seq:
+ * mod.protected_method_defined?(symbol) => true or false
+ *
+ * Returns +true+ if the named protected method is defined
+ * by _mod_ (or its included modules and, if _mod_ is a
+ * class, its ancestors).
+ *
+ * module A
+ * def method1() end
+ * end
+ * class B
+ * protected
+ * def method2() end
+ * end
+ * class C < B
+ * include A
+ * def method3() end
+ * end
+ *
+ * A.method_defined? :method1 #=> true
+ * C.protected_method_defined? "method1" #=> false
+ * C.protected_method_defined? "method2" #=> true
+ * C.method_defined? "method2" #=> true
+ */
+
static VALUE
rb_mod_protected_method_defined(mod, mid)
VALUE mod, mid;
@@ -3860,16 +4430,15 @@ rb_mod_protected_method_defined(mod, mid)
return Qfalse;
}
-NORETURN(static VALUE terminate_process _((int, const char *, long)));
+NORETURN(static VALUE terminate_process _((int, VALUE)));
static VALUE
-terminate_process(status, mesg, mlen)
+terminate_process(status, mesg)
int status;
- const char *mesg;
- long mlen;
+ VALUE mesg;
{
VALUE args[2];
args[0] = INT2NUM(status);
- args[1] = rb_str_new(mesg, mlen);
+ args[1] = mesg;
rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
}
@@ -3879,12 +4448,51 @@ rb_exit(status)
int status;
{
if (prot_tag) {
- terminate_process(status, "exit", 4);
+ terminate_process(status, rb_str_new("exit", 4));
}
ruby_finalize();
exit(status);
}
+
+/*
+ * call-seq:
+ * exit(integer=0)
+ * Kernel::exit(integer=0)
+ * Process::exit(integer=0)
+ *
+ * Initiates the termination of the Ruby script by raising the
+ * <code>SystemExit</code> exception. This exception may be caught. The
+ * optional parameter is used to return a status code to the invoking
+ * environment.
+ *
+ * begin
+ * exit
+ * puts "never get here"
+ * rescue SystemExit
+ * puts "rescued a SystemExit exception"
+ * end
+ * puts "after begin block"
+ *
+ * <em>produces:</em>
+ *
+ * rescued a SystemExit exception
+ * after begin block
+ *
+ * Just prior to termination, Ruby executes any <code>at_exit</code> functions
+ * (see Kernel::at_exit) and runs any object finalizers (see
+ * ObjectSpace::define_finalizer).
+ *
+ * at_exit { puts "at_exit function" }
+ * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
+ * exit
+ *
+ * <em>produces:</em>
+ *
+ * at_exit function
+ * in finalizer
+ */
+
VALUE
rb_f_exit(argc, argv)
int argc;
@@ -3904,6 +4512,9 @@ rb_f_exit(argc, argv)
break;
default:
istatus = NUM2INT(status);
+#if EXIT_SUCCESS != 0
+ if (istatus == 0) istatus = EXIT_SUCCESS;
+#endif
break;
}
}
@@ -3914,6 +4525,18 @@ rb_f_exit(argc, argv)
return Qnil; /* not reached */
}
+
+/*
+ * call-seq:
+ * abort
+ * Kernel::abort
+ * Process::abort
+ *
+ * Terminate execution immediately, effectively by calling
+ * <code>Kernel.exit(1)</code>. If _msg_ is given, it is written
+ * to STDERR prior to terminating.
+ */
+
VALUE
rb_f_abort(argc, argv)
int argc;
@@ -3930,9 +4553,9 @@ rb_f_abort(argc, argv)
VALUE mesg;
rb_scan_args(argc, argv, "1", &mesg);
- StringValue(argv[0]);
- rb_io_puts(argc, argv, rb_stderr);
- terminate_process(EXIT_FAILURE, RSTRING(argv[0])->ptr, RSTRING(argv[0])->len);
+ StringValue(mesg);
+ rb_io_puts(1, &mesg, rb_stderr);
+ terminate_process(EXIT_FAILURE, mesg);
}
return Qnil; /* not reached */
}
@@ -3940,7 +4563,7 @@ rb_f_abort(argc, argv)
void
rb_iter_break()
{
- localjump_destination(TAG_BREAK, Qnil);
+ break_jump(Qnil);
}
NORETURN(static void rb_longjmp _((int, VALUE)));
@@ -3952,8 +4575,9 @@ rb_longjmp(tag, mesg)
VALUE mesg;
{
VALUE at;
+ rb_thread_t th = curr_thread;
- if (thread_set_raised()) {
+ if (rb_thread_set_raised(th)) {
ruby_errinfo = exception_error;
JUMP_TAG(TAG_FATAL);
}
@@ -3967,6 +4591,9 @@ rb_longjmp(tag, mesg)
at = get_backtrace(mesg);
if (NIL_P(at)) {
at = make_backtrace();
+ if (OBJ_FROZEN(mesg)) {
+ mesg = rb_obj_dup(mesg);
+ }
set_backtrace(mesg, at);
}
}
@@ -3992,14 +4619,14 @@ rb_longjmp(tag, mesg)
ruby_errinfo = mesg;
}
else if (status) {
- thread_reset_raised();
+ rb_thread_reset_raised(th);
JUMP_TAG(status);
}
}
rb_trap_restore_mask();
- if (trace_func && tag != TAG_FATAL) {
- call_trace_func("raise", ruby_current_node,
+ if (tag != TAG_FATAL) {
+ EXEC_EVENT_HOOK(RUBY_EVENT_RAISE, ruby_current_node,
ruby_frame->self,
ruby_frame->last_func,
ruby_frame->last_class);
@@ -4007,11 +4634,20 @@ rb_longjmp(tag, mesg)
if (!prot_tag) {
error_print();
}
- thread_reset_raised();
+ rb_thread_raised_clear(th);
JUMP_TAG(tag);
}
void
+rb_exc_jump(mesg)
+ VALUE mesg;
+{
+ rb_thread_raised_clear(rb_curr_thread);
+ ruby_errinfo = mesg;
+ JUMP_TAG(TAG_RAISE);
+}
+
+void
rb_exc_raise(mesg)
VALUE mesg;
{
@@ -4028,14 +4664,48 @@ rb_exc_fatal(mesg)
void
rb_interrupt()
{
- rb_raise(rb_eInterrupt, "");
+ static const char fmt[1] = {'\0'};
+ rb_raise(rb_eInterrupt, fmt);
}
+/*
+ * call-seq:
+ * raise
+ * raise(string)
+ * raise(exception [, string [, array]])
+ * fail
+ * fail(string)
+ * fail(exception [, string [, array]])
+ *
+ * With no arguments, raises the exception in <code>$!</code> or raises
+ * a <code>RuntimeError</code> if <code>$!</code> is +nil+.
+ * With a single +String+ argument, raises a
+ * +RuntimeError+ with the string as a message. Otherwise,
+ * the first parameter should be the name of an +Exception+
+ * class (or an object that returns an +Exception+ object when sent
+ * an +exception+ message). The optional second parameter sets the
+ * message associated with the exception, and the third parameter is an
+ * array of callback information. Exceptions are caught by the
+ * +rescue+ clause of <code>begin...end</code> blocks.
+ *
+ * raise "Failed to create socket"
+ * raise ArgumentError, "No parameters", caller
+ */
+
static VALUE
rb_f_raise(argc, argv)
int argc;
VALUE *argv;
{
+ rb_raise_jump(rb_make_exception(argc, argv));
+ return Qnil; /* not reached */
+}
+
+static VALUE
+rb_make_exception(argc, argv)
+ int argc;
+ VALUE *argv;
+{
VALUE mesg;
ID exception;
int n;
@@ -4071,9 +4741,17 @@ rb_f_raise(argc, argv)
if (argc > 0) {
if (!rb_obj_is_kind_of(mesg, rb_eException))
rb_raise(rb_eTypeError, "exception object expected");
- set_backtrace(mesg, (argc>2)?argv[2]:Qnil);
+ if (argc>2)
+ set_backtrace(mesg, argv[2]);
}
+ return mesg;
+}
+
+static void
+rb_raise_jump(mesg)
+ VALUE mesg;
+{
if (ruby_frame != top_frame) {
PUSH_FRAME(); /* fake frame */
*ruby_frame = *_frame.prev->prev;
@@ -4081,8 +4759,6 @@ rb_f_raise(argc, argv)
POP_FRAME();
}
rb_longjmp(TAG_RAISE, mesg);
-
- return Qnil; /* not reached */
}
void
@@ -4106,6 +4782,28 @@ rb_iterator_p()
return rb_block_given_p();
}
+/*
+ * call-seq:
+ * block_given? => true or false
+ * iterator? => true or false
+ *
+ * Returns <code>true</code> if <code>yield</code> would execute a
+ * block in the current context. The <code>iterator?</code> form
+ * is mildly deprecated.
+ *
+ * def try
+ * if block_given?
+ * yield
+ * else
+ * "no block"
+ * end
+ * end
+ * try #=> "no block"
+ * try { "hello" } #=> "hello"
+ * try do "hello" end #=> "hello"
+ */
+
+
static VALUE
rb_f_block_given_p()
{
@@ -4114,31 +4812,122 @@ rb_f_block_given_p()
return Qfalse;
}
-static VALUE rb_eThreadError;
+VALUE rb_eThreadError;
+NORETURN(static void proc_jump_error(int, VALUE));
static void
-localjump_destination(state, retval)
+proc_jump_error(state, result)
int state;
+ VALUE result;
+{
+ char mesg[32];
+ const char *statement;
+
+ switch (state) {
+ case TAG_BREAK:
+ statement = "break"; break;
+ case TAG_RETURN:
+ statement = "return"; break;
+ case TAG_RETRY:
+ statement = "retry"; break;
+ default:
+ statement = "local-jump"; break; /* should not happen */
+ }
+ snprintf(mesg, sizeof mesg, "%s from proc-closure", statement);
+ localjump_error(mesg, result, state);
+}
+
+static void
+return_jump(retval)
VALUE retval;
{
struct tag *tt = prot_tag;
- VALUE tag = (state == TAG_BREAK) ? PROT_ITER : PROT_FUNC;
+ int yield = Qfalse;
if (retval == Qundef) retval = Qnil;
while (tt) {
- if (tt->tag == PROT_PCALL || (tt->tag == PROT_THREAD && state == TAG_BREAK) ||
- (tt->tag == PROT_CALL || tt->tag == tag) && tt->frame->uniq == ruby_frame->uniq) {
+ if (tt->tag == PROT_YIELD) {
+ yield = Qtrue;
+ tt = tt->prev;
+ }
+ if (tt->tag == PROT_FUNC && tt->frame->uniq == ruby_frame->uniq) {
tt->dst = (VALUE)ruby_frame->uniq;
tt->retval = retval;
- JUMP_TAG(state);
+ JUMP_TAG(TAG_RETURN);
+ }
+ if (tt->tag == PROT_LAMBDA && !yield) {
+ tt->dst = (VALUE)tt->frame->uniq;
+ tt->retval = retval;
+ JUMP_TAG(TAG_RETURN);
}
- if (tt->tag == PROT_FUNC && tt->frame->uniq == ruby_frame->uniq) break;
if (tt->tag == PROT_THREAD) {
- rb_raise(rb_eThreadError, "return jump can't across threads");
+ rb_raise(rb_eThreadError, "return can't jump across threads");
+ }
+ tt = tt->prev;
+ }
+ localjump_error("unexpected return", retval, TAG_RETURN);
+}
+
+static void
+break_jump(retval)
+ VALUE retval;
+{
+ struct tag *tt = prot_tag;
+
+ if (retval == Qundef) retval = Qnil;
+ while (tt) {
+ switch (tt->tag) {
+ case PROT_THREAD:
+ case PROT_YIELD:
+ case PROT_LOOP:
+ case PROT_LAMBDA:
+ tt->dst = (VALUE)tt->frame->uniq;
+ tt->retval = retval;
+ JUMP_TAG(TAG_BREAK);
+ break;
+ case PROT_FUNC:
+ tt = 0;
+ continue;
+ default:
+ break;
+ }
+ tt = tt->prev;
+ }
+ localjump_error("unexpected break", retval, TAG_BREAK);
+}
+
+static void
+next_jump(retval)
+ VALUE retval;
+{
+ struct tag *tt = prot_tag;
+
+ if (retval == Qundef) retval = Qnil;
+ while (tt) {
+ switch (tt->tag) {
+ case PROT_THREAD:
+ case PROT_YIELD:
+ case PROT_LOOP:
+ case PROT_LAMBDA:
+ case PROT_FUNC:
+ tt->dst = (VALUE)tt->frame->uniq;
+ tt->retval = retval;
+ JUMP_TAG(TAG_NEXT);
+ break;
+ default:
+ break;
}
tt = tt->prev;
}
- jump_tag_but_local_jump(state);
+ localjump_error("unexpected next", retval, TAG_NEXT);
+}
+
+void
+rb_need_block()
+{
+ if (!rb_block_given_p()) {
+ localjump_error("no block given", Qnil, 0);
+ }
}
static VALUE
@@ -4146,7 +4935,7 @@ rb_yield_0(val, self, klass, flags, avalue)
VALUE val, self, klass; /* OK */
int flags, avalue;
{
- NODE *node;
+ NODE *node, *var;
volatile VALUE result = Qnil;
volatile VALUE old_cref;
volatile VALUE old_wrapper;
@@ -4155,16 +4944,16 @@ rb_yield_0(val, self, klass, flags, avalue)
int old_vmode;
struct FRAME frame;
NODE *cnode = ruby_current_node;
+ int lambda = flags & YIELD_LAMBDA_CALL;
int state;
- if (!rb_block_given_p()) {
- localjump_error("no block given", Qnil, 0);
- }
+ rb_need_block();
PUSH_VARS();
block = ruby_block;
frame = block->frame;
frame.prev = ruby_frame;
+ frame.node = cnode;
ruby_frame = &(frame);
old_cref = (VALUE)ruby_cref;
ruby_cref = block->cref;
@@ -4188,27 +4977,35 @@ rb_yield_0(val, self, klass, flags, avalue)
self = block->self;
}
node = block->body;
+ var = block->var;
- if (block->var) {
+ if (var) {
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- if (block->var == (NODE*)1) { /* no parameter || */
- if ((flags & YIELD_PROC_CALL) && RARRAY(val)->len != 0) {
+ NODE *bvar = NULL;
+ block_var:
+ if (var == (NODE*)1) { /* no parameter || */
+ if (lambda && RARRAY(val)->len != 0) {
rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
RARRAY(val)->len);
}
}
- else if (block->var == (NODE*)2) {
+ else if (var == (NODE*)2) {
if (TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) {
rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
RARRAY(val)->len);
}
}
- else if (nd_type(block->var) == NODE_MASGN) {
+ else if (!bvar && nd_type(var) == NODE_BLOCK_PASS) {
+ bvar = var->nd_body;
+ var = var->nd_args;
+ goto block_var;
+ }
+ else if (nd_type(var) == NODE_MASGN) {
if (!avalue) {
- val = svalue_to_mrhs(val, block->var->nd_head);
+ val = svalue_to_mrhs(val, var->nd_head);
}
- massign(self, block->var, val, flags&YIELD_PROC_CALL);
+ massign(self, var, val, lambda);
}
else {
int len = 0;
@@ -4229,13 +5026,21 @@ rb_yield_0(val, self, klass, flags, avalue)
val = Qnil;
multi_values:
{
- ruby_current_node = block->var;
+ ruby_current_node = var;
rb_warn("multiple values for a block parameter (%d for 1)\n\tfrom %s:%d",
len, cnode->nd_file, nd_line(cnode));
ruby_current_node = cnode;
}
}
- assign(self, block->var, val, flags&YIELD_PROC_CALL);
+ assign(self, var, val, lambda);
+ }
+ if (bvar) {
+ VALUE blk;
+ if (flags & YIELD_PROC_CALL)
+ blk = block->block_obj;
+ else
+ blk = rb_block_proc();
+ assign(self, bvar, blk, 0);
}
}
POP_TAG();
@@ -4248,16 +5053,22 @@ rb_yield_0(val, self, klass, flags, avalue)
ruby_current_node = node;
PUSH_ITER(block->iter);
- PUSH_TAG(PROT_NONE);
+ PUSH_TAG(lambda ? PROT_NONE : PROT_YIELD);
if ((state = EXEC_TAG()) == 0) {
redo:
if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) {
- if (node->nd_state == YIELD_FUNC_AVALUE) {
+ switch (node->nd_state) {
+ case YIELD_FUNC_LAMBDA:
+ if (!avalue) {
+ val = (val == Qundef) ? rb_ary_new2(0) : rb_ary_new3(1, val);
+ }
+ break;
+ case YIELD_FUNC_AVALUE:
if (!avalue) {
val = svalue_to_avalue(val);
}
- }
- else {
+ break;
+ default:
if (avalue) {
val = avalue_to_svalue(val);
}
@@ -4277,8 +5088,18 @@ rb_yield_0(val, self, klass, flags, avalue)
CHECK_INTS;
goto redo;
case TAG_NEXT:
- state = 0;
- result = prot_tag->retval;
+ if (!lambda) {
+ state = 0;
+ result = prot_tag->retval;
+ }
+ break;
+ case TAG_BREAK:
+ if (TAG_DST()) {
+ result = prot_tag->retval;
+ }
+ else {
+ lambda = Qtrue; /* just pass TAG_BREAK */
+ }
break;
default:
break;
@@ -4308,10 +5129,31 @@ rb_yield_0(val, self, klass, flags, avalue)
ruby_cref = (NODE*)old_cref;
ruby_wrapper = old_wrapper;
if (ruby_scope->flags & SCOPE_DONT_RECYCLE)
- scope_dup(old_scope);
+ scope_dup(old_scope);
ruby_scope = old_scope;
scope_vmode = old_vmode;
- if (state) JUMP_TAG(state);
+ switch (state) {
+ case 0:
+ break;
+ case TAG_BREAK:
+ if (!lambda) {
+ struct tag *tt = prot_tag;
+
+ while (tt) {
+ if (tt->tag == PROT_LOOP && tt->blkid == ruby_block->uniq) {
+ tt->dst = (VALUE)tt->frame->uniq;
+ tt->retval = result;
+ JUMP_TAG(TAG_BREAK);
+ }
+ tt = tt->prev;
+ }
+ proc_jump_error(TAG_BREAK, result);
+ }
+ /* fall through */
+ default:
+ JUMP_TAG(state);
+ break;
+ }
ruby_current_node = cnode;
return result;
}
@@ -4320,7 +5162,7 @@ VALUE
rb_yield(val)
VALUE val;
{
- return rb_yield_0(val, 0, 0, Qfalse, Qfalse);
+ return rb_yield_0(val, 0, 0, 0, Qfalse);
}
VALUE
@@ -4336,7 +5178,7 @@ rb_yield_values(n, va_alist)
VALUE ary;
if (n == 0) {
- return rb_yield_0(Qundef, 0, 0, Qfalse, Qfalse);
+ return rb_yield_0(Qundef, 0, 0, 0, Qfalse);
}
ary = rb_ary_new2(n);
va_init_list(args, n);
@@ -4344,7 +5186,7 @@ rb_yield_values(n, va_alist)
rb_ary_push(ary, va_arg(args, VALUE));
}
va_end(args);
- return rb_yield_0(ary, 0, 0, Qfalse, Qtrue);
+ return rb_yield_0(ary, 0, 0, 0, Qtrue);
}
VALUE
@@ -4361,16 +5203,39 @@ rb_yield_splat(values)
avalue = Qtrue;
}
}
- return rb_yield_0(values, 0, 0, Qfalse, avalue);
+ return rb_yield_0(values, 0, 0, 0, avalue);
}
static VALUE
-rb_f_loop()
+loop_i()
{
for (;;) {
- rb_yield_0(Qundef, 0, 0, Qfalse, Qfalse);
+ rb_yield_0(Qundef, 0, 0, 0, Qfalse);
CHECK_INTS;
}
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * loop {|| block }
+ *
+ * Repeatedly executes the block.
+ *
+ * loop do
+ * print "Input: "
+ * line = gets
+ * break if !line or line =~ /^qQ/
+ * # ...
+ * end
+ *
+ * StopIteration raised in the block breaks the loop.
+ */
+
+static VALUE
+rb_f_loop()
+{
+ rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
return Qnil; /* dummy */
}
@@ -4392,7 +5257,7 @@ massign(self, node, val, pcall)
}
if (pcall && list) goto arg_error;
if (node->nd_args) {
- if (node->nd_args == (NODE*)-1) {
+ if ((long)(node->nd_args) == -1) {
/* no check for mere `*' */
}
else if (!list && i<len) {
@@ -4497,7 +5362,7 @@ assign(self, lhs, val, pcall)
/* attr set */
ruby_current_node = lhs;
SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, scope);
+ rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, scope, self);
}
else {
/* array set */
@@ -4508,7 +5373,7 @@ assign(self, lhs, val, pcall)
ruby_current_node = lhs;
SET_CURRENT_SOURCE();
rb_call(CLASS_OF(recv), recv, lhs->nd_mid,
- RARRAY(args)->len, RARRAY(args)->ptr, scope);
+ RARRAY(args)->len, RARRAY(args)->ptr, scope, self);
}
}
break;
@@ -4529,10 +5394,9 @@ rb_iterate(it_proc, data1, bl_proc, data2)
NODE *node = NEW_IFUNC(bl_proc, data2);
VALUE self = ruby_top_self;
- PUSH_ITER(ITER_PRE);
+ PUSH_TAG(PROT_LOOP);
PUSH_BLOCK(0, node);
-
- PUSH_TAG(PROT_ITER);
+ PUSH_ITER(ITER_PRE);
state = EXEC_TAG();
if (state == 0) {
iter_retry:
@@ -4546,9 +5410,9 @@ rb_iterate(it_proc, data1, bl_proc, data2)
state = 0;
goto iter_retry;
}
- POP_TAG();
- POP_BLOCK();
POP_ITER();
+ POP_BLOCK();
+ POP_TAG();
switch (state) {
case 0:
@@ -4598,19 +5462,25 @@ rb_rescue2(b_proc, data1, r_proc, data2, va_alist)
int state;
volatile VALUE result;
volatile VALUE e_info = ruby_errinfo;
+ volatile int handle = Qfalse;
+ VALUE eclass;
va_list args;
PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- retry_entry:
+ switch (state = EXEC_TAG()) {
+ case TAG_RETRY:
+ if (!handle) break;
+ handle = Qfalse;
+ state = 0;
+ ruby_errinfo = Qnil;
+ case 0:
result = (*b_proc)(data1);
- }
- else if (state == TAG_RAISE) {
- int handle = Qfalse;
- VALUE eclass;
-
+ break;
+ case TAG_RAISE:
+ if (handle) break;
+ handle = Qfalse;
va_init_list(args, data2);
- while (eclass = va_arg(args, VALUE)) {
+ while ((eclass = va_arg(args, VALUE)) != 0) {
if (rb_obj_is_kind_of(ruby_errinfo, eclass)) {
handle = Qtrue;
break;
@@ -4619,25 +5489,14 @@ rb_rescue2(b_proc, data1, r_proc, data2, va_alist)
va_end(args);
if (handle) {
+ state = 0;
if (r_proc) {
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- result = (*r_proc)(data2, ruby_errinfo);
- }
- POP_TAG();
- if (state == TAG_RETRY) {
- state = 0;
- ruby_errinfo = Qnil;
- goto retry_entry;
- }
+ result = (*r_proc)(data2, ruby_errinfo);
}
else {
result = Qnil;
- state = 0;
- }
- if (state == 0) {
- ruby_errinfo = e_info;
}
+ ruby_errinfo = e_info;
}
}
POP_TAG();
@@ -4654,6 +5513,8 @@ rb_rescue(b_proc, data1, r_proc, data2)
return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError, (VALUE)0);
}
+static VALUE cont_protect;
+
VALUE
rb_protect(proc, data, state)
VALUE (*proc) _((VALUE));
@@ -4664,9 +5525,11 @@ rb_protect(proc, data, state)
int status;
PUSH_TAG(PROT_NONE);
+ cont_protect = (VALUE)rb_node_newnode(NODE_MEMO, cont_protect, 0, 0);
if ((status = EXEC_TAG()) == 0) {
result = (*proc)(data);
}
+ cont_protect = ((NODE *)cont_protect)->u1.value;
POP_TAG();
if (state) {
*state = status;
@@ -4695,7 +5558,9 @@ rb_ensure(b_proc, data1, e_proc, data2)
}
POP_TAG();
retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */
- (*e_proc)(data2);
+ if (!thread_no_ensure()) {
+ (*e_proc)(data2);
+ }
if (prot_tag) return_value(retval);
if (state) JUMP_TAG(state);
return result;
@@ -4710,32 +5575,31 @@ rb_with_disable_interrupt(proc, data)
int status;
DEFER_INTS;
- PUSH_TAG(PROT_NONE);
- if ((status = EXEC_TAG()) == 0) {
- result = (*proc)(data);
+ {
+ int thr_critical = rb_thread_critical;
+
+ rb_thread_critical = Qtrue;
+ PUSH_TAG(PROT_NONE);
+ if ((status = EXEC_TAG()) == 0) {
+ result = (*proc)(data);
+ }
+ POP_TAG();
+ rb_thread_critical = thr_critical;
}
- POP_TAG();
- ALLOW_INTS;
+ ENABLE_INTS;
if (status) JUMP_TAG(status);
return result;
}
-static inline void
+static void
stack_check()
{
- static int overflowing = 0;
+ rb_thread_t th = rb_curr_thread;
- if (!overflowing && ruby_stack_check()) {
- int state;
- overflowing = 1;
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- rb_exc_raise(sysstack_error);
- }
- POP_TAG();
- overflowing = 0;
- JUMP_TAG(state);
+ if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
+ rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
+ rb_exc_raise(sysstack_error);
}
}
@@ -4746,57 +5610,35 @@ static int last_call_status;
#define CSTAT_VCALL 4
#define CSTAT_SUPER 8
-static VALUE
-name_err_to_s(exc)
- VALUE exc;
-{
- VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
- ID id_recv = rb_intern("recv");
-
- if (NIL_P(mesg)) return rb_class_path(CLASS_OF(exc));
- if (rb_ivar_defined(exc, id_recv)) {
- char buf[BUFSIZ];
- char *desc = "";
- volatile VALUE d = 0;
- int noclass;
- VALUE obj = rb_ivar_get(exc, id_recv);
- int state;
-
- switch (TYPE(obj)) {
- case T_NIL:
- desc = "nil";
- break;
- case T_TRUE:
- desc = "true";
- break;
- case T_FALSE:
- desc = "false";
- break;
- default:
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- d = rb_inspect(obj);
- }
- POP_TAG();
- if (!d || RSTRING(d)->len > 65) {
- d = rb_any_to_s(obj);
- }
- break;
- }
- if (d) {
- desc = RSTRING(d)->ptr;
- }
- noclass = (!desc || desc[0]=='#');
- snprintf(buf, BUFSIZ, RSTRING(mesg)->ptr, desc,
- noclass ? "" : ":",
- noclass ? "" : rb_obj_classname(obj));
- mesg = rb_str_new2(buf);
- rb_iv_set(exc, "mesg", mesg);
- st_delete(ROBJECT(exc)->iv_tbl, (st_data_t*)&id_recv, 0);
- }
- if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
- return mesg;
-}
+/*
+ * call-seq:
+ * obj.method_missing(symbol [, *args] ) => result
+ *
+ * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
+ * <i>symbol</i> is the symbol for the method called, and <i>args</i>
+ * are any arguments that were passed to it. By default, the interpreter
+ * raises an error when this method is called. However, it is possible
+ * to override the method to provide more dynamic behavior.
+ * The example below creates
+ * a class <code>Roman</code>, which responds to methods with names
+ * consisting of roman numerals, returning the corresponding integer
+ * values.
+ *
+ * class Roman
+ * def romanToInt(str)
+ * # ...
+ * end
+ * def method_missing(methId)
+ * str = methId.id2name
+ * romanToInt(str)
+ * end
+ * end
+ *
+ * r = Roman.new
+ * r.iv #=> 4
+ * r.xxiii #=> 23
+ * r.mm #=> 2000
+ */
static VALUE
rb_method_missing(argc, argv, obj)
@@ -4806,7 +5648,7 @@ rb_method_missing(argc, argv, obj)
{
ID id;
VALUE exc = rb_eNoMethodError;
- char *format = 0;
+ const char *format = 0;
NODE *cnode = ruby_current_node;
if (argc == 0 || !SYMBOL_P(argv[0])) {
@@ -4818,36 +5660,34 @@ rb_method_missing(argc, argv, obj)
id = SYM2ID(argv[0]);
if (last_call_status & CSTAT_PRIV) {
- format = "private method `%s' called for %%s%%s%%s";
+ format = "private method `%s' called for %s";
}
else if (last_call_status & CSTAT_PROT) {
- format = "protected method `%s' called for %%s%%s%%s";
+ format = "protected method `%s' called for %s";
}
else if (last_call_status & CSTAT_VCALL) {
- format = "undefined local variable or method `%s' for %%s%%s%%s";
+ format = "undefined local variable or method `%s' for %s";
exc = rb_eNameError;
}
else if (last_call_status & CSTAT_SUPER) {
format = "super: no superclass method `%s'";
}
if (!format) {
- format = "undefined method `%s' for %%s%%s%%s";
+ format = "undefined method `%s' for %s";
}
ruby_current_node = cnode;
{
- char buf[BUFSIZ];
int n = 0;
VALUE args[3];
- snprintf(buf, BUFSIZ, format, rb_id2name(id));
- args[n++] = rb_str_new2(buf);
+ args[n++] = rb_funcall(rb_const_get(exc, rb_intern("message")), '!',
+ 3, rb_str_new2(format), obj, argv[0]);
args[n++] = argv[0];
if (exc == rb_eNoMethodError) {
args[n++] = rb_ary_new4(argc-1, argv+1);
}
exc = rb_class_new_instance(n, args, exc);
- rb_iv_set(exc, "recv", obj);
ruby_frame = ruby_frame->prev; /* pop frame for "method_missing" */
rb_exc_raise(exc);
}
@@ -4873,13 +5713,23 @@ method_missing(obj, id, argc, argv, call_status)
POP_FRAME();
}
else if (id == ID_ALLOCATOR) {
- rb_raise(rb_eNoMethodError, "allocator undefined for %s", rb_class2name(obj));
+ rb_raise(rb_eTypeError, "allocator undefined for %s", rb_class2name(obj));
}
+ if (argc < 0) {
+ VALUE tmp;
- nargv = ALLOCA_N(VALUE, argc+1);
+ argc = -argc-1;
+ tmp = splat_value(argv[argc]);
+ nargv = ALLOCA_N(VALUE, argc + RARRAY(tmp)->len + 1);
+ MEMCPY(nargv+1, argv, VALUE, argc);
+ MEMCPY(nargv+1+argc, RARRAY(tmp)->ptr, VALUE, RARRAY(tmp)->len);
+ argc += RARRAY(tmp)->len;
+ }
+ else {
+ nargv = ALLOCA_N(VALUE, argc+1);
+ MEMCPY(nargv+1, argv, VALUE, argc);
+ }
nargv[0] = ID2SYM(id);
- MEMCPY(nargv+1, argv, VALUE, argc);
-
return rb_funcall2(obj, missing, argc+1, nargv);
}
@@ -4891,7 +5741,7 @@ call_cfunc(func, recv, len, argc, argv)
VALUE *argv;
{
if (len >= 0 && argc != len) {
- rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)",
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
argc, len);
}
@@ -4965,30 +5815,36 @@ call_cfunc(func, recv, len, argc, argv)
argv[11], argv[12], argv[13], argv[14]);
break;
default:
- rb_raise(rb_eArgError, "too many arguments(%d)", len);
+ rb_raise(rb_eArgError, "too many arguments (%d)", len);
break;
}
return Qnil; /* not reached */
}
static VALUE
-rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
+rb_call0(klass, recv, id, oid, argc, argv, body, flags)
VALUE klass, recv;
ID id;
ID oid;
int argc; /* OK */
VALUE *argv; /* OK */
- NODE *body; /* OK */
- int nosuper;
+ NODE * volatile body;
+ int flags;
{
NODE *b2; /* OK */
volatile VALUE result = Qnil;
int itr;
static int tick;
TMP_PROTECT;
+ volatile int safe = -1;
+ if (NOEX_SAFE(flags) > ruby_safe_level && NOEX_SAFE(flags) > 2) {
+ rb_raise(rb_eSecurityError, "calling insecure method: %s",
+ rb_id2name(id));
+ }
switch (ruby_iter->iter) {
case ITER_PRE:
+ case ITER_PAS:
itr = ITER_CUR;
break;
case ITER_CUR:
@@ -5000,16 +5856,29 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
if ((++tick & 0xff) == 0) {
CHECK_INTS; /* better than nothing */
stack_check();
+ rb_gc_finalize_deferred();
+ }
+ if (argc < 0) {
+ VALUE tmp;
+ VALUE *nargv;
+
+ argc = -argc-1;
+ tmp = splat_value(argv[argc]);
+ nargv = TMP_ALLOC(argc + RARRAY(tmp)->len);
+ MEMCPY(nargv, argv, VALUE, argc);
+ MEMCPY(nargv+argc, RARRAY(tmp)->ptr, VALUE, RARRAY(tmp)->len);
+ argc += RARRAY(tmp)->len;
+ argv = nargv;
}
PUSH_ITER(itr);
PUSH_FRAME();
ruby_frame->last_func = id;
ruby_frame->orig_func = oid;
- ruby_frame->last_class = nosuper?0:klass;
+ ruby_frame->last_class = (flags & NOEX_NOSUPER)?0:klass;
ruby_frame->self = recv;
ruby_frame->argc = argc;
- ruby_frame->argv = argv;
+ ruby_frame->flags = 0;
switch (nd_type(body)) {
case NODE_CFUNC:
@@ -5017,20 +5886,22 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
int len = body->nd_argc;
if (len < -2) {
- rb_bug("bad argc(%d) specified for `%s(%s)'",
+ rb_bug("bad argc (%d) specified for `%s(%s)'",
len, rb_class2name(klass), rb_id2name(id));
}
- if (trace_func) {
+ if (event_hooks) {
int state;
- call_trace_func("c-call", ruby_current_node, recv, id, klass);
+ EXEC_EVENT_HOOK(RUBY_EVENT_C_CALL, ruby_current_node,
+ recv, id, klass);
PUSH_TAG(PROT_FUNC);
if ((state = EXEC_TAG()) == 0) {
result = call_cfunc(body->nd_cfnc, recv, len, argc, argv);
}
POP_TAG();
ruby_current_node = ruby_frame->node;
- call_trace_func("c-return", ruby_current_node, recv, id, klass);
+ EXEC_EVENT_HOOK(RUBY_EVENT_C_RETURN, ruby_current_node,
+ recv, id, klass);
if (state) JUMP_TAG(state);
}
else {
@@ -5042,15 +5913,19 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
/* for attr get/set */
case NODE_IVAR:
if (argc != 0) {
- rb_raise(rb_eArgError, "wrong number of arguments(%d for 0)", argc);
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
}
result = rb_attr_get(recv, body->nd_vid);
break;
case NODE_ATTRSET:
- /* for re-scoped/renamed method */
+ if (argc != 1)
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
+ result = rb_ivar_set(recv, body->nd_vid, argv[0]);
+ break;
+
case NODE_ZSUPER:
- result = rb_eval(recv, body);
+ result = rb_call_super(argc, argv);
break;
case NODE_DMETHOD:
@@ -5058,7 +5933,16 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
break;
case NODE_BMETHOD:
+ ruby_frame->flags |= FRAME_DMETH;
+ if (event_hooks) {
+ struct BLOCK *data;
+ Data_Get_Struct(body->nd_cval, struct BLOCK, data);
+ EXEC_EVENT_HOOK(RUBY_EVENT_CALL, data->body, recv, id, klass);
+ }
result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass);
+ if (event_hooks) {
+ EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, ruby_current_node, recv, id, klass);
+ }
break;
case NODE_SCOPE:
@@ -5068,7 +5952,6 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
NODE *saved_cref = 0;
PUSH_SCOPE();
-
if (body->nd_rval) {
saved_cref = ruby_cref;
ruby_cref = (NODE*)body->nd_rval;
@@ -5087,12 +5970,15 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
}
b2 = body = body->nd_next;
+ if (NOEX_SAFE(flags) > ruby_safe_level) {
+ safe = ruby_safe_level;
+ ruby_safe_level = NOEX_SAFE(flags);
+ }
PUSH_VARS();
PUSH_TAG(PROT_FUNC);
-
if ((state = EXEC_TAG()) == 0) {
NODE *node = 0;
- int i;
+ int i, nopt = 0;
if (nd_type(body) == NODE_ARGS) {
node = body;
@@ -5109,58 +5995,66 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
i = node->nd_cnt;
if (i > argc) {
- rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)",
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
argc, i);
}
- if (node->nd_rest == -1) {
- int opt = i;
+ if (!node->nd_rest) {
NODE *optnode = node->nd_opt;
+ nopt = i;
while (optnode) {
- opt++;
+ nopt++;
optnode = optnode->nd_next;
}
- if (opt < argc) {
- rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)",
- argc, opt);
+ if (nopt < argc) {
+ rb_raise(rb_eArgError,
+ "wrong number of arguments (%d for %d)",
+ argc, nopt);
}
- ruby_frame->argc = opt;
- ruby_frame->argv = local_vars+2;
}
-
if (local_vars) {
if (i > 0) {
/* +2 for $_ and $~ */
MEMCPY(local_vars+2, argv, VALUE, i);
}
- argv += i; argc -= i;
- if (node->nd_opt) {
- NODE *opt = node->nd_opt;
-
- while (opt && argc) {
- assign(recv, opt->nd_head, *argv, 1);
- argv++; argc--;
+ }
+ argv += i; argc -= i;
+ if (node->nd_opt) {
+ NODE *opt = node->nd_opt;
+
+ while (opt && argc) {
+ assign(recv, opt->nd_head, *argv, 1);
+ argv++; argc--;
+ ++i;
+ opt = opt->nd_next;
+ }
+ if (opt) {
+ rb_eval(recv, opt);
+ while (opt) {
opt = opt->nd_next;
+ ++i;
}
- if (opt) {
- rb_eval(recv, opt);
- }
}
- local_vars = ruby_scope->local_vars;
- if (node->nd_rest >= 0) {
- VALUE v;
-
- if (argc > 0)
- v = rb_ary_new4(argc,argv);
- else
- v = rb_ary_new2(0);
- ruby_scope->local_vars[node->nd_rest] = v;
+ }
+ if (!node->nd_rest) {
+ i = nopt;
+ }
+ else {
+ VALUE v;
+
+ if (argc > 0) {
+ v = rb_ary_new4(argc,argv);
+ i = -i - 1;
+ }
+ else {
+ v = rb_ary_new2(0);
}
+ assign(recv, node->nd_rest, v, 1);
}
+ ruby_frame->argc = i;
}
-
- if (trace_func) {
- call_trace_func("call", b2, recv, id, klass);
+ if (event_hooks) {
+ EXEC_EVENT_HOOK(RUBY_EVENT_CALL, b2, recv, id, klass);
}
result = rb_eval(recv, body);
}
@@ -5169,13 +6063,14 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
state = 0;
}
POP_TAG();
+ if (event_hooks) {
+ EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, ruby_current_node, recv, id, klass);
+ }
POP_VARS();
POP_CLASS();
POP_SCOPE();
ruby_cref = saved_cref;
- if (trace_func) {
- call_trace_func("return", ruby_frame->prev->node, recv, id, klass);
- }
+ if (safe >= 0) ruby_safe_level = safe;
switch (state) {
case 0:
break;
@@ -5189,14 +6084,14 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
if (rb_block_given_p()) JUMP_TAG(state);
/* fall through */
default:
- jump_tag_but_local_jump(state);
+ jump_tag_but_local_jump(state, result);
break;
}
}
break;
default:
- rb_bug("unknown node type %d", nd_type(body));
+ unknown_node(body);
break;
}
POP_FRAME();
@@ -5205,12 +6100,13 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
}
static VALUE
-rb_call(klass, recv, mid, argc, argv, scope)
+rb_call(klass, recv, mid, argc, argv, scope, self)
VALUE klass, recv;
ID mid;
int argc; /* OK */
const VALUE *argv; /* OK */
int scope;
+ VALUE self;
{
NODE *body; /* OK */
int noex;
@@ -5238,24 +6134,25 @@ rb_call(klass, recv, mid, argc, argv, scope)
return method_missing(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
}
- if (mid != missing) {
+ if (mid != missing && scope == 0) {
/* receiver specified form for private method */
- if ((noex & NOEX_PRIVATE) && scope == 0)
+ if (noex & NOEX_PRIVATE)
return method_missing(recv, mid, argc, argv, CSTAT_PRIV);
/* self must be kind of a specified form for protected method */
- if ((noex & NOEX_PROTECTED)) {
+ if (noex & NOEX_PROTECTED) {
VALUE defined_class = klass;
+ if (self == Qundef) self = ruby_frame->self;
if (TYPE(defined_class) == T_ICLASS) {
defined_class = RBASIC(defined_class)->klass;
}
- if (!rb_obj_is_kind_of(ruby_frame->self, rb_class_real(defined_class)))
+ if (!rb_obj_is_kind_of(self, rb_class_real(defined_class)))
return method_missing(recv, mid, argc, argv, CSTAT_PROT);
}
}
- return rb_call0(klass, recv, mid, id, argc, argv, body, noex & NOEX_NOSUPER);
+ return rb_call0(klass, recv, mid, id, argc, argv, body, noex);
}
VALUE
@@ -5270,9 +6167,27 @@ rb_apply(recv, mid, args)
argc = RARRAY(args)->len; /* Assigns LONG, but argc is INT */
argv = ALLOCA_N(VALUE, argc);
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1);
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1, Qundef);
}
+/*
+ * call-seq:
+ * obj.send(symbol [, args...]) => obj
+ * obj.__send__(symbol [, args...]) => obj
+ *
+ * Invokes the method identified by _symbol_, passing it any
+ * arguments specified. You can use <code>\_\_send__</code> if the name
+ * +send+ clashes with an existing method in _obj_.
+ *
+ * class Klass
+ * def hello(*args)
+ * "Hello " + args.join(' ')
+ * end
+ * end
+ * k = Klass.new
+ * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
+ */
+
static VALUE
rb_f_send(argc, argv, recv)
int argc;
@@ -5285,24 +6200,19 @@ rb_f_send(argc, argv, recv)
vid = *argv++; argc--;
PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
- vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, 1);
+ vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, 1, Qundef);
POP_ITER();
return vid;
}
-VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_funcall(VALUE recv, ID mid, int n, ...)
-#else
-rb_funcall(recv, mid, n, va_alist)
+static VALUE
+vafuncall(recv, mid, n, ar)
VALUE recv;
ID mid;
int n;
- va_dcl
-#endif
+ va_list *ar;
{
- va_list ar;
VALUE *argv;
if (n > 0) {
@@ -5310,17 +6220,65 @@ rb_funcall(recv, mid, n, va_alist)
argv = ALLOCA_N(VALUE, n);
- va_init_list(ar, n);
for (i=0;i<n;i++) {
- argv[i] = va_arg(ar, VALUE);
+ argv[i] = va_arg(*ar, VALUE);
}
- va_end(ar);
+ va_end(*ar);
}
else {
argv = 0;
}
- return rb_call(CLASS_OF(recv), recv, mid, n, argv, 1);
+ return rb_call(CLASS_OF(recv), recv, mid, n, argv, 1, Qundef);
+}
+
+VALUE
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_funcall(VALUE recv, ID mid, int n, ...)
+#else
+rb_funcall(recv, mid, n, va_alist)
+ VALUE recv;
+ ID mid;
+ int n;
+ va_dcl
+#endif
+{
+ va_list ar;
+ va_init_list(ar, n);
+
+ return vafuncall(recv, mid, n, &ar);
+}
+
+VALUE
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_funcall_rescue(VALUE recv, ID mid, int n, ...)
+#else
+rb_funcall_rescue(recv, mid, n, va_alist)
+ VALUE recv;
+ ID mid;
+ int n;
+ va_dcl
+#endif
+{
+ VALUE result = Qnil; /* OK */
+ int status;
+ va_list ar;
+
+ va_init_list(ar, n);
+
+ PUSH_TAG(PROT_NONE);
+ if ((status = EXEC_TAG()) == 0) {
+ result = vafuncall(recv, mid, n, &ar);
+ }
+ POP_TAG();
+ switch (status) {
+ case 0:
+ return result;
+ case TAG_RAISE:
+ return Qundef;
+ default:
+ JUMP_TAG(status);
+ }
}
VALUE
@@ -5330,7 +6288,7 @@ rb_funcall2(recv, mid, argc, argv)
int argc;
const VALUE *argv;
{
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1);
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1, Qundef);
}
VALUE
@@ -5340,7 +6298,7 @@ rb_funcall3(recv, mid, argc, argv)
int argc;
const VALUE *argv;
{
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0);
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0, Qundef);
}
VALUE
@@ -5348,32 +6306,21 @@ rb_call_super(argc, argv)
int argc;
const VALUE *argv;
{
- VALUE result, self, klass, k;
+ VALUE result, self, klass;
if (ruby_frame->last_class == 0) {
rb_name_error(ruby_frame->last_func, "calling `super' from `%s' is prohibited",
- rb_id2name(ruby_frame->last_func));
+ rb_id2name(ruby_frame->orig_func));
}
self = ruby_frame->self;
klass = ruby_frame->last_class;
- if (BUILTIN_TYPE(klass) == T_MODULE) {
- k = search_iclass(self, klass);
- if (!k) {
- rb_raise(rb_eTypeError, "%s is not included in %s",
- rb_class2name(klass),
- rb_class2name(CLASS_OF(self)));
- }
- if (RCLASS(k)->super == 0) {
- rb_name_error(ruby_frame->last_func,
- "super: no superclass method `%s'",
- rb_id2name(ruby_frame->last_func));
- }
- klass = k;
+ if (RCLASS(klass)->super == 0) {
+ return method_missing(self, ruby_frame->orig_func, argc, argv, CSTAT_SUPER);
}
PUSH_ITER(ruby_iter->iter ? ITER_PRE : ITER_NOT);
- result = rb_call(RCLASS(klass)->super, self, ruby_frame->orig_func, argc, argv, 3);
+ result = rb_call(RCLASS(klass)->super, self, ruby_frame->orig_func, argc, argv, 3, Qundef);
POP_ITER();
return result;
@@ -5417,8 +6364,11 @@ backtrace(lev)
}
}
}
- while (frame && (n = frame->node)) {
+ for (; frame && (n = frame->node); frame = frame->prev) {
if (frame->prev && frame->prev->last_func) {
+ if (frame->prev->node == n) {
+ if (frame->prev->last_func == frame->last_func) continue;
+ }
snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
n->nd_file, nd_line(n),
rb_id2name(frame->prev->last_func));
@@ -5427,12 +6377,36 @@ backtrace(lev)
snprintf(buf, BUFSIZ, "%s:%d", n->nd_file, nd_line(n));
}
rb_ary_push(ary, rb_str_new2(buf));
- frame = frame->prev;
}
return ary;
}
+/*
+ * call-seq:
+ * caller(start=1) => array
+ *
+ * Returns the current execution stack---an array containing strings in
+ * the form ``<em>file:line</em>'' or ``<em>file:line: in
+ * `method'</em>''. The optional _start_ parameter
+ * determines the number of initial stack entries to omit from the
+ * result.
+ *
+ * def a(skip)
+ * caller(skip)
+ * end
+ * def b(skip)
+ * a(skip)
+ * end
+ * def c(skip)
+ * b(skip)
+ * end
+ * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
+ * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
+ * c(2) #=> ["prog:8:in `c'", "prog:12"]
+ * c(3) #=> ["prog:13"]
+ */
+
static VALUE
rb_f_caller(argc, argv)
int argc;
@@ -5445,7 +6419,7 @@ rb_f_caller(argc, argv)
if (NIL_P(level)) lev = 1;
else lev = NUM2INT(level);
- if (lev < 0) rb_raise(rb_eArgError, "negative level(%d)", lev);
+ if (lev < 0) rb_raise(rb_eArgError, "negative level (%d)", lev);
return backtrace(lev);
}
@@ -5474,10 +6448,16 @@ rb_frame_last_func()
return ruby_frame->last_func;
}
+ID
+rb_frame_this_func()
+{
+ return ruby_frame->orig_func;
+}
+
static NODE*
compile(src, file, line)
VALUE src;
- char *file;
+ const char *file;
int line;
{
NODE *node;
@@ -5497,7 +6477,7 @@ compile(src, file, line)
static VALUE
eval(self, src, scope, file, line)
VALUE self, src, scope;
- char *file;
+ const char *file;
int line;
{
struct BLOCK *data = NULL;
@@ -5511,6 +6491,7 @@ eval(self, src, scope, file, line)
struct FRAME frame;
NODE *nodesave = ruby_current_node;
volatile int iter = ruby_frame->iter;
+ volatile int safe = ruby_safe_level;
int state;
if (!NIL_P(scope)) {
@@ -5536,10 +6517,10 @@ eval(self, src, scope, file, line)
ruby_cref = data->cref;
old_wrapper = ruby_wrapper;
ruby_wrapper = data->wrapper;
- if ((file == 0 || (line == 1 && strcmp(file, "(eval)") == 0)) && data->body) {
- file = data->body->nd_file;
+ if ((file == 0 || (line == 1 && strcmp(file, "(eval)") == 0)) && data->frame.node) {
+ file = data->frame.node->nd_file;
if (!file) file = "__builtin__";
- line = nd_line(data->body);
+ line = nd_line(data->frame.node);
}
self = data->self;
@@ -5555,7 +6536,7 @@ eval(self, src, scope, file, line)
file = ruby_sourcefile;
line = ruby_sourceline;
}
- PUSH_CLASS(ruby_cbase);
+ PUSH_CLASS(data ? data->klass : ruby_class);
ruby_in_eval++;
if (TYPE(ruby_class) == T_ICLASS) {
ruby_class = RBASIC(ruby_class)->klass;
@@ -5564,9 +6545,11 @@ eval(self, src, scope, file, line)
if ((state = EXEC_TAG()) == 0) {
NODE *node;
+ ruby_safe_level = 0;
result = ruby_errinfo;
ruby_errinfo = Qnil;
node = compile(src, file, line);
+ ruby_safe_level = safe;
if (ruby_nerrs > 0) {
compile_error(0);
}
@@ -5608,14 +6591,18 @@ eval(self, src, scope, file, line)
if (state) {
if (state == TAG_RAISE) {
if (strcmp(file, "(eval)") == 0) {
- VALUE mesg, errat;
+ VALUE mesg, errat, bt2;
errat = get_backtrace(ruby_errinfo);
- mesg = rb_attr_get(ruby_errinfo, rb_intern("mesg"));
- if (!NIL_P(mesg) && TYPE(mesg) == T_STRING) {
- rb_str_update(mesg, 0, 0, RARRAY(errat)->ptr[0]);
+ mesg = rb_attr_get(ruby_errinfo, rb_intern("mesg"));
+ if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
+ (bt2 = backtrace(-2), RARRAY_LEN(bt2) > 0)) {
+ if (!NIL_P(mesg) && TYPE(mesg) == T_STRING) {
+ rb_str_update(mesg, 0, 0, rb_str_new2(": "));
+ rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
+ }
+ RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
}
- RARRAY(errat)->ptr[0] = RARRAY(backtrace(-2))->ptr[0];
}
rb_exc_raise(ruby_errinfo);
}
@@ -5625,6 +6612,25 @@ eval(self, src, scope, file, line)
return result;
}
+/*
+ * call-seq:
+ * eval(string [, binding [, filename [,lineno]]]) => obj
+ *
+ * Evaluates the Ruby expression(s) in <em>string</em>. If
+ * <em>binding</em> is given, the evaluation is performed in its
+ * context. The binding may be a <code>Binding</code> object or a
+ * <code>Proc</code> object. If the optional <em>filename</em> and
+ * <em>lineno</em> parameters are present, they will be used when
+ * reporting syntax errors.
+ *
+ * def getBinding(str)
+ * return binding
+ * end
+ * str = "hello"
+ * eval "str + ' Fred'" #=> "hello Fred"
+ * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
+ */
+
static VALUE
rb_f_eval(argc, argv, self)
int argc;
@@ -5632,7 +6638,7 @@ rb_f_eval(argc, argv, self)
VALUE self;
{
VALUE src, scope, vfile, vline;
- char *file = "(eval)";
+ const char *file = "(eval)";
int line = 1;
rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
@@ -5646,12 +6652,13 @@ rb_f_eval(argc, argv, self)
SafeStringValue(src);
}
if (argc >= 3) {
- file = StringValuePtr(vfile);
+ StringValue(vfile);
}
if (argc >= 4) {
line = NUM2INT(vline);
}
+ if (!NIL_P(vfile)) file = RSTRING(vfile)->ptr;
if (NIL_P(scope) && ruby_frame->prev) {
struct FRAME *prev;
VALUE val;
@@ -5678,14 +6685,15 @@ exec_under(func, under, cbase, args)
VALUE val = Qnil; /* OK */
int state;
int mode;
+ struct FRAME *f = ruby_frame;
PUSH_CLASS(under);
PUSH_FRAME();
- ruby_frame->self = _frame.prev->self;
- ruby_frame->last_func = _frame.prev->last_func;
- ruby_frame->last_class = _frame.prev->last_class;
- ruby_frame->argc = _frame.prev->argc;
- ruby_frame->argv = _frame.prev->argv;
+ ruby_frame->self = f->self;
+ ruby_frame->last_func = f->last_func;
+ ruby_frame->orig_func = f->orig_func;
+ ruby_frame->last_class = f->last_class;
+ ruby_frame->argc = f->argc;
if (cbase) {
PUSH_CREF(cbase);
}
@@ -5710,6 +6718,11 @@ static VALUE
eval_under_i(args)
VALUE *args;
{
+ struct FRAME *f = ruby_frame;
+
+ if (f && (f = f->prev) && (f = f->prev)) {
+ ruby_frame = f;
+ }
return eval(args[0], args[1], Qnil, (char*)args[2], (int)args[3]);
}
@@ -5742,12 +6755,28 @@ yield_under_i(self)
return rb_yield_0(self, self, ruby_class, YIELD_PUBLIC_DEF, Qfalse);
}
+static VALUE
+yield_args_under_i(vinfo)
+ VALUE vinfo;
+{
+ VALUE *info = (VALUE *)vinfo;
+
+ return rb_yield_0(info[0], info[1], ruby_class, YIELD_PUBLIC_DEF, Qtrue);
+}
+
/* block eval under the class/module context */
static VALUE
-yield_under(under, self)
- VALUE under, self;
+yield_under(under, self, args)
+ VALUE under, self, args;
{
- return exec_under(yield_under_i, under, 0, self);
+ if (args == Qundef) {
+ return exec_under(yield_under_i, under, 0, self);
+ }
+ else {
+ VALUE info[2] = { args, self };
+
+ return exec_under(yield_args_under_i, under, 0, (VALUE)info);
+ }
}
static VALUE
@@ -5760,10 +6789,10 @@ specific_eval(argc, argv, klass, self)
if (argc > 0) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
}
- return yield_under(klass, self);
+ return yield_under(klass, self, Qundef);
}
else {
- char *file = "(eval)";
+ const char *file = "(eval)";
int line = 1;
if (argc == 0) {
@@ -5781,15 +6810,38 @@ specific_eval(argc, argv, klass, self)
rb_id2name(ruby_frame->last_func),
rb_id2name(ruby_frame->last_func));
}
+ if (argc > 2) line = NUM2INT(argv[2]);
if (argc > 1) {
file = StringValuePtr(argv[1]);
}
- if (argc > 2) line = NUM2INT(argv[2]);
}
return eval_under(klass, self, argv[0], file, line);
}
}
+/*
+ * call-seq:
+ * obj.instance_eval(string [, filename [, lineno]] ) => obj
+ * obj.instance_eval {| | block } => obj
+ *
+ * Evaluates a string containing Ruby source code, or the given block,
+ * within the context of the receiver (_obj_). In order to set the
+ * context, the variable +self+ is set to _obj_ while
+ * the code is executing, giving the code access to _obj_'s
+ * instance variables. In the version of <code>instance_eval</code>
+ * that takes a +String+, the optional second and third
+ * parameters supply a filename and starting line number that are used
+ * when reporting compilation errors.
+ *
+ * class Klass
+ * def initialize
+ * @secret = 99
+ * end
+ * end
+ * k = Klass.new
+ * k.instance_eval { @secret } #=> 99
+ */
+
VALUE
rb_obj_instance_eval(argc, argv, self)
int argc;
@@ -5798,16 +6850,74 @@ rb_obj_instance_eval(argc, argv, self)
{
VALUE klass;
- if (rb_special_const_p(self)) {
+ if (SPECIAL_CONST_P(self)) {
klass = Qnil;
}
else {
klass = rb_singleton_class(self);
}
-
return specific_eval(argc, argv, klass, self);
}
+/*
+ * call-seq:
+ * obj.instance_exec(arg...) {|var...| block } => obj
+ *
+ * Executes the given block within the context of the receiver
+ * (_obj_). In order to set the context, the variable +self+ is set
+ * to _obj_ while the code is executing, giving the code access to
+ * _obj_'s instance variables. Arguments are passed as block parameters.
+ *
+ * class KlassWithSecret
+ * def initialize
+ * @secret = 99
+ * end
+ * end
+ * k = KlassWithSecret.new
+ * k.instance_exec(5) {|x| @secret+x } #=> 104
+ */
+
+VALUE
+rb_obj_instance_exec(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE klass;
+
+ if (SPECIAL_CONST_P(self)) {
+ klass = Qnil;
+ }
+ else {
+ klass = rb_singleton_class(self);
+ }
+ return yield_under(klass, self, rb_ary_new4(argc, argv));
+}
+
+/*
+ * call-seq:
+ * mod.class_eval(string [, filename [, lineno]]) => obj
+ * mod.module_eval {|| block } => obj
+ *
+ * Evaluates the string or block in the context of _mod_. This can
+ * be used to add methods to a class. <code>module_eval</code> returns
+ * the result of evaluating its argument. The optional _filename_
+ * and _lineno_ parameters set the text for error messages.
+ *
+ * class Thing
+ * end
+ * a = %q{def hello() "Hello there!" end}
+ * Thing.module_eval(a)
+ * puts Thing.new.hello()
+ * Thing.module_eval("invalid code", "dummy", 123)
+ *
+ * <em>produces:</em>
+ *
+ * Hello there!
+ * dummy:123:in `module_eval': undefined local variable
+ * or method `code' for Thing:Class
+ */
+
VALUE
rb_mod_module_eval(argc, argv, mod)
int argc;
@@ -5817,6 +6927,35 @@ rb_mod_module_eval(argc, argv, mod)
return specific_eval(argc, argv, mod, mod);
}
+/*
+ * call-seq:
+ * mod.module_exec(arg...) {|var...| block } => obj
+ * mod.class_exec(arg...) {|var...| block } => obj
+ *
+ * Evaluates the given block in the context of the class/module.
+ * The method defined in the block will belong to the receiver.
+ *
+ * class Thing
+ * end
+ * Thing.class_exec{
+ * def hello() "Hello there!" end
+ * }
+ * puts Thing.new.hello()
+ *
+ * <em>produces:</em>
+ *
+ * Hello there!
+ */
+
+VALUE
+rb_mod_module_exec(argc, argv, mod)
+ int argc;
+ VALUE *argv;
+ VALUE mod;
+{
+ return yield_under(mod, mod, rb_ary_new4(argc, argv));
+}
+
VALUE rb_load_path;
NORETURN(static void load_failed _((VALUE)));
@@ -5830,11 +6969,10 @@ rb_load(fname, wrap)
int state;
volatile int prohibit_int = rb_prohibit_interrupt;
volatile ID last_func;
- volatile VALUE wrapper = 0;
+ volatile VALUE wrapper = ruby_wrapper;
volatile VALUE self = ruby_top_self;
NODE *volatile last_node;
NODE *saved_cref = ruby_cref;
- TMP_PROTECT;
if (wrap && ruby_safe_level >= 4) {
StringValue(fname);
@@ -5842,6 +6980,7 @@ rb_load(fname, wrap)
else {
SafeStringValue(fname);
}
+ fname = rb_str_new4(fname);
tmp = rb_find_file(fname);
if (!tmp) {
load_failed(fname);
@@ -5851,7 +6990,7 @@ rb_load(fname, wrap)
ruby_errinfo = Qnil; /* ensure */
PUSH_VARS();
PUSH_CLASS(ruby_wrapper);
- ruby_cref = top_cref;
+ ruby_cref = ruby_top_cref;
if (!wrap) {
rb_secure(4); /* should alter global state */
ruby_class = rb_cObject;
@@ -5918,7 +7057,7 @@ rb_load(fname, wrap)
ruby_nerrs = 0;
rb_exc_raise(ruby_errinfo);
}
- if (state) jump_tag_but_local_jump(state);
+ if (state) jump_tag_but_local_jump(state, Qundef);
if (!NIL_P(ruby_errinfo)) /* exception during load */
rb_exc_raise(ruby_errinfo);
}
@@ -5939,6 +7078,21 @@ rb_load_protect(fname, wrap, state)
if (state) *state = status;
}
+/*
+ * call-seq:
+ * load(filename, wrap=false) => true
+ *
+ * Loads and executes the Ruby
+ * program in the file _filename_. If the filename does not
+ * resolve to an absolute path, the file is searched for in the library
+ * directories listed in <code>$:</code>. If the optional _wrap_
+ * parameter is +true+, the loaded script will be executed
+ * under an anonymous module, protecting the calling program's global
+ * namespace. In no circumstance will any local variables in the loaded
+ * file be propagated to the loading environment.
+ */
+
+
static VALUE
rb_f_load(argc, argv)
int argc;
@@ -5962,13 +7116,25 @@ static st_table *loading_tbl;
#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0)
#endif
-static char *
-rb_feature_p(feature, ext, rb)
- const char *feature, *ext;
+
+static const char *const loadable_ext[] = {
+ ".rb", DLEXT,
+#ifdef DLEXT2
+ DLEXT2,
+#endif
+ 0
+};
+
+static int rb_feature_p _((const char **, const char *, int));
+static int search_required _((VALUE, VALUE *, VALUE *));
+
+static int
+rb_feature_p(ftptr, ext, rb)
+ const char **ftptr, *ext;
int rb;
{
VALUE v;
- char *f, *e;
+ const char *f, *e, *feature = *ftptr;
long i, len, elen;
if (ext) {
@@ -5979,38 +7145,69 @@ rb_feature_p(feature, ext, rb)
len = strlen(feature);
elen = 0;
}
- for (i = 0; i < RARRAY(rb_features)->len; ++i) {
- v = RARRAY(rb_features)->ptr[i];
+ for (i = 0; i < RARRAY_LEN(rb_features); ++i) {
+ v = RARRAY_PTR(rb_features)[i];
f = StringValuePtr(v);
- if (strncmp(f, feature, len) != 0) continue;
+ if (RSTRING_LEN(v) < len || strncmp(f, feature, len) != 0)
+ continue;
if (!*(e = f + len)) {
if (ext) continue;
- return e;
+ *ftptr = 0;
+ return 'u';
}
if (*e != '.') continue;
if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
- return e;
+ *ftptr = 0;
+ return 's';
}
if ((rb || !ext) && (strcmp(e, ".rb") == 0)) {
- return e;
+ *ftptr = 0;
+ return 'r';
+ }
+ }
+ if (loading_tbl) {
+ if (st_lookup(loading_tbl, (st_data_t)feature, (st_data_t *)ftptr)) {
+ if (!ext) return 'u';
+ return strcmp(ext, ".rb") ? 's' : 'r';
+ }
+ else {
+ char *buf;
+
+ if (ext && *ext) return 0;
+ buf = ALLOCA_N(char, len + DLEXT_MAXLEN + 1);
+ MEMCPY(buf, feature, char, len);
+ for (i = 0; (e = loadable_ext[i]) != 0; i++) {
+ strncpy(buf + len, e, DLEXT_MAXLEN + 1);
+ if (st_lookup(loading_tbl, (st_data_t)buf, (st_data_t *)ftptr)) {
+ return i ? 's' : 'r';
+ }
+ }
}
}
return 0;
}
-
-static const char *const loadable_ext[] = {
- ".rb", DLEXT,
-#ifdef DLEXT2
- DLEXT2,
-#endif
- 0
-};
+#define rb_feature_p(feature, ext, rb) rb_feature_p(&feature, ext, rb)
int
rb_provided(feature)
const char *feature;
{
- return rb_feature_p(feature, 0, Qfalse) ? Qtrue : Qfalse;
+ const char *ext = strrchr(feature, '.');
+
+ if (ext && !strchr(ext, '/')) {
+ if (strcmp(".rb", ext) == 0) {
+ if (rb_feature_p(feature, ext, Qtrue)) return Qtrue;
+ return Qfalse;
+ }
+ else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
+ if (rb_feature_p(feature, ext, Qfalse)) return Qtrue;
+ return Qfalse;
+ }
+ }
+ if (rb_feature_p(feature, feature + strlen(feature), Qtrue))
+ return Qtrue;
+
+ return Qfalse;
}
static void
@@ -6027,21 +7224,66 @@ rb_provide(feature)
rb_provide_feature(rb_str_new2(feature));
}
-static void
-load_wait(ftptr)
- char *ftptr;
+static char *
+load_lock(ftptr)
+ const char *ftptr;
{
st_data_t th;
- if (!loading_tbl) return;
- if (!st_lookup(loading_tbl, (st_data_t)ftptr, &th)) return;
- if ((rb_thread_t)th == curr_thread) return;
+ if (!loading_tbl ||
+ !st_lookup(loading_tbl, (st_data_t)ftptr, &th))
+ {
+ /* loading ruby library should be serialized. */
+ if (!loading_tbl) {
+ loading_tbl = st_init_strtable();
+ }
+ /* partial state */
+ ftptr = ruby_strdup(ftptr);
+ st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread);
+ return (char *)ftptr;
+ }
do {
- CHECK_INTS;
- rb_thread_schedule();
+ rb_thread_t owner = (rb_thread_t)th;
+ if (owner == curr_thread) return 0;
+ rb_thread_join(owner->thread, -1.0);
} while (st_lookup(loading_tbl, (st_data_t)ftptr, &th));
+ return 0;
+}
+
+static void
+load_unlock(const char *ftptr)
+{
+ if (ftptr) {
+ st_data_t key = (st_data_t)ftptr;
+
+ if (st_delete(loading_tbl, &key, 0)) {
+ free((char *)key);
+ }
+ }
}
+/*
+ * call-seq:
+ * require(string) => true or false
+ *
+ * Ruby tries to load the library named _string_, returning
+ * +true+ if successful. If the filename does not resolve to
+ * an absolute path, it will be searched for in the directories listed
+ * in <code>$:</code>. If the file has the extension ``.rb'', it is
+ * loaded as a source file; if the extension is ``.so'', ``.o'', or
+ * ``.dll'', or whatever the default shared library extension is on
+ * the current platform, Ruby loads the shared library as a Ruby
+ * extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on
+ * to the name. The name of the loaded feature is added to the array in
+ * <code>$"</code>. A feature will not be loaded if it's name already
+ * appears in <code>$"</code>. However, the file name is not converted
+ * to an absolute path, so that ``<code>require 'a';require
+ * './a'</code>'' will load <code>a.rb</code> twice.
+ *
+ * require "my-library.rb"
+ * require "db-driver"
+ */
+
VALUE
rb_f_require(obj, fname)
VALUE obj, fname;
@@ -6054,22 +7296,30 @@ search_required(fname, featurep, path)
VALUE fname, *featurep, *path;
{
VALUE tmp;
- char *ext, *ftptr;
+ const char *ext, *ftptr;
+ int type;
*featurep = fname;
*path = 0;
- ext = strrchr(ftptr = RSTRING(fname)->ptr, '.');
+ ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
if (ext && !strchr(ext, '/')) {
if (strcmp(".rb", ext) == 0) {
- if (rb_feature_p(ftptr, ext, Qtrue)) return 'r';
- if (*path = rb_find_file(fname)) return 'r';
+ if (rb_feature_p(ftptr, ext, Qtrue)) {
+ if (ftptr) *path = rb_str_new2(ftptr);
+ return 'r';
+ }
+ if ((*path = rb_find_file(fname)) != 0) return 'r';
return 0;
}
else if (IS_SOEXT(ext)) {
- if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
- tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr);
+ if (rb_feature_p(ftptr, ext, Qfalse)) {
+ if (ftptr) *path = rb_str_new2(ftptr);
+ return 's';
+ }
+ tmp = rb_str_new(RSTRING_PTR(fname), ext-RSTRING_PTR(fname));
*featurep = tmp;
#ifdef DLEXT2
+ OBJ_FREEZE(tmp);
if (rb_find_file_ext(&tmp, loadable_ext+1)) {
*featurep = tmp;
*path = rb_find_file(tmp);
@@ -6077,41 +7327,44 @@ search_required(fname, featurep, path)
}
#else
rb_str_cat2(tmp, DLEXT);
- if (*path = rb_find_file(tmp)) {
+ OBJ_FREEZE(tmp);
+ if ((*path = rb_find_file(tmp)) != 0) {
return 's';
}
#endif
}
else if (IS_DLEXT(ext)) {
- if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
- if (*path = rb_find_file(fname)) return 's';
+ if (rb_feature_p(ftptr, ext, Qfalse)) {
+ if (ftptr) *path = rb_str_new2(ftptr);
+ return 's';
+ }
+ if ((*path = rb_find_file(fname)) != 0) return 's';
}
}
- if ((ext = rb_feature_p(ftptr, 0, Qfalse)) != 0) {
- return strcmp(ext, ".rb") == 0 ? 'r' : 's';
- }
tmp = fname;
- switch (rb_find_file_ext(&tmp, loadable_ext)) {
+ type = rb_find_file_ext(&tmp, loadable_ext);
+ *featurep = tmp;
+ switch (type) {
case 0:
- return 0;
-
- case 1:
- *featurep = tmp;
- *path = rb_find_file(tmp);
- return 'r';
+ type = rb_feature_p(ftptr, 0, Qfalse);
+ if (type && ftptr) *path = rb_str_new2(ftptr);
+ return type;
default:
- *featurep = tmp;
- *path = rb_find_file(tmp);
- return 's';
+ ext = strrchr(ftptr = RSTRING(tmp)->ptr, '.');
+ if (!rb_feature_p(ftptr, ext, !--type))
+ *path = rb_find_file(tmp);
+ else if (ftptr)
+ *path = rb_str_new2(ftptr);
}
+ return type ? 's' : 'r';
}
static void
load_failed(fname)
VALUE fname;
{
- rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
+ rb_raise(rb_eLoadError, "no such file to load -- %s", RSTRING(fname)->ptr);
}
VALUE
@@ -6120,6 +7373,7 @@ rb_require_safe(fname, safe)
int safe;
{
VALUE result = Qnil;
+ volatile VALUE errinfo = ruby_errinfo;
int state;
struct {
NODE *node;
@@ -6132,6 +7386,7 @@ rb_require_safe(fname, safe)
rb_check_safe_obj(fname);
}
StringValue(fname);
+ fname = rb_str_new4(fname);
saved.vmode = scope_vmode;
saved.node = ruby_current_node;
saved.func = ruby_frame->last_func;
@@ -6145,26 +7400,13 @@ rb_require_safe(fname, safe)
ruby_safe_level = safe;
found = search_required(fname, &feature, &path);
if (found) {
- if (!path) {
- load_wait(RSTRING(feature)->ptr);
+ if (!path || !(ftptr = load_lock(RSTRING_PTR(feature)))) {
result = Qfalse;
}
else {
ruby_safe_level = 0;
- rb_provide_feature(feature);
switch (found) {
case 'r':
- /* loading ruby library should be serialized. */
- if (!loading_tbl) {
- loading_tbl = st_init_strtable();
- }
- /* partial state */
- ftptr = ruby_strdup(RSTRING(feature)->ptr);
- st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread);
- if (feature == fname && !OBJ_FROZEN(feature)) {
- feature = rb_str_dup(feature);
- OBJ_FREEZE(feature);
- }
rb_load(path, 0);
break;
@@ -6178,6 +7420,7 @@ rb_require_safe(fname, safe)
rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
break;
}
+ rb_provide_feature(feature);
result = Qtrue;
}
}
@@ -6188,16 +7431,12 @@ rb_require_safe(fname, safe)
ruby_frame->last_func = saved.func;
SCOPE_SET(saved.vmode);
ruby_safe_level = saved.safe;
- if (ftptr) {
- if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */
- free(ftptr);
- }
- }
+ load_unlock(ftptr);
if (state) JUMP_TAG(state);
if (NIL_P(result)) {
load_failed(fname);
}
- ruby_errinfo = Qnil;
+ ruby_errinfo = errinfo;
return result;
}
@@ -6206,7 +7445,27 @@ VALUE
rb_require(fname)
const char *fname;
{
- return rb_require_safe(rb_str_new2(fname), ruby_safe_level);
+ VALUE fn = rb_str_new2(fname);
+ OBJ_FREEZE(fn);
+ return rb_require_safe(fn, ruby_safe_level);
+}
+
+void
+ruby_init_ext(name, init)
+ const char *name;
+ void (*init) _((void));
+{
+ ruby_current_node = 0;
+ ruby_sourcefile = rb_source_filename(name);
+ ruby_sourceline = 0;
+ ruby_frame->last_func = 0;
+ ruby_frame->orig_func = 0;
+ SCOPE_SET(SCOPE_PUBLIC);
+ if (load_lock(name)) {
+ (*init)();
+ rb_provide(name);
+ load_unlock(name);
+ }
}
static void
@@ -6234,6 +7493,16 @@ set_method_visibility(self, argc, argv, ex)
rb_clear_cache_by_class(self);
}
+/*
+ * call-seq:
+ * public => self
+ * public(symbol, ...) => self
+ *
+ * With no arguments, sets the default visibility for subsequently
+ * defined methods to public. With arguments, sets the named methods to
+ * have public visibility.
+ */
+
static VALUE
rb_mod_public(argc, argv, module)
int argc;
@@ -6250,6 +7519,16 @@ rb_mod_public(argc, argv, module)
return module;
}
+/*
+ * call-seq:
+ * protected => self
+ * protected(symbol, ...) => self
+ *
+ * With no arguments, sets the default visibility for subsequently
+ * defined methods to protected. With arguments, sets the named methods
+ * to have protected visibility.
+ */
+
static VALUE
rb_mod_protected(argc, argv, module)
int argc;
@@ -6266,6 +7545,25 @@ rb_mod_protected(argc, argv, module)
return module;
}
+/*
+ * call-seq:
+ * private => self
+ * private(symbol, ...) => self
+ *
+ * With no arguments, sets the default visibility for subsequently
+ * defined methods to private. With arguments, sets the named methods
+ * to have private visibility.
+ *
+ * module Mod
+ * def a() end
+ * def b() end
+ * private
+ * def c() end
+ * private :a
+ * end
+ * Mod.private_instance_methods #=> ["a", "c"]
+ */
+
static VALUE
rb_mod_private(argc, argv, module)
int argc;
@@ -6282,6 +7580,13 @@ rb_mod_private(argc, argv, module)
return module;
}
+/*
+ * call-seq:
+ * mod.public_class_method(symbol, ...) => mod
+ *
+ * Makes a list of existing class methods public.
+ */
+
static VALUE
rb_mod_public_method(argc, argv, obj)
int argc;
@@ -6292,6 +7597,22 @@ rb_mod_public_method(argc, argv, obj)
return obj;
}
+/*
+ * call-seq:
+ * mod.private_class_method(symbol, ...) => mod
+ *
+ * Makes existing class methods private. Often used to hide the default
+ * constructor <code>new</code>.
+ *
+ * class SimpleSingleton # Not thread safe
+ * private_class_method :new
+ * def SimpleSingleton.create(*args, &block)
+ * @me = new(*args, &block) if ! @me
+ * @me
+ * end
+ * end
+ */
+
static VALUE
rb_mod_private_method(argc, argv, obj)
int argc;
@@ -6302,6 +7623,16 @@ rb_mod_private_method(argc, argv, obj)
return obj;
}
+/*
+ * call-seq:
+ * public
+ * public(symbol, ...)
+ *
+ * With no arguments, sets the default visibility for subsequently
+ * defined methods to public. With arguments, sets the named methods to
+ * have public visibility.
+ */
+
static VALUE
top_public(argc, argv)
int argc;
@@ -6318,6 +7649,42 @@ top_private(argc, argv)
return rb_mod_private(argc, argv, rb_cObject);
}
+/*
+ * call-seq:
+ * module_function(symbol, ...) => self
+ *
+ * Creates module functions for the named methods. These functions may
+ * be called with the module as a receiver, and also become available
+ * as instance methods to classes that mix in the module. Module
+ * functions are copies of the original, and so may be changed
+ * independently. The instance-method versions are made private. If
+ * used with no arguments, subsequently defined methods become module
+ * functions.
+ *
+ * module Mod
+ * def one
+ * "This is one"
+ * end
+ * module_function :one
+ * end
+ * class Cls
+ * include Mod
+ * def callOne
+ * one
+ * end
+ * end
+ * Mod.one #=> "This is one"
+ * c = Cls.new
+ * c.callOne #=> "This is one"
+ * module Mod
+ * def one
+ * "This is the new one"
+ * end
+ * end
+ * Mod.one #=> "This is one"
+ * c.callOne #=> "This is the new one"
+ */
+
static VALUE
rb_mod_modfunc(argc, argv, module)
int argc;
@@ -6345,19 +7712,35 @@ rb_mod_modfunc(argc, argv, module)
id = rb_to_id(argv[i]);
for (;;) {
body = search_method(m, id, &m);
+ if (body == 0) {
+ body = search_method(rb_cObject, id, &m);
+ }
if (body == 0 || body->nd_body == 0) {
- rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
+ print_undef(module, id);
}
if (nd_type(body->nd_body) != NODE_ZSUPER) {
break; /* normal case: need not to follow 'super' link */
}
m = RCLASS(m)->super;
+ if (!m) break;
}
rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC);
}
return module;
}
+/*
+ * call-seq:
+ * append_features(mod) => mod
+ *
+ * When this module is included in another, Ruby calls
+ * <code>append_features</code> in this module, passing it the
+ * receiving module in _mod_. Ruby's default implementation is
+ * to add the constants, methods, and module variables of this module
+ * to _mod_ if this module has not already been added to
+ * _mod_ or one of its ancestors. See also <code>Module#include</code>.
+ */
+
static VALUE
rb_mod_append_features(module, include)
VALUE module, include;
@@ -6375,6 +7758,13 @@ rb_mod_append_features(module, include)
return module;
}
+/*
+ * call-seq:
+ * include(module, ...) => self
+ *
+ * Invokes <code>Module.append_features</code> on each parameter in turn.
+ */
+
static VALUE
rb_mod_include(argc, argv, module)
int argc;
@@ -6409,6 +7799,33 @@ rb_extend_object(obj, module)
rb_include_module(rb_singleton_class(obj), module);
}
+/*
+ * call-seq:
+ * extend_object(obj) => obj
+ *
+ * Extends the specified object by adding this module's constants and
+ * methods (which are added as singleton methods). This is the callback
+ * method used by <code>Object#extend</code>.
+ *
+ * module Picky
+ * def Picky.extend_object(o)
+ * if String === o
+ * puts "Can't add Picky to a String"
+ * else
+ * puts "Picky added to #{o.class}"
+ * super
+ * end
+ * end
+ * end
+ * (s = Array.new).extend Picky # Call Object.extend
+ * (s = "quick brown fox").extend Picky
+ *
+ * <em>produces:</em>
+ *
+ * Picky added to Array
+ * Can't add Picky to a String
+ */
+
static VALUE
rb_mod_extend_object(mod, obj)
VALUE mod, obj;
@@ -6417,6 +7834,31 @@ rb_mod_extend_object(mod, obj)
return obj;
}
+/*
+ * call-seq:
+ * obj.extend(module, ...) => obj
+ *
+ * Adds to _obj_ the instance methods from each module given as a
+ * parameter.
+ *
+ * module Mod
+ * def hello
+ * "Hello from Mod.\n"
+ * end
+ * end
+ *
+ * class Klass
+ * def hello
+ * "Hello from Klass.\n"
+ * end
+ * end
+ *
+ * k = Klass.new
+ * k.hello #=> "Hello from Klass.\n"
+ * k.extend(Mod) #=> #<Klass:0x401b3bc8>
+ * k.hello #=> "Hello from Mod.\n"
+ */
+
static VALUE
rb_obj_extend(argc, argv, obj)
int argc;
@@ -6426,7 +7868,7 @@ rb_obj_extend(argc, argv, obj)
int i;
if (argc == 0) {
- rb_raise(rb_eArgError, "wrong number of arguments(0 for 1)");
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
}
for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
while (argc--) {
@@ -6436,6 +7878,15 @@ rb_obj_extend(argc, argv, obj)
return obj;
}
+/*
+ * call-seq:
+ * include(module, ...) => self
+ *
+ * Invokes <code>Module.append_features</code>
+ * on each parameter in turn. Effectively adds the methods and constants
+ * in each module to the receiver.
+ */
+
static VALUE
top_include(argc, argv, self)
int argc;
@@ -6444,12 +7895,10 @@ top_include(argc, argv, self)
{
rb_secure(4);
if (ruby_wrapper) {
- rb_warn("main#include in the wrapped load is effective only for toplevel");
- return rb_obj_extend(argc, argv, self);
- }
- else {
- return rb_mod_include(argc, argv, rb_cObject);
+ rb_warning("main#include in the wrapped load is effective only in wrapper module");
+ return rb_mod_include(argc, argv, ruby_wrapper);
}
+ return rb_mod_include(argc, argv, rb_cObject);
}
VALUE rb_f_trace_var();
@@ -6486,6 +7935,19 @@ errat_setter(val, id, var)
set_backtrace(ruby_errinfo, val);
}
+/*
+ * call-seq:
+ * local_variables => array
+ *
+ * Returns the names of the current local variables.
+ *
+ * fred = 1
+ * for i in 1..10
+ * # ...
+ * end
+ * local_variables #=> ["fred", "i"]
+ */
+
static VALUE
rb_f_local_variables()
{
@@ -6592,6 +8054,27 @@ rb_f_END()
POP_FRAME();
}
+/*
+ * call-seq:
+ * at_exit { block } -> proc
+ *
+ * Converts _block_ to a +Proc+ object (and therefore
+ * binds it at the point of call) and registers it for execution when
+ * the program exits. If multiple handlers are registered, they are
+ * executed in reverse order of registration.
+ *
+ * def do_at_exit(str1)
+ * at_exit { print str1 }
+ * end
+ * at_exit { puts "cruel world" }
+ * do_at_exit("goodbye ")
+ * exit
+ *
+ * <em>produces:</em>
+ *
+ * goodbye cruel world
+ */
+
static VALUE
rb_f_at_exit()
{
@@ -6651,6 +8134,37 @@ rb_exec_end_proc()
ruby_safe_level = safe;
}
+/*
+ * call-seq:
+ * __method__ => symbol
+ *
+ * Returns the name of the current method as a Symbol.
+ * If called from inside of an aliased method it will return the original
+ * nonaliased name.
+ * If called outside of a method, it returns <code>nil</code>.
+ *
+ * def foo
+ * __method__
+ * end
+ * alias bar foo
+ *
+ * foo # => :foo
+ * bar # => :foo
+ *
+ */
+
+static VALUE
+rb_f_method_name()
+{
+ struct FRAME* prev = ruby_frame->prev;
+ if (prev && prev->orig_func) {
+ return ID2SYM(prev->orig_func);
+ }
+ else {
+ return Qnil;
+ }
+}
+
void
Init_eval()
{
@@ -6672,11 +8186,11 @@ Init_eval()
__id__ = rb_intern("__id__");
__send__ = rb_intern("__send__");
- rb_global_variable((VALUE*)&top_scope);
- rb_global_variable((VALUE*)&ruby_eval_tree_begin);
+ rb_global_variable((void *)&top_scope);
+ rb_global_variable((void *)&ruby_eval_tree_begin);
- rb_global_variable((VALUE*)&ruby_eval_tree);
- rb_global_variable((VALUE*)&ruby_dyna_vars);
+ rb_global_variable((void *)&ruby_eval_tree);
+ rb_global_variable((void *)&ruby_dyna_vars);
rb_define_virtual_variable("$@", errat_getter, errat_setter);
rb_define_hooked_variable("$!", &ruby_errinfo, 0, errinfo_setter);
@@ -6687,8 +8201,11 @@ Init_eval()
rb_define_global_function("method_missing", rb_method_missing, -1);
rb_define_global_function("loop", rb_f_loop, 0);
- rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1);
-
+ rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
+ respond_to = rb_intern("respond_to?");
+ rb_global_variable((void *)&basic_respond_to);
+ basic_respond_to = rb_method_node(rb_cObject, respond_to);
+
rb_define_global_function("raise", rb_f_raise, -1);
rb_define_global_function("fail", rb_f_raise, -1);
@@ -6701,12 +8218,15 @@ Init_eval()
rb_define_global_function("catch", rb_f_catch, 1);
rb_define_global_function("throw", rb_f_throw, -1);
- rb_define_global_function("global_variables", rb_f_global_variables, 0);
+ rb_define_global_function("global_variables", rb_f_global_variables, 0); /* in variable.c */
rb_define_global_function("local_variables", rb_f_local_variables, 0);
+ rb_define_global_function("__method__", rb_f_method_name, 0);
+
rb_define_method(rb_mKernel, "send", rb_f_send, -1);
rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
+ rb_define_method(rb_mKernel, "instance_exec", rb_obj_instance_exec, -1);
rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
@@ -6722,7 +8242,9 @@ Init_eval()
rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
+ rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
+ rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
rb_undef_method(rb_cClass, "module_function");
@@ -6740,8 +8262,8 @@ Init_eval()
rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
- rb_define_global_function("trace_var", rb_f_trace_var, -1);
- rb_define_global_function("untrace_var", rb_f_untrace_var, -1);
+ rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */
+ rb_define_global_function("untrace_var", rb_f_untrace_var, -1); /* in variable.c */
rb_define_global_function("set_trace_func", set_trace_func, 1);
rb_global_variable(&trace_func);
@@ -6749,6 +8271,20 @@ Init_eval()
rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
}
+/*
+ * call-seq:
+ * mod.autoload(name, filename) => nil
+ *
+ * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
+ * the first time that _name_ (which may be a <code>String</code> or
+ * a symbol) is accessed in the namespace of _mod_.
+ *
+ * module A
+ * end
+ * A.autoload(:B, "b")
+ * A::B.doit # autoloads "b"
+ */
+
static VALUE
rb_mod_autoload(mod, sym, file)
VALUE mod;
@@ -6762,6 +8298,19 @@ rb_mod_autoload(mod, sym, file)
return Qnil;
}
+/*
+ * call-seq:
+ * mod.autoload?(name) => String or nil
+ *
+ * Returns _filename_ to be loaded if _name_ is registered as
+ * +autoload+ in the namespace of _mod_.
+ *
+ * module A
+ * end
+ * A.autoload(:B, "b")
+ * A.autoload?(:B) # => "b"
+ */
+
static VALUE
rb_mod_autoload_p(mod, sym)
VALUE mod, sym;
@@ -6769,34 +8318,63 @@ rb_mod_autoload_p(mod, sym)
return rb_autoload_p(mod, rb_to_id(sym));
}
+/*
+ * call-seq:
+ * autoload(module, filename) => nil
+ *
+ * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
+ * the first time that _module_ (which may be a <code>String</code> or
+ * a symbol) is accessed.
+ *
+ * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
+ */
+
static VALUE
rb_f_autoload(obj, sym, file)
VALUE obj;
VALUE sym;
VALUE file;
{
+ if (NIL_P(ruby_cbase)) {
+ rb_raise(rb_eTypeError, "no class/module for autoload target");
+ }
return rb_mod_autoload(ruby_cbase, sym, file);
}
+/*
+ * call-seq:
+ * autoload(module, filename) => nil
+ *
+ * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
+ * the first time that _module_ (which may be a <code>String</code> or
+ * a symbol) is accessed.
+ *
+ * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
+ */
+
static VALUE
rb_f_autoload_p(obj, sym)
VALUE obj;
VALUE sym;
{
/* use ruby_cbase as same as rb_f_autoload. */
+ if (NIL_P(ruby_cbase)) {
+ return Qfalse;
+ }
return rb_mod_autoload_p(ruby_cbase, sym);
}
void
Init_load()
{
- rb_load_path = rb_ary_new();
rb_define_readonly_variable("$:", &rb_load_path);
rb_define_readonly_variable("$-I", &rb_load_path);
rb_define_readonly_variable("$LOAD_PATH", &rb_load_path);
+ rb_load_path = rb_ary_new();
- rb_features = rb_ary_new();
rb_define_readonly_variable("$\"", &rb_features);
+ rb_define_readonly_variable("$LOADED_FEATURES", &rb_features);
+ rb_features = rb_ary_new();
rb_define_global_function("load", rb_f_load, -1);
rb_define_global_function("require", rb_f_require, 1);
@@ -6806,11 +8384,8 @@ Init_load()
rb_define_global_function("autoload?", rb_f_autoload_p, 1);
rb_global_variable(&ruby_wrapper);
- ruby_dln_librefs = rb_ary_new();
rb_global_variable(&ruby_dln_librefs);
-
- /* not really a right place */
- rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
+ ruby_dln_librefs = rb_ary_new();
}
static void
@@ -6852,23 +8427,27 @@ blk_mark(data)
}
static void
-blk_free(data)
- struct BLOCK *data;
-{
+frame_free(frame)
struct FRAME *frame;
- void *tmp;
+{
+ struct FRAME *tmp;
- frame = data->frame.prev;
+ frame = frame->prev;
while (frame) {
- if (frame->argc > 0 && (frame->flags & FRAME_MALLOC))
- free(frame->argv);
tmp = frame;
frame = frame->prev;
free(tmp);
}
+}
+
+static void
+blk_free(data)
+ struct BLOCK *data;
+{
+ void *tmp;
+
while (data) {
- if (data->frame.argc > 0)
- free(data->frame.argv);
+ frame_free(&data->frame);
tmp = data;
data = data->prev;
free(tmp);
@@ -6876,6 +8455,23 @@ blk_free(data)
}
static void
+frame_dup(frame)
+ struct FRAME *frame;
+{
+ struct FRAME *tmp;
+
+ for (;;) {
+ frame->tmp = 0; /* should not preserve tmp */
+ if (!frame->prev) break;
+ tmp = ALLOC(struct FRAME);
+ *tmp = *frame->prev;
+ frame->prev = tmp;
+ frame = tmp;
+ }
+}
+
+
+static void
blk_copy_prev(block)
struct BLOCK *block;
{
@@ -6885,12 +8481,8 @@ blk_copy_prev(block)
while (block->prev) {
tmp = ALLOC_N(struct BLOCK, 1);
MEMCPY(tmp, block->prev, struct BLOCK, 1);
- if (tmp->frame.argc > 0) {
- tmp->frame.argv = ALLOC_N(VALUE, tmp->frame.argc);
- MEMCPY(tmp->frame.argv, block->prev->frame.argv, VALUE, tmp->frame.argc);
- tmp->frame.flags |= FRAME_MALLOC;
- }
scope_dup(tmp->scope);
+ frame_dup(&tmp->frame);
for (vars = tmp->dyna_vars; vars; vars = vars->next) {
if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
@@ -6902,29 +8494,26 @@ blk_copy_prev(block)
}
}
+
static void
-frame_dup(frame)
- struct FRAME *frame;
+blk_dup(dup, orig)
+ struct BLOCK *dup, *orig;
{
- VALUE *argv;
- struct FRAME *tmp;
+ MEMCPY(dup, orig, struct BLOCK, 1);
+ frame_dup(&dup->frame);
- for (;;) {
- if (frame->argc > 0) {
- argv = ALLOC_N(VALUE, frame->argc);
- MEMCPY(argv, frame->argv, VALUE, frame->argc);
- frame->argv = argv;
- frame->flags |= FRAME_MALLOC;
- }
- frame->tmp = 0; /* should not preserve tmp */
- if (!frame->prev) break;
- tmp = ALLOC(struct FRAME);
- *tmp = *frame->prev;
- frame->prev = tmp;
- frame = tmp;
+ if (dup->iter) {
+ blk_copy_prev(dup);
+ }
+ else {
+ dup->prev = 0;
}
}
+/*
+ * MISSING: documentation
+ */
+
static VALUE
proc_clone(self)
VALUE self;
@@ -6935,19 +8524,67 @@ proc_clone(self)
Data_Get_Struct(self, struct BLOCK, orig);
bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data);
CLONESETUP(bind, self);
- MEMCPY(data, orig, struct BLOCK, 1);
- frame_dup(&data->frame);
+ blk_dup(data, orig);
- if (data->iter) {
- blk_copy_prev(data);
- }
- else {
- data->prev = 0;
- }
+ return bind;
+}
+
+/*
+ * MISSING: documentation
+ */
+
+#define PROC_TSHIFT (FL_USHIFT+1)
+#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3)
+#define PROC_TMAX (PROC_TMASK >> PROC_TSHIFT)
+
+static int proc_get_safe_level(VALUE);
+
+static VALUE
+proc_dup(self)
+ VALUE self;
+{
+ struct BLOCK *orig, *data;
+ VALUE bind;
+ int safe = proc_get_safe_level(self);
+
+ Data_Get_Struct(self, struct BLOCK, orig);
+ bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data);
+ blk_dup(data, orig);
+ if (safe > PROC_TMAX) safe = PROC_TMAX;
+ FL_SET(bind, (safe << PROC_TSHIFT) & PROC_TMASK);
return bind;
}
+VALUE
+rb_block_dup(self, klass, cref)
+ VALUE self, klass, cref;
+{
+ struct BLOCK *block;
+ VALUE obj = proc_dup(self);
+ Data_Get_Struct(obj, struct BLOCK, block);
+ block->klass = klass;
+ block->cref = NEW_NODE(nd_type(block->cref), cref, block->cref->u2.node,
+ block->cref->u3.node);
+ return obj;
+}
+
+/*
+ * call-seq:
+ * binding -> a_binding
+ *
+ * Returns a +Binding+ object, describing the variable and
+ * method bindings at the point of call. This object can be used when
+ * calling +eval+ to execute the evaluated command in this
+ * environment. Also see the description of class +Binding+.
+ *
+ * def getBinding(param)
+ * return binding
+ * end
+ * b = getBinding("hello")
+ * eval("param", b) #=> "hello"
+ */
+
static VALUE
rb_f_binding(self)
VALUE self;
@@ -6967,6 +8604,7 @@ rb_f_binding(self)
if (ruby_frame->prev) {
data->frame.last_func = ruby_frame->prev->last_func;
data->frame.last_class = ruby_frame->prev->last_class;
+ data->frame.orig_func = ruby_frame->prev->orig_func;
}
if (data->iter) {
@@ -6988,14 +8626,44 @@ rb_f_binding(self)
return bind;
}
-#define PROC_TSHIFT (FL_USHIFT+1)
-#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3)
+/*
+ * call-seq:
+ * binding.eval(string [, filename [,lineno]]) => obj
+ *
+ * Evaluates the Ruby expression(s) in <em>string</em>, in the
+ * <em>binding</em>'s context. If the optional <em>filename</em> and
+ * <em>lineno</em> parameters are present, they will be used when
+ * reporting syntax errors.
+ *
+ * def getBinding(param)
+ * return binding
+ * end
+ * b = getBinding("hello")
+ * b.eval("param") #=> "hello"
+ */
+
+static VALUE
+bind_eval(argc, argv, bindval)
+ int argc;
+ VALUE *argv;
+ VALUE bindval;
+{
+ VALUE args[4];
+
+ rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]);
+ args[1] = bindval;
+ return rb_f_eval(argc+1, args, Qnil /* self will be searched in eval */);
+}
+
+#define SAFE_LEVEL_MAX PROC_TMASK
static void
proc_save_safe_level(data)
VALUE data;
{
- FL_SET(data, (ruby_safe_level << PROC_TSHIFT) & PROC_TMASK);
+ int safe = ruby_safe_level;
+ if (safe > PROC_TMAX) safe = PROC_TMAX;
+ FL_SET(data, (safe << PROC_TSHIFT) & PROC_TMASK);
}
static int
@@ -7037,6 +8705,7 @@ proc_alloc(klass, proc)
data->orig_thread = rb_thread_current();
data->wrapper = ruby_wrapper;
data->iter = data->prev?Qtrue:Qfalse;
+ data->block_obj = block;
frame_dup(&data->frame);
if (data->iter) {
blk_copy_prev(data);
@@ -7063,6 +8732,23 @@ proc_alloc(klass, proc)
return block;
}
+/*
+ * call-seq:
+ * Proc.new {|...| block } => a_proc
+ * Proc.new => a_proc
+ *
+ * Creates a new <code>Proc</code> object, bound to the current
+ * context. <code>Proc::new</code> may be called without a block only
+ * within a method with an attached block, in which case that block is
+ * converted to the <code>Proc</code> object.
+ *
+ * def proc_from
+ * Proc.new
+ * end
+ * proc = proc_from { "hello" }
+ * proc.call #=> "hello"
+ */
+
static VALUE
proc_s_new(argc, argv, klass)
int argc;
@@ -7088,6 +8774,15 @@ rb_f_lambda()
return proc_alloc(rb_cProc, Qtrue);
}
+/*
+ * call-seq:
+ * proc { |...| block } => a_proc
+ * lambda { |...| block } => a_proc
+ *
+ * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
+ * check the number of parameters passed when called.
+ */
+
static VALUE
proc_lambda()
{
@@ -7117,72 +8812,81 @@ proc_invoke(proc, args, self, klass)
struct BLOCK *data;
volatile VALUE result = Qundef;
int state;
- volatile int orphan;
volatile int safe = ruby_safe_level;
volatile VALUE old_wrapper = ruby_wrapper;
- struct RVarmap * volatile old_dvars = ruby_dyna_vars;
volatile int pcall, avalue = Qtrue;
+ volatile VALUE tmp = args;
+ VALUE bvar = Qnil;
if (rb_block_given_p() && ruby_frame->last_func) {
- rb_warning("block for %s#%s is useless",
- rb_obj_classname(proc),
- rb_id2name(ruby_frame->last_func));
+ if (klass != ruby_frame->last_class)
+ klass = rb_obj_class(proc);
+ bvar = rb_block_proc();
}
Data_Get_Struct(proc, struct BLOCK, data);
- orphan = block_orphan(data);
- pcall = data->flags & BLOCK_LAMBDA ? YIELD_PROC_CALL : 0;
+ pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0;
if (!pcall && RARRAY(args)->len == 1) {
avalue = Qfalse;
args = RARRAY(args)->ptr[0];
}
+ PUSH_VARS();
ruby_wrapper = data->wrapper;
ruby_dyna_vars = data->dyna_vars;
/* PUSH BLOCK from data */
old_block = ruby_block;
_block = *data;
+ _block.block_obj = bvar;
if (self != Qundef) _block.frame.self = self;
if (klass) _block.frame.last_class = klass;
+ _block.frame.argc = RARRAY(tmp)->len;
+ _block.frame.flags = ruby_frame->flags;
+ if (_block.frame.argc && DMETHOD_P()) {
+ NEWOBJ(scope, struct SCOPE);
+ OBJSETUP(scope, tmp, T_SCOPE);
+ scope->local_tbl = _block.scope->local_tbl;
+ scope->local_vars = _block.scope->local_vars;
+ scope->flags |= SCOPE_CLONE;
+ _block.scope = scope;
+ }
+ /* modify current frame */
ruby_block = &_block;
-
PUSH_ITER(ITER_CUR);
ruby_frame->iter = ITER_CUR;
- PUSH_TAG((pcall || orphan) ? PROT_PCALL : PROT_CALL);
+ PUSH_TAG(pcall ? PROT_LAMBDA : PROT_NONE);
state = EXEC_TAG();
if (state == 0) {
proc_set_safe_level(proc);
- result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0, pcall, avalue);
+ result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0,
+ pcall | YIELD_PROC_CALL, avalue);
}
- else if (pcall || orphan || TAG_DST()) {
+ else if (TAG_DST()) {
result = prot_tag->retval;
}
POP_TAG();
POP_ITER();
ruby_block = old_block;
ruby_wrapper = old_wrapper;
- ruby_dyna_vars = old_dvars;
+ POP_VARS();
ruby_safe_level = safe;
switch (state) {
case 0:
break;
case TAG_RETRY:
- if (pcall || orphan) {
- localjump_error("retry from proc-closure", Qnil, state);
- }
- /* fall through */
+ proc_jump_error(TAG_RETRY, Qnil); /* xxx */
+ JUMP_TAG(state);
+ break;
+ case TAG_NEXT:
case TAG_BREAK:
- case TAG_RETURN:
- if (pcall) break;
- if (orphan) { /* orphan block */
- char mesg[32];
- snprintf(mesg, sizeof mesg, "%s from proc-closure",
- state == TAG_BREAK ? "break" : "return");
- localjump_error(mesg, result, state);
+ if (!pcall && result != Qundef) {
+ proc_jump_error(state, result);
}
+ case TAG_RETURN:
if (result != Qundef) {
- localjump_destination(state, result);
+ if (pcall) break;
+ return_jump(result);
}
default:
JUMP_TAG(state);
@@ -7190,8 +8894,42 @@ proc_invoke(proc, args, self, klass)
return result;
}
-static VALUE
-proc_call(proc, args)
+/* CHECKME: are the argument checking semantics correct? */
+
+/*
+ * call-seq:
+ * prc.call(params,...) => obj
+ * prc[params,...] => obj
+ *
+ * Invokes the block, setting the block's parameters to the values in
+ * <i>params</i> using something close to method calling semantics.
+ * Generates a warning if multiple values are passed to a proc that
+ * expects just one (previously this silently converted the parameters
+ * to an array).
+ *
+ * For procs created using <code>Kernel.proc</code>, generates an
+ * error if the wrong number of parameters
+ * are passed to a proc with multiple parameters. For procs created using
+ * <code>Proc.new</code>, extra parameters are silently discarded.
+ *
+ * Returns the value of the last expression evaluated in the block. See
+ * also <code>Proc#yield</code>.
+ *
+ * a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
+ * a_proc.call(9, 1, 2, 3) #=> [9, 18, 27]
+ * a_proc[9, 1, 2, 3] #=> [9, 18, 27]
+ * a_proc = Proc.new {|a,b| a}
+ * a_proc.call(1,2,3)
+ *
+ * <em>produces:</em>
+ *
+ * prog.rb:5: wrong number of arguments (3 for 2) (ArgumentError)
+ * from prog.rb:4:in `call'
+ * from prog.rb:5
+ */
+
+VALUE
+rb_proc_call(proc, args)
VALUE proc, args; /* OK */
{
return proc_invoke(proc, args, Qundef, 0);
@@ -7200,39 +8938,73 @@ proc_call(proc, args)
static VALUE bmcall _((VALUE, VALUE));
static VALUE method_arity _((VALUE));
+/*
+ * call-seq:
+ * prc.arity -> fixnum
+ *
+ * Returns the number of arguments that would not be ignored. If the block
+ * is declared to take no arguments, returns 0. If the block is known
+ * to take exactly n arguments, returns n. If the block has optional
+ * arguments, return -n-1, where n is the number of mandatory
+ * arguments. A <code>proc</code> with no argument declarations
+ * is the same a block declaring <code>||</code> as its arguments.
+ *
+ * Proc.new {}.arity #=> 0
+ * Proc.new {||}.arity #=> 0
+ * Proc.new {|a|}.arity #=> 1
+ * Proc.new {|a,b|}.arity #=> 2
+ * Proc.new {|a,b,c|}.arity #=> 3
+ * Proc.new {|*a|}.arity #=> -1
+ * Proc.new {|a,*b|}.arity #=> -2
+ */
+
static VALUE
proc_arity(proc)
VALUE proc;
{
struct BLOCK *data;
- NODE *list;
+ NODE *var, *list;
int n;
Data_Get_Struct(proc, struct BLOCK, data);
- if (data->var == 0) {
+ var = data->var;
+ if (var == 0) {
if (data->body && nd_type(data->body) == NODE_IFUNC &&
data->body->nd_cfnc == bmcall) {
return method_arity(data->body->nd_tval);
}
return INT2FIX(-1);
}
- if (data->var == (NODE*)1) return INT2FIX(0);
- if (data->var == (NODE*)2) return INT2FIX(0);
- switch (nd_type(data->var)) {
+ if (var == (NODE*)1) return INT2FIX(0);
+ if (var == (NODE*)2) return INT2FIX(0);
+ if (nd_type(var) == NODE_BLOCK_ARG) {
+ var = var->nd_args;
+ if (var == (NODE*)1) return INT2FIX(0);
+ if (var == (NODE*)2) return INT2FIX(0);
+ }
+ switch (nd_type(var)) {
default:
return INT2FIX(1);
case NODE_MASGN:
- list = data->var->nd_head;
+ list = var->nd_head;
n = 0;
while (list) {
n++;
list = list->nd_next;
}
- if (data->var->nd_args) return INT2FIX(-n-1);
+ if (var->nd_args) return INT2FIX(-n-1);
return INT2FIX(n);
}
}
+/*
+ * call-seq:
+ * prc == other_proc => true or false
+ *
+ * Return <code>true</code> if <i>prc</i> is the same object as
+ * <i>other_proc</i>, or if they are both procs with the same body.
+ */
+
static VALUE
proc_eq(self, other)
VALUE self, other;
@@ -7245,18 +9017,31 @@ proc_eq(self, other)
if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse;
Data_Get_Struct(self, struct BLOCK, data);
Data_Get_Struct(other, struct BLOCK, data2);
- if (data->body == data2->body) return Qtrue;
- return Qfalse;
+ if (data->body != data2->body) return Qfalse;
+ if (data->var != data2->var) return Qfalse;
+ if (data->scope != data2->scope) return Qfalse;
+ if (data->dyna_vars != data2->dyna_vars) return Qfalse;
+ if (data->flags != data2->flags) return Qfalse;
+
+ return Qtrue;
}
+/*
+ * call-seq:
+ * prc.to_s => string
+ *
+ * Shows the unique identifier for this proc, along with
+ * an indication of where the proc was defined.
+ */
+
static VALUE
-proc_to_s(self, other)
- VALUE self, other;
+proc_to_s(self)
+ VALUE self;
{
struct BLOCK *data;
NODE *node;
- char *cname = rb_obj_classname(self);
- const int w = (SIZEOF_LONG * CHAR_BIT) / 4;
+ const char *cname = rb_obj_classname(self);
+ const int w = (sizeof(VALUE) * CHAR_BIT) / 4;
long len = strlen(cname)+6+w; /* 6:tags 16:addr */
VALUE str;
@@ -7264,12 +9049,14 @@ proc_to_s(self, other)
if ((node = data->frame.node) || (node = data->body)) {
len += strlen(node->nd_file) + 2 + (SIZEOF_LONG*CHAR_BIT-NODE_LSHIFT)/3;
str = rb_str_new(0, len);
- sprintf(RSTRING(str)->ptr, "#<%s:0x%.*lx@%s:%d>", cname, w, (VALUE)data->body,
- node->nd_file, nd_line(node));
+ snprintf(RSTRING(str)->ptr, len+1,
+ "#<%s:0x%.*lx@%s:%d>", cname, w, (VALUE)data->body,
+ node->nd_file, nd_line(node));
}
else {
str = rb_str_new(0, len);
- sprintf(RSTRING(str)->ptr, "#<%s:0x%.*lx>", cname, w, (VALUE)data->body);
+ snprintf(RSTRING(str)->ptr, len+1,
+ "#<%s:0x%.*lx>", cname, w, (VALUE)data->body);
}
RSTRING(str)->len = strlen(RSTRING(str)->ptr);
if (OBJ_TAINTED(self)) OBJ_TAINT(str);
@@ -7277,6 +9064,15 @@ proc_to_s(self, other)
return str;
}
+/*
+ * call-seq:
+ * prc.to_proc -> prc
+ *
+ * Part of the protocol for converting objects to <code>Proc</code>
+ * objects. Instances of class <code>Proc</code> simply return
+ * themselves.
+ */
+
static VALUE
proc_to_self(self)
VALUE self;
@@ -7284,6 +9080,23 @@ proc_to_self(self)
return self;
}
+/*
+ * call-seq:
+ * prc.binding => binding
+ *
+ * Returns the binding associated with <i>prc</i>. Note that
+ * <code>Kernel#eval</code> accepts either a <code>Proc</code> or a
+ * <code>Binding</code> object as its second parameter.
+ *
+ * def fred(param)
+ * proc {}
+ * end
+ *
+ * b = fred(99)
+ * eval("param", b.binding) #=> 99
+ * eval("param", b) #=> 99
+ */
+
static VALUE
proc_binding(proc)
VALUE proc;
@@ -7336,14 +9149,13 @@ block_pass(self, node)
proc = b;
}
- if (ruby_safe_level >= 1 && OBJ_TAINTED(proc)) {
- if (ruby_safe_level > proc_get_safe_level(proc)) {
- rb_raise(rb_eSecurityError, "Insecure: tainted block value");
- }
+ if (ruby_safe_level >= 1 && OBJ_TAINTED(proc) &&
+ ruby_safe_level > proc_get_safe_level(proc)) {
+ rb_raise(rb_eSecurityError, "Insecure: tainted block value");
}
if (ruby_block && ruby_block->block_obj == proc) {
- PUSH_ITER(ITER_PRE);
+ PUSH_ITER(ITER_PAS);
result = rb_eval(self, node->nd_iter);
POP_ITER();
return result;
@@ -7356,12 +9168,13 @@ block_pass(self, node)
old_block = ruby_block;
_block = *data;
_block.outer = ruby_block;
+ if (orphan) _block.uniq = block_unique++;
ruby_block = &_block;
PUSH_ITER(ITER_PRE);
if (ruby_frame->iter == ITER_NOT)
ruby_frame->iter = ITER_PRE;
- PUSH_TAG(PROT_ITER);
+ PUSH_TAG(PROT_LOOP);
state = EXEC_TAG();
if (state == 0) {
retry:
@@ -7388,7 +9201,7 @@ block_pass(self, node)
break;
case TAG_RETURN:
if (orphan) {
- localjump_error("return from proc-closure", prot_tag->retval, state);
+ proc_jump_error(state, prot_tag->retval);
}
default:
JUMP_TAG(state);
@@ -7401,6 +9214,7 @@ struct METHOD {
VALUE klass, rklass;
VALUE recv;
ID id, oid;
+ int safe_level;
NODE *body;
};
@@ -7448,11 +9262,46 @@ mnew(klass, obj, id, mklass)
data->body = body;
data->rklass = rklass;
data->oid = oid;
+ data->safe_level = NOEX_WITH_SAFE(noex);
OBJ_INFECT(method, klass);
return method;
}
+
+/**********************************************************************
+ *
+ * Document-class : Method
+ *
+ * Method objects are created by <code>Object#method</code>, and are
+ * associated with a particular object (not just with a class). They
+ * may be used to invoke the method within the object, and as a block
+ * associated with an iterator. They may also be unbound from one
+ * object (creating an <code>UnboundMethod</code>) and bound to
+ * another.
+ *
+ * class Thing
+ * def square(n)
+ * n*n
+ * end
+ * end
+ * thing = Thing.new
+ * meth = thing.method(:square)
+ *
+ * meth.call(9) #=> 81
+ * [ 1, 2, 3 ].collect(&meth) #=> [1, 4, 9]
+ *
+ */
+
+/*
+ * call-seq:
+ * meth == other_meth => true or false
+ *
+ * Two method objects are equal if that are bound to the same
+ * object and contain the same body.
+ */
+
+
static VALUE
method_eq(method, other)
VALUE method, other;
@@ -7474,6 +9323,15 @@ method_eq(method, other)
return Qtrue;
}
+/*
+ * call-seq:
+ * meth.unbind => unbound_method
+ *
+ * Dissociates <i>meth</i> from it's current receiver. The resulting
+ * <code>UnboundMethod</code> can subsequently be bound to a new object
+ * of the same class (see <code>UnboundMethod</code>).
+ */
+
static VALUE
method_unbind(obj)
VALUE obj;
@@ -7494,7 +9352,86 @@ method_unbind(obj)
return method;
}
+/*
+ * call-seq:
+ * meth.receiver => object
+ *
+ * Returns the bound receiver of the method object.
+ */
+
+static VALUE
+method_receiver(obj)
+ VALUE obj;
+{
+ struct METHOD *data;
+
+ Data_Get_Struct(obj, struct METHOD, data);
+ return data->recv;
+}
+
+/*
+ * call-seq:
+ * meth.name => string
+ *
+ * Returns the name of the method.
+ */
+
+static VALUE
+method_name(obj)
+ VALUE obj;
+{
+ struct METHOD *data;
+
+ Data_Get_Struct(obj, struct METHOD, data);
+ return rb_str_new2(rb_id2name(data->oid));
+}
+
+/*
+ * call-seq:
+ * meth.owner => class_or_module
+ *
+ * Returns the class or module that defines the method.
+ */
+
static VALUE
+method_owner(obj)
+ VALUE obj;
+{
+ struct METHOD *data;
+
+ Data_Get_Struct(obj, struct METHOD, data);
+ return data->klass;
+}
+
+/*
+ * call-seq:
+ * obj.method(sym) => method
+ *
+ * Looks up the named method as a receiver in <i>obj</i>, returning a
+ * <code>Method</code> object (or raising <code>NameError</code>). The
+ * <code>Method</code> object acts as a closure in <i>obj</i>'s object
+ * instance, so instance variables and the value of <code>self</code>
+ * remain available.
+ *
+ * class Demo
+ * def initialize(n)
+ * @iv = n
+ * end
+ * def hello()
+ * "Hello, @iv = #{@iv}"
+ * end
+ * end
+ *
+ * k = Demo.new(99)
+ * m = k.method(:hello)
+ * m.call #=> "Hello, @iv = 99"
+ *
+ * l = Demo.new('Fred')
+ * m = l.method("hello")
+ * m.call #=> "Hello, @iv = Fred"
+ */
+
+VALUE
rb_obj_method(obj, vid)
VALUE obj;
VALUE vid;
@@ -7502,6 +9439,38 @@ rb_obj_method(obj, vid)
return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod);
}
+/*
+ * call-seq:
+ * mod.instance_method(symbol) => unbound_method
+ *
+ * Returns an +UnboundMethod+ representing the given
+ * instance method in _mod_.
+ *
+ * class Interpreter
+ * def do_a() print "there, "; end
+ * def do_d() print "Hello "; end
+ * def do_e() print "!\n"; end
+ * def do_v() print "Dave"; end
+ * Dispatcher = {
+ * ?a => instance_method(:do_a),
+ * ?d => instance_method(:do_d),
+ * ?e => instance_method(:do_e),
+ * ?v => instance_method(:do_v)
+ * }
+ * def interpret(string)
+ * string.each_byte {|b| Dispatcher[b].bind(self).call }
+ * end
+ * end
+ *
+ *
+ * interpreter = Interpreter.new
+ * interpreter.interpret('dave')
+ *
+ * <em>produces:</em>
+ *
+ * Hello there, Dave!
+ */
+
static VALUE
rb_mod_method(mod, vid)
VALUE mod;
@@ -7510,6 +9479,10 @@ rb_mod_method(mod, vid)
return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod);
}
+/*
+ * MISSING: documentation
+ */
+
static VALUE
method_clone(self)
VALUE self;
@@ -7525,6 +9498,42 @@ method_clone(self)
return clone;
}
+VALUE
+rb_method_dup(self, klass, cref)
+ VALUE self;
+ VALUE klass;
+ VALUE cref;
+{
+ VALUE clone;
+ struct METHOD *orig, *data;
+
+ Data_Get_Struct(self, struct METHOD, orig);
+ clone = Data_Make_Struct(CLASS_OF(self),struct METHOD, bm_mark, free, data);
+ *data = *orig;
+ data->rklass = klass;
+ if (data->body->nd_rval) {
+ NODE *tmp = NEW_NODE(nd_type(data->body->u2.node), cref,
+ data->body->u2.node->u2.node,
+ data->body->u2.node->u3.node);
+ data->body = NEW_NODE(nd_type(data->body), data->body->u1.node, tmp,
+ data->body->u3.node);
+ }
+ return clone;
+}
+
+/*
+ * call-seq:
+ * meth.call(args, ...) => obj
+ * meth[args, ...] => obj
+ *
+ * Invokes the <i>meth</i> with the specified arguments, returning the
+ * method's return value.
+ *
+ * m = 12.method("+")
+ * m.call(3) #=> 15
+ * m.call(20) #=> 32
+ */
+
static VALUE
method_call(argc, argv, method)
int argc;
@@ -7533,44 +9542,136 @@ method_call(argc, argv, method)
{
VALUE result = Qnil; /* OK */
struct METHOD *data;
- int state;
- volatile int safe = ruby_safe_level;
+ int safe;
Data_Get_Struct(method, struct METHOD, data);
if (data->recv == Qundef) {
- rb_raise(rb_eTypeError, "you cannot call unbound method; bind first");
+ rb_raise(rb_eTypeError, "can't call unbound method; bind first");
}
- PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
- PUSH_TAG(PROT_NONE);
- if (OBJ_TAINTED(method) && ruby_safe_level < 4) {
- ruby_safe_level = 4;
+ if (OBJ_TAINTED(method)) {
+ safe = NOEX_WITH(data->safe_level, 4)|NOEX_TAINTED;
}
- if ((state = EXEC_TAG()) == 0) {
- result = rb_call0(data->klass,data->recv,data->id,data->oid,argc,argv,data->body,0);
+ else {
+ safe = data->safe_level;
}
- POP_TAG();
+ PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
+ result = rb_call0(data->klass,data->recv,data->id,data->oid,argc,argv,data->body,safe);
POP_ITER();
- ruby_safe_level = safe;
- if (state) JUMP_TAG(state);
return result;
}
+/**********************************************************************
+ *
+ * Document-class: UnboundMethod
+ *
+ * Ruby supports two forms of objectified methods. Class
+ * <code>Method</code> is used to represent methods that are associated
+ * with a particular object: these method objects are bound to that
+ * object. Bound method objects for an object can be created using
+ * <code>Object#method</code>.
+ *
+ * Ruby also supports unbound methods; methods objects that are not
+ * associated with a particular object. These can be created either by
+ * calling <code>Module#instance_method</code> or by calling
+ * <code>unbind</code> on a bound method object. The result of both of
+ * these is an <code>UnboundMethod</code> object.
+ *
+ * Unbound methods can only be called after they are bound to an
+ * object. That object must be be a kind_of? the method's original
+ * class.
+ *
+ * class Square
+ * def area
+ * @side * @side
+ * end
+ * def initialize(side)
+ * @side = side
+ * end
+ * end
+ *
+ * area_un = Square.instance_method(:area)
+ *
+ * s = Square.new(12)
+ * area = area_un.bind(s)
+ * area.call #=> 144
+ *
+ * Unbound methods are a reference to the method at the time it was
+ * objectified: subsequent changes to the underlying class will not
+ * affect the unbound method.
+ *
+ * class Test
+ * def test
+ * :original
+ * end
+ * end
+ * um = Test.instance_method(:test)
+ * class Test
+ * def test
+ * :modified
+ * end
+ * end
+ * t = Test.new
+ * t.test #=> :modified
+ * um.bind(t).call #=> :original
+ *
+ */
+
+/*
+ * call-seq:
+ * umeth.bind(obj) -> method
+ *
+ * Bind <i>umeth</i> to <i>obj</i>. If <code>Klass</code> was the class
+ * from which <i>umeth</i> was obtained,
+ * <code>obj.kind_of?(Klass)</code> must be true.
+ *
+ * class A
+ * def test
+ * puts "In test, class = #{self.class}"
+ * end
+ * end
+ * class B < A
+ * end
+ * class C < B
+ * end
+ *
+ *
+ * um = B.instance_method(:test)
+ * bm = um.bind(C.new)
+ * bm.call
+ * bm = um.bind(B.new)
+ * bm.call
+ * bm = um.bind(A.new)
+ * bm.call
+ *
+ * <em>produces:</em>
+ *
+ * In test, class = C
+ * In test, class = B
+ * prog.rb:16:in `bind': bind argument must be an instance of B (TypeError)
+ * from prog.rb:16
+ */
+
static VALUE
umethod_bind(method, recv)
VALUE method, recv;
{
struct METHOD *data, *bound;
+ VALUE rklass = CLASS_OF(recv);
Data_Get_Struct(method, struct METHOD, data);
- if (data->rklass != CLASS_OF(recv)) {
+ if (data->rklass != rklass) {
if (FL_TEST(data->rklass, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "singleton method called for a different object");
+ rb_raise(rb_eTypeError, "singleton method bound for a different object");
}
- if (FL_TEST(CLASS_OF(recv), FL_SINGLETON) &&
- st_lookup(RCLASS(CLASS_OF(recv))->m_tbl, data->oid, 0)) {
- rb_raise(rb_eTypeError, "method `%s' overridden", rb_id2name(data->oid));
+ if (TYPE(data->rklass) == T_MODULE) {
+ st_table *m_tbl = RCLASS(data->rklass)->m_tbl;
+ while (RCLASS(rklass)->m_tbl != m_tbl) {
+ rklass = RCLASS(rklass)->super;
+ if (!rklass) goto not_instace;
+ }
}
- if(!rb_obj_is_kind_of(recv, data->rklass)) {
+ else if (!rb_obj_is_kind_of(recv, data->rklass)) {
+ not_instace:
rb_raise(rb_eTypeError, "bind argument must be an instance of %s",
rb_class2name(data->rklass));
}
@@ -7579,11 +9680,44 @@ umethod_bind(method, recv)
method = Data_Make_Struct(rb_cMethod,struct METHOD,bm_mark,free,bound);
*bound = *data;
bound->recv = recv;
- bound->rklass = CLASS_OF(recv);
+ bound->rklass = rklass;
return method;
}
+/*
+ * call-seq:
+ * meth.arity => fixnum
+ *
+ * Returns an indication of the number of arguments accepted by a
+ * method. Returns a nonnegative integer for methods that take a fixed
+ * number of arguments. For Ruby methods that take a variable number of
+ * arguments, returns -n-1, where n is the number of required
+ * arguments. For methods written in C, returns -1 if the call takes a
+ * variable number of arguments.
+ *
+ * class C
+ * def one; end
+ * def two(a); end
+ * def three(*a); end
+ * def four(a, b); end
+ * def five(a, b, *c); end
+ * def six(a, b, *c, &d); end
+ * end
+ * c = C.new
+ * c.method(:one).arity #=> 0
+ * c.method(:two).arity #=> 1
+ * c.method(:three).arity #=> -1
+ * c.method(:four).arity #=> 2
+ * c.method(:five).arity #=> -3
+ * c.method(:six).arity #=> -3
+ *
+ * "cat".method(:size).arity #=> 0
+ * "cat".method(:replace).arity #=> 1
+ * "cat".method(:squeeze).arity #=> -1
+ * "cat".method(:count).arity #=> -1
+ */
+
static VALUE
method_arity(method)
VALUE method;
@@ -7606,20 +9740,33 @@ method_arity(method)
case NODE_IVAR:
return INT2FIX(0);
case NODE_BMETHOD:
+ return proc_arity(body->nd_cval);
case NODE_DMETHOD:
- return proc_arity(body->nd_cval);
- default:
+ return method_arity(body->nd_cval);
+ case NODE_SCOPE:
body = body->nd_next; /* skip NODE_SCOPE */
if (nd_type(body) == NODE_BLOCK)
body = body->nd_head;
if (!body) return INT2FIX(0);
n = body->nd_cnt;
- if (body->nd_opt || body->nd_rest != -1)
+ if (body->nd_opt || body->nd_rest)
n = -n-1;
return INT2FIX(n);
- }
+ default:
+ rb_raise(rb_eArgError, "invalid node 0x%x", nd_type(body));
+ }
}
+/*
+ * call-seq:
+ * meth.to_s => string
+ * meth.inspect => string
+ *
+ * Show the name of the underlying method.
+ *
+ * "cat".method(:count).inspect #=> "#<Method: String#count>"
+ */
+
static VALUE
method_inspect(method)
VALUE method;
@@ -7627,7 +9774,7 @@ method_inspect(method)
struct METHOD *data;
VALUE str;
const char *s;
- char *sharp = "#";
+ const char *sharp = "#";
Data_Get_Struct(method, struct METHOD, data);
str = rb_str_buf_new2("#<");
@@ -7689,9 +9836,12 @@ bmcall(args, method)
VALUE args, method;
{
volatile VALUE a;
+ VALUE ret;
a = svalue_to_avalue(args);
- return method_call(RARRAY(a)->len, RARRAY(a)->ptr, method);
+ ret = method_call(RARRAY(a)->len, RARRAY(a)->ptr, method);
+ a = Qnil; /* prevent tail call */
+ return ret;
}
VALUE
@@ -7703,10 +9853,18 @@ rb_proc_new(func, val)
VALUE proc = rb_iterate((VALUE(*)_((VALUE)))mproc, 0, func, val);
Data_Get_Struct(proc, struct BLOCK, data);
- data->body->nd_state = YIELD_FUNC_AVALUE;
+ data->body->nd_state = YIELD_FUNC_LAMBDA;
+ data->flags |= BLOCK_LAMBDA;
return proc;
}
+/*
+ * call-seq:
+ * meth.to_proc => prc
+ *
+ * Returns a <code>Proc</code> object corresponding to this method.
+ */
+
static VALUE
method_proc(method)
VALUE method;
@@ -7735,6 +9893,43 @@ rb_obj_is_method(m)
return Qfalse;
}
+/*
+ * call-seq:
+ * define_method(symbol, method) => new_method
+ * define_method(symbol) { block } => proc
+ *
+ * Defines an instance method in the receiver. The _method_
+ * parameter can be a +Proc+ or +Method+ object.
+ * If a block is specified, it is used as the method body. This block
+ * is evaluated using <code>instance_eval</code>, a point that is
+ * tricky to demonstrate because <code>define_method</code> is private.
+ * (This is why we resort to the +send+ hack in this example.)
+ *
+ * class A
+ * def fred
+ * puts "In Fred"
+ * end
+ * def create_method(name, &block)
+ * self.class.send(:define_method, name, &block)
+ * end
+ * define_method(:wilma) { puts "Charge it!" }
+ * end
+ * class B < A
+ * define_method(:barney, instance_method(:fred))
+ * end
+ * a = B.new
+ * a.barney
+ * a.wilma
+ * a.create_method(:betty) { p self }
+ * a.betty
+ *
+ * <em>produces:</em>
+ *
+ * In Fred
+ * Charge it!
+ * #<B:0x401b39e8>
+ */
+
static VALUE
rb_mod_define_method(argc, argv, mod)
int argc;
@@ -7759,7 +9954,7 @@ rb_mod_define_method(argc, argv, mod)
}
}
else {
- rb_raise(rb_eArgError, "wrong number of arguments(%d for 1)", argc);
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
}
if (RDATA(body)->dmark == (RUBY_DATA_FUNC)bm_mark) {
node = NEW_DMETHOD(method_unbind(body));
@@ -7779,19 +9974,37 @@ rb_mod_define_method(argc, argv, mod)
rb_raise(rb_eTypeError, "wrong argument type (expected Proc/Method)");
}
- if (SCOPE_TEST(SCOPE_PRIVATE)) {
- noex = NOEX_PRIVATE;
- }
- else if (SCOPE_TEST(SCOPE_PROTECTED)) {
- noex = NOEX_PROTECTED;
- }
- else {
- noex = NOEX_PUBLIC;
+ noex = NOEX_PUBLIC;
+ if (ruby_cbase == mod) {
+ if (SCOPE_TEST(SCOPE_PRIVATE)) {
+ noex = NOEX_PRIVATE;
+ }
+ else if (SCOPE_TEST(SCOPE_PROTECTED)) {
+ noex = NOEX_PROTECTED;
+ }
}
rb_add_method(mod, id, node, noex);
return body;
}
+/*
+ * <code>Proc</code> objects are blocks of code that have been bound to
+ * a set of local variables. Once bound, the code may be called in
+ * different contexts and still access those variables.
+ *
+ * def gen_times(factor)
+ * return Proc.new {|n| n*factor }
+ * end
+ *
+ * times3 = gen_times(3)
+ * times5 = gen_times(5)
+ *
+ * times3.call(12) #=> 36
+ * times5.call(5) #=> 25
+ * times3.call(times5.call(4)) #=> 60
+ *
+ */
+
void
Init_Proc()
{
@@ -7799,22 +10012,28 @@ Init_Proc()
rb_define_method(rb_eLocalJumpError, "exit_value", localjump_xvalue, 0);
rb_define_method(rb_eLocalJumpError, "reason", localjump_reason, 0);
- exception_error = rb_exc_new2(rb_eFatal, "exception reentered");
rb_global_variable(&exception_error);
+ exception_error = rb_exc_new3(rb_eFatal,
+ rb_obj_freeze(rb_str_new2("exception reentered")));
+ OBJ_TAINT(exception_error);
+ OBJ_FREEZE(exception_error);
rb_eSysStackError = rb_define_class("SystemStackError", rb_eStandardError);
- sysstack_error = rb_exc_new2(rb_eSysStackError, "stack level too deep");
- OBJ_TAINT(sysstack_error);
rb_global_variable(&sysstack_error);
+ sysstack_error = rb_exc_new3(rb_eSysStackError,
+ rb_obj_freeze(rb_str_new2("stack level too deep")));
+ OBJ_TAINT(sysstack_error);
+ OBJ_FREEZE(sysstack_error);
rb_cProc = rb_define_class("Proc", rb_cObject);
rb_undef_alloc_func(rb_cProc);
rb_define_singleton_method(rb_cProc, "new", proc_s_new, -1);
rb_define_method(rb_cProc, "clone", proc_clone, 0);
- rb_define_method(rb_cProc, "call", proc_call, -2);
+ rb_define_method(rb_cProc, "dup", proc_dup, 0);
+ rb_define_method(rb_cProc, "call", rb_proc_call, -2);
rb_define_method(rb_cProc, "arity", proc_arity, 0);
- rb_define_method(rb_cProc, "[]", proc_call, -2);
+ rb_define_method(rb_cProc, "[]", rb_proc_call, -2);
rb_define_method(rb_cProc, "==", proc_eq, 1);
rb_define_method(rb_cProc, "to_s", proc_to_s, 0);
rb_define_method(rb_cProc, "to_proc", proc_to_self, 0);
@@ -7823,12 +10042,6 @@ Init_Proc()
rb_define_global_function("proc", proc_lambda, 0);
rb_define_global_function("lambda", proc_lambda, 0);
- rb_cBinding = rb_define_class("Binding", rb_cObject);
- rb_undef_alloc_func(rb_cBinding);
- rb_undef_method(CLASS_OF(rb_cBinding), "new");
- rb_define_method(rb_cBinding, "clone", proc_clone, 0);
- rb_define_global_function("binding", rb_f_binding, 0);
-
rb_cMethod = rb_define_class("Method", rb_cObject);
rb_undef_alloc_func(rb_cMethod);
rb_undef_method(CLASS_OF(rb_cMethod), "new");
@@ -7840,6 +10053,9 @@ Init_Proc()
rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
rb_define_method(rb_cMethod, "to_s", method_inspect, 0);
rb_define_method(rb_cMethod, "to_proc", method_proc, 0);
+ rb_define_method(rb_cMethod, "receiver", method_receiver, 0);
+ rb_define_method(rb_cMethod, "name", method_name, 0);
+ rb_define_method(rb_cMethod, "owner", method_owner, 0);
rb_define_method(rb_cMethod, "unbind", method_unbind, 0);
rb_define_method(rb_mKernel, "method", rb_obj_method, 1);
@@ -7851,23 +10067,58 @@ Init_Proc()
rb_define_method(rb_cUnboundMethod, "arity", method_arity, 0);
rb_define_method(rb_cUnboundMethod, "inspect", method_inspect, 0);
rb_define_method(rb_cUnboundMethod, "to_s", method_inspect, 0);
+ rb_define_method(rb_cUnboundMethod, "name", method_name, 0);
+ rb_define_method(rb_cUnboundMethod, "owner", method_owner, 0);
rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
rb_define_method(rb_cModule, "instance_method", rb_mod_method, 1);
}
-#ifdef __ia64__
-#include <ucontext.h>
-#if defined(__FreeBSD__)
/*
- * FreeBSD/ia64 currently does not have a way for a process to get the
- * base address for the RSE backing store, so hardcode it.
+ * Objects of class <code>Binding</code> encapsulate the execution
+ * context at some particular place in the code and retain this context
+ * for future use. The variables, methods, value of <code>self</code>,
+ * and possibly an iterator block that can be accessed in this context
+ * are all retained. Binding objects can be created using
+ * <code>Kernel#binding</code>, and are made available to the callback
+ * of <code>Kernel#set_trace_func</code>.
+ *
+ * These binding objects can be passed as the second argument of the
+ * <code>Kernel#eval</code> method, establishing an environment for the
+ * evaluation.
+ *
+ * class Demo
+ * def initialize(n)
+ * @secret = n
+ * end
+ * def getBinding
+ * return binding()
+ * end
+ * end
+ *
+ * k1 = Demo.new(99)
+ * b1 = k1.getBinding
+ * k2 = Demo.new(-3)
+ * b2 = k2.getBinding
+ *
+ * eval("@secret", b1) #=> 99
+ * eval("@secret", b2) #=> -3
+ * eval("@secret") #=> nil
+ *
+ * Binding objects have no class-specific methods.
+ *
*/
-#define __libc_ia64_register_backing_store_base (4ULL<<61)
-#else
-#pragma weak __libc_ia64_register_backing_store_base
-extern unsigned long __libc_ia64_register_backing_store_base;
-#endif
-#endif
+
+void
+Init_Binding()
+{
+ rb_cBinding = rb_define_class("Binding", rb_cObject);
+ rb_undef_alloc_func(rb_cBinding);
+ rb_undef_method(CLASS_OF(rb_cBinding), "new");
+ rb_define_method(rb_cBinding, "clone", proc_clone, 0);
+ rb_define_method(rb_cBinding, "dup", proc_dup, 0);
+ rb_define_method(rb_cBinding, "eval", bind_eval, -1);
+ rb_define_global_function("binding", rb_f_binding, 0);
+}
/* Windows SEH refers data on the stack. */
#undef SAVE_WIN32_EXCEPTION_LIST
@@ -7933,13 +10184,6 @@ VALUE rb_cThread;
extern VALUE rb_last_status;
-enum thread_status {
- THREAD_TO_KILL,
- THREAD_RUNNABLE,
- THREAD_STOPPED,
- THREAD_KILLED,
-};
-
#define WAIT_FD (1<<0)
#define WAIT_SELECT (1<<1)
#define WAIT_TIME (1<<2)
@@ -7957,75 +10201,9 @@ enum thread_status {
# endif
#endif
-/* typedef struct thread * rb_thread_t; */
-
-struct thread {
- struct thread *next, *prev;
-#ifdef __ia64__
- ucontext_t context;
- int context_status;
-#else
- jmp_buf context;
-#endif
-#ifdef SAVE_WIN32_EXCEPTION_LIST
- DWORD win32_exception_list;
-#endif
-
- VALUE result;
-
- long stk_len;
- long stk_max;
- VALUE *stk_ptr;
- VALUE *stk_pos;
-#ifdef __ia64__
- VALUE *bstr_ptr;
- long bstr_len;
-#endif
-
- struct FRAME *frame;
- struct SCOPE *scope;
- struct RVarmap *dyna_vars;
- struct BLOCK *block;
- struct iter *iter;
- struct tag *tag;
- VALUE klass;
- VALUE wrapper;
- NODE *cref;
-
- int flags; /* misc. states (vmode/rb_trap_immediate/raised) */
-
- NODE *node;
-
- int tracing;
- VALUE errinfo;
- VALUE last_status;
- VALUE last_line;
- VALUE last_match;
-
- int safe;
-
- enum thread_status status;
- int wait_for;
- int fd;
- fd_set readfds;
- fd_set writefds;
- fd_set exceptfds;
- int select_value;
- double delay;
- rb_thread_t join;
-
- int abort;
- int priority;
- VALUE thgroup;
-
- st_table *locals;
-
- VALUE thread;
-};
-
-#define THREAD_RAISED 0x200 /* temporary flag */
#define THREAD_TERMINATING 0x400 /* persistent flag */
-#define THREAD_FLAGS_MASK 0x400 /* mask for persistent flags */
+#define THREAD_NO_ENSURE 0x800 /* persistent flag */
+#define THREAD_FLAGS_MASK 0xfc00 /* mask for persistent flags */
#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
#define END_FOREACH_FROM(f,x) } while (x != f)
@@ -8044,7 +10222,7 @@ struct thread_status_t {
int safe;
- enum thread_status status;
+ enum rb_thread_status status;
int wait_for;
int fd;
fd_set readfds;
@@ -8077,46 +10255,68 @@ struct thread_status_t {
(dst)->join = (src)->join, \
0)
-static int
-thread_set_raised()
+int
+rb_thread_set_raised(th)
+ rb_thread_t th;
{
- if (curr_thread->flags & THREAD_RAISED) return 1;
- curr_thread->flags |= THREAD_RAISED;
+ if (th->flags & RAISED_EXCEPTION) {
+ return 1;
+ }
+ th->flags |= RAISED_EXCEPTION;
return 0;
}
-static int
-thread_reset_raised()
+int
+rb_thread_reset_raised(th)
+ rb_thread_t th;
{
- if (!(curr_thread->flags & THREAD_RAISED)) return 0;
- curr_thread->flags &= ~THREAD_RAISED;
+ if (!(th->flags & RAISED_EXCEPTION)) {
+ return 0;
+ }
+ th->flags &= ~RAISED_EXCEPTION;
return 1;
}
+static int
+thread_no_ensure()
+{
+ return ((curr_thread->flags & THREAD_NO_ENSURE) == THREAD_NO_ENSURE);
+}
+
static void rb_thread_ready _((rb_thread_t));
+static VALUE run_trap_eval _((VALUE));
static VALUE
-rb_trap_eval(cmd, sig)
+run_trap_eval(arg)
+ VALUE arg;
+{
+ VALUE *p = (VALUE *)arg;
+ return rb_eval_cmd(p[0], p[1], (int)p[2]);
+}
+
+static VALUE
+rb_trap_eval(cmd, sig, safe)
VALUE cmd;
- int sig;
+ int sig, safe;
{
int state;
VALUE val = Qnil; /* OK */
volatile struct thread_status_t save;
+ VALUE arg[3];
+ arg[0] = cmd;
+ arg[1] = rb_ary_new3(1, INT2FIX(sig));
+ arg[2] = (VALUE)safe;
THREAD_COPY_STATUS(curr_thread, &save);
rb_thread_ready(curr_thread);
- PUSH_TAG(PROT_NONE);
PUSH_ITER(ITER_NOT);
- if ((state = EXEC_TAG()) == 0) {
- val = rb_eval_cmd(cmd, rb_ary_new3(1, INT2FIX(sig)), 0);
- }
+ val = rb_protect(run_trap_eval, (VALUE)&arg, &state);
POP_ITER();
- POP_TAG();
THREAD_COPY_STATUS(&save, curr_thread);
if (state) {
rb_trap_immediate = 0;
+ rb_thread_ready(curr_thread);
JUMP_TAG(state);
}
@@ -8130,7 +10330,7 @@ rb_trap_eval(cmd, sig)
static const char *
thread_status_name(status)
- enum thread_status status;
+ enum rb_thread_status status;
{
switch (status) {
case THREAD_RUNNABLE:
@@ -8152,6 +10352,7 @@ rb_set_safe_level(level)
int level;
{
if (level > ruby_safe_level) {
+ if (level > SAFE_LEVEL_MAX) level = SAFE_LEVEL_MAX;
ruby_safe_level = level;
curr_thread->safe = level;
}
@@ -8173,6 +10374,7 @@ safe_setter(val)
rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d",
ruby_safe_level, level);
}
+ if (level > SAFE_LEVEL_MAX) level = SAFE_LEVEL_MAX;
ruby_safe_level = level;
curr_thread->safe = level;
}
@@ -8182,32 +10384,19 @@ static double
timeofday()
{
struct timeval tv;
+#ifdef CLOCK_MONOTONIC
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
+ return (double)tp.tv_sec + (double)tp.tv_nsec * 1e-9;
+ }
+#endif
gettimeofday(&tv, NULL);
return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
}
#define STACK(addr) (th->stk_pos<(VALUE*)(addr) && (VALUE*)(addr)<th->stk_pos+th->stk_len)
#define ADJ(addr) (void*)(STACK(addr)?(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr):(VALUE*)(addr))
-#ifdef C_ALLOCA
-# define MARK_FRAME_ADJ(f) rb_gc_mark_frame(f)
-#else
-# define MARK_FRAME_ADJ(f) mark_frame_adj(f, th)
-static void
-mark_frame_adj(frame, th)
- struct FRAME *frame;
- rb_thread_t th;
-{
- if (frame->flags & FRAME_MALLOC) {
- rb_gc_mark_locations(frame->argv, frame->argv+frame->argc);
- }
- else {
- VALUE *start = ADJ(frame->argv);
- rb_gc_mark_locations(start, start+frame->argc);
- }
- rb_gc_mark((VALUE)frame->node);
-}
-#endif
-
static void
thread_mark(th)
rb_thread_t th;
@@ -8226,9 +10415,12 @@ thread_mark(th)
rb_gc_mark((VALUE)th->scope);
rb_gc_mark((VALUE)th->dyna_vars);
rb_gc_mark(th->errinfo);
+ rb_gc_mark(th->last_status);
rb_gc_mark(th->last_line);
rb_gc_mark(th->last_match);
rb_mark_tbl(th->locals);
+ rb_gc_mark(th->thgroup);
+ rb_gc_mark_maybe(th->sandbox);
/* mark data in copied stack */
if (th == curr_thread) return;
@@ -8239,22 +10431,22 @@ thread_mark(th)
#if defined(THINK_C) || defined(__human68k__)
rb_gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
#endif
-#ifdef __ia64__
+#ifdef __ia64
if (th->bstr_ptr) {
- rb_gc_mark_locations(th->bstr_ptr, th->bstr_ptr+th->bstr_len);
+ rb_gc_mark_locations(th->bstr_ptr, th->bstr_ptr+th->bstr_len);
}
#endif
}
frame = th->frame;
while (frame && frame != top_frame) {
frame = ADJ(frame);
- MARK_FRAME_ADJ(frame);
+ rb_gc_mark_frame(frame);
if (frame->tmp) {
struct FRAME *tmp = frame->tmp;
while (tmp && tmp != top_frame) {
tmp = ADJ(tmp);
- MARK_FRAME_ADJ(tmp);
+ rb_gc_mark_frame(tmp);
tmp = tmp->prev;
}
}
@@ -8263,11 +10455,21 @@ thread_mark(th)
block = th->block;
while (block) {
block = ADJ(block);
- MARK_FRAME_ADJ(&block->frame);
+ rb_gc_mark_frame(&block->frame);
block = block->prev;
}
}
+static int
+mark_loading_thread(key, value, lev)
+ ID key;
+ VALUE value;
+ int lev;
+{
+ rb_gc_mark(((rb_thread_t)value)->thread);
+ return ST_CONTINUE;
+}
+
void
rb_gc_mark_threads()
{
@@ -8277,21 +10479,57 @@ rb_gc_mark_threads()
rb_gc_mark((VALUE)ruby_cref);
if (!curr_thread) return;
- FOREACH_THREAD(th) {
+ rb_gc_mark(main_thread->thread);
+ rb_gc_mark(curr_thread->thread);
+ FOREACH_THREAD_FROM(main_thread, th) {
+ switch (th->status) {
+ case THREAD_TO_KILL:
+ case THREAD_RUNNABLE:
+ break;
+ case THREAD_STOPPED:
+ if (th->wait_for) break;
+ default:
+ continue;
+ }
rb_gc_mark(th->thread);
- } END_FOREACH(th);
+ } END_FOREACH_FROM(main_thread, th);
+ if (loading_tbl) st_foreach(loading_tbl, mark_loading_thread, 0);
}
-static void
-thread_free(th)
+void
+rb_gc_abort_threads()
+{
+ rb_thread_t th;
+
+ if (!main_thread)
+ return;
+
+ FOREACH_THREAD_FROM(main_thread, th) {
+ if (FL_TEST(th->thread, FL_MARK)) continue;
+ if (th->status == THREAD_STOPPED) {
+ th->status = THREAD_TO_KILL;
+ rb_gc_mark(th->thread);
+ }
+ } END_FOREACH_FROM(main_thread, th);
+}
+
+static inline void
+stack_free(th)
rb_thread_t th;
{
if (th->stk_ptr) free(th->stk_ptr);
th->stk_ptr = 0;
-#ifdef __ia64__
+#ifdef __ia64
if (th->bstr_ptr) free(th->bstr_ptr);
th->bstr_ptr = 0;
#endif
+}
+
+static void
+thread_free(th)
+ rb_thread_t th;
+{
+ stack_free(th);
if (th->locals) st_free_table(th->locals);
if (th->status != THREAD_KILLED) {
if (th->prev) th->prev->next = th->next;
@@ -8313,12 +10551,10 @@ rb_thread_check(data)
static VALUE rb_thread_raise _((int, VALUE*, rb_thread_t));
-static int th_raise_argc;
-static VALUE th_raise_argv[2];
+static VALUE th_raise_exception;
static NODE *th_raise_node;
static VALUE th_cmd;
-static int th_sig;
-static char *th_signm;
+static int th_sig, th_safe;
#define RESTORE_NORMAL 1
#define RESTORE_FATAL 2
@@ -8329,41 +10565,43 @@ static char *th_signm;
#define RESTORE_EXIT 7
extern VALUE *rb_gc_stack_start;
+#ifdef __ia64
+extern VALUE *rb_gc_register_stack_start;
+#endif
static void
rb_thread_save_context(th)
rb_thread_t th;
{
VALUE *pos;
- int len;
+ size_t len;
static VALUE tval;
len = ruby_stack_length(&pos);
th->stk_len = 0;
th->stk_pos = pos;
if (len > th->stk_max) {
- REALLOC_N(th->stk_ptr, VALUE, len);
+ VALUE *ptr = realloc(th->stk_ptr, sizeof(VALUE) * len);
+ if (!ptr) rb_memerror();
+ th->stk_ptr = ptr;
th->stk_max = len;
}
th->stk_len = len;
FLUSH_REGISTER_WINDOWS;
MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
-#ifdef __ia64__
- {
- ucontext_t ctx;
- VALUE *top, *bot;
-
- getcontext(&ctx);
- bot = (VALUE*)__libc_ia64_register_backing_store_base;
-#if defined(__FreeBSD__)
- top = (VALUE*)ctx.uc_mcontext.mc_special.bspstore;
-#else
- top = (VALUE*)ctx.uc_mcontext.sc_ar_bsp;
-#endif
- th->bstr_len = top - bot;
- REALLOC_N(th->bstr_ptr, VALUE, th->bstr_len);
- MEMCPY(th->bstr_ptr, (VALUE*)__libc_ia64_register_backing_store_base, VALUE, th->bstr_len);
- }
+#ifdef __ia64
+ th->bstr_pos = rb_gc_register_stack_start;
+ len = (VALUE*)rb_ia64_bsp() - th->bstr_pos;
+ th->bstr_len = 0;
+ if (len > th->bstr_max) {
+ VALUE *ptr = realloc(th->bstr_ptr, sizeof(VALUE) * len);
+ if (!ptr) rb_memerror();
+ th->bstr_ptr = ptr;
+ th->bstr_max = len;
+ }
+ th->bstr_len = len;
+ rb_ia64_flushrs();
+ MEMCPY(th->bstr_ptr, th->bstr_pos, VALUE, th->bstr_len);
#endif
#ifdef SAVE_WIN32_EXCEPTION_LIST
th->win32_exception_list = win32_get_exception_list();
@@ -8371,6 +10609,7 @@ rb_thread_save_context(th)
th->frame = ruby_frame;
th->scope = ruby_scope;
+ ruby_scope->flags |= SCOPE_DONT_RECYCLE;
th->klass = ruby_class;
th->wrapper = ruby_wrapper;
th->cref = ruby_cref;
@@ -8392,6 +10631,9 @@ rb_thread_save_context(th)
th->safe = ruby_safe_level;
th->node = ruby_current_node;
+ if (ruby_sandbox_save != NULL) {
+ ruby_sandbox_save(th);
+ }
}
static int
@@ -8409,21 +10651,23 @@ rb_thread_switch(n)
rb_interrupt();
break;
case RESTORE_TRAP:
- rb_trap_eval(th_cmd, th_sig);
+ rb_trap_eval(th_cmd, th_sig, th_safe);
break;
case RESTORE_RAISE:
ruby_frame->last_func = 0;
ruby_current_node = th_raise_node;
- rb_f_raise(th_raise_argc, th_raise_argv);
+ rb_raise_jump(th_raise_exception);
break;
case RESTORE_SIGNAL:
- rb_raise(rb_eSignal, "SIG%s", th_signm);
+ rb_thread_signal_raise(th_sig);
break;
case RESTORE_EXIT:
- ruby_errinfo = th_raise_argv[0];
+ ruby_errinfo = th_raise_exception;
ruby_current_node = th_raise_node;
- error_print();
- terminate_process(EXIT_FAILURE, 0, 0);
+ if (!rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
+ terminate_process(EXIT_FAILURE, ruby_errinfo);
+ }
+ rb_exc_raise(th_raise_exception);
break;
case RESTORE_NORMAL:
default:
@@ -8432,58 +10676,24 @@ rb_thread_switch(n)
return 1;
}
-#ifdef __ia64__
-# define THREAD_SAVE_CONTEXT(th) \
- (rb_thread_save_context(th),\
- th->context_status = 0,\
- rb_thread_switch((FLUSH_REGISTER_WINDOWS, getcontext(&th->context),(th)->context_status)))
-#else
-# define THREAD_SAVE_CONTEXT(th) \
- (rb_thread_save_context(th),\
- rb_thread_switch((FLUSH_REGISTER_WINDOWS, setjmp((th)->context))))
-#endif
+#define THREAD_SAVE_CONTEXT(th) \
+ (rb_thread_switch(ruby_setjmp(rb_thread_save_context(th), (th)->context)))
NORETURN(static void rb_thread_restore_context _((rb_thread_t,int)));
+NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int)));
+NORETURN(NOINLINE(static void stack_extend(rb_thread_t, int)));
static void
-stack_extend(th, exit)
- rb_thread_t th;
- int exit;
-{
- VALUE space[1024];
-
- memset(space, 0, 1); /* prevent array from optimization */
- rb_thread_restore_context(th, exit);
-}
-
-static void
-rb_thread_restore_context(th, exit)
- rb_thread_t th;
- int exit;
+rb_thread_restore_context_0(rb_thread_t th, int exit)
{
- VALUE v;
static rb_thread_t tmp;
static int ex;
static VALUE tval;
- if (!th->stk_ptr) rb_bug("unsaved context");
-
-#if STACK_GROW_DIRECTION < 0
- if (&v > th->stk_pos) stack_extend(th, exit);
-#elif STACK_GROW_DIRECTION > 0
- if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
-#else
- if (&v < rb_gc_stack_start) {
- /* Stack grows downward */
- if (&v > th->stk_pos) stack_extend(th, exit);
- }
- else {
- /* Stack grows upward */
- if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
- }
-#endif
-
rb_trap_immediate = 0; /* inhibit interrupts from here */
+ if (ruby_sandbox_restore != NULL) {
+ ruby_sandbox_restore(th);
+ }
ruby_frame = th->frame;
ruby_scope = th->scope;
ruby_class = th->klass;
@@ -8508,8 +10718,8 @@ rb_thread_restore_context(th, exit)
ex = exit;
FLUSH_REGISTER_WINDOWS;
MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
-#ifdef __ia64__
- MEMCPY((VALUE*)__libc_ia64_register_backing_store_base, tmp->bstr_ptr, VALUE, tmp->bstr_len);
+#ifdef __ia64
+ MEMCPY(tmp->bstr_pos, tmp->bstr_ptr, VALUE, tmp->bstr_len);
#endif
tval = rb_lastline_get();
@@ -8519,12 +10729,90 @@ rb_thread_restore_context(th, exit)
rb_backref_set(tmp->last_match);
tmp->last_match = tval;
-#ifdef __ia64__
- tmp->context_status = ex;
- setcontext(&tmp->context);
-#else
- longjmp(tmp->context, ex);
+ ruby_longjmp(tmp->context, ex);
+}
+
+#ifdef __ia64
+#define C(a) rse_##a##0, rse_##a##1, rse_##a##2, rse_##a##3, rse_##a##4
+#define E(a) rse_##a##0= rse_##a##1= rse_##a##2= rse_##a##3= rse_##a##4
+static volatile int C(a), C(b), C(c), C(d), C(e);
+static volatile int C(f), C(g), C(h), C(i), C(j);
+static volatile int C(k), C(l), C(m), C(n), C(o);
+static volatile int C(p), C(q), C(r), C(s), C(t);
+int rb_dummy_false = 0;
+NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, VALUE *)));
+static void
+register_stack_extend(rb_thread_t th, int exit, VALUE *curr_bsp)
+{
+ if (rb_dummy_false) {
+ /* use registers as much as possible */
+ E(a) = E(b) = E(c) = E(d) = E(e) =
+ E(f) = E(g) = E(h) = E(i) = E(j) =
+ E(k) = E(l) = E(m) = E(n) = E(o) =
+ E(p) = E(q) = E(r) = E(s) = E(t) = 0;
+ E(a) = E(b) = E(c) = E(d) = E(e) =
+ E(f) = E(g) = E(h) = E(i) = E(j) =
+ E(k) = E(l) = E(m) = E(n) = E(o) =
+ E(p) = E(q) = E(r) = E(s) = E(t) = 0;
+ }
+ if (curr_bsp < th->bstr_pos+th->bstr_len) {
+ register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp());
+ }
+ stack_extend(th, exit);
+}
+#undef C
+#undef E
+#endif
+
+static void
+stack_extend(rb_thread_t th, int exit)
+{
+#define STACK_PAD_SIZE 1024
+ volatile VALUE space[STACK_PAD_SIZE], *sp = space;
+
+#if !STACK_GROW_DIRECTION
+ if (space < rb_gc_stack_start) {
+ /* Stack grows downward */
+#endif
+#if STACK_GROW_DIRECTION <= 0
+ if (space > th->stk_pos) {
+# ifdef HAVE_ALLOCA
+ sp = ALLOCA_N(VALUE, &space[0] - th->stk_pos);
+# else
+ stack_extend(th, exit);
+# endif
+ }
+#endif
+#if !STACK_GROW_DIRECTION
+ }
+ else {
+ /* Stack grows upward */
+#endif
+#if STACK_GROW_DIRECTION >= 0
+ if (&space[STACK_PAD_SIZE] < th->stk_pos + th->stk_len) {
+# ifdef HAVE_ALLOCA
+ sp = ALLOCA_N(VALUE, th->stk_pos + th->stk_len - &space[STACK_PAD_SIZE]);
+# else
+ stack_extend(th, exit);
+# endif
+ }
#endif
+#if !STACK_GROW_DIRECTION
+ }
+#endif
+ rb_thread_restore_context_0(th, exit);
+}
+#ifdef __ia64
+#define stack_extend(th, exit) register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp())
+#endif
+
+static void
+rb_thread_restore_context(th, exit)
+ rb_thread_t th;
+ int exit;
+{
+ if (!th->stk_ptr) rb_bug("unsaved context");
+ stack_extend(th, exit);
}
static void
@@ -8543,8 +10831,7 @@ rb_thread_die(th)
{
th->thgroup = 0;
th->status = THREAD_KILLED;
- if (th->stk_ptr) free(th->stk_ptr);
- th->stk_ptr = 0;
+ stack_free(th);
}
static void
@@ -8592,8 +10879,7 @@ rb_thread_main_jump(err, tag)
int tag;
{
curr_thread = main_thread;
- th_raise_argc = 1;
- th_raise_argv[0] = err;
+ th_raise_exception = err;
th_raise_node = ruby_current_node;
rb_thread_restore_context(main_thread, tag);
}
@@ -8688,6 +10974,7 @@ rb_thread_schedule()
rb_thread_t next; /* OK */
rb_thread_t th;
rb_thread_t curr;
+ rb_thread_t th_found = 0;
int found = 0;
fd_set readfds;
@@ -8705,6 +10992,7 @@ rb_thread_schedule()
}
#endif
rb_thread_pending = 0;
+ rb_gc_finalize_deferred();
if (curr_thread == curr_thread->next
&& curr_thread->status == THREAD_RUNNABLE)
return;
@@ -8822,9 +11110,9 @@ rb_thread_schedule()
th->wait_for = 0;
th->select_value = 0;
found = 1;
- intersect_fds(&readfds, &th->readfds, max);
- intersect_fds(&writefds, &th->writefds, max);
- intersect_fds(&exceptfds, &th->exceptfds, max);
+ intersect_fds(&readfds, &th->readfds, max);
+ intersect_fds(&writefds, &th->writefds, max);
+ intersect_fds(&exceptfds, &th->exceptfds, max);
}
}
END_FOREACH_FROM(curr, th);
@@ -8832,28 +11120,22 @@ rb_thread_schedule()
if (n > 0) {
now = -1.0;
/* Some descriptors are ready.
- Make the corresponding threads runnable. */
+ * Choose a thread which may run next.
+ * Don't change the status of threads which don't run next.
+ */
FOREACH_THREAD_FROM(curr, th) {
if ((th->wait_for&WAIT_FD) && FD_ISSET(th->fd, &readfds)) {
- /* Wake up only one thread per fd. */
- FD_CLR(th->fd, &readfds);
- th->status = THREAD_RUNNABLE;
- th->fd = 0;
- th->wait_for = 0;
+ th_found = th;
found = 1;
+ break;
}
if ((th->wait_for&WAIT_SELECT) &&
(match_fds(&readfds, &th->readfds, max) ||
match_fds(&writefds, &th->writefds, max) ||
match_fds(&exceptfds, &th->exceptfds, max))) {
- /* Wake up only one thread per fd. */
- th->status = THREAD_RUNNABLE;
- th->wait_for = 0;
- n = intersect_fds(&readfds, &th->readfds, max) +
- intersect_fds(&writefds, &th->writefds, max) +
- intersect_fds(&exceptfds, &th->exceptfds, max);
- th->select_value = n;
- found = 1;
+ th_found = th;
+ found = 1;
+ break;
}
}
END_FOREACH_FROM(curr, th);
@@ -8869,9 +11151,23 @@ rb_thread_schedule()
next = th;
break;
}
- if (th->status == THREAD_RUNNABLE && th->stk_ptr) {
- if (!next || next->priority < th->priority)
- next = th;
+ if ((th->status == THREAD_RUNNABLE || th == th_found) && th->stk_ptr) {
+ if (!next || next->priority < th->priority) {
+ if (th == th_found) {
+ th_found->status = THREAD_RUNNABLE;
+ th_found->wait_for = 0;
+ if (th->wait_for&WAIT_FD) {
+ th_found->fd = 0;
+ }
+ else { /* th->wait_for&WAIT_SELECT */
+ n = intersect_fds(&readfds, &th_found->readfds, max) +
+ intersect_fds(&writefds, &th_found->writefds, max) +
+ intersect_fds(&exceptfds, &th_found->exceptfds, max);
+ th_found->select_value = n;
+ }
+ }
+ next = th;
+ }
}
}
END_FOREACH_FROM(curr, th);
@@ -8952,6 +11248,7 @@ rb_thread_fd_writable(fd)
if (rb_thread_critical) return Qtrue;
if (curr_thread == curr_thread->next) return Qtrue;
if (curr_thread->status == THREAD_TO_KILL) return Qtrue;
+ if (curr_thread->status == THREAD_KILLED) return Qtrue;
curr_thread->status = THREAD_STOPPED;
FD_ZERO(&curr_thread->readfds);
@@ -8974,13 +11271,16 @@ rb_thread_wait_for(time)
curr_thread == curr_thread->next ||
curr_thread->status == THREAD_TO_KILL) {
int n;
+ int thr_critical = rb_thread_critical;
#ifndef linux
double d, limit;
limit = timeofday()+(double)time.tv_sec+(double)time.tv_usec*1e-6;
#endif
for (;;) {
+ rb_thread_critical = Qtrue;
TRAP_BEG;
n = select(0, 0, 0, 0, &time);
+ rb_thread_critical = thr_critical;
TRAP_END;
if (n == 0) return;
if (n < 0) {
@@ -8989,7 +11289,7 @@ rb_thread_wait_for(time)
#ifdef ERESTART
case ERESTART:
#endif
- return;
+ break;
default:
rb_sys_fail("sleep");
}
@@ -9029,7 +11329,9 @@ rb_thread_select(max, read, write, except, timeout)
fd_set *read, *write, *except;
struct timeval *timeout;
{
+#ifndef linux
double limit;
+#endif
int n;
if (!read && !write && !except) {
@@ -9041,10 +11343,12 @@ rb_thread_select(max, read, write, except, timeout)
return 0;
}
+#ifndef linux
if (timeout) {
limit = timeofday()+
(double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
}
+#endif
if (rb_thread_critical ||
curr_thread == curr_thread->next ||
@@ -9109,14 +11413,12 @@ rb_thread_select(max, read, write, except, timeout)
return curr_thread->select_value;
}
-static int rb_thread_join _((rb_thread_t, double));
-
static int
rb_thread_join(th, limit)
rb_thread_t th;
double limit;
{
- enum thread_status last_status = THREAD_RUNNABLE;
+ enum rb_thread_status last_status = THREAD_RUNNABLE;
if (rb_thread_critical) rb_thread_deadlock();
if (!rb_thread_dead(th)) {
@@ -9139,20 +11441,62 @@ rb_thread_join(th, limit)
if (!rb_thread_dead(th)) return Qfalse;
}
- if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED)) {
+ if (!NIL_P(th->errinfo) && (th->flags & RAISED_EXCEPTION)) {
VALUE oldbt = get_backtrace(th->errinfo);
VALUE errat = make_backtrace();
+ VALUE errinfo = rb_obj_dup(th->errinfo);
if (TYPE(oldbt) == T_ARRAY && RARRAY(oldbt)->len > 0) {
rb_ary_unshift(errat, rb_ary_entry(oldbt, 0));
}
- set_backtrace(th->errinfo, errat);
- rb_exc_raise(th->errinfo);
+ set_backtrace(errinfo, errat);
+ rb_exc_raise(errinfo);
}
return Qtrue;
}
+
+/*
+ * call-seq:
+ * thr.join => thr
+ * thr.join(limit) => thr
+ *
+ * The calling thread will suspend execution and run <i>thr</i>. Does not
+ * return until <i>thr</i> exits or until <i>limit</i> seconds have passed. If
+ * the time limit expires, <code>nil</code> will be returned, otherwise
+ * <i>thr</i> is returned.
+ *
+ * Any threads not joined will be killed when the main program exits. If
+ * <i>thr</i> had previously raised an exception and the
+ * <code>abort_on_exception</code> and <code>$DEBUG</code> flags are not set
+ * (so the exception has not yet been processed) it will be processed at this
+ * time.
+ *
+ * a = Thread.new { print "a"; sleep(10); print "b"; print "c" }
+ * x = Thread.new { print "x"; Thread.pass; print "y"; print "z" }
+ * x.join # Let x thread finish, a will be killed on exit.
+ *
+ * <em>produces:</em>
+ *
+ * axyz
+ *
+ * The following example illustrates the <i>limit</i> parameter.
+ *
+ * y = Thread.new { 4.times { sleep 0.1; puts 'tick... ' }}
+ * puts "Waiting" until y.join(0.15)
+ *
+ * <em>produces:</em>
+ *
+ * tick...
+ * Waiting
+ * tick...
+ * Waitingtick...
+ *
+ *
+ * tick...
+ */
+
static VALUE
rb_thread_join_m(argc, argv, thread)
int argc;
@@ -9170,18 +11514,59 @@ rb_thread_join_m(argc, argv, thread)
return thread;
}
+
+/*
+ * call-seq:
+ * Thread.current => thread
+ *
+ * Returns the currently executing thread.
+ *
+ * Thread.current #=> #<Thread:0x401bdf4c run>
+ */
+
VALUE
rb_thread_current()
{
return curr_thread->thread;
}
+
+/*
+ * call-seq:
+ * Thread.main => thread
+ *
+ * Returns the main thread for the process.
+ *
+ * Thread.main #=> #<Thread:0x401bdf4c run>
+ */
+
VALUE
rb_thread_main()
{
return main_thread->thread;
}
+
+/*
+ * call-seq:
+ * Thread.list => array
+ *
+ * Returns an array of <code>Thread</code> objects for all threads that are
+ * either runnable or stopped.
+ *
+ * Thread.new { sleep(200) }
+ * Thread.new { 1000000.times {|i| i*i } }
+ * Thread.new { Thread.stop }
+ * Thread.list.each {|t| p t}
+ *
+ * <em>produces:</em>
+ *
+ * #<Thread:0x401b3e84 sleep>
+ * #<Thread:0x401b3f38 run>
+ * #<Thread:0x401b3fb0 sleep>
+ * #<Thread:0x401bdf4c run>
+ */
+
VALUE
rb_thread_list()
{
@@ -9203,19 +11588,65 @@ rb_thread_list()
return ary;
}
+
+/*
+ * call-seq:
+ * thr.wakeup => thr
+ *
+ * Marks <i>thr</i> as eligible for scheduling (it may still remain blocked on
+ * I/O, however). Does not invoke the scheduler (see <code>Thread#run</code>).
+ *
+ * c = Thread.new { Thread.stop; puts "hey!" }
+ * c.wakeup
+ *
+ * <em>produces:</em>
+ *
+ * hey!
+ */
+
VALUE
rb_thread_wakeup(thread)
VALUE thread;
{
+ if (!RTEST(rb_thread_wakeup_alive(thread)))
+ rb_raise(rb_eThreadError, "killed thread");
+ return thread;
+}
+
+VALUE
+rb_thread_wakeup_alive(thread)
+ VALUE thread;
+{
rb_thread_t th = rb_thread_check(thread);
if (th->status == THREAD_KILLED)
- rb_raise(rb_eThreadError, "killed thread");
+ return Qnil;
rb_thread_ready(th);
return thread;
}
+
+/*
+ * call-seq:
+ * thr.run => thr
+ *
+ * Wakes up <i>thr</i>, making it eligible for scheduling. If not in a critical
+ * section, then invokes the scheduler.
+ *
+ * a = Thread.new { puts "a"; Thread.stop; puts "c" }
+ * Thread.pass
+ * puts "Got here"
+ * a.run
+ * a.join
+ *
+ * <em>produces:</em>
+ *
+ * a
+ * Got here
+ * c
+ */
+
VALUE
rb_thread_run(thread)
VALUE thread;
@@ -9226,25 +11657,84 @@ rb_thread_run(thread)
return thread;
}
-VALUE
-rb_thread_kill(thread)
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
+static void
+rb_kill_thread(th, flags)
+ rb_thread_t th;
+ int flags;
+{
if (th != curr_thread && th->safe < 4) {
rb_secure(4);
}
if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED)
- return thread;
+ return;
if (th == th->next || th == main_thread) rb_exit(EXIT_SUCCESS);
rb_thread_ready(th);
+ th->flags |= flags;
th->status = THREAD_TO_KILL;
if (!rb_thread_critical) rb_thread_schedule();
+}
+
+
+/*
+ * call-seq:
+ * thr.exit => thr
+ * thr.kill => thr
+ * thr.terminate => thr
+ *
+ * Terminates <i>thr</i> and schedules another thread to be run, returning
+ * the terminated <code>Thread</code>. If this is the main thread, or the
+ * last thread, exits the process.
+ */
+
+VALUE
+rb_thread_kill(thread)
+ VALUE thread;
+{
+ rb_thread_t th = rb_thread_check(thread);
+
+ rb_kill_thread(th, 0);
+ return thread;
+}
+
+
+/*
+ * call-seq:
+ * thr.exit! => thr
+ * thr.kill! => thr
+ * thr.terminate! => thr
+ *
+ * Terminates <i>thr</i> without calling ensure clauses and schedules
+ * another thread to be run, returning the terminated <code>Thread</code>.
+ * If this is the main thread, or the last thread, exits the process.
+ *
+ * See <code>Thread#exit</code> for the safer version.
+ */
+
+static VALUE
+rb_thread_kill_bang(thread)
+ VALUE thread;
+{
+ rb_thread_t th = rb_thread_check(thread);
+ rb_kill_thread(th, THREAD_NO_ENSURE);
return thread;
}
+/*
+ * call-seq:
+ * Thread.kill(thread) => thread
+ *
+ * Causes the given <em>thread</em> to exit (see <code>Thread::exit</code>).
+ *
+ * count = 0
+ * a = Thread.new { loop { count += 1 } }
+ * sleep(0.1) #=> 0
+ * Thread.kill(a) #=> #<Thread:0x401b3d30 dead>
+ * count #=> 93947
+ * a.alive? #=> false
+ */
+
static VALUE
rb_thread_s_kill(obj, th)
VALUE obj, th;
@@ -9252,12 +11742,44 @@ rb_thread_s_kill(obj, th)
return rb_thread_kill(th);
}
+
+/*
+ * call-seq:
+ * Thread.exit => thread
+ *
+ * Terminates the currently running thread and schedules another thread to be
+ * run. If this thread is already marked to be killed, <code>exit</code>
+ * returns the <code>Thread</code>. If this is the main thread, or the last
+ * thread, exit the process.
+ */
+
static VALUE
rb_thread_exit()
{
return rb_thread_kill(curr_thread->thread);
}
+
+/*
+ * call-seq:
+ * Thread.pass => nil
+ *
+ * Invokes the thread scheduler to pass execution to another thread.
+ *
+ * a = Thread.new { print "a"; Thread.pass;
+ * print "b"; Thread.pass;
+ * print "c" }
+ * b = Thread.new { print "x"; Thread.pass;
+ * print "y"; Thread.pass;
+ * print "z" }
+ * a.join
+ * b.join
+ *
+ * <em>produces:</em>
+ *
+ * axbycz
+ */
+
static VALUE
rb_thread_pass()
{
@@ -9265,10 +11787,30 @@ rb_thread_pass()
return Qnil;
}
+
+/*
+ * call-seq:
+ * Thread.stop => nil
+ *
+ * Stops execution of the current thread, putting it into a ``sleep'' state,
+ * and schedules execution of another thread. Resets the ``critical'' condition
+ * to <code>false</code>.
+ *
+ * a = Thread.new { print "a"; Thread.stop; print "c" }
+ * Thread.pass
+ * print "b"
+ * a.run
+ * a.join
+ *
+ * <em>produces:</em>
+ *
+ * abc
+ */
+
VALUE
rb_thread_stop()
{
- enum thread_status last_status = THREAD_RUNNABLE;
+ enum rb_thread_status last_status = THREAD_RUNNABLE;
rb_thread_critical = 0;
if (curr_thread == curr_thread->next) {
@@ -9312,10 +11854,13 @@ rb_thread_sleep(sec)
void
rb_thread_sleep_forever()
{
+ int thr_critical = rb_thread_critical;
if (curr_thread == curr_thread->next ||
curr_thread->status == THREAD_TO_KILL) {
+ rb_thread_critical = Qtrue;
TRAP_BEG;
pause();
+ rb_thread_critical = thr_critical;
TRAP_END;
return;
}
@@ -9326,6 +11871,19 @@ rb_thread_sleep_forever()
rb_thread_schedule();
}
+
+/*
+ * call-seq:
+ * thr.priority => integer
+ *
+ * Returns the priority of <i>thr</i>. Default is inherited from the
+ * current thread which creating the new thread, or zero for the
+ * initial main thread; higher-priority threads will run before
+ * lower-priority threads.
+ *
+ * Thread.current.priority #=> 0
+ */
+
static VALUE
rb_thread_priority(thread)
VALUE thread;
@@ -9333,6 +11891,30 @@ rb_thread_priority(thread)
return INT2NUM(rb_thread_check(thread)->priority);
}
+
+/*
+ * call-seq:
+ * thr.priority= integer => thr
+ *
+ * Sets the priority of <i>thr</i> to <i>integer</i>. Higher-priority threads
+ * will run before lower-priority threads.
+ *
+ * count1 = count2 = 0
+ * a = Thread.new do
+ * loop { count1 += 1 }
+ * end
+ * a.priority = -1
+ *
+ * b = Thread.new do
+ * loop { count2 += 1 }
+ * end
+ * b.priority = -2
+ * sleep 1 #=> 1
+ * Thread.critical = 1
+ * count1 #=> 622504
+ * count2 #=> 5832
+ */
+
static VALUE
rb_thread_priority_set(thread, prio)
VALUE thread, prio;
@@ -9347,6 +11929,19 @@ rb_thread_priority_set(thread, prio)
return prio;
}
+
+/*
+ * call-seq:
+ * thr.safe_level => integer
+ *
+ * Returns the safe level in effect for <i>thr</i>. Setting thread-local safe
+ * levels can help when implementing sandboxes which run insecure code.
+ *
+ * thr = Thread.new { $SAFE = 3; sleep }
+ * Thread.current.safe_level #=> 0
+ * thr.safe_level #=> 3
+ */
+
static VALUE
rb_thread_safe_level(thread)
VALUE thread;
@@ -9363,12 +11958,50 @@ rb_thread_safe_level(thread)
static int ruby_thread_abort;
static VALUE thgroup_default;
+
+/*
+ * call-seq:
+ * Thread.abort_on_exception => true or false
+ *
+ * Returns the status of the global ``abort on exception'' condition. The
+ * default is <code>false</code>. When set to <code>true</code>, or if the
+ * global <code>$DEBUG</code> flag is <code>true</code> (perhaps because the
+ * command line option <code>-d</code> was specified) all threads will abort
+ * (the process will <code>exit(0)</code>) if an exception is raised in any
+ * thread. See also <code>Thread::abort_on_exception=</code>.
+ */
+
static VALUE
rb_thread_s_abort_exc()
{
return ruby_thread_abort?Qtrue:Qfalse;
}
+
+/*
+ * call-seq:
+ * Thread.abort_on_exception= boolean => true or false
+ *
+ * When set to <code>true</code>, all threads will abort if an exception is
+ * raised. Returns the new state.
+ *
+ * Thread.abort_on_exception = true
+ * t1 = Thread.new do
+ * puts "In new thread"
+ * raise "Exception from thread"
+ * end
+ * sleep(1)
+ * puts "not reached"
+ *
+ * <em>produces:</em>
+ *
+ * In new thread
+ * prog.rb:4: Exception from thread (RuntimeError)
+ * from prog.rb:2:in `initialize'
+ * from prog.rb:2:in `new'
+ * from prog.rb:2
+ */
+
static VALUE
rb_thread_s_abort_exc_set(self, val)
VALUE self, val;
@@ -9378,6 +12011,16 @@ rb_thread_s_abort_exc_set(self, val)
return val;
}
+
+/*
+ * call-seq:
+ * thr.abort_on_exception => true or false
+ *
+ * Returns the status of the thread-local ``abort on exception'' condition for
+ * <i>thr</i>. The default is <code>false</code>. See also
+ * <code>Thread::abort_on_exception=</code>.
+ */
+
static VALUE
rb_thread_abort_exc(thread)
VALUE thread;
@@ -9385,6 +12028,16 @@ rb_thread_abort_exc(thread)
return rb_thread_check(thread)->abort?Qtrue:Qfalse;
}
+
+/*
+ * call-seq:
+ * thr.abort_on_exception= boolean => true or false
+ *
+ * When set to <code>true</code>, causes all threads (including the main
+ * program) to abort if an exception is raised in <i>thr</i>. The process will
+ * effectively <code>exit(0)</code>.
+ */
+
static VALUE
rb_thread_abort_exc_set(thread, val)
VALUE thread, val;
@@ -9394,6 +12047,17 @@ rb_thread_abort_exc_set(thread, val)
return val;
}
+
+/*
+ * call-seq:
+ * thr.group => thgrp or nil
+ *
+ * Returns the <code>ThreadGroup</code> which contains <i>thr</i>, or nil if
+ * the thread is not a member of any group.
+ *
+ * Thread.main.group #=> #<ThreadGroup:0x4029d914>
+ */
+
VALUE
rb_thread_group(thread)
VALUE thread;
@@ -9405,14 +12069,14 @@ rb_thread_group(thread)
return group;
}
-#ifdef __ia64__
+#ifdef __ia64
# define IA64_INIT(x) x
#else
# define IA64_INIT(x)
#endif
#define THREAD_ALLOC(th) do {\
- th = ALLOC(struct thread);\
+ th = ALLOC(struct rb_thread);\
\
th->next = 0;\
th->prev = 0;\
@@ -9427,6 +12091,7 @@ rb_thread_group(thread)
th->wait_for = 0;\
IA64_INIT(th->bstr_ptr = 0);\
IA64_INIT(th->bstr_len = 0);\
+ IA64_INIT(th->bstr_max = 0);\
FD_ZERO(&th->readfds);\
FD_ZERO(&th->writefds);\
FD_ZERO(&th->exceptfds);\
@@ -9451,6 +12116,12 @@ rb_thread_group(thread)
th->priority = 0;\
th->thgroup = thgroup_default;\
th->locals = 0;\
+ th->thread = 0;\
+ if (curr_thread == 0) {\
+ th->sandbox = Qnil;\
+ } else {\
+ th->sandbox = curr_thread->sandbox;\
+ }\
} while (0)
static rb_thread_t
@@ -9470,7 +12141,9 @@ rb_thread_alloc(klass)
return th;
}
-#if defined(HAVE_SETITIMER)
+static int thread_init;
+
+#if defined(_THREAD_SAFE)
static void
catch_timer(sig)
int sig;
@@ -9478,19 +12151,64 @@ catch_timer(sig)
#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
signal(sig, catch_timer);
#endif
- if (!rb_thread_critical) {
- if (rb_trap_immediate) {
- rb_thread_schedule();
- }
- else rb_thread_pending = 1;
- }
+ /* cause EINTR */
}
+
+static pthread_t time_thread;
+
+static void*
+thread_timer(dummy)
+ void *dummy;
+{
+ sigset_t all_signals;
+
+ sigfillset(&all_signals);
+ pthread_sigmask(SIG_BLOCK, &all_signals, 0);
+
+ for (;;) {
+#ifdef HAVE_NANOSLEEP
+ struct timespec req, rem;
+
+ req.tv_sec = 0;
+ req.tv_nsec = 10000000;
+ nanosleep(&req, &rem);
#else
-int rb_thread_tick = THREAD_TICK;
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+ select(0, NULL, NULL, NULL, &tv);
#endif
+ if (!rb_thread_critical) {
+ rb_thread_pending = 1;
+ if (rb_trap_immediate) {
+ pthread_kill(ruby_thid, SIGVTALRM);
+ }
+ }
+ }
+}
+
+void
+rb_thread_start_timer()
+{
+}
-#if defined(HAVE_SETITIMER)
-static int thread_init = 0;
+void
+rb_thread_stop_timer()
+{
+}
+#elif defined(HAVE_SETITIMER)
+static void
+catch_timer(sig)
+ int sig;
+{
+#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
+ signal(sig, catch_timer);
+#endif
+ if (!rb_thread_critical) {
+ rb_thread_pending = 1;
+ }
+ /* cause EINTR */
+}
void
rb_thread_start_timer()
@@ -9515,6 +12233,8 @@ rb_thread_stop_timer()
tval.it_value = tval.it_interval;
setitimer(ITIMER_VIRTUAL, &tval, NULL);
}
+#else /* !(_THREAD_SAFE || HAVE_SETITIMER) */
+int rb_thread_tick = THREAD_TICK;
#endif
static VALUE
@@ -9525,8 +12245,8 @@ rb_thread_start_0(fn, arg, th)
{
volatile rb_thread_t th_save = th;
volatile VALUE thread = th->thread;
- struct BLOCK *volatile saved_block = 0, *block;
- enum thread_status status;
+ struct BLOCK *volatile saved_block = 0;
+ enum rb_thread_status status;
int state;
if (OBJ_FROZEN(curr_thread->thgroup)) {
@@ -9534,18 +12254,22 @@ rb_thread_start_0(fn, arg, th)
"can't start a new thread (frozen ThreadGroup)");
}
-#if defined(HAVE_SETITIMER)
if (!thread_init) {
-#ifdef POSIX_SIGNAL
+ thread_init = 1;
+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
+#if defined(POSIX_SIGNAL)
posix_signal(SIGVTALRM, catch_timer);
#else
signal(SIGVTALRM, catch_timer);
#endif
- thread_init = 1;
+#ifdef _THREAD_SAFE
+ pthread_create(&time_thread, 0, thread_timer, 0);
+#else
rb_thread_start_timer();
- }
#endif
+#endif
+ }
if (THREAD_SAVE_CONTEXT(curr_thread)) {
return thread;
@@ -9588,17 +12312,12 @@ rb_thread_start_0(fn, arg, th)
if (th == main_thread) ruby_stop(state);
rb_thread_remove(th);
- for (block = saved_block; block;) {
- struct BLOCK *tmp = block;
-
- if (tmp->frame.argc > 0)
- free(tmp->frame.argv);
- block = tmp->prev;
- free((void*)tmp);
+ if (saved_block) {
+ blk_free(saved_block);
}
if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) {
- th->flags |= THREAD_RAISED;
+ th->flags |= RAISED_EXCEPTION;
if (state == TAG_FATAL) {
/* fatal error within this thread, need to stop whole script */
main_thread->errinfo = ruby_errinfo;
@@ -9618,6 +12337,7 @@ rb_thread_start_0(fn, arg, th)
}
else if (th->safe < 4 && (ruby_thread_abort || th->abort || RTEST(ruby_debug))) {
/* exit on main_thread */
+ error_print();
rb_thread_main_jump(ruby_errinfo, RESTORE_EXIT);
}
else {
@@ -9634,7 +12354,7 @@ rb_thread_create(fn, arg)
VALUE (*fn)();
void *arg;
{
- Init_stack((VALUE*)&arg);
+ Init_stack((void *)&arg);
return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
}
@@ -9660,9 +12380,27 @@ rb_thread_yield(arg, th)
rb_dvar_push('~', Qnil);
ruby_block->dyna_vars = ruby_dyna_vars;
- return rb_yield_0(arg, 0, 0, Qtrue, Qtrue);
+ return rb_yield_0(arg, 0, 0, YIELD_LAMBDA_CALL, Qtrue);
}
+/*
+ * call-seq:
+ * Thread.new([arg]*) {|args| block } => thread
+ *
+ * Creates and runs a new thread to execute the instructions given in
+ * <i>block</i>. Any arguments passed to <code>Thread::new</code> are passed
+ * into the block.
+ *
+ * x = Thread.new { sleep 0.1; print "x"; print "y"; print "z" }
+ * a = Thread.new { print "a"; print "b"; sleep 0.2; print "c" }
+ * x.join # Let the threads finish before
+ * a.join # main thread exits...
+ *
+ * <em>produces:</em>
+ *
+ * abxyzc
+ */
+
static VALUE
rb_thread_s_new(argc, argv, klass)
int argc;
@@ -9682,16 +12420,57 @@ rb_thread_s_new(argc, argv, klass)
return th->thread;
}
+
+/*
+ * call-seq:
+ * Thread.new([arg]*) {|args| block } => thread
+ *
+ * Creates and runs a new thread to execute the instructions given in
+ * <i>block</i>. Any arguments passed to <code>Thread::new</code> are passed
+ * into the block.
+ *
+ * x = Thread.new { sleep 0.1; print "x"; print "y"; print "z" }
+ * a = Thread.new { print "a"; print "b"; sleep 0.2; print "c" }
+ * x.join # Let the threads finish before
+ * a.join # main thread exits...
+ *
+ * <em>produces:</em>
+ *
+ * abxyzc
+ */
+
static VALUE
rb_thread_initialize(thread, args)
VALUE thread, args;
{
+ rb_thread_t th;
+
if (!rb_block_given_p()) {
rb_raise(rb_eThreadError, "must be called with a block");
}
- return rb_thread_start_0(rb_thread_yield, args, rb_thread_check(thread));
+ th = rb_thread_check(thread);
+ if (th->stk_max) {
+ NODE *node = th->node;
+ if (!node) {
+ rb_raise(rb_eThreadError, "already initialized thread");
+ }
+ rb_raise(rb_eThreadError, "already initialized thread - %s:%d",
+ node->nd_file, nd_line(node));
+ }
+ return rb_thread_start_0(rb_thread_yield, args, th);
}
+
+/*
+ * call-seq:
+ * Thread.start([args]*) {|args| block } => thread
+ * Thread.fork([args]*) {|args| block } => thread
+ *
+ * Basically the same as <code>Thread::new</code>. However, if class
+ * <code>Thread</code> is subclassed, then calling <code>start</code> in that
+ * subclass will not invoke the subclass's <code>initialize</code> method.
+ */
+
static VALUE
rb_thread_start(klass, args)
VALUE klass, args;
@@ -9702,6 +12481,18 @@ rb_thread_start(klass, args)
return rb_thread_start_0(rb_thread_yield, args, rb_thread_alloc(klass));
}
+
+/*
+ * call-seq:
+ * thr.value => obj
+ *
+ * Waits for <i>thr</i> to complete (via <code>Thread#join</code>) and returns
+ * its value.
+ *
+ * a = Thread.new { 2 + 2 }
+ * a.value #=> 4
+ */
+
static VALUE
rb_thread_value(thread)
VALUE thread;
@@ -9713,6 +12504,30 @@ rb_thread_value(thread)
return th->result;
}
+
+/*
+ * call-seq:
+ * thr.status => string, false or nil
+ *
+ * Returns the status of <i>thr</i>: ``<code>sleep</code>'' if <i>thr</i> is
+ * sleeping or waiting on I/O, ``<code>run</code>'' if <i>thr</i> is executing,
+ * ``<code>aborting</code>'' if <i>thr</i> is aborting, <code>false</code> if
+ * <i>thr</i> terminated normally, and <code>nil</code> if <i>thr</i>
+ * terminated with an exception.
+ *
+ * a = Thread.new { raise("die now") }
+ * b = Thread.new { Thread.stop }
+ * c = Thread.new { Thread.exit }
+ * d = Thread.new { sleep }
+ * Thread.critical = true
+ * d.kill #=> #<Thread:0x401b3678 aborting>
+ * a.status #=> nil
+ * b.status #=> "sleep"
+ * c.status #=> false
+ * d.status #=> "aborting"
+ * Thread.current.status #=> "run"
+ */
+
static VALUE
rb_thread_status(thread)
VALUE thread;
@@ -9720,7 +12535,7 @@ rb_thread_status(thread)
rb_thread_t th = rb_thread_check(thread);
if (rb_thread_dead(th)) {
- if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED))
+ if (!NIL_P(th->errinfo) && (th->flags & RAISED_EXCEPTION))
return Qnil;
return Qfalse;
}
@@ -9728,7 +12543,20 @@ rb_thread_status(thread)
return rb_str_new2(thread_status_name(th->status));
}
-static VALUE
+
+/*
+ * call-seq:
+ * thr.alive? => true or false
+ *
+ * Returns <code>true</code> if <i>thr</i> is running or sleeping.
+ *
+ * thr = Thread.new { }
+ * thr.join #=> #<Thread:0x401b3fb0 dead>
+ * Thread.current.alive? #=> true
+ * thr.alive? #=> false
+ */
+
+VALUE
rb_thread_alive_p(thread)
VALUE thread;
{
@@ -9738,6 +12566,19 @@ rb_thread_alive_p(thread)
return Qtrue;
}
+
+/*
+ * call-seq:
+ * thr.stop? => true or false
+ *
+ * Returns <code>true</code> if <i>thr</i> is dead or sleeping.
+ *
+ * a = Thread.new { Thread.stop }
+ * b = Thread.current
+ * a.stop? #=> true
+ * b.stop? #=> false
+ */
+
static VALUE
rb_thread_stop_p(thread)
VALUE thread;
@@ -9796,12 +12637,35 @@ rb_thread_cleanup()
int rb_thread_critical;
+
+/*
+ * call-seq:
+ * Thread.critical => true or false
+ *
+ * Returns the status of the global ``thread critical'' condition.
+ */
+
static VALUE
rb_thread_critical_get()
{
return rb_thread_critical?Qtrue:Qfalse;
}
+
+/*
+ * call-seq:
+ * Thread.critical= boolean => true or false
+ *
+ * Sets the status of the global ``thread critical'' condition and returns
+ * it. When set to <code>true</code>, prohibits scheduling of any existing
+ * thread. Does not block new threads from being created and run. Certain
+ * thread operations (such as stopping or killing a thread, sleeping in the
+ * current thread, and raising an exception) may cause a thread to be scheduled
+ * even when in a critical section. <code>Thread::critical</code> is not
+ * intended for daily use: it is primarily there to support folks writing
+ * threading libraries.
+ */
+
static VALUE
rb_thread_critical_set(obj, val)
VALUE obj, val;
@@ -9829,13 +12693,15 @@ rb_thread_interrupt()
void
rb_thread_signal_raise(sig)
- char *sig;
+ int sig;
{
- if (sig == 0) return; /* should not happen */
rb_thread_critical = 0;
if (curr_thread == main_thread) {
+ VALUE argv[1];
+
rb_thread_ready(curr_thread);
- rb_raise(rb_eSignal, "SIG%s", sig);
+ argv[0] = INT2FIX(sig);
+ rb_exc_raise(rb_class_new_instance(1, argv, rb_eSignal));
}
rb_thread_ready(main_thread);
if (!rb_thread_dead(curr_thread)) {
@@ -9843,17 +12709,21 @@ rb_thread_signal_raise(sig)
return;
}
}
- th_signm = sig;
+ th_sig = sig;
curr_thread = main_thread;
rb_thread_restore_context(curr_thread, RESTORE_SIGNAL);
}
void
-rb_thread_trap_eval(cmd, sig)
+rb_thread_trap_eval(cmd, sig, safe)
VALUE cmd;
- int sig;
+ int sig, safe;
{
rb_thread_critical = 0;
+ if (curr_thread == main_thread) {
+ rb_trap_eval(cmd, sig, safe);
+ return;
+ }
if (!rb_thread_dead(curr_thread)) {
if (THREAD_SAVE_CONTEXT(curr_thread)) {
return;
@@ -9861,10 +12731,33 @@ rb_thread_trap_eval(cmd, sig)
}
th_cmd = cmd;
th_sig = sig;
+ th_safe = safe;
curr_thread = main_thread;
rb_thread_restore_context(curr_thread, RESTORE_TRAP);
}
+void
+rb_thread_signal_exit()
+{
+ VALUE args[2];
+
+ rb_thread_critical = 0;
+ if (curr_thread == main_thread) {
+ rb_thread_ready(curr_thread);
+ rb_exit(EXIT_SUCCESS);
+ }
+ args[0] = INT2NUM(EXIT_SUCCESS);
+ args[1] = rb_str_new2("exit");
+ rb_thread_ready(main_thread);
+ if (!rb_thread_dead(curr_thread)) {
+ if (THREAD_SAVE_CONTEXT(curr_thread)) {
+ return;
+ }
+ }
+ rb_thread_main_jump(rb_class_new_instance(2, args, rb_eSystemExit),
+ RESTORE_EXIT);
+}
+
static VALUE
rb_thread_raise(argc, argv, th)
int argc;
@@ -9872,10 +12765,15 @@ rb_thread_raise(argc, argv, th)
rb_thread_t th;
{
volatile rb_thread_t th_save = th;
+ VALUE exc;
+ if (!th->next) {
+ rb_raise(rb_eArgError, "unstarted thread");
+ }
if (rb_thread_dead(th)) return Qnil;
+ exc = rb_make_exception(argc, argv);
if (curr_thread == th) {
- rb_f_raise(argc, argv);
+ rb_raise_jump(exc);
}
if (!rb_thread_dead(curr_thread)) {
@@ -9884,16 +12782,35 @@ rb_thread_raise(argc, argv, th)
}
}
- rb_scan_args(argc, argv, "11", &th_raise_argv[0], &th_raise_argv[1]);
rb_thread_ready(th);
curr_thread = th;
- th_raise_argc = argc;
+ th_raise_exception = exc;
th_raise_node = ruby_current_node;
rb_thread_restore_context(curr_thread, RESTORE_RAISE);
return Qnil; /* not reached */
}
+
+/*
+ * call-seq:
+ * thr.raise(exception)
+ *
+ * Raises an exception (see <code>Kernel::raise</code>) from <i>thr</i>. The
+ * caller does not have to be <i>thr</i>.
+ *
+ * Thread.abort_on_exception = true
+ * a = Thread.new { sleep(200) }
+ * a.raise("Gotcha")
+ *
+ * <em>produces:</em>
+ *
+ * prog.rb:3: Gotcha (RuntimeError)
+ * from prog.rb:2:in `initialize'
+ * from prog.rb:2:in `new'
+ * from prog.rb:2
+ */
+
static VALUE
rb_thread_raise_m(argc, argv, thread)
int argc;
@@ -9928,6 +12845,28 @@ rb_thread_local_aref(thread, id)
return Qnil;
}
+
+/*
+ * call-seq:
+ * thr[sym] => obj or nil
+ *
+ * Attribute Reference---Returns the value of a thread-local variable, using
+ * either a symbol or a string name. If the specified variable does not exist,
+ * returns <code>nil</code>.
+ *
+ * a = Thread.new { Thread.current["name"] = "A"; Thread.stop }
+ * b = Thread.new { Thread.current[:name] = "B"; Thread.stop }
+ * c = Thread.new { Thread.current["name"] = "C"; Thread.stop }
+ * Thread.list.each {|x| puts "#{x.inspect}: #{x[:name]}" }
+ *
+ * <em>produces:</em>
+ *
+ * #<Thread:0x401b3b3c sleep>: C
+ * #<Thread:0x401b3bc8 sleep>: B
+ * #<Thread:0x401b3c68 sleep>: A
+ * #<Thread:0x401bdf4c run>:
+ */
+
static VALUE
rb_thread_aref(thread, id)
VALUE thread, id;
@@ -9960,6 +12899,15 @@ rb_thread_local_aset(thread, id, val)
return val;
}
+
+/*
+ * call-seq:
+ * thr[sym] = obj => obj
+ *
+ * Attribute Assignment---Sets or creates the value of a thread-local variable,
+ * using either a symbol or a string. See also <code>Thread#[]</code>.
+ */
+
static VALUE
rb_thread_aset(thread, id, val)
VALUE thread, id, val;
@@ -9967,6 +12915,20 @@ rb_thread_aset(thread, id, val)
return rb_thread_local_aset(thread, rb_to_id(id), val);
}
+
+/*
+ * call-seq:
+ * thr.key?(sym) => true or false
+ *
+ * Returns <code>true</code> if the given string (or symbol) exists as a
+ * thread-local variable.
+ *
+ * me = Thread.current
+ * me[:oliver] = "a"
+ * me.key?(:oliver) #=> true
+ * me.key?(:stanley) #=> false
+ */
+
static VALUE
rb_thread_key_p(thread, id)
VALUE thread, id;
@@ -9988,6 +12950,21 @@ thread_keys_i(key, value, ary)
return ST_CONTINUE;
}
+
+/*
+ * call-seq:
+ * thr.keys => array
+ *
+ * Returns an an array of the names of the thread-local variables (as Symbols).
+ *
+ * thr = Thread.new do
+ * Thread.current[:cat] = 'meow'
+ * Thread.current["dog"] = 'woof'
+ * end
+ * thr.join #=> #<Thread:0x401b3f10 dead>
+ * thr.keys #=> [:dog, :cat]
+ */
+
static VALUE
rb_thread_keys(thread)
VALUE thread;
@@ -10001,17 +12978,25 @@ rb_thread_keys(thread)
return ary;
}
+/*
+ * call-seq:
+ * thr.inspect => string
+ *
+ * Dump the name, id, and status of _thr_ to a string.
+ */
+
static VALUE
rb_thread_inspect(thread)
VALUE thread;
{
- char *cname = rb_obj_classname(thread);
+ const char *cname = rb_obj_classname(thread);
rb_thread_t th = rb_thread_check(thread);
const char *status = thread_status_name(th->status);
VALUE str;
+ size_t len = strlen(cname)+7+16+9+1;
- str = rb_str_new(0, strlen(cname)+7+16+9+1); /* 7:tags 16:addr 9:status 1:nul */
- sprintf(RSTRING(str)->ptr, "#<%s:0x%lx %s>", cname, thread, status);
+ str = rb_str_new(0, len); /* 7:tags 16:addr 9:status 1:nul */
+ snprintf(RSTRING(str)->ptr, len, "#<%s:0x%lx %s>", cname, thread, status);
RSTRING(str)->len = strlen(RSTRING(str)->ptr);
OBJ_INFECT(str, thread);
@@ -10026,7 +13011,6 @@ rb_thread_atfork()
if (rb_thread_alone()) return;
FOREACH_THREAD(th) {
if (th != curr_thread) {
- rb_warn("fork terminates thread at %s:%d", th->node->nd_file, nd_line(th->node));
rb_thread_die(th);
}
}
@@ -10036,7 +13020,101 @@ rb_thread_atfork()
curr_thread->prev = curr_thread;
}
-static VALUE rb_cCont;
+
+static void
+cc_purge(cc)
+ rb_thread_t cc;
+{
+ /* free continuation's stack if it has just died */
+ if (NIL_P(cc->thread)) return;
+ if (rb_thread_check(cc->thread)->status == THREAD_KILLED) {
+ cc->thread = Qnil;
+ rb_thread_die(cc); /* can't possibly activate this stack */
+ }
+}
+
+static void
+cc_mark(cc)
+ rb_thread_t cc;
+{
+ /* mark this continuation's stack only if its parent thread is still alive */
+ cc_purge(cc);
+ thread_mark(cc);
+}
+
+static rb_thread_t
+rb_cont_check(data)
+ VALUE data;
+{
+ if (TYPE(data) != T_DATA || RDATA(data)->dmark != (RUBY_DATA_FUNC)cc_mark) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Continuation)",
+ rb_obj_classname(data));
+ }
+ return (rb_thread_t)RDATA(data)->data;
+}
+
+/*
+ * Document-class: Continuation
+ *
+ * Continuation objects are generated by
+ * <code>Kernel#callcc</code>. They hold a return address and execution
+ * context, allowing a nonlocal return to the end of the
+ * <code>callcc</code> block from anywhere within a program.
+ * Continuations are somewhat analogous to a structured version of C's
+ * <code>setjmp/longjmp</code> (although they contain more state, so
+ * you might consider them closer to threads).
+ *
+ * For instance:
+ *
+ * arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
+ * callcc{|$cc|}
+ * puts(message = arr.shift)
+ * $cc.call unless message =~ /Max/
+ *
+ * <em>produces:</em>
+ *
+ * Freddie
+ * Herbie
+ * Ron
+ * Max
+ *
+ * This (somewhat contrived) example allows the inner loop to abandon
+ * processing early:
+ *
+ * callcc {|cont|
+ * for i in 0..4
+ * print "\n#{i}: "
+ * for j in i*5...(i+1)*5
+ * cont.call() if j == 17
+ * printf "%3d", j
+ * end
+ * end
+ * }
+ * print "\n"
+ *
+ * <em>produces:</em>
+ *
+ * 0: 0 1 2 3 4
+ * 1: 5 6 7 8 9
+ * 2: 10 11 12 13 14
+ * 3: 15 16
+ */
+
+VALUE rb_cCont;
+
+/*
+ * call-seq:
+ * callcc {|cont| block } => obj
+ *
+ * Generates a <code>Continuation</code> object, which it passes to the
+ * associated block. Performing a <em>cont</em><code>.call</code> will
+ * cause the <code>callcc</code> to return (as will falling through the
+ * end of the block). The value returned by the <code>callcc</code> is
+ * the value of the block, or the value passed to
+ * <em>cont</em><code>.call</code>. See class <code>Continuation</code>
+ * for more details. Also see <code>Kernel::throw</code> for
+ * an alternative mechanism for unwinding a call stack.
+ */
static VALUE
rb_callcc(self)
@@ -10049,19 +13127,21 @@ rb_callcc(self)
struct RVarmap *vars;
THREAD_ALLOC(th);
- cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
+ /* must finish th initialization before any possible gc.
+ * brent@mbari.org */
+ th->thread = curr_thread->thread;
+ th->thgroup = cont_protect;
+ cont = Data_Wrap_Struct(rb_cCont, cc_mark, thread_free, th);
scope_dup(ruby_scope);
for (tag=prot_tag; tag; tag=tag->prev) {
scope_dup(tag->scope);
}
- th->thread = curr_thread->thread;
- for (vars = th->dyna_vars; vars; vars = vars->next) {
+ for (vars = ruby_dyna_vars; vars; vars = vars->next) {
if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
FL_SET(vars, DVAR_DONT_RECYCLE);
}
-
th_save = th;
if (THREAD_SAVE_CONTEXT(th)) {
return th_save->result;
@@ -10071,17 +13151,36 @@ rb_callcc(self)
}
}
+/*
+ * call-seq:
+ * cont.call(args, ...)
+ * cont[args, ...]
+ *
+ * Invokes the continuation. The program continues from the end of the
+ * <code>callcc</code> block. If no arguments are given, the original
+ * <code>callcc</code> returns <code>nil</code>. If one argument is
+ * given, <code>callcc</code> returns it. Otherwise, an array
+ * containing <i>args</i> is returned.
+ *
+ * callcc {|cont| cont.call } #=> nil
+ * callcc {|cont| cont.call 1 } #=> 1
+ * callcc {|cont| cont.call 1, 2, 3 } #=> [1, 2, 3]
+ */
+
static VALUE
rb_cont_call(argc, argv, cont)
int argc;
VALUE *argv;
VALUE cont;
{
- rb_thread_t th = rb_thread_check(cont);
+ rb_thread_t th = rb_cont_check(cont);
if (th->thread != curr_thread->thread) {
rb_raise(rb_eRuntimeError, "continuation called across threads");
}
+ if (th->thgroup != cont_protect) {
+ rb_raise(rb_eRuntimeError, "continuation called across trap");
+ }
switch (argc) {
case 0:
th->result = Qnil;
@@ -10103,6 +13202,19 @@ struct thgroup {
VALUE group;
};
+
+/*
+ * Document-class: ThreadGroup
+ *
+ * <code>ThreadGroup</code> provides a means of keeping track of a number of
+ * threads as a group. A <code>Thread</code> can belong to only one
+ * <code>ThreadGroup</code> at a time; adding a thread to a new group will
+ * remove it from any previous group.
+ *
+ * Newly created threads belong to the same group as the thread from which they
+ * were created.
+ */
+
static VALUE thgroup_s_alloc _((VALUE));
static VALUE
thgroup_s_alloc(klass)
@@ -10118,6 +13230,17 @@ thgroup_s_alloc(klass)
return group;
}
+
+/*
+ * call-seq:
+ * thgrp.list => array
+ *
+ * Returns an array of all existing <code>Thread</code> objects that belong to
+ * this group.
+ *
+ * ThreadGroup::Default.list #=> [#<Thread:0x401bdf4c run>]
+ */
+
static VALUE
thgroup_list(group)
VALUE group;
@@ -10139,7 +13262,26 @@ thgroup_list(group)
return ary;
}
-VALUE
+
+/*
+ * call-seq:
+ * thgrp.enclose => thgrp
+ *
+ * Prevents threads from being added to or removed from the receiving
+ * <code>ThreadGroup</code>. New threads can still be started in an enclosed
+ * <code>ThreadGroup</code>.
+ *
+ * ThreadGroup::Default.enclose #=> #<ThreadGroup:0x4029d914>
+ * thr = Thread::new { Thread.stop } #=> #<Thread:0x402a7210 sleep>
+ * tg = ThreadGroup::new #=> #<ThreadGroup:0x402752d4>
+ * tg.add thr
+ *
+ * <em>produces:</em>
+ *
+ * ThreadError: can't move from the enclosed thread group
+ */
+
+static VALUE
thgroup_enclose(group)
VALUE group;
{
@@ -10151,6 +13293,15 @@ thgroup_enclose(group)
return group;
}
+
+/*
+ * call-seq:
+ * thgrp.enclosed? => true or false
+ *
+ * Returns <code>true</code> if <em>thgrp</em> is enclosed. See also
+ * ThreadGroup#enclose.
+ */
+
static VALUE
thgroup_enclosed_p(group)
VALUE group;
@@ -10162,6 +13313,33 @@ thgroup_enclosed_p(group)
return Qfalse;
}
+
+/*
+ * call-seq:
+ * thgrp.add(thread) => thgrp
+ *
+ * Adds the given <em>thread</em> to this group, removing it from any other
+ * group to which it may have previously belonged.
+ *
+ * puts "Initial group is #{ThreadGroup::Default.list}"
+ * tg = ThreadGroup.new
+ * t1 = Thread.new { sleep }
+ * t2 = Thread.new { sleep }
+ * puts "t1 is #{t1}"
+ * puts "t2 is #{t2}"
+ * tg.add(t1)
+ * puts "Initial group now #{ThreadGroup::Default.list}"
+ * puts "tg group now #{tg.list}"
+ *
+ * <em>produces:</em>
+ *
+ * Initial group is #<Thread:0x401bdf4c>
+ * t1 is #<Thread:0x401b3c90>
+ * t2 is #<Thread:0x401b3c18>
+ * Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
+ * tg group now #<Thread:0x401b3c90>
+ */
+
static VALUE
thgroup_add(group, thread)
VALUE group, thread;
@@ -10195,11 +13373,125 @@ thgroup_add(group, thread)
return group;
}
+
+/* variables for recursive traversals */
+static ID recursive_key;
+
+static VALUE
+recursive_check(hash, obj)
+ VALUE hash;
+ VALUE obj;
+{
+ if (NIL_P(hash) || TYPE(hash) != T_HASH) {
+ return Qfalse;
+ }
+ else {
+ VALUE list = rb_hash_aref(hash, ID2SYM(rb_frame_last_func()));
+
+ if (NIL_P(list) || TYPE(list) != T_HASH)
+ return Qfalse;
+ if (NIL_P(rb_hash_lookup(list, obj)))
+ return Qfalse;
+ return Qtrue;
+ }
+}
+
+static VALUE
+recursive_push(hash, obj)
+ VALUE hash;
+ VALUE obj;
+{
+ VALUE list, sym;
+
+ sym = ID2SYM(rb_frame_last_func());
+ if (NIL_P(hash) || TYPE(hash) != T_HASH) {
+ hash = rb_hash_new();
+ rb_thread_local_aset(rb_thread_current(), recursive_key, hash);
+ list = Qnil;
+ }
+ else {
+ list = rb_hash_aref(hash, sym);
+ }
+ if (NIL_P(list) || TYPE(list) != T_HASH) {
+ list = rb_hash_new();
+ rb_hash_aset(hash, sym, list);
+ }
+ rb_hash_aset(list, obj, Qtrue);
+ return hash;
+}
+
+static void
+recursive_pop(hash, obj)
+ VALUE hash;
+ VALUE obj;
+{
+ VALUE list, sym;
+
+ sym = ID2SYM(rb_frame_last_func());
+ if (NIL_P(hash) || TYPE(hash) != T_HASH) {
+ VALUE symname;
+ VALUE thrname;
+ symname = rb_inspect(sym);
+ thrname = rb_inspect(rb_thread_current());
+
+ rb_raise(rb_eTypeError, "invalid inspect_tbl hash for %s in %s",
+ StringValuePtr(symname), StringValuePtr(thrname));
+ }
+ list = rb_hash_aref(hash, sym);
+ if (NIL_P(list) || TYPE(list) != T_HASH) {
+ VALUE symname = rb_inspect(sym);
+ VALUE thrname = rb_inspect(rb_thread_current());
+ rb_raise(rb_eTypeError, "invalid inspect_tbl list for %s in %s",
+ StringValuePtr(symname), StringValuePtr(thrname));
+ }
+ rb_hash_delete(list, obj);
+}
+
+VALUE
+rb_exec_recursive(func, obj, arg)
+ VALUE (*func) _((VALUE, VALUE, int));
+ VALUE obj;
+ VALUE arg;
+{
+ VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
+ VALUE objid = rb_obj_id(obj);
+
+ if (recursive_check(hash, objid)) {
+ return (*func) (obj, arg, Qtrue);
+ }
+ else {
+ VALUE result = Qundef;
+ int state;
+
+ hash = recursive_push(hash, objid);
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ result = (*func) (obj, arg, Qfalse);
+ }
+ POP_TAG();
+ recursive_pop(hash, objid);
+ if (state)
+ JUMP_TAG(state);
+ return result;
+ }
+}
+
+
+/*
+ * +Thread+ encapsulates the behavior of a thread of
+ * execution, including the main thread of the Ruby script.
+ *
+ * In the descriptions of the methods in this class, the parameter _sym_
+ * refers to a symbol, which is either a quoted string or a
+ * +Symbol+ (such as <code>:name</code>).
+ */
+
void
Init_Thread()
{
VALUE cThGroup;
+ recursive_key = rb_intern("__recursive_key__");
rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
rb_cThread = rb_define_class("Thread", rb_cObject);
rb_undef_alloc_func(rb_cThread);
@@ -10228,6 +13520,9 @@ Init_Thread()
rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
rb_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
+ rb_define_method(rb_cThread, "kill!", rb_thread_kill_bang, 0);
+ rb_define_method(rb_cThread, "terminate!", rb_thread_kill_bang, 0);
+ rb_define_method(rb_cThread, "exit!", rb_thread_kill_bang, 0);
rb_define_method(rb_cThread, "value", rb_thread_value, 0);
rb_define_method(rb_cThread, "status", rb_thread_status, 0);
rb_define_method(rb_cThread, "join", rb_thread_join_m, -1);
@@ -10256,6 +13551,7 @@ Init_Thread()
rb_define_method(rb_cCont, "call", rb_cont_call, -1);
rb_define_method(rb_cCont, "[]", rb_cont_call, -1);
rb_define_global_function("callcc", rb_callcc, 0);
+ rb_global_variable(&cont_protect);
cThGroup = rb_define_class("ThreadGroup", rb_cObject);
rb_define_alloc_func(cThGroup, thgroup_s_alloc);
@@ -10263,15 +13559,46 @@ Init_Thread()
rb_define_method(cThGroup, "enclose", thgroup_enclose, 0);
rb_define_method(cThGroup, "enclosed?", thgroup_enclosed_p, 0);
rb_define_method(cThGroup, "add", thgroup_add, 1);
+ rb_global_variable(&thgroup_default);
thgroup_default = rb_obj_alloc(cThGroup);
rb_define_const(cThGroup, "Default", thgroup_default);
- rb_global_variable(&thgroup_default);
/* allocate main thread */
main_thread = rb_thread_alloc(rb_cThread);
curr_thread = main_thread->prev = main_thread->next = main_thread;
}
+/*
+ * call-seq:
+ * catch(symbol) {| | block } > obj
+ *
+ * +catch+ executes its block. If a +throw+ is
+ * executed, Ruby searches up its stack for a +catch+ block
+ * with a tag corresponding to the +throw+'s
+ * _symbol_. If found, that block is terminated, and
+ * +catch+ returns the value given to +throw+. If
+ * +throw+ is not called, the block terminates normally, and
+ * the value of +catch+ is the value of the last expression
+ * evaluated. +catch+ expressions may be nested, and the
+ * +throw+ call need not be in lexical scope.
+ *
+ * def routine(n)
+ * puts n
+ * throw :done if n <= 0
+ * routine(n-1)
+ * end
+ *
+ *
+ * catch(:done) { routine(3) }
+ *
+ * <em>produces:</em>
+ *
+ * 3
+ * 2
+ * 1
+ * 0
+ */
+
static VALUE
rb_f_catch(dmy, tag)
VALUE dmy, tag;
@@ -10282,7 +13609,7 @@ rb_f_catch(dmy, tag)
tag = ID2SYM(rb_to_id(tag));
PUSH_TAG(tag);
if ((state = EXEC_TAG()) == 0) {
- val = rb_yield_0(tag, 0, 0, Qfalse, Qfalse);
+ val = rb_yield_0(tag, 0, 0, 0, Qfalse);
}
else if (state == TAG_THROW && tag == prot_tag->dst) {
val = prot_tag->retval;
@@ -10310,6 +13637,18 @@ rb_catch(tag, func, data)
return rb_iterate((VALUE(*)_((VALUE)))catch_i, ID2SYM(rb_intern(tag)), func, data);
}
+/*
+ * call-seq:
+ * throw(symbol [, obj])
+ *
+ * Transfers control to the end of the active +catch+ block
+ * waiting for _symbol_. Raises +NameError+ if there
+ * is no +catch+ block for the symbol. The optional second
+ * parameter supplies a return value for the +catch+ block,
+ * which otherwise defaults to +nil+. For examples, see
+ * <code>Kernel::catch</code>.
+ */
+
static VALUE
rb_f_throw(argc, argv)
int argc;
diff --git a/ext/.document b/ext/.document
new file mode 100644
index 0000000000..ba8182593e
--- /dev/null
+++ b/ext/.document
@@ -0,0 +1,11 @@
+# Add files to this as they become documented
+
+enumerator/enumerator.c
+iconv/iconv.c
+nkf/lib/kconv.rb
+nkf/nkf.c
+socket/socket.c
+stringio/stringio.c
+strscan/strscan.c
+win32ole
+zlib/zlib.c
diff --git a/ext/Setup b/ext/Setup
index 7b214abde3..d0d6317a5e 100644
--- a/ext/Setup
+++ b/ext/Setup
@@ -28,6 +28,7 @@
#syck
#syslog
#tcltklib
+#thread
#tk
#win32ole
#zlib
diff --git a/ext/Setup.atheos b/ext/Setup.atheos
index 9b1bdecb95..6bda3a4cfb 100644
--- a/ext/Setup.atheos
+++ b/ext/Setup.atheos
@@ -28,6 +28,7 @@ strscan
syck
syslog
#tcltklib
+thread
#tk
#win32ole
zlib
diff --git a/ext/Setup.dj b/ext/Setup.dj
index f2ed3a4f16..4f94788886 100644
--- a/ext/Setup.dj
+++ b/ext/Setup.dj
@@ -28,6 +28,7 @@ strscan
syck
#syslog
#tcltklib
+thread
#tk
#win32ole
zlib
diff --git a/ext/Setup.emx b/ext/Setup.emx
index 7ea04543c5..afc5923577 100644
--- a/ext/Setup.emx
+++ b/ext/Setup.emx
@@ -28,6 +28,7 @@ strscan
#syck
#syslog
#tcltklib
+thread
#tk
#win32ole
#zlib
diff --git a/ext/Setup.nt b/ext/Setup.nt
index 7a330f801a..9f8abf9b8d 100644
--- a/ext/Setup.nt
+++ b/ext/Setup.nt
@@ -28,6 +28,7 @@ strscan
syck
#syslog
#tcltklib
+thread
#tk
win32ole
#zlib
diff --git a/ext/Setup.x68 b/ext/Setup.x68
index 9b9563d941..0966e737e9 100644
--- a/ext/Setup.x68
+++ b/ext/Setup.x68
@@ -28,6 +28,7 @@ strscan
#syck
#syslog
#tcltklib
+thread
#tk
#win32ole
#zlib
diff --git a/ext/Win32API/MANIFEST b/ext/Win32API/MANIFEST
deleted file mode 100644
index a4dcaa858e..0000000000
--- a/ext/Win32API/MANIFEST
+++ /dev/null
@@ -1,8 +0,0 @@
-MANIFEST
-depend
-Win32API.c
-extconf.rb
-getch.rb
-point.rb
-lib/win32/registry.rb
-lib/win32/resolv.rb
diff --git a/ext/Win32API/Win32API.c b/ext/Win32API/Win32API.c
index 776df56ecb..a4fd0396f0 100644
--- a/ext/Win32API/Win32API.c
+++ b/ext/Win32API/Win32API.c
@@ -53,12 +53,12 @@ Win32API_initialize(self, dllname, proc, import, export)
hdll = LoadLibrary(RSTRING(dllname)->ptr);
if (!hdll)
rb_raise(rb_eRuntimeError, "LoadLibrary: %s\n", RSTRING(dllname)->ptr);
- rb_iv_set(self, "__hdll__", Data_Wrap_Struct(rb_cData, 0, Win32API_FreeLibrary, hdll));
- hproc = GetProcAddress(hdll, RSTRING(proc)->ptr);
+ rb_iv_set(self, "__hdll__", Data_Wrap_Struct(rb_cData, 0, Win32API_FreeLibrary, (void*)hdll));
+ hproc = (HANDLE)GetProcAddress(hdll, RSTRING(proc)->ptr);
if (!hproc) {
str = rb_str_new3(proc);
str = rb_str_cat(str, "A", 1);
- hproc = GetProcAddress(hdll, RSTRING(str)->ptr);
+ hproc = (HANDLE)GetProcAddress(hdll, RSTRING(str)->ptr);
if (!hproc)
rb_raise(rb_eRuntimeError, "GetProcAddress: %s or %s\n",
RSTRING(proc)->ptr, RSTRING(str)->ptr);
@@ -108,7 +108,7 @@ Win32API_initialize(self, dllname, proc, import, export)
}
if (16 < RARRAY(a_import)->len) {
- rb_raise(rb_eRuntimeError, "too many parameters: %d\n", RARRAY(a_import)->len);
+ rb_raise(rb_eRuntimeError, "too many parameters: %ld\n", RARRAY(a_import)->len);
}
rb_iv_set(self, "__import__", a_import);
@@ -137,6 +137,9 @@ Win32API_initialize(self, dllname, proc, import, export)
return Qnil;
}
+#ifdef _MSC_VER
+#pragma optimize("g", off)
+#endif
static VALUE
Win32API_Call(argc, argv, obj)
int argc;
@@ -160,7 +163,7 @@ Win32API_Call(argc, argv, obj)
if (items != nimport)
- rb_raise(rb_eRuntimeError, "Wrong number of parameters: expected %d, got %d.\n",
+ rb_raise(rb_eRuntimeError, "wrong number of parameters: expected %d, got %d",
nimport, items);
for (i = 0; i < nimport; i++) {
diff --git a/ext/Win32API/extconf.rb b/ext/Win32API/extconf.rb
index 134a6e5b92..865788556f 100644
--- a/ext/Win32API/extconf.rb
+++ b/ext/Win32API/extconf.rb
@@ -1,5 +1,6 @@
require 'mkmf'
+dir_config("win32")
if have_header("windows.h") and have_library("kernel32")
create_makefile("Win32API")
end
diff --git a/ext/Win32API/lib/win32/registry.rb b/ext/Win32API/lib/win32/registry.rb
index 2671551a33..9a2f3827b7 100644
--- a/ext/Win32API/lib/win32/registry.rb
+++ b/ext/Win32API/lib/win32/registry.rb
@@ -493,7 +493,7 @@ module Win32
# utility functions
#
def self.expand_environ(str)
- str.gsub(/%([^%]+)%/) { ENV[$1] || $& }
+ str.gsub(/%([^%]+)%/) { ENV[$1] || ENV[$1.upcase] || $& }
end
@@type2name = { }
diff --git a/ext/Win32API/lib/win32/resolv.rb b/ext/Win32API/lib/win32/resolv.rb
index 5a99d04d55..92336fac28 100644
--- a/ext/Win32API/lib/win32/resolv.rb
+++ b/ext/Win32API/lib/win32/resolv.rb
@@ -11,7 +11,7 @@ module Win32
def self.get_hosts_path
path = get_hosts_dir
- path = File.join(path.gsub(/\\/, File::SEPARATOR), 'hosts')
+ path = File.expand_path('hosts', path)
File.exist?(path) ? path : nil
end
@@ -84,7 +84,7 @@ if info.unpack('V5')[4] == 2 # VER_PLATFORM_WIN32_NT
[ 'NameServer', 'DhcpNameServer' ].each do |key|
ns = regif.read_s(key)
unless ns.empty?
- nameserver.concat(ns.split(/\s+/))
+ nameserver.concat(ns.split(/[,\s]\s*/))
break
end
end
@@ -141,7 +141,7 @@ else
slist = reg.read_s("SearchList")
search << domain unless domain.empty?
search.concat(slist.split(/,\s*/))
- nameserver.concat(ns.split(/,\s*/))
+ nameserver.concat(ns.split(/[,\s]\s*/))
end
end
rescue Registry::Error
diff --git a/ext/bigdecimal/MANIFEST b/ext/bigdecimal/MANIFEST
deleted file mode 100644
index bb647c3414..0000000000
--- a/ext/bigdecimal/MANIFEST
+++ /dev/null
@@ -1,18 +0,0 @@
-MANIFEST
-README
-bigdecimal.def
-bigdecimal.c
-bigdecimal.h
-depend
-extconf.rb
-bigdecimal_en.html
-bigdecimal_ja.html
-lib/bigdecimal/jacobian.rb
-lib/bigdecimal/newton.rb
-lib/bigdecimal/ludcmp.rb
-lib/bigdecimal/util.rb
-lib/bigdecimal/nlsolve.rb
-lib/bigdecimal/math.rb
-sample/linear.rb
-sample/nlsolve.rb
-sample/pi.rb
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index ae5f7a0895..7400b313a4 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -13,6 +13,7 @@
*
*/
+#include "ruby.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
@@ -20,7 +21,6 @@
#include <errno.h>
#include <float.h>
#include <math.h>
-#include "ruby.h"
#include "math.h"
#include "version.h"
@@ -41,8 +41,123 @@ VALUE rb_cBigDecimal;
*/
#define DoSomeOne(x,y) rb_num_coerce_bin(x,y)
+#if 0
+/* BigDecimal provides arbitrary-precision floating point decimal arithmetic.
+ *
+ * Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Artistic License, as specified in the README file
+ * of the BigDecimal distribution.
+ *
+ * Documented by mathew <meta@pobox.com>.
+ *
+ * = Introduction
+ *
+ * Ruby provides built-in support for arbitrary precision integer arithmetic.
+ * For example:
+ *
+ * 42**13 -> 1265437718438866624512
+ *
+ * BigDecimal provides similar support for very large or very accurate floating
+ * point numbers.
+ *
+ * Decimal arithmetic is also useful for general calculation, because it
+ * provides the correct answers people expect--whereas normal binary floating
+ * point arithmetic often introduces subtle errors because of the conversion
+ * between base 10 and base 2. For example, try:
+ *
+ * sum = 0
+ * for i in (1..10000)
+ * sum = sum + 0.0001
+ * end
+ * print sum
+ *
+ * and contrast with the output from:
+ *
+ * require 'bigdecimal'
+ *
+ * sum = BigDecimal.new("0")
+ * for i in (1..10000)
+ * sum = sum + BigDecimal.new("0.0001")
+ * end
+ * print sum
+ *
+ * Similarly:
+ *
+ * (BigDecimal.new("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") -> true
+ *
+ * (1.2 - 1.0) == 0.2 -> false
+ *
+ * = Special features of accurate decimal arithmetic
+ *
+ * Because BigDecimal is more accurate than normal binary floating point
+ * arithmetic, it requires some special values.
+ *
+ * == Infinity
+ *
+ * BigDecimal sometimes needs to return infinity, for example if you divide
+ * a value by zero.
+ *
+ * BigDecimal.new("1.0") / BigDecimal.new("0.0") -> infinity
+ *
+ * BigDecimal.new("-1.0") / BigDecimal.new("0.0") -> -infinity
+ *
+ * You can represent infinite numbers to BigDecimal using the strings
+ * 'Infinity', '+Infinity' and '-Infinity' (case-sensitive)
+ *
+ * == Not a Number
+ *
+ * When a computation results in an undefined value, the special value NaN
+ * (for 'not a number') is returned.
+ *
+ * Example:
+ *
+ * BigDecimal.new("0.0") / BigDecimal.new("0.0") -> NaN
+ *
+ * You can also create undefined values. NaN is never considered to be the
+ * same as any other value, even NaN itself:
+ *
+ * n = BigDecimal.new('NaN')
+ *
+ * n == 0.0 -> nil
+ *
+ * n == n -> nil
+ *
+ * == Positive and negative zero
+ *
+ * If a computation results in a value which is too small to be represented as
+ * a BigDecimal within the currently specified limits of precision, zero must
+ * be returned.
+ *
+ * If the value which is too small to be represented is negative, a BigDecimal
+ * value of negative zero is returned. If the value is positive, a value of
+ * positive zero is returned.
+ *
+ * BigDecimal.new("1.0") / BigDecimal.new("-Infinity") -> -0.0
+ *
+ * BigDecimal.new("1.0") / BigDecimal.new("Infinity") -> 0.0
+ *
+ * (See BigDecimal.mode for how to specify limits of precision.)
+ *
+ * Note that -0.0 and 0.0 are considered to be the same for the purposes of
+ * comparison.
+ *
+ * Note also that in mathematics, there is no particular concept of negative
+ * or positive zero; true mathematical zero has no sign.
+ */
+void
+Init_BigDecimal()
+{
+ /* This is a #if-ed out function to fool Rdoc into documenting the class. */
+ /* The real init function is Init_bigdecimal() further down. */
+}
+#endif
+
/*
- * **** BigDecimal version ****
+ * Returns the BigDecimal version number.
+ *
+ * Ruby 1.8.0 returns 1.0.0.
+ * Ruby 1.8.1 thru 1.8.3 return 1.0.1.
*/
static VALUE
BigDecimal_version(VALUE self)
@@ -103,20 +218,20 @@ GetVpValue(VALUE v, int must)
}
break;
case T_FIXNUM:
- sprintf(szD, "%d", FIX2INT(v));
+ sprintf(szD, "%ld", FIX2LONG(v));
return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
#ifdef ENABLE_NUMERIC_STRING
case T_STRING:
SafeStringValue(v);
- return VpCreateRbObject(strlen(RSTRING(v)->ptr) + VpBaseFig() + 1,
- RSTRING(v)->ptr);
+ return VpCreateRbObject(strlen(RSTRING_PTR(v)) + VpBaseFig() + 1,
+ RSTRING_PTR(v));
#endif /* ENABLE_NUMERIC_STRING */
case T_BIGNUM:
bg = rb_big2str(v, 10);
- return VpCreateRbObject(strlen(RSTRING(bg)->ptr) + VpBaseFig() + 1,
- RSTRING(bg)->ptr);
+ return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
+ RSTRING_PTR(bg));
default:
goto SomeOneMayDoIt;
}
@@ -125,19 +240,35 @@ SomeOneMayDoIt:
if(must) {
rb_raise(rb_eTypeError, "%s can't be coerced into BigDecimal",
rb_special_const_p(v)?
- RSTRING(rb_inspect(v))->ptr:
+ RSTRING_PTR(rb_inspect(v)):
rb_obj_classname(v)
);
}
return NULL; /* NULL means to coerce */
}
+/* call-seq:
+ * BigDecimal.double_fig
+ *
+ * The BigDecimal.double_fig class method returns the number of digits a
+ * Float number is allowed to have. The result depends upon the CPU and OS
+ * in use.
+ */
static VALUE
BigDecimal_double_fig(VALUE self)
{
return INT2FIX(VpDblFig());
}
+/* call-seq:
+ * precs
+ *
+ * Returns an Array of two Integer values.
+ *
+ * The first value is the current number of significant digits in the
+ * BigDecimal. The second value is the maximum number of significant digits
+ * for the BigDecimal.
+ */
static VALUE
BigDecimal_prec(VALUE self)
{
@@ -146,9 +277,8 @@ BigDecimal_prec(VALUE self)
VALUE obj;
GUARD_OBJ(p,GetVpValue(self,1));
- obj = rb_ary_new();
- obj = rb_ary_push(obj,INT2NUM(p->Prec*VpBaseFig()));
- obj = rb_ary_push(obj,INT2NUM(p->MaxPrec*VpBaseFig()));
+ obj = rb_assoc_new(INT2NUM(p->Prec*VpBaseFig()),
+ INT2NUM(p->MaxPrec*VpBaseFig()));
return obj;
}
@@ -189,6 +319,9 @@ BigDecimal_dump(int argc, VALUE *argv, VALUE self)
return rb_str_new2(psz);
}
+/*
+ * Internal method used to provide marshalling support. See the Marshal module.
+ */
static VALUE
BigDecimal_load(VALUE self, VALUE str)
{
@@ -199,21 +332,59 @@ BigDecimal_load(VALUE self, VALUE str)
unsigned long m=0;
SafeStringValue(str);
- pch = RSTRING(str)->ptr;
+ pch = (unsigned char *)RSTRING_PTR(str);
/* First get max prec */
while((*pch)!=(unsigned char)'\0' && (ch=*pch++)!=(unsigned char)':') {
if(!ISDIGIT(ch)) {
- rb_raise(rb_eTypeError, "Load failed: invalid character in the marshaled string");
+ rb_raise(rb_eTypeError, "load failed: invalid character in the marshaled string");
}
m = m*10 + (unsigned long)(ch-'0');
}
if(m>VpBaseFig()) m -= VpBaseFig();
- GUARD_OBJ(pv,VpNewRbClass(m,pch,self));
+ GUARD_OBJ(pv,VpNewRbClass(m,(char *)pch,self));
m /= VpBaseFig();
if(m && pv->MaxPrec>m) pv->MaxPrec = m+1;
return ToValue(pv);
}
+ /* call-seq:
+ * BigDecimal.mode(mode, value)
+ *
+ * Controls handling of arithmetic exceptions and rounding. If no value
+ * is supplied, the current value is returned.
+ *
+ * Six values of the mode parameter control the handling of arithmetic
+ * exceptions:
+ *
+ * BigDecimal::EXCEPTION_NaN
+ * BigDecimal::EXCEPTION_INFINITY
+ * BigDecimal::EXCEPTION_UNDERFLOW
+ * BigDecimal::EXCEPTION_OVERFLOW
+ * BigDecimal::EXCEPTION_ZERODIVIDE
+ * BigDecimal::EXCEPTION_ALL
+ *
+ * For each mode parameter above, if the value set is false, computation
+ * continues after an arithmetic exception of the appropriate type.
+ * When computation continues, results are as follows:
+ *
+ * EXCEPTION_NaN:: NaN
+ * EXCEPTION_INFINITY:: +infinity or -infinity
+ * EXCEPTION_UNDERFLOW:: 0
+ * EXCEPTION_OVERFLOW:: +infinity or -infinity
+ * EXCEPTION_ZERODIVIDE:: +infinity or -infinity
+ *
+ * One value of the mode parameter controls the rounding of numeric values:
+ * BigDecimal::ROUND_MODE. The values it can take are:
+ *
+ * ROUND_UP:: round away from zero
+ * ROUND_DOWN:: round towards zero (truncate)
+ * ROUND_HALF_UP:: round up if the appropriate digit >= 5, otherwise truncate (default)
+ * ROUND_HALF_DOWN:: round up if the appropriate digit >= 6, otherwise truncate
+ * ROUND_HALF_EVEN:: round towards the even neighbor (Banker's rounding)
+ * ROUND_CEILING:: round towards positive infinity (ceil)
+ * ROUND_FLOOR:: round towards negative infinity (floor)
+ *
+ */
static VALUE
BigDecimal_mode(int argc, VALUE *argv, VALUE self)
{
@@ -231,7 +402,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
fo = VpGetException();
if(val==Qnil) return INT2FIX(fo);
if(val!=Qfalse && val!=Qtrue) {
- rb_raise(rb_eTypeError, "The second argument must be true or false.");
+ rb_raise(rb_eTypeError, "second argument must be true or false");
return Qnil; /* Not reached */
}
if(f&VP_EXCEPTION_INFINITY) {
@@ -251,13 +422,13 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
if(val==Qnil) return INT2FIX(fo);
Check_Type(val, T_FIXNUM);
if(!VpIsRoundMode(FIX2INT(val))) {
- rb_raise(rb_eTypeError, "Invalid rounding mode.");
+ rb_raise(rb_eTypeError, "invalid rounding mode");
return Qnil;
}
fo = VpSetRoundMode((unsigned long)FIX2INT(val));
return INT2FIX(fo);
}
- rb_raise(rb_eTypeError, "The first argument for BigDecimal#mode is invalid.");
+ rb_raise(rb_eTypeError, "first argument for BigDecimal#mode invalid");
return Qnil;
}
@@ -303,14 +474,14 @@ VpNewRbClass(U_LONG mx, char *str, VALUE klass)
}
VP_EXPORT Real *
-VpCreateRbObject(U_LONG mx, char *str)
+VpCreateRbObject(U_LONG mx, const char *str)
{
Real *pv = VpAlloc(mx,str);
pv->obj = (VALUE)Data_Wrap_Struct(rb_cBigDecimal, 0, BigDecimal_delete, pv);
return pv;
}
-
+/* Returns True if the value is Not a Number */
static VALUE
BigDecimal_IsNaN(VALUE self)
{
@@ -319,6 +490,7 @@ BigDecimal_IsNaN(VALUE self)
return Qfalse;
}
+/* Returns True if the value is infinite */
static VALUE
BigDecimal_IsInfinite(VALUE self)
{
@@ -328,6 +500,7 @@ BigDecimal_IsInfinite(VALUE self)
return Qnil;
}
+/* Returns True if the value is finite (not NaN or infinite) */
static VALUE
BigDecimal_IsFinite(VALUE self)
{
@@ -337,6 +510,10 @@ BigDecimal_IsFinite(VALUE self)
return Qtrue;
}
+/* Returns the value as an integer (Fixnum or Bignum).
+ *
+ * If the BigNumber is infinity or NaN, returns nil.
+ */
static VALUE
BigDecimal_to_i(VALUE self)
{
@@ -400,26 +577,47 @@ BigDecimal_induced_from(VALUE self, VALUE x)
return p->obj;
}
+/* Returns a new Float object having approximately the same value as the
+ * BigDecimal number. Normal accuracy limits and built-in errors of binary
+ * Float arithmetic apply.
+ */
static VALUE
BigDecimal_to_f(VALUE self)
{
ENTER(1);
Real *p;
- double d, d2;
+ double d;
S_LONG e;
+ char *buf;
GUARD_OBJ(p,GetVpValue(self,1));
if(VpVtoD(&d, &e, p)!=1) return rb_float_new(d);
+ buf = ALLOCA_N(char,(unsigned int)VpNumOfChars(p,"E"));
+ VpToString(p, buf, 0, 0);
errno = 0;
- d2 = pow(10.0,(double)e);
- if((errno == ERANGE && e>0) || (d2>1.0 && (fabs(d) > (DBL_MAX / d2)))) {
- VpException(VP_EXCEPTION_OVERFLOW,"BigDecimal to Float conversion.",0);
+ d = strtod(buf, 0);
+ if(errno == ERANGE) {
+ VpException(VP_EXCEPTION_OVERFLOW,"BigDecimal to Float conversion",0);
if(d>0.0) return rb_float_new(DBL_MAX);
else return rb_float_new(-DBL_MAX);
}
- return rb_float_new(d*d2);
+ return rb_float_new(d);
}
+/* The coerce method provides support for Ruby type coercion. It is not
+ * enabled by default.
+ *
+ * This means that binary operations like + * / or - can often be performed
+ * on a BigDecimal and an object of another type, if the other object can
+ * be coerced into a BigDecimal value.
+ *
+ * e.g.
+ * a = BigDecimal.new("1.0")
+ * b = a / 2.0 -> 0.5
+ *
+ * Note that coercing a String to a BigDecimal is not supported by default;
+ * it requires a special compile-time option when building Ruby.
+ */
static VALUE
BigDecimal_coerce(VALUE self, VALUE other)
{
@@ -427,14 +625,10 @@ BigDecimal_coerce(VALUE self, VALUE other)
VALUE obj;
Real *b;
if(TYPE(other) == T_FLOAT) {
- obj = rb_ary_new();
- obj = rb_ary_push(obj,other);
- obj = rb_ary_push(obj,BigDecimal_to_f(self));
+ obj = rb_assoc_new(other, BigDecimal_to_f(self));
} else {
GUARD_OBJ(b,GetVpValue(other,1));
- obj = rb_ary_new();
- obj = rb_ary_push(obj, b->obj);
- obj = rb_ary_push(obj, self);
+ obj = rb_assoc_new(b->obj, self);
}
return obj;
}
@@ -445,6 +639,17 @@ BigDecimal_uplus(VALUE self)
return self;
}
+ /* call-seq:
+ * add(value, digits)
+ *
+ * Add the specified value.
+ *
+ * e.g.
+ * c = a.add(b,n)
+ * c = a + b
+ *
+ * digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
+ */
static VALUE
BigDecimal_add(VALUE self, VALUE r)
{
@@ -472,6 +677,17 @@ BigDecimal_add(VALUE self, VALUE r)
return ToValue(c);
}
+ /* call-seq:
+ * sub(value, digits)
+ *
+ * Subtract the specified value.
+ *
+ * e.g.
+ * c = a.sub(b,n)
+ * c = a - b
+ *
+ * digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
+ */
static VALUE
BigDecimal_sub(VALUE self, VALUE r)
{
@@ -527,6 +743,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
rb_bug("Undefined operation in BigDecimalCmp()");
}
+/* Returns True if the value is zero. */
static VALUE
BigDecimal_zero(VALUE self)
{
@@ -534,6 +751,7 @@ BigDecimal_zero(VALUE self)
return VpIsZero(a) ? Qtrue : Qfalse;
}
+/* Returns True if the value is non-zero. */
static VALUE
BigDecimal_nonzero(VALUE self)
{
@@ -541,42 +759,73 @@ BigDecimal_nonzero(VALUE self)
return VpIsZero(a) ? Qnil : self;
}
+/* The comparison operator.
+ * a <=> b is 0 if a == b, 1 if a > b, -1 if a < b.
+ */
static VALUE
BigDecimal_comp(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, '*');
}
+/*
+ * Tests for value equality; returns true if the values are equal.
+ *
+ * The == and === operators and the eql? method have the same implementation
+ * for BigDecimal.
+ *
+ * Values may be coerced to perform the comparison:
+ *
+ * BigDecimal.new('1.0') == 1.0 -> true
+ */
static VALUE
BigDecimal_eq(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, '=');
}
-static VALUE
-BigDecimal_ne(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '!');
-}
-
+/* call-seq:
+ * a < b
+ *
+ * Returns true if a is less than b. Values may be coerced to perform the
+ * comparison (see ==, coerce).
+ */
static VALUE
BigDecimal_lt(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, '<');
}
+/* call-seq:
+ * a <= b
+ *
+ * Returns true if a is less than or equal to b. Values may be coerced to
+ * perform the comparison (see ==, coerce).
+ */
static VALUE
BigDecimal_le(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, 'L');
}
+/* call-seq:
+ * a > b
+ *
+ * Returns true if a is greater than b. Values may be coerced to
+ * perform the comparison (see ==, coerce).
+ */
static VALUE
BigDecimal_gt(VALUE self, VALUE r)
{
return BigDecimalCmp(self, r, '>');
}
+/* call-seq:
+ * a >= b
+ *
+ * Returns true if a is greater than or equal to b. Values may be coerced to
+ * perform the comparison (see ==, coerce)
+ */
static VALUE
BigDecimal_ge(VALUE self, VALUE r)
{
@@ -584,7 +833,7 @@ BigDecimal_ge(VALUE self, VALUE r)
}
static VALUE
-BigDecimal_neg(VALUE self, VALUE r)
+BigDecimal_neg(VALUE self)
{
ENTER(5);
Real *c, *a;
@@ -594,6 +843,17 @@ BigDecimal_neg(VALUE self, VALUE r)
return ToValue(c);
}
+ /* call-seq:
+ * mult(value, digits)
+ *
+ * Multiply by the specified value.
+ *
+ * e.g.
+ * c = a.mult(b,n)
+ * c = a * b
+ *
+ * digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
+ */
static VALUE
BigDecimal_mult(VALUE self, VALUE r)
{
@@ -632,6 +892,23 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
return (VALUE)0;
}
+ /* call-seq:
+ * div(value, digits)
+ * quo(value)
+ *
+ * Divide by the specified value.
+ *
+ * e.g.
+ * c = a.div(b,n)
+ *
+ * digits:: If specified and less than the number of significant digits of the result, the result is rounded to that number of digits, according to BigDecimal.mode.
+ *
+ * If digits is 0, the result is the same as the / operator. If not, the
+ * result is an integer BigDecimal, by analogy with Float#div.
+ *
+ * The alias quo is provided since div(value, 0) is the same as computing
+ * the quotient; see divmod.
+ */
static VALUE
BigDecimal_div(VALUE self, VALUE r)
/* For c = self/r: with round operation */
@@ -710,6 +987,12 @@ NaN:
return (VALUE)0;
}
+/* call-seq:
+ * a % b
+ * a.modulo(b)
+ *
+ * Returns the modulus from dividing by b. See divmod.
+ */
static VALUE
BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
{
@@ -760,16 +1043,42 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
return (VALUE)0;
}
+/* Returns the remainder from dividing by the value.
+ *
+ * If the values divided are of the same sign, the remainder is the same as
+ * the modulus (see divmod).
+ *
+ * Otherwise, the remainder is the modulus minus the value divided by.
+ */
static VALUE
BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
{
VALUE f;
- Real *d,*rv;
+ Real *d,*rv=0;
f = BigDecimal_divremain(self,r,&d,&rv);
if(f!=(VALUE)0) return f;
return ToValue(rv);
}
+/* Divides by the specified value, and returns the quotient and modulus
+ * as BigDecimal numbers. The quotient is rounded towards negative infinity.
+ *
+ * For example:
+ *
+ * require 'bigdecimal'
+ *
+ * a = BigDecimal.new("42")
+ * b = BigDecimal.new("9")
+ *
+ * q,m = a.divmod(b)
+ *
+ * c = q * b + m
+ *
+ * a == c -> true
+ *
+ * The quotient q is (a/b).floor, and the modulus is the amount that must be
+ * added to q * b to get a.
+ */
static VALUE
BigDecimal_divmod(VALUE self, VALUE r)
{
@@ -780,9 +1089,7 @@ BigDecimal_divmod(VALUE self, VALUE r)
obj = BigDecimal_DoDivmod(self,r,&div,&mod);
if(obj!=(VALUE)0) return obj;
SAVE(div);SAVE(mod);
- obj = rb_ary_new();
- rb_ary_push(obj, ToValue(div));
- rb_ary_push(obj, ToValue(mod));
+ obj = rb_assoc_new(ToValue(div), ToValue(mod));
return obj;
}
@@ -873,6 +1180,12 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
}
}
+/* Returns the absolute value.
+ *
+ * BigDecimal('5').abs -> 5
+ *
+ * BigDecimal('-3').abs -> 3
+ */
static VALUE
BigDecimal_abs(VALUE self)
{
@@ -888,6 +1201,13 @@ BigDecimal_abs(VALUE self)
return ToValue(c);
}
+/* call-seq:
+ * sqrt(n)
+ *
+ * Returns the square root of the value.
+ *
+ * If n is specified, returns at least that many significant digits.
+ */
static VALUE
BigDecimal_sqrt(VALUE self, VALUE nFig)
{
@@ -905,6 +1225,8 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
return ToValue(c);
}
+/* Return the integer part of the number.
+ */
static VALUE
BigDecimal_fix(VALUE self)
{
@@ -919,12 +1241,34 @@ BigDecimal_fix(VALUE self)
return ToValue(c);
}
+/* call-seq:
+ * round(n,mode)
+ *
+ * Round to the nearest 1 (by default), returning the result as a BigDecimal.
+ *
+ * BigDecimal('3.14159').round -> 3
+ *
+ * BigDecimal('8.7').round -> 9
+ *
+ * If n is specified and positive, the fractional part of the result has no
+ * more than that many digits.
+ *
+ * If n is specified and negative, at least that many digits to the left of the
+ * decimal point will be 0 in the result.
+ *
+ * BigDecimal('3.14159').round(3) -> 3.142
+ *
+ * BigDecimal('13345.234').round(-2) -> 13300.0
+ *
+ * The value of the optional mode argument can be used to determine how
+ * rounding is performed; see BigDecimal.mode.
+ */
static VALUE
BigDecimal_round(int argc, VALUE *argv, VALUE self)
{
ENTER(5);
Real *c, *a;
- int iLoc;
+ int iLoc = 0;
U_LONG mx;
VALUE vLoc;
VALUE vRound;
@@ -947,7 +1291,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
Check_Type(vRound, T_FIXNUM);
sw = FIX2INT(vRound);
if(!VpIsRoundMode(sw)) {
- rb_raise(rb_eTypeError, "Invalid rounding mode.");
+ rb_raise(rb_eTypeError, "invalid rounding mode");
return Qnil;
}
break;
@@ -962,6 +1306,25 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
return ToValue(c);
}
+/* call-seq:
+ * truncate(n)
+ *
+ * Truncate to the nearest 1, returning the result as a BigDecimal.
+ *
+ * BigDecimal('3.14159').truncate -> 3
+ *
+ * BigDecimal('8.7').truncate -> 8
+ *
+ * If n is specified and positive, the fractional part of the result has no
+ * more than that many digits.
+ *
+ * If n is specified and negative, at least that many digits to the left of the
+ * decimal point will be 0 in the result.
+ *
+ * BigDecimal('3.14159').truncate(3) -> 3.141
+ *
+ * BigDecimal('13345.234').truncate(-2) -> 13300.0
+ */
static VALUE
BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
{
@@ -987,6 +1350,8 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
return ToValue(c);
}
+/* Return the fractional part of the number.
+ */
static VALUE
BigDecimal_frac(VALUE self)
{
@@ -1001,6 +1366,25 @@ BigDecimal_frac(VALUE self)
return ToValue(c);
}
+/* call-seq:
+ * floor(n)
+ *
+ * Return the largest integer less than or equal to the value, as a BigDecimal.
+ *
+ * BigDecimal('3.14159').floor -> 3
+ *
+ * BigDecimal('-9.1').floor -> -10
+ *
+ * If n is specified and positive, the fractional part of the result has no
+ * more than that many digits.
+ *
+ * If n is specified and negative, at least that
+ * many digits to the left of the decimal point will be 0 in the result.
+ *
+ * BigDecimal('3.14159').floor(3) -> 3.141
+ *
+ * BigDecimal('13345.234').floor(-2) -> 13300.0
+ */
static VALUE
BigDecimal_floor(int argc, VALUE *argv, VALUE self)
{
@@ -1026,6 +1410,25 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
return ToValue(c);
}
+/* call-seq:
+ * ceil(n)
+ *
+ * Return the smallest integer greater than or equal to the value, as a BigDecimal.
+ *
+ * BigDecimal('3.14159').ceil -> 4
+ *
+ * BigDecimal('-9.1').ceil -> -9
+ *
+ * If n is specified and positive, the fractional part of the result has no
+ * more than that many digits.
+ *
+ * If n is specified and negative, at least that
+ * many digits to the left of the decimal point will be 0 in the result.
+ *
+ * BigDecimal('3.14159').ceil(3) -> 3.142
+ *
+ * BigDecimal('13345.234').ceil(-2) -> 13400.0
+ */
static VALUE
BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
{
@@ -1051,6 +1454,36 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
return ToValue(c);
}
+/* call-seq:
+ * to_s(s)
+ *
+ * Converts the value to a string.
+ *
+ * The default format looks like 0.xxxxEnn.
+ *
+ * The optional parameter s consists of either an integer; or an optional '+'
+ * or ' ', followed by an optional number, followed by an optional 'E' or 'F'.
+ *
+ * If there is a '+' at the start of s, positive values are returned with
+ * a leading '+'.
+ *
+ * A space at the start of s returns positive values with a leading space.
+ *
+ * If s contains a number, a space is inserted after each group of that many
+ * fractional digits.
+ *
+ * If s ends with an 'E', engineering notation (0.xxxxEnn) is used.
+ *
+ * If s ends with an 'F', conventional floating point notation is used.
+ *
+ * Examples:
+ *
+ * BigDecimal.new('-123.45678901234567890').to_s('5F') -> '-123.45678 90123 45678 9'
+ *
+ * BigDecimal.new('123.45678901234567890').to_s('+8F') -> '+123.45678901 23456789'
+ *
+ * BigDecimal.new('123.45678901234567890').to_s(' F') -> ' 123.4567890123456789'
+ */
static VALUE
BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
{
@@ -1069,13 +1502,13 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
if(rb_scan_args(argc,argv,"01",&f)==1) {
if(TYPE(f)==T_STRING) {
SafeStringValue(f);
- psz = RSTRING(f)->ptr;
+ psz = RSTRING_PTR(f);
if(*psz==' ') {
fPlus = 1; psz++;
} else if(*psz=='+') {
fPlus = 2; psz++;
}
- while(ch=*psz++) {
+ while((ch=*psz++)!=0) {
if(ISSPACE(ch)) continue;
if(!ISDIGIT(ch)) {
if(ch=='F' || ch=='f') fmt = 1; /* F format */
@@ -1104,6 +1537,30 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
return rb_str_new2(psz);
}
+/* Splits a BigDecimal number into four parts, returned as an array of values.
+ *
+ * The first value represents the sign of the BigDecimal, and is -1 or 1, or 0
+ * if the BigDecimal is Not a Number.
+ *
+ * The second value is a string representing the significant digits of the
+ * BigDecimal, with no leading zeros.
+ *
+ * The third value is the base used for arithmetic (currently always 10) as an
+ * Integer.
+ *
+ * The fourth value is an Integer exponent.
+ *
+ * If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the
+ * string of significant digits with no leading zeros, and n is the exponent.
+ *
+ * From these values, you can translate a BigDecimal to a float as follows:
+ *
+ * sign, significant_digits, base, exponent = a.split
+ * f = sign * "0.#{significant_digits}".to_f * (base ** exponent)
+ *
+ * (Note that the to_f method is provided as a more convenient way to translate
+ * a BigDecimal to a Float.)
+ */
static VALUE
BigDecimal_split(VALUE self)
{
@@ -1124,7 +1581,7 @@ BigDecimal_split(VALUE self)
if(psz1[0]=='N') s=0; /* NaN */
e = VpExponent10(vp);
obj1 = rb_str_new2(psz1);
- obj = rb_ary_new();
+ obj = rb_ary_new2(4);
rb_ary_push(obj, INT2FIX(s));
rb_ary_push(obj, obj1);
rb_ary_push(obj, INT2FIX(10));
@@ -1132,6 +1589,11 @@ BigDecimal_split(VALUE self)
return obj;
}
+/* Returns the exponent of the BigDecimal number, as an Integer.
+ *
+ * If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string
+ * of digits with no leading zeros, then n is the exponent.
+ */
static VALUE
BigDecimal_exponent(VALUE self)
{
@@ -1139,6 +1601,16 @@ BigDecimal_exponent(VALUE self)
return INT2NUM(e);
}
+/* Returns debugging information about the value as a string of comma-separated
+ * values in angle brackets with a leading #:
+ *
+ * BigDecimal.new("1234.5678").inspect ->
+ * "#<BigDecimal:b7ea1130,'0.12345678E4',8(12)>"
+ *
+ * The first part is the address, the second is the value as a string, and
+ * the final part ss(mm) is the current number of significant digits and the
+ * maximum number of significant digits, respectively.
+ */
static VALUE
BigDecimal_inspect(VALUE self)
{
@@ -1161,6 +1633,13 @@ BigDecimal_inspect(VALUE self)
return obj;
}
+/* call-seq:
+ * power(n)
+ *
+ * Returns the value raised to the power of n. Note that n must be an Integer.
+ *
+ * Also available as the operator **
+ */
static VALUE
BigDecimal_power(VALUE self, VALUE p)
{
@@ -1200,10 +1679,22 @@ BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
mf = GetPositiveInt(nFig);
}
SafeStringValue(iniValue);
- GUARD_OBJ(pv,VpCreateRbObject(mf, RSTRING(iniValue)->ptr));
+ GUARD_OBJ(pv,VpCreateRbObject(mf, RSTRING_PTR(iniValue)));
return ToValue(pv);
}
+ /* call-seq:
+ * new(initial, digits)
+ *
+ * Create a new BigDecimal object.
+ *
+ * initial:: The initial value, as a String. Spaces are ignored, unrecognized characters terminate the value.
+ *
+ * digits:: The number of significant digits, as a Fixnum. If omitted or 0, the number of significant digits is determined from the initial value.
+ *
+ * The actual number of significant digits used in computation is usually
+ * larger than the specified number.
+ */
static VALUE
BigDecimal_new(int argc, VALUE *argv, VALUE self)
{
@@ -1219,10 +1710,22 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self)
mf = GetPositiveInt(nFig);
}
SafeStringValue(iniValue);
- GUARD_OBJ(pv,VpNewRbClass(mf, RSTRING(iniValue)->ptr,self));
+ GUARD_OBJ(pv,VpNewRbClass(mf, RSTRING_PTR(iniValue),self));
return ToValue(pv);
}
+ /* call-seq:
+ * BigDecimal.limit(digits)
+ *
+ * Limit the number of significant digits in newly created BigDecimal
+ * numbers to the specified value. Rounding is performed as necessary,
+ * as specified by BigDecimal.mode.
+ *
+ * A limit of 0, the default, means no upper limit.
+ *
+ * The limit specified by this method takes priority over any limit
+ * specified to instance methods such as ceil, floor, truncate, or round.
+ */
static VALUE
BigDecimal_limit(int argc, VALUE *argv, VALUE self)
{
@@ -1242,6 +1745,22 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
return nCur;
}
+/* Returns the sign of the value.
+ *
+ * Returns a positive value if > 0, a negative value if < 0, and a
+ * zero if == 0.
+ *
+ * The specific value returned indicates the type and sign of the BigDecimal,
+ * as follows:
+ *
+ * BigDecimal::SIGN_NaN:: value is Not a Number
+ * BigDecimal::SIGN_POSITIVE_ZERO:: value is +0
+ * BigDecimal::SIGN_NEGATIVE_ZERO:: value is -0
+ * BigDecimal::SIGN_POSITIVE_INFINITE:: value is +infinity
+ * BigDecimal::SIGN_NEGATIVE_INFINITE:: value is -infinity
+ * BigDecimal::SIGN_POSITIVE_FINITE:: value is positive
+ * BigDecimal::SIGN_NEGATIVE_FINITE:: value is negative
+ */
static VALUE
BigDecimal_sign(VALUE self)
{ /* sign */
@@ -1271,37 +1790,112 @@ Init_bigdecimal(void)
rb_define_singleton_method(rb_cBigDecimal, "ver", BigDecimal_version, 0);
/* Constants definition */
+
+ /*
+ * Base value used in internal calculations. On a 32 bit system, BASE
+ * is 10000, indicating that calculation is done in groups of 4 digits.
+ * (If it were larger, BASE**2 wouldn't fit in 32 bits, so you couldn't
+ * guarantee that two groups could always be multiplied together without
+ * overflow.)
+ */
rb_define_const(rb_cBigDecimal, "BASE", INT2FIX((S_INT)VpBaseVal()));
/* Exceptions */
+
+ /*
+ * 0xff: Determines whether overflow, underflow or zero divide result in
+ * an exception being thrown. See BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL",INT2FIX(VP_EXCEPTION_ALL));
+
+ /*
+ * 0x02: Determines what happens when the result of a computation is not a
+ * number (NaN). See BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN",INT2FIX(VP_EXCEPTION_NaN));
+
+ /*
+ * 0x01: Determines what happens when the result of a computation is
+ * infinity. See BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY",INT2FIX(VP_EXCEPTION_INFINITY));
+
+ /*
+ * 0x04: Determines what happens when the result of a computation is an
+ * underflow (a result too small to be represented). See BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW",INT2FIX(VP_EXCEPTION_UNDERFLOW));
+
+ /*
+ * 0x01: Determines what happens when the result of a computation is an
+ * underflow (a result too large to be represented). See BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW",INT2FIX(VP_EXCEPTION_OVERFLOW));
+
+ /*
+ * 0x01: Determines what happens when a division by zero is performed.
+ * See BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE",INT2FIX(VP_EXCEPTION_ZERODIVIDE));
- /* Computation mode */
+ /*
+ * 0x100: Determines what happens when a result must be rounded in order to
+ * fit in the appropriate number of significant digits. See
+ * BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_MODE",INT2FIX(VP_ROUND_MODE));
+
+ /* 1: Indicates that values should be rounded away from zero. See
+ * BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_UP",INT2FIX(VP_ROUND_UP));
+
+ /* 2: Indicates that values should be rounded towards zero. See
+ * BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_DOWN",INT2FIX(VP_ROUND_DOWN));
+
+ /* 3: Indicates that digits >= 5 should be rounded up, others rounded down.
+ * See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP",INT2FIX(VP_ROUND_HALF_UP));
+
+ /* 4: Indicates that digits >= 6 should be rounded up, others rounded down.
+ * See BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN",INT2FIX(VP_ROUND_HALF_DOWN));
+ /* 5: Round towards +infinity. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_CEILING",INT2FIX(VP_ROUND_CEIL));
+
+ /* 6: Round towards -infinity. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_FLOOR",INT2FIX(VP_ROUND_FLOOR));
+
+ /* 7: Round towards the even neighbor. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN",INT2FIX(VP_ROUND_HALF_EVEN));
- /* Constants for sign value */
+ /* 0: Indicates that a value is not a number. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NaN",INT2FIX(VP_SIGN_NaN));
+
+ /* 1: Indicates that a value is +0. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO",INT2FIX(VP_SIGN_POSITIVE_ZERO));
+
+ /* -1: Indicates that a value is -0. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO",INT2FIX(VP_SIGN_NEGATIVE_ZERO));
+
+ /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE",INT2FIX(VP_SIGN_POSITIVE_FINITE));
+
+ /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE",INT2FIX(VP_SIGN_NEGATIVE_FINITE));
+
+ /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE",INT2FIX(VP_SIGN_POSITIVE_INFINITE));
+
+ /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE",INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
/* instance methods */
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
+
rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2);
@@ -1337,7 +1931,6 @@ Init_bigdecimal(void)
rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1);
rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1);
rb_define_method(rb_cBigDecimal, "eql?", BigDecimal_eq, 1);
- rb_define_method(rb_cBigDecimal, "!=", BigDecimal_ne, 1);
rb_define_method(rb_cBigDecimal, "<", BigDecimal_lt, 1);
rb_define_method(rb_cBigDecimal, "<=", BigDecimal_le, 1);
rb_define_method(rb_cBigDecimal, ">", BigDecimal_gt, 1);
@@ -1372,17 +1965,27 @@ static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
static U_LONG gnPrecLimit = 0; /* Global upper limit of the precision newly allocated */
static U_LONG gfRoundMode = VP_ROUND_HALF_UP; /* Mode for general rounding operation */
+#ifndef BASE_FIG
static U_LONG BASE_FIG = 4; /* =log10(BASE) */
static U_LONG BASE = 10000L; /* Base value(value must be 10**BASE_FIG) */
/* The value of BASE**2 + BASE must be represented */
/* within one U_LONG. */
static U_LONG HALF_BASE = 5000L;/* =BASE/2 */
-static S_LONG DBLE_FIG = 8; /* figure of double */
static U_LONG BASE1 = 1000L; /* =BASE/10 */
+#else
+#ifndef BASE
+#error BASE_FIG is defined but BASE is not
+#endif
+#define HALF_BASE (BASE/2)
+#define BASE1 (BASE/10)
+#endif
+#ifndef DBLE_FIG
+#define DBLE_FIG (DBL_DIG+1) /* figure of double */
+#endif
static Real *VpConstOne; /* constant 1.0 */
static Real *VpPt5; /* constant 0.5 */
-static U_LONG maxnr = 100; /* Maximum iterations for calcurating sqrt. */
+#define maxnr 100UL /* Maximum iterations for calcurating sqrt. */
/* used in VpSqrt() */
/* ETC */
@@ -1499,8 +2102,8 @@ VpSetRoundMode(unsigned long n)
* (to let the compiler know they may be changed in outside
* (... but not actually..)).
*/
-volatile double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
-volatile double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
+volatile const double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
+volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
static double
Zero(void)
{
@@ -1585,7 +2188,7 @@ VpIsNegDoubleZero(double v)
}
VP_EXPORT int
-VpException(unsigned short f,char *str,int always)
+VpException(unsigned short f, const char *str,int always)
{
VALUE exc;
int fatal=0;
@@ -1622,8 +2225,8 @@ VpException(unsigned short f,char *str,int always)
return 0; /* 0 Means VpException() raised no exception */
raise:
- if(fatal) rb_fatal(str);
- else rb_raise(exc,str);
+ if(fatal) rb_fatal("%s", str);
+ else rb_raise(exc, "%s", str);
return 0;
}
@@ -1727,7 +2330,7 @@ NaN:
* returns number of chars needed to represent vp in specified format.
*/
VP_EXPORT U_LONG
-VpNumOfChars(Real *vp,char *pszFmt)
+VpNumOfChars(Real *vp,const char *pszFmt)
{
S_INT ex;
U_LONG nc;
@@ -1772,16 +2375,15 @@ VpNumOfChars(Real *vp,char *pszFmt)
VP_EXPORT U_LONG
VpInit(U_LONG BaseVal)
{
- U_LONG w;
- double v;
-
/* Setup +/- Inf NaN -0 */
VpGetDoubleNaN();
VpGetDoublePosInf();
VpGetDoubleNegInf();
VpGetDoubleNegZero();
+#ifndef BASE_FIG
if(BaseVal <= 0) {
+ U_LONG w;
/* Base <= 0, then determine Base by calcuration. */
BASE = 1;
while(
@@ -1798,6 +2400,8 @@ VpInit(U_LONG BaseVal)
BASE1 = BASE / 10;
BASE_FIG = 0;
while(BaseVal /= 10) ++BASE_FIG;
+#endif
+
/* Allocates Vp constants. */
VpConstOne = VpAlloc((U_LONG)1, "1");
VpPt5 = VpAlloc((U_LONG)1, ".5");
@@ -1806,15 +2410,6 @@ VpInit(U_LONG BaseVal)
gnAlloc = 0;
#endif /* _DEBUG */
- /* Determine # of digits available in one 'double'. */
-
- v = 1.0;
- DBLE_FIG = 0;
- while(v + 1.0 > 1.0) {
- ++DBLE_FIG;
- v /= 10;
- }
-
#ifdef _DEBUG
if(gfDebug) {
printf("VpInit: BaseVal = %lu\n", BaseVal);
@@ -1830,7 +2425,7 @@ VpInit(U_LONG BaseVal)
}
VP_EXPORT Real *
-VpOne()
+VpOne(void)
{
return VpConstOne;
}
@@ -1880,7 +2475,7 @@ overflow:
* NULL be returned if memory allocation is failed,or any error.
*/
VP_EXPORT Real *
-VpAlloc(U_LONG mx, char *szVal)
+VpAlloc(U_LONG mx, const char *szVal)
{
U_LONG i, ni, ipn, ipf, nf, ipe, ne, nalloc;
char v,*psz;
@@ -1912,14 +2507,25 @@ VpAlloc(U_LONG mx, char *szVal)
return vp;
}
- /* Skip all spaces */
+ /* Skip all '_' after digit: 2006-6-30 */
+ ni = 0;
psz = ALLOCA_N(char,strlen(szVal)+1);
i = 0;
ipn = 0;
- while(psz[i]=szVal[ipn]) {
- if(ISSPACE(szVal[ipn])) {ipn++;continue;}
+ while((psz[i]=szVal[ipn])!=0) {
+ if(ISDIGIT(psz[i])) ++ni;
+ if(psz[i]=='_') {
+ if(ni>0) {ipn++;continue;}
+ psz[i]=0;
+ break;
+ }
++i; ++ipn;
}
+ /* Skip trailing spaces */
+ while((--i)>0) {
+ if(ISSPACE(psz[i])) psz[i] = 0;
+ else break;
+ }
szVal = psz;
/* Check on Inf & NaN */
@@ -1949,7 +2555,7 @@ VpAlloc(U_LONG mx, char *szVal)
else if(szVal[i] == '+') ++i;
/* Skip digits */
ni = 0; /* digits in mantissa */
- while(v = szVal[i]) {
+ while((v = szVal[i]) != 0) {
if(!ISDIGIT(v)) break;
++i;
++ni;
@@ -1963,7 +2569,7 @@ VpAlloc(U_LONG mx, char *szVal)
if(szVal[i] == '.') { /* xxx. */
++i;
ipf = i;
- while(v = szVal[i]) { /* get fraction part. */
+ while((v = szVal[i]) != 0) { /* get fraction part. */
if(!ISDIGIT(v)) break;
++i;
++nf;
@@ -1981,7 +2587,7 @@ VpAlloc(U_LONG mx, char *szVal)
ipe = i;
v = szVal[i];
if((v == '-') ||(v == '+')) ++i;
- while(v=szVal[i]) {
+ while((v=szVal[i])!=0) {
if(!ISDIGIT(v)) break;
++i;
++ne;
@@ -2220,8 +2826,7 @@ VpAddAbs(Real *a, Real *b, Real *c)
while(b_pos + word_shift > a_pos) {
--c_pos;
if(b_pos > 0) {
- --b_pos;
- c->frac[c_pos] = b->frac[b_pos];
+ c->frac[c_pos] = b->frac[--b_pos];
} else {
--word_shift;
c->frac[c_pos] = 0;
@@ -2232,19 +2837,14 @@ VpAddAbs(Real *a, Real *b, Real *c)
/* corresponding digits to be added. */
bv = b_pos + word_shift;
while(a_pos > bv) {
- --c_pos;
- --a_pos;
- c->frac[c_pos] = a->frac[a_pos];
+ c->frac[--c_pos] = a->frac[--a_pos];
}
carry = 0; /* set first carry be zero */
/* Now perform addition until every digits of b will be */
/* exhausted. */
while(b_pos > 0) {
- --a_pos;
- --b_pos;
- --c_pos;
- c->frac[c_pos] = a->frac[a_pos] + b->frac[b_pos] + carry;
+ c->frac[--c_pos] = a->frac[--a_pos] + b->frac[--b_pos] + carry;
if(c->frac[c_pos] >= BASE) {
c->frac[c_pos] -= BASE;
carry = 1;
@@ -2256,9 +2856,7 @@ VpAddAbs(Real *a, Real *b, Real *c)
/* Just assign the first few digits of a with considering */
/* the carry obtained so far because b has been exhausted. */
while(a_pos > 0) {
- --a_pos;
- --c_pos;
- c->frac[c_pos] = a->frac[a_pos] + carry;
+ c->frac[--c_pos] = a->frac[--a_pos] + carry;
if(c->frac[c_pos] >= BASE) {
c->frac[c_pos] -= BASE;
carry = 1;
@@ -2326,19 +2924,15 @@ VpSubAbs(Real *a, Real *b, Real *c)
/* each of the last few digits of the b because the a has no */
/* corresponding digits to be subtracted. */
if(b_pos + word_shift > a_pos) {
- borrow = 1;
- --c_pos;
- --b_pos;
- c->frac[c_pos] = BASE - b->frac[b_pos];
while(b_pos + word_shift > a_pos) {
--c_pos;
if(b_pos > 0) {
- --b_pos;
- c->frac[c_pos] = BASE - b->frac[b_pos] - borrow;
+ c->frac[c_pos] = BASE - b->frac[--b_pos] - borrow;
} else {
--word_shift;
c->frac[c_pos] = BASE - borrow;
}
+ borrow = 1;
}
}
/* Just assign the last few digits of a to c because b has no */
@@ -2346,18 +2940,14 @@ VpSubAbs(Real *a, Real *b, Real *c)
bv = b_pos + word_shift;
while(a_pos > bv) {
- --c_pos;
- --a_pos;
- c->frac[c_pos] = a->frac[a_pos];
+ c->frac[--c_pos] = a->frac[--a_pos];
}
/* Now perform subtraction until every digits of b will be */
/* exhausted. */
while(b_pos > 0) {
- --a_pos;
- --b_pos;
--c_pos;
- if(a->frac[a_pos] < b->frac[b_pos] + borrow) {
+ if(a->frac[--a_pos] < b->frac[--b_pos] + borrow) {
c->frac[c_pos] = BASE + a->frac[a_pos] - b->frac[b_pos] - borrow;
borrow = 1;
} else {
@@ -2370,8 +2960,7 @@ VpSubAbs(Real *a, Real *b, Real *c)
/* the borrow obtained so far because b has been exhausted. */
while(a_pos > 0) {
--c_pos;
- --a_pos;
- if(a->frac[a_pos] < borrow) {
+ if(a->frac[--a_pos] < borrow) {
c->frac[c_pos] = BASE + a->frac[a_pos] - borrow;
borrow = 1;
} else {
@@ -3301,7 +3890,7 @@ VpToFString(Real *a,char *psz,int fFmt,int fPlus)
* ne ... number of characters in exp_chr[],not including '+/-'.
*/
VP_EXPORT int
-VpCtoV(Real *a, char *int_chr, U_LONG ni, char *frac, U_LONG nf, char *exp_chr, U_LONG ne)
+VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, const char *exp_chr, U_LONG ne)
{
U_LONG i, j, ind_a, ma, mi, me;
U_LONG loc;
@@ -3328,7 +3917,7 @@ VpCtoV(Real *a, char *int_chr, U_LONG ni, char *frac, U_LONG nf, char *exp_chr,
es = e*((S_INT)BASE_FIG);
e = e * 10 + exp_chr[i] - '0';
if(es>e*((S_INT)BASE_FIG)) {
- return VpException(VP_EXCEPTION_INFINITY,"Exponent overflow",0);
+ return VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0);
}
++i;
}
@@ -3337,7 +3926,7 @@ VpCtoV(Real *a, char *int_chr, U_LONG ni, char *frac, U_LONG nf, char *exp_chr,
/* get integer part */
i = 0;
sign = 1;
- if(ni > 0) {
+ if(ni >= 0) {
if(int_chr[0] == '-') {
sign = -1;
++i;
@@ -3747,28 +4336,50 @@ VpMidRound(Real *y, int f, int nf)
* nf: digit location to round from the the decimal point.
*/
{
- int n,i,ix,ioffset;
- U_LONG v;
+ /* fracf: any positive digit under rounding position? */
+ /* exptoadd: number of digits needed to compensate negative nf */
+ int n,i,ix,ioffset,fracf,exptoadd;
+ U_LONG v,shifter;
U_LONG div;
nf += y->exponent*((int)BASE_FIG);
+ exptoadd=0;
+ if (nf < 0) {
+ /* rounding position too left(large). */
+ if((f!=VP_ROUND_CEIL) && (f!=VP_ROUND_FLOOR)) {
+ VpSetZero(y,VpGetSign(y)); /* truncate everything */
+ return 0;
+ }
+ exptoadd = -nf;
+ nf = 0;
+ }
/* ix: x->fraq[ix] contains round position */
ix = nf/(int)BASE_FIG;
- if(ix<0 || ((U_LONG)ix)>=y->Prec) return 0; /* Unable to round */
+ if(((U_LONG)ix)>=y->Prec) return 0; /* Unable to round */
ioffset = nf - ix*((int)BASE_FIG);
- memset(y->frac+ix+1, 0, (y->Prec - (ix+1)) * sizeof(U_LONG));
v = y->frac[ix];
/* drop digits after pointed digit */
n = BASE_FIG - ioffset - 1;
- for(i=0;i<n;++i) v /= 10;
+ for(shifter=1,i=0;i<n;++i) shifter *= 10;
+ fracf = (v%(shifter*10) > 0);
+ v /= shifter;
div = v/10;
v = v - div*10;
+ if (fracf == 0) {
+ for(i=ix+1;i<y->Prec;i++) {
+ if (y->frac[i]%BASE) {
+ fracf = 1;
+ break;
+ }
+ }
+ }
+ memset(y->frac+ix+1, 0, (y->Prec - (ix+1)) * sizeof(U_LONG));
switch(f) {
case VP_ROUND_DOWN: /* Truncate */
break;
case VP_ROUND_UP: /* Roundup */
- if(v) ++div;
+ if(fracf) ++div;
break;
case VP_ROUND_HALF_UP: /* Round half up */
if(v>=5) ++div;
@@ -3777,10 +4388,10 @@ VpMidRound(Real *y, int f, int nf)
if(v>=6) ++div;
break;
case VP_ROUND_CEIL: /* ceil */
- if(v && (VpGetSign(y)>0)) ++div;
+ if(fracf && (VpGetSign(y)>0)) ++div;
break;
case VP_ROUND_FLOOR: /* floor */
- if(v && (VpGetSign(y)<0)) ++div;
+ if(fracf && (VpGetSign(y)<0)) ++div;
break;
case VP_ROUND_HALF_EVEN: /* Banker's rounding */
if(v>5) ++div;
@@ -3795,19 +4406,31 @@ VpMidRound(Real *y, int f, int nf)
}
for(i=0;i<=n;++i) div *= 10;
if(div>=BASE) {
- y->frac[ix] = 0;
if(ix) {
- VpNmlz(y);
- VpRdup(y,0);
+ y->frac[ix] = 0;
+ VpRdup(y,ix);
} else {
S_INT s = VpGetSign(y);
+ int e = y->exponent;
VpSetOne(y);
VpSetSign(y,s);
+ y->exponent = e+1;
}
} else {
y->frac[ix] = div;
VpNmlz(y);
}
+ if (exptoadd > 0) {
+ y->exponent += exptoadd/BASE_FIG;
+ exptoadd %= BASE_FIG;
+ for(i=0;i<exptoadd;i++) {
+ y->frac[0] *= 10;
+ if (y->frac[0] >= BASE) {
+ y->frac[0] /= BASE;
+ y->exponent++;
+ }
+ }
+ }
return 1;
}
@@ -3821,7 +4444,7 @@ VpLeftRound(Real *y, int f, int nf)
if(!VpHasVal(y)) return 0; /* Unable to round */
v = y->frac[0];
nf -= VpExponent(y)*BASE_FIG;
- while(v=v/10) nf--;
+ while((v /= 10) != 0) nf--;
nf += (BASE_FIG-1);
return VpMidRound(y,f,nf);
}
diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h
index aabc551a76..4f77feab00 100644
--- a/ext/bigdecimal/bigdecimal.h
+++ b/ext/bigdecimal/bigdecimal.h
@@ -105,7 +105,7 @@ typedef struct {
VP_EXPORT Real *
VpNewRbClass(U_LONG mx,char *str,VALUE klass);
-VP_EXPORT Real *VpCreateRbObject(U_LONG mx,char *str);
+VP_EXPORT Real *VpCreateRbObject(U_LONG mx,const char *str);
VP_EXPORT U_LONG VpBaseFig(void);
VP_EXPORT U_LONG VpDblFig(void);
@@ -126,13 +126,13 @@ VP_EXPORT int VpIsRoundMode(unsigned long n);
VP_EXPORT unsigned long VpGetRoundMode(void);
VP_EXPORT unsigned long VpSetRoundMode(unsigned long n);
-VP_EXPORT int VpException(unsigned short f,char *str,int always);
+VP_EXPORT int VpException(unsigned short f,const char *str,int always);
VP_EXPORT int VpIsNegDoubleZero(double v);
-VP_EXPORT U_LONG VpNumOfChars(Real *vp,char *pszFmt);
+VP_EXPORT U_LONG VpNumOfChars(Real *vp,const char *pszFmt);
VP_EXPORT U_LONG VpInit(U_LONG BaseVal);
VP_EXPORT void *VpMemAlloc(U_LONG mb);
VP_EXPORT void VpFree(Real *pv);
-VP_EXPORT Real *VpAlloc(U_LONG mx, char *szVal);
+VP_EXPORT Real *VpAlloc(U_LONG mx, const char *szVal);
VP_EXPORT int VpAsgn(Real *c,Real *a,int isw);
VP_EXPORT int VpAddSub(Real *c,Real *a,Real *b,int operation);
VP_EXPORT int VpMult(Real *c,Real *a,Real *b);
@@ -143,7 +143,7 @@ VP_EXPORT void VpSzMantissa(Real *a,char *psz);
VP_EXPORT int VpToSpecialString(Real *a,char *psz,int fPlus);
VP_EXPORT void VpToString(Real *a,char *psz,int fFmt,int fPlus);
VP_EXPORT void VpToFString(Real *a,char *psz,int fFmt,int fPlus);
-VP_EXPORT int VpCtoV(Real *a,char *int_chr,U_LONG ni,char *frac,U_LONG nf,char *exp_chr,U_LONG ne);
+VP_EXPORT int VpCtoV(Real *a,const char *int_chr,U_LONG ni,const char *frac,U_LONG nf,const char *exp_chr,U_LONG ne);
VP_EXPORT int VpVtoD(double *d,S_LONG *e,Real *m);
VP_EXPORT void VpDtoV(Real *m,double d);
VP_EXPORT void VpItoV(Real *m,S_INT ival);
@@ -155,7 +155,7 @@ VP_EXPORT void VpFrac(Real *y,Real *x);
VP_EXPORT int VpPower(Real *y,Real *x,S_INT n);
/* VP constants */
-VP_EXPORT Real *VpOne();
+VP_EXPORT Real *VpOne(void);
/*
* ------------------
diff --git a/ext/bigdecimal/bigdecimal_en.html b/ext/bigdecimal/bigdecimal_en.html
index 02c88df43e..c2b86faef6 100644
--- a/ext/bigdecimal/bigdecimal_en.html
+++ b/ext/bigdecimal/bigdecimal_en.html
@@ -379,7 +379,7 @@ after every n digits for readability.
<CODE><PRE>
BigDecimal("0.1234567890123456789").to_s(10) # ==> "0.1234567890 123456789E0"
</PRE></CODE>
-n can be an string representing a positive integer number.
+n can be a string representing a positive integer number.
<CODE><PRE>
BigDecimal("0.1234567890123456789").to_s("10") # ==> "0.1234567890 123456789E0"
</PRE></CODE>
@@ -678,10 +678,9 @@ structure.
</DL>
<H3>Disadvantage of decimal representation</H3>
-Advantages stated so far can also be disadvantages if the input from outside is
- represented in binary.
-Translation error from decimal to binary or vice versa is inevitable.
-So,translation from Float(binary) to BigDecimal(decimal) is not alway done exactly.
+Because most computers have no internal decimal representaion.
+Once you use BigDecimal,you need to keep using it without
+considering computation cost if exact computation is required.
<H4>Which is the first input?</H4>
Because most people uses decimal notatin for numeric data representation,
diff --git a/ext/bigdecimal/bigdecimal_ja.html b/ext/bigdecimal/bigdecimal_ja.html
index 8fd95a6fe3..37bbcbbb09 100644
--- a/ext/bigdecimal/bigdecimal_ja.html
+++ b/ext/bigdecimal/bigdecimal_ja.html
@@ -676,10 +676,11 @@ exponent=1Asign=2 ‚Ȃ甒l‚ª 1234.56784321 ‚Å‚ ‚é‚̂͌©‚ê‚Î’¼‚®‚É•ª‚©‚è‚Ü‚·B
<H3>10i‚̃fƒƒŠƒbƒg</H3>
ŽÀ‚Í¡‚܂ł̃ƒŠƒbƒg‚ÍA‚»‚̂܂܃fƒƒŠƒbƒg‚É‚à‚È‚è‚Ü‚·B
-‚»‚à‚»‚àA10i‚ð2iA2i‚ð10i‚ɕϊ·‚·‚邿‚¤‚È‘€ì‚͕ϊ·Œë·
+‚»‚à‚»‚àA10i‚ð2i‚ɕϊ·‚·‚邿‚¤‚È‘€ì‚͕ϊ·Œë·
‚𔺂¤ê‡‚ð‰ñ”ð‚·‚é‚±‚Ƃ͂ł«‚Ü‚¹‚ñB
-Šù‚ÉŒvŽZ‹@“à•”‚ÉŽæ‚螂܂ꂽ2i”’l‚ð BigDecimal ‚Ì“à•”•\Œ»‚É
-•ÏŠ·‚·‚邯‚«‚ɂ͌뷂ª”ð‚¯‚ç‚ê‚È‚¢ê‡‚ª‚ ‚è‚Ü‚·B
+‘åŠT‚̃Rƒ“ƒsƒ…[ƒ^‚Í10i‚Ì“à•”•\Œ»‚ðŽ‚Á‚Ä‚¢‚È‚¢‚Ì‚ÅA
+BigDecimal ‚ð—˜—p‚µ‚Č뷖³‚µ‚ÌŒvŽZ‚ð‚·‚éꇂÍAŒvŽZ‘¬“x
+‚𖳎‹‚µ‚Ä‚àÅŒã‚܂ŠBigDecimal ‚ðŽg—p‘±‚¯‚é•K—v‚ª‚ ‚è‚Ü‚·B
<H3>ʼn‚͉½‚©H</H3>
Ž©•ª‚ÅŒvŽZ‚·‚邯‚«‚ɂ킴‚í‚´2i”‚ðŽg‚¤l‚͋ɂ߂Ă܂ê‚Å‚·B
diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb
index a68a656044..0c8b98e4a3 100644
--- a/ext/bigdecimal/extconf.rb
+++ b/ext/bigdecimal/extconf.rb
@@ -1,2 +1,10 @@
require 'mkmf'
+
+base_fig = 0
+src = "(BASE * (BASE+1)) / BASE == (BASE+1)"
+while try_static_assert(src, nil, "-DBASE=10#{'0'*base_fig}UL")
+ base_fig += 1
+end
+$defs << "-DBASE=1#{'0'*base_fig}UL" << "-DBASE_FIG=#{base_fig}"
+
create_makefile('bigdecimal')
diff --git a/ext/bigdecimal/lib/bigdecimal/jacobian.rb b/ext/bigdecimal/lib/bigdecimal/jacobian.rb
index 34a60ae67a..d80eeab901 100644
--- a/ext/bigdecimal/lib/bigdecimal/jacobian.rb
+++ b/ext/bigdecimal/lib/bigdecimal/jacobian.rb
@@ -1,9 +1,27 @@
#
-# jacobian.rb
+# require 'bigdecimal/jacobian'
#
-# Computes Jacobian matrix of f at x
+# Provides methods to compute the Jacobian matrix of a set of equations at a
+# point x. In the methods below:
+#
+# f is an Object which is used to compute the Jacobian matrix of the equations.
+# It must provide the following methods:
+#
+# f.values(x):: returns the values of all functions at x
+#
+# f.zero:: returns 0.0
+# f.one:: returns 1.0
+# f.two:: returns 1.0
+# f.ten:: returns 10.0
+#
+# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
+#
+# x is the point at which to compute the Jacobian.
+#
+# fx is f.values(x).
#
module Jacobian
+ #--
def isEqual(a,b,zero=0.0,e=1.0e-8)
aa = a.abs
bb = b.abs
@@ -17,7 +35,10 @@ module Jacobian
end
end
end
+ #++
+ # Computes the derivative of f[i] at x[i].
+ # fx is the value of f at x.
def dfdxi(f,fx,x,i)
nRetry = 0
n = x.size
@@ -49,6 +70,7 @@ module Jacobian
deriv
end
+ # Computes the Jacobian of f at x. fx is the value of f at x.
def jacobian(f,fx,x)
n = x.size
dfdx = Array::new(n*n)
diff --git a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb b/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
index 1d5d3170cc..8f4888725e 100644
--- a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
+++ b/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
@@ -1,7 +1,8 @@
#
-# ludcmp.rb
+# Solves a*x = b for x, using LU decomposition.
#
module LUSolve
+ # Performs LU decomposition of the n by n matrix a.
def ludecomp(a,n,zero=0,one=1)
prec = BigDecimal.limit(nil)
ps = []
@@ -52,6 +53,12 @@ module LUSolve
ps
end
+ # Solves a*x = b for x, using LU decomposition.
+ #
+ # a is a matrix, b is a constant vector, x is the solution vector.
+ #
+ # ps is the pivot, a vector which indicates the permutation of rows performed
+ # during LU decomposition.
def lusolve(a,b,ps,zero=0.0)
prec = BigDecimal.limit(nil)
n = ps.size
diff --git a/ext/bigdecimal/lib/bigdecimal/math.rb b/ext/bigdecimal/lib/bigdecimal/math.rb
index 7b3f46ed1a..f3248a3c5c 100644
--- a/ext/bigdecimal/lib/bigdecimal/math.rb
+++ b/ext/bigdecimal/lib/bigdecimal/math.rb
@@ -1,4 +1,5 @@
#
+#--
# Contents:
# sqrt(x, prec)
# sin (x, prec)
@@ -13,19 +14,35 @@
# x ... BigDecimal number to be computed.
# |x| must be small enough to get convergence.
# prec ... Number of digits to be obtained.
+#++
+#
+# Provides mathematical functions.
+#
+# Example:
#
-# Usage:
# require "bigdecimal"
-# require "bigdecimal/math.rb"
+# require "bigdecimal/math"
+#
# include BigMath
+#
# a = BigDecimal((PI(100)/2).to_s)
-# puts sin(a,100) # => 0.10000000000000000000......E1
+# puts sin(a,100) # -> 0.10000000000000000000......E1
#
module BigMath
+
+ # Computes the square root of x to the specified number of digits of
+ # precision.
+ #
+ # BigDecimal.new('2').sqrt(16).to_s
+ # -> "0.14142135623730950488016887242096975E1"
+ #
def sqrt(x,prec)
x.sqrt(prec)
end
+ # Computes the sine of x to the specified number of digits of precision.
+ #
+ # If x is infinite or NaN, returns NaN.
def sin(x, prec)
raise ArgumentError, "Zero or negative precision for sin" if prec <= 0
return BigDecimal("NaN") if x.infinite? || x.nan?
@@ -51,6 +68,9 @@ module BigMath
y
end
+ # Computes the cosine of x to the specified number of digits of precision.
+ #
+ # If x is infinite or NaN, returns NaN.
def cos(x, prec)
raise ArgumentError, "Zero or negative precision for cos" if prec <= 0
return BigDecimal("NaN") if x.infinite? || x.nan?
@@ -76,6 +96,10 @@ module BigMath
y
end
+ # Computes the arctangent of x to the specified number of digits of precision.
+ #
+ # If x is infinite or NaN, returns NaN.
+ # Raises an argument error if x > 1.
def atan(x, prec)
raise ArgumentError, "Zero or negative precision for atan" if prec <= 0
return BigDecimal("NaN") if x.infinite? || x.nan?
@@ -96,6 +120,13 @@ module BigMath
y
end
+ # Computes the value of e (the base of natural logarithms) raised to the
+ # power of x, to the specified number of digits of precision.
+ #
+ # If x is infinite or NaN, returns NaN.
+ #
+ # BigMath::exp(BigDecimal.new('1'), 10).to_s
+ # -> "0.271828182845904523536028752390026306410273E1"
def exp(x, prec)
raise ArgumentError, "Zero or negative precision for exp" if prec <= 0
return BigDecimal("NaN") if x.infinite? || x.nan?
@@ -117,6 +148,11 @@ module BigMath
y
end
+ # Computes the natural logarithm of x to the specified number of digits
+ # of precision.
+ #
+ # Returns x if x is infinite or NaN.
+ #
def log(x, prec)
raise ArgumentError, "Zero or negative argument for log" if x <= 0 || prec <= 0
return x if x.infinite? || x.nan?
@@ -138,6 +174,7 @@ module BigMath
y*two
end
+ # Computes the value of pi to the specified number of digits of precision.
def PI(prec)
raise ArgumentError, "Zero or negative argument for PI" if prec <= 0
n = prec + BigDecimal.double_fig
@@ -176,6 +213,8 @@ module BigMath
pi
end
+ # Computes e (the base of natural logarithms) to the specified number of
+ # digits of precision.
def E(prec)
raise ArgumentError, "Zero or negative precision for E" if prec <= 0
n = prec + BigDecimal.double_fig
diff --git a/ext/bigdecimal/lib/bigdecimal/newton.rb b/ext/bigdecimal/lib/bigdecimal/newton.rb
index 67a92474ac..59ac0f7f04 100644
--- a/ext/bigdecimal/lib/bigdecimal/newton.rb
+++ b/ext/bigdecimal/lib/bigdecimal/newton.rb
@@ -1,27 +1,29 @@
#
# newton.rb
#
-# Solves nonlinear algebraic equation system f = 0 by Newton's method.
-# (This program is not dependent on BigDecimal)
+# Solves the nonlinear algebraic equation system f = 0 by Newton's method.
+# This program is not dependent on BigDecimal.
#
# To call:
# n = nlsolve(f,x)
-# where n is the number of iterations required.
-# x is the solution vector.
-# f is the object to be solved which must have following methods.
+# where n is the number of iterations required,
+# x is the initial value vector
+# f is an Object which is used to compute the values of the equations to be solved.
+# It must provide the following methods:
#
-# f ... Object to compute Jacobian matrix of the equation systems.
-# [Methods required for f]
-# f.values(x) returns values of all functions at x.
-# f.zero returns 0.0
-# f.one returns 1.0
-# f.two returns 1.0
-# f.ten returns 10.0
-# f.eps convergence criterion
-# x ... initial values
+# f.values(x):: returns the values of all functions at x
#
-require "ludcmp"
-require "jacobian"
+# f.zero:: returns 0.0
+# f.one:: returns 1.0
+# f.two:: returns 1.0
+# f.ten:: returns 10.0
+#
+# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
+#
+# On exit, x is the solution vector.
+#
+require "bigdecimal/ludcmp"
+require "bigdecimal/jacobian"
module Newton
include LUSolve
@@ -60,7 +62,7 @@ module Newton
begin
fact *= p5
if fact < minfact then
- raize "Failed to reduce function values."
+ raise "Failed to reduce function values."
end
for i in 0...n do
x[i] = xs[i] - dx[i]*fact
diff --git a/ext/bigdecimal/lib/bigdecimal/nlsolve.rb b/ext/bigdecimal/lib/bigdecimal/nlsolve.rb
deleted file mode 100644
index 08f17f9ecd..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/nlsolve.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/local/bin/ruby
-
-#
-# nlsolve.rb
-# An example for solving nonlinear algebraic equation system.
-#
-
-require "bigdecimal"
-require "newton"
-include Newton
-
-class Function
- def initialize()
- @zero = BigDecimal::new("0.0")
- @one = BigDecimal::new("1.0")
- @two = BigDecimal::new("2.0")
- @ten = BigDecimal::new("10.0")
- @eps = BigDecimal::new("1.0e-16")
- end
- def zero;@zero;end
- def one ;@one ;end
- def two ;@two ;end
- def ten ;@ten ;end
- def eps ;@eps ;end
- def values(x) # <= defines functions solved
- f = []
- f1 = x[0]*x[0] + x[1]*x[1] - @two # f1 = x**2 + y**2 - 2 => 0
- f2 = x[0] - x[1] # f2 = x - y => 0
- f <<= f1
- f <<= f2
- f
- end
-end
- f = BigDecimal::limit(100)
- f = Function.new
- x = [f.zero,f.zero] # Initial values
- n = nlsolve(f,x)
- p x
diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb
index 1f8d6c7a49..09e926acd5 100644
--- a/ext/bigdecimal/lib/bigdecimal/util.rb
+++ b/ext/bigdecimal/lib/bigdecimal/util.rb
@@ -1,19 +1,17 @@
#
# BigDecimal utility library.
-# ----------------------------------------------------------------------
-# Contents:
#
-# String#
-# to_d ... to BigDecimal
+# To use these functions, require 'bigdecimal/util'
+#
+# The following methods are provided to convert other types to BigDecimals:
#
-# Float#
-# to_d ... to BigDecimal
+# String#to_d -> BigDecimal
+# Float#to_d -> BigDecimal
+# Rational#to_d -> BigDecimal
#
-# BigDecimal#
-# to_r ... to Rational
+# The following method is provided to convert BigDecimals to other types:
#
-# Rational#
-# to_d ... to BigDecimal
+# BigDecimal#to_r -> Rational
#
# ----------------------------------------------------------------------
#
@@ -30,8 +28,8 @@ class String
end
class BigDecimal < Numeric
- # to "nnnnnn.mmm" form digit string
- # Use BigDecimal#to_s("F") instead.
+ # Converts a BigDecimal to a String of the form "nnnnnn.mmm".
+ # This method is deprecated; use BigDecimal#to_s("F") instead.
def to_digits
if self.nan? || self.infinite? || self.zero?
self.to_s
@@ -42,22 +40,21 @@ class BigDecimal < Numeric
end
end
- # Convert BigDecimal to Rational
+ # Converts a BigDecimal to a Rational.
def to_r
sign,digits,base,power = self.split
numerator = sign*digits.to_i
denomi_power = power - digits.size # base is always 10
if denomi_power < 0
- denominator = base ** (-denomi_power)
+ Rational(numerator,base ** (-denomi_power))
else
- denominator = base ** denomi_power
+ Rational(numerator * (base ** denomi_power),1)
end
- Rational(numerator,denominator)
end
end
class Rational < Numeric
- # Convert Rational to BigDecimal
+ # Converts a Rational to a BigDecimal
def to_d(nFig=0)
num = self.numerator.to_s
if nFig<=0
diff --git a/ext/bigdecimal/sample/linear.rb b/ext/bigdecimal/sample/linear.rb
index 7c8ca263eb..88a62ffa71 100644
--- a/ext/bigdecimal/sample/linear.rb
+++ b/ext/bigdecimal/sample/linear.rb
@@ -11,7 +11,7 @@
#
require "bigdecimal"
-require "ludcmp"
+require "bigdecimal/ludcmp"
#
# NOTE:
diff --git a/ext/bigdecimal/sample/nlsolve.rb b/ext/bigdecimal/sample/nlsolve.rb
index 08f17f9ecd..7f729e6aaa 100644
--- a/ext/bigdecimal/sample/nlsolve.rb
+++ b/ext/bigdecimal/sample/nlsolve.rb
@@ -6,7 +6,7 @@
#
require "bigdecimal"
-require "newton"
+require "bigdecimal/newton"
include Newton
class Function
diff --git a/ext/curses/MANIFEST b/ext/curses/MANIFEST
deleted file mode 100644
index 5882d682f0..0000000000
--- a/ext/curses/MANIFEST
+++ /dev/null
@@ -1,9 +0,0 @@
-MANIFEST
-curses.c
-depend
-extconf.rb
-hello.rb
-rain.rb
-view.rb
-view2.rb
-mouse.rb
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index 2e60b21609..9c51a2127f 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -21,7 +21,11 @@
#elif defined(HAVE_NCURSES_CURSES_H)
# include <ncurses/curses.h>
#elif defined(HAVE_CURSES_COLR_CURSES_H)
-# include <varargs.h>
+# ifdef HAVE_STDARG_PROTOTYPES
+# include <stdarg.h>
+# else
+# include <varargs.h>
+# endif
# include <curses_colr/curses.h>
#else
# include <curses.h>
@@ -50,6 +54,9 @@
# define USE_MOUSE 1
#endif
+#define NUM2CH NUM2LONG
+#define CH2FIX LONG2FIX
+
static VALUE mCurses;
static VALUE mKey;
static VALUE cWindow;
@@ -120,7 +127,7 @@ curses_init_screen()
if (rb_stdscr) return rb_stdscr;
initscr();
if (stdscr == 0) {
- rb_raise(rb_eRuntimeError, "cannot initialize curses");
+ rb_raise(rb_eRuntimeError, "can't initialize curses");
}
clear();
rb_stdscr = prep_window(cWindow, stdscr);
@@ -179,6 +186,15 @@ curses_clear(obj)
return Qnil;
}
+/* def clrtoeol */
+static VALUE
+curses_clrtoeol()
+{
+ curses_stdscr();
+ clrtoeol();
+ return Qnil;
+}
+
/* def refresh */
static VALUE
curses_refresh(obj)
@@ -358,7 +374,7 @@ curses_inch(obj)
VALUE obj;
{
curses_stdscr();
- return CHR2FIX(inch());
+ return CH2FIX(inch());
}
/* def addch(ch) */
@@ -368,7 +384,7 @@ curses_addch(obj, ch)
VALUE ch;
{
curses_stdscr();
- addch(NUM2CHR(ch));
+ addch(NUM2CH(ch));
return Qnil;
}
@@ -379,7 +395,7 @@ curses_insch(obj, ch)
VALUE ch;
{
curses_stdscr();
- insch(NUM2CHR(ch));
+ insch(NUM2CH(ch));
return Qnil;
}
@@ -442,6 +458,17 @@ curses_deleteln(obj)
return Qnil;
}
+/* def insertln */
+static VALUE
+curses_insertln(obj)
+ VALUE obj;
+{
+#if defined(HAVE_INSERTLN) || defined(insertln)
+ insertln();
+#endif
+ return Qnil;
+}
+
/* def keyname */
static VALUE
curses_keyname(obj, c)
@@ -532,7 +559,7 @@ static VALUE
curses_bkgdset(VALUE obj, VALUE ch)
{
#ifdef HAVE_BKGDSET
- bkgdset(NUM2CHR(ch));
+ bkgdset(NUM2CH(ch));
#endif
return Qnil;
}
@@ -541,7 +568,7 @@ static VALUE
curses_bkgd(VALUE obj, VALUE ch)
{
#ifdef HAVE_BKGD
- return (bkgd(NUM2CHR(ch)) == OK) ? Qtrue : Qfalse;
+ return (bkgd(NUM2CH(ch)) == OK) ? Qtrue : Qfalse;
#else
return Qfalse;
#endif
@@ -621,7 +648,7 @@ curses_pair_number(VALUE obj, VALUE attrs)
{
return INT2FIX(PAIR_NUMBER(NUM2INT(attrs)));
}
-#endif
+#endif /* USE_COLOR */
#ifdef USE_MOUSE
struct mousedata {
@@ -656,7 +683,7 @@ curses_getmouse(VALUE obj)
val = Data_Make_Struct(cMouseEvent,struct mousedata,
0,curses_mousedata_free,mdata);
- mdata->mevent = (MEVENT*)malloc(sizeof(MEVENT));
+ mdata->mevent = (MEVENT*)xmalloc(sizeof(MEVENT));
return (getmouse(mdata->mevent) == OK) ? val : Qnil;
}
@@ -762,22 +789,26 @@ window_initialize(obj, h, w, top, left)
return obj;
}
-/* def subwin(h, w, top, left) */
+/* def subwin(height, width, top, left) */
static VALUE
-window_subwin(obj, h, w, top, left)
+window_subwin(obj, height, width, top, left)
VALUE obj;
- VALUE h;
- VALUE w;
+ VALUE height;
+ VALUE width;
VALUE top;
VALUE left;
{
struct windata *winp;
WINDOW *window;
VALUE win;
+ int h, w, t, l;
+ h = NUM2INT(height);
+ w = NUM2INT(width);
+ t = NUM2INT(top);
+ l = NUM2INT(left);
GetWINDOW(obj, winp);
- window = subwin(winp->window, NUM2INT(h), NUM2INT(w),
- NUM2INT(top), NUM2INT(left));
+ window = subwin(winp->window, h, w, t, l);
win = prep_window(rb_obj_class(obj), window);
return win;
@@ -810,6 +841,19 @@ window_clear(obj)
return Qnil;
}
+/* def clrtoeol */
+static VALUE
+window_clrtoeol(obj)
+ VALUE obj;
+{
+ struct windata *winp;
+
+ GetWINDOW(obj, winp);
+ wclrtoeol(winp->window);
+
+ return Qnil;
+}
+
/* def refresh */
static VALUE
window_refresh(obj)
@@ -983,13 +1027,13 @@ window_box(argc, argv, self)
rb_scan_args(argc, argv, "21", &vert, &hor, &corn);
GetWINDOW(self, winp);
- box(winp->window, NUM2CHR(vert), NUM2CHR(hor));
+ box(winp->window, NUM2CH(vert), NUM2CH(hor));
if (!NIL_P(corn)) {
int cur_x, cur_y, x, y;
- char c;
+ chtype c;
- c = NUM2CHR(corn);
+ c = NUM2CH(corn);
getyx(winp->window, cur_y, cur_x);
x = NUM2INT(window_maxx(self)) - 1;
y = NUM2INT(window_maxy(self)) - 1;
@@ -1039,7 +1083,7 @@ window_inch(obj)
struct windata *winp;
GetWINDOW(obj, winp);
- return CHR2FIX(winch(winp->window));
+ return CH2FIX(winch(winp->window));
}
/* def addch(ch) */
@@ -1051,7 +1095,7 @@ window_addch(obj, ch)
struct windata *winp;
GetWINDOW(obj, winp);
- waddch(winp->window, NUM2CHR(ch));
+ waddch(winp->window, NUM2CH(ch));
return Qnil;
}
@@ -1065,7 +1109,7 @@ window_insch(obj, ch)
struct windata *winp;
GetWINDOW(obj, winp);
- winsch(winp->window, NUM2CHR(ch));
+ winsch(winp->window, NUM2CH(ch));
return Qnil;
}
@@ -1151,6 +1195,20 @@ window_deleteln(obj)
return Qnil;
}
+/* def insertln */
+static VALUE
+window_insertln(obj)
+ VALUE obj;
+{
+#if defined(HAVE_WINSERTLN) || defined(winsertln)
+ struct windata *winp;
+
+ GetWINDOW(obj, winp);
+ winsertln(winp->window);
+#endif
+ return Qnil;
+}
+
static VALUE
window_scrollok(VALUE obj, VALUE bf)
{
@@ -1187,6 +1245,19 @@ window_setscrreg(VALUE obj, VALUE top, VALUE bottom)
#endif
}
+#if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET)
+static VALUE
+window_color_set(VALUE obj, VALUE col)
+{
+ struct windata *winp;
+ int res;
+
+ GetWINDOW(obj, winp);
+ res = wcolor_set(winp->window, NUM2INT(col), NULL);
+ return (res == OK) ? Qtrue : Qfalse;
+}
+#endif /* USE_COLOR */
+
static VALUE
window_scroll(VALUE obj)
{
@@ -1266,7 +1337,7 @@ window_bkgdset(VALUE obj, VALUE ch)
struct windata *winp;
GetWINDOW(obj,winp);
- wbkgdset(winp->window, NUM2CHR(ch));
+ wbkgdset(winp->window, NUM2CH(ch));
#endif
return Qnil;
}
@@ -1278,7 +1349,7 @@ window_bkgd(VALUE obj, VALUE ch)
struct windata *winp;
GetWINDOW(obj,winp);
- return (wbkgd(winp->window, NUM2CHR(ch)) == OK) ? Qtrue : Qfalse;
+ return (wbkgd(winp->window, NUM2CH(ch)) == OK) ? Qtrue : Qfalse;
#else
return Qfalse;
#endif
@@ -1288,11 +1359,11 @@ static VALUE
window_getbkgd(VALUE obj)
{
#ifdef HAVE_WGETBKGD
- char c;
+ chtype c;
struct windata *winp;
GetWINDOW(obj,winp);
- return (c = getbkgd(winp->window) != ERR) ? CHR2FIX(c) : Qnil;
+ return (c = getbkgd(winp->window) != ERR) ? CH2FIX(c) : Qnil;
#else
return Qnil;
#endif
@@ -1392,6 +1463,7 @@ Init_curses()
rb_define_module_function(mCurses, "refresh", curses_refresh, 0);
rb_define_module_function(mCurses, "doupdate", curses_doupdate, 0);
rb_define_module_function(mCurses, "clear", curses_clear, 0);
+ rb_define_module_function(mCurses, "clrtoeol", curses_clrtoeol, 0);
rb_define_module_function(mCurses, "echo", curses_echo, 0);
rb_define_module_function(mCurses, "noecho", curses_noecho, 0);
rb_define_module_function(mCurses, "raw", curses_raw, 0);
@@ -1416,6 +1488,7 @@ Init_curses()
rb_define_module_function(mCurses, "getstr", curses_getstr, 0);
rb_define_module_function(mCurses, "delch", curses_delch, 0);
rb_define_module_function(mCurses, "deleteln", curses_deleteln, 0);
+ rb_define_module_function(mCurses, "insertln", curses_insertln, 0);
rb_define_module_function(mCurses, "keyname", curses_keyname, 1);
rb_define_module_function(mCurses, "lines", curses_lines, 0);
rb_define_module_function(mCurses, "cols", curses_cols, 0);
@@ -1443,7 +1516,7 @@ Init_curses()
#endif /* USE_COLOR */
#ifdef USE_MOUSE
rb_define_module_function(mCurses, "getmouse", curses_getmouse, 0);
- rb_define_module_function(mCurses, "ungetmouse", curses_getmouse, 1);
+ rb_define_module_function(mCurses, "ungetmouse", curses_ungetmouse, 1);
rb_define_module_function(mCurses, "mouseinterval", curses_mouseinterval, 1);
rb_define_module_function(mCurses, "mousemask", curses_mousemask, 1);
#endif /* USE_MOUSE */
@@ -1458,11 +1531,15 @@ Init_curses()
rb_define_method(cWindow, "subwin", window_subwin, 4);
rb_define_method(cWindow, "close", window_close, 0);
rb_define_method(cWindow, "clear", window_clear, 0);
+ rb_define_method(cWindow, "clrtoeol", window_clrtoeol, 0);
rb_define_method(cWindow, "refresh", window_refresh, 0);
rb_define_method(cWindow, "noutrefresh", window_noutrefresh, 0);
rb_define_method(cWindow, "box", window_box, -1);
rb_define_method(cWindow, "move", window_move, 2);
rb_define_method(cWindow, "setpos", window_setpos, 2);
+#if defined(USE_COLOR) && defined(HAVE_WCOLOR_SET)
+ rb_define_method(cWindow, "color_set", window_color_set, 1);
+#endif /* USE_COLOR && HAVE_WCOLOR_SET */
rb_define_method(cWindow, "cury", window_cury, 0);
rb_define_method(cWindow, "curx", window_curx, 0);
rb_define_method(cWindow, "maxy", window_maxy, 0);
@@ -1480,6 +1557,7 @@ Init_curses()
rb_define_method(cWindow, "getstr", window_getstr, 0);
rb_define_method(cWindow, "delch", window_delch, 0);
rb_define_method(cWindow, "deleteln", window_deleteln, 0);
+ rb_define_method(cWindow, "insertln", window_insertln, 0);
rb_define_method(cWindow, "scroll", window_scroll, 0);
rb_define_method(cWindow, "scrollok", window_scrollok, 1);
rb_define_method(cWindow, "idlok", window_idlok, 1);
@@ -1489,14 +1567,12 @@ Init_curses()
rb_define_method(cWindow, "keypad", window_keypad, 1);
rb_define_method(cWindow, "keypad=", window_keypad, 1);
-#ifdef USE_COLOR
rb_define_method(cWindow, "attroff", window_attroff, 1);
rb_define_method(cWindow, "attron", window_attron, 1);
rb_define_method(cWindow, "attrset", window_attrset, 1);
rb_define_method(cWindow, "bkgdset", window_bkgdset, 1);
rb_define_method(cWindow, "bkgd", window_bkgd, 1);
rb_define_method(cWindow, "getbkgd", window_getbkgd, 0);
-#endif /* USE_COLOR */
rb_define_method(cWindow, "nodelay=", window_nodelay, 1);
rb_define_method(cWindow, "timeout=", window_timeout, 1);
diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb
index d0eed198d3..0124bbbf4a 100644
--- a/ext/curses/extconf.rb
+++ b/ext/curses/extconf.rb
@@ -19,8 +19,8 @@ elsif have_header(*curses=%w"curses.h") and have_library("curses", "initscr")
end
if make
- for f in %w(beep bkgd bkgdset color curs deleteln doupdate flash getbkgd getnstr init isendwin keyname keypad resizeterm scrl set setscrreg ungetch wattroff wattron wattrset wbkgd wbkgdset wdeleteln wgetnstr wresize wscrl wsetscrreg def_prog_mode reset_prog_mode timeout wtimeout nodelay)
- have_func(f)
+ for f in %w(beep bkgd bkgdset curs_set deleteln doupdate flash getbkgd getnstr init isendwin keyname keypad resizeterm scrl set setscrreg ungetch wattroff wattron wattrset wbkgd wbkgdset wdeleteln wgetnstr wresize wscrl wsetscrreg def_prog_mode reset_prog_mode timeout wtimeout nodelay init_color wcolor_set)
+ have_func(f) || (have_macro(f, curses) && $defs.push(format("-DHAVE_%s", f.upcase)))
end
flag = "-D_XOPEN_SOURCE_EXTENDED"
src = "int test_var[(sizeof(char*)>sizeof(int))*2-1];"
diff --git a/ext/curses/view.rb b/ext/curses/view.rb
index 5ba1a8413c..d9a82a57db 100644
--- a/ext/curses/view.rb
+++ b/ext/curses/view.rb
@@ -49,7 +49,7 @@ while TRUE
n = 0
while TRUE
c = getch.chr
- if c =~ "[0-9]" then
+ if c =~ /[0-9]/
n = 10 * n + c.to_i
else
break
diff --git a/ext/dbm/MANIFEST b/ext/dbm/MANIFEST
deleted file mode 100644
index c8719f62a7..0000000000
--- a/ext/dbm/MANIFEST
+++ /dev/null
@@ -1,5 +0,0 @@
-MANIFEST
-dbm.c
-depend
-extconf.rb
-testdbm.rb
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index c422394405..0247387fdc 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -24,6 +24,8 @@
static VALUE rb_cDBM, rb_eDBMError;
+#define RUBY_DBM_RW_BIT 0x20000000
+
struct dbmdata {
int di_size;
DBM *di_dbm;
@@ -41,6 +43,11 @@ closed_dbm()
if (dbmp->di_dbm == 0) closed_dbm();\
}
+#define GetDBM2(obj, data, dbm) {\
+ GetDBM(obj, data);\
+ (dbm) = dbmp->di_dbm;\
+}
+
static void
free_dbm(dbmp)
struct dbmdata *dbmp;
@@ -64,6 +71,21 @@ fdbm_close(obj)
return Qnil;
}
+static VALUE
+fdbm_closed(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp == 0)
+ return Qtrue;
+ if (dbmp->di_dbm == 0)
+ return Qtrue;
+
+ return Qfalse;
+}
+
static VALUE fdbm_alloc _((VALUE));
static VALUE
fdbm_alloc(klass)
@@ -78,12 +100,12 @@ fdbm_initialize(argc, argv, obj)
VALUE *argv;
VALUE obj;
{
- VALUE file, vmode;
+ VALUE file, vmode, vflags;
DBM *dbm;
struct dbmdata *dbmp;
- int mode;
+ int mode, flags = 0;
- if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
+ if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
mode = 0666; /* default value */
}
else if (NIL_P(vmode)) {
@@ -92,17 +114,27 @@ fdbm_initialize(argc, argv, obj)
else {
mode = NUM2INT(vmode);
}
+
+ if (!NIL_P(vflags))
+ flags = NUM2INT(vflags);
+
SafeStringValue(file);
- dbm = 0;
- if (mode >= 0) {
- dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
- }
- if (!dbm) {
- dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, 0);
+ if (flags & RUBY_DBM_RW_BIT) {
+ flags &= ~RUBY_DBM_RW_BIT;
+ dbm = dbm_open(RSTRING(file)->ptr, flags, mode);
}
- if (!dbm) {
- dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, 0);
+ else {
+ dbm = 0;
+ if (mode >= 0) {
+ dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
+ }
+ if (!dbm) {
+ dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, 0);
+ }
+ if (!dbm) {
+ dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, 0);
+ }
}
if (!dbm) {
@@ -149,8 +181,7 @@ fdbm_fetch(obj, keystr, ifnone)
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
value = dbm_fetch(dbm, key);
if (value.dptr == 0) {
if (ifnone == Qnil && rb_block_given_p())
@@ -195,8 +226,7 @@ fdbm_index(obj, valstr)
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
if (val.dsize == RSTRING(valstr)->len &&
@@ -241,17 +271,18 @@ fdbm_select(argc, argv, obj)
if (argc > 0) {
rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
}
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- VALUE assoc;
+ VALUE assoc, v;
val = dbm_fetch(dbm, key);
assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
rb_tainted_str_new(val.dptr, val.dsize));
- if (RTEST(rb_yield(assoc)))
- rb_ary_push(new, assoc);
- }
+ v = rb_yield(assoc);
+ if (RTEST(v)) {
+ rb_ary_push(new, assoc);
+ }
+ GetDBM2(obj, dbmp, dbm);
+ }
}
else {
rb_warn("DBM#select(index..) is deprecated; use DBM#values_at");
@@ -280,6 +311,14 @@ fdbm_values_at(argc, argv, obj)
return new;
}
+static void
+fdbm_modify(obj)
+ VALUE obj;
+{
+ rb_secure(4);
+ if (OBJ_FROZEN(obj)) rb_error_frozen("DBM");
+}
+
static VALUE
fdbm_delete(obj, keystr)
VALUE obj, keystr;
@@ -289,14 +328,12 @@ fdbm_delete(obj, keystr)
DBM *dbm;
VALUE valstr;
- rb_secure(4);
+ fdbm_modify(obj);
StringValue(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
value = dbm_fetch(dbm, key);
if (value.dptr == 0) {
if (rb_block_given_p()) return rb_yield(keystr);
@@ -325,9 +362,8 @@ fdbm_shift(obj)
DBM *dbm;
VALUE keystr, valstr;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ fdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
dbmp->di_size = -1;
key = dbm_firstkey(dbm);
@@ -351,9 +387,8 @@ fdbm_delete_if(obj)
VALUE ret, ary = rb_ary_new();
int i, status = 0, n;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ fdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
n = dbmp->di_size;
dbmp->di_size = -1;
@@ -364,10 +399,12 @@ fdbm_delete_if(obj)
ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
if (status != 0) break;
if (RTEST(ret)) rb_ary_push(ary, keystr);
+ GetDBM2(obj, dbmp, dbm);
}
for (i = 0; i < RARRAY(ary)->len; i++) {
keystr = RARRAY(ary)->ptr[i];
+ StringValue(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
if (dbm_delete(dbm, key)) {
@@ -388,9 +425,8 @@ fdbm_clear(obj)
struct dbmdata *dbmp;
DBM *dbm;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ fdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
dbmp->di_size = -1;
while (key = dbm_firstkey(dbm), key.dptr) {
if (dbm_delete(dbm, key)) {
@@ -412,8 +448,7 @@ fdbm_invert(obj)
VALUE keystr, valstr;
VALUE hash = rb_hash_new();
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
keystr = rb_tainted_str_new(key.dptr, key.dsize);
@@ -471,19 +506,18 @@ fdbm_store(obj, keystr, valstr)
struct dbmdata *dbmp;
DBM *dbm;
- rb_secure(4);
+ fdbm_modify(obj);
keystr = rb_obj_as_string(keystr);
+ valstr = rb_obj_as_string(valstr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- valstr = rb_obj_as_string(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- GetDBM(obj, dbmp);
+ GetDBM2(obj, dbmp, dbm);
dbmp->di_size = -1;
- dbm = dbmp->di_dbm;
if (dbm_store(dbm, key, val, DBM_REPLACE)) {
#ifdef HAVE_DBM_CLEARERR
dbm_clearerr(dbm);
@@ -504,9 +538,8 @@ fdbm_length(obj)
DBM *dbm;
int i = 0;
- GetDBM(obj, dbmp);
+ GetDBM2(obj, dbmp, dbm);
if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
- dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
i++;
@@ -525,7 +558,7 @@ fdbm_empty_p(obj)
DBM *dbm;
int i = 0;
- GetDBM(obj, dbmp);
+ GetDBM2(obj, dbmp, dbm);
if (dbmp->di_size < 0) {
dbm = dbmp->di_dbm;
@@ -548,11 +581,11 @@ fdbm_each_value(obj)
struct dbmdata *dbmp;
DBM *dbm;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
}
@@ -565,10 +598,10 @@ fdbm_each_key(obj)
struct dbmdata *dbmp;
DBM *dbm;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
}
@@ -582,14 +615,14 @@ fdbm_each_pair(obj)
struct dbmdata *dbmp;
VALUE keystr, valstr;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
keystr = rb_tainted_str_new(key.dptr, key.dsize);
valstr = rb_tainted_str_new(val.dptr, val.dsize);
rb_yield(rb_assoc_new(keystr, valstr));
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
@@ -604,8 +637,7 @@ fdbm_keys(obj)
DBM *dbm;
VALUE ary;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
@@ -624,9 +656,7 @@ fdbm_values(obj)
DBM *dbm;
VALUE ary;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
@@ -648,8 +678,7 @@ fdbm_has_key(obj, keystr)
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
val = dbm_fetch(dbm, key);
if (val.dptr) return Qtrue;
return Qfalse;
@@ -667,8 +696,7 @@ fdbm_has_value(obj, valstr)
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
if (val.dsize == RSTRING(valstr)->len &&
@@ -687,14 +715,12 @@ fdbm_to_a(obj)
DBM *dbm;
VALUE ary;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize)));
+ rb_tainted_str_new(val.dptr, val.dsize)));
}
return ary;
@@ -709,9 +735,7 @@ fdbm_to_hash(obj)
DBM *dbm;
VALUE hash;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
hash = rb_hash_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
@@ -741,6 +765,7 @@ Init_dbm()
rb_define_method(rb_cDBM, "initialize", fdbm_initialize, -1);
rb_define_method(rb_cDBM, "close", fdbm_close, 0);
+ rb_define_method(rb_cDBM, "closed?", fdbm_closed, 0);
rb_define_method(rb_cDBM, "[]", fdbm_aref, 1);
rb_define_method(rb_cDBM, "fetch", fdbm_fetch_m, -1);
rb_define_method(rb_cDBM, "[]=", fdbm_store, 2);
@@ -779,7 +804,15 @@ Init_dbm()
rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0);
rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0);
+ /* flags for dbm_open() */
+ rb_define_const(rb_cDBM, "READER", INT2FIX(O_RDONLY|RUBY_DBM_RW_BIT));
+ rb_define_const(rb_cDBM, "WRITER", INT2FIX(O_RDWR|RUBY_DBM_RW_BIT));
+ rb_define_const(rb_cDBM, "WRCREAT", INT2FIX(O_RDWR|O_CREAT|RUBY_DBM_RW_BIT));
+ rb_define_const(rb_cDBM, "NEWDB", INT2FIX(O_RDWR|O_CREAT|O_TRUNC|RUBY_DBM_RW_BIT));
+
#ifdef DB_VERSION_STRING
rb_define_const(rb_cDBM, "VERSION", rb_str_new2(DB_VERSION_STRING));
+#else
+ rb_define_const(rb_cDBM, "VERSION", rb_str_new2("unknown"));
#endif
}
diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb
index 5a67603e69..0074ab605b 100644
--- a/ext/dbm/extconf.rb
+++ b/ext/dbm/extconf.rb
@@ -2,9 +2,13 @@ require 'mkmf'
dir_config("dbm")
-dblib = with_config("dbm-type", nil)
+if dblib = with_config("dbm-type", nil)
+ dblib = dblib.split(/[ ,]+/)
+else
+ dblib = %w(db db2 db1 dbm gdbm gdbm_compat qdbm)
+end
-$dbm_conf_headers = {
+headers = {
"db" => ["db.h"],
"db1" => ["db1/ndbm.h", "db1.h", "ndbm.h"],
"db2" => ["db2/db.h", "db2.h", "db.h"],
@@ -14,48 +18,36 @@ $dbm_conf_headers = {
"qdbm" => ["relic.h"],
}
-def db_check(db)
- $dbm_conf_db_prefix = ""
- $dbm_conf_have_gdbm = false
- hsearch = ""
+def headers.db_check(db)
+ db_prefix = nil
+ have_gdbm = false
+ hsearch = nil
case db
when /^db2?$/
- $dbm_conf_db_prefix = "__db_n"
+ db_prefix = "__db_n"
hsearch = "-DDB_DBM_HSEARCH "
when "gdbm"
- $dbm_conf_have_gdbm = true
+ have_gdbm = true
when "gdbm_compat"
- $dbm_conf_have_gdbm = true
+ have_gdbm = true
have_library("gdbm") or return false
end
-
- if have_library(db, db_prefix("dbm_open")) || have_func(db_prefix("dbm_open"))
- for hdr in $dbm_conf_headers.fetch(db, ["ndbm.h"])
- if have_header(hdr.dup) and have_type("DBM", hdr.dup, hsearch)
- $CFLAGS += " " + hsearch + '-DDBM_HDR="<'+hdr+'>"'
- return true
- end
- end
- end
- return false
-end
-
-def db_prefix(func)
- $dbm_conf_db_prefix+func
-end
-
-if dblib
- db_check(dblib)
-else
- for dblib in %w(db db2 db1 dbm gdbm gdbm_compat qdbm)
- db_check(dblib) and break
+ db_prefix ||= ""
+
+ if (have_library(db, db_prefix+"dbm_open") || have_func(db_prefix+"dbm_open")) and
+ hdr = self.fetch(db, ["ndbm.h"]).find {|hdr| have_type("DBM", hdr, hsearch)}
+ have_func(db_prefix+"dbm_clearerr") unless have_gdbm
+ $defs << hsearch if hsearch
+ $defs << '-DDBM_HDR="<'+hdr+'>"'
+ true
+ else
+ false
end
end
-have_header("cdefs.h")
-have_header("sys/cdefs.h")
-if /DBM_HDR/ =~ $CFLAGS and have_func(db_prefix("dbm_open"))
- have_func(db_prefix("dbm_clearerr")) unless $dbm_conf_have_gdbm
+if dblib.any? {|db| headers.db_check(db)}
+ have_header("cdefs.h")
+ have_header("sys/cdefs.h")
create_makefile("dbm")
end
diff --git a/ext/dbm/testdbm.rb b/ext/dbm/testdbm.rb
deleted file mode 100644
index 4942ffb64a..0000000000
--- a/ext/dbm/testdbm.rb
+++ /dev/null
@@ -1,593 +0,0 @@
-require 'runit/testcase'
-require 'runit/cui/testrunner'
-
-if $".grep(/\bdbm.so\b/).empty?
- begin
- require './dbm'
- rescue LoadError
- require 'dbm'
- end
-end
-
-def uname_s
- require 'rbconfig'
- case Config::CONFIG['host_os']
- when 'cygwin'
- require 'Win32API'
- uname = Win32API.new('cygwin1', 'uname', 'P', 'I')
- utsname = ' ' * 100
- raise 'cannot get system name' if uname.call(utsname) == -1
-
- utsname.unpack('A20' * 5)[0]
- else
- Config::CONFIG['host_os']
- end
-end
-
-SYSTEM = uname_s
-
-class TestDBM < RUNIT::TestCase
- def setup
- @path = "tmptest_dbm_"
- assert_instance_of(DBM, @dbm = DBM.new(@path))
-
- # prepare to make readonly DBM file
- DBM.open("tmptest_dbm_rdonly") {|dbm|
- dbm['foo'] = 'FOO'
- }
-
- File.chmod(0400, *Dir.glob("tmptest_dbm_rdonly.*"))
-
- assert_instance_of(DBM, @dbm_rdonly = DBM.new("tmptest_dbm_rdonly", nil))
- end
- def teardown
- assert_nil(@dbm.close)
- assert_nil(@dbm_rdonly.close)
- GC.start
- File.delete *Dir.glob("tmptest_dbm*").to_a
- p Dir.glob("tmptest_dbm*") if $DEBUG
- end
-
- def check_size(expect, dbm=@dbm)
- assert_equals(expect, dbm.size)
- n = 0
- dbm.each { n+=1 }
- assert_equals(expect, n)
- if expect == 0
- assert_equals(true, dbm.empty?)
- else
- assert_equals(false, dbm.empty?)
- end
- end
-
- def test_version
- STDERR.print DBM::VERSION
- end
-
- def test_s_new_has_no_block
- # DBM.new ignore the block
- foo = true
- assert_instance_of(DBM, dbm = DBM.new("tmptest_dbm") { foo = false })
- assert_equals(foo, true)
- assert_nil(dbm.close)
- end
- def test_s_open_no_create
- assert_nil(dbm = DBM.open("tmptest_dbm", nil))
- ensure
- dbm.close if dbm
- end
- def test_s_open_with_block
- assert_equals(DBM.open("tmptest_dbm") { :foo }, :foo)
- end
- def test_s_open_lock
- fork() {
- assert_instance_of(DBM, dbm = DBM.open("tmptest_dbm", 0644))
- sleep 2
- }
- begin
- sleep 1
- assert_exception(Errno::EWOULDBLOCK, "NEVER MIND IF YOU USE Berkeley DB3") {
- begin
- assert_instance_of(DBM, dbm2 = DBM.open("tmptest_dbm", 0644))
- rescue Errno::EAGAIN, Errno::EACCES, Errno::EINVAL
- raise Errno::EWOULDBLOCK
- end
- }
- ensure
- Process.wait
- end
- end
-
-=begin
- # Is it guaranteed on many OS?
- def test_s_open_lock_one_process
- # locking on one process
- assert_instance_of(DBM, dbm = DBM.open("tmptest_dbm", 0644))
- assert_exception(Errno::EWOULDBLOCK) {
- begin
- DBM.open("tmptest_dbm", 0644)
- rescue Errno::EAGAIN
- raise Errno::EWOULDBLOCK
- end
- }
- end
-=end
-
- def test_s_open_nolock
- # dbm 1.8.0 specific
- if not defined? DBM::NOLOCK
- return
- end
-
- fork() {
- assert_instance_of(DBM, dbm = DBM.open("tmptest_dbm", 0644,
- DBM::NOLOCK))
- sleep 2
- }
- sleep 1
- begin
- dbm2 = nil
- assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
- assert_instance_of(DBM, dbm2 = DBM.open("tmptest_dbm", 0644))
- }
- ensure
- Process.wait
- dbm2.close if dbm2
- end
-
- p Dir.glob("tmptest_dbm*") if $DEBUG
-
- fork() {
- assert_instance_of(DBM, dbm = DBM.open("tmptest_dbm", 0644))
- sleep 2
- }
- begin
- sleep 1
- dbm2 = nil
- assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
- # this test is failed on Cygwin98 (???)
- assert_instance_of(DBM, dbm2 = DBM.open("tmptest_dbm", 0644,
- DBM::NOLOCK))
- }
- ensure
- Process.wait
- dbm2.close if dbm2
- end
- end
-
- def test_s_open_error
- assert_instance_of(DBM, dbm = DBM.open("tmptest_dbm", 0))
- assert_exception(Errno::EACCES, "NEVER MIND IF YOU USE Berkeley DB3") {
- DBM.open("tmptest_dbm", 0)
- }
- dbm.close
- end
-
- def test_close
- assert_instance_of(DBM, dbm = DBM.open("tmptest_dbm"))
- assert_nil(dbm.close)
-
- # closed DBM file
- assert_exception(DBMError) { dbm.close }
- end
-
- def test_aref
- assert_equals('bar', @dbm['foo'] = 'bar')
- assert_equals('bar', @dbm['foo'])
-
- assert_nil(@dbm['bar'])
- end
-
- def test_fetch
- assert_equals('bar', @dbm['foo']='bar')
- assert_equals('bar', @dbm.fetch('foo'))
-
- # key not found
- assert_exception(IndexError) {
- @dbm.fetch('bar')
- }
-
- # test for `ifnone' arg
- assert_equals('baz', @dbm.fetch('bar', 'baz'))
-
- # test for `ifnone' block
- assert_equals('foobar', @dbm.fetch('bar') {|key| 'foo' + key })
- end
-
- def test_aset
- num = 0
- 2.times {|i|
- assert_equals('foo', @dbm['foo'] = 'foo')
- assert_equals('foo', @dbm['foo'])
- assert_equals('bar', @dbm['foo'] = 'bar')
- assert_equals('bar', @dbm['foo'])
-
- num += 1 if i == 0
- assert_equals(num, @dbm.size)
-
- # assign nil
- assert_equals('', @dbm['bar'] = '')
- assert_equals('', @dbm['bar'])
-
- num += 1 if i == 0
- assert_equals(num, @dbm.size)
-
- # empty string
- assert_equals('', @dbm[''] = '')
- assert_equals('', @dbm[''])
-
- num += 1 if i == 0
- assert_equals(num, @dbm.size)
-
- # Fixnum
- assert_equals('200', @dbm['100'] = '200')
- assert_equals('200', @dbm['100'])
-
- num += 1 if i == 0
- assert_equals(num, @dbm.size)
-
- # Big key and value
- assert_equals('y' * 100, @dbm['x' * 100] = 'y' * 100)
- assert_equals('y' * 100, @dbm['x' * 100])
-
- num += 1 if i == 0
- assert_equals(num, @dbm.size)
- }
- end
-
- def test_index
- assert_equals('bar', @dbm['foo'] = 'bar')
- assert_equals('foo', @dbm.index('bar'))
- assert_nil(@dbm['bar'])
- end
-
- def test_indexes
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
- assert_equals(values.reverse, @dbm.indexes(*keys.reverse))
- end
-
- def test_values_at
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
- assert_equals(values.reverse, @dbm.values_at(*keys.reverse))
- end
-
- def test_select_with_block
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
- ret = @dbm.select {|k,v|
- assert_equals(k.upcase, v)
- k != "bar"
- }
- assert_equals([['baz', 'BAZ'], ['foo', 'FOO']],
- ret.sort)
- end
-
- def test_length
- num = 10
- assert_equals(0, @dbm.size)
- num.times {|i|
- i = i.to_s
- @dbm[i] = i
- }
- assert_equals(num, @dbm.size)
-
- @dbm.shift
-
- assert_equals(num - 1, @dbm.size)
- end
-
- def test_empty?
- assert_equals(true, @dbm.empty?)
- @dbm['foo'] = 'FOO'
- assert_equals(false, @dbm.empty?)
- end
-
- def test_each_pair
- n = 0
- @dbm.each_pair { n += 1 }
- assert_equals(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
-
- n = 0
- ret = @dbm.each_pair {|key, val|
- assert_not_nil(i = keys.index(key))
- assert_equals(val, values[i])
-
- n += 1
- }
- assert_equals(keys.size, n)
- assert_equals(@dbm, ret)
- end
-
- def test_each_value
- n = 0
- @dbm.each_value { n += 1 }
- assert_equals(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
-
- n = 0
- ret = @dbm.each_value {|val|
- assert_not_nil(key = @dbm.index(val))
- assert_not_nil(i = keys.index(key))
- assert_equals(val, values[i])
-
- n += 1
- }
- assert_equals(keys.size, n)
- assert_equals(@dbm, ret)
- end
-
- def test_each_key
- n = 0
- @dbm.each_key { n += 1 }
- assert_equals(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
-
- n = 0
- ret = @dbm.each_key {|key|
- assert_not_nil(i = keys.index(key))
- assert_equals(@dbm[key], values[i])
-
- n += 1
- }
- assert_equals(keys.size, n)
- assert_equals(@dbm, ret)
- end
-
- def test_keys
- assert_equals([], @dbm.keys)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
-
- assert_equals(keys.sort, @dbm.keys.sort)
- assert_equals(values.sort, @dbm.values.sort)
- end
-
- def test_values
- test_keys
- end
-
- def test_shift
- assert_nil(@dbm.shift)
- assert_equals(0, @dbm.size)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
-
- ret_keys = []
- ret_values = []
- while ret = @dbm.shift
- ret_keys.push ret[0]
- ret_values.push ret[1]
-
- assert_equals(keys.size - ret_keys.size, @dbm.size)
- end
-
- assert_equals(keys.sort, ret_keys.sort)
- assert_equals(values.sort, ret_values.sort)
- end
-
- def test_delete
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- key = keys[1]
-
- assert_nil(@dbm.delete(key))
- assert_equals(0, @dbm.size)
-
- @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
-
- assert_equals('BAR', @dbm.delete(key))
- assert_nil(@dbm[key])
- assert_equals(2, @dbm.size)
-
- assert_nil(@dbm.delete(key))
-
- if /^CYGWIN_9/ !~ SYSTEM
- assert_exception(DBMError) {
- @dbm_rdonly.delete("foo")
- }
-
- assert_nil(@dbm_rdonly.delete("bar"))
- end
- end
- def test_delete_with_block
- key = 'no called block'
- @dbm[key] = 'foo'
- assert_equals('foo', @dbm.delete(key) {|k| k.replace 'called block'})
- assert_equals('no called block', key)
- assert_equals(0, @dbm.size)
-
- key = 'no called block'
- assert_equals(:blockval,
- @dbm.delete(key) {|k| k.replace 'called block'; :blockval})
- assert_equals('called block', key)
- assert_equals(0, @dbm.size)
- end
-
- def test_delete_if
- v = "0"
- 100.times {@dbm[v] = v; v = v.next}
-
- ret = @dbm.delete_if {|key, val| key.to_i < 50}
- assert_equals(@dbm, ret)
- check_size(50, @dbm)
-
- ret = @dbm.delete_if {|key, val| key.to_i >= 50}
- assert_equals(@dbm, ret)
- check_size(0, @dbm)
-
- # break
- v = "0"
- 100.times {@dbm[v] = v; v = v.next}
- check_size(100, @dbm)
- n = 0;
- @dbm.delete_if {|key, val|
- break if n > 50
- n+=1
- true
- }
- assert_equals(51, n)
- check_size(49, @dbm)
-
- @dbm.clear
-
- # raise
- v = "0"
- 100.times {@dbm[v] = v; v = v.next}
- check_size(100, @dbm)
- n = 0;
- begin
- @dbm.delete_if {|key, val|
- raise "runtime error" if n > 50
- n+=1
- true
- }
- rescue
- end
- assert_equals(51, n)
- check_size(49, @dbm)
- end
-
- def test_reject
- v = "0"
- 100.times {@dbm[v] = v; v = v.next}
-
- hash = @dbm.reject {|key, val| key.to_i < 50}
- assert_instance_of(Hash, hash)
- assert_equals(100, @dbm.size)
-
- assert_equals(50, hash.size)
- hash.each_pair {|key,val|
- assert_equals(false, key.to_i < 50)
- assert_equals(key, val)
- }
-
- hash = @dbm.reject {|key, val| key.to_i < 100}
- assert_instance_of(Hash, hash)
- assert_equals(true, hash.empty?)
- end
-
- def test_clear
- v = "1"
- 100.times {v = v.next; @dbm[v] = v}
-
- assert_equals(@dbm, @dbm.clear)
-
- # validate DBM#size
- i = 0
- @dbm.each { i += 1 }
- assert_equals(@dbm.size, i)
- assert_equals(0, i)
- end
-
- def test_invert
- v = "0"
- 100.times {@dbm[v] = v; v = v.next}
-
- hash = @dbm.invert
- assert_instance_of(Hash, hash)
- assert_equals(100, hash.size)
- hash.each_pair {|key, val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_update
- hash = {}
- v = "0"
- 100.times {v = v.next; hash[v] = v}
-
- @dbm["101"] = "101"
- @dbm.update hash
- assert_equals(101, @dbm.size)
- @dbm.each_pair {|key, val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_replace
- hash = {}
- v = "0"
- 100.times {v = v.next; hash[v] = v}
-
- @dbm["101"] = "101"
- @dbm.replace hash
- assert_equals(100, @dbm.size)
- @dbm.each_pair {|key, val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_haskey?
- assert_equals('bar', @dbm['foo']='bar')
- assert_equals(true, @dbm.has_key?('foo'))
- assert_equals(false, @dbm.has_key?('bar'))
- end
-
- def test_has_value?
- assert_equals('bar', @dbm['foo']='bar')
- assert_equals(true, @dbm.has_value?('bar'))
- assert_equals(false, @dbm.has_value?('foo'))
- end
-
- def test_to_a
- v = "0"
- 100.times {v = v.next; @dbm[v] = v}
-
- ary = @dbm.to_a
- assert_instance_of(Array, ary)
- assert_equals(100, ary.size)
- ary.each {|key,val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_to_hash
- v = "0"
- 100.times {v = v.next; @dbm[v] = v}
-
- hash = @dbm.to_hash
- assert_instance_of(Hash, hash)
- assert_equals(100, hash.size)
- hash.each {|key,val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-end
-
-if $0 == __FILE__
- if ARGV.size == 0
- suite = RUNIT::TestSuite.new
- suite.add_test(TestDBM.suite)
- else
- suite = RUNIT::TestSuite.new
- ARGV.each do |testmethod|
- suite.add_test(TestDBM.new(testmethod))
- end
- end
-
- RUNIT::CUI::TestRunner.run(suite)
-end
diff --git a/ext/digest/MANIFEST b/ext/digest/MANIFEST
deleted file mode 100644
index ef15bdb9b7..0000000000
--- a/ext/digest/MANIFEST
+++ /dev/null
@@ -1,11 +0,0 @@
-MANIFEST
-defs.h
-digest.c
-digest.h
-digest.txt
-digest.txt.ja
-extconf.rb
-lib/md5.rb
-lib/sha1.rb
-test.sh
-depend
diff --git a/ext/digest/bubblebabble/.cvsignore b/ext/digest/bubblebabble/.cvsignore
new file mode 100644
index 0000000000..4088712231
--- /dev/null
+++ b/ext/digest/bubblebabble/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+mkmf.log
+*.def
diff --git a/ext/digest/bubblebabble/bubblebabble.c b/ext/digest/bubblebabble/bubblebabble.c
new file mode 100644
index 0000000000..3a03ceced0
--- /dev/null
+++ b/ext/digest/bubblebabble/bubblebabble.c
@@ -0,0 +1,142 @@
+/************************************************
+
+ bubblebabble.c - BubbleBabble encoding support
+
+ $Author$
+ created at: Fri Oct 13 18:31:42 JST 2006
+
+ Copyright (C) 2006 Akinori MUSHA
+
+ $Id$
+
+************************************************/
+
+#include "ruby.h"
+#include "digest.h"
+
+static ID id_digest;
+
+static VALUE
+bubblebabble_str_new(VALUE str_digest)
+{
+ char *digest;
+ size_t digest_len;
+ VALUE str;
+ char *p;
+ int i, j, seed = 1;
+ static const char vowels[] = {
+ 'a', 'e', 'i', 'o', 'u', 'y'
+ };
+ static const char consonants[] = {
+ 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n',
+ 'p', 'r', 's', 't', 'v', 'z', 'x'
+ };
+
+ StringValue(str_digest);
+ digest = RSTRING_PTR(str_digest);
+ digest_len = RSTRING_LEN(str_digest);
+
+ if ((LONG_MAX - 2) / 3 < (digest_len | 1)) {
+ rb_raise(rb_eRuntimeError, "digest string too long");
+ }
+
+ str = rb_str_new(0, (digest_len | 1) * 3 + 2);
+ p = RSTRING_PTR(str);
+
+ i = j = 0;
+ p[j++] = 'x';
+
+ for (;;) {
+ unsigned char byte1, byte2;
+
+ if (i >= digest_len) {
+ p[j++] = vowels[seed % 6];
+ p[j++] = consonants[16];
+ p[j++] = vowels[seed / 6];
+ break;
+ }
+
+ byte1 = digest[i++];
+ p[j++] = vowels[(((byte1 >> 6) & 3) + seed) % 6];
+ p[j++] = consonants[(byte1 >> 2) & 15];
+ p[j++] = vowels[((byte1 & 3) + (seed / 6)) % 6];
+
+ if (i >= digest_len) {
+ break;
+ }
+
+ byte2 = digest[i++];
+ p[j++] = consonants[(byte2 >> 4) & 15];
+ p[j++] = '-';
+ p[j++] = consonants[byte2 & 15];
+
+ seed = (seed * 5 + byte1 * 7 + byte2) % 36;
+ }
+
+ p[j] = 'x';
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * Digest.bubblebabble(string) -> bubblebabble_string
+ *
+ * Returns a BubbleBabble encoded version of a given _string_.
+ */
+static VALUE
+rb_digest_s_bubblebabble(VALUE klass, VALUE str)
+{
+ return bubblebabble_str_new(str);
+}
+
+/*
+ * call-seq:
+ * Digest::Class.bubblebabble(string, ...) -> hash_string
+ *
+ * Returns the BubbleBabble encoded hash value of a given _string_.
+ */
+static VALUE
+rb_digest_class_s_bubblebabble(int argc, VALUE *argv, VALUE klass)
+{
+ return bubblebabble_str_new(rb_funcall2(klass, id_digest, argc, argv));
+}
+
+/*
+ * call-seq:
+ * digest_obj.bubblebabble -> hash_string
+ *
+ * Returns the resulting hash value in a Bubblebabble encoded form.
+ */
+static VALUE
+rb_digest_instance_bubblebabble(VALUE self)
+{
+ return bubblebabble_str_new(rb_funcall(self, id_digest, 0));
+}
+
+/*
+ * This module adds some methods to Digest classes to perform
+ * BubbleBabble encoding.
+ */
+void
+Init_bubblebabble(void)
+{
+ VALUE mDigest, mDigest_Instance, cDigest_Class;
+
+ rb_require("digest");
+
+ mDigest = rb_path2class("Digest");
+ mDigest_Instance = rb_path2class("Digest::Instance");
+ cDigest_Class = rb_path2class("Digest::Class");
+
+ /* Digest::bubblebabble() */
+ rb_define_module_function(mDigest, "bubblebabble", rb_digest_s_bubblebabble, 1);
+
+ /* Digest::Class::bubblebabble() */
+ rb_define_singleton_method(cDigest_Class, "bubblebabble", rb_digest_class_s_bubblebabble, -1);
+
+ /* Digest::Instance#bubblebabble() */
+ rb_define_method(mDigest_Instance, "bubblebabble", rb_digest_instance_bubblebabble, 0);
+
+ id_digest = rb_intern("digest");
+}
diff --git a/ext/digest/bubblebabble/depend b/ext/digest/bubblebabble/depend
new file mode 100644
index 0000000000..b20148ded4
--- /dev/null
+++ b/ext/digest/bubblebabble/depend
@@ -0,0 +1,3 @@
+bubblebabble.o: bubblebabble.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
+ $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
+ $(srcdir)/../defs.h
diff --git a/ext/digest/bubblebabble/extconf.rb b/ext/digest/bubblebabble/extconf.rb
new file mode 100644
index 0000000000..53cb83934a
--- /dev/null
+++ b/ext/digest/bubblebabble/extconf.rb
@@ -0,0 +1,6 @@
+require 'mkmf'
+
+$defs << "-DHAVE_CONFIG_H"
+$INCFLAGS << " -I$(srcdir)/.."
+
+create_makefile('digest/bubblebabble')
diff --git a/ext/digest/defs.h b/ext/digest/defs.h
index 5cfc77dd24..b9a3470e65 100644
--- a/ext/digest/defs.h
+++ b/ext/digest/defs.h
@@ -23,12 +23,8 @@
typedef unsigned int uint32_t;
# if SIZEOF_LONG == 8
typedef unsigned long uint64_t;
-# elif defined(__GNUC__)
- typedef unsigned long long uint64_t;
-# elif defined(_MSC_VER)
- typedef unsigned _int64 uint64_t;
-# elif defined(__BORLANDC__)
- typedef unsigned __int64 uint64_t;
+# elif SIZEOF_LONG_LONG == 8
+ typedef unsigned LONG_LONG uint64_t;
# else
# define NO_UINT64_T
# endif
diff --git a/ext/digest/digest.c b/ext/digest/digest.c
index c570055322..0b910e8c47 100644
--- a/ext/digest/digest.c
+++ b/ext/digest/digest.c
@@ -6,153 +6,487 @@
created at: Fri May 25 08:57:27 JST 2001
Copyright (C) 1995-2001 Yukihiro Matsumoto
- Copyright (C) 2001 Akinori MUSHA
+ Copyright (C) 2001-2006 Akinori MUSHA
$RoughId: digest.c,v 1.16 2001/07/13 15:38:27 knu Exp $
$Id$
************************************************/
+#include "digest.h"
+
+static VALUE rb_mDigest;
+static VALUE rb_mDigest_Instance;
+static VALUE rb_cDigest_Class;
+static VALUE rb_cDigest_Base;
+
+static ID id_reset, id_update, id_finish, id_digest, id_hexdigest, id_digest_length;
+static ID id_metadata;
+
+RUBY_EXTERN void Init_digest_base(void);
+
/*
- * This module provides an interface to the following hash algorithms:
+ * Document-module: Digest
*
- * - the MD5 Message-Digest Algorithm by the RSA Data Security,
- * Inc., described in RFC 1321
- *
- * - the SHA-1 Secure Hash Algorithm by NIST (the US' National
- * Institute of Standards and Technology), described in FIPS PUB
- * 180-1.
+ * This module provides a framework for message digest libraries.
+ */
+
+static VALUE
+hexencode_str_new(VALUE str_digest)
+{
+ char *digest;
+ size_t digest_len;
+ int i;
+ VALUE str;
+ char *p;
+ static const char hex[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ StringValue(str_digest);
+ digest = RSTRING_PTR(str_digest);
+ digest_len = RSTRING_LEN(str_digest);
+
+ if (LONG_MAX / 2 < digest_len) {
+ rb_raise(rb_eRuntimeError, "digest string too long");
+ }
+
+ str = rb_str_new(0, digest_len * 2);
+
+ for (i = 0, p = RSTRING_PTR(str); i < digest_len; i++) {
+ unsigned char byte = digest[i];
+
+ p[i + i] = hex[byte >> 4];
+ p[i + i + 1] = hex[byte & 0x0f];
+ }
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * Digest.hexencode(string) -> hexencoded_string
*
- * - the SHA-256/384/512 Secure Hash Algorithm by NIST (the US'
- * National Institute of Standards and Technology), described in
- * FIPS PUB 180-2.
+ * Generates a hex-encoded version of a given _string_.
+ */
+static VALUE
+rb_digest_s_hexencode(VALUE klass, VALUE str)
+{
+ return hexencode_str_new(str);
+}
+
+/*
+ * Document-module: Digest::Instance
*
- * - the RIPEMD-160 cryptographic hash function, designed by Hans
- * Dobbertin, Antoon Bosselaers, and Bart Preneel.
+ * This module provides instance methods for a digest implementation
+ * object to calculate message digest values.
*/
-#include "digest.h"
+/*
+ * call-seq:
+ * digest_obj.update(string) -> digest_obj
+ * digest_obj << string -> digest_obj
+ *
+ * Updates the digest using a given _string_ and returns self.
+ *
+ * The update() method and the left-shift operator are overridden by
+ * each implementation subclass. (One should be an alias for the
+ * other)
+ */
+static VALUE
+rb_digest_instance_update(VALUE self, VALUE str)
+{
+ rb_raise(rb_eRuntimeError, "%s does not implement update()", RSTRING_PTR(rb_inspect(self)));
+}
-static VALUE mDigest, cDigest_Base;
-static ID id_metadata;
+/*
+ * call-seq:
+ * digest_obj.instance_eval { finish } -> digest_obj
+ *
+ * Finishes the digest and returns the resulting hash value.
+ *
+ * This method is overridden by each implementation subclass and often
+ * made private, because some of those subclasses may leave internal
+ * data uninitialized. Do not call this method from outside. Use
+ * #digest!() instead, which ensures that internal data be reset for
+ * security reasons.
+ */
+static VALUE
+rb_digest_instance_finish(VALUE self)
+{
+ rb_raise(rb_eRuntimeError, "%s does not implement finish()", RSTRING_PTR(rb_inspect(self)));
+}
/*
- * Digest::Base
+ * call-seq:
+ * digest_obj.reset -> digest_obj
+ *
+ * Resets the digest to the initial state and returns self.
+ *
+ * This method is overridden by each implementation subclass.
*/
+static VALUE
+rb_digest_instance_reset(VALUE self)
+{
+ rb_raise(rb_eRuntimeError, "%s does not implement reset()", RSTRING_PTR(rb_inspect(self)));
+}
-static algo_t *
-get_digest_base_metadata(klass)
- VALUE klass;
+/*
+ * call-seq:
+ * digest_obj.new -> another_digest_obj
+ *
+ * Returns a new, initialized copy of the digest object. Equivalent
+ * to digest_obj.clone().reset().
+ */
+static VALUE
+rb_digest_instance_new(VALUE self)
{
- VALUE obj;
- algo_t *algo;
+ VALUE clone = rb_obj_clone(self);
+ rb_funcall(clone, id_reset, 0);
+ return clone;
+}
- if (rb_cvar_defined(klass, id_metadata) == Qfalse) {
- rb_notimplement();
+/*
+ * call-seq:
+ * digest_obj.digest -> string
+ * digest_obj.digest(string) -> string
+ *
+ * If none is given, returns the resulting hash value of the digest,
+ * keeping the digest's state.
+ *
+ * If a _string_ is given, returns the hash value for the given
+ * _string_, resetting the digest to the initial state before and
+ * after the process.
+ */
+static VALUE
+rb_digest_instance_digest(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str, value;
+
+ if (rb_scan_args(argc, argv, "01", &str) > 0) {
+ rb_funcall(self, id_reset, 0);
+ rb_funcall(self, id_update, 1, str);
+ value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
+ } else {
+ VALUE clone = rb_obj_clone(self);
+
+ value = rb_funcall(clone, id_finish, 0);
+ rb_funcall(clone, id_reset, 0);
}
- obj = rb_cvar_get(klass, id_metadata);
+ return value;
+}
- Data_Get_Struct(obj, algo_t, algo);
+/*
+ * call-seq:
+ * digest_obj.digest! -> string
+ *
+ * Returns the resulting hash value and resets the digest to the
+ * initial state.
+ */
+static VALUE
+rb_digest_instance_digest_bang(VALUE self)
+{
+ VALUE value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
- return algo;
+ return value;
}
-static VALUE rb_digest_base_alloc _((VALUE));
+/*
+ * call-seq:
+ * digest_obj.hexdigest -> string
+ * digest_obj.hexdigest(string) -> string
+ *
+ * If none is given, returns the resulting hash value of the digest in
+ * a hex-encoded form, keeping the digest's state.
+ *
+ * If a _string_ is given, returns the hash value for the given
+ * _string_ in a hex-encoded form, resetting the digest to the initial
+ * state before and after the process.
+ */
static VALUE
-rb_digest_base_alloc(klass)
- VALUE klass;
+rb_digest_instance_hexdigest(int argc, VALUE *argv, VALUE self)
{
- algo_t *algo;
- VALUE obj;
- void *pctx;
-
- if (klass == cDigest_Base) {
- rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
+ VALUE str, value;
+
+ if (rb_scan_args(argc, argv, "01", &str) > 0) {
+ rb_funcall(self, id_reset, 0);
+ rb_funcall(self, id_update, 1, str);
+ value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
+ } else {
+ VALUE clone = rb_obj_clone(self);
+
+ value = rb_funcall(clone, id_finish, 0);
+ rb_funcall(clone, id_reset, 0);
}
- algo = get_digest_base_metadata(klass);
+ return hexencode_str_new(value);
+}
- /* XXX: An uninitialized buffer leads ALGO_Equal() to fail */
- pctx = xcalloc(algo->ctx_size, 1);
- algo->init_func(pctx);
+/*
+ * call-seq:
+ * digest_obj.hexdigest! -> string
+ *
+ * Returns the resulting hash value and resets the digest to the
+ * initial state.
+ */
+static VALUE
+rb_digest_instance_hexdigest_bang(VALUE self)
+{
+ VALUE value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
- obj = Data_Wrap_Struct(klass, 0, free, pctx);
+ return hexencode_str_new(value);
+}
- return obj;
+/*
+ * call-seq:
+ * digest_obj.to_s -> string
+ *
+ * Returns digest_obj.hexdigest().
+ */
+static VALUE
+rb_digest_instance_to_s(VALUE self)
+{
+ return rb_funcall(self, id_hexdigest, 0);
}
+/*
+ * call-seq:
+ * digest_obj.inspect -> string
+ *
+ * Creates a printable version of the digest object.
+ */
static VALUE
-rb_digest_base_s_digest(klass, str)
- VALUE klass;
+rb_digest_instance_inspect(VALUE self)
+{
VALUE str;
+ size_t digest_len = 32; /* about this size at least */
+ char *cname;
+
+ cname = rb_obj_classname(self);
+
+ /* #<Digest::ClassName: xxxxx...xxxx> */
+ str = rb_str_buf_new(2 + strlen(cname) + 2 + digest_len * 2 + 1);
+ rb_str_buf_cat2(str, "#<");
+ rb_str_buf_cat2(str, cname);
+ rb_str_buf_cat2(str, ": ");
+ rb_str_buf_append(str, rb_digest_instance_hexdigest(0, 0, self));
+ rb_str_buf_cat2(str, ">");
+ return str;
+}
+
+/*
+ * call-seq:
+ * digest_obj == another_digest_obj -> boolean
+ * digest_obj == string -> boolean
+ *
+ * If a string is given, checks whether it is equal to the hex-encoded
+ * hash value of the digest object. If another digest instance is
+ * given, checks whether they have the same hash value. Otherwise
+ * returns false.
+ */
+static VALUE
+rb_digest_instance_equal(VALUE self, VALUE other)
{
- algo_t *algo;
- void *pctx;
- size_t len;
- unsigned char *digest;
- VALUE obj = rb_digest_base_alloc(klass);
+ VALUE str1, str2;
- algo = get_digest_base_metadata(klass);
- Data_Get_Struct(obj, void, pctx);
+ if (rb_obj_is_kind_of(other, rb_mDigest_Instance) == Qtrue) {
+ str1 = rb_digest_instance_digest(0, 0, self);
+ str2 = rb_digest_instance_digest(0, 0, other);
+ } else {
+ str1 = rb_digest_instance_to_s(self);
+ str2 = other;
+ }
- StringValue(str);
- algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
+ /* never blindly assume that subclass methods return strings */
+ StringValue(str1);
+ StringValue(str2);
- len = algo->digest_len;
+ if (RSTRING_LEN(str1) == RSTRING_LEN(str2) &&
+ rb_str_cmp(str1, str2) == 0) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
- digest = xmalloc(len);
- algo->final_func(digest, pctx);
+/*
+ * call-seq:
+ * digest_obj.digest_length -> integer
+ *
+ * Returns the length of the hash value of the digest.
+ *
+ * This method should be overridden by each implementation subclass.
+ * If not, digest_obj.digest().length() is returned.
+ */
+static VALUE
+rb_digest_instance_digest_length(VALUE self)
+{
+ /* subclasses really should redefine this method */
+ VALUE digest = rb_digest_instance_digest(0, 0, self);
- obj = rb_str_new(digest, len);
+ /* never blindly assume that #digest() returns a string */
+ StringValue(digest);
+ return INT2NUM(RSTRING_LEN(digest));
+}
- free(digest);
+/*
+ * call-seq:
+ * digest_obj.length -> integer
+ * digest_obj.size -> integer
+ *
+ * Returns digest_obj.digest_length().
+ */
+static VALUE
+rb_digest_instance_length(VALUE self)
+{
+ return rb_funcall(self, id_digest_length, 0);
+}
- return obj;
+/*
+ * call-seq:
+ * digest_obj.block_length -> integer
+ *
+ * Returns the block length of the digest.
+ *
+ * This method is overridden by each implementation subclass.
+ */
+static VALUE
+rb_digest_instance_block_length(VALUE self)
+{
+ rb_raise(rb_eRuntimeError, "%s does not implement block_length()", RSTRING_PTR(rb_inspect(self)));
}
+/*
+ * Document-class: Digest::Class
+ *
+ * This module stands as a base class for digest implementation
+ * classes.
+ */
+
+/*
+ * call-seq:
+ * Digest::Class.digest(string, *parameters) -> hash_string
+ *
+ * Returns the hash value of a given _string_. This is equivalent to
+ * Digest::Class.new(*parameters).digest(string), where extra
+ * _parameters_, if any, are passed through to the constructor and the
+ * _string_ is passed to #digest().
+ */
static VALUE
-rb_digest_base_s_hexdigest(klass, str)
- VALUE klass;
- VALUE str;
+rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass)
{
- algo_t *algo;
- void *pctx;
- size_t len;
- unsigned char *hexdigest;
- VALUE obj = rb_digest_base_alloc(klass);
+ VALUE str;
+ volatile VALUE obj;
- algo = get_digest_base_metadata(klass);
- Data_Get_Struct(obj, void, pctx);
+ if (argc < 1) {
+ rb_raise(rb_eArgError, "no data given");
+ }
+
+ str = *argv++;
+ argc--;
StringValue(str);
- algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
- len = algo->digest_len * 2;
+ obj = rb_obj_alloc(klass);
+ rb_obj_call_init(obj, argc, argv);
+
+ return rb_funcall(obj, id_digest, 1, str);
+}
+
+/*
+ * call-seq:
+ * Digest::Class.hexdigest(string[, ...]) -> hash_string
+ *
+ * Returns the hex-encoded hash value of a given _string_. This is
+ * almost equivalent to
+ * Digest.hexencode(Digest::Class.new(*parameters).digest(string)).
+ */
+static VALUE
+rb_digest_class_s_hexdigest(int argc, VALUE *argv, VALUE klass)
+{
+ return hexencode_str_new(rb_funcall2(klass, id_digest, argc, argv));
+}
+
+/*
+ * Document-class: Digest::Base
+ *
+ * This abstract class provides a common interface to message digest
+ * implementation classes written in C.
+ */
+
+static rb_digest_metadata_t *
+get_digest_base_metadata(VALUE klass)
+{
+ VALUE p;
+ VALUE obj;
+ rb_digest_metadata_t *algo;
+
+ for (p = klass; p; p = RCLASS(p)->super) {
+ if (rb_ivar_defined(p, id_metadata)) {
+ obj = rb_ivar_get(p, id_metadata);
+ break;
+ }
+ }
+
+ if (!p)
+ rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby");
+
+ Data_Get_Struct(obj, rb_digest_metadata_t, algo);
- hexdigest = xmalloc(len + 1); /* +1 is for '\0' */
- algo->end_func(pctx, hexdigest);
+ switch (algo->api_version) {
+ case 2:
+ break;
- obj = rb_str_new(hexdigest, len);
+ /*
+ * put conversion here if possible when API is updated
+ */
- free(hexdigest);
+ default:
+ rb_raise(rb_eRuntimeError, "Incompatible digest API version");
+ }
+
+ return algo;
+}
+
+static VALUE
+rb_digest_base_alloc(VALUE klass)
+{
+ rb_digest_metadata_t *algo;
+ VALUE obj;
+ void *pctx;
+
+ if (klass == rb_cDigest_Base) {
+ rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
+ }
+
+ algo = get_digest_base_metadata(klass);
+
+ pctx = xmalloc(algo->ctx_size);
+ algo->init_func(pctx);
+
+ obj = Data_Wrap_Struct(klass, 0, free, pctx);
return obj;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_copy(copy, obj)
- VALUE copy, obj;
+rb_digest_base_copy(VALUE copy, VALUE obj)
{
- algo_t *algo;
+ rb_digest_metadata_t *algo;
void *pctx1, *pctx2;
if (copy == obj) return copy;
+
rb_check_frozen(copy);
- algo = get_digest_base_metadata(CLASS_OF(copy));
- if (algo != get_digest_base_metadata(CLASS_OF(obj))) {
- rb_raise(rb_eTypeError, "wrong argument class");
- }
+
+ algo = get_digest_base_metadata(rb_obj_class(copy));
+
Data_Get_Struct(obj, void, pctx1);
Data_Get_Struct(copy, void, pctx2);
memcpy(pctx2, pctx1, algo->ctx_size);
@@ -160,157 +494,149 @@ rb_digest_base_copy(copy, obj)
return copy;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_update(self, str)
- VALUE self, str;
+rb_digest_base_reset(VALUE self)
{
- algo_t *algo;
+ rb_digest_metadata_t *algo;
void *pctx;
- StringValue(str);
- algo = get_digest_base_metadata(CLASS_OF(self));
+ algo = get_digest_base_metadata(rb_obj_class(self));
+
Data_Get_Struct(self, void, pctx);
- algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
+ algo->init_func(pctx);
return self;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_init(argc, argv, self)
- int argc;
- VALUE* argv;
- VALUE self;
+rb_digest_base_update(VALUE self, VALUE str)
{
- VALUE arg;
+ rb_digest_metadata_t *algo;
+ void *pctx;
- rb_scan_args(argc, argv, "01", &arg);
+ algo = get_digest_base_metadata(rb_obj_class(self));
- if (!NIL_P(arg)) rb_digest_base_update(self, arg);
+ Data_Get_Struct(self, void, pctx);
+
+ StringValue(str);
+ algo->update_func(pctx, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
return self;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_digest(self)
- VALUE self;
+rb_digest_base_finish(VALUE self)
{
- algo_t *algo;
- void *pctx1, *pctx2;
- unsigned char *digest;
- size_t len;
+ rb_digest_metadata_t *algo;
+ void *pctx;
VALUE str;
- algo = get_digest_base_metadata(CLASS_OF(self));
- Data_Get_Struct(self, void, pctx1);
-
- len = algo->ctx_size;
-
- pctx2 = xmalloc(len);
- memcpy(pctx2, pctx1, len);
+ algo = get_digest_base_metadata(rb_obj_class(self));
- len = algo->digest_len;
-
- digest = xmalloc(len);
- algo->final_func(digest, pctx2);
+ Data_Get_Struct(self, void, pctx);
- str = rb_str_new(digest, len);
+ str = rb_str_new(0, algo->digest_len);
+ algo->finish_func(pctx, (unsigned char *)RSTRING_PTR(str));
- free(digest);
- free(pctx2);
+ /* avoid potential coredump caused by use of a finished context */
+ algo->init_func(pctx);
return str;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_hexdigest(self)
- VALUE self;
+rb_digest_base_digest_length(VALUE self)
{
- algo_t *algo;
- void *pctx1, *pctx2;
- unsigned char *hexdigest;
- size_t len;
- VALUE str;
-
- algo = get_digest_base_metadata(CLASS_OF(self));
- Data_Get_Struct(self, void, pctx1);
-
- len = algo->ctx_size;
+ rb_digest_metadata_t *algo;
- pctx2 = xmalloc(len);
- memcpy(pctx2, pctx1, len);
+ algo = get_digest_base_metadata(rb_obj_class(self));
- len = algo->digest_len * 2;
-
- hexdigest = xmalloc(len + 1); /* +1 is for '\0' */
- algo->end_func(pctx2, hexdigest);
-
- str = rb_str_new(hexdigest, len);
-
- free(hexdigest);
- free(pctx2);
-
- return str;
+ return INT2NUM(algo->digest_len);
}
+/* :nodoc: */
static VALUE
-rb_digest_base_equal(self, other)
- VALUE self, other;
+rb_digest_base_block_length(VALUE self)
{
- algo_t *algo;
- VALUE klass;
- VALUE str1, str2;
-
- klass = CLASS_OF(self);
- algo = get_digest_base_metadata(klass);
-
- if (CLASS_OF(other) == klass) {
- void *pctx1, *pctx2;
-
- Data_Get_Struct(self, void, pctx1);
- Data_Get_Struct(other, void, pctx2);
-
- return algo->equal_func(pctx1, pctx2) ? Qtrue : Qfalse;
- }
-
- StringValue(other);
- str2 = other;
-
- if (RSTRING(str2)->len == algo->digest_len)
- str1 = rb_digest_base_digest(self);
- else
- str1 = rb_digest_base_hexdigest(self);
+ rb_digest_metadata_t *algo;
- if (RSTRING(str1)->len == RSTRING(str2)->len
- && rb_str_cmp(str1, str2) == 0)
- return Qtrue;
+ algo = get_digest_base_metadata(rb_obj_class(self));
- return Qfalse;
+ return INT2NUM(algo->block_len);
}
-/*
- * Init
- */
-
void
-Init_digest()
+Init_digest(void)
{
- mDigest = rb_define_module("Digest");
+ id_reset = rb_intern("reset");
+ id_update = rb_intern("update");
+ id_finish = rb_intern("finish");
+ id_digest = rb_intern("digest");
+ id_hexdigest = rb_intern("hexdigest");
+ id_digest_length = rb_intern("digest_length");
+
+ /*
+ * module Digest
+ */
+ rb_mDigest = rb_define_module("Digest");
+
+ /* module functions */
+ rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1);
+
+ /*
+ * module Digest::Instance
+ */
+ rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance");
+
+ /* instance methods that should be overridden */
+ rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1);
+ rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1);
+ rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0);
+ rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0);
+ rb_define_method(rb_mDigest_Instance, "digest_length", rb_digest_instance_digest_length, 0);
+ rb_define_method(rb_mDigest_Instance, "block_length", rb_digest_instance_block_length, 0);
+
+ /* instance methods that may be overridden */
+ rb_define_method(rb_mDigest_Instance, "==", rb_digest_instance_equal, 1);
+ rb_define_method(rb_mDigest_Instance, "inspect", rb_digest_instance_inspect, 0);
+
+ /* instance methods that need not usually be overridden */
+ rb_define_method(rb_mDigest_Instance, "new", rb_digest_instance_new, 0);
+ rb_define_method(rb_mDigest_Instance, "digest", rb_digest_instance_digest, -1);
+ rb_define_method(rb_mDigest_Instance, "digest!", rb_digest_instance_digest_bang, 0);
+ rb_define_method(rb_mDigest_Instance, "hexdigest", rb_digest_instance_hexdigest, -1);
+ rb_define_method(rb_mDigest_Instance, "hexdigest!", rb_digest_instance_hexdigest_bang, 0);
+ rb_define_method(rb_mDigest_Instance, "to_s", rb_digest_instance_to_s, 0);
+ rb_define_method(rb_mDigest_Instance, "length", rb_digest_instance_length, 0);
+ rb_define_method(rb_mDigest_Instance, "size", rb_digest_instance_length, 0);
+
+ /*
+ * class Digest::Class
+ */
+ rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject);
+ rb_include_module(rb_cDigest_Class, rb_mDigest_Instance);
+
+ /* class methods */
+ rb_define_singleton_method(rb_cDigest_Class, "digest", rb_digest_class_s_digest, -1);
+ rb_define_singleton_method(rb_cDigest_Class, "hexdigest", rb_digest_class_s_hexdigest, -1);
- cDigest_Base = rb_define_class_under(mDigest, "Base", rb_cObject);
+ id_metadata = rb_intern("metadata");
- rb_define_alloc_func(cDigest_Base, rb_digest_base_alloc);
- rb_define_singleton_method(cDigest_Base, "digest", rb_digest_base_s_digest, 1);
- rb_define_singleton_method(cDigest_Base, "hexdigest", rb_digest_base_s_hexdigest, 1);
+ /* class Digest::Base < Digest::Class */
+ rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class);
- rb_define_method(cDigest_Base, "initialize", rb_digest_base_init, -1);
- rb_define_method(cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
- rb_define_method(cDigest_Base, "update", rb_digest_base_update, 1);
- rb_define_method(cDigest_Base, "<<", rb_digest_base_update, 1);
- rb_define_method(cDigest_Base, "digest", rb_digest_base_digest, 0);
- rb_define_method(cDigest_Base, "hexdigest", rb_digest_base_hexdigest, 0);
- rb_define_method(cDigest_Base, "to_s", rb_digest_base_hexdigest, 0);
- rb_define_method(cDigest_Base, "==", rb_digest_base_equal, 1);
+ rb_define_alloc_func(rb_cDigest_Base, rb_digest_base_alloc);
- id_metadata = rb_intern("metadata");
+ rb_define_method(rb_cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
+ rb_define_method(rb_cDigest_Base, "reset", rb_digest_base_reset, 0);
+ rb_define_method(rb_cDigest_Base, "update", rb_digest_base_update, 1);
+ rb_define_method(rb_cDigest_Base, "<<", rb_digest_base_update, 1);
+ rb_define_private_method(rb_cDigest_Base, "finish", rb_digest_base_finish, 0);
+ rb_define_method(rb_cDigest_Base, "digest_length", rb_digest_base_digest_length, 0);
+ rb_define_method(rb_cDigest_Base, "block_length", rb_digest_base_block_length, 0);
}
diff --git a/ext/digest/digest.h b/ext/digest/digest.h
index 5e846df040..6e4906c859 100644
--- a/ext/digest/digest.h
+++ b/ext/digest/digest.h
@@ -1,12 +1,12 @@
/************************************************
- digest.c -
+ digest.h - header file for ruby digest modules
$Author$
created at: Fri May 25 08:54:56 JST 2001
- Copyright (C) 2001 Akinori MUSHA
+ Copyright (C) 2001-2006 Akinori MUSHA
$RoughId: digest.h,v 1.3 2001/07/13 15:38:27 knu Exp $
$Id$
@@ -15,18 +15,18 @@
#include "ruby.h"
-typedef void (*hash_init_func_t) _((void *));
-typedef void (*hash_update_func_t) _((void *, unsigned char *, size_t));
-typedef void (*hash_end_func_t) _((void *, unsigned char *));
-typedef void (*hash_final_func_t) _((unsigned char *, void *));
-typedef int (*hash_equal_func_t) _((void *, void *));
+#define RUBY_DIGEST_API_VERSION 2
+
+typedef void (*rb_digest_hash_init_func_t)(void *);
+typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t);
+typedef void (*rb_digest_hash_finish_func_t)(void *, unsigned char *);
typedef struct {
+ int api_version;
size_t digest_len;
+ size_t block_len;
size_t ctx_size;
- hash_init_func_t init_func;
- hash_update_func_t update_func;
- hash_end_func_t end_func;
- hash_final_func_t final_func;
- hash_equal_func_t equal_func;
-} algo_t;
+ rb_digest_hash_init_func_t init_func;
+ rb_digest_hash_update_func_t update_func;
+ rb_digest_hash_finish_func_t finish_func;
+} rb_digest_metadata_t;
diff --git a/ext/digest/digest.txt b/ext/digest/digest.txt
deleted file mode 100644
index 5797dd18f9..0000000000
--- a/ext/digest/digest.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-.\" digest.txt - -*- Indented-Text -*- created at: Fri May 25 08:13:50 JST 2001
-$RoughId: digest.txt,v 1.9 2001/07/13 19:46:51 knu Exp $
-$Id$
-
-** MD5(Class)
-
-A class to implement the MD5 Message-Digest Algorithm by RSA Data
-Security, Inc., described in RFC1321.
-
-Superclass: Digest::Base
-
-require 'digest/md5'
-
-** SHA1(Class)
-
-A class to implement the SHA-1 Secure Hash Algorithm by NIST (the US'
-National Institute of Standards and Technology), described in FIPS PUB
-180-1.
-
-Superclass: Digest::Base
-
-require 'digest/sha1'
-
-** SHA256(Class)
-** SHA384(Class)
-** SHA512(Class)
-
-Classes to implement the SHA-256/384/512 Secure Hash Algorithm(s) by
-NIST (the US' National Institute of Standards and Technology),
-described in FIPS PUB 180-2.
-
-Superclass: Digest::Base
-
-require 'digest/sha2'
-
-** RMD160(Class)
-
-A class to implement the RIPEMD-160 cryptographic hash function,
-designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel.
-
-Superclass: Digest::Base
-
-require 'digest/rmd160'
-
-
-Those above classes provide a common interface as shown below.
-
-
-Class Methods:
-
- new([str])
-
- Creates a new digest object. If a string argument is given,
- it is added to the object. (see update.)
-
- digest(str)
-
- Immediately calculates and return the hash of the given
- strings as a string. Equivalent to new(str).digest.
-
- hexdigest(str)
-
- Immediately calculates and return the hash of the given
- strings as a string of hexadecimal digits. Equivalent to
- new(str).hexdigest.
-
-Methods:
-
- clone
-
- Creates a copy of the digest object.
-
- digest
-
- Returns the hash of the added strings as a string of 16 bytes
- for MD5, 20 bytes for SHA1 and RMD160, 32 bytes for SHA256, 48
- bytes for SHA384, and 64 bytes for SHA512.
-
- hexdigest
- to_s
-
- Returns the hash of the added strings as a string of 32
- hexadecimal digits for MD5, 40 hexadecimal digits for SHA1 and
- RMD160, 64 hexadecimal digits for SHA256, 96 hexadecimal
- digits for SHA384, and 128 hexadecimal digits for SHA512.
- This method is equal to:
-
- def hexdigest
- digest.unpack("H*")[0]
- end
-
- update(str)
- << str
-
- Appends the string str to the digest object. Repeated calls
- are equivalent to a single call with the concatenation of all
- the arguments, i.e. m.update(a); m.update(b) is equivalent to
- m.update(a + b) and m << a << b is equivalent to m << a + b.
-
- == md
-
- Checks if the object is equal to the given digest object.
-
- == str
-
- Regards the value as either a digest value or a hexdigest
- value (depending on the length) and checks if the object is
- equal to the given string.
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/digest/digest.txt.ja b/ext/digest/digest.txt.ja
deleted file mode 100644
index 8997d25b9d..0000000000
--- a/ext/digest/digest.txt.ja
+++ /dev/null
@@ -1,111 +0,0 @@
-.\" digest.txt.ja - -*- Indented-Text -*- created at: Fri May 25 08:22:19 JST 2001
-$RoughId: digest.txt.jp,v 1.8 2001/07/13 15:38:27 knu Exp $
-$Id$
-
-** MD5(¥¯¥é¥¹)
-
-RFC1321¤Ëµ­½Ò¤µ¤ì¤Æ¤¤¤ëRSA Data Security, Inc. ¤Î MD5 Message-Digest
-Algorithm¤ò¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡£
-
-Superclass: Digest::Base
-
-require 'digest/md5'
-
-** SHA1(¥¯¥é¥¹)
-
-FIPS PUB 180-1¤Ëµ­½Ò¤µ¤ì¤Æ¤¤¤ëNIST (the US' National Institute of
-Standards and Technology) ¤Î SHA-1 Secure Hash Algorithm¤ò¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡£
-
-Superclass: Digest::Base
-
-require 'digest/sha1'
-
-** SHA256(¥¯¥é¥¹)
-** SHA384(¥¯¥é¥¹)
-** SHA512(¥¯¥é¥¹)
-
-FIPS PUB 180-2¤Ëµ­½Ò¤µ¤ì¤Æ¤¤¤ëNIST (the US' National Institute of
-Standards and Technology) ¤Î SHA-256/384/512 Secure Hash Algorithm¤ò
-¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡£
-
-Superclass: Digest::Base
-
-require 'digest/sha2'
-
-** RMD160(¥¯¥é¥¹)
-
-Hans Dobbertin, Antoon Bosselaers, Bart Preneel ¤Ë¤è¤Ã¤ÆÀ߷פµ¤ì¤¿
-RIPEMD-160 ¥Ï¥Ã¥·¥å´Ø¿ô¤ò¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡£
-
-Superclass: Digest::Base
-
-require 'digest/rmd160'
-
-
-¤³¤ì¤é¤Î¥¯¥é¥¹¤Ï°Ê²¼¤Î¤è¤¦¤Ê¶¦Ä̤Υ¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òÄ󶡤¹¤ë¡£
-
-
-Class Methods:
-
- new([str])
-
- ¿·¤·¤¤¥À¥¤¥¸¥§¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¡¥Ê¸»úÎó°ú¿ô¤¬Í¿¤¨¤é¤ì¤ë
- ¤È¤½¤ì¤òÄɲ乤ë(see update)¡£
-
- digest(str)
-
- Í¿¤¨¤é¤ì¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤòʸ»úÎó¤ÇÊÖ¤¹¡£
- new(str).digest ¤ÈÅù²Á¡£
-
- hexdigest(str)
-
- Í¿¤¨¤é¤ì¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤò¡¢ASCII¥³¡¼¥É¤ò»È¤Ã¤Æ
- 16¿Ê¿ô¤ÎÎó¤ò¼¨¤¹Ê¸»úÎó¤Ë¥¨¥ó¥³¡¼¥É¤·¤ÆÊÖ¤¹¡£
- new(str).hexdigest ¤ÈÅù²Á¡£
-
-Methods:
-
- clone
-
- ¥À¥¤¥¸¥§¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤ÎÊ£À½¤òºî¤ë¡£
-
- digest
-
- º£¤Þ¤Ç¤ËÄɲä·¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤòʸ»úÎó¤ÇÊÖ¤¹¡£MD5¤Ç¤Ï
- 16¥Ð¥¤¥ÈĹ¡¢SHA1¤ª¤è¤ÓRMD160¤Ç¤Ï20¥Ð¥¤¥ÈĹ¡¢SHA256¤Ç¤Ï32¥Ð¥¤¥ÈĹ¡¢
- SHA384¤Ç¤Ï48¥Ð¥¤¥ÈĹ¡¢SHA512¤Ç¤Ï64¥Ð¥¤¥ÈĹ¤È¤Ê¤ë¡£
-
- hexdigest
- to_s
-
- º£¤Þ¤Ç¤ËÄɲä·¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤò¡¢ASCII¥³¡¼¥É¤ò»È¤Ã¤Æ
- 16¿Ê¿ô¤ÎÎó¤ò¼¨¤¹Ê¸»úÎó¤Ë¥¨¥ó¥³¡¼¥É¤·¤ÆÊÖ¤¹¡£MD5¤Ç¤Ï32¥Ð¥¤¥ÈĹ¡¢
- SHA1¤ª¤è¤ÓRMD160¤Ç¤Ï40¥Ð¥¤¥ÈĹ¡¢SHA256¤Ç¤Ï64¥Ð¥¤¥ÈĹ¡¢SHA384¤Ç¤Ï
- 96¥Ð¥¤¥ÈĹ¡¢SHA512¤Ç¤Ï128¥Ð¥¤¥ÈĹ¤È¤Ê¤ë¡£Ruby¤Ç½ñ¤¯¤È°Ê²¼¤ÈƱ¤¸¡£
-
- def hexdigest
- digest.unpack("H*")[0]
- end
-
- update(str)
- << str
-
- ʸ»úÎó¤òÄɲ乤롣ʣ¿ô²óupdate¤ò¸Æ¤Ö¤³¤È¤Ïʸ»úÎó¤òÏ¢·ë¤·¤Æ
- update¤ò¸Æ¤Ö¤³¤È¤ÈÅù¤·¤¤¡£¤¹¤Ê¤ï¤Á m.update(a); m.update(b) ¤Ï
- m.update(a + b) ¤È¡¢ m << a << b ¤Ï m << a + b ¤È¤½¤ì¤¾¤ìÅù²Á
- ¤Ç¤¢¤ë¡£
-
- == md
-
- Í¿¤¨¤é¤ì¤¿¥À¥¤¥¸¥§¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤ÈÈæ³Ó¤¹¤ë¡£
-
- == str
-
- Í¿¤¨¤é¤ì¤¿Ê¸»úÎó¤ò digest ÃÍ¡¢¤â¤·¤¯¤Ï hexdigest ÃͤÈÈæ³Ó¤¹¤ë¡£
- ¤¤¤º¤ì¤ÎÃͤȸ«¤ë¤«¤ÏÍ¿¤¨¤é¤ì¤¿Ê¸»úÎó¤ÎŤµ¤Ë¤è¤Ã¤Æ¼«Æ°È½ÊÌ
- ¤µ¤ì¤ë¡£
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/digest/extconf.rb b/ext/digest/extconf.rb
index cd512622a4..cf9127ecc0 100644
--- a/ext/digest/extconf.rb
+++ b/ext/digest/extconf.rb
@@ -3,4 +3,8 @@
require "mkmf"
+$INSTALLFILES = {
+ "digest.h" => "$(RUBYARCHDIR)"
+}
+
create_makefile("digest")
diff --git a/ext/digest/lib/digest.rb b/ext/digest/lib/digest.rb
new file mode 100644
index 0000000000..0c4ee3c2cc
--- /dev/null
+++ b/ext/digest/lib/digest.rb
@@ -0,0 +1,50 @@
+require 'digest.so'
+
+module Digest
+ def self.const_missing(name)
+ case name
+ when :SHA256, :SHA384, :SHA512
+ lib = 'digest/sha2.so'
+ else
+ lib = File.join('digest', name.to_s.downcase)
+ end
+
+ begin
+ require lib
+ rescue LoadError => e
+ raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1)
+ end
+ unless Digest.const_defined?(name)
+ raise NameError, "uninitialized constant Digest::#{name}", caller(1)
+ end
+ Digest.const_get(name)
+ end
+
+ class ::Digest::Class
+ # creates a digest object and reads a given file, _name_.
+ #
+ # p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest
+ # # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
+ def self.file(name)
+ new.file(name)
+ end
+ end
+
+ module Instance
+ # updates the digest with the contents of a given file _name_ and
+ # returns self.
+ def file(name)
+ File.open(name, "rb") {|f|
+ buf = ""
+ while f.read(16384, buf)
+ update buf
+ end
+ }
+ self
+ end
+ end
+end
+
+def Digest(name)
+ Digest.const_get(name)
+end
diff --git a/ext/digest/lib/md5.rb b/ext/digest/lib/md5.rb
index 1d05d7d04e..c399f2de1d 100644
--- a/ext/digest/lib/md5.rb
+++ b/ext/digest/lib/md5.rb
@@ -5,10 +5,19 @@
require 'digest/md5'
-MD5 = Digest::MD5
+class MD5 < Digest::MD5
+ class << self
+ alias orig_new new
+ def new(str = nil)
+ if str
+ orig_new.update(str)
+ else
+ orig_new
+ end
+ end
-class MD5
- def self.md5(*args)
- new(*args)
+ def md5(*args)
+ new(*args)
+ end
end
end
diff --git a/ext/digest/lib/sha1.rb b/ext/digest/lib/sha1.rb
index c4ac6f66ea..4446e12e8d 100644
--- a/ext/digest/lib/sha1.rb
+++ b/ext/digest/lib/sha1.rb
@@ -5,10 +5,19 @@
require 'digest/sha1'
-SHA1 = Digest::SHA1
+class SHA1 < Digest::SHA1
+ class << self
+ alias orig_new new
+ def new(str = nil)
+ if str
+ orig_new.update(str)
+ else
+ orig_new
+ end
+ end
-class SHA1
- def self.sha1(*args)
- new(*args)
+ def sha1(*args)
+ new(*args)
+ end
end
end
diff --git a/ext/digest/md5/MANIFEST b/ext/digest/md5/MANIFEST
deleted file mode 100644
index d4a09b3ff6..0000000000
--- a/ext/digest/md5/MANIFEST
+++ /dev/null
@@ -1,8 +0,0 @@
-MANIFEST
-extconf.rb
-md5.c
-md5.h
-md5init.c
-md5ossl.c
-md5ossl.h
-depend
diff --git a/ext/digest/md5/extconf.rb b/ext/digest/md5/extconf.rb
index 0db0404dbe..018f8ccb02 100644
--- a/ext/digest/md5/extconf.rb
+++ b/ext/digest/md5/extconf.rb
@@ -3,7 +3,8 @@
require "mkmf"
-$CFLAGS << " -DHAVE_CONFIG_H -I#{File.dirname(__FILE__)}/.."
+$defs << "-DHAVE_CONFIG_H"
+$INCFLAGS << " -I$(srcdir)/.."
$objs = [ "md5init.#{$OBJEXT}" ]
@@ -13,7 +14,6 @@ if !with_config("bundled-md5") &&
have_library("crypto") && have_header("openssl/md5.h")
$objs << "md5ossl.#{$OBJEXT}"
- $libs << " -lcrypto"
else
$objs << "md5.#{$OBJEXT}"
end
@@ -24,4 +24,6 @@ have_header("inttypes.h")
have_header("unistd.h")
+$preload = %w[digest]
+
create_makefile("digest/md5")
diff --git a/ext/digest/md5/md5.c b/ext/digest/md5/md5.c
index 6b61f031c4..993bc47a06 100644
--- a/ext/digest/md5/md5.c
+++ b/ext/digest/md5/md5.c
@@ -41,6 +41,12 @@
1999-05-03 lpd Original version.
*/
+/*
+ This code was modified for use in Ruby.
+
+ - Akinori MUSHA <knu@idaemons.org>
+ */
+
/*$OrigId: md5c.c,v 1.2 2001/03/26 08:57:14 matz Exp $ */
/*$RoughId: md5.c,v 1.2 2001/07/13 19:48:41 knu Exp $ */
/*$Id$ */
@@ -391,7 +397,7 @@ MD5_Update(MD5_CTX *pms, const uint8_t *data, size_t nbytes)
}
void
-MD5_Final(uint8_t *digest, MD5_CTX *pms)
+MD5_Finish(MD5_CTX *pms, uint8_t *digest)
{
static const uint8_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -412,21 +418,3 @@ MD5_Final(uint8_t *digest, MD5_CTX *pms)
for (i = 0; i < 16; ++i)
digest[i] = (uint8_t)(pms->state[i >> 2] >> ((i & 3) << 3));
}
-
-void
-MD5_End(MD5_CTX *pctx, uint8_t *hexdigest)
-{
- unsigned char digest[16];
- size_t i;
-
- MD5_Final(digest, pctx);
-
- for (i = 0; i < 16; i++)
- sprintf(hexdigest + i * 2, "%02x", digest[i]);
-}
-
-int MD5_Equal(MD5_CTX* pctx1, MD5_CTX* pctx2) {
- return memcmp(pctx1->count, pctx2->count, sizeof(pctx1->count)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
diff --git a/ext/digest/md5/md5.h b/ext/digest/md5/md5.h
index fc41380d38..f4580ef5e7 100644
--- a/ext/digest/md5/md5.h
+++ b/ext/digest/md5/md5.h
@@ -63,18 +63,15 @@ typedef struct md5_state_s {
} MD5_CTX;
#ifdef RUBY
+/* avoid name clash */
#define MD5_Init rb_Digest_MD5_Init
#define MD5_Update rb_Digest_MD5_Update
-#define MD5_Final rb_Digest_MD5_Final
-#define MD5_End rb_Digest_MD5_End
-#define MD5_Equal rb_Digest_MD5_Equal
+#define MD5_Finish rb_Digest_MD5_Finish
#endif
void MD5_Init _((MD5_CTX *pms));
void MD5_Update _((MD5_CTX *pms, const uint8_t *data, size_t nbytes));
-void MD5_Final _((uint8_t *digest, MD5_CTX *pms));
-void MD5_End _((MD5_CTX *pctx, uint8_t *hexdigest));
-int MD5_Equal _((MD5_CTX *pctx1, MD5_CTX *pctx2));
+void MD5_Finish _((MD5_CTX *pms, uint8_t *digest));
#define MD5_BLOCK_LENGTH 64
#define MD5_DIGEST_LENGTH 16
diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c
index 2acca16a46..17658f4fce 100644
--- a/ext/digest/md5/md5init.c
+++ b/ext/digest/md5/md5init.c
@@ -8,28 +8,33 @@
#include "md5.h"
#endif
-static algo_t md5 = {
+static rb_digest_metadata_t md5 = {
+ RUBY_DIGEST_API_VERSION,
MD5_DIGEST_LENGTH,
+ MD5_BLOCK_LENGTH,
sizeof(MD5_CTX),
- (hash_init_func_t)MD5_Init,
- (hash_update_func_t)MD5_Update,
- (hash_end_func_t)MD5_End,
- (hash_final_func_t)MD5_Final,
- (hash_equal_func_t)MD5_Equal,
+ (rb_digest_hash_init_func_t)MD5_Init,
+ (rb_digest_hash_update_func_t)MD5_Update,
+ (rb_digest_hash_finish_func_t)MD5_Finish,
};
+/*
+ * A class for calculating message digests using the MD5
+ * Message-Digest Algorithm by RSA Data Security, Inc., described in
+ * RFC1321.
+ */
void
Init_md5()
{
VALUE mDigest, cDigest_Base, cDigest_MD5;
- rb_require("digest.so");
+ rb_require("digest");
mDigest = rb_path2class("Digest");
cDigest_Base = rb_path2class("Digest::Base");
cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base);
- rb_cvar_set(cDigest_MD5, rb_intern("metadata"),
- Data_Wrap_Struct(rb_cObject, 0, 0, &md5), Qtrue);
+ rb_ivar_set(cDigest_MD5, rb_intern("metadata"),
+ Data_Wrap_Struct(rb_cObject, 0, 0, &md5));
}
diff --git a/ext/digest/md5/md5ossl.c b/ext/digest/md5/md5ossl.c
index d930c7ab51..d94ae2cd2f 100644
--- a/ext/digest/md5/md5ossl.c
+++ b/ext/digest/md5/md5ossl.c
@@ -1,30 +1,9 @@
/* $Id$ */
#include "md5ossl.h"
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
void
-MD5_End(MD5_CTX *pctx, unsigned char *hexdigest)
+MD5_Finish(MD5_CTX *pctx, unsigned char *digest)
{
- unsigned char digest[16];
- size_t i;
-
MD5_Final(digest, pctx);
-
- for (i = 0; i < 16; i++)
- sprintf(hexdigest + i * 2, "%02x", digest[i]);
-}
-
-int
-MD5_Equal(MD5_CTX* pctx1, MD5_CTX* pctx2) {
- return pctx1->num == pctx2->num
- && pctx1->A == pctx2->A
- && pctx1->B == pctx2->B
- && pctx1->C == pctx2->C
- && pctx1->D == pctx2->D
- && pctx1->Nl == pctx2->Nl
- && pctx1->Nh == pctx2->Nh
- && memcmp(pctx1->data, pctx2->data, sizeof(pctx1->data)) == 0;
}
diff --git a/ext/digest/md5/md5ossl.h b/ext/digest/md5/md5ossl.h
index dda7c743ed..1680c4f5c9 100644
--- a/ext/digest/md5/md5ossl.h
+++ b/ext/digest/md5/md5ossl.h
@@ -3,9 +3,11 @@
#ifndef MD5OSSL_H_INCLUDED
#define MD5OSSL_H_INCLUDED
+#include <stddef.h>
#include <openssl/md5.h>
-void MD5_End(MD5_CTX *pctx, unsigned char *hexdigest);
-int MD5_Equal(MD5_CTX *pctx1, MD5_CTX *pctx2);
+#define MD5_BLOCK_LENGTH MD5_CBLOCK
+
+void MD5_Finish(MD5_CTX *pctx, unsigned char *digest);
#endif
diff --git a/ext/digest/rmd160/MANIFEST b/ext/digest/rmd160/MANIFEST
deleted file mode 100644
index bcddc7d1d8..0000000000
--- a/ext/digest/rmd160/MANIFEST
+++ /dev/null
@@ -1,9 +0,0 @@
-MANIFEST
-extconf.rb
-rmd160.c
-rmd160.h
-rmd160hl.c
-rmd160init.c
-rmd160ossl.c
-rmd160ossl.h
-depend
diff --git a/ext/digest/rmd160/depend b/ext/digest/rmd160/depend
index 0ca79c5f40..a21d7188dc 100644
--- a/ext/digest/rmd160/depend
+++ b/ext/digest/rmd160/depend
@@ -1,7 +1,5 @@
rmd160.o: rmd160.c rmd160.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-rmd160hl.o: rmd160hl.c rmd160.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
rmd160init.o: rmd160init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
rmd160.h $(srcdir)/../defs.h
diff --git a/ext/digest/rmd160/extconf.rb b/ext/digest/rmd160/extconf.rb
index 3f6a88e756..09359944f2 100644
--- a/ext/digest/rmd160/extconf.rb
+++ b/ext/digest/rmd160/extconf.rb
@@ -3,7 +3,8 @@
require "mkmf"
-$CFLAGS << " -DHAVE_CONFIG_H -I#{File.dirname(__FILE__)}/.."
+$defs << "-DNDEBUG" << "-DHAVE_CONFIG_H"
+$INCFLAGS << " -I$(srcdir)/.."
$objs = [ "rmd160init.#{$OBJEXT}" ]
@@ -12,9 +13,8 @@ dir_config("openssl")
if !with_config("bundled-rmd160") &&
have_library("crypto") && have_header("openssl/ripemd.h")
$objs << "rmd160ossl.#{$OBJEXT}"
- $libs << " -lcrypto"
else
- $objs << "rmd160.#{$OBJEXT}" << "rmd160hl.#{$OBJEXT}"
+ $objs << "rmd160.#{$OBJEXT}"
end
have_header("sys/cdefs.h")
@@ -23,4 +23,6 @@ have_header("inttypes.h")
have_header("unistd.h")
+$preload = %w[digest]
+
create_makefile("digest/rmd160")
diff --git a/ext/digest/rmd160/rmd160.c b/ext/digest/rmd160/rmd160.c
index 2de3c99b29..88918728cd 100644
--- a/ext/digest/rmd160/rmd160.c
+++ b/ext/digest/rmd160/rmd160.c
@@ -409,7 +409,7 @@ RMD160_Update(RMD160_CTX *context, const uint8_t *data, size_t nbytes)
/********************************************************************/
void
-RMD160_Final(uint8_t digest[20], RMD160_CTX *context)
+RMD160_Finish(RMD160_CTX *context, uint8_t digest[20])
{
uint32_t i;
uint32_t X[16];
@@ -454,11 +454,4 @@ RMD160_Final(uint8_t digest[20], RMD160_CTX *context)
}
}
-int RMD160_Equal(RMD160_CTX* pctx1, RMD160_CTX* pctx2) {
- return pctx1->buflen == pctx2->buflen
- && memcmp(pctx1->length, pctx2->length, sizeof(pctx1->length)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->bbuffer, pctx2->bbuffer, sizeof(pctx1->bbuffer)) == 0;
-}
-
/************************ end of file rmd160.c **********************/
diff --git a/ext/digest/rmd160/rmd160.h b/ext/digest/rmd160/rmd160.h
index 24f9a025f0..54d1ca9140 100644
--- a/ext/digest/rmd160/rmd160.h
+++ b/ext/digest/rmd160/rmd160.h
@@ -39,26 +39,14 @@ typedef struct {
#define RMD160_Init rb_Digest_RMD160_Init
#define RMD160_Transform rb_Digest_RMD160_Transform
#define RMD160_Update rb_Digest_RMD160_Update
-#define RMD160_Final rb_Digest_RMD160_Final
-#define RMD160_Equal rb_Digest_RMD160_Equal
-#ifndef _KERNEL
-#define RMD160_End rb_Digest_RMD160_End
-#define RMD160_File rb_Digest_RMD160_File
-#define RMD160_Data rb_Digest_RMD160_Data
-#endif /* _KERNEL */
+#define RMD160_Finish rb_Digest_RMD160_Finish
#endif
__BEGIN_DECLS
void RMD160_Init _((RMD160_CTX *));
void RMD160_Transform _((uint32_t[5], const uint32_t[16]));
void RMD160_Update _((RMD160_CTX *, const uint8_t *, size_t));
-void RMD160_Final _((uint8_t[20], RMD160_CTX *));
-int RMD160_Equal _((RMD160_CTX *, RMD160_CTX *));
-#ifndef _KERNEL
-char *RMD160_End _((RMD160_CTX *, char *));
-char *RMD160_File _((char *, char *));
-char *RMD160_Data _((const uint8_t *, size_t, char *));
-#endif /* _KERNEL */
+void RMD160_Finish _((RMD160_CTX *, uint8_t[20]));
__END_DECLS
#define RMD160_BLOCK_LENGTH 64
diff --git a/ext/digest/rmd160/rmd160hl.c b/ext/digest/rmd160/rmd160hl.c
deleted file mode 100644
index 4c5e0217d9..0000000000
--- a/ext/digest/rmd160/rmd160hl.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $NetBSD: rmd160hl.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $ */
-/* $RoughId: rmd160hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id$ */
-
-/* rmd160hl.c
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * from OpenBSD: rmd160hl.c,v 1.2 1999/08/17 09:13:12 millert Exp $
- */
-
-#include "rmd160.h"
-
-#ifndef lint
-/* __RCSID("$NetBSD: rmd160hl.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $"); */
-#endif /* not lint */
-
-/* #include "namespace.h" */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-
-char *
-RMD160_End(RMD160_CTX *ctx, char *buf)
-{
- size_t i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- RMD160_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[(uint32_t)digest[i] >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-char *
-RMD160_File(char *filename, char *buf)
-{
- uint8_t buffer[BUFSIZ];
- RMD160_CTX ctx;
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- RMD160_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return(0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- RMD160_Update(&ctx, buffer, (size_t)num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return(num < 0 ? 0 : RMD160_End(&ctx, buf));
-}
-
-char *
-RMD160_Data(const uint8_t *data, size_t len, char *buf)
-{
- RMD160_CTX ctx;
-
- _DIAGASSERT(data != NULL);
- /* XXX: buf may be NULL ? */
-
- RMD160_Init(&ctx);
- RMD160_Update(&ctx, data, len);
- return(RMD160_End(&ctx, buf));
-}
diff --git a/ext/digest/rmd160/rmd160init.c b/ext/digest/rmd160/rmd160init.c
index b16cdbbed8..763867df86 100644
--- a/ext/digest/rmd160/rmd160init.c
+++ b/ext/digest/rmd160/rmd160init.c
@@ -8,31 +8,33 @@
#include "rmd160.h"
#endif
-static algo_t rmd160 = {
+static rb_digest_metadata_t rmd160 = {
+ RUBY_DIGEST_API_VERSION,
RMD160_DIGEST_LENGTH,
+ RMD160_BLOCK_LENGTH,
sizeof(RMD160_CTX),
- (hash_init_func_t)RMD160_Init,
- (hash_update_func_t)RMD160_Update,
- (hash_end_func_t)RMD160_End,
- (hash_final_func_t)RMD160_Final,
- (hash_equal_func_t)RMD160_Equal,
+ (rb_digest_hash_init_func_t)RMD160_Init,
+ (rb_digest_hash_update_func_t)RMD160_Update,
+ (rb_digest_hash_finish_func_t)RMD160_Finish,
};
+/*
+ * A class for calculating message digests using RIPEMD-160
+ * cryptographic hash function, designed by Hans Dobbertin, Antoon
+ * Bosselaers, and Bart Preneel.
+ */
void
Init_rmd160()
{
VALUE mDigest, cDigest_Base, cDigest_RMD160;
- ID id_metadata;
- rb_require("digest.so");
+ rb_require("digest");
mDigest = rb_path2class("Digest");
cDigest_Base = rb_path2class("Digest::Base");
cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base);
- id_metadata = rb_intern("metadata");
-
- rb_cvar_set(cDigest_RMD160, id_metadata,
- Data_Wrap_Struct(rb_cObject, 0, 0, &rmd160), Qtrue);
+ rb_ivar_set(cDigest_RMD160, rb_intern("metadata"),
+ Data_Wrap_Struct(rb_cObject, 0, 0, &rmd160));
}
diff --git a/ext/digest/rmd160/rmd160ossl.c b/ext/digest/rmd160/rmd160ossl.c
index be66d81ff9..f24e63e3d8 100644
--- a/ext/digest/rmd160/rmd160ossl.c
+++ b/ext/digest/rmd160/rmd160ossl.c
@@ -1,45 +1,8 @@
/* $Id$ */
-#include "rmd160ossl.h"
#include "defs.h"
-#include <assert.h>
-#include <stdlib.h>
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-char *
-RMD160_End(RMD160_CTX *ctx, char *buf)
-{
- size_t i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- RMD160_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[(uint32_t)digest[i] >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
+#include "rmd160ossl.h"
-int RMD160_Equal(RMD160_CTX* pctx1, RMD160_CTX* pctx2) {
- return pctx1->num == pctx2->num
- && pctx1->A == pctx2->A
- && pctx1->B == pctx2->B
- && pctx1->C == pctx2->C
- && pctx1->D == pctx2->D
- && pctx1->E == pctx2->E
- && pctx1->Nl == pctx2->Nl
- && pctx1->Nh == pctx2->Nh
- && memcmp(pctx1->data, pctx2->data, sizeof(pctx1->data)) == 0;
+void RMD160_Finish(RMD160_CTX *ctx, char *buf) {
+ RIPEMD160_Final((unsigned char *)buf, ctx);
}
diff --git a/ext/digest/rmd160/rmd160ossl.h b/ext/digest/rmd160/rmd160ossl.h
index 824a1bf32f..3df38a01c0 100644
--- a/ext/digest/rmd160/rmd160ossl.h
+++ b/ext/digest/rmd160/rmd160ossl.h
@@ -3,18 +3,17 @@
#ifndef RMD160OSSL_H_INCLUDED
#define RMD160OSSL_H_INCLUDED
+#include <stddef.h>
#include <openssl/ripemd.h>
#define RMD160_CTX RIPEMD160_CTX
#define RMD160_Init RIPEMD160_Init
#define RMD160_Update RIPEMD160_Update
-#define RMD160_Final RIPEMD160_Final
#define RMD160_BLOCK_LENGTH RIPEMD160_CBLOCK
#define RMD160_DIGEST_LENGTH RIPEMD160_DIGEST_LENGTH
-char *RMD160_End(RMD160_CTX *ctx, char *buf);
-int RMD160_Equal(RMD160_CTX *pctx1, RMD160_CTX *pctx2);
+void RMD160_Finish(RMD160_CTX *ctx, char *buf);
#endif
diff --git a/ext/digest/sha1/MANIFEST b/ext/digest/sha1/MANIFEST
deleted file mode 100644
index 2c49b577df..0000000000
--- a/ext/digest/sha1/MANIFEST
+++ /dev/null
@@ -1,9 +0,0 @@
-MANIFEST
-extconf.rb
-sha1.c
-sha1.h
-sha1hl.c
-sha1init.c
-sha1ossl.c
-sha1ossl.h
-depend
diff --git a/ext/digest/sha1/depend b/ext/digest/sha1/depend
index a159f456d3..61607844d0 100644
--- a/ext/digest/sha1/depend
+++ b/ext/digest/sha1/depend
@@ -1,7 +1,5 @@
sha1.o: sha1.c sha1.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-sha1hl.o: sha1hl.c sha1.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
sha1init.o: sha1init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
sha1.h $(srcdir)/../defs.h
diff --git a/ext/digest/sha1/extconf.rb b/ext/digest/sha1/extconf.rb
index c249a415ed..87b74c34af 100644
--- a/ext/digest/sha1/extconf.rb
+++ b/ext/digest/sha1/extconf.rb
@@ -3,7 +3,8 @@
require "mkmf"
-$CFLAGS << " -DHAVE_CONFIG_H -I#{File.dirname(__FILE__)}/.."
+$defs << "-DHAVE_CONFIG_H"
+$INCFLAGS << " -I$(srcdir)/.."
$objs = [ "sha1init.#{$OBJEXT}" ]
@@ -13,7 +14,7 @@ if !with_config("bundled-sha1") &&
have_library("crypto") && have_header("openssl/sha.h")
$objs << "sha1ossl.#{$OBJEXT}"
else
- $objs << "sha1.#{$OBJEXT}" << "sha1hl.#{$OBJEXT}"
+ $objs << "sha1.#{$OBJEXT}"
end
have_header("sys/cdefs.h")
@@ -22,4 +23,6 @@ have_header("inttypes.h")
have_header("unistd.h")
+$preload = %w[digest]
+
create_makefile("digest/sha1")
diff --git a/ext/digest/sha1/sha1.c b/ext/digest/sha1/sha1.c
index 1012ef8751..6196ca6b82 100644
--- a/ext/digest/sha1/sha1.c
+++ b/ext/digest/sha1/sha1.c
@@ -129,9 +129,7 @@ do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LON
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
-void SHA1_Transform(state, buffer)
- uint32_t state[5];
- const uint8_t buffer[64];
+void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
{
uint32_t a, b, c, d, e;
CHAR64LONG16 *block;
@@ -201,8 +199,7 @@ void SHA1_Transform(state, buffer)
/*
* SHA1_Init - Initialize new context
*/
-void SHA1_Init(context)
- SHA1_CTX *context;
+void SHA1_Init(SHA1_CTX *context)
{
_DIAGASSERT(context != 0);
@@ -220,10 +217,7 @@ void SHA1_Init(context)
/*
* Run your data through this.
*/
-void SHA1_Update(context, data, len)
- SHA1_CTX *context;
- const uint8_t *data;
- size_t len;
+void SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len)
{
uint32_t i, j;
@@ -250,9 +244,7 @@ void SHA1_Update(context, data, len)
/*
* Add padding and return the message digest.
*/
-void SHA1_Final(digest, context)
- uint8_t digest[20];
- SHA1_CTX* context;
+void SHA1_Finish(SHA1_CTX* context, uint8_t digest[20])
{
size_t i;
uint8_t finalcount[8];
@@ -275,9 +267,3 @@ void SHA1_Final(digest, context)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
}
-
-int SHA1_Equal(SHA1_CTX* pctx1, SHA1_CTX* pctx2) {
- return memcmp(pctx1->count, pctx2->count, sizeof(pctx1->count)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
diff --git a/ext/digest/sha1/sha1.h b/ext/digest/sha1/sha1.h
index 2303cecc2b..60e3b01fe2 100644
--- a/ext/digest/sha1/sha1.h
+++ b/ext/digest/sha1/sha1.h
@@ -20,28 +20,17 @@ typedef struct {
} SHA1_CTX;
#ifdef RUBY
+/* avoid name clash */
#define SHA1_Transform rb_Digest_SHA1_Transform
#define SHA1_Init rb_Digest_SHA1_Init
#define SHA1_Update rb_Digest_SHA1_Update
-#define SHA1_Final rb_Digest_SHA1_Final
-#define SHA1_Equal rb_Digest_SHA1_Equal
-#ifndef _KERNEL
-#define SHA1_End rb_Digest_SHA1_End
-#define SHA1_File rb_Digest_SHA1_File
-#define SHA1_Data rb_Digest_SHA1_Data
-#endif /* _KERNEL */
+#define SHA1_Finish rb_Digest_SHA1_Finish
#endif
void SHA1_Transform _((uint32_t state[5], const uint8_t buffer[64]));
void SHA1_Init _((SHA1_CTX *context));
void SHA1_Update _((SHA1_CTX *context, const uint8_t *data, size_t len));
-void SHA1_Final _((uint8_t digest[20], SHA1_CTX *context));
-int SHA1_Equal _((SHA1_CTX *pctx1, SHA1_CTX *pctx2));
-#ifndef _KERNEL
-char *SHA1_End _((SHA1_CTX *, char *));
-char *SHA1_File _((char *, char *));
-char *SHA1_Data _((const uint8_t *, size_t, char *));
-#endif /* _KERNEL */
+void SHA1_Finish _((SHA1_CTX *context, uint8_t digest[20]));
#define SHA1_BLOCK_LENGTH 64
#define SHA1_DIGEST_LENGTH 20
diff --git a/ext/digest/sha1/sha1hl.c b/ext/digest/sha1/sha1hl.c
deleted file mode 100644
index d1a236b22c..0000000000
--- a/ext/digest/sha1/sha1hl.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/* $NetBSD: sha1hl.c,v 1.2 2001/03/10 15:55:14 tron Exp $ */
-/* $RoughId: sha1hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id$ */
-
-/* sha1hl.c
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- */
-
-/* #include "namespace.h" */
-
-#include "sha1.h"
-#include <fcntl.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/* __RCSID("$NetBSD: sha1hl.c,v 1.2 2001/03/10 15:55:14 tron Exp $"); */
-#endif /* LIBC_SCCS and not lint */
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-
-/* ARGSUSED */
-char *
-SHA1_End(ctx, buf)
- SHA1_CTX *ctx;
- char *buf;
-{
- int i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- SHA1_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[((uint32_t)digest[i]) >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-char *
-SHA1_File (filename, buf)
- char *filename;
- char *buf;
-{
- uint8_t buffer[BUFSIZ];
- SHA1_CTX ctx;
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA1_Init(&ctx);
-
- if ((fd = open(filename,O_RDONLY)) < 0)
- return(0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA1_Update(&ctx, buffer, (size_t)num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return(num < 0 ? 0 : SHA1_End(&ctx, buf));
-}
-
-char *
-SHA1_Data (data, len, buf)
- const uint8_t *data;
- size_t len;
- char *buf;
-{
- SHA1_CTX ctx;
-
- _DIAGASSERT(data != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, data, len);
- return(SHA1_End(&ctx, buf));
-}
diff --git a/ext/digest/sha1/sha1init.c b/ext/digest/sha1/sha1init.c
index 426afb7cd0..b2146f05a9 100644
--- a/ext/digest/sha1/sha1init.c
+++ b/ext/digest/sha1/sha1init.c
@@ -8,31 +8,33 @@
#include "sha1.h"
#endif
-static algo_t sha1 = {
+static rb_digest_metadata_t sha1 = {
+ RUBY_DIGEST_API_VERSION,
SHA1_DIGEST_LENGTH,
+ SHA1_BLOCK_LENGTH,
sizeof(SHA1_CTX),
- (hash_init_func_t)SHA1_Init,
- (hash_update_func_t)SHA1_Update,
- (hash_end_func_t)SHA1_End,
- (hash_final_func_t)SHA1_Final,
- (hash_equal_func_t)SHA1_Equal,
+ (rb_digest_hash_init_func_t)SHA1_Init,
+ (rb_digest_hash_update_func_t)SHA1_Update,
+ (rb_digest_hash_finish_func_t)SHA1_Finish,
};
+/*
+ * A class for calculating message digests using the SHA-1 Secure Hash
+ * Algorithm by NIST (the US' National Institute of Standards and
+ * Technology), described in FIPS PUB 180-1.
+ */
void
Init_sha1()
{
VALUE mDigest, cDigest_Base, cDigest_SHA1;
- ID id_metadata;
-
- rb_require("digest.so");
-
+
+ rb_require("digest");
+
mDigest = rb_path2class("Digest");
cDigest_Base = rb_path2class("Digest::Base");
cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base);
- id_metadata = rb_intern("metadata");
-
- rb_cvar_set(cDigest_SHA1, id_metadata,
- Data_Wrap_Struct(rb_cObject, 0, 0, &sha1), Qtrue);
+ rb_ivar_set(cDigest_SHA1, rb_intern("metadata"),
+ Data_Wrap_Struct(rb_cObject, 0, 0, &sha1));
}
diff --git a/ext/digest/sha1/sha1ossl.c b/ext/digest/sha1/sha1ossl.c
index b125128f82..452cf35084 100644
--- a/ext/digest/sha1/sha1ossl.c
+++ b/ext/digest/sha1/sha1ossl.c
@@ -1,45 +1,10 @@
/* $Id$ */
-#include "sha1ossl.h"
#include "defs.h"
-#include <assert.h>
-#include <stdlib.h>
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
+#include "sha1ossl.h"
-char *
-SHA1_End(SHA1_CTX *ctx, char *buf)
+void
+SHA1_Finish(SHA1_CTX *ctx, char *buf)
{
- int i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- SHA1_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[((uint32_t)digest[i]) >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-int SHA1_Equal(SHA1_CTX* pctx1, SHA1_CTX* pctx2) {
- return pctx1->num == pctx2->num
- && pctx1->h0 == pctx2->h0
- && pctx1->h1 == pctx2->h1
- && pctx1->h2 == pctx2->h2
- && pctx1->h3 == pctx2->h3
- && pctx1->h4 == pctx2->h4
- && pctx1->Nl == pctx2->Nl
- && pctx1->Nh == pctx2->Nh
- && memcmp(pctx1->data, pctx2->data, sizeof(pctx1->data)) == 0;
+ SHA1_Final((unsigned char *)buf, ctx);
}
diff --git a/ext/digest/sha1/sha1ossl.h b/ext/digest/sha1/sha1ossl.h
index e8d7e74baf..8f9984cc64 100644
--- a/ext/digest/sha1/sha1ossl.h
+++ b/ext/digest/sha1/sha1ossl.h
@@ -3,14 +3,18 @@
#ifndef SHA1OSSL_H_INCLUDED
#define SHA1OSSL_H_INCLUDED
+#include <stddef.h>
#include <openssl/sha.h>
#define SHA1_CTX SHA_CTX
+#ifdef SHA_BLOCK_LENGTH
#define SHA1_BLOCK_LENGTH SHA_BLOCK_LENGTH
+#else
+#define SHA1_BLOCK_LENGTH SHA_CBLOCK
+#endif
#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
-char *SHA1_End(SHA1_CTX *ctx, char *buf);
-int SHA1_Equal(SHA1_CTX *pctx1, SHA1_CTX *pctx2);
+void SHA1_Finish(SHA1_CTX *ctx, char *buf);
#endif
diff --git a/ext/digest/sha2/MANIFEST b/ext/digest/sha2/MANIFEST
deleted file mode 100644
index d94089e17b..0000000000
--- a/ext/digest/sha2/MANIFEST
+++ /dev/null
@@ -1,7 +0,0 @@
-MANIFEST
-extconf.rb
-sha2.c
-sha2.h
-sha2hl.c
-sha2init.c
-depend
diff --git a/ext/digest/sha2/depend b/ext/digest/sha2/depend
index 2587415fdc..225d6ad52b 100644
--- a/ext/digest/sha2/depend
+++ b/ext/digest/sha2/depend
@@ -1,7 +1,5 @@
sha2.o: sha2.c sha2.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-sha2hl.o: sha2hl.c sha2.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
sha2init.o: sha2init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
sha2.h $(srcdir)/../defs.h
diff --git a/ext/digest/sha2/extconf.rb b/ext/digest/sha2/extconf.rb
index c982aa64de..c084a51a64 100644
--- a/ext/digest/sha2/extconf.rb
+++ b/ext/digest/sha2/extconf.rb
@@ -3,11 +3,11 @@
require "mkmf"
-$CFLAGS << " -DHAVE_CONFIG_H -I#{File.dirname(__FILE__)}/.."
+$defs << "-DHAVE_CONFIG_H"
+$INCFLAGS << " -I$(srcdir)/.."
$objs = [
"sha2.#{$OBJEXT}",
- "sha2hl.#{$OBJEXT}",
"sha2init.#{$OBJEXT}",
]
@@ -17,12 +17,8 @@ have_header("inttypes.h")
have_header("unistd.h")
-if try_cpp(<<SRC, $defs.join(' '))
-#include "defs.h"
-#ifdef NO_UINT64_T
- #error ** Cannot find a 64bit integer type - skipping the SHA2 module.
-#endif
-SRC
-then
+$preload = %w[digest]
+
+if have_type("uint64_t", "defs.h", $defs.join(' '))
create_makefile("digest/sha2")
end
diff --git a/ext/digest/sha2/lib/sha2.rb b/ext/digest/sha2/lib/sha2.rb
new file mode 100644
index 0000000000..52dd639f9b
--- /dev/null
+++ b/ext/digest/sha2/lib/sha2.rb
@@ -0,0 +1,73 @@
+#--
+# sha2.rb - defines Digest::SHA2 class which wraps up the SHA256,
+# SHA384, and SHA512 classes.
+#++
+# Copyright (c) 2006 Akinori MUSHA <knu@iDaemons.org>
+#
+# All rights reserved. You can redistribute and/or modify it under the same
+# terms as Ruby.
+#
+# $Id$
+
+require 'digest'
+
+module Digest
+ #
+ # A meta digest provider class for SHA256, SHA384 and SHA512.
+ #
+ class SHA2 < Digest::Class
+ # call-seq:
+ # Digest::SHA2.new(bitlen = 256) -> digest_obj
+ #
+ # Creates a new SHA2 hash object with a given bit length.
+ def initialize(bitlen = 256)
+ case bitlen
+ when 256
+ @sha2 = Digest::SHA256.new
+ when 384
+ @sha2 = Digest::SHA384.new
+ when 512
+ @sha2 = Digest::SHA512.new
+ else
+ raise ArgumentError, "unsupported bit length: %s" % bitlen.inspect
+ end
+ @bitlen = bitlen
+ end
+
+ # :nodoc:
+ def reset
+ @sha2.reset
+ self
+ end
+
+ # :nodoc:
+ def update(str)
+ @sha2.update(str)
+ self
+ end
+ alias << update
+
+ def finish
+ @sha2.digest!
+ end
+ private :finish
+
+ def block_length
+ @sha2.block_length
+ end
+
+ def digest_length
+ @sha2.digest_length
+ end
+
+ # :nodoc:
+ def initialize_copy(other)
+ @sha2 = other.instance_eval { @sha2.clone }
+ end
+
+ # :nodoc:
+ def inspect
+ "#<%s:%d %s>" % [self.class.name, @bitlen, hexdigest]
+ end
+ end
+end
diff --git a/ext/digest/sha2/sha2.c b/ext/digest/sha2/sha2.c
index 24a57ded0d..aca9ee926f 100644
--- a/ext/digest/sha2/sha2.c
+++ b/ext/digest/sha2/sha2.c
@@ -67,7 +67,7 @@ typedef uint8_t sha2_byte; /* Exactly 1 byte */
typedef uint32_t sha2_word32; /* Exactly 4 bytes */
typedef uint64_t sha2_word64; /* Exactly 8 bytes */
-#if defined(__GNUC__) || defined(_HPUX_SOURCE)
+#if defined(__GNUC__) || defined(_HPUX_SOURCE) || defined(__IBMC__)
#define ULL(number) number##ULL
#else
#define ULL(number) (uint64_t)(number)
@@ -515,7 +515,7 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
usedspace = freespace = 0;
}
-void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+void SHA256_Finish(SHA256_CTX* context, sha2_byte digest[]) {
sha2_word32 *d = (sha2_word32*)digest;
unsigned int usedspace;
@@ -578,12 +578,6 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
usedspace = 0;
}
-int SHA256_Equal(SHA256_CTX* pctx1, SHA256_CTX* pctx2) {
- return pctx1->bitcount == pctx2->bitcount
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
-
/*** SHA-512: *********************************************************/
void SHA512_Init(SHA512_CTX* context) {
if (context == (SHA512_CTX*)0) {
@@ -852,7 +846,7 @@ void SHA512_Last(SHA512_CTX* context) {
SHA512_Transform(context, (const sha2_word64*)context->buffer);
}
-void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+void SHA512_Finish(SHA512_CTX* context, sha2_byte digest[]) {
sha2_word64 *d = (sha2_word64*)digest;
/* Sanity check: */
@@ -881,12 +875,6 @@ void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
MEMSET_BZERO(context, sizeof(SHA512_CTX));
}
-int SHA512_Equal(SHA512_CTX* pctx1, SHA512_CTX* pctx2) {
- return memcmp(pctx1->bitcount, pctx2->bitcount, sizeof(pctx1->bitcount)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
-
/*** SHA-384: *********************************************************/
void SHA384_Init(SHA384_CTX* context) {
if (context == (SHA384_CTX*)0) {
@@ -901,7 +889,7 @@ void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
SHA512_Update((SHA512_CTX*)context, data, len);
}
-void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
+void SHA384_Finish(SHA384_CTX* context, sha2_byte digest[]) {
sha2_word64 *d = (sha2_word64*)digest;
/* Sanity check: */
@@ -929,9 +917,3 @@ void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
/* Zero out state data */
MEMSET_BZERO(context, sizeof(SHA384_CTX));
}
-
-int SHA384_Equal(SHA384_CTX* pctx1, SHA384_CTX* pctx2) {
- return memcmp(pctx1->bitcount, pctx2->bitcount, sizeof(pctx1->bitcount)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
diff --git a/ext/digest/sha2/sha2.h b/ext/digest/sha2/sha2.h
index 4689ad93ce..917d415b73 100644
--- a/ext/digest/sha2/sha2.h
+++ b/ext/digest/sha2/sha2.h
@@ -77,53 +77,29 @@ typedef SHA512_CTX SHA384_CTX;
#ifdef RUBY
#define SHA256_Init rb_Digest_SHA256_Init
#define SHA256_Update rb_Digest_SHA256_Update
-#define SHA256_Final rb_Digest_SHA256_Final
-#define SHA256_End rb_Digest_SHA256_End
-#define SHA256_Data rb_Digest_SHA256_Data
-#define SHA256_File rb_Digest_SHA256_File
-#define SHA256_Equal rb_Digest_SHA256_Equal
+#define SHA256_Finish rb_Digest_SHA256_Finish
#define SHA384_Init rb_Digest_SHA384_Init
#define SHA384_Update rb_Digest_SHA384_Update
-#define SHA384_Final rb_Digest_SHA384_Final
-#define SHA384_End rb_Digest_SHA384_End
-#define SHA384_Data rb_Digest_SHA384_Data
-#define SHA384_File rb_Digest_SHA384_File
-#define SHA384_Equal rb_Digest_SHA384_Equal
+#define SHA384_Finish rb_Digest_SHA384_Finish
#define SHA512_Init rb_Digest_SHA512_Init
#define SHA512_Update rb_Digest_SHA512_Update
-#define SHA512_Final rb_Digest_SHA512_Final
-#define SHA512_End rb_Digest_SHA512_End
-#define SHA512_Data rb_Digest_SHA512_Data
-#define SHA512_File rb_Digest_SHA512_File
-#define SHA512_Equal rb_Digest_SHA512_Equal
+#define SHA512_Finish rb_Digest_SHA512_Finish
#endif
/*** SHA-256/384/512 Function Prototypes ******************************/
void SHA256_Init _((SHA256_CTX *));
void SHA256_Update _((SHA256_CTX*, const uint8_t*, size_t));
-void SHA256_Final _((uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*));
-char* SHA256_End _((SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]));
-char* SHA256_Data _((const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]));
-char *SHA256_File _((char *, char *));
-int SHA256_Equal _((SHA256_CTX*, SHA256_CTX*));
+void SHA256_Finish _((SHA256_CTX*, uint8_t[SHA256_DIGEST_LENGTH]));
void SHA384_Init _((SHA384_CTX*));
void SHA384_Update _((SHA384_CTX*, const uint8_t*, size_t));
-void SHA384_Final _((uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*));
-char* SHA384_End _((SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]));
-char* SHA384_Data _((const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]));
-char *SHA384_File _((char *, char *));
-int SHA384_Equal _((SHA384_CTX*, SHA384_CTX*));
+void SHA384_Finish _((SHA384_CTX*, uint8_t[SHA384_DIGEST_LENGTH]));
void SHA512_Init _((SHA512_CTX*));
void SHA512_Update _((SHA512_CTX*, const uint8_t*, size_t));
-void SHA512_Final _((uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*));
-char* SHA512_End _((SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]));
-char* SHA512_Data _((const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]));
-char *SHA512_File _((char *, char *));
-int SHA512_Equal _((SHA512_CTX*, SHA512_CTX*));
+void SHA512_Finish _((SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]));
#ifdef __cplusplus
}
diff --git a/ext/digest/sha2/sha2hl.c b/ext/digest/sha2/sha2hl.c
deleted file mode 100644
index 03fde538c3..0000000000
--- a/ext/digest/sha2/sha2hl.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* $NetBSD: sha2hl.c,v 1.1 2001/03/12 09:08:40 agc Exp $ */
-/* $RoughId: sha2hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id$ */
-
-/*
- * sha2hl.c
- * This code includes some functions taken from sha2.c, hence the
- * following licence reproduction.
- *
- * This code is not a verbatim copy, since some routines have been added,
- * and some bugs have been fixed.
- *
- * Version 1.0.0beta1
- *
- * Written by Aaron D. Gifford <me@aarongifford.com>
- *
- * Copyright 2000 Aaron D. Gifford. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include "sha2.h"
-
-#ifndef lint
-/* __RCSID("$NetBSD: sha2hl.c,v 1.1 2001/03/12 09:08:40 agc Exp $"); */
-#endif /* not lint */
-
-/* #include "namespace.h" */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-/*
- * Constant used by SHA256/384/512_End() functions for converting the
- * digest to a readable hexadecimal character string:
- */
-static const char sha2_hex_digits[] = "0123456789abcdef";
-
-char *
-SHA256_File(char *filename, char *buf)
-{
- uint8_t buffer[BUFSIZ * 20];
- SHA256_CTX ctx;
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA256_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return (0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA256_Update(&ctx, buffer, (size_t) num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return (num < 0 ? 0 : SHA256_End(&ctx, buf));
-}
-
-
-char *
-SHA256_End(SHA256_CTX *ctx, char buffer[])
-{
- uint8_t digest[SHA256_DIGEST_LENGTH], *d = digest;
- uint8_t *ret;
- int i;
-
- /* Sanity check: */
- assert(ctx != NULL);
-
- if ((ret = buffer) != NULL) {
- SHA256_Final(digest, ctx);
-
- for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char) 0;
- } else {
- (void) memset(ctx, 0, sizeof(SHA256_CTX));
- }
- (void) memset(digest, 0, SHA256_DIGEST_LENGTH);
- return ret;
-}
-
-char *
-SHA256_Data(const uint8_t * data, size_t len, char *digest)
-{
- SHA256_CTX ctx;
-
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, data, len);
- return SHA256_End(&ctx, digest);
-}
-
-char *
-SHA384_File(char *filename, char *buf)
-{
- SHA384_CTX ctx;
- uint8_t buffer[BUFSIZ * 20];
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA384_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return (0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA384_Update(&ctx, buffer, (size_t) num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return (num < 0 ? 0 : SHA384_End(&ctx, buf));
-}
-
-char *
-SHA384_End(SHA384_CTX * ctx, char buffer[])
-{
- uint8_t digest[SHA384_DIGEST_LENGTH], *d = digest;
- uint8_t *ret;
- int i;
-
- /* Sanity check: */
- assert(ctx != NULL);
-
- if ((ret = buffer) != NULL) {
- SHA384_Final(digest, ctx);
-
- for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char) 0;
- } else {
- (void) memset(ctx, 0, sizeof(SHA384_CTX));
- }
- (void) memset(digest, 0, SHA384_DIGEST_LENGTH);
- return ret;
-}
-
-char *
-SHA384_Data(const uint8_t * data, size_t len, char *digest)
-{
- SHA384_CTX ctx;
-
- SHA384_Init(&ctx);
- SHA384_Update(&ctx, data, len);
- return SHA384_End(&ctx, digest);
-}
-
-char *
-SHA512_File(char *filename, char *buf)
-{
- SHA512_CTX ctx;
- uint8_t buffer[BUFSIZ * 20];
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA512_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return (0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA512_Update(&ctx, buffer, (size_t) num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return (num < 0 ? 0 : SHA512_End(&ctx, buf));
-}
-
-char *
-SHA512_End(SHA512_CTX * ctx, char buffer[])
-{
- uint8_t digest[SHA512_DIGEST_LENGTH], *d = digest;
- uint8_t *ret;
- int i;
-
- /* Sanity check: */
- assert(ctx != NULL);
-
- if ((ret = buffer) != NULL) {
- SHA512_Final(digest, ctx);
-
- for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char) 0;
- } else {
- (void) memset(ctx, 0, sizeof(SHA512_CTX));
- }
- (void) memset(digest, 0, SHA512_DIGEST_LENGTH);
- return ret;
-}
-
-char *
-SHA512_Data(const uint8_t * data, size_t len, char *digest)
-{
- SHA512_CTX ctx;
-
- SHA512_Init(&ctx);
- SHA512_Update(&ctx, data, len);
- return SHA512_End(&ctx, digest);
-}
diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c
index 4b14031811..c83a29316a 100644
--- a/ext/digest/sha2/sha2init.c
+++ b/ext/digest/sha2/sha2init.c
@@ -7,18 +7,23 @@
#define FOREACH_BITLEN(func) func(256) func(384) func(512)
#define DEFINE_ALGO_METADATA(bitlen) \
-static algo_t sha##bitlen = { \
+static rb_digest_metadata_t sha##bitlen = { \
+ RUBY_DIGEST_API_VERSION, \
SHA##bitlen##_DIGEST_LENGTH, \
+ SHA##bitlen##_BLOCK_LENGTH, \
sizeof(SHA##bitlen##_CTX), \
- (hash_init_func_t)SHA##bitlen##_Init, \
- (hash_update_func_t)SHA##bitlen##_Update, \
- (hash_end_func_t)SHA##bitlen##_End, \
- (hash_final_func_t)SHA##bitlen##_Final, \
- (hash_equal_func_t)SHA##bitlen##_Equal, \
+ (rb_digest_hash_init_func_t)SHA##bitlen##_Init, \
+ (rb_digest_hash_update_func_t)SHA##bitlen##_Update, \
+ (rb_digest_hash_finish_func_t)SHA##bitlen##_Finish, \
};
FOREACH_BITLEN(DEFINE_ALGO_METADATA)
+/*
+ * Classes for calculating message digests using the SHA-256/384/512
+ * Secure Hash Algorithm(s) by NIST (the US' National Institute of
+ * Standards and Technology), described in FIPS PUB 180-2.
+ */
void
Init_sha2()
{
@@ -30,7 +35,7 @@ Init_sha2()
FOREACH_BITLEN(DECLARE_ALGO_CLASS)
- rb_require("digest.so");
+ rb_require("digest");
id_metadata = rb_intern("metadata");
@@ -40,8 +45,8 @@ Init_sha2()
#define DEFINE_ALGO_CLASS(bitlen) \
cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \
\
- rb_cvar_set(cDigest_SHA##bitlen, id_metadata, \
- Data_Wrap_Struct(rb_cObject, 0, 0, &sha##bitlen), Qtrue);
+ rb_ivar_set(cDigest_SHA##bitlen, id_metadata, \
+ Data_Wrap_Struct(rb_cObject, 0, 0, &sha##bitlen));
FOREACH_BITLEN(DEFINE_ALGO_CLASS)
}
diff --git a/ext/digest/test.sh b/ext/digest/test.sh
index 6fb07d2177..328c7575e6 100644
--- a/ext/digest/test.sh
+++ b/ext/digest/test.sh
@@ -11,8 +11,6 @@ ${RUBY} extconf.rb --with-cflags="${CFLAGS}"
${MAKE} clean
${MAKE}
-mkdir -p lib/digest
-
for algo in md5 rmd160 sha1 sha2; do
args=--with-cflags="${CFLAGS}"
@@ -27,7 +25,6 @@ for algo in md5 rmd160 sha1 sha2; do
ln -sf ../../$algo/$algo.so lib/digest/
done
-${RUBY} -I. -I./lib test.rb
+${RUBY} -I. -I./lib ../../test/digest/test_digest.rb
rm lib/digest/*.so
-rmdir lib/digest
diff --git a/ext/dl/MANIFEST b/ext/dl/MANIFEST
deleted file mode 100644
index d44344421d..0000000000
--- a/ext/dl/MANIFEST
+++ /dev/null
@@ -1,31 +0,0 @@
-MANIFEST
-depend
-dl.c
-dl.def
-dl.h
-doc/dl.txt
-extconf.rb
-h2rb
-handle.c
-install.rb
-lib/dl/import.rb
-lib/dl/struct.rb
-lib/dl/types.rb
-lib/dl/win32.rb
-mkcall.rb
-mkcallback.rb
-mkcbtable.rb
-ptr.c
-sample/c++sample.C
-sample/c++sample.rb
-sample/drives.rb
-sample/getch.rb
-sample/libc.rb
-sample/msgbox.rb
-sample/msgbox2.rb
-sample/stream.rb
-sym.c
-test/libtest.def
-test/test.c
-test/test.rb
-type.rb
diff --git a/ext/dl/dl.c b/ext/dl/dl.c
index 22abb754d2..f65247be86 100644
--- a/ext/dl/dl.c
+++ b/ext/dl/dl.c
@@ -147,7 +147,7 @@ dlstrdup(const char *str)
{
char *newstr;
- newstr = (char*)dlmalloc(strlen(str));
+ newstr = (char*)dlmalloc(strlen(str)+1);
strcpy(newstr,str);
return newstr;
@@ -435,7 +435,15 @@ c_parray(VALUE v, long *size)
ary[i] = (void*)(pdata->ptr);
}
else{
- rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
+ e = rb_funcall(e, rb_intern("to_ptr"), 0);
+ if (rb_obj_is_kind_of(e, rb_cDLPtrData)) {
+ struct ptr_data *pdata;
+ Data_Get_Struct(e, struct ptr_data, pdata);
+ ary[i] = (void*)(pdata->ptr);
+ }
+ else{
+ rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
+ }
}
break;
}
@@ -451,7 +459,7 @@ rb_ary2cary(char t, VALUE v, long *size)
VALUE val0;
val0 = rb_check_array_type(v);
- if(NIL_P(TYPE(val0))) {
+ if(NIL_P(val0)) {
rb_raise(rb_eDLTypeError, "an array is expected.");
}
v = val0;
@@ -495,6 +503,12 @@ rb_ary2cary(char t, VALUE v, long *size)
if (rb_obj_is_kind_of(val0, rb_cDLPtrData)) {
return (void*)c_parray(v,size);
}
+ else{
+ val0 = rb_funcall(val0, rb_intern("to_ptr"), 0);
+ if (rb_obj_is_kind_of(val0, rb_cDLPtrData)) {
+ return (void*)c_parray(v,size);
+ }
+ }
rb_raise(rb_eDLTypeError, "type mismatch");
case T_NIL:
return (void*)c_parray(v, size);
@@ -508,12 +522,15 @@ rb_str_to_ptr(VALUE self)
{
char *ptr;
int len;
+ VALUE p;
len = RSTRING(self)->len;
ptr = (char*)dlmalloc(len + 1);
memcpy(ptr, RSTRING(self)->ptr, len);
ptr[len] = '\0';
- return rb_dlptr_new((void*)ptr,len,dlfree);
+ p = rb_dlptr_new((void*)ptr,len,dlfree);
+ OBJ_INFECT(p, self);
+ return p;
}
VALUE
@@ -531,25 +548,30 @@ rb_ary_to_ptr(int argc, VALUE argv[], VALUE self)
ptr = rb_ary2cary(0, self, &size);
break;
}
- return ptr ? rb_dlptr_new(ptr, size, dlfree) : Qnil;
+ if (ptr) {
+ VALUE p = rb_dlptr_new(ptr, size, dlfree);
+ OBJ_INFECT(p, self);
+ return p;
+ }
+ return Qnil;
}
VALUE
rb_io_to_ptr(VALUE self)
{
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *fp;
GetOpenFile(self, fptr);
fp = fptr->f;
- return fp ? rb_dlptr_new(fp, sizeof(FILE), 0) : Qnil;
+ return fp ? rb_dlptr_new(fp, 0, 0) : Qnil;
}
VALUE
rb_dl_dlopen(int argc, VALUE argv[], VALUE self)
{
- rb_secure(4);
+ rb_secure(2);
return rb_class_new_instance(argc, argv, rb_cDLHandle);
}
diff --git a/ext/dl/handle.c b/ext/dl/handle.c
index 95b6dc74dc..69d47caac0 100644
--- a/ext/dl/handle.c
+++ b/ext/dl/handle.c
@@ -66,12 +66,12 @@ rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
ptr = dlopen(clib, cflag);
#if defined(HAVE_DLERROR)
if (!ptr && (err = dlerror())) {
- rb_raise(rb_eRuntimeError, err);
+ rb_raise(rb_eRuntimeError, "%s", err);
}
#else
if (!ptr) {
err = dlerror();
- rb_raise(rb_eRuntimeError, err);
+ rb_raise(rb_eRuntimeError, "%s", err);
}
#endif
Data_Get_Struct(self, struct dl_handle, dlhandle);
@@ -161,7 +161,7 @@ rb_dlhandle_sym(int argc, VALUE argv[], VALUE self)
Data_Get_Struct(self, struct dl_handle, dlhandle);
if (!dlhandle->open) {
- rb_raise(rb_eRuntimeError, "Closed handle.");
+ rb_raise(rb_eRuntimeError, "closed handle");
}
handle = dlhandle->ptr;
@@ -187,11 +187,11 @@ rb_dlhandle_sym(int argc, VALUE argv[], VALUE self)
if (!func)
#endif
{
- rb_raise(rb_eRuntimeError, "Unknown symbol \"%sA\".", name);
+ rb_raise(rb_eRuntimeError, "unknown symbol \"%sA\"", name);
}
}
#else
- rb_raise(rb_eRuntimeError, "Unknown symbol \"%s\".", name);
+ rb_raise(rb_eRuntimeError, "unknown symbol \"%s\"", name);
#endif
}
val = rb_dlsym_new(func, name, stype);
diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb
index c0dfb5f705..01ee2490e8 100644
--- a/ext/dl/lib/dl/import.rb
+++ b/ext/dl/lib/dl/import.rb
@@ -9,15 +9,11 @@ module DL
module Internal
def init_types()
- if( !@types )
- @types = ::DL::Types.new
- end
+ @types ||= ::DL::Types.new
end
def init_sym()
- if( !@SYM )
- @SYM = {}
- end
+ @SYM ||= {}
end
def [](name)
@@ -42,10 +38,10 @@ module DL
case proto
when /^([\d\w\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/
ret = $1
- args = $2
+ args = $2.strip()
ret = ret.split(/\s+/)
args = args.split(/\s*,\s*/)
- func = ret.pop
+ func = ret.pop()
if( func =~ /^\*/ )
func.gsub!(/^\*+/,"")
ret.push("*")
@@ -74,8 +70,11 @@ module DL
init_types()
init_sym()
- rty,renc,rdec = @types.encode_type(ret)
- ty,enc,dec = encode_types(args)
+ rty,renc,rdec = @types.encode_return_type(ret)
+ if( !rty )
+ raise(TypeError, "unsupported type: #{ret}")
+ end
+ ty,enc,dec = encode_argument_types(args)
symty = rty + ty
module_eval("module_function :#{func}")
@@ -85,10 +84,10 @@ module DL
" args = enc.call(args) if enc",
" r,rs = #{func}(*args)",
" r = renc.call(r) if rdec",
- " rs = dec.call(rs) if dec",
+ " rs = dec.call(rs) if (dec && rs)",
" @retval = r",
" @args = rs",
- " @retval",
+ " r",
"}",
].join("\n"))
@@ -100,9 +99,10 @@ module DL
# example:
# typealias("uint", "unsigned int")
#
- def typealias(*args)
+ def typealias(alias_type, ty1, enc1=nil, dec1=nil, ty2=nil, enc2=nil, dec2=nil)
init_types()
- @types.typealias(*args)
+ @types.typealias(alias_type, ty1, enc1, dec1,
+ ty2||ty1, enc2, dec2)
end
# example:
@@ -135,8 +135,11 @@ module DL
init_types()
init_sym()
- rty,_,rdec = @types.encode_type(rettype)
- ty,enc,dec = encode_types(argtypes)
+ rty,_,rdec = @types.encode_return_type(rettype)
+ if( !rty )
+ raise(TypeError, "unsupported type: #{rettype}")
+ end
+ ty,enc,dec = encode_argument_types(argtypes)
symty = rty + ty
sym = symbol(name, symty)
@@ -166,7 +169,7 @@ module DL
" rs = dec.call(rs) if dec",
" @retval = r",
" @args = rs",
- " return @retval",
+ " return r",
"end",
"module_function :#{mname}",
].join("\n")
@@ -182,13 +185,16 @@ module DL
return @retval
end
- def encode_types(tys)
+ def encode_argument_types(tys)
init_types()
encty = []
enc = nil
dec = nil
tys.each_with_index{|ty,idx|
- ty,c1,c2,_,_ = @types.encode_type(ty)
+ ty,c1,c2 = @types.encode_argument_type(ty)
+ if( !ty )
+ raise(TypeError, "unsupported type: #{ty}")
+ end
encty.push(ty)
if( enc )
if( c1 )
diff --git a/ext/dl/lib/dl/struct.rb b/ext/dl/lib/dl/struct.rb
index 2c52d5040d..33f303fe22 100644
--- a/ext/dl/lib/dl/struct.rb
+++ b/ext/dl/lib/dl/struct.rb
@@ -33,7 +33,7 @@ module DL
"def #{name}",
" v = @ptr[\"#{name}\"]",
" if( @len[\"#{name}\"] )",
- " v = v.collect{|x| @dec[\"#{name}\"].call(x) if @dec[\"#{name}\"] }",
+ " v = v.collect{|x| @dec[\"#{name}\"] ? @dec[\"#{name}\"].call(x) : x }",
" else",
" v = @dec[\"#{name}\"].call(v) if @dec[\"#{name}\"]",
" end",
@@ -41,7 +41,7 @@ module DL
"end",
"def #{name}=(v)",
" if( @len[\"#{name}\"] )",
- " v = v.collect{|x| @enc[\"#{name}\"].call(x) if @enc[\"#{name}\"] }",
+ " v = v.collect{|x| @enc[\"#{name}\"] ? @enc[\"#{name}\"].call(x) : x }",
" else",
" v = @enc[\"#{name}\"].call(v) if @enc[\"#{name}\"]",
" end",
@@ -128,7 +128,10 @@ module DL
else
raise(RuntimeError, "invalid element: #{elem}")
end
- ty,_,_,enc,dec = @types.encode_type(ty)
+ ty,enc,dec = @types.encode_struct_type(ty)
+ if( !ty )
+ raise(TypeError, "unsupported type: #{ty}")
+ end
return [name,ty,num,enc,dec]
end
end # class Struct
diff --git a/ext/dl/lib/dl/types.rb b/ext/dl/lib/dl/types.rb
index b9a235f3b4..1144917dae 100644
--- a/ext/dl/lib/dl/types.rb
+++ b/ext/dl/lib/dl/types.rb
@@ -6,174 +6,240 @@ module DL
class Types
TYPES = [
# FORMAT:
- # ["alias name", "type name",
- # encoding_method, decoding_method, for function prototypes
- # encoding_method, decoding_method] for structures (not implemented)
+ # ["alias name",
+ # "type name", encoding_method, decoding_method, for function prototypes
+ # "type name", encoding_method, decoding_method] for structures (not implemented)
# for Windows
- ["DWORD", "unsigned long", nil, nil, nil, nil],
- ["PDWORD", "unsigned long *", nil, nil, nil, nil],
- ["WORD", "unsigned short", nil, nil, nil, nil],
- ["PWORD", "unsigned int *", nil, nil, nil, nil],
- ["BYTE", "unsigned char", nil, nil, nil, nil],
- ["PBYTE", "unsigned char *", nil, nil, nil, nil],
- ["BOOL", "ibool", nil, nil, nil, nil],
- ["ATOM", "int", nil, nil, nil, nil],
- ["BYTE", "unsigned char", nil, nil, nil, nil],
- ["PBYTE", "unsigned char *", nil, nil, nil, nil],
- ["UINT", "unsigned int", nil, nil, nil, nil],
- ["ULONG", "unsigned long", nil, nil, nil, nil],
- ["UCHAR", "unsigned char", nil, nil, nil, nil],
- ["HANDLE", "unsigned long", nil, nil, nil, nil],
- ["PHANDLE","void*", nil, nil, nil, nil],
- ["PVOID", "void*", nil, nil, nil, nil],
- ["LPCSTR", "char*", nil, nil, nil, nil],
- ["HDC", "unsigned int", nil, nil, nil, nil],
- ["HWND", "unsigned int", nil, nil, nil, nil],
+ ["DWORD", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
+ ["PDWORD", "unsigned long *", nil, nil,
+ "unsigned long *", nil, nil],
+ ["WORD", "unsigned short", nil, nil,
+ "unsigned short", nil, nil],
+ ["PWORD", "unsigned int *", nil, nil,
+ "unsigned int *", nil, nil],
+ ["BYTE", "unsigned char", nil, nil,
+ "unsigned char", nil, nil],
+ ["PBYTE", "unsigned char *", nil, nil,
+ "unsigned char *", nil, nil],
+ ["BOOL", "ibool", nil, nil,
+ "ibool", nil, nil],
+ ["ATOM", "int", nil, nil,
+ "int", nil, nil],
+ ["BYTE", "unsigned char", nil, nil,
+ "unsigned char", nil, nil],
+ ["PBYTE", "unsigned char *", nil, nil,
+ "unsigned char *", nil, nil],
+ ["UINT", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
+ ["ULONG", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
+ ["UCHAR", "unsigned char", nil, nil,
+ "unsigned char", nil, nil],
+ ["HANDLE", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
+ ["PHANDLE","void*", nil, nil,
+ "void*", nil, nil],
+ ["PVOID", "void*", nil, nil,
+ "void*", nil, nil],
+ ["LPCSTR", "char*", nil, nil,
+ "char*", nil, nil],
+ ["HDC", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
+ ["HWND", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
# Others
- ["uint", "unsigned int", nil, nil, nil, nil],
- ["u_int", "unsigned int", nil, nil, nil, nil],
- ["ulong", "unsigned long", nil, nil, nil, nil],
- ["u_long", "unsigned long", nil, nil, nil, nil],
+ ["uint", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
+ ["u_int", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
+ ["ulong", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
+ ["u_long", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
# DL::Importable primitive types
- ["ibool", "I",
+ ["ibool",
+ "I",
proc{|v| v ? 1 : 0},
proc{|v| (v != 0) ? true : false},
+ "I",
proc{|v| v ? 1 : 0 },
proc{|v| (v != 0) ? true : false} ],
- ["cbool", "C",
+ ["cbool",
+ "C",
proc{|v| v ? 1 : 0},
proc{|v| (v != 0) ? true : false},
+ "C",
proc{|v,len| v ? 1 : 0},
proc{|v,len| (v != 0) ? true : false}],
- ["lbool", "L",
+ ["lbool",
+ "L",
proc{|v| v ? 1 : 0},
proc{|v| (v != 0) ? true : false},
+ "L",
proc{|v,len| v ? 1 : 0},
proc{|v,len| (v != 0) ? true : false}],
- ["unsigned char", "I",
+ ["unsigned char",
+ "C",
proc{|v| [v].pack("C").unpack("c")[0]},
proc{|v| [v].pack("c").unpack("C")[0]},
+ "C",
proc{|v| [v].pack("C").unpack("c")[0]},
proc{|v| [v].pack("c").unpack("C")[0]}],
- ["unsigned short", "H",
+ ["unsigned short",
+ "H",
proc{|v| [v].pack("S").unpack("s")[0]},
proc{|v| [v].pack("s").unpack("S")[0]},
+ "H",
proc{|v| [v].pack("S").unpack("s")[0]},
proc{|v| [v].pack("s").unpack("S")[0]}],
- ["unsigned int", "I",
+ ["unsigned int",
+ "I",
proc{|v| [v].pack("I").unpack("i")[0]},
proc{|v| [v].pack("i").unpack("I")[0]},
+ "I",
proc{|v| [v].pack("I").unpack("i")[0]},
proc{|v| [v].pack("i").unpack("I")[0]}],
- ["unsigned long", "L",
+ ["unsigned long",
+ "L",
proc{|v| [v].pack("L").unpack("l")[0]},
proc{|v| [v].pack("l").unpack("L")[0]},
+ "L",
proc{|v| [v].pack("L").unpack("l")[0]},
proc{|v| [v].pack("l").unpack("L")[0]}],
- ["unsigned char ref", "i",
+ ["unsigned char ref",
+ "c",
proc{|v| [v].pack("C").unpack("c")[0]},
proc{|v| [v].pack("c").unpack("C")[0]},
- nil, nil],
- ["unsigned int ref", "i",
+ nil, nil, nil],
+ ["unsigned int ref",
+ "i",
proc{|v| [v].pack("I").unpack("i")[0]},
proc{|v| [v].pack("i").unpack("I")[0]},
- nil, nil],
- ["unsigned long ref", "l",
+ nil, nil, nil],
+ ["unsigned long ref",
+ "l",
proc{|v| [v].pack("L").unpack("l")[0]},
proc{|v| [v].pack("l").unpack("L")[0]},
- nil, nil],
- ["char ref", "c", nil, nil, nil, nil],
- ["short ref", "h", nil, nil, nil, nil],
- ["int ref", "i", nil, nil, nil, nil],
- ["long ref", "l", nil, nil, nil, nil],
- ["float ref", "f", nil, nil, nil, nil],
- ["double ref","d", nil, nil, nil, nil],
- ["char", "C", nil, nil, nil, nil],
- ["short", "H", nil, nil, nil, nil],
- ["int", "I", nil, nil, nil, nil],
- ["long", "L", nil, nil, nil, nil],
- ["float", "F", nil, nil, nil, nil],
- ["double", "D", nil, nil, nil, nil],
- [/^char\s*\*$/,"S",nil, nil, nil, nil],
- [/^.+\*$/, "P", nil, nil, nil, nil],
- [/^.+\[\]$/, "a", nil, nil, nil, nil],
- ["void", "0", nil, nil, nil, nil],
+ nil, nil, nil],
+ ["char ref", "c", nil, nil,
+ nil, nil, nil],
+ ["short ref", "h", nil, nil,
+ nil, nil, nil],
+ ["int ref", "i", nil, nil,
+ nil, nil, nil],
+ ["long ref", "l", nil, nil,
+ nil, nil, nil],
+ ["float ref", "f", nil, nil,
+ nil, nil, nil],
+ ["double ref","d", nil, nil,
+ nil, nil, nil],
+ ["char", "C", nil, nil,
+ "C", nil, nil],
+ ["short", "H", nil, nil,
+ "H", nil, nil],
+ ["int", "I", nil, nil,
+ "I", nil, nil],
+ ["long", "L", nil, nil,
+ "L", nil, nil],
+ ["float", "F", nil, nil,
+ "F", nil, nil],
+ ["double", "D", nil, nil,
+ "D", nil, nil],
+ [/^char\s*\*$/,"s",nil, nil,
+ "S",nil, nil],
+ [/^const char\s*\*$/,"S",nil, nil,
+ "S",nil, nil],
+ [/^.+\*$/, "P", nil, nil,
+ "P", nil, nil],
+ [/^.+\[\]$/, "a", nil, nil,
+ "a", nil, nil],
+ ["void", "0", nil, nil,
+ nil, nil, nil],
]
def initialize
init_types()
end
- def typealias(ty1, ty2, enc=nil, dec=nil, senc=nil, sdec=nil)
- @TYDEFS.unshift([ty1,ty2, enc,dec, senc, sdec])
+ def typealias(ty1, ty2, enc=nil, dec=nil, ty3=nil, senc=nil, sdec=nil)
+ @TYDEFS.unshift([ty1, ty2, enc, dec, ty3, senc, sdec])
end
def init_types
@TYDEFS = TYPES.dup
end
- def encode_type(ty)
- orig_ty = ty
- enc = nil
- dec = nil
- senc = nil
- sdec = nil
- @TYDEFS.each{|t1,t2,c1,c2,c3,c4|
-# if( t1.is_a?(String) )
-# t1 = Regexp.new("^" + t1 + "$")
-# end
- if( (t1.is_a?(Regexp) && (t1 =~ ty)) || (t1 == ty) )
- ty = ty.gsub(t1,t2)
- if( enc )
- if( c1 )
- conv1 = enc
- enc = proc{|v| c1.call(conv1.call(v))}
+ def encode_argument_type(alias_type)
+ proc_encode = nil
+ proc_decode = nil
+ @TYDEFS.each{|aty,ty,enc,dec,_,_,_|
+ if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
+ alias_type = alias_type.gsub(aty,ty) if ty
+ alias_type.strip! if alias_type
+ if( proc_encode )
+ if( enc )
+ conv1 = proc_encode
+ proc_encode = proc{|v| enc.call(conv1.call(v))}
end
else
- if( c1 )
- enc = c1
+ if( enc )
+ proc_encode = enc
end
end
- if( dec )
- if( c2 )
- conv2 = dec
- dec = proc{|v| c2.call(conv2.call(v))}
+ if( proc_decode )
+ if( dec )
+ conv2 = proc_decode
+ proc_decode = proc{|v| dec.call(conv2.call(v))}
end
else
- if( c2 )
- dec = c2
+ if( dec )
+ proc_decode = dec
end
end
- if( senc )
- if( c3 )
- conv3 = senc
- senc = proc{|v| c3.call(conv3.call(v))}
+ end
+ }
+ return [alias_type, proc_encode, proc_decode]
+ end
+
+ def encode_return_type(ty)
+ ty, enc, dec = encode_argument_type(ty)
+ return [ty, enc, dec]
+ end
+
+ def encode_struct_type(alias_type)
+ proc_encode = nil
+ proc_decode = nil
+ @TYDEFS.each{|aty,_,_,_,ty,enc,dec|
+ if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
+ alias_type = alias_type.gsub(aty,ty) if ty
+ alias_type.strip! if alias_type
+ if( proc_encode )
+ if( enc )
+ conv1 = proc_encode
+ proc_encode = proc{|v| enc.call(conv1.call(v))}
end
else
- if( c3 )
- senc = c3
+ if( enc )
+ proc_encode = enc
end
end
- if( sdec )
- if( c4 )
- conv4 = sdec
- sdec = proc{|v| c4.call(conv4.call(v))}
+ if( proc_decode )
+ if( dec )
+ conv2 = proc_decode
+ proc_decode = proc{|v| dec.call(conv2.call(v))}
end
else
- if( c4 )
- sdec = c4
+ if( dec )
+ proc_decode = dec
end
end
end
}
- ty = ty.strip
- if( ty.length != 1 )
- raise(TypeError, "unknown type: #{orig_ty}.")
- end
- return [ty,enc,dec,senc,sdec]
+ return [alias_type, proc_encode, proc_decode]
end
end # end of Types
end
diff --git a/ext/dl/lib/dl/win32.rb b/ext/dl/lib/dl/win32.rb
index 92f473d392..0fed47c324 100644
--- a/ext/dl/lib/dl/win32.rb
+++ b/ext/dl/lib/dl/win32.rb
@@ -6,7 +6,7 @@ class Win32API
DLL = {}
def initialize(dllname, func, import, export = "0")
- prototype = (export + import.to_s).tr("VPpNnLlIi", "0SSI")
+ prototype = (export + import.to_s).tr("VPpNnLlIi", "0SSI").sub(/^(.)0*$/, '\1')
handle = DLL[dllname] ||= DL::Handle.new(dllname)
@sym = handle.sym(func, prototype)
end
diff --git a/ext/dl/mkcallback.rb b/ext/dl/mkcallback.rb
index b7ea1718d0..c9f92e4a0d 100644
--- a/ext/dl/mkcallback.rb
+++ b/ext/dl/mkcallback.rb
@@ -31,6 +31,9 @@ def mkfunc(rettype, fnum, argc)
subst_code,
"",
" obj = rb_hash_aref(DLFuncTable, rb_assoc_new(INT2NUM(#{rettype.to_s}),INT2NUM(#{fnum.to_s})));",
+ " if(NIL_P(obj))",
+ " rb_raise(rb_eDLError, \"callback function does not exist in DL::FuncTable\");",
+ " Check_Type(obj, T_ARRAY);",
" proto = rb_ary_entry(obj, 0);",
" proc = rb_ary_entry(obj, 1);",
" Check_Type(proto, T_STRING);",
diff --git a/ext/dl/ptr.c b/ext/dl/ptr.c
index 32f78c4de5..01eb31da20 100644
--- a/ext/dl/ptr.c
+++ b/ext/dl/ptr.c
@@ -4,30 +4,22 @@
#include <ruby.h>
#include <ctype.h>
-#include <version.h> /* for ruby version code */
+#include "st.h"
#include "dl.h"
VALUE rb_cDLPtrData;
VALUE rb_mDLMemorySpace;
-static VALUE DLMemoryTable;
+static st_table* st_memory_table;
#ifndef T_SYMBOL
# define T_SYMBOL T_FIXNUM
#endif
-#if RUBY_VERSION_CODE < 171
-static VALUE
-rb_hash_delete(VALUE hash, VALUE key)
-{
- return rb_funcall(hash, rb_intern("delete"), 1, key);
-}
-#endif
-
static void
rb_dlmem_delete(void *ptr)
{
rb_secure(4);
- rb_hash_delete(DLMemoryTable, DLLONG2NUM(ptr));
+ st_delete(st_memory_table, (st_data_t*)&ptr, NULL);
}
static void
@@ -37,7 +29,7 @@ rb_dlmem_aset(void *ptr, VALUE obj)
rb_dlmem_delete(ptr);
}
else{
- rb_hash_aset(DLMemoryTable, DLLONG2NUM(ptr), DLLONG2NUM(obj));
+ st_insert(st_memory_table, (st_data_t)ptr, (st_data_t)obj);
}
}
@@ -46,8 +38,8 @@ rb_dlmem_aref(void *ptr)
{
VALUE val;
- val = rb_hash_aref(DLMemoryTable, DLLONG2NUM(ptr));
- return val == Qnil ? Qnil : (VALUE)DLNUM2LONG(val);
+ if(!st_lookup(st_memory_table, (st_data_t)ptr, &val)) return Qnil;
+ return val == Qundef ? Qnil : val;
}
void
@@ -344,7 +336,7 @@ rb_dlptr_to_array(int argc, VALUE argv[], VALUE self)
n = data->size / sizeof(void*);
break;
case 'S': case 's':
- for (n=0; ((void**)(data->ptr))[n]; n++) {};
+ n = data->size / sizeof(char*);
break;
default:
n = 0;
@@ -466,8 +458,9 @@ rb_dlptr_inspect(VALUE self)
char str[1024];
Data_Get_Struct(self, struct ptr_data, data);
- snprintf(str, 1023, "#<%s:0x%p ptr=0x%p size=%ld free=0x%p>",
- rb_class2name(CLASS_OF(self)), data, data->ptr, data->size, data->free);
+ snprintf(str, 1023, "#<%s:0x%lx ptr=0x%lx size=%ld free=0x%lx>",
+ rb_class2name(CLASS_OF(self)), data, data->ptr, data->size,
+ (long)data->free);
return rb_str_new2(str);
}
@@ -753,32 +746,32 @@ rb_dlptr_aref(int argc, VALUE argv[], VALUE self)
switch (data->ctype) {
case DLPTR_CTYPE_STRUCT:
for (i=0; i < data->ids_num; i++) {
+ switch (data->stype[i]) {
+ case 'I':
+ DLALIGN(data->ptr,offset,INT_ALIGN);
+ break;
+ case 'L':
+ DLALIGN(data->ptr,offset,LONG_ALIGN);
+ break;
+ case 'P':
+ case 'S':
+ DLALIGN(data->ptr,offset,VOIDP_ALIGN);
+ break;
+ case 'F':
+ DLALIGN(data->ptr,offset,FLOAT_ALIGN);
+ break;
+ case 'D':
+ DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
+ break;
+ case 'C':
+ break;
+ case 'H':
+ DLALIGN(data->ptr,offset,SHORT_ALIGN);
+ break;
+ default:
+ rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
+ }
if (data->ids[i] == id) {
- switch (data->stype[i]) {
- case 'I':
- DLALIGN(data->ptr,offset,INT_ALIGN);
- break;
- case 'L':
- DLALIGN(data->ptr,offset,LONG_ALIGN);
- break;
- case 'P':
- case 'S':
- DLALIGN(data->ptr,offset,VOIDP_ALIGN);
- break;
- case 'F':
- DLALIGN(data->ptr,offset,FLOAT_ALIGN);
- break;
- case 'D':
- DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
- break;
- case 'C':
- break;
- case 'H':
- DLALIGN(data->ptr,offset,SHORT_ALIGN);
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
- }
return cary2ary((char *)data->ptr + offset, data->stype[i], data->ssize[i]);
}
switch (data->stype[i]) {
@@ -883,34 +876,35 @@ rb_dlptr_aset(int argc, VALUE argv[], VALUE self)
case DLPTR_CTYPE_STRUCT:
offset = 0;
for (i=0; i < data->ids_num; i++) {
+ switch (data->stype[i]) {
+ case 'I':
+ DLALIGN(data->ptr,offset,INT_ALIGN);
+ break;
+ case 'L':
+ DLALIGN(data->ptr,offset,LONG_ALIGN);
+ break;
+ case 'P':
+ case 'S':
+ DLALIGN(data->ptr,offset,VOIDP_ALIGN);
+ break;
+ case 'D':
+ DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
+ break;
+ case 'F':
+ DLALIGN(data->ptr,offset,FLOAT_ALIGN);
+ break;
+ case 'C':
+ break;
+ case 'H':
+ DLALIGN(data->ptr,offset,SHORT_ALIGN);
+ break;
+ default:
+ rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
+ }
if (data->ids[i] == id) {
- switch (data->stype[i]) {
- case 'I':
- DLALIGN(data->ptr,offset,INT_ALIGN);
- break;
- case 'L':
- DLALIGN(data->ptr,offset,LONG_ALIGN);
- break;
- case 'P':
- case 'S':
- DLALIGN(data->ptr,offset,VOIDP_ALIGN);
- break;
- case 'D':
- DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
- break;
- case 'F':
- DLALIGN(data->ptr,offset,FLOAT_ALIGN);
- break;
- case 'C':
- break;
- case 'H':
- DLALIGN(data->ptr,offset,SHORT_ALIGN);
- break;
- default:
- rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
- }
memimg = ary2cary(data->stype[i], val, &memsize);
memcpy((char *)data->ptr + offset, memimg, memsize);
+ dlfree(memimg);
return val;
}
switch (data->stype[i]) {
@@ -981,6 +975,7 @@ rb_dlptr_aset(int argc, VALUE argv[], VALUE self)
}
memimg = ary2cary(data->stype[i], val, NULL);
memcpy(data->ptr, memimg, memsize);
+ dlfree(memimg);
}
}
return val;
@@ -1007,20 +1002,18 @@ rb_dlptr_size(int argc, VALUE argv[], VALUE self)
}
}
-static VALUE
-dlmem_each_i(VALUE assoc, void *data)
+static int
+dlmem_each_i(void* key, VALUE value, void* arg)
{
- VALUE key, val;
- key = rb_ary_entry(assoc, 0);
- val = rb_ary_entry(assoc, 1);
- rb_yield(rb_assoc_new(key,(VALUE)DLNUM2LONG(val)));
+ VALUE vkey = DLLONG2NUM(key);
+ rb_yield(rb_assoc_new(vkey, value));
return Qnil;
}
VALUE
rb_dlmem_each(VALUE self)
{
- rb_iterate(rb_each, DLMemoryTable, dlmem_each_i, 0);
+ st_foreach(st_memory_table, dlmem_each_i, 0);
return Qnil;
}
@@ -1059,7 +1052,7 @@ Init_dlptr()
rb_define_method(rb_cDLPtrData, "size=", rb_dlptr_size, -1);
rb_mDLMemorySpace = rb_define_module_under(rb_mDL, "MemorySpace");
- DLMemoryTable = rb_hash_new();
- rb_define_const(rb_mDLMemorySpace, "MemoryTable", DLMemoryTable);
+ st_memory_table = st_init_numtable();
+ rb_define_const(rb_mDLMemorySpace, "MemoryTable", Qnil); /* historical */
rb_define_module_function(rb_mDLMemorySpace, "each", rb_dlmem_each, 0);
}
diff --git a/ext/dl/sym.c b/ext/dl/sym.c
index 8044e6a4bb..933fb7f4f0 100644
--- a/ext/dl/sym.c
+++ b/ext/dl/sym.c
@@ -154,8 +154,9 @@ rb_dlsym_initialize(int argc, VALUE argv[], VALUE self)
rb_scan_args(argc, argv, "12", &addr, &name, &type);
saddr = (void*)(DLNUM2LONG(rb_Integer(addr)));
- sname = NIL_P(name) ? NULL : StringValuePtr(name);
+ if (!NIL_P(name)) StringValue(name);
stype = NIL_P(type) ? NULL : StringValuePtr(type);
+ sname = NIL_P(name) ? NULL : RSTRING(name)->ptr;
if( saddr ){
Data_Get_Struct(self, struct sym_data, data);
@@ -267,7 +268,7 @@ rb_dlsym_inspect(VALUE self)
str_size = RSTRING(proto)->len + 100;
str = dlmalloc(str_size);
snprintf(str, str_size - 1,
- "#<DL::Symbol:0x%p func=0x%p '%s'>",
+ "#<DL::Symbol:0x%lx func=0x%lx '%s'>",
sym, sym->func, RSTRING(proto)->ptr);
val = rb_tainted_str_new2(str);
dlfree(str);
@@ -362,7 +363,7 @@ __declspec(noinline)
static int
rb_dlsym_guardcall(char type, ANY_TYPE *ret, long *stack, void *func)
{
- volatile char *guard = ALLOCA_N(char, 1); /* guard stack pointer */
+ char *volatile guard = ALLOCA_N(char, 1); /* guard stack pointer */
switch(type){
case '0':
{
@@ -491,6 +492,7 @@ rb_dlsym_call(int argc, VALUE argv[], VALUE self)
rb_raise(rb_eDLTypeError, "unexpected type of argument #%d", i);
}
}
+ rb_check_safe_obj(pval);
Data_Get_Struct(pval, struct ptr_data, data);
ANY2P(args[i]) = DLVOIDP(data->ptr);
}
@@ -519,11 +521,11 @@ rb_dlsym_call(int argc, VALUE argv[], VALUE self)
PUSH_P(ftype);
break;
case 'H':
- ANY2H(args[i]) = DLSHORT(NUM2CHR(argv[i]));
+ ANY2H(args[i]) = DLSHORT(NUM2INT(argv[i]));
PUSH_C(ftype);
break;
case 'h':
- ANY2H(dargs[i]) = DLSHORT(NUM2CHR(argv[i]));
+ ANY2H(dargs[i]) = DLSHORT(NUM2INT(argv[i]));
ANY2P(args[i]) = DLVOIDP(&(ANY2H(dargs[i])));
dtypes[i] = 'h';
PUSH_P(ftype);
@@ -940,6 +942,7 @@ rb_dlsym_call(int argc, VALUE argv[], VALUE self)
}
}
+ FREE_ARGS;
#undef FREE_ARGS
return rb_assoc_new(val,dvals);
}
diff --git a/ext/dl/test/test.rb b/ext/dl/test/test.rb
index 52be04699f..bf8dfc18e3 100644
--- a/ext/dl/test/test.rb
+++ b/ext/dl/test/test.rb
@@ -273,7 +273,7 @@ assert("data_aref", :must,
GC.start
-ptr = DL::malloc(1024)
+ptr = DL::malloc(32)
ptr.struct!("CHIL", "c", "h", "i", "l")
ptr["c"] = 1
ptr["h"] = 2
@@ -291,5 +291,16 @@ ptr["n"] = 10
ptr["ptr"] = nil
assert("struct!", :must, ptr["n"] == 10 && ptr["ptr"] == nil)
+ptr = DL::malloc(16)
+ptr.struct!("CICI", "c1", "i1", "c2", "i2")
+ptr["c1"] = 0xf1
+ptr["c2"] = 0xf2
+c1 = [ptr["c1"]].pack("c").unpack("C")[0]
+c2 = [ptr["c2"]].pack("c").unpack("C")[0]
+assert("struct!", :must,
+ c1 == 0xf1 &&
+ c2 == 0xf2)
+
+
GC.start
printf("fail/total = #{$FAIL}/#{$TOTAL}\n")
diff --git a/ext/enumerator/.cvsignore b/ext/enumerator/.cvsignore
deleted file mode 100644
index fc802ff1c2..0000000000
--- a/ext/enumerator/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-mkmf.log
diff --git a/ext/enumerator/MANIFEST b/ext/enumerator/MANIFEST
deleted file mode 100644
index b1ab0ba8e2..0000000000
--- a/ext/enumerator/MANIFEST
+++ /dev/null
@@ -1,3 +0,0 @@
-MANIFEST
-enumerator.c
-enumerator.txt
diff --git a/ext/enumerator/enumerator.c b/ext/enumerator/enumerator.c
deleted file mode 100644
index 8c3c566178..0000000000
--- a/ext/enumerator/enumerator.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/************************************************
-
- enumerator.c - provides Enumerator class
-
- $Author$
-
- Copyright (C) 2001-2003 Akinori MUSHA
-
- $Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
- $RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
- $Id$
-
-************************************************/
-
-#include "ruby.h"
-#include "node.h"
-
-static VALUE rb_cEnumerator;
-static ID sym_each, sym_each_with_index, sym_each_slice, sym_each_cons;
-static ID id_new, id_enum_obj, id_enum_method, id_enum_args;
-
-static VALUE
-obj_to_enum(obj, enum_args)
- VALUE obj, enum_args;
-{
- rb_ary_unshift(enum_args, obj);
-
- return rb_apply(rb_cEnumerator, id_new, enum_args);
-}
-
-static VALUE
-enumerator_enum_with_index(obj)
- VALUE obj;
-{
- return rb_funcall(rb_cEnumerator, id_new, 2, obj, sym_each_with_index);
-}
-
-static VALUE
-each_slice_i(val, memo)
- VALUE val;
- NODE *memo;
-{
- VALUE ary = memo->u1.value;
- long size = memo->u3.cnt;
-
- rb_ary_push(ary, val);
-
- if (RARRAY(ary)->len == size) {
- rb_yield(ary);
- memo->u1.value = rb_ary_new2(size);
- }
-
- return Qnil;
-}
-
-static VALUE
-enum_each_slice(obj, n)
- VALUE obj, n;
-{
- long size = NUM2LONG(n);
- NODE *memo;
- VALUE ary;
-
- if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
-
- memo = rb_node_newnode(NODE_MEMO, rb_ary_new2(size), 0, size);
-
- rb_iterate(rb_each, obj, each_slice_i, (VALUE)memo);
-
- ary = memo->u1.value;
- if (RARRAY(ary)->len > 0) rb_yield(ary);
-
- rb_gc_force_recycle((VALUE)memo);
- return Qnil;
-}
-
-static VALUE
-enumerator_enum_slice(obj, n)
- VALUE obj, n;
-{
- return rb_funcall(rb_cEnumerator, id_new, 3, obj, sym_each_slice, n);
-}
-
-static VALUE
-each_cons_i(val, memo)
- VALUE val;
- NODE *memo;
-{
- VALUE ary = memo->u1.value;
- long size = memo->u3.cnt;
- long len = RARRAY(ary)->len;
-
- if (len == size) {
- rb_ary_shift(ary);
- rb_ary_push(ary, val);
- rb_yield(ary);
- } else {
- rb_ary_push(ary, val);
- if (len + 1 == size) rb_yield(ary);
- }
- return Qnil;
-}
-
-static VALUE
-enum_each_cons(obj, n)
- VALUE obj, n;
-{
- long size = NUM2LONG(n);
- NODE *memo;
- VALUE ary;
-
- if (size <= 0) rb_raise(rb_eArgError, "invalid size");
- memo = rb_node_newnode(NODE_MEMO, rb_ary_new2(size), 0, size);
-
- rb_iterate(rb_each, obj, each_cons_i, (VALUE)memo);
-
- rb_gc_force_recycle((VALUE)memo);
- return Qnil;
-}
-
-static VALUE
-enumerator_enum_cons(obj, n)
- VALUE obj, n;
-{
- return rb_funcall(rb_cEnumerator, id_new, 3, obj, sym_each_cons, n);
-}
-
-static VALUE
-enumerator_initialize(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE enum_obj, enum_method, enum_args;
-
- rb_scan_args(argc, argv, "11*", &enum_obj, &enum_method, &enum_args);
-
- if (enum_method == Qnil)
- enum_method = sym_each;
-
- rb_ivar_set(obj, id_enum_obj, enum_obj);
- rb_ivar_set(obj, id_enum_method, enum_method);
- rb_ivar_set(obj, id_enum_args, enum_args);
-
- return Qnil;
-}
-
-static VALUE
-enumerator_iter(memo)
- NODE *memo;
-{
- return rb_apply(memo->u1.value, memo->u2.id, memo->u3.value);
-}
-
-static VALUE
-enumerator_each(obj)
- VALUE obj;
-{
- VALUE val;
-
- obj = (VALUE)rb_node_newnode(NODE_MEMO,
- rb_ivar_get(obj, id_enum_obj),
- rb_to_id(rb_ivar_get(obj, id_enum_method)),
- rb_ivar_get(obj, id_enum_args));
- val = rb_iterate((VALUE (*)_((VALUE)))enumerator_iter, obj, rb_yield, 0);
- rb_gc_force_recycle(obj);
- return val;
-}
-
-void
-Init_enumerator()
-{
- VALUE rb_mEnumerable;
-
- rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -2);
- rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -2);
-
- rb_mEnumerable = rb_path2class("Enumerable");
-
- rb_define_method(rb_mEnumerable, "enum_with_index", enumerator_enum_with_index, 0);
- rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
- rb_define_method(rb_mEnumerable, "enum_slice", enumerator_enum_slice, 1);
- rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
- rb_define_method(rb_mEnumerable, "enum_cons", enumerator_enum_cons, 1);
-
- rb_cEnumerator = rb_define_class_under(rb_mEnumerable, "Enumerator", rb_cObject);
- rb_include_module(rb_cEnumerator, rb_mEnumerable);
-
- rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
- rb_define_method(rb_cEnumerator, "each", enumerator_each, 0);
-
- sym_each = ID2SYM(rb_intern("each"));
- sym_each_with_index = ID2SYM(rb_intern("each_with_index"));
- sym_each_slice = ID2SYM(rb_intern("each_slice"));
- sym_each_cons = ID2SYM(rb_intern("each_cons"));
-
- id_new = rb_intern("new");
- id_enum_obj = rb_intern("enum_obj");
- id_enum_method = rb_intern("enum_method");
- id_enum_args = rb_intern("enum_args");
-}
diff --git a/ext/enumerator/enumerator.txt b/ext/enumerator/enumerator.txt
deleted file mode 100644
index 64c7d50226..0000000000
--- a/ext/enumerator/enumerator.txt
+++ /dev/null
@@ -1,102 +0,0 @@
-.\" enumerator.txt - -*- Indented-Text -*-
-$Idaemons: /home/cvs/rb/enumerator/enumerator.txt,v 1.2 2001/07/15 10:19:24 knu Exp $
-$RoughId: enumerator.txt,v 1.5 2003/02/20 12:24:51 knu Exp $
-$Id$
-
-** Enumerable::Enumerator(Class)
-
-A class which provides a method `each' to be used as an Enumerable
-object.
-
-Superclass: Object
-
-Mix-ins: Enumerable
-
-require 'enumerator'
-
-Class Methods:
-
- new(obj, method = :each, *args)
-
- Creates a new Enumerable::Enumerator object, which is to be
- used as an Enumerable object using the given object's given
- method with the given arguments.
-
- e.g.:
- str = "xyz"
-
- enum = Enumerable::Enumerator.new(str, :each_byte)
- a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
-
-Methods:
-
- each {...}
-
- Iterates the given block using the object and the method
- specified in the first place.
-
-
-Requiring this module also adds some methods to the Object class:
-
- to_enum(method = :each, *args)
- enum_for(method = :each, *args)
-
- Returns Enumerable::Enumerator.new(self, method, *args).
-
- e.g.:
- str = "xyz"
-
- enum = str.enum_for(:each_byte)
- a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
-
- # protects an array from being modified
- a = [1, 2, 3]
- some_method(a.to_enum)
-
-And the Enumerable module.
-
- each_slice(n) {...}
-
- Iterates the given block for each slice of <n> elements.
-
- e.g.:
- (1..10).each_slice(3) {|a| p a}
- # outputs below
- [1, 2, 3]
- [4, 5, 6]
- [7, 8, 9]
- [10]
-
- enum_slice(n)
-
- Returns Enumerable::Enumerator.new(self, :each_slice, n).
-
- each_cons(n) {...}
-
- Iterates the given block for each array of consecutive <n>
- elements.
-
- e.g.:
- (1..10).each_cons(3) {|a| p a}
- # outputs below
- [1, 2, 3]
- [2, 3, 4]
- [3, 4, 5]
- [4, 5, 6]
- [5, 6, 7]
- [6, 7, 8]
- [7, 8, 9]
- [8, 9, 10]
-
- enum_cons(n)
-
- Returns Enumerable::Enumerator.new(self, :each_cons, n).
-
- enum_with_index
-
- Returns Enumerable::Enumerator.new(self, :each_with_index).
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/etc/MANIFEST b/ext/etc/MANIFEST
deleted file mode 100644
index 62cf5be233..0000000000
--- a/ext/etc/MANIFEST
+++ /dev/null
@@ -1,6 +0,0 @@
-MANIFEST
-etc.c
-etc.txt
-etc.txt.ja
-depend
-extconf.rb
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index c42f279d58..ecb9e16411 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -23,6 +23,10 @@
#include <grp.h>
#endif
+#ifndef HAVE_TYPE_UID_T
+#define uid_t int
+#endif
+
static VALUE sPasswd, sGroup;
#ifndef _WIN32
@@ -30,6 +34,13 @@ char *getenv();
#endif
char *getlogin();
+/* Returns the short user name of the currently logged in user.
+ * Unfortunately, it is often rather easy to fool getlogin().
+ * Avoid getlogin() for security-related purposes.
+ *
+ * e.g.
+ * Etc.getlogin -> 'guest'
+ */
static VALUE
etc_getlogin(obj)
VALUE obj;
@@ -70,21 +81,21 @@ setup_passwd(pwd)
#ifdef HAVE_ST_PW_PASSWD
safe_setup_str(pwd->pw_passwd),
#endif
- INT2FIX(pwd->pw_uid),
- INT2FIX(pwd->pw_gid),
+ PW_UID2VAL(pwd->pw_uid),
+ PW_GID2VAL(pwd->pw_gid),
#ifdef HAVE_ST_PW_GECOS
safe_setup_str(pwd->pw_gecos),
#endif
safe_setup_str(pwd->pw_dir),
safe_setup_str(pwd->pw_shell),
#ifdef HAVE_ST_PW_CHANGE
- INT2FIX(pwd->pw_change),
+ INT2NUM(pwd->pw_change),
#endif
#ifdef HAVE_ST_PW_QUOTA
- INT2FIX(pwd->pw_quota),
+ INT2NUM(pwd->pw_quota),
#endif
#ifdef HAVE_ST_PW_AGE
- INT2FIX(pwd->pw_age),
+ PW_AGE2VAL(pwd->pw_age),
#endif
#ifdef HAVE_ST_PW_CLASS
safe_setup_str(pwd->pw_class),
@@ -93,13 +104,22 @@ setup_passwd(pwd)
safe_setup_str(pwd->pw_comment),
#endif
#ifdef HAVE_ST_PW_EXPIRE
- INT2FIX(pwd->pw_expire),
+ INT2NUM(pwd->pw_expire),
#endif
0 /*dummy*/
);
}
#endif
+/* Returns the /etc/passwd information for the user with specified integer
+ * user id (uid).
+ *
+ * The information is returned as a Struct::Passwd; see getpwent above for
+ * details.
+ *
+ * e.g. * Etc.getpwuid(0) -> #<struct Struct::Passwd name="root",
+ * passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
+ */
static VALUE
etc_getpwuid(argc, argv, obj)
int argc;
@@ -108,12 +128,12 @@ etc_getpwuid(argc, argv, obj)
{
#if defined(HAVE_GETPWENT)
VALUE id;
- int uid;
+ uid_t uid;
struct passwd *pwd;
rb_secure(4);
if (rb_scan_args(argc, argv, "01", &id) == 1) {
- uid = NUM2INT(id);
+ uid = PW_VAL2UID(id);
}
else {
uid = getuid();
@@ -126,6 +146,14 @@ etc_getpwuid(argc, argv, obj)
#endif
}
+/* Returns the /etc/passwd information for the user with specified login name.
+ *
+ * The information is returned as a Struct::Passwd; see getpwent above for
+ * details.
+ *
+ * e.g. * Etc.getpwnam('root') -> #<struct Struct::Passwd name="root",
+ * passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
+ */
static VALUE
etc_getpwnam(obj, nam)
VALUE obj, nam;
@@ -165,6 +193,21 @@ passwd_iterate()
}
#endif
+/* Provides a convenient Ruby iterator which executes a block for each entry
+ * in the /etc/passwd file.
+ *
+ * The code block is passed an Etc::Passwd struct; see getpwent above for
+ * details.
+ *
+ * Example:
+ *
+ * require 'etc'
+ *
+ * Etc.passwd {|u|
+ * puts u.name + " = " + u.gecos
+ * }
+ *
+ */
static VALUE
etc_passwd(obj)
VALUE obj;
@@ -187,6 +230,9 @@ etc_passwd(obj)
return Qnil;
}
+/* Resets the process of reading the /etc/passwd file, so that the next call
+ * to getpwent will return the first entry again.
+ */
static VALUE
etc_setpwent(obj)
VALUE obj;
@@ -197,6 +243,9 @@ etc_setpwent(obj)
return Qnil;
}
+/* Ends the process of scanning through the /etc/passwd file begun with
+ * getpwent, and closes the file.
+ */
static VALUE
etc_endpwent(obj)
VALUE obj;
@@ -207,6 +256,32 @@ etc_endpwent(obj)
return Qnil;
}
+/* Returns an entry from the /etc/passwd file. The first time it is called it
+ * opens the file and returns the first entry; each successive call returns
+ * the next entry, or nil if the end of the file has been reached.
+ *
+ * To close the file when processing is complete, call endpwent.
+ *
+ * Each entry is returned as a Struct::Passwd:
+ *
+ * - Passwd#name contains the short login name of the user as a String.
+ *
+ * - Passwd#passwd contains the encrypted password of the user as a String.
+ * an 'x' is returned if shadow passwords are in use. An '*' is returned
+ * if the user cannot log in using a password.
+ *
+ * - Passwd#uid contains the integer user ID (uid) of the user.
+ *
+ * - Passwd#gid contains the integer group ID (gid) of the user's primary group.
+ *
+ * - Passwd#gecos contains a longer String description of the user, such as
+ * a full name. Some Unix systems provide structured information in the
+ * gecos field, but this is system-dependent.
+ *
+ * - Passwd#dir contains the path to the home directory of the user as a String.
+ *
+ * - Passwd#shell contains the path to the login shell of the user as a String.
+ */
static VALUE
etc_getpwent(obj)
VALUE obj;
@@ -240,21 +315,31 @@ setup_group(grp)
#ifdef HAVE_ST_GR_PASSWD
safe_setup_str(grp->gr_passwd),
#endif
- INT2FIX(grp->gr_gid),
+ PW_GID2VAL(grp->gr_gid),
mem);
}
#endif
+/* Returns information about the group with specified integer group id (gid),
+ * as found in /etc/group.
+ *
+ * The information is returned as a Struct::Group; see getgrent above for
+ * details.
+ *
+ * e.g. Etc.getgrgid(100) -> #<struct Struct::Group name="users", passwd="x",
+ * gid=100, mem=["meta", "root"]>
+ *
+ */
static VALUE
etc_getgrgid(obj, id)
VALUE obj, id;
{
#ifdef HAVE_GETGRENT
- int gid;
+ gid_t gid;
struct group *grp;
rb_secure(4);
- gid = NUM2INT(id);
+ gid = PW_VAL2GID(id);
grp = getgrgid(gid);
if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", gid);
return setup_group(grp);
@@ -263,6 +348,16 @@ etc_getgrgid(obj, id)
#endif
}
+/* Returns information about the group with specified String name, as found
+ * in /etc/group.
+ *
+ * The information is returned as a Struct::Group; see getgrent above for
+ * details.
+ *
+ * e.g. Etc.getgrnam('users') -> #<struct Struct::Group name="users",
+ * passwd="x", gid=100, mem=["meta", "root"]>
+ *
+ */
static VALUE
etc_getgrnam(obj, nam)
VALUE obj, nam;
@@ -303,6 +398,21 @@ group_iterate()
}
#endif
+/* Provides a convenient Ruby iterator which executes a block for each entry
+ * in the /etc/group file.
+ *
+ * The code block is passed an Etc::Group struct; see getgrent above for
+ * details.
+ *
+ * Example:
+ *
+ * require 'etc'
+ *
+ * Etc.group {|g|
+ * puts g.name + ": " + g.mem.join(', ')
+ * }
+ *
+ */
static VALUE
etc_group(obj)
VALUE obj;
@@ -325,6 +435,9 @@ etc_group(obj)
return Qnil;
}
+/* Resets the process of reading the /etc/group file, so that the next call
+ * to getgrent will return the first entry again.
+ */
static VALUE
etc_setgrent(obj)
VALUE obj;
@@ -335,6 +448,9 @@ etc_setgrent(obj)
return Qnil;
}
+/* Ends the process of scanning through the /etc/group file begun by
+ * getgrent, and closes the file.
+ */
static VALUE
etc_endgrent(obj)
VALUE obj;
@@ -345,6 +461,26 @@ etc_endgrent(obj)
return Qnil;
}
+/* Returns an entry from the /etc/group file. The first time it is called it
+ * opens the file and returns the first entry; each successive call returns
+ * the next entry, or nil if the end of the file has been reached.
+ *
+ * To close the file when processing is complete, call endgrent.
+ *
+ * Each entry is returned as a Struct::Group:
+ *
+ * - Group#name contains the name of the group as a String.
+ *
+ * - Group#passwd contains the encrypted password as a String. An 'x' is
+ * returned if password access to the group is not available; an empty
+ * string is returned if no password is needed to obtain membership of
+ * the group.
+ *
+ * - Group#gid contains the group's numeric ID as an integer.
+ *
+ * - Group#mem is an Array of Strings containing the short login names of the
+ * members of the group.
+ */
static VALUE
etc_getgrent(obj)
VALUE obj;
@@ -361,6 +497,11 @@ etc_getgrent(obj)
static VALUE mEtc;
+/* The etc module provides access to information from the /etc/passwd and
+ * /etc/group files on Linux and Unix systems.
+ *
+ * Documented by mathew <meta@pobox.com>.
+ */
void
Init_etc()
{
@@ -382,6 +523,7 @@ Init_etc()
rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
+ rb_global_variable(&sPasswd);
sPasswd = rb_struct_define("Passwd",
"name", "passwd", "uid", "gid",
#ifdef HAVE_ST_PW_GECOS
@@ -407,10 +549,13 @@ Init_etc()
"expire",
#endif
NULL);
- rb_global_variable(&sPasswd);
#ifdef HAVE_GETGRENT
- sGroup = rb_struct_define("Group", "name", "passwd", "gid", "mem", NULL);
rb_global_variable(&sGroup);
+ sGroup = rb_struct_define("Group", "name",
+#ifdef HAVE_ST_GR_PASSWD
+ "passwd",
+#endif
+ "gid", "mem", NULL);
#endif
}
diff --git a/ext/etc/extconf.rb b/ext/etc/extconf.rb
index 16f2da352b..dbd0672545 100644
--- a/ext/etc/extconf.rb
+++ b/ext/etc/extconf.rb
@@ -8,11 +8,36 @@ if a or b or c
have_struct_member('struct passwd', 'pw_gecos', 'pwd.h')
have_struct_member('struct passwd', 'pw_change', 'pwd.h')
have_struct_member('struct passwd', 'pw_quota', 'pwd.h')
- have_struct_member('struct passwd', 'pw_age', 'pwd.h')
+ if have_struct_member('struct passwd', 'pw_age', 'pwd.h')
+ case what_type?('struct passwd', 'pw_age', 'pwd.h')
+ when "string"
+ f = "safe_setup_str"
+ when "long long"
+ f = "LL2NUM"
+ else
+ f = "INT2NUM"
+ end
+ $defs.push("-DPW_AGE2VAL="+f)
+ end
have_struct_member('struct passwd', 'pw_class', 'pwd.h')
have_struct_member('struct passwd', 'pw_comment', 'pwd.h') unless /cygwin/ === RUBY_PLATFORM
have_struct_member('struct passwd', 'pw_expire', 'pwd.h')
have_struct_member('struct passwd', 'pw_passwd', 'pwd.h')
have_struct_member('struct group', 'gr_passwd', 'grp.h')
+ [%w"uid_t pwd.h", %w"gid_t grp.h"].each do |t, *h|
+ h.unshift("sys/types.h")
+ f = "INT2NUM"
+ if have_type(t, h)
+ if try_static_assert("sizeof(#{t}) > sizeof(long)", h)
+ f = "LL2NUM"
+ end
+ if try_static_assert("(#{t})-1 > 0", h)
+ f = "U#{f}"
+ end
+ end
+ t = t.chomp('_t').upcase
+ $defs.push("-DPW_#{t}2VAL=#{f}")
+ $defs.push("-DPW_VAL2#{t}=#{f.sub(/([A-Z]+)2(NUM)/, '\22\1')}")
+ end
create_makefile("etc")
end
diff --git a/ext/extmk.rb b/ext/extmk.rb
index fe777a4ceb..2527645ad8 100644
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -1,13 +1,19 @@
#! /usr/local/bin/ruby
# -*- ruby -*-
+$extension = nil
+$extstatic = nil
$force_static = nil
$install = nil
$destdir = nil
+$dryrun = false
$clean = nil
$nodynamic = nil
$extinit = nil
$extobjs = nil
+$extflags = ""
+$extlibs = nil
+$extpath = nil
$ignore = nil
$message = nil
@@ -16,26 +22,76 @@ alias $PROGRAM_NAME $0
alias $0 $progname
$extlist = []
+$compiled = {}
-$:.replace ["."]
+$:.replace([Dir.pwd])
require 'rbconfig'
-srcdir = Config::CONFIG["srcdir"]
+srcdir = File.dirname(File.dirname(__FILE__))
-$:.replace [srcdir, srcdir+"/lib", "."]
+$:.unshift(srcdir, File.expand_path("lib", srcdir))
-require 'mkmf'
-require 'getopts'
-
-$topdir = File.expand_path(".")
+$topdir = "."
$top_srcdir = srcdir
-$hdrdir = $top_srcdir
+
+require 'mkmf'
+require 'optparse/shellwords'
def sysquote(x)
@quote ||= /human|os2|macos/ =~ (CROSS_COMPILING || RUBY_PLATFORM)
@quote ? x.quote : x
end
+def relative_from(path, base)
+ dir = File.join(path, "")
+ if File.expand_path(dir) == File.expand_path(dir, base)
+ path
+ else
+ File.join(base, path)
+ end
+end
+
+def extract_makefile(makefile, keep = true)
+ m = File.read(makefile)
+ if !(target = m[/^TARGET[ \t]*=[ \t]*(\S*)/, 1])
+ return keep
+ end
+ installrb = {}
+ m.scan(/^install-rb-default:[ \t]*(\S+)\n\1:[ \t]*(\S+)/) {installrb[$2] = $1}
+ oldrb = installrb.keys.sort
+ newrb = install_rb(nil, "").collect {|d, *f| f}.flatten.sort
+ if target_prefix = m[/^target_prefix[ \t]*=[ \t]*\/(.*)/, 1]
+ target = "#{target_prefix}/#{target}"
+ end
+ unless oldrb == newrb
+ if $extout
+ newrb.each {|f| installrb.delete(f)}
+ unless installrb.empty?
+ config = CONFIG.dup
+ install_dirs(target_prefix).each {|var, val| config[var] = val}
+ FileUtils.rm_f(installrb.values.collect {|f| Config.expand(f, config)}, :verbose => true)
+ end
+ end
+ return false
+ end
+ $target = target
+ $extconf_h = m[/^RUBY_EXTCONF_H[ \t]*=[ \t]*(\S+)/, 1]
+ $static ||= m[/^EXTSTATIC[ \t]*=[ \t]*(\S+)/, 1] || false
+ /^STATIC_LIB[ \t]*=[ \t]*\S+/ =~ m or $static = nil
+ $preload = Shellwords.shellwords(m[/^preload[ \t]*=[ \t]*(.*)/, 1] || "")
+ $DLDFLAGS += " " + (m[/^dldflags[ \t]*=[ \t]*(.*)/, 1] || "")
+ if s = m[/^LIBS[ \t]*=[ \t]*(.*)/, 1]
+ s.sub!(/^#{Regexp.quote($LIBRUBYARG)} */, "")
+ s.sub!(/ *#{Regexp.quote($LIBS)}$/, "")
+ $libs = s
+ end
+ $objs = (m[/^OBJS[ \t]*=[ \t](.*)/, 1] || "").split
+ $srcs = (m[/^SRCS[ \t]*=[ \t](.*)/, 1] || "").split
+ $LOCAL_LIBS = m[/^LOCAL_LIBS[ \t]*=[ \t]*(.*)/, 1] || ""
+ $LIBPATH = Shellwords.shellwords(m[/^libpath[ \t]*=[ \t]*(.*)/, 1] || "") - %w[$(libdir) $(topdir)]
+ true
+end
+
def extmake(target)
print "#{$message} #{target}\n"
$stdout.flush
@@ -49,96 +105,203 @@ def extmake(target)
return true if $nodynamic and not $static
end
- init_mkmf
-
+ FileUtils.mkpath target unless File.directory?(target)
begin
dir = Dir.pwd
FileUtils.mkpath target unless File.directory?(target)
Dir.chdir target
+ top_srcdir = $top_srcdir
+ topdir = $topdir
+ hdrdir = $hdrdir
+ prefix = "../" * (target.count("/")+1)
+ $top_srcdir = relative_from(top_srcdir, prefix)
+ $hdrdir = relative_from(hdrdir, prefix)
+ $topdir = prefix + $topdir
$target = target
$mdir = target
$srcdir = File.join($top_srcdir, "ext", $mdir)
$preload = nil
+ $objs = ""
+ $srcs = ""
+ $compiled[target] = false
makefile = "./Makefile"
+ ok = File.exist?(makefile)
unless $ignore
- if $static ||
- !(t = modified?(makefile, MTIMES)) ||
- %W<#{$srcdir}/makefile.rb #{$srcdir}/extconf.rb
- #{$srcdir}/depend #{$srcdir}/MANIFEST>.any? {|f| modified?(f, [t])}
- then
- $defs = []
- Logging::logfile 'mkmf.log'
- Config::CONFIG["srcdir"] = $srcdir
- rm_f makefile
- begin
- if File.exist?($0 = "#{$srcdir}/makefile.rb")
- load $0
- elsif File.exist?($0 = "#{$srcdir}/extconf.rb")
- load $0
+ rbconfig0 = Config::CONFIG
+ mkconfig0 = CONFIG
+ rbconfig = {
+ "hdrdir" => $hdrdir,
+ "srcdir" => $srcdir,
+ "topdir" => $topdir,
+ }
+ mkconfig = {
+ "hdrdir" => "$(top_srcdir)",
+ "srcdir" => "$(top_srcdir)/ext/#{$mdir}",
+ "topdir" => $topdir,
+ }
+ rbconfig0.each_pair {|key, val| rbconfig[key] ||= val.dup}
+ mkconfig0.each_pair {|key, val| mkconfig[key] ||= val.dup}
+ Config.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig)
+ }
+ Object.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig)
+ }
+ begin
+ $extconf_h = nil
+ ok &&= extract_makefile(makefile)
+ conf = ["#{$srcdir}/makefile.rb", "#{$srcdir}/extconf.rb"].find {|f| File.exist?(f)}
+ if (($extconf_h && !File.exist?($extconf_h)) ||
+ !(t = modified?(makefile, MTIMES)) ||
+ [conf, "#{$srcdir}/depend"].any? {|f| modified?(f, [t])})
+ then
+ ok = false
+ init_mkmf
+ Logging::logfile 'mkmf.log'
+ rm_f makefile
+ if conf
+ load $0 = conf
else
create_makefile(target)
end
- File.exist?(makefile)
- rescue SystemExit
- # ignore
- ensure
- rm_f "conftest*"
- $0 = $PROGRAM_NAME
- Config::CONFIG["srcdir"] = $top_srcdir
+ $defs << "-DRUBY_EXPORT" if $static
+ ok = File.exist?(makefile)
end
- else
- true
+ rescue SystemExit
+ # ignore
+ ensure
+ rm_f "conftest*"
+ config = $0
+ $0 = $PROGRAM_NAME
+ end
+ end
+ ok = yield(ok) if block_given?
+ unless ok
+ open(makefile, "w") do |f|
+ f.print dummy_makefile(CONFIG["srcdir"])
end
- else
- File.exist?(makefile)
- end or open(makefile, "w") do |f|
- f.print dummy_makefile($srcdir)
return true
end
args = sysquote($mflags)
+ unless $destdir.to_s.empty? or $mflags.include?("DESTDIR")
+ args += [sysquote("DESTDIR=" + relative_from($destdir, "../"+prefix))]
+ end
if $static
- args += ["static"]
+ args += ["static"] unless $clean
$extlist.push [$static, $target, File.basename($target), $preload]
end
unless system($make, *args)
$ignore or $continue or return false
end
+ $compiled[target] = true
+ if $clean
+ FileUtils.rm_f("mkmf.log")
+ if $clean != true
+ FileUtils.rm_f([makefile, $extconf_h || "extconf.h"])
+ end
+ File.unlink(makefile) rescue nil
+ end
if $static
$extflags ||= ""
$extlibs ||= []
$extpath ||= []
- $extflags += " " + $DLDFLAGS unless $DLDFLAGS.empty?
- $extflags += " " + $LDFLAGS unless $LDFLAGS.empty?
- $extlibs |= $libs.split | $LOCAL_LIBS.split
+ unless $mswin
+ $extflags = ($extflags.split | $DLDFLAGS.split | $LDFLAGS.split).join(" ")
+ end
+ $extlibs = merge_libs($extlibs, $libs.split, $LOCAL_LIBS.split)
$extpath |= $LIBPATH
end
ensure
+ unless $ignore
+ Config.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig0)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig0)
+ }
+ Object.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig0)
+ }
+ end
+ $top_srcdir = top_srcdir
+ $topdir = topdir
+ $hdrdir = hdrdir
Dir.chdir dir
end
+ begin
+ Dir.rmdir target
+ target = File.dirname(target)
+ rescue SystemCallError
+ break
+ end while true
true
end
+def compiled?(target)
+ $compiled[target]
+end
+
def parse_args()
- getopts('n', 'extstatic:', 'dest-dir:',
- 'make:', 'make-flags:', 'mflags:')
-
- $dryrun = $OPT['n']
- $force_static = $OPT['extstatic'] == 'static'
- $destdir = $OPT['dest-dir'] || ''
- $make = $OPT['make'] || $make || 'make'
- mflags = ($OPT['make-flags'] || '').strip
- mflags = ($OPT['mflags'] || '').strip if mflags.empty?
-
- $mflags = Shellwords.shellwords(mflags)
- if arg = $mflags.first
- arg.insert(0, '-') if /\A[^-][^=]*\Z/ =~ arg
+ $mflags = []
+
+ opts = nil
+ $optparser ||= OptionParser.new do |opts|
+ opts.on('-n') {$dryrun = true}
+ opts.on('--[no-]extension [EXTS]', Array) do |v|
+ $extension = (v == false ? [] : v)
+ end
+ opts.on('--[no-]extstatic [STATIC]', Array) do |v|
+ if ($extstatic = v) == false
+ $extstatic = []
+ elsif v
+ $force_static = true if $extstatic.delete("static")
+ $extstatic = nil if $extstatic.empty?
+ end
+ end
+ opts.on('--dest-dir=DIR') do |v|
+ $destdir = v
+ end
+ opts.on('--extout=DIR') do |v|
+ $extout = (v unless v.empty?)
+ end
+ opts.on('--make=MAKE') do |v|
+ $make = v || 'make'
+ end
+ opts.on('--make-flags=FLAGS', '--mflags', Shellwords) do |v|
+ v.grep(/\A([-\w]+)=(.*)/) {$configure_args["--#{$1}"] = $2}
+ if arg = v.first
+ arg.insert(0, '-') if /\A[^-][^=]*\Z/ =~ arg
+ end
+ $mflags.concat(v)
+ end
+ opts.on('--message [MESSAGE]', String) do |v|
+ $message = v
+ end
end
+ begin
+ $optparser.parse!(ARGV)
+ rescue OptionParser::InvalidOption => e
+ retry if /^--/ =~ e.args[0]
+ $optparser.warn(e)
+ abort opts.to_s
+ end
+
+ $destdir ||= ''
$make, *rest = Shellwords.shellwords($make)
$mflags.unshift(*rest) unless rest.empty?
def $mflags.set?(flag)
- grep(/\A-(?!-).*#{'%c' % flag}/i) { return true }
+ grep(/\A-(?!-).*#{flag.chr}/i) { return true }
+ false
+ end
+ def $mflags.defined?(var)
+ grep(/\A#{var}=(.*)/) {return $1}
false
end
@@ -149,25 +312,34 @@ def parse_args()
end
$continue = $mflags.set?(?k)
- $mflags |= ["DESTDIR=#{$destdir}"]
+ if $extout
+ $extout = '$(topdir)/'+$extout
+ Config::CONFIG["extout"] = CONFIG["extout"] = $extout
+ $extout_prefix = $extout ? "$(extout)$(target_prefix)/" : ""
+ $mflags << "extout=#$extout" << "extout_prefix=#$extout_prefix"
+ end
end
parse_args()
+if target = ARGV.shift and /^[a-z-]+$/ =~ target
+ $mflags.push(target)
+ case target
+ when /^(dist|real)?(clean)$/
+ target = $2
+ $ignore ||= true
+ $clean = $1 ? $1[0] : true
+ when /^install\b/
+ $install = true
+ $ignore ||= true
+ $mflags.unshift("INSTALL_PROG=install -c -p -m 0755",
+ "INSTALL_DATA=install -c -p -m 0644",
+ "MAKEDIRS=mkdir -p") if $dryrun
+ end
+end
unless $message
- if $message = ARGV.shift and /^[a-z]+$/ =~ $message
- $mflags.push($message)
- $message = $message.sub(/^(?:dist|real)(?=(?:clean)?$)/, '\1')
- case $message
- when "clean"
- $ignore ||= true
- when "install"
- $ignore ||= true
- $mflags.unshift("INSTALL_PROG=install -c -p -m 0755",
- "INSTALL_DATA=install -c -p -m 0644",
- "MAKEDIRS=mkdir -p") if $dryrun
- end
- $message.sub!(/e?$/, "ing")
+ if target
+ $message = target.sub(/^(\w+)e?\b/, '\1ing').tr('-', ' ')
else
$message = "compiling"
end
@@ -176,22 +348,36 @@ end
EXEEXT = CONFIG['EXEEXT']
if CROSS_COMPILING
$ruby = CONFIG['MINIRUBY']
-elsif $nmake
- $ruby = '$(topdir:/=\\)\\miniruby' + EXEEXT
+elsif sep = config_string('BUILD_FILE_SEPARATOR')
+ $ruby = "$(topdir:/=#{sep})#{sep}miniruby" + EXEEXT
else
$ruby = '$(topdir)/miniruby' + EXEEXT
end
-$ruby << " -I$(topdir) -I$(hdrdir)/lib"
+$ruby << " -I'$(topdir)'"
+unless CROSS_COMPILING
+ $ruby << " -I'$(top_srcdir)/lib'"
+ $ruby << " -I'$(extout)/$(arch)' -I'$(extout)/common'" if $extout
+ $ruby << " -I./- -I'$(top_srcdir)/ext' -rpurelib.rb"
+ ENV["RUBYLIB"] = "-"
+ ENV["RUBYOPT"] = "-rpurelib.rb"
+end
$config_h = '$(topdir)/config.h'
+$mflags << "ruby=#$ruby"
-MTIMES = [__FILE__, srcdir+'/lib/mkmf.rb'].collect {|f| File.mtime(f)}
+MTIMES = [__FILE__, 'rbconfig.rb', srcdir+'/lib/mkmf.rb'].collect {|f| File.mtime(f)}
# get static-link modules
$static_ext = {}
+if $extstatic
+ $extstatic.each do |target|
+ target = target.downcase if /mswin32|bccwin32/ =~ RUBY_PLATFORM
+ $static_ext[target] = $static_ext.size
+ end
+end
for dir in ["ext", File::join($top_srcdir, "ext")]
setup = File::join(dir, CONFIG['setup'])
if File.file? setup
- f = open(setup)
+ f = open(setup)
while line = f.gets()
line.chomp!
line.sub!(/#.*$/, '')
@@ -205,64 +391,135 @@ for dir in ["ext", File::join($top_srcdir, "ext")]
next
end
target = target.downcase if /mswin32|bccwin32/ =~ RUBY_PLATFORM
- $static_ext[target] = true
+ $static_ext[target] = $static_ext.size
end
MTIMES << f.mtime
$setup = setup
f.close
break
end
+end unless $extstatic
+
+ext_prefix = "#{$top_srcdir}/ext"
+exts = $static_ext.sort_by {|t, i| i}.collect {|t, i| t}
+if $extension
+ exts |= $extension.select {|d| File.directory?("#{ext_prefix}/#{d}")}
+else
+ withes, withouts = %w[--with --without].collect {|w|
+ if not (w = %w[-extensions -ext].collect {|opt|arg_config(w+opt)}).any?
+ proc {false}
+ elsif (w = w.grep(String)).empty?
+ proc {true}
+ else
+ proc {|c1| w.collect {|opt| opt.split(/,/)}.flatten.any?(&c1)}
+ end
+ }
+ cond = proc {|ext|
+ cond1 = proc {|n| File.fnmatch(n, ext, File::FNM_PATHNAME)}
+ withes.call(cond1) or !withouts.call(cond1)
+ }
+ exts |= Dir.glob("#{ext_prefix}/*/**/extconf.rb").collect {|d|
+ d = File.dirname(d)
+ d.slice!(0, ext_prefix.length + 1)
+ d
+ }.find_all {|ext|
+ with_config(ext, &cond)
+ }.sort
end
+if $extout
+ extout = Config.expand("#{$extout}", Config::CONFIG.merge("topdir"=>$topdir))
+ unless $ignore
+ FileUtils.mkpath(extout)
+ end
+end
+
+dir = Dir.pwd
FileUtils::makedirs('ext')
Dir::chdir('ext')
-ext_prefix = "#{$top_srcdir}/ext"
-Dir.glob("#{ext_prefix}/*/**/MANIFEST") do |d|
- d = File.dirname(d)
- d.slice!(0, ext_prefix.length + 1)
- extmake(d) or exit(1)
+hdrdir = $hdrdir
+$hdrdir = $top_srcdir = relative_from(srcdir, $topdir = "..")
+exts.each do |d|
+ extmake(d) or abort
end
+$top_srcdir = srcdir
+$topdir = "."
+$hdrdir = hdrdir
+extinit = Struct.new(:c, :o) {
+ def initialize(src)
+ super("#{src}.c", "#{src}.#{$OBJEXT}")
+ end
+}.new("extinit")
if $ignore
+ FileUtils.rm_f(extinit.to_a) if $clean
Dir.chdir ".."
+ if $clean
+ Dir.rmdir('ext') rescue nil
+ if $extout
+ FileUtils.rm_rf([extout+"/common", extout+"/include/ruby", extout+"/rdoc"])
+ FileUtils.rm_rf(extout+"/"+CONFIG["arch"])
+ if $clean != true
+ FileUtils.rm_rf(extout+"/include/"+CONFIG["arch"])
+ FileUtils.rm_f($mflags.defined?("INSTALLED_LIST")||ENV["INSTALLED_LIST"]||".installed.list")
+ Dir.rmdir(extout+"/include") rescue nil
+ Dir.rmdir(extout) rescue nil
+ end
+ end
+ end
exit
end
-if $extlist.size > 0
- $extinit ||= ""
- $extobjs ||= ""
+$extinit ||= ""
+$extobjs ||= ""
+$extpath ||= []
+$extflags ||= ""
+$extlibs ||= []
+unless $extlist.empty?
+ $extinit << "\n" unless $extinit.empty?
list = $extlist.dup
- until list.empty?
- s,t,i,r = list.shift
- if r and list.any? {|l| r.include?(l[1])}
- list << [s,t,i]
+ built = []
+ while e = list.shift
+ s,t,i,r = e
+ if r and !(r -= built).empty?
+ l = list.size
+ if (while l > 0; break true if r.include?(list[l-=1][1]) end)
+ list.insert(l + 1, e)
+ end
next
end
f = format("%s/%s.%s", s, i, $LIBEXT)
if File.exist?(f)
- $extinit += "\tinit(Init_#{i}, \"#{t}.so\");\n"
- $extobjs += "ext/#{f} "
+ $extinit << " init(Init_#{i}, \"#{t}.so\");\n"
+ $extobjs << "ext/#{f} "
+ built << t
end
end
- src = <<SRC
-extern char *ruby_sourcefile, *rb_source_filename();
-#define init(func, name) (ruby_sourcefile = src = rb_source_filename(name), func(), rb_provide(src))
-void Init_ext() {\n\tchar* src;\n#$extinit}
-SRC
- if !modified?("extinit.c", MTIMES) || IO.read("extinit.c") != src
- open("extinit.c", "w") {|f| f.print src}
+ src = %{\
+#include "ruby.h"
+
+#define init(func, name) {void func _((void)); ruby_init_ext(name, func);}
+
+void ruby_init_ext _((const char *name, void (*init)(void)));
+
+void Init_ext _((void))\n{\n#$extinit}
+}
+ if !modified?(extinit.c, MTIMES) || IO.read(extinit.c) != src
+ open(extinit.c, "w") {|f| f.print src}
end
- $extobjs = "ext/extinit.#{$OBJEXT} " + $extobjs
+ $extobjs = "ext/#{extinit.o} #{$extobjs}"
if RUBY_PLATFORM =~ /m68k-human|beos/
$extflags.delete("-L/usr/local/lib")
end
$extpath.delete("$(topdir)")
$extflags = libpathflag($extpath) << " " << $extflags.strip
conf = [
- ['SETUP', $setup], [$enable_shared ? 'DLDOBJS' : 'EXTOBJS', $extobjs],
+ ['LIBRUBY_SO_UPDATE', '$(LIBRUBY_EXTS)'],
+ ['SETUP', $setup],
+ [enable_config("shared", $enable_shared) ? 'DLDOBJS' : 'EXTOBJS', $extobjs],
['EXTLIBS', $extlibs.join(' ')], ['EXTLDFLAGS', $extflags]
].map {|n, v|
"#{n}=#{v}" if v and !(v = v.strip).empty?
@@ -270,20 +527,38 @@ SRC
puts conf
$stdout.flush
$mflags.concat(conf)
+else
+ FileUtils.rm_f(extinit.to_a)
end
rubies = []
-%w[RUBY RUBYW].each {|r|
- config_string(r+"_INSTALL_NAME") {|r| rubies << r+EXEEXT}
+%w[RUBY RUBYW STATIC_RUBY].each {|r|
+ n = r
+ if r = arg_config("--"+r.downcase) || config_string(r+"_INSTALL_NAME")
+ rubies << Config.expand(r+=EXEEXT)
+ $mflags << "#{n}=#{r}"
+ end
}
Dir.chdir ".."
-if $extlist.size > 0
- rm_f(Config::CONFIG["LIBRUBY_SO"])
+unless $destdir.to_s.empty?
+ $mflags.defined?("DESTDIR") or $mflags << "DESTDIR=#{$destdir}"
end
puts "making #{rubies.join(', ')}"
$stdout.flush
$mflags.concat(rubies)
+if $nmake == ?b
+ unless (vars = $mflags.grep(/\A\w+=/n)).empty?
+ open(mkf = "libruby.mk", "wb") do |tmf|
+ tmf.puts("!include Makefile")
+ tmf.puts
+ tmf.puts(*vars.map {|v| v.sub(/=/, " = ")})
+ tmf.puts("PRE_LIBRUBY_UPDATE = del #{mkf}")
+ end
+ $mflags.unshift("-f#{mkf}")
+ vars.each {|flag| flag.sub!(/\A/, "-D")}
+ end
+end
system($make, *sysquote($mflags)) or exit($?.exitstatus)
#Local variables:
diff --git a/ext/fcntl/MANIFEST b/ext/fcntl/MANIFEST
deleted file mode 100644
index aef7ad4ca0..0000000000
--- a/ext/fcntl/MANIFEST
+++ /dev/null
@@ -1,3 +0,0 @@
-MANIFEST
-depend
-fcntl.c
diff --git a/ext/fcntl/extconf.rb b/ext/fcntl/extconf.rb
new file mode 100644
index 0000000000..8b717d4a5b
--- /dev/null
+++ b/ext/fcntl/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('fcntl')
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index d48630fc66..57cca103f4 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -34,6 +34,81 @@ pack up your own arguments to pass as args for locking functions, etc.
#include "ruby.h"
#include <fcntl.h>
+/* Fcntl loads the constants defined in the system's <fcntl.h> C header
+ * file, and used with both the fcntl(2) and open(2) POSIX system calls.
+ *
+ * Copyright (C) 1997-2001 Yukihiro Matsumoto
+ *
+ * Documented by mathew <meta@pobox.com>
+ *
+ * = Usage
+ *
+ * To perform a fcntl(2) operation, use IO::fcntl in the core classes.
+ *
+ * To perform an open(2) operation, use IO::sysopen.
+ *
+ * The set of operations and constants available depends upon specific OS
+ * platform. Some values listed below may not be supported on your system.
+ *
+ * The constants supported by Ruby for use with IO::fcntl are:
+ *
+ * - F_DUPFD - duplicate a close-on-exec file handle to a non-close-on-exec
+ * file handle.
+ *
+ * - F_GETFD - read the close-on-exec flag of a file handle.
+ *
+ * - F_SETFD - set the close-on-exec flag of a file handle.
+ *
+ * - FD_CLOEXEC - the value of the close-on-exec flag.
+ *
+ * - F_GETFL - get file descriptor flags.
+ *
+ * - F_SETFL - set file descriptor flags.
+ *
+ * - O_APPEND, O_NONBLOCK, etc (see below) - file descriptor flag
+ * values for the above.
+ *
+ * - F_GETLK - determine whether a given region of a file is locked.
+ *
+ * - F_SETLK - acquire a lock on a region of a file.
+ *
+ * - F_SETLKW - acquire a lock on a region of a file, waiting if necessary.
+ *
+ * - F_RDLCK, F_WRLCK, F_UNLCK - types of lock for the above.
+ *
+ * The constants supported by Ruby for use with IO::sysopen are:
+ *
+ * - O_APPEND - open file in append mode.
+ *
+ * - O_NOCTTY - open tty without it becoming controlling tty.
+ *
+ * - O_CREAT - create file if it doesn't exist.
+ *
+ * - O_EXCL - used with O_CREAT, fail if file exists.
+ *
+ * - O_TRUNC - truncate file on open.
+ *
+ * - O_NONBLOCK / O_NDELAY - open in non-blocking mode.
+ *
+ * - O_RDONLY - open read-only.
+ *
+ * - O_WRONLY - open write-only.
+ *
+ * - O_RDWR - open read-write.
+ *
+ * - O_ACCMODE - mask to extract read/write flags.
+ *
+ * Example:
+ *
+ * require 'fcntl'
+ *
+ * fd = IO::sysopen('/tmp/tempfile',
+ * Fcntl::O_WRONLY | Fcntl::O_EXCL | Fcntl::O_CREAT)
+ * f = IO.open(fd)
+ * f.syswrite("TEMP DATA")
+ * f.close
+ *
+ */
void
Init_fcntl()
{
diff --git a/ext/gdbm/MANIFEST b/ext/gdbm/MANIFEST
deleted file mode 100644
index 1359b4fdaf..0000000000
--- a/ext/gdbm/MANIFEST
+++ /dev/null
@@ -1,6 +0,0 @@
-MANIFEST
-README
-depend
-extconf.rb
-gdbm.c
-testgdbm.rb
diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c
index 84996896ab..2057101206 100644
--- a/ext/gdbm/gdbm.c
+++ b/ext/gdbm/gdbm.c
@@ -6,6 +6,8 @@
$Date$
modified at: Mon Jan 24 15:59:52 JST 1994
+ Documentation by Peter Adolphs < futzilogik at users dot sourceforge dot net >
+
************************************************/
#include "ruby.h"
@@ -14,15 +16,73 @@
#include <fcntl.h>
#include <errno.h>
+/*
+ * Document-class: GDBM
+ *
+ * == Summary
+ *
+ * Ruby extension for GNU dbm (gdbm) -- a simple database engine for storing
+ * key-value pairs on disk.
+ *
+ * == Description
+ *
+ * GNU dbm is a library for simple databases. A database is a file that stores
+ * key-value pairs. Gdbm allows the user to store, retrieve, and delete data by
+ * key. It furthermore allows a non-sorted traversal of all key-value pairs.
+ * A gdbm database thus provides the same functionality as a hash. As
+ * with objects of the Hash class, elements can be accessed with <tt>[]</tt>.
+ * Furthermore, GDBM mixes in the Enumerable module, thus providing convenient
+ * methods such as #find, #collect, #map, etc.
+ *
+ * A process is allowed to open several different databases at the same time.
+ * A process can open a database as a "reader" or a "writer". Whereas a reader
+ * has only read-access to the database, a writer has read- and write-access.
+ * A database can be accessed either by any number of readers or by exactly one
+ * writer at the same time.
+ *
+ * == Examples
+ *
+ * 1. Opening/creating a database, and filling it with some entries:
+ *
+ * require 'gdbm'
+ *
+ * gdbm = GDBM.new("fruitstore.db")
+ * gdbm["ananas"] = "3"
+ * gdbm["banana"] = "8"
+ * gdbm["cranberry"] = "4909"
+ * gdbm.close
+ *
+ * 2. Reading out a database:
+ *
+ * require 'gdbm'
+ *
+ * gdbm = GDBM.new("fruitstore.db")
+ * gdbm.each_pair do |key, value|
+ * print "#{key}: #{value}\n"
+ * end
+ * gdbm.close
+ *
+ * produces
+ *
+ * banana: 8
+ * ananas: 3
+ * cranberry: 4909
+ *
+ * == Links
+ *
+ * * http://www.gnu.org/software/gdbm/
+ */
static VALUE rb_cGDBM, rb_eGDBMError, rb_eGDBMFatalError;
+#define RUBY_GDBM_RW_BIT 0x20000000
+
#define MY_BLOCK_SIZE (2048)
#define MY_FATAL_FUNC rb_gdbm_fatal
static void
rb_gdbm_fatal(msg)
char *msg;
{
- rb_raise(rb_eGDBMFatalError, msg);
+ rb_raise(rb_eGDBMFatalError, "%s", msg);
}
struct dbmdata {
@@ -42,16 +102,27 @@ closed_dbm()
if (dbmp->di_dbm == 0) closed_dbm();\
} while (0)
+#define GetDBM2(obj, data, dbm) {\
+ GetDBM(obj, data);\
+ (dbm) = dbmp->di_dbm;\
+}
+
static void
free_dbm(dbmp)
struct dbmdata *dbmp;
{
if (dbmp) {
- if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
- free(dbmp);
+ if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
+ free(dbmp);
}
}
+/*
+ * call-seq:
+ * gdbm.close -> nil
+ *
+ * Closes the associated database file.
+ */
static VALUE
fgdbm_close(obj)
VALUE obj;
@@ -65,6 +136,27 @@ fgdbm_close(obj)
return Qnil;
}
+/*
+ * call-seq:
+ * gdbm.closed? -> true or false
+ *
+ * Returns true if the associated database file has been closed.
+ */
+static VALUE
+fgdbm_closed(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp == 0)
+ return Qtrue;
+ if (dbmp->di_dbm == 0)
+ return Qtrue;
+
+ return Qfalse;
+}
+
static VALUE fgdbm_s_alloc _((VALUE));
static VALUE
@@ -74,6 +166,29 @@ fgdbm_s_alloc(klass)
return Data_Wrap_Struct(klass, 0, free_dbm, 0);
}
+/*
+ * call-seq:
+ * GDBM.new(filename, mode = 0666, flags = nil)
+ *
+ * Creates a new GDBM instance by opening a gdbm file named _filename_.
+ * If the file does not exist, a new file with file mode _mode_ will be
+ * created. _flags_ may be one of the following:
+ * * *READER* - open as a reader
+ * * *WRITER* - open as a writer
+ * * *WRCREAT* - open as a writer; if the database does not exist, create a new one
+ * * *NEWDB* - open as a writer; overwrite any existing databases
+ *
+ * The values *WRITER*, *WRCREAT* and *NEWDB* may be combined with the following
+ * values by bitwise or:
+ * * *SYNC* - cause all database operations to be synchronized to the disk
+ * * *NOLOCK* - do not lock the database file
+ *
+ * If no _flags_ are specified, the GDBM object will try to open the database
+ * file as a writer and will create it if it does not already exist
+ * (cf. flag <tt>WRCREAT</tt>). If this fails (for instance, if another process
+ * has already opened the database as a reader), it will try to open the
+ * database file as a reader (cf. flag <tt>READER</tt>).
+ */
static VALUE
fgdbm_initialize(argc, argv, obj)
int argc;
@@ -86,13 +201,13 @@ fgdbm_initialize(argc, argv, obj)
int mode, flags = 0;
if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
- mode = 0666; /* default value */
+ mode = 0666; /* default value */
}
else if (NIL_P(vmode)) {
- mode = -1; /* return nil if DB not exist */
+ mode = -1; /* return nil if DB does not exist */
}
else {
- mode = NUM2INT(vmode);
+ mode = NUM2INT(vmode);
}
if (!NIL_P(vflags))
@@ -100,16 +215,23 @@ fgdbm_initialize(argc, argv, obj)
SafeStringValue(file);
- dbm = 0;
- if (mode >= 0)
- dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- GDBM_WRCREAT|flags, mode, MY_FATAL_FUNC);
- if (!dbm)
+ if (flags & RUBY_GDBM_RW_BIT) {
+ flags &= ~RUBY_GDBM_RW_BIT;
dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- GDBM_WRITER|flags, 0, MY_FATAL_FUNC);
- if (!dbm)
- dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
- GDBM_READER|flags, 0, MY_FATAL_FUNC);
+ flags, mode, MY_FATAL_FUNC);
+ }
+ else {
+ dbm = 0;
+ if (mode >= 0)
+ dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
+ GDBM_WRCREAT|flags, mode, MY_FATAL_FUNC);
+ if (!dbm)
+ dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
+ GDBM_WRITER|flags, 0, MY_FATAL_FUNC);
+ if (!dbm)
+ dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
+ GDBM_READER|flags, 0, MY_FATAL_FUNC);
+ }
if (!dbm) {
if (mode == -1) return Qnil;
@@ -131,6 +253,25 @@ fgdbm_initialize(argc, argv, obj)
return obj;
}
+/*
+ * call-seq:
+ * GDBM.open(filename, mode = 0666, flags = nil)
+ * GDBM.open(filename, mode = 0666, flags = nil) { |gdbm| ... }
+ *
+ * If called without a block, this is synonymous to GDBM::new.
+ * If a block is given, the new GDBM instance will be passed to the block
+ * as a parameter, and the corresponding database file will be closed
+ * after the execution of the block code has been finished.
+ *
+ * Example for an open call with a block:
+ *
+ * require 'gdbm'
+ * GDBM.open("fruitstore.db") do |gdbm|
+ * gdbm.each_pair do |key, value|
+ * print "#{key}: #{value}\n"
+ * end
+ * end
+ */
static VALUE
fgdbm_s_open(argc, argv, klass)
int argc;
@@ -162,14 +303,10 @@ rb_gdbm_fetch(dbm, key)
if (val.dptr == 0)
return Qnil;
- str = rb_obj_alloc(rb_cString);
- RSTRING(str)->len = val.dsize;
- RSTRING(str)->aux.capa = val.dsize;
- RSTRING(str)->ptr = REALLOC_N(val.dptr,char,val.dsize+1);
- RSTRING(str)->ptr[val.dsize] = '\0';
-
+ str = rb_str_new(val.dptr, val.dsize);
+ free(val.dptr);
OBJ_TAINT(str);
- return (VALUE)str;
+ return str;
}
static VALUE
@@ -193,8 +330,7 @@ rb_gdbm_fetch3(obj, keystr)
struct dbmdata *dbmp;
GDBM_FILE dbm;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
return rb_gdbm_fetch2(dbm, keystr);
}
@@ -209,12 +345,8 @@ rb_gdbm_firstkey(dbm)
if (key.dptr == 0)
return Qnil;
- str = rb_obj_alloc(rb_cString);
- RSTRING(str)->len = key.dsize;
- RSTRING(str)->aux.capa = key.dsize;
- RSTRING(str)->ptr = REALLOC_N(key.dptr,char,key.dsize+1);
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
-
+ str = rb_str_new(key.dptr, key.dsize);
+ free(key.dptr);
OBJ_TAINT(str);
return str;
}
@@ -233,12 +365,8 @@ rb_gdbm_nextkey(dbm, keystr)
if (key2.dptr == 0)
return Qnil;
- str = rb_obj_alloc(rb_cString);
- RSTRING(str)->len = key2.dsize;
- RSTRING(str)->aux.capa = key2.dsize;
- RSTRING(str)->ptr = REALLOC_N(key2.dptr,char,key2.dsize+1);
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
-
+ str = rb_str_new(key2.dptr, key2.dsize);
+ free(key2.dptr);
OBJ_TAINT(str);
return str;
}
@@ -258,6 +386,12 @@ fgdbm_fetch(obj, keystr, ifnone)
return valstr;
}
+/*
+ * call-seq:
+ * gdbm[key] -> value
+ *
+ * Retrieves the _value_ corresponding to _key_.
+ */
static VALUE
fgdbm_aref(obj, keystr)
VALUE obj, keystr;
@@ -265,6 +399,13 @@ fgdbm_aref(obj, keystr)
return rb_gdbm_fetch3(obj, keystr);
}
+/*
+ * call-seq:
+ * gdbm.fetch(key [, default]) -> value
+ *
+ * Retrieves the _value_ corresponding to _key_. If there is no value
+ * associated with _key_, _default_ will be returned instead.
+ */
static VALUE
fgdbm_fetch_m(argc, argv, obj)
int argc;
@@ -276,11 +417,18 @@ fgdbm_fetch_m(argc, argv, obj)
rb_scan_args(argc, argv, "11", &keystr, &ifnone);
valstr = fgdbm_fetch(obj, keystr, ifnone);
if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
- rb_raise(rb_eIndexError, "key not found");
+ rb_raise(rb_eIndexError, "key not found");
return valstr;
}
+/*
+ * call-seq:
+ * gdbm.index(value) -> key
+ *
+ * Returns the _key_ for a given _value_. If several keys may map to the
+ * same value, the key that is found first will be returned.
+ */
static VALUE
fgdbm_index(obj, valstr)
VALUE obj, valstr;
@@ -290,8 +438,7 @@ fgdbm_index(obj, valstr)
VALUE keystr, valstr2;
StringValue(valstr);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
@@ -323,6 +470,13 @@ fgdbm_indexes(argc, argv, obj)
return new;
}
+/*
+ * call-seq:
+ * gdbm.select { |value| block } -> array
+ *
+ * Returns a new array of all values of the database for which _block_
+ * evaluates to true.
+ */
static VALUE
fgdbm_select(argc, argv, obj)
int argc;
@@ -340,15 +494,16 @@ fgdbm_select(argc, argv, obj)
if (argc > 0) {
rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
}
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
VALUE assoc = rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr));
+ VALUE v = rb_yield(assoc);
- if (RTEST(rb_yield(assoc)))
- rb_ary_push(new, assoc);
+ if (RTEST(v)) {
+ rb_ary_push(new, assoc);
+ }
+ GetDBM2(obj, dbmp, dbm);
}
}
else {
@@ -362,6 +517,12 @@ fgdbm_select(argc, argv, obj)
return new;
}
+/*
+ * call-seq:
+ * gdbm.values_at(key, ...) -> array
+ *
+ * Returns an array of the values associated with each specified _key_.
+ */
static VALUE
fgdbm_values_at(argc, argv, obj)
int argc;
@@ -378,6 +539,14 @@ fgdbm_values_at(argc, argv, obj)
return new;
}
+static void
+rb_gdbm_modify(obj)
+ VALUE obj;
+{
+ rb_secure(4);
+ if (OBJ_FROZEN(obj)) rb_error_frozen("GDBM");
+}
+
static VALUE
rb_gdbm_delete(obj, keystr)
VALUE obj, keystr;
@@ -386,28 +555,33 @@ rb_gdbm_delete(obj, keystr)
struct dbmdata *dbmp;
GDBM_FILE dbm;
- rb_secure(4);
+ rb_gdbm_modify(obj);
StringValue(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
if (!gdbm_exists(dbm, key)) {
- return Qnil;
+ return Qnil;
}
if (gdbm_delete(dbm, key)) {
- dbmp->di_size = -1;
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ dbmp->di_size = -1;
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
else if (dbmp->di_size >= 0) {
- dbmp->di_size--;
+ dbmp->di_size--;
}
return obj;
}
+/*
+ * call-seq:
+ * gdbm.delete(key) -> value or nil
+ *
+ * Removes the key-value-pair with the specified _key_ from this database and
+ * returns the corresponding _value_. Returns nil if the database is empty.
+ */
static VALUE
fgdbm_delete(obj, keystr)
VALUE obj, keystr;
@@ -419,6 +593,13 @@ fgdbm_delete(obj, keystr)
return valstr;
}
+/*
+ * call-seq:
+ * gdbm.shift -> (key, value) or nil
+ *
+ * Removes a key-value-pair from this database and returns it as a
+ * two-item array [ _key_, _value_ ]. Returns nil if the database is empty.
+ */
static VALUE
fgdbm_shift(obj)
VALUE obj;
@@ -427,10 +608,8 @@ fgdbm_shift(obj)
GDBM_FILE dbm;
VALUE keystr, valstr;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ rb_gdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
keystr = rb_gdbm_firstkey(dbm);
if (NIL_P(keystr)) return Qnil;
valstr = rb_gdbm_fetch2(dbm, keystr);
@@ -439,6 +618,13 @@ fgdbm_shift(obj)
return rb_assoc_new(keystr, valstr);
}
+/*
+ * call-seq:
+ * gdbm.delete_if { |key, value| block } -> gdbm
+ * gdbm.reject! { |key, value| block } -> gdbm
+ *
+ * Deletes every key-value pair from _gdbm_ for which _block_ evaluates to true.
+ */
static VALUE
fgdbm_delete_if(obj)
VALUE obj;
@@ -449,19 +635,19 @@ fgdbm_delete_if(obj)
VALUE ret, ary = rb_ary_new();
int i, status = 0, n;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ rb_gdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
n = dbmp->di_size;
dbmp->di_size = -1;
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
- valstr = rb_gdbm_fetch2(dbm, keystr);
+ valstr = rb_gdbm_fetch2(dbm, keystr);
ret = rb_protect(rb_yield, rb_assoc_new(keystr, valstr), &status);
if (status != 0) break;
- if (RTEST(ret)) rb_ary_push(ary, keystr);
+ if (RTEST(ret)) rb_ary_push(ary, keystr);
+ GetDBM2(obj, dbmp, dbm);
}
for (i = 0; i < RARRAY(ary)->len; i++)
@@ -472,6 +658,12 @@ fgdbm_delete_if(obj)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.clear -> gdbm
+ *
+ * Removes all the key-value pairs within _gdbm_.
+ */
static VALUE
fgdbm_clear(obj)
VALUE obj;
@@ -480,18 +672,17 @@ fgdbm_clear(obj)
struct dbmdata *dbmp;
GDBM_FILE dbm;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ rb_gdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
dbmp->di_size = -1;
#if 0
while (key = gdbm_firstkey(dbm), key.dptr) {
- if (gdbm_delete(dbm, key)) {
- free(key.dptr);
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
- free(key.dptr);
+ if (gdbm_delete(dbm, key)) {
+ free(key.dptr);
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ free(key.dptr);
}
#else
while (key = gdbm_firstkey(dbm), key.dptr) {
@@ -511,6 +702,13 @@ fgdbm_clear(obj)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.invert -> hash
+ *
+ * Returns a hash created by using _gdbm_'s values as keys, and the keys
+ * as values.
+ */
static VALUE
fgdbm_invert(obj)
VALUE obj;
@@ -520,8 +718,7 @@ fgdbm_invert(obj)
VALUE keystr, valstr;
VALUE hash = rb_hash_new();
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
valstr = rb_gdbm_fetch2(dbm, keystr);
@@ -554,6 +751,14 @@ update_i(pair, dbm)
return Qnil;
}
+/*
+ * call-seq:
+ * gdbm.update(other) -> gdbm
+ *
+ * Adds the key-value pairs of _other_ to _gdbm_, overwriting entries with
+ * duplicate keys with those from _other_. _other_ must have an each_pair
+ * method.
+ */
static VALUE
fgdbm_update(obj, other)
VALUE obj, other;
@@ -562,6 +767,13 @@ fgdbm_update(obj, other)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.replace(other) -> gdbm
+ *
+ * Replaces the content of _gdbm_ with the key-value pairs of _other_.
+ * _other_ must have an each_pair method.
+ */
static VALUE
fgdbm_replace(obj, other)
VALUE obj, other;
@@ -571,6 +783,13 @@ fgdbm_replace(obj, other)
return obj;
}
+/*
+ * call-seq:
+ * gdbm[key]= value -> value
+ * gdbm.store(key, value) -> value
+ *
+ * Associates the value _value_ with the specified _key_.
+ */
static VALUE
fgdbm_store(obj, keystr, valstr)
VALUE obj, keystr, valstr;
@@ -579,26 +798,33 @@ fgdbm_store(obj, keystr, valstr)
struct dbmdata *dbmp;
GDBM_FILE dbm;
- rb_secure(4);
+ rb_gdbm_modify(obj);
StringValue(keystr);
+ StringValue(valstr);
+
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- StringValue(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- GetDBM(obj, dbmp);
+ GetDBM2(obj, dbmp, dbm);
dbmp->di_size = -1;
- dbm = dbmp->di_dbm;
if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
- if (errno == EPERM) rb_sys_fail(0);
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ if (errno == EPERM) rb_sys_fail(0);
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
return valstr;
}
+/*
+ * call-seq:
+ * gdbm.length -> fixnum
+ * gdbm.size -> fixnum
+ *
+ * Returns the number of key-value pairs in this database.
+ */
static VALUE
fgdbm_length(obj)
VALUE obj;
@@ -608,9 +834,8 @@ fgdbm_length(obj)
GDBM_FILE dbm;
int i = 0;
- GetDBM(obj, dbmp);
+ GetDBM2(obj, dbmp, dbm);
if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
- dbm = dbmp->di_dbm;
for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
nextkey = gdbm_nextkey(dbm, key);
@@ -622,6 +847,12 @@ fgdbm_length(obj)
return INT2FIX(i);
}
+/*
+ * call-seq:
+ * gdbm.empty? -> true or false
+ *
+ * Returns true if the database is empty.
+ */
static VALUE
fgdbm_empty_p(obj)
VALUE obj;
@@ -646,6 +877,13 @@ fgdbm_empty_p(obj)
return Qfalse;
}
+/*
+ * call-seq:
+ * gdbm.each_value { |value| block } -> gdbm
+ *
+ * Executes _block_ for each key in the database, passing the corresponding
+ * _value_ as a parameter.
+ */
static VALUE
fgdbm_each_value(obj)
VALUE obj;
@@ -654,17 +892,23 @@ fgdbm_each_value(obj)
GDBM_FILE dbm;
VALUE keystr;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
rb_yield(rb_gdbm_fetch2(dbm, keystr));
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
}
+/*
+ * call-seq:
+ * gdbm.each_key { |key| block } -> gdbm
+ *
+ * Executes _block_ for each key in the database, passing the
+ * _key_ as a parameter.
+ */
static VALUE
fgdbm_each_key(obj)
VALUE obj;
@@ -673,17 +917,23 @@ fgdbm_each_key(obj)
GDBM_FILE dbm;
VALUE keystr;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
rb_yield(keystr);
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
}
+/*
+ * call-seq:
+ * gdbm.each_pair { |key, value| block } -> gdbm
+ *
+ * Executes _block_ for each key in the database, passing the _key_ and the
+ * correspoding _value_ as a parameter.
+ */
static VALUE
fgdbm_each_pair(obj)
VALUE obj;
@@ -692,18 +942,23 @@ fgdbm_each_pair(obj)
struct dbmdata *dbmp;
VALUE keystr;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
rb_yield(rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr)));
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
}
+/*
+ * call-seq:
+ * gdbm.keys -> array
+ *
+ * Returns an array of all keys of this database.
+ */
static VALUE
fgdbm_keys(obj)
VALUE obj;
@@ -712,9 +967,7 @@ fgdbm_keys(obj)
GDBM_FILE dbm;
VALUE keystr, ary;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
@@ -725,6 +978,12 @@ fgdbm_keys(obj)
return ary;
}
+/*
+ * call-seq:
+ * gdbm.values -> array
+ *
+ * Returns an array of all values of this database.
+ */
static VALUE
fgdbm_values(obj)
VALUE obj;
@@ -734,20 +993,26 @@ fgdbm_values(obj)
GDBM_FILE dbm;
VALUE valstr, ary;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
nextkey = gdbm_nextkey(dbm, key);
- valstr = rb_gdbm_fetch(dbm, key);
+ valstr = rb_gdbm_fetch(dbm, key);
free(key.dptr);
- rb_ary_push(ary, valstr);
+ rb_ary_push(ary, valstr);
}
return ary;
}
+/*
+ * call-seq:
+ * gdbm.has_key?(k) -> true or false
+ * gdbm.key?(k) -> true or false
+ *
+ * Returns true if the given key _k_ exists within the database.
+ * Returns false otherwise.
+ */
static VALUE
fgdbm_has_key(obj, keystr)
VALUE obj, keystr;
@@ -760,13 +1025,20 @@ fgdbm_has_key(obj, keystr)
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
if (gdbm_exists(dbm, key))
return Qtrue;
return Qfalse;
}
+/*
+ * call-seq:
+ * gdbm.has_value?(v) -> true or false
+ * gdbm.value?(v) -> true or false
+ *
+ * Returns true if the given value _v_ exists within the database.
+ * Returns false otherwise.
+ */
static VALUE
fgdbm_has_value(obj, valstr)
VALUE obj, valstr;
@@ -776,8 +1048,7 @@ fgdbm_has_value(obj, valstr)
VALUE keystr, valstr2;
StringValue(valstr);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
@@ -793,6 +1064,12 @@ fgdbm_has_value(obj, valstr)
return Qfalse;
}
+/*
+ * call-seq:
+ * gdbm.to_a -> array
+ *
+ * Returns an array of all key-value pairs contained in the database.
+ */
static VALUE
fgdbm_to_a(obj)
VALUE obj;
@@ -801,9 +1078,7 @@ fgdbm_to_a(obj)
GDBM_FILE dbm;
VALUE keystr, ary;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
@@ -814,6 +1089,14 @@ fgdbm_to_a(obj)
return ary;
}
+/*
+ * call-seq:
+ * gdbm.reorganize -> gdbm
+ *
+ * Reorganizes the database file. This operation removes reserved space of
+ * elements that have already been deleted. It is only useful after a lot of
+ * deletions in the database.
+ */
static VALUE
fgdbm_reorganize(obj)
VALUE obj;
@@ -821,13 +1104,22 @@ fgdbm_reorganize(obj)
struct dbmdata *dbmp;
GDBM_FILE dbm;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ rb_gdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
gdbm_reorganize(dbm);
return obj;
}
+/*
+ * call-seq:
+ * gdbm.sync -> gdbm
+ *
+ * Unless the _gdbm_ object has been opened with the *SYNC* flag, it is not
+ * guarenteed that database modification operations are immediately applied to
+ * the database file. This method ensures that all recent modifications
+ * to the database are written to the file. Blocks until all writing operations
+ * to the disk have been finished.
+ */
static VALUE
fgdbm_sync(obj)
VALUE obj;
@@ -835,13 +1127,18 @@ fgdbm_sync(obj)
struct dbmdata *dbmp;
GDBM_FILE dbm;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ rb_gdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
gdbm_sync(dbm);
return obj;
}
+/*
+ * call-seq:
+ * gdbm.cachesize = size -> size
+ *
+ * Sets the size of the internal bucket cache to _size_.
+ */
static VALUE
fgdbm_set_cachesize(obj, val)
VALUE obj, val;
@@ -850,16 +1147,24 @@ fgdbm_set_cachesize(obj, val)
GDBM_FILE dbm;
int optval;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
optval = FIX2INT(val);
if (gdbm_setopt(dbm, GDBM_CACHESIZE, &optval, sizeof(optval)) == -1) {
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
return val;
}
+/*
+ * call-seq:
+ * gdbm.fastmode = boolean -> boolean
+ *
+ * Turns the database's fast mode on or off. If fast mode is turned on, gdbm
+ * does not wait for writes to be flushed to the disk before continuing.
+ *
+ * This option is obsolete for gdbm >= 1.8 since fast mode is turned on by
+ * default. See also: #syncmode=
+ */
static VALUE
fgdbm_set_fastmode(obj, val)
VALUE obj, val;
@@ -868,19 +1173,30 @@ fgdbm_set_fastmode(obj, val)
GDBM_FILE dbm;
int optval;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
optval = 0;
if (RTEST(val))
optval = 1;
if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
return val;
}
+/*
+ * call-seq:
+ * gdbm.syncmode = boolean -> boolean
+ *
+ * Turns the database's synchronization mode on or off. If the synchronization
+ * mode is turned on, the database's in-memory state will be synchronized to
+ * disk after every database modification operation. If the synchronization
+ * mode is turned off, GDBM does not wait for writes to be flushed to the disk
+ * before continuing.
+ *
+ * This option is only available for gdbm >= 1.8 where syncmode is turned off
+ * by default. See also: #fastmode=
+ */
static VALUE
fgdbm_set_syncmode(obj, val)
VALUE obj, val;
@@ -893,20 +1209,24 @@ fgdbm_set_syncmode(obj, val)
GDBM_FILE dbm;
int optval;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
optval = 0;
if (RTEST(val))
optval = 1;
if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
return val;
#endif
}
+/*
+ * call-seq:
+ * gdbm.to_hash -> hash
+ *
+ * Returns a hash of all key-value pairs contained in the database.
+ */
static VALUE
fgdbm_to_hash(obj)
VALUE obj;
@@ -915,9 +1235,7 @@ fgdbm_to_hash(obj)
GDBM_FILE dbm;
VALUE keystr, hash;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
hash = rb_hash_new();
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
@@ -928,6 +1246,13 @@ fgdbm_to_hash(obj)
return hash;
}
+/*
+ * call-seq:
+ * gdbm.reject { |key, value| block } -> hash
+ *
+ * Returns a hash copy of _gdbm_ where all key-value pairs from _gdbm_ for
+ * which _block_ evaluates to true are removed. See also: #delete_if
+ */
static VALUE
fgdbm_reject(obj)
VALUE obj;
@@ -948,6 +1273,7 @@ Init_gdbm()
rb_define_method(rb_cGDBM, "initialize", fgdbm_initialize, -1);
rb_define_method(rb_cGDBM, "close", fgdbm_close, 0);
+ rb_define_method(rb_cGDBM, "closed?", fgdbm_closed, 0);
rb_define_method(rb_cGDBM, "[]", fgdbm_aref, 1);
rb_define_method(rb_cGDBM, "fetch", fgdbm_fetch_m, -1);
rb_define_method(rb_cGDBM, "[]=", fgdbm_store, 2);
@@ -972,15 +1298,15 @@ Init_gdbm()
rb_define_method(rb_cGDBM, "reject!", fgdbm_delete_if, 0);
rb_define_method(rb_cGDBM, "reject", fgdbm_reject, 0);
rb_define_method(rb_cGDBM, "clear", fgdbm_clear, 0);
- rb_define_method(rb_cGDBM,"invert", fgdbm_invert, 0);
- rb_define_method(rb_cGDBM,"update", fgdbm_update, 1);
- rb_define_method(rb_cGDBM,"replace", fgdbm_replace, 1);
- rb_define_method(rb_cGDBM,"reorganize", fgdbm_reorganize, 0);
- rb_define_method(rb_cGDBM,"sync", fgdbm_sync, 0);
- /* rb_define_method(rb_cGDBM,"setopt", fgdbm_setopt, 2); */
- rb_define_method(rb_cGDBM,"cachesize=", fgdbm_set_cachesize, 1);
- rb_define_method(rb_cGDBM,"fastmode=", fgdbm_set_fastmode, 1);
- rb_define_method(rb_cGDBM,"syncmode=", fgdbm_set_syncmode, 1);
+ rb_define_method(rb_cGDBM, "invert", fgdbm_invert, 0);
+ rb_define_method(rb_cGDBM, "update", fgdbm_update, 1);
+ rb_define_method(rb_cGDBM, "replace", fgdbm_replace, 1);
+ rb_define_method(rb_cGDBM, "reorganize", fgdbm_reorganize, 0);
+ rb_define_method(rb_cGDBM, "sync", fgdbm_sync, 0);
+ /* rb_define_method(rb_cGDBM, "setopt", fgdbm_setopt, 2); */
+ rb_define_method(rb_cGDBM, "cachesize=", fgdbm_set_cachesize, 1);
+ rb_define_method(rb_cGDBM, "fastmode=", fgdbm_set_fastmode, 1);
+ rb_define_method(rb_cGDBM, "syncmode=", fgdbm_set_syncmode, 1);
rb_define_method(rb_cGDBM, "include?", fgdbm_has_key, 1);
rb_define_method(rb_cGDBM, "has_key?", fgdbm_has_key, 1);
@@ -992,23 +1318,29 @@ Init_gdbm()
rb_define_method(rb_cGDBM, "to_a", fgdbm_to_a, 0);
rb_define_method(rb_cGDBM, "to_hash", fgdbm_to_hash, 0);
- /* flags for gdbm_opn() */
- /*
- rb_define_const(rb_cGDBM, "READER", INT2FIX(GDBM_READER));
- rb_define_const(rb_cGDBM, "WRITER", INT2FIX(GDBM_WRITER));
- rb_define_const(rb_cGDBM, "WRCREAT", INT2FIX(GDBM_WRCREAT));
- rb_define_const(rb_cGDBM, "NEWDB", INT2FIX(GDBM_NEWDB));
- */
+ /* flag for #new and #open: open database as a reader */
+ rb_define_const(rb_cGDBM, "READER", INT2FIX(GDBM_READER|RUBY_GDBM_RW_BIT));
+ /* flag for #new and #open: open database as a writer */
+ rb_define_const(rb_cGDBM, "WRITER", INT2FIX(GDBM_WRITER|RUBY_GDBM_RW_BIT));
+ /* flag for #new and #open: open database as a writer; if the database does not exist, create a new one */
+ rb_define_const(rb_cGDBM, "WRCREAT", INT2FIX(GDBM_WRCREAT|RUBY_GDBM_RW_BIT));
+ /* flag for #new and #open: open database as a writer; overwrite any existing databases */
+ rb_define_const(rb_cGDBM, "NEWDB", INT2FIX(GDBM_NEWDB|RUBY_GDBM_RW_BIT));
+
+ /* flag for #new and #open. this flag is obsolete for gdbm >= 1.8 */
rb_define_const(rb_cGDBM, "FAST", INT2FIX(GDBM_FAST));
/* this flag is obsolete in gdbm 1.8.
On gdbm 1.8, fast mode is default behavior. */
/* gdbm version 1.8 specific */
#if defined(GDBM_SYNC)
+ /* flag for #new and #open. only for gdbm >= 1.8 */
rb_define_const(rb_cGDBM, "SYNC", INT2FIX(GDBM_SYNC));
#endif
#if defined(GDBM_NOLOCK)
+ /* flag for #new and #open */
rb_define_const(rb_cGDBM, "NOLOCK", INT2FIX(GDBM_NOLOCK));
#endif
+ /* version of the gdbm library*/
rb_define_const(rb_cGDBM, "VERSION", rb_str_new2(gdbm_version));
}
diff --git a/ext/gdbm/testgdbm.rb b/ext/gdbm/testgdbm.rb
deleted file mode 100644
index a435498640..0000000000
--- a/ext/gdbm/testgdbm.rb
+++ /dev/null
@@ -1,663 +0,0 @@
-require 'runit/testcase'
-require 'runit/cui/testrunner'
-
-if $".grep(/\bgdbm.so\b/).empty?
- begin
- require './gdbm'
- rescue LoadError
- require 'gdbm'
- end
-end
-
-def uname_s
- require 'rbconfig'
- case Config::CONFIG['host_os']
- when 'cygwin'
- require 'Win32API'
- uname = Win32API.new('cygwin1', 'uname', 'P', 'I')
- utsname = ' ' * 100
- raise 'cannot get system name' if uname.call(utsname) == -1
-
- utsname.unpack('A20' * 5)[0]
- else
- Config::CONFIG['host_os']
- end
-end
-
-SYSTEM = uname_s
-
-class TestGDBM < RUNIT::TestCase
- def setup
- @path = "tmptest_gdbm_"
- assert_instance_of(GDBM, @gdbm = GDBM.new(@path))
-
- # prepare to make readonly GDBM file
- GDBM.open("tmptest_gdbm_rdonly", 0400) {|gdbm|
- gdbm['foo'] = 'FOO'
- }
- assert_instance_of(GDBM, @gdbm_rdonly = GDBM.new("tmptest_gdbm_rdonly", nil))
- end
- def teardown
- assert_nil(@gdbm.close)
- assert_nil(@gdbm_rdonly.close)
- GC.start
- File.delete *Dir.glob("tmptest_gdbm*").to_a
- p Dir.glob("tmptest_gdbm*") if $DEBUG
- end
-
- def check_size(expect, gdbm=@gdbm)
- assert_equals(expect, gdbm.size)
- n = 0
- gdbm.each { n+=1 }
- assert_equals(expect, n)
- if expect == 0
- assert_equals(true, gdbm.empty?)
- else
- assert_equals(false, gdbm.empty?)
- end
- end
-
- def test_version
- STDERR.print GDBM::VERSION
- end
-
- def test_s_new_has_no_block
- # GDBM.new ignore the block
- foo = true
- assert_instance_of(GDBM, gdbm = GDBM.new("tmptest_gdbm") { foo = false })
- assert_equals(foo, true)
- assert_nil(gdbm.close)
- end
- def test_s_open_create_new
- return if /^CYGWIN_9/ =~ SYSTEM
-
- save_mask = File.umask(0)
- begin
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm"))
- gdbm.close
- assert_equals(File.stat("tmptest_gdbm").mode & 0777, 0666)
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm2", 0644))
- gdbm.close
- assert_equals(File.stat("tmptest_gdbm2").mode & 0777, 0644)
- ensure
- File.umask save_mask
- end
- end
- def test_s_open_no_create
- # this test is failed on libgdbm 1.8.0
- assert_nil(gdbm = GDBM.open("tmptest_gdbm", nil))
- ensure
- gdbm.close if gdbm
- end
- def test_s_open_3rd_arg
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm", 0644,
- GDBM::FAST))
- gdbm.close
-
- # gdbm 1.8.0 specific
- if defined? GDBM::SYNC
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm", 0644,
- GDBM::SYNC))
- gdbm.close
- end
- # gdbm 1.8.0 specific
- if defined? GDBM::NOLOCK
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm", 0644,
- GDBM::NOLOCK))
- gdbm.close
- end
- end
- def test_s_open_with_block
- assert_equals(GDBM.open("tmptest_gdbm") { :foo }, :foo)
- end
- def test_s_open_lock
- fork() {
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm", 0644))
- sleep 2
- }
- begin
- sleep 1
- assert_exception(Errno::EWOULDBLOCK) {
- begin
- assert_instance_of(GDBM, gdbm2 = GDBM.open("tmptest_gdbm", 0644))
- rescue Errno::EAGAIN, Errno::EACCES
- raise Errno::EWOULDBLOCK
- end
- }
- ensure
- Process.wait
- end
- end
-
-=begin
- # Is it guaranteed on many OS?
- def test_s_open_lock_one_process
- # locking on one process
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm", 0644))
- assert_exception(Errno::EWOULDBLOCK) {
- begin
- GDBM.open("tmptest_gdbm", 0644)
- rescue Errno::EAGAIN
- raise Errno::EWOULDBLOCK
- end
- }
- end
-=end
-
- def test_s_open_nolock
- # gdbm 1.8.0 specific
- if not defined? GDBM::NOLOCK
- return
- end
-
- fork() {
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm", 0644,
- GDBM::NOLOCK))
- sleep 2
- }
- sleep 1
- begin
- gdbm2 = nil
- assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
- assert_instance_of(GDBM, gdbm2 = GDBM.open("tmptest_gdbm", 0644))
- }
- ensure
- Process.wait
- gdbm2.close if gdbm2
- end
-
- p Dir.glob("tmptest_gdbm*") if $DEBUG
-
- fork() {
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm", 0644))
- sleep 2
- }
- begin
- sleep 1
- gdbm2 = nil
- assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
- # this test is failed on Cygwin98 (???)
- assert_instance_of(GDBM, gdbm2 = GDBM.open("tmptest_gdbm", 0644,
- GDBM::NOLOCK))
- }
- ensure
- Process.wait
- gdbm2.close if gdbm2
- end
- end
-
- def test_s_open_error
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm", 0))
- assert_exception(Errno::EACCES) {
- GDBM.open("tmptest_gdbm", 0)
- }
- gdbm.close
- end
-
- def test_close
- assert_instance_of(GDBM, gdbm = GDBM.open("tmptest_gdbm"))
- assert_nil(gdbm.close)
-
- # closed GDBM file
- assert_exception(RuntimeError) { gdbm.close }
- end
-
- def test_aref
- assert_equals('bar', @gdbm['foo'] = 'bar')
- assert_equals('bar', @gdbm['foo'])
-
- assert_nil(@gdbm['bar'])
- end
-
- def test_fetch
- assert_equals('bar', @gdbm['foo']='bar')
- assert_equals('bar', @gdbm.fetch('foo'))
-
- # key not found
- assert_exception(IndexError) {
- @gdbm.fetch('bar')
- }
-
- # test for `ifnone' arg
- assert_equals('baz', @gdbm.fetch('bar', 'baz'))
-
- # test for `ifnone' block
- assert_equals('foobar', @gdbm.fetch('bar') {|key| 'foo' + key })
- end
-
- def test_aset
- num = 0
- 2.times {|i|
- assert_equals('foo', @gdbm['foo'] = 'foo')
- assert_equals('foo', @gdbm['foo'])
- assert_equals('bar', @gdbm['foo'] = 'bar')
- assert_equals('bar', @gdbm['foo'])
-
- num += 1 if i == 0
- assert_equals(num, @gdbm.size)
-
- # assign nil
- assert_equals('', @gdbm['bar'] = '')
- assert_equals('', @gdbm['bar'])
-
- num += 1 if i == 0
- assert_equals(num, @gdbm.size)
-
- # empty string
- assert_equals('', @gdbm[''] = '')
- assert_equals('', @gdbm[''])
-
- num += 1 if i == 0
- assert_equals(num, @gdbm.size)
-
- # Fixnum
- assert_equals('200', @gdbm['100'] = '200')
- assert_equals('200', @gdbm['100'])
-
- num += 1 if i == 0
- assert_equals(num, @gdbm.size)
-
- # Big key and value
- assert_equals('y' * 100, @gdbm['x' * 100] = 'y' * 100)
- assert_equals('y' * 100, @gdbm['x' * 100])
-
- num += 1 if i == 0
- assert_equals(num, @gdbm.size)
- }
- end
-
- def test_index
- assert_equals('bar', @gdbm['foo'] = 'bar')
- assert_equals('foo', @gdbm.index('bar'))
- assert_nil(@gdbm['bar'])
- end
-
- def test_indexes
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
- assert_equals(values.reverse, @gdbm.indexes(*keys.reverse))
- end
-
- def test_values_at
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
- assert_equals(values.reverse, @gdbm.values_at(*keys.reverse))
- end
-
- def test_select_with_block
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
- ret = @gdbm.select {|k,v|
- assert_equals(k.upcase, v)
- k != "bar"
- }
- assert_equals([['baz', 'BAZ'], ['foo', 'FOO']],
- ret.sort)
- end
-
- def test_length
- num = 10
- assert_equals(0, @gdbm.size)
- num.times {|i|
- i = i.to_s
- @gdbm[i] = i
- }
- assert_equals(num, @gdbm.size)
-
- @gdbm.shift
-
- assert_equals(num - 1, @gdbm.size)
- end
-
- def test_empty?
- assert_equals(true, @gdbm.empty?)
- @gdbm['foo'] = 'FOO'
- assert_equals(false, @gdbm.empty?)
- end
-
- def test_each_pair
- n = 0
- @gdbm.each_pair { n += 1 }
- assert_equals(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
-
- n = 0
- ret = @gdbm.each_pair {|key, val|
- assert_not_nil(i = keys.index(key))
- assert_equals(val, values[i])
-
- n += 1
- }
- assert_equals(keys.size, n)
- assert_equals(@gdbm, ret)
- end
-
- def test_each_value
- n = 0
- @gdbm.each_value { n += 1 }
- assert_equals(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
-
- n = 0
- ret = @gdbm.each_value {|val|
- assert_not_nil(key = @gdbm.index(val))
- assert_not_nil(i = keys.index(key))
- assert_equals(val, values[i])
-
- n += 1
- }
- assert_equals(keys.size, n)
- assert_equals(@gdbm, ret)
- end
-
- def test_each_key
- n = 0
- @gdbm.each_key { n += 1 }
- assert_equals(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
-
- n = 0
- ret = @gdbm.each_key {|key|
- assert_not_nil(i = keys.index(key))
- assert_equals(@gdbm[key], values[i])
-
- n += 1
- }
- assert_equals(keys.size, n)
- assert_equals(@gdbm, ret)
- end
-
- def test_keys
- assert_equals([], @gdbm.keys)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
-
- assert_equals(keys.sort, @gdbm.keys.sort)
- assert_equals(values.sort, @gdbm.values.sort)
- end
-
- def test_values
- test_keys
- end
-
- def test_shift
- assert_nil(@gdbm.shift)
- assert_equals(0, @gdbm.size)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
-
- ret_keys = []
- ret_values = []
- while ret = @gdbm.shift
- ret_keys.push ret[0]
- ret_values.push ret[1]
-
- assert_equals(keys.size - ret_keys.size, @gdbm.size)
- end
-
- assert_equals(keys.sort, ret_keys.sort)
- assert_equals(values.sort, ret_values.sort)
- end
-
- def test_delete
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- key = keys[1]
-
- assert_nil(@gdbm.delete(key))
- assert_equals(0, @gdbm.size)
-
- @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
-
- assert_equals('BAR', @gdbm.delete(key))
- assert_nil(@gdbm[key])
- assert_equals(2, @gdbm.size)
-
- assert_nil(@gdbm.delete(key))
-
- if /^CYGWIN_9/ !~ SYSTEM
- assert_exception(GDBMError) {
- @gdbm_rdonly.delete("foo")
- }
-
- assert_nil(@gdbm_rdonly.delete("bar"))
- end
- end
- def test_delete_with_block
- key = 'no called block'
- @gdbm[key] = 'foo'
- assert_equals('foo', @gdbm.delete(key) {|k| k.replace 'called block'})
- assert_equals('no called block', key)
- assert_equals(0, @gdbm.size)
-
- key = 'no called block'
- assert_equals(:blockval,
- @gdbm.delete(key) {|k| k.replace 'called block'; :blockval})
- assert_equals('called block', key)
- assert_equals(0, @gdbm.size)
- end
-
- def test_delete_if
- v = "0"
- 100.times {@gdbm[v] = v; v = v.next}
-
- ret = @gdbm.delete_if {|key, val| key.to_i < 50}
- assert_equals(@gdbm, ret)
- check_size(50, @gdbm)
-
- ret = @gdbm.delete_if {|key, val| key.to_i >= 50}
- assert_equals(@gdbm, ret)
- check_size(0, @gdbm)
-
- # break
- v = "0"
- 100.times {@gdbm[v] = v; v = v.next}
- check_size(100, @gdbm)
- n = 0;
- @gdbm.delete_if {|key, val|
- break if n > 50
- n+=1
- true
- }
- assert_equals(51, n)
- check_size(49, @gdbm)
-
- @gdbm.clear
-
- # raise
- v = "0"
- 100.times {@gdbm[v] = v; v = v.next}
- check_size(100, @gdbm)
- n = 0;
- begin
- @gdbm.delete_if {|key, val|
- raise "runtime error" if n > 50
- n+=1
- true
- }
- rescue
- end
- assert_equals(51, n)
- check_size(49, @gdbm)
- end
-
- def test_reject
- v = "0"
- 100.times {@gdbm[v] = v; v = v.next}
-
- hash = @gdbm.reject {|key, val| key.to_i < 50}
- assert_instance_of(Hash, hash)
- assert_equals(100, @gdbm.size)
-
- assert_equals(50, hash.size)
- hash.each_pair {|key,val|
- assert_equals(false, key.to_i < 50)
- assert_equals(key, val)
- }
-
- hash = @gdbm.reject {|key, val| key.to_i < 100}
- assert_instance_of(Hash, hash)
- assert_equals(true, hash.empty?)
- end
-
- def test_clear
- v = "1"
- 100.times {v = v.next; @gdbm[v] = v}
-
- assert_equals(@gdbm, @gdbm.clear)
-
- # validate GDBM#size
- i = 0
- @gdbm.each { i += 1 }
- assert_equals(@gdbm.size, i)
- assert_equals(0, i)
- end
-
- def test_invert
- v = "0"
- 100.times {@gdbm[v] = v; v = v.next}
-
- hash = @gdbm.invert
- assert_instance_of(Hash, hash)
- assert_equals(100, hash.size)
- hash.each_pair {|key, val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_update
- hash = {}
- v = "0"
- 100.times {v = v.next; hash[v] = v}
-
- @gdbm["101"] = "101"
- @gdbm.update hash
- assert_equals(101, @gdbm.size)
- @gdbm.each_pair {|key, val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_replace
- hash = {}
- v = "0"
- 100.times {v = v.next; hash[v] = v}
-
- @gdbm["101"] = "101"
- @gdbm.replace hash
- assert_equals(100, @gdbm.size)
- @gdbm.each_pair {|key, val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_reorganize
- size1 = File.size(@path)
- i = "1"
- 1000.times {i = i.next; @gdbm[i] = i}
- @gdbm.clear
- @gdbm.sync
-
- size2 = File.size(@path)
- @gdbm.reorganize
- size3 = File.size(@path)
-
- # p [size1, size2, size3]
- assert_equals(true, size1 < size2)
- # this test is failed on Cygwin98. `GDBM version 1.8.0, as of May 19, 1999'
- assert_equals(true, size3 < size2)
- assert_equals(size1, size3)
- end
-
- def test_sync
- assert_instance_of(GDBM, gdbm = GDBM.open('tmptest_gdbm', 0666, GDBM::FAST))
- assert_equals(gdbm.sync, gdbm)
- gdbm.close
- assert_instance_of(GDBM, gdbm = GDBM.open('tmptest_gdbm', 0666))
- assert_equals(gdbm.sync, gdbm)
- gdbm.close
- end
-
- def test_cachesize=
- assert_equals(@gdbm.cachesize = 1024, 1024)
- end
-
- def test_fastmode=
- assert_equals(@gdbm.fastmode = true, true)
- end
-
- def test_syncmode=
- assert_equals(@gdbm.syncmode = true, true)
- end
-
- def test_haskey?
- assert_equals('bar', @gdbm['foo']='bar')
- assert_equals(true, @gdbm.has_key?('foo'))
- assert_equals(false, @gdbm.has_key?('bar'))
- end
-
- def test_has_value?
- assert_equals('bar', @gdbm['foo']='bar')
- assert_equals(true, @gdbm.has_value?('bar'))
- assert_equals(false, @gdbm.has_value?('foo'))
- end
-
- def test_to_a
- v = "0"
- 100.times {v = v.next; @gdbm[v] = v}
-
- ary = @gdbm.to_a
- assert_instance_of(Array, ary)
- assert_equals(100, ary.size)
- ary.each {|key,val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_to_hash
- v = "0"
- 100.times {v = v.next; @gdbm[v] = v}
-
- hash = @gdbm.to_hash
- assert_instance_of(Hash, hash)
- assert_equals(100, hash.size)
- hash.each {|key,val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-end
-
-if $0 == __FILE__
- if ARGV.size == 0
- suite = RUNIT::TestSuite.new
- suite.add_test(TestGDBM.suite)
- else
- suite = RUNIT::TestSuite.new
- ARGV.each do |testmethod|
- suite.add_test(TestGDBM.new(testmethod))
- end
- end
-
- RUNIT::CUI::TestRunner.run(suite)
-end
diff --git a/ext/iconv/.cvsignore b/ext/iconv/.cvsignore
index 4088712231..394787fced 100644
--- a/ext/iconv/.cvsignore
+++ b/ext/iconv/.cvsignore
@@ -1,3 +1,5 @@
Makefile
mkmf.log
*.def
+iconv.rb
+config.charset
diff --git a/ext/iconv/MANIFEST b/ext/iconv/MANIFEST
deleted file mode 100644
index fd7e22deda..0000000000
--- a/ext/iconv/MANIFEST
+++ /dev/null
@@ -1,5 +0,0 @@
-MANIFEST
-extconf.rb
-iconv.c
-depend
-charset_alias.rb
diff --git a/ext/iconv/charset_alias.rb b/ext/iconv/charset_alias.rb
index 48f0fae5f9..aed4644290 100644
--- a/ext/iconv/charset_alias.rb
+++ b/ext/iconv/charset_alias.rb
@@ -1,39 +1,103 @@
#! /usr/bin/ruby
+# :stopdoc:
require 'rbconfig'
+require 'optparse'
# http://www.ctan.org/tex-archive/macros/texinfo/texinfo/intl/config.charset
# Fri, 30 May 2003 00:09:00 GMT'
-OS = Config::CONFIG["target"]
+OS = Config::CONFIG["target_os"]
SHELL = Config::CONFIG['SHELL']
+class Hash::Ordered < Hash
+ def [](key)
+ val = super and val.last
+ end
+ def []=(key, val)
+ ary = fetch(key) {return super(key, [self.size, key, val])} and
+ ary << val
+ end
+ def sort
+ values.sort.collect {|i, *rest| rest}
+ end
+ def each(&block)
+ sort.each(&block)
+ end
+end
+
def charset_alias(config_charset, mapfile, target = OS)
- map = {}
+ map = Hash::Ordered.new
comments = []
- IO.foreach("|#{SHELL} #{config_charset} #{target}") do |list|
- next comments << list if /^\#/ =~ list
- next unless /^(\S+)\s+(\S+)$/ =~ list
- sys, can = $1, $2
- next if sys == can
- next if can.downcase! and sys == can
- map[can] = sys
+ open(config_charset) do |input|
+ input.find {|line| /^case "\$os" in/ =~ line} or break
+ input.find {|line|
+ /^\s*([-\w\*]+(?:\s*\|\s*[-\w\*]+)*)(?=\))/ =~ line and
+ $&.split('|').any? {|pattern| File.fnmatch?(pattern.strip, target)}
+ } or break
+ input.find do |line|
+ case line
+ when /^\s*echo "(?:\$\w+\.)?([-\w*]+)\s+([-\w]+)"/
+ sys, can = $1, $2
+ can.downcase!
+ map[can] = sys
+ false
+ when /^\s*;;/
+ true
+ else
+ false
+ end
+ end
end
case target
when /linux|-gnu/
- map.delete('ascii')
- when /cygwin/
+ # map.delete('ascii')
+ when /cygwin|os2-emx/
# get rid of tilde/yen problem.
map['shift_jis'] = 'cp932'
end
- open(mapfile, "w") do |f|
+ st = Hash.new(0)
+ map = map.sort.collect do |can, *sys|
+ if sys.grep(/^en_us(?=.|$)/i) {break true} == true
+ noen = %r"^(?!en_us)\w+_\w+#{Regexp.new($')}$"i #"
+ sys.reject! {|s| noen =~ s}
+ end
+ sys = sys.first
+ st[sys] += 1
+ [can, sys]
+ end
+ st.delete_if {|sys, i| i == 1}.empty?
+ st.keys.each {|sys| st[sys] = nil}
+ st.default = nil
+ writer = proc do |f|
f.puts("require 'iconv.so'")
f.puts
f.puts(comments)
f.puts("class Iconv")
- map.each {|can, sys| f.puts(" charset_map['#{can}'.freeze] = '#{sys}'.freeze")}
+ i = 0
+ map.each do |can, sys|
+ if s = st[sys]
+ sys = s
+ elsif st.key?(sys)
+ sys = (st[sys] = "sys#{i+=1}") + " = '#{sys}'.freeze"
+ else
+ sys = "'#{sys}'.freeze"
+ end
+ f.puts(" charset_map['#{can}'] = #{sys}")
+ end
f.puts("end")
end
+ if mapfile
+ open(mapfile, "w", &writer)
+ else
+ writer[STDOUT]
+ end
end
-(2..3) === ARGV.size or abort "usage: #$0 config.status map.rb [target]"
-charset_alias(*ARGV)
+target = OS
+opt = nil
+ARGV.options do |opt|
+ opt.banner << " config.status map.rb"
+ opt.on("--target OS") {|t| target = t}
+ opt.parse! and (1..2) === ARGV.size
+end or abort opt.to_s
+charset_alias(ARGV[0], ARGV[1], target)
diff --git a/ext/iconv/extconf.rb b/ext/iconv/extconf.rb
index 7176fa45e3..a9d0cfb5e6 100644
--- a/ext/iconv/extconf.rb
+++ b/ext/iconv/extconf.rb
@@ -5,39 +5,47 @@ dir_config("iconv")
conf = File.exist?(File.join($srcdir, "config.charset"))
conf = with_config("config-charset", enable_config("config-charset", conf))
-if have_header("iconv.h")
- if !try_compile("", "-Werror") or checking_for("iconv() 2nd argument is const") do
- !try_compile('
-#include <iconv.h>
-size_t
-test(iconv_t cd, char **inptr, size_t *inlen, char **outptr, size_t *outlen)
-{
- return iconv(cd, inptr, inlen, outptr, outlen);
-}
-', "-Werror")
+if have_func("iconv", "iconv.h") or
+ have_library("iconv", "iconv", "iconv.h")
+ if checking_for("const of iconv() 2nd argument") do
+ create_tmpsrc(cpp_include("iconv.h") + "---> iconv(cd,0,0,0,0) <---")
+ src = xpopen(cpp_command("")) {|f|f.read}
+ if !(func = src[/^--->\s*(\w+).*\s*<---/, 1])
+ Logging::message "iconv function name not found"
+ false
+ elsif !(second = src[%r"\b#{func}\s*\(.*?,(.*?),.*?\)\s*;"m, 1])
+ Logging::message "prototype for #{func}() not found"
+ false
+ else
+ Logging::message $&+"\n"
+ /\bconst\b/ =~ second
+ end
end
- $defs.push('-DICONV_INPTR_CAST=""')
- else
- $defs.push('-DICONV_INPTR_CAST="(char **)"')
+ $defs.push('-DICONV_INPTR_CONST')
end
- have_library("iconv")
if conf
prefix = '$(srcdir)'
prefix = $nmake ? "{#{prefix}}" : "#{prefix}/"
- $INSTALLFILES = [["./iconv.rb", "$(RUBYLIBDIR)"]]
+ if $extout
+ wrapper = "$(RUBYARCHDIR)/iconv.rb"
+ else
+ wrapper = "./iconv.rb"
+ $INSTALLFILES = [[wrapper, "$(RUBYARCHDIR)"]]
+ end
if String === conf
require 'uri'
scheme = URI.parse(conf).scheme
else
- conf = prefix + "config.charset"
+ conf = "$(srcdir)/config.charset"
end
+ $cleanfiles << wrapper
end
create_makefile("iconv")
if conf
open("Makefile", "a") do |mf|
- mf.print("\nall: iconv.rb\n\niconv.rb: ", prefix, "charset_alias.rb")
+ mf.print("\nall: #{wrapper}\n\n#{wrapper}: #{prefix}charset_alias.rb")
mf.print(" ", conf) unless scheme
- mf.print("\n\t$(RUBY) ", prefix, "charset_alias.rb ", conf, " $@\n")
+ mf.print("\n\t$(RUBY) $(srcdir)/charset_alias.rb #{conf} $@\n")
end
end
end
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index 8e978b8730..d989b97df2 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -10,27 +10,9 @@
All the files in this distribution are covered under the Ruby's
license (see the file COPYING).
-**********************************************************************/
-
-/*
-=begin
-= Summary
-Ruby extension for codeset conversion.
-
-= Abstract
-Iconv is a wrapper class for UNIX 95 (({iconv()})) function family, which
-translates string between various coding systems.
-
-See ((<Open Group|URL:http://www.opengroup.org/>))'s on-line documents for more details.
-* ((<iconv.h|URL:http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.h.html>))
-* ((<iconv_open()|URL:http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_open.html>))
-* ((<iconv()|URL:http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html>))
-* ((<iconv_close()|URL:http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_close.html>))
+ Documentation by Yukihiro Matsumoto and Gavin Sinclair.
-Which coding systems are available, it depends on the platform.
-
-=end
-*/
+**********************************************************************/
#include "ruby.h"
#include <errno.h>
@@ -39,6 +21,54 @@ Which coding systems are available, it depends on the platform.
#include "st.h"
#include "intern.h"
+/*
+ * Document-class: Iconv
+ *
+ * == Summary
+ *
+ * Ruby extension for charset conversion.
+ *
+ * == Abstract
+ *
+ * Iconv is a wrapper class for the UNIX 95 <tt>iconv()</tt> function family,
+ * which translates string between various encoding systems.
+ *
+ * See Open Group's on-line documents for more details.
+ * * <tt>iconv.h</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.h.html
+ * * <tt>iconv_open()</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_open.html
+ * * <tt>iconv()</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html
+ * * <tt>iconv_close()</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_close.html
+ *
+ * Which coding systems are available is platform-dependent.
+ *
+ * == Examples
+ *
+ * 1. Simple conversion between two charsets.
+ *
+ * converted_text = Iconv.conv('iso-8859-15', 'utf-8', text)
+ *
+ * 2. Instantiate a new Iconv and use method Iconv#iconv.
+ *
+ * cd = Iconv.new(to, from)
+ * begin
+ * input.each { |s| output << cd.iconv(s) }
+ * output << cd.iconv(nil) # Don't forget this!
+ * ensure
+ * cd.close
+ * end
+ *
+ * 3. Invoke Iconv.open with a block.
+ *
+ * Iconv.open(to, from) do |cd|
+ * input.each { |s| output << cd.iconv(s) }
+ * output << cd.iconv(nil)
+ * end
+ *
+ * 4. Shorthand for (3).
+ *
+ * Iconv.iconv(to, from, *input.to_a)
+ */
+
/* Invalid value for iconv_t is -1 but 0 for VALUE, I hope VALUE is
big enough to keep iconv_t */
#define VALUE2ICONV(v) ((iconv_t)((VALUE)(v) ^ -1))
@@ -53,10 +83,12 @@ struct iconv_env_t
VALUE (*append)_((VALUE, VALUE));
};
+static VALUE rb_eIconvInvalidEncoding;
static VALUE rb_eIconvFailure;
static VALUE rb_eIconvIllegalSeq;
static VALUE rb_eIconvInvalidChar;
static VALUE rb_eIconvOutOfRange;
+static VALUE rb_eIconvBrokenLibrary;
static ID rb_success, rb_failed;
static VALUE iconv_fail _((VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, const char *mesg));
@@ -69,7 +101,7 @@ static void iconv_dfree _((void *cd));
static VALUE iconv_free _((VALUE cd));
static VALUE iconv_try _((iconv_t cd, const char **inptr, size_t *inlen, char **outptr, size_t *outlen));
static VALUE rb_str_derive _((VALUE str, const char* ptr, int len));
-static VALUE iconv_convert _((iconv_t cd, VALUE str, int start, int length, struct iconv_env_t* env));
+static VALUE iconv_convert _((iconv_t cd, VALUE str, long start, long length, struct iconv_env_t* env));
static VALUE iconv_s_allocate _((VALUE klass));
static VALUE iconv_initialize _((VALUE self, VALUE to, VALUE from));
static VALUE iconv_s_open _((VALUE self, VALUE to, VALUE from));
@@ -79,20 +111,14 @@ static VALUE iconv_init_state _((VALUE cd));
static VALUE iconv_finish _((VALUE self));
static VALUE iconv_iconv _((int argc, VALUE *argv, VALUE self));
-
-/*
-=begin
-= Classes & Modules
-=end
-*/
-
-/*
-=begin
-== Iconv
-=end
-*/
static VALUE charset_map;
+/*
+ * Document-method: charset_map
+ * call-seq: Iconv.charset_map
+ *
+ * Returns the map from canonical name to system dependent name.
+ */
static VALUE charset_map_get _((void))
{
return charset_map;
@@ -110,17 +136,13 @@ map_charset
VALUE val = *code;
if (RHASH(charset_map)->tbl && RHASH(charset_map)->tbl->num_entries) {
- val = rb_funcall2(val, rb_intern("downcase"), 0, 0);
- StringValuePtr(val);
- if (st_lookup(RHASH(charset_map)->tbl, val, &val)) {
- StringValuePtr(val);
+ VALUE key = rb_funcall2(val, rb_intern("downcase"), 0, 0);
+ StringValuePtr(key);
+ if (st_lookup(RHASH(charset_map)->tbl, key, &val)) {
*code = val;
}
}
- else {
- StringValuePtr(val);
- }
- return RSTRING(val)->ptr;
+ return StringValuePtr(*code);
}
static iconv_t
@@ -147,10 +169,18 @@ iconv_create
cd = iconv_open(tocode, fromcode);
}
if (cd == (iconv_t)-1) {
- volatile VALUE msg = rb_str_new2("iconv(\"");
- rb_str_buf_cat2(rb_str_buf_append(msg, to), "\", \"");
- rb_str_buf_cat2(rb_str_buf_append(msg, from), "\")");
- rb_sys_fail(StringValuePtr(msg));
+ int inval = errno == EINVAL;
+ const char *s = inval ? "invalid encoding " : "iconv";
+ volatile VALUE msg = rb_str_new(0, strlen(s) + RSTRING(to)->len +
+ RSTRING(from)->len + 8);
+
+ sprintf(RSTRING(msg)->ptr, "%s(\"%s\", \"%s\")",
+ s, RSTRING(to)->ptr, RSTRING(from)->ptr);
+ s = RSTRING(msg)->ptr;
+ RSTRING(msg)->len = strlen(s);
+ if (!inval) rb_sys_fail(s);
+ iconv_fail(rb_eIconvInvalidEncoding,
+ Qnil, rb_ary_new3(2, to, from), NULL, s);
}
}
@@ -214,7 +244,15 @@ iconv_try
size_t *outlen;
#endif /* HAVE_PROTOTYPES */
{
- size_t ret = iconv(cd, ICONV_INPTR_CAST inptr, inlen, outptr, outlen);
+#ifdef ICONV_INPTR_CONST
+#define ICONV_INPTR_CAST
+#else
+#define ICONV_INPTR_CAST (char **)
+#endif
+ size_t ret;
+
+ errno = 0;
+ ret = iconv(cd, ICONV_INPTR_CAST inptr, inlen, outptr, outlen);
if (ret == (size_t)-1) {
if (!*inlen)
return Qfalse;
@@ -226,6 +264,8 @@ iconv_try
return rb_eIconvIllegalSeq;
case EINVAL:
return rb_eIconvInvalidChar;
+ case 0:
+ return rb_eIconvBrokenLibrary;
default:
rb_sys_fail("iconv");
}
@@ -322,13 +362,13 @@ rb_str_derive
static VALUE
iconv_convert
#ifdef HAVE_PROTOTYPES
- (iconv_t cd, VALUE str, int start, int length, struct iconv_env_t* env)
+ (iconv_t cd, VALUE str, long start, long length, struct iconv_env_t* env)
#else /* HAVE_PROTOTYPES */
(cd, str, start, length, env)
iconv_t cd;
VALUE str;
- int start;
- int length;
+ long start;
+ long length;
struct iconv_env_t *env;
#endif /* HAVE_PROTOTYPES */
{
@@ -377,14 +417,9 @@ iconv_convert
slen = RSTRING(str)->len;
inptr = RSTRING(str)->ptr;
- if (start < 0 ? (start += slen) < 0 : start >= slen)
- length = 0;
- else if (length < 0 && (length += slen + 1) < 0)
- length = 0;
- else if ((length -= start) < 0)
- length = 0;
- else
- inptr += start;
+ inptr += start;
+ if (length < 0 || length > start + slen)
+ length = slen - start;
}
instart = inptr;
inlen = length;
@@ -426,7 +461,7 @@ iconv_convert
}
else {
/* Some iconv() have a bug, return *outlen out of range */
- sprintf(errmsg, "bug?(output length = %d)", sizeof(buffer) - outlen);
+ sprintf(errmsg, "bug?(output length = %ld)", (long)(sizeof(buffer) - outlen));
error = rb_eIconvOutOfRange;
}
@@ -463,36 +498,6 @@ iconv_convert
return ret;
}
-
-/*
-=begin
-=== Class methods
-=end
-*/
-/*
-=begin
---- Iconv.new(to, from) {|cd| ...}
- Creates new code converter from a coding-system designated with ((|from|))
- to another one designated with ((|to|)).
- :Parameters
- :((|to|))
- coding-system name for destination.
- :((|from|))
- coding-system name for source.
- :Exceptions
- :(({TypeError}))
- if ((|to|)) or ((|from|)) aren't String
- :(({ArgumentError}))
- if designated converter couldn't find out.
- :(({SystemCallError}))
- when (({iconv_open(3)})) failed.
-
---- Iconv.open(to, from)
- Equivalents to ((<Iconv.new>)) except with in the case of called
- with a block, yields with the new instance and closes it, and
- returns the result which returned from the block.
-=end
-*/
static VALUE
iconv_s_allocate
#ifdef HAVE_PROTOTYPES
@@ -505,6 +510,24 @@ iconv_s_allocate
return Data_Wrap_Struct(klass, 0, ICONV_FREE, 0);
}
+/*
+ * Document-method: new
+ * call-seq: Iconv.new(to, from)
+ *
+ * Creates new code converter from a coding-system designated with +from+
+ * to another one designated with +to+.
+ *
+ * === Parameters
+ *
+ * +to+:: encoding name for destination
+ * +from+:: encoding name for source
+ *
+ * === Exceptions
+ *
+ * TypeError:: if +to+ or +from+ aren't String
+ * InvalidEncoding:: if designated converter couldn't find out
+ * SystemCallError:: if <tt>iconv_open(3)</tt> fails
+ */
static VALUE
iconv_initialize
#ifdef HAVE_PROTOTYPES
@@ -522,6 +545,14 @@ iconv_initialize
return self;
}
+/*
+ * Document-method: open
+ * call-seq: Iconv.open(to, from) { |iconv| ... }
+ *
+ * Equivalent to Iconv.new except that when it is called with a block, it
+ * yields with the new instance and closes it, and returns the result which
+ * returned from the block.
+ */
static VALUE
iconv_s_open
#ifdef HAVE_PROTOTYPES
@@ -544,22 +575,6 @@ iconv_s_open
}
}
-/*
-=begin
---- Iconv.iconv(to, from, *strs)
- Shorthand for
- Iconv.open(to, from) {|cd| (strs + [nil]).collect {|s| cd.iconv(s)}}
- :Parameters
- :((|to|)), ((|from|))
- see ((<Iconv.new>)).
- :((|strs|))
- strings to be converted.
- :Exceptions
- exceptions thrown by ((<Iconv.new>)), ((<Iconv.open>)) and
- ((<Iconv#iconv>)).
-=end
-*/
-
static VALUE
iconv_s_convert
#ifdef HAVE_PROTOTYPES
@@ -585,6 +600,24 @@ iconv_s_convert
return env->ret;
}
+/*
+ * Document-method: Iconv::iconv
+ * call-seq: Iconv.iconv(to, from, *strs)
+ *
+ * Shorthand for
+ * Iconv.open(to, from) { |cd|
+ * (strs + [nil]).collect { |s| cd.iconv(s) }
+ * }
+ *
+ * === Parameters
+ *
+ * <tt>to, from</tt>:: see Iconv.new
+ * <tt>strs</tt>:: strings to be converted
+ *
+ * === Exceptions
+ *
+ * Exceptions thrown by Iconv.new, Iconv.open and Iconv#iconv.
+ */
static VALUE
iconv_s_iconv
#ifdef HAVE_PROTOTYPES
@@ -599,7 +632,7 @@ iconv_s_iconv
struct iconv_env_t arg;
if (argc < 2) /* needs `to' and `from' arguments at least */
- rb_raise(rb_eArgError, "wrong # of arguments (%d for %d)", argc, 2);
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, 2);
arg.argc = argc -= 2;
arg.argv = argv + 2;
@@ -609,6 +642,14 @@ iconv_s_iconv
return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
}
+/*
+ * Document-method: Iconv::conv
+ * call-seq: Iconv.conv(to, from, str)
+ *
+ * Shorthand for
+ * Iconv.iconv(to, from, str).join
+ * See Iconv.iconv.
+ */
static VALUE
iconv_s_conv
#ifdef HAVE_PROTOTYPES
@@ -628,23 +669,17 @@ iconv_s_conv
return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
}
-
/*
-=begin
-=== Instance methods
-=end
-*/
-/*
-=begin
---- Iconv#close
- Finishes conversion.
- * After calling this, invoking method ((<Iconv#iconv>)) will cause
- exception, but multiple calls of (({close})) are guaranteed to
- end successfully.
- * Returns a string contains the byte sequence to change the
- output buffer to its initial shift state.
-=end
-*/
+ * Document-method: close
+ *
+ * Finishes conversion.
+ *
+ * After calling this, calling Iconv#iconv will cause an exception, but
+ * multiple calls of #close are guaranteed to end successfully.
+ *
+ * Returns a string containing the byte sequence to change the output buffer to
+ * its initial shift state.
+ */
static VALUE
iconv_init_state
#ifdef HAVE_PROTOTYPES
@@ -675,30 +710,32 @@ iconv_finish
}
/*
-=begin
---- Iconv#iconv(str, [ start = 0, [ length = -1 ] ])
- Converts string and returns converted one.
- * In the case of ((|str|)) is (({String})), converts (({str[start, length]})).
- Returns converted string.
- * In the case of ((|str|)) is (({nil})), places ((|converter|))
- itself into initial shift state and just returns a string contains
- the byte sequence to change the output buffer to its initial shift
- state.
- * Otherwise, causes exception.
- :Parameters
- :((|str|))
- string to be converted or (({nil})).
- :((|start|))
- starting offset.
- :((|length|))
- conversion length,
- (({nil})) or (({-1})) means whole string from (({start})).
- :Exceptions
- * ((<Iconv::IllegalSequence>))
- * ((<Iconv::InvalidCharacter>))
- * ((<Iconv::OutOfRange>))
-=end
-*/
+ * Document-method: Iconv#iconv
+ * call-seq: iconv(str, start=0, length=-1)
+ *
+ * Converts string and returns the result.
+ * * If +str+ is a String, converts <tt>str[start, length]</tt> and returns the converted string.
+ * * If +str+ is +nil+, places converter itself into initial shift state and
+ * just returns a string containing the byte sequence to change the output
+ * buffer to its initial shift state.
+ * * Otherwise, raises an exception.
+ *
+ * === Parameters
+ *
+ * str:: string to be converted, or nil
+ * start:: starting offset
+ * length:: conversion length; nil or -1 means whole the string from start
+ *
+ * === Exceptions
+ *
+ * * IconvIllegalSequence
+ * * IconvInvalidCharacter
+ * * IconvOutOfRange
+ *
+ * === Examples
+ *
+ * See the Iconv documentation.
+ */
static VALUE
iconv_iconv
#ifdef HAVE_PROTOTYPES
@@ -712,39 +749,39 @@ iconv_iconv
{
VALUE str, n1, n2;
VALUE cd = check_iconv(self);
+ long start = 0, length = 0, slen = 0;
- n1 = n2 = Qnil;
rb_scan_args(argc, argv, "12", &str, &n1, &n2);
+ if (!NIL_P(str)) slen = RSTRING_LEN(StringValue(str));
+ if (argc != 2 || !RTEST(rb_range_beg_len(n1, &start, &length, slen, 0))) {
+ if (NIL_P(n1) || ((start = NUM2LONG(n1)) < 0 ? (start += slen) >= 0 : start < slen)) {
+ if (NIL_P(n2)) {
+ length = -1;
+ }
+ else if ((length = NUM2LONG(n2)) >= slen - start) {
+ length = slen - start;
+ }
+ }
+ }
- return iconv_convert(VALUE2ICONV(cd), str,
- NIL_P(n1) ? 0 : NUM2INT(n1),
- NIL_P(n2) ? -1 : NUM2INT(n1),
- NULL);
+ return iconv_convert(VALUE2ICONV(cd), str, start, length, NULL);
}
-
/*
-=begin
-= Exceptions
-=end
-*/
-/*
-=begin
-== Iconv::Failure
-Base exceptional attributes from ((<Iconv>)).
+ * Document-class: Iconv::Failure
+ *
+ * Base attributes for Iconv exceptions.
+ */
-=== Instance methods
-=end
-*/
/*
-=begin
---- Iconv::Failure#success
- Returns string(s) translated successfully until the exception occurred.
- * In the case of failure occurred within ((<Iconv.iconv>)), returned
- value is an array of strings translated successfully preceding
- failure and the last element is string on the way.
-=end
-*/
+ * Document-method: success
+ * call-seq: success
+ *
+ * Returns string(s) translated successfully until the exception occurred.
+ * * In the case of failure occurred within Iconv.iconv, returned
+ * value is an array of strings translated successfully preceding
+ * failure and the last element is string on the way.
+ */
static VALUE
iconv_failure_success
#ifdef HAVE_PROTOTYPES
@@ -758,12 +795,12 @@ iconv_failure_success
}
/*
-=begin
---- Iconv::Failure#failed
- Returns substring of the original string passed to ((<Iconv>)) that
- starts at the character caused the exception.
-=end
-*/
+ * Document-method: failed
+ * call-seq: failed
+ *
+ * Returns substring of the original string passed to Iconv that starts at the
+ * character caused the exception.
+ */
static VALUE
iconv_failure_failed
#ifdef HAVE_PROTOTYPES
@@ -777,11 +814,11 @@ iconv_failure_failed
}
/*
-=begin
---- Iconv::Failure#inspect
- Returns inspected string like as: #<(({type})): "(({success}))", "(({failed}))">
-=end
-*/
+ * Document-method: inspect
+ * call-seq: inspect
+ *
+ * Returns inspected string like as: #<_class_: _success_, _failed_>
+ */
static VALUE
iconv_failure_inspect
#ifdef HAVE_PROTOTYPES
@@ -791,7 +828,7 @@ iconv_failure_inspect
VALUE self;
#endif /* HAVE_PROTOTYPES */
{
- char *cname = rb_class2name(CLASS_OF(self));
+ const char *cname = rb_class2name(CLASS_OF(self));
VALUE success = rb_attr_get(self, rb_success);
VALUE failed = rb_attr_get(self, rb_failed);
VALUE str = rb_str_buf_cat2(rb_str_new2("#<"), cname);
@@ -803,40 +840,43 @@ iconv_failure_inspect
}
/*
- Hmmm, I don't like to write RD inside of function :-<.
-
-=begin
-== Iconv::IllegalSequence
-Input conversion stopped due to an input byte that does not belong to
-the input codeset, or the output codeset does not contain the
-character.
-=== Superclass
-(({ArgumentError}))
-=== Included Modules
-((<Iconv::Failure>))
-
-== Iconv::InvalidCharacter
-Input conversion stopped due to an incomplete character or shift
-sequence at the end of the input buffer.
-=== Superclass
-(({ArgumentError}))
-=== Included Modules
-((<Iconv::Failure>))
-
-== Iconv::OutOfRange
-Iconv library internal error. Must not occur.
-=== Superclass
-(({RuntimeError}))
-=== Included Modules
-((<Iconv::Failure>))
-=end
-*/
+ * Document-class: Iconv::InvalidEncoding
+ *
+ * Requested coding-system is not available on this system.
+ */
+
+/*
+ * Document-class: Iconv::IllegalSequence
+ *
+ * Input conversion stopped due to an input byte that does not belong to
+ * the input codeset, or the output codeset does not contain the
+ * character.
+ */
+
+/*
+ * Document-class: Iconv::InvalidCharacter
+ *
+ * Input conversion stopped due to an incomplete character or shift
+ * sequence at the end of the input buffer.
+ */
+
+/*
+ * Document-class: Iconv::OutOfRange
+ *
+ * Iconv library internal error. Must not occur.
+ */
+
+/*
+ * Document-class: Iconv::BrokenLibrary
+ *
+ * Detected a bug of underlying iconv(3) libray.
+ * * returns an error without setting errno properly
+ */
void
Init_iconv _((void))
{
VALUE rb_cIconv = rb_define_class("Iconv", rb_cData);
- VALUE metaclass = RBASIC(rb_cIconv)->klass;
rb_define_alloc_func(rb_cIconv, iconv_s_allocate);
rb_define_singleton_method(rb_cIconv, "open", iconv_s_open, 2);
@@ -852,39 +892,22 @@ Init_iconv _((void))
rb_define_method(rb_eIconvFailure, "failed", iconv_failure_failed, 0);
rb_define_method(rb_eIconvFailure, "inspect", iconv_failure_inspect, 0);
+ rb_eIconvInvalidEncoding = rb_define_class_under(rb_cIconv, "InvalidEncoding", rb_eArgError);
rb_eIconvIllegalSeq = rb_define_class_under(rb_cIconv, "IllegalSequence", rb_eArgError);
rb_eIconvInvalidChar = rb_define_class_under(rb_cIconv, "InvalidCharacter", rb_eArgError);
rb_eIconvOutOfRange = rb_define_class_under(rb_cIconv, "OutOfRange", rb_eRuntimeError);
+ rb_eIconvBrokenLibrary = rb_define_class_under(rb_cIconv, "BrokenLibrary", rb_eRuntimeError);
+ rb_include_module(rb_eIconvInvalidEncoding, rb_eIconvFailure);
rb_include_module(rb_eIconvIllegalSeq, rb_eIconvFailure);
rb_include_module(rb_eIconvInvalidChar, rb_eIconvFailure);
rb_include_module(rb_eIconvOutOfRange, rb_eIconvFailure);
+ rb_include_module(rb_eIconvBrokenLibrary, rb_eIconvFailure);
rb_success = rb_intern("success");
rb_failed = rb_intern("failed");
- charset_map = rb_hash_new();
rb_gc_register_address(&charset_map);
+ charset_map = rb_hash_new();
rb_define_singleton_method(rb_cIconv, "charset_map", charset_map_get, 0);
}
-
-/*
-=begin
-== Example
-(1) Instantiate a new ((<Iconv>)), use method ((<Iconv#iconv>)).
- cd = Iconv.new(to, from)
- begin
- input.each {|s| output << cd.iconv(s)}
- output << cd.iconv(nil) # don't forget this
- ensure
- cd.close
- end
-(2) Invoke ((<Iconv.open>)) with a block.
- Iconv.open(to, from) do |cd|
- input.each {|s| output << cd.iconv(s)}
- output << cd.iconv(nil)
- end
-(3) Shorthand for (2).
- Iconv.iconv(to, from, *input.to_a)
-=end
-*/
diff --git a/ext/io/wait/MANIFEST b/ext/io/wait/MANIFEST
deleted file mode 100644
index a08526c13a..0000000000
--- a/ext/io/wait/MANIFEST
+++ /dev/null
@@ -1,4 +0,0 @@
-MANIFEST
-extconf.rb
-wait.c
-lib/nonblock.rb
diff --git a/ext/io/wait/extconf.rb b/ext/io/wait/extconf.rb
index ea7dc9f6cf..e8181d25f5 100644
--- a/ext/io/wait/extconf.rb
+++ b/ext/io/wait/extconf.rb
@@ -3,10 +3,15 @@ target = "io/wait"
unless macro_defined?("DOSISH", "#include <ruby.h>")
fionread = %w[sys/ioctl.h sys/filio.h].find do |h|
- checking_for("FIONREAD") {macro_defined?("FIONREAD", "#include <#{h}>\n")}
+ have_macro("FIONREAD", h)
end
if fionread
$defs << "-DFIONREAD_HEADER=\"<#{fionread}>\""
create_makefile(target)
end
+else
+ if have_func("rb_w32_ioctlsocket", "ruby.h")
+ have_func("rb_w32_is_socket", "ruby.h")
+ create_makefile(target)
+ end
end
diff --git a/ext/io/wait/lib/nonblock.rb b/ext/io/wait/lib/nonblock.rb
index 46511fb40c..2103fdf25b 100644
--- a/ext/io/wait/lib/nonblock.rb
+++ b/ext/io/wait/lib/nonblock.rb
@@ -20,4 +20,4 @@ class IO
ensure
self.nonblock = nb
end
-end
+end if defined?(Fcntl::F_GETFL)
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index 53d5bd7d18..02cb54a014 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -15,7 +15,24 @@
#include "rubyio.h"
#include <sys/types.h>
+#if defined(FIONREAD_HEADER)
#include FIONREAD_HEADER
+#endif
+
+#ifdef HAVE_RB_W32_IOCTLSOCKET
+#define ioctl ioctlsocket
+#define ioctl_arg u_long
+#define ioctl_arg2num(i) ULONG2NUM(i)
+#else
+#define ioctl_arg int
+#define ioctl_arg2num(i) INT2NUM(i)
+#endif
+
+#ifdef HAVE_RB_W32_IS_SOCKET
+#define FIONREAD_POSSIBLE_P(fd) rb_w32_is_socket(fd)
+#else
+#define FIONREAD_POSSIBLE_P(fd) ((fd),Qtrue)
+#endif
static VALUE io_ready_p _((VALUE io));
static VALUE io_wait _((int argc, VALUE *argv, VALUE io));
@@ -39,17 +56,18 @@ static VALUE
io_ready_p(io)
VALUE io;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *fp;
- int n;
+ ioctl_arg n;
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
+ if (!FIONREAD_POSSIBLE_P(fileno(fptr->f))) return Qfalse;
fp = fptr->f;
if (feof(fp)) return Qfalse;
if (rb_read_pending(fp)) return Qtrue;
if (ioctl(fileno(fp), FIONREAD, &n)) rb_sys_fail(0);
- if (n > 0) return INT2NUM(n);
+ if (n > 0) return ioctl_arg2num(n);
return Qnil;
}
@@ -66,10 +84,11 @@ io_wait(argc, argv, io)
VALUE *argv;
VALUE io;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
fd_set rd;
FILE *fp;
- int fd, n;
+ int fd;
+ ioctl_arg n;
VALUE timeout;
struct timeval *tp, timerec;
@@ -93,6 +112,7 @@ io_wait(argc, argv, io)
if (rb_thread_select(fd + 1, &rd, NULL, NULL, tp) < 0)
rb_sys_fail(0);
rb_io_check_closed(fptr);
+ if (!FIONREAD_POSSIBLE_P(fileno(fptr->f))) return Qfalse;
if (ioctl(fileno(fp), FIONREAD, &n)) rb_sys_fail(0);
if (n > 0) return io;
return Qnil;
diff --git a/ext/nkf/MANIFEST b/ext/nkf/MANIFEST
deleted file mode 100644
index 5114a3762a..0000000000
--- a/ext/nkf/MANIFEST
+++ /dev/null
@@ -1,7 +0,0 @@
-MANIFEST
-depend
-extconf.rb
-lib/kconv.rb
-nkf.c
-nkf1.7/nkf.c
-test.rb
diff --git a/ext/nkf/depend b/ext/nkf/depend
index 13e32e6074..0ed8fea8d2 100644
--- a/ext/nkf/depend
+++ b/ext/nkf/depend
@@ -1 +1 @@
-nkf.o : nkf.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(srcdir)/nkf1.7/nkf.c
+nkf.o : nkf.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(srcdir)/nkf-utf8/nkf.c $(srcdir)/nkf-utf8/utf8tbl.c $(srcdir)/nkf-utf8/config.h
diff --git a/ext/nkf/lib/kconv.rb b/ext/nkf/lib/kconv.rb
index af6d82275f..4ffe8d984e 100644
--- a/ext/nkf/lib/kconv.rb
+++ b/ext/nkf/lib/kconv.rb
@@ -1,73 +1,367 @@
+#
+# kconv.rb - Kanji Converter.
+#
+# $Id$
+#
+# ----
+#
+# kconv.rb implements the Kconv class for Kanji Converter. Additionally,
+# some methods in String classes are added to allow easy conversion.
+#
+
require 'nkf'
+#
+# Kanji Converter for Ruby.
+#
module Kconv
+ #
+ # Public Constants
+ #
+
+ #Constant of Encoding
+
+ # Auto-Detect
AUTO = NKF::AUTO
+ # ISO-2022-JP
JIS = NKF::JIS
+ # EUC-JP
EUC = NKF::EUC
+ # Shift_JIS
SJIS = NKF::SJIS
+ # BINARY
BINARY = NKF::BINARY
+ # NOCONV
NOCONV = NKF::NOCONV
+ # ASCII
+ ASCII = NKF::ASCII
+ # UTF-8
+ UTF8 = NKF::UTF8
+ # UTF-16
+ UTF16 = NKF::UTF16
+ # UTF-32
+ UTF32 = NKF::UTF32
+ # UNKNOWN
UNKNOWN = NKF::UNKNOWN
+
+ #
+ # Private Constants
+ #
+
+ # Revision of kconv.rb
+ REVISION = %q$Revision$
+
+ #Regexp of Encoding
+
+ # Regexp of Shift_JIS string (private constant)
+ RegexpShiftjis = /\A(?:
+ [\x00-\x7f\xa1-\xdf] |
+ [\x81-\x9f\xe0-\xfc][\x40-\x7e\x80-\xfc]
+ )*\z/nx
+
+ # Regexp of EUC-JP string (private constant)
+ RegexpEucjp = /\A(?:
+ [\x00-\x7f] |
+ \x8e [\xa1-\xdf] |
+ \x8f [\xa1-\xfe] [\xa1-\xfe] |
+ [\xa1-\xfe] [\xa1-\xfe]
+ )*\z/nx
+
+ # Regexp of UTF-8 string (private constant)
+ RegexpUtf8 = /\A(?:
+ [\x00-\x7f] |
+ [\xc2-\xdf] [\x80-\xbf] |
+ \xe0 [\xa0-\xbf] [\x80-\xbf] |
+ [\xe1-\xef] [\x80-\xbf] [\x80-\xbf] |
+ \xf0 [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] |
+ [\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] |
+ \xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf]
+ )*\z/nx
+
+ #
+ # Public Methods
+ #
+
+ # call-seq:
+ # Kconv.kconv(str, out_code, in_code = Kconv::AUTO)
+ #
+ # Convert <code>str</code> to out_code.
+ # <code>out_code</code> and <code>in_code</code> are given as constants of Kconv.
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want to decode them, use NKF.nkf.
def kconv(str, out_code, in_code = AUTO)
opt = '-'
case in_code
- when NKF::JIS
+ when ::NKF::JIS
opt << 'J'
- when NKF::EUC
+ when ::NKF::EUC
opt << 'E'
- when NKF::SJIS
+ when ::NKF::SJIS
opt << 'S'
+ when ::NKF::UTF8
+ opt << 'W'
+ when ::NKF::UTF16
+ opt << 'W16'
end
case out_code
- when NKF::JIS
+ when ::NKF::JIS
opt << 'j'
- when NKF::EUC
+ when ::NKF::EUC
opt << 'e'
- when NKF::SJIS
+ when ::NKF::SJIS
opt << 's'
- when NKF::NOCONV
+ when ::NKF::UTF8
+ opt << 'w'
+ when ::NKF::UTF16
+ opt << 'w16'
+ when ::NKF::NOCONV
return str
end
opt = '' if opt == '-'
- NKF::nkf(opt, str)
+ ::NKF::nkf(opt, str)
end
module_function :kconv
+ #
+ # Encode to
+ #
+
+ # call-seq:
+ # Kconv.tojis(str) -> string
+ #
+ # Convert <code>str</code> to ISO-2022-JP
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-jxm0', str).
def tojis(str)
- NKF::nkf('-j', str)
+ ::NKF::nkf('-jm', str)
end
module_function :tojis
+ # call-seq:
+ # Kconv.toeuc(str) -> string
+ #
+ # Convert <code>str</code> to EUC-JP
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-exm0', str).
def toeuc(str)
- NKF::nkf('-e', str)
+ ::NKF::nkf('-em', str)
end
module_function :toeuc
+ # call-seq:
+ # Kconv.tosjis(str) -> string
+ #
+ # Convert <code>str</code> to Shift_JIS
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-sxm0', str).
def tosjis(str)
- NKF::nkf('-s', str)
+ ::NKF::nkf('-sm', str)
end
module_function :tosjis
+ # call-seq:
+ # Kconv.toutf8(str) -> string
+ #
+ # Convert <code>str</code> to UTF-8
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-wxm0', str).
+ def toutf8(str)
+ ::NKF::nkf('-wm', str)
+ end
+ module_function :toutf8
+
+ # call-seq:
+ # Kconv.toutf16(str) -> string
+ #
+ # Convert <code>str</code> to UTF-16
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-w16xm0', str).
+ def toutf16(str)
+ ::NKF::nkf('-w16m', str)
+ end
+ module_function :toutf16
+
+ #
+ # guess
+ #
+
+ # call-seq:
+ # Kconv.guess(str) -> integer
+ #
+ # Guess input encoding by NKF.guess2
def guess(str)
- NKF::guess(str)
+ ::NKF::guess(str)
end
module_function :guess
+
+ # call-seq:
+ # Kconv.guess_old(str) -> integer
+ #
+ # Guess input encoding by NKF.guess1
+ def guess_old(str)
+ ::NKF::guess1(str)
+ end
+ module_function :guess_old
+
+ #
+ # isEncoding
+ #
+
+ # call-seq:
+ # Kconv.iseuc(str) -> obj or nil
+ #
+ # Returns whether input encoding is EUC-JP or not.
+ #
+ # *Note* don't expect this return value is MatchData.
+ def iseuc(str)
+ RegexpEucjp.match( str )
+ end
+ module_function :iseuc
+
+ # call-seq:
+ # Kconv.issjis(str) -> obj or nil
+ #
+ # Returns whether input encoding is Shift_JIS or not.
+ #
+ # *Note* don't expect this return value is MatchData.
+ def issjis(str)
+ RegexpShiftjis.match( str )
+ end
+ module_function :issjis
+
+ # call-seq:
+ # Kconv.isutf8(str) -> obj or nil
+ #
+ # Returns whether input encoding is UTF-8 or not.
+ #
+ # *Note* don't expect this return value is MatchData.
+ def isutf8(str)
+ RegexpUtf8.match( str )
+ end
+ module_function :isutf8
+
end
class String
+ # call-seq:
+ # String#kconv(out_code, in_code = Kconv::AUTO)
+ #
+ # Convert <code>self</code> to out_code.
+ # <code>out_code</code> and <code>in_code</code> are given as constants of Kconv.
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want to decode them, use NKF.nkf.
def kconv(out_code, in_code=Kconv::AUTO)
Kconv::kconv(self, out_code, in_code)
end
- def tojis
- NKF::nkf('-j', self)
- end
- def toeuc
- NKF::nkf('-e', self)
- end
- def tosjis
- NKF::nkf('-s', self)
- end
+
+ #
+ # to Encoding
+ #
+
+ # call-seq:
+ # String#tojis -> string
+ #
+ # Convert <code>self</code> to ISO-2022-JP
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-jxm0', str).
+ def tojis; Kconv.tojis(self) end
+
+ # call-seq:
+ # String#toeuc -> string
+ #
+ # Convert <code>self</code> to EUC-JP
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-exm0', str).
+ def toeuc; Kconv.toeuc(self) end
+
+ # call-seq:
+ # String#tosjis -> string
+ #
+ # Convert <code>self</code> to Shift_JIS
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-sxm0', str).
+ def tosjis; Kconv.tosjis(self) end
+
+ # call-seq:
+ # String#toutf8 -> string
+ #
+ # Convert <code>self</code> to UTF-8
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-wxm0', str).
+ def toutf8; Kconv.toutf8(self) end
+
+ # call-seq:
+ # String#toutf16 -> string
+ #
+ # Convert <code>self</code> to UTF-16
+ #
+ # *Note*
+ # This method decode MIME encoded string and
+ # convert halfwidth katakana to fullwidth katakana.
+ # If you don't want it, use NKF.nkf('-w16xm0', str).
+ def toutf16; Kconv.toutf16(self) end
+
+ #
+ # is Encoding
+ #
+
+ # call-seq:
+ # String#iseuc -> obj or nil
+ #
+ # Returns whether <code>self</code>'s encoding is EUC-JP or not.
+ #
+ # *Note* don't expect this return value is MatchData.
+ def iseuc; Kconv.iseuc(self) end
+
+ # call-seq:
+ # String#issjis -> obj or nil
+ #
+ # Returns whether <code>self</code>'s encoding is Shift_JIS or not.
+ #
+ # *Note* don't expect this return value is MatchData.
+ def issjis; Kconv.issjis(self) end
+
+ # call-seq:
+ # String#isutf8 -> obj or nil
+ #
+ # Returns whether <code>self</code>'s encoding is UTF-8 or not.
+ #
+ # *Note* don't expect this return value is MatchData.
+ def isutf8; Kconv.isutf8(self) end
end
diff --git a/ext/nkf/nkf-utf8/config.h b/ext/nkf/nkf-utf8/config.h
new file mode 100644
index 0000000000..9da82c6aee
--- /dev/null
+++ b/ext/nkf/nkf-utf8/config.h
@@ -0,0 +1,88 @@
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+/* UTF8 $BF~=PNO(B */
+#define UTF8_INPUT_ENABLE
+#define UTF8_OUTPUT_ENABLE
+
+/* Shift_JIS $BHO0O30$NJ8;z$r!"(BCP932 $B$GF1CM$JJ8;z$KFI$_49$($k(B */
+#define SHIFTJIS_CP932
+
+/* $B%*%W%7%g%s$GF~NO$r;XDj$7$?;~$K!"J8;z%3!<%I$r8GDj$9$k(B */
+#define INPUT_CODE_FIX
+
+/* --overwrite $B%*%W%7%g%s(B */
+/* by Satoru Takabayashi <ccsatoru@vega.aichi-u.ac.jp> */
+#define OVERWRITE
+
+/* --cap-input, --url-input $B%*%W%7%g%s(B */
+#define INPUT_OPTION
+
+/* --numchar-input $B%*%W%7%g%s(B */
+#define NUMCHAR_OPTION
+
+/* --debug, --no-output $B%*%W%7%g%s(B */
+#define CHECK_OPTION
+
+/* JIS X0212 */
+#define X0212_ENABLE
+
+/* --exec-in, --exec-out $B%*%W%7%g%s(B
+ * pipe, fork, execvp $B$"$?$j$,L5$$$HF0$-$^$;$s!#(B
+ * MS-DOS, MinGW $B$J$I$G$O(B undef $B$K$7$F$/$@$5$$(B
+ * child process $B=*N;;~$N=hM}$,$$$$$+$2$s$J$N$G!"(B
+ * $B%G%U%)%k%H$GL58z$K$7$F$$$^$9!#(B
+ */
+/* #define EXEC_IO */
+
+/* SunOS $B$N(B cc $B$r;H$&$H$-$O(B undef $B$K$7$F$/$@$5$$(B */
+#define ANSI_C_PROTOTYPE
+
+/* int $B$,(B 32bit $BL$K~$N4D6-$G(B NUMCHAR_OPTION $B$r;H$&$K$O!"(B
+ * $B%3%a%s%H$r30$7$F$/$@$5$$!#(B
+ */
+/* #define INT_IS_SHORT */
+
+
+#if defined(INT_IS_SHORT)
+typedef long nkf_char;
+typedef unsigned char nkf_nfchar;
+#else
+typedef int nkf_char;
+typedef int nkf_nfchar;
+#endif
+
+/* Unicode Normalization */
+#define UNICODE_NORMALIZATION
+
+#ifndef WIN32DLL
+/******************************/
+/* $B%G%U%)%k%H$N=PNO%3!<%IA*Br(B */
+/* Select DEFAULT_CODE */
+#define DEFAULT_CODE_JIS
+/* #define DEFAULT_CODE_SJIS */
+/* #define DEFAULT_CODE_EUC */
+/* #define DEFAULT_CODE_UTF8 */
+/******************************/
+#else
+#define DEFAULT_CODE_SJIS
+#endif
+
+#if defined(NUMCHAR_OPTION) && !defined(UTF8_INPUT_ENABLE)
+#define UTF8_INPUT_ENABLE
+#endif
+
+#ifdef UNICODE_NORMALIZATION
+#ifndef UTF8_INPUT_ENABLE
+#define UTF8_INPUT_ENABLE
+#endif
+#define NORMALIZATION_TABLE_LENGTH 942
+#define NORMALIZATION_TABLE_NFC_LENGTH 3
+#define NORMALIZATION_TABLE_NFD_LENGTH 9
+struct normalization_pair{
+ const nkf_nfchar nfc[NORMALIZATION_TABLE_NFC_LENGTH];
+ const nkf_nfchar nfd[NORMALIZATION_TABLE_NFD_LENGTH];
+};
+#endif
+
+#endif /* _CONFIG_H_ */
diff --git a/ext/nkf/nkf-utf8/nkf.c b/ext/nkf/nkf-utf8/nkf.c
new file mode 100644
index 0000000000..9a31c9d879
--- /dev/null
+++ b/ext/nkf/nkf-utf8/nkf.c
@@ -0,0 +1,6040 @@
+/** Network Kanji Filter. (PDS Version)
+************************************************************************
+** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
+** $BO"Mm@h!'(B $B!J3t!KIY;NDL8&5f=j!!%=%U%H#38&!!;T@n!!;j(B
+** $B!J(BE-Mail Address: ichikawa@flab.fujitsu.co.jp$B!K(B
+** Copyright (C) 1996,1998
+** Copyright (C) 2002
+** $BO"Mm@h!'(B $BN05eBg3X>pJs9)3X2J(B $B2OLn(B $B??<#(B mime/X0208 support
+** $B!J(BE-Mail Address: kono@ie.u-ryukyu.ac.jp$B!K(B
+** $BO"Mm@h!'(B COW for DOS & Win16 & Win32 & OS/2
+** $B!J(BE-Mail Address: GHG00637@niftyserve.or.p$B!K(B
+**
+** $B$3$N%=!<%9$N$$$+$J$kJ#<L!$2~JQ!$=$@5$b5vBz$7$^$9!#$?$@$7!"(B
+** $B$=$N:]$K$O!"C/$,9W8%$7$?$r<($9$3$NItJ,$r;D$9$3$H!#(B
+** $B:FG[I[$d;(;o$NIUO?$J$I$NLd$$9g$o$;$bI,MW$"$j$^$;$s!#(B
+** $B1DMxMxMQ$b>e5-$KH?$7$J$$HO0O$G5v2D$7$^$9!#(B
+** $B%P%$%J%j$NG[I[$N:]$K$O(Bversion message$B$rJ]B8$9$k$3$H$r>r7o$H$7$^$9!#(B
+** $B$3$N%W%m%0%i%`$K$D$$$F$OFC$K2?$NJ]>Z$b$7$J$$!"0-$7$+$i$:!#(B
+**
+** Everyone is permitted to do anything on this program
+** including copying, modifying, improving,
+** as long as you don't try to pretend that you wrote it.
+** i.e., the above copyright notice has to appear in all copies.
+** Binary distribution requires original version messages.
+** You don't have to ask before copying, redistribution or publishing.
+** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
+***********************************************************************/
+
+/***********************************************************************
+** UTF-8 $B%5%]!<%H$K$D$$$F(B
+** $B=>Mh$N(B nkf $B$HF~$l$+$($F$=$N$^$^;H$($k$h$&$K$J$C$F$$$^$9(B
+** nkf -e $B$J$I$H$7$F5/F0$9$k$H!"<+F0H=JL$G(B UTF-8 $B$HH=Dj$5$l$l$P!"(B
+** $B$=$N$^$^(B euc-jp $B$KJQ49$5$l$^$9(B
+**
+** $B$^$@%P%0$,$"$k2DG=@-$,9b$$$G$9!#(B
+** ($BFC$K<+F0H=JL!"%3!<%I:.:_!"%(%i!<=hM}7O(B)
+**
+** $B2?$+LdBj$r8+$D$1$?$i!"(B
+** E-Mail: furukawa@tcp-ip.or.jp
+** $B$^$G8fO"Mm$r$*4j$$$7$^$9!#(B
+***********************************************************************/
+/* $Id$ */
+#define NKF_VERSION "2.0.8"
+#define NKF_RELEASE_DATE "2008-11-08"
+#include "config.h"
+#include "utf8tbl.h"
+
+#define COPY_RIGHT \
+ "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),2000 S. Kono, COW\n" \
+ "Copyright (C) 2002-2008 Kono, Furukawa, Naruse, mastodon"
+
+
+/*
+**
+**
+**
+** USAGE: nkf [flags] [file]
+**
+** Flags:
+** b Output is buffered (DEFAULT)
+** u Output is unbuffered
+**
+** t no operation
+**
+** j Output code is JIS 7 bit (DEFAULT SELECT)
+** s Output code is MS Kanji (DEFAULT SELECT)
+** e Output code is AT&T JIS (DEFAULT SELECT)
+** w Output code is AT&T JIS (DEFAULT SELECT)
+** l Output code is JIS 7bit and ISO8859-1 Latin-1
+**
+** m MIME conversion for ISO-2022-JP
+** I Convert non ISO-2022-JP charactor to GETA by Pekoe <pekoe@lair.net>
+** i_ Output sequence to designate JIS-kanji (DEFAULT_J)
+** o_ Output sequence to designate single-byte roman characters (DEFAULT_R)
+** M MIME output conversion
+**
+** r {de/en}crypt ROT13/47
+**
+** v display Version
+**
+** T Text mode output (for MS-DOS)
+**
+** x Do not convert X0201 kana into X0208
+** Z Convert X0208 alphabet to ASCII
+**
+** f60 fold option
+**
+** m MIME decode
+** B try to fix broken JIS, missing Escape
+** B[1-9] broken level
+**
+** O Output to 'nkf.out' file or last file name
+** d Delete \r in line feed
+** c Add \r in line feed
+** -- other long option
+** -- ignore following option (don't use with -O )
+**
+**/
+
+#if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || defined(__MINGW32__) || defined(__EMX__) || defined(__MSDOS__) || defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)) && !defined(MSDOS)
+#define MSDOS
+#if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__)
+#define __WIN32__
+#endif
+#endif
+
+#ifdef PERL_XS
+#undef OVERWRITE
+#endif
+
+#ifndef PERL_XS
+#include <stdio.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(MSDOS) || defined(__OS2__)
+#include <fcntl.h>
+#include <io.h>
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+#define mktemp _mktemp
+#endif
+#endif
+
+#ifdef MSDOS
+#ifdef LSI_C
+#define setbinmode(fp) fsetbin(fp)
+#elif defined(__DJGPP__)
+#include <libc/dosio.h>
+#define setbinmode(fp) djgpp_setbinmode(fp)
+#else /* Microsoft C, Turbo C */
+#define setbinmode(fp) setmode(fileno(fp), O_BINARY)
+#endif
+#else /* UNIX */
+#define setbinmode(fp)
+#endif
+
+#if defined(__DJGPP__)
+void djgpp_setbinmode(FILE *fp)
+{
+ /* we do not use libc's setmode(), which changes COOKED/RAW mode in device. */
+ int fd, m;
+ fd = fileno(fp);
+ m = (__file_handle_modes[fd] & (~O_TEXT)) | O_BINARY;
+ __file_handle_set(fd, m);
+}
+#endif
+
+#ifdef _IOFBF /* SysV and MSDOS, Windows */
+#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size)
+#else /* BSD */
+#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size)
+#endif
+
+/*Borland C++ 4.5 EasyWin*/
+#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
+#define EASYWIN
+#ifndef __WIN16__
+#define __WIN16__
+#endif
+#include <windows.h>
+#endif
+
+#ifdef OVERWRITE
+/* added by satoru@isoternet.org */
+#if defined(__EMX__)
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+#if !defined(MSDOS) || defined(__DJGPP__) /* UNIX, djgpp */
+#include <unistd.h>
+#if defined(__WATCOMC__)
+#include <sys/utime.h>
+#else
+#include <utime.h>
+#endif
+#else /* defined(MSDOS) */
+#ifdef __WIN32__
+#ifdef __BORLANDC__ /* BCC32 */
+#include <utime.h>
+#else /* !defined(__BORLANDC__) */
+#include <sys/utime.h>
+#endif /* (__BORLANDC__) */
+#else /* !defined(__WIN32__) */
+#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__) || defined(__OS2__) || defined(__EMX__) || defined(__IBMC__) || defined(__IBMCPP__) /* VC++, MinGW, Watcom, emx+gcc, IBM VAC++ */
+#include <sys/utime.h>
+#elif defined(__TURBOC__) /* BCC */
+#include <utime.h>
+#elif defined(LSI_C) /* LSI C */
+#endif /* (__WIN32__) */
+#endif
+#endif
+#endif
+
+#define FALSE 0
+#define TRUE 1
+
+/* state of output_mode and input_mode
+
+ c2 0 means ASCII
+ X0201
+ ISO8859_1
+ X0208
+ EOF all termination
+ c1 32bit data
+
+ */
+
+#define ASCII 0
+#define X0208 1
+#define X0201 2
+#define ISO8859_1 8
+#define NO_X0201 3
+#define X0212 0x2844
+#define X0213_1 0x284F
+#define X0213_2 0x2850
+
+/* Input Assumption */
+
+#define JIS_INPUT 4
+#define EUC_INPUT 16
+#define SJIS_INPUT 5
+#define LATIN1_INPUT 6
+#define FIXED_MIME 7
+#define STRICT_MIME 8
+
+/* MIME ENCODE */
+
+#define ISO2022JP 9
+#define JAPANESE_EUC 10
+#define SHIFT_JIS 11
+
+#define UTF8 12
+#define UTF8_INPUT 13
+#define UTF16_INPUT 1015
+#define UTF32_INPUT 1017
+
+/* byte order */
+
+#define ENDIAN_BIG 1234
+#define ENDIAN_LITTLE 4321
+#define ENDIAN_2143 2143
+#define ENDIAN_3412 3412
+
+#define WISH_TRUE 15
+
+/* ASCII CODE */
+
+#define BS 0x08
+#define TAB 0x09
+#define NL 0x0a
+#define CR 0x0d
+#define ESC 0x1b
+#define SPACE 0x20
+#define AT 0x40
+#define SSP 0xa0
+#define DEL 0x7f
+#define SI 0x0f
+#define SO 0x0e
+#define SSO 0x8e
+#define SS3 0x8f
+
+#define is_alnum(c) \
+ (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
+
+/* I don't trust portablity of toupper */
+#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c)
+#define nkf_isoctal(c) ('0'<=c && c<='7')
+#define nkf_isdigit(c) ('0'<=c && c<='9')
+#define nkf_isxdigit(c) (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
+#define nkf_isblank(c) (c == SPACE || c == TAB)
+#define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == NL)
+#define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
+#define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c))
+#define nkf_isprint(c) (' '<=c && c<='~')
+#define nkf_isgraph(c) ('!'<=c && c<='~')
+#define hex2bin(c) (('0'<=c&&c<='9') ? (c-'0') : \
+ ('A'<=c&&c<='F') ? (c-'A'+10) : \
+ ('a'<=c&&c<='f') ? (c-'a'+10) : 0 )
+#define is_eucg3(c2) (((unsigned short)c2 >> 8) == SS3)
+
+#define CP932_TABLE_BEGIN 0xFA
+#define CP932_TABLE_END 0xFC
+#define CP932INV_TABLE_BEGIN 0xED
+#define CP932INV_TABLE_END 0xEE
+#define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END)
+
+#define HOLD_SIZE 1024
+#if defined(INT_IS_SHORT)
+#define IOBUF_SIZE 2048
+#else
+#define IOBUF_SIZE 16384
+#endif
+
+#define DEFAULT_J 'B'
+#define DEFAULT_R 'B'
+
+#define SJ0162 0x00e1 /* 01 - 62 ku offset */
+#define SJ6394 0x0161 /* 63 - 94 ku offset */
+
+#define RANGE_NUM_MAX 18
+#define GETA1 0x22
+#define GETA2 0x2e
+
+
+#if defined(UTF8_OUTPUT_ENABLE) || defined(UTF8_INPUT_ENABLE)
+#define sizeof_euc_to_utf8_1byte 94
+#define sizeof_euc_to_utf8_2bytes 94
+#define sizeof_utf8_to_euc_C2 64
+#define sizeof_utf8_to_euc_E5B8 64
+#define sizeof_utf8_to_euc_2bytes 112
+#define sizeof_utf8_to_euc_3bytes 16
+#endif
+
+/* MIME preprocessor */
+
+#ifdef EASYWIN /*Easy Win */
+extern POINT _BufferSize;
+#endif
+
+struct input_code{
+ char *name;
+ nkf_char stat;
+ nkf_char score;
+ nkf_char index;
+ nkf_char buf[3];
+ void (*status_func)(struct input_code *, nkf_char);
+ nkf_char (*iconv_func)(nkf_char c2, nkf_char c1, nkf_char c0);
+ int _file_stat;
+};
+
+static char *input_codename = "";
+
+#ifndef PERL_XS
+static const char *CopyRight = COPY_RIGHT;
+#endif
+#if !defined(PERL_XS) && !defined(WIN32DLL)
+static nkf_char noconvert(FILE *f);
+#endif
+static void module_connection(void);
+static nkf_char kanji_convert(FILE *f);
+static nkf_char h_conv(FILE *f,nkf_char c2,nkf_char c1);
+static nkf_char push_hold_buf(nkf_char c2);
+static void set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0));
+static nkf_char s_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
+static nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1);
+static nkf_char e_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
+#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
+/* UCS Mapping
+ * 0: Shift_JIS, eucJP-ascii
+ * 1: eucJP-ms
+ * 2: CP932, CP51932
+ */
+#define UCS_MAP_ASCII 0
+#define UCS_MAP_MS 1
+#define UCS_MAP_CP932 2
+static int ms_ucs_map_f = UCS_MAP_ASCII;
+#endif
+#ifdef UTF8_INPUT_ENABLE
+/* no NEC special, NEC-selected IBM extended and IBM extended characters */
+static int no_cp932ext_f = FALSE;
+/* ignore ZERO WIDTH NO-BREAK SPACE */
+static int no_best_fit_chars_f = FALSE;
+static int input_endian = ENDIAN_BIG;
+static nkf_char unicode_subchar = '?'; /* the regular substitution character */
+static void nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c);
+static void encode_fallback_html(nkf_char c);
+static void encode_fallback_xml(nkf_char c);
+static void encode_fallback_java(nkf_char c);
+static void encode_fallback_perl(nkf_char c);
+static void encode_fallback_subchar(nkf_char c);
+static void (*encode_fallback)(nkf_char c) = NULL;
+static nkf_char w2e_conv(nkf_char c2,nkf_char c1,nkf_char c0,nkf_char *p2,nkf_char *p1);
+static nkf_char w_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
+static nkf_char w_iconv16(nkf_char c2,nkf_char c1,nkf_char c0);
+static nkf_char w_iconv32(nkf_char c2,nkf_char c1,nkf_char c0);
+static nkf_char unicode_to_jis_common(nkf_char c2,nkf_char c1,nkf_char c0,nkf_char *p2,nkf_char *p1);
+static nkf_char w_iconv_common(nkf_char c1,nkf_char c0,const unsigned short *const *pp,nkf_char psize,nkf_char *p2,nkf_char *p1);
+static void w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0);
+static nkf_char ww16_conv(nkf_char c2, nkf_char c1, nkf_char c0);
+static nkf_char w16e_conv(nkf_char val,nkf_char *p2,nkf_char *p1);
+static void w_status(struct input_code *, nkf_char);
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+static int output_bom_f = FALSE;
+static int output_endian = ENDIAN_BIG;
+static nkf_char e2w_conv(nkf_char c2,nkf_char c1);
+static void w_oconv(nkf_char c2,nkf_char c1);
+static void w_oconv16(nkf_char c2,nkf_char c1);
+static void w_oconv32(nkf_char c2,nkf_char c1);
+#endif
+static void e_oconv(nkf_char c2,nkf_char c1);
+static nkf_char e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1);
+static void s_oconv(nkf_char c2,nkf_char c1);
+static void j_oconv(nkf_char c2,nkf_char c1);
+static void fold_conv(nkf_char c2,nkf_char c1);
+static void cr_conv(nkf_char c2,nkf_char c1);
+static void z_conv(nkf_char c2,nkf_char c1);
+static void rot_conv(nkf_char c2,nkf_char c1);
+static void hira_conv(nkf_char c2,nkf_char c1);
+static void base64_conv(nkf_char c2,nkf_char c1);
+static void iso2022jp_check_conv(nkf_char c2,nkf_char c1);
+static void no_connection(nkf_char c2,nkf_char c1);
+static nkf_char no_connection2(nkf_char c2,nkf_char c1,nkf_char c0);
+
+static void code_score(struct input_code *ptr);
+static void code_status(nkf_char c);
+
+static void std_putc(nkf_char c);
+static nkf_char std_getc(FILE *f);
+static nkf_char std_ungetc(nkf_char c,FILE *f);
+
+static nkf_char broken_getc(FILE *f);
+static nkf_char broken_ungetc(nkf_char c,FILE *f);
+
+static nkf_char mime_begin(FILE *f);
+static nkf_char mime_getc(FILE *f);
+static nkf_char mime_ungetc(nkf_char c,FILE *f);
+
+static void switch_mime_getc(void);
+static void unswitch_mime_getc(void);
+static nkf_char mime_begin_strict(FILE *f);
+static nkf_char mime_getc_buf(FILE *f);
+static nkf_char mime_ungetc_buf(nkf_char c,FILE *f);
+static nkf_char mime_integrity(FILE *f,const unsigned char *p);
+
+static nkf_char base64decode(nkf_char c);
+static void mime_prechar(nkf_char c2, nkf_char c1);
+static void mime_putc(nkf_char c);
+static void open_mime(nkf_char c);
+static void close_mime(void);
+static void eof_mime(void);
+static void mimeout_addchar(nkf_char c);
+#ifndef PERL_XS
+static void usage(void);
+static void version(void);
+#endif
+static void options(unsigned char *c);
+#if defined(PERL_XS) || defined(WIN32DLL)
+static void reinit(void);
+#endif
+
+/* buffers */
+
+#if !defined(PERL_XS) && !defined(WIN32DLL)
+static unsigned char stdibuf[IOBUF_SIZE];
+static unsigned char stdobuf[IOBUF_SIZE];
+#endif
+static unsigned char hold_buf[HOLD_SIZE*2];
+static int hold_count = 0;
+
+/* MIME preprocessor fifo */
+
+#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */
+#define MIME_BUF_MASK (MIME_BUF_SIZE-1)
+#define Fifo(n) mime_buf[(n)&MIME_BUF_MASK]
+static unsigned char mime_buf[MIME_BUF_SIZE];
+static unsigned int mime_top = 0;
+static unsigned int mime_last = 0; /* decoded */
+static unsigned int mime_input = 0; /* undecoded */
+static nkf_char (*mime_iconv_back)(nkf_char c2,nkf_char c1,nkf_char c0) = NULL;
+
+/* flags */
+static int unbuf_f = FALSE;
+static int estab_f = FALSE;
+static int nop_f = FALSE;
+static int binmode_f = TRUE; /* binary mode */
+static int rot_f = FALSE; /* rot14/43 mode */
+static int hira_f = FALSE; /* hira/kata henkan */
+static int input_f = FALSE; /* non fixed input code */
+static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */
+static int mime_f = STRICT_MIME; /* convert MIME B base64 or Q */
+static int mime_decode_f = FALSE; /* mime decode is explicitly on */
+static int mimebuf_f = FALSE; /* MIME buffered input */
+static int broken_f = FALSE; /* convert ESC-less broken JIS */
+static int iso8859_f = FALSE; /* ISO8859 through */
+static int mimeout_f = FALSE; /* base64 mode */
+#if defined(MSDOS) || defined(__OS2__)
+static int x0201_f = TRUE; /* Assume JISX0201 kana */
+#else
+static int x0201_f = NO_X0201; /* Assume NO JISX0201 */
+#endif
+static int iso2022jp_f = FALSE; /* convert ISO-2022-JP */
+
+#ifdef UNICODE_NORMALIZATION
+static int nfc_f = FALSE;
+static nkf_char (*i_nfc_getc)(FILE *) = std_getc; /* input of ugetc */
+static nkf_char (*i_nfc_ungetc)(nkf_char c ,FILE *f) = std_ungetc;
+static nkf_char nfc_getc(FILE *f);
+static nkf_char nfc_ungetc(nkf_char c,FILE *f);
+#endif
+
+#ifdef INPUT_OPTION
+static int cap_f = FALSE;
+static nkf_char (*i_cgetc)(FILE *) = std_getc; /* input of cgetc */
+static nkf_char (*i_cungetc)(nkf_char c ,FILE *f) = std_ungetc;
+static nkf_char cap_getc(FILE *f);
+static nkf_char cap_ungetc(nkf_char c,FILE *f);
+
+static int url_f = FALSE;
+static nkf_char (*i_ugetc)(FILE *) = std_getc; /* input of ugetc */
+static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc;
+static nkf_char url_getc(FILE *f);
+static nkf_char url_ungetc(nkf_char c,FILE *f);
+#endif
+
+#if defined(INT_IS_SHORT)
+#define NKF_INT32_C(n) (n##L)
+#else
+#define NKF_INT32_C(n) (n)
+#endif
+#define PREFIX_EUCG3 NKF_INT32_C(0x8F00)
+#define CLASS_MASK NKF_INT32_C(0xFF000000)
+#define CLASS_UNICODE NKF_INT32_C(0x01000000)
+#define VALUE_MASK NKF_INT32_C(0x00FFFFFF)
+#define UNICODE_MAX NKF_INT32_C(0x0010FFFF)
+#define is_unicode_capsule(c) ((c & CLASS_MASK) == CLASS_UNICODE)
+#define is_unicode_bmp(c) ((c & VALUE_MASK) <= NKF_INT32_C(0xFFFF))
+
+#ifdef NUMCHAR_OPTION
+static int numchar_f = FALSE;
+static nkf_char (*i_ngetc)(FILE *) = std_getc; /* input of ugetc */
+static nkf_char (*i_nungetc)(nkf_char c ,FILE *f) = std_ungetc;
+static nkf_char numchar_getc(FILE *f);
+static nkf_char numchar_ungetc(nkf_char c,FILE *f);
+#endif
+
+#ifdef CHECK_OPTION
+static int noout_f = FALSE;
+static void no_putc(nkf_char c);
+static nkf_char debug_f = FALSE;
+static void debug(const char *str);
+static nkf_char (*iconv_for_check)(nkf_char c2,nkf_char c1,nkf_char c0) = 0;
+#endif
+
+static int guess_f = FALSE;
+#if !defined PERL_XS
+static void print_guessed_code(char *filename);
+#endif
+static void set_input_codename(char *codename);
+static int is_inputcode_mixed = FALSE;
+static int is_inputcode_set = FALSE;
+
+#ifdef EXEC_IO
+static int exec_f = 0;
+#endif
+
+#ifdef SHIFTJIS_CP932
+/* invert IBM extended characters to others */
+static int cp51932_f = FALSE;
+
+/* invert NEC-selected IBM extended characters to IBM extended characters */
+static int cp932inv_f = TRUE;
+
+/* static nkf_char cp932_conv(nkf_char c2, nkf_char c1); */
+#endif /* SHIFTJIS_CP932 */
+
+#ifdef X0212_ENABLE
+static int x0212_f = FALSE;
+static nkf_char x0212_shift(nkf_char c);
+static nkf_char x0212_unshift(nkf_char c);
+#endif
+static int x0213_f = FALSE;
+
+static unsigned char prefix_table[256];
+
+static void set_code_score(struct input_code *ptr, nkf_char score);
+static void clr_code_score(struct input_code *ptr, nkf_char score);
+static void status_disable(struct input_code *ptr);
+static void status_push_ch(struct input_code *ptr, nkf_char c);
+static void status_clear(struct input_code *ptr);
+static void status_reset(struct input_code *ptr);
+static void status_reinit(struct input_code *ptr);
+static void status_check(struct input_code *ptr, nkf_char c);
+static void e_status(struct input_code *, nkf_char);
+static void s_status(struct input_code *, nkf_char);
+
+struct input_code input_code_list[] = {
+ {"EUC-JP", 0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
+ {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
+#ifdef UTF8_INPUT_ENABLE
+ {"UTF-8", 0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
+ {"UTF-16", 0, 0, 0, {0, 0, 0}, NULL, w_iconv16, 0},
+ {"UTF-32", 0, 0, 0, {0, 0, 0}, NULL, w_iconv32, 0},
+#endif
+ {0}
+};
+
+static int mimeout_mode = 0;
+static int base64_count = 0;
+
+/* X0208 -> ASCII converter */
+
+/* fold parameter */
+static int f_line = 0; /* chars in line */
+static int f_prev = 0;
+static int fold_preserve_f = FALSE; /* preserve new lines */
+static int fold_f = FALSE;
+static int fold_len = 0;
+
+/* options */
+static unsigned char kanji_intro = DEFAULT_J;
+static unsigned char ascii_intro = DEFAULT_R;
+
+/* Folding */
+
+#define FOLD_MARGIN 10
+#define DEFAULT_FOLD 60
+
+static int fold_margin = FOLD_MARGIN;
+
+/* converters */
+
+#ifdef DEFAULT_CODE_JIS
+# define DEFAULT_CONV j_oconv
+#endif
+#ifdef DEFAULT_CODE_SJIS
+# define DEFAULT_CONV s_oconv
+#endif
+#ifdef DEFAULT_CODE_EUC
+# define DEFAULT_CONV e_oconv
+#endif
+#ifdef DEFAULT_CODE_UTF8
+# define DEFAULT_CONV w_oconv
+#endif
+
+/* process default */
+static void (*output_conv)(nkf_char c2,nkf_char c1) = DEFAULT_CONV;
+
+static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection;
+/* s_iconv or oconv */
+static nkf_char (*iconv)(nkf_char c2,nkf_char c1,nkf_char c0) = no_connection2;
+
+static void (*o_zconv)(nkf_char c2,nkf_char c1) = no_connection;
+static void (*o_fconv)(nkf_char c2,nkf_char c1) = no_connection;
+static void (*o_crconv)(nkf_char c2,nkf_char c1) = no_connection;
+static void (*o_rot_conv)(nkf_char c2,nkf_char c1) = no_connection;
+static void (*o_hira_conv)(nkf_char c2,nkf_char c1) = no_connection;
+static void (*o_base64conv)(nkf_char c2,nkf_char c1) = no_connection;
+static void (*o_iso2022jp_check_conv)(nkf_char c2,nkf_char c1) = no_connection;
+
+/* static redirections */
+
+static void (*o_putc)(nkf_char c) = std_putc;
+
+static nkf_char (*i_getc)(FILE *f) = std_getc; /* general input */
+static nkf_char (*i_ungetc)(nkf_char c,FILE *f) =std_ungetc;
+
+static nkf_char (*i_bgetc)(FILE *) = std_getc; /* input of mgetc */
+static nkf_char (*i_bungetc)(nkf_char c ,FILE *f) = std_ungetc;
+
+static void (*o_mputc)(nkf_char c) = std_putc ; /* output of mputc */
+
+static nkf_char (*i_mgetc)(FILE *) = std_getc; /* input of mgetc */
+static nkf_char (*i_mungetc)(nkf_char c ,FILE *f) = std_ungetc;
+
+/* for strict mime */
+static nkf_char (*i_mgetc_buf)(FILE *) = std_getc; /* input of mgetc_buf */
+static nkf_char (*i_mungetc_buf)(nkf_char c,FILE *f) = std_ungetc;
+
+/* Global states */
+static int output_mode = ASCII, /* output kanji mode */
+ input_mode = ASCII, /* input kanji mode */
+ shift_mode = FALSE; /* TRUE shift out, or X0201 */
+static int mime_decode_mode = FALSE; /* MIME mode B base64, Q hex */
+
+/* X0201 / X0208 conversion tables */
+
+/* X0201 kana conversion table */
+/* 90-9F A0-DF */
+static const
+unsigned char cv[]= {
+ 0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
+ 0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
+ 0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
+ 0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
+ 0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
+ 0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
+ 0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
+ 0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
+ 0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
+ 0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
+ 0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
+ 0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
+ 0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
+ 0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
+ 0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
+ 0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
+ 0x00,0x00};
+
+
+/* X0201 kana conversion table for daguten */
+/* 90-9F A0-DF */
+static const
+unsigned char dv[]= {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74,
+ 0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
+ 0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
+ 0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
+ 0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
+ 0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
+ 0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
+
+/* X0201 kana conversion table for han-daguten */
+/* 90-9F A0-DF */
+static const
+unsigned char ev[]= {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
+ 0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
+
+
+/* X0208 kigou conversion table */
+/* 0x8140 - 0x819e */
+static const
+unsigned char fv[] = {
+
+ 0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
+ 0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
+ 0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
+ 0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
+ 0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
+ 0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
+ 0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+} ;
+
+
+#define CRLF 1
+
+static int file_out_f = FALSE;
+#ifdef OVERWRITE
+static int overwrite_f = FALSE;
+static int preserve_time_f = FALSE;
+static int backup_f = FALSE;
+static char *backup_suffix = "";
+static char *get_backup_filename(const char *suffix, const char *filename);
+#endif
+
+static int crmode_f = 0; /* CR, NL, CRLF */
+#ifdef EASYWIN /*Easy Win */
+static int end_check;
+#endif /*Easy Win */
+
+#define STD_GC_BUFSIZE (256)
+nkf_char std_gc_buf[STD_GC_BUFSIZE];
+nkf_char std_gc_ndx;
+
+#ifdef WIN32DLL
+#include "nkf32dll.c"
+#elif defined(PERL_XS)
+#else /* WIN32DLL */
+int main(int argc, char **argv)
+{
+ FILE *fin;
+ unsigned char *cp;
+
+ char *outfname = NULL;
+ char *origfname;
+
+#ifdef EASYWIN /*Easy Win */
+ _BufferSize.y = 400;/*Set Scroll Buffer Size*/
+#endif
+
+ for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
+ cp = (unsigned char *)*argv;
+ options(cp);
+#ifdef EXEC_IO
+ if (exec_f){
+ int fds[2], pid;
+ if (pipe(fds) < 0 || (pid = fork()) < 0){
+ abort();
+ }
+ if (pid == 0){
+ if (exec_f > 0){
+ close(fds[0]);
+ dup2(fds[1], 1);
+ }else{
+ close(fds[1]);
+ dup2(fds[0], 0);
+ }
+ execvp(argv[1], &argv[1]);
+ }
+ if (exec_f > 0){
+ close(fds[1]);
+ dup2(fds[0], 0);
+ }else{
+ close(fds[0]);
+ dup2(fds[1], 1);
+ }
+ argc = 0;
+ break;
+ }
+#endif
+ }
+ if(x0201_f == WISH_TRUE)
+ x0201_f = ((!iso2022jp_f)? TRUE : NO_X0201);
+
+ if (binmode_f == TRUE)
+#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
+ if (freopen("","wb",stdout) == NULL)
+ return (-1);
+#else
+ setbinmode(stdout);
+#endif
+
+ if (unbuf_f)
+ setbuf(stdout, (char *) NULL);
+ else
+ setvbuffer(stdout, (char *) stdobuf, IOBUF_SIZE);
+
+ if (argc == 0) {
+ if (binmode_f == TRUE)
+#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
+ if (freopen("","rb",stdin) == NULL) return (-1);
+#else
+ setbinmode(stdin);
+#endif
+ setvbuffer(stdin, (char *) stdibuf, IOBUF_SIZE);
+ if (nop_f)
+ noconvert(stdin);
+ else {
+ kanji_convert(stdin);
+ if (guess_f) print_guessed_code(NULL);
+ }
+ } else {
+ int nfiles = argc;
+ int is_argument_error = FALSE;
+ while (argc--) {
+ is_inputcode_mixed = FALSE;
+ is_inputcode_set = FALSE;
+ input_codename = "";
+#ifdef CHECK_OPTION
+ iconv_for_check = 0;
+#endif
+ if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
+ perror(*--argv);
+ *argv++;
+ is_argument_error = TRUE;
+ continue;
+ } else {
+#ifdef OVERWRITE
+ int fd = 0;
+ int fd_backup = 0;
+#endif
+
+/* reopen file for stdout */
+ if (file_out_f == TRUE) {
+#ifdef OVERWRITE
+ if (overwrite_f){
+ outfname = malloc(strlen(origfname)
+ + strlen(".nkftmpXXXXXX")
+ + 1);
+ if (!outfname){
+ perror(origfname);
+ return -1;
+ }
+ strcpy(outfname, origfname);
+#ifdef MSDOS
+ {
+ int i;
+ for (i = strlen(outfname); i; --i){
+ if (outfname[i - 1] == '/'
+ || outfname[i - 1] == '\\'){
+ break;
+ }
+ }
+ outfname[i] = '\0';
+ }
+ strcat(outfname, "ntXXXXXX");
+ mktemp(outfname);
+ fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
+ S_IREAD | S_IWRITE);
+#else
+ strcat(outfname, ".nkftmpXXXXXX");
+ fd = mkstemp(outfname);
+#endif
+ if (fd < 0
+ || (fd_backup = dup(fileno(stdout))) < 0
+ || dup2(fd, fileno(stdout)) < 0
+ ){
+ perror(origfname);
+ return -1;
+ }
+ }else
+#endif
+ if(argc == 1 ) {
+ outfname = *argv++;
+ argc--;
+ } else {
+ outfname = "nkf.out";
+ }
+
+ if(freopen(outfname, "w", stdout) == NULL) {
+ perror (outfname);
+ return (-1);
+ }
+ if (binmode_f == TRUE) {
+#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
+ if (freopen("","wb",stdout) == NULL)
+ return (-1);
+#else
+ setbinmode(stdout);
+#endif
+ }
+ }
+ if (binmode_f == TRUE)
+#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
+ if (freopen("","rb",fin) == NULL)
+ return (-1);
+#else
+ setbinmode(fin);
+#endif
+ setvbuffer(fin, (char *) stdibuf, IOBUF_SIZE);
+ if (nop_f)
+ noconvert(fin);
+ else {
+ char *filename = NULL;
+ kanji_convert(fin);
+ if (nfiles > 1) filename = origfname;
+ if (guess_f) print_guessed_code(filename);
+ }
+ fclose(fin);
+#ifdef OVERWRITE
+ if (overwrite_f) {
+ struct stat sb;
+#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
+ time_t tb[2];
+#else
+ struct utimbuf tb;
+#endif
+
+ fflush(stdout);
+ close(fd);
+ if (dup2(fd_backup, fileno(stdout)) < 0){
+ perror("dup2");
+ }
+ if (stat(origfname, &sb)) {
+ fprintf(stderr, "Can't stat %s\n", origfname);
+ }
+ /* $B%Q!<%_%C%7%g%s$rI|85(B */
+ if (chmod(outfname, sb.st_mode)) {
+ fprintf(stderr, "Can't set permission %s\n", outfname);
+ }
+
+ /* $B%?%$%`%9%?%s%W$rI|85(B */
+ if(preserve_time_f){
+#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
+ tb[0] = tb[1] = sb.st_mtime;
+ if (utime(outfname, tb)) {
+ fprintf(stderr, "Can't set timestamp %s\n", outfname);
+ }
+#else
+ tb.actime = sb.st_atime;
+ tb.modtime = sb.st_mtime;
+ if (utime(outfname, &tb)) {
+ fprintf(stderr, "Can't set timestamp %s\n", outfname);
+ }
+#endif
+ }
+ if(backup_f){
+ char *backup_filename = get_backup_filename(backup_suffix, origfname);
+#ifdef MSDOS
+ unlink(backup_filename);
+#endif
+ if (rename(origfname, backup_filename)) {
+ perror(backup_filename);
+ fprintf(stderr, "Can't rename %s to %s\n",
+ origfname, backup_filename);
+ }
+ }else{
+#ifdef MSDOS
+ if (unlink(origfname)){
+ perror(origfname);
+ }
+#endif
+ }
+ if (rename(outfname, origfname)) {
+ perror(origfname);
+ fprintf(stderr, "Can't rename %s to %s\n",
+ outfname, origfname);
+ }
+ free(outfname);
+ }
+#endif
+ }
+ }
+ if (is_argument_error)
+ return(-1);
+ }
+#ifdef EASYWIN /*Easy Win */
+ if (file_out_f == FALSE)
+ scanf("%d",&end_check);
+ else
+ fclose(stdout);
+#else /* for Other OS */
+ if (file_out_f == TRUE)
+ fclose(stdout);
+#endif /*Easy Win */
+ return (0);
+}
+#endif /* WIN32DLL */
+
+#ifdef OVERWRITE
+char *get_backup_filename(const char *suffix, const char *filename)
+{
+ char *backup_filename;
+ int asterisk_count = 0;
+ int i, j;
+ int filename_length = strlen(filename);
+
+ for(i = 0; suffix[i]; i++){
+ if(suffix[i] == '*') asterisk_count++;
+ }
+
+ if(asterisk_count){
+ backup_filename = malloc(strlen(suffix) + (asterisk_count * (filename_length - 1)) + 1);
+ if (!backup_filename){
+ perror("Can't malloc backup filename.");
+ return NULL;
+ }
+
+ for(i = 0, j = 0; suffix[i];){
+ if(suffix[i] == '*'){
+ backup_filename[j] = '\0';
+ strncat(backup_filename, filename, filename_length);
+ i++;
+ j += filename_length;
+ }else{
+ backup_filename[j++] = suffix[i++];
+ }
+ }
+ backup_filename[j] = '\0';
+ }else{
+ j = strlen(suffix) + filename_length;
+ backup_filename = malloc( + 1);
+ strcpy(backup_filename, filename);
+ strcat(backup_filename, suffix);
+ backup_filename[j] = '\0';
+ }
+ return backup_filename;
+}
+#endif
+
+static const
+struct {
+ const char *name;
+ const char *alias;
+} long_option[] = {
+ {"ic=", ""},
+ {"oc=", ""},
+ {"base64","jMB"},
+ {"euc","e"},
+ {"euc-input","E"},
+ {"fj","jm"},
+ {"help","v"},
+ {"jis","j"},
+ {"jis-input","J"},
+ {"mac","sLm"},
+ {"mime","jM"},
+ {"mime-input","m"},
+ {"msdos","sLw"},
+ {"sjis","s"},
+ {"sjis-input","S"},
+ {"unix","eLu"},
+ {"version","V"},
+ {"windows","sLw"},
+ {"hiragana","h1"},
+ {"katakana","h2"},
+ {"katakana-hiragana","h3"},
+ {"guess", "g"},
+ {"cp932", ""},
+ {"no-cp932", ""},
+#ifdef X0212_ENABLE
+ {"x0212", ""},
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ {"utf8", "w"},
+ {"utf16", "w16"},
+ {"ms-ucs-map", ""},
+ {"fb-skip", ""},
+ {"fb-html", ""},
+ {"fb-xml", ""},
+ {"fb-perl", ""},
+ {"fb-java", ""},
+ {"fb-subchar", ""},
+ {"fb-subchar=", ""},
+#endif
+#ifdef UTF8_INPUT_ENABLE
+ {"utf8-input", "W"},
+ {"utf16-input", "W16"},
+ {"no-cp932ext", ""},
+ {"no-best-fit-chars",""},
+#endif
+#ifdef UNICODE_NORMALIZATION
+ {"utf8mac-input", ""},
+#endif
+#ifdef OVERWRITE
+ {"overwrite", ""},
+ {"overwrite=", ""},
+ {"in-place", ""},
+ {"in-place=", ""},
+#endif
+#ifdef INPUT_OPTION
+ {"cap-input", ""},
+ {"url-input", ""},
+#endif
+#ifdef NUMCHAR_OPTION
+ {"numchar-input", ""},
+#endif
+#ifdef CHECK_OPTION
+ {"no-output", ""},
+ {"debug", ""},
+#endif
+#ifdef SHIFTJIS_CP932
+ {"cp932inv", ""},
+#endif
+#ifdef EXEC_IO
+ {"exec-in", ""},
+ {"exec-out", ""},
+#endif
+ {"prefix=", ""},
+};
+
+static int option_mode = 0;
+
+void options(unsigned char *cp)
+{
+ nkf_char i, j;
+ unsigned char *p;
+ unsigned char *cp_back = NULL;
+ char codeset[32];
+
+ if (option_mode==1)
+ return;
+ while(*cp && *cp++!='-');
+ while (*cp || cp_back) {
+ if(!*cp){
+ cp = cp_back;
+ cp_back = NULL;
+ continue;
+ }
+ p = 0;
+ switch (*cp++) {
+ case '-': /* literal options */
+ if (!*cp || *cp == SPACE) { /* ignore the rest of arguments */
+ option_mode = 1;
+ return;
+ }
+ for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
+ p = (unsigned char *)long_option[i].name;
+ for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
+ if (*p == cp[j] || cp[j] == ' '){
+ p = &cp[j] + 1;
+ break;
+ }
+ p = 0;
+ }
+ if (p == 0) return;
+ while(*cp && *cp != SPACE && cp++);
+ if (long_option[i].alias[0]){
+ cp_back = cp;
+ cp = (unsigned char *)long_option[i].alias;
+ }else{
+ if (strcmp(long_option[i].name, "ic=") == 0){
+ for (i=0; i < 16 && SPACE < p[i] && p[i] < DEL; i++){
+ codeset[i] = nkf_toupper(p[i]);
+ }
+ codeset[i] = 0;
+ if(strcmp(codeset, "ISO-2022-JP") == 0){
+ input_f = JIS_INPUT;
+ }else if(strcmp(codeset, "X-ISO2022JP-CP932") == 0 ||
+ strcmp(codeset, "CP50220") == 0 ||
+ strcmp(codeset, "CP50221") == 0 ||
+ strcmp(codeset, "CP50222") == 0){
+ input_f = JIS_INPUT;
+#ifdef SHIFTJIS_CP932
+ cp51932_f = TRUE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "ISO-2022-JP-1") == 0){
+ input_f = JIS_INPUT;
+#ifdef X0212_ENABLE
+ x0212_f = TRUE;
+#endif
+ }else if(strcmp(codeset, "ISO-2022-JP-3") == 0){
+ input_f = JIS_INPUT;
+#ifdef X0212_ENABLE
+ x0212_f = TRUE;
+#endif
+ x0213_f = TRUE;
+ }else if(strcmp(codeset, "SHIFT_JIS") == 0){
+ input_f = SJIS_INPUT;
+ }else if(strcmp(codeset, "WINDOWS-31J") == 0 ||
+ strcmp(codeset, "CSWINDOWS31J") == 0 ||
+ strcmp(codeset, "CP932") == 0 ||
+ strcmp(codeset, "MS932") == 0){
+ input_f = SJIS_INPUT;
+#ifdef SHIFTJIS_CP932
+ cp51932_f = TRUE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "EUCJP") == 0 ||
+ strcmp(codeset, "EUC-JP") == 0){
+ input_f = EUC_INPUT;
+ }else if(strcmp(codeset, "CP51932") == 0){
+ input_f = EUC_INPUT;
+#ifdef SHIFTJIS_CP932
+ cp51932_f = TRUE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "EUC-JP-MS") == 0 ||
+ strcmp(codeset, "EUCJP-MS") == 0 ||
+ strcmp(codeset, "EUCJPMS") == 0){
+ input_f = EUC_INPUT;
+#ifdef SHIFTJIS_CP932
+ cp51932_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_MS;
+#endif
+ }else if(strcmp(codeset, "EUC-JP-ASCII") == 0 ||
+ strcmp(codeset, "EUCJP-ASCII") == 0){
+ input_f = EUC_INPUT;
+#ifdef SHIFTJIS_CP932
+ cp51932_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_ASCII;
+#endif
+ }else if(strcmp(codeset, "SHIFT_JISX0213") == 0 ||
+ strcmp(codeset, "SHIFT_JIS-2004") == 0){
+ input_f = SJIS_INPUT;
+ x0213_f = TRUE;
+#ifdef SHIFTJIS_CP932
+ cp51932_f = FALSE;
+#endif
+ }else if(strcmp(codeset, "EUC-JISX0213") == 0 ||
+ strcmp(codeset, "EUC-JIS-2004") == 0){
+ input_f = EUC_INPUT;
+ x0213_f = TRUE;
+#ifdef SHIFTJIS_CP932
+ cp51932_f = FALSE;
+#endif
+#ifdef UTF8_INPUT_ENABLE
+ }else if(strcmp(codeset, "UTF-8") == 0 ||
+ strcmp(codeset, "UTF-8N") == 0 ||
+ strcmp(codeset, "UTF-8-BOM") == 0){
+ input_f = UTF8_INPUT;
+#ifdef UNICODE_NORMALIZATION
+ }else if(strcmp(codeset, "UTF8-MAC") == 0 ||
+ strcmp(codeset, "UTF-8-MAC") == 0){
+ input_f = UTF8_INPUT;
+ nfc_f = TRUE;
+#endif
+ }else if(strcmp(codeset, "UTF-16") == 0 ||
+ strcmp(codeset, "UTF-16BE") == 0 ||
+ strcmp(codeset, "UTF-16BE-BOM") == 0){
+ input_f = UTF16_INPUT;
+ input_endian = ENDIAN_BIG;
+ }else if(strcmp(codeset, "UTF-16LE") == 0 ||
+ strcmp(codeset, "UTF-16LE-BOM") == 0){
+ input_f = UTF16_INPUT;
+ input_endian = ENDIAN_LITTLE;
+ }else if(strcmp(codeset, "UTF-32") == 0 ||
+ strcmp(codeset, "UTF-32BE") == 0 ||
+ strcmp(codeset, "UTF-32BE-BOM") == 0){
+ input_f = UTF32_INPUT;
+ input_endian = ENDIAN_BIG;
+ }else if(strcmp(codeset, "UTF-32LE") == 0 ||
+ strcmp(codeset, "UTF-32LE-BOM") == 0){
+ input_f = UTF32_INPUT;
+ input_endian = ENDIAN_LITTLE;
+#endif
+ }
+ continue;
+ }
+ if (strcmp(long_option[i].name, "oc=") == 0){
+ x0201_f = FALSE;
+ for (i=0; i < 16 && SPACE < p[i] && p[i] < DEL; i++){
+ codeset[i] = nkf_toupper(p[i]);
+ }
+ codeset[i] = 0;
+ if(strcmp(codeset, "ISO-2022-JP") == 0){
+ output_conv = j_oconv;
+ }else if(strcmp(codeset, "X-ISO2022JP-CP932") == 0){
+ output_conv = j_oconv;
+ no_cp932ext_f = TRUE;
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "CP50220") == 0){
+ output_conv = j_oconv;
+ x0201_f = TRUE;
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "CP50221") == 0){
+ output_conv = j_oconv;
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "ISO-2022-JP-1") == 0){
+ output_conv = j_oconv;
+#ifdef X0212_ENABLE
+ x0212_f = TRUE;
+#endif
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
+#endif
+ }else if(strcmp(codeset, "ISO-2022-JP-3") == 0){
+ output_conv = j_oconv;
+#ifdef X0212_ENABLE
+ x0212_f = TRUE;
+#endif
+ x0213_f = TRUE;
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
+#endif
+ }else if(strcmp(codeset, "SHIFT_JIS") == 0){
+ output_conv = s_oconv;
+ }else if(strcmp(codeset, "WINDOWS-31J") == 0 ||
+ strcmp(codeset, "CSWINDOWS31J") == 0 ||
+ strcmp(codeset, "CP932") == 0 ||
+ strcmp(codeset, "MS932") == 0){
+ output_conv = s_oconv;
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "EUCJP") == 0 ||
+ strcmp(codeset, "EUC-JP") == 0){
+ output_conv = e_oconv;
+ }else if(strcmp(codeset, "CP51932") == 0){
+ output_conv = e_oconv;
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "EUC-JP-MS") == 0 ||
+ strcmp(codeset, "EUCJP-MS") == 0 ||
+ strcmp(codeset, "EUCJPMS") == 0){
+ output_conv = e_oconv;
+#ifdef X0212_ENABLE
+ x0212_f = TRUE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_MS;
+#endif
+ }else if(strcmp(codeset, "EUC-JP-ASCII") == 0 ||
+ strcmp(codeset, "EUCJP-ASCII") == 0){
+ output_conv = e_oconv;
+#ifdef X0212_ENABLE
+ x0212_f = TRUE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_ASCII;
+#endif
+ }else if(strcmp(codeset, "SHIFT_JISX0213") == 0 ||
+ strcmp(codeset, "SHIFT_JIS-2004") == 0){
+ output_conv = s_oconv;
+ x0213_f = TRUE;
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
+#endif
+ }else if(strcmp(codeset, "EUC-JISX0213") == 0 ||
+ strcmp(codeset, "EUC-JIS-2004") == 0){
+ output_conv = e_oconv;
+#ifdef X0212_ENABLE
+ x0212_f = TRUE;
+#endif
+ x0213_f = TRUE;
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ }else if(strcmp(codeset, "UTF-8") == 0){
+ output_conv = w_oconv;
+ }else if(strcmp(codeset, "UTF-8N") == 0){
+ output_conv = w_oconv;
+ }else if(strcmp(codeset, "UTF-8-BOM") == 0){
+ output_conv = w_oconv;
+ output_bom_f = TRUE;
+ }else if(strcmp(codeset, "UTF-16BE") == 0){
+ output_conv = w_oconv16;
+ }else if(strcmp(codeset, "UTF-16") == 0 ||
+ strcmp(codeset, "UTF-16BE-BOM") == 0){
+ output_conv = w_oconv16;
+ output_bom_f = TRUE;
+ }else if(strcmp(codeset, "UTF-16LE") == 0){
+ output_conv = w_oconv16;
+ output_endian = ENDIAN_LITTLE;
+ }else if(strcmp(codeset, "UTF-16LE-BOM") == 0){
+ output_conv = w_oconv16;
+ output_endian = ENDIAN_LITTLE;
+ output_bom_f = TRUE;
+ }else if(strcmp(codeset, "UTF-32") == 0 ||
+ strcmp(codeset, "UTF-32BE") == 0){
+ output_conv = w_oconv32;
+ }else if(strcmp(codeset, "UTF-32BE-BOM") == 0){
+ output_conv = w_oconv32;
+ output_bom_f = TRUE;
+ }else if(strcmp(codeset, "UTF-32LE") == 0){
+ output_conv = w_oconv32;
+ output_endian = ENDIAN_LITTLE;
+ }else if(strcmp(codeset, "UTF-32LE-BOM") == 0){
+ output_conv = w_oconv32;
+ output_endian = ENDIAN_LITTLE;
+ output_bom_f = TRUE;
+#endif
+ }
+ continue;
+ }
+#ifdef OVERWRITE
+ if (strcmp(long_option[i].name, "overwrite") == 0){
+ file_out_f = TRUE;
+ overwrite_f = TRUE;
+ preserve_time_f = TRUE;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "overwrite=") == 0){
+ file_out_f = TRUE;
+ overwrite_f = TRUE;
+ preserve_time_f = TRUE;
+ backup_f = TRUE;
+ backup_suffix = malloc(strlen((char *) p) + 1);
+ strcpy(backup_suffix, (char *) p);
+ continue;
+ }
+ if (strcmp(long_option[i].name, "in-place") == 0){
+ file_out_f = TRUE;
+ overwrite_f = TRUE;
+ preserve_time_f = FALSE;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "in-place=") == 0){
+ file_out_f = TRUE;
+ overwrite_f = TRUE;
+ preserve_time_f = FALSE;
+ backup_f = TRUE;
+ backup_suffix = malloc(strlen((char *) p) + 1);
+ strcpy(backup_suffix, (char *) p);
+ continue;
+ }
+#endif
+#ifdef INPUT_OPTION
+ if (strcmp(long_option[i].name, "cap-input") == 0){
+ cap_f = TRUE;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "url-input") == 0){
+ url_f = TRUE;
+ continue;
+ }
+#endif
+#ifdef NUMCHAR_OPTION
+ if (strcmp(long_option[i].name, "numchar-input") == 0){
+ numchar_f = TRUE;
+ continue;
+ }
+#endif
+#ifdef CHECK_OPTION
+ if (strcmp(long_option[i].name, "no-output") == 0){
+ noout_f = TRUE;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "debug") == 0){
+ debug_f = TRUE;
+ continue;
+ }
+#endif
+ if (strcmp(long_option[i].name, "cp932") == 0){
+#ifdef SHIFTJIS_CP932
+ cp51932_f = TRUE;
+ cp932inv_f = TRUE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ continue;
+ }
+ if (strcmp(long_option[i].name, "no-cp932") == 0){
+#ifdef SHIFTJIS_CP932
+ cp51932_f = FALSE;
+ cp932inv_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_ASCII;
+#endif
+ continue;
+ }
+#ifdef SHIFTJIS_CP932
+ if (strcmp(long_option[i].name, "cp932inv") == 0){
+ cp932inv_f = TRUE;
+ continue;
+ }
+#endif
+
+#ifdef X0212_ENABLE
+ if (strcmp(long_option[i].name, "x0212") == 0){
+ x0212_f = TRUE;
+ continue;
+ }
+#endif
+
+#ifdef EXEC_IO
+ if (strcmp(long_option[i].name, "exec-in") == 0){
+ exec_f = 1;
+ return;
+ }
+ if (strcmp(long_option[i].name, "exec-out") == 0){
+ exec_f = -1;
+ return;
+ }
+#endif
+#if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
+ if (strcmp(long_option[i].name, "no-cp932ext") == 0){
+ no_cp932ext_f = TRUE;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "no-best-fit-chars") == 0){
+ no_best_fit_chars_f = TRUE;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "fb-skip") == 0){
+ encode_fallback = NULL;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "fb-html") == 0){
+ encode_fallback = encode_fallback_html;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "fb-xml" ) == 0){
+ encode_fallback = encode_fallback_xml;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "fb-java") == 0){
+ encode_fallback = encode_fallback_java;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "fb-perl") == 0){
+ encode_fallback = encode_fallback_perl;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "fb-subchar") == 0){
+ encode_fallback = encode_fallback_subchar;
+ continue;
+ }
+ if (strcmp(long_option[i].name, "fb-subchar=") == 0){
+ encode_fallback = encode_fallback_subchar;
+ unicode_subchar = 0;
+ if (p[0] != '0'){
+ /* decimal number */
+ for (i = 0; i < 7 && nkf_isdigit(p[i]); i++){
+ unicode_subchar *= 10;
+ unicode_subchar += hex2bin(p[i]);
+ }
+ }else if(p[1] == 'x' || p[1] == 'X'){
+ /* hexadecimal number */
+ for (i = 2; i < 8 && nkf_isxdigit(p[i]); i++){
+ unicode_subchar <<= 4;
+ unicode_subchar |= hex2bin(p[i]);
+ }
+ }else{
+ /* octal number */
+ for (i = 1; i < 8 && nkf_isoctal(p[i]); i++){
+ unicode_subchar *= 8;
+ unicode_subchar += hex2bin(p[i]);
+ }
+ }
+ w16e_conv(unicode_subchar, &i, &j);
+ unicode_subchar = i<<8 | j;
+ continue;
+ }
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
+ ms_ucs_map_f = UCS_MAP_MS;
+ continue;
+ }
+#endif
+#ifdef UNICODE_NORMALIZATION
+ if (strcmp(long_option[i].name, "utf8mac-input") == 0){
+ input_f = UTF8_INPUT;
+ nfc_f = TRUE;
+ continue;
+ }
+#endif
+ if (strcmp(long_option[i].name, "prefix=") == 0){
+ if (nkf_isgraph(p[0])){
+ for (i = 1; nkf_isgraph(p[i]); i++){
+ prefix_table[p[i]] = p[0];
+ }
+ }
+ continue;
+ }
+ }
+ continue;
+ case 'b': /* buffered mode */
+ unbuf_f = FALSE;
+ continue;
+ case 'u': /* non bufferd mode */
+ unbuf_f = TRUE;
+ continue;
+ case 't': /* transparent mode */
+ if (*cp=='1') {
+ /* alias of -t */
+ nop_f = TRUE;
+ *cp++;
+ } else if (*cp=='2') {
+ /*
+ * -t with put/get
+ *
+ * nkf -t2MB hoge.bin | nkf -t2mB | diff -s - hoge.bin
+ *
+ */
+ nop_f = 2;
+ *cp++;
+ } else
+ nop_f = TRUE;
+ continue;
+ case 'j': /* JIS output */
+ case 'n':
+ output_conv = j_oconv;
+ continue;
+ case 'e': /* AT&T EUC output */
+ output_conv = e_oconv;
+ cp932inv_f = FALSE;
+ continue;
+ case 's': /* SJIS output */
+ output_conv = s_oconv;
+ continue;
+ case 'l': /* ISO8859 Latin-1 support, no conversion */
+ iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
+ input_f = LATIN1_INPUT;
+ continue;
+ case 'i': /* Kanji IN ESC-$-@/B */
+ if (*cp=='@'||*cp=='B')
+ kanji_intro = *cp++;
+ continue;
+ case 'o': /* ASCII IN ESC-(-J/B */
+ if (*cp=='J'||*cp=='B'||*cp=='H')
+ ascii_intro = *cp++;
+ continue;
+ case 'h':
+ /*
+ bit:1 katakana->hiragana
+ bit:2 hiragana->katakana
+ */
+ if ('9'>= *cp && *cp>='0')
+ hira_f |= (*cp++ -'0');
+ else
+ hira_f |= 1;
+ continue;
+ case 'r':
+ rot_f = TRUE;
+ continue;
+#if defined(MSDOS) || defined(__OS2__)
+ case 'T':
+ binmode_f = FALSE;
+ continue;
+#endif
+#ifndef PERL_XS
+ case 'V':
+ version();
+ exit(1);
+ break;
+ case 'v':
+ usage();
+ exit(1);
+ break;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ case 'w': /* UTF-8 output */
+ if (cp[0] == '8') {
+ output_conv = w_oconv; cp++;
+ if (cp[0] == '0'){
+ cp++;
+ } else {
+ output_bom_f = TRUE;
+ }
+ } else {
+ if ('1'== cp[0] && '6'==cp[1]) {
+ output_conv = w_oconv16; cp+=2;
+ } else if ('3'== cp[0] && '2'==cp[1]) {
+ output_conv = w_oconv32; cp+=2;
+ } else {
+ output_conv = w_oconv;
+ continue;
+ }
+ if (cp[0]=='L') {
+ cp++;
+ output_endian = ENDIAN_LITTLE;
+ } else if (cp[0] == 'B') {
+ cp++;
+ } else {
+ continue;
+ }
+ if (cp[0] == '0'){
+ cp++;
+ } else {
+ output_bom_f = TRUE;
+ }
+ }
+ continue;
+#endif
+#ifdef UTF8_INPUT_ENABLE
+ case 'W': /* UTF input */
+ if (cp[0] == '8') {
+ cp++;
+ input_f = UTF8_INPUT;
+ }else{
+ if ('1'== cp[0] && '6'==cp[1]) {
+ cp += 2;
+ input_f = UTF16_INPUT;
+ input_endian = ENDIAN_BIG;
+ } else if ('3'== cp[0] && '2'==cp[1]) {
+ cp += 2;
+ input_f = UTF32_INPUT;
+ input_endian = ENDIAN_BIG;
+ } else {
+ input_f = UTF8_INPUT;
+ continue;
+ }
+ if (cp[0]=='L') {
+ cp++;
+ input_endian = ENDIAN_LITTLE;
+ } else if (cp[0] == 'B') {
+ cp++;
+ }
+ }
+ continue;
+#endif
+ /* Input code assumption */
+ case 'J': /* JIS input */
+ input_f = JIS_INPUT;
+ continue;
+ case 'E': /* AT&T EUC input */
+ input_f = EUC_INPUT;
+ continue;
+ case 'S': /* MS Kanji input */
+ input_f = SJIS_INPUT;
+ if (x0201_f==NO_X0201) x0201_f=TRUE;
+ continue;
+ case 'Z': /* Convert X0208 alphabet to asii */
+ /* bit:0 Convert X0208
+ bit:1 Convert Kankaku to one space
+ bit:2 Convert Kankaku to two spaces
+ bit:3 Convert HTML Entity
+ */
+ if ('9'>= *cp && *cp>='0')
+ alpha_f |= 1<<(*cp++ -'0');
+ else
+ alpha_f |= TRUE;
+ continue;
+ case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
+ x0201_f = FALSE; /* No X0201->X0208 conversion */
+ /* accept X0201
+ ESC-(-I in JIS, EUC, MS Kanji
+ SI/SO in JIS, EUC, MS Kanji
+ SSO in EUC, JIS, not in MS Kanji
+ MS Kanji (0xa0-0xdf)
+ output X0201
+ ESC-(-I in JIS (0x20-0x5f)
+ SSO in EUC (0xa0-0xdf)
+ 0xa0-0xd in MS Kanji (0xa0-0xdf)
+ */
+ continue;
+ case 'X': /* Assume X0201 kana */
+ /* Default value is NO_X0201 for EUC/MS-Kanji mix */
+ x0201_f = TRUE;
+ continue;
+ case 'F': /* prserve new lines */
+ fold_preserve_f = TRUE;
+ case 'f': /* folding -f60 or -f */
+ fold_f = TRUE;
+ fold_len = 0;
+ while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
+ fold_len *= 10;
+ fold_len += *cp++ - '0';
+ }
+ if (!(0<fold_len && fold_len<BUFSIZ))
+ fold_len = DEFAULT_FOLD;
+ if (*cp=='-') {
+ fold_margin = 0;
+ cp++;
+ while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
+ fold_margin *= 10;
+ fold_margin += *cp++ - '0';
+ }
+ }
+ continue;
+ case 'm': /* MIME support */
+ /* mime_decode_f = TRUE; */ /* this has too large side effects... */
+ if (*cp=='B'||*cp=='Q') {
+ mime_decode_mode = *cp++;
+ mimebuf_f = FIXED_MIME;
+ } else if (*cp=='N') {
+ mime_f = TRUE; cp++;
+ } else if (*cp=='S') {
+ mime_f = STRICT_MIME; cp++;
+ } else if (*cp=='0') {
+ mime_decode_f = FALSE;
+ mime_f = FALSE; cp++;
+ }
+ continue;
+ case 'M': /* MIME output */
+ if (*cp=='B') {
+ mimeout_mode = 'B';
+ mimeout_f = FIXED_MIME; cp++;
+ } else if (*cp=='Q') {
+ mimeout_mode = 'Q';
+ mimeout_f = FIXED_MIME; cp++;
+ } else {
+ mimeout_f = TRUE;
+ }
+ continue;
+ case 'B': /* Broken JIS support */
+ /* bit:0 no ESC JIS
+ bit:1 allow any x on ESC-(-x or ESC-$-x
+ bit:2 reset to ascii on NL
+ */
+ if ('9'>= *cp && *cp>='0')
+ broken_f |= 1<<(*cp++ -'0');
+ else
+ broken_f |= TRUE;
+ continue;
+#ifndef PERL_XS
+ case 'O':/* for Output file */
+ file_out_f = TRUE;
+ continue;
+#endif
+ case 'c':/* add cr code */
+ crmode_f = CRLF;
+ continue;
+ case 'd':/* delete cr code */
+ crmode_f = NL;
+ continue;
+ case 'I': /* ISO-2022-JP output */
+ iso2022jp_f = TRUE;
+ continue;
+ case 'L': /* line mode */
+ if (*cp=='u') { /* unix */
+ crmode_f = NL; cp++;
+ } else if (*cp=='m') { /* mac */
+ crmode_f = CR; cp++;
+ } else if (*cp=='w') { /* windows */
+ crmode_f = CRLF; cp++;
+ } else if (*cp=='0') { /* no conversion */
+ crmode_f = 0; cp++;
+ }
+ continue;
+ case 'g':
+#ifndef PERL_XS
+ guess_f = TRUE;
+#endif
+ continue;
+ case ' ':
+ /* module muliple options in a string are allowed for Perl moudle */
+ while(*cp && *cp++!='-');
+ continue;
+ default:
+ /* bogus option but ignored */
+ continue;
+ }
+ }
+}
+
+struct input_code * find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
+{
+ if (iconv_func){
+ struct input_code *p = input_code_list;
+ while (p->name){
+ if (iconv_func == p->iconv_func){
+ return p;
+ }
+ p++;
+ }
+ }
+ return 0;
+}
+
+void set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
+{
+#ifdef INPUT_CODE_FIX
+ if (f || !input_f)
+#endif
+ if (estab_f != f){
+ estab_f = f;
+ }
+
+ if (iconv_func
+#ifdef INPUT_CODE_FIX
+ && (f == -TRUE || !input_f) /* -TRUE means "FORCE" */
+#endif
+ ){
+ iconv = iconv_func;
+ }
+#ifdef CHECK_OPTION
+ if (estab_f && iconv_for_check != iconv){
+ struct input_code *p = find_inputcode_byfunc(iconv);
+ if (p){
+ set_input_codename(p->name);
+ debug(input_codename);
+ }
+ iconv_for_check = iconv;
+ }
+#endif
+}
+
+#define SCORE_L2 (1) /* $BBh(B2$B?e=`4A;z(B */
+#define SCORE_KANA (SCORE_L2 << 1) /* $B$$$o$f$kH>3Q%+%J(B */
+#define SCORE_DEPEND (SCORE_KANA << 1) /* $B5!<o0MB8J8;z(B */
+#ifdef SHIFTJIS_CP932
+#define SCORE_CP932 (SCORE_DEPEND << 1) /* CP932 $B$K$h$kFI$_49$((B */
+#define SCORE_NO_EXIST (SCORE_CP932 << 1) /* $BB8:_$7$J$$J8;z(B */
+#else
+#define SCORE_NO_EXIST (SCORE_DEPEND << 1) /* $BB8:_$7$J$$J8;z(B */
+#endif
+#define SCORE_iMIME (SCORE_NO_EXIST << 1) /* MIME $B$K$h$k;XDj(B */
+#define SCORE_ERROR (SCORE_iMIME << 1) /* $B%(%i!<(B */
+
+#define SCORE_INIT (SCORE_iMIME)
+
+const nkf_char score_table_A0[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
+ SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
+};
+
+const nkf_char score_table_F0[] = {
+ SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
+ SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
+ SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
+ SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
+};
+
+void set_code_score(struct input_code *ptr, nkf_char score)
+{
+ if (ptr){
+ ptr->score |= score;
+ }
+}
+
+void clr_code_score(struct input_code *ptr, nkf_char score)
+{
+ if (ptr){
+ ptr->score &= ~score;
+ }
+}
+
+void code_score(struct input_code *ptr)
+{
+ nkf_char c2 = ptr->buf[0];
+#ifdef UTF8_OUTPUT_ENABLE
+ nkf_char c1 = ptr->buf[1];
+#endif
+ if (c2 < 0){
+ set_code_score(ptr, SCORE_ERROR);
+ }else if (c2 == SSO){
+ set_code_score(ptr, SCORE_KANA);
+#ifdef UTF8_OUTPUT_ENABLE
+ }else if (!e2w_conv(c2, c1)){
+ set_code_score(ptr, SCORE_NO_EXIST);
+#endif
+ }else if ((c2 & 0x70) == 0x20){
+ set_code_score(ptr, score_table_A0[c2 & 0x0f]);
+ }else if ((c2 & 0x70) == 0x70){
+ set_code_score(ptr, score_table_F0[c2 & 0x0f]);
+ }else if ((c2 & 0x70) >= 0x50){
+ set_code_score(ptr, SCORE_L2);
+ }
+}
+
+void status_disable(struct input_code *ptr)
+{
+ ptr->stat = -1;
+ ptr->buf[0] = -1;
+ code_score(ptr);
+ if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
+}
+
+void status_push_ch(struct input_code *ptr, nkf_char c)
+{
+ ptr->buf[ptr->index++] = c;
+}
+
+void status_clear(struct input_code *ptr)
+{
+ ptr->stat = 0;
+ ptr->index = 0;
+}
+
+void status_reset(struct input_code *ptr)
+{
+ status_clear(ptr);
+ ptr->score = SCORE_INIT;
+}
+
+void status_reinit(struct input_code *ptr)
+{
+ status_reset(ptr);
+ ptr->_file_stat = 0;
+}
+
+void status_check(struct input_code *ptr, nkf_char c)
+{
+ if (c <= DEL && estab_f){
+ status_reset(ptr);
+ }
+}
+
+void s_status(struct input_code *ptr, nkf_char c)
+{
+ switch(ptr->stat){
+ case -1:
+ status_check(ptr, c);
+ break;
+ case 0:
+ if (c <= DEL){
+ break;
+#ifdef NUMCHAR_OPTION
+ }else if (is_unicode_capsule(c)){
+ break;
+#endif
+ }else if (0xa1 <= c && c <= 0xdf){
+ status_push_ch(ptr, SSO);
+ status_push_ch(ptr, c);
+ code_score(ptr);
+ status_clear(ptr);
+ }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xef)){
+ ptr->stat = 1;
+ status_push_ch(ptr, c);
+#ifdef SHIFTJIS_CP932
+ }else if (cp51932_f
+ && is_ibmext_in_sjis(c)){
+ ptr->stat = 2;
+ status_push_ch(ptr, c);
+#endif /* SHIFTJIS_CP932 */
+#ifdef X0212_ENABLE
+ }else if (x0212_f && 0xf0 <= c && c <= 0xfc){
+ ptr->stat = 1;
+ status_push_ch(ptr, c);
+#endif /* X0212_ENABLE */
+ }else{
+ status_disable(ptr);
+ }
+ break;
+ case 1:
+ if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
+ status_push_ch(ptr, c);
+ s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
+ code_score(ptr);
+ status_clear(ptr);
+ }else{
+ status_disable(ptr);
+ }
+ break;
+ case 2:
+#ifdef SHIFTJIS_CP932
+ if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
+ status_push_ch(ptr, c);
+ if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0){
+ set_code_score(ptr, SCORE_CP932);
+ status_clear(ptr);
+ break;
+ }
+ }
+#endif /* SHIFTJIS_CP932 */
+#ifndef X0212_ENABLE
+ status_disable(ptr);
+#endif
+ break;
+ }
+}
+
+void e_status(struct input_code *ptr, nkf_char c)
+{
+ switch (ptr->stat){
+ case -1:
+ status_check(ptr, c);
+ break;
+ case 0:
+ if (c <= DEL){
+ break;
+#ifdef NUMCHAR_OPTION
+ }else if (is_unicode_capsule(c)){
+ break;
+#endif
+ }else if (SSO == c || (0xa1 <= c && c <= 0xfe)){
+ ptr->stat = 1;
+ status_push_ch(ptr, c);
+#ifdef X0212_ENABLE
+ }else if (0x8f == c){
+ ptr->stat = 2;
+ status_push_ch(ptr, c);
+#endif /* X0212_ENABLE */
+ }else{
+ status_disable(ptr);
+ }
+ break;
+ case 1:
+ if (0xa1 <= c && c <= 0xfe){
+ status_push_ch(ptr, c);
+ code_score(ptr);
+ status_clear(ptr);
+ }else{
+ status_disable(ptr);
+ }
+ break;
+#ifdef X0212_ENABLE
+ case 2:
+ if (0xa1 <= c && c <= 0xfe){
+ ptr->stat = 1;
+ status_push_ch(ptr, c);
+ }else{
+ status_disable(ptr);
+ }
+#endif /* X0212_ENABLE */
+ }
+}
+
+#ifdef UTF8_INPUT_ENABLE
+void w_status(struct input_code *ptr, nkf_char c)
+{
+ switch (ptr->stat){
+ case -1:
+ status_check(ptr, c);
+ break;
+ case 0:
+ if (c <= DEL){
+ break;
+#ifdef NUMCHAR_OPTION
+ }else if (is_unicode_capsule(c)){
+ break;
+#endif
+ }else if (0xc0 <= c && c <= 0xdf){
+ ptr->stat = 1;
+ status_push_ch(ptr, c);
+ }else if (0xe0 <= c && c <= 0xef){
+ ptr->stat = 2;
+ status_push_ch(ptr, c);
+ }else if (0xf0 <= c && c <= 0xf4){
+ ptr->stat = 3;
+ status_push_ch(ptr, c);
+ }else{
+ status_disable(ptr);
+ }
+ break;
+ case 1:
+ case 2:
+ if (0x80 <= c && c <= 0xbf){
+ status_push_ch(ptr, c);
+ if (ptr->index > ptr->stat){
+ int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
+ && ptr->buf[2] == 0xbf);
+ w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
+ &ptr->buf[0], &ptr->buf[1]);
+ if (!bom){
+ code_score(ptr);
+ }
+ status_clear(ptr);
+ }
+ }else{
+ status_disable(ptr);
+ }
+ break;
+ case 3:
+ if (0x80 <= c && c <= 0xbf){
+ if (ptr->index < ptr->stat){
+ status_push_ch(ptr, c);
+ } else {
+ status_clear(ptr);
+ }
+ }else{
+ status_disable(ptr);
+ }
+ break;
+ }
+}
+#endif
+
+void code_status(nkf_char c)
+{
+ int action_flag = 1;
+ struct input_code *result = 0;
+ struct input_code *p = input_code_list;
+ while (p->name){
+ if (!p->status_func) {
+ ++p;
+ continue;
+ }
+ if (!p->status_func)
+ continue;
+ (p->status_func)(p, c);
+ if (p->stat > 0){
+ action_flag = 0;
+ }else if(p->stat == 0){
+ if (result){
+ action_flag = 0;
+ }else{
+ result = p;
+ }
+ }
+ ++p;
+ }
+
+ if (action_flag){
+ if (result && !estab_f){
+ set_iconv(TRUE, result->iconv_func);
+ }else if (c <= DEL){
+ struct input_code *ptr = input_code_list;
+ while (ptr->name){
+ status_reset(ptr);
+ ++ptr;
+ }
+ }
+ }
+}
+
+#ifndef WIN32DLL
+nkf_char std_getc(FILE *f)
+{
+ if (std_gc_ndx){
+ return std_gc_buf[--std_gc_ndx];
+ }
+ return getc(f);
+}
+#endif /*WIN32DLL*/
+
+nkf_char std_ungetc(nkf_char c, FILE *f)
+{
+ if (std_gc_ndx == STD_GC_BUFSIZE){
+ return EOF;
+ }
+ std_gc_buf[std_gc_ndx++] = c;
+ return c;
+}
+
+#ifndef WIN32DLL
+void std_putc(nkf_char c)
+{
+ if(c!=EOF)
+ putchar(c);
+}
+#endif /*WIN32DLL*/
+
+#if !defined(PERL_XS) && !defined(WIN32DLL)
+nkf_char noconvert(FILE *f)
+{
+ nkf_char c;
+
+ if (nop_f == 2)
+ module_connection();
+ while ((c = (*i_getc)(f)) != EOF)
+ (*o_putc)(c);
+ (*o_putc)(EOF);
+ return 1;
+}
+#endif
+
+void module_connection(void)
+{
+ oconv = output_conv;
+ o_putc = std_putc;
+
+ /* replace continucation module, from output side */
+
+ /* output redicrection */
+#ifdef CHECK_OPTION
+ if (noout_f || guess_f){
+ o_putc = no_putc;
+ }
+#endif
+ if (mimeout_f) {
+ o_mputc = o_putc;
+ o_putc = mime_putc;
+ if (mimeout_f == TRUE) {
+ o_base64conv = oconv; oconv = base64_conv;
+ }
+ /* base64_count = 0; */
+ }
+
+ if (crmode_f) {
+ o_crconv = oconv; oconv = cr_conv;
+ }
+ if (rot_f) {
+ o_rot_conv = oconv; oconv = rot_conv;
+ }
+ if (iso2022jp_f) {
+ o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
+ }
+ if (hira_f) {
+ o_hira_conv = oconv; oconv = hira_conv;
+ }
+ if (fold_f) {
+ o_fconv = oconv; oconv = fold_conv;
+ f_line = 0;
+ }
+ if (alpha_f || x0201_f) {
+ o_zconv = oconv; oconv = z_conv;
+ }
+
+ i_getc = std_getc;
+ i_ungetc = std_ungetc;
+ /* input redicrection */
+#ifdef INPUT_OPTION
+ if (cap_f){
+ i_cgetc = i_getc; i_getc = cap_getc;
+ i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
+ }
+ if (url_f){
+ i_ugetc = i_getc; i_getc = url_getc;
+ i_uungetc = i_ungetc; i_ungetc= url_ungetc;
+ }
+#endif
+#ifdef NUMCHAR_OPTION
+ if (numchar_f){
+ i_ngetc = i_getc; i_getc = numchar_getc;
+ i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
+ }
+#endif
+#ifdef UNICODE_NORMALIZATION
+ if (nfc_f && input_f == UTF8_INPUT){
+ i_nfc_getc = i_getc; i_getc = nfc_getc;
+ i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc;
+ }
+#endif
+ if (mime_f && mimebuf_f==FIXED_MIME) {
+ i_mgetc = i_getc; i_getc = mime_getc;
+ i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
+ }
+ if (broken_f & 1) {
+ i_bgetc = i_getc; i_getc = broken_getc;
+ i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
+ }
+ if (input_f == JIS_INPUT || input_f == EUC_INPUT || input_f == LATIN1_INPUT) {
+ set_iconv(-TRUE, e_iconv);
+ } else if (input_f == SJIS_INPUT) {
+ set_iconv(-TRUE, s_iconv);
+#ifdef UTF8_INPUT_ENABLE
+ } else if (input_f == UTF8_INPUT) {
+ set_iconv(-TRUE, w_iconv);
+ } else if (input_f == UTF16_INPUT) {
+ set_iconv(-TRUE, w_iconv16);
+ } else if (input_f == UTF32_INPUT) {
+ set_iconv(-TRUE, w_iconv32);
+#endif
+ } else {
+ set_iconv(FALSE, e_iconv);
+ }
+
+ {
+ struct input_code *p = input_code_list;
+ while (p->name){
+ status_reinit(p++);
+ }
+ }
+}
+
+/*
+ * Check and Ignore BOM
+ */
+void check_bom(FILE *f)
+{
+ int c2;
+ switch(c2 = (*i_getc)(f)){
+ case 0x00:
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if((c2 = (*i_getc)(f)) == 0xFE){
+ if((c2 = (*i_getc)(f)) == 0xFF){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv32);
+ }
+ if (iconv == w_iconv32) {
+ input_endian = ENDIAN_BIG;
+ return;
+ }
+ (*i_ungetc)(0xFF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xFE,f);
+ }else if(c2 == 0xFF){
+ if((c2 = (*i_getc)(f)) == 0xFE){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv32);
+ }
+ if (iconv == w_iconv32) {
+ input_endian = ENDIAN_2143;
+ return;
+ }
+ (*i_ungetc)(0xFF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xFF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0x00,f);
+ break;
+ case 0xEF:
+ if((c2 = (*i_getc)(f)) == 0xBB){
+ if((c2 = (*i_getc)(f)) == 0xBF){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv);
+ }
+ if (iconv == w_iconv) {
+ return;
+ }
+ (*i_ungetc)(0xBF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xBB,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xEF,f);
+ break;
+ case 0xFE:
+ if((c2 = (*i_getc)(f)) == 0xFF){
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv32);
+ }
+ if (iconv == w_iconv32) {
+ input_endian = ENDIAN_3412;
+ return;
+ }
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ if(!input_f){
+ set_iconv(TRUE, w_iconv16);
+ }
+ if (iconv == w_iconv16) {
+ input_endian = ENDIAN_BIG;
+ return;
+ }
+ (*i_ungetc)(0xFF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xFE,f);
+ break;
+ case 0xFF:
+ if((c2 = (*i_getc)(f)) == 0xFE){
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv32);
+ }
+ if (iconv == w_iconv32) {
+ input_endian = ENDIAN_LITTLE;
+ return;
+ }
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ if(!input_f){
+ set_iconv(TRUE, w_iconv16);
+ }
+ if (iconv == w_iconv16) {
+ input_endian = ENDIAN_LITTLE;
+ return;
+ }
+ (*i_ungetc)(0xFE,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xFF,f);
+ break;
+ default:
+ (*i_ungetc)(c2,f);
+ break;
+ }
+}
+
+/*
+ Conversion main loop. Code detection only.
+ */
+
+nkf_char kanji_convert(FILE *f)
+{
+ nkf_char c3, c2=0, c1, c0=0;
+ int is_8bit = FALSE;
+
+ if(input_f == SJIS_INPUT || input_f == EUC_INPUT
+#ifdef UTF8_INPUT_ENABLE
+ || input_f == UTF8_INPUT || input_f == UTF16_INPUT
+#endif
+ ){
+ is_8bit = TRUE;
+ }
+
+ input_mode = ASCII;
+ output_mode = ASCII;
+ shift_mode = FALSE;
+
+#define NEXT continue /* no output, get next */
+#define SEND ; /* output c1 and c2, get next */
+#define LAST break /* end of loop, go closing */
+
+ module_connection();
+ check_bom(f);
+
+ while ((c1 = (*i_getc)(f)) != EOF) {
+#ifdef INPUT_CODE_FIX
+ if (!input_f)
+#endif
+ code_status(c1);
+ if (c2) {
+ /* second byte */
+ if (c2 > ((input_f == JIS_INPUT && ms_ucs_map_f) ? 0x92 : DEL)) {
+ /* in case of 8th bit is on */
+ if (!estab_f&&!mime_decode_mode) {
+ /* in case of not established yet */
+ /* It is still ambiguious */
+ if (h_conv(f, c2, c1)==EOF)
+ LAST;
+ else
+ c2 = 0;
+ NEXT;
+ } else {
+ /* in case of already established */
+ if (c1 < AT) {
+ /* ignore bogus code and not CP5022x UCD */
+ c2 = 0;
+ NEXT;
+ } else {
+ SEND;
+ }
+ }
+ } else
+ /* second byte, 7 bit code */
+ /* it might be kanji shitfted */
+ if ((c1 == DEL) || (c1 <= SPACE)) {
+ /* ignore bogus first code */
+ c2 = 0;
+ NEXT;
+ } else
+ SEND;
+ } else {
+ /* first byte */
+#ifdef UTF8_INPUT_ENABLE
+ if (iconv == w_iconv16) {
+ if (input_endian == ENDIAN_BIG) {
+ c2 = c1;
+ if ((c1 = (*i_getc)(f)) != EOF) {
+ if (0xD8 <= c2 && c2 <= 0xDB) {
+ if ((c0 = (*i_getc)(f)) != EOF) {
+ c0 <<= 8;
+ if ((c3 = (*i_getc)(f)) != EOF) {
+ c0 |= c3;
+ } else c2 = EOF;
+ } else c2 = EOF;
+ }
+ } else c2 = EOF;
+ } else {
+ if ((c2 = (*i_getc)(f)) != EOF) {
+ if (0xD8 <= c2 && c2 <= 0xDB) {
+ if ((c3 = (*i_getc)(f)) != EOF) {
+ if ((c0 = (*i_getc)(f)) != EOF) {
+ c0 <<= 8;
+ c0 |= c3;
+ } else c2 = EOF;
+ } else c2 = EOF;
+ }
+ } else c2 = EOF;
+ }
+ SEND;
+ } else if(iconv == w_iconv32){
+ int c3 = c1;
+ if((c2 = (*i_getc)(f)) != EOF &&
+ (c1 = (*i_getc)(f)) != EOF &&
+ (c0 = (*i_getc)(f)) != EOF){
+ switch(input_endian){
+ case ENDIAN_BIG:
+ c1 = (c2&0xFF)<<16 | (c1&0xFF)<<8 | (c0&0xFF);
+ break;
+ case ENDIAN_LITTLE:
+ c1 = (c3&0xFF) | (c2&0xFF)<<8 | (c1&0xFF)<<16;
+ break;
+ case ENDIAN_2143:
+ c1 = (c3&0xFF)<<16 | (c1&0xFF) | (c0&0xFF)<<8;
+ break;
+ case ENDIAN_3412:
+ c1 = (c3&0xFF)<<8 | (c2&0xFF) | (c0&0xFF)<<16;
+ break;
+ }
+ c2 = 0;
+ }else{
+ c2 = EOF;
+ }
+ SEND;
+ } else
+#endif
+#ifdef NUMCHAR_OPTION
+ if (is_unicode_capsule(c1)){
+ SEND;
+ } else
+#endif
+ if (c1 > ((input_f == JIS_INPUT && ms_ucs_map_f) ? 0x92 : DEL)) {
+ /* 8 bit code */
+ if (!estab_f && !iso8859_f) {
+ /* not established yet */
+ c2 = c1;
+ NEXT;
+ } else { /* estab_f==TRUE */
+ if (iso8859_f) {
+ c2 = ISO8859_1;
+ c1 &= 0x7f;
+ SEND;
+ } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
+ /* SJIS X0201 Case... */
+ if(iso2022jp_f && x0201_f==NO_X0201) {
+ (*oconv)(GETA1, GETA2);
+ NEXT;
+ } else {
+ c2 = X0201;
+ c1 &= 0x7f;
+ SEND;
+ }
+ } else if (c1==SSO && iconv != s_iconv) {
+ /* EUC X0201 Case */
+ c1 = (*i_getc)(f); /* skip SSO */
+ code_status(c1);
+ if (SSP<=c1 && c1<0xe0) {
+ if(iso2022jp_f && x0201_f==NO_X0201) {
+ (*oconv)(GETA1, GETA2);
+ NEXT;
+ } else {
+ c2 = X0201;
+ c1 &= 0x7f;
+ SEND;
+ }
+ } else { /* bogus code, skip SSO and one byte */
+ NEXT;
+ }
+ } else {
+ /* already established */
+ c2 = c1;
+ NEXT;
+ }
+ }
+ } else if ((c1 > SPACE) && (c1 != DEL)) {
+ /* in case of Roman characters */
+ if (shift_mode) {
+ /* output 1 shifted byte */
+ if (iso8859_f) {
+ c2 = ISO8859_1;
+ SEND;
+ } else if (SPACE<=c1 && c1<(0xe0&0x7f) ){
+ /* output 1 shifted byte */
+ if(iso2022jp_f && x0201_f==NO_X0201) {
+ (*oconv)(GETA1, GETA2);
+ NEXT;
+ } else {
+ c2 = X0201;
+ SEND;
+ }
+ } else {
+ /* look like bogus code */
+ NEXT;
+ }
+ } else if (input_mode == X0208 || input_mode == X0212 ||
+ input_mode == X0213_1 || input_mode == X0213_2) {
+ /* in case of Kanji shifted */
+ c2 = c1;
+ NEXT;
+ } else if (c1 == '=' && mime_f && !mime_decode_mode ) {
+ /* Check MIME code */
+ if ((c1 = (*i_getc)(f)) == EOF) {
+ (*oconv)(0, '=');
+ LAST;
+ } else if (c1 == '?') {
+ /* =? is mime conversion start sequence */
+ if(mime_f == STRICT_MIME) {
+ /* check in real detail */
+ if (mime_begin_strict(f) == EOF)
+ LAST;
+ else
+ NEXT;
+ } else if (mime_begin(f) == EOF)
+ LAST;
+ else
+ NEXT;
+ } else {
+ (*oconv)(0, '=');
+ (*i_ungetc)(c1,f);
+ NEXT;
+ }
+ } else {
+ /* normal ASCII code */
+ SEND;
+ }
+ } else if (c1 == SI && (!is_8bit || mime_decode_mode)) {
+ shift_mode = FALSE;
+ NEXT;
+ } else if (c1 == SO && (!is_8bit || mime_decode_mode)) {
+ shift_mode = TRUE;
+ NEXT;
+ } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) {
+ if ((c1 = (*i_getc)(f)) == EOF) {
+ /* (*oconv)(0, ESC); don't send bogus code */
+ LAST;
+ } else if (c1 == '$') {
+ if ((c1 = (*i_getc)(f)) == EOF) {
+ /*
+ (*oconv)(0, ESC); don't send bogus code
+ (*oconv)(0, '$'); */
+ LAST;
+ } else if (c1 == '@'|| c1 == 'B') {
+ /* This is kanji introduction */
+ input_mode = X0208;
+ shift_mode = FALSE;
+ set_input_codename("ISO-2022-JP");
+#ifdef CHECK_OPTION
+ debug(input_codename);
+#endif
+ NEXT;
+ } else if (c1 == '(') {
+ if ((c1 = (*i_getc)(f)) == EOF) {
+ /* don't send bogus code
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
+ (*oconv)(0, '(');
+ */
+ LAST;
+ } else if (c1 == '@'|| c1 == 'B') {
+ /* This is kanji introduction */
+ input_mode = X0208;
+ shift_mode = FALSE;
+ NEXT;
+#ifdef X0212_ENABLE
+ } else if (c1 == 'D'){
+ input_mode = X0212;
+ shift_mode = FALSE;
+ NEXT;
+#endif /* X0212_ENABLE */
+ } else if (c1 == (X0213_1&0x7F)){
+ input_mode = X0213_1;
+ shift_mode = FALSE;
+ NEXT;
+ } else if (c1 == (X0213_2&0x7F)){
+ input_mode = X0213_2;
+ shift_mode = FALSE;
+ NEXT;
+ } else {
+ /* could be some special code */
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
+ (*oconv)(0, '(');
+ (*oconv)(0, c1);
+ NEXT;
+ }
+ } else if (broken_f&0x2) {
+ /* accept any ESC-(-x as broken code ... */
+ input_mode = X0208;
+ shift_mode = FALSE;
+ NEXT;
+ } else {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
+ (*oconv)(0, c1);
+ NEXT;
+ }
+ } else if (c1 == '(') {
+ if ((c1 = (*i_getc)(f)) == EOF) {
+ /* don't send bogus code
+ (*oconv)(0, ESC);
+ (*oconv)(0, '('); */
+ LAST;
+ } else {
+ if (c1 == 'I') {
+ /* This is X0201 kana introduction */
+ input_mode = X0201; shift_mode = X0201;
+ NEXT;
+ } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
+ /* This is X0208 kanji introduction */
+ input_mode = ASCII; shift_mode = FALSE;
+ NEXT;
+ } else if (broken_f&0x2) {
+ input_mode = ASCII; shift_mode = FALSE;
+ NEXT;
+ } else {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '(');
+ /* maintain various input_mode here */
+ SEND;
+ }
+ }
+ } else if ( c1 == 'N' || c1 == 'n' ){
+ /* SS2 */
+ c3 = (*i_getc)(f); /* skip SS2 */
+ if ( (SPACE<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
+ c1 = c3;
+ c2 = X0201;
+ SEND;
+ }else{
+ (*i_ungetc)(c3, f);
+ /* lonely ESC */
+ (*oconv)(0, ESC);
+ SEND;
+ }
+ } else {
+ /* lonely ESC */
+ (*oconv)(0, ESC);
+ SEND;
+ }
+ } else if (c1 == ESC && iconv == s_iconv) {
+ /* ESC in Shift_JIS */
+ if ((c1 = (*i_getc)(f)) == EOF) {
+ /* (*oconv)(0, ESC); don't send bogus code */
+ LAST;
+ } else if (c1 == '$') {
+ /* J-PHONE emoji */
+ if ((c1 = (*i_getc)(f)) == EOF) {
+ /*
+ (*oconv)(0, ESC); don't send bogus code
+ (*oconv)(0, '$'); */
+ LAST;
+ } else {
+ if (('E' <= c1 && c1 <= 'G') ||
+ ('O' <= c1 && c1 <= 'Q')) {
+ /*
+ NUM : 0 1 2 3 4 5
+ BYTE: G E F O P Q
+ C%7 : 1 6 0 2 3 4
+ C%7 : 0 1 2 3 4 5 6
+ NUM : 2 0 3 4 5 X 1
+ */
+ static const int jphone_emoji_first_table[7] = {2, 0, 3, 4, 5, 0, 1};
+ c0 = (jphone_emoji_first_table[c1 % 7] << 8) - SPACE + 0xE000 + CLASS_UNICODE;
+ while ((c1 = (*i_getc)(f)) != EOF) {
+ if (SPACE <= c1 && c1 <= 'z') {
+ (*oconv)(0, c1 + c0);
+ } else break; /* c1 == SO */
+ }
+ }
+ }
+ if (c1 == EOF) LAST;
+ NEXT;
+ } else {
+ /* lonely ESC */
+ (*oconv)(0, ESC);
+ SEND;
+ }
+ } else if ((c1 == NL || c1 == CR) && broken_f&4) {
+ input_mode = ASCII; set_iconv(FALSE, 0);
+ SEND;
+ } else if (c1 == NL && mime_decode_f && !mime_decode_mode ) {
+ if ((c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
+ i_ungetc(SPACE,f);
+ continue;
+ } else {
+ i_ungetc(c1,f);
+ }
+ c1 = NL;
+ SEND;
+ } else if (c1 == CR && mime_decode_f && !mime_decode_mode ) {
+ if ((c1=(*i_getc)(f))!=EOF) {
+ if (c1==SPACE) {
+ i_ungetc(SPACE,f);
+ continue;
+ } else if (c1 == NL && (c1=(*i_getc)(f))!=EOF && c1 == SPACE) {
+ i_ungetc(SPACE,f);
+ continue;
+ } else {
+ i_ungetc(c1,f);
+ }
+ i_ungetc(NL,f);
+ } else {
+ i_ungetc(c1,f);
+ }
+ c1 = CR;
+ SEND;
+ } else if (c1 == DEL && input_mode == X0208 ) {
+ /* CP5022x */
+ c2 = c1;
+ NEXT;
+ } else
+ SEND;
+ }
+ /* send: */
+ switch(input_mode){
+ case ASCII:
+ switch ((*iconv)(c2, c1, c0)) { /* can be EUC / SJIS / UTF-8 / UTF-16 */
+ case -2:
+ /* 4 bytes UTF-8 */
+ if ((c0 = (*i_getc)(f)) != EOF) {
+ code_status(c0);
+ c0 <<= 8;
+ if ((c3 = (*i_getc)(f)) != EOF) {
+ code_status(c3);
+ (*iconv)(c2, c1, c0|c3);
+ }
+ }
+ break;
+ case -1:
+ /* 3 bytes EUC or UTF-8 */
+ if ((c0 = (*i_getc)(f)) != EOF) {
+ code_status(c0);
+ (*iconv)(c2, c1, c0);
+ }
+ break;
+ }
+ break;
+ case X0208:
+ case X0213_1:
+ if (ms_ucs_map_f &&
+ 0x7F <= c2 && c2 <= 0x92 &&
+ 0x21 <= c1 && c1 <= 0x7E) {
+ /* CP932 UDC */
+ if(c1 == 0x7F) return 0;
+ c1 = (c2 - 0x7F) * 94 + c1 - 0x21 + 0xE000 + CLASS_UNICODE;
+ c2 = 0;
+ }
+ (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
+ break;
+#ifdef X0212_ENABLE
+ case X0212:
+ (*oconv)(PREFIX_EUCG3 | c2, c1);
+ break;
+#endif /* X0212_ENABLE */
+ case X0213_2:
+ (*oconv)(PREFIX_EUCG3 | c2, c1);
+ break;
+ default:
+ (*oconv)(input_mode, c1); /* other special case */
+ }
+
+ c2 = 0;
+ c0 = 0;
+ continue;
+ /* goto next_word */
+ }
+
+ /* epilogue */
+ (*iconv)(EOF, 0, 0);
+ if (!is_inputcode_set)
+ {
+ if (is_8bit) {
+ struct input_code *p = input_code_list;
+ struct input_code *result = p;
+ while (p->name){
+ if (p->score < result->score) result = p;
+ ++p;
+ }
+ set_input_codename(result->name);
+ }
+ }
+ return 1;
+}
+
+nkf_char
+h_conv(FILE *f, nkf_char c2, nkf_char c1)
+{
+ nkf_char ret, c3, c0;
+ int hold_index;
+
+
+ /** it must NOT be in the kanji shifte sequence */
+ /** it must NOT be written in JIS7 */
+ /** and it must be after 2 byte 8bit code */
+
+ hold_count = 0;
+ push_hold_buf(c2);
+ push_hold_buf(c1);
+
+ while ((c1 = (*i_getc)(f)) != EOF) {
+ if (c1 == ESC){
+ (*i_ungetc)(c1,f);
+ break;
+ }
+ code_status(c1);
+ if (push_hold_buf(c1) == EOF || estab_f){
+ break;
+ }
+ }
+
+ if (!estab_f){
+ struct input_code *p = input_code_list;
+ struct input_code *result = p;
+ if (c1 == EOF){
+ code_status(c1);
+ }
+ while (p->name){
+ if (p->status_func && p->score < result->score){
+ result = p;
+ }
+ ++p;
+ }
+ set_iconv(TRUE, result->iconv_func);
+ }
+
+
+ /** now,
+ ** 1) EOF is detected, or
+ ** 2) Code is established, or
+ ** 3) Buffer is FULL (but last word is pushed)
+ **
+ ** in 1) and 3) cases, we continue to use
+ ** Kanji codes by oconv and leave estab_f unchanged.
+ **/
+
+ ret = c1;
+ hold_index = 0;
+ while (hold_index < hold_count){
+ c2 = hold_buf[hold_index++];
+ if (c2 <= DEL
+#ifdef NUMCHAR_OPTION
+ || is_unicode_capsule(c2)
+#endif
+ ){
+ (*iconv)(0, c2, 0);
+ continue;
+ }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
+ (*iconv)(X0201, c2, 0);
+ continue;
+ }
+ if (hold_index < hold_count){
+ c1 = hold_buf[hold_index++];
+ }else{
+ c1 = (*i_getc)(f);
+ if (c1 == EOF){
+ c3 = EOF;
+ break;
+ }
+ code_status(c1);
+ }
+ c0 = 0;
+ switch ((*iconv)(c2, c1, 0)) { /* can be EUC/SJIS/UTF-8 */
+ case -2:
+ /* 4 bytes UTF-8 */
+ if (hold_index < hold_count){
+ c0 = hold_buf[hold_index++];
+ } else if ((c0 = (*i_getc)(f)) == EOF) {
+ ret = EOF;
+ break;
+ } else {
+ code_status(c0);
+ c0 <<= 8;
+ if (hold_index < hold_count){
+ c3 = hold_buf[hold_index++];
+ } else if ((c3 = (*i_getc)(f)) == EOF) {
+ c0 = ret = EOF;
+ break;
+ } else {
+ code_status(c3);
+ (*iconv)(c2, c1, c0|c3);
+ }
+ }
+ break;
+ case -1:
+ /* 3 bytes EUC or UTF-8 */
+ if (hold_index < hold_count){
+ c0 = hold_buf[hold_index++];
+ } else if ((c0 = (*i_getc)(f)) == EOF) {
+ ret = EOF;
+ break;
+ } else {
+ code_status(c0);
+ }
+ (*iconv)(c2, c1, c0);
+ break;
+ }
+ if (c0 == EOF) break;
+ }
+ return ret;
+}
+
+nkf_char push_hold_buf(nkf_char c2)
+{
+ if (hold_count >= HOLD_SIZE*2)
+ return (EOF);
+ hold_buf[hold_count++] = (unsigned char)c2;
+ return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
+}
+
+nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
+{
+#if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE)
+ nkf_char val;
+#endif
+ static const nkf_char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
+#ifdef SHIFTJIS_CP932
+ if (!cp932inv_f && is_ibmext_in_sjis(c2)){
+#if 0
+ extern const unsigned short shiftjis_cp932[3][189];
+#endif
+ val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
+ if (val){
+ c2 = val >> 8;
+ c1 = val & 0xff;
+ }
+ }
+ if (cp932inv_f
+ && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
+#if 0
+ extern const unsigned short cp932inv[2][189];
+#endif
+ nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
+ if (c){
+ c2 = c >> 8;
+ c1 = c & 0xff;
+ }
+ }
+#endif /* SHIFTJIS_CP932 */
+#ifdef X0212_ENABLE
+ if (!x0213_f && is_ibmext_in_sjis(c2)){
+#if 0
+ extern const unsigned short shiftjis_x0212[3][189];
+#endif
+ val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
+ if (val){
+ if (val > 0x7FFF){
+ c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f);
+ c1 = val & 0xff;
+ }else{
+ c2 = val >> 8;
+ c1 = val & 0xff;
+ }
+ if (p2) *p2 = c2;
+ if (p1) *p1 = c1;
+ return 0;
+ }
+ }
+#endif
+ if(c2 >= 0x80){
+ if(x0213_f && c2 >= 0xF0){
+ if(c2 <= 0xF3 || (c2 == 0xF4 && c1 < 0x9F)){ /* k=1, 3<=k<=5, k=8, 12<=k<=15 */
+ c2 = PREFIX_EUCG3 | 0x20 | shift_jisx0213_s1a3_table[c2 - 0xF0][0x9E < c1];
+ }else{ /* 78<=k<=94 */
+ c2 = PREFIX_EUCG3 | (c2 * 2 - 0x17B);
+ if (0x9E < c1) c2++;
+ }
+ }else{
+ c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394);
+ if (0x9E < c1) c2++;
+ }
+ if (c1 < 0x9F)
+ c1 = c1 - ((c1 > DEL) ? SPACE : 0x1F);
+ else {
+ c1 = c1 - 0x7E;
+ }
+ }
+
+#ifdef X0212_ENABLE
+ c2 = x0212_unshift(c2);
+#endif
+ if (p2) *p2 = c2;
+ if (p1) *p1 = c1;
+ return 0;
+}
+
+nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
+{
+ if (c2 == X0201) {
+ c1 &= 0x7f;
+ } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
+ /* NOP */
+ } else if (!x0213_f && 0xF0 <= c2 && c2 <= 0xF9 && 0x40 <= c1 && c1 <= 0xFC) {
+ /* CP932 UDC */
+ if(c1 == 0x7F) return 0;
+ c1 = (c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000 + CLASS_UNICODE;
+ c2 = 0;
+ } else {
+ nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
+ if (ret) return ret;
+ }
+ (*oconv)(c2, c1);
+ return 0;
+}
+
+nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
+{
+ if (c2 == X0201) {
+ c1 &= 0x7f;
+#ifdef X0212_ENABLE
+ }else if (c2 == 0x8f){
+ if (c0 == 0){
+ return -1;
+ }
+ if (!cp51932_f && !x0213_f && 0xF5 <= c1 && c1 <= 0xFE && 0xA1 <= c0 && c0 <= 0xFE) {
+ /* encoding is eucJP-ms, so invert to Unicode Private User Area */
+ c1 = (c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC + CLASS_UNICODE;
+ c2 = 0;
+ } else {
+ c2 = (c2 << 8) | (c1 & 0x7f);
+ c1 = c0 & 0x7f;
+#ifdef SHIFTJIS_CP932
+ if (cp51932_f){
+ nkf_char s2, s1;
+ if (e2s_conv(c2, c1, &s2, &s1) == 0){
+ s2e_conv(s2, s1, &c2, &c1);
+ if (c2 < 0x100){
+ c1 &= 0x7f;
+ c2 &= 0x7f;
+ }
+ }
+ }
+#endif /* SHIFTJIS_CP932 */
+ }
+#endif /* X0212_ENABLE */
+ } else if (c2 == SSO){
+ c2 = X0201;
+ c1 &= 0x7f;
+ } else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
+ /* NOP */
+ } else {
+ if (!cp51932_f && ms_ucs_map_f && 0xF5 <= c2 && c2 <= 0xFE && 0xA1 <= c1 && c1 <= 0xFE) {
+ /* encoding is eucJP-ms, so invert to Unicode Private User Area */
+ c1 = (c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000 + CLASS_UNICODE;
+ c2 = 0;
+ } else {
+ c1 &= 0x7f;
+ c2 &= 0x7f;
+#ifdef SHIFTJIS_CP932
+ if (cp51932_f && 0x79 <= c2 && c2 <= 0x7c){
+ nkf_char s2, s1;
+ if (e2s_conv(c2, c1, &s2, &s1) == 0){
+ s2e_conv(s2, s1, &c2, &c1);
+ if (c2 < 0x100){
+ c1 &= 0x7f;
+ c2 &= 0x7f;
+ }
+ }
+ }
+#endif /* SHIFTJIS_CP932 */
+ }
+ }
+ (*oconv)(c2, c1);
+ return 0;
+}
+
+#ifdef UTF8_INPUT_ENABLE
+nkf_char w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
+{
+ nkf_char ret = 0;
+
+ if (!c1){
+ *p2 = 0;
+ *p1 = c2;
+ }else if (0xc0 <= c2 && c2 <= 0xef) {
+ ret = unicode_to_jis_common(c2, c1, c0, p2, p1);
+#ifdef NUMCHAR_OPTION
+ if (ret > 0){
+ if (p2) *p2 = 0;
+ if (p1) *p1 = CLASS_UNICODE | ww16_conv(c2, c1, c0);
+ ret = 0;
+ }
+#endif
+ }
+ return ret;
+}
+
+nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
+{
+ nkf_char ret = 0;
+ static const int w_iconv_utf8_1st_byte[] =
+ { /* 0xC0 - 0xFF */
+ 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33,
+ 40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70};
+
+ if (c2 < 0 || 0xff < c2) {
+ }else if (c2 == 0) { /* 0 : 1 byte*/
+ c0 = 0;
+ } else if ((c2 & 0xc0) == 0x80) { /* 0x80-0xbf : trail byte */
+ return 0;
+ } else{
+ switch (w_iconv_utf8_1st_byte[c2 - 0xC0]) {
+ case 21:
+ if (c1 < 0x80 || 0xBF < c1) return 0;
+ break;
+ case 30:
+ if (c0 == 0) return -1;
+ if (c1 < 0xA0 || 0xBF < c1 || (c0 & 0xc0) != 0x80)
+ return 0;
+ break;
+ case 31:
+ case 33:
+ if (c0 == 0) return -1;
+ if ((c1 & 0xc0) != 0x80 || (c0 & 0xc0) != 0x80)
+ return 0;
+ break;
+ case 32:
+ if (c0 == 0) return -1;
+ if (c1 < 0x80 || 0x9F < c1 || (c0 & 0xc0) != 0x80)
+ return 0;
+ break;
+ case 40:
+ if (c0 == 0) return -2;
+ if (c1 < 0x90 || 0xBF < c1 || (c0 & 0xc0c0) != 0x8080)
+ return 0;
+ break;
+ case 41:
+ if (c0 == 0) return -2;
+ if (c1 < 0x80 || 0xBF < c1 || (c0 & 0xc0c0) != 0x8080)
+ return 0;
+ break;
+ case 42:
+ if (c0 == 0) return -2;
+ if (c1 < 0x80 || 0x8F < c1 || (c0 & 0xc0c0) != 0x8080)
+ return 0;
+ break;
+ default:
+ return 0;
+ break;
+ }
+ }
+ if (c2 == 0 || c2 == EOF){
+ } else if ((c2 & 0xf8) == 0xf0) { /* 4 bytes */
+ c1 = CLASS_UNICODE | ww16_conv(c2, c1, c0);
+ c2 = 0;
+ } else {
+ ret = w2e_conv(c2, c1, c0, &c2, &c1);
+ }
+ if (ret == 0){
+ (*oconv)(c2, c1);
+ }
+ return ret;
+}
+#endif
+
+#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
+void w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0)
+{
+ val &= VALUE_MASK;
+ if (val < 0x80){
+ *p2 = val;
+ *p1 = 0;
+ *p0 = 0;
+ }else if (val < 0x800){
+ *p2 = 0xc0 | (val >> 6);
+ *p1 = 0x80 | (val & 0x3f);
+ *p0 = 0;
+ } else if (val <= NKF_INT32_C(0xFFFF)) {
+ *p2 = 0xe0 | (val >> 12);
+ *p1 = 0x80 | ((val >> 6) & 0x3f);
+ *p0 = 0x80 | (val & 0x3f);
+ } else if (val <= NKF_INT32_C(0x10FFFF)) {
+ *p2 = 0xe0 | (val >> 16);
+ *p1 = 0x80 | ((val >> 12) & 0x3f);
+ *p0 = 0x8080 | ((val << 2) & 0x3f00)| (val & 0x3f);
+ } else {
+ *p2 = 0;
+ *p1 = 0;
+ *p0 = 0;
+ }
+}
+#endif
+
+#ifdef UTF8_INPUT_ENABLE
+nkf_char ww16_conv(nkf_char c2, nkf_char c1, nkf_char c0)
+{
+ nkf_char val;
+ if (c2 >= 0xf8) {
+ val = -1;
+ } else if (c2 >= 0xf0){
+ /* c2: 1st, c1: 2nd, c0: 3rd/4th */
+ val = (c2 & 0x0f) << 18;
+ val |= (c1 & 0x3f) << 12;
+ val |= (c0 & 0x3f00) >> 2;
+ val |= (c0 & 0x3f);
+ }else if (c2 >= 0xe0){
+ val = (c2 & 0x0f) << 12;
+ val |= (c1 & 0x3f) << 6;
+ val |= (c0 & 0x3f);
+ }else if (c2 >= 0xc0){
+ val = (c2 & 0x1f) << 6;
+ val |= (c1 & 0x3f);
+ }else{
+ val = c2;
+ }
+ return val;
+}
+
+nkf_char w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
+{
+ nkf_char c2, c1, c0;
+ nkf_char ret = 0;
+ val &= VALUE_MASK;
+ if (val < 0x80){
+ *p2 = 0;
+ *p1 = val;
+ }else{
+ w16w_conv(val, &c2, &c1, &c0);
+ ret = unicode_to_jis_common(c2, c1, c0, p2, p1);
+#ifdef NUMCHAR_OPTION
+ if (ret > 0){
+ *p2 = 0;
+ *p1 = CLASS_UNICODE | val;
+ ret = 0;
+ }
+#endif
+ }
+ return ret;
+}
+#endif
+
+#ifdef UTF8_INPUT_ENABLE
+nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
+{
+ nkf_char ret = 0;
+ if ((c2==0 && c1 < 0x80) || c2==EOF) {
+ (*oconv)(c2, c1);
+ return 0;
+ }else if (0xD8 <= c2 && c2 <= 0xDB) {
+ if (c0 < NKF_INT32_C(0xDC00) || NKF_INT32_C(0xDFFF) < c0)
+ return -2;
+ c1 = CLASS_UNICODE | ((c2 << 18) + (c1 << 10) + c0 - NKF_INT32_C(0x35FDC00));
+ c2 = 0;
+ }else if ((c2>>3) == 27) { /* unpaired surrogate */
+ /*
+ return 2;
+ */
+ return 1;
+ }else ret = w16e_conv(((c2 & 0xff)<<8) + c1, &c2, &c1);
+ if (ret) return ret;
+ (*oconv)(c2, c1);
+ return 0;
+}
+
+nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
+{
+ int ret = 0;
+
+ if ((c2 == 0 && c1 < 0x80) || c2==EOF) {
+ } else if (is_unicode_bmp(c1)) {
+ ret = w16e_conv(c1, &c2, &c1);
+ } else {
+ c2 = 0;
+ c1 = CLASS_UNICODE | c1;
+ }
+ if (ret) return ret;
+ (*oconv)(c2, c1);
+ return 0;
+}
+
+nkf_char unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
+{
+#if 0
+ extern const unsigned short *const utf8_to_euc_2bytes[];
+ extern const unsigned short *const utf8_to_euc_2bytes_ms[];
+ extern const unsigned short *const utf8_to_euc_2bytes_932[];
+ extern const unsigned short *const *const utf8_to_euc_3bytes[];
+ extern const unsigned short *const *const utf8_to_euc_3bytes_ms[];
+ extern const unsigned short *const *const utf8_to_euc_3bytes_932[];
+#endif
+ const unsigned short *const *pp;
+ const unsigned short *const *const *ppp;
+ static const int no_best_fit_chars_table_C2[] =
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 1, 2,
+ 0, 0, 1, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1};
+ static const int no_best_fit_chars_table_C2_ms[] =
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0};
+ static const int no_best_fit_chars_table_932_C2[] =
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0};
+ static const int no_best_fit_chars_table_932_C3[] =
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1};
+ nkf_char ret = 0;
+
+ if(c2 < 0x80){
+ *p2 = 0;
+ *p1 = c2;
+ }else if(c2 < 0xe0){
+ if(no_best_fit_chars_f){
+ if(ms_ucs_map_f == UCS_MAP_CP932){
+ switch(c2){
+ case 0xC2:
+ if(no_best_fit_chars_table_932_C2[c1&0x3F]) return 1;
+ break;
+ case 0xC3:
+ if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
+ break;
+ }
+ }else if(!cp932inv_f){
+ switch(c2){
+ case 0xC2:
+ if(no_best_fit_chars_table_C2[c1&0x3F]) return 1;
+ break;
+ case 0xC3:
+ if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
+ break;
+ }
+ }else if(ms_ucs_map_f == UCS_MAP_MS){
+ if(c2 == 0xC2 && no_best_fit_chars_table_C2_ms[c1&0x3F]) return 1;
+ }
+ }
+ pp =
+ ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_2bytes_932 :
+ ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms :
+ utf8_to_euc_2bytes;
+ ret = w_iconv_common(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1);
+ }else if(c0 < 0xF0){
+ if(no_best_fit_chars_f){
+ if(ms_ucs_map_f == UCS_MAP_CP932){
+ if(c2 == 0xE3 && c1 == 0x82 && c0 == 0x94) return 1;
+ }else if(ms_ucs_map_f == UCS_MAP_MS){
+ switch(c2){
+ case 0xE2:
+ switch(c1){
+ case 0x80:
+ if(c0 == 0x94 || c0 == 0x96 || c0 == 0xBE) return 1;
+ break;
+ case 0x88:
+ if(c0 == 0x92) return 1;
+ break;
+ }
+ break;
+ case 0xE3:
+ if(c1 == 0x80 || c0 == 0x9C) return 1;
+ break;
+ }
+ }else{
+ switch(c2){
+ case 0xE2:
+ switch(c1){
+ case 0x80:
+ if(c0 == 0x95) return 1;
+ break;
+ case 0x88:
+ if(c0 == 0xA5) return 1;
+ break;
+ }
+ break;
+ case 0xEF:
+ switch(c1){
+ case 0xBC:
+ if(c0 == 0x8D) return 1;
+ break;
+ case 0xBD:
+ if(c0 == 0x9E && !cp932inv_f) return 1;
+ break;
+ case 0xBF:
+ if(0xA0 <= c0 && c0 <= 0xA5) return 1;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ ppp =
+ ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_3bytes_932 :
+ ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms :
+ utf8_to_euc_3bytes;
+ ret = w_iconv_common(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
+ }else return -1;
+#ifdef SHIFTJIS_CP932
+ if (!ret && !cp932inv_f && is_eucg3(*p2)) {
+ nkf_char s2, s1;
+ if (e2s_conv(*p2, *p1, &s2, &s1) == 0) {
+ s2e_conv(s2, s1, p2, p1);
+ }else{
+ ret = 1;
+ }
+ }
+#endif
+ return ret;
+}
+
+nkf_char w_iconv_common(nkf_char c1, nkf_char c0, const unsigned short *const *pp, nkf_char psize, nkf_char *p2, nkf_char *p1)
+{
+ nkf_char c2;
+ const unsigned short *p;
+ unsigned short val;
+
+ if (pp == 0) return 1;
+
+ c1 -= 0x80;
+ if (c1 < 0 || psize <= c1) return 1;
+ p = pp[c1];
+ if (p == 0) return 1;
+
+ c0 -= 0x80;
+ if (c0 < 0 || sizeof_utf8_to_euc_C2 <= c0) return 1;
+ val = p[c0];
+ if (val == 0) return 1;
+ if (no_cp932ext_f && (
+ (val>>8) == 0x2D || /* NEC special characters */
+ val > NKF_INT32_C(0xF300) /* IBM extended characters */
+ )) return 1;
+
+ c2 = val >> 8;
+ if (val > 0x7FFF){
+ c2 &= 0x7f;
+ c2 |= PREFIX_EUCG3;
+ }
+ if (c2 == SO) c2 = X0201;
+ c1 = val & 0x7f;
+ if (p2) *p2 = c2;
+ if (p1) *p1 = c1;
+ return 0;
+}
+
+void nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c)
+{
+ const char *hex = "0123456789ABCDEF";
+ int shift = 20;
+ c &= VALUE_MASK;
+ while(shift >= 0){
+ if(c >= 1<<shift){
+ while(shift >= 0){
+ (*f)(0, hex[(c>>shift)&0xF]);
+ shift -= 4;
+ }
+ }else{
+ shift -= 4;
+ }
+ }
+ return;
+}
+
+void encode_fallback_html(nkf_char c)
+{
+ (*oconv)(0, '&');
+ (*oconv)(0, '#');
+ c &= VALUE_MASK;
+ if(c >= NKF_INT32_C(1000000))
+ (*oconv)(0, 0x30+(c/NKF_INT32_C(1000000))%10);
+ if(c >= NKF_INT32_C(100000))
+ (*oconv)(0, 0x30+(c/NKF_INT32_C(100000) )%10);
+ if(c >= 10000)
+ (*oconv)(0, 0x30+(c/10000 )%10);
+ if(c >= 1000)
+ (*oconv)(0, 0x30+(c/1000 )%10);
+ if(c >= 100)
+ (*oconv)(0, 0x30+(c/100 )%10);
+ if(c >= 10)
+ (*oconv)(0, 0x30+(c/10 )%10);
+ if(c >= 0)
+ (*oconv)(0, 0x30+ c %10);
+ (*oconv)(0, ';');
+ return;
+}
+
+void encode_fallback_xml(nkf_char c)
+{
+ (*oconv)(0, '&');
+ (*oconv)(0, '#');
+ (*oconv)(0, 'x');
+ nkf_each_char_to_hex(oconv, c);
+ (*oconv)(0, ';');
+ return;
+}
+
+void encode_fallback_java(nkf_char c)
+{
+ const char *hex = "0123456789ABCDEF";
+ (*oconv)(0, '\\');
+ c &= VALUE_MASK;
+ if(!is_unicode_bmp(c)){
+ (*oconv)(0, 'U');
+ (*oconv)(0, '0');
+ (*oconv)(0, '0');
+ (*oconv)(0, hex[(c>>20)&0xF]);
+ (*oconv)(0, hex[(c>>16)&0xF]);
+ }else{
+ (*oconv)(0, 'u');
+ }
+ (*oconv)(0, hex[(c>>12)&0xF]);
+ (*oconv)(0, hex[(c>> 8)&0xF]);
+ (*oconv)(0, hex[(c>> 4)&0xF]);
+ (*oconv)(0, hex[ c &0xF]);
+ return;
+}
+
+void encode_fallback_perl(nkf_char c)
+{
+ (*oconv)(0, '\\');
+ (*oconv)(0, 'x');
+ (*oconv)(0, '{');
+ nkf_each_char_to_hex(oconv, c);
+ (*oconv)(0, '}');
+ return;
+}
+
+void encode_fallback_subchar(nkf_char c)
+{
+ c = unicode_subchar;
+ (*oconv)((c>>8)&0xFF, c&0xFF);
+ return;
+}
+#endif
+
+#ifdef UTF8_OUTPUT_ENABLE
+nkf_char e2w_conv(nkf_char c2, nkf_char c1)
+{
+#if 0
+ extern const unsigned short euc_to_utf8_1byte[];
+ extern const unsigned short *const euc_to_utf8_2bytes[];
+ extern const unsigned short *const euc_to_utf8_2bytes_ms[];
+ extern const unsigned short *const x0212_to_utf8_2bytes[];
+#endif
+ const unsigned short *p;
+
+ if (c2 == X0201) {
+ p = euc_to_utf8_1byte;
+#ifdef X0212_ENABLE
+ } else if (is_eucg3(c2)){
+ if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){
+ return 0xA6;
+ }
+ c2 = (c2&0x7f) - 0x21;
+ if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
+ p = x0212_to_utf8_2bytes[c2];
+ else
+ return 0;
+#endif
+ } else {
+ c2 &= 0x7f;
+ c2 = (c2&0x7f) - 0x21;
+ if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
+ p = ms_ucs_map_f != UCS_MAP_ASCII ? euc_to_utf8_2bytes_ms[c2] : euc_to_utf8_2bytes[c2];
+ else
+ return 0;
+ }
+ if (!p) return 0;
+ c1 = (c1 & 0x7f) - 0x21;
+ if (0<=c1 && c1<sizeof_euc_to_utf8_1byte)
+ return p[c1];
+ return 0;
+}
+
+void w_oconv(nkf_char c2, nkf_char c1)
+{
+ nkf_char c0;
+ nkf_char val;
+
+ if (output_bom_f) {
+ output_bom_f = FALSE;
+ (*o_putc)('\357');
+ (*o_putc)('\273');
+ (*o_putc)('\277');
+ }
+
+ if (c2 == EOF) {
+ (*o_putc)(EOF);
+ return;
+ }
+
+#ifdef NUMCHAR_OPTION
+ if (c2 == 0 && is_unicode_capsule(c1)){
+ val = c1 & VALUE_MASK;
+ if (val < 0x80){
+ (*o_putc)(val);
+ }else if (val < 0x800){
+ (*o_putc)(0xC0 | (val >> 6));
+ (*o_putc)(0x80 | (val & 0x3f));
+ } else if (val <= NKF_INT32_C(0xFFFF)) {
+ (*o_putc)(0xE0 | (val >> 12));
+ (*o_putc)(0x80 | ((val >> 6) & 0x3f));
+ (*o_putc)(0x80 | (val & 0x3f));
+ } else if (val <= NKF_INT32_C(0x10FFFF)) {
+ (*o_putc)(0xF0 | ( val>>18));
+ (*o_putc)(0x80 | ((val>>12) & 0x3f));
+ (*o_putc)(0x80 | ((val>> 6) & 0x3f));
+ (*o_putc)(0x80 | ( val & 0x3f));
+ }
+ return;
+ }
+#endif
+
+ if (c2 == 0) {
+ output_mode = ASCII;
+ (*o_putc)(c1);
+ } else if (c2 == ISO8859_1) {
+ output_mode = ISO8859_1;
+ (*o_putc)(c1 | 0x080);
+ } else {
+ output_mode = UTF8;
+ val = e2w_conv(c2, c1);
+ if (val){
+ w16w_conv(val, &c2, &c1, &c0);
+ (*o_putc)(c2);
+ if (c1){
+ (*o_putc)(c1);
+ if (c0) (*o_putc)(c0);
+ }
+ }
+ }
+}
+
+void w_oconv16(nkf_char c2, nkf_char c1)
+{
+ if (output_bom_f) {
+ output_bom_f = FALSE;
+ if (output_endian == ENDIAN_LITTLE){
+ (*o_putc)((unsigned char)'\377');
+ (*o_putc)('\376');
+ }else{
+ (*o_putc)('\376');
+ (*o_putc)((unsigned char)'\377');
+ }
+ }
+
+ if (c2 == EOF) {
+ (*o_putc)(EOF);
+ return;
+ }
+
+ if (c2 == ISO8859_1) {
+ c2 = 0;
+ c1 |= 0x80;
+#ifdef NUMCHAR_OPTION
+ } else if (c2 == 0 && is_unicode_capsule(c1)) {
+ if (is_unicode_bmp(c1)) {
+ c2 = (c1 >> 8) & 0xff;
+ c1 &= 0xff;
+ } else {
+ c1 &= VALUE_MASK;
+ if (c1 <= UNICODE_MAX) {
+ c2 = (c1 >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */
+ c1 = (c1 & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
+ if (output_endian == ENDIAN_LITTLE){
+ (*o_putc)(c2 & 0xff);
+ (*o_putc)((c2 >> 8) & 0xff);
+ (*o_putc)(c1 & 0xff);
+ (*o_putc)((c1 >> 8) & 0xff);
+ }else{
+ (*o_putc)((c2 >> 8) & 0xff);
+ (*o_putc)(c2 & 0xff);
+ (*o_putc)((c1 >> 8) & 0xff);
+ (*o_putc)(c1 & 0xff);
+ }
+ }
+ return;
+ }
+#endif
+ } else if (c2) {
+ nkf_char val = e2w_conv(c2, c1);
+ c2 = (val >> 8) & 0xff;
+ c1 = val & 0xff;
+ if (!val) return;
+ }
+ if (output_endian == ENDIAN_LITTLE){
+ (*o_putc)(c1);
+ (*o_putc)(c2);
+ }else{
+ (*o_putc)(c2);
+ (*o_putc)(c1);
+ }
+}
+
+void w_oconv32(nkf_char c2, nkf_char c1)
+{
+ if (output_bom_f) {
+ output_bom_f = FALSE;
+ if (output_endian == ENDIAN_LITTLE){
+ (*o_putc)((unsigned char)'\377');
+ (*o_putc)('\376');
+ (*o_putc)('\000');
+ (*o_putc)('\000');
+ }else{
+ (*o_putc)('\000');
+ (*o_putc)('\000');
+ (*o_putc)('\376');
+ (*o_putc)((unsigned char)'\377');
+ }
+ }
+
+ if (c2 == EOF) {
+ (*o_putc)(EOF);
+ return;
+ }
+
+ if (c2 == ISO8859_1) {
+ c1 |= 0x80;
+#ifdef NUMCHAR_OPTION
+ } else if (c2 == 0 && is_unicode_capsule(c1)) {
+ c1 &= VALUE_MASK;
+#endif
+ } else if (c2) {
+ c1 = e2w_conv(c2, c1);
+ if (!c1) return;
+ }
+ if (output_endian == ENDIAN_LITTLE){
+ (*o_putc)( c1 & NKF_INT32_C(0x000000FF));
+ (*o_putc)((c1 & NKF_INT32_C(0x0000FF00)) >> 8);
+ (*o_putc)((c1 & NKF_INT32_C(0x00FF0000)) >> 16);
+ (*o_putc)('\000');
+ }else{
+ (*o_putc)('\000');
+ (*o_putc)((c1 & NKF_INT32_C(0x00FF0000)) >> 16);
+ (*o_putc)((c1 & NKF_INT32_C(0x0000FF00)) >> 8);
+ (*o_putc)( c1 & NKF_INT32_C(0x000000FF));
+ }
+}
+#endif
+
+void e_oconv(nkf_char c2, nkf_char c1)
+{
+#ifdef NUMCHAR_OPTION
+ if (c2 == 0 && is_unicode_capsule(c1)){
+ w16e_conv(c1, &c2, &c1);
+ if (c2 == 0 && is_unicode_capsule(c1)){
+ c2 = c1 & VALUE_MASK;
+ if (x0212_f && 0xE000 <= c2 && c2 <= 0xE757) {
+ /* eucJP-ms UDC */
+ c1 &= 0xFFF;
+ c2 = c1 / 94;
+ c2 += c2 < 10 ? 0x75 : 0x8FEB;
+ c1 = 0x21 + c1 % 94;
+ if (is_eucg3(c2)){
+ (*o_putc)(0x8f);
+ (*o_putc)((c2 & 0x7f) | 0x080);
+ (*o_putc)(c1 | 0x080);
+ }else{
+ (*o_putc)((c2 & 0x7f) | 0x080);
+ (*o_putc)(c1 | 0x080);
+ }
+ return;
+ } else {
+ if (encode_fallback) (*encode_fallback)(c1);
+ return;
+ }
+ }
+ }
+#endif
+ if (c2 == EOF) {
+ (*o_putc)(EOF);
+ return;
+ } else if (c2 == 0) {
+ output_mode = ASCII;
+ (*o_putc)(c1);
+ } else if (c2 == X0201) {
+ output_mode = JAPANESE_EUC;
+ (*o_putc)(SSO); (*o_putc)(c1|0x80);
+ } else if (c2 == ISO8859_1) {
+ output_mode = ISO8859_1;
+ (*o_putc)(c1 | 0x080);
+#ifdef X0212_ENABLE
+ } else if (is_eucg3(c2)){
+ output_mode = JAPANESE_EUC;
+#ifdef SHIFTJIS_CP932
+ if (!cp932inv_f){
+ nkf_char s2, s1;
+ if (e2s_conv(c2, c1, &s2, &s1) == 0){
+ s2e_conv(s2, s1, &c2, &c1);
+ }
+ }
+#endif
+ if (c2 == 0) {
+ output_mode = ASCII;
+ (*o_putc)(c1);
+ }else if (is_eucg3(c2)){
+ if (x0212_f){
+ (*o_putc)(0x8f);
+ (*o_putc)((c2 & 0x7f) | 0x080);
+ (*o_putc)(c1 | 0x080);
+ }
+ }else{
+ (*o_putc)((c2 & 0x7f) | 0x080);
+ (*o_putc)(c1 | 0x080);
+ }
+#endif
+ } else {
+ if (!nkf_isgraph(c1) || !nkf_isgraph(c2)) {
+ set_iconv(FALSE, 0);
+ return; /* too late to rescue this char */
+ }
+ output_mode = JAPANESE_EUC;
+ (*o_putc)(c2 | 0x080);
+ (*o_putc)(c1 | 0x080);
+ }
+}
+
+#ifdef X0212_ENABLE
+nkf_char x0212_shift(nkf_char c)
+{
+ nkf_char ret = c;
+ c &= 0x7f;
+ if (is_eucg3(ret)){
+ if (0x75 <= c && c <= 0x7f){
+ ret = c + (0x109 - 0x75);
+ }
+ }else{
+ if (0x75 <= c && c <= 0x7f){
+ ret = c + (0x113 - 0x75);
+ }
+ }
+ return ret;
+}
+
+
+nkf_char x0212_unshift(nkf_char c)
+{
+ nkf_char ret = c;
+ if (0x7f <= c && c <= 0x88){
+ ret = c + (0x75 - 0x7f);
+ }else if (0x89 <= c && c <= 0x92){
+ ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89));
+ }
+ return ret;
+}
+#endif /* X0212_ENABLE */
+
+nkf_char e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
+{
+ nkf_char ndx;
+ if (is_eucg3(c2)){
+ ndx = c2 & 0x7f;
+ if (x0213_f){
+ if((0x21 <= ndx && ndx <= 0x2F)){
+ if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3;
+ if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
+ return 0;
+ }else if(0x6E <= ndx && ndx <= 0x7E){
+ if (p2) *p2 = ((ndx - 1) >> 1) + 0xbe;
+ if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
+ return 0;
+ }
+ return 1;
+ }
+#ifdef X0212_ENABLE
+ else if(nkf_isgraph(ndx)){
+ nkf_char val = 0;
+ const unsigned short *ptr;
+#if 0
+ extern const unsigned short *const x0212_shiftjis[];
+#endif
+ ptr = x0212_shiftjis[ndx - 0x21];
+ if (ptr){
+ val = ptr[(c1 & 0x7f) - 0x21];
+ }
+ if (val){
+ c2 = val >> 8;
+ c1 = val & 0xff;
+ if (p2) *p2 = c2;
+ if (p1) *p1 = c1;
+ return 0;
+ }
+ c2 = x0212_shift(c2);
+ }
+#endif /* X0212_ENABLE */
+ }
+ if(0x7F < c2) return 1;
+ if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
+ if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
+ return 0;
+}
+
+void s_oconv(nkf_char c2, nkf_char c1)
+{
+#ifdef NUMCHAR_OPTION
+ if (c2 == 0 && is_unicode_capsule(c1)){
+ w16e_conv(c1, &c2, &c1);
+ if (c2 == 0 && is_unicode_capsule(c1)){
+ c2 = c1 & VALUE_MASK;
+ if (!x0213_f && 0xE000 <= c2 && c2 <= 0xE757) {
+ /* CP932 UDC */
+ c1 &= 0xFFF;
+ c2 = c1 / 188 + 0xF0;
+ c1 = c1 % 188;
+ c1 += 0x40 + (c1 > 0x3e);
+ (*o_putc)(c2);
+ (*o_putc)(c1);
+ return;
+ } else {
+ if(encode_fallback)(*encode_fallback)(c1);
+ return;
+ }
+ }
+ }
+#endif
+ if (c2 == EOF) {
+ (*o_putc)(EOF);
+ return;
+ } else if (c2 == 0) {
+ output_mode = ASCII;
+ (*o_putc)(c1);
+ } else if (c2 == X0201) {
+ output_mode = SHIFT_JIS;
+ (*o_putc)(c1|0x80);
+ } else if (c2 == ISO8859_1) {
+ output_mode = ISO8859_1;
+ (*o_putc)(c1 | 0x080);
+#ifdef X0212_ENABLE
+ } else if (is_eucg3(c2)){
+ output_mode = SHIFT_JIS;
+ if (e2s_conv(c2, c1, &c2, &c1) == 0){
+ (*o_putc)(c2);
+ (*o_putc)(c1);
+ }
+#endif
+ } else {
+ if (!nkf_isprint(c1) || !nkf_isprint(c2)) {
+ set_iconv(FALSE, 0);
+ return; /* too late to rescue this char */
+ }
+ output_mode = SHIFT_JIS;
+ e2s_conv(c2, c1, &c2, &c1);
+
+#ifdef SHIFTJIS_CP932
+ if (cp932inv_f
+ && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
+#if 0
+ extern const unsigned short cp932inv[2][189];
+#endif
+ nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
+ if (c){
+ c2 = c >> 8;
+ c1 = c & 0xff;
+ }
+ }
+#endif /* SHIFTJIS_CP932 */
+
+ (*o_putc)(c2);
+ if (prefix_table[(unsigned char)c1]){
+ (*o_putc)(prefix_table[(unsigned char)c1]);
+ }
+ (*o_putc)(c1);
+ }
+}
+
+void j_oconv(nkf_char c2, nkf_char c1)
+{
+#ifdef NUMCHAR_OPTION
+ if (c2 == 0 && is_unicode_capsule(c1)){
+ w16e_conv(c1, &c2, &c1);
+ if (c2 == 0 && is_unicode_capsule(c1)){
+ c2 = c1 & VALUE_MASK;
+ if (ms_ucs_map_f && 0xE000 <= c2 && c2 <= 0xE757) {
+ /* CP5022x UDC */
+ c1 &= 0xFFF;
+ c2 = 0x7F + c1 / 94;
+ c1 = 0x21 + c1 % 94;
+ } else {
+ if (encode_fallback) (*encode_fallback)(c1);
+ return;
+ }
+ }
+ }
+#endif
+ if (c2 == EOF) {
+ if (output_mode !=ASCII && output_mode!=ISO8859_1) {
+ (*o_putc)(ESC);
+ (*o_putc)('(');
+ (*o_putc)(ascii_intro);
+ output_mode = ASCII;
+ }
+ (*o_putc)(EOF);
+#ifdef X0212_ENABLE
+ } else if (is_eucg3(c2)){
+ if(x0213_f){
+ if(output_mode!=X0213_2){
+ output_mode = X0213_2;
+ (*o_putc)(ESC);
+ (*o_putc)('$');
+ (*o_putc)('(');
+ (*o_putc)(X0213_2&0x7F);
+ }
+ }else{
+ if(output_mode!=X0212){
+ output_mode = X0212;
+ (*o_putc)(ESC);
+ (*o_putc)('$');
+ (*o_putc)('(');
+ (*o_putc)(X0212&0x7F);
+ }
+ }
+ (*o_putc)(c2 & 0x7f);
+ (*o_putc)(c1);
+#endif
+ } else if (c2==X0201) {
+ if (output_mode!=X0201) {
+ output_mode = X0201;
+ (*o_putc)(ESC);
+ (*o_putc)('(');
+ (*o_putc)('I');
+ }
+ (*o_putc)(c1);
+ } else if (c2==ISO8859_1) {
+ /* iso8859 introduction, or 8th bit on */
+ /* Can we convert in 7bit form using ESC-'-'-A ?
+ Is this popular? */
+ output_mode = ISO8859_1;
+ (*o_putc)(c1|0x80);
+ } else if (c2 == 0) {
+ if (output_mode !=ASCII && output_mode!=ISO8859_1) {
+ (*o_putc)(ESC);
+ (*o_putc)('(');
+ (*o_putc)(ascii_intro);
+ output_mode = ASCII;
+ }
+ (*o_putc)(c1);
+ } else {
+ if(ms_ucs_map_f
+ ? c2<0x20 || 0x92<c2 || c1<0x20 || 0x7e<c1
+ : c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
+ if(x0213_f){
+ if (output_mode!=X0213_1) {
+ output_mode = X0213_1;
+ (*o_putc)(ESC);
+ (*o_putc)('$');
+ (*o_putc)('(');
+ (*o_putc)(X0213_1&0x7F);
+ }
+ }else if (output_mode != X0208) {
+ output_mode = X0208;
+ (*o_putc)(ESC);
+ (*o_putc)('$');
+ (*o_putc)(kanji_intro);
+ }
+ (*o_putc)(c2);
+ (*o_putc)(c1);
+ }
+}
+
+void base64_conv(nkf_char c2, nkf_char c1)
+{
+ mime_prechar(c2, c1);
+ (*o_base64conv)(c2,c1);
+}
+
+
+static nkf_char broken_buf[3];
+static int broken_counter = 0;
+static int broken_last = 0;
+nkf_char broken_getc(FILE *f)
+{
+ nkf_char c,c1;
+
+ if (broken_counter>0) {
+ return broken_buf[--broken_counter];
+ }
+ c= (*i_bgetc)(f);
+ if (c=='$' && broken_last != ESC
+ && (input_mode==ASCII || input_mode==X0201)) {
+ c1= (*i_bgetc)(f);
+ broken_last = 0;
+ if (c1=='@'|| c1=='B') {
+ broken_buf[0]=c1; broken_buf[1]=c;
+ broken_counter=2;
+ return ESC;
+ } else {
+ (*i_bungetc)(c1,f);
+ return c;
+ }
+ } else if (c=='(' && broken_last != ESC
+ && (input_mode==X0208 || input_mode==X0201)) { /* ) */
+ c1= (*i_bgetc)(f);
+ broken_last = 0;
+ if (c1=='J'|| c1=='B') {
+ broken_buf[0]=c1; broken_buf[1]=c;
+ broken_counter=2;
+ return ESC;
+ } else {
+ (*i_bungetc)(c1,f);
+ return c;
+ }
+ } else {
+ broken_last = c;
+ return c;
+ }
+}
+
+nkf_char broken_ungetc(nkf_char c, FILE *f)
+{
+ if (broken_counter<2)
+ broken_buf[broken_counter++]=c;
+ return c;
+}
+
+static nkf_char prev_cr = 0;
+
+void cr_conv(nkf_char c2, nkf_char c1)
+{
+ if (prev_cr) {
+ prev_cr = 0;
+ if (! (c2==0&&c1==NL) ) {
+ cr_conv(0,'\n');
+ }
+ }
+ if (c2) {
+ (*o_crconv)(c2,c1);
+ } else if (c1=='\r') {
+ prev_cr = c1;
+ } else if (c1=='\n') {
+ if (crmode_f==CRLF) {
+ (*o_crconv)(0,'\r');
+ } else if (crmode_f==CR) {
+ (*o_crconv)(0,'\r');
+ return;
+ }
+ (*o_crconv)(0,NL);
+ } else if (c1!='\032' || crmode_f!=NL){
+ (*o_crconv)(c2,c1);
+ }
+}
+
+/*
+ Return value of fold_conv()
+
+ \n add newline and output char
+ \r add newline and output nothing
+ ' ' space
+ 0 skip
+ 1 (or else) normal output
+
+ fold state in prev (previous character)
+
+ >0x80 Japanese (X0208/X0201)
+ <0x80 ASCII
+ \n new line
+ ' ' space
+
+ This fold algorthm does not preserve heading space in a line.
+ This is the main difference from fmt.
+*/
+
+#define char_size(c2,c1) (c2?2:1)
+
+void fold_conv(nkf_char c2, nkf_char c1)
+{
+ nkf_char prev0;
+ nkf_char fold_state;
+
+ if (c1== '\r' && !fold_preserve_f) {
+ fold_state=0; /* ignore cr */
+ }else if (c1== '\n'&&f_prev=='\r' && fold_preserve_f) {
+ f_prev = '\n';
+ fold_state=0; /* ignore cr */
+ } else if (c1== BS) {
+ if (f_line>0) f_line--;
+ fold_state = 1;
+ } else if (c2==EOF && f_line != 0) { /* close open last line */
+ fold_state = '\n';
+ } else if ((c1=='\n' && !fold_preserve_f)
+ || ((c1=='\r'||(c1=='\n'&&f_prev!='\r'))
+ && fold_preserve_f)) {
+ /* new line */
+ if (fold_preserve_f) {
+ f_prev = c1;
+ f_line = 0;
+ fold_state = '\r';
+ } else if ((f_prev == c1 && !fold_preserve_f)
+ || (f_prev == '\n' && fold_preserve_f)
+ ) { /* duplicate newline */
+ if (f_line) {
+ f_line = 0;
+ fold_state = '\n'; /* output two newline */
+ } else {
+ f_line = 0;
+ fold_state = 1;
+ }
+ } else {
+ if (f_prev&0x80) { /* Japanese? */
+ f_prev = c1;
+ fold_state = 0; /* ignore given single newline */
+ } else if (f_prev==' ') {
+ fold_state = 0;
+ } else {
+ f_prev = c1;
+ if (++f_line<=fold_len)
+ fold_state = ' ';
+ else {
+ f_line = 0;
+ fold_state = '\r'; /* fold and output nothing */
+ }
+ }
+ }
+ } else if (c1=='\f') {
+ f_prev = '\n';
+ f_line = 0;
+ fold_state = '\n'; /* output newline and clear */
+ } else if ( (c2==0 && c1==' ')||
+ (c2==0 && c1=='\t')||
+ (c2=='!'&& c1=='!')) {
+ /* X0208 kankaku or ascii space */
+ if (f_prev == ' ') {
+ fold_state = 0; /* remove duplicate spaces */
+ } else {
+ f_prev = ' ';
+ if (++f_line<=fold_len)
+ fold_state = ' '; /* output ASCII space only */
+ else {
+ f_prev = ' '; f_line = 0;
+ fold_state = '\r'; /* fold and output nothing */
+ }
+ }
+ } else {
+ prev0 = f_prev; /* we still need this one... , but almost done */
+ f_prev = c1;
+ if (c2 || c2==X0201)
+ f_prev |= 0x80; /* this is Japanese */
+ f_line += char_size(c2,c1);
+ if (f_line<=fold_len) { /* normal case */
+ fold_state = 1;
+ } else {
+ if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
+ f_line = char_size(c2,c1);
+ fold_state = '\n'; /* We can't wait, do fold now */
+ } else if (c2==X0201) {
+ /* simple kinsoku rules return 1 means no folding */
+ if (c1==(0xde&0x7f)) fold_state = 1; /* $B!+(B*/
+ else if (c1==(0xdf&0x7f)) fold_state = 1; /* $B!,(B*/
+ else if (c1==(0xa4&0x7f)) fold_state = 1; /* $B!#(B*/
+ else if (c1==(0xa3&0x7f)) fold_state = 1; /* $B!$(B*/
+ else if (c1==(0xa1&0x7f)) fold_state = 1; /* $B!W(B*/
+ else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
+ else if (SPACE<=c1 && c1<=(0xdf&0x7f)) { /* X0201 */
+ f_line = 1;
+ fold_state = '\n';/* add one new f_line before this character */
+ } else {
+ f_line = 1;
+ fold_state = '\n';/* add one new f_line before this character */
+ }
+ } else if (c2==0) {
+ /* kinsoku point in ASCII */
+ if ( c1==')'|| /* { [ ( */
+ c1==']'||
+ c1=='}'||
+ c1=='.'||
+ c1==','||
+ c1=='!'||
+ c1=='?'||
+ c1=='/'||
+ c1==':'||
+ c1==';' ) {
+ fold_state = 1;
+ /* just after special */
+ } else if (!is_alnum(prev0)) {
+ f_line = char_size(c2,c1);
+ fold_state = '\n';
+ } else if ((prev0==' ') || /* ignored new f_line */
+ (prev0=='\n')|| /* ignored new f_line */
+ (prev0&0x80)) { /* X0208 - ASCII */
+ f_line = char_size(c2,c1);
+ fold_state = '\n';/* add one new f_line before this character */
+ } else {
+ fold_state = 1; /* default no fold in ASCII */
+ }
+ } else {
+ if (c2=='!') {
+ if (c1=='"') fold_state = 1; /* $B!"(B */
+ else if (c1=='#') fold_state = 1; /* $B!#(B */
+ else if (c1=='W') fold_state = 1; /* $B!W(B */
+ else if (c1=='K') fold_state = 1; /* $B!K(B */
+ else if (c1=='$') fold_state = 1; /* $B!$(B */
+ else if (c1=='%') fold_state = 1; /* $B!%(B */
+ else if (c1=='\'') fold_state = 1; /* $B!\(B */
+ else if (c1=='(') fold_state = 1; /* $B!((B */
+ else if (c1==')') fold_state = 1; /* $B!)(B */
+ else if (c1=='*') fold_state = 1; /* $B!*(B */
+ else if (c1=='+') fold_state = 1; /* $B!+(B */
+ else if (c1==',') fold_state = 1; /* $B!,(B */
+ /* default no fold in kinsoku */
+ else {
+ fold_state = '\n';
+ f_line = char_size(c2,c1);
+ /* add one new f_line before this character */
+ }
+ } else {
+ f_line = char_size(c2,c1);
+ fold_state = '\n';
+ /* add one new f_line before this character */
+ }
+ }
+ }
+ }
+ /* terminator process */
+ switch(fold_state) {
+ case '\n':
+ (*o_fconv)(0,'\n');
+ (*o_fconv)(c2,c1);
+ break;
+ case 0:
+ return;
+ case '\r':
+ (*o_fconv)(0,'\n');
+ break;
+ case '\t':
+ case ' ':
+ (*o_fconv)(0,' ');
+ break;
+ default:
+ (*o_fconv)(c2,c1);
+ }
+}
+
+nkf_char z_prev2=0,z_prev1=0;
+
+void z_conv(nkf_char c2, nkf_char c1)
+{
+
+ /* if (c2) c1 &= 0x7f; assertion */
+
+ if (x0201_f && z_prev2==X0201) { /* X0201 */
+ if (c1==(0xde&0x7f)) { /* $BByE@(B */
+ z_prev2=0;
+ (*o_zconv)(dv[(z_prev1-SPACE)*2],dv[(z_prev1-SPACE)*2+1]);
+ return;
+ } else if (c1==(0xdf&0x7f)&&ev[(z_prev1-SPACE)*2]) { /* $BH>ByE@(B */
+ z_prev2=0;
+ (*o_zconv)(ev[(z_prev1-SPACE)*2],ev[(z_prev1-SPACE)*2+1]);
+ return;
+ } else {
+ z_prev2=0;
+ (*o_zconv)(cv[(z_prev1-SPACE)*2],cv[(z_prev1-SPACE)*2+1]);
+ }
+ }
+
+ if (c2==EOF) {
+ (*o_zconv)(c2,c1);
+ return;
+ }
+
+ if (x0201_f && c2==X0201) {
+ if (dv[(c1-SPACE)*2]||ev[(c1-SPACE)*2]) {
+ /* wait for $BByE@(B or $BH>ByE@(B */
+ z_prev1 = c1; z_prev2 = c2;
+ return;
+ } else {
+ (*o_zconv)(cv[(c1-SPACE)*2],cv[(c1-SPACE)*2+1]);
+ return;
+ }
+ }
+
+ /* JISX0208 Alphabet */
+ if (alpha_f && c2 == 0x23 ) {
+ c2 = 0;
+ } else if (alpha_f && c2 == 0x21 ) {
+ /* JISX0208 Kigou */
+ if (0x21==c1) {
+ if (alpha_f&0x2) {
+ c1 = ' ';
+ c2 = 0;
+ } else if (alpha_f&0x4) {
+ (*o_zconv)(0,' ');
+ (*o_zconv)(0,' ');
+ return;
+ }
+ } else if (0x20<c1 && c1<0x7f && fv[c1-0x20]) {
+ c1 = fv[c1-0x20];
+ c2 = 0;
+ if (alpha_f&0x8) {
+ char *entity = 0;
+ switch (c1){
+ case '>': entity = "&gt;"; break;
+ case '<': entity = "&lt;"; break;
+ case '\"': entity = "&quot;"; break;
+ case '&': entity = "&amp;"; break;
+ }
+ if (entity){
+ while (*entity) (*o_zconv)(0, *entity++);
+ return;
+ }
+ }
+ }
+ }
+ (*o_zconv)(c2,c1);
+}
+
+
+#define rot13(c) ( \
+ ( c < 'A' ) ? c: \
+ (c <= 'M') ? (c + 13): \
+ (c <= 'Z') ? (c - 13): \
+ (c < 'a') ? (c): \
+ (c <= 'm') ? (c + 13): \
+ (c <= 'z') ? (c - 13): \
+ (c) \
+)
+
+#define rot47(c) ( \
+ ( c < '!' ) ? c: \
+ ( c <= 'O' ) ? (c + 47) : \
+ ( c <= '~' ) ? (c - 47) : \
+ c \
+)
+
+void rot_conv(nkf_char c2, nkf_char c1)
+{
+ if (c2==0 || c2==X0201 || c2==ISO8859_1) {
+ c1 = rot13(c1);
+ } else if (c2) {
+ c1 = rot47(c1);
+ c2 = rot47(c2);
+ }
+ (*o_rot_conv)(c2,c1);
+}
+
+void hira_conv(nkf_char c2, nkf_char c1)
+{
+ if (hira_f & 1) {
+ if (c2 == 0x25) {
+ if (0x20 < c1 && c1 < 0x74) {
+ c2 = 0x24;
+ (*o_hira_conv)(c2,c1);
+ return;
+ } else if (c1 == 0x74 && (output_conv == w_oconv || output_conv == w_oconv16)) {
+ c2 = 0;
+ c1 = CLASS_UNICODE | 0x3094;
+ (*o_hira_conv)(c2,c1);
+ return;
+ }
+ } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) {
+ c1 += 2;
+ (*o_hira_conv)(c2,c1);
+ return;
+ }
+ }
+ if (hira_f & 2) {
+ if (c2 == 0 && c1 == (CLASS_UNICODE | 0x3094)) {
+ c2 = 0x25;
+ c1 = 0x74;
+ } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
+ c2 = 0x25;
+ } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) {
+ c1 -= 2;
+ }
+ }
+ (*o_hira_conv)(c2,c1);
+}
+
+
+void iso2022jp_check_conv(nkf_char c2, nkf_char c1)
+{
+ static const nkf_char range[RANGE_NUM_MAX][2] = {
+ {0x222f, 0x2239,},
+ {0x2242, 0x2249,},
+ {0x2251, 0x225b,},
+ {0x226b, 0x2271,},
+ {0x227a, 0x227d,},
+ {0x2321, 0x232f,},
+ {0x233a, 0x2340,},
+ {0x235b, 0x2360,},
+ {0x237b, 0x237e,},
+ {0x2474, 0x247e,},
+ {0x2577, 0x257e,},
+ {0x2639, 0x2640,},
+ {0x2659, 0x267e,},
+ {0x2742, 0x2750,},
+ {0x2772, 0x277e,},
+ {0x2841, 0x287e,},
+ {0x4f54, 0x4f7e,},
+ {0x7425, 0x747e},
+ };
+ nkf_char i;
+ nkf_char start, end, c;
+
+ if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
+ c2 = GETA1;
+ c1 = GETA2;
+ }
+ if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
+ c2 = GETA1;
+ c1 = GETA2;
+ }
+
+ for (i = 0; i < RANGE_NUM_MAX; i++) {
+ start = range[i][0];
+ end = range[i][1];
+ c = (c2 << 8) + c1;
+ if (c >= start && c <= end) {
+ c2 = GETA1;
+ c1 = GETA2;
+ }
+ }
+ (*o_iso2022jp_check_conv)(c2,c1);
+}
+
+
+/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */
+
+const unsigned char *mime_pattern[] = {
+ (const unsigned char *)"\075?EUC-JP?B?",
+ (const unsigned char *)"\075?SHIFT_JIS?B?",
+ (const unsigned char *)"\075?ISO-8859-1?Q?",
+ (const unsigned char *)"\075?ISO-8859-1?B?",
+ (const unsigned char *)"\075?ISO-2022-JP?B?",
+ (const unsigned char *)"\075?ISO-2022-JP?Q?",
+#if defined(UTF8_INPUT_ENABLE)
+ (const unsigned char *)"\075?UTF-8?B?",
+ (const unsigned char *)"\075?UTF-8?Q?",
+#endif
+ (const unsigned char *)"\075?US-ASCII?Q?",
+ NULL
+};
+
+
+/* $B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u(B */
+nkf_char (*mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = {
+ e_iconv, s_iconv, 0, 0, 0, 0,
+#if defined(UTF8_INPUT_ENABLE)
+ w_iconv, w_iconv,
+#endif
+ 0,
+};
+
+const nkf_char mime_encode[] = {
+ JAPANESE_EUC, SHIFT_JIS,ISO8859_1, ISO8859_1, X0208, X0201,
+#if defined(UTF8_INPUT_ENABLE)
+ UTF8, UTF8,
+#endif
+ ASCII,
+ 0
+};
+
+const nkf_char mime_encode_method[] = {
+ 'B', 'B','Q', 'B', 'B', 'Q',
+#if defined(UTF8_INPUT_ENABLE)
+ 'B', 'Q',
+#endif
+ 'Q',
+ 0
+};
+
+
+#define MAXRECOVER 20
+
+void switch_mime_getc(void)
+{
+ if (i_getc!=mime_getc) {
+ i_mgetc = i_getc; i_getc = mime_getc;
+ i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
+ if(mime_f==STRICT_MIME) {
+ i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
+ i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
+ }
+ }
+}
+
+void unswitch_mime_getc(void)
+{
+ if(mime_f==STRICT_MIME) {
+ i_mgetc = i_mgetc_buf;
+ i_mungetc = i_mungetc_buf;
+ }
+ i_getc = i_mgetc;
+ i_ungetc = i_mungetc;
+ if(mime_iconv_back)set_iconv(FALSE, mime_iconv_back);
+ mime_iconv_back = NULL;
+}
+
+nkf_char mime_begin_strict(FILE *f)
+{
+ nkf_char c1 = 0;
+ int i,j,k;
+ const unsigned char *p,*q;
+ nkf_char r[MAXRECOVER]; /* recovery buffer, max mime pattern length */
+
+ mime_decode_mode = FALSE;
+ /* =? has been checked */
+ j = 0;
+ p = mime_pattern[j];
+ r[0]='='; r[1]='?';
+
+ for(i=2;p[i]>' ';i++) { /* start at =? */
+ if ( ((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i] ) {
+ /* pattern fails, try next one */
+ q = p;
+ while (mime_pattern[++j]) {
+ p = mime_pattern[j];
+ for(k=2;k<i;k++) /* assume length(p) > i */
+ if (p[k]!=q[k]) break;
+ if (k==i && nkf_toupper(c1)==p[k]) break;
+ }
+ p = mime_pattern[j];
+ if (p) continue; /* found next one, continue */
+ /* all fails, output from recovery buffer */
+ (*i_ungetc)(c1,f);
+ for(j=0;j<i;j++) {
+ (*oconv)(0,r[j]);
+ }
+ return c1;
+ }
+ }
+ mime_decode_mode = p[i-2];
+
+ mime_iconv_back = iconv;
+ set_iconv(FALSE, mime_priority_func[j]);
+ clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
+
+ if (mime_decode_mode=='B') {
+ mimebuf_f = unbuf_f;
+ if (!unbuf_f) {
+ /* do MIME integrity check */
+ return mime_integrity(f,mime_pattern[j]);
+ }
+ }
+ switch_mime_getc();
+ mimebuf_f = TRUE;
+ return c1;
+}
+
+nkf_char mime_getc_buf(FILE *f)
+{
+ /* we don't keep eof of Fifo, becase it contains ?= as
+ a terminator. It was checked in mime_integrity. */
+ return ((mimebuf_f)?
+ (*i_mgetc_buf)(f):Fifo(mime_input++));
+}
+
+nkf_char mime_ungetc_buf(nkf_char c, FILE *f)
+{
+ if (mimebuf_f)
+ (*i_mungetc_buf)(c,f);
+ else
+ Fifo(--mime_input) = (unsigned char)c;
+ return c;
+}
+
+nkf_char mime_begin(FILE *f)
+{
+ nkf_char c1;
+ int i,k;
+
+ /* In NONSTRICT mode, only =? is checked. In case of failure, we */
+ /* re-read and convert again from mime_buffer. */
+
+ /* =? has been checked */
+ k = mime_last;
+ Fifo(mime_last++)='='; Fifo(mime_last++)='?';
+ for(i=2;i<MAXRECOVER;i++) { /* start at =? */
+ /* We accept any character type even if it is breaked by new lines */
+ c1 = (*i_getc)(f); Fifo(mime_last++) = (unsigned char)c1;
+ if (c1=='\n'||c1==' '||c1=='\r'||
+ c1=='-'||c1=='_'||is_alnum(c1) ) continue;
+ if (c1=='=') {
+ /* Failed. But this could be another MIME preemble */
+ (*i_ungetc)(c1,f);
+ mime_last--;
+ break;
+ }
+ if (c1!='?') break;
+ else {
+ /* c1=='?' */
+ c1 = (*i_getc)(f); Fifo(mime_last++) = (unsigned char)c1;
+ if (!(++i<MAXRECOVER) || c1==EOF) break;
+ if (c1=='b'||c1=='B') {
+ mime_decode_mode = 'B';
+ } else if (c1=='q'||c1=='Q') {
+ mime_decode_mode = 'Q';
+ } else {
+ break;
+ }
+ c1 = (*i_getc)(f); Fifo(mime_last++) = (unsigned char)c1;
+ if (!(++i<MAXRECOVER) || c1==EOF) break;
+ if (c1!='?') {
+ mime_decode_mode = FALSE;
+ }
+ break;
+ }
+ }
+ switch_mime_getc();
+ if (!mime_decode_mode) {
+ /* false MIME premble, restart from mime_buffer */
+ mime_decode_mode = 1; /* no decode, but read from the mime_buffer */
+ /* Since we are in MIME mode until buffer becomes empty, */
+ /* we never go into mime_begin again for a while. */
+ return c1;
+ }
+ /* discard mime preemble, and goto MIME mode */
+ mime_last = k;
+ /* do no MIME integrity check */
+ return c1; /* used only for checking EOF */
+}
+
+#ifdef CHECK_OPTION
+void no_putc(nkf_char c)
+{
+ ;
+}
+
+void debug(const char *str)
+{
+ if (debug_f){
+ fprintf(stderr, "%s\n", str);
+ }
+}
+#endif
+
+void set_input_codename(char *codename)
+{
+ if (guess_f &&
+ is_inputcode_set &&
+ strcmp(codename, "") != 0 &&
+ strcmp(codename, input_codename) != 0)
+ {
+ is_inputcode_mixed = TRUE;
+ }
+ input_codename = codename;
+ is_inputcode_set = TRUE;
+}
+
+#if !defined(PERL_XS) && !defined(WIN32DLL)
+void print_guessed_code(char *filename)
+{
+ char *codename = "BINARY";
+ if (!is_inputcode_mixed) {
+ if (strcmp(input_codename, "") == 0) {
+ codename = "ASCII";
+ } else {
+ codename = input_codename;
+ }
+ }
+ if (filename != NULL) printf("%s:", filename);
+ printf("%s\n", codename);
+}
+#endif /*WIN32DLL*/
+
+#ifdef INPUT_OPTION
+
+nkf_char hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f))
+{
+ nkf_char c1, c2, c3;
+ c1 = (*g)(f);
+ if (c1 != ch){
+ return c1;
+ }
+ c2 = (*g)(f);
+ if (!nkf_isxdigit(c2)){
+ (*u)(c2, f);
+ return c1;
+ }
+ c3 = (*g)(f);
+ if (!nkf_isxdigit(c3)){
+ (*u)(c2, f);
+ (*u)(c3, f);
+ return c1;
+ }
+ return (hex2bin(c2) << 4) | hex2bin(c3);
+}
+
+nkf_char cap_getc(FILE *f)
+{
+ return hex_getc(':', f, i_cgetc, i_cungetc);
+}
+
+nkf_char cap_ungetc(nkf_char c, FILE *f)
+{
+ return (*i_cungetc)(c, f);
+}
+
+nkf_char url_getc(FILE *f)
+{
+ return hex_getc('%', f, i_ugetc, i_uungetc);
+}
+
+nkf_char url_ungetc(nkf_char c, FILE *f)
+{
+ return (*i_uungetc)(c, f);
+}
+#endif
+
+#ifdef NUMCHAR_OPTION
+nkf_char numchar_getc(FILE *f)
+{
+ nkf_char (*g)(FILE *) = i_ngetc;
+ nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc;
+ int i = 0, j;
+ nkf_char buf[8];
+ long c = -1;
+
+ buf[i] = (*g)(f);
+ if (buf[i] == '&'){
+ buf[++i] = (*g)(f);
+ if (buf[i] == '#'){
+ c = 0;
+ buf[++i] = (*g)(f);
+ if (buf[i] == 'x' || buf[i] == 'X'){
+ for (j = 0; j < 7; j++){
+ buf[++i] = (*g)(f);
+ if (!nkf_isxdigit(buf[i])){
+ if (buf[i] != ';'){
+ c = -1;
+ }
+ break;
+ }
+ c <<= 4;
+ c |= hex2bin(buf[i]);
+ }
+ }else{
+ for (j = 0; j < 8; j++){
+ if (j){
+ buf[++i] = (*g)(f);
+ }
+ if (!nkf_isdigit(buf[i])){
+ if (buf[i] != ';'){
+ c = -1;
+ }
+ break;
+ }
+ c *= 10;
+ c += hex2bin(buf[i]);
+ }
+ }
+ }
+ }
+ if (c != -1){
+ return CLASS_UNICODE | c;
+ }
+ while (i > 0){
+ (*u)(buf[i], f);
+ --i;
+ }
+ return buf[0];
+}
+
+nkf_char numchar_ungetc(nkf_char c, FILE *f)
+{
+ return (*i_nungetc)(c, f);
+}
+#endif
+
+#ifdef UNICODE_NORMALIZATION
+
+/* Normalization Form C */
+nkf_char nfc_getc(FILE *f)
+{
+ nkf_char (*g)(FILE *f) = i_nfc_getc;
+ nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc;
+ int i=0, j, k=1, lower, upper;
+ nkf_char buf[9];
+ const nkf_nfchar *array;
+#if 0
+ extern const struct normalization_pair normalization_table[];
+#endif
+
+ buf[i] = (*g)(f);
+ while (k > 0 && ((buf[i] & 0xc0) != 0x80)){
+ lower=0, upper=NORMALIZATION_TABLE_LENGTH-1;
+ while (upper >= lower) {
+ j = (lower+upper) / 2;
+ array = normalization_table[j].nfd;
+ for (k=0; k < NORMALIZATION_TABLE_NFD_LENGTH && array[k]; k++){
+ if (array[k] != buf[k]){
+ array[k] < buf[k] ? (lower = j + 1) : (upper = j - 1);
+ k = 0;
+ break;
+ } else if (k >= i)
+ buf[++i] = (*g)(f);
+ }
+ if (k > 0){
+ array = normalization_table[j].nfc;
+ for (i=0; i < NORMALIZATION_TABLE_NFC_LENGTH && array[i]; i++)
+ buf[i] = (nkf_char)(array[i]);
+ i--;
+ break;
+ }
+ }
+ while (i > 0)
+ (*u)(buf[i--], f);
+ }
+ return buf[0];
+}
+
+nkf_char nfc_ungetc(nkf_char c, FILE *f)
+{
+ return (*i_nfc_ungetc)(c, f);
+}
+#endif /* UNICODE_NORMALIZATION */
+
+
+nkf_char
+mime_getc(FILE *f)
+{
+ nkf_char c1, c2, c3, c4, cc;
+ nkf_char t1, t2, t3, t4, mode, exit_mode;
+ nkf_char lwsp_count;
+ char *lwsp_buf;
+ char *lwsp_buf_new;
+ nkf_char lwsp_size = 128;
+
+ if (mime_top != mime_last) { /* Something is in FIFO */
+ return Fifo(mime_top++);
+ }
+ if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
+ mime_decode_mode=FALSE;
+ unswitch_mime_getc();
+ return (*i_getc)(f);
+ }
+
+ if (mimebuf_f == FIXED_MIME)
+ exit_mode = mime_decode_mode;
+ else
+ exit_mode = FALSE;
+ if (mime_decode_mode == 'Q') {
+ if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
+restart_mime_q:
+ if (c1=='_' && mimebuf_f != FIXED_MIME) return ' ';
+ if (c1<=' ' || DEL<=c1) {
+ mime_decode_mode = exit_mode; /* prepare for quit */
+ return c1;
+ }
+ if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) {
+ return c1;
+ }
+
+ mime_decode_mode = exit_mode; /* prepare for quit */
+ if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
+ if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
+ /* end Q encoding */
+ input_mode = exit_mode;
+ lwsp_count = 0;
+ lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
+ if (lwsp_buf==NULL) {
+ perror("can't malloc");
+ return -1;
+ }
+ while ((c1=(*i_getc)(f))!=EOF) {
+ switch (c1) {
+ case NL:
+ case CR:
+ if (c1==NL) {
+ if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
+ i_ungetc(SPACE,f);
+ continue;
+ } else {
+ i_ungetc(c1,f);
+ }
+ c1 = NL;
+ } else {
+ if ((c1=(*i_getc)(f))!=EOF && c1 == NL) {
+ if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
+ i_ungetc(SPACE,f);
+ continue;
+ } else {
+ i_ungetc(c1,f);
+ }
+ i_ungetc(NL,f);
+ } else {
+ i_ungetc(c1,f);
+ }
+ c1 = CR;
+ }
+ break;
+ case SPACE:
+ case TAB:
+ lwsp_buf[lwsp_count] = (unsigned char)c1;
+ if (lwsp_count++>lwsp_size){
+ lwsp_size <<= 1;
+ lwsp_buf_new = realloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
+ if (lwsp_buf_new==NULL) {
+ free(lwsp_buf);
+ perror("can't realloc");
+ return -1;
+ }
+ lwsp_buf = lwsp_buf_new;
+ }
+ continue;
+ }
+ break;
+ }
+ if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SPACE && lwsp_buf[lwsp_count-1] != TAB))) {
+ i_ungetc(c1,f);
+ for(lwsp_count--;lwsp_count>0;lwsp_count--)
+ i_ungetc(lwsp_buf[lwsp_count],f);
+ c1 = lwsp_buf[0];
+ }
+ free(lwsp_buf);
+ return c1;
+ }
+ if (c1=='='&&c2<' ') { /* this is soft wrap */
+ while((c1 = (*i_mgetc)(f)) <=' ') {
+ if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
+ }
+ mime_decode_mode = 'Q'; /* still in MIME */
+ goto restart_mime_q;
+ }
+ if (c1=='?') {
+ mime_decode_mode = 'Q'; /* still in MIME */
+ (*i_mungetc)(c2,f);
+ return c1;
+ }
+ if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
+ if (c2<=' ') return c2;
+ mime_decode_mode = 'Q'; /* still in MIME */
+ return ((hex2bin(c2)<<4) + hex2bin(c3));
+ }
+
+ if (mime_decode_mode != 'B') {
+ mime_decode_mode = FALSE;
+ return (*i_mgetc)(f);
+ }
+
+
+ /* Base64 encoding */
+ /*
+ MIME allows line break in the middle of
+ Base64, but we are very pessimistic in decoding
+ in unbuf mode because MIME encoded code may broken by
+ less or editor's control sequence (such as ESC-[-K in unbuffered
+ mode. ignore incomplete MIME.
+ */
+ mode = mime_decode_mode;
+ mime_decode_mode = exit_mode; /* prepare for quit */
+
+ while ((c1 = (*i_mgetc)(f))<=' ') {
+ if (c1==EOF)
+ return (EOF);
+ }
+mime_c2_retry:
+ if ((c2 = (*i_mgetc)(f))<=' ') {
+ if (c2==EOF)
+ return (EOF);
+ if (mime_f != STRICT_MIME) goto mime_c2_retry;
+ if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
+ return c2;
+ }
+ if ((c1 == '?') && (c2 == '=')) {
+ input_mode = ASCII;
+ lwsp_count = 0;
+ lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
+ if (lwsp_buf==NULL) {
+ perror("can't malloc");
+ return -1;
+ }
+ while ((c1=(*i_getc)(f))!=EOF) {
+ switch (c1) {
+ case NL:
+ case CR:
+ if (c1==NL) {
+ if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
+ i_ungetc(SPACE,f);
+ continue;
+ } else {
+ i_ungetc(c1,f);
+ }
+ c1 = NL;
+ } else {
+ if ((c1=(*i_getc)(f))!=EOF) {
+ if (c1==SPACE) {
+ i_ungetc(SPACE,f);
+ continue;
+ } else if ((c1=(*i_getc)(f))!=EOF && (c1==SPACE||c1==TAB)) {
+ i_ungetc(SPACE,f);
+ continue;
+ } else {
+ i_ungetc(c1,f);
+ }
+ i_ungetc(NL,f);
+ } else {
+ i_ungetc(c1,f);
+ }
+ c1 = CR;
+ }
+ break;
+ case SPACE:
+ case TAB:
+ lwsp_buf[lwsp_count] = (unsigned char)c1;
+ if (lwsp_count++>lwsp_size){
+ lwsp_size <<= 1;
+ lwsp_buf_new = realloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
+ if (lwsp_buf_new==NULL) {
+ free(lwsp_buf);
+ perror("can't realloc");
+ return -1;
+ }
+ lwsp_buf = lwsp_buf_new;
+ }
+ continue;
+ }
+ break;
+ }
+ if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SPACE && lwsp_buf[lwsp_count-1] != TAB))) {
+ i_ungetc(c1,f);
+ for(lwsp_count--;lwsp_count>0;lwsp_count--)
+ i_ungetc(lwsp_buf[lwsp_count],f);
+ c1 = lwsp_buf[0];
+ }
+ free(lwsp_buf);
+ return c1;
+ }
+mime_c3_retry:
+ if ((c3 = (*i_mgetc)(f))<=' ') {
+ if (c3==EOF)
+ return (EOF);
+ if (mime_f != STRICT_MIME) goto mime_c3_retry;
+ if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
+ return c3;
+ }
+mime_c4_retry:
+ if ((c4 = (*i_mgetc)(f))<=' ') {
+ if (c4==EOF)
+ return (EOF);
+ if (mime_f != STRICT_MIME) goto mime_c4_retry;
+ if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
+ return c4;
+ }
+
+ mime_decode_mode = mode; /* still in MIME sigh... */
+
+ /* BASE 64 decoding */
+
+ t1 = 0x3f & base64decode(c1);
+ t2 = 0x3f & base64decode(c2);
+ t3 = 0x3f & base64decode(c3);
+ t4 = 0x3f & base64decode(c4);
+ cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
+ if (c2 != '=') {
+ Fifo(mime_last++) = (unsigned char)cc;
+ cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
+ if (c3 != '=') {
+ Fifo(mime_last++) = (unsigned char)cc;
+ cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
+ if (c4 != '=')
+ Fifo(mime_last++) = (unsigned char)cc;
+ }
+ } else {
+ return c1;
+ }
+ return Fifo(mime_top++);
+}
+
+nkf_char mime_ungetc(nkf_char c, FILE *f)
+{
+ Fifo(--mime_top) = (unsigned char)c;
+ return c;
+}
+
+nkf_char mime_integrity(FILE *f, const unsigned char *p)
+{
+ nkf_char c,d;
+ unsigned int q;
+ /* In buffered mode, read until =? or NL or buffer full
+ */
+ mime_input = mime_top;
+ mime_last = mime_top;
+
+ while(*p) Fifo(mime_input++) = *p++;
+ d = 0;
+ q = mime_input;
+ while((c=(*i_getc)(f))!=EOF) {
+ if (((mime_input-mime_top)&MIME_BUF_MASK)==0) {
+ break; /* buffer full */
+ }
+ if (c=='=' && d=='?') {
+ /* checked. skip header, start decode */
+ Fifo(mime_input++) = (unsigned char)c;
+ /* mime_last_input = mime_input; */
+ mime_input = q;
+ switch_mime_getc();
+ return 1;
+ }
+ if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
+ break;
+ /* Should we check length mod 4? */
+ Fifo(mime_input++) = (unsigned char)c;
+ d=c;
+ }
+ /* In case of Incomplete MIME, no MIME decode */
+ Fifo(mime_input++) = (unsigned char)c;
+ mime_last = mime_input; /* point undecoded buffer */
+ mime_decode_mode = 1; /* no decode on Fifo last in mime_getc */
+ switch_mime_getc(); /* anyway we need buffered getc */
+ return 1;
+}
+
+nkf_char base64decode(nkf_char c)
+{
+ int i;
+ if (c > '@') {
+ if (c < '[') {
+ i = c - 'A'; /* A..Z 0-25 */
+ } else {
+ i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */
+ }
+ } else if (c > '/') {
+ i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */
+ } else if (c == '+') {
+ i = '>' /* 62 */ ; /* + 62 */
+ } else {
+ i = '?' /* 63 */ ; /* / 63 */
+ }
+ return (i);
+}
+
+static const char basis_64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static nkf_char b64c;
+#define MIMEOUT_BUF_LENGTH (60)
+char mimeout_buf[MIMEOUT_BUF_LENGTH+1];
+int mimeout_buf_count = 0;
+int mimeout_preserve_space = 0;
+#define itoh4(c) (c>=10?c+'A'-10:c+'0')
+
+void open_mime(nkf_char mode)
+{
+ const unsigned char *p;
+ int i;
+ int j;
+ p = mime_pattern[0];
+ for(i=0;mime_encode[i];i++) {
+ if (mode == mime_encode[i]) {
+ p = mime_pattern[i];
+ break;
+ }
+ }
+ mimeout_mode = mime_encode_method[i];
+
+ i = 0;
+ if (base64_count>45) {
+ if (mimeout_buf_count>0 && nkf_isblank(mimeout_buf[i])){
+ (*o_mputc)(mimeout_buf[i]);
+ i++;
+ }
+ (*o_mputc)(NL);
+ (*o_mputc)(SPACE);
+ base64_count = 1;
+ if (!mimeout_preserve_space && mimeout_buf_count>0
+ && (mimeout_buf[i]==SPACE || mimeout_buf[i]==TAB
+ || mimeout_buf[i]==CR || mimeout_buf[i]==NL )) {
+ i++;
+ }
+ }
+ if (!mimeout_preserve_space) {
+ for (;i<mimeout_buf_count;i++) {
+ if (mimeout_buf[i]==SPACE || mimeout_buf[i]==TAB
+ || mimeout_buf[i]==CR || mimeout_buf[i]==NL ) {
+ (*o_mputc)(mimeout_buf[i]);
+ base64_count ++;
+ } else {
+ break;
+ }
+ }
+ }
+ mimeout_preserve_space = FALSE;
+
+ while(*p) {
+ (*o_mputc)(*p++);
+ base64_count ++;
+ }
+ j = mimeout_buf_count;
+ mimeout_buf_count = 0;
+ for (;i<j;i++) {
+ mime_putc(mimeout_buf[i]);
+ }
+}
+
+void close_mime(void)
+{
+ (*o_mputc)('?');
+ (*o_mputc)('=');
+ base64_count += 2;
+ mimeout_mode = 0;
+}
+
+void eof_mime(void)
+{
+ switch(mimeout_mode) {
+ case 'Q':
+ case 'B':
+ break;
+ case 2:
+ (*o_mputc)(basis_64[((b64c & 0x3)<< 4)]);
+ (*o_mputc)('=');
+ (*o_mputc)('=');
+ base64_count += 3;
+ break;
+ case 1:
+ (*o_mputc)(basis_64[((b64c & 0xF) << 2)]);
+ (*o_mputc)('=');
+ base64_count += 2;
+ break;
+ }
+ if (mimeout_mode) {
+ if (mimeout_f!=FIXED_MIME) {
+ close_mime();
+ } else if (mimeout_mode != 'Q')
+ mimeout_mode = 'B';
+ }
+}
+
+void mimeout_addchar(nkf_char c)
+{
+ switch(mimeout_mode) {
+ case 'Q':
+ if (c==CR||c==NL) {
+ (*o_mputc)(c);
+ base64_count = 0;
+ } else if(!nkf_isalnum(c)) {
+ (*o_mputc)('=');
+ (*o_mputc)(itoh4(((c>>4)&0xf)));
+ (*o_mputc)(itoh4((c&0xf)));
+ base64_count += 3;
+ } else {
+ (*o_mputc)(c);
+ base64_count++;
+ }
+ break;
+ case 'B':
+ b64c=c;
+ (*o_mputc)(basis_64[c>>2]);
+ mimeout_mode=2;
+ base64_count ++;
+ break;
+ case 2:
+ (*o_mputc)(basis_64[((b64c & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
+ b64c=c;
+ mimeout_mode=1;
+ base64_count ++;
+ break;
+ case 1:
+ (*o_mputc)(basis_64[((b64c & 0xF) << 2) | ((c & 0xC0) >>6)]);
+ (*o_mputc)(basis_64[c & 0x3F]);
+ mimeout_mode='B';
+ base64_count += 2;
+ break;
+ default:
+ (*o_mputc)(c);
+ base64_count++;
+ break;
+ }
+}
+
+nkf_char mime_lastchar2, mime_lastchar1;
+
+void mime_prechar(nkf_char c2, nkf_char c1)
+{
+ if (mimeout_mode){
+ if (c2){
+ if (base64_count + mimeout_buf_count/3*4> 66){
+ (*o_base64conv)(EOF,0);
+ (*o_base64conv)(0,NL);
+ (*o_base64conv)(0,SPACE);
+ }
+ }/*else if (mime_lastchar2){
+ if (c1 <=DEL && !nkf_isspace(c1)){
+ (*o_base64conv)(0,SPACE);
+ }
+ }*/
+ }/*else{
+ if (c2 && mime_lastchar2 == 0
+ && mime_lastchar1 && !nkf_isspace(mime_lastchar1)){
+ (*o_base64conv)(0,SPACE);
+ }
+ }*/
+ mime_lastchar2 = c2;
+ mime_lastchar1 = c1;
+}
+
+void mime_putc(nkf_char c)
+{
+ int i, j;
+ nkf_char lastchar;
+
+ if (mimeout_f == FIXED_MIME){
+ if (mimeout_mode == 'Q'){
+ if (base64_count > 71){
+ if (c!=CR && c!=NL) {
+ (*o_mputc)('=');
+ (*o_mputc)(NL);
+ }
+ base64_count = 0;
+ }
+ }else{
+ if (base64_count > 71){
+ eof_mime();
+ (*o_mputc)(NL);
+ base64_count = 0;
+ }
+ if (c == EOF) { /* c==EOF */
+ eof_mime();
+ }
+ }
+ if (c != EOF) { /* c==EOF */
+ mimeout_addchar(c);
+ }
+ return;
+ }
+
+ /* mimeout_f != FIXED_MIME */
+
+ if (c == EOF) { /* c==EOF */
+ j = mimeout_buf_count;
+ mimeout_buf_count = 0;
+ i = 0;
+ if (mimeout_mode) {
+ for (;i<j;i++) {
+ if (nkf_isspace(mimeout_buf[i]) && base64_count < 71){
+ break;
+ }
+ mimeout_addchar(mimeout_buf[i]);
+ }
+ eof_mime();
+ for (;i<j;i++) {
+ mimeout_addchar(mimeout_buf[i]);
+ }
+ } else {
+ for (;i<j;i++) {
+ mimeout_addchar(mimeout_buf[i]);
+ }
+ }
+ return;
+ }
+
+ if (mimeout_mode=='Q') {
+ if (c <= DEL && (output_mode==ASCII ||output_mode == ISO8859_1 ) ) {
+ if (c <= SPACE) {
+ close_mime();
+ (*o_mputc)(SPACE);
+ base64_count++;
+ }
+ (*o_mputc)(c);
+ base64_count++;
+ }
+ return;
+ }
+
+ if (mimeout_buf_count > 0){
+ lastchar = mimeout_buf[mimeout_buf_count - 1];
+ }else{
+ lastchar = -1;
+ }
+
+ if (!mimeout_mode) {
+ if (c <= DEL && (output_mode==ASCII ||output_mode == ISO8859_1)) {
+ if (nkf_isspace(c)) {
+ if (c==CR || c==NL) {
+ base64_count=0;
+ }
+ for (i=0;i<mimeout_buf_count;i++) {
+ (*o_mputc)(mimeout_buf[i]);
+ if (mimeout_buf[i] == CR || mimeout_buf[i] == NL){
+ base64_count = 0;
+ }else{
+ base64_count++;
+ }
+ }
+ mimeout_buf[0] = (char)c;
+ mimeout_buf_count = 1;
+ }else{
+ if (base64_count > 1
+ && base64_count + mimeout_buf_count > 76){
+ (*o_mputc)(NL);
+ base64_count = 0;
+ if (!nkf_isspace(mimeout_buf[0])){
+ (*o_mputc)(SPACE);
+ base64_count++;
+ }
+ }
+ mimeout_buf[mimeout_buf_count++] = (char)c;
+ if (mimeout_buf_count>MIMEOUT_BUF_LENGTH) {
+ open_mime(output_mode);
+ }
+ }
+ return;
+ }else{
+ if (lastchar==CR || lastchar == NL){
+ for (i=0;i<mimeout_buf_count;i++) {
+ (*o_mputc)(mimeout_buf[i]);
+ }
+ base64_count = 0;
+ mimeout_buf_count = 0;
+ }
+ if (lastchar==SPACE) {
+ for (i=0;i<mimeout_buf_count-1;i++) {
+ (*o_mputc)(mimeout_buf[i]);
+ base64_count++;
+ }
+ mimeout_buf[0] = SPACE;
+ mimeout_buf_count = 1;
+ }
+ open_mime(output_mode);
+ }
+ }else{
+ /* mimeout_mode == 'B', 1, 2 */
+ if ( c<=DEL && (output_mode==ASCII ||output_mode == ISO8859_1 ) ) {
+ if (lastchar == CR || lastchar == NL){
+ if (nkf_isblank(c)) {
+ for (i=0;i<mimeout_buf_count;i++) {
+ mimeout_addchar(mimeout_buf[i]);
+ }
+ mimeout_buf_count = 0;
+ } else if (SPACE<c && c<DEL) {
+ eof_mime();
+ for (i=0;i<mimeout_buf_count;i++) {
+ (*o_mputc)(mimeout_buf[i]);
+ }
+ base64_count = 0;
+ mimeout_buf_count = 0;
+ }
+ }
+ if (c==SPACE || c==TAB || c==CR || c==NL) {
+ for (i=0;i<mimeout_buf_count;i++) {
+ if (SPACE<mimeout_buf[i] && mimeout_buf[i]<DEL) {
+ eof_mime();
+ for (i=0;i<mimeout_buf_count;i++) {
+ (*o_mputc)(mimeout_buf[i]);
+ base64_count++;
+ }
+ mimeout_buf_count = 0;
+ }
+ }
+ mimeout_buf[mimeout_buf_count++] = (char)c;
+ if (mimeout_buf_count>MIMEOUT_BUF_LENGTH) {
+ eof_mime();
+ for (i=0;i<mimeout_buf_count;i++) {
+ (*o_mputc)(mimeout_buf[i]);
+ base64_count++;
+ }
+ mimeout_buf_count = 0;
+ }
+ return;
+ }
+ if (mimeout_buf_count>0 && SPACE<c && c!='=') {
+ mimeout_buf[mimeout_buf_count++] = (char)c;
+ if (mimeout_buf_count>MIMEOUT_BUF_LENGTH) {
+ j = mimeout_buf_count;
+ mimeout_buf_count = 0;
+ for (i=0;i<j;i++) {
+ mimeout_addchar(mimeout_buf[i]);
+ }
+ }
+ return;
+ }
+ }
+ }
+ if (mimeout_buf_count>0) {
+ j = mimeout_buf_count;
+ mimeout_buf_count = 0;
+ for (i=0;i<j;i++) {
+ if (mimeout_buf[i]==CR || mimeout_buf[i]==NL)
+ break;
+ mimeout_addchar(mimeout_buf[i]);
+ }
+ if (i<j) {
+ eof_mime();
+ base64_count=0;
+ for (;i<j;i++) {
+ (*o_mputc)(mimeout_buf[i]);
+ }
+ open_mime(output_mode);
+ }
+ }
+ mimeout_addchar(c);
+}
+
+
+#if defined(PERL_XS) || defined(WIN32DLL)
+void reinit(void)
+{
+ {
+ struct input_code *p = input_code_list;
+ while (p->name){
+ status_reinit(p++);
+ }
+ }
+ unbuf_f = FALSE;
+ estab_f = FALSE;
+ nop_f = FALSE;
+ binmode_f = TRUE;
+ rot_f = FALSE;
+ hira_f = FALSE;
+ input_f = FALSE;
+ alpha_f = FALSE;
+ mime_f = STRICT_MIME;
+ mime_decode_f = FALSE;
+ mimebuf_f = FALSE;
+ broken_f = FALSE;
+ iso8859_f = FALSE;
+ mimeout_f = FALSE;
+#if defined(MSDOS) || defined(__OS2__)
+ x0201_f = TRUE;
+#else
+ x0201_f = NO_X0201;
+#endif
+ iso2022jp_f = FALSE;
+#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
+ ms_ucs_map_f = UCS_MAP_ASCII;
+#endif
+#ifdef UTF8_INPUT_ENABLE
+ no_cp932ext_f = FALSE;
+ no_best_fit_chars_f = FALSE;
+ encode_fallback = NULL;
+ unicode_subchar = '?';
+ input_endian = ENDIAN_BIG;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ output_bom_f = FALSE;
+ output_endian = ENDIAN_BIG;
+#endif
+#ifdef UNICODE_NORMALIZATION
+ nfc_f = FALSE;
+#endif
+#ifdef INPUT_OPTION
+ cap_f = FALSE;
+ url_f = FALSE;
+ numchar_f = FALSE;
+#endif
+#ifdef CHECK_OPTION
+ noout_f = FALSE;
+ debug_f = FALSE;
+#endif
+ guess_f = FALSE;
+ is_inputcode_mixed = FALSE;
+ is_inputcode_set = FALSE;
+#ifdef EXEC_IO
+ exec_f = 0;
+#endif
+#ifdef SHIFTJIS_CP932
+ cp51932_f = TRUE;
+ cp932inv_f = TRUE;
+#endif
+#ifdef X0212_ENABLE
+ x0212_f = FALSE;
+ x0213_f = FALSE;
+#endif
+ {
+ int i;
+ for (i = 0; i < 256; i++){
+ prefix_table[i] = 0;
+ }
+ }
+ hold_count = 0;
+ mimeout_buf_count = 0;
+ mimeout_mode = 0;
+ base64_count = 0;
+ f_line = 0;
+ f_prev = 0;
+ fold_preserve_f = FALSE;
+ fold_f = FALSE;
+ fold_len = 0;
+ kanji_intro = DEFAULT_J;
+ ascii_intro = DEFAULT_R;
+ fold_margin = FOLD_MARGIN;
+ output_conv = DEFAULT_CONV;
+ oconv = DEFAULT_CONV;
+ o_zconv = no_connection;
+ o_fconv = no_connection;
+ o_crconv = no_connection;
+ o_rot_conv = no_connection;
+ o_hira_conv = no_connection;
+ o_base64conv = no_connection;
+ o_iso2022jp_check_conv = no_connection;
+ o_putc = std_putc;
+ i_getc = std_getc;
+ i_ungetc = std_ungetc;
+ i_bgetc = std_getc;
+ i_bungetc = std_ungetc;
+ o_mputc = std_putc;
+ i_mgetc = std_getc;
+ i_mungetc = std_ungetc;
+ i_mgetc_buf = std_getc;
+ i_mungetc_buf = std_ungetc;
+ output_mode = ASCII;
+ input_mode = ASCII;
+ shift_mode = FALSE;
+ mime_decode_mode = FALSE;
+ file_out_f = FALSE;
+ crmode_f = 0;
+ option_mode = 0;
+ broken_counter = 0;
+ broken_last = 0;
+ z_prev2=0,z_prev1=0;
+#ifdef CHECK_OPTION
+ iconv_for_check = 0;
+#endif
+ input_codename = "";
+#ifdef WIN32DLL
+ reinitdll();
+#endif /*WIN32DLL*/
+}
+#endif
+
+void no_connection(nkf_char c2, nkf_char c1)
+{
+ no_connection2(c2,c1,0);
+}
+
+nkf_char no_connection2(nkf_char c2, nkf_char c1, nkf_char c0)
+{
+ fprintf(stderr,"nkf internal module connection failure.\n");
+ exit(1);
+ return 0; /* LINT */
+}
+
+#ifndef PERL_XS
+#ifdef WIN32DLL
+#define fprintf dllprintf
+#endif
+void usage(void)
+{
+ fprintf(stderr,"USAGE: nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
+ fprintf(stderr,"Flags:\n");
+ fprintf(stderr,"b,u Output is buffered (DEFAULT),Output is unbuffered\n");
+#ifdef DEFAULT_CODE_SJIS
+ fprintf(stderr,"j,s,e,w Output code is JIS 7 bit, Shift_JIS (DEFAULT), EUC-JP, UTF-8N\n");
+#endif
+#ifdef DEFAULT_CODE_JIS
+ fprintf(stderr,"j,s,e,w Output code is JIS 7 bit (DEFAULT), Shift JIS, EUC-JP, UTF-8N\n");
+#endif
+#ifdef DEFAULT_CODE_EUC
+ fprintf(stderr,"j,s,e,w Output code is JIS 7 bit, Shift JIS, EUC-JP (DEFAULT), UTF-8N\n");
+#endif
+#ifdef DEFAULT_CODE_UTF8
+ fprintf(stderr,"j,s,e,w Output code is JIS 7 bit, Shift JIS, EUC-JP, UTF-8N (DEFAULT)\n");
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ fprintf(stderr," After 'w' you can add more options. -w[ 8 [0], 16 [[BL] [0]] ]\n");
+#endif
+ fprintf(stderr,"J,S,E,W Input assumption is JIS 7 bit , Shift JIS, EUC-JP, UTF-8\n");
+#ifdef UTF8_INPUT_ENABLE
+ fprintf(stderr," After 'W' you can add more options. -W[ 8, 16 [BL] ] \n");
+#endif
+ fprintf(stderr,"t no conversion\n");
+ fprintf(stderr,"i[@B] Specify the Esc Seq for JIS X 0208-1978/83 (DEFAULT B)\n");
+ fprintf(stderr,"o[BJH] Specify the Esc Seq for ASCII/Roman (DEFAULT B)\n");
+ fprintf(stderr,"r {de/en}crypt ROT13/47\n");
+ fprintf(stderr,"h 1 katakana->hiragana, 2 hiragana->katakana, 3 both\n");
+ fprintf(stderr,"v Show this usage. V: show version\n");
+ fprintf(stderr,"m[BQN0] MIME decode [B:base64,Q:quoted,N:non-strict,0:no decode]\n");
+ fprintf(stderr,"M[BQ] MIME encode [B:base64 Q:quoted]\n");
+ fprintf(stderr,"l ISO8859-1 (Latin-1) support\n");
+ fprintf(stderr,"f/F Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n");
+ fprintf(stderr,"Z[0-3] Convert X0208 alphabet to ASCII\n");
+ fprintf(stderr," 1: Kankaku to 1 space 2: to 2 spaces 3: Convert to HTML Entity\n");
+ fprintf(stderr,"X,x Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
+ fprintf(stderr,"B[0-2] Broken input 0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
+#ifdef MSDOS
+ fprintf(stderr,"T Text mode output\n");
+#endif
+ fprintf(stderr,"O Output to File (DEFAULT 'nkf.out')\n");
+ fprintf(stderr,"I Convert non ISO-2022-JP charactor to GETA\n");
+ fprintf(stderr,"d,c Convert line breaks -d: LF -c: CRLF\n");
+ fprintf(stderr,"-L[uwm] line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"Long name options\n");
+ fprintf(stderr," --ic=<input codeset> --oc=<output codeset>\n");
+ fprintf(stderr," Specify the input or output codeset\n");
+ fprintf(stderr," --fj --unix --mac --windows\n");
+ fprintf(stderr," --jis --euc --sjis --utf8 --utf16 --mime --base64\n");
+ fprintf(stderr," Convert for the system or code\n");
+ fprintf(stderr," --hiragana --katakana --katakana-hiragana\n");
+ fprintf(stderr," To Hiragana/Katakana Conversion\n");
+ fprintf(stderr," --prefix= Insert escape before troublesome characters of Shift_JIS\n");
+#ifdef INPUT_OPTION
+ fprintf(stderr," --cap-input, --url-input Convert hex after ':' or '%%'\n");
+#endif
+#ifdef NUMCHAR_OPTION
+ fprintf(stderr," --numchar-input Convert Unicode Character Reference\n");
+#endif
+#ifdef UTF8_INPUT_ENABLE
+ fprintf(stderr," --fb-{skip, html, xml, perl, java, subchar}\n");
+ fprintf(stderr," Specify how nkf handles unassigned characters\n");
+#endif
+#ifdef OVERWRITE
+ fprintf(stderr," --in-place[=SUFFIX] --overwrite[=SUFFIX]\n");
+ fprintf(stderr," Overwrite original listed files by filtered result\n");
+ fprintf(stderr," --overwrite preserves timestamp of original files\n");
+#endif
+ fprintf(stderr," -g --guess Guess the input code\n");
+ fprintf(stderr," --help --version Show this help/the version\n");
+ fprintf(stderr," For more information, see also man nkf\n");
+ fprintf(stderr,"\n");
+ version();
+}
+
+void version(void)
+{
+ fprintf(stderr,"Network Kanji Filter Version %s (%s) "
+#if defined(MSDOS) && !defined(__WIN32__) && !defined(__WIN16__) && !defined(__OS2__)
+ "for DOS"
+#endif
+#if defined(MSDOS) && defined(__WIN16__)
+ "for Win16"
+#endif
+#if defined(MSDOS) && defined(__WIN32__)
+ "for Win32"
+#endif
+#ifdef __OS2__
+ "for OS/2"
+#endif
+ ,NKF_VERSION,NKF_RELEASE_DATE);
+ fprintf(stderr,"\n%s\n",CopyRight);
+}
+#endif /*PERL_XS*/
+
+/**
+ ** $B%Q%C%A@):n<T(B
+ ** void@merope.pleiades.or.jp (Kusakabe Youichi)
+ ** NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
+ ** ohta@src.ricoh.co.jp (Junn Ohta)
+ ** inouet@strl.nhk.or.jp (Tomoyuki Inoue)
+ ** kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
+ ** Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
+ ** a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
+ ** kono@ie.u-ryukyu.ac.jp (Shinji Kono)
+ ** GHG00637@nifty-serve.or.jp (COW)
+ **
+ **/
+
+/* end */
diff --git a/ext/nkf/nkf-utf8/utf8tbl.c b/ext/nkf/nkf-utf8/utf8tbl.c
new file mode 100644
index 0000000000..e43ad553d6
--- /dev/null
+++ b/ext/nkf/nkf-utf8/utf8tbl.c
@@ -0,0 +1,8500 @@
+#include "config.h"
+
+#ifdef UTF8_OUTPUT_ENABLE
+const unsigned short euc_to_utf8_A1[] = {
+ 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A,
+ 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8,
+ 0xFF3E, 0x203E, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003,
+ 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2014, 0x2010, 0xFF0F,
+ 0xFF3C, 0x301C, 0x2016, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019,
+ 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D,
+ 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D,
+ 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0x2212, 0x00B1, 0x00D7,
+ 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E,
+ 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0x00A5,
+ 0xFF04, 0x00A2, 0x00A3, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20,
+ 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7,
+};
+
+/* Microsoft UCS Mapping Compatible */
+const unsigned short euc_to_utf8_A1_ms[] = {
+ 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A,
+ 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8,
+ 0xFF3E, 0xFFE3, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003,
+ 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F,
+ 0xFF3C, 0xFF5E, 0x2225, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019,
+ 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D,
+ 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D,
+ 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0xFF0D, 0x00B1, 0x00D7,
+ 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E,
+ 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0xFFE5,
+ 0xFF04, 0xFFE0, 0xFFE1, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20,
+ 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7,
+};
+const unsigned short euc_to_utf8_A2[] = {
+ 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC,
+ 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283,
+ 0x222A, 0x2229, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2227, 0x2228, 0x00AC, 0x21D2, 0x21D4, 0x2200,
+ 0x2203, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202,
+ 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D,
+ 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0,
+ 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020,
+ 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF,
+};
+
+/* Microsoft UCS Mapping Compatible */
+const unsigned short euc_to_utf8_A2_ms[] = {
+ 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC,
+ 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283,
+ 0x222A, 0x2229, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2227, 0x2228, 0xFFE2, 0x21D2, 0x21D4, 0x2200,
+ 0x2203, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202,
+ 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D,
+ 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0,
+ 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020,
+ 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF,
+};
+const unsigned short euc_to_utf8_A3[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
+ 0xFF18, 0xFF19, 0, 0, 0, 0, 0, 0,
+ 0, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27,
+ 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,
+ 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,
+ 0xFF38, 0xFF39, 0xFF3A, 0, 0, 0, 0, 0,
+ 0, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
+ 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
+ 0xFF58, 0xFF59, 0xFF5A, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_A4[] = {
+ 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047,
+ 0x3048, 0x3049, 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F,
+ 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057,
+ 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, 0x305E, 0x305F,
+ 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067,
+ 0x3068, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F,
+ 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077,
+ 0x3078, 0x3079, 0x307A, 0x307B, 0x307C, 0x307D, 0x307E, 0x307F,
+ 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087,
+ 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308E, 0x308F,
+ 0x3090, 0x3091, 0x3092, 0x3093, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_A5[] = {
+ 0x30A1, 0x30A2, 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7,
+ 0x30A8, 0x30A9, 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, 0x30AF,
+ 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, 0x30B5, 0x30B6, 0x30B7,
+ 0x30B8, 0x30B9, 0x30BA, 0x30BB, 0x30BC, 0x30BD, 0x30BE, 0x30BF,
+ 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, 0x30C7,
+ 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF,
+ 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7,
+ 0x30D8, 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, 0x30DF,
+ 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7,
+ 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF,
+ 0x30F0, 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, 0x30F6, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_A6[] = {
+ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8,
+ 0x03A9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
+ 0x03C9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_A7[] = {
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401,
+ 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D,
+ 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
+ 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D,
+ 0x042E, 0x042F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451,
+ 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D,
+ 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
+ 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D,
+ 0x044E, 0x044F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_A8[] = {
+ 0x2500, 0x2502, 0x250C, 0x2510, 0x2518, 0x2514, 0x251C,
+ 0x252C, 0x2524, 0x2534, 0x253C, 0x2501, 0x2503, 0x250F, 0x2513,
+ 0x251B, 0x2517, 0x2523, 0x2533, 0x252B, 0x253B, 0x254B, 0x2520,
+ 0x252F, 0x2528, 0x2537, 0x253F, 0x251D, 0x2530, 0x2525, 0x2538,
+ 0x2542, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_A9[] = {
+ 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466,
+ 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E,
+ 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x2474,
+ 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247A, 0x247B, 0x247C,
+ 0x247D, 0x247E, 0x247F, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484,
+ 0x2485, 0x2486, 0x2487, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x2776, 0x2777, 0x2778,
+ 0x2779, 0x277A, 0x277B, 0x277C, 0x277D, 0x277E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D,
+ 0x248E, 0x248F, 0x2490, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_AA[] = {
+ 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166,
+ 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x2170, 0x2171, 0x2172,
+ 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A,
+ 0x217B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x249C, 0x249D, 0x249E,
+ 0x249F, 0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6,
+ 0x24A7, 0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE,
+ 0x24AF, 0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_AB[] = {
+ 0x339C, 0x339F, 0x339D, 0x33A0, 0x33A4, 0, 0x33A1,
+ 0x33A5, 0x339E, 0x33A2, 0x338E, 0, 0x338F, 0x33C4, 0x3396,
+ 0x3397, 0x2113, 0x3398, 0x33B3, 0x33B2, 0x33B1, 0x33B0, 0x2109,
+ 0x33D4, 0x33CB, 0x3390, 0x3385, 0x3386, 0x3387, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x2116, 0x33CD, 0x2121, 0,
+};
+const unsigned short euc_to_utf8_AC[] = {
+ 0x2664, 0x2667, 0x2661, 0x2662, 0x2660, 0x2663, 0x2665,
+ 0x2666, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x3020, 0x260E, 0x3004,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x261E, 0x261C, 0x261D, 0x261F, 0x21C6, 0x21C4, 0x21C5,
+ 0, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_AD[] = {
+ 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466,
+ 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E,
+ 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x2160, 0x2161, 0x2162,
+ 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0,
+ 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336,
+ 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B,
+ 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x337B,
+ 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6,
+ 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C,
+ 0x2252, 0x2261, 0x222B, 0x222E, 0x2211, 0x221A, 0x22A5, 0x2220,
+ 0x221F, 0x22BF, 0x2235, 0x2229, 0x222A, 0, 0x3299,
+};
+const unsigned short euc_to_utf8_AE[] = {
+ 0x3349, 0x3322, 0x334D, 0x3314, 0x3316, 0x3305, 0x3333,
+ 0x334E, 0x3303, 0x3336, 0x3318, 0x3315, 0x3327, 0x3351, 0x334A,
+ 0x3339, 0x3357, 0x330D, 0x3342, 0x3323, 0x3326, 0x333B, 0x332B,
+ 0, 0, 0, 0, 0, 0, 0, 0x3300,
+ 0x331E, 0x332A, 0x3331, 0x3347, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x337E,
+ 0x337D, 0x337C, 0x337B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x337F, 0, 0,
+};
+const unsigned short euc_to_utf8_AF[] = {
+ 0x222E, 0x221F, 0x22BF, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x301D, 0x301F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x3094, 0, 0x30F7, 0x30F8, 0x30F9, 0x30FA, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_B0[] = {
+ 0x4E9C, 0x5516, 0x5A03, 0x963F, 0x54C0, 0x611B, 0x6328,
+ 0x59F6, 0x9022, 0x8475, 0x831C, 0x7A50, 0x60AA, 0x63E1, 0x6E25,
+ 0x65ED, 0x8466, 0x82A6, 0x9BF5, 0x6893, 0x5727, 0x65A1, 0x6271,
+ 0x5B9B, 0x59D0, 0x867B, 0x98F4, 0x7D62, 0x7DBE, 0x9B8E, 0x6216,
+ 0x7C9F, 0x88B7, 0x5B89, 0x5EB5, 0x6309, 0x6697, 0x6848, 0x95C7,
+ 0x978D, 0x674F, 0x4EE5, 0x4F0A, 0x4F4D, 0x4F9D, 0x5049, 0x56F2,
+ 0x5937, 0x59D4, 0x5A01, 0x5C09, 0x60DF, 0x610F, 0x6170, 0x6613,
+ 0x6905, 0x70BA, 0x754F, 0x7570, 0x79FB, 0x7DAD, 0x7DEF, 0x80C3,
+ 0x840E, 0x8863, 0x8B02, 0x9055, 0x907A, 0x533B, 0x4E95, 0x4EA5,
+ 0x57DF, 0x80B2, 0x90C1, 0x78EF, 0x4E00, 0x58F1, 0x6EA2, 0x9038,
+ 0x7A32, 0x8328, 0x828B, 0x9C2F, 0x5141, 0x5370, 0x54BD, 0x54E1,
+ 0x56E0, 0x59FB, 0x5F15, 0x98F2, 0x6DEB, 0x80E4, 0x852D,
+};
+const unsigned short euc_to_utf8_B1[] = {
+ 0x9662, 0x9670, 0x96A0, 0x97FB, 0x540B, 0x53F3, 0x5B87,
+ 0x70CF, 0x7FBD, 0x8FC2, 0x96E8, 0x536F, 0x9D5C, 0x7ABA, 0x4E11,
+ 0x7893, 0x81FC, 0x6E26, 0x5618, 0x5504, 0x6B1D, 0x851A, 0x9C3B,
+ 0x59E5, 0x53A9, 0x6D66, 0x74DC, 0x958F, 0x5642, 0x4E91, 0x904B,
+ 0x96F2, 0x834F, 0x990C, 0x53E1, 0x55B6, 0x5B30, 0x5F71, 0x6620,
+ 0x66F3, 0x6804, 0x6C38, 0x6CF3, 0x6D29, 0x745B, 0x76C8, 0x7A4E,
+ 0x9834, 0x82F1, 0x885B, 0x8A60, 0x92ED, 0x6DB2, 0x75AB, 0x76CA,
+ 0x99C5, 0x60A6, 0x8B01, 0x8D8A, 0x95B2, 0x698E, 0x53AD, 0x5186,
+ 0x5712, 0x5830, 0x5944, 0x5BB4, 0x5EF6, 0x6028, 0x63A9, 0x63F4,
+ 0x6CBF, 0x6F14, 0x708E, 0x7114, 0x7159, 0x71D5, 0x733F, 0x7E01,
+ 0x8276, 0x82D1, 0x8597, 0x9060, 0x925B, 0x9D1B, 0x5869, 0x65BC,
+ 0x6C5A, 0x7525, 0x51F9, 0x592E, 0x5965, 0x5F80, 0x5FDC,
+};
+const unsigned short euc_to_utf8_B2[] = {
+ 0x62BC, 0x65FA, 0x6A2A, 0x6B27, 0x6BB4, 0x738B, 0x7FC1,
+ 0x8956, 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104,
+ 0x5C4B, 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378,
+ 0x6069, 0x6E29, 0x7A4F, 0x97F3, 0x4E0B, 0x5316, 0x4EEE, 0x4F55,
+ 0x4F3D, 0x4FA1, 0x4F73, 0x52A0, 0x53EF, 0x5609, 0x590F, 0x5AC1,
+ 0x5BB6, 0x5BE1, 0x79D1, 0x6687, 0x679C, 0x67B6, 0x6B4C, 0x6CB3,
+ 0x706B, 0x73C2, 0x798D, 0x79BE, 0x7A3C, 0x7B87, 0x82B1, 0x82DB,
+ 0x8304, 0x8377, 0x83EF, 0x83D3, 0x8766, 0x8AB2, 0x5629, 0x8CA8,
+ 0x8FE6, 0x904E, 0x971E, 0x868A, 0x4FC4, 0x5CE8, 0x6211, 0x7259,
+ 0x753B, 0x81E5, 0x82BD, 0x86FE, 0x8CC0, 0x96C5, 0x9913, 0x99D5,
+ 0x4ECB, 0x4F1A, 0x89E3, 0x56DE, 0x584A, 0x58CA, 0x5EFB, 0x5FEB,
+ 0x602A, 0x6094, 0x6062, 0x61D0, 0x6212, 0x62D0, 0x6539,
+};
+const unsigned short euc_to_utf8_B3[] = {
+ 0x9B41, 0x6666, 0x68B0, 0x6D77, 0x7070, 0x754C, 0x7686,
+ 0x7D75, 0x82A5, 0x87F9, 0x958B, 0x968E, 0x8C9D, 0x51F1, 0x52BE,
+ 0x5916, 0x54B3, 0x5BB3, 0x5D16, 0x6168, 0x6982, 0x6DAF, 0x788D,
+ 0x84CB, 0x8857, 0x8A72, 0x93A7, 0x9AB8, 0x6D6C, 0x99A8, 0x86D9,
+ 0x57A3, 0x67FF, 0x86CE, 0x920E, 0x5283, 0x5687, 0x5404, 0x5ED3,
+ 0x62E1, 0x64B9, 0x683C, 0x6838, 0x6BBB, 0x7372, 0x78BA, 0x7A6B,
+ 0x899A, 0x89D2, 0x8D6B, 0x8F03, 0x90ED, 0x95A3, 0x9694, 0x9769,
+ 0x5B66, 0x5CB3, 0x697D, 0x984D, 0x984E, 0x639B, 0x7B20, 0x6A2B,
+ 0x6A7F, 0x68B6, 0x9C0D, 0x6F5F, 0x5272, 0x559D, 0x6070, 0x62EC,
+ 0x6D3B, 0x6E07, 0x6ED1, 0x845B, 0x8910, 0x8F44, 0x4E14, 0x9C39,
+ 0x53F6, 0x691B, 0x6A3A, 0x9784, 0x682A, 0x515C, 0x7AC3, 0x84B2,
+ 0x91DC, 0x938C, 0x565B, 0x9D28, 0x6822, 0x8305, 0x8431,
+};
+const unsigned short euc_to_utf8_B4[] = {
+ 0x7CA5, 0x5208, 0x82C5, 0x74E6, 0x4E7E, 0x4F83, 0x51A0,
+ 0x5BD2, 0x520A, 0x52D8, 0x52E7, 0x5DFB, 0x559A, 0x582A, 0x59E6,
+ 0x5B8C, 0x5B98, 0x5BDB, 0x5E72, 0x5E79, 0x60A3, 0x611F, 0x6163,
+ 0x61BE, 0x63DB, 0x6562, 0x67D1, 0x6853, 0x68FA, 0x6B3E, 0x6B53,
+ 0x6C57, 0x6F22, 0x6F97, 0x6F45, 0x74B0, 0x7518, 0x76E3, 0x770B,
+ 0x7AFF, 0x7BA1, 0x7C21, 0x7DE9, 0x7F36, 0x7FF0, 0x809D, 0x8266,
+ 0x839E, 0x89B3, 0x8ACC, 0x8CAB, 0x9084, 0x9451, 0x9593, 0x9591,
+ 0x95A2, 0x9665, 0x97D3, 0x9928, 0x8218, 0x4E38, 0x542B, 0x5CB8,
+ 0x5DCC, 0x73A9, 0x764C, 0x773C, 0x5CA9, 0x7FEB, 0x8D0B, 0x96C1,
+ 0x9811, 0x9854, 0x9858, 0x4F01, 0x4F0E, 0x5371, 0x559C, 0x5668,
+ 0x57FA, 0x5947, 0x5B09, 0x5BC4, 0x5C90, 0x5E0C, 0x5E7E, 0x5FCC,
+ 0x63EE, 0x673A, 0x65D7, 0x65E2, 0x671F, 0x68CB, 0x68C4,
+};
+const unsigned short euc_to_utf8_B5[] = {
+ 0x6A5F, 0x5E30, 0x6BC5, 0x6C17, 0x6C7D, 0x757F, 0x7948,
+ 0x5B63, 0x7A00, 0x7D00, 0x5FBD, 0x898F, 0x8A18, 0x8CB4, 0x8D77,
+ 0x8ECC, 0x8F1D, 0x98E2, 0x9A0E, 0x9B3C, 0x4E80, 0x507D, 0x5100,
+ 0x5993, 0x5B9C, 0x622F, 0x6280, 0x64EC, 0x6B3A, 0x72A0, 0x7591,
+ 0x7947, 0x7FA9, 0x87FB, 0x8ABC, 0x8B70, 0x63AC, 0x83CA, 0x97A0,
+ 0x5409, 0x5403, 0x55AB, 0x6854, 0x6A58, 0x8A70, 0x7827, 0x6775,
+ 0x9ECD, 0x5374, 0x5BA2, 0x811A, 0x8650, 0x9006, 0x4E18, 0x4E45,
+ 0x4EC7, 0x4F11, 0x53CA, 0x5438, 0x5BAE, 0x5F13, 0x6025, 0x6551,
+ 0x673D, 0x6C42, 0x6C72, 0x6CE3, 0x7078, 0x7403, 0x7A76, 0x7AAE,
+ 0x7B08, 0x7D1A, 0x7CFE, 0x7D66, 0x65E7, 0x725B, 0x53BB, 0x5C45,
+ 0x5DE8, 0x62D2, 0x62E0, 0x6319, 0x6E20, 0x865A, 0x8A31, 0x8DDD,
+ 0x92F8, 0x6F01, 0x79A6, 0x9B5A, 0x4EA8, 0x4EAB, 0x4EAC,
+};
+const unsigned short euc_to_utf8_B6[] = {
+ 0x4F9B, 0x4FA0, 0x50D1, 0x5147, 0x7AF6, 0x5171, 0x51F6,
+ 0x5354, 0x5321, 0x537F, 0x53EB, 0x55AC, 0x5883, 0x5CE1, 0x5F37,
+ 0x5F4A, 0x602F, 0x6050, 0x606D, 0x631F, 0x6559, 0x6A4B, 0x6CC1,
+ 0x72C2, 0x72ED, 0x77EF, 0x80F8, 0x8105, 0x8208, 0x854E, 0x90F7,
+ 0x93E1, 0x97FF, 0x9957, 0x9A5A, 0x4EF0, 0x51DD, 0x5C2D, 0x6681,
+ 0x696D, 0x5C40, 0x66F2, 0x6975, 0x7389, 0x6850, 0x7C81, 0x50C5,
+ 0x52E4, 0x5747, 0x5DFE, 0x9326, 0x65A4, 0x6B23, 0x6B3D, 0x7434,
+ 0x7981, 0x79BD, 0x7B4B, 0x7DCA, 0x82B9, 0x83CC, 0x887F, 0x895F,
+ 0x8B39, 0x8FD1, 0x91D1, 0x541F, 0x9280, 0x4E5D, 0x5036, 0x53E5,
+ 0x533A, 0x72D7, 0x7396, 0x77E9, 0x82E6, 0x8EAF, 0x99C6, 0x99C8,
+ 0x99D2, 0x5177, 0x611A, 0x865E, 0x55B0, 0x7A7A, 0x5076, 0x5BD3,
+ 0x9047, 0x9685, 0x4E32, 0x6ADB, 0x91E7, 0x5C51, 0x5C48,
+};
+const unsigned short euc_to_utf8_B7[] = {
+ 0x6398, 0x7A9F, 0x6C93, 0x9774, 0x8F61, 0x7AAA, 0x718A,
+ 0x9688, 0x7C82, 0x6817, 0x7E70, 0x6851, 0x936C, 0x52F2, 0x541B,
+ 0x85AB, 0x8A13, 0x7FA4, 0x8ECD, 0x90E1, 0x5366, 0x8888, 0x7941,
+ 0x4FC2, 0x50BE, 0x5211, 0x5144, 0x5553, 0x572D, 0x73EA, 0x578B,
+ 0x5951, 0x5F62, 0x5F84, 0x6075, 0x6176, 0x6167, 0x61A9, 0x63B2,
+ 0x643A, 0x656C, 0x666F, 0x6842, 0x6E13, 0x7566, 0x7A3D, 0x7CFB,
+ 0x7D4C, 0x7D99, 0x7E4B, 0x7F6B, 0x830E, 0x834A, 0x86CD, 0x8A08,
+ 0x8A63, 0x8B66, 0x8EFD, 0x981A, 0x9D8F, 0x82B8, 0x8FCE, 0x9BE8,
+ 0x5287, 0x621F, 0x6483, 0x6FC0, 0x9699, 0x6841, 0x5091, 0x6B20,
+ 0x6C7A, 0x6F54, 0x7A74, 0x7D50, 0x8840, 0x8A23, 0x6708, 0x4EF6,
+ 0x5039, 0x5026, 0x5065, 0x517C, 0x5238, 0x5263, 0x55A7, 0x570F,
+ 0x5805, 0x5ACC, 0x5EFA, 0x61B2, 0x61F8, 0x62F3, 0x6372,
+};
+const unsigned short euc_to_utf8_B8[] = {
+ 0x691C, 0x6A29, 0x727D, 0x72AC, 0x732E, 0x7814, 0x786F,
+ 0x7D79, 0x770C, 0x80A9, 0x898B, 0x8B19, 0x8CE2, 0x8ED2, 0x9063,
+ 0x9375, 0x967A, 0x9855, 0x9A13, 0x9E78, 0x5143, 0x539F, 0x53B3,
+ 0x5E7B, 0x5F26, 0x6E1B, 0x6E90, 0x7384, 0x73FE, 0x7D43, 0x8237,
+ 0x8A00, 0x8AFA, 0x9650, 0x4E4E, 0x500B, 0x53E4, 0x547C, 0x56FA,
+ 0x59D1, 0x5B64, 0x5DF1, 0x5EAB, 0x5F27, 0x6238, 0x6545, 0x67AF,
+ 0x6E56, 0x72D0, 0x7CCA, 0x88B4, 0x80A1, 0x80E1, 0x83F0, 0x864E,
+ 0x8A87, 0x8DE8, 0x9237, 0x96C7, 0x9867, 0x9F13, 0x4E94, 0x4E92,
+ 0x4F0D, 0x5348, 0x5449, 0x543E, 0x5A2F, 0x5F8C, 0x5FA1, 0x609F,
+ 0x68A7, 0x6A8E, 0x745A, 0x7881, 0x8A9E, 0x8AA4, 0x8B77, 0x9190,
+ 0x4E5E, 0x9BC9, 0x4EA4, 0x4F7C, 0x4FAF, 0x5019, 0x5016, 0x5149,
+ 0x516C, 0x529F, 0x52B9, 0x52FE, 0x539A, 0x53E3, 0x5411,
+};
+const unsigned short euc_to_utf8_B9[] = {
+ 0x540E, 0x5589, 0x5751, 0x57A2, 0x597D, 0x5B54, 0x5B5D,
+ 0x5B8F, 0x5DE5, 0x5DE7, 0x5DF7, 0x5E78, 0x5E83, 0x5E9A, 0x5EB7,
+ 0x5F18, 0x6052, 0x614C, 0x6297, 0x62D8, 0x63A7, 0x653B, 0x6602,
+ 0x6643, 0x66F4, 0x676D, 0x6821, 0x6897, 0x69CB, 0x6C5F, 0x6D2A,
+ 0x6D69, 0x6E2F, 0x6E9D, 0x7532, 0x7687, 0x786C, 0x7A3F, 0x7CE0,
+ 0x7D05, 0x7D18, 0x7D5E, 0x7DB1, 0x8015, 0x8003, 0x80AF, 0x80B1,
+ 0x8154, 0x818F, 0x822A, 0x8352, 0x884C, 0x8861, 0x8B1B, 0x8CA2,
+ 0x8CFC, 0x90CA, 0x9175, 0x9271, 0x783F, 0x92FC, 0x95A4, 0x964D,
+ 0x9805, 0x9999, 0x9AD8, 0x9D3B, 0x525B, 0x52AB, 0x53F7, 0x5408,
+ 0x58D5, 0x62F7, 0x6FE0, 0x8C6A, 0x8F5F, 0x9EB9, 0x514B, 0x523B,
+ 0x544A, 0x56FD, 0x7A40, 0x9177, 0x9D60, 0x9ED2, 0x7344, 0x6F09,
+ 0x8170, 0x7511, 0x5FFD, 0x60DA, 0x9AA8, 0x72DB, 0x8FBC,
+};
+const unsigned short euc_to_utf8_BA[] = {
+ 0x6B64, 0x9803, 0x4ECA, 0x56F0, 0x5764, 0x58BE, 0x5A5A,
+ 0x6068, 0x61C7, 0x660F, 0x6606, 0x6839, 0x68B1, 0x6DF7, 0x75D5,
+ 0x7D3A, 0x826E, 0x9B42, 0x4E9B, 0x4F50, 0x53C9, 0x5506, 0x5D6F,
+ 0x5DE6, 0x5DEE, 0x67FB, 0x6C99, 0x7473, 0x7802, 0x8A50, 0x9396,
+ 0x88DF, 0x5750, 0x5EA7, 0x632B, 0x50B5, 0x50AC, 0x518D, 0x6700,
+ 0x54C9, 0x585E, 0x59BB, 0x5BB0, 0x5F69, 0x624D, 0x63A1, 0x683D,
+ 0x6B73, 0x6E08, 0x707D, 0x91C7, 0x7280, 0x7815, 0x7826, 0x796D,
+ 0x658E, 0x7D30, 0x83DC, 0x88C1, 0x8F09, 0x969B, 0x5264, 0x5728,
+ 0x6750, 0x7F6A, 0x8CA1, 0x51B4, 0x5742, 0x962A, 0x583A, 0x698A,
+ 0x80B4, 0x54B2, 0x5D0E, 0x57FC, 0x7895, 0x9DFA, 0x4F5C, 0x524A,
+ 0x548B, 0x643E, 0x6628, 0x6714, 0x67F5, 0x7A84, 0x7B56, 0x7D22,
+ 0x932F, 0x685C, 0x9BAD, 0x7B39, 0x5319, 0x518A, 0x5237,
+};
+const unsigned short euc_to_utf8_BB[] = {
+ 0x5BDF, 0x62F6, 0x64AE, 0x64E6, 0x672D, 0x6BBA, 0x85A9,
+ 0x96D1, 0x7690, 0x9BD6, 0x634C, 0x9306, 0x9BAB, 0x76BF, 0x6652,
+ 0x4E09, 0x5098, 0x53C2, 0x5C71, 0x60E8, 0x6492, 0x6563, 0x685F,
+ 0x71E6, 0x73CA, 0x7523, 0x7B97, 0x7E82, 0x8695, 0x8B83, 0x8CDB,
+ 0x9178, 0x9910, 0x65AC, 0x66AB, 0x6B8B, 0x4ED5, 0x4ED4, 0x4F3A,
+ 0x4F7F, 0x523A, 0x53F8, 0x53F2, 0x55E3, 0x56DB, 0x58EB, 0x59CB,
+ 0x59C9, 0x59FF, 0x5B50, 0x5C4D, 0x5E02, 0x5E2B, 0x5FD7, 0x601D,
+ 0x6307, 0x652F, 0x5B5C, 0x65AF, 0x65BD, 0x65E8, 0x679D, 0x6B62,
+ 0x6B7B, 0x6C0F, 0x7345, 0x7949, 0x79C1, 0x7CF8, 0x7D19, 0x7D2B,
+ 0x80A2, 0x8102, 0x81F3, 0x8996, 0x8A5E, 0x8A69, 0x8A66, 0x8A8C,
+ 0x8AEE, 0x8CC7, 0x8CDC, 0x96CC, 0x98FC, 0x6B6F, 0x4E8B, 0x4F3C,
+ 0x4F8D, 0x5150, 0x5B57, 0x5BFA, 0x6148, 0x6301, 0x6642,
+};
+const unsigned short euc_to_utf8_BC[] = {
+ 0x6B21, 0x6ECB, 0x6CBB, 0x723E, 0x74BD, 0x75D4, 0x78C1,
+ 0x793A, 0x800C, 0x8033, 0x81EA, 0x8494, 0x8F9E, 0x6C50, 0x9E7F,
+ 0x5F0F, 0x8B58, 0x9D2B, 0x7AFA, 0x8EF8, 0x5B8D, 0x96EB, 0x4E03,
+ 0x53F1, 0x57F7, 0x5931, 0x5AC9, 0x5BA4, 0x6089, 0x6E7F, 0x6F06,
+ 0x75BE, 0x8CEA, 0x5B9F, 0x8500, 0x7BE0, 0x5072, 0x67F4, 0x829D,
+ 0x5C61, 0x854A, 0x7E1E, 0x820E, 0x5199, 0x5C04, 0x6368, 0x8D66,
+ 0x659C, 0x716E, 0x793E, 0x7D17, 0x8005, 0x8B1D, 0x8ECA, 0x906E,
+ 0x86C7, 0x90AA, 0x501F, 0x52FA, 0x5C3A, 0x6753, 0x707C, 0x7235,
+ 0x914C, 0x91C8, 0x932B, 0x82E5, 0x5BC2, 0x5F31, 0x60F9, 0x4E3B,
+ 0x53D6, 0x5B88, 0x624B, 0x6731, 0x6B8A, 0x72E9, 0x73E0, 0x7A2E,
+ 0x816B, 0x8DA3, 0x9152, 0x9996, 0x5112, 0x53D7, 0x546A, 0x5BFF,
+ 0x6388, 0x6A39, 0x7DAC, 0x9700, 0x56DA, 0x53CE, 0x5468,
+};
+const unsigned short euc_to_utf8_BD[] = {
+ 0x5B97, 0x5C31, 0x5DDE, 0x4FEE, 0x6101, 0x62FE, 0x6D32,
+ 0x79C0, 0x79CB, 0x7D42, 0x7E4D, 0x7FD2, 0x81ED, 0x821F, 0x8490,
+ 0x8846, 0x8972, 0x8B90, 0x8E74, 0x8F2F, 0x9031, 0x914B, 0x916C,
+ 0x96C6, 0x919C, 0x4EC0, 0x4F4F, 0x5145, 0x5341, 0x5F93, 0x620E,
+ 0x67D4, 0x6C41, 0x6E0B, 0x7363, 0x7E26, 0x91CD, 0x9283, 0x53D4,
+ 0x5919, 0x5BBF, 0x6DD1, 0x795D, 0x7E2E, 0x7C9B, 0x587E, 0x719F,
+ 0x51FA, 0x8853, 0x8FF0, 0x4FCA, 0x5CFB, 0x6625, 0x77AC, 0x7AE3,
+ 0x821C, 0x99FF, 0x51C6, 0x5FAA, 0x65EC, 0x696F, 0x6B89, 0x6DF3,
+ 0x6E96, 0x6F64, 0x76FE, 0x7D14, 0x5DE1, 0x9075, 0x9187, 0x9806,
+ 0x51E6, 0x521D, 0x6240, 0x6691, 0x66D9, 0x6E1A, 0x5EB6, 0x7DD2,
+ 0x7F72, 0x66F8, 0x85AF, 0x85F7, 0x8AF8, 0x52A9, 0x53D9, 0x5973,
+ 0x5E8F, 0x5F90, 0x6055, 0x92E4, 0x9664, 0x50B7, 0x511F,
+};
+const unsigned short euc_to_utf8_BE[] = {
+ 0x52DD, 0x5320, 0x5347, 0x53EC, 0x54E8, 0x5546, 0x5531,
+ 0x5617, 0x5968, 0x59BE, 0x5A3C, 0x5BB5, 0x5C06, 0x5C0F, 0x5C11,
+ 0x5C1A, 0x5E84, 0x5E8A, 0x5EE0, 0x5F70, 0x627F, 0x6284, 0x62DB,
+ 0x638C, 0x6377, 0x6607, 0x660C, 0x662D, 0x6676, 0x677E, 0x68A2,
+ 0x6A1F, 0x6A35, 0x6CBC, 0x6D88, 0x6E09, 0x6E58, 0x713C, 0x7126,
+ 0x7167, 0x75C7, 0x7701, 0x785D, 0x7901, 0x7965, 0x79F0, 0x7AE0,
+ 0x7B11, 0x7CA7, 0x7D39, 0x8096, 0x83D6, 0x848B, 0x8549, 0x885D,
+ 0x88F3, 0x8A1F, 0x8A3C, 0x8A54, 0x8A73, 0x8C61, 0x8CDE, 0x91A4,
+ 0x9266, 0x937E, 0x9418, 0x969C, 0x9798, 0x4E0A, 0x4E08, 0x4E1E,
+ 0x4E57, 0x5197, 0x5270, 0x57CE, 0x5834, 0x58CC, 0x5B22, 0x5E38,
+ 0x60C5, 0x64FE, 0x6761, 0x6756, 0x6D44, 0x72B6, 0x7573, 0x7A63,
+ 0x84B8, 0x8B72, 0x91B8, 0x9320, 0x5631, 0x57F4, 0x98FE,
+};
+const unsigned short euc_to_utf8_BF[] = {
+ 0x62ED, 0x690D, 0x6B96, 0x71ED, 0x7E54, 0x8077, 0x8272,
+ 0x89E6, 0x98DF, 0x8755, 0x8FB1, 0x5C3B, 0x4F38, 0x4FE1, 0x4FB5,
+ 0x5507, 0x5A20, 0x5BDD, 0x5BE9, 0x5FC3, 0x614E, 0x632F, 0x65B0,
+ 0x664B, 0x68EE, 0x699B, 0x6D78, 0x6DF1, 0x7533, 0x75B9, 0x771F,
+ 0x795E, 0x79E6, 0x7D33, 0x81E3, 0x82AF, 0x85AA, 0x89AA, 0x8A3A,
+ 0x8EAB, 0x8F9B, 0x9032, 0x91DD, 0x9707, 0x4EBA, 0x4EC1, 0x5203,
+ 0x5875, 0x58EC, 0x5C0B, 0x751A, 0x5C3D, 0x814E, 0x8A0A, 0x8FC5,
+ 0x9663, 0x976D, 0x7B25, 0x8ACF, 0x9808, 0x9162, 0x56F3, 0x53A8,
+ 0x9017, 0x5439, 0x5782, 0x5E25, 0x63A8, 0x6C34, 0x708A, 0x7761,
+ 0x7C8B, 0x7FE0, 0x8870, 0x9042, 0x9154, 0x9310, 0x9318, 0x968F,
+ 0x745E, 0x9AC4, 0x5D07, 0x5D69, 0x6570, 0x67A2, 0x8DA8, 0x96DB,
+ 0x636E, 0x6749, 0x6919, 0x83C5, 0x9817, 0x96C0, 0x88FE,
+};
+const unsigned short euc_to_utf8_C0[] = {
+ 0x6F84, 0x647A, 0x5BF8, 0x4E16, 0x702C, 0x755D, 0x662F,
+ 0x51C4, 0x5236, 0x52E2, 0x59D3, 0x5F81, 0x6027, 0x6210, 0x653F,
+ 0x6574, 0x661F, 0x6674, 0x68F2, 0x6816, 0x6B63, 0x6E05, 0x7272,
+ 0x751F, 0x76DB, 0x7CBE, 0x8056, 0x58F0, 0x88FD, 0x897F, 0x8AA0,
+ 0x8A93, 0x8ACB, 0x901D, 0x9192, 0x9752, 0x9759, 0x6589, 0x7A0E,
+ 0x8106, 0x96BB, 0x5E2D, 0x60DC, 0x621A, 0x65A5, 0x6614, 0x6790,
+ 0x77F3, 0x7A4D, 0x7C4D, 0x7E3E, 0x810A, 0x8CAC, 0x8D64, 0x8DE1,
+ 0x8E5F, 0x78A9, 0x5207, 0x62D9, 0x63A5, 0x6442, 0x6298, 0x8A2D,
+ 0x7A83, 0x7BC0, 0x8AAC, 0x96EA, 0x7D76, 0x820C, 0x8749, 0x4ED9,
+ 0x5148, 0x5343, 0x5360, 0x5BA3, 0x5C02, 0x5C16, 0x5DDD, 0x6226,
+ 0x6247, 0x64B0, 0x6813, 0x6834, 0x6CC9, 0x6D45, 0x6D17, 0x67D3,
+ 0x6F5C, 0x714E, 0x717D, 0x65CB, 0x7A7F, 0x7BAD, 0x7DDA,
+};
+const unsigned short euc_to_utf8_C1[] = {
+ 0x7E4A, 0x7FA8, 0x817A, 0x821B, 0x8239, 0x85A6, 0x8A6E,
+ 0x8CCE, 0x8DF5, 0x9078, 0x9077, 0x92AD, 0x9291, 0x9583, 0x9BAE,
+ 0x524D, 0x5584, 0x6F38, 0x7136, 0x5168, 0x7985, 0x7E55, 0x81B3,
+ 0x7CCE, 0x564C, 0x5851, 0x5CA8, 0x63AA, 0x66FE, 0x66FD, 0x695A,
+ 0x72D9, 0x758F, 0x758E, 0x790E, 0x7956, 0x79DF, 0x7C97, 0x7D20,
+ 0x7D44, 0x8607, 0x8A34, 0x963B, 0x9061, 0x9F20, 0x50E7, 0x5275,
+ 0x53CC, 0x53E2, 0x5009, 0x55AA, 0x58EE, 0x594F, 0x723D, 0x5B8B,
+ 0x5C64, 0x531D, 0x60E3, 0x60F3, 0x635C, 0x6383, 0x633F, 0x63BB,
+ 0x64CD, 0x65E9, 0x66F9, 0x5DE3, 0x69CD, 0x69FD, 0x6F15, 0x71E5,
+ 0x4E89, 0x75E9, 0x76F8, 0x7A93, 0x7CDF, 0x7DCF, 0x7D9C, 0x8061,
+ 0x8349, 0x8358, 0x846C, 0x84BC, 0x85FB, 0x88C5, 0x8D70, 0x9001,
+ 0x906D, 0x9397, 0x971C, 0x9A12, 0x50CF, 0x5897, 0x618E,
+};
+const unsigned short euc_to_utf8_C2[] = {
+ 0x81D3, 0x8535, 0x8D08, 0x9020, 0x4FC3, 0x5074, 0x5247,
+ 0x5373, 0x606F, 0x6349, 0x675F, 0x6E2C, 0x8DB3, 0x901F, 0x4FD7,
+ 0x5C5E, 0x8CCA, 0x65CF, 0x7D9A, 0x5352, 0x8896, 0x5176, 0x63C3,
+ 0x5B58, 0x5B6B, 0x5C0A, 0x640D, 0x6751, 0x905C, 0x4ED6, 0x591A,
+ 0x592A, 0x6C70, 0x8A51, 0x553E, 0x5815, 0x59A5, 0x60F0, 0x6253,
+ 0x67C1, 0x8235, 0x6955, 0x9640, 0x99C4, 0x9A28, 0x4F53, 0x5806,
+ 0x5BFE, 0x8010, 0x5CB1, 0x5E2F, 0x5F85, 0x6020, 0x614B, 0x6234,
+ 0x66FF, 0x6CF0, 0x6EDE, 0x80CE, 0x817F, 0x82D4, 0x888B, 0x8CB8,
+ 0x9000, 0x902E, 0x968A, 0x9EDB, 0x9BDB, 0x4EE3, 0x53F0, 0x5927,
+ 0x7B2C, 0x918D, 0x984C, 0x9DF9, 0x6EDD, 0x7027, 0x5353, 0x5544,
+ 0x5B85, 0x6258, 0x629E, 0x62D3, 0x6CA2, 0x6FEF, 0x7422, 0x8A17,
+ 0x9438, 0x6FC1, 0x8AFE, 0x8338, 0x51E7, 0x86F8, 0x53EA,
+};
+const unsigned short euc_to_utf8_C3[] = {
+ 0x53E9, 0x4F46, 0x9054, 0x8FB0, 0x596A, 0x8131, 0x5DFD,
+ 0x7AEA, 0x8FBF, 0x68DA, 0x8C37, 0x72F8, 0x9C48, 0x6A3D, 0x8AB0,
+ 0x4E39, 0x5358, 0x5606, 0x5766, 0x62C5, 0x63A2, 0x65E6, 0x6B4E,
+ 0x6DE1, 0x6E5B, 0x70AD, 0x77ED, 0x7AEF, 0x7BAA, 0x7DBB, 0x803D,
+ 0x80C6, 0x86CB, 0x8A95, 0x935B, 0x56E3, 0x58C7, 0x5F3E, 0x65AD,
+ 0x6696, 0x6A80, 0x6BB5, 0x7537, 0x8AC7, 0x5024, 0x77E5, 0x5730,
+ 0x5F1B, 0x6065, 0x667A, 0x6C60, 0x75F4, 0x7A1A, 0x7F6E, 0x81F4,
+ 0x8718, 0x9045, 0x99B3, 0x7BC9, 0x755C, 0x7AF9, 0x7B51, 0x84C4,
+ 0x9010, 0x79E9, 0x7A92, 0x8336, 0x5AE1, 0x7740, 0x4E2D, 0x4EF2,
+ 0x5B99, 0x5FE0, 0x62BD, 0x663C, 0x67F1, 0x6CE8, 0x866B, 0x8877,
+ 0x8A3B, 0x914E, 0x92F3, 0x99D0, 0x6A17, 0x7026, 0x732A, 0x82E7,
+ 0x8457, 0x8CAF, 0x4E01, 0x5146, 0x51CB, 0x558B, 0x5BF5,
+};
+const unsigned short euc_to_utf8_C4[] = {
+ 0x5E16, 0x5E33, 0x5E81, 0x5F14, 0x5F35, 0x5F6B, 0x5FB4,
+ 0x61F2, 0x6311, 0x66A2, 0x671D, 0x6F6E, 0x7252, 0x753A, 0x773A,
+ 0x8074, 0x8139, 0x8178, 0x8776, 0x8ABF, 0x8ADC, 0x8D85, 0x8DF3,
+ 0x929A, 0x9577, 0x9802, 0x9CE5, 0x52C5, 0x6357, 0x76F4, 0x6715,
+ 0x6C88, 0x73CD, 0x8CC3, 0x93AE, 0x9673, 0x6D25, 0x589C, 0x690E,
+ 0x69CC, 0x8FFD, 0x939A, 0x75DB, 0x901A, 0x585A, 0x6802, 0x63B4,
+ 0x69FB, 0x4F43, 0x6F2C, 0x67D8, 0x8FBB, 0x8526, 0x7DB4, 0x9354,
+ 0x693F, 0x6F70, 0x576A, 0x58F7, 0x5B2C, 0x7D2C, 0x722A, 0x540A,
+ 0x91E3, 0x9DB4, 0x4EAD, 0x4F4E, 0x505C, 0x5075, 0x5243, 0x8C9E,
+ 0x5448, 0x5824, 0x5B9A, 0x5E1D, 0x5E95, 0x5EAD, 0x5EF7, 0x5F1F,
+ 0x608C, 0x62B5, 0x633A, 0x63D0, 0x68AF, 0x6C40, 0x7887, 0x798E,
+ 0x7A0B, 0x7DE0, 0x8247, 0x8A02, 0x8AE6, 0x8E44, 0x9013,
+};
+const unsigned short euc_to_utf8_C5[] = {
+ 0x90B8, 0x912D, 0x91D8, 0x9F0E, 0x6CE5, 0x6458, 0x64E2,
+ 0x6575, 0x6EF4, 0x7684, 0x7B1B, 0x9069, 0x93D1, 0x6EBA, 0x54F2,
+ 0x5FB9, 0x64A4, 0x8F4D, 0x8FED, 0x9244, 0x5178, 0x586B, 0x5929,
+ 0x5C55, 0x5E97, 0x6DFB, 0x7E8F, 0x751C, 0x8CBC, 0x8EE2, 0x985B,
+ 0x70B9, 0x4F1D, 0x6BBF, 0x6FB1, 0x7530, 0x96FB, 0x514E, 0x5410,
+ 0x5835, 0x5857, 0x59AC, 0x5C60, 0x5F92, 0x6597, 0x675C, 0x6E21,
+ 0x767B, 0x83DF, 0x8CED, 0x9014, 0x90FD, 0x934D, 0x7825, 0x783A,
+ 0x52AA, 0x5EA6, 0x571F, 0x5974, 0x6012, 0x5012, 0x515A, 0x51AC,
+ 0x51CD, 0x5200, 0x5510, 0x5854, 0x5858, 0x5957, 0x5B95, 0x5CF6,
+ 0x5D8B, 0x60BC, 0x6295, 0x642D, 0x6771, 0x6843, 0x68BC, 0x68DF,
+ 0x76D7, 0x6DD8, 0x6E6F, 0x6D9B, 0x706F, 0x71C8, 0x5F53, 0x75D8,
+ 0x7977, 0x7B49, 0x7B54, 0x7B52, 0x7CD6, 0x7D71, 0x5230,
+};
+const unsigned short euc_to_utf8_C6[] = {
+ 0x8463, 0x8569, 0x85E4, 0x8A0E, 0x8B04, 0x8C46, 0x8E0F,
+ 0x9003, 0x900F, 0x9419, 0x9676, 0x982D, 0x9A30, 0x95D8, 0x50CD,
+ 0x52D5, 0x540C, 0x5802, 0x5C0E, 0x61A7, 0x649E, 0x6D1E, 0x77B3,
+ 0x7AE5, 0x80F4, 0x8404, 0x9053, 0x9285, 0x5CE0, 0x9D07, 0x533F,
+ 0x5F97, 0x5FB3, 0x6D9C, 0x7279, 0x7763, 0x79BF, 0x7BE4, 0x6BD2,
+ 0x72EC, 0x8AAD, 0x6803, 0x6A61, 0x51F8, 0x7A81, 0x6934, 0x5C4A,
+ 0x9CF6, 0x82EB, 0x5BC5, 0x9149, 0x701E, 0x5678, 0x5C6F, 0x60C7,
+ 0x6566, 0x6C8C, 0x8C5A, 0x9041, 0x9813, 0x5451, 0x66C7, 0x920D,
+ 0x5948, 0x90A3, 0x5185, 0x4E4D, 0x51EA, 0x8599, 0x8B0E, 0x7058,
+ 0x637A, 0x934B, 0x6962, 0x99B4, 0x7E04, 0x7577, 0x5357, 0x6960,
+ 0x8EDF, 0x96E3, 0x6C5D, 0x4E8C, 0x5C3C, 0x5F10, 0x8FE9, 0x5302,
+ 0x8CD1, 0x8089, 0x8679, 0x5EFF, 0x65E5, 0x4E73, 0x5165,
+};
+const unsigned short euc_to_utf8_C7[] = {
+ 0x5982, 0x5C3F, 0x97EE, 0x4EFB, 0x598A, 0x5FCD, 0x8A8D,
+ 0x6FE1, 0x79B0, 0x7962, 0x5BE7, 0x8471, 0x732B, 0x71B1, 0x5E74,
+ 0x5FF5, 0x637B, 0x649A, 0x71C3, 0x7C98, 0x4E43, 0x5EFC, 0x4E4B,
+ 0x57DC, 0x56A2, 0x60A9, 0x6FC3, 0x7D0D, 0x80FD, 0x8133, 0x81BF,
+ 0x8FB2, 0x8997, 0x86A4, 0x5DF4, 0x628A, 0x64AD, 0x8987, 0x6777,
+ 0x6CE2, 0x6D3E, 0x7436, 0x7834, 0x5A46, 0x7F75, 0x82AD, 0x99AC,
+ 0x4FF3, 0x5EC3, 0x62DD, 0x6392, 0x6557, 0x676F, 0x76C3, 0x724C,
+ 0x80CC, 0x80BA, 0x8F29, 0x914D, 0x500D, 0x57F9, 0x5A92, 0x6885,
+ 0x6973, 0x7164, 0x72FD, 0x8CB7, 0x58F2, 0x8CE0, 0x966A, 0x9019,
+ 0x877F, 0x79E4, 0x77E7, 0x8429, 0x4F2F, 0x5265, 0x535A, 0x62CD,
+ 0x67CF, 0x6CCA, 0x767D, 0x7B94, 0x7C95, 0x8236, 0x8584, 0x8FEB,
+ 0x66DD, 0x6F20, 0x7206, 0x7E1B, 0x83AB, 0x99C1, 0x9EA6,
+};
+const unsigned short euc_to_utf8_C8[] = {
+ 0x51FD, 0x7BB1, 0x7872, 0x7BB8, 0x8087, 0x7B48, 0x6AE8,
+ 0x5E61, 0x808C, 0x7551, 0x7560, 0x516B, 0x9262, 0x6E8C, 0x767A,
+ 0x9197, 0x9AEA, 0x4F10, 0x7F70, 0x629C, 0x7B4F, 0x95A5, 0x9CE9,
+ 0x567A, 0x5859, 0x86E4, 0x96BC, 0x4F34, 0x5224, 0x534A, 0x53CD,
+ 0x53DB, 0x5E06, 0x642C, 0x6591, 0x677F, 0x6C3E, 0x6C4E, 0x7248,
+ 0x72AF, 0x73ED, 0x7554, 0x7E41, 0x822C, 0x85E9, 0x8CA9, 0x7BC4,
+ 0x91C6, 0x7169, 0x9812, 0x98EF, 0x633D, 0x6669, 0x756A, 0x76E4,
+ 0x78D0, 0x8543, 0x86EE, 0x532A, 0x5351, 0x5426, 0x5983, 0x5E87,
+ 0x5F7C, 0x60B2, 0x6249, 0x6279, 0x62AB, 0x6590, 0x6BD4, 0x6CCC,
+ 0x75B2, 0x76AE, 0x7891, 0x79D8, 0x7DCB, 0x7F77, 0x80A5, 0x88AB,
+ 0x8AB9, 0x8CBB, 0x907F, 0x975E, 0x98DB, 0x6A0B, 0x7C38, 0x5099,
+ 0x5C3E, 0x5FAE, 0x6787, 0x6BD8, 0x7435, 0x7709, 0x7F8E,
+};
+const unsigned short euc_to_utf8_C9[] = {
+ 0x9F3B, 0x67CA, 0x7A17, 0x5339, 0x758B, 0x9AED, 0x5F66,
+ 0x819D, 0x83F1, 0x8098, 0x5F3C, 0x5FC5, 0x7562, 0x7B46, 0x903C,
+ 0x6867, 0x59EB, 0x5A9B, 0x7D10, 0x767E, 0x8B2C, 0x4FF5, 0x5F6A,
+ 0x6A19, 0x6C37, 0x6F02, 0x74E2, 0x7968, 0x8868, 0x8A55, 0x8C79,
+ 0x5EDF, 0x63CF, 0x75C5, 0x79D2, 0x82D7, 0x9328, 0x92F2, 0x849C,
+ 0x86ED, 0x9C2D, 0x54C1, 0x5F6C, 0x658C, 0x6D5C, 0x7015, 0x8CA7,
+ 0x8CD3, 0x983B, 0x654F, 0x74F6, 0x4E0D, 0x4ED8, 0x57E0, 0x592B,
+ 0x5A66, 0x5BCC, 0x51A8, 0x5E03, 0x5E9C, 0x6016, 0x6276, 0x6577,
+ 0x65A7, 0x666E, 0x6D6E, 0x7236, 0x7B26, 0x8150, 0x819A, 0x8299,
+ 0x8B5C, 0x8CA0, 0x8CE6, 0x8D74, 0x961C, 0x9644, 0x4FAE, 0x64AB,
+ 0x6B66, 0x821E, 0x8461, 0x856A, 0x90E8, 0x5C01, 0x6953, 0x98A8,
+ 0x847A, 0x8557, 0x4F0F, 0x526F, 0x5FA9, 0x5E45, 0x670D,
+};
+const unsigned short euc_to_utf8_CA[] = {
+ 0x798F, 0x8179, 0x8907, 0x8986, 0x6DF5, 0x5F17, 0x6255,
+ 0x6CB8, 0x4ECF, 0x7269, 0x9B92, 0x5206, 0x543B, 0x5674, 0x58B3,
+ 0x61A4, 0x626E, 0x711A, 0x596E, 0x7C89, 0x7CDE, 0x7D1B, 0x96F0,
+ 0x6587, 0x805E, 0x4E19, 0x4F75, 0x5175, 0x5840, 0x5E63, 0x5E73,
+ 0x5F0A, 0x67C4, 0x4E26, 0x853D, 0x9589, 0x965B, 0x7C73, 0x9801,
+ 0x50FB, 0x58C1, 0x7656, 0x78A7, 0x5225, 0x77A5, 0x8511, 0x7B86,
+ 0x504F, 0x5909, 0x7247, 0x7BC7, 0x7DE8, 0x8FBA, 0x8FD4, 0x904D,
+ 0x4FBF, 0x52C9, 0x5A29, 0x5F01, 0x97AD, 0x4FDD, 0x8217, 0x92EA,
+ 0x5703, 0x6355, 0x6B69, 0x752B, 0x88DC, 0x8F14, 0x7A42, 0x52DF,
+ 0x5893, 0x6155, 0x620A, 0x66AE, 0x6BCD, 0x7C3F, 0x83E9, 0x5023,
+ 0x4FF8, 0x5305, 0x5446, 0x5831, 0x5949, 0x5B9D, 0x5CF0, 0x5CEF,
+ 0x5D29, 0x5E96, 0x62B1, 0x6367, 0x653E, 0x65B9, 0x670B,
+};
+const unsigned short euc_to_utf8_CB[] = {
+ 0x6CD5, 0x6CE1, 0x70F9, 0x7832, 0x7E2B, 0x80DE, 0x82B3,
+ 0x840C, 0x84EC, 0x8702, 0x8912, 0x8A2A, 0x8C4A, 0x90A6, 0x92D2,
+ 0x98FD, 0x9CF3, 0x9D6C, 0x4E4F, 0x4EA1, 0x508D, 0x5256, 0x574A,
+ 0x59A8, 0x5E3D, 0x5FD8, 0x5FD9, 0x623F, 0x66B4, 0x671B, 0x67D0,
+ 0x68D2, 0x5192, 0x7D21, 0x80AA, 0x81A8, 0x8B00, 0x8C8C, 0x8CBF,
+ 0x927E, 0x9632, 0x5420, 0x982C, 0x5317, 0x50D5, 0x535C, 0x58A8,
+ 0x64B2, 0x6734, 0x7267, 0x7766, 0x7A46, 0x91E6, 0x52C3, 0x6CA1,
+ 0x6B86, 0x5800, 0x5E4C, 0x5954, 0x672C, 0x7FFB, 0x51E1, 0x76C6,
+ 0x6469, 0x78E8, 0x9B54, 0x9EBB, 0x57CB, 0x59B9, 0x6627, 0x679A,
+ 0x6BCE, 0x54E9, 0x69D9, 0x5E55, 0x819C, 0x6795, 0x9BAA, 0x67FE,
+ 0x9C52, 0x685D, 0x4EA6, 0x4FE3, 0x53C8, 0x62B9, 0x672B, 0x6CAB,
+ 0x8FC4, 0x4FAD, 0x7E6D, 0x9EBF, 0x4E07, 0x6162, 0x6E80,
+};
+const unsigned short euc_to_utf8_CC[] = {
+ 0x6F2B, 0x8513, 0x5473, 0x672A, 0x9B45, 0x5DF3, 0x7B95,
+ 0x5CAC, 0x5BC6, 0x871C, 0x6E4A, 0x84D1, 0x7A14, 0x8108, 0x5999,
+ 0x7C8D, 0x6C11, 0x7720, 0x52D9, 0x5922, 0x7121, 0x725F, 0x77DB,
+ 0x9727, 0x9D61, 0x690B, 0x5A7F, 0x5A18, 0x51A5, 0x540D, 0x547D,
+ 0x660E, 0x76DF, 0x8FF7, 0x9298, 0x9CF4, 0x59EA, 0x725D, 0x6EC5,
+ 0x514D, 0x68C9, 0x7DBF, 0x7DEC, 0x9762, 0x9EBA, 0x6478, 0x6A21,
+ 0x8302, 0x5984, 0x5B5F, 0x6BDB, 0x731B, 0x76F2, 0x7DB2, 0x8017,
+ 0x8499, 0x5132, 0x6728, 0x9ED9, 0x76EE, 0x6762, 0x52FF, 0x9905,
+ 0x5C24, 0x623B, 0x7C7E, 0x8CB0, 0x554F, 0x60B6, 0x7D0B, 0x9580,
+ 0x5301, 0x4E5F, 0x51B6, 0x591C, 0x723A, 0x8036, 0x91CE, 0x5F25,
+ 0x77E2, 0x5384, 0x5F79, 0x7D04, 0x85AC, 0x8A33, 0x8E8D, 0x9756,
+ 0x67F3, 0x85AE, 0x9453, 0x6109, 0x6108, 0x6CB9, 0x7652,
+};
+const unsigned short euc_to_utf8_CD[] = {
+ 0x8AED, 0x8F38, 0x552F, 0x4F51, 0x512A, 0x52C7, 0x53CB,
+ 0x5BA5, 0x5E7D, 0x60A0, 0x6182, 0x63D6, 0x6709, 0x67DA, 0x6E67,
+ 0x6D8C, 0x7336, 0x7337, 0x7531, 0x7950, 0x88D5, 0x8A98, 0x904A,
+ 0x9091, 0x90F5, 0x96C4, 0x878D, 0x5915, 0x4E88, 0x4F59, 0x4E0E,
+ 0x8A89, 0x8F3F, 0x9810, 0x50AD, 0x5E7C, 0x5996, 0x5BB9, 0x5EB8,
+ 0x63DA, 0x63FA, 0x64C1, 0x66DC, 0x694A, 0x69D8, 0x6D0B, 0x6EB6,
+ 0x7194, 0x7528, 0x7AAF, 0x7F8A, 0x8000, 0x8449, 0x84C9, 0x8981,
+ 0x8B21, 0x8E0A, 0x9065, 0x967D, 0x990A, 0x617E, 0x6291, 0x6B32,
+ 0x6C83, 0x6D74, 0x7FCC, 0x7FFC, 0x6DC0, 0x7F85, 0x87BA, 0x88F8,
+ 0x6765, 0x83B1, 0x983C, 0x96F7, 0x6D1B, 0x7D61, 0x843D, 0x916A,
+ 0x4E71, 0x5375, 0x5D50, 0x6B04, 0x6FEB, 0x85CD, 0x862D, 0x89A7,
+ 0x5229, 0x540F, 0x5C65, 0x674E, 0x68A8, 0x7406, 0x7483,
+};
+const unsigned short euc_to_utf8_CE[] = {
+ 0x75E2, 0x88CF, 0x88E1, 0x91CC, 0x96E2, 0x9678, 0x5F8B,
+ 0x7387, 0x7ACB, 0x844E, 0x63A0, 0x7565, 0x5289, 0x6D41, 0x6E9C,
+ 0x7409, 0x7559, 0x786B, 0x7C92, 0x9686, 0x7ADC, 0x9F8D, 0x4FB6,
+ 0x616E, 0x65C5, 0x865C, 0x4E86, 0x4EAE, 0x50DA, 0x4E21, 0x51CC,
+ 0x5BEE, 0x6599, 0x6881, 0x6DBC, 0x731F, 0x7642, 0x77AD, 0x7A1C,
+ 0x7CE7, 0x826F, 0x8AD2, 0x907C, 0x91CF, 0x9675, 0x9818, 0x529B,
+ 0x7DD1, 0x502B, 0x5398, 0x6797, 0x6DCB, 0x71D0, 0x7433, 0x81E8,
+ 0x8F2A, 0x96A3, 0x9C57, 0x9E9F, 0x7460, 0x5841, 0x6D99, 0x7D2F,
+ 0x985E, 0x4EE4, 0x4F36, 0x4F8B, 0x51B7, 0x52B1, 0x5DBA, 0x601C,
+ 0x73B2, 0x793C, 0x82D3, 0x9234, 0x96B7, 0x96F6, 0x970A, 0x9E97,
+ 0x9F62, 0x66A6, 0x6B74, 0x5217, 0x52A3, 0x70C8, 0x88C2, 0x5EC9,
+ 0x604B, 0x6190, 0x6F23, 0x7149, 0x7C3E, 0x7DF4, 0x806F,
+};
+const unsigned short euc_to_utf8_CF[] = {
+ 0x84EE, 0x9023, 0x932C, 0x5442, 0x9B6F, 0x6AD3, 0x7089,
+ 0x8CC2, 0x8DEF, 0x9732, 0x52B4, 0x5A41, 0x5ECA, 0x5F04, 0x6717,
+ 0x697C, 0x6994, 0x6D6A, 0x6F0F, 0x7262, 0x72FC, 0x7BED, 0x8001,
+ 0x807E, 0x874B, 0x90CE, 0x516D, 0x9E93, 0x7984, 0x808B, 0x9332,
+ 0x8AD6, 0x502D, 0x548C, 0x8A71, 0x6B6A, 0x8CC4, 0x8107, 0x60D1,
+ 0x67A0, 0x9DF2, 0x4E99, 0x4E98, 0x9C10, 0x8A6B, 0x85C1, 0x8568,
+ 0x6900, 0x6E7E, 0x7897, 0x8155, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_D0[] = {
+ 0x5F0C, 0x4E10, 0x4E15, 0x4E2A, 0x4E31, 0x4E36, 0x4E3C,
+ 0x4E3F, 0x4E42, 0x4E56, 0x4E58, 0x4E82, 0x4E85, 0x8C6B, 0x4E8A,
+ 0x8212, 0x5F0D, 0x4E8E, 0x4E9E, 0x4E9F, 0x4EA0, 0x4EA2, 0x4EB0,
+ 0x4EB3, 0x4EB6, 0x4ECE, 0x4ECD, 0x4EC4, 0x4EC6, 0x4EC2, 0x4ED7,
+ 0x4EDE, 0x4EED, 0x4EDF, 0x4EF7, 0x4F09, 0x4F5A, 0x4F30, 0x4F5B,
+ 0x4F5D, 0x4F57, 0x4F47, 0x4F76, 0x4F88, 0x4F8F, 0x4F98, 0x4F7B,
+ 0x4F69, 0x4F70, 0x4F91, 0x4F6F, 0x4F86, 0x4F96, 0x5118, 0x4FD4,
+ 0x4FDF, 0x4FCE, 0x4FD8, 0x4FDB, 0x4FD1, 0x4FDA, 0x4FD0, 0x4FE4,
+ 0x4FE5, 0x501A, 0x5028, 0x5014, 0x502A, 0x5025, 0x5005, 0x4F1C,
+ 0x4FF6, 0x5021, 0x5029, 0x502C, 0x4FFE, 0x4FEF, 0x5011, 0x5006,
+ 0x5043, 0x5047, 0x6703, 0x5055, 0x5050, 0x5048, 0x505A, 0x5056,
+ 0x506C, 0x5078, 0x5080, 0x509A, 0x5085, 0x50B4, 0x50B2,
+};
+const unsigned short euc_to_utf8_D1[] = {
+ 0x50C9, 0x50CA, 0x50B3, 0x50C2, 0x50D6, 0x50DE, 0x50E5,
+ 0x50ED, 0x50E3, 0x50EE, 0x50F9, 0x50F5, 0x5109, 0x5101, 0x5102,
+ 0x5116, 0x5115, 0x5114, 0x511A, 0x5121, 0x513A, 0x5137, 0x513C,
+ 0x513B, 0x513F, 0x5140, 0x5152, 0x514C, 0x5154, 0x5162, 0x7AF8,
+ 0x5169, 0x516A, 0x516E, 0x5180, 0x5182, 0x56D8, 0x518C, 0x5189,
+ 0x518F, 0x5191, 0x5193, 0x5195, 0x5196, 0x51A4, 0x51A6, 0x51A2,
+ 0x51A9, 0x51AA, 0x51AB, 0x51B3, 0x51B1, 0x51B2, 0x51B0, 0x51B5,
+ 0x51BD, 0x51C5, 0x51C9, 0x51DB, 0x51E0, 0x8655, 0x51E9, 0x51ED,
+ 0x51F0, 0x51F5, 0x51FE, 0x5204, 0x520B, 0x5214, 0x520E, 0x5227,
+ 0x522A, 0x522E, 0x5233, 0x5239, 0x524F, 0x5244, 0x524B, 0x524C,
+ 0x525E, 0x5254, 0x526A, 0x5274, 0x5269, 0x5273, 0x527F, 0x527D,
+ 0x528D, 0x5294, 0x5292, 0x5271, 0x5288, 0x5291, 0x8FA8,
+};
+const unsigned short euc_to_utf8_D2[] = {
+ 0x8FA7, 0x52AC, 0x52AD, 0x52BC, 0x52B5, 0x52C1, 0x52CD,
+ 0x52D7, 0x52DE, 0x52E3, 0x52E6, 0x98ED, 0x52E0, 0x52F3, 0x52F5,
+ 0x52F8, 0x52F9, 0x5306, 0x5308, 0x7538, 0x530D, 0x5310, 0x530F,
+ 0x5315, 0x531A, 0x5323, 0x532F, 0x5331, 0x5333, 0x5338, 0x5340,
+ 0x5346, 0x5345, 0x4E17, 0x5349, 0x534D, 0x51D6, 0x535E, 0x5369,
+ 0x536E, 0x5918, 0x537B, 0x5377, 0x5382, 0x5396, 0x53A0, 0x53A6,
+ 0x53A5, 0x53AE, 0x53B0, 0x53B6, 0x53C3, 0x7C12, 0x96D9, 0x53DF,
+ 0x66FC, 0x71EE, 0x53EE, 0x53E8, 0x53ED, 0x53FA, 0x5401, 0x543D,
+ 0x5440, 0x542C, 0x542D, 0x543C, 0x542E, 0x5436, 0x5429, 0x541D,
+ 0x544E, 0x548F, 0x5475, 0x548E, 0x545F, 0x5471, 0x5477, 0x5470,
+ 0x5492, 0x547B, 0x5480, 0x5476, 0x5484, 0x5490, 0x5486, 0x54C7,
+ 0x54A2, 0x54B8, 0x54A5, 0x54AC, 0x54C4, 0x54C8, 0x54A8,
+};
+const unsigned short euc_to_utf8_D3[] = {
+ 0x54AB, 0x54C2, 0x54A4, 0x54BE, 0x54BC, 0x54D8, 0x54E5,
+ 0x54E6, 0x550F, 0x5514, 0x54FD, 0x54EE, 0x54ED, 0x54FA, 0x54E2,
+ 0x5539, 0x5540, 0x5563, 0x554C, 0x552E, 0x555C, 0x5545, 0x5556,
+ 0x5557, 0x5538, 0x5533, 0x555D, 0x5599, 0x5580, 0x54AF, 0x558A,
+ 0x559F, 0x557B, 0x557E, 0x5598, 0x559E, 0x55AE, 0x557C, 0x5583,
+ 0x55A9, 0x5587, 0x55A8, 0x55DA, 0x55C5, 0x55DF, 0x55C4, 0x55DC,
+ 0x55E4, 0x55D4, 0x5614, 0x55F7, 0x5616, 0x55FE, 0x55FD, 0x561B,
+ 0x55F9, 0x564E, 0x5650, 0x71DF, 0x5634, 0x5636, 0x5632, 0x5638,
+ 0x566B, 0x5664, 0x562F, 0x566C, 0x566A, 0x5686, 0x5680, 0x568A,
+ 0x56A0, 0x5694, 0x568F, 0x56A5, 0x56AE, 0x56B6, 0x56B4, 0x56C2,
+ 0x56BC, 0x56C1, 0x56C3, 0x56C0, 0x56C8, 0x56CE, 0x56D1, 0x56D3,
+ 0x56D7, 0x56EE, 0x56F9, 0x5700, 0x56FF, 0x5704, 0x5709,
+};
+const unsigned short euc_to_utf8_D4[] = {
+ 0x5708, 0x570B, 0x570D, 0x5713, 0x5718, 0x5716, 0x55C7,
+ 0x571C, 0x5726, 0x5737, 0x5738, 0x574E, 0x573B, 0x5740, 0x574F,
+ 0x5769, 0x57C0, 0x5788, 0x5761, 0x577F, 0x5789, 0x5793, 0x57A0,
+ 0x57B3, 0x57A4, 0x57AA, 0x57B0, 0x57C3, 0x57C6, 0x57D4, 0x57D2,
+ 0x57D3, 0x580A, 0x57D6, 0x57E3, 0x580B, 0x5819, 0x581D, 0x5872,
+ 0x5821, 0x5862, 0x584B, 0x5870, 0x6BC0, 0x5852, 0x583D, 0x5879,
+ 0x5885, 0x58B9, 0x589F, 0x58AB, 0x58BA, 0x58DE, 0x58BB, 0x58B8,
+ 0x58AE, 0x58C5, 0x58D3, 0x58D1, 0x58D7, 0x58D9, 0x58D8, 0x58E5,
+ 0x58DC, 0x58E4, 0x58DF, 0x58EF, 0x58FA, 0x58F9, 0x58FB, 0x58FC,
+ 0x58FD, 0x5902, 0x590A, 0x5910, 0x591B, 0x68A6, 0x5925, 0x592C,
+ 0x592D, 0x5932, 0x5938, 0x593E, 0x7AD2, 0x5955, 0x5950, 0x594E,
+ 0x595A, 0x5958, 0x5962, 0x5960, 0x5967, 0x596C, 0x5969,
+};
+const unsigned short euc_to_utf8_D5[] = {
+ 0x5978, 0x5981, 0x599D, 0x4F5E, 0x4FAB, 0x59A3, 0x59B2,
+ 0x59C6, 0x59E8, 0x59DC, 0x598D, 0x59D9, 0x59DA, 0x5A25, 0x5A1F,
+ 0x5A11, 0x5A1C, 0x5A09, 0x5A1A, 0x5A40, 0x5A6C, 0x5A49, 0x5A35,
+ 0x5A36, 0x5A62, 0x5A6A, 0x5A9A, 0x5ABC, 0x5ABE, 0x5ACB, 0x5AC2,
+ 0x5ABD, 0x5AE3, 0x5AD7, 0x5AE6, 0x5AE9, 0x5AD6, 0x5AFA, 0x5AFB,
+ 0x5B0C, 0x5B0B, 0x5B16, 0x5B32, 0x5AD0, 0x5B2A, 0x5B36, 0x5B3E,
+ 0x5B43, 0x5B45, 0x5B40, 0x5B51, 0x5B55, 0x5B5A, 0x5B5B, 0x5B65,
+ 0x5B69, 0x5B70, 0x5B73, 0x5B75, 0x5B78, 0x6588, 0x5B7A, 0x5B80,
+ 0x5B83, 0x5BA6, 0x5BB8, 0x5BC3, 0x5BC7, 0x5BC9, 0x5BD4, 0x5BD0,
+ 0x5BE4, 0x5BE6, 0x5BE2, 0x5BDE, 0x5BE5, 0x5BEB, 0x5BF0, 0x5BF6,
+ 0x5BF3, 0x5C05, 0x5C07, 0x5C08, 0x5C0D, 0x5C13, 0x5C20, 0x5C22,
+ 0x5C28, 0x5C38, 0x5C39, 0x5C41, 0x5C46, 0x5C4E, 0x5C53,
+};
+const unsigned short euc_to_utf8_D6[] = {
+ 0x5C50, 0x5C4F, 0x5B71, 0x5C6C, 0x5C6E, 0x4E62, 0x5C76,
+ 0x5C79, 0x5C8C, 0x5C91, 0x5C94, 0x599B, 0x5CAB, 0x5CBB, 0x5CB6,
+ 0x5CBC, 0x5CB7, 0x5CC5, 0x5CBE, 0x5CC7, 0x5CD9, 0x5CE9, 0x5CFD,
+ 0x5CFA, 0x5CED, 0x5D8C, 0x5CEA, 0x5D0B, 0x5D15, 0x5D17, 0x5D5C,
+ 0x5D1F, 0x5D1B, 0x5D11, 0x5D14, 0x5D22, 0x5D1A, 0x5D19, 0x5D18,
+ 0x5D4C, 0x5D52, 0x5D4E, 0x5D4B, 0x5D6C, 0x5D73, 0x5D76, 0x5D87,
+ 0x5D84, 0x5D82, 0x5DA2, 0x5D9D, 0x5DAC, 0x5DAE, 0x5DBD, 0x5D90,
+ 0x5DB7, 0x5DBC, 0x5DC9, 0x5DCD, 0x5DD3, 0x5DD2, 0x5DD6, 0x5DDB,
+ 0x5DEB, 0x5DF2, 0x5DF5, 0x5E0B, 0x5E1A, 0x5E19, 0x5E11, 0x5E1B,
+ 0x5E36, 0x5E37, 0x5E44, 0x5E43, 0x5E40, 0x5E4E, 0x5E57, 0x5E54,
+ 0x5E5F, 0x5E62, 0x5E64, 0x5E47, 0x5E75, 0x5E76, 0x5E7A, 0x9EBC,
+ 0x5E7F, 0x5EA0, 0x5EC1, 0x5EC2, 0x5EC8, 0x5ED0, 0x5ECF,
+};
+const unsigned short euc_to_utf8_D7[] = {
+ 0x5ED6, 0x5EE3, 0x5EDD, 0x5EDA, 0x5EDB, 0x5EE2, 0x5EE1,
+ 0x5EE8, 0x5EE9, 0x5EEC, 0x5EF1, 0x5EF3, 0x5EF0, 0x5EF4, 0x5EF8,
+ 0x5EFE, 0x5F03, 0x5F09, 0x5F5D, 0x5F5C, 0x5F0B, 0x5F11, 0x5F16,
+ 0x5F29, 0x5F2D, 0x5F38, 0x5F41, 0x5F48, 0x5F4C, 0x5F4E, 0x5F2F,
+ 0x5F51, 0x5F56, 0x5F57, 0x5F59, 0x5F61, 0x5F6D, 0x5F73, 0x5F77,
+ 0x5F83, 0x5F82, 0x5F7F, 0x5F8A, 0x5F88, 0x5F91, 0x5F87, 0x5F9E,
+ 0x5F99, 0x5F98, 0x5FA0, 0x5FA8, 0x5FAD, 0x5FBC, 0x5FD6, 0x5FFB,
+ 0x5FE4, 0x5FF8, 0x5FF1, 0x5FDD, 0x60B3, 0x5FFF, 0x6021, 0x6060,
+ 0x6019, 0x6010, 0x6029, 0x600E, 0x6031, 0x601B, 0x6015, 0x602B,
+ 0x6026, 0x600F, 0x603A, 0x605A, 0x6041, 0x606A, 0x6077, 0x605F,
+ 0x604A, 0x6046, 0x604D, 0x6063, 0x6043, 0x6064, 0x6042, 0x606C,
+ 0x606B, 0x6059, 0x6081, 0x608D, 0x60E7, 0x6083, 0x609A,
+};
+const unsigned short euc_to_utf8_D8[] = {
+ 0x6084, 0x609B, 0x6096, 0x6097, 0x6092, 0x60A7, 0x608B,
+ 0x60E1, 0x60B8, 0x60E0, 0x60D3, 0x60B4, 0x5FF0, 0x60BD, 0x60C6,
+ 0x60B5, 0x60D8, 0x614D, 0x6115, 0x6106, 0x60F6, 0x60F7, 0x6100,
+ 0x60F4, 0x60FA, 0x6103, 0x6121, 0x60FB, 0x60F1, 0x610D, 0x610E,
+ 0x6147, 0x613E, 0x6128, 0x6127, 0x614A, 0x613F, 0x613C, 0x612C,
+ 0x6134, 0x613D, 0x6142, 0x6144, 0x6173, 0x6177, 0x6158, 0x6159,
+ 0x615A, 0x616B, 0x6174, 0x616F, 0x6165, 0x6171, 0x615F, 0x615D,
+ 0x6153, 0x6175, 0x6199, 0x6196, 0x6187, 0x61AC, 0x6194, 0x619A,
+ 0x618A, 0x6191, 0x61AB, 0x61AE, 0x61CC, 0x61CA, 0x61C9, 0x61F7,
+ 0x61C8, 0x61C3, 0x61C6, 0x61BA, 0x61CB, 0x7F79, 0x61CD, 0x61E6,
+ 0x61E3, 0x61F6, 0x61FA, 0x61F4, 0x61FF, 0x61FD, 0x61FC, 0x61FE,
+ 0x6200, 0x6208, 0x6209, 0x620D, 0x620C, 0x6214, 0x621B,
+};
+const unsigned short euc_to_utf8_D9[] = {
+ 0x621E, 0x6221, 0x622A, 0x622E, 0x6230, 0x6232, 0x6233,
+ 0x6241, 0x624E, 0x625E, 0x6263, 0x625B, 0x6260, 0x6268, 0x627C,
+ 0x6282, 0x6289, 0x627E, 0x6292, 0x6293, 0x6296, 0x62D4, 0x6283,
+ 0x6294, 0x62D7, 0x62D1, 0x62BB, 0x62CF, 0x62FF, 0x62C6, 0x64D4,
+ 0x62C8, 0x62DC, 0x62CC, 0x62CA, 0x62C2, 0x62C7, 0x629B, 0x62C9,
+ 0x630C, 0x62EE, 0x62F1, 0x6327, 0x6302, 0x6308, 0x62EF, 0x62F5,
+ 0x6350, 0x633E, 0x634D, 0x641C, 0x634F, 0x6396, 0x638E, 0x6380,
+ 0x63AB, 0x6376, 0x63A3, 0x638F, 0x6389, 0x639F, 0x63B5, 0x636B,
+ 0x6369, 0x63BE, 0x63E9, 0x63C0, 0x63C6, 0x63E3, 0x63C9, 0x63D2,
+ 0x63F6, 0x63C4, 0x6416, 0x6434, 0x6406, 0x6413, 0x6426, 0x6436,
+ 0x651D, 0x6417, 0x6428, 0x640F, 0x6467, 0x646F, 0x6476, 0x644E,
+ 0x652A, 0x6495, 0x6493, 0x64A5, 0x64A9, 0x6488, 0x64BC,
+};
+const unsigned short euc_to_utf8_DA[] = {
+ 0x64DA, 0x64D2, 0x64C5, 0x64C7, 0x64BB, 0x64D8, 0x64C2,
+ 0x64F1, 0x64E7, 0x8209, 0x64E0, 0x64E1, 0x62AC, 0x64E3, 0x64EF,
+ 0x652C, 0x64F6, 0x64F4, 0x64F2, 0x64FA, 0x6500, 0x64FD, 0x6518,
+ 0x651C, 0x6505, 0x6524, 0x6523, 0x652B, 0x6534, 0x6535, 0x6537,
+ 0x6536, 0x6538, 0x754B, 0x6548, 0x6556, 0x6555, 0x654D, 0x6558,
+ 0x655E, 0x655D, 0x6572, 0x6578, 0x6582, 0x6583, 0x8B8A, 0x659B,
+ 0x659F, 0x65AB, 0x65B7, 0x65C3, 0x65C6, 0x65C1, 0x65C4, 0x65CC,
+ 0x65D2, 0x65DB, 0x65D9, 0x65E0, 0x65E1, 0x65F1, 0x6772, 0x660A,
+ 0x6603, 0x65FB, 0x6773, 0x6635, 0x6636, 0x6634, 0x661C, 0x664F,
+ 0x6644, 0x6649, 0x6641, 0x665E, 0x665D, 0x6664, 0x6667, 0x6668,
+ 0x665F, 0x6662, 0x6670, 0x6683, 0x6688, 0x668E, 0x6689, 0x6684,
+ 0x6698, 0x669D, 0x66C1, 0x66B9, 0x66C9, 0x66BE, 0x66BC,
+};
+const unsigned short euc_to_utf8_DB[] = {
+ 0x66C4, 0x66B8, 0x66D6, 0x66DA, 0x66E0, 0x663F, 0x66E6,
+ 0x66E9, 0x66F0, 0x66F5, 0x66F7, 0x670F, 0x6716, 0x671E, 0x6726,
+ 0x6727, 0x9738, 0x672E, 0x673F, 0x6736, 0x6741, 0x6738, 0x6737,
+ 0x6746, 0x675E, 0x6760, 0x6759, 0x6763, 0x6764, 0x6789, 0x6770,
+ 0x67A9, 0x677C, 0x676A, 0x678C, 0x678B, 0x67A6, 0x67A1, 0x6785,
+ 0x67B7, 0x67EF, 0x67B4, 0x67EC, 0x67B3, 0x67E9, 0x67B8, 0x67E4,
+ 0x67DE, 0x67DD, 0x67E2, 0x67EE, 0x67B9, 0x67CE, 0x67C6, 0x67E7,
+ 0x6A9C, 0x681E, 0x6846, 0x6829, 0x6840, 0x684D, 0x6832, 0x684E,
+ 0x68B3, 0x682B, 0x6859, 0x6863, 0x6877, 0x687F, 0x689F, 0x688F,
+ 0x68AD, 0x6894, 0x689D, 0x689B, 0x6883, 0x6AAE, 0x68B9, 0x6874,
+ 0x68B5, 0x68A0, 0x68BA, 0x690F, 0x688D, 0x687E, 0x6901, 0x68CA,
+ 0x6908, 0x68D8, 0x6922, 0x6926, 0x68E1, 0x690C, 0x68CD,
+};
+const unsigned short euc_to_utf8_DC[] = {
+ 0x68D4, 0x68E7, 0x68D5, 0x6936, 0x6912, 0x6904, 0x68D7,
+ 0x68E3, 0x6925, 0x68F9, 0x68E0, 0x68EF, 0x6928, 0x692A, 0x691A,
+ 0x6923, 0x6921, 0x68C6, 0x6979, 0x6977, 0x695C, 0x6978, 0x696B,
+ 0x6954, 0x697E, 0x696E, 0x6939, 0x6974, 0x693D, 0x6959, 0x6930,
+ 0x6961, 0x695E, 0x695D, 0x6981, 0x696A, 0x69B2, 0x69AE, 0x69D0,
+ 0x69BF, 0x69C1, 0x69D3, 0x69BE, 0x69CE, 0x5BE8, 0x69CA, 0x69DD,
+ 0x69BB, 0x69C3, 0x69A7, 0x6A2E, 0x6991, 0x69A0, 0x699C, 0x6995,
+ 0x69B4, 0x69DE, 0x69E8, 0x6A02, 0x6A1B, 0x69FF, 0x6B0A, 0x69F9,
+ 0x69F2, 0x69E7, 0x6A05, 0x69B1, 0x6A1E, 0x69ED, 0x6A14, 0x69EB,
+ 0x6A0A, 0x6A12, 0x6AC1, 0x6A23, 0x6A13, 0x6A44, 0x6A0C, 0x6A72,
+ 0x6A36, 0x6A78, 0x6A47, 0x6A62, 0x6A59, 0x6A66, 0x6A48, 0x6A38,
+ 0x6A22, 0x6A90, 0x6A8D, 0x6AA0, 0x6A84, 0x6AA2, 0x6AA3,
+};
+const unsigned short euc_to_utf8_DD[] = {
+ 0x6A97, 0x8617, 0x6ABB, 0x6AC3, 0x6AC2, 0x6AB8, 0x6AB3,
+ 0x6AAC, 0x6ADE, 0x6AD1, 0x6ADF, 0x6AAA, 0x6ADA, 0x6AEA, 0x6AFB,
+ 0x6B05, 0x8616, 0x6AFA, 0x6B12, 0x6B16, 0x9B31, 0x6B1F, 0x6B38,
+ 0x6B37, 0x76DC, 0x6B39, 0x98EE, 0x6B47, 0x6B43, 0x6B49, 0x6B50,
+ 0x6B59, 0x6B54, 0x6B5B, 0x6B5F, 0x6B61, 0x6B78, 0x6B79, 0x6B7F,
+ 0x6B80, 0x6B84, 0x6B83, 0x6B8D, 0x6B98, 0x6B95, 0x6B9E, 0x6BA4,
+ 0x6BAA, 0x6BAB, 0x6BAF, 0x6BB2, 0x6BB1, 0x6BB3, 0x6BB7, 0x6BBC,
+ 0x6BC6, 0x6BCB, 0x6BD3, 0x6BDF, 0x6BEC, 0x6BEB, 0x6BF3, 0x6BEF,
+ 0x9EBE, 0x6C08, 0x6C13, 0x6C14, 0x6C1B, 0x6C24, 0x6C23, 0x6C5E,
+ 0x6C55, 0x6C62, 0x6C6A, 0x6C82, 0x6C8D, 0x6C9A, 0x6C81, 0x6C9B,
+ 0x6C7E, 0x6C68, 0x6C73, 0x6C92, 0x6C90, 0x6CC4, 0x6CF1, 0x6CD3,
+ 0x6CBD, 0x6CD7, 0x6CC5, 0x6CDD, 0x6CAE, 0x6CB1, 0x6CBE,
+};
+const unsigned short euc_to_utf8_DE[] = {
+ 0x6CBA, 0x6CDB, 0x6CEF, 0x6CD9, 0x6CEA, 0x6D1F, 0x884D,
+ 0x6D36, 0x6D2B, 0x6D3D, 0x6D38, 0x6D19, 0x6D35, 0x6D33, 0x6D12,
+ 0x6D0C, 0x6D63, 0x6D93, 0x6D64, 0x6D5A, 0x6D79, 0x6D59, 0x6D8E,
+ 0x6D95, 0x6FE4, 0x6D85, 0x6DF9, 0x6E15, 0x6E0A, 0x6DB5, 0x6DC7,
+ 0x6DE6, 0x6DB8, 0x6DC6, 0x6DEC, 0x6DDE, 0x6DCC, 0x6DE8, 0x6DD2,
+ 0x6DC5, 0x6DFA, 0x6DD9, 0x6DE4, 0x6DD5, 0x6DEA, 0x6DEE, 0x6E2D,
+ 0x6E6E, 0x6E2E, 0x6E19, 0x6E72, 0x6E5F, 0x6E3E, 0x6E23, 0x6E6B,
+ 0x6E2B, 0x6E76, 0x6E4D, 0x6E1F, 0x6E43, 0x6E3A, 0x6E4E, 0x6E24,
+ 0x6EFF, 0x6E1D, 0x6E38, 0x6E82, 0x6EAA, 0x6E98, 0x6EC9, 0x6EB7,
+ 0x6ED3, 0x6EBD, 0x6EAF, 0x6EC4, 0x6EB2, 0x6ED4, 0x6ED5, 0x6E8F,
+ 0x6EA5, 0x6EC2, 0x6E9F, 0x6F41, 0x6F11, 0x704C, 0x6EEC, 0x6EF8,
+ 0x6EFE, 0x6F3F, 0x6EF2, 0x6F31, 0x6EEF, 0x6F32, 0x6ECC,
+};
+const unsigned short euc_to_utf8_DF[] = {
+ 0x6F3E, 0x6F13, 0x6EF7, 0x6F86, 0x6F7A, 0x6F78, 0x6F81,
+ 0x6F80, 0x6F6F, 0x6F5B, 0x6FF3, 0x6F6D, 0x6F82, 0x6F7C, 0x6F58,
+ 0x6F8E, 0x6F91, 0x6FC2, 0x6F66, 0x6FB3, 0x6FA3, 0x6FA1, 0x6FA4,
+ 0x6FB9, 0x6FC6, 0x6FAA, 0x6FDF, 0x6FD5, 0x6FEC, 0x6FD4, 0x6FD8,
+ 0x6FF1, 0x6FEE, 0x6FDB, 0x7009, 0x700B, 0x6FFA, 0x7011, 0x7001,
+ 0x700F, 0x6FFE, 0x701B, 0x701A, 0x6F74, 0x701D, 0x7018, 0x701F,
+ 0x7030, 0x703E, 0x7032, 0x7051, 0x7063, 0x7099, 0x7092, 0x70AF,
+ 0x70F1, 0x70AC, 0x70B8, 0x70B3, 0x70AE, 0x70DF, 0x70CB, 0x70DD,
+ 0x70D9, 0x7109, 0x70FD, 0x711C, 0x7119, 0x7165, 0x7155, 0x7188,
+ 0x7166, 0x7162, 0x714C, 0x7156, 0x716C, 0x718F, 0x71FB, 0x7184,
+ 0x7195, 0x71A8, 0x71AC, 0x71D7, 0x71B9, 0x71BE, 0x71D2, 0x71C9,
+ 0x71D4, 0x71CE, 0x71E0, 0x71EC, 0x71E7, 0x71F5, 0x71FC,
+};
+const unsigned short euc_to_utf8_E0[] = {
+ 0x71F9, 0x71FF, 0x720D, 0x7210, 0x721B, 0x7228, 0x722D,
+ 0x722C, 0x7230, 0x7232, 0x723B, 0x723C, 0x723F, 0x7240, 0x7246,
+ 0x724B, 0x7258, 0x7274, 0x727E, 0x7282, 0x7281, 0x7287, 0x7292,
+ 0x7296, 0x72A2, 0x72A7, 0x72B9, 0x72B2, 0x72C3, 0x72C6, 0x72C4,
+ 0x72CE, 0x72D2, 0x72E2, 0x72E0, 0x72E1, 0x72F9, 0x72F7, 0x500F,
+ 0x7317, 0x730A, 0x731C, 0x7316, 0x731D, 0x7334, 0x732F, 0x7329,
+ 0x7325, 0x733E, 0x734E, 0x734F, 0x9ED8, 0x7357, 0x736A, 0x7368,
+ 0x7370, 0x7378, 0x7375, 0x737B, 0x737A, 0x73C8, 0x73B3, 0x73CE,
+ 0x73BB, 0x73C0, 0x73E5, 0x73EE, 0x73DE, 0x74A2, 0x7405, 0x746F,
+ 0x7425, 0x73F8, 0x7432, 0x743A, 0x7455, 0x743F, 0x745F, 0x7459,
+ 0x7441, 0x745C, 0x7469, 0x7470, 0x7463, 0x746A, 0x7476, 0x747E,
+ 0x748B, 0x749E, 0x74A7, 0x74CA, 0x74CF, 0x74D4, 0x73F1,
+};
+const unsigned short euc_to_utf8_E1[] = {
+ 0x74E0, 0x74E3, 0x74E7, 0x74E9, 0x74EE, 0x74F2, 0x74F0,
+ 0x74F1, 0x74F8, 0x74F7, 0x7504, 0x7503, 0x7505, 0x750C, 0x750E,
+ 0x750D, 0x7515, 0x7513, 0x751E, 0x7526, 0x752C, 0x753C, 0x7544,
+ 0x754D, 0x754A, 0x7549, 0x755B, 0x7546, 0x755A, 0x7569, 0x7564,
+ 0x7567, 0x756B, 0x756D, 0x7578, 0x7576, 0x7586, 0x7587, 0x7574,
+ 0x758A, 0x7589, 0x7582, 0x7594, 0x759A, 0x759D, 0x75A5, 0x75A3,
+ 0x75C2, 0x75B3, 0x75C3, 0x75B5, 0x75BD, 0x75B8, 0x75BC, 0x75B1,
+ 0x75CD, 0x75CA, 0x75D2, 0x75D9, 0x75E3, 0x75DE, 0x75FE, 0x75FF,
+ 0x75FC, 0x7601, 0x75F0, 0x75FA, 0x75F2, 0x75F3, 0x760B, 0x760D,
+ 0x7609, 0x761F, 0x7627, 0x7620, 0x7621, 0x7622, 0x7624, 0x7634,
+ 0x7630, 0x763B, 0x7647, 0x7648, 0x7646, 0x765C, 0x7658, 0x7661,
+ 0x7662, 0x7668, 0x7669, 0x766A, 0x7667, 0x766C, 0x7670,
+};
+const unsigned short euc_to_utf8_E2[] = {
+ 0x7672, 0x7676, 0x7678, 0x767C, 0x7680, 0x7683, 0x7688,
+ 0x768B, 0x768E, 0x7696, 0x7693, 0x7699, 0x769A, 0x76B0, 0x76B4,
+ 0x76B8, 0x76B9, 0x76BA, 0x76C2, 0x76CD, 0x76D6, 0x76D2, 0x76DE,
+ 0x76E1, 0x76E5, 0x76E7, 0x76EA, 0x862F, 0x76FB, 0x7708, 0x7707,
+ 0x7704, 0x7729, 0x7724, 0x771E, 0x7725, 0x7726, 0x771B, 0x7737,
+ 0x7738, 0x7747, 0x775A, 0x7768, 0x776B, 0x775B, 0x7765, 0x777F,
+ 0x777E, 0x7779, 0x778E, 0x778B, 0x7791, 0x77A0, 0x779E, 0x77B0,
+ 0x77B6, 0x77B9, 0x77BF, 0x77BC, 0x77BD, 0x77BB, 0x77C7, 0x77CD,
+ 0x77D7, 0x77DA, 0x77DC, 0x77E3, 0x77EE, 0x77FC, 0x780C, 0x7812,
+ 0x7926, 0x7820, 0x792A, 0x7845, 0x788E, 0x7874, 0x7886, 0x787C,
+ 0x789A, 0x788C, 0x78A3, 0x78B5, 0x78AA, 0x78AF, 0x78D1, 0x78C6,
+ 0x78CB, 0x78D4, 0x78BE, 0x78BC, 0x78C5, 0x78CA, 0x78EC,
+};
+const unsigned short euc_to_utf8_E3[] = {
+ 0x78E7, 0x78DA, 0x78FD, 0x78F4, 0x7907, 0x7912, 0x7911,
+ 0x7919, 0x792C, 0x792B, 0x7940, 0x7960, 0x7957, 0x795F, 0x795A,
+ 0x7955, 0x7953, 0x797A, 0x797F, 0x798A, 0x799D, 0x79A7, 0x9F4B,
+ 0x79AA, 0x79AE, 0x79B3, 0x79B9, 0x79BA, 0x79C9, 0x79D5, 0x79E7,
+ 0x79EC, 0x79E1, 0x79E3, 0x7A08, 0x7A0D, 0x7A18, 0x7A19, 0x7A20,
+ 0x7A1F, 0x7980, 0x7A31, 0x7A3B, 0x7A3E, 0x7A37, 0x7A43, 0x7A57,
+ 0x7A49, 0x7A61, 0x7A62, 0x7A69, 0x9F9D, 0x7A70, 0x7A79, 0x7A7D,
+ 0x7A88, 0x7A97, 0x7A95, 0x7A98, 0x7A96, 0x7AA9, 0x7AC8, 0x7AB0,
+ 0x7AB6, 0x7AC5, 0x7AC4, 0x7ABF, 0x9083, 0x7AC7, 0x7ACA, 0x7ACD,
+ 0x7ACF, 0x7AD5, 0x7AD3, 0x7AD9, 0x7ADA, 0x7ADD, 0x7AE1, 0x7AE2,
+ 0x7AE6, 0x7AED, 0x7AF0, 0x7B02, 0x7B0F, 0x7B0A, 0x7B06, 0x7B33,
+ 0x7B18, 0x7B19, 0x7B1E, 0x7B35, 0x7B28, 0x7B36, 0x7B50,
+};
+const unsigned short euc_to_utf8_E4[] = {
+ 0x7B7A, 0x7B04, 0x7B4D, 0x7B0B, 0x7B4C, 0x7B45, 0x7B75,
+ 0x7B65, 0x7B74, 0x7B67, 0x7B70, 0x7B71, 0x7B6C, 0x7B6E, 0x7B9D,
+ 0x7B98, 0x7B9F, 0x7B8D, 0x7B9C, 0x7B9A, 0x7B8B, 0x7B92, 0x7B8F,
+ 0x7B5D, 0x7B99, 0x7BCB, 0x7BC1, 0x7BCC, 0x7BCF, 0x7BB4, 0x7BC6,
+ 0x7BDD, 0x7BE9, 0x7C11, 0x7C14, 0x7BE6, 0x7BE5, 0x7C60, 0x7C00,
+ 0x7C07, 0x7C13, 0x7BF3, 0x7BF7, 0x7C17, 0x7C0D, 0x7BF6, 0x7C23,
+ 0x7C27, 0x7C2A, 0x7C1F, 0x7C37, 0x7C2B, 0x7C3D, 0x7C4C, 0x7C43,
+ 0x7C54, 0x7C4F, 0x7C40, 0x7C50, 0x7C58, 0x7C5F, 0x7C64, 0x7C56,
+ 0x7C65, 0x7C6C, 0x7C75, 0x7C83, 0x7C90, 0x7CA4, 0x7CAD, 0x7CA2,
+ 0x7CAB, 0x7CA1, 0x7CA8, 0x7CB3, 0x7CB2, 0x7CB1, 0x7CAE, 0x7CB9,
+ 0x7CBD, 0x7CC0, 0x7CC5, 0x7CC2, 0x7CD8, 0x7CD2, 0x7CDC, 0x7CE2,
+ 0x9B3B, 0x7CEF, 0x7CF2, 0x7CF4, 0x7CF6, 0x7CFA, 0x7D06,
+};
+const unsigned short euc_to_utf8_E5[] = {
+ 0x7D02, 0x7D1C, 0x7D15, 0x7D0A, 0x7D45, 0x7D4B, 0x7D2E,
+ 0x7D32, 0x7D3F, 0x7D35, 0x7D46, 0x7D73, 0x7D56, 0x7D4E, 0x7D72,
+ 0x7D68, 0x7D6E, 0x7D4F, 0x7D63, 0x7D93, 0x7D89, 0x7D5B, 0x7D8F,
+ 0x7D7D, 0x7D9B, 0x7DBA, 0x7DAE, 0x7DA3, 0x7DB5, 0x7DC7, 0x7DBD,
+ 0x7DAB, 0x7E3D, 0x7DA2, 0x7DAF, 0x7DDC, 0x7DB8, 0x7D9F, 0x7DB0,
+ 0x7DD8, 0x7DDD, 0x7DE4, 0x7DDE, 0x7DFB, 0x7DF2, 0x7DE1, 0x7E05,
+ 0x7E0A, 0x7E23, 0x7E21, 0x7E12, 0x7E31, 0x7E1F, 0x7E09, 0x7E0B,
+ 0x7E22, 0x7E46, 0x7E66, 0x7E3B, 0x7E35, 0x7E39, 0x7E43, 0x7E37,
+ 0x7E32, 0x7E3A, 0x7E67, 0x7E5D, 0x7E56, 0x7E5E, 0x7E59, 0x7E5A,
+ 0x7E79, 0x7E6A, 0x7E69, 0x7E7C, 0x7E7B, 0x7E83, 0x7DD5, 0x7E7D,
+ 0x8FAE, 0x7E7F, 0x7E88, 0x7E89, 0x7E8C, 0x7E92, 0x7E90, 0x7E93,
+ 0x7E94, 0x7E96, 0x7E8E, 0x7E9B, 0x7E9C, 0x7F38, 0x7F3A,
+};
+const unsigned short euc_to_utf8_E6[] = {
+ 0x7F45, 0x7F4C, 0x7F4D, 0x7F4E, 0x7F50, 0x7F51, 0x7F55,
+ 0x7F54, 0x7F58, 0x7F5F, 0x7F60, 0x7F68, 0x7F69, 0x7F67, 0x7F78,
+ 0x7F82, 0x7F86, 0x7F83, 0x7F88, 0x7F87, 0x7F8C, 0x7F94, 0x7F9E,
+ 0x7F9D, 0x7F9A, 0x7FA3, 0x7FAF, 0x7FB2, 0x7FB9, 0x7FAE, 0x7FB6,
+ 0x7FB8, 0x8B71, 0x7FC5, 0x7FC6, 0x7FCA, 0x7FD5, 0x7FD4, 0x7FE1,
+ 0x7FE6, 0x7FE9, 0x7FF3, 0x7FF9, 0x98DC, 0x8006, 0x8004, 0x800B,
+ 0x8012, 0x8018, 0x8019, 0x801C, 0x8021, 0x8028, 0x803F, 0x803B,
+ 0x804A, 0x8046, 0x8052, 0x8058, 0x805A, 0x805F, 0x8062, 0x8068,
+ 0x8073, 0x8072, 0x8070, 0x8076, 0x8079, 0x807D, 0x807F, 0x8084,
+ 0x8086, 0x8085, 0x809B, 0x8093, 0x809A, 0x80AD, 0x5190, 0x80AC,
+ 0x80DB, 0x80E5, 0x80D9, 0x80DD, 0x80C4, 0x80DA, 0x80D6, 0x8109,
+ 0x80EF, 0x80F1, 0x811B, 0x8129, 0x8123, 0x812F, 0x814B,
+};
+const unsigned short euc_to_utf8_E7[] = {
+ 0x968B, 0x8146, 0x813E, 0x8153, 0x8151, 0x80FC, 0x8171,
+ 0x816E, 0x8165, 0x8166, 0x8174, 0x8183, 0x8188, 0x818A, 0x8180,
+ 0x8182, 0x81A0, 0x8195, 0x81A4, 0x81A3, 0x815F, 0x8193, 0x81A9,
+ 0x81B0, 0x81B5, 0x81BE, 0x81B8, 0x81BD, 0x81C0, 0x81C2, 0x81BA,
+ 0x81C9, 0x81CD, 0x81D1, 0x81D9, 0x81D8, 0x81C8, 0x81DA, 0x81DF,
+ 0x81E0, 0x81E7, 0x81FA, 0x81FB, 0x81FE, 0x8201, 0x8202, 0x8205,
+ 0x8207, 0x820A, 0x820D, 0x8210, 0x8216, 0x8229, 0x822B, 0x8238,
+ 0x8233, 0x8240, 0x8259, 0x8258, 0x825D, 0x825A, 0x825F, 0x8264,
+ 0x8262, 0x8268, 0x826A, 0x826B, 0x822E, 0x8271, 0x8277, 0x8278,
+ 0x827E, 0x828D, 0x8292, 0x82AB, 0x829F, 0x82BB, 0x82AC, 0x82E1,
+ 0x82E3, 0x82DF, 0x82D2, 0x82F4, 0x82F3, 0x82FA, 0x8393, 0x8303,
+ 0x82FB, 0x82F9, 0x82DE, 0x8306, 0x82DC, 0x8309, 0x82D9,
+};
+const unsigned short euc_to_utf8_E8[] = {
+ 0x8335, 0x8334, 0x8316, 0x8332, 0x8331, 0x8340, 0x8339,
+ 0x8350, 0x8345, 0x832F, 0x832B, 0x8317, 0x8318, 0x8385, 0x839A,
+ 0x83AA, 0x839F, 0x83A2, 0x8396, 0x8323, 0x838E, 0x8387, 0x838A,
+ 0x837C, 0x83B5, 0x8373, 0x8375, 0x83A0, 0x8389, 0x83A8, 0x83F4,
+ 0x8413, 0x83EB, 0x83CE, 0x83FD, 0x8403, 0x83D8, 0x840B, 0x83C1,
+ 0x83F7, 0x8407, 0x83E0, 0x83F2, 0x840D, 0x8422, 0x8420, 0x83BD,
+ 0x8438, 0x8506, 0x83FB, 0x846D, 0x842A, 0x843C, 0x855A, 0x8484,
+ 0x8477, 0x846B, 0x84AD, 0x846E, 0x8482, 0x8469, 0x8446, 0x842C,
+ 0x846F, 0x8479, 0x8435, 0x84CA, 0x8462, 0x84B9, 0x84BF, 0x849F,
+ 0x84D9, 0x84CD, 0x84BB, 0x84DA, 0x84D0, 0x84C1, 0x84C6, 0x84D6,
+ 0x84A1, 0x8521, 0x84FF, 0x84F4, 0x8517, 0x8518, 0x852C, 0x851F,
+ 0x8515, 0x8514, 0x84FC, 0x8540, 0x8563, 0x8558, 0x8548,
+};
+const unsigned short euc_to_utf8_E9[] = {
+ 0x8541, 0x8602, 0x854B, 0x8555, 0x8580, 0x85A4, 0x8588,
+ 0x8591, 0x858A, 0x85A8, 0x856D, 0x8594, 0x859B, 0x85EA, 0x8587,
+ 0x859C, 0x8577, 0x857E, 0x8590, 0x85C9, 0x85BA, 0x85CF, 0x85B9,
+ 0x85D0, 0x85D5, 0x85DD, 0x85E5, 0x85DC, 0x85F9, 0x860A, 0x8613,
+ 0x860B, 0x85FE, 0x85FA, 0x8606, 0x8622, 0x861A, 0x8630, 0x863F,
+ 0x864D, 0x4E55, 0x8654, 0x865F, 0x8667, 0x8671, 0x8693, 0x86A3,
+ 0x86A9, 0x86AA, 0x868B, 0x868C, 0x86B6, 0x86AF, 0x86C4, 0x86C6,
+ 0x86B0, 0x86C9, 0x8823, 0x86AB, 0x86D4, 0x86DE, 0x86E9, 0x86EC,
+ 0x86DF, 0x86DB, 0x86EF, 0x8712, 0x8706, 0x8708, 0x8700, 0x8703,
+ 0x86FB, 0x8711, 0x8709, 0x870D, 0x86F9, 0x870A, 0x8734, 0x873F,
+ 0x8737, 0x873B, 0x8725, 0x8729, 0x871A, 0x8760, 0x875F, 0x8778,
+ 0x874C, 0x874E, 0x8774, 0x8757, 0x8768, 0x876E, 0x8759,
+};
+const unsigned short euc_to_utf8_EA[] = {
+ 0x8753, 0x8763, 0x876A, 0x8805, 0x87A2, 0x879F, 0x8782,
+ 0x87AF, 0x87CB, 0x87BD, 0x87C0, 0x87D0, 0x96D6, 0x87AB, 0x87C4,
+ 0x87B3, 0x87C7, 0x87C6, 0x87BB, 0x87EF, 0x87F2, 0x87E0, 0x880F,
+ 0x880D, 0x87FE, 0x87F6, 0x87F7, 0x880E, 0x87D2, 0x8811, 0x8816,
+ 0x8815, 0x8822, 0x8821, 0x8831, 0x8836, 0x8839, 0x8827, 0x883B,
+ 0x8844, 0x8842, 0x8852, 0x8859, 0x885E, 0x8862, 0x886B, 0x8881,
+ 0x887E, 0x889E, 0x8875, 0x887D, 0x88B5, 0x8872, 0x8882, 0x8897,
+ 0x8892, 0x88AE, 0x8899, 0x88A2, 0x888D, 0x88A4, 0x88B0, 0x88BF,
+ 0x88B1, 0x88C3, 0x88C4, 0x88D4, 0x88D8, 0x88D9, 0x88DD, 0x88F9,
+ 0x8902, 0x88FC, 0x88F4, 0x88E8, 0x88F2, 0x8904, 0x890C, 0x890A,
+ 0x8913, 0x8943, 0x891E, 0x8925, 0x892A, 0x892B, 0x8941, 0x8944,
+ 0x893B, 0x8936, 0x8938, 0x894C, 0x891D, 0x8960, 0x895E,
+};
+const unsigned short euc_to_utf8_EB[] = {
+ 0x8966, 0x8964, 0x896D, 0x896A, 0x896F, 0x8974, 0x8977,
+ 0x897E, 0x8983, 0x8988, 0x898A, 0x8993, 0x8998, 0x89A1, 0x89A9,
+ 0x89A6, 0x89AC, 0x89AF, 0x89B2, 0x89BA, 0x89BD, 0x89BF, 0x89C0,
+ 0x89DA, 0x89DC, 0x89DD, 0x89E7, 0x89F4, 0x89F8, 0x8A03, 0x8A16,
+ 0x8A10, 0x8A0C, 0x8A1B, 0x8A1D, 0x8A25, 0x8A36, 0x8A41, 0x8A5B,
+ 0x8A52, 0x8A46, 0x8A48, 0x8A7C, 0x8A6D, 0x8A6C, 0x8A62, 0x8A85,
+ 0x8A82, 0x8A84, 0x8AA8, 0x8AA1, 0x8A91, 0x8AA5, 0x8AA6, 0x8A9A,
+ 0x8AA3, 0x8AC4, 0x8ACD, 0x8AC2, 0x8ADA, 0x8AEB, 0x8AF3, 0x8AE7,
+ 0x8AE4, 0x8AF1, 0x8B14, 0x8AE0, 0x8AE2, 0x8AF7, 0x8ADE, 0x8ADB,
+ 0x8B0C, 0x8B07, 0x8B1A, 0x8AE1, 0x8B16, 0x8B10, 0x8B17, 0x8B20,
+ 0x8B33, 0x97AB, 0x8B26, 0x8B2B, 0x8B3E, 0x8B28, 0x8B41, 0x8B4C,
+ 0x8B4F, 0x8B4E, 0x8B49, 0x8B56, 0x8B5B, 0x8B5A, 0x8B6B,
+};
+const unsigned short euc_to_utf8_EC[] = {
+ 0x8B5F, 0x8B6C, 0x8B6F, 0x8B74, 0x8B7D, 0x8B80, 0x8B8C,
+ 0x8B8E, 0x8B92, 0x8B93, 0x8B96, 0x8B99, 0x8B9A, 0x8C3A, 0x8C41,
+ 0x8C3F, 0x8C48, 0x8C4C, 0x8C4E, 0x8C50, 0x8C55, 0x8C62, 0x8C6C,
+ 0x8C78, 0x8C7A, 0x8C82, 0x8C89, 0x8C85, 0x8C8A, 0x8C8D, 0x8C8E,
+ 0x8C94, 0x8C7C, 0x8C98, 0x621D, 0x8CAD, 0x8CAA, 0x8CBD, 0x8CB2,
+ 0x8CB3, 0x8CAE, 0x8CB6, 0x8CC8, 0x8CC1, 0x8CE4, 0x8CE3, 0x8CDA,
+ 0x8CFD, 0x8CFA, 0x8CFB, 0x8D04, 0x8D05, 0x8D0A, 0x8D07, 0x8D0F,
+ 0x8D0D, 0x8D10, 0x9F4E, 0x8D13, 0x8CCD, 0x8D14, 0x8D16, 0x8D67,
+ 0x8D6D, 0x8D71, 0x8D73, 0x8D81, 0x8D99, 0x8DC2, 0x8DBE, 0x8DBA,
+ 0x8DCF, 0x8DDA, 0x8DD6, 0x8DCC, 0x8DDB, 0x8DCB, 0x8DEA, 0x8DEB,
+ 0x8DDF, 0x8DE3, 0x8DFC, 0x8E08, 0x8E09, 0x8DFF, 0x8E1D, 0x8E1E,
+ 0x8E10, 0x8E1F, 0x8E42, 0x8E35, 0x8E30, 0x8E34, 0x8E4A,
+};
+const unsigned short euc_to_utf8_ED[] = {
+ 0x8E47, 0x8E49, 0x8E4C, 0x8E50, 0x8E48, 0x8E59, 0x8E64,
+ 0x8E60, 0x8E2A, 0x8E63, 0x8E55, 0x8E76, 0x8E72, 0x8E7C, 0x8E81,
+ 0x8E87, 0x8E85, 0x8E84, 0x8E8B, 0x8E8A, 0x8E93, 0x8E91, 0x8E94,
+ 0x8E99, 0x8EAA, 0x8EA1, 0x8EAC, 0x8EB0, 0x8EC6, 0x8EB1, 0x8EBE,
+ 0x8EC5, 0x8EC8, 0x8ECB, 0x8EDB, 0x8EE3, 0x8EFC, 0x8EFB, 0x8EEB,
+ 0x8EFE, 0x8F0A, 0x8F05, 0x8F15, 0x8F12, 0x8F19, 0x8F13, 0x8F1C,
+ 0x8F1F, 0x8F1B, 0x8F0C, 0x8F26, 0x8F33, 0x8F3B, 0x8F39, 0x8F45,
+ 0x8F42, 0x8F3E, 0x8F4C, 0x8F49, 0x8F46, 0x8F4E, 0x8F57, 0x8F5C,
+ 0x8F62, 0x8F63, 0x8F64, 0x8F9C, 0x8F9F, 0x8FA3, 0x8FAD, 0x8FAF,
+ 0x8FB7, 0x8FDA, 0x8FE5, 0x8FE2, 0x8FEA, 0x8FEF, 0x9087, 0x8FF4,
+ 0x9005, 0x8FF9, 0x8FFA, 0x9011, 0x9015, 0x9021, 0x900D, 0x901E,
+ 0x9016, 0x900B, 0x9027, 0x9036, 0x9035, 0x9039, 0x8FF8,
+};
+const unsigned short euc_to_utf8_EE[] = {
+ 0x904F, 0x9050, 0x9051, 0x9052, 0x900E, 0x9049, 0x903E,
+ 0x9056, 0x9058, 0x905E, 0x9068, 0x906F, 0x9076, 0x96A8, 0x9072,
+ 0x9082, 0x907D, 0x9081, 0x9080, 0x908A, 0x9089, 0x908F, 0x90A8,
+ 0x90AF, 0x90B1, 0x90B5, 0x90E2, 0x90E4, 0x6248, 0x90DB, 0x9102,
+ 0x9112, 0x9119, 0x9132, 0x9130, 0x914A, 0x9156, 0x9158, 0x9163,
+ 0x9165, 0x9169, 0x9173, 0x9172, 0x918B, 0x9189, 0x9182, 0x91A2,
+ 0x91AB, 0x91AF, 0x91AA, 0x91B5, 0x91B4, 0x91BA, 0x91C0, 0x91C1,
+ 0x91C9, 0x91CB, 0x91D0, 0x91D6, 0x91DF, 0x91E1, 0x91DB, 0x91FC,
+ 0x91F5, 0x91F6, 0x921E, 0x91FF, 0x9214, 0x922C, 0x9215, 0x9211,
+ 0x925E, 0x9257, 0x9245, 0x9249, 0x9264, 0x9248, 0x9295, 0x923F,
+ 0x924B, 0x9250, 0x929C, 0x9296, 0x9293, 0x929B, 0x925A, 0x92CF,
+ 0x92B9, 0x92B7, 0x92E9, 0x930F, 0x92FA, 0x9344, 0x932E,
+};
+const unsigned short euc_to_utf8_EF[] = {
+ 0x9319, 0x9322, 0x931A, 0x9323, 0x933A, 0x9335, 0x933B,
+ 0x935C, 0x9360, 0x937C, 0x936E, 0x9356, 0x93B0, 0x93AC, 0x93AD,
+ 0x9394, 0x93B9, 0x93D6, 0x93D7, 0x93E8, 0x93E5, 0x93D8, 0x93C3,
+ 0x93DD, 0x93D0, 0x93C8, 0x93E4, 0x941A, 0x9414, 0x9413, 0x9403,
+ 0x9407, 0x9410, 0x9436, 0x942B, 0x9435, 0x9421, 0x943A, 0x9441,
+ 0x9452, 0x9444, 0x945B, 0x9460, 0x9462, 0x945E, 0x946A, 0x9229,
+ 0x9470, 0x9475, 0x9477, 0x947D, 0x945A, 0x947C, 0x947E, 0x9481,
+ 0x947F, 0x9582, 0x9587, 0x958A, 0x9594, 0x9596, 0x9598, 0x9599,
+ 0x95A0, 0x95A8, 0x95A7, 0x95AD, 0x95BC, 0x95BB, 0x95B9, 0x95BE,
+ 0x95CA, 0x6FF6, 0x95C3, 0x95CD, 0x95CC, 0x95D5, 0x95D4, 0x95D6,
+ 0x95DC, 0x95E1, 0x95E5, 0x95E2, 0x9621, 0x9628, 0x962E, 0x962F,
+ 0x9642, 0x964C, 0x964F, 0x964B, 0x9677, 0x965C, 0x965E,
+};
+const unsigned short euc_to_utf8_F0[] = {
+ 0x965D, 0x965F, 0x9666, 0x9672, 0x966C, 0x968D, 0x9698,
+ 0x9695, 0x9697, 0x96AA, 0x96A7, 0x96B1, 0x96B2, 0x96B0, 0x96B4,
+ 0x96B6, 0x96B8, 0x96B9, 0x96CE, 0x96CB, 0x96C9, 0x96CD, 0x894D,
+ 0x96DC, 0x970D, 0x96D5, 0x96F9, 0x9704, 0x9706, 0x9708, 0x9713,
+ 0x970E, 0x9711, 0x970F, 0x9716, 0x9719, 0x9724, 0x972A, 0x9730,
+ 0x9739, 0x973D, 0x973E, 0x9744, 0x9746, 0x9748, 0x9742, 0x9749,
+ 0x975C, 0x9760, 0x9764, 0x9766, 0x9768, 0x52D2, 0x976B, 0x9771,
+ 0x9779, 0x9785, 0x977C, 0x9781, 0x977A, 0x9786, 0x978B, 0x978F,
+ 0x9790, 0x979C, 0x97A8, 0x97A6, 0x97A3, 0x97B3, 0x97B4, 0x97C3,
+ 0x97C6, 0x97C8, 0x97CB, 0x97DC, 0x97ED, 0x9F4F, 0x97F2, 0x7ADF,
+ 0x97F6, 0x97F5, 0x980F, 0x980C, 0x9838, 0x9824, 0x9821, 0x9837,
+ 0x983D, 0x9846, 0x984F, 0x984B, 0x986B, 0x986F, 0x9870,
+};
+const unsigned short euc_to_utf8_F1[] = {
+ 0x9871, 0x9874, 0x9873, 0x98AA, 0x98AF, 0x98B1, 0x98B6,
+ 0x98C4, 0x98C3, 0x98C6, 0x98E9, 0x98EB, 0x9903, 0x9909, 0x9912,
+ 0x9914, 0x9918, 0x9921, 0x991D, 0x991E, 0x9924, 0x9920, 0x992C,
+ 0x992E, 0x993D, 0x993E, 0x9942, 0x9949, 0x9945, 0x9950, 0x994B,
+ 0x9951, 0x9952, 0x994C, 0x9955, 0x9997, 0x9998, 0x99A5, 0x99AD,
+ 0x99AE, 0x99BC, 0x99DF, 0x99DB, 0x99DD, 0x99D8, 0x99D1, 0x99ED,
+ 0x99EE, 0x99F1, 0x99F2, 0x99FB, 0x99F8, 0x9A01, 0x9A0F, 0x9A05,
+ 0x99E2, 0x9A19, 0x9A2B, 0x9A37, 0x9A45, 0x9A42, 0x9A40, 0x9A43,
+ 0x9A3E, 0x9A55, 0x9A4D, 0x9A5B, 0x9A57, 0x9A5F, 0x9A62, 0x9A65,
+ 0x9A64, 0x9A69, 0x9A6B, 0x9A6A, 0x9AAD, 0x9AB0, 0x9ABC, 0x9AC0,
+ 0x9ACF, 0x9AD1, 0x9AD3, 0x9AD4, 0x9ADE, 0x9ADF, 0x9AE2, 0x9AE3,
+ 0x9AE6, 0x9AEF, 0x9AEB, 0x9AEE, 0x9AF4, 0x9AF1, 0x9AF7,
+};
+const unsigned short euc_to_utf8_F2[] = {
+ 0x9AFB, 0x9B06, 0x9B18, 0x9B1A, 0x9B1F, 0x9B22, 0x9B23,
+ 0x9B25, 0x9B27, 0x9B28, 0x9B29, 0x9B2A, 0x9B2E, 0x9B2F, 0x9B32,
+ 0x9B44, 0x9B43, 0x9B4F, 0x9B4D, 0x9B4E, 0x9B51, 0x9B58, 0x9B74,
+ 0x9B93, 0x9B83, 0x9B91, 0x9B96, 0x9B97, 0x9B9F, 0x9BA0, 0x9BA8,
+ 0x9BB4, 0x9BC0, 0x9BCA, 0x9BB9, 0x9BC6, 0x9BCF, 0x9BD1, 0x9BD2,
+ 0x9BE3, 0x9BE2, 0x9BE4, 0x9BD4, 0x9BE1, 0x9C3A, 0x9BF2, 0x9BF1,
+ 0x9BF0, 0x9C15, 0x9C14, 0x9C09, 0x9C13, 0x9C0C, 0x9C06, 0x9C08,
+ 0x9C12, 0x9C0A, 0x9C04, 0x9C2E, 0x9C1B, 0x9C25, 0x9C24, 0x9C21,
+ 0x9C30, 0x9C47, 0x9C32, 0x9C46, 0x9C3E, 0x9C5A, 0x9C60, 0x9C67,
+ 0x9C76, 0x9C78, 0x9CE7, 0x9CEC, 0x9CF0, 0x9D09, 0x9D08, 0x9CEB,
+ 0x9D03, 0x9D06, 0x9D2A, 0x9D26, 0x9DAF, 0x9D23, 0x9D1F, 0x9D44,
+ 0x9D15, 0x9D12, 0x9D41, 0x9D3F, 0x9D3E, 0x9D46, 0x9D48,
+};
+const unsigned short euc_to_utf8_F3[] = {
+ 0x9D5D, 0x9D5E, 0x9D64, 0x9D51, 0x9D50, 0x9D59, 0x9D72,
+ 0x9D89, 0x9D87, 0x9DAB, 0x9D6F, 0x9D7A, 0x9D9A, 0x9DA4, 0x9DA9,
+ 0x9DB2, 0x9DC4, 0x9DC1, 0x9DBB, 0x9DB8, 0x9DBA, 0x9DC6, 0x9DCF,
+ 0x9DC2, 0x9DD9, 0x9DD3, 0x9DF8, 0x9DE6, 0x9DED, 0x9DEF, 0x9DFD,
+ 0x9E1A, 0x9E1B, 0x9E1E, 0x9E75, 0x9E79, 0x9E7D, 0x9E81, 0x9E88,
+ 0x9E8B, 0x9E8C, 0x9E92, 0x9E95, 0x9E91, 0x9E9D, 0x9EA5, 0x9EA9,
+ 0x9EB8, 0x9EAA, 0x9EAD, 0x9761, 0x9ECC, 0x9ECE, 0x9ECF, 0x9ED0,
+ 0x9ED4, 0x9EDC, 0x9EDE, 0x9EDD, 0x9EE0, 0x9EE5, 0x9EE8, 0x9EEF,
+ 0x9EF4, 0x9EF6, 0x9EF7, 0x9EF9, 0x9EFB, 0x9EFC, 0x9EFD, 0x9F07,
+ 0x9F08, 0x76B7, 0x9F15, 0x9F21, 0x9F2C, 0x9F3E, 0x9F4A, 0x9F52,
+ 0x9F54, 0x9F63, 0x9F5F, 0x9F60, 0x9F61, 0x9F66, 0x9F67, 0x9F6C,
+ 0x9F6A, 0x9F77, 0x9F72, 0x9F76, 0x9F95, 0x9F9C, 0x9FA0,
+};
+const unsigned short euc_to_utf8_F4[] = {
+ 0x582F, 0x69C7, 0x9059, 0x7464, 0x51DC, 0x7199, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_F5[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFE33, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFE31, 0, 0,
+ 0, 0, 0, 0, 0, 0xFE30, 0, 0,
+ 0, 0, 0xFE35, 0xFE36, 0xFE39, 0xFE3A, 0, 0,
+ 0xFE37, 0xFE38, 0xFE3F, 0xFE40, 0xFE3D, 0xFE3E, 0xFE41, 0xFE42,
+ 0xFE43, 0xFE44, 0xFE3B, 0xFE3C, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_F9[] = {
+ 0x7E8A, 0x891C, 0x9348, 0x9288, 0x84DC, 0x4FC9, 0x70BB,
+ 0x6631, 0x68C8, 0x92F9, 0x66FB, 0x5F45, 0x4E28, 0x4EE1, 0x4EFC,
+ 0x4F00, 0x4F03, 0x4F39, 0x4F56, 0x4F92, 0x4F8A, 0x4F9A, 0x4F94,
+ 0x4FCD, 0x5040, 0x5022, 0x4FFF, 0x501E, 0x5046, 0x5070, 0x5042,
+ 0x5094, 0x50F4, 0x50D8, 0x514A, 0x5164, 0x519D, 0x51BE, 0x51EC,
+ 0x5215, 0x529C, 0x52A6, 0x52C0, 0x52DB, 0x5300, 0x5307, 0x5324,
+ 0x5372, 0x5393, 0x53B2, 0x53DD, 0xFA0E, 0x549C, 0x548A, 0x54A9,
+ 0x54FF, 0x5586, 0x5759, 0x5765, 0x57AC, 0x57C8, 0x57C7, 0xFA0F,
+ 0xFA10, 0x589E, 0x58B2, 0x590B, 0x5953, 0x595B, 0x595D, 0x5963,
+ 0x59A4, 0x59BA, 0x5B56, 0x5BC0, 0x752F, 0x5BD8, 0x5BEC, 0x5C1E,
+ 0x5CA6, 0x5CBA, 0x5CF5, 0x5D27, 0x5D53, 0xFA11, 0x5D42, 0x5D6D,
+ 0x5DB8, 0x5DB9, 0x5DD0, 0x5F21, 0x5F34, 0x5F67, 0x5FB7,
+};
+const unsigned short euc_to_utf8_FA[] = {
+ 0x5FDE, 0x605D, 0x6085, 0x608A, 0x60DE, 0x60D5, 0x6120,
+ 0x60F2, 0x6111, 0x6137, 0x6130, 0x6198, 0x6213, 0x62A6, 0x63F5,
+ 0x6460, 0x649D, 0x64CE, 0x654E, 0x6600, 0x6615, 0x663B, 0x6609,
+ 0x662E, 0x661E, 0x6624, 0x6665, 0x6657, 0x6659, 0xFA12, 0x6673,
+ 0x6699, 0x66A0, 0x66B2, 0x66BF, 0x66FA, 0x670E, 0xF929, 0x6766,
+ 0x67BB, 0x6852, 0x67C0, 0x6801, 0x6844, 0x68CF, 0xFA13, 0x6968,
+ 0xFA14, 0x6998, 0x69E2, 0x6A30, 0x6A6B, 0x6A46, 0x6A73, 0x6A7E,
+ 0x6AE2, 0x6AE4, 0x6BD6, 0x6C3F, 0x6C5C, 0x6C86, 0x6C6F, 0x6CDA,
+ 0x6D04, 0x6D87, 0x6D6F, 0x6D96, 0x6DAC, 0x6DCF, 0x6DF8, 0x6DF2,
+ 0x6DFC, 0x6E39, 0x6E5C, 0x6E27, 0x6E3C, 0x6EBF, 0x6F88, 0x6FB5,
+ 0x6FF5, 0x7005, 0x7007, 0x7028, 0x7085, 0x70AB, 0x710F, 0x7104,
+ 0x715C, 0x7146, 0x7147, 0xFA15, 0x71C1, 0x71FE, 0x72B1,
+};
+const unsigned short euc_to_utf8_FB[] = {
+ 0x72BE, 0x7324, 0xFA16, 0x7377, 0x73BD, 0x73C9, 0x73D6,
+ 0x73E3, 0x73D2, 0x7407, 0x73F5, 0x7426, 0x742A, 0x7429, 0x742E,
+ 0x7462, 0x7489, 0x749F, 0x7501, 0x756F, 0x7682, 0x769C, 0x769E,
+ 0x769B, 0x76A6, 0xFA17, 0x7746, 0x52AF, 0x7821, 0x784E, 0x7864,
+ 0x787A, 0x7930, 0xFA18, 0xFA19, 0xFA1A, 0x7994, 0xFA1B, 0x799B,
+ 0x7AD1, 0x7AE7, 0xFA1C, 0x7AEB, 0x7B9E, 0xFA1D, 0x7D48, 0x7D5C,
+ 0x7DB7, 0x7DA0, 0x7DD6, 0x7E52, 0x7F47, 0x7FA1, 0xFA1E, 0x8301,
+ 0x8362, 0x837F, 0x83C7, 0x83F6, 0x8448, 0x84B4, 0x8553, 0x8559,
+ 0x856B, 0xFA1F, 0x85B0, 0xFA20, 0xFA21, 0x8807, 0x88F5, 0x8A12,
+ 0x8A37, 0x8A79, 0x8AA7, 0x8ABE, 0x8ADF, 0xFA22, 0x8AF6, 0x8B53,
+ 0x8B7F, 0x8CF0, 0x8CF4, 0x8D12, 0x8D76, 0xFA23, 0x8ECF, 0xFA24,
+ 0xFA25, 0x9067, 0x90DE, 0xFA26, 0x9115, 0x9127, 0x91DA,
+};
+const unsigned short euc_to_utf8_FC[] = {
+ 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206,
+ 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251,
+ 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9,
+ 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB,
+ 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4,
+ 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC,
+ 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F,
+ 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C,
+ 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1,
+ 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0,
+ 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176,
+ 0x2177, 0x2178, 0x2179, 0xFFE2, 0x00A6, 0xFF07, 0xFF02,
+};
+
+/* Microsoft UCS Mapping Compatible */
+const unsigned short euc_to_utf8_FC_ms[] = {
+ 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206,
+ 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251,
+ 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9,
+ 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB,
+ 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4,
+ 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC,
+ 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F,
+ 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C,
+ 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1,
+ 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0,
+ 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176,
+ 0x2177, 0x2178, 0x2179, 0xFFE2, 0xFFE4, 0xFF07, 0xFF02,
+};
+
+#ifdef X0212_ENABLE
+const unsigned short euc_to_utf8_8FA2[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x02D8,
+ 0x02C7, 0x00B8, 0x02D9, 0x02DD, 0x00AF, 0x02DB, 0x02DA, 0xFF5E,
+ 0x0384, 0x0385, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x00A1, 0xFFE4, 0x00BF, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x00BA, 0x00AA, 0x00A9, 0x00AE, 0x2122,
+ 0x00A4, 0x2116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_8FA6[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x0386, 0x0388, 0x0389, 0x038A, 0x03AA, 0, 0x038C,
+ 0, 0x038E, 0x03AB, 0, 0x038F, 0, 0, 0,
+ 0, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03CA, 0x0390, 0x03CC,
+ 0x03C2, 0x03CD, 0x03CB, 0x03B0, 0x03CE, 0, 0,
+};
+const unsigned short euc_to_utf8_8FA7[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+ 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045E, 0x045F,
+};
+const unsigned short euc_to_utf8_8FA9[] = {
+ 0x00C6, 0x0110, 0, 0x0126, 0, 0x0132, 0,
+ 0x0141, 0x013F, 0, 0x014A, 0x00D8, 0x0152, 0, 0x0166,
+ 0x00DE, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x00E6, 0x0111, 0x00F0, 0x0127, 0x0131, 0x0133, 0x0138,
+ 0x0142, 0x0140, 0x0149, 0x014B, 0x00F8, 0x0153, 0x00DF, 0x0167,
+ 0x00FE, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_8FAA[] = {
+ 0x00C1, 0x00C0, 0x00C4, 0x00C2, 0x0102, 0x01CD, 0x0100,
+ 0x0104, 0x00C5, 0x00C3, 0x0106, 0x0108, 0x010C, 0x00C7, 0x010A,
+ 0x010E, 0x00C9, 0x00C8, 0x00CB, 0x00CA, 0x011A, 0x0116, 0x0112,
+ 0x0118, 0, 0x011C, 0x011E, 0x0122, 0x0120, 0x0124, 0x00CD,
+ 0x00CC, 0x00CF, 0x00CE, 0x01CF, 0x0130, 0x012A, 0x012E, 0x0128,
+ 0x0134, 0x0136, 0x0139, 0x013D, 0x013B, 0x0143, 0x0147, 0x0145,
+ 0x00D1, 0x00D3, 0x00D2, 0x00D6, 0x00D4, 0x01D1, 0x0150, 0x014C,
+ 0x00D5, 0x0154, 0x0158, 0x0156, 0x015A, 0x015C, 0x0160, 0x015E,
+ 0x0164, 0x0162, 0x00DA, 0x00D9, 0x00DC, 0x00DB, 0x016C, 0x01D3,
+ 0x0170, 0x016A, 0x0172, 0x016E, 0x0168, 0x01D7, 0x01DB, 0x01D9,
+ 0x01D5, 0x0174, 0x00DD, 0x0178, 0x0176, 0x0179, 0x017D, 0x017B,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_8FAB[] = {
+ 0x00E1, 0x00E0, 0x00E4, 0x00E2, 0x0103, 0x01CE, 0x0101,
+ 0x0105, 0x00E5, 0x00E3, 0x0107, 0x0109, 0x010D, 0x00E7, 0x010B,
+ 0x010F, 0x00E9, 0x00E8, 0x00EB, 0x00EA, 0x011B, 0x0117, 0x0113,
+ 0x0119, 0x01F5, 0x011D, 0x011F, 0, 0x0121, 0x0125, 0x00ED,
+ 0x00EC, 0x00EF, 0x00EE, 0x01D0, 0, 0x012B, 0x012F, 0x0129,
+ 0x0135, 0x0137, 0x013A, 0x013E, 0x013C, 0x0144, 0x0148, 0x0146,
+ 0x00F1, 0x00F3, 0x00F2, 0x00F6, 0x00F4, 0x01D2, 0x0151, 0x014D,
+ 0x00F5, 0x0155, 0x0159, 0x0157, 0x015B, 0x015D, 0x0161, 0x015F,
+ 0x0165, 0x0163, 0x00FA, 0x00F9, 0x00FC, 0x00FB, 0x016D, 0x01D4,
+ 0x0171, 0x016B, 0x0173, 0x016F, 0x0169, 0x01D8, 0x01DC, 0x01DA,
+ 0x01D6, 0x0175, 0x00FD, 0x00FF, 0x0177, 0x017A, 0x017E, 0x017C,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_8FB0[] = {
+ 0x4E02, 0x4E04, 0x4E05, 0x4E0C, 0x4E12, 0x4E1F, 0x4E23,
+ 0x4E24, 0x4E28, 0x4E2B, 0x4E2E, 0x4E2F, 0x4E30, 0x4E35, 0x4E40,
+ 0x4E41, 0x4E44, 0x4E47, 0x4E51, 0x4E5A, 0x4E5C, 0x4E63, 0x4E68,
+ 0x4E69, 0x4E74, 0x4E75, 0x4E79, 0x4E7F, 0x4E8D, 0x4E96, 0x4E97,
+ 0x4E9D, 0x4EAF, 0x4EB9, 0x4EC3, 0x4ED0, 0x4EDA, 0x4EDB, 0x4EE0,
+ 0x4EE1, 0x4EE2, 0x4EE8, 0x4EEF, 0x4EF1, 0x4EF3, 0x4EF5, 0x4EFD,
+ 0x4EFE, 0x4EFF, 0x4F00, 0x4F02, 0x4F03, 0x4F08, 0x4F0B, 0x4F0C,
+ 0x4F12, 0x4F15, 0x4F16, 0x4F17, 0x4F19, 0x4F2E, 0x4F31, 0x4F60,
+ 0x4F33, 0x4F35, 0x4F37, 0x4F39, 0x4F3B, 0x4F3E, 0x4F40, 0x4F42,
+ 0x4F48, 0x4F49, 0x4F4B, 0x4F4C, 0x4F52, 0x4F54, 0x4F56, 0x4F58,
+ 0x4F5F, 0x4F63, 0x4F6A, 0x4F6C, 0x4F6E, 0x4F71, 0x4F77, 0x4F78,
+ 0x4F79, 0x4F7A, 0x4F7D, 0x4F7E, 0x4F81, 0x4F82, 0x4F84,
+};
+const unsigned short euc_to_utf8_8FB1[] = {
+ 0x4F85, 0x4F89, 0x4F8A, 0x4F8C, 0x4F8E, 0x4F90, 0x4F92,
+ 0x4F93, 0x4F94, 0x4F97, 0x4F99, 0x4F9A, 0x4F9E, 0x4F9F, 0x4FB2,
+ 0x4FB7, 0x4FB9, 0x4FBB, 0x4FBC, 0x4FBD, 0x4FBE, 0x4FC0, 0x4FC1,
+ 0x4FC5, 0x4FC6, 0x4FC8, 0x4FC9, 0x4FCB, 0x4FCC, 0x4FCD, 0x4FCF,
+ 0x4FD2, 0x4FDC, 0x4FE0, 0x4FE2, 0x4FF0, 0x4FF2, 0x4FFC, 0x4FFD,
+ 0x4FFF, 0x5000, 0x5001, 0x5004, 0x5007, 0x500A, 0x500C, 0x500E,
+ 0x5010, 0x5013, 0x5017, 0x5018, 0x501B, 0x501C, 0x501D, 0x501E,
+ 0x5022, 0x5027, 0x502E, 0x5030, 0x5032, 0x5033, 0x5035, 0x5040,
+ 0x5041, 0x5042, 0x5045, 0x5046, 0x504A, 0x504C, 0x504E, 0x5051,
+ 0x5052, 0x5053, 0x5057, 0x5059, 0x505F, 0x5060, 0x5062, 0x5063,
+ 0x5066, 0x5067, 0x506A, 0x506D, 0x5070, 0x5071, 0x503B, 0x5081,
+ 0x5083, 0x5084, 0x5086, 0x508A, 0x508E, 0x508F, 0x5090,
+};
+const unsigned short euc_to_utf8_8FB2[] = {
+ 0x5092, 0x5093, 0x5094, 0x5096, 0x509B, 0x509C, 0x509E,
+ 0x509F, 0x50A0, 0x50A1, 0x50A2, 0x50AA, 0x50AF, 0x50B0, 0x50B9,
+ 0x50BA, 0x50BD, 0x50C0, 0x50C3, 0x50C4, 0x50C7, 0x50CC, 0x50CE,
+ 0x50D0, 0x50D3, 0x50D4, 0x50D8, 0x50DC, 0x50DD, 0x50DF, 0x50E2,
+ 0x50E4, 0x50E6, 0x50E8, 0x50E9, 0x50EF, 0x50F1, 0x50F6, 0x50FA,
+ 0x50FE, 0x5103, 0x5106, 0x5107, 0x5108, 0x510B, 0x510C, 0x510D,
+ 0x510E, 0x50F2, 0x5110, 0x5117, 0x5119, 0x511B, 0x511C, 0x511D,
+ 0x511E, 0x5123, 0x5127, 0x5128, 0x512C, 0x512D, 0x512F, 0x5131,
+ 0x5133, 0x5134, 0x5135, 0x5138, 0x5139, 0x5142, 0x514A, 0x514F,
+ 0x5153, 0x5155, 0x5157, 0x5158, 0x515F, 0x5164, 0x5166, 0x517E,
+ 0x5183, 0x5184, 0x518B, 0x518E, 0x5198, 0x519D, 0x51A1, 0x51A3,
+ 0x51AD, 0x51B8, 0x51BA, 0x51BC, 0x51BE, 0x51BF, 0x51C2,
+};
+const unsigned short euc_to_utf8_8FB3[] = {
+ 0x51C8, 0x51CF, 0x51D1, 0x51D2, 0x51D3, 0x51D5, 0x51D8,
+ 0x51DE, 0x51E2, 0x51E5, 0x51EE, 0x51F2, 0x51F3, 0x51F4, 0x51F7,
+ 0x5201, 0x5202, 0x5205, 0x5212, 0x5213, 0x5215, 0x5216, 0x5218,
+ 0x5222, 0x5228, 0x5231, 0x5232, 0x5235, 0x523C, 0x5245, 0x5249,
+ 0x5255, 0x5257, 0x5258, 0x525A, 0x525C, 0x525F, 0x5260, 0x5261,
+ 0x5266, 0x526E, 0x5277, 0x5278, 0x5279, 0x5280, 0x5282, 0x5285,
+ 0x528A, 0x528C, 0x5293, 0x5295, 0x5296, 0x5297, 0x5298, 0x529A,
+ 0x529C, 0x52A4, 0x52A5, 0x52A6, 0x52A7, 0x52AF, 0x52B0, 0x52B6,
+ 0x52B7, 0x52B8, 0x52BA, 0x52BB, 0x52BD, 0x52C0, 0x52C4, 0x52C6,
+ 0x52C8, 0x52CC, 0x52CF, 0x52D1, 0x52D4, 0x52D6, 0x52DB, 0x52DC,
+ 0x52E1, 0x52E5, 0x52E8, 0x52E9, 0x52EA, 0x52EC, 0x52F0, 0x52F1,
+ 0x52F4, 0x52F6, 0x52F7, 0x5300, 0x5303, 0x530A, 0x530B,
+};
+const unsigned short euc_to_utf8_8FB4[] = {
+ 0x530C, 0x5311, 0x5313, 0x5318, 0x531B, 0x531C, 0x531E,
+ 0x531F, 0x5325, 0x5327, 0x5328, 0x5329, 0x532B, 0x532C, 0x532D,
+ 0x5330, 0x5332, 0x5335, 0x533C, 0x533D, 0x533E, 0x5342, 0x534C,
+ 0x534B, 0x5359, 0x535B, 0x5361, 0x5363, 0x5365, 0x536C, 0x536D,
+ 0x5372, 0x5379, 0x537E, 0x5383, 0x5387, 0x5388, 0x538E, 0x5393,
+ 0x5394, 0x5399, 0x539D, 0x53A1, 0x53A4, 0x53AA, 0x53AB, 0x53AF,
+ 0x53B2, 0x53B4, 0x53B5, 0x53B7, 0x53B8, 0x53BA, 0x53BD, 0x53C0,
+ 0x53C5, 0x53CF, 0x53D2, 0x53D3, 0x53D5, 0x53DA, 0x53DD, 0x53DE,
+ 0x53E0, 0x53E6, 0x53E7, 0x53F5, 0x5402, 0x5413, 0x541A, 0x5421,
+ 0x5427, 0x5428, 0x542A, 0x542F, 0x5431, 0x5434, 0x5435, 0x5443,
+ 0x5444, 0x5447, 0x544D, 0x544F, 0x545E, 0x5462, 0x5464, 0x5466,
+ 0x5467, 0x5469, 0x546B, 0x546D, 0x546E, 0x5474, 0x547F,
+};
+const unsigned short euc_to_utf8_8FB5[] = {
+ 0x5481, 0x5483, 0x5485, 0x5488, 0x5489, 0x548D, 0x5491,
+ 0x5495, 0x5496, 0x549C, 0x549F, 0x54A1, 0x54A6, 0x54A7, 0x54A9,
+ 0x54AA, 0x54AD, 0x54AE, 0x54B1, 0x54B7, 0x54B9, 0x54BA, 0x54BB,
+ 0x54BF, 0x54C6, 0x54CA, 0x54CD, 0x54CE, 0x54E0, 0x54EA, 0x54EC,
+ 0x54EF, 0x54F6, 0x54FC, 0x54FE, 0x54FF, 0x5500, 0x5501, 0x5505,
+ 0x5508, 0x5509, 0x550C, 0x550D, 0x550E, 0x5515, 0x552A, 0x552B,
+ 0x5532, 0x5535, 0x5536, 0x553B, 0x553C, 0x553D, 0x5541, 0x5547,
+ 0x5549, 0x554A, 0x554D, 0x5550, 0x5551, 0x5558, 0x555A, 0x555B,
+ 0x555E, 0x5560, 0x5561, 0x5564, 0x5566, 0x557F, 0x5581, 0x5582,
+ 0x5586, 0x5588, 0x558E, 0x558F, 0x5591, 0x5592, 0x5593, 0x5594,
+ 0x5597, 0x55A3, 0x55A4, 0x55AD, 0x55B2, 0x55BF, 0x55C1, 0x55C3,
+ 0x55C6, 0x55C9, 0x55CB, 0x55CC, 0x55CE, 0x55D1, 0x55D2,
+};
+const unsigned short euc_to_utf8_8FB6[] = {
+ 0x55D3, 0x55D7, 0x55D8, 0x55DB, 0x55DE, 0x55E2, 0x55E9,
+ 0x55F6, 0x55FF, 0x5605, 0x5608, 0x560A, 0x560D, 0x560E, 0x560F,
+ 0x5610, 0x5611, 0x5612, 0x5619, 0x562C, 0x5630, 0x5633, 0x5635,
+ 0x5637, 0x5639, 0x563B, 0x563C, 0x563D, 0x563F, 0x5640, 0x5641,
+ 0x5643, 0x5644, 0x5646, 0x5649, 0x564B, 0x564D, 0x564F, 0x5654,
+ 0x565E, 0x5660, 0x5661, 0x5662, 0x5663, 0x5666, 0x5669, 0x566D,
+ 0x566F, 0x5671, 0x5672, 0x5675, 0x5684, 0x5685, 0x5688, 0x568B,
+ 0x568C, 0x5695, 0x5699, 0x569A, 0x569D, 0x569E, 0x569F, 0x56A6,
+ 0x56A7, 0x56A8, 0x56A9, 0x56AB, 0x56AC, 0x56AD, 0x56B1, 0x56B3,
+ 0x56B7, 0x56BE, 0x56C5, 0x56C9, 0x56CA, 0x56CB, 0x56CF, 0x56D0,
+ 0x56CC, 0x56CD, 0x56D9, 0x56DC, 0x56DD, 0x56DF, 0x56E1, 0x56E4,
+ 0x56E5, 0x56E6, 0x56E7, 0x56E8, 0x56F1, 0x56EB, 0x56ED,
+};
+const unsigned short euc_to_utf8_8FB7[] = {
+ 0x56F6, 0x56F7, 0x5701, 0x5702, 0x5707, 0x570A, 0x570C,
+ 0x5711, 0x5715, 0x571A, 0x571B, 0x571D, 0x5720, 0x5722, 0x5723,
+ 0x5724, 0x5725, 0x5729, 0x572A, 0x572C, 0x572E, 0x572F, 0x5733,
+ 0x5734, 0x573D, 0x573E, 0x573F, 0x5745, 0x5746, 0x574C, 0x574D,
+ 0x5752, 0x5762, 0x5765, 0x5767, 0x5768, 0x576B, 0x576D, 0x576E,
+ 0x576F, 0x5770, 0x5771, 0x5773, 0x5774, 0x5775, 0x5777, 0x5779,
+ 0x577A, 0x577B, 0x577C, 0x577E, 0x5781, 0x5783, 0x578C, 0x5794,
+ 0x5797, 0x5799, 0x579A, 0x579C, 0x579D, 0x579E, 0x579F, 0x57A1,
+ 0x5795, 0x57A7, 0x57A8, 0x57A9, 0x57AC, 0x57B8, 0x57BD, 0x57C7,
+ 0x57C8, 0x57CC, 0x57CF, 0x57D5, 0x57DD, 0x57DE, 0x57E4, 0x57E6,
+ 0x57E7, 0x57E9, 0x57ED, 0x57F0, 0x57F5, 0x57F6, 0x57F8, 0x57FD,
+ 0x57FE, 0x57FF, 0x5803, 0x5804, 0x5808, 0x5809, 0x57E1,
+};
+const unsigned short euc_to_utf8_8FB8[] = {
+ 0x580C, 0x580D, 0x581B, 0x581E, 0x581F, 0x5820, 0x5826,
+ 0x5827, 0x582D, 0x5832, 0x5839, 0x583F, 0x5849, 0x584C, 0x584D,
+ 0x584F, 0x5850, 0x5855, 0x585F, 0x5861, 0x5864, 0x5867, 0x5868,
+ 0x5878, 0x587C, 0x587F, 0x5880, 0x5881, 0x5887, 0x5888, 0x5889,
+ 0x588A, 0x588C, 0x588D, 0x588F, 0x5890, 0x5894, 0x5896, 0x589D,
+ 0x58A0, 0x58A1, 0x58A2, 0x58A6, 0x58A9, 0x58B1, 0x58B2, 0x58C4,
+ 0x58BC, 0x58C2, 0x58C8, 0x58CD, 0x58CE, 0x58D0, 0x58D2, 0x58D4,
+ 0x58D6, 0x58DA, 0x58DD, 0x58E1, 0x58E2, 0x58E9, 0x58F3, 0x5905,
+ 0x5906, 0x590B, 0x590C, 0x5912, 0x5913, 0x5914, 0x8641, 0x591D,
+ 0x5921, 0x5923, 0x5924, 0x5928, 0x592F, 0x5930, 0x5933, 0x5935,
+ 0x5936, 0x593F, 0x5943, 0x5946, 0x5952, 0x5953, 0x5959, 0x595B,
+ 0x595D, 0x595E, 0x595F, 0x5961, 0x5963, 0x596B, 0x596D,
+};
+const unsigned short euc_to_utf8_8FB9[] = {
+ 0x596F, 0x5972, 0x5975, 0x5976, 0x5979, 0x597B, 0x597C,
+ 0x598B, 0x598C, 0x598E, 0x5992, 0x5995, 0x5997, 0x599F, 0x59A4,
+ 0x59A7, 0x59AD, 0x59AE, 0x59AF, 0x59B0, 0x59B3, 0x59B7, 0x59BA,
+ 0x59BC, 0x59C1, 0x59C3, 0x59C4, 0x59C8, 0x59CA, 0x59CD, 0x59D2,
+ 0x59DD, 0x59DE, 0x59DF, 0x59E3, 0x59E4, 0x59E7, 0x59EE, 0x59EF,
+ 0x59F1, 0x59F2, 0x59F4, 0x59F7, 0x5A00, 0x5A04, 0x5A0C, 0x5A0D,
+ 0x5A0E, 0x5A12, 0x5A13, 0x5A1E, 0x5A23, 0x5A24, 0x5A27, 0x5A28,
+ 0x5A2A, 0x5A2D, 0x5A30, 0x5A44, 0x5A45, 0x5A47, 0x5A48, 0x5A4C,
+ 0x5A50, 0x5A55, 0x5A5E, 0x5A63, 0x5A65, 0x5A67, 0x5A6D, 0x5A77,
+ 0x5A7A, 0x5A7B, 0x5A7E, 0x5A8B, 0x5A90, 0x5A93, 0x5A96, 0x5A99,
+ 0x5A9C, 0x5A9E, 0x5A9F, 0x5AA0, 0x5AA2, 0x5AA7, 0x5AAC, 0x5AB1,
+ 0x5AB2, 0x5AB3, 0x5AB5, 0x5AB8, 0x5ABA, 0x5ABB, 0x5ABF,
+};
+const unsigned short euc_to_utf8_8FBA[] = {
+ 0x5AC4, 0x5AC6, 0x5AC8, 0x5ACF, 0x5ADA, 0x5ADC, 0x5AE0,
+ 0x5AE5, 0x5AEA, 0x5AEE, 0x5AF5, 0x5AF6, 0x5AFD, 0x5B00, 0x5B01,
+ 0x5B08, 0x5B17, 0x5B34, 0x5B19, 0x5B1B, 0x5B1D, 0x5B21, 0x5B25,
+ 0x5B2D, 0x5B38, 0x5B41, 0x5B4B, 0x5B4C, 0x5B52, 0x5B56, 0x5B5E,
+ 0x5B68, 0x5B6E, 0x5B6F, 0x5B7C, 0x5B7D, 0x5B7E, 0x5B7F, 0x5B81,
+ 0x5B84, 0x5B86, 0x5B8A, 0x5B8E, 0x5B90, 0x5B91, 0x5B93, 0x5B94,
+ 0x5B96, 0x5BA8, 0x5BA9, 0x5BAC, 0x5BAD, 0x5BAF, 0x5BB1, 0x5BB2,
+ 0x5BB7, 0x5BBA, 0x5BBC, 0x5BC0, 0x5BC1, 0x5BCD, 0x5BCF, 0x5BD6,
+ 0x5BD7, 0x5BD8, 0x5BD9, 0x5BDA, 0x5BE0, 0x5BEF, 0x5BF1, 0x5BF4,
+ 0x5BFD, 0x5C0C, 0x5C17, 0x5C1E, 0x5C1F, 0x5C23, 0x5C26, 0x5C29,
+ 0x5C2B, 0x5C2C, 0x5C2E, 0x5C30, 0x5C32, 0x5C35, 0x5C36, 0x5C59,
+ 0x5C5A, 0x5C5C, 0x5C62, 0x5C63, 0x5C67, 0x5C68, 0x5C69,
+};
+const unsigned short euc_to_utf8_8FBB[] = {
+ 0x5C6D, 0x5C70, 0x5C74, 0x5C75, 0x5C7A, 0x5C7B, 0x5C7C,
+ 0x5C7D, 0x5C87, 0x5C88, 0x5C8A, 0x5C8F, 0x5C92, 0x5C9D, 0x5C9F,
+ 0x5CA0, 0x5CA2, 0x5CA3, 0x5CA6, 0x5CAA, 0x5CB2, 0x5CB4, 0x5CB5,
+ 0x5CBA, 0x5CC9, 0x5CCB, 0x5CD2, 0x5CDD, 0x5CD7, 0x5CEE, 0x5CF1,
+ 0x5CF2, 0x5CF4, 0x5D01, 0x5D06, 0x5D0D, 0x5D12, 0x5D2B, 0x5D23,
+ 0x5D24, 0x5D26, 0x5D27, 0x5D31, 0x5D34, 0x5D39, 0x5D3D, 0x5D3F,
+ 0x5D42, 0x5D43, 0x5D46, 0x5D48, 0x5D55, 0x5D51, 0x5D59, 0x5D4A,
+ 0x5D5F, 0x5D60, 0x5D61, 0x5D62, 0x5D64, 0x5D6A, 0x5D6D, 0x5D70,
+ 0x5D79, 0x5D7A, 0x5D7E, 0x5D7F, 0x5D81, 0x5D83, 0x5D88, 0x5D8A,
+ 0x5D92, 0x5D93, 0x5D94, 0x5D95, 0x5D99, 0x5D9B, 0x5D9F, 0x5DA0,
+ 0x5DA7, 0x5DAB, 0x5DB0, 0x5DB4, 0x5DB8, 0x5DB9, 0x5DC3, 0x5DC7,
+ 0x5DCB, 0x5DD0, 0x5DCE, 0x5DD8, 0x5DD9, 0x5DE0, 0x5DE4,
+};
+const unsigned short euc_to_utf8_8FBC[] = {
+ 0x5DE9, 0x5DF8, 0x5DF9, 0x5E00, 0x5E07, 0x5E0D, 0x5E12,
+ 0x5E14, 0x5E15, 0x5E18, 0x5E1F, 0x5E20, 0x5E2E, 0x5E28, 0x5E32,
+ 0x5E35, 0x5E3E, 0x5E4B, 0x5E50, 0x5E49, 0x5E51, 0x5E56, 0x5E58,
+ 0x5E5B, 0x5E5C, 0x5E5E, 0x5E68, 0x5E6A, 0x5E6B, 0x5E6C, 0x5E6D,
+ 0x5E6E, 0x5E70, 0x5E80, 0x5E8B, 0x5E8E, 0x5EA2, 0x5EA4, 0x5EA5,
+ 0x5EA8, 0x5EAA, 0x5EAC, 0x5EB1, 0x5EB3, 0x5EBD, 0x5EBE, 0x5EBF,
+ 0x5EC6, 0x5ECC, 0x5ECB, 0x5ECE, 0x5ED1, 0x5ED2, 0x5ED4, 0x5ED5,
+ 0x5EDC, 0x5EDE, 0x5EE5, 0x5EEB, 0x5F02, 0x5F06, 0x5F07, 0x5F08,
+ 0x5F0E, 0x5F19, 0x5F1C, 0x5F1D, 0x5F21, 0x5F22, 0x5F23, 0x5F24,
+ 0x5F28, 0x5F2B, 0x5F2C, 0x5F2E, 0x5F30, 0x5F34, 0x5F36, 0x5F3B,
+ 0x5F3D, 0x5F3F, 0x5F40, 0x5F44, 0x5F45, 0x5F47, 0x5F4D, 0x5F50,
+ 0x5F54, 0x5F58, 0x5F5B, 0x5F60, 0x5F63, 0x5F64, 0x5F67,
+};
+const unsigned short euc_to_utf8_8FBD[] = {
+ 0x5F6F, 0x5F72, 0x5F74, 0x5F75, 0x5F78, 0x5F7A, 0x5F7D,
+ 0x5F7E, 0x5F89, 0x5F8D, 0x5F8F, 0x5F96, 0x5F9C, 0x5F9D, 0x5FA2,
+ 0x5FA7, 0x5FAB, 0x5FA4, 0x5FAC, 0x5FAF, 0x5FB0, 0x5FB1, 0x5FB8,
+ 0x5FC4, 0x5FC7, 0x5FC8, 0x5FC9, 0x5FCB, 0x5FD0, 0x5FD1, 0x5FD2,
+ 0x5FD3, 0x5FD4, 0x5FDE, 0x5FE1, 0x5FE2, 0x5FE8, 0x5FE9, 0x5FEA,
+ 0x5FEC, 0x5FED, 0x5FEE, 0x5FEF, 0x5FF2, 0x5FF3, 0x5FF6, 0x5FFA,
+ 0x5FFC, 0x6007, 0x600A, 0x600D, 0x6013, 0x6014, 0x6017, 0x6018,
+ 0x601A, 0x601F, 0x6024, 0x602D, 0x6033, 0x6035, 0x6040, 0x6047,
+ 0x6048, 0x6049, 0x604C, 0x6051, 0x6054, 0x6056, 0x6057, 0x605D,
+ 0x6061, 0x6067, 0x6071, 0x607E, 0x607F, 0x6082, 0x6086, 0x6088,
+ 0x608A, 0x608E, 0x6091, 0x6093, 0x6095, 0x6098, 0x609D, 0x609E,
+ 0x60A2, 0x60A4, 0x60A5, 0x60A8, 0x60B0, 0x60B1, 0x60B7,
+};
+const unsigned short euc_to_utf8_8FBE[] = {
+ 0x60BB, 0x60BE, 0x60C2, 0x60C4, 0x60C8, 0x60C9, 0x60CA,
+ 0x60CB, 0x60CE, 0x60CF, 0x60D4, 0x60D5, 0x60D9, 0x60DB, 0x60DD,
+ 0x60DE, 0x60E2, 0x60E5, 0x60F2, 0x60F5, 0x60F8, 0x60FC, 0x60FD,
+ 0x6102, 0x6107, 0x610A, 0x610C, 0x6110, 0x6111, 0x6112, 0x6113,
+ 0x6114, 0x6116, 0x6117, 0x6119, 0x611C, 0x611E, 0x6122, 0x612A,
+ 0x612B, 0x6130, 0x6131, 0x6135, 0x6136, 0x6137, 0x6139, 0x6141,
+ 0x6145, 0x6146, 0x6149, 0x615E, 0x6160, 0x616C, 0x6172, 0x6178,
+ 0x617B, 0x617C, 0x617F, 0x6180, 0x6181, 0x6183, 0x6184, 0x618B,
+ 0x618D, 0x6192, 0x6193, 0x6197, 0x6198, 0x619C, 0x619D, 0x619F,
+ 0x61A0, 0x61A5, 0x61A8, 0x61AA, 0x61AD, 0x61B8, 0x61B9, 0x61BC,
+ 0x61C0, 0x61C1, 0x61C2, 0x61CE, 0x61CF, 0x61D5, 0x61DC, 0x61DD,
+ 0x61DE, 0x61DF, 0x61E1, 0x61E2, 0x61E7, 0x61E9, 0x61E5,
+};
+const unsigned short euc_to_utf8_8FBF[] = {
+ 0x61EC, 0x61ED, 0x61EF, 0x6201, 0x6203, 0x6204, 0x6207,
+ 0x6213, 0x6215, 0x621C, 0x6220, 0x6222, 0x6223, 0x6227, 0x6229,
+ 0x622B, 0x6239, 0x623D, 0x6242, 0x6243, 0x6244, 0x6246, 0x624C,
+ 0x6250, 0x6251, 0x6252, 0x6254, 0x6256, 0x625A, 0x625C, 0x6264,
+ 0x626D, 0x626F, 0x6273, 0x627A, 0x627D, 0x628D, 0x628E, 0x628F,
+ 0x6290, 0x62A6, 0x62A8, 0x62B3, 0x62B6, 0x62B7, 0x62BA, 0x62BE,
+ 0x62BF, 0x62C4, 0x62CE, 0x62D5, 0x62D6, 0x62DA, 0x62EA, 0x62F2,
+ 0x62F4, 0x62FC, 0x62FD, 0x6303, 0x6304, 0x630A, 0x630B, 0x630D,
+ 0x6310, 0x6313, 0x6316, 0x6318, 0x6329, 0x632A, 0x632D, 0x6335,
+ 0x6336, 0x6339, 0x633C, 0x6341, 0x6342, 0x6343, 0x6344, 0x6346,
+ 0x634A, 0x634B, 0x634E, 0x6352, 0x6353, 0x6354, 0x6358, 0x635B,
+ 0x6365, 0x6366, 0x636C, 0x636D, 0x6371, 0x6374, 0x6375,
+};
+const unsigned short euc_to_utf8_8FC0[] = {
+ 0x6378, 0x637C, 0x637D, 0x637F, 0x6382, 0x6384, 0x6387,
+ 0x638A, 0x6390, 0x6394, 0x6395, 0x6399, 0x639A, 0x639E, 0x63A4,
+ 0x63A6, 0x63AD, 0x63AE, 0x63AF, 0x63BD, 0x63C1, 0x63C5, 0x63C8,
+ 0x63CE, 0x63D1, 0x63D3, 0x63D4, 0x63D5, 0x63DC, 0x63E0, 0x63E5,
+ 0x63EA, 0x63EC, 0x63F2, 0x63F3, 0x63F5, 0x63F8, 0x63F9, 0x6409,
+ 0x640A, 0x6410, 0x6412, 0x6414, 0x6418, 0x641E, 0x6420, 0x6422,
+ 0x6424, 0x6425, 0x6429, 0x642A, 0x642F, 0x6430, 0x6435, 0x643D,
+ 0x643F, 0x644B, 0x644F, 0x6451, 0x6452, 0x6453, 0x6454, 0x645A,
+ 0x645B, 0x645C, 0x645D, 0x645F, 0x6460, 0x6461, 0x6463, 0x646D,
+ 0x6473, 0x6474, 0x647B, 0x647D, 0x6485, 0x6487, 0x648F, 0x6490,
+ 0x6491, 0x6498, 0x6499, 0x649B, 0x649D, 0x649F, 0x64A1, 0x64A3,
+ 0x64A6, 0x64A8, 0x64AC, 0x64B3, 0x64BD, 0x64BE, 0x64BF,
+};
+const unsigned short euc_to_utf8_8FC1[] = {
+ 0x64C4, 0x64C9, 0x64CA, 0x64CB, 0x64CC, 0x64CE, 0x64D0,
+ 0x64D1, 0x64D5, 0x64D7, 0x64E4, 0x64E5, 0x64E9, 0x64EA, 0x64ED,
+ 0x64F0, 0x64F5, 0x64F7, 0x64FB, 0x64FF, 0x6501, 0x6504, 0x6508,
+ 0x6509, 0x650A, 0x650F, 0x6513, 0x6514, 0x6516, 0x6519, 0x651B,
+ 0x651E, 0x651F, 0x6522, 0x6526, 0x6529, 0x652E, 0x6531, 0x653A,
+ 0x653C, 0x653D, 0x6543, 0x6547, 0x6549, 0x6550, 0x6552, 0x6554,
+ 0x655F, 0x6560, 0x6567, 0x656B, 0x657A, 0x657D, 0x6581, 0x6585,
+ 0x658A, 0x6592, 0x6595, 0x6598, 0x659D, 0x65A0, 0x65A3, 0x65A6,
+ 0x65AE, 0x65B2, 0x65B3, 0x65B4, 0x65BF, 0x65C2, 0x65C8, 0x65C9,
+ 0x65CE, 0x65D0, 0x65D4, 0x65D6, 0x65D8, 0x65DF, 0x65F0, 0x65F2,
+ 0x65F4, 0x65F5, 0x65F9, 0x65FE, 0x65FF, 0x6600, 0x6604, 0x6608,
+ 0x6609, 0x660D, 0x6611, 0x6612, 0x6615, 0x6616, 0x661D,
+};
+const unsigned short euc_to_utf8_8FC2[] = {
+ 0x661E, 0x6621, 0x6622, 0x6623, 0x6624, 0x6626, 0x6629,
+ 0x662A, 0x662B, 0x662C, 0x662E, 0x6630, 0x6631, 0x6633, 0x6639,
+ 0x6637, 0x6640, 0x6645, 0x6646, 0x664A, 0x664C, 0x6651, 0x664E,
+ 0x6657, 0x6658, 0x6659, 0x665B, 0x665C, 0x6660, 0x6661, 0x66FB,
+ 0x666A, 0x666B, 0x666C, 0x667E, 0x6673, 0x6675, 0x667F, 0x6677,
+ 0x6678, 0x6679, 0x667B, 0x6680, 0x667C, 0x668B, 0x668C, 0x668D,
+ 0x6690, 0x6692, 0x6699, 0x669A, 0x669B, 0x669C, 0x669F, 0x66A0,
+ 0x66A4, 0x66AD, 0x66B1, 0x66B2, 0x66B5, 0x66BB, 0x66BF, 0x66C0,
+ 0x66C2, 0x66C3, 0x66C8, 0x66CC, 0x66CE, 0x66CF, 0x66D4, 0x66DB,
+ 0x66DF, 0x66E8, 0x66EB, 0x66EC, 0x66EE, 0x66FA, 0x6705, 0x6707,
+ 0x670E, 0x6713, 0x6719, 0x671C, 0x6720, 0x6722, 0x6733, 0x673E,
+ 0x6745, 0x6747, 0x6748, 0x674C, 0x6754, 0x6755, 0x675D,
+};
+const unsigned short euc_to_utf8_8FC3[] = {
+ 0x6766, 0x676C, 0x676E, 0x6774, 0x6776, 0x677B, 0x6781,
+ 0x6784, 0x678E, 0x678F, 0x6791, 0x6793, 0x6796, 0x6798, 0x6799,
+ 0x679B, 0x67B0, 0x67B1, 0x67B2, 0x67B5, 0x67BB, 0x67BC, 0x67BD,
+ 0x67F9, 0x67C0, 0x67C2, 0x67C3, 0x67C5, 0x67C8, 0x67C9, 0x67D2,
+ 0x67D7, 0x67D9, 0x67DC, 0x67E1, 0x67E6, 0x67F0, 0x67F2, 0x67F6,
+ 0x67F7, 0x6852, 0x6814, 0x6819, 0x681D, 0x681F, 0x6828, 0x6827,
+ 0x682C, 0x682D, 0x682F, 0x6830, 0x6831, 0x6833, 0x683B, 0x683F,
+ 0x6844, 0x6845, 0x684A, 0x684C, 0x6855, 0x6857, 0x6858, 0x685B,
+ 0x686B, 0x686E, 0x686F, 0x6870, 0x6871, 0x6872, 0x6875, 0x6879,
+ 0x687A, 0x687B, 0x687C, 0x6882, 0x6884, 0x6886, 0x6888, 0x6896,
+ 0x6898, 0x689A, 0x689C, 0x68A1, 0x68A3, 0x68A5, 0x68A9, 0x68AA,
+ 0x68AE, 0x68B2, 0x68BB, 0x68C5, 0x68C8, 0x68CC, 0x68CF,
+};
+const unsigned short euc_to_utf8_8FC4[] = {
+ 0x68D0, 0x68D1, 0x68D3, 0x68D6, 0x68D9, 0x68DC, 0x68DD,
+ 0x68E5, 0x68E8, 0x68EA, 0x68EB, 0x68EC, 0x68ED, 0x68F0, 0x68F1,
+ 0x68F5, 0x68F6, 0x68FB, 0x68FC, 0x68FD, 0x6906, 0x6909, 0x690A,
+ 0x6910, 0x6911, 0x6913, 0x6916, 0x6917, 0x6931, 0x6933, 0x6935,
+ 0x6938, 0x693B, 0x6942, 0x6945, 0x6949, 0x694E, 0x6957, 0x695B,
+ 0x6963, 0x6964, 0x6965, 0x6966, 0x6968, 0x6969, 0x696C, 0x6970,
+ 0x6971, 0x6972, 0x697A, 0x697B, 0x697F, 0x6980, 0x698D, 0x6992,
+ 0x6996, 0x6998, 0x69A1, 0x69A5, 0x69A6, 0x69A8, 0x69AB, 0x69AD,
+ 0x69AF, 0x69B7, 0x69B8, 0x69BA, 0x69BC, 0x69C5, 0x69C8, 0x69D1,
+ 0x69D6, 0x69D7, 0x69E2, 0x69E5, 0x69EE, 0x69EF, 0x69F1, 0x69F3,
+ 0x69F5, 0x69FE, 0x6A00, 0x6A01, 0x6A03, 0x6A0F, 0x6A11, 0x6A15,
+ 0x6A1A, 0x6A1D, 0x6A20, 0x6A24, 0x6A28, 0x6A30, 0x6A32,
+};
+const unsigned short euc_to_utf8_8FC5[] = {
+ 0x6A34, 0x6A37, 0x6A3B, 0x6A3E, 0x6A3F, 0x6A45, 0x6A46,
+ 0x6A49, 0x6A4A, 0x6A4E, 0x6A50, 0x6A51, 0x6A52, 0x6A55, 0x6A56,
+ 0x6A5B, 0x6A64, 0x6A67, 0x6A6A, 0x6A71, 0x6A73, 0x6A7E, 0x6A81,
+ 0x6A83, 0x6A86, 0x6A87, 0x6A89, 0x6A8B, 0x6A91, 0x6A9B, 0x6A9D,
+ 0x6A9E, 0x6A9F, 0x6AA5, 0x6AAB, 0x6AAF, 0x6AB0, 0x6AB1, 0x6AB4,
+ 0x6ABD, 0x6ABE, 0x6ABF, 0x6AC6, 0x6AC9, 0x6AC8, 0x6ACC, 0x6AD0,
+ 0x6AD4, 0x6AD5, 0x6AD6, 0x6ADC, 0x6ADD, 0x6AE4, 0x6AE7, 0x6AEC,
+ 0x6AF0, 0x6AF1, 0x6AF2, 0x6AFC, 0x6AFD, 0x6B02, 0x6B03, 0x6B06,
+ 0x6B07, 0x6B09, 0x6B0F, 0x6B10, 0x6B11, 0x6B17, 0x6B1B, 0x6B1E,
+ 0x6B24, 0x6B28, 0x6B2B, 0x6B2C, 0x6B2F, 0x6B35, 0x6B36, 0x6B3B,
+ 0x6B3F, 0x6B46, 0x6B4A, 0x6B4D, 0x6B52, 0x6B56, 0x6B58, 0x6B5D,
+ 0x6B60, 0x6B67, 0x6B6B, 0x6B6E, 0x6B70, 0x6B75, 0x6B7D,
+};
+const unsigned short euc_to_utf8_8FC6[] = {
+ 0x6B7E, 0x6B82, 0x6B85, 0x6B97, 0x6B9B, 0x6B9F, 0x6BA0,
+ 0x6BA2, 0x6BA3, 0x6BA8, 0x6BA9, 0x6BAC, 0x6BAD, 0x6BAE, 0x6BB0,
+ 0x6BB8, 0x6BB9, 0x6BBD, 0x6BBE, 0x6BC3, 0x6BC4, 0x6BC9, 0x6BCC,
+ 0x6BD6, 0x6BDA, 0x6BE1, 0x6BE3, 0x6BE6, 0x6BE7, 0x6BEE, 0x6BF1,
+ 0x6BF7, 0x6BF9, 0x6BFF, 0x6C02, 0x6C04, 0x6C05, 0x6C09, 0x6C0D,
+ 0x6C0E, 0x6C10, 0x6C12, 0x6C19, 0x6C1F, 0x6C26, 0x6C27, 0x6C28,
+ 0x6C2C, 0x6C2E, 0x6C33, 0x6C35, 0x6C36, 0x6C3A, 0x6C3B, 0x6C3F,
+ 0x6C4A, 0x6C4B, 0x6C4D, 0x6C4F, 0x6C52, 0x6C54, 0x6C59, 0x6C5B,
+ 0x6C5C, 0x6C6B, 0x6C6D, 0x6C6F, 0x6C74, 0x6C76, 0x6C78, 0x6C79,
+ 0x6C7B, 0x6C85, 0x6C86, 0x6C87, 0x6C89, 0x6C94, 0x6C95, 0x6C97,
+ 0x6C98, 0x6C9C, 0x6C9F, 0x6CB0, 0x6CB2, 0x6CB4, 0x6CC2, 0x6CC6,
+ 0x6CCD, 0x6CCF, 0x6CD0, 0x6CD1, 0x6CD2, 0x6CD4, 0x6CD6,
+};
+const unsigned short euc_to_utf8_8FC7[] = {
+ 0x6CDA, 0x6CDC, 0x6CE0, 0x6CE7, 0x6CE9, 0x6CEB, 0x6CEC,
+ 0x6CEE, 0x6CF2, 0x6CF4, 0x6D04, 0x6D07, 0x6D0A, 0x6D0E, 0x6D0F,
+ 0x6D11, 0x6D13, 0x6D1A, 0x6D26, 0x6D27, 0x6D28, 0x6C67, 0x6D2E,
+ 0x6D2F, 0x6D31, 0x6D39, 0x6D3C, 0x6D3F, 0x6D57, 0x6D5E, 0x6D5F,
+ 0x6D61, 0x6D65, 0x6D67, 0x6D6F, 0x6D70, 0x6D7C, 0x6D82, 0x6D87,
+ 0x6D91, 0x6D92, 0x6D94, 0x6D96, 0x6D97, 0x6D98, 0x6DAA, 0x6DAC,
+ 0x6DB4, 0x6DB7, 0x6DB9, 0x6DBD, 0x6DBF, 0x6DC4, 0x6DC8, 0x6DCA,
+ 0x6DCE, 0x6DCF, 0x6DD6, 0x6DDB, 0x6DDD, 0x6DDF, 0x6DE0, 0x6DE2,
+ 0x6DE5, 0x6DE9, 0x6DEF, 0x6DF0, 0x6DF4, 0x6DF6, 0x6DFC, 0x6E00,
+ 0x6E04, 0x6E1E, 0x6E22, 0x6E27, 0x6E32, 0x6E36, 0x6E39, 0x6E3B,
+ 0x6E3C, 0x6E44, 0x6E45, 0x6E48, 0x6E49, 0x6E4B, 0x6E4F, 0x6E51,
+ 0x6E52, 0x6E53, 0x6E54, 0x6E57, 0x6E5C, 0x6E5D, 0x6E5E,
+};
+const unsigned short euc_to_utf8_8FC8[] = {
+ 0x6E62, 0x6E63, 0x6E68, 0x6E73, 0x6E7B, 0x6E7D, 0x6E8D,
+ 0x6E93, 0x6E99, 0x6EA0, 0x6EA7, 0x6EAD, 0x6EAE, 0x6EB1, 0x6EB3,
+ 0x6EBB, 0x6EBF, 0x6EC0, 0x6EC1, 0x6EC3, 0x6EC7, 0x6EC8, 0x6ECA,
+ 0x6ECD, 0x6ECE, 0x6ECF, 0x6EEB, 0x6EED, 0x6EEE, 0x6EF9, 0x6EFB,
+ 0x6EFD, 0x6F04, 0x6F08, 0x6F0A, 0x6F0C, 0x6F0D, 0x6F16, 0x6F18,
+ 0x6F1A, 0x6F1B, 0x6F26, 0x6F29, 0x6F2A, 0x6F2F, 0x6F30, 0x6F33,
+ 0x6F36, 0x6F3B, 0x6F3C, 0x6F2D, 0x6F4F, 0x6F51, 0x6F52, 0x6F53,
+ 0x6F57, 0x6F59, 0x6F5A, 0x6F5D, 0x6F5E, 0x6F61, 0x6F62, 0x6F68,
+ 0x6F6C, 0x6F7D, 0x6F7E, 0x6F83, 0x6F87, 0x6F88, 0x6F8B, 0x6F8C,
+ 0x6F8D, 0x6F90, 0x6F92, 0x6F93, 0x6F94, 0x6F96, 0x6F9A, 0x6F9F,
+ 0x6FA0, 0x6FA5, 0x6FA6, 0x6FA7, 0x6FA8, 0x6FAE, 0x6FAF, 0x6FB0,
+ 0x6FB5, 0x6FB6, 0x6FBC, 0x6FC5, 0x6FC7, 0x6FC8, 0x6FCA,
+};
+const unsigned short euc_to_utf8_8FC9[] = {
+ 0x6FDA, 0x6FDE, 0x6FE8, 0x6FE9, 0x6FF0, 0x6FF5, 0x6FF9,
+ 0x6FFC, 0x6FFD, 0x7000, 0x7005, 0x7006, 0x7007, 0x700D, 0x7017,
+ 0x7020, 0x7023, 0x702F, 0x7034, 0x7037, 0x7039, 0x703C, 0x7043,
+ 0x7044, 0x7048, 0x7049, 0x704A, 0x704B, 0x7054, 0x7055, 0x705D,
+ 0x705E, 0x704E, 0x7064, 0x7065, 0x706C, 0x706E, 0x7075, 0x7076,
+ 0x707E, 0x7081, 0x7085, 0x7086, 0x7094, 0x7095, 0x7096, 0x7097,
+ 0x7098, 0x709B, 0x70A4, 0x70AB, 0x70B0, 0x70B1, 0x70B4, 0x70B7,
+ 0x70CA, 0x70D1, 0x70D3, 0x70D4, 0x70D5, 0x70D6, 0x70D8, 0x70DC,
+ 0x70E4, 0x70FA, 0x7103, 0x7104, 0x7105, 0x7106, 0x7107, 0x710B,
+ 0x710C, 0x710F, 0x711E, 0x7120, 0x712B, 0x712D, 0x712F, 0x7130,
+ 0x7131, 0x7138, 0x7141, 0x7145, 0x7146, 0x7147, 0x714A, 0x714B,
+ 0x7150, 0x7152, 0x7157, 0x715A, 0x715C, 0x715E, 0x7160,
+};
+const unsigned short euc_to_utf8_8FCA[] = {
+ 0x7168, 0x7179, 0x7180, 0x7185, 0x7187, 0x718C, 0x7192,
+ 0x719A, 0x719B, 0x71A0, 0x71A2, 0x71AF, 0x71B0, 0x71B2, 0x71B3,
+ 0x71BA, 0x71BF, 0x71C0, 0x71C1, 0x71C4, 0x71CB, 0x71CC, 0x71D3,
+ 0x71D6, 0x71D9, 0x71DA, 0x71DC, 0x71F8, 0x71FE, 0x7200, 0x7207,
+ 0x7208, 0x7209, 0x7213, 0x7217, 0x721A, 0x721D, 0x721F, 0x7224,
+ 0x722B, 0x722F, 0x7234, 0x7238, 0x7239, 0x7241, 0x7242, 0x7243,
+ 0x7245, 0x724E, 0x724F, 0x7250, 0x7253, 0x7255, 0x7256, 0x725A,
+ 0x725C, 0x725E, 0x7260, 0x7263, 0x7268, 0x726B, 0x726E, 0x726F,
+ 0x7271, 0x7277, 0x7278, 0x727B, 0x727C, 0x727F, 0x7284, 0x7289,
+ 0x728D, 0x728E, 0x7293, 0x729B, 0x72A8, 0x72AD, 0x72AE, 0x72B1,
+ 0x72B4, 0x72BE, 0x72C1, 0x72C7, 0x72C9, 0x72CC, 0x72D5, 0x72D6,
+ 0x72D8, 0x72DF, 0x72E5, 0x72F3, 0x72F4, 0x72FA, 0x72FB,
+};
+const unsigned short euc_to_utf8_8FCB[] = {
+ 0x72FE, 0x7302, 0x7304, 0x7305, 0x7307, 0x730B, 0x730D,
+ 0x7312, 0x7313, 0x7318, 0x7319, 0x731E, 0x7322, 0x7324, 0x7327,
+ 0x7328, 0x732C, 0x7331, 0x7332, 0x7335, 0x733A, 0x733B, 0x733D,
+ 0x7343, 0x734D, 0x7350, 0x7352, 0x7356, 0x7358, 0x735D, 0x735E,
+ 0x735F, 0x7360, 0x7366, 0x7367, 0x7369, 0x736B, 0x736C, 0x736E,
+ 0x736F, 0x7371, 0x7377, 0x7379, 0x737C, 0x7380, 0x7381, 0x7383,
+ 0x7385, 0x7386, 0x738E, 0x7390, 0x7393, 0x7395, 0x7397, 0x7398,
+ 0x739C, 0x739E, 0x739F, 0x73A0, 0x73A2, 0x73A5, 0x73A6, 0x73AA,
+ 0x73AB, 0x73AD, 0x73B5, 0x73B7, 0x73B9, 0x73BC, 0x73BD, 0x73BF,
+ 0x73C5, 0x73C6, 0x73C9, 0x73CB, 0x73CC, 0x73CF, 0x73D2, 0x73D3,
+ 0x73D6, 0x73D9, 0x73DD, 0x73E1, 0x73E3, 0x73E6, 0x73E7, 0x73E9,
+ 0x73F4, 0x73F5, 0x73F7, 0x73F9, 0x73FA, 0x73FB, 0x73FD,
+};
+const unsigned short euc_to_utf8_8FCC[] = {
+ 0x73FF, 0x7400, 0x7401, 0x7404, 0x7407, 0x740A, 0x7411,
+ 0x741A, 0x741B, 0x7424, 0x7426, 0x7428, 0x7429, 0x742A, 0x742B,
+ 0x742C, 0x742D, 0x742E, 0x742F, 0x7430, 0x7431, 0x7439, 0x7440,
+ 0x7443, 0x7444, 0x7446, 0x7447, 0x744B, 0x744D, 0x7451, 0x7452,
+ 0x7457, 0x745D, 0x7462, 0x7466, 0x7467, 0x7468, 0x746B, 0x746D,
+ 0x746E, 0x7471, 0x7472, 0x7480, 0x7481, 0x7485, 0x7486, 0x7487,
+ 0x7489, 0x748F, 0x7490, 0x7491, 0x7492, 0x7498, 0x7499, 0x749A,
+ 0x749C, 0x749F, 0x74A0, 0x74A1, 0x74A3, 0x74A6, 0x74A8, 0x74A9,
+ 0x74AA, 0x74AB, 0x74AE, 0x74AF, 0x74B1, 0x74B2, 0x74B5, 0x74B9,
+ 0x74BB, 0x74BF, 0x74C8, 0x74C9, 0x74CC, 0x74D0, 0x74D3, 0x74D8,
+ 0x74DA, 0x74DB, 0x74DE, 0x74DF, 0x74E4, 0x74E8, 0x74EA, 0x74EB,
+ 0x74EF, 0x74F4, 0x74FA, 0x74FB, 0x74FC, 0x74FF, 0x7506,
+};
+const unsigned short euc_to_utf8_8FCD[] = {
+ 0x7512, 0x7516, 0x7517, 0x7520, 0x7521, 0x7524, 0x7527,
+ 0x7529, 0x752A, 0x752F, 0x7536, 0x7539, 0x753D, 0x753E, 0x753F,
+ 0x7540, 0x7543, 0x7547, 0x7548, 0x754E, 0x7550, 0x7552, 0x7557,
+ 0x755E, 0x755F, 0x7561, 0x756F, 0x7571, 0x7579, 0x757A, 0x757B,
+ 0x757C, 0x757D, 0x757E, 0x7581, 0x7585, 0x7590, 0x7592, 0x7593,
+ 0x7595, 0x7599, 0x759C, 0x75A2, 0x75A4, 0x75B4, 0x75BA, 0x75BF,
+ 0x75C0, 0x75C1, 0x75C4, 0x75C6, 0x75CC, 0x75CE, 0x75CF, 0x75D7,
+ 0x75DC, 0x75DF, 0x75E0, 0x75E1, 0x75E4, 0x75E7, 0x75EC, 0x75EE,
+ 0x75EF, 0x75F1, 0x75F9, 0x7600, 0x7602, 0x7603, 0x7604, 0x7607,
+ 0x7608, 0x760A, 0x760C, 0x760F, 0x7612, 0x7613, 0x7615, 0x7616,
+ 0x7619, 0x761B, 0x761C, 0x761D, 0x761E, 0x7623, 0x7625, 0x7626,
+ 0x7629, 0x762D, 0x7632, 0x7633, 0x7635, 0x7638, 0x7639,
+};
+const unsigned short euc_to_utf8_8FCE[] = {
+ 0x763A, 0x763C, 0x764A, 0x7640, 0x7641, 0x7643, 0x7644,
+ 0x7645, 0x7649, 0x764B, 0x7655, 0x7659, 0x765F, 0x7664, 0x7665,
+ 0x766D, 0x766E, 0x766F, 0x7671, 0x7674, 0x7681, 0x7685, 0x768C,
+ 0x768D, 0x7695, 0x769B, 0x769C, 0x769D, 0x769F, 0x76A0, 0x76A2,
+ 0x76A3, 0x76A4, 0x76A5, 0x76A6, 0x76A7, 0x76A8, 0x76AA, 0x76AD,
+ 0x76BD, 0x76C1, 0x76C5, 0x76C9, 0x76CB, 0x76CC, 0x76CE, 0x76D4,
+ 0x76D9, 0x76E0, 0x76E6, 0x76E8, 0x76EC, 0x76F0, 0x76F1, 0x76F6,
+ 0x76F9, 0x76FC, 0x7700, 0x7706, 0x770A, 0x770E, 0x7712, 0x7714,
+ 0x7715, 0x7717, 0x7719, 0x771A, 0x771C, 0x7722, 0x7728, 0x772D,
+ 0x772E, 0x772F, 0x7734, 0x7735, 0x7736, 0x7739, 0x773D, 0x773E,
+ 0x7742, 0x7745, 0x7746, 0x774A, 0x774D, 0x774E, 0x774F, 0x7752,
+ 0x7756, 0x7757, 0x775C, 0x775E, 0x775F, 0x7760, 0x7762,
+};
+const unsigned short euc_to_utf8_8FCF[] = {
+ 0x7764, 0x7767, 0x776A, 0x776C, 0x7770, 0x7772, 0x7773,
+ 0x7774, 0x777A, 0x777D, 0x7780, 0x7784, 0x778C, 0x778D, 0x7794,
+ 0x7795, 0x7796, 0x779A, 0x779F, 0x77A2, 0x77A7, 0x77AA, 0x77AE,
+ 0x77AF, 0x77B1, 0x77B5, 0x77BE, 0x77C3, 0x77C9, 0x77D1, 0x77D2,
+ 0x77D5, 0x77D9, 0x77DE, 0x77DF, 0x77E0, 0x77E4, 0x77E6, 0x77EA,
+ 0x77EC, 0x77F0, 0x77F1, 0x77F4, 0x77F8, 0x77FB, 0x7805, 0x7806,
+ 0x7809, 0x780D, 0x780E, 0x7811, 0x781D, 0x7821, 0x7822, 0x7823,
+ 0x782D, 0x782E, 0x7830, 0x7835, 0x7837, 0x7843, 0x7844, 0x7847,
+ 0x7848, 0x784C, 0x784E, 0x7852, 0x785C, 0x785E, 0x7860, 0x7861,
+ 0x7863, 0x7864, 0x7868, 0x786A, 0x786E, 0x787A, 0x787E, 0x788A,
+ 0x788F, 0x7894, 0x7898, 0x78A1, 0x789D, 0x789E, 0x789F, 0x78A4,
+ 0x78A8, 0x78AC, 0x78AD, 0x78B0, 0x78B1, 0x78B2, 0x78B3,
+};
+const unsigned short euc_to_utf8_8FD0[] = {
+ 0x78BB, 0x78BD, 0x78BF, 0x78C7, 0x78C8, 0x78C9, 0x78CC,
+ 0x78CE, 0x78D2, 0x78D3, 0x78D5, 0x78D6, 0x78E4, 0x78DB, 0x78DF,
+ 0x78E0, 0x78E1, 0x78E6, 0x78EA, 0x78F2, 0x78F3, 0x7900, 0x78F6,
+ 0x78F7, 0x78FA, 0x78FB, 0x78FF, 0x7906, 0x790C, 0x7910, 0x791A,
+ 0x791C, 0x791E, 0x791F, 0x7920, 0x7925, 0x7927, 0x7929, 0x792D,
+ 0x7931, 0x7934, 0x7935, 0x793B, 0x793D, 0x793F, 0x7944, 0x7945,
+ 0x7946, 0x794A, 0x794B, 0x794F, 0x7951, 0x7954, 0x7958, 0x795B,
+ 0x795C, 0x7967, 0x7969, 0x796B, 0x7972, 0x7979, 0x797B, 0x797C,
+ 0x797E, 0x798B, 0x798C, 0x7991, 0x7993, 0x7994, 0x7995, 0x7996,
+ 0x7998, 0x799B, 0x799C, 0x79A1, 0x79A8, 0x79A9, 0x79AB, 0x79AF,
+ 0x79B1, 0x79B4, 0x79B8, 0x79BB, 0x79C2, 0x79C4, 0x79C7, 0x79C8,
+ 0x79CA, 0x79CF, 0x79D4, 0x79D6, 0x79DA, 0x79DD, 0x79DE,
+};
+const unsigned short euc_to_utf8_8FD1[] = {
+ 0x79E0, 0x79E2, 0x79E5, 0x79EA, 0x79EB, 0x79ED, 0x79F1,
+ 0x79F8, 0x79FC, 0x7A02, 0x7A03, 0x7A07, 0x7A09, 0x7A0A, 0x7A0C,
+ 0x7A11, 0x7A15, 0x7A1B, 0x7A1E, 0x7A21, 0x7A27, 0x7A2B, 0x7A2D,
+ 0x7A2F, 0x7A30, 0x7A34, 0x7A35, 0x7A38, 0x7A39, 0x7A3A, 0x7A44,
+ 0x7A45, 0x7A47, 0x7A48, 0x7A4C, 0x7A55, 0x7A56, 0x7A59, 0x7A5C,
+ 0x7A5D, 0x7A5F, 0x7A60, 0x7A65, 0x7A67, 0x7A6A, 0x7A6D, 0x7A75,
+ 0x7A78, 0x7A7E, 0x7A80, 0x7A82, 0x7A85, 0x7A86, 0x7A8A, 0x7A8B,
+ 0x7A90, 0x7A91, 0x7A94, 0x7A9E, 0x7AA0, 0x7AA3, 0x7AAC, 0x7AB3,
+ 0x7AB5, 0x7AB9, 0x7ABB, 0x7ABC, 0x7AC6, 0x7AC9, 0x7ACC, 0x7ACE,
+ 0x7AD1, 0x7ADB, 0x7AE8, 0x7AE9, 0x7AEB, 0x7AEC, 0x7AF1, 0x7AF4,
+ 0x7AFB, 0x7AFD, 0x7AFE, 0x7B07, 0x7B14, 0x7B1F, 0x7B23, 0x7B27,
+ 0x7B29, 0x7B2A, 0x7B2B, 0x7B2D, 0x7B2E, 0x7B2F, 0x7B30,
+};
+const unsigned short euc_to_utf8_8FD2[] = {
+ 0x7B31, 0x7B34, 0x7B3D, 0x7B3F, 0x7B40, 0x7B41, 0x7B47,
+ 0x7B4E, 0x7B55, 0x7B60, 0x7B64, 0x7B66, 0x7B69, 0x7B6A, 0x7B6D,
+ 0x7B6F, 0x7B72, 0x7B73, 0x7B77, 0x7B84, 0x7B89, 0x7B8E, 0x7B90,
+ 0x7B91, 0x7B96, 0x7B9B, 0x7B9E, 0x7BA0, 0x7BA5, 0x7BAC, 0x7BAF,
+ 0x7BB0, 0x7BB2, 0x7BB5, 0x7BB6, 0x7BBA, 0x7BBB, 0x7BBC, 0x7BBD,
+ 0x7BC2, 0x7BC5, 0x7BC8, 0x7BCA, 0x7BD4, 0x7BD6, 0x7BD7, 0x7BD9,
+ 0x7BDA, 0x7BDB, 0x7BE8, 0x7BEA, 0x7BF2, 0x7BF4, 0x7BF5, 0x7BF8,
+ 0x7BF9, 0x7BFA, 0x7BFC, 0x7BFE, 0x7C01, 0x7C02, 0x7C03, 0x7C04,
+ 0x7C06, 0x7C09, 0x7C0B, 0x7C0C, 0x7C0E, 0x7C0F, 0x7C19, 0x7C1B,
+ 0x7C20, 0x7C25, 0x7C26, 0x7C28, 0x7C2C, 0x7C31, 0x7C33, 0x7C34,
+ 0x7C36, 0x7C39, 0x7C3A, 0x7C46, 0x7C4A, 0x7C55, 0x7C51, 0x7C52,
+ 0x7C53, 0x7C59, 0x7C5A, 0x7C5B, 0x7C5C, 0x7C5D, 0x7C5E,
+};
+const unsigned short euc_to_utf8_8FD3[] = {
+ 0x7C61, 0x7C63, 0x7C67, 0x7C69, 0x7C6D, 0x7C6E, 0x7C70,
+ 0x7C72, 0x7C79, 0x7C7C, 0x7C7D, 0x7C86, 0x7C87, 0x7C8F, 0x7C94,
+ 0x7C9E, 0x7CA0, 0x7CA6, 0x7CB0, 0x7CB6, 0x7CB7, 0x7CBA, 0x7CBB,
+ 0x7CBC, 0x7CBF, 0x7CC4, 0x7CC7, 0x7CC8, 0x7CC9, 0x7CCD, 0x7CCF,
+ 0x7CD3, 0x7CD4, 0x7CD5, 0x7CD7, 0x7CD9, 0x7CDA, 0x7CDD, 0x7CE6,
+ 0x7CE9, 0x7CEB, 0x7CF5, 0x7D03, 0x7D07, 0x7D08, 0x7D09, 0x7D0F,
+ 0x7D11, 0x7D12, 0x7D13, 0x7D16, 0x7D1D, 0x7D1E, 0x7D23, 0x7D26,
+ 0x7D2A, 0x7D2D, 0x7D31, 0x7D3C, 0x7D3D, 0x7D3E, 0x7D40, 0x7D41,
+ 0x7D47, 0x7D48, 0x7D4D, 0x7D51, 0x7D53, 0x7D57, 0x7D59, 0x7D5A,
+ 0x7D5C, 0x7D5D, 0x7D65, 0x7D67, 0x7D6A, 0x7D70, 0x7D78, 0x7D7A,
+ 0x7D7B, 0x7D7F, 0x7D81, 0x7D82, 0x7D83, 0x7D85, 0x7D86, 0x7D88,
+ 0x7D8B, 0x7D8C, 0x7D8D, 0x7D91, 0x7D96, 0x7D97, 0x7D9D,
+};
+const unsigned short euc_to_utf8_8FD4[] = {
+ 0x7D9E, 0x7DA6, 0x7DA7, 0x7DAA, 0x7DB3, 0x7DB6, 0x7DB7,
+ 0x7DB9, 0x7DC2, 0x7DC3, 0x7DC4, 0x7DC5, 0x7DC6, 0x7DCC, 0x7DCD,
+ 0x7DCE, 0x7DD7, 0x7DD9, 0x7E00, 0x7DE2, 0x7DE5, 0x7DE6, 0x7DEA,
+ 0x7DEB, 0x7DED, 0x7DF1, 0x7DF5, 0x7DF6, 0x7DF9, 0x7DFA, 0x7E08,
+ 0x7E10, 0x7E11, 0x7E15, 0x7E17, 0x7E1C, 0x7E1D, 0x7E20, 0x7E27,
+ 0x7E28, 0x7E2C, 0x7E2D, 0x7E2F, 0x7E33, 0x7E36, 0x7E3F, 0x7E44,
+ 0x7E45, 0x7E47, 0x7E4E, 0x7E50, 0x7E52, 0x7E58, 0x7E5F, 0x7E61,
+ 0x7E62, 0x7E65, 0x7E6B, 0x7E6E, 0x7E6F, 0x7E73, 0x7E78, 0x7E7E,
+ 0x7E81, 0x7E86, 0x7E87, 0x7E8A, 0x7E8D, 0x7E91, 0x7E95, 0x7E98,
+ 0x7E9A, 0x7E9D, 0x7E9E, 0x7F3C, 0x7F3B, 0x7F3D, 0x7F3E, 0x7F3F,
+ 0x7F43, 0x7F44, 0x7F47, 0x7F4F, 0x7F52, 0x7F53, 0x7F5B, 0x7F5C,
+ 0x7F5D, 0x7F61, 0x7F63, 0x7F64, 0x7F65, 0x7F66, 0x7F6D,
+};
+const unsigned short euc_to_utf8_8FD5[] = {
+ 0x7F71, 0x7F7D, 0x7F7E, 0x7F7F, 0x7F80, 0x7F8B, 0x7F8D,
+ 0x7F8F, 0x7F90, 0x7F91, 0x7F96, 0x7F97, 0x7F9C, 0x7FA1, 0x7FA2,
+ 0x7FA6, 0x7FAA, 0x7FAD, 0x7FB4, 0x7FBC, 0x7FBF, 0x7FC0, 0x7FC3,
+ 0x7FC8, 0x7FCE, 0x7FCF, 0x7FDB, 0x7FDF, 0x7FE3, 0x7FE5, 0x7FE8,
+ 0x7FEC, 0x7FEE, 0x7FEF, 0x7FF2, 0x7FFA, 0x7FFD, 0x7FFE, 0x7FFF,
+ 0x8007, 0x8008, 0x800A, 0x800D, 0x800E, 0x800F, 0x8011, 0x8013,
+ 0x8014, 0x8016, 0x801D, 0x801E, 0x801F, 0x8020, 0x8024, 0x8026,
+ 0x802C, 0x802E, 0x8030, 0x8034, 0x8035, 0x8037, 0x8039, 0x803A,
+ 0x803C, 0x803E, 0x8040, 0x8044, 0x8060, 0x8064, 0x8066, 0x806D,
+ 0x8071, 0x8075, 0x8081, 0x8088, 0x808E, 0x809C, 0x809E, 0x80A6,
+ 0x80A7, 0x80AB, 0x80B8, 0x80B9, 0x80C8, 0x80CD, 0x80CF, 0x80D2,
+ 0x80D4, 0x80D5, 0x80D7, 0x80D8, 0x80E0, 0x80ED, 0x80EE,
+};
+const unsigned short euc_to_utf8_8FD6[] = {
+ 0x80F0, 0x80F2, 0x80F3, 0x80F6, 0x80F9, 0x80FA, 0x80FE,
+ 0x8103, 0x810B, 0x8116, 0x8117, 0x8118, 0x811C, 0x811E, 0x8120,
+ 0x8124, 0x8127, 0x812C, 0x8130, 0x8135, 0x813A, 0x813C, 0x8145,
+ 0x8147, 0x814A, 0x814C, 0x8152, 0x8157, 0x8160, 0x8161, 0x8167,
+ 0x8168, 0x8169, 0x816D, 0x816F, 0x8177, 0x8181, 0x8190, 0x8184,
+ 0x8185, 0x8186, 0x818B, 0x818E, 0x8196, 0x8198, 0x819B, 0x819E,
+ 0x81A2, 0x81AE, 0x81B2, 0x81B4, 0x81BB, 0x81CB, 0x81C3, 0x81C5,
+ 0x81CA, 0x81CE, 0x81CF, 0x81D5, 0x81D7, 0x81DB, 0x81DD, 0x81DE,
+ 0x81E1, 0x81E4, 0x81EB, 0x81EC, 0x81F0, 0x81F1, 0x81F2, 0x81F5,
+ 0x81F6, 0x81F8, 0x81F9, 0x81FD, 0x81FF, 0x8200, 0x8203, 0x820F,
+ 0x8213, 0x8214, 0x8219, 0x821A, 0x821D, 0x8221, 0x8222, 0x8228,
+ 0x8232, 0x8234, 0x823A, 0x8243, 0x8244, 0x8245, 0x8246,
+};
+const unsigned short euc_to_utf8_8FD7[] = {
+ 0x824B, 0x824E, 0x824F, 0x8251, 0x8256, 0x825C, 0x8260,
+ 0x8263, 0x8267, 0x826D, 0x8274, 0x827B, 0x827D, 0x827F, 0x8280,
+ 0x8281, 0x8283, 0x8284, 0x8287, 0x8289, 0x828A, 0x828E, 0x8291,
+ 0x8294, 0x8296, 0x8298, 0x829A, 0x829B, 0x82A0, 0x82A1, 0x82A3,
+ 0x82A4, 0x82A7, 0x82A8, 0x82A9, 0x82AA, 0x82AE, 0x82B0, 0x82B2,
+ 0x82B4, 0x82B7, 0x82BA, 0x82BC, 0x82BE, 0x82BF, 0x82C6, 0x82D0,
+ 0x82D5, 0x82DA, 0x82E0, 0x82E2, 0x82E4, 0x82E8, 0x82EA, 0x82ED,
+ 0x82EF, 0x82F6, 0x82F7, 0x82FD, 0x82FE, 0x8300, 0x8301, 0x8307,
+ 0x8308, 0x830A, 0x830B, 0x8354, 0x831B, 0x831D, 0x831E, 0x831F,
+ 0x8321, 0x8322, 0x832C, 0x832D, 0x832E, 0x8330, 0x8333, 0x8337,
+ 0x833A, 0x833C, 0x833D, 0x8342, 0x8343, 0x8344, 0x8347, 0x834D,
+ 0x834E, 0x8351, 0x8355, 0x8356, 0x8357, 0x8370, 0x8378,
+};
+const unsigned short euc_to_utf8_8FD8[] = {
+ 0x837D, 0x837F, 0x8380, 0x8382, 0x8384, 0x8386, 0x838D,
+ 0x8392, 0x8394, 0x8395, 0x8398, 0x8399, 0x839B, 0x839C, 0x839D,
+ 0x83A6, 0x83A7, 0x83A9, 0x83AC, 0x83BE, 0x83BF, 0x83C0, 0x83C7,
+ 0x83C9, 0x83CF, 0x83D0, 0x83D1, 0x83D4, 0x83DD, 0x8353, 0x83E8,
+ 0x83EA, 0x83F6, 0x83F8, 0x83F9, 0x83FC, 0x8401, 0x8406, 0x840A,
+ 0x840F, 0x8411, 0x8415, 0x8419, 0x83AD, 0x842F, 0x8439, 0x8445,
+ 0x8447, 0x8448, 0x844A, 0x844D, 0x844F, 0x8451, 0x8452, 0x8456,
+ 0x8458, 0x8459, 0x845A, 0x845C, 0x8460, 0x8464, 0x8465, 0x8467,
+ 0x846A, 0x8470, 0x8473, 0x8474, 0x8476, 0x8478, 0x847C, 0x847D,
+ 0x8481, 0x8485, 0x8492, 0x8493, 0x8495, 0x849E, 0x84A6, 0x84A8,
+ 0x84A9, 0x84AA, 0x84AF, 0x84B1, 0x84B4, 0x84BA, 0x84BD, 0x84BE,
+ 0x84C0, 0x84C2, 0x84C7, 0x84C8, 0x84CC, 0x84CF, 0x84D3,
+};
+const unsigned short euc_to_utf8_8FD9[] = {
+ 0x84DC, 0x84E7, 0x84EA, 0x84EF, 0x84F0, 0x84F1, 0x84F2,
+ 0x84F7, 0x8532, 0x84FA, 0x84FB, 0x84FD, 0x8502, 0x8503, 0x8507,
+ 0x850C, 0x850E, 0x8510, 0x851C, 0x851E, 0x8522, 0x8523, 0x8524,
+ 0x8525, 0x8527, 0x852A, 0x852B, 0x852F, 0x8533, 0x8534, 0x8536,
+ 0x853F, 0x8546, 0x854F, 0x8550, 0x8551, 0x8552, 0x8553, 0x8556,
+ 0x8559, 0x855C, 0x855D, 0x855E, 0x855F, 0x8560, 0x8561, 0x8562,
+ 0x8564, 0x856B, 0x856F, 0x8579, 0x857A, 0x857B, 0x857D, 0x857F,
+ 0x8581, 0x8585, 0x8586, 0x8589, 0x858B, 0x858C, 0x858F, 0x8593,
+ 0x8598, 0x859D, 0x859F, 0x85A0, 0x85A2, 0x85A5, 0x85A7, 0x85B4,
+ 0x85B6, 0x85B7, 0x85B8, 0x85BC, 0x85BD, 0x85BE, 0x85BF, 0x85C2,
+ 0x85C7, 0x85CA, 0x85CB, 0x85CE, 0x85AD, 0x85D8, 0x85DA, 0x85DF,
+ 0x85E0, 0x85E6, 0x85E8, 0x85ED, 0x85F3, 0x85F6, 0x85FC,
+};
+const unsigned short euc_to_utf8_8FDA[] = {
+ 0x85FF, 0x8600, 0x8604, 0x8605, 0x860D, 0x860E, 0x8610,
+ 0x8611, 0x8612, 0x8618, 0x8619, 0x861B, 0x861E, 0x8621, 0x8627,
+ 0x8629, 0x8636, 0x8638, 0x863A, 0x863C, 0x863D, 0x8640, 0x8642,
+ 0x8646, 0x8652, 0x8653, 0x8656, 0x8657, 0x8658, 0x8659, 0x865D,
+ 0x8660, 0x8661, 0x8662, 0x8663, 0x8664, 0x8669, 0x866C, 0x866F,
+ 0x8675, 0x8676, 0x8677, 0x867A, 0x868D, 0x8691, 0x8696, 0x8698,
+ 0x869A, 0x869C, 0x86A1, 0x86A6, 0x86A7, 0x86A8, 0x86AD, 0x86B1,
+ 0x86B3, 0x86B4, 0x86B5, 0x86B7, 0x86B8, 0x86B9, 0x86BF, 0x86C0,
+ 0x86C1, 0x86C3, 0x86C5, 0x86D1, 0x86D2, 0x86D5, 0x86D7, 0x86DA,
+ 0x86DC, 0x86E0, 0x86E3, 0x86E5, 0x86E7, 0x8688, 0x86FA, 0x86FC,
+ 0x86FD, 0x8704, 0x8705, 0x8707, 0x870B, 0x870E, 0x870F, 0x8710,
+ 0x8713, 0x8714, 0x8719, 0x871E, 0x871F, 0x8721, 0x8723,
+};
+const unsigned short euc_to_utf8_8FDB[] = {
+ 0x8728, 0x872E, 0x872F, 0x8731, 0x8732, 0x8739, 0x873A,
+ 0x873C, 0x873D, 0x873E, 0x8740, 0x8743, 0x8745, 0x874D, 0x8758,
+ 0x875D, 0x8761, 0x8764, 0x8765, 0x876F, 0x8771, 0x8772, 0x877B,
+ 0x8783, 0x8784, 0x8785, 0x8786, 0x8787, 0x8788, 0x8789, 0x878B,
+ 0x878C, 0x8790, 0x8793, 0x8795, 0x8797, 0x8798, 0x8799, 0x879E,
+ 0x87A0, 0x87A3, 0x87A7, 0x87AC, 0x87AD, 0x87AE, 0x87B1, 0x87B5,
+ 0x87BE, 0x87BF, 0x87C1, 0x87C8, 0x87C9, 0x87CA, 0x87CE, 0x87D5,
+ 0x87D6, 0x87D9, 0x87DA, 0x87DC, 0x87DF, 0x87E2, 0x87E3, 0x87E4,
+ 0x87EA, 0x87EB, 0x87ED, 0x87F1, 0x87F3, 0x87F8, 0x87FA, 0x87FF,
+ 0x8801, 0x8803, 0x8806, 0x8809, 0x880A, 0x880B, 0x8810, 0x8819,
+ 0x8812, 0x8813, 0x8814, 0x8818, 0x881A, 0x881B, 0x881C, 0x881E,
+ 0x881F, 0x8828, 0x882D, 0x882E, 0x8830, 0x8832, 0x8835,
+};
+const unsigned short euc_to_utf8_8FDC[] = {
+ 0x883A, 0x883C, 0x8841, 0x8843, 0x8845, 0x8848, 0x8849,
+ 0x884A, 0x884B, 0x884E, 0x8851, 0x8855, 0x8856, 0x8858, 0x885A,
+ 0x885C, 0x885F, 0x8860, 0x8864, 0x8869, 0x8871, 0x8879, 0x887B,
+ 0x8880, 0x8898, 0x889A, 0x889B, 0x889C, 0x889F, 0x88A0, 0x88A8,
+ 0x88AA, 0x88BA, 0x88BD, 0x88BE, 0x88C0, 0x88CA, 0x88CB, 0x88CC,
+ 0x88CD, 0x88CE, 0x88D1, 0x88D2, 0x88D3, 0x88DB, 0x88DE, 0x88E7,
+ 0x88EF, 0x88F0, 0x88F1, 0x88F5, 0x88F7, 0x8901, 0x8906, 0x890D,
+ 0x890E, 0x890F, 0x8915, 0x8916, 0x8918, 0x8919, 0x891A, 0x891C,
+ 0x8920, 0x8926, 0x8927, 0x8928, 0x8930, 0x8931, 0x8932, 0x8935,
+ 0x8939, 0x893A, 0x893E, 0x8940, 0x8942, 0x8945, 0x8946, 0x8949,
+ 0x894F, 0x8952, 0x8957, 0x895A, 0x895B, 0x895C, 0x8961, 0x8962,
+ 0x8963, 0x896B, 0x896E, 0x8970, 0x8973, 0x8975, 0x897A,
+};
+const unsigned short euc_to_utf8_8FDD[] = {
+ 0x897B, 0x897C, 0x897D, 0x8989, 0x898D, 0x8990, 0x8994,
+ 0x8995, 0x899B, 0x899C, 0x899F, 0x89A0, 0x89A5, 0x89B0, 0x89B4,
+ 0x89B5, 0x89B6, 0x89B7, 0x89BC, 0x89D4, 0x89D5, 0x89D6, 0x89D7,
+ 0x89D8, 0x89E5, 0x89E9, 0x89EB, 0x89ED, 0x89F1, 0x89F3, 0x89F6,
+ 0x89F9, 0x89FD, 0x89FF, 0x8A04, 0x8A05, 0x8A07, 0x8A0F, 0x8A11,
+ 0x8A12, 0x8A14, 0x8A15, 0x8A1E, 0x8A20, 0x8A22, 0x8A24, 0x8A26,
+ 0x8A2B, 0x8A2C, 0x8A2F, 0x8A35, 0x8A37, 0x8A3D, 0x8A3E, 0x8A40,
+ 0x8A43, 0x8A45, 0x8A47, 0x8A49, 0x8A4D, 0x8A4E, 0x8A53, 0x8A56,
+ 0x8A57, 0x8A58, 0x8A5C, 0x8A5D, 0x8A61, 0x8A65, 0x8A67, 0x8A75,
+ 0x8A76, 0x8A77, 0x8A79, 0x8A7A, 0x8A7B, 0x8A7E, 0x8A7F, 0x8A80,
+ 0x8A83, 0x8A86, 0x8A8B, 0x8A8F, 0x8A90, 0x8A92, 0x8A96, 0x8A97,
+ 0x8A99, 0x8A9F, 0x8AA7, 0x8AA9, 0x8AAE, 0x8AAF, 0x8AB3,
+};
+const unsigned short euc_to_utf8_8FDE[] = {
+ 0x8AB6, 0x8AB7, 0x8ABB, 0x8ABE, 0x8AC3, 0x8AC6, 0x8AC8,
+ 0x8AC9, 0x8ACA, 0x8AD1, 0x8AD3, 0x8AD4, 0x8AD5, 0x8AD7, 0x8ADD,
+ 0x8ADF, 0x8AEC, 0x8AF0, 0x8AF4, 0x8AF5, 0x8AF6, 0x8AFC, 0x8AFF,
+ 0x8B05, 0x8B06, 0x8B0B, 0x8B11, 0x8B1C, 0x8B1E, 0x8B1F, 0x8B0A,
+ 0x8B2D, 0x8B30, 0x8B37, 0x8B3C, 0x8B42, 0x8B43, 0x8B44, 0x8B45,
+ 0x8B46, 0x8B48, 0x8B52, 0x8B53, 0x8B54, 0x8B59, 0x8B4D, 0x8B5E,
+ 0x8B63, 0x8B6D, 0x8B76, 0x8B78, 0x8B79, 0x8B7C, 0x8B7E, 0x8B81,
+ 0x8B84, 0x8B85, 0x8B8B, 0x8B8D, 0x8B8F, 0x8B94, 0x8B95, 0x8B9C,
+ 0x8B9E, 0x8B9F, 0x8C38, 0x8C39, 0x8C3D, 0x8C3E, 0x8C45, 0x8C47,
+ 0x8C49, 0x8C4B, 0x8C4F, 0x8C51, 0x8C53, 0x8C54, 0x8C57, 0x8C58,
+ 0x8C5B, 0x8C5D, 0x8C59, 0x8C63, 0x8C64, 0x8C66, 0x8C68, 0x8C69,
+ 0x8C6D, 0x8C73, 0x8C75, 0x8C76, 0x8C7B, 0x8C7E, 0x8C86,
+};
+const unsigned short euc_to_utf8_8FDF[] = {
+ 0x8C87, 0x8C8B, 0x8C90, 0x8C92, 0x8C93, 0x8C99, 0x8C9B,
+ 0x8C9C, 0x8CA4, 0x8CB9, 0x8CBA, 0x8CC5, 0x8CC6, 0x8CC9, 0x8CCB,
+ 0x8CCF, 0x8CD6, 0x8CD5, 0x8CD9, 0x8CDD, 0x8CE1, 0x8CE8, 0x8CEC,
+ 0x8CEF, 0x8CF0, 0x8CF2, 0x8CF5, 0x8CF7, 0x8CF8, 0x8CFE, 0x8CFF,
+ 0x8D01, 0x8D03, 0x8D09, 0x8D12, 0x8D17, 0x8D1B, 0x8D65, 0x8D69,
+ 0x8D6C, 0x8D6E, 0x8D7F, 0x8D82, 0x8D84, 0x8D88, 0x8D8D, 0x8D90,
+ 0x8D91, 0x8D95, 0x8D9E, 0x8D9F, 0x8DA0, 0x8DA6, 0x8DAB, 0x8DAC,
+ 0x8DAF, 0x8DB2, 0x8DB5, 0x8DB7, 0x8DB9, 0x8DBB, 0x8DC0, 0x8DC5,
+ 0x8DC6, 0x8DC7, 0x8DC8, 0x8DCA, 0x8DCE, 0x8DD1, 0x8DD4, 0x8DD5,
+ 0x8DD7, 0x8DD9, 0x8DE4, 0x8DE5, 0x8DE7, 0x8DEC, 0x8DF0, 0x8DBC,
+ 0x8DF1, 0x8DF2, 0x8DF4, 0x8DFD, 0x8E01, 0x8E04, 0x8E05, 0x8E06,
+ 0x8E0B, 0x8E11, 0x8E14, 0x8E16, 0x8E20, 0x8E21, 0x8E22,
+};
+const unsigned short euc_to_utf8_8FE0[] = {
+ 0x8E23, 0x8E26, 0x8E27, 0x8E31, 0x8E33, 0x8E36, 0x8E37,
+ 0x8E38, 0x8E39, 0x8E3D, 0x8E40, 0x8E41, 0x8E4B, 0x8E4D, 0x8E4E,
+ 0x8E4F, 0x8E54, 0x8E5B, 0x8E5C, 0x8E5D, 0x8E5E, 0x8E61, 0x8E62,
+ 0x8E69, 0x8E6C, 0x8E6D, 0x8E6F, 0x8E70, 0x8E71, 0x8E79, 0x8E7A,
+ 0x8E7B, 0x8E82, 0x8E83, 0x8E89, 0x8E90, 0x8E92, 0x8E95, 0x8E9A,
+ 0x8E9B, 0x8E9D, 0x8E9E, 0x8EA2, 0x8EA7, 0x8EA9, 0x8EAD, 0x8EAE,
+ 0x8EB3, 0x8EB5, 0x8EBA, 0x8EBB, 0x8EC0, 0x8EC1, 0x8EC3, 0x8EC4,
+ 0x8EC7, 0x8ECF, 0x8ED1, 0x8ED4, 0x8EDC, 0x8EE8, 0x8EEE, 0x8EF0,
+ 0x8EF1, 0x8EF7, 0x8EF9, 0x8EFA, 0x8EED, 0x8F00, 0x8F02, 0x8F07,
+ 0x8F08, 0x8F0F, 0x8F10, 0x8F16, 0x8F17, 0x8F18, 0x8F1E, 0x8F20,
+ 0x8F21, 0x8F23, 0x8F25, 0x8F27, 0x8F28, 0x8F2C, 0x8F2D, 0x8F2E,
+ 0x8F34, 0x8F35, 0x8F36, 0x8F37, 0x8F3A, 0x8F40, 0x8F41,
+};
+const unsigned short euc_to_utf8_8FE1[] = {
+ 0x8F43, 0x8F47, 0x8F4F, 0x8F51, 0x8F52, 0x8F53, 0x8F54,
+ 0x8F55, 0x8F58, 0x8F5D, 0x8F5E, 0x8F65, 0x8F9D, 0x8FA0, 0x8FA1,
+ 0x8FA4, 0x8FA5, 0x8FA6, 0x8FB5, 0x8FB6, 0x8FB8, 0x8FBE, 0x8FC0,
+ 0x8FC1, 0x8FC6, 0x8FCA, 0x8FCB, 0x8FCD, 0x8FD0, 0x8FD2, 0x8FD3,
+ 0x8FD5, 0x8FE0, 0x8FE3, 0x8FE4, 0x8FE8, 0x8FEE, 0x8FF1, 0x8FF5,
+ 0x8FF6, 0x8FFB, 0x8FFE, 0x9002, 0x9004, 0x9008, 0x900C, 0x9018,
+ 0x901B, 0x9028, 0x9029, 0x902F, 0x902A, 0x902C, 0x902D, 0x9033,
+ 0x9034, 0x9037, 0x903F, 0x9043, 0x9044, 0x904C, 0x905B, 0x905D,
+ 0x9062, 0x9066, 0x9067, 0x906C, 0x9070, 0x9074, 0x9079, 0x9085,
+ 0x9088, 0x908B, 0x908C, 0x908E, 0x9090, 0x9095, 0x9097, 0x9098,
+ 0x9099, 0x909B, 0x90A0, 0x90A1, 0x90A2, 0x90A5, 0x90B0, 0x90B2,
+ 0x90B3, 0x90B4, 0x90B6, 0x90BD, 0x90CC, 0x90BE, 0x90C3,
+};
+const unsigned short euc_to_utf8_8FE2[] = {
+ 0x90C4, 0x90C5, 0x90C7, 0x90C8, 0x90D5, 0x90D7, 0x90D8,
+ 0x90D9, 0x90DC, 0x90DD, 0x90DF, 0x90E5, 0x90D2, 0x90F6, 0x90EB,
+ 0x90EF, 0x90F0, 0x90F4, 0x90FE, 0x90FF, 0x9100, 0x9104, 0x9105,
+ 0x9106, 0x9108, 0x910D, 0x9110, 0x9114, 0x9116, 0x9117, 0x9118,
+ 0x911A, 0x911C, 0x911E, 0x9120, 0x9125, 0x9122, 0x9123, 0x9127,
+ 0x9129, 0x912E, 0x912F, 0x9131, 0x9134, 0x9136, 0x9137, 0x9139,
+ 0x913A, 0x913C, 0x913D, 0x9143, 0x9147, 0x9148, 0x914F, 0x9153,
+ 0x9157, 0x9159, 0x915A, 0x915B, 0x9161, 0x9164, 0x9167, 0x916D,
+ 0x9174, 0x9179, 0x917A, 0x917B, 0x9181, 0x9183, 0x9185, 0x9186,
+ 0x918A, 0x918E, 0x9191, 0x9193, 0x9194, 0x9195, 0x9198, 0x919E,
+ 0x91A1, 0x91A6, 0x91A8, 0x91AC, 0x91AD, 0x91AE, 0x91B0, 0x91B1,
+ 0x91B2, 0x91B3, 0x91B6, 0x91BB, 0x91BC, 0x91BD, 0x91BF,
+};
+const unsigned short euc_to_utf8_8FE3[] = {
+ 0x91C2, 0x91C3, 0x91C5, 0x91D3, 0x91D4, 0x91D7, 0x91D9,
+ 0x91DA, 0x91DE, 0x91E4, 0x91E5, 0x91E9, 0x91EA, 0x91EC, 0x91ED,
+ 0x91EE, 0x91EF, 0x91F0, 0x91F1, 0x91F7, 0x91F9, 0x91FB, 0x91FD,
+ 0x9200, 0x9201, 0x9204, 0x9205, 0x9206, 0x9207, 0x9209, 0x920A,
+ 0x920C, 0x9210, 0x9212, 0x9213, 0x9216, 0x9218, 0x921C, 0x921D,
+ 0x9223, 0x9224, 0x9225, 0x9226, 0x9228, 0x922E, 0x922F, 0x9230,
+ 0x9233, 0x9235, 0x9236, 0x9238, 0x9239, 0x923A, 0x923C, 0x923E,
+ 0x9240, 0x9242, 0x9243, 0x9246, 0x9247, 0x924A, 0x924D, 0x924E,
+ 0x924F, 0x9251, 0x9258, 0x9259, 0x925C, 0x925D, 0x9260, 0x9261,
+ 0x9265, 0x9267, 0x9268, 0x9269, 0x926E, 0x926F, 0x9270, 0x9275,
+ 0x9276, 0x9277, 0x9278, 0x9279, 0x927B, 0x927C, 0x927D, 0x927F,
+ 0x9288, 0x9289, 0x928A, 0x928D, 0x928E, 0x9292, 0x9297,
+};
+const unsigned short euc_to_utf8_8FE4[] = {
+ 0x9299, 0x929F, 0x92A0, 0x92A4, 0x92A5, 0x92A7, 0x92A8,
+ 0x92AB, 0x92AF, 0x92B2, 0x92B6, 0x92B8, 0x92BA, 0x92BB, 0x92BC,
+ 0x92BD, 0x92BF, 0x92C0, 0x92C1, 0x92C2, 0x92C3, 0x92C5, 0x92C6,
+ 0x92C7, 0x92C8, 0x92CB, 0x92CC, 0x92CD, 0x92CE, 0x92D0, 0x92D3,
+ 0x92D5, 0x92D7, 0x92D8, 0x92D9, 0x92DC, 0x92DD, 0x92DF, 0x92E0,
+ 0x92E1, 0x92E3, 0x92E5, 0x92E7, 0x92E8, 0x92EC, 0x92EE, 0x92F0,
+ 0x92F9, 0x92FB, 0x92FF, 0x9300, 0x9302, 0x9308, 0x930D, 0x9311,
+ 0x9314, 0x9315, 0x931C, 0x931D, 0x931E, 0x931F, 0x9321, 0x9324,
+ 0x9325, 0x9327, 0x9329, 0x932A, 0x9333, 0x9334, 0x9336, 0x9337,
+ 0x9347, 0x9348, 0x9349, 0x9350, 0x9351, 0x9352, 0x9355, 0x9357,
+ 0x9358, 0x935A, 0x935E, 0x9364, 0x9365, 0x9367, 0x9369, 0x936A,
+ 0x936D, 0x936F, 0x9370, 0x9371, 0x9373, 0x9374, 0x9376,
+};
+const unsigned short euc_to_utf8_8FE5[] = {
+ 0x937A, 0x937D, 0x937F, 0x9380, 0x9381, 0x9382, 0x9388,
+ 0x938A, 0x938B, 0x938D, 0x938F, 0x9392, 0x9395, 0x9398, 0x939B,
+ 0x939E, 0x93A1, 0x93A3, 0x93A4, 0x93A6, 0x93A8, 0x93AB, 0x93B4,
+ 0x93B5, 0x93B6, 0x93BA, 0x93A9, 0x93C1, 0x93C4, 0x93C5, 0x93C6,
+ 0x93C7, 0x93C9, 0x93CA, 0x93CB, 0x93CC, 0x93CD, 0x93D3, 0x93D9,
+ 0x93DC, 0x93DE, 0x93DF, 0x93E2, 0x93E6, 0x93E7, 0x93F9, 0x93F7,
+ 0x93F8, 0x93FA, 0x93FB, 0x93FD, 0x9401, 0x9402, 0x9404, 0x9408,
+ 0x9409, 0x940D, 0x940E, 0x940F, 0x9415, 0x9416, 0x9417, 0x941F,
+ 0x942E, 0x942F, 0x9431, 0x9432, 0x9433, 0x9434, 0x943B, 0x943F,
+ 0x943D, 0x9443, 0x9445, 0x9448, 0x944A, 0x944C, 0x9455, 0x9459,
+ 0x945C, 0x945F, 0x9461, 0x9463, 0x9468, 0x946B, 0x946D, 0x946E,
+ 0x946F, 0x9471, 0x9472, 0x9484, 0x9483, 0x9578, 0x9579,
+};
+const unsigned short euc_to_utf8_8FE6[] = {
+ 0x957E, 0x9584, 0x9588, 0x958C, 0x958D, 0x958E, 0x959D,
+ 0x959E, 0x959F, 0x95A1, 0x95A6, 0x95A9, 0x95AB, 0x95AC, 0x95B4,
+ 0x95B6, 0x95BA, 0x95BD, 0x95BF, 0x95C6, 0x95C8, 0x95C9, 0x95CB,
+ 0x95D0, 0x95D1, 0x95D2, 0x95D3, 0x95D9, 0x95DA, 0x95DD, 0x95DE,
+ 0x95DF, 0x95E0, 0x95E4, 0x95E6, 0x961D, 0x961E, 0x9622, 0x9624,
+ 0x9625, 0x9626, 0x962C, 0x9631, 0x9633, 0x9637, 0x9638, 0x9639,
+ 0x963A, 0x963C, 0x963D, 0x9641, 0x9652, 0x9654, 0x9656, 0x9657,
+ 0x9658, 0x9661, 0x966E, 0x9674, 0x967B, 0x967C, 0x967E, 0x967F,
+ 0x9681, 0x9682, 0x9683, 0x9684, 0x9689, 0x9691, 0x9696, 0x969A,
+ 0x969D, 0x969F, 0x96A4, 0x96A5, 0x96A6, 0x96A9, 0x96AE, 0x96AF,
+ 0x96B3, 0x96BA, 0x96CA, 0x96D2, 0x5DB2, 0x96D8, 0x96DA, 0x96DD,
+ 0x96DE, 0x96DF, 0x96E9, 0x96EF, 0x96F1, 0x96FA, 0x9702,
+};
+const unsigned short euc_to_utf8_8FE7[] = {
+ 0x9703, 0x9705, 0x9709, 0x971A, 0x971B, 0x971D, 0x9721,
+ 0x9722, 0x9723, 0x9728, 0x9731, 0x9733, 0x9741, 0x9743, 0x974A,
+ 0x974E, 0x974F, 0x9755, 0x9757, 0x9758, 0x975A, 0x975B, 0x9763,
+ 0x9767, 0x976A, 0x976E, 0x9773, 0x9776, 0x9777, 0x9778, 0x977B,
+ 0x977D, 0x977F, 0x9780, 0x9789, 0x9795, 0x9796, 0x9797, 0x9799,
+ 0x979A, 0x979E, 0x979F, 0x97A2, 0x97AC, 0x97AE, 0x97B1, 0x97B2,
+ 0x97B5, 0x97B6, 0x97B8, 0x97B9, 0x97BA, 0x97BC, 0x97BE, 0x97BF,
+ 0x97C1, 0x97C4, 0x97C5, 0x97C7, 0x97C9, 0x97CA, 0x97CC, 0x97CD,
+ 0x97CE, 0x97D0, 0x97D1, 0x97D4, 0x97D7, 0x97D8, 0x97D9, 0x97DD,
+ 0x97DE, 0x97E0, 0x97DB, 0x97E1, 0x97E4, 0x97EF, 0x97F1, 0x97F4,
+ 0x97F7, 0x97F8, 0x97FA, 0x9807, 0x980A, 0x9819, 0x980D, 0x980E,
+ 0x9814, 0x9816, 0x981C, 0x981E, 0x9820, 0x9823, 0x9826,
+};
+const unsigned short euc_to_utf8_8FE8[] = {
+ 0x982B, 0x982E, 0x982F, 0x9830, 0x9832, 0x9833, 0x9835,
+ 0x9825, 0x983E, 0x9844, 0x9847, 0x984A, 0x9851, 0x9852, 0x9853,
+ 0x9856, 0x9857, 0x9859, 0x985A, 0x9862, 0x9863, 0x9865, 0x9866,
+ 0x986A, 0x986C, 0x98AB, 0x98AD, 0x98AE, 0x98B0, 0x98B4, 0x98B7,
+ 0x98B8, 0x98BA, 0x98BB, 0x98BF, 0x98C2, 0x98C5, 0x98C8, 0x98CC,
+ 0x98E1, 0x98E3, 0x98E5, 0x98E6, 0x98E7, 0x98EA, 0x98F3, 0x98F6,
+ 0x9902, 0x9907, 0x9908, 0x9911, 0x9915, 0x9916, 0x9917, 0x991A,
+ 0x991B, 0x991C, 0x991F, 0x9922, 0x9926, 0x9927, 0x992B, 0x9931,
+ 0x9932, 0x9933, 0x9934, 0x9935, 0x9939, 0x993A, 0x993B, 0x993C,
+ 0x9940, 0x9941, 0x9946, 0x9947, 0x9948, 0x994D, 0x994E, 0x9954,
+ 0x9958, 0x9959, 0x995B, 0x995C, 0x995E, 0x995F, 0x9960, 0x999B,
+ 0x999D, 0x999F, 0x99A6, 0x99B0, 0x99B1, 0x99B2, 0x99B5,
+};
+const unsigned short euc_to_utf8_8FE9[] = {
+ 0x99B9, 0x99BA, 0x99BD, 0x99BF, 0x99C3, 0x99C9, 0x99D3,
+ 0x99D4, 0x99D9, 0x99DA, 0x99DC, 0x99DE, 0x99E7, 0x99EA, 0x99EB,
+ 0x99EC, 0x99F0, 0x99F4, 0x99F5, 0x99F9, 0x99FD, 0x99FE, 0x9A02,
+ 0x9A03, 0x9A04, 0x9A0B, 0x9A0C, 0x9A10, 0x9A11, 0x9A16, 0x9A1E,
+ 0x9A20, 0x9A22, 0x9A23, 0x9A24, 0x9A27, 0x9A2D, 0x9A2E, 0x9A33,
+ 0x9A35, 0x9A36, 0x9A38, 0x9A47, 0x9A41, 0x9A44, 0x9A4A, 0x9A4B,
+ 0x9A4C, 0x9A4E, 0x9A51, 0x9A54, 0x9A56, 0x9A5D, 0x9AAA, 0x9AAC,
+ 0x9AAE, 0x9AAF, 0x9AB2, 0x9AB4, 0x9AB5, 0x9AB6, 0x9AB9, 0x9ABB,
+ 0x9ABE, 0x9ABF, 0x9AC1, 0x9AC3, 0x9AC6, 0x9AC8, 0x9ACE, 0x9AD0,
+ 0x9AD2, 0x9AD5, 0x9AD6, 0x9AD7, 0x9ADB, 0x9ADC, 0x9AE0, 0x9AE4,
+ 0x9AE5, 0x9AE7, 0x9AE9, 0x9AEC, 0x9AF2, 0x9AF3, 0x9AF5, 0x9AF9,
+ 0x9AFA, 0x9AFD, 0x9AFF, 0x9B00, 0x9B01, 0x9B02, 0x9B03,
+};
+const unsigned short euc_to_utf8_8FEA[] = {
+ 0x9B04, 0x9B05, 0x9B08, 0x9B09, 0x9B0B, 0x9B0C, 0x9B0D,
+ 0x9B0E, 0x9B10, 0x9B12, 0x9B16, 0x9B19, 0x9B1B, 0x9B1C, 0x9B20,
+ 0x9B26, 0x9B2B, 0x9B2D, 0x9B33, 0x9B34, 0x9B35, 0x9B37, 0x9B39,
+ 0x9B3A, 0x9B3D, 0x9B48, 0x9B4B, 0x9B4C, 0x9B55, 0x9B56, 0x9B57,
+ 0x9B5B, 0x9B5E, 0x9B61, 0x9B63, 0x9B65, 0x9B66, 0x9B68, 0x9B6A,
+ 0x9B6B, 0x9B6C, 0x9B6D, 0x9B6E, 0x9B73, 0x9B75, 0x9B77, 0x9B78,
+ 0x9B79, 0x9B7F, 0x9B80, 0x9B84, 0x9B85, 0x9B86, 0x9B87, 0x9B89,
+ 0x9B8A, 0x9B8B, 0x9B8D, 0x9B8F, 0x9B90, 0x9B94, 0x9B9A, 0x9B9D,
+ 0x9B9E, 0x9BA6, 0x9BA7, 0x9BA9, 0x9BAC, 0x9BB0, 0x9BB1, 0x9BB2,
+ 0x9BB7, 0x9BB8, 0x9BBB, 0x9BBC, 0x9BBE, 0x9BBF, 0x9BC1, 0x9BC7,
+ 0x9BC8, 0x9BCE, 0x9BD0, 0x9BD7, 0x9BD8, 0x9BDD, 0x9BDF, 0x9BE5,
+ 0x9BE7, 0x9BEA, 0x9BEB, 0x9BEF, 0x9BF3, 0x9BF7, 0x9BF8,
+};
+const unsigned short euc_to_utf8_8FEB[] = {
+ 0x9BF9, 0x9BFA, 0x9BFD, 0x9BFF, 0x9C00, 0x9C02, 0x9C0B,
+ 0x9C0F, 0x9C11, 0x9C16, 0x9C18, 0x9C19, 0x9C1A, 0x9C1C, 0x9C1E,
+ 0x9C22, 0x9C23, 0x9C26, 0x9C27, 0x9C28, 0x9C29, 0x9C2A, 0x9C31,
+ 0x9C35, 0x9C36, 0x9C37, 0x9C3D, 0x9C41, 0x9C43, 0x9C44, 0x9C45,
+ 0x9C49, 0x9C4A, 0x9C4E, 0x9C4F, 0x9C50, 0x9C53, 0x9C54, 0x9C56,
+ 0x9C58, 0x9C5B, 0x9C5D, 0x9C5E, 0x9C5F, 0x9C63, 0x9C69, 0x9C6A,
+ 0x9C5C, 0x9C6B, 0x9C68, 0x9C6E, 0x9C70, 0x9C72, 0x9C75, 0x9C77,
+ 0x9C7B, 0x9CE6, 0x9CF2, 0x9CF7, 0x9CF9, 0x9D0B, 0x9D02, 0x9D11,
+ 0x9D17, 0x9D18, 0x9D1C, 0x9D1D, 0x9D1E, 0x9D2F, 0x9D30, 0x9D32,
+ 0x9D33, 0x9D34, 0x9D3A, 0x9D3C, 0x9D45, 0x9D3D, 0x9D42, 0x9D43,
+ 0x9D47, 0x9D4A, 0x9D53, 0x9D54, 0x9D5F, 0x9D63, 0x9D62, 0x9D65,
+ 0x9D69, 0x9D6A, 0x9D6B, 0x9D70, 0x9D76, 0x9D77, 0x9D7B,
+};
+const unsigned short euc_to_utf8_8FEC[] = {
+ 0x9D7C, 0x9D7E, 0x9D83, 0x9D84, 0x9D86, 0x9D8A, 0x9D8D,
+ 0x9D8E, 0x9D92, 0x9D93, 0x9D95, 0x9D96, 0x9D97, 0x9D98, 0x9DA1,
+ 0x9DAA, 0x9DAC, 0x9DAE, 0x9DB1, 0x9DB5, 0x9DB9, 0x9DBC, 0x9DBF,
+ 0x9DC3, 0x9DC7, 0x9DC9, 0x9DCA, 0x9DD4, 0x9DD5, 0x9DD6, 0x9DD7,
+ 0x9DDA, 0x9DDE, 0x9DDF, 0x9DE0, 0x9DE5, 0x9DE7, 0x9DE9, 0x9DEB,
+ 0x9DEE, 0x9DF0, 0x9DF3, 0x9DF4, 0x9DFE, 0x9E0A, 0x9E02, 0x9E07,
+ 0x9E0E, 0x9E10, 0x9E11, 0x9E12, 0x9E15, 0x9E16, 0x9E19, 0x9E1C,
+ 0x9E1D, 0x9E7A, 0x9E7B, 0x9E7C, 0x9E80, 0x9E82, 0x9E83, 0x9E84,
+ 0x9E85, 0x9E87, 0x9E8E, 0x9E8F, 0x9E96, 0x9E98, 0x9E9B, 0x9E9E,
+ 0x9EA4, 0x9EA8, 0x9EAC, 0x9EAE, 0x9EAF, 0x9EB0, 0x9EB3, 0x9EB4,
+ 0x9EB5, 0x9EC6, 0x9EC8, 0x9ECB, 0x9ED5, 0x9EDF, 0x9EE4, 0x9EE7,
+ 0x9EEC, 0x9EED, 0x9EEE, 0x9EF0, 0x9EF1, 0x9EF2, 0x9EF5,
+};
+const unsigned short euc_to_utf8_8FED[] = {
+ 0x9EF8, 0x9EFF, 0x9F02, 0x9F03, 0x9F09, 0x9F0F, 0x9F10,
+ 0x9F11, 0x9F12, 0x9F14, 0x9F16, 0x9F17, 0x9F19, 0x9F1A, 0x9F1B,
+ 0x9F1F, 0x9F22, 0x9F26, 0x9F2A, 0x9F2B, 0x9F2F, 0x9F31, 0x9F32,
+ 0x9F34, 0x9F37, 0x9F39, 0x9F3A, 0x9F3C, 0x9F3D, 0x9F3F, 0x9F41,
+ 0x9F43, 0x9F44, 0x9F45, 0x9F46, 0x9F47, 0x9F53, 0x9F55, 0x9F56,
+ 0x9F57, 0x9F58, 0x9F5A, 0x9F5D, 0x9F5E, 0x9F68, 0x9F69, 0x9F6D,
+ 0x9F6E, 0x9F6F, 0x9F70, 0x9F71, 0x9F73, 0x9F75, 0x9F7A, 0x9F7D,
+ 0x9F8F, 0x9F90, 0x9F91, 0x9F92, 0x9F94, 0x9F96, 0x9F97, 0x9F9E,
+ 0x9FA1, 0x9FA2, 0x9FA3, 0x9FA5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short euc_to_utf8_8FF3[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174,
+ 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x2160, 0x2161,
+};
+const unsigned short euc_to_utf8_8FF4[] = {
+ 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168,
+ 0x2169, 0xff07, 0xff02, 0x3231, 0x2116, 0x2121, 0x70bb, 0x4efc,
+ 0x50f4, 0x51ec, 0x5307, 0x5324, 0xfa0e, 0x548a, 0x5759, 0xfa0f,
+ 0xfa10, 0x589e, 0x5bec, 0x5cf5, 0x5d53, 0xfa11, 0x5fb7, 0x6085,
+ 0x6120, 0x654e, 0x663b, 0x6665, 0xfa12, 0xf929, 0x6801, 0xfa13,
+ 0xfa14, 0x6a6b, 0x6ae2, 0x6df8, 0x6df2, 0x7028, 0xfa15, 0xfa16,
+ 0x7501, 0x7682, 0x769e, 0xfa17, 0x7930, 0xfa18, 0xfa19, 0xfa1a,
+ 0xfa1b, 0x7ae7, 0xfa1c, 0xfa1d, 0x7da0, 0x7dd6, 0xfa1e, 0x8362,
+ 0xfa1f, 0x85b0, 0xfa20, 0xfa21, 0x8807, 0xfa22, 0x8b7f, 0x8cf4,
+ 0x8d76, 0xfa23, 0xfa24, 0xfa25, 0x90de, 0xfa26, 0x9115, 0xfa27,
+ 0xfa28, 0x9592, 0xf9dc, 0xfa29, 0x973b, 0x974d, 0x9751, 0xfa2a,
+ 0xfa2b, 0xfa2c, 0x999e, 0x9ad9, 0x9b72, 0xfa2d, 0x9ed1,
+};
+#endif /* X0212_ENABLE */
+
+const unsigned short euc_to_utf8_1byte[] = {
+ 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
+ 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
+ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
+ 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
+ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
+ 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
+ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
+ 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x00A9, 0x2122,
+};
+const unsigned short *const euc_to_utf8_2bytes[] = {
+ euc_to_utf8_A1, euc_to_utf8_A2, euc_to_utf8_A3,
+ euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7,
+ euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB,
+ euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF,
+ euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3,
+ euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7,
+ euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB,
+ euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF,
+ euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3,
+ euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7,
+ euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB,
+ euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF,
+ euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3,
+ euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7,
+ euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB,
+ euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF,
+ euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3,
+ euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7,
+ euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB,
+ euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF,
+ euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3,
+ euc_to_utf8_F4, euc_to_utf8_F5, 0, 0,
+ 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB,
+ euc_to_utf8_FC, 0, 0,
+};
+/* Microsoft UCS Mapping Compatible */
+const unsigned short *const euc_to_utf8_2bytes_ms[] = {
+ euc_to_utf8_A1_ms, euc_to_utf8_A2_ms, euc_to_utf8_A3,
+ euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7,
+ euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB,
+ euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF,
+ euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3,
+ euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7,
+ euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB,
+ euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF,
+ euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3,
+ euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7,
+ euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB,
+ euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF,
+ euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3,
+ euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7,
+ euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB,
+ euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF,
+ euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3,
+ euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7,
+ euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB,
+ euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF,
+ euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3,
+ euc_to_utf8_F4, euc_to_utf8_F5, 0, 0,
+ 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB,
+ euc_to_utf8_FC_ms, 0, 0,
+};
+
+#ifdef X0212_ENABLE
+const unsigned short *const x0212_to_utf8_2bytes[] = {
+ 0, euc_to_utf8_8FA2, 0,
+ 0, 0, euc_to_utf8_8FA6, euc_to_utf8_8FA7,
+ 0, euc_to_utf8_8FA9, euc_to_utf8_8FAA, euc_to_utf8_8FAB,
+ 0, 0, 0, 0,
+ euc_to_utf8_8FB0, euc_to_utf8_8FB1, euc_to_utf8_8FB2, euc_to_utf8_8FB3,
+ euc_to_utf8_8FB4, euc_to_utf8_8FB5, euc_to_utf8_8FB6, euc_to_utf8_8FB7,
+ euc_to_utf8_8FB8, euc_to_utf8_8FB9, euc_to_utf8_8FBA, euc_to_utf8_8FBB,
+ euc_to_utf8_8FBC, euc_to_utf8_8FBD, euc_to_utf8_8FBE, euc_to_utf8_8FBF,
+ euc_to_utf8_8FC0, euc_to_utf8_8FC1, euc_to_utf8_8FC2, euc_to_utf8_8FC3,
+ euc_to_utf8_8FC4, euc_to_utf8_8FC5, euc_to_utf8_8FC6, euc_to_utf8_8FC7,
+ euc_to_utf8_8FC8, euc_to_utf8_8FC9, euc_to_utf8_8FCA, euc_to_utf8_8FCB,
+ euc_to_utf8_8FCC, euc_to_utf8_8FCD, euc_to_utf8_8FCE, euc_to_utf8_8FCF,
+ euc_to_utf8_8FD0, euc_to_utf8_8FD1, euc_to_utf8_8FD2, euc_to_utf8_8FD3,
+ euc_to_utf8_8FD4, euc_to_utf8_8FD5, euc_to_utf8_8FD6, euc_to_utf8_8FD7,
+ euc_to_utf8_8FD8, euc_to_utf8_8FD9, euc_to_utf8_8FDA, euc_to_utf8_8FDB,
+ euc_to_utf8_8FDC, euc_to_utf8_8FDD, euc_to_utf8_8FDE, euc_to_utf8_8FDF,
+ euc_to_utf8_8FE0, euc_to_utf8_8FE1, euc_to_utf8_8FE2, euc_to_utf8_8FE3,
+ euc_to_utf8_8FE4, euc_to_utf8_8FE5, euc_to_utf8_8FE6, euc_to_utf8_8FE7,
+ euc_to_utf8_8FE8, euc_to_utf8_8FE9, euc_to_utf8_8FEA, euc_to_utf8_8FEB,
+ euc_to_utf8_8FEC, euc_to_utf8_8FED, 0, 0,
+ 0, 0, 0, euc_to_utf8_8FF3,
+ euc_to_utf8_8FF4, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0,};
+#endif /* X0212_ENABLE */
+#endif /* UTF8_OUTPUT_ENABLE */
+
+#ifdef UTF8_INPUT_ENABLE
+const unsigned short utf8_to_euc_C2[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x216F, 0xA243, 0x2178,
+ 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234,
+ 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0,
+ 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244,
+};
+const unsigned short utf8_to_euc_C2_ms[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178,
+ 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234,
+ 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0,
+ 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244,
+};
+const unsigned short utf8_to_euc_C2_932[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x21, 0x2171, 0x2172, 0, 0x5C, 0x7C, 0x2178,
+ 0x212F, 0x63, 0x61, 0x2263, 0x224C, 0x2D, 0x52, 0x2131,
+ 0x216B, 0x215E, 0x32, 0x33, 0x212D, 0x264C, 0x2279, 0x2126,
+ 0x2124, 0x31, 0x6F, 0x2264, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_C3[] = {
+ 0xAA22, 0xAA21, 0xAA24, 0xAA2A, 0xAA23, 0xAA29, 0xA921, 0xAA2E,
+ 0xAA32, 0xAA31, 0xAA34, 0xAA33, 0xAA40, 0xAA3F, 0xAA42, 0xAA41,
+ 0, 0xAA50, 0xAA52, 0xAA51, 0xAA54, 0xAA58, 0xAA53, 0x215F,
+ 0xA92C, 0xAA63, 0xAA62, 0xAA65, 0xAA64, 0xAA72, 0xA930, 0xA94E,
+ 0xAB22, 0xAB21, 0xAB24, 0xAB2A, 0xAB23, 0xAB29, 0xA941, 0xAB2E,
+ 0xAB32, 0xAB31, 0xAB34, 0xAB33, 0xAB40, 0xAB3F, 0xAB42, 0xAB41,
+ 0xA943, 0xAB50, 0xAB52, 0xAB51, 0xAB54, 0xAB58, 0xAB53, 0x2160,
+ 0xA94C, 0xAB63, 0xAB62, 0xAB65, 0xAB64, 0xAB72, 0xA950, 0xAB73,
+};
+const unsigned short utf8_to_euc_C3_932[] = {
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
+ 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x215F,
+ 0x4F, 0x55, 0x55, 0x55, 0x55, 0x59, 0x54, 0x73,
+ 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x63,
+ 0x65, 0x65, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69,
+ 0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x2160,
+ 0x6F, 0x75, 0x75, 0x75, 0x75, 0x79, 0x74, 0x79,
+};
+const unsigned short utf8_to_euc_C4[] = {
+ 0xAA27, 0xAB27, 0xAA25, 0xAB25, 0xAA28, 0xAB28, 0xAA2B, 0xAB2B,
+ 0xAA2C, 0xAB2C, 0xAA2F, 0xAB2F, 0xAA2D, 0xAB2D, 0xAA30, 0xAB30,
+ 0xA922, 0xA942, 0xAA37, 0xAB37, 0, 0, 0xAA36, 0xAB36,
+ 0xAA38, 0xAB38, 0xAA35, 0xAB35, 0xAA3A, 0xAB3A, 0xAA3B, 0xAB3B,
+ 0xAA3D, 0xAB3D, 0xAA3C, 0, 0xAA3E, 0xAB3E, 0xA924, 0xA944,
+ 0xAA47, 0xAB47, 0xAA45, 0xAB45, 0, 0, 0xAA46, 0xAB46,
+ 0xAA44, 0xA945, 0xA926, 0xA946, 0xAA48, 0xAB48, 0xAA49, 0xAB49,
+ 0xA947, 0xAA4A, 0xAB4A, 0xAA4C, 0xAB4C, 0xAA4B, 0xAB4B, 0xA929,
+};
+const unsigned short utf8_to_euc_C5[] = {
+ 0xA949, 0xA928, 0xA948, 0xAA4D, 0xAB4D, 0xAA4F, 0xAB4F, 0xAA4E,
+ 0xAB4E, 0xA94A, 0xA92B, 0xA94B, 0xAA57, 0xAB57, 0, 0,
+ 0xAA56, 0xAB56, 0xA92D, 0xA94D, 0xAA59, 0xAB59, 0xAA5B, 0xAB5B,
+ 0xAA5A, 0xAB5A, 0xAA5C, 0xAB5C, 0xAA5D, 0xAB5D, 0xAA5F, 0xAB5F,
+ 0xAA5E, 0xAB5E, 0xAA61, 0xAB61, 0xAA60, 0xAB60, 0xA92F, 0xA94F,
+ 0xAA6C, 0xAB6C, 0xAA69, 0xAB69, 0xAA66, 0xAB66, 0xAA6B, 0xAB6B,
+ 0xAA68, 0xAB68, 0xAA6A, 0xAB6A, 0xAA71, 0xAB71, 0xAA74, 0xAB74,
+ 0xAA73, 0xAA75, 0xAB75, 0xAA77, 0xAB77, 0xAA76, 0xAB76, 0,
+};
+const unsigned short utf8_to_euc_C7[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xAA26, 0xAB26, 0xAA43,
+ 0xAB43, 0xAA55, 0xAB55, 0xAA67, 0xAB67, 0xAA70, 0xAB70, 0xAA6D,
+ 0xAB6D, 0xAA6F, 0xAB6F, 0xAA6E, 0xAB6E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xAB39, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_CB[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0xA230,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xA22F, 0xA232, 0xA236, 0xA235, 0, 0xA233, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_CE[] = {
+ 0, 0, 0, 0, 0xA238, 0xA239, 0xA661, 0,
+ 0xA662, 0xA663, 0xA664, 0, 0xA667, 0, 0xA669, 0xA66C,
+ 0xA676, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627,
+ 0x2628, 0x2629, 0x262A, 0x262B, 0x262C, 0x262D, 0x262E, 0x262F,
+ 0x2630, 0x2631, 0, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636,
+ 0x2637, 0x2638, 0xA665, 0xA66A, 0xA671, 0xA672, 0xA673, 0xA674,
+ 0xA67B, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647,
+ 0x2648, 0x2649, 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F,
+};
+const unsigned short utf8_to_euc_CF[] = {
+ 0x2650, 0x2651, 0xA678, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656,
+ 0x2657, 0x2658, 0xA675, 0xA67A, 0xA677, 0xA679, 0xA67C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_D0[] = {
+ 0, 0x2727, 0xA742, 0xA743, 0xA744, 0xA745, 0xA746, 0xA747,
+ 0xA748, 0xA749, 0xA74A, 0xA74B, 0xA74C, 0, 0xA74D, 0xA74E,
+ 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2728, 0x2729,
+ 0x272A, 0x272B, 0x272C, 0x272D, 0x272E, 0x272F, 0x2730, 0x2731,
+ 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, 0x2739,
+ 0x273A, 0x273B, 0x273C, 0x273D, 0x273E, 0x273F, 0x2740, 0x2741,
+ 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2758, 0x2759,
+ 0x275A, 0x275B, 0x275C, 0x275D, 0x275E, 0x275F, 0x2760, 0x2761,
+};
+const unsigned short utf8_to_euc_D1[] = {
+ 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769,
+ 0x276A, 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, 0x2770, 0x2771,
+ 0, 0x2757, 0xA772, 0xA773, 0xA774, 0xA775, 0xA776, 0xA777,
+ 0xA778, 0xA779, 0xA77A, 0xA77B, 0xA77C, 0, 0xA77D, 0xA77E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E280[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0,
+ 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
+ 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
+ 0, 0, 0, 0x2228, 0, 0, 0x2131, 0,
+};
+const unsigned short utf8_to_euc_E280_ms[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0,
+ 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
+ 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
+ 0, 0, 0, 0x2228, 0, 0, 0x7E, 0,
+};
+const unsigned short utf8_to_euc_E280_932[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x213E, 0, 0, 0, 0, 0x213D, 0, 0,
+ 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
+ 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
+ 0, 0, 0, 0x2228, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E284[] = {
+ 0, 0, 0, 0x216E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x2D62, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x2D64, 0xA26F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x2272, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E285[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x2D35, 0x2D36, 0x2D37, 0x2D38, 0x2D39, 0x2D3A, 0x2D3B, 0x2D3C,
+ 0x2D3D, 0x2D3E, 0, 0, 0, 0, 0, 0,
+ 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A,
+ 0xF37B, 0xF37C, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E286[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x222B, 0x222C, 0x222A, 0x222D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E287[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x224D, 0, 0x224E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E288[] = {
+ 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260,
+ 0x223A, 0, 0, 0x223B, 0, 0, 0, 0,
+ 0, 0x2D74, 0x215D, 0, 0, 0, 0, 0,
+ 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78,
+ 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A,
+ 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0,
+ 0, 0, 0, 0, 0x2168, 0x2268, 0, 0,
+ 0, 0, 0, 0, 0, 0x2266, 0, 0,
+};
+const unsigned short utf8_to_euc_E288_932[] = {
+ 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260,
+ 0x223A, 0, 0, 0x223B, 0, 0, 0, 0,
+ 0, 0x2D74, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78,
+ 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A,
+ 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0,
+ 0, 0, 0, 0, 0x2168, 0x2268, 0, 0,
+ 0, 0, 0, 0, 0, 0x2266, 0, 0,
+};
+const unsigned short utf8_to_euc_E289[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2262, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x2162, 0x2261, 0, 0, 0, 0, 0x2165, 0x2166,
+ 0, 0, 0x2263, 0x2264, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E28A[] = {
+ 0, 0, 0x223E, 0x223F, 0, 0, 0x223C, 0x223D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x225D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x2D79,
+};
+const unsigned short utf8_to_euc_E28C[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x225E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E291[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x2D21, 0x2D22, 0x2D23, 0x2D24, 0x2D25, 0x2D26, 0x2D27, 0x2D28,
+ 0x2D29, 0x2D2A, 0x2D2B, 0x2D2C, 0x2D2D, 0x2D2E, 0x2D2F, 0x2D30,
+ 0x2D31, 0x2D32, 0x2D33, 0x2D34, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E294[] = {
+ 0x2821, 0x282C, 0x2822, 0x282D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x2823, 0, 0, 0x282E,
+ 0x2824, 0, 0, 0x282F, 0x2826, 0, 0, 0x2831,
+ 0x2825, 0, 0, 0x2830, 0x2827, 0x283C, 0, 0,
+ 0x2837, 0, 0, 0x2832, 0x2829, 0x283E, 0, 0,
+ 0x2839, 0, 0, 0x2834, 0x2828, 0, 0, 0x2838,
+ 0x283D, 0, 0, 0x2833, 0x282A, 0, 0, 0x283A,
+ 0x283F, 0, 0, 0x2835, 0x282B, 0, 0, 0x283B,
+};
+const unsigned short utf8_to_euc_E295[] = {
+ 0, 0, 0x2840, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x2836, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E296[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x2223, 0x2222, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2225, 0x2224, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x2227, 0x2226, 0, 0,
+};
+const unsigned short utf8_to_euc_E297[] = {
+ 0, 0, 0, 0, 0, 0, 0x2221, 0x217E,
+ 0, 0, 0, 0x217B, 0, 0, 0x217D, 0x217C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x227E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E298[] = {
+ 0, 0, 0, 0, 0, 0x217A, 0x2179, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E299[] = {
+ 0x216A, 0, 0x2169, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2276, 0, 0, 0x2275, 0, 0x2274,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E380[] = {
+ 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B,
+ 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159,
+ 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0,
+ 0, 0, 0, 0, 0x2141, 0x2D60, 0, 0x2D61,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E380_932[] = {
+ 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B,
+ 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159,
+ 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0,
+ 0, 0, 0, 0, 0, 0x2D60, 0, 0x2D61,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E381[] = {
+ 0, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427,
+ 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F,
+ 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437,
+ 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F,
+ 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447,
+ 0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F,
+ 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457,
+ 0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F,
+};
+const unsigned short utf8_to_euc_E382[] = {
+ 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
+ 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F,
+ 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0, 0,
+ 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0,
+ 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
+ 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F,
+ 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
+ 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F,
+};
+const unsigned short utf8_to_euc_E382_932[] = {
+ 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
+ 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F,
+ 0x2470, 0x2471, 0x2472, 0x2473, 0x2574, 0, 0, 0,
+ 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0,
+ 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
+ 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F,
+ 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
+ 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F,
+};
+const unsigned short utf8_to_euc_E383[] = {
+ 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547,
+ 0x2548, 0x2549, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, 0x254F,
+ 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557,
+ 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F,
+ 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567,
+ 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F,
+ 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0,
+ 0, 0, 0, 0x2126, 0x213C, 0x2133, 0x2134, 0,
+};
+const unsigned short utf8_to_euc_E388[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x2D6A, 0x2D6B, 0, 0, 0, 0, 0,
+ 0, 0x2D6C, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E38A[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x2D65, 0x2D66, 0x2D67, 0x2D68,
+ 0x2D69, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E38C[] = {
+ 0, 0, 0, 0x2D46, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x2D4A, 0, 0,
+ 0, 0, 0, 0, 0x2D41, 0, 0, 0,
+ 0x2D44, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x2D42, 0x2D4C, 0, 0, 0x2D4B, 0x2D45,
+ 0, 0, 0, 0x2D4D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x2D47, 0,
+ 0, 0, 0, 0x2D4F, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E38D[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x2D40, 0x2D4E, 0, 0, 0x2D43, 0, 0,
+ 0, 0x2D48, 0, 0, 0, 0, 0, 0x2D49,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x2D5F, 0x2D6F, 0x2D6E, 0x2D6D, 0,
+};
+const unsigned short utf8_to_euc_E38E[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x2D53, 0x2D54,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x2D50, 0x2D51, 0x2D52, 0,
+ 0, 0x2D56, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E38F[] = {
+ 0, 0, 0, 0, 0x2D55, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x2D63, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E4B8[] = {
+ 0x306C, 0x437A, 0xB021, 0x3C37, 0xB022, 0xB023, 0, 0x4B7C,
+ 0x3E66, 0x3B30, 0x3E65, 0x323C, 0xB024, 0x4954, 0x4D3F, 0,
+ 0x5022, 0x312F, 0xB025, 0, 0x336E, 0x5023, 0x4024, 0x5242,
+ 0x3556, 0x4A3A, 0, 0, 0, 0, 0x3E67, 0xB026,
+ 0, 0x4E3E, 0, 0xB027, 0xB028, 0, 0x4A42, 0,
+ 0xB029, 0, 0x5024, 0xB02A, 0, 0x4366, 0xB02B, 0xB02C,
+ 0xB02D, 0x5025, 0x367A, 0, 0, 0xB02E, 0x5026, 0,
+ 0x345D, 0x4330, 0, 0x3C67, 0x5027, 0, 0, 0x5028,
+};
+const unsigned short utf8_to_euc_E4B9[] = {
+ 0xB02F, 0xB030, 0x5029, 0x4735, 0xB031, 0x3557, 0, 0xB032,
+ 0, 0, 0, 0x4737, 0, 0x4663, 0x3843, 0x4B33,
+ 0, 0xB033, 0, 0, 0, 0x6949, 0x502A, 0x3E68,
+ 0x502B, 0x3235, 0xB034, 0, 0xB035, 0x3665, 0x3870, 0x4C69,
+ 0, 0, 0x5626, 0xB036, 0, 0, 0, 0,
+ 0xB037, 0xB038, 0, 0, 0, 0, 0, 0,
+ 0, 0x4D70, 0, 0x467D, 0xB039, 0xB03A, 0, 0,
+ 0, 0xB03B, 0, 0, 0, 0, 0x3425, 0xB03C,
+};
+const unsigned short utf8_to_euc_E4BA[] = {
+ 0x3535, 0, 0x502C, 0, 0, 0x502D, 0x4E3B, 0,
+ 0x4D3D, 0x4168, 0x502F, 0x3B76, 0x4673, 0xB03D, 0x5032, 0,
+ 0, 0x313E, 0x385F, 0, 0x385E, 0x3066, 0xB03E, 0xB03F,
+ 0x4F4B, 0x4F4A, 0, 0x3A33, 0x3021, 0xB040, 0x5033, 0x5034,
+ 0x5035, 0x4B34, 0x5036, 0, 0x3872, 0x3067, 0x4B72, 0,
+ 0x357C, 0, 0, 0x357D, 0x357E, 0x4462, 0x4E3C, 0xB041,
+ 0x5037, 0, 0, 0x5038, 0, 0, 0x5039, 0,
+ 0, 0xB042, 0x3F4D, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E4BB[] = {
+ 0x3D3A, 0x3F4E, 0x503E, 0xB043, 0x503C, 0, 0x503D, 0x3558,
+ 0, 0, 0x3A23, 0x3270, 0, 0x503B, 0x503A, 0x4A29,
+ 0xB044, 0, 0, 0, 0x3B46, 0x3B45, 0x423E, 0x503F,
+ 0x4955, 0x4067, 0xB045, 0xB046, 0, 0x2138, 0x5040, 0x5042,
+ 0xB047, 0xB048, 0xB049, 0x4265, 0x4E61, 0x304A, 0, 0,
+ 0xB04A, 0, 0, 0, 0, 0x5041, 0x323E, 0xB04B,
+ 0x3644, 0xB04C, 0x4367, 0xB04D, 0, 0xB04E, 0x376F, 0x5043,
+ 0, 0, 0, 0x4724, 0xF42F, 0xB04F, 0xB050, 0xB051,
+};
+const unsigned short utf8_to_euc_E4BC[] = {
+ 0xB052, 0x346B, 0xB053, 0xB054, 0, 0, 0, 0,
+ 0xB055, 0x5044, 0x304B, 0xB056, 0xB057, 0x3860, 0x346C, 0x497A,
+ 0x4832, 0x3559, 0xB058, 0, 0, 0xB059, 0xB05A, 0xB05B,
+ 0, 0xB05C, 0x3271, 0, 0x5067, 0x4541, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xB05D, 0x476C,
+ 0x5046, 0xB05E, 0, 0xB060, 0x483C, 0xB061, 0x4E62, 0xB062,
+ 0x3F2D, 0xB063, 0x3B47, 0xB064, 0x3B77, 0x3240, 0xB065, 0,
+};
+const unsigned short utf8_to_euc_E4BD[] = {
+ 0xB066, 0, 0xB067, 0x4451, 0, 0, 0x4322, 0x504A,
+ 0xB068, 0xB069, 0, 0xB06A, 0xB06B, 0x304C, 0x4463, 0x3D3B,
+ 0x3A34, 0x4D24, 0xB06C, 0x424E, 0xB06D, 0x323F, 0xB06E, 0x5049,
+ 0xB06F, 0x4D3E, 0x5045, 0x5047, 0x3A6E, 0x5048, 0x5524, 0xB070,
+ 0xB05F, 0, 0, 0xB071, 0, 0, 0, 0,
+ 0, 0x5050, 0xB072, 0, 0xB073, 0, 0xB074, 0x5053,
+ 0x5051, 0xB075, 0, 0x3242, 0, 0x4A3B, 0x504B, 0xB076,
+ 0xB077, 0xB078, 0xB079, 0x504F, 0x3873, 0xB07A, 0xB07B, 0x3B48,
+};
+const unsigned short utf8_to_euc_E4BE[] = {
+ 0, 0xB07C, 0xB07D, 0x3426, 0xB07E, 0xB121, 0x5054, 0,
+ 0x504C, 0xB122, 0xB123, 0x4E63, 0xB124, 0x3B78, 0xB125, 0x504D,
+ 0xB126, 0x5052, 0xB127, 0xB128, 0xB129, 0, 0x5055, 0xB12A,
+ 0x504E, 0xB12B, 0xB12C, 0x3621, 0, 0x304D, 0xB12D, 0xB12E,
+ 0x3622, 0x3241, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x5525, 0, 0x4B79, 0x496E, 0x3874,
+ 0, 0, 0xB12F, 0, 0, 0x3F2F, 0x4E37, 0xB130,
+ 0, 0xB131, 0, 0xB132, 0xB133, 0xB134, 0xB135, 0x4A58,
+};
+const unsigned short utf8_to_euc_E4BF[] = {
+ 0xB136, 0xB137, 0x3738, 0x4225, 0x3264, 0xB138, 0xB139, 0,
+ 0xB13A, 0xB13B, 0x3D53, 0xB13C, 0xB13D, 0xB13E, 0x5059, 0xB13F,
+ 0x505E, 0x505C, 0xB140, 0, 0x5057, 0, 0, 0x422F,
+ 0x505A, 0, 0x505D, 0x505B, 0xB141, 0x4A5D, 0, 0x5058,
+ 0xB142, 0x3F2E, 0xB143, 0x4B73, 0x505F, 0x5060, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x3D24, 0x506D,
+ 0xB144, 0, 0xB145, 0x4750, 0, 0x4936, 0x5068, 0,
+ 0x4A70, 0, 0x3236, 0, 0xB146, 0xB147, 0x506C, 0xB148,
+};
+const unsigned short utf8_to_euc_E580[] = {
+ 0xB149, 0xB14A, 0, 0, 0xB14B, 0x5066, 0x506F, 0xB14C,
+ 0, 0x4152, 0xB14D, 0x3844, 0xB14E, 0x475C, 0xB14F, 0x6047,
+ 0xB150, 0x506E, 0x455D, 0xB151, 0x5063, 0, 0x3876, 0xB152,
+ 0xB153, 0x3875, 0x5061, 0xB154, 0xB155, 0xB156, 0xB157, 0x3C5A,
+ 0, 0x5069, 0xB158, 0x4A6F, 0x434D, 0x5065, 0x3771, 0xB159,
+ 0x5062, 0x506A, 0x5064, 0x4E51, 0x506B, 0x4F41, 0xB15A, 0,
+ 0xB15B, 0, 0xB15C, 0xB15D, 0, 0xB15E, 0x3666, 0,
+ 0, 0x3770, 0, 0xB176, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E581[] = {
+ 0xB15F, 0xB160, 0xB161, 0x5070, 0, 0xB162, 0xB163, 0x5071,
+ 0x5075, 0x304E, 0xB164, 0, 0xB165, 0, 0xB166, 0x4A50,
+ 0x5074, 0xB167, 0xB168, 0xB169, 0, 0x5073, 0x5077, 0xB16A,
+ 0, 0xB16B, 0x5076, 0, 0x4464, 0, 0, 0xB16C,
+ 0xB16D, 0, 0xB16E, 0xB16F, 0, 0x3772, 0xB170, 0xB171,
+ 0, 0, 0xB172, 0, 0x5078, 0xB173, 0, 0,
+ 0xB174, 0xB175, 0x3C45, 0, 0x4226, 0x4465, 0x3676, 0,
+ 0x5079, 0, 0, 0, 0, 0x3536, 0, 0,
+};
+const unsigned short utf8_to_euc_E582[] = {
+ 0x507A, 0xB177, 0, 0xB178, 0xB179, 0x507C, 0xB17A, 0,
+ 0, 0, 0xB17B, 0, 0, 0x4B35, 0xB17C, 0xB17D,
+ 0xB17E, 0x3766, 0xB221, 0xB222, 0xB223, 0, 0xB224, 0,
+ 0x3B31, 0x4877, 0x507B, 0xB225, 0xB226, 0, 0xB227, 0xB228,
+ 0xB229, 0xB22A, 0xB22B, 0, 0, 0, 0, 0,
+ 0, 0, 0xB22C, 0, 0x3A45, 0x4D43, 0, 0xB22D,
+ 0xB22E, 0, 0x507E, 0x5123, 0x507D, 0x3A44, 0, 0x3D7D,
+ 0, 0xB22F, 0xB230, 0, 0, 0xB231, 0x3739, 0,
+};
+const unsigned short utf8_to_euc_E583[] = {
+ 0xB232, 0, 0x5124, 0xB233, 0xB234, 0x364F, 0, 0xB235,
+ 0, 0x5121, 0x5122, 0, 0xB236, 0x462F, 0xB237, 0x417C,
+ 0xB238, 0x3623, 0, 0xB239, 0xB23A, 0x4B4D, 0x5125, 0,
+ 0xB23B, 0, 0x4E3D, 0, 0xB23C, 0xB23D, 0x5126, 0xB23E,
+ 0, 0, 0xB23F, 0x5129, 0xB240, 0x5127, 0xB241, 0x414E,
+ 0xB242, 0xB243, 0, 0, 0, 0x5128, 0x512A, 0xB244,
+ 0, 0xB245, 0xB251, 0, 0xF430, 0x512C, 0xB246, 0,
+ 0, 0x512B, 0xB247, 0x4A48, 0, 0, 0xB248, 0,
+};
+const unsigned short utf8_to_euc_E584[] = {
+ 0x3537, 0x512E, 0x512F, 0xB249, 0x322F, 0, 0xB24A, 0xB24B,
+ 0xB24C, 0x512D, 0, 0xB24D, 0xB24E, 0xB24F, 0xB250, 0,
+ 0xB252, 0, 0x3C74, 0, 0x5132, 0x5131, 0x5130, 0xB253,
+ 0x5056, 0xB254, 0x5133, 0xB255, 0xB256, 0xB257, 0xB258, 0x3D7E,
+ 0, 0x5134, 0, 0xB259, 0, 0, 0, 0xB25A,
+ 0xB25B, 0, 0x4D25, 0, 0xB25C, 0xB25D, 0, 0xB25E,
+ 0, 0xB25F, 0x4C59, 0xB260, 0xB261, 0xB262, 0, 0x5136,
+ 0xB263, 0xB264, 0x5135, 0x5138, 0x5137, 0, 0, 0x5139,
+};
+const unsigned short utf8_to_euc_E585[] = {
+ 0x513A, 0x3074, 0xB265, 0x3835, 0x373B, 0x3D3C, 0x437B, 0x3624,
+ 0x4068, 0x3877, 0xB266, 0x396E, 0x513C, 0x4C48, 0x4546, 0xB267,
+ 0x3B79, 0, 0x513B, 0xB268, 0x513D, 0xB269, 0, 0xB26A,
+ 0xB26B, 0, 0x455E, 0, 0x3375, 0, 0, 0xB26C,
+ 0, 0, 0x513E, 0, 0xB26D, 0x467E, 0xB26E, 0,
+ 0x4134, 0x5140, 0x5141, 0x482C, 0x3878, 0x4F3B, 0x5142, 0,
+ 0, 0x3626, 0, 0, 0, 0x4A3C, 0x4236, 0x3671,
+ 0x4535, 0, 0, 0, 0x3773, 0, 0xB26F, 0,
+};
+const unsigned short utf8_to_euc_E586[] = {
+ 0x5143, 0, 0x5144, 0xB270, 0xB271, 0x4662, 0x315F, 0,
+ 0, 0x5147, 0x3A7D, 0xB272, 0x5146, 0x3A46, 0xB273, 0x5148,
+ 0x666E, 0x5149, 0x4B41, 0x514A, 0, 0x514B, 0x514C, 0x3E69,
+ 0xB274, 0x3C4C, 0, 0, 0, 0xB275, 0, 0,
+ 0x3427, 0xB276, 0x514F, 0xB277, 0x514D, 0x4C3D, 0x514E, 0,
+ 0x495A, 0x5150, 0x5151, 0x5152, 0x455F, 0xB278, 0, 0,
+ 0x5156, 0x5154, 0x5155, 0x5153, 0x3A63, 0x5157, 0x4C6A, 0x4E64,
+ 0xB279, 0, 0xB27A, 0, 0xB27B, 0x5158, 0xB27C, 0xB27D,
+};
+const unsigned short utf8_to_euc_E587[] = {
+ 0, 0, 0xB27E, 0, 0x4028, 0x5159, 0x3D5A, 0,
+ 0xB321, 0x515A, 0, 0x437C, 0x4E3F, 0x4560, 0, 0xB322,
+ 0, 0xB323, 0xB324, 0xB325, 0, 0xB326, 0x5245, 0,
+ 0xB327, 0, 0, 0x515B, 0x7425, 0x3645, 0xB328, 0,
+ 0x515C, 0x4B5E, 0xB329, 0, 0, 0xB32A, 0x3D68, 0x427C,
+ 0, 0x515E, 0x4664, 0, 0xF431, 0x515F, 0xB32B, 0,
+ 0x5160, 0x332E, 0xB32C, 0xB32D, 0xB32E, 0x5161, 0x3627, 0xB32F,
+ 0x464C, 0x317A, 0x3D50, 0, 0, 0x4821, 0x5162, 0,
+};
+const unsigned short utf8_to_euc_E588[] = {
+ 0x4561, 0xB330, 0xB331, 0x3F4F, 0x5163, 0xB332, 0x4A2C, 0x405A,
+ 0x3422, 0, 0x3429, 0x5164, 0, 0, 0x5166, 0,
+ 0, 0x373A, 0xB333, 0xB334, 0x5165, 0xB335, 0xB336, 0x4E73,
+ 0xB337, 0, 0, 0, 0, 0x3D69, 0, 0,
+ 0, 0, 0xB338, 0, 0x483D, 0x4A4C, 0, 0x5167,
+ 0xB339, 0x4D78, 0x5168, 0, 0, 0, 0x5169, 0,
+ 0x457E, 0xB33A, 0xB33B, 0x516A, 0, 0xB33C, 0x4029, 0x3A7E,
+ 0x3774, 0x516B, 0x3B49, 0x396F, 0xB33D, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E589[] = {
+ 0, 0, 0, 0x4466, 0x516D, 0xB33E, 0, 0x4227,
+ 0, 0xB33F, 0x3A6F, 0x516E, 0x516F, 0x4130, 0, 0x516C,
+ 0, 0, 0, 0, 0x5171, 0xB340, 0x4B36, 0xB341,
+ 0xB342, 0, 0xB343, 0x3964, 0xB344, 0, 0x5170, 0xB345,
+ 0xB346, 0xB347, 0, 0x3775, 0x3A5E, 0x476D, 0xB348, 0,
+ 0, 0x5174, 0x5172, 0, 0, 0, 0xB349, 0x497B,
+ 0x3E6A, 0x517B, 0x3364, 0x5175, 0x5173, 0x414F, 0, 0xB34A,
+ 0xB34B, 0xB34C, 0, 0, 0, 0x5177, 0, 0x5176,
+};
+const unsigned short utf8_to_euc_E58A[] = {
+ 0xB34D, 0, 0xB34E, 0x3344, 0, 0xB34F, 0, 0x3760,
+ 0x517C, 0x4E2D, 0xB350, 0, 0xB351, 0x5178, 0, 0,
+ 0, 0x517D, 0x517A, 0xB352, 0x5179, 0xB353, 0xB354, 0xB355,
+ 0xB356, 0, 0xB357, 0x4E4F, 0xB358, 0, 0, 0x3879,
+ 0x3243, 0, 0, 0x4E74, 0xB359, 0xB35A, 0xB35B, 0xB35C,
+ 0, 0x3D75, 0x4558, 0x3965, 0x5222, 0x5223, 0, 0xB35D,
+ 0xB35E, 0x4E65, 0, 0, 0x4F2B, 0x5225, 0xB35F, 0xB360,
+ 0xB361, 0x387A, 0xB362, 0xB363, 0x5224, 0xB364, 0x332F, 0,
+};
+const unsigned short utf8_to_euc_E58B[] = {
+ 0xB365, 0x5226, 0, 0x4B56, 0xB366, 0x443C, 0xB367, 0x4D26,
+ 0xB368, 0x4A59, 0, 0, 0xB369, 0x5227, 0, 0xB36A,
+ 0, 0xB36B, 0x7055, 0, 0xB36C, 0x4630, 0xB36D, 0x5228,
+ 0x342A, 0x4C33, 0, 0xB36E, 0xB36F, 0x3E21, 0x5229, 0x4A67,
+ 0x522D, 0xB370, 0x402A, 0x522A, 0x3650, 0xB371, 0x522B, 0x342B,
+ 0xB372, 0xB373, 0xB374, 0, 0xB375, 0, 0, 0,
+ 0xB376, 0xB377, 0x372E, 0x522E, 0xB378, 0x522F, 0xB379, 0xB37A,
+ 0x5230, 0x5231, 0x3C5B, 0, 0, 0, 0x387B, 0x4C5E,
+};
+const unsigned short utf8_to_euc_E58C[] = {
+ 0xB37B, 0x4C68, 0x4677, 0xB37C, 0, 0x4A71, 0x5232, 0xF432,
+ 0x5233, 0, 0xB37D, 0xB37E, 0xB421, 0x5235, 0, 0x5237,
+ 0x5236, 0xB422, 0, 0xB423, 0, 0x5238, 0x323D, 0x4B4C,
+ 0xB424, 0x3A7C, 0x5239, 0xB425, 0xB426, 0x4159, 0xB427, 0xB428,
+ 0x3E22, 0x3629, 0, 0x523A, 0xF433, 0xB429, 0, 0xB42A,
+ 0xB42B, 0xB42C, 0x485B, 0xB42D, 0xB42E, 0xB42F, 0, 0x523B,
+ 0xB430, 0x523C, 0xB431, 0x523D, 0, 0xB432, 0, 0,
+ 0x523E, 0x4924, 0x3668, 0x3065, 0xB433, 0xB434, 0xB435, 0x463F,
+};
+const unsigned short utf8_to_euc_E58D[] = {
+ 0x523F, 0x3D3D, 0xB436, 0x4069, 0, 0x5241, 0x5240, 0x3E23,
+ 0x3861, 0x5243, 0x483E, 0xB438, 0xB437, 0x5244, 0, 0,
+ 0, 0x485C, 0x4234, 0x426E, 0x3628, 0, 0, 0x466E,
+ 0x4331, 0xB439, 0x476E, 0xB43A, 0x4B4E, 0, 0x5246, 0,
+ 0x406A, 0xB43B, 0, 0xB43C, 0, 0xB43D, 0x3735, 0,
+ 0, 0x5247, 0, 0, 0xB43E, 0xB43F, 0x5248, 0x312C,
+ 0x3075, 0x346D, 0xB440, 0x4228, 0x3551, 0x4D71, 0, 0x524B,
+ 0x3237, 0xB441, 0, 0x524A, 0, 0, 0xB442, 0x362A,
+};
+const unsigned short utf8_to_euc_E58E[] = {
+ 0, 0, 0x524C, 0xB443, 0x4C71, 0, 0, 0xB444,
+ 0xB445, 0, 0, 0, 0, 0, 0xB446, 0,
+ 0, 0, 0, 0xB447, 0xB448, 0, 0x524D, 0,
+ 0x4E52, 0xB449, 0x387C, 0, 0, 0xB44A, 0, 0x3836,
+ 0x524E, 0xB44B, 0, 0, 0xB44C, 0x5250, 0x524F, 0,
+ 0x3F5F, 0x3139, 0xB44D, 0xB44E, 0, 0x315E, 0x5251, 0xB44F,
+ 0x5252, 0, 0xB450, 0x3837, 0xB451, 0xB452, 0x5253, 0xB453,
+ 0xB454, 0, 0xB455, 0x356E, 0, 0xB456, 0, 0,
+};
+const unsigned short utf8_to_euc_E58F[] = {
+ 0xB457, 0, 0x3B32, 0x5254, 0, 0xB458, 0, 0,
+ 0x4B74, 0x3A35, 0x355A, 0x4D27, 0x4150, 0x483F, 0x3C7D, 0xB459,
+ 0, 0, 0xB45A, 0xB45B, 0x3D47, 0xB45C, 0x3C68, 0x3C75,
+ 0, 0x3D76, 0xB45D, 0x4840, 0, 0xB45E, 0xB45F, 0x5257,
+ 0xB460, 0x3143, 0x4151, 0x387D, 0x3845, 0x3667, 0xB461, 0xB462,
+ 0x525B, 0x4321, 0x427E, 0x362B, 0x3E24, 0x525C, 0x525A, 0x3244,
+ 0x4266, 0x3C38, 0x3B4B, 0x3126, 0, 0xB463, 0x3370, 0x3966,
+ 0x3B4A, 0, 0x525D, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E590[] = {
+ 0, 0x525E, 0xB464, 0x3549, 0x3346, 0, 0, 0,
+ 0x3967, 0x3548, 0x445F, 0x3125, 0x4631, 0x4C3E, 0x3921, 0x4D79,
+ 0x4547, 0x387E, 0, 0xB465, 0, 0, 0, 0,
+ 0, 0, 0xB466, 0x372F, 0, 0x5267, 0, 0x3663,
+ 0x4B4A, 0xB467, 0, 0, 0, 0, 0x485D, 0xB468,
+ 0xB469, 0x5266, 0xB46A, 0x345E, 0x5261, 0x5262, 0x5264, 0xB46B,
+ 0, 0xB46C, 0, 0, 0xB46D, 0xB46E, 0x5265, 0,
+ 0x355B, 0x3F61, 0, 0x4A2D, 0x5263, 0x525F, 0x3863, 0,
+};
+const unsigned short utf8_to_euc_E591[] = {
+ 0x5260, 0, 0x4F24, 0xB46F, 0xB470, 0, 0x4A72, 0xB471,
+ 0x4468, 0x3862, 0x3970, 0, 0, 0xB472, 0x5268, 0xB473,
+ 0, 0x465D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xB474, 0x526C,
+ 0, 0, 0xB475, 0, 0xB476, 0, 0xB477, 0xB478,
+ 0x3C7E, 0xB479, 0x3C76, 0xB47A, 0, 0xB47B, 0xB47C, 0,
+ 0x526F, 0x526D, 0, 0x4C23, 0xB47D, 0x526A, 0x5273, 0x526E,
+ 0, 0, 0, 0x5271, 0x3846, 0x4C3F, 0, 0xB47E,
+};
+const unsigned short utf8_to_euc_E592[] = {
+ 0x5272, 0xB521, 0, 0xB522, 0x5274, 0xB523, 0x5276, 0,
+ 0xB524, 0xB525, 0xF435, 0x3A70, 0x4F42, 0xB526, 0x526B, 0x5269,
+ 0x5275, 0xB527, 0x5270, 0, 0, 0xB528, 0xB529, 0,
+ 0, 0, 0, 0, 0xB52A, 0, 0, 0xB52B,
+ 0, 0xB52C, 0x5278, 0, 0x5323, 0x527A, 0xB52D, 0xB52E,
+ 0x527E, 0xB52F, 0xB530, 0x5321, 0x527B, 0xB531, 0xB532, 0x533E,
+ 0, 0xB533, 0x3A69, 0x3331, 0, 0, 0, 0xB534,
+ 0x5279, 0xB535, 0xB536, 0xB537, 0x5325, 0x3076, 0x5324, 0xB538,
+};
+const unsigned short utf8_to_euc_E593[] = {
+ 0x3025, 0x494A, 0x5322, 0, 0x527C, 0, 0xB539, 0x5277,
+ 0x527D, 0x3A48, 0xB53A, 0, 0, 0xB53B, 0xB53C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x5326, 0, 0, 0, 0, 0, 0, 0,
+ 0xB53D, 0x3077, 0x532F, 0, 0, 0x5327, 0x5328, 0,
+ 0x3E25, 0x4B69, 0xB53E, 0, 0xB53F, 0x532D, 0x532C, 0xB540,
+ 0, 0, 0x452F, 0, 0, 0, 0xB541, 0,
+ 0, 0, 0x532E, 0, 0xB542, 0x532B, 0xB543, 0xB544,
+};
+const unsigned short utf8_to_euc_E594[] = {
+ 0xB545, 0xB546, 0, 0, 0x3134, 0xB547, 0x3A36, 0x3F30,
+ 0xB548, 0xB549, 0, 0, 0xB54A, 0xB54B, 0xB54C, 0x5329,
+ 0x4562, 0, 0, 0, 0x532A, 0xB54D, 0x3022, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xB54E, 0xB54F, 0, 0, 0x5334, 0x4D23,
+ 0, 0x3E27, 0xB550, 0x533A, 0, 0xB551, 0xB552, 0,
+ 0x5339, 0x5330, 0, 0xB553, 0xB554, 0xB555, 0x4243, 0,
+};
+const unsigned short utf8_to_euc_E595[] = {
+ 0x5331, 0xB556, 0, 0, 0x426F, 0x5336, 0x3E26, 0xB557,
+ 0, 0xB558, 0xB559, 0, 0x5333, 0xB55A, 0, 0x4C64,
+ 0xB55B, 0xB55C, 0, 0x373C, 0, 0, 0x5337, 0x5338,
+ 0xB55D, 0, 0xB55E, 0xB55F, 0x5335, 0x533B, 0xB560, 0,
+ 0xB561, 0xB562, 0, 0x5332, 0xB563, 0, 0xB564, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x5341, 0x5346, 0, 0x5342, 0xB565,
+};
+const unsigned short utf8_to_euc_E596[] = {
+ 0x533D, 0xB566, 0xB567, 0x5347, 0x4131, 0, 0xB568, 0x5349,
+ 0xB569, 0x3922, 0x533F, 0x437D, 0, 0, 0xB56A, 0xB56B,
+ 0, 0xB56C, 0xB56D, 0xB56E, 0xB56F, 0, 0, 0xB570,
+ 0x5343, 0x533C, 0x342D, 0, 0x346E, 0x3365, 0x5344, 0x5340,
+ 0, 0, 0, 0xB571, 0xB572, 0, 0, 0x3776,
+ 0x534A, 0x5348, 0x4153, 0x354A, 0x362C, 0xB573, 0x5345, 0,
+ 0x3674, 0, 0xB574, 0, 0, 0, 0x3144, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xB575,
+};
+const unsigned short utf8_to_euc_E597[] = {
+ 0, 0xB576, 0, 0xB577, 0x534E, 0x534C, 0xB578, 0x5427,
+ 0, 0xB579, 0, 0xB57A, 0xB57B, 0, 0xB57C, 0,
+ 0, 0xB57D, 0xB57E, 0xB621, 0x5351, 0, 0, 0xB622,
+ 0xB623, 0, 0x534B, 0xB624, 0x534F, 0, 0xB625, 0x534D,
+ 0, 0, 0xB626, 0x3B4C, 0x5350, 0, 0, 0,
+ 0, 0xB627, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xB628, 0x5353,
+ 0, 0x5358, 0, 0, 0, 0x5356, 0x5355, 0xB629,
+};
+const unsigned short utf8_to_euc_E598[] = {
+ 0, 0, 0, 0, 0, 0xB62A, 0x4332, 0,
+ 0xB62B, 0x3245, 0xB62C, 0, 0, 0xB62D, 0xB62E, 0xB62F,
+ 0xB630, 0xB631, 0xB632, 0, 0x5352, 0, 0x5354, 0x3E28,
+ 0x3133, 0xB633, 0, 0x5357, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x325E, 0, 0, 0xB634, 0, 0, 0x5362,
+ 0xB635, 0x3E7C, 0x535E, 0xB636, 0x535C, 0xB637, 0x535D, 0xB638,
+ 0x535F, 0xB639, 0, 0xB63A, 0xB63B, 0xB63C, 0, 0xB63D,
+};
+const unsigned short utf8_to_euc_E599[] = {
+ 0xB63E, 0xB63F, 0x313D, 0xB640, 0xB641, 0, 0xB642, 0,
+ 0, 0xB643, 0, 0xB644, 0x4139, 0xB645, 0x5359, 0xB646,
+ 0x535A, 0, 0, 0, 0xB647, 0, 0, 0,
+ 0, 0, 0, 0x337A, 0, 0, 0xB648, 0,
+ 0xB649, 0xB64A, 0xB64B, 0xB64C, 0x5361, 0, 0xB64D, 0,
+ 0x346F, 0xB64E, 0x5364, 0x5360, 0x5363, 0xB64F, 0, 0xB650,
+ 0, 0xB651, 0xB652, 0, 0x4A2E, 0xB653, 0, 0,
+ 0x4655, 0, 0x4838, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E59A[] = {
+ 0x5366, 0, 0, 0, 0xB654, 0xB655, 0x5365, 0x3345,
+ 0xB656, 0, 0x5367, 0xB657, 0xB658, 0, 0, 0x536A,
+ 0, 0, 0, 0, 0x5369, 0xB659, 0, 0,
+ 0, 0xB65A, 0xB65B, 0, 0, 0xB65C, 0xB65D, 0xB65E,
+ 0x5368, 0, 0x4739, 0, 0, 0x536B, 0xB65F, 0xB660,
+ 0xB661, 0xB662, 0, 0xB663, 0xB664, 0xB665, 0x536C, 0,
+ 0, 0xB666, 0, 0xB667, 0x536E, 0, 0x536D, 0xB668,
+ 0, 0, 0, 0, 0x5370, 0, 0xB669, 0,
+};
+const unsigned short utf8_to_euc_E59B[] = {
+ 0x5373, 0x5371, 0x536F, 0x5372, 0, 0xB66A, 0, 0,
+ 0x5374, 0xB66B, 0xB66C, 0xB66D, 0xB670, 0xB671, 0x5375, 0xB66E,
+ 0xB66F, 0x5376, 0, 0x5377, 0, 0, 0, 0x5378,
+ 0x5145, 0xB672, 0x3C7C, 0x3B4D, 0xB673, 0xB674, 0x3273, 0xB675,
+ 0x3078, 0xB676, 0, 0x4344, 0xB677, 0xB678, 0xB679, 0xB67A,
+ 0xB67B, 0, 0, 0xB67D, 0, 0xB67E, 0x5379, 0,
+ 0x3A24, 0xB67C, 0x304F, 0x3F5E, 0, 0, 0xB721, 0xB722,
+ 0, 0x537A, 0x3847, 0, 0, 0x3971, 0, 0x537C,
+};
+const unsigned short utf8_to_euc_E59C[] = {
+ 0x537B, 0xB723, 0xB724, 0x4A60, 0x537D, 0, 0, 0xB725,
+ 0x5421, 0x537E, 0xB726, 0x5422, 0xB727, 0x5423, 0, 0x3777,
+ 0, 0xB728, 0x3160, 0x5424, 0, 0xB729, 0x5426, 0,
+ 0x5425, 0, 0xB72A, 0xB72B, 0x5428, 0xB72C, 0, 0x455A,
+ 0xB72D, 0, 0xB72E, 0xB72F, 0xB730, 0xB731, 0x5429, 0x3035,
+ 0x3A5F, 0xB732, 0xB733, 0, 0xB734, 0x373D, 0xB735, 0xB736,
+ 0x434F, 0, 0, 0xB737, 0xB738, 0, 0, 0x542A,
+ 0x542B, 0, 0, 0x542D, 0, 0xB739, 0xB73A, 0xB73B,
+};
+const unsigned short utf8_to_euc_E59D[] = {
+ 0x542E, 0, 0x3A64, 0, 0, 0xB73C, 0xB73D, 0x3651,
+ 0, 0, 0x4B37, 0, 0xB73E, 0xB73F, 0x542C, 0x542F,
+ 0x3A41, 0x3923, 0xB740, 0, 0, 0, 0, 0,
+ 0, 0xF436, 0, 0, 0, 0, 0, 0,
+ 0, 0x5433, 0xB741, 0, 0x3A25, 0xB742, 0x4333, 0xB743,
+ 0xB744, 0x5430, 0x445A, 0xB745, 0, 0xB746, 0xB747, 0xB748,
+ 0xB749, 0xB74A, 0, 0xB74B, 0xB74C, 0xB74D, 0, 0xB74E,
+ 0, 0xB74F, 0xB750, 0xB751, 0xB752, 0, 0xB753, 0x5434,
+};
+const unsigned short utf8_to_euc_E59E[] = {
+ 0, 0xB754, 0x3F62, 0xB755, 0, 0, 0, 0,
+ 0x5432, 0x5435, 0, 0x373F, 0xB756, 0, 0, 0,
+ 0, 0, 0, 0x5436, 0xB757, 0xB760, 0, 0xB758,
+ 0, 0xB759, 0xB75A, 0, 0xB75B, 0xB75C, 0xB75D, 0xB75E,
+ 0x5437, 0xB75F, 0x3924, 0x3340, 0x5439, 0, 0, 0xB761,
+ 0xB762, 0xB763, 0x543A, 0, 0xB764, 0, 0, 0,
+ 0x543B, 0, 0, 0x5438, 0, 0, 0, 0,
+ 0xB765, 0, 0, 0, 0, 0xB766, 0, 0,
+};
+const unsigned short utf8_to_euc_E59F[] = {
+ 0x5431, 0, 0, 0x543C, 0, 0, 0x543D, 0xB767,
+ 0xB768, 0, 0, 0x4B64, 0xB769, 0, 0x3E6B, 0xB76A,
+ 0, 0, 0x543F, 0x5440, 0x543E, 0xB76B, 0x5442, 0,
+ 0, 0, 0, 0, 0x4738, 0xB76C, 0xB76D, 0x3068,
+ 0x4956, 0xB77E, 0, 0x5443, 0xB76E, 0, 0xB76F, 0xB770,
+ 0, 0xB771, 0, 0, 0, 0xB772, 0, 0,
+ 0xB773, 0, 0, 0, 0x3E7D, 0xB774, 0xB775, 0x3C39,
+ 0xB776, 0x475D, 0x3470, 0, 0x3A6B, 0xB777, 0xB778, 0xB779,
+};
+const unsigned short utf8_to_euc_E5A0[] = {
+ 0x4B59, 0, 0x4632, 0xB77A, 0xB77B, 0x3778, 0x424F, 0,
+ 0xB77C, 0xB77D, 0x5441, 0x5444, 0xB821, 0xB822, 0, 0,
+ 0, 0, 0, 0, 0, 0x4244, 0, 0,
+ 0, 0x5445, 0, 0xB823, 0, 0x5446, 0xB824, 0xB825,
+ 0xB826, 0x5448, 0, 0, 0x4469, 0, 0xB827, 0xB828,
+ 0, 0, 0x342E, 0, 0, 0xB829, 0, 0x7421,
+ 0x3161, 0x4A73, 0xB82A, 0, 0x3E6C, 0x4548, 0, 0,
+ 0, 0xB82B, 0x3A66, 0, 0, 0x544E, 0, 0xB82C,
+};
+const unsigned short utf8_to_euc_E5A1[] = {
+ 0x4A3D, 0x4E5D, 0, 0, 0, 0, 0, 0,
+ 0, 0xB82D, 0x3274, 0x544A, 0xB82E, 0xB82F, 0, 0xB830,
+ 0xB831, 0x413A, 0x544D, 0, 0x4563, 0xB832, 0, 0x4549,
+ 0x4564, 0x4839, 0x444D, 0, 0, 0, 0x3A49, 0xB833,
+ 0, 0xB834, 0x5449, 0, 0xB835, 0, 0, 0xB836,
+ 0xB837, 0x3176, 0, 0x4536, 0, 0, 0, 0,
+ 0x544B, 0, 0x5447, 0, 0, 0x3F50, 0, 0,
+ 0xB838, 0x544F, 0, 0, 0xB839, 0, 0x3D4E, 0xB83A,
+};
+const unsigned short utf8_to_euc_E5A2[] = {
+ 0xB83B, 0xB83C, 0, 0x362D, 0, 0x5450, 0, 0xB83D,
+ 0xB83E, 0xB83F, 0xB840, 0, 0xB841, 0xB842, 0, 0xB843,
+ 0xB844, 0, 0, 0x4A68, 0xB845, 0, 0xB846, 0x417D,
+ 0, 0, 0, 0, 0x4446, 0xB847, 0xF439, 0x5452,
+ 0xB848, 0xB849, 0xB84A, 0, 0, 0, 0xB84B, 0,
+ 0x4B4F, 0xB84C, 0, 0x5453, 0, 0, 0x5458, 0,
+ 0, 0xB84D, 0xB84E, 0x4A2F, 0, 0, 0, 0,
+ 0x5457, 0x5451, 0x5454, 0x5456, 0xB850, 0, 0x3A26, 0,
+};
+const unsigned short utf8_to_euc_E5A3[] = {
+ 0, 0x4A49, 0xB851, 0, 0xB84F, 0x5459, 0, 0x4345,
+ 0xB852, 0, 0x3275, 0, 0x3E6D, 0xB853, 0xB854, 0,
+ 0xB855, 0x545B, 0xB856, 0x545A, 0xB857, 0x3968, 0xB858, 0x545C,
+ 0x545E, 0x545D, 0xB859, 0, 0x5460, 0xB85A, 0x5455, 0x5462,
+ 0, 0xB85B, 0xB85C, 0, 0x5461, 0x545F, 0, 0,
+ 0, 0xB85D, 0, 0x3B4E, 0x3F51, 0, 0x4154, 0x5463,
+ 0x403C, 0x306D, 0x4764, 0xB85E, 0, 0, 0, 0x445B,
+ 0, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0, 0,
+};
+const unsigned short utf8_to_euc_E5A4[] = {
+ 0, 0, 0x5469, 0, 0, 0xB85F, 0xB860, 0,
+ 0, 0x4A51, 0x546A, 0xB861, 0xB862, 0, 0, 0x3246,
+ 0x546B, 0, 0xB863, 0xB864, 0xB865, 0x4D3C, 0x3330, 0,
+ 0x5249, 0x3D48, 0x423F, 0x546C, 0x4C6B, 0xB867, 0, 0,
+ 0, 0xB868, 0x4C34, 0xB869, 0xB86A, 0x546E, 0, 0x4267,
+ 0xB86B, 0x4537, 0x4240, 0x4957, 0x546F, 0x5470, 0x317B, 0xB86C,
+ 0xB86D, 0x3C3A, 0x5471, 0xB86E, 0, 0xB86F, 0xB870, 0x3050,
+ 0x5472, 0, 0, 0, 0, 0, 0x5473, 0xB871,
+};
+const unsigned short utf8_to_euc_E5A5[] = {
+ 0, 0, 0, 0xB872, 0x3162, 0, 0xB873, 0x3471,
+ 0x4660, 0x4A74, 0, 0, 0, 0, 0x5477, 0x4155,
+ 0x5476, 0x3740, 0xB874, 0xB875, 0x4B5B, 0x5475, 0, 0x4565,
+ 0x5479, 0xB876, 0x5478, 0xB877, 0, 0xB878, 0xB879, 0xB87A,
+ 0x547B, 0xB87B, 0x547A, 0xB87C, 0, 0x317C, 0, 0x547C,
+ 0x3E29, 0x547E, 0x4325, 0xB87D, 0x547D, 0xB87E, 0x4A33, 0xB921,
+ 0, 0, 0xB922, 0x3D77, 0x455B, 0xB923, 0xB924, 0,
+ 0x5521, 0xB925, 0, 0xB926, 0xB927, 0x3925, 0, 0,
+};
+const unsigned short utf8_to_euc_E5A6[] = {
+ 0, 0x5522, 0x4721, 0x485E, 0x4C51, 0, 0, 0,
+ 0, 0, 0x4725, 0xB928, 0xB929, 0x552B, 0xB92A, 0,
+ 0, 0, 0xB92B, 0x3538, 0, 0xB92C, 0x4D45, 0xB92D,
+ 0, 0x4C2F, 0, 0x562C, 0, 0x5523, 0, 0xB92E,
+ 0, 0, 0, 0x5526, 0xB92F, 0x4245, 0, 0xB930,
+ 0x4B38, 0, 0, 0, 0x454A, 0xB931, 0xB932, 0xB933,
+ 0xB934, 0, 0x5527, 0xB935, 0, 0, 0, 0xB936,
+ 0, 0x4B65, 0xB937, 0x3A4A, 0xB938, 0, 0x3E2A, 0,
+};
+const unsigned short utf8_to_euc_E5A7[] = {
+ 0, 0xB939, 0, 0xB93A, 0xB93B, 0, 0x5528, 0,
+ 0xB93C, 0x3B50, 0xB93D, 0x3B4F, 0, 0xB93E, 0, 0,
+ 0x3039, 0x3848, 0xB93F, 0x402B, 0x3051, 0, 0, 0,
+ 0, 0x552C, 0x552D, 0, 0x552A, 0xB940, 0xB941, 0xB942,
+ 0, 0, 0, 0xB943, 0xB944, 0x3138, 0x342F, 0xB945,
+ 0x5529, 0, 0x4C45, 0x4931, 0, 0, 0xB946, 0xB947,
+ 0, 0xB948, 0xB949, 0, 0xB94A, 0, 0x3028, 0xB94B,
+ 0, 0, 0, 0x3079, 0, 0, 0, 0x3B51,
+};
+const unsigned short utf8_to_euc_E5A8[] = {
+ 0xB94C, 0x3052, 0, 0x3023, 0xB94D, 0, 0, 0,
+ 0, 0x5532, 0, 0, 0xB94E, 0xB94F, 0xB950, 0,
+ 0, 0x5530, 0xB951, 0xB952, 0, 0, 0, 0,
+ 0x4C3C, 0, 0x5533, 0, 0x5531, 0, 0xB953, 0x552F,
+ 0x3F31, 0, 0, 0xB954, 0xB955, 0x552E, 0, 0xB956,
+ 0xB957, 0x4A5A, 0xB958, 0, 0, 0xB959, 0, 0x3864,
+ 0xB95A, 0, 0, 0, 0, 0x5537, 0x5538, 0,
+ 0, 0, 0, 0, 0x3E2B, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E5A9[] = {
+ 0x5534, 0x4F2C, 0, 0, 0xB95B, 0xB95C, 0x474C, 0xB95D,
+ 0xB95E, 0x5536, 0, 0, 0xB95F, 0, 0, 0,
+ 0xB960, 0, 0, 0, 0, 0xB961, 0, 0,
+ 0, 0, 0x3A27, 0, 0, 0, 0xB962, 0,
+ 0, 0, 0x5539, 0xB963, 0, 0xB964, 0x4958, 0xB965,
+ 0, 0, 0x553A, 0, 0x5535, 0xB966, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xB967,
+ 0, 0, 0xB968, 0xB969, 0, 0, 0xB96A, 0x4C3B,
+};
+const unsigned short utf8_to_euc_E5AA[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xB96B, 0, 0, 0, 0,
+ 0xB96C, 0, 0x475E, 0xB96D, 0, 0, 0xB96E, 0,
+ 0, 0xB96F, 0x553B, 0x4932, 0xB970, 0, 0xB971, 0xB972,
+ 0xB973, 0, 0xB974, 0, 0, 0, 0, 0xB975,
+ 0, 0, 0, 0, 0xB976, 0, 0, 0,
+ 0, 0xB977, 0xB978, 0xB979, 0, 0xB97A, 0, 0,
+ 0xB97B, 0, 0xB97C, 0xB97D, 0x553C, 0x5540, 0x553D, 0xB97E,
+};
+const unsigned short utf8_to_euc_E5AB[] = {
+ 0, 0x3247, 0x553F, 0, 0xBA21, 0, 0xBA22, 0,
+ 0xBA23, 0x3C3B, 0, 0x553E, 0x3779, 0, 0, 0xBA24,
+ 0x554C, 0, 0, 0, 0, 0, 0x5545, 0x5542,
+ 0, 0, 0xBA25, 0, 0xBA26, 0, 0, 0,
+ 0xBA27, 0x4364, 0, 0x5541, 0, 0xBA28, 0x5543, 0,
+ 0, 0x5544, 0xBA29, 0, 0, 0, 0xBA2A, 0,
+ 0, 0, 0, 0, 0, 0xBA2B, 0xBA2C, 0,
+ 0, 0, 0x5546, 0x5547, 0, 0xBA2D, 0, 0,
+};
+const unsigned short utf8_to_euc_E5AC[] = {
+ 0xBA2E, 0xBA2F, 0, 0, 0, 0, 0, 0,
+ 0xBA30, 0x3472, 0, 0x5549, 0x5548, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x554A, 0xBA31,
+ 0, 0xBA33, 0, 0xBA34, 0, 0xBA35, 0, 0,
+ 0, 0xBA36, 0x3E6E, 0, 0, 0xBA37, 0, 0,
+ 0, 0, 0x554D, 0, 0x445C, 0xBA38, 0, 0,
+ 0x3145, 0, 0x554B, 0, 0xBA32, 0, 0x554E, 0,
+ 0xBA39, 0, 0, 0, 0, 0, 0x554F, 0,
+};
+const unsigned short utf8_to_euc_E5AD[] = {
+ 0x5552, 0xBA3A, 0, 0x5550, 0, 0x5551, 0, 0,
+ 0, 0, 0, 0xBA3B, 0xBA3C, 0, 0, 0,
+ 0x3B52, 0x5553, 0xBA3D, 0, 0x3926, 0x5554, 0xBA3E, 0x3B7A,
+ 0x4238, 0, 0x5555, 0x5556, 0x3B5A, 0x3927, 0xBA3F, 0x4C52,
+ 0, 0, 0, 0x3528, 0x3849, 0x5557, 0x3358, 0,
+ 0xBA40, 0x5558, 0, 0x4239, 0, 0, 0xBA41, 0xBA42,
+ 0x5559, 0x5623, 0, 0x555A, 0, 0x555B, 0, 0,
+ 0x555C, 0, 0x555E, 0, 0xBA43, 0xBA44, 0xBA45, 0xBA46,
+};
+const unsigned short utf8_to_euc_E5AE[] = {
+ 0x555F, 0xBA47, 0, 0x5560, 0xBA48, 0x4270, 0xBA49, 0x3127,
+ 0x3C69, 0x3042, 0xBA4A, 0x4157, 0x3430, 0x3C35, 0xBA4B, 0x3928,
+ 0xBA4C, 0xBA4D, 0, 0xBA4E, 0xBA4F, 0x4566, 0xBA50, 0x3D21,
+ 0x3431, 0x4368, 0x446A, 0x3038, 0x3539, 0x4A75, 0, 0x3C42,
+ 0, 0, 0x3552, 0x406B, 0x3C3C, 0x4D28, 0x5561, 0,
+ 0xBA51, 0xBA52, 0, 0, 0xBA53, 0xBA54, 0x355C, 0xBA55,
+ 0x3A4B, 0xBA56, 0xBA57, 0x3332, 0x3163, 0x3E2C, 0x3248, 0xBA58,
+ 0x5562, 0x4D46, 0xBA59, 0, 0xBA5A, 0, 0, 0x3D49,
+};
+const unsigned short utf8_to_euc_E5AF[] = {
+ 0xBA5B, 0xBA5C, 0x3C64, 0x5563, 0x3473, 0x4652, 0x4C29, 0x5564,
+ 0, 0x5565, 0, 0, 0x4959, 0xBA5D, 0, 0xBA5E,
+ 0x5567, 0, 0x3428, 0x3677, 0x5566, 0, 0xBA5F, 0xBA60,
+ 0xBA61, 0xBA62, 0xBA63, 0x3432, 0, 0x3F32, 0x556B, 0x3B21,
+ 0xBA64, 0x3249, 0x556A, 0, 0x5568, 0x556C, 0x5569, 0x472B,
+ 0x5C4D, 0x3F33, 0, 0x556D, 0xF43A, 0, 0x4E40, 0xBA65,
+ 0x556E, 0xBA66, 0, 0x5570, 0xBA67, 0x437E, 0x556F, 0,
+ 0x4023, 0, 0x3B7B, 0, 0, 0xBA68, 0x4250, 0x3C77,
+};
+const unsigned short utf8_to_euc_E5B0[] = {
+ 0, 0x4975, 0x406C, 0, 0x3C4D, 0x5571, 0x3E2D, 0x5572,
+ 0x5573, 0x3053, 0x423A, 0x3F52, 0xBA69, 0x5574, 0x4633, 0x3E2E,
+ 0, 0x3E2F, 0, 0x5575, 0, 0, 0x406D, 0xBA6A,
+ 0, 0, 0x3E30, 0, 0, 0, 0xBA6B, 0xBA6C,
+ 0x5576, 0, 0x5577, 0xBA6D, 0x4C60, 0, 0xBA6E, 0,
+ 0x5578, 0xBA6F, 0, 0xBA70, 0xBA71, 0x3646, 0xBA72, 0,
+ 0xBA73, 0x3D22, 0xBA74, 0, 0, 0xBA75, 0xBA76, 0,
+ 0x5579, 0x557A, 0x3C5C, 0x3F2C, 0x4674, 0x3F54, 0x4878, 0x4722,
+};
+const unsigned short utf8_to_euc_E5B1[] = {
+ 0x3649, 0x557B, 0, 0, 0, 0x356F, 0x557C, 0,
+ 0x367E, 0, 0x464F, 0x3230, 0, 0x3B53, 0x557D, 0x5622,
+ 0x5621, 0x367D, 0, 0x557E, 0, 0x4538, 0, 0,
+ 0, 0xBA77, 0xBA78, 0, 0xBA79, 0, 0x4230, 0,
+ 0x454B, 0x3C48, 0xBA7A, 0xBA7B, 0x4158, 0x4D7A, 0, 0xBA7C,
+ 0xBA7D, 0xBA7E, 0, 0, 0x5624, 0xBB21, 0x5625, 0x4656,
+ 0xBB22, 0x3B33, 0, 0, 0xBB23, 0xBB24, 0x5627, 0,
+ 0, 0x5628, 0xBB25, 0xBB26, 0xBB27, 0xBB28, 0, 0,
+};
+const unsigned short utf8_to_euc_E5B2[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0xBB29,
+ 0xBB2A, 0, 0xBB2B, 0, 0x5629, 0, 0, 0xBB2C,
+ 0x3474, 0x562A, 0xBB2D, 0, 0x562B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xBB2E, 0, 0xBB2F,
+ 0xBB30, 0x322C, 0xBB31, 0xBB32, 0, 0, 0xBB33, 0,
+ 0x413B, 0x3464, 0xBB34, 0x562D, 0x4C28, 0, 0, 0,
+ 0, 0x4252, 0xBB35, 0x3359, 0xBB36, 0xBB37, 0x562F, 0x5631,
+ 0x345F, 0, 0xBB38, 0x562E, 0x5630, 0, 0x5633, 0,
+};
+const unsigned short utf8_to_euc_E5B3[] = {
+ 0, 0, 0, 0, 0, 0x5632, 0, 0x5634,
+ 0, 0xBB39, 0, 0xBB3A, 0, 0, 0, 0,
+ 0, 0, 0xBB3B, 0, 0, 0, 0, 0xBB3D,
+ 0, 0x5635, 0, 0, 0, 0xBB3C, 0, 0,
+ 0x463D, 0x362E, 0, 0, 0, 0, 0, 0,
+ 0x3265, 0x5636, 0x563B, 0, 0, 0x5639, 0xBB3E, 0x4A77,
+ 0x4A76, 0xBB3F, 0xBB40, 0, 0xBB41, 0xF43B, 0x4567, 0,
+ 0, 0, 0x5638, 0x3D54, 0, 0x5637, 0, 0,
+};
+const unsigned short utf8_to_euc_E5B4[] = {
+ 0, 0xBB42, 0, 0, 0, 0, 0xBB43, 0x3F72,
+ 0, 0, 0, 0x563C, 0, 0xBB44, 0x3A6A, 0,
+ 0, 0x5642, 0xBB45, 0, 0x5643, 0x563D, 0x3333, 0x563E,
+ 0x5647, 0x5646, 0x5645, 0x5641, 0, 0, 0, 0x5640,
+ 0, 0, 0x5644, 0xBB47, 0xBB48, 0, 0xBB49, 0xBB4A,
+ 0, 0x4A78, 0, 0xBB46, 0, 0, 0, 0,
+ 0, 0xBB4B, 0, 0, 0xBB4C, 0, 0, 0,
+ 0, 0xBB4D, 0, 0, 0, 0xBB4E, 0, 0xBB4F,
+};
+const unsigned short utf8_to_euc_E5B5[] = {
+ 0, 0, 0xBB50, 0xBB51, 0, 0, 0xBB52, 0,
+ 0xBB53, 0, 0xBB57, 0x564B, 0x5648, 0, 0x564A, 0,
+ 0x4D72, 0xBB55, 0x5649, 0xF43C, 0, 0xBB54, 0, 0,
+ 0, 0xBB56, 0, 0, 0x563F, 0, 0, 0xBB58,
+ 0xBB59, 0xBB5A, 0xBB5B, 0, 0xBB5C, 0, 0, 0,
+ 0, 0x3F73, 0xBB5D, 0, 0x564C, 0xBB5E, 0, 0x3A37,
+ 0xBB5F, 0, 0, 0x564D, 0, 0, 0x564E, 0,
+ 0, 0xBB60, 0xBB61, 0, 0, 0, 0xBB62, 0xBB63,
+};
+const unsigned short utf8_to_euc_E5B6[] = {
+ 0, 0xBB64, 0x5651, 0xBB65, 0x5650, 0, 0, 0x564F,
+ 0xBB66, 0, 0xBB67, 0x4568, 0x563A, 0, 0, 0,
+ 0x5657, 0, 0xBB68, 0xBB69, 0xBB6A, 0xBB6B, 0, 0,
+ 0, 0xBB6C, 0, 0xBB6D, 0, 0x5653, 0, 0xBB6E,
+ 0xBB6F, 0, 0x5652, 0, 0, 0, 0, 0xBB70,
+ 0, 0, 0, 0xBB71, 0x5654, 0, 0x5655, 0,
+ 0xBB72, 0, 0xE674, 0, 0xBB73, 0, 0, 0x5658,
+ 0xBB74, 0xBB75, 0x4E66, 0, 0x5659, 0x5656, 0, 0,
+};
+const unsigned short utf8_to_euc_E5B7[] = {
+ 0, 0, 0, 0xBB76, 0, 0, 0, 0xBB77,
+ 0, 0x565A, 0, 0xBB78, 0x3460, 0x565B, 0xBB7A, 0,
+ 0xBB79, 0, 0x565D, 0x565C, 0, 0, 0x565E, 0,
+ 0xBB7B, 0xBB7C, 0, 0x565F, 0, 0x406E, 0x3D23, 0,
+ 0xBB7D, 0x3D64, 0, 0x4163, 0xBB7E, 0x3929, 0x3A38, 0x392A,
+ 0x3570, 0xBC21, 0, 0x5660, 0, 0, 0x3A39, 0,
+ 0, 0x384A, 0x5661, 0x4C26, 0x4743, 0x5662, 0, 0x392B,
+ 0xBC22, 0xBC23, 0, 0x342C, 0, 0x4327, 0x3652, 0,
+};
+const unsigned short utf8_to_euc_E5B8[] = {
+ 0xBC24, 0, 0x3B54, 0x495B, 0, 0, 0x4841, 0xBC25,
+ 0, 0, 0, 0x5663, 0x3475, 0xBC26, 0, 0,
+ 0, 0x5666, 0xBC27, 0, 0xBC28, 0xBC29, 0x4421, 0,
+ 0xBC2A, 0x5665, 0x5664, 0x5667, 0, 0x446B, 0, 0xBC2B,
+ 0xBC2C, 0, 0, 0, 0, 0x3F63, 0, 0,
+ 0xBC2E, 0, 0, 0x3B55, 0, 0x404A, 0xBC2D, 0x4253,
+ 0x3522, 0, 0xBC2F, 0x4422, 0, 0xBC30, 0x5668, 0x5669,
+ 0x3E6F, 0, 0, 0, 0, 0x4B39, 0xBC31, 0,
+};
+const unsigned short utf8_to_euc_E5B9[] = {
+ 0x566C, 0, 0, 0x566B, 0x566A, 0x497D, 0, 0x5673,
+ 0, 0xBC34, 0, 0xBC32, 0x4B5A, 0, 0x566D, 0,
+ 0xBC33, 0xBC35, 0, 0, 0x566F, 0x4B6B, 0xBC36, 0x566E,
+ 0xBC37, 0, 0, 0xBC38, 0xBC39, 0, 0xBC3A, 0x5670,
+ 0, 0x4828, 0x5671, 0x4A3E, 0x5672, 0, 0, 0,
+ 0xBC3B, 0, 0xBC3C, 0xBC3D, 0xBC3E, 0xBC3F, 0xBC40, 0,
+ 0xBC41, 0, 0x3433, 0x4A3F, 0x472F, 0x5674, 0x5675, 0,
+ 0x392C, 0x3434, 0x5676, 0x3838, 0x4D44, 0x4D29, 0x3476, 0x5678,
+};
+const unsigned short utf8_to_euc_E5BA[] = {
+ 0xBC42, 0x4423, 0, 0x392D, 0x3E31, 0, 0, 0x485F,
+ 0, 0, 0x3E32, 0xBC43, 0, 0, 0xBC44, 0x3D78,
+ 0, 0, 0, 0, 0, 0x446C, 0x4A79, 0x4539,
+ 0, 0, 0x392E, 0, 0x495C, 0, 0, 0,
+ 0x5679, 0, 0xBC45, 0, 0xBC46, 0xBC47, 0x4559, 0x3A42,
+ 0xBC48, 0, 0xBC49, 0x384B, 0xBC4A, 0x446D, 0, 0,
+ 0, 0xBC4B, 0, 0xBC4C, 0, 0x3043, 0x3D6E, 0x392F,
+ 0x4D47, 0, 0, 0, 0, 0xBC4D, 0xBC4E, 0xBC4F,
+};
+const unsigned short utf8_to_euc_E5BB[] = {
+ 0, 0x567A, 0x567B, 0x4751, 0, 0, 0xBC50, 0,
+ 0x567C, 0x4E77, 0x4F2D, 0xBC52, 0xBC51, 0, 0xBC53, 0x567E,
+ 0x567D, 0xBC54, 0xBC55, 0x3347, 0xBC56, 0xBC57, 0x5721, 0,
+ 0, 0, 0x5724, 0x5725, 0xBC58, 0x5723, 0xBC59, 0x4940,
+ 0x3E33, 0x5727, 0x5726, 0x5722, 0, 0xBC5A, 0, 0,
+ 0x5728, 0x5729, 0, 0xBC5B, 0x572A, 0, 0, 0,
+ 0x572D, 0x572B, 0, 0x572C, 0x572E, 0, 0x3164, 0x446E,
+ 0x572F, 0, 0x377A, 0x3276, 0x4736, 0, 0x5730, 0x467B,
+};
+const unsigned short utf8_to_euc_E5BC[] = {
+ 0, 0x4A5B, 0xBC5C, 0x5731, 0x4F2E, 0, 0xBC5D, 0xBC5E,
+ 0xBC5F, 0x5732, 0x4A40, 0x5735, 0x5021, 0x5031, 0xBC60, 0x3C30,
+ 0x4675, 0x5736, 0, 0x355D, 0x4424, 0x307A, 0x5737, 0x4A26,
+ 0x3930, 0xBC61, 0, 0x4350, 0xBC62, 0xBC63, 0, 0x446F,
+ 0, 0xBC64, 0xBC65, 0xBC66, 0xBC67, 0x4C6F, 0x3839, 0x384C,
+ 0xBC68, 0x5738, 0, 0xBC69, 0xBC6A, 0x5739, 0xBC6B, 0x573F,
+ 0xBC6C, 0x3C65, 0, 0, 0xBC6D, 0x4425, 0xBC6E, 0x362F,
+ 0x573A, 0, 0, 0xBC6F, 0x492B, 0xBC70, 0x4346, 0xBC71,
+};
+const unsigned short utf8_to_euc_E5BD[] = {
+ 0xBC72, 0x573B, 0, 0, 0xBC73, 0xBC74, 0, 0xBC75,
+ 0x573C, 0, 0x3630, 0, 0x573D, 0xBC76, 0x573E, 0,
+ 0xBC77, 0x5740, 0, 0x4576, 0xBC78, 0, 0x5741, 0x5742,
+ 0xBC79, 0x5743, 0, 0xBC7A, 0x5734, 0x5733, 0, 0,
+ 0xBC7B, 0x5744, 0x3741, 0xBC7C, 0xBC7D, 0, 0x4927, 0xBC7E,
+ 0, 0x3A4C, 0x4937, 0x4426, 0x494B, 0x5745, 0, 0xBD21,
+ 0x3E34, 0x3146, 0xBD22, 0x5746, 0xBD23, 0xBD24, 0, 0x5747,
+ 0xBD25, 0x4C72, 0xBD26, 0, 0x4860, 0xBD27, 0xBD28, 0x574A,
+};
+const unsigned short utf8_to_euc_E5BE[] = {
+ 0x317D, 0x402C, 0x5749, 0x5748, 0x3742, 0x4254, 0, 0x574E,
+ 0x574C, 0xBD29, 0x574B, 0x4E27, 0x3865, 0xBD2A, 0, 0xBD2B,
+ 0x3D79, 0x574D, 0x454C, 0x3D3E, 0, 0, 0xBD2C, 0x4640,
+ 0x5751, 0x5750, 0, 0, 0xBD2D, 0xBD2E, 0x574F, 0,
+ 0x5752, 0x3866, 0xBD2F, 0, 0xBD32, 0, 0, 0xBD30,
+ 0x5753, 0x497C, 0x3D5B, 0xBD31, 0xBD33, 0x5754, 0x4879, 0xBD34,
+ 0xBD35, 0xBD36, 0, 0x4641, 0x4427, 0, 0, 0xF43E,
+ 0xBD37, 0x4530, 0, 0, 0x5755, 0x352B, 0, 0,
+};
+const unsigned short utf8_to_euc_E5BF[] = {
+ 0, 0, 0, 0x3F34, 0xBD38, 0x492C, 0, 0xBD39,
+ 0xBD3A, 0xBD3B, 0, 0xBD3C, 0x3477, 0x4726, 0, 0,
+ 0xBD3D, 0xBD3E, 0xBD3F, 0xBD40, 0xBD41, 0, 0x5756, 0x3B56,
+ 0x4B3A, 0x4B3B, 0, 0, 0x317E, 0x575B, 0xBD42, 0,
+ 0x4369, 0xBD43, 0xBD44, 0, 0x5758, 0, 0, 0,
+ 0xBD45, 0xBD46, 0xBD47, 0x3277, 0xBD48, 0xBD49, 0xBD4A, 0xBD4B,
+ 0x582D, 0x575A, 0xBD4C, 0xBD4D, 0, 0x4730, 0xBD4E, 0,
+ 0x5759, 0, 0xBD4F, 0x5757, 0xBD50, 0x397A, 0, 0x575D,
+};
+const unsigned short utf8_to_euc_E680[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0xBD51,
+ 0, 0, 0xBD52, 0, 0, 0xBD53, 0x5763, 0x5769,
+ 0x5761, 0, 0x455C, 0xBD54, 0xBD55, 0x5766, 0x495D, 0xBD56,
+ 0xBD57, 0x5760, 0xBD58, 0x5765, 0x4E67, 0x3B57, 0, 0xBD59,
+ 0x4255, 0x575E, 0, 0, 0xBD5A, 0x355E, 0x5768, 0x402D,
+ 0x3165, 0x5762, 0x3278, 0x5767, 0, 0xBD5B, 0, 0x3631,
+ 0, 0x5764, 0, 0xBD5C, 0, 0xBD5D, 0, 0,
+ 0, 0, 0x576A, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E681[] = {
+ 0xBD5E, 0x576C, 0x5776, 0x5774, 0, 0, 0x5771, 0xBD5F,
+ 0xBD60, 0xBD61, 0x5770, 0x4E78, 0xBD62, 0x5772, 0, 0,
+ 0x3632, 0xBD63, 0x3931, 0, 0xBD64, 0x3D7A, 0xBD65, 0xBD66,
+ 0, 0x5779, 0x576B, 0, 0, 0xBD67, 0, 0x576F,
+ 0x575F, 0xBD68, 0x327A, 0x5773, 0x5775, 0x4351, 0, 0xBD69,
+ 0x3A28, 0x3238, 0x576D, 0x5778, 0x5777, 0x3633, 0, 0x4229,
+ 0x3366, 0xBD6A, 0, 0, 0, 0x3743, 0, 0x576E,
+ 0, 0, 0, 0, 0, 0, 0xBD6B, 0xBD6C,
+};
+const unsigned short utf8_to_euc_E682[] = {
+ 0, 0x577A, 0xBD6D, 0x577D, 0x5821, 0xF43F, 0xBD6E, 0,
+ 0xBD6F, 0x3C3D, 0xBD70, 0x5827, 0x4470, 0x577B, 0xBD71, 0,
+ 0, 0xBD72, 0x5825, 0xBD73, 0x3279, 0xBD74, 0x5823, 0x5824,
+ 0xBD75, 0, 0x577E, 0x5822, 0, 0xBD76, 0xBD77, 0x3867,
+ 0x4D2A, 0, 0xBD78, 0x3435, 0xBD79, 0xBD7A, 0x3159, 0x5826,
+ 0xBD7B, 0x473A, 0x302D, 0, 0, 0, 0, 0,
+ 0xBD7C, 0xBD7D, 0x4861, 0x575C, 0x582C, 0x5830, 0x4C65, 0xBD7E,
+ 0x5829, 0, 0, 0xBE21, 0x4569, 0x582E, 0xBE22, 0,
+};
+const unsigned short utf8_to_euc_E683[] = {
+ 0, 0, 0xBE23, 0, 0xBE24, 0x3E70, 0x582F, 0x4657,
+ 0xBE25, 0xBE26, 0xBE27, 0xBE28, 0, 0, 0xBE29, 0xBE2A,
+ 0, 0x4F47, 0, 0x582B, 0xBE2B, 0xBE2C, 0, 0,
+ 0x5831, 0xBE2D, 0x397B, 0xBE2E, 0x404B, 0xBE2F, 0xBE30, 0x3054,
+ 0x582A, 0x5828, 0xBE31, 0x415A, 0, 0xBE32, 0, 0x577C,
+ 0x3B34, 0, 0, 0, 0, 0, 0, 0,
+ 0x4246, 0x583D, 0xBE33, 0x415B, 0x5838, 0xBE34, 0x5835, 0x5836,
+ 0xBE35, 0x3C66, 0x5839, 0x583C, 0xBE36, 0xBE37, 0, 0,
+};
+const unsigned short utf8_to_euc_E684[] = {
+ 0x5837, 0x3D25, 0xBE38, 0x583A, 0, 0, 0x5834, 0xBE39,
+ 0x4C7C, 0x4C7B, 0xBE3A, 0, 0xBE3B, 0x583E, 0x583F, 0x3055,
+ 0xBE3C, 0xBE3D, 0xBE3E, 0xBE3F, 0xBE40, 0x5833, 0xBE41, 0xBE42,
+ 0, 0xBE43, 0x3672, 0x3026, 0xBE44, 0, 0xBE45, 0x3436,
+ 0xF440, 0x583B, 0xBE46, 0, 0, 0, 0, 0x5843,
+ 0x5842, 0, 0xBE47, 0xBE48, 0x5847, 0, 0, 0,
+ 0xBE49, 0xBE4A, 0, 0, 0x5848, 0xBE4B, 0xBE4C, 0xBE4D,
+ 0, 0xBE4E, 0, 0, 0x5846, 0x5849, 0x5841, 0x5845,
+};
+const unsigned short utf8_to_euc_E685[] = {
+ 0, 0xBE4F, 0x584A, 0, 0x584B, 0xBE50, 0xBE51, 0x5840,
+ 0x3B7C, 0xBE52, 0x5844, 0x4256, 0x3932, 0x5832, 0x3F35, 0,
+ 0, 0, 0, 0x5858, 0, 0x4A69, 0, 0,
+ 0x584E, 0x584F, 0x5850, 0, 0, 0x5857, 0xBE53, 0x5856,
+ 0xBE54, 0, 0x4B7D, 0x3437, 0, 0x5854, 0, 0x3745,
+ 0x3334, 0, 0, 0x5851, 0xBE55, 0, 0x4E38, 0x5853,
+ 0x3056, 0x5855, 0xBE56, 0x584C, 0x5852, 0x5859, 0x3744, 0x584D,
+ 0xBE57, 0, 0, 0xBE58, 0xBE59, 0, 0x4D5D, 0xBE5A,
+};
+const unsigned short utf8_to_euc_E686[] = {
+ 0xBE5B, 0xBE5C, 0x4D2B, 0xBE5D, 0xBE5E, 0, 0, 0x585C,
+ 0, 0, 0x5860, 0xBE5F, 0, 0xBE60, 0x417E, 0,
+ 0x4E79, 0x5861, 0xBE61, 0xBE62, 0x585E, 0, 0x585B, 0xBE63,
+ 0xBE64, 0x585A, 0x585F, 0, 0xBE65, 0xBE66, 0, 0xBE67,
+ 0xBE68, 0, 0, 0, 0x4A30, 0xBE69, 0, 0x4634,
+ 0xBE6A, 0x3746, 0xBE6B, 0x5862, 0x585D, 0xBE6C, 0x5863, 0,
+ 0, 0, 0x377B, 0, 0, 0, 0x3231, 0,
+ 0xBE6D, 0xBE6E, 0x586B, 0, 0xBE6F, 0, 0x3438, 0,
+};
+const unsigned short utf8_to_euc_E687[] = {
+ 0xBE70, 0xBE71, 0xBE72, 0x5869, 0, 0, 0x586A, 0x3A29,
+ 0x5868, 0x5866, 0x5865, 0x586C, 0x5864, 0x586E, 0xBE73, 0xBE74,
+ 0x327B, 0, 0, 0, 0, 0xBE75, 0, 0,
+ 0, 0, 0, 0, 0xBE76, 0xBE77, 0xBE78, 0xBE79,
+ 0, 0xBE7A, 0xBE7B, 0x5870, 0, 0xBE7E, 0x586F, 0xBE7C,
+ 0, 0xBE7D, 0, 0, 0xBF21, 0xBF22, 0, 0xBF23,
+ 0, 0, 0x4428, 0, 0x5873, 0, 0x5871, 0x5867,
+ 0x377C, 0, 0x5872, 0, 0x5876, 0x5875, 0x5877, 0x5874,
+};
+const unsigned short utf8_to_euc_E688[] = {
+ 0x5878, 0xBF24, 0, 0xBF25, 0xBF26, 0, 0, 0xBF27,
+ 0x5879, 0x587A, 0x4A6A, 0, 0x587C, 0x587B, 0x3D3F, 0,
+ 0x402E, 0x3266, 0x327C, 0xBF28, 0x587D, 0xBF29, 0x303F, 0,
+ 0, 0, 0x404C, 0x587E, 0xBF2A, 0x6C43, 0x5921, 0x3761,
+ 0xBF2B, 0x5922, 0xBF2C, 0xBF2D, 0, 0, 0x406F, 0xBF2E,
+ 0, 0xBF2F, 0x5923, 0xBF30, 0, 0, 0x5924, 0x353A,
+ 0x5925, 0, 0x5926, 0x5927, 0x4257, 0, 0, 0,
+ 0x384D, 0xBF31, 0, 0x4C61, 0, 0xBF32, 0, 0x4B3C,
+};
+const unsigned short utf8_to_euc_E689[] = {
+ 0x3D6A, 0x5928, 0xBF33, 0xBF34, 0xBF35, 0, 0xBF36, 0x4070,
+ 0x6E3D, 0x4862, 0, 0x3C6A, 0xBF37, 0x3A4D, 0x5929, 0,
+ 0xBF38, 0xBF39, 0xBF3A, 0x4247, 0xBF3B, 0x4A27, 0xBF3C, 0,
+ 0x4271, 0, 0xBF3D, 0x592C, 0xBF3E, 0, 0x592A, 0,
+ 0x592D, 0, 0, 0x592B, 0xBF3F, 0, 0, 0,
+ 0x592E, 0, 0, 0, 0, 0xBF40, 0x4A31, 0xBF41,
+ 0, 0x3037, 0, 0xBF42, 0, 0, 0x495E, 0,
+ 0, 0x4863, 0xBF43, 0, 0x592F, 0xBF44, 0x5932, 0x3E35,
+};
+const unsigned short utf8_to_euc_E68A[] = {
+ 0x353B, 0, 0x5930, 0x5937, 0x3E36, 0, 0, 0,
+ 0, 0x5931, 0x4744, 0, 0, 0xBF45, 0xBF46, 0xBF47,
+ 0xBF48, 0x4D5E, 0x5933, 0x5934, 0x5938, 0x456A, 0x5935, 0x3933,
+ 0x405E, 0, 0, 0x5946, 0x4834, 0, 0x4272, 0,
+ 0, 0, 0, 0, 0, 0, 0xBF49, 0,
+ 0xBF4A, 0, 0, 0x4864, 0x5A2D, 0, 0, 0,
+ 0, 0x4A7A, 0, 0xBF4B, 0, 0x4471, 0xBF4C, 0xBF4D,
+ 0, 0x4B75, 0xBF4E, 0x593B, 0x3221, 0x436A, 0xBF4F, 0xBF50,
+};
+const unsigned short utf8_to_euc_E68B[] = {
+ 0, 0, 0x5944, 0, 0xBF51, 0x4334, 0x593E, 0x5945,
+ 0x5940, 0x5947, 0x5943, 0, 0x5942, 0x476F, 0xBF52, 0x593C,
+ 0x327D, 0x593A, 0x3571, 0x4273, 0x5936, 0xBF53, 0xBF54, 0x5939,
+ 0x3934, 0x405B, 0xBF55, 0x3E37, 0x5941, 0x4752, 0, 0,
+ 0x3572, 0x3348, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xBF56, 0, 0x3367, 0x3F21, 0x5949, 0x594E,
+ 0, 0x594A, 0xBF57, 0x377D, 0xBF58, 0x594F, 0x3B22, 0x3969,
+ 0, 0, 0, 0, 0xBF59, 0xBF5A, 0x3D26, 0x593D,
+};
+const unsigned short utf8_to_euc_E68C[] = {
+ 0, 0x3B7D, 0x594C, 0xBF5B, 0xBF5C, 0, 0, 0x3B58,
+ 0x594D, 0x3044, 0xBF5D, 0xBF5E, 0x5948, 0xBF5F, 0, 0,
+ 0xBF60, 0x4429, 0, 0xBF61, 0, 0, 0xBF62, 0,
+ 0xBF63, 0x3573, 0, 0, 0, 0, 0, 0x3634,
+ 0, 0, 0, 0, 0, 0, 0, 0x594B,
+ 0x3027, 0xBF64, 0xBF65, 0x3A43, 0, 0xBF66, 0, 0x3F36,
+ 0, 0, 0, 0, 0, 0xBF67, 0xBF68, 0,
+ 0, 0xBF69, 0x4472, 0, 0xBF6A, 0x4854, 0x5951, 0x415E,
+};
+const unsigned short utf8_to_euc_E68D[] = {
+ 0, 0xBF6B, 0xBF6C, 0xBF6D, 0xBF6E, 0, 0xBF6F, 0,
+ 0, 0x422A, 0xBF70, 0xBF71, 0x3B2B, 0x5952, 0xBF72, 0x5954,
+ 0x5950, 0, 0xBF73, 0xBF74, 0xBF75, 0x4A61, 0, 0x443D,
+ 0xBF76, 0, 0, 0xBF77, 0x415C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xBF78, 0xBF79, 0x4A7B,
+ 0x3C4E, 0x5960, 0, 0x595F, 0xBF7A, 0xBF7B, 0x3F78, 0,
+ 0, 0xBF7C, 0x377E, 0, 0xBF7D, 0xBF7E, 0x5959, 0x3E39,
+ 0xC021, 0, 0x4668, 0x4731, 0xC022, 0xC023, 0, 0xC024,
+};
+const unsigned short utf8_to_euc_E68E[] = {
+ 0x5957, 0, 0xC025, 0x415D, 0xC026, 0, 0, 0xC027,
+ 0x3C78, 0x595C, 0xC028, 0, 0x3E38, 0, 0x5956, 0x595B,
+ 0xC029, 0, 0x4753, 0, 0xC02A, 0xC02B, 0x5955, 0,
+ 0x3721, 0xC02C, 0xC02D, 0x335D, 0, 0, 0xC02E, 0x595D,
+ 0x4E2B, 0x3A4E, 0x4335, 0x595A, 0xC02F, 0x405C, 0xC030, 0x3935,
+ 0x3F64, 0x3166, 0x413C, 0x5958, 0x3545, 0xC031, 0xC032, 0xC033,
+ 0, 0, 0x3747, 0, 0x444F, 0x595E, 0, 0,
+ 0, 0, 0, 0x415F, 0, 0xC034, 0x5961, 0,
+};
+const unsigned short utf8_to_euc_E68F[] = {
+ 0x5963, 0xC035, 0, 0x4237, 0x5969, 0xC036, 0x5964, 0,
+ 0xC037, 0x5966, 0, 0, 0, 0, 0xC038, 0x4941,
+ 0x4473, 0xC039, 0x5967, 0xC03A, 0xC03B, 0xC03C, 0x4D2C, 0,
+ 0, 0, 0x4D48, 0x3439, 0xC03D, 0, 0, 0,
+ 0xC03E, 0x302E, 0, 0x5965, 0, 0xC03F, 0, 0,
+ 0, 0x5962, 0xC040, 0, 0xC041, 0, 0x3478, 0,
+ 0, 0, 0xC042, 0xC043, 0x3167, 0xC044, 0x5968, 0,
+ 0xC045, 0xC046, 0x4D49, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E690[] = {
+ 0, 0, 0, 0, 0, 0, 0x596C, 0,
+ 0, 0xC047, 0xC048, 0, 0, 0x423B, 0, 0x5973,
+ 0xC049, 0, 0xC04A, 0x596D, 0xC04B, 0, 0x596A, 0x5971,
+ 0xC04C, 0, 0, 0, 0x5953, 0, 0xC04D, 0,
+ 0xC04E, 0, 0xC04F, 0, 0xC050, 0xC051, 0x596E, 0,
+ 0x5972, 0xC052, 0xC053, 0, 0x4842, 0x456B, 0, 0xC054,
+ 0xC055, 0, 0, 0, 0x596B, 0xC056, 0x596F, 0,
+ 0, 0, 0x3748, 0, 0, 0xC057, 0x3A71, 0xC058,
+};
+const unsigned short utf8_to_euc_E691[] = {
+ 0, 0, 0x405D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xC059, 0, 0, 0x5977, 0xC05A,
+ 0, 0xC05B, 0xC05C, 0xC05D, 0xC05E, 0, 0, 0,
+ 0x4526, 0, 0xC05F, 0xC060, 0xC061, 0xC062, 0, 0xC063,
+ 0xC064, 0xC065, 0, 0xC066, 0, 0, 0, 0x5974,
+ 0, 0x4B60, 0, 0, 0, 0xC067, 0, 0x5975,
+ 0, 0, 0, 0xC068, 0xC069, 0, 0x5976, 0,
+ 0x4C4E, 0, 0x4022, 0xC06A, 0, 0xC06B, 0, 0,
+};
+const unsigned short utf8_to_euc_E692[] = {
+ 0, 0, 0, 0x3762, 0, 0xC06C, 0, 0xC06D,
+ 0x597D, 0, 0, 0, 0, 0, 0, 0xC06E,
+ 0xC06F, 0xC070, 0x3B35, 0x597A, 0, 0x5979, 0, 0,
+ 0xC071, 0xC072, 0x4732, 0xC073, 0, 0xC074, 0x4635, 0xC075,
+ 0, 0xC076, 0, 0xC077, 0x4531, 0x597B, 0xC078, 0,
+ 0xC079, 0x597C, 0, 0x496F, 0xC07A, 0x4745, 0x3B23, 0,
+ 0x4071, 0, 0x4B50, 0xC07B, 0, 0, 0, 0,
+ 0, 0x3349, 0, 0x5A25, 0x597E, 0xC07C, 0xC07D, 0xC07E,
+};
+const unsigned short utf8_to_euc_E693[] = {
+ 0, 0x4D4A, 0x5A27, 0, 0xC121, 0x5A23, 0, 0x5A24,
+ 0, 0xC122, 0xC123, 0xC124, 0xC125, 0x4160, 0xC126, 0,
+ 0xC127, 0xC128, 0x5A22, 0, 0x593F, 0xC129, 0, 0xC12A,
+ 0x5A26, 0, 0x5A21, 0, 0, 0, 0, 0,
+ 0x5A2B, 0x5A2C, 0x4527, 0x5A2E, 0xC12B, 0xC12C, 0x3B24, 0x5A29,
+ 0, 0xC12D, 0xC12E, 0, 0x353C, 0xC12F, 0, 0x5A2F,
+ 0xC130, 0x5A28, 0x5A33, 0, 0x5A32, 0xC131, 0x5A31, 0xC132,
+ 0, 0, 0x5A34, 0xC133, 0, 0x5A36, 0x3E71, 0xC134,
+};
+const unsigned short utf8_to_euc_E694[] = {
+ 0x5A35, 0xC135, 0, 0, 0xC136, 0x5A39, 0, 0,
+ 0xC137, 0xC138, 0xC139, 0, 0, 0, 0, 0xC13A,
+ 0, 0, 0, 0xC13B, 0xC13C, 0, 0xC13D, 0,
+ 0x5A37, 0xC13E, 0, 0xC13F, 0x5A38, 0x5970, 0xC140, 0xC141,
+ 0, 0, 0xC142, 0x5A3B, 0x5A3A, 0, 0xC143, 0,
+ 0, 0xC144, 0x5978, 0x5A3C, 0x5A30, 0, 0xC145, 0x3B59,
+ 0, 0xC146, 0, 0, 0x5A3D, 0x5A3E, 0x5A40, 0x5A3F,
+ 0x5A41, 0x327E, 0xC147, 0x3936, 0xC148, 0xC149, 0x4A7C, 0x402F,
+};
+const unsigned short utf8_to_euc_E695[] = {
+ 0, 0, 0, 0xC14A, 0, 0x384E, 0, 0xC14B,
+ 0x5A43, 0xC14C, 0, 0, 0, 0x5A46, 0xF441, 0x4952,
+ 0xC14D, 0x355F, 0xC14E, 0, 0xC14F, 0x5A45, 0x5A44, 0x4754,
+ 0x5A47, 0x3635, 0, 0, 0, 0x5A49, 0x5A48, 0xC150,
+ 0xC151, 0, 0x343A, 0x3B36, 0, 0, 0x4658, 0xC152,
+ 0, 0, 0, 0xC153, 0x3749, 0, 0, 0,
+ 0x3F74, 0, 0x5A4A, 0, 0x4030, 0x4528, 0, 0x495F,
+ 0x5A4B, 0, 0xC154, 0, 0, 0xC155, 0, 0,
+};
+const unsigned short utf8_to_euc_E696[] = {
+ 0, 0xC156, 0x5A4C, 0x5A4D, 0, 0xC157, 0, 0x4A38,
+ 0x555D, 0x4046, 0xC158, 0, 0x494C, 0, 0x3A58, 0,
+ 0x4865, 0x4843, 0xC159, 0, 0, 0xC15A, 0, 0x454D,
+ 0xC15B, 0x4E41, 0, 0x5A4F, 0x3C50, 0xC15C, 0, 0x5A50,
+ 0xC15D, 0x3036, 0, 0xC15E, 0x3654, 0x404D, 0xC15F, 0x4960,
+ 0, 0, 0, 0x5A51, 0x3B42, 0x4347, 0xC160, 0x3B5B,
+ 0x3F37, 0, 0xC161, 0xC162, 0xC163, 0, 0, 0x5A52,
+ 0, 0x4A7D, 0, 0, 0x3177, 0x3B5C, 0, 0xC164,
+};
+const unsigned short utf8_to_euc_E697[] = {
+ 0, 0x5A55, 0xC165, 0x5A53, 0x5A56, 0x4E39, 0x5A54, 0,
+ 0xC166, 0xC167, 0, 0x407B, 0x5A57, 0, 0xC168, 0x4232,
+ 0xC169, 0, 0x5A58, 0, 0xC16A, 0, 0xC16B, 0x347A,
+ 0xC16C, 0x5A5A, 0, 0x5A59, 0, 0, 0, 0xC16D,
+ 0x5A5B, 0x5A5C, 0x347B, 0, 0, 0x467C, 0x4336, 0x356C,
+ 0x3B5D, 0x4161, 0, 0, 0x3D5C, 0x3030, 0, 0,
+ 0xC16E, 0x5A5D, 0xC16F, 0, 0xC170, 0xC171, 0, 0,
+ 0, 0xC172, 0x3222, 0x5A61, 0, 0, 0xC173, 0xC174,
+};
+const unsigned short utf8_to_euc_E698[] = {
+ 0xC175, 0, 0x3937, 0x5A60, 0xC176, 0, 0x3A2B, 0x3E3A,
+ 0xC177, 0xC178, 0x5A5F, 0, 0x3E3B, 0xC179, 0x4C40, 0x3A2A,
+ 0, 0xC17A, 0xC17B, 0x3057, 0x404E, 0xC17C, 0xC17D, 0,
+ 0, 0, 0, 0, 0x5A66, 0xC17E, 0xC221, 0x4031,
+ 0x3147, 0xC222, 0xC223, 0xC224, 0xC225, 0x3D55, 0xC226, 0x4B66,
+ 0x3A72, 0xC227, 0xC228, 0xC229, 0xC22A, 0x3E3C, 0xC22B, 0x4027,
+ 0xC22C, 0xC22D, 0, 0xC22E, 0x5A65, 0x5A63, 0x5A64, 0xC230,
+ 0, 0xC22F, 0, 0xF442, 0x436B, 0, 0, 0x5B26,
+};
+const unsigned short utf8_to_euc_E699[] = {
+ 0xC231, 0x5A6A, 0x3B7E, 0x3938, 0x5A68, 0xC232, 0xC233, 0,
+ 0, 0x5A69, 0xC234, 0x3F38, 0xC235, 0, 0xC237, 0x5A67,
+ 0, 0xC236, 0x3B2F, 0, 0, 0, 0, 0xC238,
+ 0xC239, 0xC23A, 0, 0xC23B, 0xC23C, 0x5A6C, 0x5A6B, 0x5A70,
+ 0xC23D, 0xC23E, 0x5A71, 0, 0x5A6D, 0xF443, 0x3322, 0x5A6E,
+ 0x5A6F, 0x4855, 0xC240, 0xC241, 0xC242, 0, 0x4961, 0x374A,
+ 0x5A72, 0, 0, 0xC244, 0x4032, 0xC245, 0x3E3D, 0xC247,
+ 0xC248, 0xC249, 0x4352, 0xC24A, 0xC24C, 0, 0xC243, 0xC246,
+};
+const unsigned short utf8_to_euc_E69A[] = {
+ 0xC24B, 0x3647, 0, 0x5A73, 0x5A77, 0, 0, 0x324B,
+ 0x5A74, 0x5A76, 0, 0xC24D, 0xC24E, 0xC24F, 0x5A75, 0,
+ 0xC250, 0x3D6B, 0xC251, 0, 0, 0, 0x4348, 0x3045,
+ 0x5A78, 0xC252, 0xC253, 0xC254, 0xC255, 0x5A79, 0, 0xC256,
+ 0xC257, 0, 0x442A, 0, 0xC258, 0, 0x4E71, 0,
+ 0, 0, 0, 0x3B43, 0, 0xC259, 0x4A6B, 0,
+ 0, 0xC25A, 0xC25B, 0, 0x4B3D, 0xC25C, 0, 0,
+ 0x5B22, 0x5A7B, 0, 0xC25D, 0x5A7E, 0, 0x5A7D, 0xC25E,
+};
+const unsigned short utf8_to_euc_E69B[] = {
+ 0xC25F, 0x5A7A, 0xC260, 0xC261, 0x5B21, 0, 0, 0x465E,
+ 0xC262, 0x5A7C, 0, 0, 0xC263, 0, 0xC264, 0xC265,
+ 0, 0, 0, 0, 0xC266, 0, 0x5B23, 0,
+ 0, 0x3D6C, 0x5B24, 0xC267, 0x4D4B, 0x4778, 0, 0xC268,
+ 0x5B25, 0, 0, 0, 0, 0, 0x5B27, 0,
+ 0xC269, 0x5B28, 0, 0xC26A, 0xC26B, 0, 0xC26C, 0,
+ 0x5B29, 0, 0x364A, 0x3148, 0x3939, 0x5B2A, 0, 0x5B2B,
+ 0x3D71, 0x4162, 0xC26D, 0xC23F, 0x5258, 0x413E, 0x413D, 0x4258,
+};
+const unsigned short utf8_to_euc_E69C[] = {
+ 0x3A47, 0, 0, 0x5072, 0, 0xC26E, 0, 0xC26F,
+ 0x376E, 0x4D2D, 0, 0x4A7E, 0, 0x497E, 0xC270, 0x5B2C,
+ 0, 0, 0, 0xC271, 0x3A73, 0x443F, 0x5B2D, 0x4F2F,
+ 0, 0xC272, 0, 0x4B3E, 0xC273, 0x442B, 0x5B2E, 0x347C,
+ 0xC274, 0, 0xC275, 0, 0, 0, 0x5B2F, 0x5B30,
+ 0x4C5A, 0, 0x4C24, 0x4B76, 0x4B5C, 0x3B25, 0x5B32, 0,
+ 0, 0x3C6B, 0, 0xC276, 0x4B51, 0, 0x5B34, 0x5B37,
+ 0x5B36, 0, 0x3479, 0, 0, 0x3560, 0xC277, 0x5B33,
+};
+const unsigned short utf8_to_euc_E69D[] = {
+ 0, 0x5B35, 0, 0, 0, 0xC278, 0x5B38, 0xC279,
+ 0xC27A, 0x3F79, 0, 0, 0xC27B, 0, 0x4D7B, 0x3049,
+ 0x3A60, 0x423C, 0, 0x3C5D, 0xC27C, 0xC27D, 0x3E73, 0,
+ 0, 0x5B3B, 0, 0, 0x454E, 0xC27E, 0x5B39, 0x422B,
+ 0x5B3A, 0x3E72, 0x4C5D, 0x5B3C, 0x5B3D, 0x4D68, 0xC321, 0,
+ 0, 0, 0x5B42, 0, 0xC322, 0x393A, 0xC323, 0x4755,
+ 0x5B3F, 0x456C, 0x5A5E, 0x5A62, 0xC324, 0x354F, 0xC325, 0x4747,
+ 0, 0, 0, 0xC326, 0x5B41, 0, 0x3E3E, 0x4844,
+};
+const unsigned short utf8_to_euc_E69E[] = {
+ 0, 0xC327, 0, 0, 0xC328, 0x5B47, 0, 0x487A,
+ 0, 0x5B3E, 0, 0x5B44, 0x5B43, 0, 0xC329, 0xC32A,
+ 0x404F, 0xC32B, 0, 0xC32C, 0, 0x4B6D, 0xC32D, 0x4E53,
+ 0xC32E, 0xC32F, 0x4B67, 0xC330, 0x324C, 0x3B5E, 0, 0,
+ 0x4F48, 0x5B46, 0x3F75, 0, 0, 0, 0x5B45, 0,
+ 0, 0x5B40, 0, 0, 0, 0, 0, 0x384F,
+ 0xC331, 0xC332, 0xC333, 0x5B4C, 0x5B4A, 0xC334, 0x324D, 0x5B48,
+ 0x5B4E, 0x5B54, 0, 0xC335, 0xC336, 0xC337, 0, 0,
+};
+const unsigned short utf8_to_euc_E69F[] = {
+ 0xC339, 0x4248, 0xC33A, 0xC33B, 0x4A41, 0xC33C, 0x5B56, 0,
+ 0xC33D, 0xC33E, 0x4922, 0, 0, 0, 0x5B55, 0x4770,
+ 0x4B3F, 0x343B, 0xC33F, 0x4077, 0x3D40, 0, 0, 0xC340,
+ 0x4453, 0xC341, 0x4D2E, 0, 0xC342, 0x5B51, 0x5B50, 0,
+ 0, 0xC343, 0x5B52, 0, 0x5B4F, 0, 0xC344, 0x5B57,
+ 0, 0x5B4D, 0, 0, 0x5B4B, 0, 0x5B53, 0x5B49,
+ 0xC345, 0x436C, 0xC346, 0x4C78, 0x3C46, 0x3A74, 0xC347, 0xC348,
+ 0, 0xC338, 0, 0x3A3A, 0, 0, 0x4B6F, 0x3341,
+};
+const unsigned short utf8_to_euc_E6A0[] = {
+ 0, 0xF446, 0x444E, 0x464A, 0x3149, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x4072, 0xC34A, 0, 0x4034, 0x372A,
+ 0, 0xC34B, 0, 0, 0, 0xC34C, 0x5B59, 0xC34D,
+ 0, 0x393B, 0x337C, 0, 0, 0, 0, 0xC34F,
+ 0xC34E, 0x5B5B, 0x3374, 0x5B61, 0xC350, 0xC351, 0, 0xC352,
+ 0xC353, 0xC354, 0x5B5E, 0xC355, 0x4073, 0, 0, 0,
+ 0x334B, 0x3A2C, 0, 0xC356, 0x334A, 0x3A4F, 0, 0xC357,
+};
+const unsigned short utf8_to_euc_E6A1[] = {
+ 0x5B5C, 0x3765, 0x374B, 0x456D, 0xC358, 0xC359, 0x5B5A, 0,
+ 0x3046, 0, 0xC35A, 0, 0xC35B, 0x5B5D, 0x5B5F, 0,
+ 0x364D, 0x372C, 0xC349, 0x343C, 0x354B, 0xC35C, 0, 0xC35D,
+ 0xC35E, 0x5B62, 0, 0xC35F, 0x3A79, 0x4B71, 0, 0x3B37,
+ 0, 0, 0, 0x5B63, 0, 0, 0, 0x4930,
+ 0, 0, 0, 0xC360, 0, 0, 0xC361, 0xC362,
+ 0xC363, 0xC364, 0xC365, 0, 0x5B6F, 0xC366, 0x3233, 0x5B64,
+ 0, 0xC367, 0xC368, 0xC369, 0xC36A, 0, 0x5B75, 0x5B65,
+};
+const unsigned short utf8_to_euc_E6A2[] = {
+ 0, 0x4E42, 0xC36B, 0x5B6C, 0xC36C, 0x475F, 0xC36D, 0,
+ 0xC36E, 0, 0, 0, 0, 0x5B74, 0, 0x5B67,
+ 0, 0, 0, 0x3034, 0x5B69, 0, 0xC36F, 0x393C,
+ 0xC370, 0, 0xC371, 0x5B6B, 0xC372, 0x5B6A, 0, 0x5B66,
+ 0x5B71, 0xC373, 0x3E3F, 0xC374, 0, 0xC375, 0x546D, 0x3868,
+ 0x4D7C, 0xC376, 0xC377, 0, 0, 0x5B68, 0xC378, 0x4474,
+ 0x3323, 0x3A2D, 0xC379, 0x5B60, 0, 0x5B70, 0x3361, 0,
+ 0, 0x5B6E, 0x5B72, 0xC37A, 0x456E, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E6A3[] = {
+ 0, 0, 0, 0, 0x347E, 0xC37B, 0x5C32, 0,
+ 0xC37C, 0x4C49, 0x5B77, 0x347D, 0xC37D, 0x5B7E, 0, 0xC37E,
+ 0xC421, 0xC422, 0x4B40, 0xC423, 0x5C21, 0x5C23, 0xC424, 0x5C27,
+ 0x5B79, 0xC425, 0x432A, 0, 0xC426, 0xC427, 0, 0x456F,
+ 0x5C2B, 0x5B7C, 0, 0x5C28, 0, 0xC428, 0, 0x5C22,
+ 0xC429, 0, 0xC42A, 0xC42B, 0xC42C, 0xC42D, 0x3F39, 0x5C2C,
+ 0xC42E, 0xC42F, 0x4033, 0, 0, 0xC430, 0xC431, 0,
+ 0, 0x5C2A, 0x343D, 0xC432, 0xC433, 0xC434, 0, 0,
+};
+const unsigned short utf8_to_euc_E6A4[] = {
+ 0x4F50, 0x5B76, 0, 0, 0x5C26, 0x3058, 0xC435, 0,
+ 0x5B78, 0xC436, 0xC437, 0x4C3A, 0x5B7D, 0x3F22, 0x4447, 0x5B73,
+ 0xC438, 0xC439, 0x5C25, 0xC43A, 0, 0, 0xC43B, 0xC43C,
+ 0, 0x3F7A, 0x5C2F, 0x3371, 0x3821, 0, 0, 0,
+ 0, 0x5C31, 0x5B7A, 0x5C30, 0, 0x5C29, 0x5B7B, 0,
+ 0x5C2D, 0, 0x5C2E, 0, 0, 0, 0, 0,
+ 0x5C3F, 0xC43D, 0, 0xC43E, 0x464E, 0xC43F, 0x5C24, 0,
+ 0xC440, 0x5C3B, 0, 0xC441, 0, 0x5C3D, 0, 0x4458,
+};
+const unsigned short utf8_to_euc_E6A5[] = {
+ 0, 0, 0xC442, 0, 0, 0xC443, 0, 0,
+ 0, 0xC444, 0x4D4C, 0, 0, 0, 0xC445, 0,
+ 0, 0, 0, 0x4976, 0x5C38, 0x424A, 0, 0xC446,
+ 0, 0x5C3E, 0x413F, 0xC447, 0x5C35, 0x5C42, 0x5C41, 0,
+ 0x466F, 0x5C40, 0x466A, 0xC448, 0xC449, 0xC44A, 0xC44B, 0,
+ 0xC44C, 0xC44D, 0x5C44, 0x5C37, 0xC44E, 0x3648, 0x5C3A, 0x3D5D,
+ 0xC44F, 0xC450, 0xC451, 0x4760, 0x5C3C, 0x364B, 0, 0x5C34,
+ 0x5C36, 0x5C33, 0xC452, 0xC453, 0x4F30, 0x335A, 0x5C39, 0xC454,
+};
+const unsigned short utf8_to_euc_E6A6[] = {
+ 0xC455, 0x5C43, 0x3335, 0, 0, 0, 0, 0,
+ 0, 0, 0x3A67, 0, 0, 0xC456, 0x315D, 0,
+ 0, 0x5C54, 0xC457, 0, 0x4F31, 0x5C57, 0xC458, 0,
+ 0xC459, 0, 0, 0x3F3A, 0x5C56, 0, 0, 0,
+ 0x5C55, 0xC45A, 0, 0, 0, 0xC45B, 0xC45C, 0x5C52,
+ 0xC45D, 0, 0, 0xC45E, 0, 0xC45F, 0x5C46, 0xC460,
+ 0, 0x5C63, 0x5C45, 0, 0x5C58, 0, 0, 0xC461,
+ 0xC462, 0, 0xC463, 0x5C50, 0xC464, 0, 0x5C4B, 0x5C48,
+};
+const unsigned short utf8_to_euc_E6A7[] = {
+ 0, 0x5C49, 0, 0x5C51, 0, 0xC465, 0, 0x7422,
+ 0xC466, 0, 0x5C4E, 0x393D, 0x4448, 0x4164, 0x5C4C, 0,
+ 0x5C47, 0xC467, 0, 0x5C4A, 0, 0, 0xC468, 0xC469,
+ 0x4D4D, 0x4B6A, 0, 0, 0, 0x5C4F, 0x5C59, 0,
+ 0, 0, 0xC46A, 0, 0, 0xC46B, 0, 0x5C61,
+ 0x5C5A, 0, 0, 0x5C67, 0, 0x5C65, 0xC46C, 0xC46D,
+ 0, 0xC46E, 0x5C60, 0xC46F, 0, 0xC470, 0, 0,
+ 0, 0x5C5F, 0, 0x4450, 0, 0x4165, 0xC471, 0x5C5D,
+};
+const unsigned short utf8_to_euc_E6A8[] = {
+ 0xC472, 0xC473, 0x5C5B, 0xC474, 0, 0x5C62, 0, 0,
+ 0, 0, 0x5C68, 0x4875, 0x5C6E, 0, 0, 0xC475,
+ 0, 0xC476, 0x5C69, 0x5C6C, 0x5C66, 0xC477, 0, 0x4374,
+ 0, 0x4938, 0xC478, 0x5C5C, 0, 0xC479, 0x5C64, 0x3E40,
+ 0xC47A, 0x4C4F, 0x5C78, 0x5C6B, 0xC47B, 0, 0, 0,
+ 0xC47C, 0x3822, 0x3223, 0x335F, 0, 0, 0x5C53, 0,
+ 0xC47D, 0, 0xC47E, 0, 0xC521, 0x3E41, 0x5C70, 0xC522,
+ 0x5C77, 0x3C79, 0x3372, 0xC523, 0, 0x432E, 0xC524, 0xC525,
+};
+const unsigned short utf8_to_euc_E6A9[] = {
+ 0, 0, 0, 0, 0x5C6D, 0xC526, 0xC527, 0x5C72,
+ 0x5C76, 0xC528, 0xC529, 0x3636, 0, 0, 0xC52A, 0,
+ 0xC52B, 0xC52C, 0xC52D, 0, 0, 0xC52E, 0xC52F, 0,
+ 0x354C, 0x5C74, 0, 0xC530, 0, 0, 0, 0x3521,
+ 0, 0x464B, 0x5C73, 0, 0xC531, 0, 0x5C75, 0xC532,
+ 0, 0, 0xC533, 0xF449, 0, 0, 0, 0,
+ 0, 0xC534, 0x5C6F, 0xC535, 0, 0, 0, 0,
+ 0x5C71, 0, 0, 0, 0, 0, 0xC536, 0x3360,
+};
+const unsigned short utf8_to_euc_E6AA[] = {
+ 0x4349, 0xC537, 0, 0xC538, 0x5C7C, 0, 0xC539, 0xC53A,
+ 0, 0xC53B, 0, 0xC53C, 0, 0x5C7A, 0x3869, 0,
+ 0x5C79, 0xC53D, 0, 0, 0, 0, 0, 0x5D21,
+ 0, 0, 0, 0xC53E, 0x5B58, 0xC53F, 0xC540, 0xC541,
+ 0x5C7B, 0, 0x5C7D, 0x5C7E, 0, 0xC542, 0, 0,
+ 0, 0, 0x5D2C, 0xC543, 0x5D28, 0, 0x5B6D, 0xC544,
+ 0xC545, 0xC546, 0, 0x5D27, 0xC547, 0, 0, 0,
+ 0x5D26, 0, 0, 0x5D23, 0, 0xC548, 0xC549, 0xC54A,
+};
+const unsigned short utf8_to_euc_E6AB[] = {
+ 0, 0x5C6A, 0x5D25, 0x5D24, 0, 0, 0xC54B, 0,
+ 0xC54D, 0xC54C, 0, 0, 0xC54E, 0, 0, 0,
+ 0xC54F, 0x5D2A, 0, 0x4F26, 0xC550, 0xC551, 0xC552, 0,
+ 0, 0, 0x5D2D, 0x367B, 0xC553, 0xC554, 0x5D29, 0x5D2B,
+ 0, 0, 0xF44A, 0, 0xC555, 0, 0, 0xC556,
+ 0x4827, 0, 0x5D2E, 0, 0xC557, 0, 0, 0,
+ 0xC558, 0xC559, 0xC55A, 0, 0, 0, 0, 0,
+ 0, 0, 0x5D32, 0x5D2F, 0xC55B, 0xC55C, 0, 0,
+};
+const unsigned short utf8_to_euc_E6AC[] = {
+ 0, 0, 0xC55D, 0xC55E, 0x4D73, 0x5D30, 0xC55F, 0xC560,
+ 0, 0xC561, 0x5C5E, 0, 0, 0, 0, 0xC562,
+ 0xC563, 0xC564, 0x5D33, 0, 0, 0, 0x5D34, 0xC565,
+ 0, 0, 0, 0xC566, 0, 0x3135, 0xC567, 0x5D36,
+ 0x3767, 0x3C21, 0, 0x3655, 0xC568, 0, 0, 0x3224,
+ 0xC569, 0, 0, 0xC56A, 0xC56B, 0, 0, 0xC56C,
+ 0, 0, 0x4D5F, 0, 0, 0xC56D, 0xC56E, 0x5D38,
+ 0x5D37, 0x5D3A, 0x353D, 0xC56F, 0, 0x3656, 0x343E, 0xC570,
+};
+const unsigned short utf8_to_euc_E6AD[] = {
+ 0, 0, 0, 0x5D3D, 0, 0, 0xC571, 0x5D3C,
+ 0, 0x5D3E, 0xC572, 0, 0x324E, 0xC573, 0x4337, 0,
+ 0x5D3F, 0, 0xC574, 0x343F, 0x5D41, 0, 0xC575, 0,
+ 0xC576, 0x5D40, 0, 0x5D42, 0, 0xC577, 0, 0x5D43,
+ 0xC578, 0x5D44, 0x3B5F, 0x4035, 0x3A21, 0, 0x4970, 0xC579,
+ 0, 0x4A62, 0x4F44, 0xC57A, 0, 0, 0xC57B, 0x3B75,
+ 0xC57C, 0, 0, 0x3A50, 0x4E72, 0xC57D, 0, 0,
+ 0x5D45, 0x5D46, 0, 0x3B60, 0, 0xC57E, 0xC621, 0x5D47,
+};
+const unsigned short utf8_to_euc_E6AE[] = {
+ 0x5D48, 0, 0xC622, 0x5D4A, 0x5D49, 0xC623, 0x4B58, 0,
+ 0, 0x3D5E, 0x3C6C, 0x3B44, 0, 0x5D4B, 0, 0,
+ 0, 0, 0, 0, 0, 0x5D4D, 0x3F23, 0xC624,
+ 0x5D4C, 0, 0, 0xC625, 0, 0, 0x5D4E, 0xC626,
+ 0xC627, 0, 0xC628, 0xC629, 0x5D4F, 0, 0, 0,
+ 0xC62A, 0xC62B, 0x5D50, 0x5D51, 0xC62C, 0xC62D, 0xC62E, 0x5D52,
+ 0xC62F, 0x5D54, 0x5D53, 0x5D55, 0x3225, 0x434A, 0, 0x5D56,
+ 0xC630, 0xC631, 0x3B26, 0x334C, 0x5D57, 0xC632, 0xC633, 0x4542,
+};
+const unsigned short utf8_to_euc_E6AF[] = {
+ 0x544C, 0, 0, 0xC634, 0xC635, 0x3523, 0x5D58, 0,
+ 0, 0xC636, 0, 0x5D59, 0xC637, 0x4A6C, 0x4B68, 0,
+ 0, 0, 0x4647, 0x5D5A, 0x4866, 0, 0xC638, 0,
+ 0x487B, 0, 0xC639, 0x4C53, 0, 0, 0, 0x5D5B,
+ 0, 0xC63A, 0, 0xC63B, 0, 0, 0xC63C, 0xC63D,
+ 0, 0, 0, 0x5D5D, 0x5D5C, 0, 0xC63E, 0x5D5F,
+ 0, 0xC63F, 0, 0x5D5E, 0, 0, 0, 0xC640,
+ 0, 0xC641, 0, 0, 0, 0, 0, 0xC642,
+};
+const unsigned short utf8_to_euc_E6B0[] = {
+ 0, 0, 0xC643, 0, 0xC644, 0xC645, 0, 0,
+ 0x5D61, 0xC646, 0, 0, 0, 0xC647, 0xC648, 0x3B61,
+ 0xC649, 0x4C31, 0xC64A, 0x5D62, 0x5D63, 0, 0, 0x3524,
+ 0, 0xC64B, 0, 0x5D64, 0, 0, 0, 0xC64C,
+ 0, 0, 0, 0x5D66, 0x5D65, 0, 0xC64D, 0xC64E,
+ 0xC64F, 0, 0, 0, 0xC650, 0, 0xC651, 0,
+ 0, 0, 0, 0xC652, 0x3F65, 0xC653, 0xC654, 0x4939,
+ 0x314A, 0, 0xC655, 0xC656, 0, 0, 0x4845, 0xC657,
+};
+const unsigned short utf8_to_euc_E6B1[] = {
+ 0x4475, 0x3D41, 0x3561, 0, 0, 0, 0, 0,
+ 0, 0, 0xC658, 0xC659, 0, 0xC65A, 0x4846, 0xC65B,
+ 0x3C2E, 0, 0xC65C, 0, 0xC65D, 0x5D68, 0, 0x3440,
+ 0, 0xC65E, 0x3178, 0xC65F, 0xC660, 0x4672, 0x5D67, 0x393E,
+ 0x4353, 0, 0x5D69, 0, 0, 0, 0, 0xC736,
+ 0x5D71, 0, 0x5D6A, 0xC661, 0, 0xC662, 0, 0xC663,
+ 0x4241, 0, 0x3562, 0x5D72, 0xC664, 0, 0xC665, 0,
+ 0xC666, 0xC667, 0x3768, 0xC668, 0, 0x3525, 0x5D70, 0,
+};
+const unsigned short utf8_to_euc_E6B2[] = {
+ 0, 0x5D6E, 0x5D6B, 0x4D60, 0, 0xC669, 0xC66A, 0xC66B,
+ 0x4440, 0xC66C, 0, 0, 0x4659, 0x5D6C, 0, 0,
+ 0x5D74, 0, 0x5D73, 0x3723, 0xC66D, 0xC66E, 0x322D, 0xC66F,
+ 0xC670, 0x3A3B, 0x5D6D, 0x5D6F, 0xC671, 0, 0, 0xC672,
+ 0, 0x4B57, 0x4274, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x4B77, 0, 0, 0x5D7C, 0,
+ 0xC673, 0x5D7D, 0xC674, 0x324F, 0xC675, 0, 0, 0,
+ 0x4A28, 0x4C7D, 0x5E21, 0x3C23, 0x3E42, 0x5D78, 0x5D7E, 0x3168,
+};
+const unsigned short utf8_to_euc_E6B3[] = {
+ 0, 0x3637, 0xC676, 0, 0x5D75, 0x5D7A, 0xC677, 0,
+ 0, 0x4074, 0x4771, 0, 0x4867, 0xC678, 0, 0xC679,
+ 0xC67A, 0xC67B, 0xC67C, 0x5D77, 0xC67D, 0x4B21, 0xC67E, 0x5D79,
+ 0, 0x5E24, 0xC721, 0x5E22, 0xC722, 0x5D7B, 0, 0,
+ 0xC723, 0x4B22, 0x4748, 0x3563, 0, 0x4525, 0, 0xC724,
+ 0x436D, 0xC725, 0x5E25, 0xC726, 0xC727, 0, 0xC728, 0x5E23,
+ 0x4259, 0x5D76, 0xC729, 0x314B, 0xC72A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E6B4[] = {
+ 0, 0, 0, 0, 0xC72B, 0, 0, 0xC72C,
+ 0, 0, 0xC72D, 0x4D4E, 0x5E30, 0, 0xC72E, 0xC72F,
+ 0, 0xC730, 0x5E2F, 0xC731, 0, 0, 0, 0x4076,
+ 0, 0x5E2C, 0xC732, 0x4D6C, 0, 0, 0x4636, 0x5E26,
+ 0, 0, 0, 0, 0, 0x4445, 0xC733, 0xC734,
+ 0xC735, 0x314C, 0x393F, 0x5E29, 0, 0, 0xC737, 0xC738,
+ 0, 0xC739, 0x3D27, 0x5E2E, 0, 0x5E2D, 0x5E28, 0,
+ 0x5E2B, 0xC73A, 0, 0x3368, 0xC73B, 0x5E2A, 0x4749, 0xC73C,
+};
+const unsigned short utf8_to_euc_E6B5[] = {
+ 0, 0x4E2E, 0, 0, 0x3E74, 0x4075, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xC73D,
+ 0, 0x5E36, 0x5E34, 0, 0x494D, 0, 0xC73E, 0xC73F,
+ 0, 0xC740, 0, 0x5E31, 0x5E33, 0xC741, 0x313A, 0xC742,
+ 0, 0x3940, 0x4F32, 0, 0x333D, 0, 0x4962, 0xC743,
+ 0xC744, 0, 0, 0, 0x4D61, 0, 0, 0x3324,
+ 0x3F3B, 0x5E35, 0, 0, 0xC745, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E6B6[] = {
+ 0, 0, 0xC746, 0, 0, 0x5E3A, 0, 0xC747,
+ 0x3E43, 0, 0, 0, 0x4D30, 0, 0x5E37, 0,
+ 0, 0xC748, 0xC749, 0x5E32, 0xC74A, 0x5E38, 0xC74B, 0xC74C,
+ 0xC74D, 0x4E5E, 0, 0x4573, 0x4642, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xC74E, 0, 0xC74F, 0, 0, 0x3336,
+ 0, 0, 0x3155, 0, 0xC750, 0x5E3E, 0, 0xC751,
+ 0x5E41, 0xC752, 0, 0, 0x4E43, 0xC753, 0, 0xC754,
+};
+const unsigned short utf8_to_euc_E6B7[] = {
+ 0x4D64, 0, 0, 0, 0xC755, 0x5E48, 0x5E42, 0x5E3F,
+ 0xC756, 0, 0xC757, 0x4E54, 0x5E45, 0, 0xC758, 0xC759,
+ 0, 0x3D4A, 0x5E47, 0, 0, 0x5E4C, 0xC75A, 0,
+ 0x4571, 0x5E4A, 0, 0xC75B, 0, 0xC75C, 0x5E44, 0xC75D,
+ 0xC75E, 0x4338, 0xC75F, 0, 0x5E4B, 0xC760, 0x5E40, 0,
+ 0x5E46, 0xC761, 0x5E4D, 0x307C, 0x5E43, 0, 0x5E4E, 0xC762,
+ 0xC763, 0x3F3C, 0xF44C, 0x3D5F, 0xC764, 0x4A25, 0xC765, 0x3A2E,
+ 0xF44B, 0x5E3B, 0x5E49, 0x453A, 0xC766, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E6B8[] = {
+ 0xC767, 0, 0, 0, 0xC768, 0x4036, 0, 0x3369,
+ 0x3A51, 0x3E44, 0x5E3D, 0x3D42, 0, 0, 0, 0,
+ 0, 0, 0, 0x374C, 0, 0x5E3C, 0, 0,
+ 0, 0x5E52, 0x3D6D, 0x383A, 0, 0x5E61, 0xC769, 0x5E5B,
+ 0x3574, 0x454F, 0xC76A, 0x5E56, 0x5E5F, 0x302F, 0x3132, 0xC76B,
+ 0, 0x3239, 0, 0x5E58, 0x422C, 0x5E4F, 0x5E51, 0x3941,
+ 0, 0, 0xC76C, 0, 0, 0, 0xC76D, 0,
+ 0x5E62, 0xC76E, 0x5E5D, 0xC76F, 0xC770, 0, 0x5E55, 0,
+};
+const unsigned short utf8_to_euc_E6B9[] = {
+ 0, 0, 0, 0x5E5C, 0xC771, 0xC772, 0, 0,
+ 0xC773, 0xC774, 0x4C2B, 0xC775, 0, 0x5E5A, 0x5E5E, 0xC776,
+ 0, 0xC777, 0xC778, 0xC779, 0xC77A, 0, 0x3850, 0xC77B,
+ 0x3E45, 0, 0, 0x4339, 0xC77C, 0xC77D, 0xC77E, 0x5E54,
+ 0, 0, 0xC821, 0xC822, 0, 0, 0, 0x4D2F,
+ 0xC823, 0, 0, 0x5E57, 0, 0, 0x5E50, 0x4572,
+ 0, 0, 0x5E53, 0xC824, 0, 0, 0x5E59, 0,
+ 0, 0, 0, 0xC825, 0, 0xC826, 0x4F51, 0x3C3E,
+};
+const unsigned short utf8_to_euc_E6BA[] = {
+ 0x4B7E, 0, 0x5E63, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x482E, 0xC827, 0, 0x5E6F,
+ 0x383B, 0, 0, 0xC828, 0, 0, 0x3D60, 0,
+ 0x5E65, 0xC829, 0, 0, 0x4E2F, 0x3942, 0, 0x5E72,
+ 0xC82A, 0, 0x306E, 0, 0, 0x5E70, 0, 0xC82B,
+ 0, 0, 0x5E64, 0, 0, 0xC82C, 0xC82D, 0x5E6A,
+ 0, 0xC82E, 0x5E6C, 0xC82F, 0, 0, 0x4D4F, 0x5E67,
+ 0, 0, 0x452E, 0xC830, 0, 0x5E69, 0, 0xC831,
+};
+const unsigned short utf8_to_euc_E6BB[] = {
+ 0xC832, 0xC833, 0x5E71, 0xC834, 0x5E6B, 0x4C47, 0, 0xC835,
+ 0xC836, 0x5E66, 0xC837, 0x3C22, 0x5E7E, 0xC838, 0xC839, 0xC83A,
+ 0, 0x336A, 0, 0x5E68, 0x5E6D, 0x5E6E, 0, 0,
+ 0, 0, 0, 0, 0, 0x426C, 0x425A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xC83B, 0x5E76, 0xC83C, 0xC83D, 0x5E7C,
+ 0, 0, 0x5E7A, 0, 0x4529, 0, 0, 0x5F23,
+ 0x5E77, 0xC83E, 0, 0xC83F, 0, 0xC840, 0x5E78, 0x5E60,
+};
+const unsigned short utf8_to_euc_E6BC[] = {
+ 0, 0x3579, 0x493A, 0, 0xC841, 0, 0x3C3F, 0,
+ 0xC842, 0x3977, 0xC843, 0, 0xC844, 0xC845, 0, 0x4F33,
+ 0, 0x5E74, 0, 0x5F22, 0x3169, 0x4166, 0xC846, 0,
+ 0xC847, 0, 0xC848, 0xC849, 0, 0, 0, 0,
+ 0x4779, 0, 0x3441, 0x4E7A, 0, 0, 0xC84A, 0,
+ 0, 0xC84B, 0xC84C, 0x4C21, 0x4452, 0xC853, 0, 0xC84D,
+ 0xC84E, 0x5E7B, 0x5E7D, 0xC84F, 0, 0, 0xC850, 0,
+ 0x4132, 0, 0, 0xC851, 0xC852, 0, 0x5F21, 0x5E79,
+};
+const unsigned short utf8_to_euc_E6BD[] = {
+ 0, 0x5E73, 0, 0, 0, 0x3443, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xC854,
+ 0, 0xC855, 0xC856, 0xC857, 0x3769, 0, 0, 0xC858,
+ 0x5F2F, 0xC859, 0xC85A, 0x5F2A, 0x4078, 0xC85B, 0xC85C, 0x3363,
+ 0, 0xC85D, 0xC85E, 0, 0x3D61, 0, 0x5F33, 0,
+ 0xC85F, 0, 0, 0, 0xC860, 0x5F2C, 0x442C, 0x5F29,
+ 0x4459, 0, 0, 0, 0x5F4C, 0, 0, 0,
+ 0x5F26, 0, 0x5F25, 0, 0x5F2E, 0xC861, 0xC862, 0,
+};
+const unsigned short utf8_to_euc_E6BE[] = {
+ 0x5F28, 0x5F27, 0x5F2D, 0xC863, 0x4021, 0, 0x5F24, 0xC864,
+ 0xC865, 0, 0, 0xC866, 0xC867, 0xC868, 0x5F30, 0,
+ 0xC869, 0x5F31, 0xC86A, 0xC86B, 0xC86C, 0, 0xC86D, 0x3442,
+ 0, 0, 0xC86E, 0, 0, 0, 0, 0xC86F,
+ 0xC870, 0x5F36, 0, 0x5F35, 0x5F37, 0xC871, 0xC872, 0xC873,
+ 0xC874, 0, 0x5F3A, 0, 0, 0, 0xC875, 0xC876,
+ 0xC877, 0x4543, 0, 0x5F34, 0, 0xC878, 0xC879, 0,
+ 0, 0x5F38, 0, 0, 0xC87A, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E6BF[] = {
+ 0x3763, 0x4279, 0x5F32, 0x473B, 0, 0xC87B, 0x5F39, 0xC87C,
+ 0xC87D, 0, 0xC87E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x5F3E, 0x5F3C, 0, 0,
+ 0x5F3F, 0, 0xC921, 0x5F42, 0, 0, 0xC922, 0x5F3B,
+ 0x396A, 0x4728, 0, 0, 0x5E39, 0, 0, 0,
+ 0xC923, 0xC924, 0, 0x4D74, 0x5F3D, 0, 0x5F41, 0x4275,
+ 0xC925, 0x5F40, 0, 0x5F2B, 0, 0xC926, 0x6F69, 0,
+ 0, 0xC927, 0x5F45, 0, 0xC928, 0xC929, 0x5F49, 0,
+};
+const unsigned short utf8_to_euc_E780[] = {
+ 0xC92A, 0x5F47, 0, 0, 0, 0xC92B, 0xC92C, 0xC92D,
+ 0, 0x5F43, 0, 0x5F44, 0, 0xC92E, 0, 0x5F48,
+ 0, 0x5F46, 0, 0, 0, 0x494E, 0, 0xC92F,
+ 0x5F4E, 0, 0x5F4B, 0x5F4A, 0, 0x5F4D, 0x4654, 0x5F4F,
+ 0xC930, 0, 0, 0xC931, 0, 0, 0x4375, 0x426D,
+ 0xF44D, 0, 0, 0, 0x4025, 0, 0, 0xC932,
+ 0x5F50, 0, 0x5F52, 0, 0xC933, 0, 0, 0xC934,
+ 0, 0xC935, 0, 0, 0xC936, 0, 0x5F51, 0,
+};
+const unsigned short utf8_to_euc_E781[] = {
+ 0, 0, 0, 0xC937, 0xC938, 0, 0, 0,
+ 0xC939, 0xC93A, 0xC93B, 0xC93C, 0x5E75, 0, 0xC941, 0,
+ 0, 0x5F53, 0, 0, 0xC93D, 0xC93E, 0, 0,
+ 0x4667, 0, 0, 0, 0, 0xC93F, 0xC940, 0,
+ 0, 0, 0, 0x5F54, 0xC942, 0xC943, 0, 0,
+ 0, 0, 0, 0x3250, 0xC944, 0, 0xC945, 0x4574,
+ 0x3325, 0, 0, 0, 0, 0xC946, 0xC947, 0,
+ 0x3564, 0, 0, 0, 0x3C5E, 0x3A52, 0xC948, 0,
+};
+const unsigned short utf8_to_euc_E782[] = {
+ 0, 0xC949, 0, 0, 0, 0xC94A, 0xC94B, 0,
+ 0, 0x4F27, 0x3F66, 0, 0, 0, 0x316A, 0,
+ 0, 0, 0x5F56, 0, 0xC94C, 0xC94D, 0xC94E, 0xC94F,
+ 0xC950, 0x5F55, 0, 0xC951, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xC952, 0, 0, 0,
+ 0, 0, 0, 0xC953, 0x5F59, 0x433A, 0x5F5C, 0x5F57,
+ 0xC954, 0xC955, 0, 0x5F5B, 0xC956, 0, 0, 0xC957,
+ 0x5F5A, 0x4540, 0x3059, 0xF42E, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E783[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x4E75, 0, 0xC958, 0x5F5E, 0, 0, 0, 0x3128,
+ 0, 0xC959, 0, 0xC95A, 0xC95B, 0xC95C, 0xC95D, 0,
+ 0xC95E, 0x5F60, 0, 0, 0xC95F, 0x5F5F, 0, 0x5F5D,
+ 0, 0, 0, 0, 0xC960, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x5F58, 0, 0, 0, 0, 0, 0,
+ 0, 0x4B23, 0xC961, 0, 0, 0x5F62, 0, 0,
+};
+const unsigned short utf8_to_euc_E784[] = {
+ 0, 0, 0, 0xC962, 0xC963, 0xC964, 0xC965, 0xC966,
+ 0, 0x5F61, 0, 0xC967, 0xC968, 0, 0, 0xC969,
+ 0, 0, 0, 0, 0x316B, 0, 0, 0,
+ 0, 0x5F64, 0x4A32, 0, 0x5F63, 0, 0xC96A, 0,
+ 0xC96B, 0x4C35, 0, 0, 0, 0, 0x3E47, 0,
+ 0, 0, 0, 0xC96C, 0, 0xC96D, 0, 0xC96E,
+ 0xC96F, 0xC970, 0, 0, 0, 0, 0x4133, 0,
+ 0xC971, 0, 0, 0, 0x3E46, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E785[] = {
+ 0, 0xC972, 0, 0, 0, 0xC973, 0xC974, 0xC975,
+ 0, 0x4E7B, 0xC976, 0xC977, 0x5F6A, 0, 0x4079, 0,
+ 0xC978, 0, 0xC979, 0, 0, 0x5F66, 0x5F6B, 0xC97A,
+ 0, 0x316C, 0xC97B, 0, 0xC97C, 0, 0xC97D, 0,
+ 0xC97E, 0, 0x5F69, 0, 0x4761, 0x5F65, 0x5F68, 0x3E48,
+ 0xCA21, 0x4851, 0, 0, 0x5F6C, 0, 0x3C51, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xCA22, 0, 0, 0, 0x407A, 0, 0,
+};
+const unsigned short utf8_to_euc_E786[] = {
+ 0xCA23, 0, 0, 0, 0x5F6F, 0xCA24, 0, 0xCA25,
+ 0x5F67, 0, 0x3727, 0, 0xCA26, 0, 0, 0x5F6D,
+ 0, 0, 0xCA27, 0, 0x4D50, 0x5F70, 0, 0,
+ 0, 0x7426, 0xCA28, 0xCA29, 0, 0, 0, 0x3D4F,
+ 0xCA2A, 0, 0xCA2B, 0, 0, 0, 0, 0,
+ 0x5F71, 0, 0, 0, 0x5F72, 0, 0, 0xCA2C,
+ 0xCA2D, 0x472E, 0xCA2E, 0xCA2F, 0, 0, 0, 0,
+ 0, 0x5F74, 0xCA30, 0, 0, 0, 0x5F75, 0xCA31,
+};
+const unsigned short utf8_to_euc_E787[] = {
+ 0xCA32, 0xCA33, 0, 0x4733, 0xCA34, 0, 0, 0,
+ 0x4575, 0x5F77, 0, 0xCA35, 0xCA36, 0, 0x5F79, 0,
+ 0x4E55, 0, 0x5F76, 0xCA37, 0x5F78, 0x316D, 0xCA38, 0x5F73,
+ 0, 0xCA39, 0xCA3A, 0, 0xCA3B, 0, 0, 0x535B,
+ 0x5F7A, 0, 0, 0, 0, 0x4167, 0x3B38, 0x5F7C,
+ 0, 0, 0, 0, 0x5F7B, 0x3F24, 0x5259, 0,
+ 0, 0, 0, 0, 0, 0x5F7D, 0, 0,
+ 0xCA3C, 0x6021, 0, 0x5F6E, 0x5F7E, 0, 0xCA3D, 0x6022,
+};
+const unsigned short utf8_to_euc_E788[] = {
+ 0xCA3E, 0, 0, 0, 0, 0, 0x477A, 0xCA3F,
+ 0xCA40, 0xCA41, 0, 0, 0, 0x6023, 0, 0,
+ 0x6024, 0, 0, 0xCA42, 0, 0, 0, 0xCA43,
+ 0, 0, 0xCA44, 0x6025, 0, 0xCA45, 0, 0xCA46,
+ 0, 0, 0, 0, 0xCA47, 0, 0, 0,
+ 0x6026, 0, 0x445E, 0xCA48, 0x6028, 0x6027, 0, 0xCA49,
+ 0x6029, 0, 0x602A, 0, 0xCA4A, 0x3C5F, 0x4963, 0,
+ 0xCA4B, 0xCA4C, 0x4C6C, 0x602B, 0x602C, 0x4156, 0x3C24, 0x602D,
+};
+const unsigned short utf8_to_euc_E789[] = {
+ 0x602E, 0xCA4D, 0xCA4E, 0xCA4F, 0, 0xCA50, 0x602F, 0x4A52,
+ 0x4847, 0, 0, 0x6030, 0x4757, 0, 0xCA51, 0xCA52,
+ 0xCA53, 0, 0x442D, 0xCA54, 0, 0xCA55, 0xCA56, 0,
+ 0x6031, 0x3267, 0xCA57, 0x356D, 0xCA58, 0x4C46, 0xCA59, 0x4C36,
+ 0xCA5A, 0x3234, 0x4F34, 0xCA5B, 0, 0, 0, 0x4B52,
+ 0xCA5C, 0x4A2A, 0, 0xCA5D, 0, 0, 0xCA5E, 0xCA5F,
+ 0, 0xCA60, 0x4037, 0, 0x6032, 0, 0, 0xCA61,
+ 0xCA62, 0x4643, 0, 0xCA63, 0xCA64, 0x3823, 0x6033, 0xCA65,
+};
+const unsigned short utf8_to_euc_E78A[] = {
+ 0x3A54, 0x6035, 0x6034, 0, 0xCA66, 0, 0, 0x6036,
+ 0, 0xCA67, 0, 0, 0, 0xCA68, 0xCA69, 0,
+ 0, 0, 0x6037, 0xCA6A, 0, 0, 0x6038, 0,
+ 0, 0, 0, 0xCA6B, 0, 0, 0, 0,
+ 0x353E, 0, 0x6039, 0, 0, 0, 0, 0x603A,
+ 0xCA6C, 0, 0, 0, 0x3824, 0xCA6D, 0xCA6E, 0x4848,
+ 0, 0xCA6F, 0x603C, 0, 0xCA70, 0, 0x3E75, 0,
+ 0, 0x603B, 0, 0, 0, 0, 0xCA71, 0,
+};
+const unsigned short utf8_to_euc_E78B[] = {
+ 0, 0xCA72, 0x3638, 0x603D, 0x603F, 0, 0x603E, 0xCA73,
+ 0, 0xCA74, 0, 0, 0xCA75, 0, 0x6040, 0,
+ 0x3851, 0, 0x6041, 0, 0, 0xCA76, 0xCA77, 0x3669,
+ 0xCA78, 0x4140, 0, 0x397D, 0, 0, 0, 0xCA79,
+ 0x6043, 0x6044, 0x6042, 0, 0, 0xCA7A, 0, 0,
+ 0, 0x3C6D, 0, 0, 0x4648, 0x3639, 0, 0,
+ 0, 0, 0, 0xCA7B, 0xCA7C, 0, 0, 0x6046,
+ 0x432C, 0x6045, 0xCA7D, 0xCA7E, 0x4F35, 0x4762, 0xCB21, 0,
+};
+const unsigned short utf8_to_euc_E78C[] = {
+ 0, 0, 0xCB22, 0, 0xCB23, 0xCB24, 0, 0xCB25,
+ 0, 0, 0x6049, 0xCB26, 0, 0xCB27, 0, 0,
+ 0, 0, 0xCB28, 0xCB29, 0, 0, 0x604B, 0x6048,
+ 0xCB2A, 0xCB2B, 0, 0x4C54, 0x604A, 0x604C, 0xCB2C, 0x4E44,
+ 0, 0, 0xCB2D, 0, 0xCB2E, 0x6050, 0, 0xCB2F,
+ 0xCB30, 0x604F, 0x4376, 0x472D, 0xCB31, 0, 0x3825, 0x604E,
+ 0, 0xCB32, 0xCB33, 0, 0x604D, 0xCB34, 0x4D31, 0x4D32,
+ 0, 0, 0xCB35, 0xCB36, 0, 0xCB37, 0x6051, 0x316E,
+};
+const unsigned short utf8_to_euc_E78D[] = {
+ 0, 0, 0, 0xCB38, 0x3976, 0x3B62, 0, 0,
+ 0, 0, 0, 0, 0, 0xCB39, 0x6052, 0x6053,
+ 0xCB3A, 0, 0xCB3B, 0, 0, 0, 0xCB3C, 0x6055,
+ 0xCB3D, 0, 0, 0, 0, 0xCB3E, 0xCB3F, 0xCB40,
+ 0xCB41, 0, 0, 0x3D43, 0, 0, 0xCB42, 0xCB43,
+ 0x6057, 0xCB44, 0x6056, 0xCB45, 0xCB46, 0, 0xCB47, 0xCB48,
+ 0x6058, 0xCB49, 0x334D, 0, 0, 0x605A, 0, 0xCB4A,
+ 0x6059, 0xCB4B, 0x605C, 0x605B, 0xCB4C, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E78E[] = {
+ 0xCB4D, 0xCB4E, 0, 0xCB4F, 0x383C, 0xCB50, 0xCB51, 0x4E28,
+ 0, 0x364C, 0, 0x3226, 0, 0, 0xCB52, 0,
+ 0xCB53, 0, 0, 0xCB54, 0, 0xCB55, 0x366A, 0xCB56,
+ 0xCB57, 0, 0, 0, 0xCB58, 0, 0xCB59, 0xCB5A,
+ 0xCB5B, 0, 0xCB5C, 0, 0, 0xCB5D, 0xCB5E, 0,
+ 0, 0x3461, 0xCB5F, 0xCB60, 0, 0xCB61, 0, 0,
+ 0, 0, 0x4E68, 0x605E, 0, 0xCB62, 0, 0xCB63,
+ 0, 0xCB64, 0, 0x6060, 0xCB65, 0xCB66, 0, 0xCB67,
+};
+const unsigned short utf8_to_euc_E78F[] = {
+ 0x6061, 0, 0x3251, 0, 0, 0xCB68, 0xCB69, 0,
+ 0x605D, 0xCB6A, 0x3B39, 0xCB6B, 0xCB6C, 0x4441, 0x605F, 0xCB6D,
+ 0, 0, 0xCB6E, 0xCB6F, 0, 0, 0xCB70, 0,
+ 0, 0xCB71, 0, 0, 0, 0xCB72, 0x6064, 0,
+ 0x3C6E, 0xCB73, 0, 0xCB74, 0, 0x6062, 0xCB75, 0xCB76,
+ 0, 0xCB77, 0x373E, 0, 0, 0x4849, 0x6063, 0,
+ 0, 0x607E, 0, 0, 0xCB78, 0xCB79, 0, 0xCB7A,
+ 0x6069, 0xCB7B, 0xCB7C, 0xCB7D, 0, 0xCB7E, 0x383D, 0xCC21,
+};
+const unsigned short utf8_to_euc_E790[] = {
+ 0xCC22, 0xCC23, 0, 0x3565, 0xCC24, 0x6066, 0x4D7D, 0xCC25,
+ 0, 0x4E30, 0xCC26, 0, 0, 0, 0, 0,
+ 0, 0xCC27, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xCC28, 0xCC29, 0, 0, 0, 0,
+ 0, 0, 0x4276, 0, 0xCC2A, 0x6068, 0xCC2B, 0,
+ 0xCC2C, 0xCC2D, 0xCC2E, 0xCC2F, 0xCC30, 0xCC31, 0xCC32, 0xCC33,
+ 0xCC34, 0xCC35, 0x606A, 0x4E56, 0x3657, 0x487C, 0x474A, 0,
+ 0, 0xCC36, 0x606B, 0, 0, 0, 0, 0x606D,
+};
+const unsigned short utf8_to_euc_E791[] = {
+ 0xCC37, 0x6070, 0, 0xCC38, 0xCC39, 0, 0xCC3A, 0xCC3B,
+ 0, 0, 0, 0xCC3C, 0, 0xCC3D, 0, 0,
+ 0, 0xCC3E, 0xCC3F, 0, 0, 0x606C, 0, 0xCC40,
+ 0, 0x606F, 0x386A, 0x314D, 0x6071, 0xCC41, 0x3F70, 0x606E,
+ 0x4E5C, 0, 0xCC42, 0x6074, 0x7424, 0, 0xCC43, 0xCC44,
+ 0xCC45, 0x6072, 0x6075, 0xCC46, 0, 0xCC47, 0xCC48, 0x6067,
+ 0x6073, 0xCC49, 0xCC4A, 0x3A3C, 0, 0, 0x6076, 0,
+ 0, 0, 0, 0, 0, 0, 0x6077, 0,
+};
+const unsigned short utf8_to_euc_E792[] = {
+ 0xCC4B, 0xCC4C, 0, 0x4D7E, 0, 0xCC4D, 0xCC4E, 0xCC4F,
+ 0, 0xCC50, 0, 0x6078, 0, 0, 0, 0xCC51,
+ 0xCC52, 0xCC53, 0xCC54, 0, 0, 0, 0, 0,
+ 0xCC55, 0xCC56, 0xCC57, 0, 0xCC58, 0, 0x6079, 0xCC59,
+ 0xCC5A, 0xCC5B, 0x6065, 0xCC5C, 0, 0, 0xCC5D, 0x607A,
+ 0xCC5E, 0xCC5F, 0xCC60, 0xCC61, 0, 0, 0xCC62, 0xCC63,
+ 0x3444, 0xCC64, 0xCC65, 0, 0, 0xCC66, 0, 0,
+ 0, 0xCC67, 0, 0xCC68, 0, 0x3C25, 0, 0xCC69,
+};
+const unsigned short utf8_to_euc_E793[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xCC6A, 0xCC6B, 0x607B, 0, 0xCC6C, 0, 0, 0x607C,
+ 0xCC6D, 0, 0, 0xCC6E, 0x607D, 0, 0, 0,
+ 0xCC6F, 0, 0xCC70, 0xCC71, 0x313B, 0, 0xCC72, 0xCC73,
+ 0x6121, 0, 0x493B, 0x6122, 0xCC74, 0, 0x3424, 0x6123,
+ 0xCC75, 0x6124, 0xCC76, 0xCC77, 0, 0, 0x6125, 0xCC78,
+ 0x6127, 0x6128, 0x6126, 0, 0xCC79, 0, 0x4953, 0x612A,
+ 0x6129, 0, 0xCC7A, 0xCC7B, 0xCC7C, 0, 0, 0xCC7D,
+};
+const unsigned short utf8_to_euc_E794[] = {
+ 0, 0xF450, 0, 0x612C, 0x612B, 0x612D, 0xCC7E, 0,
+ 0, 0, 0, 0, 0x612E, 0x6130, 0x612F, 0,
+ 0, 0x3979, 0xCD21, 0x6132, 0, 0x6131, 0xCD22, 0xCD23,
+ 0x3445, 0, 0x3F53, 0, 0x453C, 0, 0x6133, 0x4038,
+ 0xCD24, 0xCD25, 0, 0x3B3A, 0xCD26, 0x3179, 0x6134, 0xCD27,
+ 0x4D51, 0xCD28, 0xCD29, 0x4A63, 0x6135, 0, 0, 0xCD2A,
+ 0x4544, 0x4D33, 0x3943, 0x3F3D, 0, 0, 0xCD2B, 0x434B,
+ 0x5234, 0xCD2C, 0x442E, 0x3268, 0x6136, 0xCD2D, 0xCD2E, 0xCD2F,
+};
+const unsigned short utf8_to_euc_E795[] = {
+ 0xCD30, 0, 0, 0xCD31, 0x6137, 0, 0x613C, 0xCD32,
+ 0xCD33, 0x613A, 0x6139, 0x5A42, 0x3326, 0x6138, 0xCD34, 0x305A,
+ 0xCD35, 0x482A, 0xCD36, 0, 0x484A, 0, 0, 0xCD37,
+ 0, 0x4E31, 0x613D, 0x613B, 0x435C, 0x4026, 0xCD38, 0xCD39,
+ 0x482B, 0xCD3A, 0x492D, 0, 0x613F, 0x4E2C, 0x374D, 0x6140,
+ 0, 0x613E, 0x4856, 0x6141, 0, 0x6142, 0, 0xCD3B,
+ 0x305B, 0xCD3C, 0, 0x3E76, 0x6147, 0, 0x6144, 0x466D,
+ 0x6143, 0xCD3D, 0xCD3E, 0xCD3F, 0xCD40, 0xCD41, 0xCD42, 0x3526,
+};
+const unsigned short utf8_to_euc_E796[] = {
+ 0, 0xCD43, 0x614A, 0, 0, 0xCD44, 0x6145, 0x6146,
+ 0, 0x6149, 0x6148, 0x4925, 0, 0, 0x4142, 0x4141,
+ 0xCD45, 0x353F, 0xCD46, 0xCD47, 0x614B, 0xCD48, 0, 0,
+ 0, 0xCD49, 0x614C, 0, 0xCD4A, 0x614D, 0, 0,
+ 0, 0, 0xCD4B, 0x614F, 0xCD4C, 0x614E, 0, 0,
+ 0, 0, 0, 0x3156, 0, 0, 0, 0,
+ 0, 0x6157, 0x4868, 0x6151, 0xCD4D, 0x6153, 0, 0,
+ 0x6155, 0x3F3E, 0xCD4E, 0, 0x6156, 0x6154, 0x3C40, 0xCD4F,
+};
+const unsigned short utf8_to_euc_E797[] = {
+ 0xCD50, 0xCD51, 0x6150, 0x6152, 0xCD52, 0x4942, 0xCD53, 0x3E49,
+ 0, 0, 0x6159, 0, 0xCD54, 0x6158, 0xCD55, 0xCD56,
+ 0, 0, 0x615A, 0, 0x3C26, 0x3A2F, 0, 0xCD57,
+ 0x4577, 0x615B, 0, 0x444B, 0xCD58, 0, 0x615D, 0xCD59,
+ 0xCD5A, 0xCD5B, 0x4E21, 0x615C, 0xCD5C, 0, 0, 0xCD5D,
+ 0, 0x4169, 0, 0, 0xCD5E, 0, 0xCD5F, 0xCD60,
+ 0x6162, 0xCD61, 0x6164, 0x6165, 0x4354, 0, 0, 0,
+ 0, 0xCD62, 0x6163, 0, 0x6160, 0, 0x615E, 0x615F,
+};
+const unsigned short utf8_to_euc_E798[] = {
+ 0xCD63, 0x6161, 0xCD64, 0xCD65, 0xCD66, 0, 0, 0xCD67,
+ 0xCD68, 0x6168, 0xCD69, 0x6166, 0xCD6A, 0x6167, 0, 0xCD6B,
+ 0, 0, 0xCD6C, 0xCD6D, 0, 0xCD6E, 0xCD6F, 0,
+ 0, 0xCD70, 0, 0xCD71, 0xCD72, 0xCD73, 0xCD74, 0x6169,
+ 0x616B, 0x616C, 0x616D, 0xCD75, 0x616E, 0xCD76, 0xCD77, 0x616A,
+ 0, 0xCD78, 0, 0, 0, 0xCD79, 0, 0,
+ 0x6170, 0, 0xCD7A, 0xCD7B, 0x616F, 0xCD7C, 0, 0,
+ 0xCD7D, 0xCD7E, 0xCE21, 0x6171, 0xCE22, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E799[] = {
+ 0xCE24, 0xCE25, 0x4E45, 0xCE26, 0xCE27, 0xCE28, 0x6174, 0x6172,
+ 0x6173, 0xCE29, 0xCE23, 0xCE2A, 0x3462, 0, 0, 0,
+ 0, 0, 0x4C7E, 0, 0, 0xCE2B, 0x4A4A, 0,
+ 0x6176, 0xCE2C, 0, 0, 0x6175, 0, 0, 0xCE2D,
+ 0, 0x6177, 0x6178, 0, 0xCE2E, 0xCE2F, 0, 0x617C,
+ 0x6179, 0x617A, 0x617B, 0, 0x617D, 0xCE30, 0xCE31, 0xCE32,
+ 0x617E, 0xCE33, 0x6221, 0, 0xCE34, 0, 0x6222, 0,
+ 0x6223, 0, 0x482F, 0x4550, 0x6224, 0x4772, 0x4934, 0,
+};
+const unsigned short utf8_to_euc_E79A[] = {
+ 0x6225, 0xCE35, 0xF451, 0x6226, 0x452A, 0xCE36, 0x3327, 0x3944,
+ 0x6227, 0, 0, 0x6228, 0xCE37, 0xCE38, 0x6229, 0,
+ 0x3B29, 0, 0, 0x622B, 0, 0xCE39, 0x622A, 0,
+ 0, 0x622C, 0x622D, 0xCE3A, 0xCE3B, 0xCE3C, 0xF452, 0xCE3D,
+ 0xCE3E, 0, 0xCE3F, 0xCE40, 0xCE41, 0xCE42, 0xCE43, 0xCE44,
+ 0xCE45, 0, 0xCE46, 0, 0, 0xCE47, 0x4869, 0,
+ 0x622E, 0, 0, 0, 0x622F, 0, 0, 0x7369,
+ 0x6230, 0x6231, 0x6232, 0, 0, 0xCE48, 0, 0x3B2E,
+};
+const unsigned short utf8_to_euc_E79B[] = {
+ 0, 0xCE49, 0x6233, 0x4756, 0, 0xCE4A, 0x4B5F, 0,
+ 0x314E, 0xCE4B, 0x3157, 0xCE4C, 0xCE4D, 0x6234, 0xCE4E, 0,
+ 0, 0, 0x6236, 0, 0xCE4F, 0, 0x6235, 0x4570,
+ 0, 0xCE50, 0, 0x4039, 0x5D39, 0, 0x6237, 0x4C41,
+ 0xCE51, 0x6238, 0, 0x3446, 0x4857, 0x6239, 0xCE52, 0x623A,
+ 0xCE53, 0, 0x623B, 0, 0xCE54, 0, 0x4C5C, 0,
+ 0xCE55, 0xCE56, 0x4C55, 0, 0x443E, 0, 0xCE57, 0,
+ 0x416A, 0xCE58, 0, 0x623D, 0xCE59, 0, 0x3D62, 0,
+};
+const unsigned short utf8_to_euc_E79C[] = {
+ 0xCE5A, 0x3E4A, 0, 0, 0x6240, 0, 0xCE5B, 0x623F,
+ 0x623E, 0x487D, 0xCE5C, 0x3447, 0x3829, 0, 0xCE5D, 0,
+ 0, 0, 0xCE5E, 0, 0xCE5F, 0xCE60, 0, 0xCE61,
+ 0, 0xCE62, 0xCE63, 0x6246, 0xCE64, 0, 0x6243, 0x3F3F,
+ 0x4C32, 0, 0xCE65, 0, 0x6242, 0x6244, 0x6245, 0,
+ 0xCE66, 0x6241, 0, 0, 0, 0xCE67, 0xCE68, 0xCE69,
+ 0, 0, 0, 0, 0xCE6A, 0xCE6B, 0xCE6C, 0x6247,
+ 0x6248, 0xCE6D, 0x442F, 0, 0x3463, 0xCE6E, 0xCE6F, 0,
+};
+const unsigned short utf8_to_euc_E79D[] = {
+ 0x4365, 0, 0xCE70, 0, 0, 0xCE71, 0xCE72, 0x6249,
+ 0, 0, 0xCE73, 0, 0, 0xCE74, 0xCE75, 0xCE76,
+ 0, 0, 0xCE77, 0, 0, 0, 0xCE78, 0xCE79,
+ 0, 0, 0x624A, 0x624D, 0xCE7A, 0, 0xCE7B, 0xCE7C,
+ 0xCE7D, 0x3F67, 0xCE7E, 0x4644, 0xCF21, 0x624E, 0x4B53, 0xCF22,
+ 0x624B, 0, 0xCF23, 0x624C, 0xCF24, 0, 0, 0,
+ 0xCF25, 0, 0xCF26, 0xCF27, 0xCF28, 0, 0, 0,
+ 0, 0x6251, 0xCF29, 0, 0, 0xCF2A, 0x6250, 0x624F,
+};
+const unsigned short utf8_to_euc_E79E[] = {
+ 0xCF2B, 0, 0, 0, 0xCF2C, 0, 0, 0,
+ 0, 0, 0, 0x6253, 0xCF2D, 0xCF2E, 0x6252, 0,
+ 0, 0x6254, 0, 0, 0xCF2F, 0xCF30, 0xCF31, 0,
+ 0, 0, 0xCF32, 0, 0, 0, 0x6256, 0xCF33,
+ 0x6255, 0, 0xCF34, 0, 0, 0x4A4D, 0, 0xCF35,
+ 0, 0, 0xCF36, 0, 0x3D56, 0x4E46, 0xCF37, 0xCF38,
+ 0x6257, 0xCF39, 0, 0x4637, 0, 0xCF3A, 0x6258, 0,
+ 0, 0x6259, 0, 0x625D, 0x625B, 0x625C, 0xCF3B, 0x625A,
+};
+const unsigned short utf8_to_euc_E79F[] = {
+ 0, 0, 0, 0xCF3C, 0, 0, 0, 0x625E,
+ 0, 0xCF3D, 0, 0, 0, 0x625F, 0, 0,
+ 0, 0xCF3E, 0xCF3F, 0, 0, 0xCF40, 0, 0x6260,
+ 0, 0xCF41, 0x6261, 0x4C37, 0x6262, 0, 0xCF42, 0xCF43,
+ 0xCF44, 0, 0x4C70, 0x6263, 0xCF45, 0x434E, 0xCF46, 0x476A,
+ 0, 0x366B, 0xCF47, 0, 0xCF48, 0x433B, 0x6264, 0x363A,
+ 0xCF49, 0xCF4A, 0, 0x4050, 0xCF4B, 0, 0, 0,
+ 0xCF4C, 0, 0, 0xCF4D, 0x6265, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E7A0[] = {
+ 0, 0, 0x3A3D, 0, 0, 0xCF4E, 0xCF4F, 0,
+ 0, 0xCF50, 0, 0, 0x6266, 0xCF51, 0xCF52, 0,
+ 0, 0xCF53, 0x6267, 0, 0x3826, 0x3A55, 0, 0,
+ 0, 0, 0, 0, 0, 0xCF54, 0, 0,
+ 0x6269, 0xCF55, 0xCF56, 0xCF57, 0, 0x4556, 0x3A56, 0x354E,
+ 0, 0, 0, 0, 0, 0xCF58, 0xCF59, 0,
+ 0xCF5A, 0, 0x4B24, 0, 0x474B, 0xCF5B, 0, 0xCF5C,
+ 0, 0, 0x4557, 0, 0, 0, 0, 0x395C,
+};
+const unsigned short utf8_to_euc_E7A1[] = {
+ 0, 0, 0, 0xCF5D, 0xCF5E, 0x626B, 0, 0xCF5F,
+ 0xCF60, 0, 0, 0, 0xCF61, 0, 0xCF62, 0,
+ 0, 0, 0xCF63, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xCF64, 0x3E4B, 0xCF65, 0,
+ 0xCF66, 0xCF67, 0, 0xCF68, 0xCF69, 0, 0, 0,
+ 0xCF6A, 0, 0xCF6B, 0x4E32, 0x3945, 0, 0xCF6C, 0x3827,
+ 0, 0, 0x4823, 0, 0x626D, 0, 0, 0,
+ 0, 0, 0xCF6D, 0, 0x626F, 0, 0xCF6E, 0,
+};
+const unsigned short utf8_to_euc_E7A2[] = {
+ 0, 0x386B, 0, 0, 0, 0, 0x626E, 0x4476,
+ 0, 0, 0xCF6F, 0, 0x6271, 0x3337, 0x626C, 0xCF70,
+ 0, 0x486A, 0, 0x3130, 0xCF71, 0x3A6C, 0, 0x4F52,
+ 0xCF72, 0, 0x6270, 0, 0, 0xCF74, 0xCF75, 0xCF76,
+ 0, 0xCF73, 0, 0x6272, 0xCF77, 0, 0, 0x4A4B,
+ 0xCF78, 0x4059, 0x6274, 0, 0xCF79, 0xCF7A, 0, 0x6275,
+ 0xCF7B, 0xCF7C, 0xCF7D, 0xCF7E, 0, 0x6273, 0, 0,
+ 0, 0, 0x334E, 0xD021, 0x627B, 0xD022, 0x627A, 0xD023,
+};
+const unsigned short utf8_to_euc_E7A3[] = {
+ 0, 0x3C27, 0, 0, 0, 0x627C, 0x6277, 0xD024,
+ 0xD025, 0xD026, 0x627D, 0x6278, 0xD027, 0, 0xD028, 0,
+ 0x4858, 0x6276, 0xD029, 0xD02A, 0x6279, 0xD02B, 0xD02C, 0,
+ 0, 0, 0x6322, 0xD02E, 0, 0, 0, 0xD02F,
+ 0xD030, 0xD031, 0, 0, 0xD02D, 0, 0xD032, 0x6321,
+ 0x4B61, 0, 0xD033, 0, 0x627E, 0, 0, 0x306B,
+ 0, 0, 0xD034, 0xD035, 0x6324, 0, 0xD037, 0xD038,
+ 0, 0, 0xD039, 0xD03A, 0, 0x6323, 0, 0xD03B,
+};
+const unsigned short utf8_to_euc_E7A4[] = {
+ 0xD036, 0x3E4C, 0, 0, 0, 0, 0xD03C, 0x6325,
+ 0, 0, 0, 0, 0xD03D, 0, 0x4143, 0,
+ 0xD03E, 0x6327, 0x6326, 0, 0, 0, 0, 0,
+ 0, 0x6328, 0xD03F, 0, 0xD040, 0, 0xD041, 0xD042,
+ 0xD043, 0, 0, 0, 0, 0xD044, 0x6268, 0xD045,
+ 0, 0xD046, 0x626A, 0x632A, 0x6329, 0xD047, 0, 0,
+ 0xF454, 0xD048, 0, 0, 0xD049, 0xD04A, 0, 0,
+ 0, 0, 0x3C28, 0xD04B, 0x4E69, 0xD04C, 0x3C52, 0xD04D,
+};
+const unsigned short utf8_to_euc_E7A5[] = {
+ 0x632B, 0x3737, 0, 0, 0xD04E, 0xD04F, 0xD050, 0x3540,
+ 0x3527, 0x3B63, 0xD051, 0xD052, 0, 0, 0, 0xD053,
+ 0x4D34, 0xD054, 0, 0x6331, 0xD055, 0x6330, 0x4144, 0x632D,
+ 0xD056, 0, 0x632F, 0xD057, 0xD058, 0x3D4B, 0x3F40, 0x632E,
+ 0x632C, 0, 0x472A, 0, 0, 0x3E4D, 0, 0xD059,
+ 0x493C, 0xD05A, 0, 0xD05B, 0, 0x3A57, 0, 0,
+ 0, 0, 0xD05C, 0, 0, 0, 0, 0x4578,
+ 0, 0xD05D, 0x6332, 0xD05E, 0xD05F, 0, 0xD060, 0x6333,
+};
+const unsigned short utf8_to_euc_E7A6[] = {
+ 0x6349, 0x3658, 0, 0, 0x4F3D, 0x4135, 0, 0,
+ 0, 0, 0x6334, 0xD061, 0xD062, 0x3252, 0x4477, 0x4A21,
+ 0, 0xD063, 0, 0xD064, 0xD065, 0xD066, 0xD067, 0,
+ 0xD068, 0, 0, 0xD069, 0xD06A, 0x6335, 0, 0,
+ 0, 0xD06B, 0, 0, 0, 0, 0x357A, 0x6336,
+ 0xD06C, 0xD06D, 0x6338, 0xD06E, 0, 0, 0x6339, 0xD06F,
+ 0x4729, 0xD070, 0, 0x633A, 0xD071, 0, 0, 0,
+ 0xD072, 0x633B, 0x633C, 0xD073, 0, 0x3659, 0x3253, 0x4645,
+};
+const unsigned short utf8_to_euc_E7A7[] = {
+ 0x3D28, 0x3B64, 0xD074, 0, 0xD075, 0, 0, 0xD076,
+ 0xD077, 0x633D, 0xD078, 0x3D29, 0, 0, 0, 0xD079,
+ 0, 0x324A, 0x4943, 0, 0xD07A, 0x633E, 0xD07B, 0,
+ 0x486B, 0, 0xD07C, 0, 0, 0xD07D, 0xD07E, 0x4145,
+ 0xD121, 0x6341, 0xD122, 0x6342, 0x4769, 0xD123, 0x3F41, 0x633F,
+ 0, 0x4361, 0xD124, 0xD125, 0x6340, 0xD126, 0, 0,
+ 0x3E4E, 0xD127, 0, 0, 0, 0, 0, 0,
+ 0xD128, 0, 0, 0x305C, 0xD129, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E7A8[] = {
+ 0x3529, 0, 0xD12A, 0xD12B, 0, 0, 0, 0xD12C,
+ 0x6343, 0xD12D, 0xD12E, 0x4478, 0xD12F, 0x6344, 0x4047, 0,
+ 0, 0xD130, 0, 0, 0x4C2D, 0xD131, 0, 0x4923,
+ 0x6345, 0x6346, 0x4355, 0xD132, 0x4E47, 0, 0xD133, 0x6348,
+ 0x6347, 0xD134, 0, 0, 0, 0, 0, 0xD135,
+ 0, 0, 0, 0xD136, 0, 0xD137, 0x3C6F, 0xD138,
+ 0xD139, 0x634A, 0x3070, 0, 0xD13A, 0xD13B, 0, 0x634D,
+ 0xD13C, 0xD13D, 0xD13E, 0x634B, 0x3254, 0x374E, 0x634C, 0x3946,
+};
+const unsigned short utf8_to_euc_E7A9[] = {
+ 0x3972, 0, 0x4A66, 0x634E, 0xD13F, 0xD140, 0x4B54, 0xD141,
+ 0xD142, 0x6350, 0, 0, 0xD143, 0x4051, 0x314F, 0x323A,
+ 0x302C, 0, 0, 0, 0, 0xD144, 0xD145, 0x634F,
+ 0, 0xD146, 0, 0, 0xD147, 0xD148, 0, 0xD149,
+ 0xD14A, 0x6351, 0x6352, 0x3E77, 0, 0xD14B, 0, 0xD14C,
+ 0, 0x6353, 0xD14D, 0x334F, 0, 0xD14E, 0, 0,
+ 0x6355, 0, 0, 0, 0x376A, 0xD14F, 0x3566, 0,
+ 0xD150, 0x6356, 0x3675, 0, 0, 0x6357, 0xD151, 0x407C,
+};
+const unsigned short utf8_to_euc_E7AA[] = {
+ 0xD152, 0x464D, 0xD153, 0x4060, 0x3A75, 0xD154, 0xD155, 0,
+ 0x6358, 0, 0xD156, 0xD157, 0, 0, 0, 0,
+ 0xD158, 0xD159, 0x4362, 0x416B, 0xD15A, 0x635A, 0x635C, 0x6359,
+ 0x635B, 0, 0, 0, 0, 0, 0xD15B, 0x3722,
+ 0xD15C, 0, 0, 0xD15D, 0, 0, 0, 0,
+ 0, 0x635D, 0x3726, 0, 0xD15E, 0, 0x3567, 0x4D52,
+ 0x635F, 0, 0, 0xD15F, 0, 0xD160, 0x6360, 0,
+ 0, 0xD161, 0x312E, 0xD162, 0xD163, 0, 0, 0x6363,
+};
+const unsigned short utf8_to_euc_E7AB[] = {
+ 0, 0, 0, 0x3376, 0x6362, 0x6361, 0xD164, 0x6365,
+ 0x635E, 0xD165, 0x6366, 0x4E29, 0xD166, 0x6367, 0xD167, 0x6368,
+ 0, 0xD168, 0x5474, 0x636A, 0, 0x6369, 0, 0,
+ 0, 0x636B, 0x636C, 0xD169, 0x4E35, 0x636D, 0, 0x706F,
+ 0x3E4F, 0x636E, 0x636F, 0x3D57, 0, 0x4638, 0x6370, 0xF459,
+ 0xD16A, 0xD16B, 0x4328, 0xD16C, 0xD16D, 0x6371, 0, 0x433C,
+ 0x6372, 0xD16E, 0, 0, 0xD16F, 0, 0x3625, 0,
+ 0x513F, 0x435D, 0x3C33, 0xD170, 0, 0xD171, 0xD172, 0x3448,
+};
+const unsigned short utf8_to_euc_E7AC[] = {
+ 0, 0, 0x6373, 0, 0x6422, 0, 0x6376, 0xD173,
+ 0x3568, 0, 0x6375, 0x6424, 0, 0, 0, 0x6374,
+ 0, 0x3E50, 0, 0, 0xD174, 0, 0, 0,
+ 0x6378, 0x6379, 0, 0x452B, 0, 0, 0x637A, 0xD175,
+ 0x335E, 0, 0, 0xD176, 0, 0x3F5A, 0x4964, 0xD177,
+ 0x637C, 0xD178, 0xD179, 0xD17A, 0x4268, 0xD17B, 0xD17C, 0xD17D,
+ 0xD17E, 0xD221, 0, 0x6377, 0xD222, 0x637B, 0x637D, 0,
+ 0, 0x3A7B, 0, 0, 0, 0xD223, 0, 0xD224,
+};
+const unsigned short utf8_to_euc_E7AD[] = {
+ 0xD225, 0xD226, 0, 0, 0, 0x6426, 0x492E, 0xD227,
+ 0x4826, 0x4579, 0, 0x365A, 0x6425, 0x6423, 0xD228, 0x4835,
+ 0x637E, 0x435E, 0x457B, 0, 0x457A, 0xD229, 0x3A76, 0,
+ 0, 0, 0, 0, 0, 0x6438, 0, 0,
+ 0xD22A, 0, 0, 0, 0xD22B, 0x6428, 0xD22C, 0x642A,
+ 0, 0xD22D, 0xD22E, 0, 0x642D, 0xD22F, 0x642E, 0xD230,
+ 0x642B, 0x642C, 0xD231, 0xD232, 0x6429, 0x6427, 0, 0xD233,
+ 0, 0, 0x6421, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E7AE[] = {
+ 0, 0, 0, 0, 0xD234, 0, 0x4A4F, 0x3255,
+ 0, 0xD235, 0, 0x6435, 0, 0x6432, 0xD236, 0x6437,
+ 0xD237, 0xD238, 0x6436, 0, 0x4773, 0x4C27, 0xD239, 0x3B3B,
+ 0x6430, 0x6439, 0x6434, 0xD23A, 0x6433, 0x642F, 0xD23B, 0x6431,
+ 0xD23C, 0x3449, 0, 0, 0, 0xD23D, 0, 0,
+ 0, 0, 0x433D, 0, 0xD23E, 0x407D, 0, 0xD23F,
+ 0xD240, 0x4822, 0xD241, 0, 0x643E, 0xD242, 0xD243, 0,
+ 0x4824, 0, 0xD244, 0xD245, 0xD246, 0xD247, 0, 0,
+};
+const unsigned short utf8_to_euc_E7AF[] = {
+ 0x4061, 0x643B, 0xD248, 0, 0x484F, 0xD249, 0x643F, 0x4A53,
+ 0xD24A, 0x435B, 0xD24B, 0x643A, 0x643C, 0, 0, 0x643D,
+ 0, 0, 0, 0, 0xD24C, 0, 0xD24D, 0xD24E,
+ 0, 0xD24F, 0xD250, 0xD251, 0, 0x6440, 0, 0,
+ 0x3C44, 0, 0, 0, 0x4646, 0x6445, 0x6444, 0,
+ 0xD252, 0x6441, 0xD253, 0, 0, 0x4F36, 0, 0,
+ 0, 0, 0xD254, 0x644A, 0xD255, 0xD256, 0x644E, 0x644B,
+ 0xD257, 0xD258, 0xD259, 0, 0xD25A, 0, 0xD25B, 0,
+};
+const unsigned short utf8_to_euc_E7B0[] = {
+ 0x6447, 0xD25C, 0xD25D, 0xD25E, 0xD25F, 0, 0xD260, 0x6448,
+ 0, 0xD261, 0, 0xD262, 0xD263, 0x644D, 0xD264, 0xD265,
+ 0, 0x6442, 0x5255, 0x6449, 0x6443, 0, 0, 0x644C,
+ 0, 0xD266, 0, 0xD267, 0, 0, 0, 0x6452,
+ 0xD268, 0x344A, 0, 0x644F, 0, 0xD269, 0xD26A, 0x6450,
+ 0xD26B, 0, 0x6451, 0x6454, 0xD26C, 0, 0, 0,
+ 0, 0xD26D, 0, 0xD26E, 0xD26F, 0, 0xD270, 0x6453,
+ 0x4876, 0xD271, 0xD272, 0, 0, 0x6455, 0x4E7C, 0x4A6D,
+};
+const unsigned short utf8_to_euc_E7B1[] = {
+ 0x645A, 0, 0, 0x6457, 0, 0, 0xD273, 0,
+ 0, 0, 0xD274, 0, 0x6456, 0x4052, 0, 0x6459,
+ 0x645B, 0xD276, 0xD277, 0xD278, 0x6458, 0xD275, 0x645F, 0,
+ 0x645C, 0xD279, 0xD27A, 0xD27B, 0xD27C, 0xD27D, 0xD27E, 0x645D,
+ 0x6446, 0xD321, 0, 0xD322, 0x645E, 0x6460, 0, 0xD323,
+ 0, 0xD324, 0, 0, 0x6461, 0xD325, 0xD326, 0,
+ 0xD327, 0, 0xD328, 0x4A46, 0, 0x6462, 0, 0,
+ 0, 0xD329, 0, 0, 0xD32A, 0xD32B, 0x4C62, 0,
+};
+const unsigned short utf8_to_euc_E7B2[] = {
+ 0, 0x364E, 0x3729, 0x6463, 0, 0, 0xD32C, 0xD32D,
+ 0, 0x4A34, 0, 0x3F68, 0, 0x4C30, 0, 0xD32E,
+ 0x6464, 0, 0x4E33, 0, 0xD32F, 0x4774, 0, 0x4146,
+ 0x4734, 0, 0, 0x3D4D, 0, 0, 0xD330, 0x3040,
+ 0xD331, 0x6469, 0x6467, 0, 0x6465, 0x3421, 0xD332, 0x3E51,
+ 0x646A, 0, 0, 0x6468, 0, 0x6466, 0x646E, 0,
+ 0xD333, 0x646D, 0x646C, 0x646B, 0, 0, 0xD334, 0xD335,
+ 0, 0x646F, 0xD336, 0xD337, 0xD338, 0x6470, 0x403A, 0xD339,
+};
+const unsigned short utf8_to_euc_E7B3[] = {
+ 0x6471, 0, 0x6473, 0, 0xD33A, 0x6472, 0, 0xD33B,
+ 0xD33C, 0xD33D, 0x3852, 0, 0, 0xD33E, 0x4138, 0xD33F,
+ 0, 0, 0x6475, 0xD340, 0xD341, 0xD342, 0x457C, 0xD343,
+ 0x6474, 0xD344, 0xD345, 0, 0x6476, 0xD346, 0x4A35, 0x416C,
+ 0x3947, 0, 0x6477, 0, 0, 0, 0xD347, 0x4E48,
+ 0, 0xD348, 0, 0xD349, 0, 0, 0, 0x6479,
+ 0, 0, 0x647A, 0, 0x647B, 0xD34A, 0x647C, 0,
+ 0x3B65, 0, 0x647D, 0x374F, 0, 0, 0x356A, 0,
+};
+const unsigned short utf8_to_euc_E7B4[] = {
+ 0x352A, 0, 0x6521, 0xD34B, 0x4C73, 0x3948, 0x647E, 0xD34C,
+ 0xD34D, 0xD34E, 0x6524, 0x4C66, 0, 0x473C, 0, 0xD34F,
+ 0x4933, 0xD350, 0xD351, 0xD352, 0x3D63, 0x6523, 0xD353, 0x3C53,
+ 0x3949, 0x3B66, 0x3569, 0x4A36, 0x6522, 0xD354, 0xD355, 0,
+ 0x4147, 0x4B42, 0x3A77, 0xD356, 0, 0, 0xD357, 0,
+ 0, 0, 0xD358, 0x3B67, 0x445D, 0xD359, 0x6527, 0x4E5F,
+ 0x3A59, 0xD35A, 0x6528, 0x3F42, 0, 0x652A, 0, 0,
+ 0, 0x3E52, 0x3A30, 0, 0xD35B, 0xD35C, 0xD35D, 0x6529,
+};
+const unsigned short utf8_to_euc_E7B5[] = {
+ 0xD35E, 0xD35F, 0x3D2A, 0x383E, 0x4148, 0x6525, 0x652B, 0xD360,
+ 0xD361, 0, 0, 0x6526, 0x3750, 0xD362, 0x652E, 0x6532,
+ 0x376B, 0xD363, 0, 0xD364, 0, 0, 0x652D, 0xD365,
+ 0, 0xD366, 0xD367, 0x6536, 0xD368, 0xD369, 0x394A, 0,
+ 0, 0x4D6D, 0x303C, 0x6533, 0, 0xD36A, 0x356B, 0xD36B,
+ 0x6530, 0, 0xD36C, 0, 0, 0, 0x6531, 0,
+ 0xD36D, 0x457D, 0x652F, 0x652C, 0, 0x3328, 0x4064, 0,
+ 0xD36E, 0x3828, 0xD36F, 0xD370, 0, 0x6538, 0, 0xD371,
+};
+const unsigned short utf8_to_euc_E7B6[] = {
+ 0, 0xD372, 0xD373, 0xD374, 0, 0xD375, 0xD376, 0,
+ 0xD377, 0x6535, 0, 0xD378, 0xD379, 0xD37A, 0, 0x6537,
+ 0, 0xD37B, 0, 0x6534, 0, 0, 0xD37C, 0xD37D,
+ 0, 0x3751, 0x4233, 0x6539, 0x416E, 0xD37E, 0xD421, 0x6546,
+ 0xF45C, 0, 0x6542, 0x653C, 0, 0, 0xD422, 0xD423,
+ 0, 0, 0xD424, 0x6540, 0x3C7A, 0x305D, 0x653B, 0x6543,
+ 0x6547, 0x394B, 0x4C56, 0xD425, 0x4456, 0x653D, 0xD426, 0xD427,
+ 0x6545, 0xD428, 0x653A, 0x433E, 0, 0x653F, 0x303D, 0x4C4A,
+};
+const unsigned short utf8_to_euc_E7B7[] = {
+ 0, 0, 0xD429, 0xD42A, 0xD42B, 0xD42C, 0xD42D, 0x653E,
+ 0, 0, 0x365B, 0x486C, 0xD42E, 0xD42F, 0xD430, 0x416D,
+ 0, 0x4E50, 0x3D6F, 0, 0, 0x656E, 0xF45D, 0xD431,
+ 0x6548, 0xD432, 0x407E, 0, 0x6544, 0x6549, 0x654B, 0,
+ 0x4479, 0x654E, 0xD434, 0, 0x654A, 0xD435, 0xD436, 0,
+ 0x4A54, 0x344B, 0xD437, 0xD438, 0x4C4B, 0xD439, 0, 0x305E,
+ 0, 0xD43A, 0x654D, 0, 0x4E7D, 0xD43B, 0xD43C, 0,
+ 0, 0xD43D, 0xD43E, 0x654C, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E7B8[] = {
+ 0xD433, 0x316F, 0, 0, 0x466C, 0x654F, 0, 0,
+ 0xD43F, 0x6556, 0x6550, 0x6557, 0, 0, 0, 0,
+ 0xD440, 0xD441, 0x6553, 0, 0, 0xD442, 0, 0xD443,
+ 0, 0, 0, 0x477B, 0xD444, 0xD445, 0x3C4A, 0x6555,
+ 0xD446, 0x6552, 0x6558, 0x6551, 0, 0, 0x3D44, 0xD447,
+ 0xD448, 0, 0, 0x4B25, 0xD449, 0xD44A, 0x3D4C, 0xD44B,
+ 0, 0x6554, 0x6560, 0xD44C, 0, 0x655C, 0xD44D, 0x655F,
+ 0, 0x655D, 0x6561, 0x655B, 0, 0x6541, 0x4053, 0xD44E,
+};
+const unsigned short utf8_to_euc_E7B9[] = {
+ 0, 0x484B, 0, 0x655E, 0xD44F, 0xD450, 0x6559, 0xD451,
+ 0, 0, 0x4121, 0x3752, 0, 0x3D2B, 0xD452, 0,
+ 0xD453, 0, 0xD454, 0, 0x3F25, 0x4136, 0x6564, 0,
+ 0xD455, 0x6566, 0x6567, 0, 0, 0x6563, 0x6565, 0xD456,
+ 0, 0xD457, 0xD458, 0, 0, 0xD459, 0x655A, 0x6562,
+ 0, 0x656A, 0x6569, 0xD45A, 0, 0x4B7A, 0xD45B, 0xD45C,
+ 0x372B, 0, 0, 0xD45D, 0, 0, 0, 0,
+ 0xD45E, 0x6568, 0, 0x656C, 0x656B, 0x656F, 0xD45F, 0x6571,
+};
+const unsigned short utf8_to_euc_E7BA[] = {
+ 0, 0xD460, 0x3B3C, 0x656D, 0, 0, 0xD461, 0xD462,
+ 0x6572, 0x6573, 0xD463, 0, 0x6574, 0xD464, 0x657A, 0x453B,
+ 0x6576, 0xD465, 0x6575, 0x6577, 0x6578, 0xD466, 0x6579, 0,
+ 0xD467, 0, 0xD468, 0x657B, 0x657C, 0xD469, 0xD46A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E7BC[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x344C, 0,
+ 0x657D, 0, 0x657E, 0xD46C, 0xD46B, 0xD46D, 0xD46E, 0xD46F,
+};
+const unsigned short utf8_to_euc_E7BD[] = {
+ 0, 0, 0, 0xD470, 0xD471, 0x6621, 0, 0xD472,
+ 0, 0, 0, 0, 0x6622, 0x6623, 0x6624, 0xD473,
+ 0x6625, 0x6626, 0xD474, 0xD475, 0x6628, 0x6627, 0, 0,
+ 0x6629, 0, 0, 0xD476, 0xD477, 0xD478, 0, 0x662A,
+ 0x662B, 0xD479, 0, 0xD47A, 0xD47B, 0xD47C, 0xD47D, 0x662E,
+ 0x662C, 0x662D, 0x3A61, 0x3753, 0, 0xD47E, 0x4356, 0,
+ 0x4833, 0xD521, 0x3D70, 0, 0, 0x474D, 0, 0x486D,
+ 0x662F, 0x586D, 0, 0, 0, 0xD522, 0xD523, 0xD524,
+};
+const unsigned short utf8_to_euc_E7BE[] = {
+ 0xD525, 0, 0x6630, 0x6632, 0, 0x4D65, 0x6631, 0x6634,
+ 0x6633, 0, 0x4D53, 0xD526, 0x6635, 0xD527, 0x487E, 0xD528,
+ 0xD529, 0xD52A, 0, 0, 0x6636, 0, 0xD52B, 0xD52C,
+ 0, 0, 0x6639, 0, 0xD52D, 0x6638, 0x6637, 0,
+ 0, 0xD52E, 0xD52F, 0x663A, 0x3732, 0, 0xD530, 0,
+ 0x4122, 0x3541, 0xD531, 0, 0, 0xD532, 0x663E, 0x663B,
+ 0, 0, 0x663C, 0, 0xD533, 0, 0x663F, 0,
+ 0x6640, 0x663D, 0, 0, 0xD534, 0x3129, 0, 0xD535,
+};
+const unsigned short utf8_to_euc_E7BF[] = {
+ 0xD536, 0x3227, 0, 0xD537, 0, 0x6642, 0x6643, 0,
+ 0xD538, 0, 0x6644, 0, 0x4D62, 0, 0xD539, 0xD53A,
+ 0, 0, 0x3D2C, 0, 0x6646, 0x6645, 0, 0,
+ 0, 0, 0, 0xD53B, 0, 0, 0, 0xD53C,
+ 0x3F69, 0x6647, 0, 0xD53D, 0, 0xD53E, 0x6648, 0,
+ 0xD53F, 0x6649, 0, 0x3465, 0xD540, 0, 0xD541, 0xD542,
+ 0x344D, 0, 0xD543, 0x664A, 0, 0, 0, 0,
+ 0, 0x664B, 0xD544, 0x4B5D, 0x4D63, 0xD545, 0xD546, 0xD547,
+};
+const unsigned short utf8_to_euc_E880[] = {
+ 0x4D54, 0x4F37, 0, 0x394D, 0x664E, 0x3C54, 0x664D, 0xD548,
+ 0xD549, 0, 0xD54A, 0x664F, 0x3C29, 0xD54B, 0xD54C, 0xD54D,
+ 0x4251, 0xD54E, 0x6650, 0xD54F, 0xD550, 0x394C, 0xD551, 0x4C57,
+ 0x6651, 0x6652, 0, 0, 0x6653, 0xD552, 0xD553, 0xD554,
+ 0xD555, 0x6654, 0, 0, 0xD556, 0, 0xD557, 0,
+ 0x6655, 0, 0, 0, 0xD558, 0, 0xD559, 0,
+ 0xD55A, 0, 0, 0x3C2A, 0xD55B, 0xD55C, 0x4C6D, 0xD55D,
+ 0, 0xD55E, 0xD55F, 0x6657, 0xD560, 0x433F, 0xD561, 0x6656,
+};
+const unsigned short utf8_to_euc_E881[] = {
+ 0xD562, 0, 0, 0, 0xD563, 0, 0x6659, 0,
+ 0, 0, 0x6658, 0, 0, 0, 0, 0,
+ 0, 0, 0x665A, 0, 0, 0, 0x403B, 0,
+ 0x665B, 0, 0x665C, 0, 0, 0, 0x4A39, 0x665D,
+ 0xD564, 0x416F, 0x665E, 0, 0xD565, 0, 0xD566, 0,
+ 0x665F, 0, 0, 0, 0, 0xD567, 0, 0x4E7E,
+ 0x6662, 0xD568, 0x6661, 0x6660, 0x4430, 0xD569, 0x6663, 0x3F26,
+ 0, 0x6664, 0, 0, 0, 0x6665, 0x4F38, 0x6666,
+};
+const unsigned short utf8_to_euc_E882[] = {
+ 0, 0xD56A, 0, 0, 0x6667, 0x6669, 0x6668, 0x4825,
+ 0xD56B, 0x4679, 0, 0x4F3E, 0x4829, 0, 0xD56C, 0,
+ 0, 0, 0, 0x666B, 0, 0, 0x3E53, 0,
+ 0x492A, 0, 0x666C, 0x666A, 0xD56D, 0x344E, 0xD56E, 0,
+ 0, 0x3854, 0x3B68, 0, 0, 0x486E, 0xD56F, 0xD570,
+ 0, 0x382A, 0x4B43, 0xD571, 0x666F, 0x666D, 0, 0x394E,
+ 0, 0x394F, 0x3069, 0, 0x3A68, 0, 0, 0,
+ 0xD572, 0xD573, 0x4759, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E883[] = {
+ 0, 0, 0, 0x305F, 0x6674, 0, 0x4340, 0,
+ 0xD574, 0, 0, 0, 0x4758, 0xD575, 0x425B, 0xD576,
+ 0, 0, 0xD577, 0, 0xD578, 0xD579, 0x6676, 0xD57A,
+ 0xD57B, 0x6672, 0x6675, 0x6670, 0, 0x6673, 0x4B26, 0,
+ 0xD57C, 0x3855, 0, 0, 0x307D, 0x6671, 0, 0,
+ 0, 0, 0, 0, 0, 0xD57D, 0xD57E, 0x6678,
+ 0xD621, 0x6679, 0xD622, 0xD623, 0x4639, 0, 0xD624, 0,
+ 0x363B, 0xD625, 0xD626, 0, 0x6726, 0x473D, 0xD627, 0,
+};
+const unsigned short utf8_to_euc_E884[] = {
+ 0, 0, 0x3B69, 0xD628, 0, 0x363C, 0x4048, 0x4F46,
+ 0x4C2E, 0x6677, 0x4054, 0xD629, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xD62A, 0xD62B,
+ 0xD62C, 0, 0x3553, 0x667A, 0xD62D, 0, 0xD62E, 0,
+ 0xD62F, 0, 0, 0x667C, 0xD630, 0, 0, 0xD631,
+ 0, 0x667B, 0, 0, 0xD632, 0, 0, 0x667D,
+ 0xD633, 0x4326, 0, 0x473E, 0, 0xD634, 0, 0,
+ 0, 0x4431, 0xD635, 0, 0xD636, 0, 0x6723, 0,
+};
+const unsigned short utf8_to_euc_E885[] = {
+ 0, 0, 0, 0, 0, 0xD637, 0x6722, 0xD638,
+ 0, 0, 0xD639, 0x667E, 0xD63A, 0, 0x3F55, 0,
+ 0x4965, 0x6725, 0xD63B, 0x6724, 0x3950, 0x4F53, 0, 0xD63C,
+ 0, 0, 0, 0, 0, 0, 0, 0x6735,
+ 0xD63D, 0xD63E, 0, 0, 0, 0x6729, 0x672A, 0xD63F,
+ 0xD640, 0xD641, 0, 0x3C70, 0, 0xD642, 0x6728, 0xD643,
+ 0x3978, 0x6727, 0, 0, 0x672B, 0, 0, 0xD644,
+ 0x4432, 0x4A22, 0x4123, 0, 0, 0, 0, 0x425C,
+};
+const unsigned short utf8_to_euc_E886[] = {
+ 0x672F, 0xD645, 0x6730, 0x672C, 0xD647, 0xD648, 0xD649, 0,
+ 0x672D, 0, 0x672E, 0xD64A, 0, 0, 0xD64B, 0x3951,
+ 0xD646, 0, 0, 0x6736, 0, 0x6732, 0xD64C, 0,
+ 0xD64D, 0, 0x4966, 0xD64E, 0x4B6C, 0x4928, 0xD64F, 0,
+ 0x6731, 0, 0xD650, 0x6734, 0x6733, 0, 0, 0,
+ 0x4B44, 0x6737, 0, 0, 0, 0, 0xD651, 0,
+ 0x6738, 0, 0xD652, 0x4137, 0xD653, 0x6739, 0, 0,
+ 0x673B, 0, 0x673F, 0xD654, 0, 0x673C, 0x673A, 0x473F,
+};
+const unsigned short utf8_to_euc_E887[] = {
+ 0x673D, 0, 0x673E, 0xD656, 0, 0xD657, 0x3232, 0,
+ 0x6745, 0x6740, 0xD658, 0xD655, 0, 0x6741, 0xD659, 0xD65A,
+ 0, 0x6742, 0, 0x4221, 0, 0xD65B, 0, 0xD65C,
+ 0x6744, 0x6743, 0x6746, 0xD65D, 0, 0xD65E, 0xD65F, 0x6747,
+ 0x6748, 0xD660, 0, 0x3F43, 0xD661, 0x3269, 0, 0x6749,
+ 0x4E57, 0, 0x3C2B, 0xD662, 0xD663, 0x3D2D, 0, 0,
+ 0xD664, 0xD665, 0xD666, 0x3B6A, 0x4357, 0xD667, 0xD668, 0,
+ 0xD669, 0xD66A, 0x674A, 0x674B, 0x3131, 0xD66B, 0x674C, 0xD66C,
+};
+const unsigned short utf8_to_euc_E888[] = {
+ 0xD66D, 0x674D, 0x674E, 0xD66E, 0, 0x674F, 0, 0x6750,
+ 0x363D, 0x5A2A, 0x6751, 0, 0x4065, 0x6752, 0x3C4B, 0xD66F,
+ 0x6753, 0, 0x5030, 0xD670, 0xD671, 0, 0x6754, 0x4A5E,
+ 0x345C, 0xD672, 0xD673, 0x4124, 0x3D58, 0xD674, 0x4971, 0x3D2E,
+ 0, 0xD675, 0xD676, 0, 0, 0, 0, 0,
+ 0xD677, 0x6755, 0x3952, 0x6756, 0x484C, 0, 0x6764, 0,
+ 0, 0, 0xD678, 0x6758, 0xD679, 0x4249, 0x4775, 0x383F,
+ 0x6757, 0x4125, 0xD67A, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E889[] = {
+ 0x6759, 0, 0, 0xD67B, 0xD67C, 0xD67D, 0xD67E, 0x447A,
+ 0, 0, 0, 0xD721, 0, 0, 0xD722, 0xD723,
+ 0, 0xD724, 0, 0, 0, 0, 0xD725, 0,
+ 0x675B, 0x675A, 0x675D, 0, 0xD726, 0x675C, 0, 0x675E,
+ 0xD727, 0, 0x6760, 0xD728, 0x675F, 0, 0x344F, 0xD729,
+ 0x6761, 0, 0x6762, 0x6763, 0, 0xD72A, 0x3A31, 0x4E49,
+ 0, 0x6765, 0x3F27, 0, 0xD72B, 0, 0x3170, 0x6766,
+ 0x6767, 0, 0, 0xD72C, 0, 0xD72D, 0x6768, 0xD72E,
+};
+const unsigned short utf8_to_euc_E88A[] = {
+ 0xD72F, 0xD730, 0, 0xD731, 0xD732, 0, 0, 0xD733,
+ 0, 0xD734, 0xD735, 0x3072, 0, 0x6769, 0xD736, 0,
+ 0, 0xD737, 0x676A, 0, 0xD738, 0, 0xD739, 0,
+ 0xD73A, 0x4967, 0xD73B, 0xD73C, 0, 0x3C47, 0, 0x676C,
+ 0xD73D, 0xD73E, 0, 0xD73F, 0xD740, 0x3329, 0x3032, 0xD741,
+ 0xD742, 0xD743, 0xD744, 0x676B, 0x676E, 0x474E, 0xD745, 0x3F44,
+ 0xD746, 0x3256, 0xD747, 0x4B27, 0xD748, 0, 0, 0xD749,
+ 0x375D, 0x365C, 0xD74A, 0x676D, 0xD74B, 0x326A, 0xD74C, 0xD74D,
+};
+const unsigned short utf8_to_euc_E88B[] = {
+ 0, 0, 0, 0, 0, 0x3423, 0xD74E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xD74F, 0x3171, 0x6772, 0x4E6A, 0x425D, 0xD750, 0, 0x4944,
+ 0, 0x677E, 0xD751, 0x3257, 0x677C, 0, 0x677A, 0x6771,
+ 0xD752, 0x676F, 0xD753, 0x6770, 0xD754, 0x3C63, 0x366C, 0x4377,
+ 0xD755, 0, 0xD756, 0x4651, 0, 0xD757, 0, 0xD758,
+ 0, 0x3151, 0, 0x6774, 0x6773, 0, 0xD759, 0xD75A,
+ 0, 0x6779, 0x6775, 0x6778, 0, 0xD75B, 0xD75C, 0,
+};
+const unsigned short utf8_to_euc_E88C[] = {
+ 0xD75D, 0xD75E, 0x4C50, 0x6777, 0x3258, 0x337D, 0x677B, 0xD75F,
+ 0xD760, 0x677D, 0xD761, 0xD762, 0, 0, 0x3754, 0,
+ 0, 0, 0, 0, 0, 0, 0x6823, 0x682C,
+ 0x682D, 0, 0, 0xD764, 0x302B, 0xD765, 0xD766, 0xD767,
+ 0, 0xD768, 0xD769, 0x6834, 0, 0, 0, 0,
+ 0x3071, 0, 0, 0x682B, 0xD76A, 0xD76B, 0xD76C, 0x682A,
+ 0xD76D, 0x6825, 0x6824, 0xD76E, 0x6822, 0x6821, 0x4363, 0xD76F,
+ 0x427B, 0x6827, 0xD770, 0, 0xD771, 0xD772, 0, 0,
+};
+const unsigned short utf8_to_euc_E88D[] = {
+ 0x6826, 0, 0xD773, 0xD774, 0xD775, 0x6829, 0, 0xD776,
+ 0, 0x4170, 0x3755, 0, 0, 0xD777, 0xD778, 0x3141,
+ 0x6828, 0xD779, 0x3953, 0xD83E, 0xD763, 0xD77A, 0xD77B, 0xD77C,
+ 0x4171, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xF45F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xD77D, 0, 0, 0x683A, 0, 0x683B, 0, 0x3259,
+ 0xD77E, 0, 0, 0x322E, 0x6838, 0xD821, 0, 0xD822,
+};
+const unsigned short utf8_to_euc_E88E[] = {
+ 0xD823, 0, 0xD824, 0, 0xD825, 0x682E, 0xD826, 0x6836,
+ 0, 0x683D, 0x6837, 0, 0, 0xD827, 0x6835, 0,
+ 0, 0, 0xD828, 0x6776, 0xD829, 0xD82A, 0x6833, 0,
+ 0xD82B, 0xD82C, 0x682F, 0xD82D, 0xD82E, 0xD82F, 0x3450, 0x6831,
+ 0x683C, 0, 0x6832, 0, 0, 0, 0xD830, 0xD831,
+ 0x683E, 0xD832, 0x6830, 0x477C, 0xD833, 0xD84C, 0, 0,
+ 0, 0x4D69, 0, 0, 0, 0x6839, 0, 0,
+ 0, 0, 0, 0, 0, 0x684F, 0xD834, 0xD835,
+};
+const unsigned short utf8_to_euc_E88F[] = {
+ 0xD836, 0x6847, 0, 0, 0, 0x3F7B, 0, 0xD837,
+ 0, 0xD838, 0x3546, 0, 0x365D, 0, 0x6842, 0xD839,
+ 0xD83A, 0xD83B, 0, 0x325B, 0xD83C, 0, 0x3E54, 0,
+ 0x6845, 0, 0, 0, 0x3A5A, 0xD83D, 0, 0x4551,
+ 0x684A, 0, 0, 0, 0, 0, 0, 0,
+ 0xD83F, 0x4A6E, 0xD840, 0x6841, 0, 0, 0, 0x325A,
+ 0x3856, 0x4929, 0x684B, 0, 0x683F, 0, 0xD841, 0x6848,
+ 0xD842, 0xD843, 0, 0x6852, 0xD844, 0x6843, 0, 0,
+};
+const unsigned short utf8_to_euc_E890[] = {
+ 0, 0xD845, 0, 0x6844, 0x463A, 0, 0xD846, 0x6849,
+ 0, 0, 0xD847, 0x6846, 0x4B28, 0x684C, 0x3060, 0xD848,
+ 0, 0xD849, 0, 0x6840, 0, 0xD84A, 0, 0,
+ 0, 0xD84B, 0, 0, 0, 0, 0, 0,
+ 0x684E, 0, 0x684D, 0, 0, 0, 0, 0,
+ 0, 0x476B, 0x6854, 0, 0x685F, 0, 0, 0xD84D,
+ 0, 0x337E, 0, 0, 0, 0x6862, 0, 0,
+ 0x6850, 0xD84E, 0, 0, 0x6855, 0x4D6E, 0, 0,
+};
+const unsigned short utf8_to_euc_E891[] = {
+ 0, 0, 0, 0, 0, 0xD84F, 0x685E, 0xD850,
+ 0xD851, 0x4D55, 0xD852, 0, 0, 0xD853, 0x4E2A, 0xD854,
+ 0, 0xD855, 0xD856, 0, 0, 0, 0xD857, 0x4378,
+ 0xD858, 0xD859, 0xD85A, 0x336B, 0xD85B, 0, 0, 0,
+ 0xD85C, 0x4972, 0x6864, 0x4621, 0xD85D, 0xD85E, 0x3031, 0xD85F,
+ 0, 0x685D, 0xD860, 0x6859, 0x4172, 0x6853, 0x685B, 0x6860,
+ 0xD861, 0x472C, 0, 0xD862, 0xD863, 0x302A, 0xD864, 0x6858,
+ 0xD865, 0x6861, 0x4978, 0, 0xD866, 0xD867, 0, 0,
+};
+const unsigned short utf8_to_euc_E892[] = {
+ 0, 0xD868, 0x685C, 0, 0x6857, 0xD869, 0, 0,
+ 0, 0, 0, 0x3E55, 0, 0, 0, 0,
+ 0x3D2F, 0, 0xD86A, 0xD86B, 0x3C2C, 0xD86C, 0, 0,
+ 0, 0x4C58, 0, 0, 0x4947, 0, 0xD86D, 0x6867,
+ 0, 0x6870, 0, 0, 0, 0, 0xD86E, 0,
+ 0xD86F, 0xD870, 0xD871, 0, 0, 0x685A, 0, 0xD872,
+ 0, 0xD873, 0x3377, 0, 0xD874, 0, 0, 0,
+ 0x3E78, 0x6865, 0xD875, 0x686A, 0x4173, 0xD876, 0xD877, 0x6866,
+};
+const unsigned short utf8_to_euc_E893[] = {
+ 0xD878, 0x686D, 0xD879, 0, 0x435F, 0, 0x686E, 0xD87A,
+ 0xD87B, 0x4D56, 0x6863, 0x3338, 0xD87C, 0x6869, 0, 0xD87D,
+ 0x686C, 0x4C2C, 0, 0xD87E, 0, 0, 0x686F, 0,
+ 0, 0x6868, 0x686B, 0, 0xD921, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xD922,
+ 0, 0, 0xD923, 0, 0x4B29, 0, 0x4F21, 0xD924,
+ 0xD925, 0xD926, 0xD927, 0, 0x6873, 0, 0, 0xD928,
+ 0, 0, 0xD92A, 0xD92B, 0x687A, 0xD92C, 0, 0x6872,
+};
+const unsigned short utf8_to_euc_E894[] = {
+ 0x3C43, 0, 0xD92D, 0xD92E, 0, 0, 0x6851, 0xD92F,
+ 0, 0, 0, 0, 0xD930, 0, 0xD931, 0,
+ 0xD932, 0x4A4E, 0, 0x4C22, 0x6879, 0x6878, 0, 0x6874,
+ 0x6875, 0, 0x3136, 0, 0xD933, 0, 0xD934, 0x6877,
+ 0, 0x6871, 0xD935, 0xD936, 0xD937, 0xD938, 0x4455, 0xD939,
+ 0, 0, 0xD93A, 0xD93B, 0x6876, 0x307E, 0, 0xD93C,
+ 0, 0, 0xD929, 0xD93D, 0xD93E, 0x4222, 0xD93F, 0,
+ 0, 0, 0, 0, 0, 0x4A43, 0, 0xD940,
+};
+const unsigned short utf8_to_euc_E895[] = {
+ 0x687B, 0x6921, 0, 0x4859, 0, 0, 0xD941, 0,
+ 0x687E, 0x3E56, 0x3C49, 0x6923, 0, 0, 0x363E, 0xD942,
+ 0xD943, 0xD944, 0xD945, 0xD946, 0, 0x6924, 0xD947, 0x4979,
+ 0x687D, 0xD948, 0x6856, 0, 0xD949, 0xD94A, 0xD94B, 0xD94C,
+ 0xD94D, 0xD94E, 0xD94F, 0x687C, 0xD950, 0, 0, 0,
+ 0x4F4F, 0x4622, 0x4973, 0xD951, 0, 0x692B, 0, 0xD952,
+ 0, 0, 0, 0, 0, 0, 0, 0x6931,
+ 0, 0xD953, 0xD954, 0xD955, 0, 0xD956, 0x6932, 0xD957,
+};
+const unsigned short utf8_to_euc_E896[] = {
+ 0x6925, 0xD958, 0, 0, 0x4776, 0xD959, 0xD95A, 0x692F,
+ 0x6927, 0xD95B, 0x6929, 0xD95C, 0xD95D, 0, 0, 0xD95E,
+ 0x6933, 0x6928, 0, 0xD95F, 0x692C, 0, 0, 0x3172,
+ 0xD960, 0x4665, 0, 0x692D, 0x6930, 0xD961, 0, 0xD962,
+ 0xD963, 0, 0xD964, 0, 0x6926, 0xD965, 0x4126, 0xD966,
+ 0x692A, 0x3B27, 0x3F45, 0x3730, 0x4C74, 0xD974, 0x4C79, 0x3D72,
+ 0xF461, 0, 0, 0, 0xD967, 0, 0xD968, 0xD969,
+ 0xD96A, 0x6937, 0x6935, 0, 0xD96B, 0xD96C, 0xD96D, 0xD96E,
+};
+const unsigned short utf8_to_euc_E897[] = {
+ 0, 0x4F4E, 0xD96F, 0, 0, 0, 0, 0xD970,
+ 0, 0x6934, 0xD971, 0xD972, 0, 0x4D75, 0xD973, 0x6936,
+ 0x6938, 0, 0, 0, 0, 0x6939, 0, 0,
+ 0xD975, 0, 0xD976, 0, 0x693C, 0x693A, 0, 0xD977,
+ 0xD978, 0, 0, 0, 0x4623, 0x693B, 0xD979, 0,
+ 0xD97A, 0x484D, 0x692E, 0, 0, 0xD97B, 0, 0,
+ 0, 0, 0, 0xD97C, 0, 0, 0xD97D, 0x3D73,
+ 0, 0x693D, 0x6942, 0x4174, 0xD97E, 0, 0x6941, 0xDA21,
+};
+const unsigned short utf8_to_euc_E898[] = {
+ 0xDA22, 0, 0x6922, 0, 0xDA23, 0xDA24, 0x6943, 0x4149,
+ 0, 0, 0x693E, 0x6940, 0, 0xDA25, 0xDA26, 0,
+ 0xDA27, 0xDA28, 0xDA29, 0x693F, 0, 0, 0x5D31, 0x5D22,
+ 0xDA2A, 0xDA2B, 0x6945, 0xDA2C, 0, 0, 0xDA2D, 0,
+ 0, 0xDA2E, 0x6944, 0, 0, 0, 0, 0xDA2F,
+ 0, 0xDA30, 0, 0, 0, 0x4D76, 0, 0x623C,
+ 0x6946, 0, 0, 0, 0, 0, 0xDA31, 0,
+ 0xDA32, 0, 0xDA33, 0, 0xDA34, 0xDA35, 0, 0x6947,
+};
+const unsigned short utf8_to_euc_E899[] = {
+ 0xDA36, 0xB866, 0xDA37, 0, 0, 0, 0xDA38, 0,
+ 0, 0, 0, 0, 0, 0x6948, 0x3857, 0,
+ 0x3554, 0, 0xDA39, 0xDA3A, 0x694A, 0x515D, 0xDA3B, 0xDA3C,
+ 0xDA3D, 0xDA3E, 0x3575, 0, 0x4E3A, 0xDA3F, 0x3673, 0x694B,
+ 0xDA40, 0xDA41, 0xDA42, 0xDA43, 0xDA44, 0, 0, 0x694C,
+ 0, 0xDA45, 0, 0x436E, 0xDA46, 0, 0, 0xDA47,
+ 0, 0x694D, 0, 0, 0, 0xDA48, 0xDA49, 0xDA4A,
+ 0, 0x467A, 0xDA4B, 0x303A, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E89A[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xDA6D, 0, 0x3263, 0x6952, 0x6953, 0xDA4C, 0, 0,
+ 0, 0xDA4D, 0, 0x694E, 0, 0x3B3D, 0xDA4E, 0,
+ 0xDA4F, 0, 0xDA50, 0, 0xDA51, 0, 0, 0,
+ 0, 0xDA52, 0, 0x694F, 0x4742, 0, 0xDA53, 0xDA54,
+ 0xDA55, 0x6950, 0x6951, 0x695B, 0, 0xDA56, 0, 0x6955,
+ 0x6958, 0xDA57, 0, 0xDA58, 0xDA59, 0xDA5A, 0x6954, 0xDA5B,
+ 0xDA5C, 0xDA5D, 0, 0, 0, 0, 0, 0xDA5E,
+};
+const unsigned short utf8_to_euc_E89B[] = {
+ 0xDA5F, 0xDA60, 0, 0xDA61, 0x6956, 0xDA62, 0x6957, 0x3C58,
+ 0, 0x6959, 0, 0x4341, 0, 0x3756, 0x3342, 0,
+ 0, 0xDA63, 0xDA64, 0, 0x695C, 0xDA65, 0, 0xDA66,
+ 0, 0x333F, 0xDA67, 0x6961, 0xDA68, 0, 0x695D, 0x6960,
+ 0xDA69, 0, 0, 0xDA6A, 0x483A, 0xDA6B, 0, 0xDA6C,
+ 0, 0x695E, 0, 0, 0x695F, 0x4948, 0x485A, 0x6962,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x427D, 0x696C, 0xDA6E, 0x6968, 0xDA6F, 0xDA70, 0x326B, 0,
+};
+const unsigned short utf8_to_euc_E89C[] = {
+ 0x6966, 0, 0x4B2A, 0x6967, 0xDA71, 0xDA72, 0x6964, 0xDA73,
+ 0x6965, 0x696A, 0x696D, 0xDA74, 0, 0x696B, 0xDA75, 0xDA76,
+ 0xDA77, 0x6969, 0x6963, 0xDA78, 0xDA79, 0, 0, 0,
+ 0x4358, 0xDA7A, 0x6974, 0, 0x4C2A, 0, 0xDA7B, 0xDA7C,
+ 0, 0xDA7D, 0, 0xDA7E, 0, 0x6972, 0, 0,
+ 0xDB21, 0x6973, 0, 0, 0, 0, 0xDB22, 0xDB23,
+ 0, 0xDB24, 0xDB25, 0, 0x696E, 0, 0, 0x6970,
+ 0, 0xDB26, 0xDB27, 0x6971, 0xDB28, 0xDB29, 0xDB2A, 0x696F,
+};
+const unsigned short utf8_to_euc_E89D[] = {
+ 0xDB2B, 0, 0, 0xDB2C, 0, 0xDB2D, 0, 0,
+ 0, 0x4066, 0, 0x4F39, 0x6978, 0xDB2E, 0x6979, 0,
+ 0, 0, 0, 0x6A21, 0, 0x3F2A, 0, 0x697B,
+ 0xDB2F, 0x697E, 0, 0, 0, 0xDB30, 0, 0x6976,
+ 0x6975, 0xDB31, 0, 0x6A22, 0xDB32, 0xDB33, 0x325C, 0,
+ 0x697C, 0, 0x6A23, 0, 0, 0, 0x697D, 0xDB34,
+ 0, 0xDB35, 0xDB36, 0, 0x697A, 0, 0x4433, 0,
+ 0x6977, 0, 0, 0xDB37, 0, 0, 0, 0x4768,
+};
+const unsigned short utf8_to_euc_E89E[] = {
+ 0, 0, 0x6A27, 0xDB38, 0xDB39, 0xDB3A, 0xDB3B, 0xDB3C,
+ 0xDB3D, 0xDB3E, 0, 0xDB3F, 0xDB40, 0x4D3B, 0, 0,
+ 0xDB41, 0, 0, 0xDB42, 0, 0xDB43, 0, 0xDB44,
+ 0xDB45, 0xDB46, 0, 0, 0, 0, 0xDB47, 0x6A26,
+ 0xDB48, 0, 0x6A25, 0xDB49, 0, 0, 0, 0xDB4A,
+ 0, 0, 0, 0x6A2E, 0xDB4B, 0xDB4C, 0xDB4D, 0x6A28,
+ 0, 0xDB4E, 0, 0x6A30, 0, 0xDB4F, 0, 0,
+ 0, 0, 0x4D66, 0x6A33, 0, 0x6A2A, 0xDB50, 0xDB51,
+};
+const unsigned short utf8_to_euc_E89F[] = {
+ 0x6A2B, 0xDB52, 0, 0, 0x6A2F, 0, 0x6A32, 0x6A31,
+ 0xDB53, 0xDB54, 0xDB55, 0x6A29, 0, 0, 0xDB56, 0,
+ 0x6A2C, 0, 0x6A3D, 0, 0, 0xDB57, 0xDB58, 0,
+ 0, 0xDB59, 0xDB5A, 0, 0xDB5B, 0, 0, 0xDB5C,
+ 0x6A36, 0, 0xDB5D, 0xDB5E, 0xDB5F, 0, 0, 0,
+ 0, 0, 0xDB60, 0xDB61, 0, 0xDB62, 0, 0x6A34,
+ 0, 0xDB63, 0x6A35, 0xDB64, 0, 0, 0x6A3A, 0x6A3B,
+ 0xDB65, 0x332A, 0xDB66, 0x3542, 0, 0, 0x6A39, 0xDB67,
+};
+const unsigned short utf8_to_euc_E8A0[] = {
+ 0, 0xDB68, 0, 0xDB69, 0, 0x6A24, 0xDB6A, 0xF464,
+ 0, 0xDB6B, 0xDB6C, 0xDB6D, 0, 0x6A38, 0x6A3C, 0x6A37,
+ 0xDB6E, 0x6A3E, 0xDB70, 0xDB71, 0xDB72, 0x6A40, 0x6A3F, 0,
+ 0xDB73, 0xDB6F, 0xDB74, 0xDB75, 0xDB76, 0, 0xDB77, 0xDB78,
+ 0, 0x6A42, 0x6A41, 0x695A, 0, 0, 0, 0x6A46,
+ 0xDB79, 0, 0, 0, 0, 0xDB7A, 0xDB7B, 0,
+ 0xDB7C, 0x6A43, 0xDB7D, 0, 0, 0xDB7E, 0x6A44, 0,
+ 0, 0x6A45, 0xDC21, 0x6A47, 0xDC22, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E8A1[] = {
+ 0x376C, 0xDC23, 0x6A49, 0xDC24, 0x6A48, 0xDC25, 0x3D30, 0,
+ 0xDC26, 0xDC27, 0xDC28, 0xDC29, 0x3954, 0x5E27, 0xDC2A, 0,
+ 0, 0xDC2B, 0x6A4A, 0x3D51, 0, 0xDC2C, 0xDC2D, 0x3339,
+ 0xDC2E, 0x6A4B, 0xDC2F, 0x3152, 0xDC30, 0x3E57, 0x6A4C, 0xDC31,
+ 0xDC32, 0x3955, 0x6A4D, 0x3061, 0xDC33, 0, 0, 0,
+ 0x493D, 0xDC34, 0, 0x6A4E, 0, 0, 0, 0,
+ 0x3F6A, 0xDC35, 0x6A55, 0, 0, 0x6A52, 0, 0x436F,
+ 0, 0xDC36, 0, 0xDC37, 0, 0x6A53, 0x6A50, 0x365E,
+};
+const unsigned short utf8_to_euc_E8A2[] = {
+ 0xDC38, 0x6A4F, 0x6A56, 0, 0, 0, 0, 0,
+ 0x3736, 0, 0, 0x425E, 0, 0x6A5C, 0, 0,
+ 0, 0, 0x6A58, 0, 0, 0, 0x4235, 0x6A57,
+ 0xDC39, 0x6A5A, 0xDC3A, 0xDC3B, 0xDC3C, 0, 0x6A51, 0xDC3D,
+ 0xDC3E, 0, 0x6A5B, 0, 0x6A5D, 0, 0, 0,
+ 0xDC3F, 0, 0xDC40, 0x486F, 0, 0, 0x6A59, 0,
+ 0x6A5E, 0x6A60, 0, 0, 0x3853, 0x6A54, 0, 0x3041,
+ 0, 0, 0xDC41, 0, 0, 0xDC42, 0xDC43, 0x6A5F,
+};
+const unsigned short utf8_to_euc_E8A3[] = {
+ 0xDC44, 0x3A5B, 0x4E76, 0x6A61, 0x6A62, 0x4175, 0, 0,
+ 0, 0, 0xDC45, 0xDC46, 0xDC47, 0xDC48, 0xDC49, 0x4E22,
+ 0, 0xDC4A, 0xDC4B, 0xDC4C, 0x6A63, 0x4D35, 0, 0,
+ 0x6A64, 0x6A65, 0, 0xDC4D, 0x4A64, 0x6A66, 0xDC4E, 0x3A40,
+ 0, 0x4E23, 0, 0, 0, 0, 0, 0xDC4F,
+ 0x6A6B, 0, 0, 0, 0, 0, 0, 0xDC50,
+ 0xDC51, 0xDC52, 0x6A6C, 0x3E58, 0x6A6A, 0xDC53, 0, 0xDC54,
+ 0x4D67, 0x6A67, 0, 0, 0x6A69, 0x403D, 0x3F7E, 0,
+};
+const unsigned short utf8_to_euc_E8A4[] = {
+ 0, 0xDC55, 0x6A68, 0, 0x6A6D, 0, 0xDC56, 0x4A23,
+ 0, 0, 0x6A6F, 0, 0x6A6E, 0xDC57, 0xDC58, 0xDC59,
+ 0x336C, 0, 0x4B2B, 0x6A70, 0, 0xDC5A, 0xDC5B, 0,
+ 0xDC5C, 0xDC5D, 0xDC5E, 0, 0xDC5F, 0x6A7C, 0x6A72, 0,
+ 0xDC60, 0, 0, 0, 0, 0x6A73, 0xDC61, 0xDC62,
+ 0xDC63, 0, 0x6A74, 0x6A75, 0, 0, 0, 0,
+ 0xDC64, 0xDC65, 0xDC66, 0, 0, 0xDC67, 0x6A79, 0,
+ 0x6A7A, 0xDC68, 0xDC69, 0x6A78, 0, 0, 0xDC6A, 0,
+};
+const unsigned short utf8_to_euc_E8A5[] = {
+ 0xDC6B, 0x6A76, 0xDC6C, 0x6A71, 0x6A77, 0xDC6D, 0xDC6E, 0,
+ 0, 0xDC6F, 0, 0, 0x6A7B, 0x7037, 0, 0xDC70,
+ 0, 0, 0xDC71, 0, 0, 0, 0x3228, 0xDC72,
+ 0, 0, 0xDC73, 0xDC74, 0xDC75, 0, 0x6A7E, 0x365F,
+ 0x6A7D, 0xDC76, 0xDC77, 0xDC78, 0x6B22, 0, 0x6B21, 0,
+ 0, 0, 0x6B24, 0xDC79, 0, 0x6B23, 0xDC7A, 0x6B25,
+ 0xDC7B, 0, 0x3D31, 0xDC7C, 0x6B26, 0xDC7D, 0, 0x6B27,
+ 0, 0, 0xDC7E, 0xDD21, 0xDD22, 0xDD23, 0x6B28, 0x403E,
+};
+const unsigned short utf8_to_euc_E8A6[] = {
+ 0, 0x4D57, 0, 0x6B29, 0, 0, 0x4A24, 0x4746,
+ 0x6B2A, 0xDD24, 0x6B2B, 0x382B, 0, 0xDD25, 0, 0x352C,
+ 0xDD26, 0, 0, 0x6B2C, 0xDD27, 0xDD28, 0x3B6B, 0x4741,
+ 0x6B2D, 0, 0x3350, 0xDD29, 0xDD2A, 0, 0, 0xDD2B,
+ 0xDD2C, 0x6B2E, 0, 0, 0, 0xDD2D, 0x6B30, 0x4D77,
+ 0, 0x6B2F, 0x3F46, 0, 0x6B31, 0, 0, 0x6B32,
+ 0xDD2E, 0, 0x6B33, 0x3451, 0xDD2F, 0xDD30, 0xDD31, 0xDD32,
+ 0, 0, 0x6B34, 0, 0xDD33, 0x6B35, 0, 0x6B36,
+};
+const unsigned short utf8_to_euc_E8A7[] = {
+ 0x6B37, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0x3351, 0, 0xDD34, 0xDD35, 0xDD36, 0xDD37,
+ 0xDD38, 0, 0x6B38, 0, 0x6B39, 0x6B3A, 0, 0,
+ 0, 0, 0, 0x3272, 0, 0xDD39, 0x3F28, 0x6B3B,
+ 0, 0xDD3A, 0, 0xDD3B, 0, 0xDD3C, 0, 0,
+ 0, 0xDD3D, 0, 0xDD3E, 0x6B3C, 0, 0xDD3F, 0,
+ 0x6B3D, 0xDD40, 0, 0, 0, 0xDD41, 0, 0xDD42,
+};
+const unsigned short utf8_to_euc_E8A8[] = {
+ 0x3840, 0, 0x447B, 0x6B3E, 0xDD43, 0xDD44, 0, 0xDD45,
+ 0x3757, 0, 0x3F56, 0, 0x6B41, 0, 0x4624, 0xDD46,
+ 0x6B40, 0xDD47, 0xDD48, 0x3731, 0xDD49, 0xDD4A, 0x6B3F, 0x4277,
+ 0x352D, 0, 0, 0x6B42, 0, 0x6B43, 0xDD4B, 0x3E59,
+ 0xDD4C, 0, 0xDD4D, 0x376D, 0xDD4E, 0x6B44, 0xDD4F, 0,
+ 0, 0, 0x4B2C, 0xDD50, 0xDD51, 0x405F, 0, 0xDD52,
+ 0, 0x3576, 0, 0x4C75, 0x414A, 0xDD53, 0x6B45, 0xDD54,
+ 0, 0, 0x3F47, 0x4370, 0x3E5A, 0xDD55, 0xDD56, 0,
+};
+const unsigned short utf8_to_euc_E8A9[] = {
+ 0xDD57, 0x6B46, 0, 0xDD58, 0, 0xDD59, 0x6B49, 0xDD5A,
+ 0x6B4A, 0xDD5B, 0, 0, 0, 0xDD5C, 0xDD5D, 0,
+ 0x3A3E, 0x4242, 0x6B48, 0xDD5E, 0x3E5B, 0x493E, 0xDD5F, 0xDD60,
+ 0xDD61, 0, 0, 0x6B47, 0xDD62, 0xDD63, 0x3B6C, 0,
+ 0x3153, 0xDD64, 0x6B4E, 0x3758, 0, 0xDD65, 0x3B6E, 0xDD66,
+ 0, 0x3B6D, 0, 0x4F4D, 0x6B4D, 0x6B4C, 0x4127, 0,
+ 0x354D, 0x4F43, 0x333A, 0x3E5C, 0, 0xDD67, 0xDD68, 0xDD69,
+ 0, 0xDD6A, 0xDD6B, 0xDD6C, 0x6B4B, 0, 0xDD6D, 0xDD6E,
+};
+const unsigned short utf8_to_euc_E8AA[] = {
+ 0xDD6F, 0, 0x6B50, 0xDD70, 0x6B51, 0x6B4F, 0xDD71, 0x3858,
+ 0, 0x4D40, 0, 0xDD72, 0x3B6F, 0x4727, 0, 0xDD73,
+ 0xDD74, 0x6B54, 0xDD75, 0x4040, 0, 0x4342, 0xDD76, 0xDD77,
+ 0x4D36, 0xDD78, 0x6B57, 0, 0, 0, 0x386C, 0xDD79,
+ 0x403F, 0x6B53, 0, 0x6B58, 0x386D, 0x6B55, 0x6B56, 0xDD7A,
+ 0x6B52, 0xDD7B, 0, 0, 0x4062, 0x4649, 0xDD7C, 0xDD7D,
+ 0x432F, 0, 0x325D, 0xDD7E, 0, 0, 0xDE21, 0xDE22,
+ 0, 0x4870, 0, 0xDE23, 0x3543, 0, 0xDE24, 0x4434,
+};
+const unsigned short utf8_to_euc_E8AB[] = {
+ 0, 0, 0x6B5B, 0xDE25, 0x6B59, 0, 0xDE26, 0x434C,
+ 0xDE27, 0xDE28, 0xDE29, 0x4041, 0x3452, 0x6B5A, 0, 0x3F5B,
+ 0, 0xDE2A, 0x4E4A, 0xDE2B, 0xDE2C, 0xDE2D, 0x4F40, 0xDE2E,
+ 0, 0, 0x6B5C, 0x6B67, 0x4435, 0xDE2F, 0x6B66, 0xDE30,
+ 0x6B63, 0x6B6B, 0x6B64, 0, 0x6B60, 0, 0x447C, 0x6B5F,
+ 0, 0, 0, 0x6B5D, 0xDE31, 0x4D21, 0x3B70, 0,
+ 0xDE32, 0x6B61, 0, 0x6B5E, 0xDE33, 0xDE34, 0xDE35, 0x6B65,
+ 0x3D74, 0, 0x3841, 0, 0xDE36, 0, 0x427A, 0xDE37,
+};
+const unsigned short utf8_to_euc_E8AC[] = {
+ 0x4B45, 0x315A, 0x3062, 0, 0x4625, 0xDE38, 0xDE39, 0x6B69,
+ 0, 0, 0xDE3F, 0xDE3A, 0x6B68, 0, 0x4666, 0,
+ 0x6B6D, 0xDE3B, 0, 0, 0x6B62, 0, 0x6B6C, 0x6B6E,
+ 0, 0x382C, 0x6B6A, 0x3956, 0xDE3C, 0x3C55, 0xDE3D, 0xDE3E,
+ 0x6B6F, 0x4D58, 0, 0, 0, 0, 0x6B72, 0,
+ 0x6B75, 0, 0, 0x6B73, 0x4935, 0xDE40, 0, 0,
+ 0xDE41, 0, 0, 0x6B70, 0, 0, 0, 0xDE42,
+ 0, 0x3660, 0, 0, 0xDE43, 0, 0x6B74, 0,
+};
+const unsigned short utf8_to_euc_E8AD[] = {
+ 0, 0x6B76, 0xDE44, 0xDE45, 0xDE46, 0xDE47, 0xDE48, 0,
+ 0xDE49, 0x6B7A, 0, 0, 0x6B77, 0xDE4E, 0x6B79, 0x6B78,
+ 0, 0, 0xDE4A, 0xDE4B, 0xDE4C, 0, 0x6B7B, 0,
+ 0x3C31, 0xDE4D, 0x6B7D, 0x6B7C, 0x4968, 0, 0xDE4F, 0x6C21,
+ 0, 0, 0, 0xDE50, 0, 0, 0x3759, 0,
+ 0, 0, 0, 0x6B7E, 0x6C22, 0xDE51, 0, 0x6C23,
+ 0x3544, 0x6641, 0x3E79, 0, 0x6C24, 0, 0xDE52, 0x386E,
+ 0xDE53, 0xDE54, 0, 0, 0xDE55, 0x6C25, 0xDE56, 0xF466,
+};
+const unsigned short utf8_to_euc_E8AE[] = {
+ 0x6C26, 0xDE57, 0, 0x3B3E, 0xDE58, 0xDE59, 0, 0,
+ 0, 0, 0x5A4E, 0xDE5A, 0x6C27, 0xDE5B, 0x6C28, 0xDE5C,
+ 0x3D32, 0, 0x6C29, 0x6C2A, 0xDE5D, 0xDE5E, 0x6C2B, 0,
+ 0, 0x6C2C, 0x6C2D, 0, 0xDE5F, 0, 0xDE60, 0xDE61,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E8B0[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x432B,
+ 0xDE62, 0xDE63, 0x6C2E, 0, 0, 0xDE64, 0xDE65, 0x6C30,
+};
+const unsigned short utf8_to_euc_E8B1[] = {
+ 0, 0x6C2F, 0, 0, 0, 0xDE66, 0x4626, 0xDE67,
+ 0x6C31, 0xDE68, 0x4B2D, 0xDE69, 0x6C32, 0, 0x6C33, 0xDE6A,
+ 0x6C34, 0xDE6B, 0, 0xDE6C, 0xDE6D, 0x6C35, 0, 0xDE6E,
+ 0xDE6F, 0xDE72, 0x465A, 0xDE70, 0, 0xDE71, 0, 0,
+ 0, 0x3E5D, 0x6C36, 0xDE73, 0xDE74, 0, 0xDE75, 0,
+ 0xDE76, 0xDE77, 0x396B, 0x502E, 0x6C37, 0xDE78, 0, 0,
+ 0, 0, 0, 0xDE79, 0, 0xDE7A, 0xDE7B, 0,
+ 0x6C38, 0x493F, 0x6C39, 0xDE7C, 0x6C41, 0, 0xDE7D, 0,
+};
+const unsigned short utf8_to_euc_E8B2[] = {
+ 0, 0, 0x6C3A, 0, 0, 0x6C3C, 0xDE7E, 0xDF21,
+ 0, 0x6C3B, 0x6C3D, 0xDF22, 0x4B46, 0x6C3E, 0x6C3F, 0,
+ 0xDF23, 0, 0xDF24, 0xDF25, 0x6C40, 0, 0, 0,
+ 0x6C42, 0xDF26, 0, 0xDF27, 0xDF28, 0x332D, 0x4467, 0,
+ 0x4969, 0x3A62, 0x3957, 0, 0xDF29, 0, 0, 0x494F,
+ 0x325F, 0x484E, 0x6C45, 0x3453, 0x4055, 0x6C44, 0x6C49, 0x4379,
+ 0x4C63, 0, 0x6C47, 0x6C48, 0x352E, 0, 0x6C4A, 0x4763,
+ 0x425F, 0xDF2A, 0xDF2B, 0x4871, 0x453D, 0x6C46, 0, 0x4B47,
+};
+const unsigned short utf8_to_euc_E8B3[] = {
+ 0x326C, 0x6C4C, 0x4F28, 0x4442, 0x4F45, 0xDF2C, 0xDF2D, 0x3B71,
+ 0x6C4B, 0xDF2E, 0x4231, 0xDF2F, 0, 0x6C5C, 0x4128, 0xDF30,
+ 0, 0x4678, 0, 0x4950, 0, 0xDF32, 0xDF31, 0,
+ 0, 0xDF33, 0x6C4F, 0x3B3F, 0x3B72, 0xDF34, 0x3E5E, 0,
+ 0x4765, 0xDF35, 0x382D, 0x6C4E, 0x6C4D, 0, 0x496A, 0,
+ 0xDF36, 0, 0x3C41, 0, 0xDF37, 0x4552, 0, 0xDF38,
+ 0xDF39, 0, 0xDF3A, 0, 0xF467, 0xDF3B, 0, 0xDF3C,
+ 0xDF3D, 0, 0x6C51, 0x6C52, 0x3958, 0x6C50, 0xDF3E, 0xDF3F,
+};
+const unsigned short utf8_to_euc_E8B4[] = {
+ 0, 0xDF40, 0, 0xDF41, 0x6C53, 0x6C54, 0, 0x6C56,
+ 0x4223, 0xDF42, 0x6C55, 0x3466, 0, 0x6C58, 0, 0x6C57,
+ 0x6C59, 0, 0xDF43, 0x6C5B, 0x6C5D, 0, 0x6C5E, 0xDF44,
+ 0, 0, 0, 0xDF45, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E8B5[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x4056, 0xDF46, 0x3C4F, 0x6C5F,
+ 0, 0xDF47, 0, 0x3352, 0xDF48, 0x6C60, 0xDF49, 0,
+ 0x4176, 0x6C61, 0, 0x6C62, 0x496B, 0, 0xF468, 0x352F,
+ 0, 0, 0, 0, 0, 0, 0, 0xDF4A,
+};
+const unsigned short utf8_to_euc_E8B6[] = {
+ 0, 0x6C63, 0xDF4B, 0, 0xDF4C, 0x4436, 0, 0,
+ 0xDF4D, 0, 0x315B, 0, 0, 0xDF4E, 0, 0,
+ 0xDF4F, 0xDF50, 0, 0, 0, 0xDF51, 0, 0,
+ 0, 0x6C64, 0, 0, 0, 0, 0xDF52, 0xDF53,
+ 0xDF54, 0, 0, 0x3C71, 0, 0, 0xDF55, 0,
+ 0x3F76, 0, 0, 0xDF56, 0xDF57, 0, 0, 0xDF58,
+ 0, 0, 0xDF59, 0x422D, 0, 0xDF5A, 0, 0xDF5B,
+ 0, 0xDF5C, 0x6C67, 0xDF5D, 0xDF6F, 0, 0x6C66, 0,
+};
+const unsigned short utf8_to_euc_E8B7[] = {
+ 0xDF5E, 0, 0x6C65, 0, 0, 0xDF5F, 0xDF60, 0xDF61,
+ 0xDF62, 0, 0xDF63, 0x6C6D, 0x6C6B, 0, 0xDF64, 0x6C68,
+ 0, 0xDF65, 0, 0, 0xDF66, 0xDF67, 0x6C6A, 0xDF68,
+ 0, 0xDF69, 0x6C69, 0x6C6C, 0, 0x3577, 0, 0x6C70,
+ 0, 0x4057, 0, 0x6C71, 0xDF6A, 0xDF6B, 0, 0xDF6C,
+ 0x3859, 0, 0x6C6E, 0x6C6F, 0xDF6D, 0, 0, 0x4F29,
+ 0xDF6E, 0xDF70, 0xDF71, 0x4437, 0xDF72, 0x4129, 0, 0,
+ 0, 0, 0, 0, 0x6C72, 0xDF73, 0, 0x6C75,
+};
+const unsigned short utf8_to_euc_E8B8[] = {
+ 0, 0xDF74, 0, 0, 0xDF75, 0xDF76, 0xDF77, 0,
+ 0x6C73, 0x6C74, 0x4D59, 0xDF78, 0, 0, 0, 0x4627,
+ 0x6C78, 0xDF79, 0, 0, 0xDF7A, 0, 0xDF7B, 0,
+ 0, 0, 0, 0, 0, 0x6C76, 0x6C77, 0x6C79,
+ 0xDF7C, 0xDF7D, 0xDF7E, 0xE021, 0, 0, 0xE022, 0xE023,
+ 0, 0, 0x6D29, 0, 0, 0, 0, 0,
+ 0x6C7C, 0xE024, 0, 0xE025, 0x6C7D, 0x6C7B, 0xE026, 0xE027,
+ 0xE028, 0xE029, 0, 0, 0, 0xE02A, 0, 0,
+};
+const unsigned short utf8_to_euc_E8B9[] = {
+ 0xE02B, 0xE02C, 0x6C7A, 0, 0x447D, 0, 0, 0x6D21,
+ 0x6D25, 0x6D22, 0x6C7E, 0xE02D, 0x6D23, 0xE02E, 0xE02F, 0xE030,
+ 0x6D24, 0, 0, 0, 0xE031, 0x6D2B, 0, 0,
+ 0, 0x6D26, 0, 0xE032, 0xE033, 0xE034, 0xE035, 0x4058,
+ 0x6D28, 0xE036, 0xE037, 0x6D2A, 0x6D27, 0, 0, 0,
+ 0, 0xE038, 0, 0, 0xE039, 0xE03A, 0, 0xE03B,
+ 0xE03C, 0xE03D, 0x6D2D, 0, 0x3D33, 0, 0x6D2C, 0,
+ 0, 0xE03E, 0xE03F, 0xE040, 0x6D2E, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E8BA[] = {
+ 0, 0x6D2F, 0xE041, 0xE042, 0x6D32, 0x6D31, 0, 0x6D30,
+ 0, 0xE043, 0x6D34, 0x6D33, 0, 0x4C76, 0, 0,
+ 0xE044, 0x6D36, 0xE045, 0x6D35, 0x6D37, 0xE046, 0, 0,
+ 0, 0x6D38, 0xE047, 0xE048, 0, 0xE049, 0xE04A, 0,
+ 0, 0x6D3A, 0xE04B, 0, 0, 0, 0, 0xE04C,
+ 0, 0xE04D, 0x6D39, 0x3F48, 0x6D3B, 0xE04E, 0xE04F, 0x366D,
+ 0x6D3C, 0x6D3E, 0, 0xE050, 0, 0xE051, 0, 0,
+ 0, 0, 0xE052, 0xE053, 0, 0, 0x6D3F, 0,
+};
+const unsigned short utf8_to_euc_E8BB[] = {
+ 0xE054, 0xE055, 0, 0xE056, 0xE057, 0x6D40, 0x6D3D, 0xE058,
+ 0x6D41, 0, 0x3C56, 0x6D42, 0x3530, 0x3733, 0, 0xE059,
+ 0, 0xE05A, 0x382E, 0, 0xE05B, 0, 0, 0,
+ 0, 0, 0, 0x6D43, 0xE05C, 0, 0, 0x4670,
+ 0, 0, 0x453E, 0x6D44, 0, 0, 0, 0,
+ 0xE05D, 0, 0, 0x6D47, 0, 0xE064, 0xE05E, 0,
+ 0xE05F, 0xE060, 0, 0, 0, 0, 0, 0xE061,
+ 0x3C34, 0xE062, 0xE063, 0x6D46, 0x6D45, 0x375A, 0x6D48, 0,
+};
+const unsigned short utf8_to_euc_E8BC[] = {
+ 0xE065, 0, 0xE066, 0x3353, 0, 0x6D4A, 0, 0xE067,
+ 0xE068, 0x3A5C, 0x6D49, 0, 0x6D52, 0, 0, 0xE069,
+ 0xE06A, 0, 0x6D4C, 0x6D4E, 0x4A65, 0x6D4B, 0xE06B, 0xE06C,
+ 0xE06D, 0x6D4D, 0, 0x6D51, 0x6D4F, 0x3531, 0xE06E, 0x6D50,
+ 0xE06F, 0xE070, 0, 0xE071, 0, 0xE072, 0x6D53, 0xE073,
+ 0xE074, 0x475A, 0x4E58, 0, 0xE075, 0xE076, 0xE077, 0x3D34,
+ 0, 0, 0, 0x6D54, 0xE078, 0xE079, 0xE07A, 0xE07B,
+ 0x4D22, 0x6D56, 0xE07C, 0x6D55, 0, 0, 0x6D59, 0x4D41,
+};
+const unsigned short utf8_to_euc_E8BD[] = {
+ 0xE07D, 0xE07E, 0x6D58, 0xE121, 0x336D, 0x6D57, 0x6D5C, 0xE122,
+ 0, 0x6D5B, 0, 0, 0x6D5A, 0x4532, 0x6D5D, 0xE123,
+ 0, 0xE124, 0xE125, 0xE126, 0xE127, 0xE128, 0, 0x6D5E,
+ 0xE129, 0, 0, 0, 0x6D5F, 0xE12A, 0xE12B, 0x396C,
+ 0, 0x3725, 0x6D60, 0x6D61, 0x6D62, 0xE12C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E8BE[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x3F49, 0x6D63, 0xE12D, 0x3C2D, 0x6D64,
+ 0xE12E, 0xE12F, 0, 0x6D65, 0xE130, 0xE131, 0xE132, 0x5221,
+ 0x517E, 0, 0, 0, 0, 0x6D66, 0x6570, 0x6D67,
+ 0x4324, 0x3F2B, 0x4740, 0, 0, 0xE133, 0xE134, 0x6D68,
+ 0xE135, 0, 0x4A55, 0x4454, 0x397E, 0, 0xE136, 0x4329,
+};
+const unsigned short utf8_to_euc_E8BF[] = {
+ 0xE137, 0xE138, 0x312A, 0, 0x4B78, 0x3F57, 0xE139, 0,
+ 0, 0, 0xE13A, 0xE13B, 0, 0xE13C, 0x375E, 0,
+ 0xE13D, 0x3661, 0xE13E, 0xE13F, 0x4A56, 0xE140, 0, 0,
+ 0, 0, 0x6D69, 0, 0, 0, 0, 0,
+ 0xE141, 0, 0x6D6B, 0xE142, 0xE143, 0x6D6A, 0x3260, 0,
+ 0xE144, 0x4676, 0x6D6C, 0x4777, 0, 0x4533, 0xE145, 0x6D6D,
+ 0x3D52, 0xE146, 0, 0, 0x6D6F, 0xE147, 0xE148, 0x4C42,
+ 0x6D7E, 0x6D71, 0x6D72, 0xE149, 0, 0x4449, 0xE14A, 0,
+};
+const unsigned short utf8_to_euc_E980[] = {
+ 0x4260, 0x4177, 0xE14B, 0x4628, 0xE14C, 0x6D70, 0x3555, 0,
+ 0xE14D, 0, 0, 0x6D79, 0xE14E, 0x6D76, 0x6E25, 0x4629,
+ 0x4360, 0x6D73, 0, 0x447E, 0x4553, 0x6D74, 0x6D78, 0x3F60,
+ 0xE14F, 0x4767, 0x444C, 0xE150, 0, 0x4042, 0x6D77, 0x422E,
+ 0x4224, 0x6D75, 0x3029, 0x4F22, 0, 0, 0, 0x6D7A,
+ 0xE151, 0xE152, 0xE154, 0, 0xE155, 0xE156, 0x4261, 0xE153,
+ 0, 0x3D35, 0x3F4A, 0xE157, 0xE158, 0x6D7C, 0x6D7B, 0xE159,
+ 0x306F, 0x6D7D, 0, 0, 0x492F, 0, 0x6E27, 0xE15A,
+};
+const unsigned short utf8_to_euc_E981[] = {
+ 0, 0x465B, 0x3F6B, 0xE15B, 0xE15C, 0x4359, 0, 0x3678,
+ 0, 0x6E26, 0x4D37, 0x313F, 0xE15D, 0x4A57, 0x3261, 0x6E21,
+ 0x6E22, 0x6E23, 0x6E24, 0x463B, 0x4323, 0x3063, 0x6E28, 0,
+ 0x6E29, 0x7423, 0, 0xE15E, 0x423D, 0xE15F, 0x6E2A, 0,
+ 0x3173, 0x414C, 0xE160, 0x382F, 0, 0x4D5A, 0xE161, 0xE162,
+ 0x6E2B, 0x452C, 0, 0, 0xE163, 0x4178, 0x3C57, 0x6E2C,
+ 0xE164, 0, 0x6E2F, 0, 0xE165, 0x3D65, 0x6E2D, 0x412B,
+ 0x412A, 0xE166, 0x3064, 0, 0x4E4B, 0x6E31, 0, 0x4872,
+};
+const unsigned short utf8_to_euc_E982[] = {
+ 0x6E33, 0x6E32, 0x6E30, 0x6364, 0x3454, 0xE167, 0, 0x6D6E,
+ 0xE168, 0x6E35, 0x6E34, 0xE169, 0xE16A, 0, 0xE16B, 0x6E36,
+ 0xE16C, 0x4D38, 0, 0, 0, 0xE16D, 0, 0xE16E,
+ 0xE16F, 0xE170, 0, 0xE171, 0, 0, 0, 0,
+ 0xE172, 0xE173, 0xE174, 0x4661, 0, 0xE175, 0x4B2E, 0,
+ 0x6E37, 0, 0x3C59, 0, 0, 0, 0, 0x6E38,
+ 0xE176, 0x6E39, 0xE177, 0xE178, 0xE179, 0x6E3A, 0xE17A, 0,
+ 0x4521, 0, 0, 0, 0, 0xE17B, 0xE17D, 0,
+};
+const unsigned short utf8_to_euc_E983[] = {
+ 0, 0x306A, 0, 0xE17E, 0xE221, 0xE222, 0, 0xE223,
+ 0xE224, 0, 0x3959, 0, 0xE17C, 0, 0x4F3A, 0,
+ 0, 0, 0xE22D, 0, 0, 0xE225, 0, 0xE226,
+ 0xE227, 0xE228, 0, 0x6E3E, 0xE229, 0xE22A, 0xF46C, 0xE22B,
+ 0, 0x3734, 0x6E3B, 0, 0x6E3C, 0xE22C, 0, 0,
+ 0x4974, 0, 0, 0xE22F, 0, 0x3354, 0, 0xE230,
+ 0xE231, 0, 0, 0, 0xE232, 0x4D39, 0xE22E, 0x363F,
+ 0, 0, 0, 0, 0, 0x4554, 0xE233, 0xE234,
+};
+const unsigned short utf8_to_euc_E984[] = {
+ 0xE235, 0, 0x6E3F, 0, 0xE236, 0xE237, 0xE238, 0,
+ 0xE239, 0, 0, 0, 0, 0xE23A, 0, 0,
+ 0xE23B, 0, 0x6E40, 0, 0xE23C, 0xF46E, 0xE23D, 0xE23E,
+ 0xE23F, 0x6E41, 0xE240, 0, 0xE241, 0, 0xE242, 0,
+ 0xE243, 0, 0xE245, 0xE246, 0, 0xE244, 0, 0xE247,
+ 0, 0xE248, 0, 0, 0, 0x4522, 0xE249, 0xE24A,
+ 0x6E43, 0xE24B, 0x6E42, 0, 0xE24C, 0, 0xE24D, 0xE24E,
+ 0, 0xE24F, 0xE250, 0, 0xE251, 0xE252, 0, 0,
+};
+const unsigned short utf8_to_euc_E985[] = {
+ 0, 0, 0, 0xE253, 0, 0, 0, 0xE254,
+ 0xE255, 0x4653, 0x6E44, 0x3D36, 0x3C60, 0x475B, 0x4371, 0xE256,
+ 0, 0, 0x3C72, 0xE257, 0x3F6C, 0, 0x6E45, 0xE258,
+ 0x6E46, 0xE259, 0xE25A, 0xE25B, 0, 0, 0, 0,
+ 0, 0xE25C, 0x3F5D, 0x6E47, 0xE25D, 0x6E48, 0, 0xE25E,
+ 0, 0x6E49, 0x4D6F, 0, 0x3D37, 0xE25F, 0, 0,
+ 0, 0, 0x6E4B, 0x6E4A, 0xE260, 0x395A, 0, 0x3973,
+ 0x3B40, 0xE261, 0xE262, 0xE263, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E986[] = {
+ 0, 0xE264, 0x6E4E, 0xE265, 0, 0xE266, 0xE267, 0x3D66,
+ 0, 0x6E4D, 0xE268, 0x6E4C, 0, 0x4269, 0xE269, 0,
+ 0x386F, 0xE26A, 0x4043, 0xE26B, 0xE26C, 0xE26D, 0, 0x4830,
+ 0xE26E, 0, 0, 0, 0x3D39, 0, 0xE26F, 0,
+ 0, 0xE270, 0x6E4F, 0, 0x3E5F, 0, 0xE271, 0,
+ 0xE272, 0, 0x6E52, 0x6E50, 0xE273, 0xE274, 0xE275, 0x6E51,
+ 0xE276, 0xE277, 0xE278, 0xE279, 0x6E54, 0x6E53, 0xE27A, 0,
+ 0x3E7A, 0, 0x6E55, 0xE27B, 0xE27C, 0xE27D, 0, 0xE27E,
+};
+const unsigned short utf8_to_euc_E987[] = {
+ 0x6E56, 0x6E57, 0xE321, 0xE322, 0, 0xE323, 0x4850, 0x3A53,
+ 0x3C61, 0x6E58, 0, 0x6E59, 0x4E24, 0x3D45, 0x4C6E, 0x4E4C,
+ 0x6E5A, 0x3662, 0, 0xE324, 0xE325, 0, 0x6E5B, 0xE326,
+ 0x4523, 0xE327, 0xE328, 0x6E5E, 0x3378, 0x3F4B, 0xE329, 0x6E5C,
+ 0, 0x6E5D, 0, 0x4460, 0xE32A, 0xE32B, 0x4B55, 0x367C,
+ 0, 0xE32C, 0xE32D, 0, 0xE32E, 0xE32F, 0xE330, 0xE331,
+ 0xE332, 0xE333, 0, 0, 0, 0x6E60, 0x6E61, 0xE334,
+ 0, 0xE335, 0, 0xE336, 0x6E5F, 0xE337, 0, 0x6E63,
+};
+const unsigned short utf8_to_euc_E988[] = {
+ 0xE338, 0xE339, 0, 0, 0xE33A, 0xE33B, 0xE33C, 0xE33D,
+ 0, 0xE33E, 0xE33F, 0, 0xE340, 0x465F, 0x3343, 0,
+ 0xE341, 0x6E67, 0xE342, 0xE343, 0x6E64, 0x6E66, 0xE344, 0,
+ 0xE345, 0, 0, 0, 0xE346, 0xE347, 0x6E62, 0,
+ 0, 0, 0, 0xE348, 0xE349, 0xE34A, 0xE34B, 0,
+ 0xE34C, 0x6F4F, 0, 0, 0x6E65, 0, 0xE34D, 0xE34E,
+ 0xE34F, 0, 0, 0xE350, 0x4E6B, 0xE351, 0xE352, 0x385A,
+ 0xE353, 0xE354, 0xE355, 0, 0xE356, 0, 0xE357, 0x6E6F,
+};
+const unsigned short utf8_to_euc_E989[] = {
+ 0xE358, 0, 0xE359, 0xE35A, 0x4534, 0x6E6A, 0xE35B, 0xE35C,
+ 0x6E6D, 0x6E6B, 0xE35D, 0x6E70, 0, 0xE35E, 0xE35F, 0xE360,
+ 0x6E71, 0xE361, 0, 0, 0, 0, 0, 0x6E69,
+ 0xE362, 0xE363, 0x6E76, 0x3174, 0xE364, 0xE365, 0x6E68, 0,
+ 0xE366, 0xE367, 0x482D, 0, 0x6E6C, 0xE368, 0x3E60, 0xE369,
+ 0xE36A, 0xE36B, 0, 0, 0, 0, 0xE36C, 0xE36D,
+ 0xE36E, 0x395B, 0, 0, 0, 0xE36F, 0xE370, 0xE371,
+ 0xE372, 0xE373, 0, 0xE374, 0xE375, 0xE376, 0x4B48, 0xE377,
+};
+const unsigned short utf8_to_euc_E98A[] = {
+ 0x3664, 0, 0, 0x3D46, 0, 0x463C, 0, 0,
+ 0xE378, 0xE379, 0xE37A, 0, 0, 0xE37B, 0xE37C, 0,
+ 0, 0x412D, 0xE37D, 0x6E74, 0, 0x6E6E, 0x6E73, 0xE37E,
+ 0x4C43, 0xE421, 0x4438, 0x6E75, 0x6E72, 0, 0, 0xE422,
+ 0xE423, 0, 0, 0, 0xE424, 0xE425, 0, 0xE426,
+ 0xE427, 0, 0, 0xE428, 0, 0x412C, 0, 0xE429,
+ 0, 0, 0xE42A, 0, 0, 0, 0xE42B, 0x6E79,
+ 0xE42C, 0x6E78, 0xE42D, 0xE42E, 0xE42F, 0xE430, 0, 0xE431,
+};
+const unsigned short utf8_to_euc_E98B[] = {
+ 0xE432, 0xE433, 0xE434, 0xE435, 0, 0xE436, 0xE437, 0xE438,
+ 0xE439, 0, 0, 0xE43A, 0xE43B, 0xE43C, 0xE43D, 0x6E77,
+ 0xE43E, 0, 0x4B2F, 0xE43F, 0, 0xE440, 0, 0xE441,
+ 0xE442, 0xE443, 0, 0, 0xE444, 0xE445, 0, 0xE446,
+ 0xE447, 0xE448, 0, 0xE449, 0x3D7B, 0xE44A, 0, 0xE44B,
+ 0xE44C, 0x6E7A, 0x4A5F, 0, 0xE44D, 0x3154, 0xE44E, 0,
+ 0xE44F, 0, 0x4946, 0x4372, 0, 0, 0, 0,
+ 0x3578, 0xE450, 0x6E7C, 0xE451, 0x395D, 0, 0, 0xE452,
+};
+const unsigned short utf8_to_euc_E98C[] = {
+ 0xE453, 0, 0xE454, 0, 0, 0, 0x3B2C, 0,
+ 0xE455, 0, 0, 0, 0, 0xE456, 0, 0x6E7B,
+ 0x3F6D, 0xE457, 0, 0, 0xE458, 0xE459, 0, 0,
+ 0x3F6E, 0x6F21, 0x6F23, 0, 0xE45A, 0xE45B, 0xE45C, 0xE45D,
+ 0x3E7B, 0xE45E, 0x6F22, 0x6F24, 0xE45F, 0xE460, 0x3653, 0xE461,
+ 0x4945, 0xE462, 0xE463, 0x3C62, 0x4F23, 0, 0x6E7E, 0x3A78,
+ 0, 0, 0x4F3F, 0xE464, 0xE465, 0x6F26, 0xE466, 0xE467,
+ 0, 0, 0x6F25, 0x6F27, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E98D[] = {
+ 0, 0, 0, 0, 0x6E7D, 0, 0, 0xE468,
+ 0xE469, 0xE46A, 0, 0x4669, 0, 0x4555, 0, 0,
+ 0xE46B, 0xE46C, 0xE46D, 0, 0x4457, 0xE46E, 0x6F2C, 0xE46F,
+ 0xE470, 0, 0xE471, 0x4343, 0x6F28, 0, 0xE472, 0,
+ 0x6F29, 0, 0, 0, 0xE473, 0xE474, 0, 0xE475,
+ 0, 0xE476, 0xE477, 0, 0x372D, 0xE478, 0x6F2B, 0xE479,
+ 0xE47A, 0xE47B, 0, 0xE47C, 0xE47D, 0x3830, 0xE47E, 0,
+ 0, 0, 0xE521, 0, 0x6F2A, 0xE522, 0x3E61, 0xE523,
+};
+const unsigned short utf8_to_euc_E98E[] = {
+ 0xE524, 0xE525, 0xE526, 0, 0, 0, 0, 0,
+ 0xE527, 0, 0xE528, 0xE529, 0x3379, 0xE52A, 0, 0xE52B,
+ 0, 0, 0xE52C, 0, 0x6F30, 0xE52D, 0x3A3F, 0x4179,
+ 0xE52E, 0, 0x444A, 0xE52F, 0, 0, 0xE530, 0,
+ 0, 0xE531, 0, 0xE532, 0xE533, 0, 0xE534, 0x333B,
+ 0xE535, 0xE53B, 0, 0xE536, 0x6F2E, 0x6F2F, 0x4443, 0,
+ 0x6F2D, 0, 0, 0, 0xE537, 0xE538, 0xE539, 0,
+ 0, 0x6F31, 0xE53A, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E98F[] = {
+ 0, 0xE53C, 0, 0x6F37, 0xE53D, 0xE53E, 0xE53F, 0xE540,
+ 0x6F3A, 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0, 0,
+ 0x6F39, 0x452D, 0, 0xE546, 0, 0, 0x6F32, 0x6F33,
+ 0x6F36, 0xE547, 0, 0, 0xE548, 0x6F38, 0xE549, 0xE54A,
+ 0, 0x3640, 0xE54B, 0, 0x6F3B, 0x6F35, 0xE54C, 0xE54D,
+ 0x6F34, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xE54F,
+ 0xE550, 0xE54E, 0xE551, 0xE552, 0, 0xE553, 0, 0,
+};
+const unsigned short utf8_to_euc_E990[] = {
+ 0, 0xE554, 0xE555, 0x6F3F, 0xE556, 0, 0, 0x6F40,
+ 0xE557, 0xE558, 0, 0, 0, 0xE559, 0xE55A, 0xE55B,
+ 0x6F41, 0, 0, 0x6F3E, 0x6F3D, 0xE55C, 0xE55D, 0xE55E,
+ 0x3E62, 0x462A, 0x6F3C, 0, 0, 0, 0, 0xE55F,
+ 0, 0x6F45, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x6F43, 0, 0, 0xE560, 0xE561,
+ 0, 0xE562, 0xE563, 0xE564, 0xE565, 0x6F44, 0x6F42, 0,
+ 0x4278, 0, 0x6F46, 0xE566, 0, 0xE568, 0, 0xE567,
+};
+const unsigned short utf8_to_euc_E991[] = {
+ 0, 0x6F47, 0, 0xE569, 0x6F49, 0xE56A, 0, 0,
+ 0xE56B, 0, 0xE56C, 0, 0xE56D, 0, 0, 0,
+ 0, 0x3455, 0x6F48, 0x4C7A, 0, 0xE56E, 0, 0,
+ 0, 0xE56F, 0x6F54, 0x6F4A, 0xE570, 0, 0x6F4D, 0xE571,
+ 0x6F4B, 0xE572, 0x6F4C, 0xE573, 0, 0, 0, 0,
+ 0xE574, 0, 0x6F4E, 0xE575, 0, 0xE576, 0xE577, 0xE578,
+ 0x6F50, 0xE579, 0xE57A, 0, 0, 0x6F51, 0, 0x6F52,
+ 0, 0, 0, 0, 0x6F55, 0x6F53, 0x6F56, 0x6F58,
+};
+const unsigned short utf8_to_euc_E992[] = {
+ 0, 0x6F57, 0, 0xE57C, 0xE57B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E995[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x4439,
+ 0xE57D, 0xE57E, 0, 0, 0, 0, 0xE621, 0,
+};
+const unsigned short utf8_to_euc_E996[] = {
+ 0x4C67, 0, 0x6F59, 0x412E, 0xE622, 0, 0, 0x6F5A,
+ 0xE623, 0x4A44, 0x6F5B, 0x332B, 0xE624, 0xE625, 0xE626, 0x313C,
+ 0, 0x3457, 0xF471, 0x3456, 0x6F5C, 0, 0x6F5D, 0,
+ 0x6F5E, 0x6F5F, 0, 0, 0, 0xE627, 0xE628, 0xE629,
+ 0x6F60, 0xE62A, 0x3458, 0x3355, 0x395E, 0x4836, 0xE62B, 0x6F62,
+ 0x6F61, 0xE62C, 0, 0xE62D, 0xE62E, 0x6F63, 0, 0,
+ 0, 0, 0x315C, 0, 0xE62F, 0, 0xE630, 0,
+ 0, 0x6F66, 0xE631, 0x6F65, 0x6F64, 0xE632, 0x6F67, 0xE633,
+};
+const unsigned short utf8_to_euc_E997[] = {
+ 0, 0, 0, 0x6F6A, 0, 0, 0xE634, 0x3047,
+ 0xE635, 0xE636, 0x6F68, 0xE637, 0x6F6C, 0x6F6B, 0, 0,
+ 0xE638, 0xE639, 0xE63A, 0xE63B, 0x6F6E, 0x6F6D, 0x6F6F, 0,
+ 0x462E, 0xE63C, 0xE63D, 0, 0x6F70, 0xE63E, 0xE63F, 0xE640,
+ 0xE641, 0x6F71, 0x6F73, 0, 0xE642, 0x6F72, 0xE643, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E998[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x496C, 0xE644, 0xE645, 0,
+ 0, 0x6F74, 0xE646, 0, 0xE647, 0xE648, 0xE649, 0,
+ 0x6F75, 0, 0x3A65, 0, 0xE64A, 0, 0x6F76, 0x6F77,
+ 0, 0xE64B, 0x4B49, 0xE64C, 0, 0, 0, 0xE64D,
+ 0xE64E, 0xE64F, 0xE650, 0x414B, 0xE651, 0xE652, 0, 0x3024,
+};
+const unsigned short utf8_to_euc_E999[] = {
+ 0x424B, 0xE653, 0x6F78, 0, 0x496D, 0, 0, 0,
+ 0, 0, 0, 0x6F7B, 0x6F79, 0x395F, 0, 0x6F7A,
+ 0x3842, 0, 0xE654, 0, 0xE655, 0, 0xE656, 0xE657,
+ 0xE658, 0, 0, 0x4A45, 0x6F7D, 0x7021, 0x6F7E, 0x7022,
+ 0, 0xE659, 0x3121, 0x3F58, 0x3D7C, 0x3459, 0x7023, 0,
+ 0, 0, 0x4766, 0, 0x7025, 0, 0xE65A, 0,
+ 0x3122, 0, 0x7024, 0x4444, 0xE65B, 0x4E4D, 0x462B, 0x6F7C,
+ 0x4E26, 0, 0x3831, 0xE65C, 0xE65D, 0x4D5B, 0xE65E, 0xE65F,
+};
+const unsigned short utf8_to_euc_E99A[] = {
+ 0, 0xE660, 0xE661, 0xE662, 0xE663, 0x3679, 0x4E34, 0,
+ 0x3728, 0xE664, 0x4262, 0x6721, 0, 0x7026, 0x332C, 0x3F6F,
+ 0, 0xE665, 0, 0, 0x3356, 0x7028, 0xE666, 0x7029,
+ 0x7027, 0x3764, 0xE667, 0x3A5D, 0x3E63, 0xE668, 0, 0xE669,
+ 0x3123, 0, 0, 0x4E59, 0xE66A, 0xE66B, 0xE66C, 0x702B,
+ 0x6E2E, 0xE66D, 0x702A, 0, 0, 0, 0xE66E, 0xE66F,
+ 0x702E, 0x702C, 0x702D, 0xE670, 0x702F, 0, 0x7030, 0x4E6C,
+ 0x7031, 0x7032, 0xE671, 0x4049, 0x483B, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E99B[] = {
+ 0x3F7D, 0x3467, 0, 0, 0x4D3A, 0x326D, 0x3D38, 0x385B,
+ 0, 0x7035, 0xE672, 0x7034, 0x3B73, 0x7036, 0x7033, 0,
+ 0, 0x3B28, 0xE673, 0, 0, 0x703A, 0x6A2D, 0,
+ 0xE675, 0x5256, 0xE676, 0x3F77, 0x7038, 0xE677, 0xE678, 0xE679,
+ 0, 0, 0x4E25, 0x4671, 0, 0, 0, 0,
+ 0x312B, 0xE67A, 0x4063, 0x3C36, 0, 0, 0, 0xE67B,
+ 0x4A37, 0xE67C, 0x3140, 0, 0, 0, 0x4E6D, 0x4D6B,
+ 0, 0x703B, 0xE67D, 0x4545, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E99C[] = {
+ 0x3C7B, 0, 0xE67E, 0xE721, 0x703C, 0xE722, 0x703D, 0x3F4C,
+ 0x703E, 0xE723, 0x4E6E, 0, 0, 0x7039, 0x7040, 0x7042,
+ 0, 0x7041, 0, 0x703F, 0, 0, 0x7043, 0,
+ 0, 0x7044, 0xE724, 0xE725, 0x417A, 0xE726, 0x3262, 0,
+ 0, 0xE727, 0xE728, 0xE729, 0x7045, 0, 0, 0x4C38,
+ 0xE72A, 0, 0x7046, 0, 0, 0, 0, 0,
+ 0x7047, 0xE72B, 0x4F2A, 0xE72C, 0, 0, 0, 0,
+ 0x5B31, 0x7048, 0, 0xF474, 0, 0x7049, 0x704A, 0,
+};
+const unsigned short utf8_to_euc_E99D[] = {
+ 0, 0xE72D, 0x704E, 0xE72E, 0x704B, 0, 0x704C, 0,
+ 0x704D, 0x704F, 0xE72F, 0, 0, 0xF475, 0xE730, 0xE731,
+ 0, 0xF476, 0x4044, 0, 0, 0xE732, 0x4C77, 0xE733,
+ 0xE734, 0x4045, 0xE735, 0xE736, 0x7050, 0, 0x4873, 0,
+ 0x7051, 0x7353, 0x4C4C, 0xE737, 0x7052, 0, 0x7053, 0xE738,
+ 0x7054, 0x3357, 0xE739, 0x7056, 0, 0x3F59, 0xE73A, 0,
+ 0, 0x7057, 0, 0xE73B, 0x3724, 0, 0xE73C, 0xE73D,
+ 0xE73E, 0x7058, 0x705C, 0xE73F, 0x705A, 0xE740, 0, 0xE741,
+};
+const unsigned short utf8_to_euc_E99E[] = {
+ 0xE742, 0x705B, 0, 0, 0x3373, 0x7059, 0x705D, 0,
+ 0, 0xE743, 0, 0x705E, 0, 0x3048, 0, 0x705F,
+ 0x7060, 0, 0, 0, 0, 0xE744, 0xE745, 0xE746,
+ 0x3E64, 0xE747, 0xE748, 0, 0x7061, 0, 0xE749, 0xE74A,
+ 0x3547, 0, 0xE74B, 0x7064, 0, 0, 0x7063, 0,
+ 0x7062, 0, 0, 0x6B71, 0xE74C, 0x4A5C, 0xE74D, 0,
+ 0, 0xE74E, 0xE74F, 0x7065, 0x7066, 0xE750, 0xE751, 0,
+ 0xE752, 0xE753, 0xE754, 0, 0xE755, 0, 0xE756, 0xE757,
+};
+const unsigned short utf8_to_euc_E99F[] = {
+ 0, 0xE758, 0, 0x7067, 0xE759, 0xE75A, 0x7068, 0xE75B,
+ 0x7069, 0xE75C, 0xE75D, 0x706A, 0xE75E, 0xE75F, 0xE760, 0,
+ 0xE761, 0xE762, 0, 0x345A, 0xE763, 0, 0, 0xE764,
+ 0xE765, 0xE766, 0, 0xE76A, 0x706B, 0xE767, 0xE768, 0,
+ 0xE769, 0xE76B, 0, 0, 0xE76C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x706C, 0x4723, 0xE76D,
+ 0, 0xE76E, 0x706E, 0x323B, 0xE76F, 0x7071, 0x7070, 0xE770,
+ 0xE771, 0, 0xE772, 0x3124, 0, 0, 0, 0x3641,
+};
+const unsigned short utf8_to_euc_E9A0[] = {
+ 0, 0x4A47, 0x443A, 0x3A22, 0, 0x3960, 0x3D67, 0xE773,
+ 0x3F5C, 0, 0xE774, 0, 0x7073, 0xE776, 0xE777, 0x7072,
+ 0x4D42, 0x3468, 0x4852, 0x465C, 0xE778, 0, 0xE779, 0x3F7C,
+ 0x4E4E, 0xE775, 0x375B, 0, 0xE77A, 0, 0xE77B, 0,
+ 0xE77C, 0x7076, 0, 0xE77D, 0x7075, 0xE828, 0xE77E, 0,
+ 0, 0, 0, 0xE821, 0x4B4B, 0x462C, 0xE822, 0xE823,
+ 0xE824, 0, 0xE825, 0xE826, 0x3150, 0xE827, 0, 0x7077,
+ 0x7074, 0, 0, 0x4951, 0x4D6A, 0x7078, 0xE829, 0,
+};
+const unsigned short utf8_to_euc_E9A1[] = {
+ 0, 0, 0, 0, 0xE82A, 0, 0x7079, 0xE82B,
+ 0, 0, 0xE82C, 0x707B, 0x426A, 0x335B, 0x335C, 0x707A,
+ 0, 0xE82D, 0xE82E, 0xE82F, 0x3469, 0x3832, 0xE830, 0xE831,
+ 0x346A, 0xE832, 0xE833, 0x453F, 0, 0, 0x4E60, 0,
+ 0, 0, 0xE834, 0xE835, 0, 0xE836, 0xE837, 0x385C,
+ 0, 0, 0xE838, 0x707C, 0xE839, 0, 0, 0x707D,
+ 0x707E, 0x7121, 0, 0x7123, 0x7122, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E9A2[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x4977, 0, 0x7124, 0xE83A, 0, 0xE83B, 0xE83C, 0x7125,
+ 0xE83D, 0x7126, 0, 0, 0xE83E, 0, 0x7127, 0xE83F,
+ 0xE840, 0, 0xE841, 0xE842, 0, 0, 0, 0xE843,
+};
+const unsigned short utf8_to_euc_E9A3[] = {
+ 0, 0, 0xE844, 0x7129, 0x7128, 0xE845, 0x712A, 0,
+ 0xE846, 0, 0, 0, 0xE847, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0x4874, 0x664C, 0, 0, 0x3F29,
+ 0, 0xE848, 0x3532, 0xE849, 0, 0xE84A, 0xE84B, 0xE84C,
+ 0, 0x712B, 0xE84D, 0x712C, 0, 0x522C, 0x5D3B, 0x4853,
+ 0, 0, 0x307B, 0xE84E, 0x303B, 0, 0xE84F, 0,
+ 0, 0, 0, 0, 0x3B74, 0x4B30, 0x3E7E, 0,
+};
+const unsigned short utf8_to_euc_E9A4[] = {
+ 0, 0, 0xE850, 0x712D, 0, 0x4C5F, 0, 0xE851,
+ 0xE852, 0x712E, 0x4D5C, 0, 0x3142, 0, 0, 0,
+ 0x3B41, 0xE853, 0x712F, 0x326E, 0x7130, 0xE854, 0xE855, 0xE856,
+ 0x7131, 0, 0xE857, 0xE858, 0xE859, 0x7133, 0x7134, 0xE85A,
+ 0x7136, 0x7132, 0xE85B, 0, 0x7135, 0, 0xE85C, 0xE85D,
+ 0x345B, 0, 0, 0xE85E, 0x7137, 0, 0x7138, 0,
+ 0, 0xE85F, 0xE860, 0xE861, 0xE862, 0xE863, 0, 0,
+ 0, 0xE864, 0xE865, 0xE866, 0xE867, 0x7139, 0x713A, 0,
+};
+const unsigned short utf8_to_euc_E9A5[] = {
+ 0xE868, 0xE869, 0x713B, 0, 0, 0x713D, 0xE86A, 0xE86B,
+ 0xE86C, 0x713C, 0, 0x713F, 0x7142, 0xE86D, 0xE86E, 0,
+ 0x713E, 0x7140, 0x7141, 0, 0xE86F, 0x7143, 0, 0x3642,
+ 0xE870, 0xE871, 0, 0xE872, 0xE873, 0, 0xE874, 0xE875,
+ 0xE876, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E9A6[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x3C73, 0x7144,
+ 0x7145, 0x3961, 0, 0xE877, 0, 0xE878, 0xF47A, 0xE879,
+ 0, 0, 0, 0, 0, 0x7146, 0xE87A, 0,
+ 0x333E, 0, 0, 0, 0x474F, 0x7147, 0x7148, 0,
+ 0xE87B, 0xE87C, 0xE87D, 0x435A, 0x466B, 0xE87E, 0, 0,
+ 0, 0xE921, 0xE922, 0, 0x7149, 0xE923, 0, 0xE924,
+};
+const unsigned short utf8_to_euc_E9A7[] = {
+ 0, 0x477D, 0, 0xE925, 0x424C, 0x3158, 0x366E, 0,
+ 0x366F, 0xE926, 0, 0, 0, 0, 0, 0,
+ 0x4373, 0x714E, 0x3670, 0xE927, 0xE928, 0x326F, 0, 0,
+ 0x714D, 0xE929, 0xE92A, 0x714B, 0xE92B, 0x714C, 0xE92C, 0x714A,
+ 0, 0, 0x7158, 0, 0, 0, 0, 0xE92D,
+ 0, 0, 0xE92E, 0xE92F, 0xE930, 0x714F, 0x7150, 0,
+ 0xE931, 0x7151, 0x7152, 0, 0xE932, 0xE933, 0, 0,
+ 0x7154, 0xE934, 0, 0x7153, 0, 0xE935, 0xE936, 0x3D59,
+};
+const unsigned short utf8_to_euc_E9A8[] = {
+ 0, 0x7155, 0xE937, 0xE938, 0xE939, 0x7157, 0, 0,
+ 0, 0, 0, 0xE93A, 0xE93B, 0, 0x3533, 0x7156,
+ 0xE93C, 0xE93D, 0x417B, 0x3833, 0, 0, 0xE93E, 0,
+ 0, 0x7159, 0, 0, 0, 0, 0xE93F, 0,
+ 0xE940, 0, 0xE941, 0xE942, 0xE943, 0, 0, 0xE944,
+ 0x424D, 0, 0, 0x715A, 0, 0xE945, 0xE946, 0,
+ 0x462D, 0, 0, 0xE947, 0, 0xE948, 0xE949, 0x715B,
+ 0xE94A, 0, 0, 0, 0, 0, 0x7160, 0,
+};
+const unsigned short utf8_to_euc_E9A9[] = {
+ 0x715E, 0xE94C, 0x715D, 0x715F, 0xE94D, 0x715C, 0, 0xE94B,
+ 0, 0, 0xE94E, 0xE94F, 0xE950, 0x7162, 0xE951, 0,
+ 0, 0xE952, 0, 0, 0xE953, 0x7161, 0xE954, 0x7164,
+ 0, 0, 0x3643, 0x7163, 0, 0xE955, 0, 0x7165,
+ 0, 0, 0x7166, 0, 0x7168, 0x7167, 0, 0,
+ 0, 0x7169, 0x716B, 0x716A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E9AA[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x397C, 0, 0xE956, 0, 0xE957, 0x716C, 0xE958, 0xE959,
+ 0x716D, 0, 0xE95A, 0, 0xE95B, 0xE95C, 0xE95D, 0,
+ 0x333C, 0xE95E, 0, 0xE95F, 0x716E, 0, 0xE960, 0xE961,
+};
+const unsigned short utf8_to_euc_E9AB[] = {
+ 0x716F, 0xE962, 0, 0xE963, 0x3F71, 0, 0xE964, 0,
+ 0xE965, 0, 0, 0, 0, 0, 0xE966, 0x7170,
+ 0xE967, 0x7171, 0xE968, 0x7172, 0x7173, 0xE969, 0xE96A, 0xE96B,
+ 0x3962, 0xF47B, 0, 0xE96C, 0xE96D, 0, 0x7174, 0x7175,
+ 0xE96E, 0, 0x7176, 0x7177, 0xE96F, 0xE970, 0x7178, 0xE971,
+ 0, 0xE972, 0x4831, 0x717A, 0xE973, 0x4926, 0x717B, 0x7179,
+ 0, 0x717D, 0xE974, 0xE975, 0x717C, 0xE976, 0, 0x717E,
+ 0, 0xE977, 0xE978, 0x7221, 0, 0xE979, 0, 0xE97A,
+};
+const unsigned short utf8_to_euc_E9AC[] = {
+ 0xE97B, 0xE97C, 0xE97D, 0xE97E, 0xEA21, 0xEA22, 0x7222, 0,
+ 0xEA23, 0xEA24, 0, 0xEA25, 0xEA26, 0xEA27, 0xEA28, 0,
+ 0xEA29, 0, 0xEA2A, 0, 0, 0, 0xEA2B, 0,
+ 0x7223, 0xEA2C, 0x7224, 0xEA2D, 0xEA2E, 0, 0, 0x7225,
+ 0xEA2F, 0, 0x7226, 0x7227, 0, 0x7228, 0xEA30, 0x7229,
+ 0x722A, 0x722B, 0x722C, 0xEA31, 0, 0xEA32, 0x722D, 0x722E,
+ 0, 0x5D35, 0x722F, 0xEA33, 0xEA34, 0xEA35, 0, 0xEA36,
+ 0, 0xEA37, 0xEA38, 0x6478, 0x3534, 0xEA39, 0, 0,
+};
+const unsigned short utf8_to_euc_E9AD[] = {
+ 0, 0x3321, 0x3A32, 0x7231, 0x7230, 0x4C25, 0, 0,
+ 0xEA3A, 0, 0, 0xEA3B, 0xEA3C, 0x7233, 0x7234, 0x7232,
+ 0, 0x7235, 0, 0, 0x4B62, 0xEA3D, 0xEA3E, 0xEA3F,
+ 0x7236, 0, 0x357B, 0xEA40, 0, 0, 0xEA41, 0,
+ 0, 0xEA42, 0, 0xEA43, 0, 0xEA44, 0xEA45, 0,
+ 0xEA46, 0, 0xEA47, 0xEA48, 0xEA49, 0xEA4A, 0xEA4B, 0x4F25,
+ 0, 0, 0xF47C, 0xEA4C, 0x7237, 0xEA4D, 0, 0xEA4E,
+ 0xEA4F, 0xEA50, 0, 0, 0, 0, 0, 0xEA51,
+};
+const unsigned short utf8_to_euc_E9AE[] = {
+ 0xEA52, 0, 0, 0x7239, 0xEA53, 0xEA54, 0xEA55, 0xEA56,
+ 0, 0xEA57, 0xEA58, 0xEA59, 0, 0xEA5A, 0x303E, 0xEA5B,
+ 0xEA5C, 0x723A, 0x4A2B, 0x7238, 0xEA5D, 0, 0x723B, 0x723C,
+ 0, 0, 0xEA5E, 0, 0, 0xEA5F, 0xEA60, 0x723D,
+ 0x723E, 0, 0, 0, 0, 0, 0xEA61, 0xEA62,
+ 0x723F, 0xEA63, 0x4B6E, 0x3B2D, 0xEA64, 0x3A7A, 0x412F, 0,
+ 0xEA65, 0xEA66, 0xEA67, 0, 0x7240, 0, 0, 0xEA68,
+ 0xEA69, 0x7243, 0, 0xEA6A, 0xEA6B, 0, 0xEA6C, 0xEA6D,
+};
+const unsigned short utf8_to_euc_E9AF[] = {
+ 0x7241, 0xEA6E, 0, 0, 0, 0, 0x7244, 0xEA6F,
+ 0xEA70, 0x3871, 0x7242, 0, 0, 0, 0xEA71, 0x7245,
+ 0xEA72, 0x7246, 0x7247, 0, 0x724B, 0, 0x3B2A, 0xEA73,
+ 0xEA74, 0, 0, 0x4264, 0, 0xEA75, 0, 0xEA76,
+ 0, 0x724C, 0x7249, 0x7248, 0x724A, 0xEA77, 0, 0xEA78,
+ 0x375F, 0, 0xEA79, 0xEA7A, 0, 0, 0, 0xEA7B,
+ 0x7250, 0x724F, 0x724E, 0xEA7C, 0, 0x3033, 0, 0xEA7D,
+ 0xEA7E, 0xEB21, 0xEB22, 0, 0, 0xEB23, 0, 0xEB24,
+};
+const unsigned short utf8_to_euc_E9B0[] = {
+ 0xEB25, 0, 0xEB26, 0, 0x725A, 0, 0x7256, 0,
+ 0x7257, 0x7253, 0x7259, 0xEB27, 0x7255, 0x3362, 0, 0xEB28,
+ 0x4F4C, 0xEB29, 0x7258, 0x7254, 0x7252, 0x7251, 0xEB2A, 0,
+ 0xEB2B, 0xEB2C, 0xEB2D, 0x725C, 0xEB2E, 0, 0xEB2F, 0,
+ 0, 0x725F, 0xEB30, 0xEB31, 0x725E, 0x725D, 0xEB32, 0xEB33,
+ 0xEB34, 0xEB35, 0xEB36, 0, 0, 0x4949, 0x725B, 0x3073,
+ 0x7260, 0xEB37, 0x7262, 0, 0, 0xEB38, 0xEB39, 0xEB3A,
+ 0, 0x336F, 0x724D, 0x3137, 0, 0xEB3B, 0x7264, 0,
+};
+const unsigned short utf8_to_euc_E9B1[] = {
+ 0, 0xEB3C, 0, 0xEB3D, 0xEB3E, 0xEB3F, 0x7263, 0x7261,
+ 0x432D, 0xEB40, 0xEB41, 0, 0, 0, 0xEB42, 0xEB43,
+ 0xEB44, 0, 0x4B70, 0xEB45, 0xEB46, 0, 0xEB47, 0x4E5A,
+ 0xEB48, 0, 0x7265, 0xEB49, 0xEB50, 0xEB4A, 0xEB4B, 0xEB4C,
+ 0x7266, 0, 0, 0xEB4D, 0, 0, 0, 0x7267,
+ 0xEB52, 0xEB4E, 0xEB4F, 0xEB51, 0, 0, 0xEB53, 0,
+ 0xEB54, 0, 0xEB55, 0, 0, 0xEB56, 0x7268, 0xEB57,
+ 0x7269, 0, 0, 0xEB58, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E9B3[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x443B, 0xEB59, 0x726A,
+ 0, 0x4837, 0, 0x726F, 0x726B, 0, 0, 0,
+ 0x726C, 0, 0xEB5A, 0x4B31, 0x4C44, 0, 0x4650, 0xEB5B,
+ 0, 0xEB5C, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E9B4[] = {
+ 0, 0, 0xEB5E, 0x7270, 0, 0, 0x7271, 0x463E,
+ 0x726E, 0x726D, 0, 0xEB5D, 0, 0, 0x322A, 0,
+ 0, 0xEB5F, 0x7279, 0, 0, 0x7278, 0, 0xEB60,
+ 0xEB61, 0, 0, 0x3175, 0xEB62, 0xEB63, 0xEB64, 0x7276,
+ 0, 0, 0, 0x7275, 0, 0, 0x7273, 0,
+ 0x337B, 0, 0x7272, 0x3C32, 0x3229, 0, 0, 0xEB65,
+ 0xEB66, 0, 0xEB67, 0xEB68, 0xEB69, 0, 0, 0,
+ 0, 0, 0xEB6A, 0x3963, 0xEB6B, 0xEB6D, 0x727C, 0x727B,
+};
+const unsigned short utf8_to_euc_E9B5[] = {
+ 0, 0x727A, 0xEB6E, 0xEB6F, 0x7277, 0xEB6C, 0x727D, 0xEB70,
+ 0x727E, 0, 0xEB71, 0, 0, 0, 0, 0,
+ 0x7325, 0x7324, 0, 0xEB72, 0xEB73, 0, 0, 0,
+ 0, 0x7326, 0, 0, 0x312D, 0x7321, 0x7322, 0xEB74,
+ 0x3974, 0x4C39, 0xEB76, 0xEB75, 0x7323, 0xEB77, 0, 0,
+ 0, 0xEB78, 0xEB79, 0xEB7A, 0x4B32, 0, 0, 0x732B,
+ 0xEB7B, 0, 0x7327, 0, 0, 0, 0xEB7C, 0xEB7D,
+ 0, 0, 0x732C, 0xEB7E, 0xEC21, 0, 0xEC22, 0,
+};
+const unsigned short utf8_to_euc_E9B6[] = {
+ 0, 0, 0, 0xEC23, 0xEC24, 0, 0xEC25, 0x7329,
+ 0, 0x7328, 0xEC26, 0, 0, 0xEC27, 0xEC28, 0x375C,
+ 0, 0, 0xEC29, 0xEC2A, 0, 0xEC2B, 0xEC2C, 0xEC2D,
+ 0xEC2E, 0, 0x732D, 0, 0, 0, 0, 0,
+ 0, 0xEC2F, 0, 0, 0x732E, 0, 0, 0,
+ 0, 0x732F, 0xEC30, 0x732A, 0xEC31, 0, 0xEC32, 0x7274,
+ 0, 0xEC33, 0x7330, 0, 0x4461, 0xEC34, 0, 0,
+ 0x7334, 0xEC35, 0x7335, 0x7333, 0xEC36, 0, 0, 0xEC37,
+};
+const unsigned short utf8_to_euc_E9B7[] = {
+ 0, 0x7332, 0x7338, 0xEC38, 0x7331, 0, 0x7336, 0xEC39,
+ 0, 0xEC3A, 0xEC3B, 0, 0, 0, 0, 0x7337,
+ 0, 0, 0, 0x733A, 0xEC3C, 0xEC3D, 0xEC3E, 0xEC3F,
+ 0, 0x7339, 0xEC40, 0, 0, 0, 0xEC41, 0xEC42,
+ 0xEC43, 0, 0, 0, 0, 0xEC44, 0x733C, 0xEC45,
+ 0, 0xEC46, 0, 0xEC47, 0, 0x733D, 0xEC48, 0x733E,
+ 0xEC49, 0, 0x4F49, 0xEC4A, 0xEC4B, 0, 0, 0,
+ 0x733B, 0x426B, 0x3A6D, 0, 0, 0x733F, 0xEC4C, 0,
+};
+const unsigned short utf8_to_euc_E9B8[] = {
+ 0, 0, 0xEC4E, 0, 0, 0, 0, 0xEC4F,
+ 0, 0, 0xEC4D, 0, 0, 0, 0xEC50, 0,
+ 0xEC51, 0xEC52, 0xEC53, 0, 0, 0xEC54, 0xEC55, 0,
+ 0, 0xEC56, 0x7340, 0x7341, 0xEC57, 0xEC58, 0x7342, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_E9B9[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x7343, 0, 0,
+ 0x3834, 0x7344, 0xEC59, 0xEC5A, 0xEC5B, 0x7345, 0, 0x3C2F,
+};
+const unsigned short utf8_to_euc_E9BA[] = {
+ 0xEC5C, 0x7346, 0xEC5D, 0xEC5E, 0xEC5F, 0xEC60, 0, 0xEC61,
+ 0x7347, 0, 0, 0x7348, 0x7349, 0, 0xEC62, 0xEC63,
+ 0, 0x734C, 0x734A, 0x4F3C, 0, 0x734B, 0xEC64, 0x4E6F,
+ 0xEC65, 0, 0, 0xEC66, 0, 0x734D, 0xEC67, 0x4E5B,
+ 0, 0, 0, 0, 0xEC68, 0x734E, 0x477E, 0,
+ 0xEC69, 0x734F, 0x7351, 0, 0xEC6A, 0x7352, 0xEC6B, 0xEC6C,
+ 0xEC6D, 0, 0, 0xEC6E, 0xEC6F, 0xEC70, 0, 0,
+ 0x7350, 0x396D, 0x4C4D, 0x4B63, 0x5677, 0, 0x5D60, 0x4B7B,
+};
+const unsigned short utf8_to_euc_E9BB[] = {
+ 0, 0, 0, 0, 0x322B, 0, 0xEC71, 0,
+ 0xEC72, 0, 0, 0xEC73, 0x7354, 0x3550, 0x7355, 0x7356,
+ 0x7357, 0xF47E, 0x3975, 0, 0x7358, 0xEC74, 0, 0,
+ 0x6054, 0x4C5B, 0, 0x4263, 0x7359, 0x735B, 0x735A, 0xEC75,
+ 0x735C, 0, 0, 0, 0xEC76, 0x735D, 0, 0xEC77,
+ 0x735E, 0, 0, 0, 0xEC78, 0xEC79, 0xEC7A, 0x735F,
+ 0xEC7B, 0xEC7C, 0xEC7D, 0, 0x7360, 0xEC7E, 0x7361, 0x7362,
+ 0xED21, 0x7363, 0, 0x7364, 0x7365, 0x7366, 0, 0xED22,
+};
+const unsigned short utf8_to_euc_E9BC[] = {
+ 0, 0, 0xED23, 0xED24, 0, 0, 0, 0x7367,
+ 0x7368, 0xED25, 0, 0, 0, 0, 0x4524, 0xED26,
+ 0xED27, 0xED28, 0xED29, 0x385D, 0xED2A, 0x736A, 0xED2B, 0xED2C,
+ 0, 0xED2D, 0xED2E, 0xED2F, 0, 0, 0, 0xED30,
+ 0x414D, 0x736B, 0xED31, 0, 0, 0, 0xED32, 0,
+ 0, 0, 0xED33, 0xED34, 0x736C, 0, 0, 0xED35,
+ 0, 0xED36, 0xED37, 0, 0xED38, 0, 0, 0xED39,
+ 0, 0xED3A, 0xED3B, 0x4921, 0xED3C, 0xED3D, 0x736D, 0xED3E,
+};
+const unsigned short utf8_to_euc_E9BD[] = {
+ 0, 0xED3F, 0, 0xED40, 0xED41, 0xED42, 0xED43, 0xED44,
+ 0, 0, 0x736E, 0x6337, 0, 0, 0x6C5A, 0x706D,
+ 0, 0, 0x736F, 0xED45, 0x7370, 0xED46, 0xED47, 0xED48,
+ 0xED49, 0, 0xED4A, 0, 0, 0xED4B, 0xED4C, 0x7372,
+ 0x7373, 0x7374, 0x4E70, 0x7371, 0, 0, 0x7375, 0x7376,
+ 0xED4D, 0xED4E, 0x7378, 0, 0x7377, 0xED4F, 0xED50, 0xED51,
+ 0xED52, 0xED53, 0x737A, 0xED54, 0, 0xED55, 0x737B, 0x7379,
+ 0, 0, 0xED56, 0, 0, 0xED57, 0, 0,
+};
+const unsigned short utf8_to_euc_E9BE[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x4E36, 0, 0xED58,
+ 0xED59, 0xED5A, 0xED5B, 0, 0xED5C, 0x737C, 0xED5D, 0xED5E,
+ 0, 0, 0, 0, 0x737D, 0x6354, 0xED5F, 0,
+ 0x737E, 0xED60, 0xED61, 0xED62, 0, 0xED63, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_EFA4[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xF445, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_EFA7[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xF472, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_EFA8[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xF434, 0xF437,
+ 0xF438, 0xF43D, 0xF444, 0xF447, 0xF448, 0xF44E, 0xF44F, 0xF453,
+ 0xF455, 0xF456, 0xF457, 0xF458, 0xF45A, 0xF45B, 0xF45E, 0xF460,
+ 0xF462, 0xF463, 0xF465, 0xF469, 0xF46A, 0xF46B, 0xF46D, 0xF46F,
+ 0xF470, 0xF473, 0xF477, 0xF478, 0xF479, 0xF47D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_EFBC[] = {
+ 0, 0x212A, 0xF42A, 0x2174, 0x2170, 0x2173, 0x2175, 0xF429,
+ 0x214A, 0x214B, 0x2176, 0x215C, 0x2124, 0x215D, 0x2125, 0x213F,
+ 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337,
+ 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129,
+ 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347,
+ 0x2348, 0x2349, 0x234A, 0x234B, 0x234C, 0x234D, 0x234E, 0x234F,
+ 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357,
+ 0x2358, 0x2359, 0x235A, 0x214E, 0x2140, 0x214F, 0x2130, 0x2132,
+};
+const unsigned short utf8_to_euc_EFBD[] = {
+ 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
+ 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F,
+ 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
+ 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0xA237, 0,
+ 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
+ 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
+ 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
+ 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F,
+};
+const unsigned short utf8_to_euc_EFBD_ms[] = {
+ 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
+ 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F,
+ 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
+ 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0x2141, 0,
+ 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
+ 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
+ 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
+ 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F,
+};
+const unsigned short utf8_to_euc_EFBE[] = {
+ 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
+ 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
+ 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
+ 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0E5C, 0x0E5D, 0x0E5E, 0x0E5F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short utf8_to_euc_EFBF[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x2171, 0x2172, 0x224C, 0x2131, 0xA243, 0x216F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short *const utf8_to_euc_E2[] = {
+ utf8_to_euc_E280, 0, 0, 0,
+ utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287,
+ utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0,
+ utf8_to_euc_E28C, 0, 0, 0,
+ 0, utf8_to_euc_E291, 0, 0,
+ utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
+ utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+const unsigned short *const utf8_to_euc_E2_ms[] = {
+ utf8_to_euc_E280_ms, 0, 0, 0,
+ utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287,
+ utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0,
+ utf8_to_euc_E28C, 0, 0, 0,
+ 0, utf8_to_euc_E291, 0, 0,
+ utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
+ utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+const unsigned short *const utf8_to_euc_E2_932[] = {
+ utf8_to_euc_E280_932, 0, 0, 0,
+ utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287,
+ utf8_to_euc_E288_932, utf8_to_euc_E289, utf8_to_euc_E28A, 0,
+ utf8_to_euc_E28C, 0, 0, 0,
+ 0, utf8_to_euc_E291, 0, 0,
+ utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
+ utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+const unsigned short *const utf8_to_euc_E3[] = {
+ utf8_to_euc_E380, utf8_to_euc_E381, utf8_to_euc_E382, utf8_to_euc_E383,
+ 0, 0, 0, 0,
+ utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0,
+ utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+const unsigned short *const utf8_to_euc_E3_932[] = {
+ utf8_to_euc_E380_932, utf8_to_euc_E381, utf8_to_euc_E382_932, utf8_to_euc_E383,
+ 0, 0, 0, 0,
+ utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0,
+ utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+const unsigned short *const utf8_to_euc_E4[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ utf8_to_euc_E4B8, utf8_to_euc_E4B9, utf8_to_euc_E4BA, utf8_to_euc_E4BB,
+ utf8_to_euc_E4BC, utf8_to_euc_E4BD, utf8_to_euc_E4BE, utf8_to_euc_E4BF,
+};
+const unsigned short *const utf8_to_euc_E5[] = {
+ utf8_to_euc_E580, utf8_to_euc_E581, utf8_to_euc_E582, utf8_to_euc_E583,
+ utf8_to_euc_E584, utf8_to_euc_E585, utf8_to_euc_E586, utf8_to_euc_E587,
+ utf8_to_euc_E588, utf8_to_euc_E589, utf8_to_euc_E58A, utf8_to_euc_E58B,
+ utf8_to_euc_E58C, utf8_to_euc_E58D, utf8_to_euc_E58E, utf8_to_euc_E58F,
+ utf8_to_euc_E590, utf8_to_euc_E591, utf8_to_euc_E592, utf8_to_euc_E593,
+ utf8_to_euc_E594, utf8_to_euc_E595, utf8_to_euc_E596, utf8_to_euc_E597,
+ utf8_to_euc_E598, utf8_to_euc_E599, utf8_to_euc_E59A, utf8_to_euc_E59B,
+ utf8_to_euc_E59C, utf8_to_euc_E59D, utf8_to_euc_E59E, utf8_to_euc_E59F,
+ utf8_to_euc_E5A0, utf8_to_euc_E5A1, utf8_to_euc_E5A2, utf8_to_euc_E5A3,
+ utf8_to_euc_E5A4, utf8_to_euc_E5A5, utf8_to_euc_E5A6, utf8_to_euc_E5A7,
+ utf8_to_euc_E5A8, utf8_to_euc_E5A9, utf8_to_euc_E5AA, utf8_to_euc_E5AB,
+ utf8_to_euc_E5AC, utf8_to_euc_E5AD, utf8_to_euc_E5AE, utf8_to_euc_E5AF,
+ utf8_to_euc_E5B0, utf8_to_euc_E5B1, utf8_to_euc_E5B2, utf8_to_euc_E5B3,
+ utf8_to_euc_E5B4, utf8_to_euc_E5B5, utf8_to_euc_E5B6, utf8_to_euc_E5B7,
+ utf8_to_euc_E5B8, utf8_to_euc_E5B9, utf8_to_euc_E5BA, utf8_to_euc_E5BB,
+ utf8_to_euc_E5BC, utf8_to_euc_E5BD, utf8_to_euc_E5BE, utf8_to_euc_E5BF,
+};
+const unsigned short *const utf8_to_euc_E6[] = {
+ utf8_to_euc_E680, utf8_to_euc_E681, utf8_to_euc_E682, utf8_to_euc_E683,
+ utf8_to_euc_E684, utf8_to_euc_E685, utf8_to_euc_E686, utf8_to_euc_E687,
+ utf8_to_euc_E688, utf8_to_euc_E689, utf8_to_euc_E68A, utf8_to_euc_E68B,
+ utf8_to_euc_E68C, utf8_to_euc_E68D, utf8_to_euc_E68E, utf8_to_euc_E68F,
+ utf8_to_euc_E690, utf8_to_euc_E691, utf8_to_euc_E692, utf8_to_euc_E693,
+ utf8_to_euc_E694, utf8_to_euc_E695, utf8_to_euc_E696, utf8_to_euc_E697,
+ utf8_to_euc_E698, utf8_to_euc_E699, utf8_to_euc_E69A, utf8_to_euc_E69B,
+ utf8_to_euc_E69C, utf8_to_euc_E69D, utf8_to_euc_E69E, utf8_to_euc_E69F,
+ utf8_to_euc_E6A0, utf8_to_euc_E6A1, utf8_to_euc_E6A2, utf8_to_euc_E6A3,
+ utf8_to_euc_E6A4, utf8_to_euc_E6A5, utf8_to_euc_E6A6, utf8_to_euc_E6A7,
+ utf8_to_euc_E6A8, utf8_to_euc_E6A9, utf8_to_euc_E6AA, utf8_to_euc_E6AB,
+ utf8_to_euc_E6AC, utf8_to_euc_E6AD, utf8_to_euc_E6AE, utf8_to_euc_E6AF,
+ utf8_to_euc_E6B0, utf8_to_euc_E6B1, utf8_to_euc_E6B2, utf8_to_euc_E6B3,
+ utf8_to_euc_E6B4, utf8_to_euc_E6B5, utf8_to_euc_E6B6, utf8_to_euc_E6B7,
+ utf8_to_euc_E6B8, utf8_to_euc_E6B9, utf8_to_euc_E6BA, utf8_to_euc_E6BB,
+ utf8_to_euc_E6BC, utf8_to_euc_E6BD, utf8_to_euc_E6BE, utf8_to_euc_E6BF,
+};
+const unsigned short *const utf8_to_euc_E7[] = {
+ utf8_to_euc_E780, utf8_to_euc_E781, utf8_to_euc_E782, utf8_to_euc_E783,
+ utf8_to_euc_E784, utf8_to_euc_E785, utf8_to_euc_E786, utf8_to_euc_E787,
+ utf8_to_euc_E788, utf8_to_euc_E789, utf8_to_euc_E78A, utf8_to_euc_E78B,
+ utf8_to_euc_E78C, utf8_to_euc_E78D, utf8_to_euc_E78E, utf8_to_euc_E78F,
+ utf8_to_euc_E790, utf8_to_euc_E791, utf8_to_euc_E792, utf8_to_euc_E793,
+ utf8_to_euc_E794, utf8_to_euc_E795, utf8_to_euc_E796, utf8_to_euc_E797,
+ utf8_to_euc_E798, utf8_to_euc_E799, utf8_to_euc_E79A, utf8_to_euc_E79B,
+ utf8_to_euc_E79C, utf8_to_euc_E79D, utf8_to_euc_E79E, utf8_to_euc_E79F,
+ utf8_to_euc_E7A0, utf8_to_euc_E7A1, utf8_to_euc_E7A2, utf8_to_euc_E7A3,
+ utf8_to_euc_E7A4, utf8_to_euc_E7A5, utf8_to_euc_E7A6, utf8_to_euc_E7A7,
+ utf8_to_euc_E7A8, utf8_to_euc_E7A9, utf8_to_euc_E7AA, utf8_to_euc_E7AB,
+ utf8_to_euc_E7AC, utf8_to_euc_E7AD, utf8_to_euc_E7AE, utf8_to_euc_E7AF,
+ utf8_to_euc_E7B0, utf8_to_euc_E7B1, utf8_to_euc_E7B2, utf8_to_euc_E7B3,
+ utf8_to_euc_E7B4, utf8_to_euc_E7B5, utf8_to_euc_E7B6, utf8_to_euc_E7B7,
+ utf8_to_euc_E7B8, utf8_to_euc_E7B9, utf8_to_euc_E7BA, 0,
+ utf8_to_euc_E7BC, utf8_to_euc_E7BD, utf8_to_euc_E7BE, utf8_to_euc_E7BF,
+};
+const unsigned short *const utf8_to_euc_E8[] = {
+ utf8_to_euc_E880, utf8_to_euc_E881, utf8_to_euc_E882, utf8_to_euc_E883,
+ utf8_to_euc_E884, utf8_to_euc_E885, utf8_to_euc_E886, utf8_to_euc_E887,
+ utf8_to_euc_E888, utf8_to_euc_E889, utf8_to_euc_E88A, utf8_to_euc_E88B,
+ utf8_to_euc_E88C, utf8_to_euc_E88D, utf8_to_euc_E88E, utf8_to_euc_E88F,
+ utf8_to_euc_E890, utf8_to_euc_E891, utf8_to_euc_E892, utf8_to_euc_E893,
+ utf8_to_euc_E894, utf8_to_euc_E895, utf8_to_euc_E896, utf8_to_euc_E897,
+ utf8_to_euc_E898, utf8_to_euc_E899, utf8_to_euc_E89A, utf8_to_euc_E89B,
+ utf8_to_euc_E89C, utf8_to_euc_E89D, utf8_to_euc_E89E, utf8_to_euc_E89F,
+ utf8_to_euc_E8A0, utf8_to_euc_E8A1, utf8_to_euc_E8A2, utf8_to_euc_E8A3,
+ utf8_to_euc_E8A4, utf8_to_euc_E8A5, utf8_to_euc_E8A6, utf8_to_euc_E8A7,
+ utf8_to_euc_E8A8, utf8_to_euc_E8A9, utf8_to_euc_E8AA, utf8_to_euc_E8AB,
+ utf8_to_euc_E8AC, utf8_to_euc_E8AD, utf8_to_euc_E8AE, 0,
+ utf8_to_euc_E8B0, utf8_to_euc_E8B1, utf8_to_euc_E8B2, utf8_to_euc_E8B3,
+ utf8_to_euc_E8B4, utf8_to_euc_E8B5, utf8_to_euc_E8B6, utf8_to_euc_E8B7,
+ utf8_to_euc_E8B8, utf8_to_euc_E8B9, utf8_to_euc_E8BA, utf8_to_euc_E8BB,
+ utf8_to_euc_E8BC, utf8_to_euc_E8BD, utf8_to_euc_E8BE, utf8_to_euc_E8BF,
+};
+const unsigned short *const utf8_to_euc_E9[] = {
+ utf8_to_euc_E980, utf8_to_euc_E981, utf8_to_euc_E982, utf8_to_euc_E983,
+ utf8_to_euc_E984, utf8_to_euc_E985, utf8_to_euc_E986, utf8_to_euc_E987,
+ utf8_to_euc_E988, utf8_to_euc_E989, utf8_to_euc_E98A, utf8_to_euc_E98B,
+ utf8_to_euc_E98C, utf8_to_euc_E98D, utf8_to_euc_E98E, utf8_to_euc_E98F,
+ utf8_to_euc_E990, utf8_to_euc_E991, utf8_to_euc_E992, 0,
+ 0, utf8_to_euc_E995, utf8_to_euc_E996, utf8_to_euc_E997,
+ utf8_to_euc_E998, utf8_to_euc_E999, utf8_to_euc_E99A, utf8_to_euc_E99B,
+ utf8_to_euc_E99C, utf8_to_euc_E99D, utf8_to_euc_E99E, utf8_to_euc_E99F,
+ utf8_to_euc_E9A0, utf8_to_euc_E9A1, utf8_to_euc_E9A2, utf8_to_euc_E9A3,
+ utf8_to_euc_E9A4, utf8_to_euc_E9A5, utf8_to_euc_E9A6, utf8_to_euc_E9A7,
+ utf8_to_euc_E9A8, utf8_to_euc_E9A9, utf8_to_euc_E9AA, utf8_to_euc_E9AB,
+ utf8_to_euc_E9AC, utf8_to_euc_E9AD, utf8_to_euc_E9AE, utf8_to_euc_E9AF,
+ utf8_to_euc_E9B0, utf8_to_euc_E9B1, 0, utf8_to_euc_E9B3,
+ utf8_to_euc_E9B4, utf8_to_euc_E9B5, utf8_to_euc_E9B6, utf8_to_euc_E9B7,
+ utf8_to_euc_E9B8, utf8_to_euc_E9B9, utf8_to_euc_E9BA, utf8_to_euc_E9BB,
+ utf8_to_euc_E9BC, utf8_to_euc_E9BD, utf8_to_euc_E9BE, 0,
+};
+const unsigned short *const utf8_to_euc_EF[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7,
+ utf8_to_euc_EFA8, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ utf8_to_euc_EFBC, utf8_to_euc_EFBD, utf8_to_euc_EFBE, utf8_to_euc_EFBF,
+};
+const unsigned short *const utf8_to_euc_EF_ms[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7,
+ utf8_to_euc_EFA8, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ utf8_to_euc_EFBC, utf8_to_euc_EFBD_ms, utf8_to_euc_EFBE, utf8_to_euc_EFBF,
+};
+const unsigned short *const utf8_to_euc_2bytes[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, utf8_to_euc_C2, utf8_to_euc_C3,
+ utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
+ 0, 0, 0, utf8_to_euc_CB,
+ 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
+ utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+const unsigned short *const utf8_to_euc_2bytes_ms[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, utf8_to_euc_C2_ms, utf8_to_euc_C3,
+ utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
+ 0, 0, 0, utf8_to_euc_CB,
+ 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
+ utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+const unsigned short *const utf8_to_euc_2bytes_932[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, utf8_to_euc_C2_932, utf8_to_euc_C3_932,
+ utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
+ 0, 0, 0, utf8_to_euc_CB,
+ 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
+ utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+const unsigned short *const *const utf8_to_euc_3bytes[] = {
+ 0, 0, utf8_to_euc_E2, utf8_to_euc_E3,
+ utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
+ utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
+ 0, 0, 0, utf8_to_euc_EF,
+};
+const unsigned short *const *const utf8_to_euc_3bytes_ms[] = {
+ 0, 0, utf8_to_euc_E2_ms, utf8_to_euc_E3,
+ utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
+ utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
+ 0, 0, 0, utf8_to_euc_EF_ms,
+};
+const unsigned short *const *const utf8_to_euc_3bytes_932[] = {
+ 0, 0, utf8_to_euc_E2_932, utf8_to_euc_E3_932,
+ utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
+ utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
+ 0, 0, 0, utf8_to_euc_EF_ms,
+};
+
+#ifdef UNICODE_NORMALIZATION
+
+/* Normalization Table by Apple */
+/* http://developer.apple.com/technotes/tn/tn1150table.html */
+
+const struct normalization_pair normalization_table[] = {
+ {{0xcd,0xbe}, {0x3b}},
+ {{0xc3,0x80}, {0x41,0xcc,0x80,0x00}},
+ {{0xc3,0x81}, {0x41,0xcc,0x81}},
+ {{0xc3,0x82}, {0x41,0xcc,0x82}},
+ {{0xe1,0xba,0xa6}, {0x41,0xcc,0x82,0xcc,0x80}},
+ {{0xe1,0xba,0xa4}, {0x41,0xcc,0x82,0xcc,0x81}},
+ {{0xe1,0xba,0xaa}, {0x41,0xcc,0x82,0xcc,0x83}},
+ {{0xe1,0xba,0xa8}, {0x41,0xcc,0x82,0xcc,0x89}},
+ {{0xc3,0x83}, {0x41,0xcc,0x83}},
+ {{0xc4,0x80}, {0x41,0xcc,0x84}},
+ {{0xc4,0x82}, {0x41,0xcc,0x86}},
+ {{0xe1,0xba,0xb0}, {0x41,0xcc,0x86,0xcc,0x80}},
+ {{0xe1,0xba,0xae}, {0x41,0xcc,0x86,0xcc,0x81}},
+ {{0xe1,0xba,0xb4}, {0x41,0xcc,0x86,0xcc,0x83}},
+ {{0xe1,0xba,0xb2}, {0x41,0xcc,0x86,0xcc,0x89}},
+ {{0xc7,0xa0}, {0x41,0xcc,0x87,0xcc,0x84}},
+ {{0xc3,0x84}, {0x41,0xcc,0x88}},
+ {{0xc7,0x9e}, {0x41,0xcc,0x88,0xcc,0x84}},
+ {{0xe1,0xba,0xa2}, {0x41,0xcc,0x89}},
+ {{0xc3,0x85}, {0x41,0xcc,0x8a}},
+ {{0xc7,0xba}, {0x41,0xcc,0x8a,0xcc,0x81}},
+ {{0xc7,0x8d}, {0x41,0xcc,0x8c}},
+ {{0xc8,0x80}, {0x41,0xcc,0x8f}},
+ {{0xc8,0x82}, {0x41,0xcc,0x91}},
+ {{0xe1,0xba,0xa0}, {0x41,0xcc,0xa3}},
+ {{0xe1,0xba,0xac}, {0x41,0xcc,0xa3,0xcc,0x82}},
+ {{0xe1,0xba,0xb6}, {0x41,0xcc,0xa3,0xcc,0x86}},
+ {{0xe1,0xb8,0x80}, {0x41,0xcc,0xa5}},
+ {{0xc4,0x84}, {0x41,0xcc,0xa8}},
+ {{0xe1,0xb8,0x82}, {0x42,0xcc,0x87}},
+ {{0xe1,0xb8,0x84}, {0x42,0xcc,0xa3}},
+ {{0xe1,0xb8,0x86}, {0x42,0xcc,0xb1}},
+ {{0xc4,0x86}, {0x43,0xcc,0x81}},
+ {{0xc4,0x88}, {0x43,0xcc,0x82}},
+ {{0xc4,0x8a}, {0x43,0xcc,0x87}},
+ {{0xc4,0x8c}, {0x43,0xcc,0x8c}},
+ {{0xc3,0x87}, {0x43,0xcc,0xa7}},
+ {{0xe1,0xb8,0x88}, {0x43,0xcc,0xa7,0xcc,0x81}},
+ {{0xe1,0xb8,0x8a}, {0x44,0xcc,0x87}},
+ {{0xc4,0x8e}, {0x44,0xcc,0x8c}},
+ {{0xe1,0xb8,0x8c}, {0x44,0xcc,0xa3}},
+ {{0xe1,0xb8,0x90}, {0x44,0xcc,0xa7}},
+ {{0xe1,0xb8,0x92}, {0x44,0xcc,0xad}},
+ {{0xe1,0xb8,0x8e}, {0x44,0xcc,0xb1}},
+ {{0xc3,0x88}, {0x45,0xcc,0x80}},
+ {{0xc3,0x89}, {0x45,0xcc,0x81}},
+ {{0xc3,0x8a}, {0x45,0xcc,0x82}},
+ {{0xe1,0xbb,0x80}, {0x45,0xcc,0x82,0xcc,0x80}},
+ {{0xe1,0xba,0xbe}, {0x45,0xcc,0x82,0xcc,0x81}},
+ {{0xe1,0xbb,0x84}, {0x45,0xcc,0x82,0xcc,0x83}},
+ {{0xe1,0xbb,0x82}, {0x45,0xcc,0x82,0xcc,0x89}},
+ {{0xe1,0xba,0xbc}, {0x45,0xcc,0x83}},
+ {{0xc4,0x92}, {0x45,0xcc,0x84}},
+ {{0xe1,0xb8,0x94}, {0x45,0xcc,0x84,0xcc,0x80}},
+ {{0xe1,0xb8,0x96}, {0x45,0xcc,0x84,0xcc,0x81}},
+ {{0xc4,0x94}, {0x45,0xcc,0x86}},
+ {{0xc4,0x96}, {0x45,0xcc,0x87}},
+ {{0xc3,0x8b}, {0x45,0xcc,0x88}},
+ {{0xe1,0xba,0xba}, {0x45,0xcc,0x89}},
+ {{0xc4,0x9a}, {0x45,0xcc,0x8c}},
+ {{0xc8,0x84}, {0x45,0xcc,0x8f}},
+ {{0xc8,0x86}, {0x45,0xcc,0x91}},
+ {{0xe1,0xba,0xb8}, {0x45,0xcc,0xa3}},
+ {{0xe1,0xbb,0x86}, {0x45,0xcc,0xa3,0xcc,0x82}},
+ {{0xe1,0xb8,0x9c}, {0x45,0xcc,0xa7,0xcc,0x86}},
+ {{0xc4,0x98}, {0x45,0xcc,0xa8}},
+ {{0xe1,0xb8,0x98}, {0x45,0xcc,0xad}},
+ {{0xe1,0xb8,0x9a}, {0x45,0xcc,0xb0}},
+ {{0xe1,0xb8,0x9e}, {0x46,0xcc,0x87}},
+ {{0xc7,0xb4}, {0x47,0xcc,0x81}},
+ {{0xc4,0x9c}, {0x47,0xcc,0x82}},
+ {{0xe1,0xb8,0xa0}, {0x47,0xcc,0x84}},
+ {{0xc4,0x9e}, {0x47,0xcc,0x86}},
+ {{0xc4,0xa0}, {0x47,0xcc,0x87}},
+ {{0xc7,0xa6}, {0x47,0xcc,0x8c}},
+ {{0xc4,0xa2}, {0x47,0xcc,0xa7}},
+ {{0xc4,0xa4}, {0x48,0xcc,0x82}},
+ {{0xe1,0xb8,0xa2}, {0x48,0xcc,0x87}},
+ {{0xe1,0xb8,0xa6}, {0x48,0xcc,0x88}},
+ {{0xe1,0xb8,0xa4}, {0x48,0xcc,0xa3}},
+ {{0xe1,0xb8,0xa8}, {0x48,0xcc,0xa7}},
+ {{0xe1,0xb8,0xaa}, {0x48,0xcc,0xae}},
+ {{0xc3,0x8c}, {0x49,0xcc,0x80}},
+ {{0xc3,0x8d}, {0x49,0xcc,0x81}},
+ {{0xc3,0x8e}, {0x49,0xcc,0x82}},
+ {{0xc4,0xa8}, {0x49,0xcc,0x83}},
+ {{0xc4,0xaa}, {0x49,0xcc,0x84}},
+ {{0xc4,0xac}, {0x49,0xcc,0x86}},
+ {{0xc4,0xb0}, {0x49,0xcc,0x87}},
+ {{0xc3,0x8f}, {0x49,0xcc,0x88}},
+ {{0xe1,0xb8,0xae}, {0x49,0xcc,0x88,0xcc,0x81}},
+ {{0xe1,0xbb,0x88}, {0x49,0xcc,0x89}},
+ {{0xc7,0x8f}, {0x49,0xcc,0x8c}},
+ {{0xc8,0x88}, {0x49,0xcc,0x8f}},
+ {{0xc8,0x8a}, {0x49,0xcc,0x91}},
+ {{0xe1,0xbb,0x8a}, {0x49,0xcc,0xa3}},
+ {{0xc4,0xae}, {0x49,0xcc,0xa8}},
+ {{0xe1,0xb8,0xac}, {0x49,0xcc,0xb0}},
+ {{0xc4,0xb4}, {0x4a,0xcc,0x82}},
+ {{0xe1,0xb8,0xb0}, {0x4b,0xcc,0x81}},
+ {{0xc7,0xa8}, {0x4b,0xcc,0x8c}},
+ {{0xe1,0xb8,0xb2}, {0x4b,0xcc,0xa3}},
+ {{0xc4,0xb6}, {0x4b,0xcc,0xa7}},
+ {{0xe1,0xb8,0xb4}, {0x4b,0xcc,0xb1}},
+ {{0xc4,0xb9}, {0x4c,0xcc,0x81}},
+ {{0xc4,0xbd}, {0x4c,0xcc,0x8c}},
+ {{0xe1,0xb8,0xb6}, {0x4c,0xcc,0xa3}},
+ {{0xe1,0xb8,0xb8}, {0x4c,0xcc,0xa3,0xcc,0x84}},
+ {{0xc4,0xbb}, {0x4c,0xcc,0xa7}},
+ {{0xe1,0xb8,0xbc}, {0x4c,0xcc,0xad}},
+ {{0xe1,0xb8,0xba}, {0x4c,0xcc,0xb1}},
+ {{0xe1,0xb8,0xbe}, {0x4d,0xcc,0x81}},
+ {{0xe1,0xb9,0x80}, {0x4d,0xcc,0x87}},
+ {{0xe1,0xb9,0x82}, {0x4d,0xcc,0xa3}},
+ {{0xc5,0x83}, {0x4e,0xcc,0x81}},
+ {{0xc3,0x91}, {0x4e,0xcc,0x83}},
+ {{0xe1,0xb9,0x84}, {0x4e,0xcc,0x87}},
+ {{0xc5,0x87}, {0x4e,0xcc,0x8c}},
+ {{0xe1,0xb9,0x86}, {0x4e,0xcc,0xa3}},
+ {{0xc5,0x85}, {0x4e,0xcc,0xa7}},
+ {{0xe1,0xb9,0x8a}, {0x4e,0xcc,0xad}},
+ {{0xe1,0xb9,0x88}, {0x4e,0xcc,0xb1}},
+ {{0xc3,0x92}, {0x4f,0xcc,0x80}},
+ {{0xc3,0x93}, {0x4f,0xcc,0x81}},
+ {{0xc3,0x94}, {0x4f,0xcc,0x82}},
+ {{0xe1,0xbb,0x92}, {0x4f,0xcc,0x82,0xcc,0x80}},
+ {{0xe1,0xbb,0x90}, {0x4f,0xcc,0x82,0xcc,0x81}},
+ {{0xe1,0xbb,0x96}, {0x4f,0xcc,0x82,0xcc,0x83}},
+ {{0xe1,0xbb,0x94}, {0x4f,0xcc,0x82,0xcc,0x89}},
+ {{0xc3,0x95}, {0x4f,0xcc,0x83}},
+ {{0xe1,0xb9,0x8c}, {0x4f,0xcc,0x83,0xcc,0x81}},
+ {{0xe1,0xb9,0x8e}, {0x4f,0xcc,0x83,0xcc,0x88}},
+ {{0xc5,0x8c}, {0x4f,0xcc,0x84}},
+ {{0xe1,0xb9,0x90}, {0x4f,0xcc,0x84,0xcc,0x80}},
+ {{0xe1,0xb9,0x92}, {0x4f,0xcc,0x84,0xcc,0x81}},
+ {{0xc5,0x8e}, {0x4f,0xcc,0x86}},
+ {{0xc3,0x96}, {0x4f,0xcc,0x88}},
+ {{0xe1,0xbb,0x8e}, {0x4f,0xcc,0x89}},
+ {{0xc5,0x90}, {0x4f,0xcc,0x8b}},
+ {{0xc7,0x91}, {0x4f,0xcc,0x8c}},
+ {{0xc8,0x8c}, {0x4f,0xcc,0x8f}},
+ {{0xc8,0x8e}, {0x4f,0xcc,0x91}},
+ {{0xc6,0xa0}, {0x4f,0xcc,0x9b}},
+ {{0xe1,0xbb,0x9c}, {0x4f,0xcc,0x9b,0xcc,0x80}},
+ {{0xe1,0xbb,0x9a}, {0x4f,0xcc,0x9b,0xcc,0x81}},
+ {{0xe1,0xbb,0xa0}, {0x4f,0xcc,0x9b,0xcc,0x83}},
+ {{0xe1,0xbb,0x9e}, {0x4f,0xcc,0x9b,0xcc,0x89}},
+ {{0xe1,0xbb,0xa2}, {0x4f,0xcc,0x9b,0xcc,0xa3}},
+ {{0xe1,0xbb,0x8c}, {0x4f,0xcc,0xa3}},
+ {{0xe1,0xbb,0x98}, {0x4f,0xcc,0xa3,0xcc,0x82}},
+ {{0xc7,0xaa}, {0x4f,0xcc,0xa8}},
+ {{0xc7,0xac}, {0x4f,0xcc,0xa8,0xcc,0x84}},
+ {{0xe1,0xb9,0x94}, {0x50,0xcc,0x81}},
+ {{0xe1,0xb9,0x96}, {0x50,0xcc,0x87}},
+ {{0xc5,0x94}, {0x52,0xcc,0x81}},
+ {{0xe1,0xb9,0x98}, {0x52,0xcc,0x87}},
+ {{0xc5,0x98}, {0x52,0xcc,0x8c}},
+ {{0xc8,0x90}, {0x52,0xcc,0x8f}},
+ {{0xc8,0x92}, {0x52,0xcc,0x91}},
+ {{0xe1,0xb9,0x9a}, {0x52,0xcc,0xa3}},
+ {{0xe1,0xb9,0x9c}, {0x52,0xcc,0xa3,0xcc,0x84}},
+ {{0xc5,0x96}, {0x52,0xcc,0xa7}},
+ {{0xe1,0xb9,0x9e}, {0x52,0xcc,0xb1}},
+ {{0xc5,0x9a}, {0x53,0xcc,0x81}},
+ {{0xe1,0xb9,0xa4}, {0x53,0xcc,0x81,0xcc,0x87}},
+ {{0xc5,0x9c}, {0x53,0xcc,0x82}},
+ {{0xe1,0xb9,0xa0}, {0x53,0xcc,0x87}},
+ {{0xc5,0xa0}, {0x53,0xcc,0x8c}},
+ {{0xe1,0xb9,0xa6}, {0x53,0xcc,0x8c,0xcc,0x87}},
+ {{0xe1,0xb9,0xa2}, {0x53,0xcc,0xa3}},
+ {{0xe1,0xb9,0xa8}, {0x53,0xcc,0xa3,0xcc,0x87}},
+ {{0xc5,0x9e}, {0x53,0xcc,0xa7}},
+ {{0xe1,0xb9,0xaa}, {0x54,0xcc,0x87}},
+ {{0xc5,0xa4}, {0x54,0xcc,0x8c}},
+ {{0xe1,0xb9,0xac}, {0x54,0xcc,0xa3}},
+ {{0xc5,0xa2}, {0x54,0xcc,0xa7}},
+ {{0xe1,0xb9,0xb0}, {0x54,0xcc,0xad}},
+ {{0xe1,0xb9,0xae}, {0x54,0xcc,0xb1}},
+ {{0xc3,0x99}, {0x55,0xcc,0x80}},
+ {{0xc3,0x9a}, {0x55,0xcc,0x81}},
+ {{0xc3,0x9b}, {0x55,0xcc,0x82}},
+ {{0xc5,0xa8}, {0x55,0xcc,0x83}},
+ {{0xe1,0xb9,0xb8}, {0x55,0xcc,0x83,0xcc,0x81}},
+ {{0xc5,0xaa}, {0x55,0xcc,0x84}},
+ {{0xe1,0xb9,0xba}, {0x55,0xcc,0x84,0xcc,0x88}},
+ {{0xc5,0xac}, {0x55,0xcc,0x86}},
+ {{0xc3,0x9c}, {0x55,0xcc,0x88}},
+ {{0xc7,0x9b}, {0x55,0xcc,0x88,0xcc,0x80}},
+ {{0xc7,0x97}, {0x55,0xcc,0x88,0xcc,0x81}},
+ {{0xc7,0x95}, {0x55,0xcc,0x88,0xcc,0x84}},
+ {{0xc7,0x99}, {0x55,0xcc,0x88,0xcc,0x8c}},
+ {{0xe1,0xbb,0xa6}, {0x55,0xcc,0x89}},
+ {{0xc5,0xae}, {0x55,0xcc,0x8a}},
+ {{0xc5,0xb0}, {0x55,0xcc,0x8b}},
+ {{0xc7,0x93}, {0x55,0xcc,0x8c}},
+ {{0xc8,0x94}, {0x55,0xcc,0x8f}},
+ {{0xc8,0x96}, {0x55,0xcc,0x91}},
+ {{0xc6,0xaf}, {0x55,0xcc,0x9b}},
+ {{0xe1,0xbb,0xaa}, {0x55,0xcc,0x9b,0xcc,0x80}},
+ {{0xe1,0xbb,0xa8}, {0x55,0xcc,0x9b,0xcc,0x81}},
+ {{0xe1,0xbb,0xae}, {0x55,0xcc,0x9b,0xcc,0x83}},
+ {{0xe1,0xbb,0xac}, {0x55,0xcc,0x9b,0xcc,0x89}},
+ {{0xe1,0xbb,0xb0}, {0x55,0xcc,0x9b,0xcc,0xa3}},
+ {{0xe1,0xbb,0xa4}, {0x55,0xcc,0xa3}},
+ {{0xe1,0xb9,0xb2}, {0x55,0xcc,0xa4}},
+ {{0xc5,0xb2}, {0x55,0xcc,0xa8}},
+ {{0xe1,0xb9,0xb6}, {0x55,0xcc,0xad}},
+ {{0xe1,0xb9,0xb4}, {0x55,0xcc,0xb0}},
+ {{0xe1,0xb9,0xbc}, {0x56,0xcc,0x83}},
+ {{0xe1,0xb9,0xbe}, {0x56,0xcc,0xa3}},
+ {{0xe1,0xba,0x80}, {0x57,0xcc,0x80}},
+ {{0xe1,0xba,0x82}, {0x57,0xcc,0x81}},
+ {{0xc5,0xb4}, {0x57,0xcc,0x82}},
+ {{0xe1,0xba,0x86}, {0x57,0xcc,0x87}},
+ {{0xe1,0xba,0x84}, {0x57,0xcc,0x88}},
+ {{0xe1,0xba,0x88}, {0x57,0xcc,0xa3}},
+ {{0xe1,0xba,0x8a}, {0x58,0xcc,0x87}},
+ {{0xe1,0xba,0x8c}, {0x58,0xcc,0x88}},
+ {{0xe1,0xbb,0xb2}, {0x59,0xcc,0x80}},
+ {{0xc3,0x9d}, {0x59,0xcc,0x81}},
+ {{0xc5,0xb6}, {0x59,0xcc,0x82}},
+ {{0xe1,0xbb,0xb8}, {0x59,0xcc,0x83}},
+ {{0xe1,0xba,0x8e}, {0x59,0xcc,0x87}},
+ {{0xc5,0xb8}, {0x59,0xcc,0x88}},
+ {{0xe1,0xbb,0xb6}, {0x59,0xcc,0x89}},
+ {{0xe1,0xbb,0xb4}, {0x59,0xcc,0xa3}},
+ {{0xc5,0xb9}, {0x5a,0xcc,0x81}},
+ {{0xe1,0xba,0x90}, {0x5a,0xcc,0x82}},
+ {{0xc5,0xbb}, {0x5a,0xcc,0x87}},
+ {{0xc5,0xbd}, {0x5a,0xcc,0x8c}},
+ {{0xe1,0xba,0x92}, {0x5a,0xcc,0xa3}},
+ {{0xe1,0xba,0x94}, {0x5a,0xcc,0xb1}},
+ {{0xe1,0xbf,0xaf}, {0x60}},
+ {{0xc3,0xa0}, {0x61,0xcc,0x80}},
+ {{0xc3,0xa1}, {0x61,0xcc,0x81}},
+ {{0xc3,0xa2}, {0x61,0xcc,0x82}},
+ {{0xe1,0xba,0xa7}, {0x61,0xcc,0x82,0xcc,0x80}},
+ {{0xe1,0xba,0xa5}, {0x61,0xcc,0x82,0xcc,0x81}},
+ {{0xe1,0xba,0xab}, {0x61,0xcc,0x82,0xcc,0x83}},
+ {{0xe1,0xba,0xa9}, {0x61,0xcc,0x82,0xcc,0x89}},
+ {{0xc3,0xa3}, {0x61,0xcc,0x83}},
+ {{0xc4,0x81}, {0x61,0xcc,0x84}},
+ {{0xc4,0x83}, {0x61,0xcc,0x86}},
+ {{0xe1,0xba,0xb1}, {0x61,0xcc,0x86,0xcc,0x80}},
+ {{0xe1,0xba,0xaf}, {0x61,0xcc,0x86,0xcc,0x81}},
+ {{0xe1,0xba,0xb5}, {0x61,0xcc,0x86,0xcc,0x83}},
+ {{0xe1,0xba,0xb3}, {0x61,0xcc,0x86,0xcc,0x89}},
+ {{0xc7,0xa1}, {0x61,0xcc,0x87,0xcc,0x84}},
+ {{0xc3,0xa4}, {0x61,0xcc,0x88}},
+ {{0xc7,0x9f}, {0x61,0xcc,0x88,0xcc,0x84}},
+ {{0xe1,0xba,0xa3}, {0x61,0xcc,0x89}},
+ {{0xc3,0xa5}, {0x61,0xcc,0x8a}},
+ {{0xc7,0xbb}, {0x61,0xcc,0x8a,0xcc,0x81}},
+ {{0xc7,0x8e}, {0x61,0xcc,0x8c}},
+ {{0xc8,0x81}, {0x61,0xcc,0x8f}},
+ {{0xc8,0x83}, {0x61,0xcc,0x91}},
+ {{0xe1,0xba,0xa1}, {0x61,0xcc,0xa3}},
+ {{0xe1,0xba,0xad}, {0x61,0xcc,0xa3,0xcc,0x82}},
+ {{0xe1,0xba,0xb7}, {0x61,0xcc,0xa3,0xcc,0x86}},
+ {{0xe1,0xb8,0x81}, {0x61,0xcc,0xa5}},
+ {{0xc4,0x85}, {0x61,0xcc,0xa8}},
+ {{0xe1,0xb8,0x83}, {0x62,0xcc,0x87}},
+ {{0xe1,0xb8,0x85}, {0x62,0xcc,0xa3}},
+ {{0xe1,0xb8,0x87}, {0x62,0xcc,0xb1}},
+ {{0xc4,0x87}, {0x63,0xcc,0x81}},
+ {{0xc4,0x89}, {0x63,0xcc,0x82}},
+ {{0xc4,0x8b}, {0x63,0xcc,0x87}},
+ {{0xc4,0x8d}, {0x63,0xcc,0x8c}},
+ {{0xc3,0xa7}, {0x63,0xcc,0xa7}},
+ {{0xe1,0xb8,0x89}, {0x63,0xcc,0xa7,0xcc,0x81}},
+ {{0xe1,0xb8,0x8b}, {0x64,0xcc,0x87}},
+ {{0xc4,0x8f}, {0x64,0xcc,0x8c}},
+ {{0xe1,0xb8,0x8d}, {0x64,0xcc,0xa3}},
+ {{0xe1,0xb8,0x91}, {0x64,0xcc,0xa7}},
+ {{0xe1,0xb8,0x93}, {0x64,0xcc,0xad}},
+ {{0xe1,0xb8,0x8f}, {0x64,0xcc,0xb1}},
+ {{0xc3,0xa8}, {0x65,0xcc,0x80}},
+ {{0xc3,0xa9}, {0x65,0xcc,0x81}},
+ {{0xc3,0xaa}, {0x65,0xcc,0x82}},
+ {{0xe1,0xbb,0x81}, {0x65,0xcc,0x82,0xcc,0x80}},
+ {{0xe1,0xba,0xbf}, {0x65,0xcc,0x82,0xcc,0x81}},
+ {{0xe1,0xbb,0x85}, {0x65,0xcc,0x82,0xcc,0x83}},
+ {{0xe1,0xbb,0x83}, {0x65,0xcc,0x82,0xcc,0x89}},
+ {{0xe1,0xba,0xbd}, {0x65,0xcc,0x83}},
+ {{0xc4,0x93}, {0x65,0xcc,0x84}},
+ {{0xe1,0xb8,0x95}, {0x65,0xcc,0x84,0xcc,0x80}},
+ {{0xe1,0xb8,0x97}, {0x65,0xcc,0x84,0xcc,0x81}},
+ {{0xc4,0x95}, {0x65,0xcc,0x86}},
+ {{0xc4,0x97}, {0x65,0xcc,0x87}},
+ {{0xc3,0xab}, {0x65,0xcc,0x88}},
+ {{0xe1,0xba,0xbb}, {0x65,0xcc,0x89}},
+ {{0xc4,0x9b}, {0x65,0xcc,0x8c}},
+ {{0xc8,0x85}, {0x65,0xcc,0x8f}},
+ {{0xc8,0x87}, {0x65,0xcc,0x91}},
+ {{0xe1,0xba,0xb9}, {0x65,0xcc,0xa3}},
+ {{0xe1,0xbb,0x87}, {0x65,0xcc,0xa3,0xcc,0x82}},
+ {{0xe1,0xb8,0x9d}, {0x65,0xcc,0xa7,0xcc,0x86}},
+ {{0xc4,0x99}, {0x65,0xcc,0xa8}},
+ {{0xe1,0xb8,0x99}, {0x65,0xcc,0xad}},
+ {{0xe1,0xb8,0x9b}, {0x65,0xcc,0xb0}},
+ {{0xe1,0xb8,0x9f}, {0x66,0xcc,0x87}},
+ {{0xc7,0xb5}, {0x67,0xcc,0x81}},
+ {{0xc4,0x9d}, {0x67,0xcc,0x82}},
+ {{0xe1,0xb8,0xa1}, {0x67,0xcc,0x84}},
+ {{0xc4,0x9f}, {0x67,0xcc,0x86}},
+ {{0xc4,0xa1}, {0x67,0xcc,0x87}},
+ {{0xc7,0xa7}, {0x67,0xcc,0x8c}},
+ {{0xc4,0xa3}, {0x67,0xcc,0xa7}},
+ {{0xc4,0xa5}, {0x68,0xcc,0x82}},
+ {{0xe1,0xb8,0xa3}, {0x68,0xcc,0x87}},
+ {{0xe1,0xb8,0xa7}, {0x68,0xcc,0x88}},
+ {{0xe1,0xb8,0xa5}, {0x68,0xcc,0xa3}},
+ {{0xe1,0xb8,0xa9}, {0x68,0xcc,0xa7}},
+ {{0xe1,0xb8,0xab}, {0x68,0xcc,0xae}},
+ {{0xe1,0xba,0x96}, {0x68,0xcc,0xb1}},
+ {{0xc3,0xac}, {0x69,0xcc,0x80}},
+ {{0xc3,0xad}, {0x69,0xcc,0x81}},
+ {{0xc3,0xae}, {0x69,0xcc,0x82}},
+ {{0xc4,0xa9}, {0x69,0xcc,0x83}},
+ {{0xc4,0xab}, {0x69,0xcc,0x84}},
+ {{0xc4,0xad}, {0x69,0xcc,0x86}},
+ {{0xc3,0xaf}, {0x69,0xcc,0x88}},
+ {{0xe1,0xb8,0xaf}, {0x69,0xcc,0x88,0xcc,0x81}},
+ {{0xe1,0xbb,0x89}, {0x69,0xcc,0x89}},
+ {{0xc7,0x90}, {0x69,0xcc,0x8c}},
+ {{0xc8,0x89}, {0x69,0xcc,0x8f}},
+ {{0xc8,0x8b}, {0x69,0xcc,0x91}},
+ {{0xe1,0xbb,0x8b}, {0x69,0xcc,0xa3}},
+ {{0xc4,0xaf}, {0x69,0xcc,0xa8}},
+ {{0xe1,0xb8,0xad}, {0x69,0xcc,0xb0}},
+ {{0xc4,0xb5}, {0x6a,0xcc,0x82}},
+ {{0xc7,0xb0}, {0x6a,0xcc,0x8c}},
+ {{0xe1,0xb8,0xb1}, {0x6b,0xcc,0x81}},
+ {{0xc7,0xa9}, {0x6b,0xcc,0x8c}},
+ {{0xe1,0xb8,0xb3}, {0x6b,0xcc,0xa3}},
+ {{0xc4,0xb7}, {0x6b,0xcc,0xa7}},
+ {{0xe1,0xb8,0xb5}, {0x6b,0xcc,0xb1}},
+ {{0xc4,0xba}, {0x6c,0xcc,0x81}},
+ {{0xc4,0xbe}, {0x6c,0xcc,0x8c}},
+ {{0xe1,0xb8,0xb7}, {0x6c,0xcc,0xa3}},
+ {{0xe1,0xb8,0xb9}, {0x6c,0xcc,0xa3,0xcc,0x84}},
+ {{0xc4,0xbc}, {0x6c,0xcc,0xa7}},
+ {{0xe1,0xb8,0xbd}, {0x6c,0xcc,0xad}},
+ {{0xe1,0xb8,0xbb}, {0x6c,0xcc,0xb1}},
+ {{0xe1,0xb8,0xbf}, {0x6d,0xcc,0x81}},
+ {{0xe1,0xb9,0x81}, {0x6d,0xcc,0x87}},
+ {{0xe1,0xb9,0x83}, {0x6d,0xcc,0xa3}},
+ {{0xc5,0x84}, {0x6e,0xcc,0x81}},
+ {{0xc3,0xb1}, {0x6e,0xcc,0x83}},
+ {{0xe1,0xb9,0x85}, {0x6e,0xcc,0x87}},
+ {{0xc5,0x88}, {0x6e,0xcc,0x8c}},
+ {{0xe1,0xb9,0x87}, {0x6e,0xcc,0xa3}},
+ {{0xc5,0x86}, {0x6e,0xcc,0xa7}},
+ {{0xe1,0xb9,0x8b}, {0x6e,0xcc,0xad}},
+ {{0xe1,0xb9,0x89}, {0x6e,0xcc,0xb1}},
+ {{0xc3,0xb2}, {0x6f,0xcc,0x80}},
+ {{0xc3,0xb3}, {0x6f,0xcc,0x81}},
+ {{0xc3,0xb4}, {0x6f,0xcc,0x82}},
+ {{0xe1,0xbb,0x93}, {0x6f,0xcc,0x82,0xcc,0x80}},
+ {{0xe1,0xbb,0x91}, {0x6f,0xcc,0x82,0xcc,0x81}},
+ {{0xe1,0xbb,0x97}, {0x6f,0xcc,0x82,0xcc,0x83}},
+ {{0xe1,0xbb,0x95}, {0x6f,0xcc,0x82,0xcc,0x89}},
+ {{0xc3,0xb5}, {0x6f,0xcc,0x83}},
+ {{0xe1,0xb9,0x8d}, {0x6f,0xcc,0x83,0xcc,0x81}},
+ {{0xe1,0xb9,0x8f}, {0x6f,0xcc,0x83,0xcc,0x88}},
+ {{0xc5,0x8d}, {0x6f,0xcc,0x84}},
+ {{0xe1,0xb9,0x91}, {0x6f,0xcc,0x84,0xcc,0x80}},
+ {{0xe1,0xb9,0x93}, {0x6f,0xcc,0x84,0xcc,0x81}},
+ {{0xc5,0x8f}, {0x6f,0xcc,0x86}},
+ {{0xc3,0xb6}, {0x6f,0xcc,0x88}},
+ {{0xe1,0xbb,0x8f}, {0x6f,0xcc,0x89}},
+ {{0xc5,0x91}, {0x6f,0xcc,0x8b}},
+ {{0xc7,0x92}, {0x6f,0xcc,0x8c}},
+ {{0xc8,0x8d}, {0x6f,0xcc,0x8f}},
+ {{0xc8,0x8f}, {0x6f,0xcc,0x91}},
+ {{0xc6,0xa1}, {0x6f,0xcc,0x9b}},
+ {{0xe1,0xbb,0x9d}, {0x6f,0xcc,0x9b,0xcc,0x80}},
+ {{0xe1,0xbb,0x9b}, {0x6f,0xcc,0x9b,0xcc,0x81}},
+ {{0xe1,0xbb,0xa1}, {0x6f,0xcc,0x9b,0xcc,0x83}},
+ {{0xe1,0xbb,0x9f}, {0x6f,0xcc,0x9b,0xcc,0x89}},
+ {{0xe1,0xbb,0xa3}, {0x6f,0xcc,0x9b,0xcc,0xa3}},
+ {{0xe1,0xbb,0x8d}, {0x6f,0xcc,0xa3}},
+ {{0xe1,0xbb,0x99}, {0x6f,0xcc,0xa3,0xcc,0x82}},
+ {{0xc7,0xab}, {0x6f,0xcc,0xa8}},
+ {{0xc7,0xad}, {0x6f,0xcc,0xa8,0xcc,0x84}},
+ {{0xe1,0xb9,0x95}, {0x70,0xcc,0x81}},
+ {{0xe1,0xb9,0x97}, {0x70,0xcc,0x87}},
+ {{0xc5,0x95}, {0x72,0xcc,0x81}},
+ {{0xe1,0xb9,0x99}, {0x72,0xcc,0x87}},
+ {{0xc5,0x99}, {0x72,0xcc,0x8c}},
+ {{0xc8,0x91}, {0x72,0xcc,0x8f}},
+ {{0xc8,0x93}, {0x72,0xcc,0x91}},
+ {{0xe1,0xb9,0x9b}, {0x72,0xcc,0xa3}},
+ {{0xe1,0xb9,0x9d}, {0x72,0xcc,0xa3,0xcc,0x84}},
+ {{0xc5,0x97}, {0x72,0xcc,0xa7}},
+ {{0xe1,0xb9,0x9f}, {0x72,0xcc,0xb1}},
+ {{0xc5,0x9b}, {0x73,0xcc,0x81}},
+ {{0xe1,0xb9,0xa5}, {0x73,0xcc,0x81,0xcc,0x87}},
+ {{0xc5,0x9d}, {0x73,0xcc,0x82}},
+ {{0xe1,0xb9,0xa1}, {0x73,0xcc,0x87}},
+ {{0xc5,0xa1}, {0x73,0xcc,0x8c}},
+ {{0xe1,0xb9,0xa7}, {0x73,0xcc,0x8c,0xcc,0x87}},
+ {{0xe1,0xb9,0xa3}, {0x73,0xcc,0xa3}},
+ {{0xe1,0xb9,0xa9}, {0x73,0xcc,0xa3,0xcc,0x87}},
+ {{0xc5,0x9f}, {0x73,0xcc,0xa7}},
+ {{0xe1,0xb9,0xab}, {0x74,0xcc,0x87}},
+ {{0xe1,0xba,0x97}, {0x74,0xcc,0x88}},
+ {{0xc5,0xa5}, {0x74,0xcc,0x8c}},
+ {{0xe1,0xb9,0xad}, {0x74,0xcc,0xa3}},
+ {{0xc5,0xa3}, {0x74,0xcc,0xa7}},
+ {{0xe1,0xb9,0xb1}, {0x74,0xcc,0xad}},
+ {{0xe1,0xb9,0xaf}, {0x74,0xcc,0xb1}},
+ {{0xc3,0xb9}, {0x75,0xcc,0x80}},
+ {{0xc3,0xba}, {0x75,0xcc,0x81}},
+ {{0xc3,0xbb}, {0x75,0xcc,0x82}},
+ {{0xc5,0xa9}, {0x75,0xcc,0x83}},
+ {{0xe1,0xb9,0xb9}, {0x75,0xcc,0x83,0xcc,0x81}},
+ {{0xc5,0xab}, {0x75,0xcc,0x84}},
+ {{0xe1,0xb9,0xbb}, {0x75,0xcc,0x84,0xcc,0x88}},
+ {{0xc5,0xad}, {0x75,0xcc,0x86}},
+ {{0xc3,0xbc}, {0x75,0xcc,0x88}},
+ {{0xc7,0x9c}, {0x75,0xcc,0x88,0xcc,0x80}},
+ {{0xc7,0x98}, {0x75,0xcc,0x88,0xcc,0x81}},
+ {{0xc7,0x96}, {0x75,0xcc,0x88,0xcc,0x84}},
+ {{0xc7,0x9a}, {0x75,0xcc,0x88,0xcc,0x8c}},
+ {{0xe1,0xbb,0xa7}, {0x75,0xcc,0x89}},
+ {{0xc5,0xaf}, {0x75,0xcc,0x8a}},
+ {{0xc5,0xb1}, {0x75,0xcc,0x8b}},
+ {{0xc7,0x94}, {0x75,0xcc,0x8c}},
+ {{0xc8,0x95}, {0x75,0xcc,0x8f}},
+ {{0xc8,0x97}, {0x75,0xcc,0x91}},
+ {{0xc6,0xb0}, {0x75,0xcc,0x9b}},
+ {{0xe1,0xbb,0xab}, {0x75,0xcc,0x9b,0xcc,0x80}},
+ {{0xe1,0xbb,0xa9}, {0x75,0xcc,0x9b,0xcc,0x81}},
+ {{0xe1,0xbb,0xaf}, {0x75,0xcc,0x9b,0xcc,0x83}},
+ {{0xe1,0xbb,0xad}, {0x75,0xcc,0x9b,0xcc,0x89}},
+ {{0xe1,0xbb,0xb1}, {0x75,0xcc,0x9b,0xcc,0xa3}},
+ {{0xe1,0xbb,0xa5}, {0x75,0xcc,0xa3}},
+ {{0xe1,0xb9,0xb3}, {0x75,0xcc,0xa4}},
+ {{0xc5,0xb3}, {0x75,0xcc,0xa8}},
+ {{0xe1,0xb9,0xb7}, {0x75,0xcc,0xad}},
+ {{0xe1,0xb9,0xb5}, {0x75,0xcc,0xb0}},
+ {{0xe1,0xb9,0xbd}, {0x76,0xcc,0x83}},
+ {{0xe1,0xb9,0xbf}, {0x76,0xcc,0xa3}},
+ {{0xe1,0xba,0x81}, {0x77,0xcc,0x80}},
+ {{0xe1,0xba,0x83}, {0x77,0xcc,0x81}},
+ {{0xc5,0xb5}, {0x77,0xcc,0x82}},
+ {{0xe1,0xba,0x87}, {0x77,0xcc,0x87}},
+ {{0xe1,0xba,0x85}, {0x77,0xcc,0x88}},
+ {{0xe1,0xba,0x98}, {0x77,0xcc,0x8a}},
+ {{0xe1,0xba,0x89}, {0x77,0xcc,0xa3}},
+ {{0xe1,0xba,0x8b}, {0x78,0xcc,0x87}},
+ {{0xe1,0xba,0x8d}, {0x78,0xcc,0x88}},
+ {{0xe1,0xbb,0xb3}, {0x79,0xcc,0x80}},
+ {{0xc3,0xbd}, {0x79,0xcc,0x81}},
+ {{0xc5,0xb7}, {0x79,0xcc,0x82}},
+ {{0xe1,0xbb,0xb9}, {0x79,0xcc,0x83}},
+ {{0xe1,0xba,0x8f}, {0x79,0xcc,0x87}},
+ {{0xc3,0xbf}, {0x79,0xcc,0x88}},
+ {{0xe1,0xbb,0xb7}, {0x79,0xcc,0x89}},
+ {{0xe1,0xba,0x99}, {0x79,0xcc,0x8a}},
+ {{0xe1,0xbb,0xb5}, {0x79,0xcc,0xa3}},
+ {{0xc5,0xba}, {0x7a,0xcc,0x81}},
+ {{0xe1,0xba,0x91}, {0x7a,0xcc,0x82}},
+ {{0xc5,0xbc}, {0x7a,0xcc,0x87}},
+ {{0xc5,0xbe}, {0x7a,0xcc,0x8c}},
+ {{0xe1,0xba,0x93}, {0x7a,0xcc,0xa3}},
+ {{0xe1,0xba,0x95}, {0x7a,0xcc,0xb1}},
+ {{0xe1,0xbf,0xad}, {0xc2,0xa8,0xcc,0x80}},
+ {{0xe1,0xbf,0xae}, {0xc2,0xa8,0xcc,0x81}},
+ {{0xce,0x85}, {0xc2,0xa8,0xcc,0x8d}},
+ {{0xe1,0xbf,0x81}, {0xc2,0xa8,0xcd,0x82}},
+ {{0xe1,0xbf,0xbd}, {0xc2,0xb4}},
+ {{0xce,0x87}, {0xc2,0xb7}},
+ {{0xd3,0x94}, {0xc3,0x86}},
+ {{0xc7,0xbc}, {0xc3,0x86,0xcc,0x81}},
+ {{0xc7,0xa2}, {0xc3,0x86,0xcc,0x84}},
+ {{0xc7,0xbe}, {0xc3,0x98,0xcc,0x81}},
+ {{0xd3,0x95}, {0xc3,0xa6}},
+ {{0xc7,0xbd}, {0xc3,0xa6,0xcc,0x81}},
+ {{0xc7,0xa3}, {0xc3,0xa6,0xcc,0x84}},
+ {{0xc7,0xbf}, {0xc3,0xb8,0xcc,0x81}},
+ {{0xe1,0xba,0x9b}, {0xc5,0xbf,0xcc,0x87}},
+ {{0xd3,0x98}, {0xc6,0x8f}},
+ {{0xd3,0x9a}, {0xc6,0x8f,0xcc,0x88}},
+ {{0xd3,0xa8}, {0xc6,0x9f}},
+ {{0xd3,0xaa}, {0xc6,0x9f,0xcc,0x88}},
+ {{0xd3,0xa0}, {0xc6,0xb7}},
+ {{0xc7,0xae}, {0xc6,0xb7,0xcc,0x8c}},
+ {{0xd3,0x99}, {0xc9,0x99}},
+ {{0xd3,0x9b}, {0xc9,0x99,0xcc,0x88}},
+ {{0xd3,0xa9}, {0xc9,0xb5}},
+ {{0xd3,0xab}, {0xc9,0xb5,0xcc,0x88}},
+ {{0xd3,0xa1}, {0xca,0x92}},
+ {{0xc7,0xaf}, {0xca,0x92,0xcc,0x8c}},
+ {{0xcd,0xb4}, {0xca,0xb9}},
+ {{0xcd,0x80}, {0xcc,0x80}},
+ {{0xcd,0x81}, {0xcc,0x81}},
+ {{0xcc,0x90}, {0xcc,0x86,0xcc,0x87}},
+ {{0xcd,0x84}, {0xcc,0x88,0xcc,0x8d}},
+ {{0xcd,0x83}, {0xcc,0x93}},
+ {{0xe1,0xbe,0xba}, {0xce,0x91,0xcc,0x80}},
+ {{0xe1,0xbe,0xbb}, {0xce,0x91,0xcc,0x81}},
+ {{0xe1,0xbe,0xb9}, {0xce,0x91,0xcc,0x84}},
+ {{0xe1,0xbe,0xb8}, {0xce,0x91,0xcc,0x86}},
+ {{0xce,0x86}, {0xce,0x91,0xcc,0x8d}},
+ {{0xe1,0xbc,0x88}, {0xce,0x91,0xcc,0x93}},
+ {{0xe1,0xbc,0x8a}, {0xce,0x91,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbc,0x8c}, {0xce,0x91,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbc,0x8e}, {0xce,0x91,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbc,0x89}, {0xce,0x91,0xcc,0x94}},
+ {{0xe1,0xbc,0x8b}, {0xce,0x91,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbc,0x8d}, {0xce,0x91,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbc,0x8f}, {0xce,0x91,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbe,0xbc}, {0xce,0x91,0xcd,0x85}},
+ {{0xe1,0xbe,0x88}, {0xce,0x91,0xcd,0x85,0xcc,0x93}},
+ {{0xe1,0xbe,0x8a}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbe,0x8c}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbe,0x8e}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbe,0x89}, {0xce,0x91,0xcd,0x85,0xcc,0x94}},
+ {{0xe1,0xbe,0x8b}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbe,0x8d}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbe,0x8f}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0x88}, {0xce,0x95,0xcc,0x80}},
+ {{0xe1,0xbf,0x89}, {0xce,0x95,0xcc,0x81}},
+ {{0xce,0x88}, {0xce,0x95,0xcc,0x8d}},
+ {{0xe1,0xbc,0x98}, {0xce,0x95,0xcc,0x93}},
+ {{0xe1,0xbc,0x9a}, {0xce,0x95,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbc,0x9c}, {0xce,0x95,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbc,0x99}, {0xce,0x95,0xcc,0x94}},
+ {{0xe1,0xbc,0x9b}, {0xce,0x95,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbc,0x9d}, {0xce,0x95,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbf,0x8a}, {0xce,0x97,0xcc,0x80}},
+ {{0xe1,0xbf,0x8b}, {0xce,0x97,0xcc,0x81}},
+ {{0xce,0x89}, {0xce,0x97,0xcc,0x8d}},
+ {{0xe1,0xbc,0xa8}, {0xce,0x97,0xcc,0x93}},
+ {{0xe1,0xbc,0xaa}, {0xce,0x97,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbc,0xac}, {0xce,0x97,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbc,0xae}, {0xce,0x97,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbc,0xa9}, {0xce,0x97,0xcc,0x94}},
+ {{0xe1,0xbc,0xab}, {0xce,0x97,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbc,0xad}, {0xce,0x97,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbc,0xaf}, {0xce,0x97,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0x8c}, {0xce,0x97,0xcd,0x85}},
+ {{0xe1,0xbe,0x98}, {0xce,0x97,0xcd,0x85,0xcc,0x93}},
+ {{0xe1,0xbe,0x9a}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbe,0x9c}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbe,0x9e}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbe,0x99}, {0xce,0x97,0xcd,0x85,0xcc,0x94}},
+ {{0xe1,0xbe,0x9b}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbe,0x9d}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbe,0x9f}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0x9a}, {0xce,0x99,0xcc,0x80}},
+ {{0xe1,0xbf,0x9b}, {0xce,0x99,0xcc,0x81}},
+ {{0xe1,0xbf,0x99}, {0xce,0x99,0xcc,0x84}},
+ {{0xe1,0xbf,0x98}, {0xce,0x99,0xcc,0x86}},
+ {{0xce,0xaa}, {0xce,0x99,0xcc,0x88}},
+ {{0xce,0x8a}, {0xce,0x99,0xcc,0x8d}},
+ {{0xe1,0xbc,0xb8}, {0xce,0x99,0xcc,0x93}},
+ {{0xe1,0xbc,0xba}, {0xce,0x99,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbc,0xbc}, {0xce,0x99,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbc,0xbe}, {0xce,0x99,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbc,0xb9}, {0xce,0x99,0xcc,0x94}},
+ {{0xe1,0xbc,0xbb}, {0xce,0x99,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbc,0xbd}, {0xce,0x99,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbc,0xbf}, {0xce,0x99,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0xb8}, {0xce,0x9f,0xcc,0x80}},
+ {{0xe1,0xbf,0xb9}, {0xce,0x9f,0xcc,0x81}},
+ {{0xce,0x8c}, {0xce,0x9f,0xcc,0x8d}},
+ {{0xe1,0xbd,0x88}, {0xce,0x9f,0xcc,0x93}},
+ {{0xe1,0xbd,0x8a}, {0xce,0x9f,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbd,0x8c}, {0xce,0x9f,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbd,0x89}, {0xce,0x9f,0xcc,0x94}},
+ {{0xe1,0xbd,0x8b}, {0xce,0x9f,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbd,0x8d}, {0xce,0x9f,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbf,0xac}, {0xce,0xa1,0xcc,0x94}},
+ {{0xe1,0xbf,0xaa}, {0xce,0xa5,0xcc,0x80}},
+ {{0xe1,0xbf,0xab}, {0xce,0xa5,0xcc,0x81}},
+ {{0xe1,0xbf,0xa9}, {0xce,0xa5,0xcc,0x84}},
+ {{0xe1,0xbf,0xa8}, {0xce,0xa5,0xcc,0x86}},
+ {{0xce,0xab}, {0xce,0xa5,0xcc,0x88}},
+ {{0xce,0x8e}, {0xce,0xa5,0xcc,0x8d}},
+ {{0xe1,0xbd,0x99}, {0xce,0xa5,0xcc,0x94}},
+ {{0xe1,0xbd,0x9b}, {0xce,0xa5,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbd,0x9d}, {0xce,0xa5,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbd,0x9f}, {0xce,0xa5,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0xba}, {0xce,0xa9,0xcc,0x80}},
+ {{0xe1,0xbf,0xbb}, {0xce,0xa9,0xcc,0x81}},
+ {{0xce,0x8f}, {0xce,0xa9,0xcc,0x8d}},
+ {{0xe1,0xbd,0xa8}, {0xce,0xa9,0xcc,0x93}},
+ {{0xe1,0xbd,0xaa}, {0xce,0xa9,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbd,0xac}, {0xce,0xa9,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbd,0xae}, {0xce,0xa9,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbd,0xa9}, {0xce,0xa9,0xcc,0x94}},
+ {{0xe1,0xbd,0xab}, {0xce,0xa9,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbd,0xad}, {0xce,0xa9,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbd,0xaf}, {0xce,0xa9,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0xbc}, {0xce,0xa9,0xcd,0x85}},
+ {{0xe1,0xbe,0xa8}, {0xce,0xa9,0xcd,0x85,0xcc,0x93}},
+ {{0xe1,0xbe,0xaa}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbe,0xac}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbe,0xae}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbe,0xa9}, {0xce,0xa9,0xcd,0x85,0xcc,0x94}},
+ {{0xe1,0xbe,0xab}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbe,0xad}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbe,0xaf}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbd,0xb0}, {0xce,0xb1,0xcc,0x80}},
+ {{0xe1,0xbd,0xb1}, {0xce,0xb1,0xcc,0x81}},
+ {{0xe1,0xbe,0xb1}, {0xce,0xb1,0xcc,0x84}},
+ {{0xe1,0xbe,0xb0}, {0xce,0xb1,0xcc,0x86}},
+ {{0xce,0xac}, {0xce,0xb1,0xcc,0x8d}},
+ {{0xe1,0xbc,0x80}, {0xce,0xb1,0xcc,0x93}},
+ {{0xe1,0xbc,0x82}, {0xce,0xb1,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbc,0x84}, {0xce,0xb1,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbc,0x86}, {0xce,0xb1,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbc,0x81}, {0xce,0xb1,0xcc,0x94}},
+ {{0xe1,0xbc,0x83}, {0xce,0xb1,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbc,0x85}, {0xce,0xb1,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbc,0x87}, {0xce,0xb1,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbe,0xb6}, {0xce,0xb1,0xcd,0x82}},
+ {{0xe1,0xbe,0xb3}, {0xce,0xb1,0xcd,0x85}},
+ {{0xe1,0xbe,0xb2}, {0xce,0xb1,0xcd,0x85,0xcc,0x80}},
+ {{0xe1,0xbe,0xb4}, {0xce,0xb1,0xcd,0x85,0xcc,0x81}},
+ {{0xe1,0xbe,0x80}, {0xce,0xb1,0xcd,0x85,0xcc,0x93}},
+ {{0xe1,0xbe,0x82}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbe,0x84}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbe,0x86}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbe,0x81}, {0xce,0xb1,0xcd,0x85,0xcc,0x94}},
+ {{0xe1,0xbe,0x83}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbe,0x85}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbe,0x87}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbe,0xb7}, {0xce,0xb1,0xcd,0x85,0xcd,0x82}},
+ {{0xe1,0xbd,0xb2}, {0xce,0xb5,0xcc,0x80}},
+ {{0xe1,0xbd,0xb3}, {0xce,0xb5,0xcc,0x81}},
+ {{0xce,0xad}, {0xce,0xb5,0xcc,0x8d}},
+ {{0xe1,0xbc,0x90}, {0xce,0xb5,0xcc,0x93}},
+ {{0xe1,0xbc,0x92}, {0xce,0xb5,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbc,0x94}, {0xce,0xb5,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbc,0x91}, {0xce,0xb5,0xcc,0x94}},
+ {{0xe1,0xbc,0x93}, {0xce,0xb5,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbc,0x95}, {0xce,0xb5,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbd,0xb4}, {0xce,0xb7,0xcc,0x80}},
+ {{0xe1,0xbd,0xb5}, {0xce,0xb7,0xcc,0x81}},
+ {{0xce,0xae}, {0xce,0xb7,0xcc,0x8d}},
+ {{0xe1,0xbc,0xa0}, {0xce,0xb7,0xcc,0x93}},
+ {{0xe1,0xbc,0xa2}, {0xce,0xb7,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbc,0xa4}, {0xce,0xb7,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbc,0xa6}, {0xce,0xb7,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbc,0xa1}, {0xce,0xb7,0xcc,0x94}},
+ {{0xe1,0xbc,0xa3}, {0xce,0xb7,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbc,0xa5}, {0xce,0xb7,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbc,0xa7}, {0xce,0xb7,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0x86}, {0xce,0xb7,0xcd,0x82}},
+ {{0xe1,0xbf,0x83}, {0xce,0xb7,0xcd,0x85}},
+ {{0xe1,0xbf,0x82}, {0xce,0xb7,0xcd,0x85,0xcc,0x80}},
+ {{0xe1,0xbf,0x84}, {0xce,0xb7,0xcd,0x85,0xcc,0x81}},
+ {{0xe1,0xbe,0x90}, {0xce,0xb7,0xcd,0x85,0xcc,0x93}},
+ {{0xe1,0xbe,0x92}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbe,0x94}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbe,0x96}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbe,0x91}, {0xce,0xb7,0xcd,0x85,0xcc,0x94}},
+ {{0xe1,0xbe,0x93}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbe,0x95}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbe,0x97}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0x87}, {0xce,0xb7,0xcd,0x85,0xcd,0x82}},
+ {{0xe1,0xbe,0xbe}, {0xce,0xb9}},
+ {{0xe1,0xbd,0xb6}, {0xce,0xb9,0xcc,0x80}},
+ {{0xe1,0xbd,0xb7}, {0xce,0xb9,0xcc,0x81}},
+ {{0xe1,0xbf,0x91}, {0xce,0xb9,0xcc,0x84}},
+ {{0xe1,0xbf,0x90}, {0xce,0xb9,0xcc,0x86}},
+ {{0xcf,0x8a}, {0xce,0xb9,0xcc,0x88}},
+ {{0xe1,0xbf,0x92}, {0xce,0xb9,0xcc,0x88,0xcc,0x80}},
+ {{0xe1,0xbf,0x93}, {0xce,0xb9,0xcc,0x88,0xcc,0x81}},
+ {{0xce,0x90}, {0xce,0xb9,0xcc,0x88,0xcc,0x8d}},
+ {{0xe1,0xbf,0x97}, {0xce,0xb9,0xcc,0x88,0xcd,0x82}},
+ {{0xce,0xaf}, {0xce,0xb9,0xcc,0x8d}},
+ {{0xe1,0xbc,0xb0}, {0xce,0xb9,0xcc,0x93}},
+ {{0xe1,0xbc,0xb2}, {0xce,0xb9,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbc,0xb4}, {0xce,0xb9,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbc,0xb6}, {0xce,0xb9,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbc,0xb1}, {0xce,0xb9,0xcc,0x94}},
+ {{0xe1,0xbc,0xb3}, {0xce,0xb9,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbc,0xb5}, {0xce,0xb9,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbc,0xb7}, {0xce,0xb9,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0x96}, {0xce,0xb9,0xcd,0x82}},
+ {{0xe1,0xbd,0xb8}, {0xce,0xbf,0xcc,0x80}},
+ {{0xe1,0xbd,0xb9}, {0xce,0xbf,0xcc,0x81}},
+ {{0xcf,0x8c}, {0xce,0xbf,0xcc,0x8d}},
+ {{0xe1,0xbd,0x80}, {0xce,0xbf,0xcc,0x93}},
+ {{0xe1,0xbd,0x82}, {0xce,0xbf,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbd,0x84}, {0xce,0xbf,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbd,0x81}, {0xce,0xbf,0xcc,0x94}},
+ {{0xe1,0xbd,0x83}, {0xce,0xbf,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbd,0x85}, {0xce,0xbf,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbf,0xb4}, {0xce,0xbf,0xcd,0x85,0xcc,0x81}},
+ {{0xe1,0xbf,0xa4}, {0xcf,0x81,0xcc,0x93}},
+ {{0xe1,0xbf,0xa5}, {0xcf,0x81,0xcc,0x94}},
+ {{0xe1,0xbd,0xba}, {0xcf,0x85,0xcc,0x80}},
+ {{0xe1,0xbd,0xbb}, {0xcf,0x85,0xcc,0x81}},
+ {{0xe1,0xbf,0xa1}, {0xcf,0x85,0xcc,0x84}},
+ {{0xe1,0xbf,0xa0}, {0xcf,0x85,0xcc,0x86}},
+ {{0xcf,0x8b}, {0xcf,0x85,0xcc,0x88}},
+ {{0xe1,0xbf,0xa2}, {0xcf,0x85,0xcc,0x88,0xcc,0x80}},
+ {{0xe1,0xbf,0xa3}, {0xcf,0x85,0xcc,0x88,0xcc,0x81}},
+ {{0xce,0xb0}, {0xcf,0x85,0xcc,0x88,0xcc,0x8d}},
+ {{0xe1,0xbf,0xa7}, {0xcf,0x85,0xcc,0x88,0xcd,0x82}},
+ {{0xcf,0x8d}, {0xcf,0x85,0xcc,0x8d}},
+ {{0xe1,0xbd,0x90}, {0xcf,0x85,0xcc,0x93}},
+ {{0xe1,0xbd,0x92}, {0xcf,0x85,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbd,0x94}, {0xcf,0x85,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbd,0x96}, {0xcf,0x85,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbd,0x91}, {0xcf,0x85,0xcc,0x94}},
+ {{0xe1,0xbd,0x93}, {0xcf,0x85,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbd,0x95}, {0xcf,0x85,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbd,0x97}, {0xcf,0x85,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0xa6}, {0xcf,0x85,0xcd,0x82}},
+ {{0xe1,0xbd,0xbc}, {0xcf,0x89,0xcc,0x80}},
+ {{0xe1,0xbd,0xbd}, {0xcf,0x89,0xcc,0x81}},
+ {{0xcf,0x8e}, {0xcf,0x89,0xcc,0x8d}},
+ {{0xe1,0xbd,0xa0}, {0xcf,0x89,0xcc,0x93}},
+ {{0xe1,0xbd,0xa2}, {0xcf,0x89,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbd,0xa4}, {0xcf,0x89,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbd,0xa6}, {0xcf,0x89,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbd,0xa1}, {0xcf,0x89,0xcc,0x94}},
+ {{0xe1,0xbd,0xa3}, {0xcf,0x89,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbd,0xa5}, {0xcf,0x89,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbd,0xa7}, {0xcf,0x89,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0xb6}, {0xcf,0x89,0xcd,0x82}},
+ {{0xe1,0xbf,0xb3}, {0xcf,0x89,0xcd,0x85}},
+ {{0xe1,0xbf,0xb2}, {0xcf,0x89,0xcd,0x85,0xcc,0x80}},
+ {{0xe1,0xbe,0xa0}, {0xcf,0x89,0xcd,0x85,0xcc,0x93}},
+ {{0xe1,0xbe,0xa2}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
+ {{0xe1,0xbe,0xa4}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
+ {{0xe1,0xbe,0xa6}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
+ {{0xe1,0xbe,0xa1}, {0xcf,0x89,0xcd,0x85,0xcc,0x94}},
+ {{0xe1,0xbe,0xa3}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
+ {{0xe1,0xbe,0xa5}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
+ {{0xe1,0xbe,0xa7}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
+ {{0xe1,0xbf,0xb7}, {0xcf,0x89,0xcd,0x85,0xcd,0x82}},
+ {{0xcf,0x94}, {0xcf,0x92,0xcc,0x88}},
+ {{0xcf,0x93}, {0xcf,0x92,0xcc,0x8d}},
+ {{0xd0,0x87}, {0xd0,0x86,0xcc,0x88}},
+ {{0xd3,0x90}, {0xd0,0x90,0xcc,0x86}},
+ {{0xd3,0x92}, {0xd0,0x90,0xcc,0x88}},
+ {{0xd0,0x83}, {0xd0,0x93,0xcc,0x81}},
+ {{0xd3,0x96}, {0xd0,0x95,0xcc,0x86}},
+ {{0xd0,0x81}, {0xd0,0x95,0xcc,0x88}},
+ {{0xd3,0x81}, {0xd0,0x96,0xcc,0x86}},
+ {{0xd3,0x9c}, {0xd0,0x96,0xcc,0x88}},
+ {{0xd3,0x9e}, {0xd0,0x97,0xcc,0x88}},
+ {{0xd3,0xa2}, {0xd0,0x98,0xcc,0x84}},
+ {{0xd0,0x99}, {0xd0,0x98,0xcc,0x86}},
+ {{0xd3,0xa4}, {0xd0,0x98,0xcc,0x88}},
+ {{0xd0,0x8c}, {0xd0,0x9a,0xcc,0x81}},
+ {{0xd3,0xa6}, {0xd0,0x9e,0xcc,0x88}},
+ {{0xd3,0xae}, {0xd0,0xa3,0xcc,0x84}},
+ {{0xd0,0x8e}, {0xd0,0xa3,0xcc,0x86}},
+ {{0xd3,0xb0}, {0xd0,0xa3,0xcc,0x88}},
+ {{0xd3,0xb2}, {0xd0,0xa3,0xcc,0x8b}},
+ {{0xd3,0xb4}, {0xd0,0xa7,0xcc,0x88}},
+ {{0xd3,0xb8}, {0xd0,0xab,0xcc,0x88}},
+ {{0xd3,0x91}, {0xd0,0xb0,0xcc,0x86}},
+ {{0xd3,0x93}, {0xd0,0xb0,0xcc,0x88}},
+ {{0xd1,0x93}, {0xd0,0xb3,0xcc,0x81}},
+ {{0xd3,0x97}, {0xd0,0xb5,0xcc,0x86}},
+ {{0xd1,0x91}, {0xd0,0xb5,0xcc,0x88}},
+ {{0xd3,0x82}, {0xd0,0xb6,0xcc,0x86}},
+ {{0xd3,0x9d}, {0xd0,0xb6,0xcc,0x88}},
+ {{0xd3,0x9f}, {0xd0,0xb7,0xcc,0x88}},
+ {{0xd3,0xa3}, {0xd0,0xb8,0xcc,0x84}},
+ {{0xd0,0xb9}, {0xd0,0xb8,0xcc,0x86}},
+ {{0xd3,0xa5}, {0xd0,0xb8,0xcc,0x88}},
+ {{0xd1,0x9c}, {0xd0,0xba,0xcc,0x81}},
+ {{0xd3,0xa7}, {0xd0,0xbe,0xcc,0x88}},
+ {{0xd3,0xaf}, {0xd1,0x83,0xcc,0x84}},
+ {{0xd1,0x9e}, {0xd1,0x83,0xcc,0x86}},
+ {{0xd3,0xb1}, {0xd1,0x83,0xcc,0x88}},
+ {{0xd3,0xb3}, {0xd1,0x83,0xcc,0x8b}},
+ {{0xd3,0xb5}, {0xd1,0x87,0xcc,0x88}},
+ {{0xd3,0xb9}, {0xd1,0x8b,0xcc,0x88}},
+ {{0xd1,0x97}, {0xd1,0x96,0xcc,0x88}},
+ {{0xd1,0xb6}, {0xd1,0xb4,0xcc,0x8f}},
+ {{0xd1,0xb7}, {0xd1,0xb5,0xcc,0x8f}},
+ {{0xef,0xac,0xae}, {0xd7,0x90,0xd6,0xb7}},
+ {{0xef,0xac,0xaf}, {0xd7,0x90,0xd6,0xb8}},
+ {{0xef,0xac,0xb0}, {0xd7,0x90,0xd6,0xbc}},
+ {{0xef,0xac,0xb1}, {0xd7,0x91,0xd6,0xbc}},
+ {{0xef,0xad,0x8c}, {0xd7,0x91,0xd6,0xbf}},
+ {{0xef,0xac,0xb2}, {0xd7,0x92,0xd6,0xbc}},
+ {{0xef,0xac,0xb3}, {0xd7,0x93,0xd6,0xbc}},
+ {{0xef,0xac,0xb4}, {0xd7,0x94,0xd6,0xbc}},
+ {{0xef,0xad,0x8b}, {0xd7,0x95,0xd6,0xb9}},
+ {{0xef,0xac,0xb5}, {0xd7,0x95,0xd6,0xbc}},
+ {{0xef,0xac,0xb6}, {0xd7,0x96,0xd6,0xbc}},
+ {{0xef,0xac,0xb8}, {0xd7,0x98,0xd6,0xbc}},
+ {{0xef,0xac,0xb9}, {0xd7,0x99,0xd6,0xbc}},
+ {{0xef,0xac,0xba}, {0xd7,0x9a,0xd6,0xbc}},
+ {{0xef,0xac,0xbb}, {0xd7,0x9b,0xd6,0xbc}},
+ {{0xef,0xad,0x8d}, {0xd7,0x9b,0xd6,0xbf}},
+ {{0xef,0xac,0xbc}, {0xd7,0x9c,0xd6,0xbc}},
+ {{0xef,0xac,0xbe}, {0xd7,0x9e,0xd6,0xbc}},
+ {{0xef,0xad,0x80}, {0xd7,0xa0,0xd6,0xbc}},
+ {{0xef,0xad,0x81}, {0xd7,0xa1,0xd6,0xbc}},
+ {{0xef,0xad,0x83}, {0xd7,0xa3,0xd6,0xbc}},
+ {{0xef,0xad,0x84}, {0xd7,0xa4,0xd6,0xbc}},
+ {{0xef,0xad,0x8e}, {0xd7,0xa4,0xd6,0xbf}},
+ {{0xef,0xad,0x86}, {0xd7,0xa6,0xd6,0xbc}},
+ {{0xef,0xad,0x87}, {0xd7,0xa7,0xd6,0xbc}},
+ {{0xef,0xad,0x88}, {0xd7,0xa8,0xd6,0xbc}},
+ {{0xef,0xad,0x89}, {0xd7,0xa9,0xd6,0xbc}},
+ {{0xef,0xac,0xac}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x81}},
+ {{0xef,0xac,0xad}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x82}},
+ {{0xef,0xac,0xaa}, {0xd7,0xa9,0xd7,0x81}},
+ {{0xef,0xac,0xab}, {0xd7,0xa9,0xd7,0x82}},
+ {{0xef,0xad,0x8a}, {0xd7,0xaa,0xd6,0xbc}},
+ {{0xef,0xac,0x9f}, {0xd7,0xb2,0xd6,0xb7}},
+ {{0xe0,0xa5,0x98}, {0xe0,0xa4,0x95,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa5,0x99}, {0xe0,0xa4,0x96,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa5,0x9a}, {0xe0,0xa4,0x97,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa5,0x9b}, {0xe0,0xa4,0x9c,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa5,0x9c}, {0xe0,0xa4,0xa1,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa5,0x9d}, {0xe0,0xa4,0xa2,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa4,0xa9}, {0xe0,0xa4,0xa8,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa5,0x9e}, {0xe0,0xa4,0xab,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa5,0x9f}, {0xe0,0xa4,0xaf,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa4,0xb1}, {0xe0,0xa4,0xb0,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa4,0xb4}, {0xe0,0xa4,0xb3,0xe0,0xa4,0xbc}},
+ {{0xe0,0xa7,0x9c}, {0xe0,0xa6,0xa1,0xe0,0xa6,0xbc}},
+ {{0xe0,0xa7,0x9d}, {0xe0,0xa6,0xa2,0xe0,0xa6,0xbc}},
+ {{0xe0,0xa6,0xb0}, {0xe0,0xa6,0xac,0xe0,0xa6,0xbc}},
+ {{0xe0,0xa7,0x9f}, {0xe0,0xa6,0xaf,0xe0,0xa6,0xbc}},
+ {{0xe0,0xa7,0x8b}, {0xe0,0xa7,0x87,0xe0,0xa6,0xbe}},
+ {{0xe0,0xa7,0x8c}, {0xe0,0xa7,0x87,0xe0,0xa7,0x97}},
+ {{0xe0,0xa9,0x99}, {0xe0,0xa8,0x96,0xe0,0xa8,0xbc}},
+ {{0xe0,0xa9,0x9a}, {0xe0,0xa8,0x97,0xe0,0xa8,0xbc}},
+ {{0xe0,0xa9,0x9b}, {0xe0,0xa8,0x9c,0xe0,0xa8,0xbc}},
+ {{0xe0,0xa9,0x9c}, {0xe0,0xa8,0xa1,0xe0,0xa8,0xbc}},
+ {{0xe0,0xa9,0x9e}, {0xe0,0xa8,0xab,0xe0,0xa8,0xbc}},
+ {{0xe0,0xad,0x9c}, {0xe0,0xac,0xa1,0xe0,0xac,0xbc}},
+ {{0xe0,0xad,0x9d}, {0xe0,0xac,0xa2,0xe0,0xac,0xbc}},
+ {{0xe0,0xad,0x9f}, {0xe0,0xac,0xaf,0xe0,0xac,0xbc}},
+ {{0xe0,0xad,0x8b}, {0xe0,0xad,0x87,0xe0,0xac,0xbe}},
+ {{0xe0,0xad,0x88}, {0xe0,0xad,0x87,0xe0,0xad,0x96}},
+ {{0xe0,0xad,0x8c}, {0xe0,0xad,0x87,0xe0,0xad,0x97}},
+ {{0xe0,0xae,0x94}, {0xe0,0xae,0x92,0xe0,0xaf,0x97}},
+ {{0xe0,0xaf,0x8a}, {0xe0,0xaf,0x86,0xe0,0xae,0xbe}},
+ {{0xe0,0xaf,0x8c}, {0xe0,0xaf,0x86,0xe0,0xaf,0x97}},
+ {{0xe0,0xaf,0x8b}, {0xe0,0xaf,0x87,0xe0,0xae,0xbe}},
+ {{0xe0,0xb1,0x88}, {0xe0,0xb1,0x86,0xe0,0xb1,0x96}},
+ {{0xe0,0xb3,0x80}, {0xe0,0xb2,0xbf,0xe0,0xb3,0x95}},
+ {{0xe0,0xb3,0x8a}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82}},
+ {{0xe0,0xb3,0x8b}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82,0xe0,0xb3,0x95}},
+ {{0xe0,0xb3,0x87}, {0xe0,0xb3,0x86,0xe0,0xb3,0x95}},
+ {{0xe0,0xb3,0x88}, {0xe0,0xb3,0x86,0xe0,0xb3,0x96}},
+ {{0xe0,0xb5,0x8a}, {0xe0,0xb5,0x86,0xe0,0xb4,0xbe}},
+ {{0xe0,0xb5,0x8c}, {0xe0,0xb5,0x86,0xe0,0xb5,0x97}},
+ {{0xe0,0xb5,0x8b}, {0xe0,0xb5,0x87,0xe0,0xb4,0xbe}},
+ {{0xe0,0xb8,0xb3}, {0xe0,0xb9,0x8d,0xe0,0xb8,0xb2}},
+ {{0xe0,0xba,0xb3}, {0xe0,0xbb,0x8d,0xe0,0xba,0xb2}},
+ {{0xe0,0xbd,0xa9}, {0xe0,0xbd,0x80,0xe0,0xbe,0xb5}},
+ {{0xe0,0xbd,0x83}, {0xe0,0xbd,0x82,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbd,0x8d}, {0xe0,0xbd,0x8c,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbd,0x92}, {0xe0,0xbd,0x91,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbd,0x97}, {0xe0,0xbd,0x96,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbd,0x9c}, {0xe0,0xbd,0x9b,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbd,0xb3}, {0xe0,0xbd,0xb2,0xe0,0xbd,0xb1}},
+ {{0xe0,0xbd,0xb5}, {0xe0,0xbd,0xb4,0xe0,0xbd,0xb1}},
+ {{0xe0,0xbe,0x81}, {0xe0,0xbe,0x80,0xe0,0xbd,0xb1}},
+ {{0xe0,0xbe,0xb9}, {0xe0,0xbe,0x90,0xe0,0xbe,0xb5}},
+ {{0xe0,0xbe,0x93}, {0xe0,0xbe,0x92,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbe,0x9d}, {0xe0,0xbe,0x9c,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbe,0xa2}, {0xe0,0xbe,0xa1,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbe,0xa7}, {0xe0,0xbe,0xa6,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbe,0xac}, {0xe0,0xbe,0xab,0xe0,0xbe,0xb7}},
+ {{0xe0,0xbd,0xb6}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80}},
+ {{0xe0,0xbd,0xb7}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}},
+ {{0xe0,0xbd,0xb8}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80}},
+ {{0xe0,0xbd,0xb9}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}},
+ {{0xe1,0xbf,0x8d}, {0xe1,0xbe,0xbf,0xcc,0x80}},
+ {{0xe1,0xbf,0x8e}, {0xe1,0xbe,0xbf,0xcc,0x81}},
+ {{0xe1,0xbf,0x8f}, {0xe1,0xbe,0xbf,0xcd,0x82}},
+ {{0xe1,0xbf,0x9d}, {0xe1,0xbf,0xbe,0xcc,0x80}},
+ {{0xe1,0xbf,0x9e}, {0xe1,0xbf,0xbe,0xcc,0x81}},
+ {{0xe1,0xbf,0x9f}, {0xe1,0xbf,0xbe,0xcd,0x82}},
+ {{0xe3,0x82,0x94}, {0xe3,0x81,0x86,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x8c}, {0xe3,0x81,0x8b,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x8e}, {0xe3,0x81,0x8d,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x90}, {0xe3,0x81,0x8f,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x92}, {0xe3,0x81,0x91,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x94}, {0xe3,0x81,0x93,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x96}, {0xe3,0x81,0x95,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x98}, {0xe3,0x81,0x97,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x9a}, {0xe3,0x81,0x99,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x9c}, {0xe3,0x81,0x9b,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0x9e}, {0xe3,0x81,0x9d,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xa0}, {0xe3,0x81,0x9f,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xa2}, {0xe3,0x81,0xa1,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xa5}, {0xe3,0x81,0xa4,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xa7}, {0xe3,0x81,0xa6,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xa9}, {0xe3,0x81,0xa8,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xb0}, {0xe3,0x81,0xaf,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xb1}, {0xe3,0x81,0xaf,0xe3,0x82,0x9a}},
+ {{0xe3,0x81,0xb3}, {0xe3,0x81,0xb2,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xb4}, {0xe3,0x81,0xb2,0xe3,0x82,0x9a}},
+ {{0xe3,0x81,0xb6}, {0xe3,0x81,0xb5,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xb7}, {0xe3,0x81,0xb5,0xe3,0x82,0x9a}},
+ {{0xe3,0x81,0xb9}, {0xe3,0x81,0xb8,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xba}, {0xe3,0x81,0xb8,0xe3,0x82,0x9a}},
+ {{0xe3,0x81,0xbc}, {0xe3,0x81,0xbb,0xe3,0x82,0x99}},
+ {{0xe3,0x81,0xbd}, {0xe3,0x81,0xbb,0xe3,0x82,0x9a}},
+ {{0xe3,0x82,0x9e}, {0xe3,0x82,0x9d,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0xb4}, {0xe3,0x82,0xa6,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xac}, {0xe3,0x82,0xab,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xae}, {0xe3,0x82,0xad,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xb0}, {0xe3,0x82,0xaf,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xb2}, {0xe3,0x82,0xb1,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xb4}, {0xe3,0x82,0xb3,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xb6}, {0xe3,0x82,0xb5,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xb8}, {0xe3,0x82,0xb7,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xba}, {0xe3,0x82,0xb9,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xbc}, {0xe3,0x82,0xbb,0xe3,0x82,0x99}},
+ {{0xe3,0x82,0xbe}, {0xe3,0x82,0xbd,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x80}, {0xe3,0x82,0xbf,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x82}, {0xe3,0x83,0x81,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x85}, {0xe3,0x83,0x84,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x87}, {0xe3,0x83,0x86,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x89}, {0xe3,0x83,0x88,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x90}, {0xe3,0x83,0x8f,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x91}, {0xe3,0x83,0x8f,0xe3,0x82,0x9a}},
+ {{0xe3,0x83,0x93}, {0xe3,0x83,0x92,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x94}, {0xe3,0x83,0x92,0xe3,0x82,0x9a}},
+ {{0xe3,0x83,0x96}, {0xe3,0x83,0x95,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x97}, {0xe3,0x83,0x95,0xe3,0x82,0x9a}},
+ {{0xe3,0x83,0x99}, {0xe3,0x83,0x98,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x9a}, {0xe3,0x83,0x98,0xe3,0x82,0x9a}},
+ {{0xe3,0x83,0x9c}, {0xe3,0x83,0x9b,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0x9d}, {0xe3,0x83,0x9b,0xe3,0x82,0x9a}},
+ {{0xe3,0x83,0xb7}, {0xe3,0x83,0xaf,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0xb8}, {0xe3,0x83,0xb0,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0xb9}, {0xe3,0x83,0xb1,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0xba}, {0xe3,0x83,0xb2,0xe3,0x82,0x99}},
+ {{0xe3,0x83,0xbe}, {0xe3,0x83,0xbd,0xe3,0x82,0x99}},
+};
+#endif /* UNICODE_NORMALIZATION */
+#endif /* UTF8_INPUT_ENABLE */
+
+#ifdef SHIFTJIS_CP932
+const unsigned short shiftjis_cp932[3][189] = {
+ {
+ 0xEEEF, 0xEEF0, 0xEEF1, 0xEEF2, 0xEEF3, 0xEEF4, 0xEEF5, 0xEEF6,
+ 0xEEF7, 0xEEF8, 0x8754, 0x8755, 0x8756, 0x8757, 0x8758, 0x8759,
+ 0x875A, 0x875B, 0x875C, 0x875D, 0x81CA, 0xEEFA, 0xEEFB, 0xEEFC,
+ 0x878A, 0x8782, 0x8784, 0x81E6, 0xED40, 0xED41, 0xED42, 0xED43,
+ 0xED44, 0xED45, 0xED46, 0xED47, 0xED48, 0xED49, 0xED4A, 0xED4B,
+ 0xED4C, 0xED4D, 0xED4E, 0xED4F, 0xED50, 0xED51, 0xED52, 0xED53,
+ 0xED54, 0xED55, 0xED56, 0xED57, 0xED58, 0xED59, 0xED5A, 0xED5B,
+ 0xED5C, 0xED5D, 0xED5E, 0xED5F, 0xED60, 0xED61, 0xED62, 0,
+ 0xED63, 0xED64, 0xED65, 0xED66, 0xED67, 0xED68, 0xED69, 0xED6A,
+ 0xED6B, 0xED6C, 0xED6D, 0xED6E, 0xED6F, 0xED70, 0xED71, 0xED72,
+ 0xED73, 0xED74, 0xED75, 0xED76, 0xED77, 0xED78, 0xED79, 0xED7A,
+ 0xED7B, 0xED7C, 0xED7D, 0xED7E, 0xED80, 0xED81, 0xED82, 0xED83,
+ 0xED84, 0xED85, 0xED86, 0xED87, 0xED88, 0xED89, 0xED8A, 0xED8B,
+ 0xED8C, 0xED8D, 0xED8E, 0xED8F, 0xED90, 0xED91, 0xED92, 0xED93,
+ 0xED94, 0xED95, 0xED96, 0xED97, 0xED98, 0xED99, 0xED9A, 0xED9B,
+ 0xED9C, 0xED9D, 0xED9E, 0xED9F, 0xEDA0, 0xEDA1, 0xEDA2, 0xEDA3,
+ 0xEDA4, 0xEDA5, 0xEDA6, 0xEDA7, 0xEDA8, 0xEDA9, 0xEDAA, 0xEDAB,
+ 0xEDAC, 0xEDAD, 0xEDAE, 0xEDAF, 0xEDB0, 0xEDB1, 0xEDB2, 0xEDB3,
+ 0xEDB4, 0xEDB5, 0xEDB6, 0xEDB7, 0xEDB8, 0xEDB9, 0xEDBA, 0xEDBB,
+ 0xEDBC, 0xEDBD, 0xEDBE, 0xEDBF, 0xEDC0, 0xEDC1, 0xEDC2, 0xEDC3,
+ 0xEDC4, 0xEDC5, 0xEDC6, 0xEDC7, 0xEDC8, 0xEDC9, 0xEDCA, 0xEDCB,
+ 0xEDCC, 0xEDCD, 0xEDCE, 0xEDCF, 0xEDD0, 0xEDD1, 0xEDD2, 0xEDD3,
+ 0xEDD4, 0xEDD5, 0xEDD6, 0xEDD7, 0xEDD8, 0xEDD9, 0xEDDA, 0xEDDB,
+ 0xEDDC, 0xEDDD, 0xEDDE, 0xEDDF, 0xEDE0,
+ },
+ {
+ 0xEDE1, 0xEDE2, 0xEDE3, 0xEDE4, 0xEDE5, 0xEDE6, 0xEDE7, 0xEDE8,
+ 0xEDE9, 0xEDEA, 0xEDEB, 0xEDEC, 0xEDED, 0xEDEE, 0xEDEF, 0xEDF0,
+ 0xEDF1, 0xEDF2, 0xEDF3, 0xEDF4, 0xEDF5, 0xEDF6, 0xEDF7, 0xEDF8,
+ 0xEDF9, 0xEDFA, 0xEDFB, 0xEDFC, 0xEE40, 0xEE41, 0xEE42, 0xEE43,
+ 0xEE44, 0xEE45, 0xEE46, 0xEE47, 0xEE48, 0xEE49, 0xEE4A, 0xEE4B,
+ 0xEE4C, 0xEE4D, 0xEE4E, 0xEE4F, 0xEE50, 0xEE51, 0xEE52, 0xEE53,
+ 0xEE54, 0xEE55, 0xEE56, 0xEE57, 0xEE58, 0xEE59, 0xEE5A, 0xEE5B,
+ 0xEE5C, 0xEE5D, 0xEE5E, 0xEE5F, 0xEE60, 0xEE61, 0xEE62, 0,
+ 0xEE63, 0xEE64, 0xEE65, 0xEE66, 0xEE67, 0xEE68, 0xEE69, 0xEE6A,
+ 0xEE6B, 0xEE6C, 0xEE6D, 0xEE6E, 0xEE6F, 0xEE70, 0xEE71, 0xEE72,
+ 0xEE73, 0xEE74, 0xEE75, 0xEE76, 0xEE77, 0xEE78, 0xEE79, 0xEE7A,
+ 0xEE7B, 0xEE7C, 0xEE7D, 0xEE7E, 0xEE80, 0xEE81, 0xEE82, 0xEE83,
+ 0xEE84, 0xEE85, 0xEE86, 0xEE87, 0xEE88, 0xEE89, 0xEE8A, 0xEE8B,
+ 0xEE8C, 0xEE8D, 0xEE8E, 0xEE8F, 0xEE90, 0xEE91, 0xEE92, 0xEE93,
+ 0xEE94, 0xEE95, 0xEE96, 0xEE97, 0xEE98, 0xEE99, 0xEE9A, 0xEE9B,
+ 0xEE9C, 0xEE9D, 0xEE9E, 0xEE9F, 0xEEA0, 0xEEA1, 0xEEA2, 0xEEA3,
+ 0xEEA4, 0xEEA5, 0xEEA6, 0xEEA7, 0xEEA8, 0xEEA9, 0xEEAA, 0xEEAB,
+ 0xEEAC, 0xEEAD, 0xEEAE, 0xEEAF, 0xEEB0, 0xEEB1, 0xEEB2, 0xEEB3,
+ 0xEEB4, 0xEEB5, 0xEEB6, 0xEEB7, 0xEEB8, 0xEEB9, 0xEEBA, 0xEEBB,
+ 0xEEBC, 0xEEBD, 0xEEBE, 0xEEBF, 0xEEC0, 0xEEC1, 0xEEC2, 0xEEC3,
+ 0xEEC4, 0xEEC5, 0xEEC6, 0xEEC7, 0xEEC8, 0xEEC9, 0xEECA, 0xEECB,
+ 0xEECC, 0xEECD, 0xEECE, 0xEECF, 0xEED0, 0xEED1, 0xEED2, 0xEED3,
+ 0xEED4, 0xEED5, 0xEED6, 0xEED7, 0xEED8, 0xEED9, 0xEEDA, 0xEEDB,
+ 0xEEDC, 0xEEDD, 0xEEDE, 0xEEDF, 0xEEE0,
+ },
+ {
+ 0xEEE1, 0xEEE2, 0xEEE3, 0xEEE4, 0xEEE5, 0xEEE6, 0xEEE7, 0xEEE8,
+ 0xEEE9, 0xEEEA, 0xEEEB, 0xEEEC, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ },
+};
+const unsigned short cp932inv[2][189] = {
+ {
+ 0xFA5C, 0xFA5D, 0xFA5E, 0xFA5F, 0xFA60, 0xFA61, 0xFA62, 0xFA63,
+ 0xFA64, 0xFA65, 0xFA66, 0xFA67, 0xFA68, 0xFA69, 0xFA6A, 0xFA6B,
+ 0xFA6C, 0xFA6D, 0xFA6E, 0xFA6F, 0xFA70, 0xFA71, 0xFA72, 0xFA73,
+ 0xFA74, 0xFA75, 0xFA76, 0xFA77, 0xFA78, 0xFA79, 0xFA7A, 0xFA7B,
+ 0xFA7C, 0xFA7D, 0xFA7E, 0xFA80, 0xFA81, 0xFA82, 0xFA83, 0xFA84,
+ 0xFA85, 0xFA86, 0xFA87, 0xFA88, 0xFA89, 0xFA8A, 0xFA8B, 0xFA8C,
+ 0xFA8D, 0xFA8E, 0xFA8F, 0xFA90, 0xFA91, 0xFA92, 0xFA93, 0xFA94,
+ 0xFA95, 0xFA96, 0xFA97, 0xFA98, 0xFA99, 0xFA9A, 0xFA9B, 0,
+ 0xFA9C, 0xFA9D, 0xFA9E, 0xFA9F, 0xFAA0, 0xFAA1, 0xFAA2, 0xFAA3,
+ 0xFAA4, 0xFAA5, 0xFAA6, 0xFAA7, 0xFAA8, 0xFAA9, 0xFAAA, 0xFAAB,
+ 0xFAAC, 0xFAAD, 0xFAAE, 0xFAAF, 0xFAB0, 0xFAB1, 0xFAB2, 0xFAB3,
+ 0xFAB4, 0xFAB5, 0xFAB6, 0xFAB7, 0xFAB8, 0xFAB9, 0xFABA, 0xFABB,
+ 0xFABC, 0xFABD, 0xFABE, 0xFABF, 0xFAC0, 0xFAC1, 0xFAC2, 0xFAC3,
+ 0xFAC4, 0xFAC5, 0xFAC6, 0xFAC7, 0xFAC8, 0xFAC9, 0xFACA, 0xFACB,
+ 0xFACC, 0xFACD, 0xFACE, 0xFACF, 0xFAD0, 0xFAD1, 0xFAD2, 0xFAD3,
+ 0xFAD4, 0xFAD5, 0xFAD6, 0xFAD7, 0xFAD8, 0xFAD9, 0xFADA, 0xFADB,
+ 0xFADC, 0xFADD, 0xFADE, 0xFADF, 0xFAE0, 0xFAE1, 0xFAE2, 0xFAE3,
+ 0xFAE4, 0xFAE5, 0xFAE6, 0xFAE7, 0xFAE8, 0xFAE9, 0xFAEA, 0xFAEB,
+ 0xFAEC, 0xFAED, 0xFAEE, 0xFAEF, 0xFAF0, 0xFAF1, 0xFAF2, 0xFAF3,
+ 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, 0xFAFA, 0xFAFB,
+ 0xFAFC, 0xFB40, 0xFB41, 0xFB42, 0xFB43, 0xFB44, 0xFB45, 0xFB46,
+ 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C, 0xFB4D, 0xFB4E,
+ 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55, 0xFB56,
+ 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B,
+ },
+ {
+ 0xFB5C, 0xFB5D, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63,
+ 0xFB64, 0xFB65, 0xFB66, 0xFB67, 0xFB68, 0xFB69, 0xFB6A, 0xFB6B,
+ 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71, 0xFB72, 0xFB73,
+ 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79, 0xFB7A, 0xFB7B,
+ 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80, 0xFB81, 0xFB82, 0xFB83, 0xFB84,
+ 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B, 0xFB8C,
+ 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94,
+ 0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0,
+ 0xFB9C, 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3,
+ 0xFBA4, 0xFBA5, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB,
+ 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF, 0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3,
+ 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBB9, 0xFBBA, 0xFBBB,
+ 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1, 0xFBC2, 0xFBC3,
+ 0xFBC4, 0xFBC5, 0xFBC6, 0xFBC7, 0xFBC8, 0xFBC9, 0xFBCA, 0xFBCB,
+ 0xFBCC, 0xFBCD, 0xFBCE, 0xFBCF, 0xFBD0, 0xFBD1, 0xFBD2, 0xFBD3,
+ 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB,
+ 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3,
+ 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB,
+ 0xFBEC, 0xFBED, 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3,
+ 0xFBF4, 0xFBF5, 0xFBF6, 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB,
+ 0xFBFC, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46,
+ 0xFC47, 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0, 0, 0xFA40,
+ 0xFA41, 0xFA42, 0xFA43, 0xFA44, 0xFA45, 0xFA46, 0xFA47, 0xFA48,
+ 0xFA49, 0x81CA, 0xFA55, 0xFA56, 0xFA57,
+ },
+};
+#endif /* SHIFTJIS_CP932 */
+
+#ifdef X0212_ENABLE
+const unsigned short shiftjis_x0212[3][189] = {
+ {
+ 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A,
+ 0xF37B, 0xF37C, 0xF37D, 0xF37E, 0xF421, 0xF422, 0xF423, 0xF424,
+ 0xF425, 0xF426, 0xF427, 0xF428, 0x224C, 0xA243, 0xF429, 0xF42A,
+ 0xF42B, 0xF42C, 0xF42D, 0x2268, 0xD463, 0xDC5F, 0xE469, 0xE378,
+ 0xD921, 0xB13B, 0xF42E, 0xC22D, 0xC37C, 0xE450, 0xC23F, 0xBC74,
+ 0xB029, 0xB048, 0xF42F, 0xB052, 0xB054, 0xB063, 0xB06E, 0xB127,
+ 0xB123, 0xB12C, 0xB129, 0xB13E, 0xB15F, 0xB158, 0xB148, 0xB157,
+ 0xB163, 0xB174, 0xB161, 0xB223, 0xF430, 0xB23B, 0xB266, 0,
+ 0xB26D, 0xB275, 0xB27C, 0xF431, 0xB335, 0xB358, 0xB35B, 0xB365,
+ 0xB36E, 0xB37B, 0xF432, 0xF433, 0xB440, 0xB447, 0xB450, 0xB45E,
+ 0xF434, 0xB52A, 0xF435, 0xB52F, 0xB544, 0xB568, 0xF436, 0xB742,
+ 0xB764, 0xB768, 0xB767, 0xF437, 0xF438, 0xF439, 0xB84E, 0xB861,
+ 0xB875, 0xB877, 0xB878, 0xB87C, 0xB92F, 0xB937, 0xBA3E, 0xBA5B,
+ 0xCD2A, 0xBA61, 0xF43A, 0xBA6B, 0xBB33, 0xBB38, 0xF43B, 0xBB4A,
+ 0xF43C, 0xF43D, 0xBB50, 0xBB5E, 0xBB74, 0xBB75, 0xBB79, 0xBC64,
+ 0xBC6D, 0xBC7E, 0xF43E, 0xBD42, 0xBD67, 0xF43F, 0xBD70, 0xBE30,
+ 0xBE2C, 0xF440, 0xBE33, 0xBE3D, 0xBE4D, 0xBE49, 0xBE64, 0xBF28,
+ 0xBF49, 0xC044, 0xC064, 0xC074, 0xC126, 0xF441, 0xC175, 0xC17C,
+ 0xF442, 0xC178, 0xC22B, 0xC221, 0xC225, 0xF443, 0xC238, 0xC23A,
+ 0xF444, 0xC244, 0xC252, 0xC257, 0xC25B, 0xC25E, 0xC26D, 0xC270,
+ 0xF445, 0xC321, 0xC335, 0xC349, 0xC339, 0xF446, 0xC358, 0xC37E,
+ 0xF447, 0xC44C, 0xF448, 0xC459, 0xC46A, 0xC47D, 0xF449, 0xC527,
+ 0xC535, 0xC536, 0xF44A, 0xC555, 0xC638, 0xC657, 0xC660, 0xC66A,
+ 0xC663, 0xC721, 0xC72B, 0xC747, 0xC743,
+ },
+ {
+ 0xC74B, 0xC74F, 0xC759, 0xF44B, 0xF44C, 0xC766, 0xC76E, 0xC77C,
+ 0xC76B, 0xC770, 0xC831, 0xC865, 0xC878, 0xC926, 0xC92B, 0xC92D,
+ 0xF44D, 0xC94A, 0xC953, 0xC969, 0xC963, 0xC97C, 0xC974, 0xC975,
+ 0xF44E, 0xCA33, 0xCA3D, 0xCA6F, 0xCA71, 0xCB2E, 0xF44F, 0xCB4A,
+ 0xCB66, 0xCB6A, 0xCB70, 0xCB74, 0xCB6E, 0xCC25, 0xCB79, 0xCC2B,
+ 0xCC2E, 0xCC2D, 0xCC32, 0xCC42, 0xCC50, 0xCC59, 0xF450, 0xCD3B,
+ 0xF451, 0xCE3B, 0xF452, 0xCE3A, 0xCE43, 0xF453, 0xCE72, 0xB35D,
+ 0xCF55, 0xCF62, 0xCF69, 0xCF6D, 0xF454, 0xF455, 0xF456, 0,
+ 0xF457, 0xD065, 0xF458, 0xD069, 0xD168, 0xF459, 0xF45A, 0xD16C,
+ 0xD23B, 0xF45B, 0xD361, 0xD368, 0xD427, 0xF45C, 0xF45D, 0xD454,
+ 0xD472, 0xD52E, 0xF45E, 0xD75E, 0xF45F, 0xD822, 0xD837, 0xD841,
+ 0xD851, 0xD874, 0xD946, 0xD948, 0xD951, 0xF460, 0xF461, 0xF462,
+ 0xF463, 0xF464, 0xDC53, 0xDD48, 0xDD54, 0xDD6A, 0xDD7A, 0xDE24,
+ 0xDE30, 0xF465, 0xDE35, 0xDE4B, 0xF466, 0xDF39, 0xF467, 0xDF43,
+ 0xF468, 0xF469, 0xE059, 0xF46A, 0xF46B, 0xE162, 0xF46C, 0xF46D,
+ 0xF46E, 0xE247, 0xE328, 0xE326, 0xE329, 0xE32F, 0xE330, 0xE32A,
+ 0xE32B, 0xE33C, 0xE341, 0xE33F, 0xE355, 0xE358, 0xE356, 0xE35F,
+ 0xE363, 0xE361, 0xE354, 0xE369, 0xE426, 0xE371, 0xE372, 0xE44B,
+ 0xE441, 0xE443, 0xE43E, 0xF46F, 0xE440, 0xE447, 0xE43F, 0xE460,
+ 0xE45E, 0xE451, 0xF470, 0xE45C, 0xE452, 0xE45B, 0xE454, 0xE47A,
+ 0xE46F, 0xE533, 0xE53F, 0xE549, 0xE550, 0xE562, 0xE56A, 0xE56B,
+ 0xF471, 0xF472, 0xF473, 0xE668, 0xE66F, 0xE72C, 0xF474, 0xE72E,
+ 0xF475, 0xE731, 0xF476, 0xE732, 0xE831, 0xE836, 0xF477, 0xF478,
+ 0xE85D, 0xF479, 0xF47A, 0xE951, 0xF47B,
+ },
+ {
+ 0xE96D, 0xEA4D, 0xF47C, 0xEA5B, 0xEA66, 0xEA6A, 0xEB25, 0xEB7B,
+ 0xEB7A, 0xF47D, 0xEC56, 0xF47E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ },
+};
+
+const unsigned short x0212_shiftjis_A2[] = {
+ 0x819F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x8143, 0, 0, 0x8150, 0, 0, 0x8160,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFA55, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_B0[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFA68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFA69, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFA6B, 0, 0xFA6C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFA6D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFA6E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_B1[] = {
+ 0, 0, 0xFA70, 0, 0, 0, 0xFA6F,
+ 0, 0xFA72, 0, 0, 0xFA71, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFA61, 0, 0, 0xFA73, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFA76, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xFA77,
+ 0xFA75, 0, 0, 0, 0, 0, 0, 0xFA74,
+ 0, 0xFA7A, 0, 0xFA78, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFA79, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_B2[] = {
+ 0, 0, 0xFA7B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFA7D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFA7E, 0,
+ 0, 0, 0, 0, 0, 0xFA80, 0, 0,
+ 0, 0, 0, 0, 0, 0xFA81, 0, 0,
+ 0, 0, 0, 0, 0xFA82, 0, 0,
+};
+const unsigned short x0212_shiftjis_B3[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFA84, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFA85, 0, 0, 0xFA86, 0, 0xFB77, 0, 0,
+ 0, 0, 0, 0, 0, 0xFA87, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFA88, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFA89, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_B4[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFA8C, 0, 0, 0, 0, 0, 0, 0xFA8D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFA8E, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFA8F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_B5[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFA91, 0, 0, 0, 0, 0xFA93,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFA94, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFA95, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_B7[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFA97, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFA98, 0, 0, 0xFA9A,
+ 0xFA99, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_B8[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFA9E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFA9F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFAA0, 0, 0xFAA1,
+ 0xFAA2, 0, 0, 0, 0xFAA3, 0, 0,
+};
+const unsigned short x0212_shiftjis_B9[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xFAA4,
+ 0, 0, 0, 0, 0, 0, 0, 0xFAA5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_BA[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFAA6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFAA7, 0, 0, 0, 0,
+ 0, 0xFAA9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFAAB, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_BB[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFAAC, 0, 0, 0, 0,
+ 0xFAAD, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFAAF, 0, 0, 0, 0, 0,
+ 0xFAB2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFAB3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFAB4, 0xFAB5, 0, 0,
+ 0, 0xFAB6, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_BC[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFAB7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFAB8, 0, 0,
+ 0, 0, 0, 0, 0xFA67, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFAB9,
+};
+const unsigned short x0212_shiftjis_BD[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFABB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xFABC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFABE, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_BE[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFAC0, 0, 0, 0,
+ 0xFABF, 0, 0, 0xFAC2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFAC3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFAC5, 0, 0, 0, 0xFAC4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFAC6, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_BF[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0xFAC7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFAC8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_C0[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFAC9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFACA, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFACB, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_C1[] = {
+ 0, 0, 0, 0, 0, 0xFACC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFACE, 0, 0,
+ 0xFAD1, 0, 0, 0, 0xFACF, 0, 0,
+};
+const unsigned short x0212_shiftjis_C2[] = {
+ 0xFAD3, 0, 0, 0, 0xFAD4, 0, 0,
+ 0, 0, 0, 0xFAD2, 0, 0xFA63, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFAD6, 0, 0xFAD7, 0, 0, 0, 0, 0xFA66,
+ 0, 0, 0, 0, 0xFAD9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFADA, 0, 0, 0, 0, 0xFADB,
+ 0, 0, 0, 0xFADC, 0, 0, 0xFADD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFADE, 0, 0,
+ 0xFADF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_C3[] = {
+ 0xFAE1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFAE2, 0, 0,
+ 0, 0xFAE4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFAE3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFAE6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFA64, 0, 0xFAE7,
+};
+const unsigned short x0212_shiftjis_C4[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFAE9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFAEB, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFAEC, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFAED, 0,
+};
+const unsigned short x0212_shiftjis_C5[] = {
+ 0, 0, 0, 0, 0, 0, 0xFAEF,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFAF0, 0xFAF1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFAF3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_C6[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFAF4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xFAF5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFAF6, 0, 0, 0xFAF8, 0, 0, 0, 0,
+ 0, 0, 0xFAF7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_C7[] = {
+ 0xFAF9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFAFA, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFAFC, 0, 0, 0, 0xFAFB,
+ 0, 0, 0, 0xFB40, 0, 0, 0, 0xFB41,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFB42, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFB45, 0,
+ 0, 0, 0, 0xFB48, 0, 0, 0xFB46, 0,
+ 0xFB49, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFB47, 0, 0,
+};
+const unsigned short x0212_shiftjis_C8[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFB4A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFB4B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFB4C, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_C9[] = {
+ 0, 0, 0, 0, 0, 0xFB4D, 0,
+ 0, 0, 0, 0xFB4E, 0, 0xFB4F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFB51, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFB52, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFB54, 0, 0, 0, 0,
+ 0, 0xFB53, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFB56, 0xFB57, 0, 0,
+ 0, 0, 0, 0, 0xFB55, 0, 0,
+};
+const unsigned short x0212_shiftjis_CA[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFB59, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFB5A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xFB5B,
+ 0, 0xFB5C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_CB[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFB5D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFB5F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFB60, 0,
+ 0, 0, 0xFB61, 0, 0, 0, 0xFB64, 0,
+ 0xFB62, 0, 0, 0, 0xFB63, 0, 0, 0,
+ 0, 0xFB66, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_CC[] = {
+ 0, 0, 0, 0, 0xFB65, 0, 0,
+ 0, 0, 0, 0xFB67, 0, 0xFB69, 0xFB68, 0,
+ 0, 0, 0xFB6A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFB6B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFB6C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFB6D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_CD[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFAA8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFB6F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_CE[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFB73, 0xFB71, 0, 0, 0, 0,
+ 0, 0, 0, 0xFB74, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFB76, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_CF[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFB78, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFB79, 0, 0, 0, 0, 0,
+ 0, 0xFB7A, 0, 0, 0, 0xFB7B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_D0[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFB81, 0, 0,
+ 0, 0xFB83, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_D1[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFB84, 0, 0, 0, 0xFB87, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_D2[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFB88, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_D3[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFB8A, 0, 0, 0, 0, 0, 0,
+ 0xFB8B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_D4[] = {
+ 0, 0, 0, 0, 0, 0, 0xFB8C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFB8F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFA5C, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFB90, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_D5[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFB91, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_D7[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFB93, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_D8[] = {
+ 0, 0xFB95, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xFB96,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFB97, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFB98, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFB99, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_D9[] = {
+ 0xFA60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFB9A, 0,
+ 0xFB9B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFB9C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_DC[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFBA2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xFA5D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_DD[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFBA3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFBA4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFBA5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFBA6, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_DE[] = {
+ 0, 0, 0, 0xFBA7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFBA8, 0, 0, 0, 0, 0xFBAA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFBAB, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_DF[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFBAD, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFBAF, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E0[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFBB2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E1[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFBB5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E2[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xFBB9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E3[] = {
+ 0, 0, 0, 0, 0, 0xFBBB, 0,
+ 0xFBBA, 0xFBBC, 0xFBBF, 0xFBC0, 0, 0, 0, 0xFBBD,
+ 0xFBBE, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFBC1, 0, 0, 0xFBC3,
+ 0, 0xFBC2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFBCA, 0xFBC4, 0xFBC6, 0,
+ 0xFBC5, 0, 0, 0, 0, 0, 0, 0xFBC7,
+ 0, 0xFBC9, 0, 0xFBC8, 0, 0, 0, 0,
+ 0, 0xFBCB, 0, 0, 0, 0, 0, 0,
+ 0, 0xFBCD, 0xFBCE, 0, 0, 0, 0, 0,
+ 0xFA5F, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E4[] = {
+ 0, 0, 0, 0, 0, 0xFBCC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFBD2, 0xFBD6,
+ 0xFBD4, 0xFBD0, 0, 0xFBD1, 0, 0, 0, 0xFBD5,
+ 0, 0, 0, 0xFBCF, 0, 0, 0, 0,
+ 0xFA65, 0xFBD9, 0xFBDC, 0, 0xFBDE, 0, 0, 0,
+ 0, 0, 0, 0xFBDD, 0xFBDB, 0, 0xFBD8, 0,
+ 0xFBD7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFA5E, 0, 0, 0, 0, 0, 0xFBE0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFBDF, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E5[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFBE1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xFBE2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFBE3, 0, 0, 0, 0, 0, 0,
+ 0xFBE4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFBE5, 0, 0, 0, 0, 0,
+ 0, 0, 0xFBE6, 0xFBE7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E6[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFBEB, 0, 0, 0, 0, 0, 0, 0xFBEC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E7[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xFBED, 0, 0xFBEF, 0,
+ 0, 0xFBF1, 0xFBF3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E8[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFBF4, 0, 0, 0, 0, 0xFBF5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFBF8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_E9[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0xFBFB, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFC40, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_EA[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xFC41, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFC43, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFC44, 0,
+ 0, 0, 0xFC45, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_EB[] = {
+ 0, 0, 0, 0, 0xFC46, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFC48, 0xFC47, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_EC[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xFC4A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+};
+const unsigned short x0212_shiftjis_F3[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0xFA40, 0xFA41, 0xFA42, 0xFA43, 0xFA44,
+ 0xFA45, 0xFA46, 0xFA47, 0xFA48, 0xFA49, 0xFA4A, 0xFA4B,
+};
+const unsigned short x0212_shiftjis_F4[] = {
+ 0xFA4C, 0xFA4D, 0xFA4E, 0xFA4F, 0xFA50, 0xFA51, 0xFA52,
+ 0xFA53, 0xFA56, 0xFA57, 0xFA58, 0xFA59, 0xFA5A, 0xFA62, 0xFA6A,
+ 0xFA7C, 0xFA83, 0xFA8A, 0xFA8B, 0xFA90, 0xFA92, 0xFA96, 0xFA9B,
+ 0xFA9C, 0xFA9D, 0xFAAA, 0xFAAE, 0xFAB0, 0xFAB1, 0xFABA, 0xFABD,
+ 0xFAC1, 0xFACD, 0xFAD0, 0xFAD5, 0xFAD8, 0xFAE0, 0xFAE5, 0xFAE8,
+ 0xFAEA, 0xFAEE, 0xFAF2, 0xFB43, 0xFB44, 0xFB50, 0xFB58, 0xFB5E,
+ 0xFB6E, 0xFB70, 0xFB72, 0xFB75, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80,
+ 0xFB82, 0xFB85, 0xFB86, 0xFB89, 0xFB8D, 0xFB8E, 0xFB92, 0xFB94,
+ 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA9, 0xFBAC, 0xFBAE,
+ 0xFBB0, 0xFBB1, 0xFBB3, 0xFBB4, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBD3,
+ 0xFBDA, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEE, 0xFBF0, 0xFBF2, 0xFBF6,
+ 0xFBF7, 0xFBF9, 0xFBFA, 0xFBFC, 0xFC42, 0xFC49, 0xFC4B,
+};
+const unsigned short *const x0212_shiftjis[] = {
+ 0, x0212_shiftjis_A2, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ x0212_shiftjis_B0, x0212_shiftjis_B1, x0212_shiftjis_B2, x0212_shiftjis_B3,
+ x0212_shiftjis_B4, x0212_shiftjis_B5, 0, x0212_shiftjis_B7,
+ x0212_shiftjis_B8, x0212_shiftjis_B9, x0212_shiftjis_BA, x0212_shiftjis_BB,
+ x0212_shiftjis_BC, x0212_shiftjis_BD, x0212_shiftjis_BE, x0212_shiftjis_BF,
+ x0212_shiftjis_C0, x0212_shiftjis_C1, x0212_shiftjis_C2, x0212_shiftjis_C3,
+ x0212_shiftjis_C4, x0212_shiftjis_C5, x0212_shiftjis_C6, x0212_shiftjis_C7,
+ x0212_shiftjis_C8, x0212_shiftjis_C9, x0212_shiftjis_CA, x0212_shiftjis_CB,
+ x0212_shiftjis_CC, x0212_shiftjis_CD, x0212_shiftjis_CE, x0212_shiftjis_CF,
+ x0212_shiftjis_D0, x0212_shiftjis_D1, x0212_shiftjis_D2, x0212_shiftjis_D3,
+ x0212_shiftjis_D4, x0212_shiftjis_D5, 0, x0212_shiftjis_D7,
+ x0212_shiftjis_D8, x0212_shiftjis_D9, 0, 0,
+ x0212_shiftjis_DC, x0212_shiftjis_DD, x0212_shiftjis_DE, x0212_shiftjis_DF,
+ x0212_shiftjis_E0, x0212_shiftjis_E1, x0212_shiftjis_E2, x0212_shiftjis_E3,
+ x0212_shiftjis_E4, x0212_shiftjis_E5, x0212_shiftjis_E6, x0212_shiftjis_E7,
+ x0212_shiftjis_E8, x0212_shiftjis_E9, x0212_shiftjis_EA, x0212_shiftjis_EB,
+ x0212_shiftjis_EC, 0, 0, 0,
+ 0, 0, 0, x0212_shiftjis_F3,
+ x0212_shiftjis_F4, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0,
+};
+#endif /* X0212_ENABLE */
diff --git a/ext/nkf/nkf-utf8/utf8tbl.h b/ext/nkf/nkf-utf8/utf8tbl.h
new file mode 100644
index 0000000000..1f40f0b363
--- /dev/null
+++ b/ext/nkf/nkf-utf8/utf8tbl.h
@@ -0,0 +1,34 @@
+#ifndef _UTF8TBL_H_
+#define _UTF8TBL_H_
+
+#ifdef UTF8_OUTPUT_ENABLE
+extern const unsigned short euc_to_utf8_1byte[];
+extern const unsigned short *const euc_to_utf8_2bytes[];
+extern const unsigned short *const euc_to_utf8_2bytes_ms[];
+extern const unsigned short *const x0212_to_utf8_2bytes[];
+#endif /* UTF8_OUTPUT_ENABLE */
+
+#ifdef UTF8_INPUT_ENABLE
+extern const unsigned short *const utf8_to_euc_2bytes[];
+extern const unsigned short *const utf8_to_euc_2bytes_ms[];
+extern const unsigned short *const utf8_to_euc_2bytes_932[];
+extern const unsigned short *const *const utf8_to_euc_3bytes[];
+extern const unsigned short *const *const utf8_to_euc_3bytes_ms[];
+extern const unsigned short *const *const utf8_to_euc_3bytes_932[];
+#endif /* UTF8_INPUT_ENABLE */
+
+#ifdef UNICODE_NORMALIZATION
+extern const struct normalization_pair normalization_table[];
+#endif
+
+#ifdef SHIFTJIS_CP932
+extern const unsigned short shiftjis_cp932[3][189];
+extern const unsigned short cp932inv[2][189];
+#endif /* SHIFTJIS_CP932 */
+
+#ifdef X0212_ENABLE
+extern const unsigned short shiftjis_x0212[3][189];
+extern const unsigned short *const x0212_shiftjis[];
+#endif /* X0212_ENABLE */
+
+#endif
diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c
index ca6de73e10..2bb0340a64 100644
--- a/ext/nkf/nkf.c
+++ b/ext/nkf/nkf.c
@@ -1,51 +1,149 @@
+/*
+ * NKF - Ruby extension for Network Kanji Filter
+ *
+ * original nkf2.x is maintained at http://sourceforge.jp/projects/nkf/
+ *
+ * $Id$
+ *
+ */
+
+#define RUBY_NKF_REVISION "$Revision$"
+#define RUBY_NKF_VERSION NKF_VERSION " (" NKF_RELEASE_DATE ")"
+
#include "ruby.h"
+/* Encoding Constants */
#define _AUTO 0
#define _JIS 1
#define _EUC 2
#define _SJIS 3
#define _BINARY 4
#define _NOCONV 4
+#define _ASCII 5
+/* 0b011x is reserved for UTF-8 Family */
+#define _UTF8 6
+/* 0b10xx is reserved for UTF-16 Family */
+#define _UTF16 8
+/* 0b11xx is reserved for UTF-32 Family */
+#define _UTF32 12
+#define _OTHER 16
#define _UNKNOWN _AUTO
+/* Replace nkf's getchar/putchar for variable modification */
+/* we never use getc, ungetc */
+
#undef getc
#undef ungetc
-#define getc(f) (input_ctr<i_len?input[input_ctr++]:-1)
-#define ungetc(c,f) input_ctr--
+#define getc(f) (input_ctr>=i_len?-1:input[input_ctr++])
+#define ungetc(c,f) input_ctr--
+#define INCSIZE 32
#undef putchar
-#define putchar(c) rb_nkf_putchar(c)
+#undef TRUE
+#undef FALSE
+#define putchar(c) rb_nkf_putchar(c)
-#define INCSIZE 32
-static int incsize;
+/* Input/Output pointers */
-static unsigned char *input, *output;
-static int input_ctr, i_len;
-static int output_ctr, o_len;
+static unsigned char *output;
+static unsigned char *input;
+static int input_ctr;
+static int i_len;
+static int output_ctr;
+static int o_len;
+static int incsize;
-static VALUE dst;
+static VALUE result;
static int
rb_nkf_putchar(c)
- unsigned int c;
+ unsigned int c;
{
if (output_ctr >= o_len) {
o_len += incsize;
- rb_str_resize(dst, o_len);
- output = RSTRING(dst)->ptr;
+ rb_str_resize(result, o_len);
incsize *= 2;
+ output = (unsigned char *)RSTRING(result)->ptr;
}
output[output_ctr++] = c;
return c;
}
+/* Include kanji filter main part */
+/* getchar and putchar will be replaced during inclusion */
+
#define PERL_XS 1
-#include "nkf1.7/nkf.c"
+#include "nkf-utf8/config.h"
+#include "nkf-utf8/utf8tbl.c"
+#include "nkf-utf8/nkf.c"
+
+int nkf_split_options(arg)
+ const char* arg;
+{
+ int count = 0;
+ char option[256];
+ int i = 0, j = 0;
+ int is_escaped = FALSE;
+ int is_single_quoted = FALSE;
+ int is_double_quoted = FALSE;
+ for(i = 0; arg[i]; i++){
+ if(j == 255){
+ return -1;
+ }else if(is_single_quoted){
+ if(arg[i] == '\''){
+ is_single_quoted = FALSE;
+ }else{
+ option[j++] = arg[i];
+ }
+ }else if(is_escaped){
+ is_escaped = FALSE;
+ option[j++] = arg[i];
+ }else if(arg[i] == '\\'){
+ is_escaped = TRUE;
+ }else if(is_double_quoted){
+ if(arg[i] == '"'){
+ is_double_quoted = FALSE;
+ }else{
+ option[j++] = arg[i];
+ }
+ }else if(arg[i] == '\''){
+ is_single_quoted = TRUE;
+ }else if(arg[i] == '"'){
+ is_double_quoted = TRUE;
+ }else if(arg[i] == ' '){
+ option[j] = '\0';
+ options(option);
+ j = 0;
+ }else{
+ option[j++] = arg[i];
+ }
+ }
+ if(j){
+ option[j] = '\0';
+ options(option);
+ }
+ return count;
+}
+
+/*
+ * call-seq:
+ * NKF.nkf(opt, str) -> string
+ *
+ * Convert _str_ and return converted result.
+ * Conversion details are specified by _opt_ as String.
+ *
+ * require 'nkf'
+ * output = NKF.nkf("-s", input)
+ *
+ * *Note*
+ * By default, nkf decodes MIME encoded string.
+ * If you want not to decode input, use NKF.nkf with <b>-m0</b> flag.
+ */
static VALUE
rb_nkf_kconv(obj, opt, src)
- VALUE obj, opt, src;
+ VALUE obj, opt, src;
{
char *opt_ptr, *opt_end;
volatile VALUE v;
@@ -54,69 +152,82 @@ rb_nkf_kconv(obj, opt, src)
StringValue(opt);
opt_ptr = RSTRING(opt)->ptr;
opt_end = opt_ptr + RSTRING(opt)->len;
- for (; opt_ptr < opt_end; opt_ptr++) {
- if (*opt_ptr != '-') {
- continue;
- }
- arguments(opt_ptr);
- }
+ nkf_split_options(opt_ptr);
incsize = INCSIZE;
- input_ctr = 0;
+ input_ctr = 0;
StringValue(src);
- input = RSTRING(src)->ptr;
+ input = (unsigned char *)RSTRING(src)->ptr;
i_len = RSTRING(src)->len;
- dst = rb_str_new(0, i_len*3 + 10);
- v = dst;
+ result = rb_str_new(0, i_len*3 + 10);
+ v = result;
output_ctr = 0;
- output = RSTRING(dst)->ptr;
- o_len = RSTRING(dst)->len;
+ output = (unsigned char *)RSTRING(result)->ptr;
+ o_len = RSTRING(result)->len;
*output = '\0';
- if(iso8859_f && (oconv != j_oconv || !x0201_f )) {
- iso8859_f = FALSE;
- }
+ if(x0201_f == WISH_TRUE)
+ x0201_f = ((!iso2022jp_f)? TRUE : NO_X0201);
kanji_convert(NULL);
- RSTRING(dst)->ptr[output_ctr] = '\0';
- RSTRING(dst)->len = output_ctr;
- OBJ_INFECT(dst, src);
+ RSTRING(result)->ptr[output_ctr] = '\0';
+ RSTRING(result)->len = output_ctr;
+ OBJ_INFECT(result, src);
- return dst;
+ return result;
}
+
/*
- * Character code detection - Algorithm described in:
- * Ken Lunde. `Understanding Japanese Information Processing'
- * Sebastopol, CA: O'Reilly & Associates.
+ * call-seq:
+ * NKF.guess1(str) -> integer
+ *
+ * Returns guessed encoding of _str_ as integer.
+ *
+ * Algorithm described in:
+ * Ken Lunde. `Understanding Japanese Information Processing'
+ * Sebastopol, CA: O'Reilly & Associates.
+ *
+ * case NKF.guess1(input)
+ * when NKF::JIS
+ * "ISO-2022-JP"
+ * when NKF::SJIS
+ * "Shift_JIS"
+ * when NKF::EUC
+ * "EUC-JP"
+ * when NKF::UNKNOWN
+ * "UNKNOWN(ASCII)"
+ * when NKF::BINARY
+ * "BINARY"
+ * end
*/
static VALUE
-rb_nkf_guess(obj, src)
- VALUE obj, src;
+rb_nkf_guess1(obj, src)
+ VALUE obj, src;
{
unsigned char *p;
unsigned char *pend;
int sequence_counter = 0;
StringValue(src);
- p = RSTRING(src)->ptr;
+ p = (unsigned char *)RSTRING(src)->ptr;
pend = p + RSTRING(src)->len;
if (p == pend) return INT2FIX(_UNKNOWN);
#define INCR do {\
- p++;\
- if (p==pend) return INT2FIX(_UNKNOWN);\
- sequence_counter++;\
- if (sequence_counter % 2 == 1 && *p != 0xa4)\
- sequence_counter = 0;\
- if (6 <= sequence_counter) {\
+ p++;\
+ if (p==pend) return INT2FIX(_UNKNOWN);\
+ sequence_counter++;\
+ if (sequence_counter % 2 == 1 && *p != 0xa4)\
sequence_counter = 0;\
- return INT2FIX(_EUC);\
- }\
-} while (0)
+ if (6 <= sequence_counter) {\
+ sequence_counter = 0;\
+ return INT2FIX(_EUC);\
+ }\
+ } while (0)
if (*p == 0xa4)
sequence_counter = 1;
@@ -180,19 +291,364 @@ rb_nkf_guess(obj, src)
return INT2FIX(_UNKNOWN);
}
+
+/*
+ * call-seq:
+ * NKF.guess2(str) -> integer
+ *
+ * Returns guessed encoding of _str_ as integer by nkf routine.
+ *
+ * case NKF.guess(input)
+ * when NKF::ASCII
+ * "ASCII"
+ * when NKF::JIS
+ * "ISO-2022-JP"
+ * when NKF::SJIS
+ * "Shift_JIS"
+ * when NKF::EUC
+ * "EUC-JP"
+ * when NKF::UTF8
+ * "UTF-8"
+ * when NKF::UTF16
+ * "UTF-16"
+ * when NKF::UNKNOWN
+ * "UNKNOWN"
+ * when NKF::BINARY
+ * "BINARY"
+ * end
+ */
+
+static VALUE
+rb_nkf_guess2(obj, src)
+ VALUE obj, src;
+{
+ int code = _BINARY;
+
+ reinit();
+
+ input_ctr = 0;
+ StringValue(src);
+ input = (unsigned char *)RSTRING(src)->ptr;
+ i_len = RSTRING(src)->len;
+
+ if(x0201_f == WISH_TRUE)
+ x0201_f = ((!iso2022jp_f)? TRUE : NO_X0201);
+
+ guess_f = TRUE;
+ kanji_convert( NULL );
+ guess_f = FALSE;
+
+ if (!is_inputcode_mixed) {
+ if (strcmp(input_codename, "") == 0) {
+ code = _ASCII;
+ } else if (strcmp(input_codename, "ISO-2022-JP") == 0) {
+ code = _JIS;
+ } else if (strcmp(input_codename, "EUC-JP") == 0) {
+ code = _EUC;
+ } else if (strcmp(input_codename, "Shift_JIS") == 0) {
+ code = _SJIS;
+ } else if (strcmp(input_codename, "UTF-8") == 0) {
+ code = _UTF8;
+ } else if (strcmp(input_codename, "UTF-16") == 0) {
+ code = _UTF16;
+ } else if (strlen(input_codename) > 0) {
+ code = _UNKNOWN;
+ }
+ }
+
+ return INT2FIX( code );
+}
+
+
+/*
+ * NKF - Ruby extension for Network Kanji Filter
+ *
+ * == Description
+ *
+ * This is a Ruby Extension version of nkf (Netowrk Kanji Filter).
+ * It converts the first argument and return converted result. Conversion
+ * details are specified by flags as the first argument.
+ *
+ * *Nkf* is a yet another kanji code converter among networks, hosts and terminals.
+ * It converts input kanji code to designated kanji code
+ * such as ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 or UTF-16.
+ *
+ * One of the most unique faculty of *nkf* is the guess of the input kanji encodings.
+ * It currently recognizes ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 and UTF-16.
+ * So users needn't set the input kanji code explicitly.
+ *
+ * By default, X0201 kana is converted into X0208 kana.
+ * For X0201 kana, SO/SI, SSO and ESC-(-I methods are supported.
+ * For automatic code detection, nkf assumes no X0201 kana in Shift_JIS.
+ * To accept X0201 in Shift_JIS, use <b>-X</b>, <b>-x</b> or <b>-S</b>.
+ *
+ * == Flags
+ *
+ * === -b -u
+ *
+ * Output is buffered (DEFAULT), Output is unbuffered.
+ *
+ * === -j -s -e -w -w16
+ *
+ * Output code is ISO-2022-JP (7bit JIS), Shift_JIS, EUC-JP,
+ * UTF-8N, UTF-16BE.
+ * Without this option and compile option, ISO-2022-JP is assumed.
+ *
+ * === -J -S -E -W -W16
+ *
+ * Input assumption is JIS 7 bit, Shift_JIS, EUC-JP,
+ * UTF-8, UTF-16LE.
+ *
+ * ==== -J
+ *
+ * Assume JIS input. It also accepts EUC-JP.
+ * This is the default. This flag does not exclude Shift_JIS.
+ *
+ * ==== -S
+ *
+ * Assume Shift_JIS and X0201 kana input. It also accepts JIS.
+ * EUC-JP is recognized as X0201 kana. Without <b>-x</b> flag,
+ * X0201 kana (halfwidth kana) is converted into X0208.
+ *
+ * ==== -E
+ *
+ * Assume EUC-JP input. It also accepts JIS.
+ * Same as -J.
+ *
+ * === -t
+ *
+ * No conversion.
+ *
+ * === -i_
+ *
+ * Output sequence to designate JIS-kanji. (DEFAULT B)
+ *
+ * === -o_
+ *
+ * Output sequence to designate ASCII. (DEFAULT B)
+ *
+ * === -r
+ *
+ * {de/en}crypt ROT13/47
+ *
+ * === -h[123] --hiragana --katakana --katakana-hiragana
+ *
+ * [-h1 --hiragana] Katakana to Hiragana conversion.
+ *
+ * [-h2 --katakana] Hiragana to Katakana conversion.
+ *
+ * [-h3 --katakana-hiragana] Katakana to Hiragana and Hiragana to Katakana conversion.
+ *
+ * === -T
+ *
+ * Text mode output (MS-DOS)
+ *
+ * === -l
+ *
+ * ISO8859-1 (Latin-1) support
+ *
+ * === -f[<code>m</code> [- <code>n</code>]]
+ *
+ * Folding on <code>m</code> length with <code>n</code> margin in a line.
+ * Without this option, fold length is 60 and fold margin is 10.
+ *
+ * === -F
+ *
+ * New line preserving line folding.
+ *
+ * === -Z[0-3]
+ *
+ * Convert X0208 alphabet (Fullwidth Alphabets) to ASCII.
+ *
+ * [-Z -Z0] Convert X0208 alphabet to ASCII.
+ *
+ * [-Z1] Converts X0208 kankaku to single ASCII space.
+ *
+ * [-Z2] Converts X0208 kankaku to double ASCII spaces.
+ *
+ * [-Z3] Replacing Fullwidth >, <, ", & into '&gt;', '&lt;', '&quot;', '&amp;' as in HTML.
+ *
+ * === -X -x
+ *
+ * Assume X0201 kana in MS-Kanji.
+ * With <b>-X</b> or without this option, X0201 is converted into X0208 Kana.
+ * With <b>-x</b>, try to preserve X0208 kana and do not convert X0201 kana to X0208.
+ * In JIS output, ESC-(-I is used. In EUC output, SSO is used.
+ *
+ * === -B[0-2]
+ *
+ * Assume broken JIS-Kanji input, which lost ESC.
+ * Useful when your site is using old B-News Nihongo patch.
+ *
+ * [-B1] allows any char after ESC-( or ESC-$.
+ *
+ * [-B2] forces ASCII after NL.
+ *
+ * === -I
+ *
+ * Replacing non iso-2022-jp char into a geta character
+ * (substitute character in Japanese).
+ *
+ * === -d -c
+ *
+ * Delete \r in line feed, Add \r in line feed.
+ *
+ * === -m[BQN0]
+ *
+ * MIME ISO-2022-JP/ISO8859-1 decode. (DEFAULT)
+ * To see ISO8859-1 (Latin-1) -l is necessary.
+ *
+ * [-mB] Decode MIME base64 encoded stream. Remove header or other part before
+ * conversion.
+ *
+ * [-mQ] Decode MIME quoted stream. '_' in quoted stream is converted to space.
+ *
+ * [-mN] Non-strict decoding.
+ * It allows line break in the middle of the base64 encoding.
+ *
+ * [-m0] No MIME decode.
+ *
+ * === -M
+ *
+ * MIME encode. Header style. All ASCII code and control characters are intact.
+ * Kanji conversion is performed before encoding, so this cannot be used as a picture encoder.
+ *
+ * [-MB] MIME encode Base64 stream.
+ *
+ * [-MQ] Perfome quoted encoding.
+ *
+ * === -l
+ *
+ * Input and output code is ISO8859-1 (Latin-1) and ISO-2022-JP.
+ * <b>-s</b>, <b>-e</b> and <b>-x</b> are not compatible with this option.
+ *
+ * === -L[uwm]
+ *
+ * new line mode
+ * Without this option, nkf doesn't convert line breaks.
+ *
+ * [-Lu] unix (LF)
+ *
+ * [-Lw] windows (CRLF)
+ *
+ * [-Lm] mac (CR)
+ *
+ * === --fj --unix --mac --msdos --windows
+ *
+ * convert for these system
+ *
+ * === --jis --euc --sjis --mime --base64
+ *
+ * convert for named code
+ *
+ * === --jis-input --euc-input --sjis-input --mime-input --base64-input
+ *
+ * assume input system
+ *
+ * === --ic=<code>input codeset</code> --oc=<code>output codeset</code>
+ *
+ * Set the input or output codeset.
+ * NKF supports following codesets and those codeset name are case insensitive.
+ *
+ * [ISO-2022-JP] a.k.a. RFC1468, 7bit JIS, JUNET
+ *
+ * [EUC-JP (eucJP-nkf)] a.k.a. AT&T JIS, Japanese EUC, UJIS
+ *
+ * [eucJP-ascii] a.k.a. x-eucjp-open-19970715-ascii
+ *
+ * [eucJP-ms] a.k.a. x-eucjp-open-19970715-ms
+ *
+ * [CP51932] Microsoft Version of EUC-JP.
+ *
+ * [Shift_JIS] SJIS, MS-Kanji
+ *
+ * [CP932] a.k.a. Windows-31J
+ *
+ * [UTF-8] same as UTF-8N
+ *
+ * [UTF-8N] UTF-8 without BOM
+ *
+ * [UTF-8-BOM] UTF-8 with BOM
+ *
+ * [UTF-16] same as UTF-16BE
+ *
+ * [UTF-16BE] UTF-16 Big Endian without BOM
+ *
+ * [UTF-16BE-BOM] UTF-16 Big Endian with BOM
+ *
+ * [UTF-16LE] UTF-16 Little Endian without BOM
+ *
+ * [UTF-16LE-BOM] UTF-16 Little Endian with BOM
+ *
+ * [UTF8-MAC] NKDed UTF-8, a.k.a. UTF8-NFD (input only)
+ *
+ * === --fb-{skip, html, xml, perl, java, subchar}
+ *
+ * Specify the way that nkf handles unassigned characters.
+ * Without this option, --fb-skip is assumed.
+ *
+ * === --prefix= <code>escape character</code> <code>target character</code> ..
+ *
+ * When nkf converts to Shift_JIS,
+ * nkf adds a specified escape character to specified 2nd byte of Shift_JIS characters.
+ * 1st byte of argument is the escape character and following bytes are target characters.
+ *
+ * === --disable-cp932ext
+ *
+ * Handle the characters extended in CP932 as unassigned characters.
+ *
+ * === --cap-input
+ *
+ * Decode hex encoded characters.
+ *
+ * === --url-input
+ *
+ * Unescape percent escaped characters.
+ *
+ * === --
+ *
+ * Ignore rest of -option.
+ */
+
void
Init_nkf()
{
+ /* hoge */
VALUE mKconv = rb_define_module("NKF");
+ /* hoge */
rb_define_module_function(mKconv, "nkf", rb_nkf_kconv, 2);
- rb_define_module_function(mKconv, "guess", rb_nkf_guess, 1);
+ rb_define_module_function(mKconv, "guess1", rb_nkf_guess1, 1);
+ rb_define_module_function(mKconv, "guess2", rb_nkf_guess2, 1);
+ rb_define_alias(mKconv, "guess", "guess2");
+ rb_define_alias(rb_singleton_class(mKconv), "guess", "guess2");
+ /* Auto-Detect */
rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO));
+ /* ISO-2022-JP */
rb_define_const(mKconv, "JIS", INT2FIX(_JIS));
+ /* EUC-JP */
rb_define_const(mKconv, "EUC", INT2FIX(_EUC));
+ /* Shift_JIS */
rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS));
+ /* BINARY */
rb_define_const(mKconv, "BINARY", INT2FIX(_BINARY));
+ /* No conversion */
rb_define_const(mKconv, "NOCONV", INT2FIX(_NOCONV));
+ /* ASCII */
+ rb_define_const(mKconv, "ASCII", INT2FIX(_ASCII));
+ /* UTF-8 */
+ rb_define_const(mKconv, "UTF8", INT2FIX(_UTF8));
+ /* UTF-16 */
+ rb_define_const(mKconv, "UTF16", INT2FIX(_UTF16));
+ /* UTF-32 */
+ rb_define_const(mKconv, "UTF32", INT2FIX(_UTF32));
+ /* UNKNOWN */
rb_define_const(mKconv, "UNKNOWN", INT2FIX(_UNKNOWN));
+ /* Full version string of nkf */
+ rb_define_const(mKconv, "VERSION", rb_str_new2(RUBY_NKF_VERSION));
+ /* Version of nkf */
+ rb_define_const(mKconv, "NKF_VERSION", rb_str_new2(NKF_VERSION));
+ /* Release date of nkf */
+ rb_define_const(mKconv, "NKF_RELEASE_DATE", rb_str_new2(NKF_RELEASE_DATE));
}
diff --git a/ext/nkf/nkf1.7/nkf.c b/ext/nkf/nkf1.7/nkf.c
deleted file mode 100644
index 09419f40a7..0000000000
--- a/ext/nkf/nkf1.7/nkf.c
+++ /dev/null
@@ -1,1900 +0,0 @@
-/** Network Kanji Filter. (PDS Version)
-************************************************************************
-** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
-** $BO"Mm@h!'(B $B!J3t!KIY;NDL8&5f=j!!%=%U%H#38&!!;T@n!!;j(B
-** $B!J(BE-Mail Address: ichikawa@flab.fujitsu.co.jp$B!K(B
-** Copyright (C) 1996,1998
-** $BO"Mm@h!'(B $BN05eBg3X>pJs9)3X2J(B $B2OLn(B $B??<#(B mine/X0208 support
-** $B!J(BE-Mail Address: kono@ie.u-ryukyu.ac.jp$B!K(B
-** $BO"Mm@h!'(B COW for DOS & Win16 & Win32 & OS/2
-** $B!J(BE-Mail Address: GHG00637@niftyserve.or.p$B!K(B
-** $B$3$N%=!<%9$N$$$+$J$kJ#<L!$2~JQ!$=$@5$b5vBz$7$^$9!#$?$@$7!"(B
-** $B$=$N:]$K$O!"C/$,9W8%$7$?$r<($9$3$NItJ,$r;D$9$3$H!#(B
-** $B:FG[I[$d;(;o$NIUO?$J$I$NLd$$9g$o$;$bI,MW$"$j$^$;$s!#(B
-** $B$3$N%W%m%0%i%`$K$D$$$F$OFC$K2?$NJ]>Z$b$7$J$$!"0-$7$+$i$:!#(B
-** Everyone is permitted to do anything on this program
-** including copying, modifying, improving.
-** as long as you don't try to pretend that you wrote it.
-** i.e., the above copyright notice has to appear in all copies.
-** You don't have to ask before copying or publishing.
-** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
-***********************************************************************/
-
-static char *CopyRight =
- "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1998 S. Kono, COW";
-static char *Version =
- "1.7";
-static char *Patchlevel =
- "0/9711/Shinji Kono";
-
-/*
-**
-**
-**
-** USAGE: nkf [flags] [file]
-**
-** Flags:
-** b Output is bufferred (DEFAULT)
-** u Output is unbufferred
-**
-** t no operation
-**
-** j Outout code is JIS 7 bit (DEFAULT SELECT)
-** s Output code is MS Kanji (DEFAULT SELECT)
-** e Output code is AT&T JIS (DEFAULT SELECT)
-** l Output code is JIS 7bit and ISO8859-1 Latin-1
-**
-** m MIME conversion for ISO-2022-JP
-** i_ Output sequence to designate JIS-kanji (DEFAULT_J)
-** o_ Output sequence to designate single-byte roman characters (DEFAULT_R)
-**
-** r {de/en}crypt ROT13/47
-**
-** v display Version
-**
-** T Text mode output (for MS-DOS)
-**
-** x Do not convert X0201 kana into X0208
-** Z Convert X0208 alphabet to ASCII
-**
-** f60 fold option
-**
-** m MIME decode
-** B try to fix broken JIS, missing Escape
-** B[1-9] broken level
-**
-** O Output to 'nkf.out' file
-** d Delete \r in line feed
-** c Add \r in line feed
-**/
-/******************************/
-/* $B%G%U%)%k%H$N=PNO%3!<%IA*Br(B */
-/* Select DEFAULT_CODE */
-#define DEFAULT_CODE_JIS
-/* #define DEFAULT_CODE_SJIS */
-/* #define DEFAULT_CODE_EUC */
-/******************************/
-
-#if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS)
-#define MSDOS
-#endif
-
-#ifndef PERL_XS
-#include <stdio.h>
-#endif
-
-#if defined(MSDOS) || defined(__OS2__)
-#include <stdlib.h>
-#include <fcntl.h>
-#include <io.h>
-#endif
-
-#ifdef MSDOS
-#ifdef LSI_C
-#define setbinmode(fp) fsetbin(fp)
-#else /* Microsoft C, Turbo C */
-#define setbinmode(fp) setmode(fileno(fp), O_BINARY)
-#endif
-#else /* UNIX,OS/2 */
-#define setbinmode(fp)
-#endif
-
-#ifdef _IOFBF /* SysV and MSDOS */
-#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size)
-#else /* BSD */
-#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size)
-#endif
-
-/*Borland C++ 4.5 EasyWin*/
-#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
-#define EASYWIN
-#include <windows.h>
-#endif
-
-#define FALSE 0
-#define TRUE 1
-
-/* state of output_mode and input_mode */
-
-#define ASCII 0
-#define X0208 1
-#define X0201 2
-#define NO_X0201 3
-#define JIS_INPUT 4
-#define SJIS_INPUT 5
-#define LATIN1_INPUT 6
-#define FIXED_MIME 7
-#define DOUBLE_SPACE -2
-
-#define NL 0x0a
-#define ESC 0x1b
-#define SPACE 0x20
-#define AT 0x40
-#define SSP 0xa0
-#define DEL 0x7f
-#define SI 0x0f
-#define SO 0x0e
-#define SSO 0x8e
-
-#define HOLD_SIZE 32
-#define IOBUF_SIZE 16384
-
-#define DEFAULT_J 'B'
-#define DEFAULT_R 'B'
-
-#define SJ0162 0x00e1 /* 01 - 62 ku offset */
-#define SJ6394 0x0161 /* 63 - 94 ku offset */
-
-
-/* MIME preprocessor */
-
-#undef STRICT_MIME /* do stupid strict mime integrity check */
-#define GETC(p) ((!mime_mode)?getc(p):mime_getc(p))
-#define UNGETC(c,p) ((!mime_mode)?ungetc(c,p):mime_ungetc(c))
-
-
-#ifdef EASYWIN /*Easy Win */
-extern POINT _BufferSize;
-#endif
-
-/* function prototype */
-
-#ifndef _
-# ifdef __STDC__
-# define _(args) args
-# else
-# define _(args) ()
-# endif
-#endif
-
-#ifndef PERL_XS
-static void noconvert _((FILE *f));
-static int mime_integrity _((FILE *f,unsigned char *p));
-static int usage _((void));
-static char stdibuf[IOBUF_SIZE];
-static char stdobuf[IOBUF_SIZE];
-static unsigned int mime_input = 0; /* undecoded */
-static int end_check;
-#endif
-
-static void kanji_convert _((FILE *f));
-static void h_conv _((FILE *f,int c2,int c1));
-static int push_hold_buf _((int c2,int c1));
-static void s_iconv _((int c2,int c1));
-static void e_oconv _((int c2,int c1));
-static void s_oconv _((int c2,int c1));
-static void j_oconv _((int c2,int c1));
-static int line_fold _((int c2,int c1));
-static int pre_convert _((int c1,int c2));
-static int mime_begin _((FILE *f));
-static int mime_getc _((FILE *f));
-static int mime_ungetc _((unsigned int c));
-static int base64decode _((int c));
-static void arguments _((char *c));
-static void reinit _((void));
-
-/* buffers */
-
-static unsigned char hold_buf[HOLD_SIZE*2];
-static int hold_count;
-
-/* MIME preprocessor fifo */
-
-#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */
-#define MIME_BUF_MASK (MIME_BUF_SIZE-1)
-#define Fifo(n) mime_buf[(n)&MIME_BUF_MASK]
-static unsigned char mime_buf[MIME_BUF_SIZE];
-static unsigned int mime_top = 0;
-static unsigned int mime_last = 0; /* decoded */
-
-/* flags */
-static int unbuf_f = FALSE;
-static int estab_f = FALSE;
-static int nop_f = FALSE;
-static int binmode_f = TRUE; /* binary mode */
-static int rot_f = FALSE; /* rot14/43 mode */
-static int input_f = FALSE; /* non fixed input code */
-static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */
-static int mime_f = TRUE; /* convert MIME B base64 or Q */
-static int mimebuf_f = FALSE; /* MIME buffered input */
-static int broken_f = FALSE; /* convert ESC-less broken JIS */
-static int iso8859_f = FALSE; /* ISO8859 through */
-#if defined(MSDOS) || defined(__OS2__)
-static int x0201_f = TRUE; /* Assume JISX0201 kana */
-#else
-static int x0201_f = NO_X0201; /* Assume NO JISX0201 */
-#endif
-
-/* X0208 -> ASCII converter */
-
-static int c1_return;
-
-/* fold parameter */
-static int line = 0; /* chars in line */
-static int prev = 0;
-static int fold_f = FALSE;
-static int fold_len = 0;
-
-/* options */
-static char kanji_intro = DEFAULT_J,
- ascii_intro = DEFAULT_R;
-
-/* Folding */
-
-int line_fold();
-#define FOLD_MARGIN 10
-#define DEFAULT_FOLD 60
-
-/* converters */
-
-#ifdef DEFAULT_CODE_JIS
-# define DEFAULT_CONV j_oconv
-#endif
-#ifdef DEFAULT_CODE_SJIS
-# define DEFAULT_CONV s_oconv
-#endif
-#ifdef DEFAULT_CODE_EUC
-# define DEFAULT_CONV e_oconv
-#endif
-
-static void (*iconv) _((int c2,int c1));
- /* s_iconv or oconv */
-static void (*oconv) _((int c2,int c1)) = DEFAULT_CONV;
- /* [ejs]_oconv */
-
-/* Global states */
-static int output_mode = ASCII, /* output kanji mode */
- input_mode = ASCII, /* input kanji mode */
- shift_mode = FALSE; /* TRUE shift out, or X0201 */
-static int mime_mode = FALSE; /* MIME mode B base64, Q hex */
-
-/* X0201 / X0208 conversion tables */
-
-/* X0201 kana conversion table */
-/* 90-9F A0-DF */
-unsigned char cv[]= {
-0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
-0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
-0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
-0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
-0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
-0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
-0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
-0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
-0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
-0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
-0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
-0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
-0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
-0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
-0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
-0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
-0x00,0x00};
-
-
-/* X0201 kana conversion table for daguten */
-/* 90-9F A0-DF */
-unsigned char dv[]= {
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
-0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
-0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
-0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
-0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
-0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00};
-
-/* X0201 kana conversion table for han-daguten */
-/* 90-9F A0-DF */
-unsigned char ev[]= {
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
-0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00};
-
-
-/* X0208 kigou conversion table */
-/* 0x8140 - 0x819e */
-unsigned char fv[] = {
-
-0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
-0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
-0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
-0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
-0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
-0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
-0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-} ;
-
-
-static int file_out = FALSE;
-static int add_cr = FALSE;
-static int del_cr = FALSE;
-
-#ifndef PERL_XS
-int
-main(argc, argv)
- int argc;
- char **argv;
-{
- FILE *fin;
- char *cp;
-
-#ifdef EASYWIN /*Easy Win */
- _BufferSize.y = 400;/*Set Scroll Buffer Size*/
-#endif
-
- for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
- cp = *argv;
- arguments(cp);
- }
-
- if(iso8859_f && (oconv != j_oconv || !x0201_f )) {
- fprintf(stderr,"Mixed ISO8859/JISX0201/SJIS/EUC output is not allowed.\n");
- exit(1);
- }
-
- if(binmode_f == TRUE)
-#ifdef __OS2__
- if(freopen("","wb",stdout) == NULL)
- return (-1);
-#else
- setbinmode(stdout);
-#endif
-
- if(unbuf_f)
- setbuf(stdout, (char *) NULL);
- else
- setvbuffer(stdout, stdobuf, IOBUF_SIZE);
-
- if(argc == 0) {
- if(binmode_f == TRUE)
-#ifdef __OS2__
- if(freopen("","rb",stdin) == NULL) return (-1);
-#else
- setbinmode(stdin);
-#endif
- setvbuffer(stdin, stdibuf, IOBUF_SIZE);
- if(nop_f)
- noconvert(stdin);
- else
- kanji_convert(stdin);
- } else {
- while (argc--) {
- if((fin = fopen(*argv++, "r")) == NULL) {
- perror(*--argv);
- return(-1);
- } else {
-/* reopen file for stdout */
- if(file_out == TRUE){
- if(argc == 1 ) {
- if(freopen(*argv++, "w", stdout) == NULL) {
- perror(*--argv);
- return (-1);
- }
- argc--;
- } else {
- if(freopen("nkf.out", "w", stdout) == NULL) {
- perror(*--argv);
- return (-1);
- }
- }
- if(binmode_f == TRUE) {
-#ifdef __OS2__
- if(freopen("","wb",stdout) == NULL)
- return (-1);
-#else
- setbinmode(stdout);
-#endif
- }
- }
- if(binmode_f == TRUE)
-#ifdef __OS2__
- if(freopen("","rb",fin) == NULL)
- return (-1);
-#else
- setbinmode(fin);
-#endif
- setvbuffer(fin, stdibuf, IOBUF_SIZE);
- if(nop_f)
- noconvert(fin);
- else
- kanji_convert(fin);
- fclose(fin);
- }
- }
- }
-#ifdef EASYWIN /*Easy Win */
- if(file_out == FALSE)
- scanf("%d",&end_check);
- else
- fclose(stdout);
-#else /* for Other OS */
- if(file_out == TRUE)
- fclose(stdout);
-#endif
- return (0);
-}
-#endif
-
-static void
-arguments(cp)
- char *cp;
-{
- while (*cp) {
- switch (*cp++) {
- case 'b': /* buffered mode */
- unbuf_f = FALSE;
- continue;
- case 'u': /* non bufferd mode */
- unbuf_f = TRUE;
- continue;
- case 't': /* transparent mode */
- nop_f = TRUE;
- continue;
- case 'j': /* JIS output */
- case 'n':
- oconv = j_oconv;
- continue;
- case 'e': /* AT&T EUC output */
- oconv = e_oconv;
- continue;
- case 's': /* SJIS output */
- oconv = s_oconv;
- continue;
- case 'l': /* ISO8859 Latin-1 support, no conversion */
- iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
- input_f = LATIN1_INPUT;
- continue;
- case 'i': /* Kanji IN ESC-$-@/B */
- if(*cp=='@'||*cp=='B')
- kanji_intro = *cp++;
- continue;
- case 'o': /* ASCII IN ESC-(-J/B */
- if(*cp=='J'||*cp=='B'||*cp=='H')
- ascii_intro = *cp++;
- continue;
- case 'r':
- rot_f = TRUE;
- continue;
-#if defined(MSDOS) || defined(__OS2__)
- case 'T':
- binmode_f = FALSE;
- continue;
-#endif
-#ifndef PERL_XS
- case 'v':
- usage();
- exit(1);
- break;
-#endif
- /* Input code assumption */
- case 'J': /* JIS input */
- case 'E': /* AT&T EUC input */
- input_f = JIS_INPUT;
- continue;
- case 'S': /* MS Kanji input */
- input_f = SJIS_INPUT;
- if(x0201_f==NO_X0201) x0201_f=TRUE;
- continue;
- case 'Z': /* Convert X0208 alphabet to asii */
- /* bit:0 Convert X0208
- bit:1 Convert Kankaku to one space
- bit:2 Convert Kankaku to two spaces
- */
- if('9'>= *cp && *cp>='0')
- alpha_f |= 1<<(*cp++ -'0');
- else
- alpha_f |= TRUE;
- continue;
- case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
- x0201_f = FALSE; /* No X0201->X0208 conversion */
- /* accept X0201
- ESC-(-I in JIS, EUC, MS Kanji
- SI/SO in JIS, EUC, MS Kanji
- SSO in EUC, JIS, not in MS Kanji
- MS Kanji (0xa0-0xdf)
- output X0201
- ESC-(-I in JIS (0x20-0x5f)
- SSO in EUC (0xa0-0xdf)
- 0xa0-0xd in MS Kanji (0xa0-0xdf)
- */
- continue;
- case 'X': /* Assume X0201 kana */
- /* Default value is NO_X0201 for EUC/MS-Kanji mix */
- x0201_f = TRUE;
- continue;
- case 'f': /* folding -f60 or -f */
- fold_f = TRUE;
- fold_len = atoi(cp);
- if(!(0<fold_len && fold_len<BUFSIZ))
- fold_len = DEFAULT_FOLD;
- while('0'<= *cp && *cp <='9') cp++;
- continue;
- case 'm': /* MIME support */
- mime_f = TRUE;
- if(*cp=='B'||*cp=='Q') {
- mime_mode = *cp++;
- mimebuf_f = FIXED_MIME;
- } else if (*cp=='0') {
- mime_f = FALSE;
- }
- continue;
- case 'M': /* MIME output */
- oconv = j_oconv; /* sorry... not yet done.. */
- continue;
- case 'B': /* Broken JIS support */
- /* bit:0 no ESC JIS
- bit:1 allow any x on ESC-(-x or ESC-$-x
- bit:2 reset to ascii on NL
- */
- if('9'>= *cp && *cp>='0')
- broken_f |= 1<<(*cp++ -'0');
- else
- broken_f |= TRUE;
- continue;
-#ifndef PERL_XS
- case 'O':/* for Output file */
- file_out = TRUE;
- continue;
-#endif
- case 'c':/* add cr code */
- add_cr = TRUE;
- continue;
- case 'd':/* delete cr code */
- del_cr = TRUE;
- continue;
- default:
- /* bogus option but ignored */
- continue;
- }
- }
-}
-
-#ifndef PERL_XS
-static void
-noconvert(f)
- FILE *f;
-{
- int c;
-
- while ((c = getc(f)) != EOF)
- putchar(c);
-}
-#endif
-
-
-static void
-kanji_convert(f)
- FILE *f;
-{
- int c1, c2;
-
- c2 = 0;
-
- if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
- estab_f = TRUE; iconv = oconv;
- } else if(input_f == SJIS_INPUT) {
- estab_f = TRUE; iconv = s_iconv;
- } else {
- estab_f = FALSE; iconv = oconv;
- }
- input_mode = ASCII;
- output_mode = ASCII;
- shift_mode = FALSE;
-
-#define NEXT continue /* no output, get next */
-#define SEND ; /* output c1 and c2, get next */
-#define LAST break /* end of loop, go closing */
-
- while ((c1 = GETC(f)) != EOF) {
- if(c2) {
- /* second byte */
- if(c2 > DEL) {
- /* in case of 8th bit is on */
- if(!estab_f) {
- /* in case of not established yet */
- if(c1 > SSP) {
- /* It is still ambiguious */
- h_conv(f, c2, c1);
- c2 = 0;
- NEXT;
- } else if(c1 < AT) {
- /* ignore bogus code */
- c2 = 0;
- NEXT;
- } else {
- /* established */
- /* it seems to be MS Kanji */
- estab_f = TRUE;
- iconv = s_iconv;
- SEND;
- }
- } else
- /* in case of already established */
- if(c1 < AT) {
- /* ignore bogus code */
- c2 = 0;
- NEXT;
- } else
- SEND;
- } else
- /* 7 bit code */
- /* it might be kanji shitfted */
- if((c1 == DEL) || (c1 <= SPACE)) {
- /* ignore bogus first code */
- c2 = 0;
- NEXT;
- } else
- SEND;
- } else {
- /* first byte */
- if(c1 > DEL) {
- /* 8 bit code */
- if(!estab_f && !iso8859_f) {
- /* not established yet */
- if(c1 < SSP) {
- /* it seems to be MS Kanji */
- estab_f = TRUE;
- iconv = s_iconv;
- } else if(c1 < 0xe0) {
- /* it seems to be EUC */
- estab_f = TRUE;
- iconv = oconv;
- } else {
- /* still ambiguious */
- }
- c2 = c1;
- NEXT;
- } else { /* estab_f==TRUE */
- if(iso8859_f) {
- SEND;
- } else if(SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
- /* SJIS X0201 Case... */
- /* This is too arrogant, but ... */
- if(x0201_f==NO_X0201) {
- iconv = oconv;
- c2 = c1;
- NEXT;
- } else
- if(x0201_f) {
- if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
- /* look ahead for X0201/X0208conversion */
- if((c2 = GETC(f)) == EOF) {
- (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
- LAST;
- } else if(c2==(0xde)) { /* $BByE@(B */
- (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
- c2=0;
- NEXT;
- } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) {
- /* $BH>ByE@(B */
- (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
- c2=0;
- NEXT;
- }
- UNGETC(c2,f); c2 = 0;
- }
- (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
- NEXT;
- } else
- SEND;
- } else if(c1==SSO && iconv != s_iconv) {
- /* EUC X0201 Case */
- /* This is too arrogant
- if(x0201_f == NO_X0201) {
- estab_f = FALSE;
- c2 = 0;
- NEXT;
- } */
- c1 = GETC(f); /* skip SSO */
- euc_1byte_check:
- if(x0201_f && SSP<=c1 && c1<0xe0) {
- if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
- if((c2 = GETC(f)) == EOF) {
- (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
- LAST;
- }
- /* forward lookup $BByE@(B/$BH>ByE@(B */
- if(c2 != SSO) {
- UNGETC(c2,f); c2 = 0;
- (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
- NEXT;
- } else if((c2 = GETC(f)) == EOF) {
- (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
- (*oconv)(0,SSO);
- LAST;
- } else if(c2==(0xde)) { /* $BByE@(B */
- (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
- c2=0;
- NEXT;
- } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) {
- /* $BH>ByE@(B */
- (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
- c2=0;
- NEXT;
- } else {
- (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
- /* we have to check this c2 */
- /* and no way to push back SSO */
- c1 = c2; c2 = 0;
- goto euc_1byte_check;
- }
- }
- (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
- NEXT;
- } else
- SEND;
- } else if(c1 < SSP && iconv != s_iconv) {
- /* strange code in EUC */
- iconv = s_iconv; /* try SJIS */
- c2 = c1;
- NEXT;
- } else {
- /* already established */
- c2 = c1;
- NEXT;
- }
- }
- } else if((c1 > SPACE) && (c1 != DEL)) {
- /* in case of Roman characters */
- if(shift_mode) {
- c1 |= 0x80;
- /* output 1 shifted byte */
- if(x0201_f && (!iso8859_f||input_mode==X0201) &&
- SSP<=c1 && c1<0xe0 ) {
- if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
- if((c2 = GETC(f)) == EOF) {
- (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
- LAST;
- } else if(c2==(0xde&0x7f)) { /* $BByE@(B */
- (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
- c2=0;
- NEXT;
- } else if(c2==(0xdf&0x7f)&&ev[(c1-SSP)*2]) {
- /* $BH>ByE@(B */
- (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
- c2=0;
- NEXT;
- }
- UNGETC(c2,f); c2 = 0;
- }
- (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
- NEXT;
- } else
- SEND;
- } else if(c1 == '(' && broken_f && input_mode == X0208
- && !mime_mode ) {
- /* Try to recover missing escape */
- if((c1 = GETC(f)) == EOF) {
- (*oconv)(0, '(');
- LAST;
- } else {
- if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
- input_mode = ASCII; shift_mode = FALSE;
- NEXT;
- } else {
- (*oconv)(0, '(');
- /* do not modify various input_mode */
- /* It can be vt100 sequence */
- SEND;
- }
- }
- } else if(input_mode == X0208) {
- /* in case of Kanji shifted */
- c2 = c1;
- NEXT;
- /* goto next_byte */
- } else if(c1 == '=' && mime_f && !mime_mode ) {
- if((c1 = getc(f)) == EOF) {
- (*oconv)(0, '=');
- LAST;
- } else if(c1 == '?') {
- /* =? is mime conversiooon start sequence */
- if(mime_begin(f) == EOF) /* check in detail */
- LAST;
- else
- NEXT;
- } else {
- (*oconv)(0, '=');
- ungetc(c1,f);
- NEXT;
- }
- } else if(c1 == '$' && broken_f && !mime_mode) {
- /* try to recover missing escape */
- if((c1 = GETC(f)) == EOF) {
- (*oconv)(0, '$');
- LAST;
- } else if(c1 == '@'|| c1 == 'B') {
- /* in case of Kanji in ESC sequence */
- input_mode = X0208;
- shift_mode = FALSE;
- NEXT;
- } else {
- /* sorry */
- (*oconv)(0, '$');
- (*oconv)(0, c1);
- NEXT;
- }
- } else
- SEND;
- } else if(c1 == SI) {
- shift_mode = FALSE;
- NEXT;
- } else if(c1 == SO) {
- shift_mode = TRUE;
- NEXT;
- } else if(c1 == ESC) {
- if((c1 = GETC(f)) == EOF) {
- (*oconv)(0, ESC);
- LAST;
- } else if(c1 == '$') {
- if((c1 = GETC(f)) == EOF) {
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- LAST;
- } else if(c1 == '@'|| c1 == 'B') {
- /* This is kanji introduction */
- input_mode = X0208;
- shift_mode = FALSE;
- NEXT;
- } else if(c1 == '(') {
- if((c1 = GETC(f)) == EOF) {
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- (*oconv)(0, '(');
- LAST;
- } else if(c1 == '@'|| c1 == 'B') {
- /* This is kanji introduction */
- input_mode = X0208;
- shift_mode = FALSE;
- NEXT;
- } else {
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- (*oconv)(0, '(');
- (*oconv)(0, c1);
- NEXT;
- }
- } else if(broken_f&0x2) {
- input_mode = X0208;
- shift_mode = FALSE;
- NEXT;
- } else {
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- (*oconv)(0, c1);
- NEXT;
- }
- } else if(c1 == '(') {
- if((c1 = GETC(f)) == EOF) {
- (*oconv)(0, ESC);
- (*oconv)(0, '(');
- LAST;
- } else {
- if(c1 == 'I') {
- /* This is X0201 kana introduction */
- input_mode = X0201; shift_mode = X0201;
- NEXT;
- } else if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
- /* This is X0208 kanji introduction */
- input_mode = ASCII; shift_mode = FALSE;
- NEXT;
- } else if(broken_f&0x2) {
- input_mode = ASCII; shift_mode = FALSE;
- NEXT;
- } else {
- (*oconv)(0, ESC);
- (*oconv)(0, '(');
- /* maintain various input_mode here */
- SEND;
- }
- }
- } else {
- /* lonely ESC */
- (*oconv)(0, ESC);
- SEND;
- }
- } else if(c1 == NL && broken_f&4) {
- input_mode = ASCII;
- SEND;
- } else
- SEND;
- }
- /* send: */
- if(input_mode == X0208)
- (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
- else
- (*iconv)(c2, c1); /* can be EUC/SJIS */
- c2 = 0;
- continue;
- /* goto next_word */
- }
-
- /* epilogue */
- (*iconv)(EOF, 0);
-}
-
-
-
-
-static void
-h_conv(f, c2, c1)
- FILE *f;
- int c1, c2;
-{
- int wc;
-
-
- /** it must NOT be in the kanji shifte sequence */
- /** it must NOT be written in JIS7 */
- /** and it must be after 2 byte 8bit code */
-
- hold_count = 0;
- push_hold_buf(c2, c1);
- c2 = 0;
-
- while ((c1 = GETC(f)) != EOF) {
- if(c2) {
- /* second byte */
- if(!estab_f) {
- /* not established */
- if(c1 > SSP) {
- /* it is still ambiguious yet */
- SEND;
- } else if(c1 < AT) {
- /* ignore bogus first byte */
- c2 = 0;
- SEND;
- } else {
- /* now established */
- /* it seems to be MS Kanji */
- estab_f = TRUE;
- iconv = s_iconv;
- SEND;
- }
- } else
- SEND;
- } else {
- /* First byte */
- if(c1 > DEL) {
- /* 8th bit is on */
- if(c1 < SSP) {
- /* it seems to be MS Kanji */
- estab_f = TRUE;
- iconv = s_iconv;
- } else if(c1 < 0xe0) {
- /* it seems to be EUC */
- estab_f = TRUE;
- iconv = oconv;
- } else {
- /* still ambiguious */
- }
- c2 = c1;
- NEXT;
- } else
- /* 7 bit code , then send without any process */
- SEND;
- }
- /* send: */
- if((push_hold_buf(c2, c1) == EOF) || estab_f)
- break;
- c2 = 0;
- continue;
- }
-
- /** now,
- ** 1) EOF is detected, or
- ** 2) Code is established, or
- ** 3) Buffer is FULL (but last word is pushed)
- **
- ** in 1) and 3) cases, we continue to use
- ** Kanji codes by oconv and leave estab_f unchanged.
- **/
-
- for (wc = 0; wc < hold_count; wc += 2) {
- c2 = hold_buf[wc];
- c1 = hold_buf[wc+1];
- (*iconv)(c2, c1);
- }
- return;
-}
-
-
-
-static int
-push_hold_buf(c2, c1)
- int c2, c1;
-{
- if(hold_count >= HOLD_SIZE*2)
- return (EOF);
- hold_buf[hold_count++] = c2;
- hold_buf[hold_count++] = c1;
- return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
-}
-
-
-static void
-s_iconv(c2, c1)
- int c2,
- c1;
-{
- if((c2 == EOF) || (c2 == 0)) {
- /* NOP */
- } else {
- c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
- if(c1 < 0x9f)
- c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
- else {
- c1 = c1 - 0x7e;
- c2++;
- }
- }
- (*oconv)(c2, c1);
-}
-
-
-static void
-e_oconv(c2, c1)
- int c2, c1;
-{
- c2 = pre_convert(c1,c2); c1 = c1_return;
- if(fold_f) {
- switch(line_fold(c2,c1)) {
- case '\n':
- if(add_cr == TRUE) {
- putchar('\r');
- c1 = '\n';
- }
- putchar('\n');
- break;
- case 0: return;
- case '\r':
- c1 = '\n'; c2 = 0;
- break;
- case '\t':
- case ' ':
- c1 = ' '; c2 = 0;
- break;
- }
- }
- if(c2==DOUBLE_SPACE) {
- putchar(' '); putchar(' ');
- return;
- }
- if(c2 == EOF)
- return;
- else if(c2 == 0 && (c1&0x80)) {
- putchar(SSO); putchar(c1);
- } else if(c2 == 0) {
- if(c1 == '\n' && add_cr == TRUE)
- putchar('\r');
- if(c1 != '\r')
- putchar(c1);
- else if(del_cr == FALSE)
- putchar(c1);
- } else {
- if((c1<0x20 || 0x7e<c1) ||
- (c2<0x20 || 0x7e<c2)) {
- estab_f = FALSE;
- return; /* too late to rescue this char */
- }
- putchar(c2 | 0x080);
- putchar(c1 | 0x080);
- }
- return;
-}
-
-
-static void
-s_oconv(c2, c1)
- int c2, c1;
-{
- c2 = pre_convert(c1,c2); c1 = c1_return;
- if(fold_f) {
- switch(line_fold(c2,c1)) {
- case '\n':
- if(add_cr == TRUE) {
- putchar('\r');
- c1 = '\n';
- }
- putchar('\n');
- break;
- case '\r':
- c1 = '\n'; c2 = 0;
- break;
- case 0: return;
- case '\t':
- case ' ':
- c1 = ' '; c2 = 0;
- break;
- }
- }
- if(c2==DOUBLE_SPACE) {
- putchar(' '); putchar(' ');
- return;
- }
- if(c2 == EOF)
- return;
- else if(c2 == 0) {
- if(c1 == '\n' && add_cr == TRUE)
- putchar('\r');
- if(c1 != '\r')
- putchar(c1);
- else if(del_cr == FALSE)
- putchar(c1);
- } else {
- if((c1<0x20 || 0x7e<c1) ||
- (c2<0x20 || 0x7e<c2)) {
- estab_f = FALSE;
- return; /* too late to rescue this char */
- }
- putchar((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));
- putchar((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
- }
- return;
-}
-
-
-static void
-j_oconv(c2, c1)
- int c2, c1;
-{
- c2 = pre_convert(c1,c2); c1 = c1_return;
- if(fold_f) {
- switch(line_fold(c2,c1)) {
- case '\n':
- if(output_mode) {
- putchar(ESC);
- putchar('(');
- putchar(ascii_intro);
- }
- if(add_cr == TRUE) {
- putchar('\r');
- c1 = '\n';
- }
- putchar('\n');
- output_mode = ASCII;
- break;
- case '\r':
- c1 = '\n'; c2 = 0;
- break;
- case '\t':
- case ' ':
- c1 = ' '; c2 = 0;
- break;
- case 0: return;
- }
- }
- if(c2 == EOF) {
- if(output_mode) {
- putchar(ESC);
- putchar('(');
- putchar(ascii_intro);
- }
- } else if(c2 == 0 && (c1 & 0x80)) {
- if(input_mode==X0201 || !iso8859_f) {
- if(output_mode!=X0201) {
- putchar(ESC);
- putchar('(');
- putchar('I');
- output_mode = X0201;
- }
- c1 &= 0x7f;
- } else {
- /* iso8859 introduction, or 8th bit on */
- /* Can we convert in 7bit form using ESC-'-'-A ?
- Is this popular? */
- }
- putchar(c1);
- } else if(c2 == 0) {
- if(output_mode) {
- putchar(ESC);
- putchar('(');
- putchar(ascii_intro);
- output_mode = ASCII;
- }
- if(c1 == '\n' && add_cr == TRUE)
- putchar('\r');
- if(c1 != '\r')
- putchar(c1);
- else if(del_cr == FALSE)
- putchar(c1);
- } else if(c2 == DOUBLE_SPACE) {
- if(output_mode) {
- putchar(ESC);
- putchar('(');
- putchar(ascii_intro);
- output_mode = ASCII;
- }
- putchar(' ');
- if(c1 == '\n' && add_cr == TRUE)
- putchar('\r');
- if(c1 != '\r')
- putchar(c1);
- else if(del_cr == FALSE)
- putchar(c1);
- } else {
- if(output_mode != X0208) {
- putchar(ESC);
- putchar('$');
- putchar(kanji_intro);
- output_mode = X0208;
- }
- if(c1<0x20 || 0x7e<c1)
- return;
- if(c2<0x20 || 0x7e<c2)
- return;
- putchar(c2);
- if(c1 == '\n' && add_cr == TRUE)
- putchar('\r');
- if(c1 != '\r')
- putchar(c1);
- else if(del_cr == FALSE)
- putchar(c1);
- }
- return;
-}
-
-
-
-#define rot13(c) ( \
- ( c < 'A' ) ? c: \
- (c <= 'M') ? (c + 13): \
- (c <= 'Z') ? (c - 13): \
- (c < 'a') ? (c): \
- (c <= 'm') ? (c + 13): \
- (c <= 'z') ? (c - 13): \
- (c) \
-)
-
-#define rot47(c) ( \
- ( c < '!' ) ? c: \
- ( c <= 'O' ) ? (c + 47) : \
- ( c <= '~' ) ? (c - 47) : \
- c \
-)
-
-
-/*
- Return value of line_fold()
-
- \n add newline and output char
- \r add newline and output nothing
- ' ' space
- 0 skip
- 1 (or else) normal output
-
- fold state in prev (previous character)
-
- >0x80 Japanese (X0208/X0201)
- <0x80 ASCII
- \n new line
- ' ' space
-
- This fold algorthm does not preserve heading space in a line.
- This is the main difference from fmt.
-*/
-
-static int
-line_fold(c2,c1)
-int c2,c1;
-{
- int prev0;
- if(c1=='\r')
- return 0; /* ignore cr */
- if(c1== 8) {
- if(line>0) line--;
- return 1;
- }
- if(c2==EOF && line != 0) /* close open last line */
- return '\n';
- /* new line */
- if(c1=='\n') {
- if(prev == c1) { /* duplicate newline */
- if(line) {
- line = 0;
- return '\n'; /* output two newline */
- } else {
- line = 0;
- return 1;
- }
- } else {
- if(prev&0x80) { /* Japanese? */
- prev = c1;
- return 0; /* ignore given single newline */
- } else if(prev==' ') {
- return 0;
- } else {
- prev = c1;
- if(++line<=fold_len)
- return ' ';
- else {
- line = 0;
- return '\r'; /* fold and output nothing */
- }
- }
- }
- }
- if(c1=='\f') {
- prev = '\n';
- if(line==0)
- return 1;
- line = 0;
- return '\n'; /* output newline and clear */
- }
- /* X0208 kankaku or ascii space */
- if( (c2==0&&c1==' ')||
- (c2==0&&c1=='\t')||
- (c2==DOUBLE_SPACE)||
- (c2=='!'&& c1=='!')) {
- if(prev == ' ') {
- return 0; /* remove duplicate spaces */
- }
- prev = ' ';
- if(++line<=fold_len)
- return ' '; /* output ASCII space only */
- else {
- prev = ' '; line = 0;
- return '\r'; /* fold and output nothing */
- }
- }
- prev0 = prev; /* we still need this one... , but almost done */
- prev = c1;
- if(c2 || (SSP<=c1 && c1<=0xdf))
- prev |= 0x80; /* this is Japanese */
- line += (c2==0)?1:2;
- if(line<=fold_len) { /* normal case */
- return 1;
- }
- if(line>=fold_len+FOLD_MARGIN) { /* too many kinsou suspension */
- line = (c2==0)?1:2;
- return '\n'; /* We can't wait, do fold now */
- }
- /* simple kinsoku rules return 1 means no folding */
- if(c2==0) {
- if(c1==0xde) return 1; /* $B!+(B*/
- if(c1==0xdf) return 1; /* $B!,(B*/
- if(c1==0xa4) return 1; /* $B!#(B*/
- if(c1==0xa3) return 1; /* $B!$(B*/
- if(c1==0xa1) return 1; /* $B!W(B*/
- if(c1==0xb0) return 1; /* - */
- if(SSP<=c1 && c1<=0xdf) { /* X0201 */
- line = 1;
- return '\n';/* add one new line before this character */
- }
- /* fold point in ASCII { [ ( */
- if(( c1!=')'&&
- c1!=']'&&
- c1!='}'&&
- c1!='.'&&
- c1!=','&&
- c1!='!'&&
- c1!='?'&&
- c1!='/'&&
- c1!=':'&&
- c1!=';')&&
- ((prev0=='\n')|| (prev0==' ')|| /* ignored new line */
- (prev0&0x80)) /* X0208 - ASCII */
- ) {
- line = 1;
- return '\n';/* add one new line before this character */
- }
- return 1; /* default no fold in ASCII */
- } else {
- if(c2=='!') {
- if(c1=='"') return 1; /* $B!"(B */
- if(c1=='#') return 1; /* $B!#(B */
- if(c1=='$') return 1; /* $B!$(B */
- if(c1=='%') return 1; /* $B!%(B */
- if(c1=='\'') return 1; /* $B!\(B */
- if(c1=='(') return 1; /* $B!((B */
- if(c1==')') return 1; /* $B!)(B */
- if(c1=='*') return 1; /* $B!*(B */
- if(c1=='+') return 1; /* $B!+(B */
- if(c1==',') return 1; /* $B!,(B */
- }
- line = 2;
- return '\n'; /* add one new line before this character */
- }
-}
-
-static int
-pre_convert(c1,c2)
- int c1,c2;
-{
- if(c2) c1 &= 0x7f;
- c1_return = c1;
- if(c2==EOF) return c2;
- c2 &= 0x7f;
- if(rot_f) {
- if(c2) {
- c1 = rot47(c1);
- c2 = rot47(c2);
- } else {
- if(!(c1 & 0x80))
- c1 = rot13(c1);
- }
- c1_return = c1;
- }
- /* JISX0208 Alphabet */
- if(alpha_f && c2 == 0x23 ) return 0;
- /* JISX0208 Kigou */
- if(alpha_f && c2 == 0x21 ) {
- if(0x21==c1) {
- if(alpha_f&0x2) {
- c1_return = ' ';
- return 0;
- } else if(alpha_f&0x4) {
- c1_return = ' ';
- return DOUBLE_SPACE;
- } else {
- return c2;
- }
- } else if(0x20<c1 && c1<0x7f && fv[c1-0x20]) {
- c1_return = fv[c1-0x20];
- return 0;
- }
- }
- return c2;
-}
-
-
-#ifdef STRICT_MIME
-/* This converts */
-
-unsigned char *mime_pattern[] = {
- (unsigned char *)"\075?ISO-8859-1?Q?",
- (unsigned char *)"\075?ISO-2022-JP?B?",
- (unsigned char *)"\075?ISO-2022-JP?Q?",
- (unsigned char *)"\075?JAPANESE_EUC?B?",
- (unsigned char *)"\075?SHIFT_JIS?B?",
- NULL
-};
-
-int mime_encode[] = {
- 'Q', 'B', 'Q',
- 0
-};
-#endif
-
-#define MAXRECOVER 20
-int iso8859_f_save;
-
-#ifdef STRICT_MIME
-
-#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c)
-/* I don't trust portablity of toupper */
-
-static int
-mime_begin(f)
- FILE *f;
-{
- int c1;
- int i,j,k;
- unsigned char *p,*q;
- int r[MAXRECOVER]; /* recovery buffer, max mime pattern lenght */
-
- mime_mode = FALSE;
- /* =? has been checked */
- j = 0;
- p = mime_pattern[j];
- r[0]='='; r[1]='?';
-
- for(i=2;p[i]>' ';i++) { /* start at =? */
- if( ((((r[i] = c1 = getc(f))==EOF) || nkf_toupper(c1) != p[i] ) {
- /* pattern fails, try next one */
- q = p;
- while (p = mime_pattern[++j]) {
- for(k=2;k<i;k++) /* assume length(p) > i */
- if(p[k]!=q[k]) break;
- if(k==i && nkf_toupper(c1)==p[k]) break;
- }
- if(p) continue; /* found next one, continue */
- /* all fails, output from recovery buffer */
- ungetc(c1,f);
- for(j=0;j<i;j++) {
- (*oconv)(0,r[j]);
- }
- return c1;
- }
- }
- mime_mode = mime_encode[j];
- iso8859_f_save = iso8859_f;
- if(j==0) {
- iso8859_f = TRUE;
- }
- if(mime_mode=='B') {
- mimebuf_f = unbuf_f;
- if(!unbuf_f) {
- /* do MIME integrity check */
- return mime_integrity(f,mime_pattern[j]);
- }
- }
- mimebuf_f = TRUE;
- return c1;
-}
-
-#define mime_getc0(f) (mimebuf_f?getc(f):Fifo(mime_input++))
-#define mime_ungetc0(c,f) (mimebuf_f?ungetc(c,f):mime_input--)
-
-#else
-static int
-mime_begin(f)
-FILE *f;
-{
- int c1;
- int i,j;
- int r[MAXRECOVER]; /* recovery buffer, max mime pattern lenght */
-
- mime_mode = FALSE;
- /* =? has been checked */
- j = 0;
- r[0]='='; r[1]='?';
- for(i=2;i<MAXRECOVER;i++) { /* start at =? */
- /* We accept any charcter type even if it is breaked by new lines */
- if( (r[i] = c1 = getc(f))==EOF) break;
- if(c1=='=') break;
- if(c1<' '&& c1!='\r' && c1!='\n') break;
- if(c1=='?') {
- i++;
- if(!(i<MAXRECOVER) || (r[i] = c1 = getc(f))==EOF) break;
- if(c1=='b'||c1=='B') {
- mime_mode = 'B';
- } else if(c1=='q'||c1=='Q') {
- mime_mode = 'Q';
- } else {
- break;
- }
- i++;
- if(!(i<MAXRECOVER) || (r[i] = c1 = getc(f))==EOF) break;
- if(c1=='?') {
- break;
- } else {
- mime_mode = FALSE;
- }
- break;
- }
- }
- if(!mime_mode || c1==EOF || i==MAXRECOVER) {
- ungetc(c1,f);
- if (i == MAXRECOVER)
- i--;
- for(j=0;j<i;j++) {
- (*oconv)(0,r[j]);
- }
- return c1;
- }
- iso8859_f_save = iso8859_f;
- /* do no MIME integrity check */
- return c1; /* used only for checking EOF */
-}
-
-#define mime_getc0(f) getc(f)
-#define mime_ungetc0(c,f) ungetc(c,f)
-
-#endif
-
-static int
-mime_getc(f)
- FILE *f;
-{
- int c1, c2, c3, c4, cc;
- int t1, t2, t3, t4, mode, exit_mode;
-
- if(mime_top != mime_last) { /* Something is in FIFO */
- return Fifo(mime_top++);
- }
-
- if(mimebuf_f == FIXED_MIME)
- exit_mode = mime_mode;
- else
- exit_mode = FALSE;
- if(mime_mode == 'Q') {
- if((c1 = mime_getc0(f)) == EOF) return (EOF);
- if(c1=='_') return ' ';
- if(c1!='=' && c1!='?')
- return c1;
- mime_mode = exit_mode; /* prepare for quit */
- if(c1<=' ') return c1;
- if((c2 = mime_getc0(f)) == EOF) return (EOF);
- if(c2<=' ') return c2;
- if(c1=='?'&&c2=='=') {
- /* end Q encoding */
- input_mode = exit_mode;
- iso8859_f = iso8859_f_save;
- return getc(f);
- }
- if(c1=='?') {
- mime_mode = 'Q'; /* still in MIME */
- mime_ungetc0(c2,f);
- return c1;
- }
- if((c3 = mime_getc0(f)) == EOF) return (EOF);
- if(c2<=' ') return c2;
- mime_mode = 'Q'; /* still in MIME */
-#define hex(c) (('0'<=c&&c<='9')?(c-'0'):\
- ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)
- return ((hex(c2)<<4) + hex(c3));
- }
-
- if(mime_mode != 'B') {
- mime_mode = FALSE;
- return getc(f);
- }
-
-
- /* Base64 encoding */
- /*
- MIME allows line break in the middle of
- Base64, but we are very pessimistic in decoding
- in unbuf mode because MIME encoded code may broken by
- less or editor's control sequence (such as ESC-[-K in unbuffered
- mode. ignore incomplete MIME.
- */
- mode = mime_mode;
- mime_mode = exit_mode; /* prepare for quit */
-
- while ((c1 = mime_getc0(f))<=' ') {
- if(c1==EOF)
- return (EOF);
- }
- if((c2 = mime_getc0(f))<=' ') {
- if(c2==EOF)
- return (EOF);
- if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
- return c2;
- }
- if((c1 == '?') && (c2 == '=')) {
- input_mode = ASCII;
- while((c1 = getc(f))==' ' /* || c1=='\n' || c1=='\r' */);
- return c1;
- }
- if((c3 = mime_getc0(f))<=' ') {
- if(c3==EOF)
- return (EOF);
- if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
- return c3;
- }
- if((c4 = mime_getc0(f))<=' ') {
- if(c4==EOF)
- return (EOF);
- if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
- return c4;
- }
-
- mime_mode = mode; /* still in MIME sigh... */
-
- /* BASE 64 decoding */
-
- t1 = 0x3f & base64decode(c1);
- t2 = 0x3f & base64decode(c2);
- t3 = 0x3f & base64decode(c3);
- t4 = 0x3f & base64decode(c4);
- cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
- if(c2 != '=') {
- Fifo(mime_last++) = cc;
- cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
- if(c3 != '=') {
- Fifo(mime_last++) = cc;
- cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
- if(c4 != '=')
- Fifo(mime_last++) = cc;
- }
- } else {
- return c1;
- }
- return Fifo(mime_top++);
-}
-
-static int
-mime_ungetc(c)
- unsigned int c;
-{
- Fifo(mime_last++) = c;
- return c;
-}
-
-#ifdef STRICT_MIME
-int
-mime_integrity(f,p)
- FILE *f;
- unsigned char *p;
-{
- int c,d;
- unsigned int q;
- /* In buffered mode, read until =? or NL or buffer fffull
- */
- mime_input = mime_top;
- mime_last = mime_top;
- while(*p) Fifo(mime_input++) = *p++;
- d = 0;
- q = mime_input;
- while((c=getc(f))!=EOF) {
- if(((mime_input-mime_top)&MIME_BUF_MASK)==0) break;
- if(c=='=' && d=='?') {
- /* checked. skip header, start decode */
- Fifo(mime_input++) = c;
- mime_input = q;
- return 1;
- }
- if(!( (c=='+'||c=='/'|| c=='=' || c=='?' ||
- ('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))))
- break;
- /* Should we check length mod 4? */
- Fifo(mime_input++) = c;
- d=c;
- }
- /* In case of Incomplete MIME, no MIME decode */
- Fifo(mime_input++) = c;
- mime_last = mime_input; /* point undecoded buffer */
- mime_mode = 1; /* no decode on Fifo last in mime_getc */
- return 1;
-}
-#endif
-
-static int
-base64decode(c)
- int c;
-{
- int i;
- if(c > '@')
- if(c < '[')
- i = c - 'A'; /* A..Z 0-25 */
- else
- i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */
- else if(c > '/')
- i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */
- else if(c == '+')
- i = '>' /* 62 */ ; /* + 62 */
- else
- i = '?' /* 63 */ ; /* / 63 */
- return (i);
-}
-
-static void
-reinit()
-{
- unbuf_f = FALSE;
- estab_f = FALSE;
- nop_f = FALSE;
- binmode_f = TRUE;
- rot_f = FALSE;
- input_f = FALSE;
- alpha_f = FALSE;
- mime_f = TRUE;
- mimebuf_f = FALSE;
- broken_f = FALSE;
- iso8859_f = FALSE;
- x0201_f = TRUE;
- x0201_f = NO_X0201;
- fold_f = FALSE;
- kanji_intro = DEFAULT_J;
- ascii_intro = DEFAULT_R;
- oconv = DEFAULT_CONV;
- output_mode = ASCII;
- input_mode = ASCII;
- shift_mode = FALSE;
- mime_mode = FALSE;
- file_out = FALSE;
- add_cr = FALSE;
- del_cr = FALSE;
- line = 0;
-}
-
-#ifndef PERL_XS
-int
-usage()
-{
- fprintf(stderr,"USAGE: nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
- fprintf(stderr,"Flags:\n");
- fprintf(stderr,"b,u Output is bufferred (DEFAULT),Output is unbufferred\n");
-#ifdef DEFAULT_CODE_SJIS
- fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC)\n");
-#endif
-#ifdef DEFAULT_CODE_JIS
- fprintf(stderr,"j,s,e Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC)\n");
-#endif
-#ifdef DEFAULT_CODE_EUC
- fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT)\n");
-#endif
- fprintf(stderr,"J,S,E Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC)\n");
- fprintf(stderr,"t no conversion\n");
- fprintf(stderr,"i_ Output sequence to designate JIS-kanji (DEFAULT B)\n");
- fprintf(stderr,"o_ Output sequence to designate ASCII (DEFAULT B)\n");
- fprintf(stderr,"r {de/en}crypt ROT13/47\n");
- fprintf(stderr,"v Show this usage\n");
- fprintf(stderr,"m[BQ0] MIME decode [B:base64,Q:quoted,0:no decode]\n");
- fprintf(stderr,"l ISO8859-1 (Latin-1) support\n");
- fprintf(stderr,"f Folding: -f60 or -f\n");
- fprintf(stderr,"Z[0-2] Convert X0208 alphabet to ASCII 1: Kankaku to space,2: 2 spaces\n");
- fprintf(stderr,"X,x Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
- fprintf(stderr,"B[0-2] Broken input 0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
-#ifdef MSDOS
- fprintf(stderr,"T Text mode output\n");
-#endif
- fprintf(stderr,"O Output to File (DEFAULT 'nkf.out')\n");
- fprintf(stderr,"d,c Delete \\r in line feed, Add \\r in line feed\n");
- fprintf(stderr,"Network Kanji Filter Version %s (%s) "
-#if defined(MSDOS) && !defined(_Windows)
- "for DOS"
-#endif
-#if !defined(__WIN32__) && defined(_Windows)
- "for Win16"
-#endif
-#if defined(__WIN32__) && defined(_Windows)
- "for Win32"
-#endif
-#ifdef __OS2__
- "for OS/2"
-#endif
- ,Version,Patchlevel);
- fprintf(stderr,"\n%s\n",CopyRight);
- return 0;
-}
-#endif
-
-/**
- ** $B%Q%C%A@):n<T(B
- ** void@merope.pleiades.or.jp (Kusakabe Youichi)
- ** NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
- ** ohta@src.ricoh.co.jp (Junn Ohta)
- ** inouet@strl.nhk.or.jp (Tomoyuki Inoue)
- ** kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
- ** Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
- ** a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
- ** kono@ie.u-ryukyu.ac.jp (Shinji Kono)
- ** GHG00637@nifty-serve.or.jp (COW)
- **
- ** $B:G=*99?7F|(B
- ** 1998.11.7
- **/
-
-/* end */
diff --git a/ext/nkf/test.rb b/ext/nkf/test.rb
deleted file mode 100644
index 4519f8ba7e..0000000000
--- a/ext/nkf/test.rb
+++ /dev/null
@@ -1,318 +0,0 @@
-$counter = 0
-def result(result, message = nil)
- $counter += 1
- printf("%s %d%s\n",
- result ? 'ok' : 'no',
- $counter,
- message ? ' ... ' + message : '')
-end
-
-begin
- require 'nkf'
- include NKF
-rescue LoadError
- result(false)
-end
-result(true)
-
-if nkf('-me', '1')
- result(true);
-else
- result(false);
-end
-
-output = nkf('-e', "\033\$@#1#3#2%B")
-if output
- # print output, "\n"
- result(true, output)
-else
- result(false)
-end
-
-output = nkf('-Zj', "\033\$@#1#3#2%B")
-if output
- # print output, "\n"
- result(true, output)
-else
- result(false)
-end
-
-output = "\244\306 " * 1024
-old = output.length
-output = nkf("-j", output)
-if output
- # print output, "\n"
- result(true, "#{old} #{output.length}")
-else
- result(false)
-end
-
-
-$detail = false
-def test(opt, input, expect)
- print "\nINPUT:\n", input if $detail
- print "\nEXPECT:\n", expect if $detail
- result = nkf(opt, input)
- print "\nGOT:\n", result if $detail
-
- print result == expect ? "Ok\n" : "Fail\n"
- return result
-end
-
-# Basic Conversion
-print "\nBasic Conversion test\n\n"
-
-example = {}
-example['jis'] = <<'eofeof'.unpack('u')[0]
-M1FER<W0@4W1A9V4@&R1"(3DQ(3%^2R%+?D]3&RA"(%-E8V]N9"!3=&%G92`;
-M)$)0)TU:&RA"($AI<F%G86YA(!LD0B0B)"0D)B0H)"HD;R1R)',;*$(*2V%T
-M86MA;F$@&R1")2(E)"4F)2@E*B5O)7(E<QLH0B!+:6=O=2`;)$(A)B%G(S`C
-/029!)E@G(B=!*$`;*$(*
-eofeof
-#'
-
-example['sjis'] = <<'eofeof'.unpack('u')[0]
-M1FER<W0@4W1A9V4@@5B)0(F>ED"6GIAR(%-E8V]N9"!3=&%G92"8I9=Y($AI
-M<F%G86YA((*@@J*"I(*F@JB"[8+P@O$*2V%T86MA;F$@@T&#0X-%@T>#28./
->@Y*#DR!+:6=O=2"!18&'@D^"8(._@]:$081@A+X*
-eofeof
-#'
-
-example['euc'] = <<'eofeof'.unpack('u')[0]
-M1FER<W0@4W1A9V4@H;FQH;'^RZ'+_L_3(%-E8V]N9"!3=&%G92#0I\W:($AI
-M<F%G86YA(*2BI*2DIJ2HI*JD[Z3RI/,*2V%T86MA;F$@I:*EI*6FI:BEJJ7O
->I?*E\R!+:6=O=2"AIJ'GH["CP:;!IMBGHJ?!J,`*
-eofeof
-#'
-
-example['amb'] = <<'eofeof'.unpack('u')[0]
-MI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&E
-MPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*P
-ML:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&E
-MPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"
-ML+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"Q
-MI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"
-ML+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*
-eofeof
-
-example['amb.euc'] = <<'eofeof'.unpack('u')[0]
-M&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25"
-M,#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P,25"
-M,#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;
-M*$(*&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P
-M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P
-M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
-M)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
->)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*
-eofeof
-
-example['amb.sjis'] = <<'eofeof'.unpack('u')[0]
-M&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25"
-M,#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P,25"
-M,#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;
-M*$(*&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P
-M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P
-M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
-M)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
->)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*
-eofeof
-
-example['x0201.sjis'] = <<'eofeof'.unpack('u')[0]
-MD5.*<(-*@TR#3H-0@U*#2X--@T^#48-3"I%3B7""8()A@F*"8X)D@F6"9H*!
-M@H*"@X*$@H6"AH*'"I%3BTR-AH%)@9>!E(&0@9.!3X&5@9:!:8%J@7R!>X&!
-M@6V!;H%O@7"!CPJ4O(IPMK>X/;FZMMZWWKC>N=ZZWH+&"I2\BG#*W\O?S-_-
-MW\[?M]^QW@K*W\O?S`IH86YK86MU(,K?R]_,I`K*W\O?S-VA"I2\BG""S(SC
-!"@!"
-eofeof
-#'
-
-example['x0201.euc'] = <<'eofeof'.unpack('u')[0]
-MP;2ST:6KI:VEKZ6QI;.EK*6NI;"ELJ6T"L&TL=&CP:/"H\.CQ*/%H\:CQZ/A
-MH^*CXZ/DH^6CYJ/G"L&TM:VYYJ&JH?>A]*'PH?.AL*'UH?:ARJ'+H=VAW*'A
-MH<ZASZ'0H=&A[PK(OK/1CK:.MXZX/8ZYCKJ.MH[>CK>.WHZXCMZ.N8[>CKJ.
-MWJ3("LB^L]&.RH[?CLN.WX[,CM^.S8[?CLZ.WXZWCM^.L8[>"H[*CM^.RX[?
-MCLP*:&%N:V%K=2".RH[?CLN.WX[,CJ0*CLJ.WX[+CM^.S([=CJ$*R+ZST:3.
-#N.4*
-eofeof
-#'
-
-example['x0201.jis'] = <<'eofeof'.unpack('u')[0]
-M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA""ALD0D$T,5$C02-"(T,C
-M1"-%(T8C1R-A(V(C8R-D(V4C9B-G&RA""ALD0D$T-2TY9B$J(7<A="%P(7,A
-M,"%U(78A2B%+(5TA7"%A(4XA3R%0(5$A;QLH0@H;)$)(/C-1&RA)-C<X&RA"
-M/1LH23DZ-EXW7CA>.5XZ7ALD0B1(&RA""ALD0D@^,U$;*$E*7TM?3%]-7TY?
-M-U\Q7ALH0@H;*$E*7TM?3!LH0@IH86YK86MU(!LH24I?2U],)!LH0@H;*$E*
-97TM?3%TA&RA""ALD0D@^,U$D3CAE&RA""@``
-eofeof
-#`
-
-example['x0201.sosi'] = <<'eofeof'.unpack('u')[0]
-M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA*"ALD0D$T,5$C02-"(T,C
-M1"-%(T8C1R-A(V(C8R-D(V4C9B-G&RA*"ALD0D$T-2TY9B$J(7<A="%P(7,A
-M,"%U(78A2B%+(5TA7"%A(4XA3R%0(5$A;QLH2@H;)$)(/C-1&RA*#C8W.`\;
-M*$H]#CDZ-EXW7CA>.5XZ7@\;)$(D2!LH2@H;)$)(/C-1&RA*#DI?2U],7TU?
-M3E\W7S%>#PH.2E]+7TP/&RA*"FAA;FMA:W4@#DI?2U],)`\;*$H*#DI?2U],
-672$/&RA*"ALD0D@^,U$D3CAE&RA""@``
-eofeof
-#"
-
-example['x0201.x0208'] = <<'eofeof'.unpack('u')[0]
-M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA""ALD0D$T,5$;*$)!0D-$
-M149'86)C9&5F9PH;)$)!-#4M.68;*$(A0",D)5XF*B@I+2L]6UU[?1LD0B%O
-M&RA""ALD0D@^,U$E*R4M)2\;*$(]&R1")3$E,R4L)2XE,"4R)30D2!LH0@H;
-M)$)(/C-1)5$E5"57)5HE724M(2PE(B$K&RA""ALD0B51)50E51LH0@IH86YK
-M86MU(!LD0B51)50E52$B&RA""ALD0B51)50E525S(2,;*$(*&R1"2#XS421.
-&.&4;*$(*
-eofeof
-#`
-
-example['mime.iso2022'] = <<'eofeof'.unpack('u')[0]
-M/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23TI566Q/4U9)1WEH2S\]"CT_
-M:7-O+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]*55EL3U-624=Y:$L_/0H]/VES
-M;RTR,#(R+4I0/U$_/3%")$(D1B11/3%"*$)?96YD/ST*&R1`)#TD)B0K)$H;
-M*$H@/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D:'-O4V<]/3\]
-M(&5N9"!O9B!L:6YE"CT_25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]0>6LW
-M9&AS;U-G/3T_/2`]/TE33RTR,#(R+4I0/T(_1WE204Y%13=E:5)/4'EK-V1H
-M<V]39ST]/ST*0G)O:V5N(&-A<V4*/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W
-M96E23U!Y:S=D"FAS;U-G/3T_/2`]/TE33RTR,`HR,BU*4#]"/T=Y4D%.144W
-M96E23U!Y:S=D:'-O4V<]/3\]"CT_25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I
-44D]*55EL3QM;2U-624=Y:$L_/0H_
-eofeof
-#'
-
-example['mime.ans.strict'] = <<'eofeof'.unpack('u')[0]
-M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
-M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
-M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
-M/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D"FAS;U-G/3T_/2`]
-M/TE33RTR,`HR,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D:'-O4V<]/3\]"CT_
-L25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]*55EL3QM;2U-624=Y:$L_/0H_
-eofeof
-#'
-
-example['mime.unbuf.strict'] = <<'eofeof'.unpack('u')[0]
-M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
-M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
-M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
-M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@/3])4T\M,C`*,C(M2E`_0C]'>5)!
-M3D5%-V5I4D]0>6LW9&AS;U-G/3T_/0H;)$(T03MZ)$XE1ALH0EM+4U9)1WEH
-$2S\]"F5I
-eofeof
-
-example['mime.ans'] = <<'eofeof'.unpack('u')[0]
-M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
-M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
-M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
-M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@&R1"-$$[>B1./RD[=ALH0@H;)$(T
-603MZ)$XE1ALH0EM+4U9)1WEH2S\]"@`*
-eofeof
-#"
-
-example['mime.unbuf'] = <<'eofeof'.unpack('u')[0]
-M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
-M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
-M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
-M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@&R1"-$$[>B1./RD[=ALH0@H;)$(T
-603MZ)$XE1ALH0EM+4U9)1WEH2S\]"@`*
-eofeof
-#"
-
-example['mime.base64'] = <<'eofeof'.unpack('u')[0]
-M9W-M5"])3&YG<FU#>$I+-&=Q=4,S24LS9W%Q0E%:3TUI-39,,S0Q-&=S5T)1
-M43!+9VUA1%9O3T@*9S)+1%1O3'=K8C)1;$E+;V=Q2T-X24MG9W5M0W%*3EEG
-<<T=#>$E+9V=U;4,X64Q&9W)70S592VMG<6U""F=Q
-eofeof
-#"
-
-example['mime.base64.ans'] = <<'eofeof'.unpack('u')[0]
-M&R1")$M&?B1I)#LD1D0Z)"TD7B0Y)"PA(D5L-7XV83E9)$<A(ALH0@T*&R1"
-M(T<E-R5G)4,E+R1R0C\_="0J)"0D1B0B)&LD*D4Y)$,D1B0B)&LD<R1')#<D
-(9R0F)"L;*$(E
-eofeof
-#'
-
-example['mime.is8859'] = <<'eofeof'.unpack('u')[0]
-M/3])4T\M.#@U.2TQ/U$_*CU#-V%V83\_/2`*4&5E<B!4]G)N9W)E;@I,87-S
-M92!(:6QL97+X92!0971E<G-E;B`@7"`B36EN(&MA97!H97-T(&AA<B!F86%E
-M="!E="!F;V5L(2(*06%R:'5S(%5N:79E<G-I='DL($1%3DU!4DL@(%P@(DUI
-<;B!KYG!H97-T(&AA<B!FY65T(&5T(&;X;"$B"@!K
-eofeof
-
-example['mime.is8859.ans'] = <<'eofeof'.unpack('u')[0]
-M*L=A=F$_(`I0965R(%3V<FYG<F5N"DQA<W-E($AI;&QE<OAE(%!E=&5R<V5N
-M("!<(")-:6X@:V%E<&AE<W0@:&%R(&9A865T(&5T(&9O96PA(@I!87)H=7,@
-M56YI=F5R<VET>2P@1$5.34%22R`@7"`B36EN(&OF<&AE<W0@:&%R(&;E970@
-)970@9OAL(2(*
-eofeof
-#"
-
-print 'JIS to JIS ... '; test(' ', example['jis'], example['jis'])
-print 'JIS to SJIS... '; test('-s', example['jis'], example['sjis'])
-print 'JIS to EUC ... '; test('-e', example['jis'], example['euc'])
-
-print 'SJIS to JIS ... '; test('-j', example['sjis'], example['jis'])
-print 'SJIS to SJIS... '; test('-s', example['sjis'], example['sjis'])
-print 'SJIS to EUC ... '; test('-e', example['sjis'], example['euc'])
-
-print 'EUC to JIS ... '; test(' ', example['euc'], example['jis'])
-print 'EUC to SJIS... '; test('-s', example['euc'], example['sjis'])
-print 'EUC to EUC ... '; test('-e', example['euc'], example['euc'])
-
-
-# Ambigous Case
-print 'Ambiguous Case. '; test('' , example['amb'], example['amb.euc'])
-
-# Input assumption
-print 'SJIS Input assumption '
-test('-Sx', example['amb'], example['amb.sjis'])
-
-# X0201 ²¾Ì¾
-# X0201->X0208 conversion
-# X0208 aphabet -> ASCII
-# X0201 Áê¸ßÊÑ´¹
-
-print "\nX0201 test\n\n"
-
-# -X is necessary to allow X0201 in SJIS
-# -Z convert X0208 alphabet to ASCII
-print 'X0201 conversion: SJIS '
-test('-XZ', example['x0201.sjis'], example['x0201.x0208'])
-print 'X0201 conversion: JIS '
-test('-Z', example['x0201.jis'], example['x0201.x0208'])
-print 'X0201 conversion:SI/SO '
-test('-Z', example['x0201.sosi'], example['x0201.x0208'])
-print 'X0201 conversion: EUC '
-test('-Z', example['x0201.euc'], example['x0201.x0208'])
-# -x means X0201 output
-print 'X0201 output: SJIS '
-test('-xs', example['x0201.euc'], example['x0201.sjis'])
-print 'X0201 output: JIS '
-test('-xj', example['x0201.sjis'], example['x0201.jis'])
-print 'X0201 output: EUC '
-test('-xe', example['x0201.jis'], example['x0201.euc'])
-
-# MIME decode
-
-print "\nMIME test\n\n"
-
-# MIME ISO-2022-JP
-
-print "Next test is expeced to Fail.\n"
-
-print 'MIME decode (strict) '
-tmp = test('-m', example['mime.iso2022'], example['mime.ans.strict'])
-print 'MIME decode (nonstrict)'
-tmp = test('-m', example['mime.iso2022'], example['mime.ans'])
-# open(OUT,'>tmp1');print OUT pack('u',$tmp);close(OUT);
-# unbuf mode implies more pessimistic decode
-print 'MIME decode (unbuf) '
-test('-mu', example['mime.iso2022'], example['mime.unbuf'])
-print 'MIME decode (base64) '
-t = test('-mB', example['mime.base64'], example['mime.base64.ans'])
-
-# MIME ISO-8859-1
-
-# Without -l, ISO-8859-1 was handled as X0201.
-
-print 'MIME ISO-8859-1 (Q) '
-test('-ml', example['mime.is8859'], example['mime.is8859.ans'])
diff --git a/ext/openssl/.cvsignore b/ext/openssl/.cvsignore
index dfb8bfb8bb..3a9a9f341f 100644
--- a/ext/openssl/.cvsignore
+++ b/ext/openssl/.cvsignore
@@ -2,3 +2,4 @@ GNUmakefile
Makefile
mkmf.log
dep
+extconf.h
diff --git a/ext/openssl/MANIFEST b/ext/openssl/MANIFEST
deleted file mode 100644
index cdaf55c926..0000000000
--- a/ext/openssl/MANIFEST
+++ /dev/null
@@ -1,60 +0,0 @@
-MANIFEST
-extconf.rb
-lib/net/ftptls.rb
-lib/net/https.rb
-lib/net/protocols.rb
-lib/net/telnets.rb
-lib/openssl.rb
-lib/openssl/bn.rb
-lib/openssl/buffering.rb
-lib/openssl/cipher.rb
-lib/openssl/digest.rb
-lib/openssl/ssl.rb
-lib/openssl/x509.rb
-openssl_missing.c
-openssl_missing.h
-ossl.c
-ossl.h
-ossl_asn1.c
-ossl_asn1.h
-ossl_bio.c
-ossl_bio.h
-ossl_bn.c
-ossl_bn.h
-ossl_cipher.c
-ossl_cipher.h
-ossl_config.c
-ossl_config.h
-ossl_digest.c
-ossl_digest.h
-ossl_engine.c
-ossl_engine.h
-ossl_hmac.c
-ossl_hmac.h
-ossl_ns_spki.c
-ossl_ns_spki.h
-ossl_ocsp.c
-ossl_ocsp.h
-ossl_pkcs7.c
-ossl_pkcs7.h
-ossl_pkey.c
-ossl_pkey.h
-ossl_pkey_dh.c
-ossl_pkey_dsa.c
-ossl_pkey_rsa.c
-ossl_rand.c
-ossl_rand.h
-ossl_ssl.c
-ossl_ssl.h
-ossl_version.h
-ossl_x509.c
-ossl_x509.h
-ossl_x509attr.c
-ossl_x509cert.c
-ossl_x509crl.c
-ossl_x509ext.c
-ossl_x509name.c
-ossl_x509req.c
-ossl_x509revoked.c
-ossl_x509store.c
-ruby_missing.h
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index a4239a1225..02e06b7149 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -33,13 +33,9 @@ if with_config("debug") or enable_config("debug")
end
end
-
-
message "=== Checking for system dependent stuff... ===\n"
have_library("nsl", "t_open")
have_library("socket", "socket")
-have_header("unistd.h")
-have_header("sys/time.h")
have_header("assert.h")
message "=== Checking for required stuff... ===\n"
@@ -58,71 +54,73 @@ if !result
end
end
+unless have_header("openssl/conf_api.h")
+ message "OpenSSL 0.9.6 or later required.\n"
+ exit 1
+end
+
+%w"rb_str_set_len rb_block_call".each {|func| have_func(func, "ruby.h")}
+
message "=== Checking for OpenSSL features... ===\n"
-have_func("HMAC_CTX_copy")
-have_func("X509_STORE_get_ex_data")
-have_func("X509_STORE_set_ex_data")
-have_func("EVP_MD_CTX_create")
+have_func("ERR_peek_last_error")
+have_func("BN_mod_add")
+have_func("BN_mod_sqr")
+have_func("BN_mod_sub")
+have_func("BN_pseudo_rand_range")
+have_func("BN_rand_range")
+have_func("CONF_get1_default_config_file")
+have_func("EVP_CIPHER_CTX_copy")
+have_func("EVP_CIPHER_CTX_set_padding")
+have_func("EVP_CipherFinal_ex")
+have_func("EVP_CipherInit_ex")
+have_func("EVP_DigestFinal_ex")
+have_func("EVP_DigestInit_ex")
have_func("EVP_MD_CTX_cleanup")
+have_func("EVP_MD_CTX_create")
have_func("EVP_MD_CTX_destroy")
-have_func("PEM_def_callback")
have_func("EVP_MD_CTX_init")
-have_func("HMAC_CTX_init")
have_func("HMAC_CTX_cleanup")
-have_func("X509_CRL_set_version")
+have_func("HMAC_CTX_copy")
+have_func("HMAC_CTX_init")
+have_func("PEM_def_callback")
+have_func("PKCS5_PBKDF2_HMAC")
+have_func("PKCS5_PBKDF2_HMAC_SHA1")
+have_func("X509V3_set_nconf")
+have_func("X509V3_EXT_nconf_nid")
+have_func("X509_CRL_add0_revoked")
have_func("X509_CRL_set_issuer_name")
+have_func("X509_CRL_set_version")
have_func("X509_CRL_sort")
-have_func("X509_CRL_add0_revoked")
-have_func("CONF_get1_default_config_file")
-have_func("BN_mod_sqr")
-have_func("BN_mod_add")
-have_func("BN_mod_sub")
-have_func("BN_rand_range")
-have_func("BN_pseudo_rand_range")
-have_func("CONF_get1_default_config_file")
-have_func("X509V3_set_nconf")
+have_func("X509_STORE_get_ex_data")
+have_func("X509_STORE_set_ex_data")
+have_func("OBJ_NAME_do_all_sorted")
+have_func("SSL_SESSION_get_id")
+have_func("OPENSSL_cleanse")
if try_compile("#define FOO(a, ...) foo(a, ##__VA_ARGS__)\n int x(){FOO(1);FOO(1,2);FOO(1,2,3);}\n")
$defs.push("-DHAVE_VA_ARGS_MACRO")
end
if have_header("openssl/engine.h")
+ have_func("ENGINE_add")
have_func("ENGINE_load_builtin_engines")
have_func("ENGINE_load_openbsd_dev_crypto")
have_func("ENGINE_get_digest")
have_func("ENGINE_get_cipher")
have_func("ENGINE_cleanup")
end
-have_header("openssl/ocsp.h")
+if try_compile(<<SRC)
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+# error "OpenSSL version is less than 0.9.7."
+#endif
+SRC
+ have_header("openssl/ocsp.h")
+end
have_struct_member("EVP_CIPHER_CTX", "flags", "openssl/evp.h")
+have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h")
have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h")
message "=== Checking done. ===\n"
-$distcleanfiles << "GNUmakefile" << "dep"
-create_makefile("openssl")
-if /gcc/ =~ CONFIG["CC"]
- File.open("GNUmakefile", "w") {|f|
- f.print <<EOD
-include Makefile
-SRCS = $(OBJS:.o=.c)
-
-test-link: $(OBJS)
- $(CC) $(DLDFLAGS) #{OUTFLAG}.testlink $(OBJS) $(LIBPATH) $(LIBS) $(LOCAL_LIBS)
- @$(RM) .testlink
- @echo "Done."
-
-dep:
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $(SRCS) -MM | \\
- $(RUBY) -p -e 'BEGIN{S = []' \\
- -e 'while !ARGV.empty? and /^(\\w+)=(.*)/ =~ ARGV[0]' \\
- -e 'S << [/\#{Regexp.quote($$2)}\\//, "$$(\#{$$1})/"]' \\
- -e 'ARGV.shift' \\
- -e 'end' \\
- -e '}' -e 'S.each(&method(:gsub!))' -- \\
- 'topdir=$(topdir)' 'srcdir=$(srcdir)' 'hdrdir=$(hdrdir)' \\
- > dep
-
-include dep
-EOD
- }
-end
+create_header
+create_makefile("openssl")
message "Done.\n"
diff --git a/ext/openssl/lib/net/ftptls.rb b/ext/openssl/lib/net/ftptls.rb
index f433457923..a21c1f6c3c 100644
--- a/ext/openssl/lib/net/ftptls.rb
+++ b/ext/openssl/lib/net/ftptls.rb
@@ -29,13 +29,23 @@ require 'net/ftp'
module Net
class FTPTLS < FTP
+ def connect(host, port=FTP_PORT)
+ @hostname = host
+ super
+ end
+
def login(user = "anonymous", passwd = nil, acct = nil)
+ store = OpenSSL::X509::Store.new
+ store.set_default_paths
ctx = OpenSSL::SSL::SSLContext.new('SSLv23')
+ ctx.cert_store = store
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.key = nil
ctx.cert = nil
voidcmd("AUTH TLS")
@sock = OpenSSL::SSL::SSLSocket.new(@sock, ctx)
@sock.connect
+ @sock.post_connection_check(@hostname)
super(user, passwd, acct)
voidcmd("PBSZ 0")
end
diff --git a/ext/openssl/lib/net/https.rb b/ext/openssl/lib/net/https.rb
deleted file mode 100644
index fb7f53c555..0000000000
--- a/ext/openssl/lib/net/https.rb
+++ /dev/null
@@ -1,188 +0,0 @@
-=begin
-= $RCSfile$ -- SSL/TLS enhancement for Net::HTTP.
-
-= Info
- 'OpenSSL for Ruby 2' project
- Copyright (C) 2001 GOTOU Yuuzou <gotoyuzo@notwork.org>
- All rights reserved.
-
-= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Requirements
- This program requires Net 1.2.0 or higher version.
- You can get it from RAA or Ruby's CVS repository.
-
-= Version
- $Id$
-
- 2001/11/06: Contiributed to Ruby/OpenSSL project.
-
-== class Net::HTTP
-
-== Example
-
-Simple HTTP client is here:
-
- require 'net/http'
- host, port, path = "localhost", 80, "/"
- if %r!http://(.*?)(?::(\d+))?(/.*)! =~ ARGV[0]
- host = $1
- port = $2.to_i if $2
- path = $3
- end
- h = Net::HTTP.new(host, port)
- h.get2(path){ |resp| print resp.body }
-
-It can be replaced by follow one:
-
- require 'net/https'
- host, port, path = "localhost", 80, "/"
- if %r!(https?)://(.*?)(?::(\d+))?(/.*)! =~ ARGV[0]
- scheme = $1
- host = $2
- port = $3 ? $3.to_i : ((scheme == "http") ? 80 : 443)
- path = $4
- end
- h = Net::HTTP.new(host, port)
- h.use_ssl = true if scheme == "https" # enable SSL/TLS
- h.get2(path){ |resp| print resp.body }
-
-=== Instance Methods
-
-: use_ssl
- returns ture if use SSL/TLS with HTTP.
-
-: use_ssl=((|true_or_false|))
- sets use_ssl.
-
-: peer_cert
- return the X.509 certificates the server presented.
-
-: key=((|key|))
- Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
- (This method is appeared in Michal Rokos's OpenSSL extention.)
-
-: key_file=((|path|))
- Sets a private key file to use in PEM format.
-
-: cert=((|cert|))
- Sets an OpenSSL::X509::Certificate object as client certificate.
- (This method is appeared in Michal Rokos's OpenSSL extention.)
-
-: cert_file=((|path|))
- Sets pathname of a X.509 certification file in PEM format.
-
-: ca_file=((|path|))
- Sets path of a CA certification file in PEM format.
- The file can contrain several CA certificats.
-
-: ca_path=((|path|))
- Sets path of a CA certification directory containing certifications
- in PEM format.
-
-: verify_mode=((|mode|))
- Sets the flags for server the certification verification at
- begining of SSL/TLS session.
- OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER is acceptable.
-
-: verify_callback=((|proc|))
- Sets the verify callback for the server certification verification.
-
-: verify_depth=((|num|))
- Sets the maximum depth for the certificate chain verification.
-
-: cert_store=((|store|))
- Sets the X509::Store to verify peer certificate.
-
-=end
-
-require 'net/protocols'
-require 'net/http'
-
-module Net
- class HTTP
- class Conn < HTTPRequest
- REQUEST_HAS_BODY=false
- RESPONSE_HAS_BODY=false
- METHOD="connect"
-
- def initialize
- super nil, nil
- end
-
- def exec( sock, addr, port, ver )
- @socket = sock
- request(addr, port, ver)
- end
-
- def request( addr, port, ver )
- @socket.writeline sprintf('CONNECT %s:%s HTTP/%s', addr, port, ver)
- @socket.writeline ''
- end
- end
-
- module ProxyMod
- def edit_path( path )
- if use_ssl
- 'https://' + addr_port + path
- else
- 'http://' + addr_port + path
- end
- end
- end
-
- def self.socket_type
- SSLIO
- end
-
- attr_reader :use_ssl
- attr_writer :key, :cert
- attr_writer :ca_file, :ca_path
- attr_writer :verify_mode, :verify_callback, :verify_depth
- attr_writer :cert_store, :timeout
- attr_reader :peer_cert
-
- alias :default_initialize :initialize
-
- def initialize(*args)
- default_initialize(*args)
- @key = @cert = @ca_file = @ca_path = @verify_mode =
- @verify_callback = @verify_depth = @timeout = @cert_store = nil
- @already_connected = false
- end
-
- def use_ssl=(flag)
- if @already_connected && !@use_ssl
- raise ProtocolError, "connection is alrady set up"
- end
- @use_ssl = flag
- end
-
- def on_connect
- if use_ssl
- if proxy?
- Conn.new.exec(@socket, @address, @port, "1.0")
- resp = HTTPResponse.read_new(@socket)
- if resp.code != '200'
- raise resp.message
- end
- end
- @socket.key = @key if @key
- @socket.cert = @cert if @cert
- @socket.ca_file = @ca_file
- @socket.ca_path = @ca_path
- @socket.verify_mode = @verify_mode
- @socket.verify_callback = @verify_callback
- @socket.verify_depth = @verify_depth
- @socket.timeout = @timeout
- @socket.cert_store = @cert_store
- @socket.ssl_connect
- @peer_cert = @socket.peer_cert
- end
- @already_connected = true
- end
-
- end
-end
diff --git a/ext/openssl/lib/net/protocols.rb b/ext/openssl/lib/net/protocols.rb
deleted file mode 100644
index 073d4f3027..0000000000
--- a/ext/openssl/lib/net/protocols.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-=begin
-= $RCSfile$ -- SSL/TLS enhancement for Net.
-
-= Info
- 'OpenSSL for Ruby 2' project
- Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
- All rights reserved.
-
-= Licence
- This program is licenced under the same licence as Ruby.
- (See the file 'LICENCE'.)
-
-= Requirements
- This program requires Net 1.2.0 or higher version.
- You can get it from RAA or Ruby's CVS repository.
-
-= Version
- $Id$
-
- 2001/11/06: Contiributed to Ruby/OpenSSL project.
-=end
-
-require 'net/protocol'
-require 'forwardable'
-require 'openssl'
-
-module Net
- class SSLIO < InternetMessageIO
- extend Forwardable
-
- def_delegators(:@ssl_context,
- :key=, :cert=, :key_file=, :cert_file=,
- :ca_file=, :ca_path=,
- :verify_mode=, :verify_callback=, :verify_depth=,
- :timeout=, :cert_store=)
-
- def initialize(addr, port, otime = nil, rtime = nil, dout = nil)
- super
- @ssl_context = OpenSSL::SSL::SSLContext.new()
- end
-
- def ssl_connect()
- unless @ssl_context.verify_mode
- warn "warning: peer certificate won't be verified in this SSL session."
- @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
- end
- @socket = OpenSSL::SSL::SSLSocket.new(@socket, @ssl_context)
- @socket.sync_close = true
- @socket.connect
- end
-
- def peer_cert
- @socket.peer_cert
- end
- end
-end
diff --git a/ext/openssl/lib/net/telnets.rb b/ext/openssl/lib/net/telnets.rb
index c7ecbd717a..2b69280432 100644
--- a/ext/openssl/lib/net/telnets.rb
+++ b/ext/openssl/lib/net/telnets.rb
@@ -124,9 +124,7 @@ module Net
elsif SB[0] == $1[0] # respond to "IAC SB xxx IAC SE"
if OPT_STARTTLS[0] == $1[1] && TLS_FOLLOWS[0] == $2[0]
@sock = OpenSSL::SSL::SSLSocket.new(@sock)
- @sock.cert_file = @options['CertFile']
@sock.cert = @options['Cert'] unless @sock.cert
- @sock.key_file = @options['KeyFile']
@sock.key = @options['Key'] unless @sock.key
@sock.ca_cert = @options['CACert']
@sock.ca_file = @options['CAFile']
@@ -136,6 +134,9 @@ module Net
@sock.verify_callback = @options['VerifyCallback']
@sock.verify_depth = @options['VerifyDepth']
@sock.connect
+ if @options['VerifyMode'] != OpenSSL::SSL::VERIFY_NONE
+ @sock.post_connection_check(@options['Host'])
+ end
@ssl = true
end
''
diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb
index 24a9eed136..f10985ed2c 100644
--- a/ext/openssl/lib/openssl.rb
+++ b/ext/openssl/lib/openssl.rb
@@ -19,6 +19,7 @@ require 'openssl.so'
require 'openssl/bn'
require 'openssl/cipher'
require 'openssl/digest'
+require 'openssl/pkcs7'
require 'openssl/ssl'
require 'openssl/x509'
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index fdbd71bc0c..761a017487 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -20,6 +20,8 @@ module Buffering
BLOCK_SIZE = 1024*16
def initialize(*args)
+ @eof = false
+ @rbuffer = ""
@sync = @io.sync
end
@@ -29,20 +31,17 @@ module Buffering
private
def fill_rbuff
- @rbuffer = "" unless defined? @rbuffer
begin
- if self.respond_to?(:to_io)
- IO.select([self.to_io], nil, nil)
- end
@rbuffer << self.sysread(BLOCK_SIZE)
+ rescue Errno::EAGAIN
+ retry
rescue EOFError
@eof = true
end
end
def consume_rbuff(size=nil)
- if @rbuffer.size == 0
- @eof = nil
+ if @rbuffer.empty?
nil
else
size = @rbuffer.size unless size
@@ -54,20 +53,54 @@ module Buffering
public
- def read(size=nil)
- fill_rbuff unless defined? @rbuffer
- @eof ||= nil
+ def read(size=nil, buf=nil)
+ if size == 0
+ if buf
+ buf.clear
+ else
+ buf = ""
+ end
+ return @eof ? nil : buf
+ end
until @eof
break if size && size <= @rbuffer.size
fill_rbuff
end
- consume_rbuff(size)
+ ret = consume_rbuff(size) || ""
+ if buf
+ buf.replace(ret)
+ ret = buf
+ end
+ (size && ret.empty?) ? nil : ret
+ end
+
+ def readpartial(maxlen, buf=nil)
+ if maxlen == 0
+ if buf
+ buf.clear
+ else
+ buf = ""
+ end
+ return @eof ? nil : buf
+ end
+ if @rbuffer.empty?
+ begin
+ return sysread(maxlen, buf)
+ rescue Errno::EAGAIN
+ retry
+ end
+ end
+ ret = consume_rbuff(maxlen)
+ if buf
+ buf.replace(ret)
+ ret = buf
+ end
+ raise EOFError if ret.empty?
+ ret
end
def gets(eol=$/)
- fill_rbuff unless defined? @rbuffer
idx = @rbuffer.index(eol)
- @eof ||= nil
until @eof
break if idx
fill_rbuff
@@ -82,7 +115,7 @@ module Buffering
end
def each(eol=$/)
- while line = self.gets(eol?)
+ while line = self.gets(eol)
yield line
end
end
@@ -97,13 +130,13 @@ module Buffering
end
def readline(eol=$/)
- raise EOFErorr if eof?
+ raise EOFError if eof?
gets(eol)
end
def getc
c = read(1)
- c ? c.to_i : nil
+ c ? c[0] : nil
end
def each_byte
@@ -113,7 +146,7 @@ module Buffering
end
def readchar
- raise EOFErorr if eof?
+ raise EOFError if eof?
getc
end
@@ -122,8 +155,8 @@ module Buffering
end
def eof?
- @eof ||= nil
- @eof && @rbuffer.size == 0
+ fill_rbuff if !@eof && @rbuffer.empty?
+ @eof && @rbuffer.empty?
end
alias eof eof?
@@ -140,11 +173,16 @@ module Buffering
remain = idx ? idx + $/.size : @wbuffer.length
nwritten = 0
while remain > 0
- nwrote = syswrite(@wbuffer[nwritten,remain])
+ str = @wbuffer[nwritten,remain]
+ begin
+ nwrote = syswrite(str)
+ rescue Errno::EAGAIN
+ retry
+ end
remain -= nwrote
nwritten += nwrote
end
- @wbuffer = ""
+ @wbuffer[0,nwritten] = ""
end
end
@@ -162,10 +200,13 @@ module Buffering
def puts(*args)
s = ""
+ if args.empty?
+ s << "\n"
+ end
args.each{|arg|
s << arg.to_s
- unless /#{$/}\Z/o =~ s
- s << $/
+ if $/ && /\n\z/ !~ s
+ s << "\n"
end
}
do_write(s)
diff --git a/ext/openssl/lib/openssl/cipher.rb b/ext/openssl/lib/openssl/cipher.rb
index 11153104ee..290e9c1d2d 100644
--- a/ext/openssl/lib/openssl/cipher.rb
+++ b/ext/openssl/lib/openssl/cipher.rb
@@ -19,34 +19,47 @@
#require 'openssl'
module OpenSSL
- module Cipher
- %w(AES Cast5 BF DES Idea RC2 RC4 RC5).each{|cipher|
- eval(<<-EOD)
- class #{cipher} < Cipher
- def initialize(*args)
- args = args.join('-')
- if args.size == 0
- super(\"#{cipher}\")
- else
- super(\"#{cipher}-#\{args\}\")
- end
- end
- end
- EOD
+ class Cipher
+ %w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
+ klass = Class.new(Cipher){
+ define_method(:initialize){|*args|
+ cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" }
+ super(cipher_name)
+ }
+ }
+ const_set(name, klass)
}
- class Cipher
- def random_key
- str = OpenSSL::Random.random_bytes(self.key_len)
- self.key = str
- return str
- end
-
- def random_iv
- str = OpenSSL::Random.random_bytes(self.iv_len)
- self.iv = str
- return str
- end
+ %w(128 192 256).each{|keylen|
+ klass = Class.new(Cipher){
+ define_method(:initialize){|mode|
+ mode ||= "CBC"
+ cipher_name = "AES-#{keylen}-#{mode}"
+ super(cipher_name)
+ }
+ }
+ const_set("AES#{keylen}", klass)
+ }
+
+ # Generate, set, and return a random key.
+ # You must call cipher.encrypt or cipher.decrypt before calling this method.
+ def random_key
+ str = OpenSSL::Random.random_bytes(self.key_len)
+ self.key = str
+ return str
+ end
+
+ # Generate, set, and return a random iv.
+ # You must call cipher.encrypt or cipher.decrypt before calling this method.
+ def random_iv
+ str = OpenSSL::Random.random_bytes(self.iv_len)
+ self.iv = str
+ return str
+ end
+
+ # This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
+ class Cipher < Cipher
+ # add warning
end
end # Cipher
end # OpenSSL
diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb
index 58622f543e..4810f0121b 100644
--- a/ext/openssl/lib/openssl/digest.rb
+++ b/ext/openssl/lib/openssl/digest.rb
@@ -19,26 +19,43 @@
#require 'openssl'
module OpenSSL
- module Digest
-
- %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1).each{|digest|
- eval(<<-EOD)
- class #{digest} < Digest
- def initialize(data=nil)
- super(\"#{digest}\", data)
- end
-
- def #{digest}::digest(data)
- Digest::digest(\"#{digest}\", data)
+ class Digest
+
+ alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
+ if OPENSSL_VERSION_NUMBER > 0x00908000
+ alg += %w(SHA224 SHA256 SHA384 SHA512)
+ end
+
+ def self.digest(name, data)
+ super(data, name)
+ end
+
+ alg.each{|name|
+ klass = Class.new(Digest){
+ define_method(:initialize){|*data|
+ if data.length > 1
+ raise ArgumentError,
+ "wrong number of arguments (#{data.length} for 1)"
end
-
- def #{digest}::hexdigest(data)
- Digest::hexdigest(\"#{digest}\", data)
- end
- end
- EOD
+ super(name, data.first)
+ }
+ }
+ singleton = (class <<klass; self; end)
+ singleton.class_eval{
+ define_method(:digest){|data| Digest.digest(name, data) }
+ define_method(:hexdigest){|data| Digest.hexdigest(name, data) }
+ }
+ const_set(name, klass)
}
+ # This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
+ class Digest < Digest
+ def initialize(*args)
+ # add warning
+ super(*args)
+ end
+ end
+
end # Digest
end # OpenSSL
diff --git a/ext/openssl/lib/openssl/pkcs7.rb b/ext/openssl/lib/openssl/pkcs7.rb
new file mode 100644
index 0000000000..1f88c1de5e
--- /dev/null
+++ b/ext/openssl/lib/openssl/pkcs7.rb
@@ -0,0 +1,25 @@
+=begin
+= $RCSfile$ -- PKCS7
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: digest.rb 12148 2007-04-05 05:59:22Z technorama $
+=end
+
+module OpenSSL
+ class PKCS7
+ # This class is only provided for backwards compatibility. Use OpenSSL::PKCS7 in the future.
+ class PKCS7 < PKCS7
+ def initialize(*args)
+ super(*args)
+
+ warn("Warning: OpenSSL::PKCS7::PKCS7 is deprecated after Ruby 1.9; use OpenSSL::PKCS7 instead")
+ end
+ end
+
+ end # PKCS7
+end # OpenSSL
+
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index 811a935509..f722cb0c45 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -14,10 +14,39 @@
$Id$
=end
-require 'openssl/buffering'
+require "openssl"
+require "openssl/buffering"
+require "fcntl"
module OpenSSL
module SSL
+ class SSLContext
+ DEFAULT_PARAMS = {
+ :ssl_version => "SSLv23",
+ :verify_mode => OpenSSL::SSL::VERIFY_PEER,
+ :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
+ :options => OpenSSL::SSL::OP_ALL,
+ }
+
+ DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
+ DEFAULT_CERT_STORE.set_default_paths
+ if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
+ DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
+ end
+
+ def set_params(params={})
+ params = DEFAULT_PARAMS.merge(params)
+ self.ssl_version = params.delete(:ssl_version)
+ params.each{|name, value| self.__send__("#{name}=", value) }
+ if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
+ unless self.ca_file or self.ca_path or self.cert_store
+ self.cert_store = DEFAULT_CERT_STORE
+ end
+ end
+ return params
+ end
+ end
+
module SocketForwarder
def addr
to_io.addr
@@ -27,12 +56,12 @@ module OpenSSL
to_io.peeraddr
end
- def getsockopt(level, optname, optval)
+ def setsockopt(level, optname, optval)
to_io.setsockopt(level, optname, optval)
end
- def setsockopt(level, optname)
- to_io.setsockopt(level, optname)
+ def getsockopt(level, optname)
+ to_io.getsockopt(level, optname)
end
def fcntl(*args)
@@ -42,11 +71,65 @@ module OpenSSL
def closed?
to_io.closed?
end
+
+ def do_not_reverse_lookup=(flag)
+ to_io.do_not_reverse_lookup = flag
+ end
+ end
+
+ module Nonblock
+ def initialize(*args)
+ flag = File::NONBLOCK
+ flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
+ @io.fcntl(Fcntl::F_SETFL, flag)
+ super
+ end
end
+ def verify_certificate_identity(cert, hostname)
+ should_verify_common_name = true
+ cert.extensions.each{|ext|
+ next if ext.oid != "subjectAltName"
+ ext.value.split(/,\s+/).each{|general_name|
+ if /\ADNS:(.*)/ =~ general_name
+ should_verify_common_name = false
+ reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
+ return true if /\A#{reg}\z/i =~ hostname
+ elsif /\AIP Address:(.*)/ =~ general_name
+ should_verify_common_name = false
+ return true if $1 == hostname
+ end
+ }
+ }
+ if should_verify_common_name
+ cert.subject.to_a.each{|oid, value|
+ if oid == "CN"
+ reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
+ return true if /\A#{reg}\z/i =~ hostname
+ end
+ }
+ end
+ return false
+ end
+ module_function :verify_certificate_identity
+
class SSLSocket
include Buffering
include SocketForwarder
+ include Nonblock
+
+ def post_connection_check(hostname)
+ unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
+ raise SSLError, "hostname was not match with the server certificate"
+ end
+ return true
+ end
+
+ def session
+ SSL::Session.new(self)
+ rescue SSL::Session::SessionError
+ nil
+ end
end
class SSLServer
@@ -56,6 +139,10 @@ module OpenSSL
def initialize(svr, ctx)
@svr = svr
@ctx = ctx
+ unless ctx.session_id_context
+ session_id = OpenSSL::Digest::MD5.hexdigest($0)
+ @ctx.session_id_context = session_id
+ end
@start_immediately = true
end
@@ -63,10 +150,14 @@ module OpenSSL
@svr
end
- def listen(basklog=5)
+ def listen(backlog=5)
@svr.listen(backlog)
end
+ def shutdown(how=Socket::SHUT_RDWR)
+ @svr.shutdown(how)
+ end
+
def accept
sock = @svr.accept
begin
diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb
index 40b1a6dd15..e711bda39c 100644
--- a/ext/openssl/lib/openssl/x509.rb
+++ b/ext/openssl/lib/openssl/x509.rb
@@ -14,9 +14,7 @@
$Id$
=end
-##
-# Should we care what if somebody require this file directly?
-#require 'openssl'
+require "openssl"
module OpenSSL
module X509
@@ -44,7 +42,7 @@ module OpenSSL
def create_ext_from_hash(hash)
create_ext(hash["oid"], hash["value"], hash["critical"])
end
- end # ExtensionFactory
+ end
class Extension
def to_s # "oid = critical, value"
@@ -61,14 +59,96 @@ module OpenSSL
def to_a
[ self.oid, self.value, self.critical? ]
end
- end # Extension
-
+ end
+
class Name
- def self.parse(str, type=ASN1::UTF8STRING)
- ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=") }
- self.new(ary, type)
+ module RFC2253DN
+ Special = ',=+<>#;'
+ HexChar = /[0-9a-fA-F]/
+ HexPair = /#{HexChar}#{HexChar}/
+ HexString = /#{HexPair}+/
+ Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/
+ StringChar = /[^#{Special}\\"]/
+ QuoteChar = /[^\\"]/
+ AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/
+ AttributeValue = /
+ (?!["#])((?:#{StringChar}|#{Pair})*)|
+ \#(#{HexString})|
+ "((?:#{QuoteChar}|#{Pair})*)"
+ /x
+ TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/
+
+ module_function
+
+ def expand_pair(str)
+ return nil unless str
+ return str.gsub(Pair){|pair|
+ case pair.size
+ when 2 then pair[1,1]
+ when 3 then Integer("0x#{pair[1,2]}").chr
+ else raise OpenSSL::X509::NameError, "invalid pair: #{str}"
+ end
+ }
+ end
+
+ def expand_hexstring(str)
+ return nil unless str
+ der = str.gsub(HexPair){|hex| Integer("0x#{hex}").chr }
+ a1 = OpenSSL::ASN1.decode(der)
+ return a1.value, a1.tag
+ end
+
+ def expand_value(str1, str2, str3)
+ value = expand_pair(str1)
+ value, tag = expand_hexstring(str2) unless value
+ value = expand_pair(str3) unless value
+ return value, tag
+ end
+
+ def scan(dn)
+ str = dn
+ ary = []
+ while true
+ if md = TypeAndValue.match(str)
+ matched = md.to_s
+ remain = md.post_match
+ type = md[1]
+ value, tag = expand_value(md[2], md[3], md[4]) rescue nil
+ if value
+ type_and_value = [type, value]
+ type_and_value.push(tag) if tag
+ ary.unshift(type_and_value)
+ if remain.length > 2 && remain[0] == ?,
+ str = remain[1..-1]
+ next
+ elsif remain.length > 2 && remain[0] == ?+
+ raise OpenSSL::X509::NameError,
+ "multi-valued RDN is not supported: #{dn}"
+ elsif remain.empty?
+ break
+ end
+ end
+ end
+ msg_dn = dn[0, dn.length - str.length] + " =>" + str
+ raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}"
+ end
+ return ary
+ end
end
- end # Name
- end # X509
-end # OpenSSL
+ class <<self
+ def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
+ ary = OpenSSL::X509::Name::RFC2253DN.scan(str)
+ self.new(ary, template)
+ end
+
+ def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
+ ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) }
+ self.new(ary, template)
+ end
+
+ alias parse parse_openssl
+ end
+ end
+ end
+end
diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
index 0c0be5fc1f..724f36b8ae 100644
--- a/ext/openssl/openssl_missing.c
+++ b/ext/openssl/openssl_missing.c
@@ -8,29 +8,34 @@
* This program is licenced under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
+#include RUBY_EXTCONF_H
+
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE)
+# include <openssl/engine.h>
+#endif
+#include <openssl/x509_vfy.h>
#if !defined(OPENSSL_NO_HMAC)
#include <string.h> /* memcpy() */
#include <openssl/hmac.h>
+#include "openssl_missing.h"
+
#if !defined(HAVE_HMAC_CTX_COPY)
-int
+void
HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
{
- if (!out || !in) return 0;
+ if (!out || !in) return;
memcpy(out, in, sizeof(HMAC_CTX));
- if (!EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx)
- || !EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx)
- || !EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx))
- return 0;
- return 1;
+ EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx);
+ EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx);
+ EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx);
}
#endif /* HAVE_HMAC_CTX_COPY */
#endif /* NO_HMAC */
#if !defined(HAVE_X509_STORE_SET_EX_DATA)
-#include <openssl/x509_vfy.h>
int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data)
{
@@ -105,6 +110,29 @@ HMAC_CTX_cleanup(HMAC_CTX *ctx)
}
#endif
+#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
+/*
+ * this function does not exist in OpenSSL yet... or ever?.
+ * a future version may break this function.
+ * tested on 0.9.7d.
+ */
+int
+EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in)
+{
+ memcpy(out, in, sizeof(EVP_CIPHER_CTX));
+
+#if defined(HAVE_ENGINE_ADD) && defined(HAVE_ST_ENGINE)
+ if (in->engine) ENGINE_add(out->engine);
+ if (in->cipher_data) {
+ out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
+ memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
+ }
+#endif
+
+ return 1;
+}
+#endif
+
#if !defined(HAVE_X509_CRL_SET_VERSION)
int
X509_CRL_set_version(X509_CRL *x, long version)
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index 7a755f79b5..5a71f73c64 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -15,6 +15,10 @@
extern "C" {
#endif
+#ifndef TYPEDEF_D2I_OF
+typedef char *d2i_of_void();
+#endif
+
/*
* These functions are not included in headers of OPENSSL <= 0.9.6b
*/
@@ -56,12 +60,51 @@ extern "C" {
(char *(*)())d2i_PKCS7_RECIP_INFO, (char *)ri)
#endif
-int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
-void *X509_STORE_get_ex_data(X509_STORE *str, int idx);
-int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data);
+#if !defined(HAVE_EVP_MD_CTX_INIT)
+void HMAC_CTX_init(HMAC_CTX *ctx);
+#endif
+
+#if !defined(HAVE_HMAC_CTX_COPY)
+void HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
+#endif
+
+#if !defined(HAVE_HMAC_CTX_CLEANUP)
+void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_CREATE)
EVP_MD_CTX *EVP_MD_CTX_create(void);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_INIT)
+void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_CLEANUP)
int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_DESTROY)
void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
+int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
+#endif
+
+#if !defined(HAVE_EVP_DIGESTINIT_EX)
+# define EVP_DigestInit_ex(ctx, md, engine) EVP_DigestInit(ctx, md)
+#endif
+#if !defined(HAVE_EVP_DIGESTFINAL_EX)
+# define EVP_DigestFinal_ex(ctx, buf, len) EVP_DigestFinal(ctx, buf, len)
+#endif
+
+#if !defined(HAVE_EVP_CIPHERINIT_EX)
+# define EVP_CipherInit_ex(ctx, type, impl, key, iv, enc) EVP_CipherInit(ctx, type, key, iv, enc)
+#endif
+#if !defined(HAVE_EVP_CIPHERFINAL_EX)
+# define EVP_CipherFinal_ex(ctx, outm, outl) EVP_CipherFinal(ctx, outm, outl)
+#endif
#if !defined(EVP_CIPHER_name)
# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
@@ -71,9 +114,9 @@ void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_type(e))
#endif
-void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
-void HMAC_CTX_init(HMAC_CTX *ctx);
-void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+#if !defined(HAVE_EVP_HMAC_INIT_EX)
+# define HMAC_Init_ex(ctx, key, len, digest, engine) HMAC_Init(ctx, key, len, digest)
+#endif
#if !defined(PKCS7_is_detached)
# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
@@ -83,17 +126,58 @@ void HMAC_CTX_cleanup(HMAC_CTX *ctx);
# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
#endif
+#if !defined(HAVE_OPENSSL_CLEANSE)
+#define OPENSSL_cleanse(p, l) memset(p, 0, l)
+#endif
+
+#if !defined(HAVE_X509_STORE_SET_EX_DATA)
+void *X509_STORE_get_ex_data(X509_STORE *str, int idx);
+int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data);
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_VERSION)
int X509_CRL_set_version(X509_CRL *x, long version);
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME)
int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
+#endif
+
+#if !defined(HAVE_X509_CRL_SORT)
int X509_CRL_sort(X509_CRL *c);
+#endif
+
+#if !defined(HAVE_X509_CRL_ADD0_REVOKED)
int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+#endif
+
+#if !defined(HAVE_BN_MOD_SQR)
int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+#endif
+
+#if !defined(HAVE_BN_MOD_ADD)
int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+#endif
+
+#if !defined(HAVE_BN_MOD_SUB)
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+#endif
+
+#if !defined(HAVE_BN_RAND_RANGE)
int BN_rand_range(BIGNUM *r, BIGNUM *range);
+#endif
+
+#if !defined(HAVE_BN_PSEUDO_RAND_RANGE)
int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range);
+#endif
+
+#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE)
char *CONF_get1_default_config_file(void);
+#endif
+
+#if !defined(HAVE_PEM_DEF_CALLBACK)
int PEM_def_callback(char *buf, int num, int w, void *key);
+#endif
#if defined(__cplusplus)
}
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index 6646bafc2e..53f476fd65 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -59,11 +59,11 @@ ossl_x509_ary2sk0(VALUE ary)
sk = sk_X509_new_null();
if (!sk) ossl_raise(eOSSLError, NULL);
- for (i = 0; i < RARRAY(ary)->len; i++) {
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
val = rb_ary_entry(ary, i);
if (!rb_obj_is_kind_of(val, cX509Cert)) {
sk_X509_pop_free(sk, X509_free);
- ossl_raise(eOSSLError, "object except X509 cert is in array");
+ ossl_raise(eOSSLError, "object not X509 cert in array");
}
x509 = DupX509CertPtr(val); /* NEED TO DUP */
sk_X509_push(sk, x509);
@@ -131,7 +131,7 @@ ossl_buf2str(char *buf, int len)
int status = 0;
str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status);
- if(!NIL_P(str)) memcpy(RSTRING(str)->ptr, buf, len);
+ if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len);
OPENSSL_free(buf);
if(status) rb_jump_tag(status);
@@ -170,7 +170,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
rflag = flag ? Qtrue : Qfalse;
pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
if (status) return -1; /* exception was raised. */
- len = RSTRING(pass)->len;
+ len = RSTRING_LEN(pass);
if (len < 4) { /* 4 is OpenSSL hardcoded limit */
rb_warning("password must be longer than 4 bytes");
continue;
@@ -179,7 +179,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
rb_warning("password must be shorter then %d bytes", max_len-1);
continue;
}
- memcpy(buf, RSTRING(pass)->ptr, len);
+ memcpy(buf, RSTRING_PTR(pass), len);
break;
}
return len;
@@ -278,28 +278,61 @@ ossl_raise(VALUE exc, const char *fmt, ...)
va_list args;
char buf[BUFSIZ];
const char *msg;
- long e = ERR_get_error();
+ long e;
int len = 0;
+#ifdef HAVE_ERR_PEEK_LAST_ERROR
+ e = ERR_peek_last_error();
+#else
+ e = ERR_peek_error();
+#endif
if (fmt) {
va_start(args, fmt);
len = vsnprintf(buf, BUFSIZ, fmt, args);
va_end(args);
- len += snprintf(buf+len, BUFSIZ-len, ": ");
}
- if (e) {
+ if (len < BUFSIZ && e) {
if (dOSSL == Qtrue) /* FULL INFO */
msg = ERR_error_string(e, NULL);
else
msg = ERR_reason_error_string(e);
- ERR_clear_error();
- len += snprintf(buf+len, BUFSIZ-len, "%s", msg);
+ fmt = len ? ": %s" : "%s";
+ len += snprintf(buf+len, BUFSIZ-len, fmt, msg);
+ }
+ if (dOSSL == Qtrue){ /* show all errors on the stack */
+ while ((e = ERR_get_error()) != 0){
+ rb_warn("error on stack: %s", ERR_error_string(e, NULL));
+ }
}
+ ERR_clear_error();
+ if(len > BUFSIZ) len = strlen(buf);
rb_exc_raise(rb_exc_new(exc, buf, len));
}
/*
+ * call-seq:
+ * OpenSSL.errors -> [String...]
+ *
+ * See any remaining errors held in queue.
+ *
+ * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation.
+ */
+VALUE
+ossl_get_errors()
+{
+ VALUE ary;
+ long e;
+
+ ary = rb_ary_new();
+ while ((e = ERR_get_error()) != 0){
+ rb_ary_push(ary, rb_str_new2(ERR_error_string(e, NULL)));
+ }
+
+ return ary;
+}
+
+/*
* Debug
*/
VALUE dOSSL;
@@ -320,12 +353,23 @@ ossl_debug(const char *fmt, ...)
}
#endif
+/*
+ * call-seq:
+ * OpenSSL.debug -> true | false
+ */
static VALUE
ossl_debug_get(VALUE self)
{
return dOSSL;
}
+/*
+ * call-seq:
+ * OpenSSL.debug = boolean -> boolean
+ *
+ * Turns on or off CRYPTO_MEM_CHECK.
+ * Also shows some debugging message on stderr.
+ */
static VALUE
ossl_debug_set(VALUE self, VALUE val)
{
@@ -362,6 +406,7 @@ Init_openssl()
*/
/* CRYPTO_malloc_init(); */
/* ENGINE_load_builtin_engines(); */
+ OpenSSL_add_ssl_algorithms();
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
SSL_load_error_strings();
@@ -401,8 +446,8 @@ Init_openssl()
/*
* Verify callback Proc index for ext-data
*/
- ossl_verify_cb_idx =
- X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0);
+ if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0)) < 0)
+ ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
/*
* Init debug core
@@ -410,6 +455,7 @@ Init_openssl()
dOSSL = Qfalse;
rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0);
rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
+ rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
/*
* Get ID of to_der
@@ -425,7 +471,9 @@ Init_openssl()
Init_ossl_digest();
Init_ossl_hmac();
Init_ossl_ns_spki();
+ Init_ossl_pkcs12();
Init_ossl_pkcs7();
+ Init_ossl_pkcs5();
Init_ossl_pkey();
Init_ossl_rand();
Init_ossl_ssl();
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index b0e26bee91..3cc30ae2e8 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -11,10 +11,26 @@
#if !defined(_OSSL_H_)
#define _OSSL_H_
+#include RUBY_EXTCONF_H
+
#if defined(__cplusplus)
extern "C" {
#endif
+#if 0
+ mOSSL = rb_define_module("OpenSSL");
+ mX509 = rb_define_module_under(mOSSL, "X509");
+#endif
+
+/*
+* OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
+*/
+#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
+# undef RFILE
+#endif
+#include <ruby.h>
+#include <rubyio.h>
+
/*
* Check the OpenSSL version
* The only supported are:
@@ -29,21 +45,27 @@ extern "C" {
#endif
#if defined(_WIN32)
-# define OpenFile WINAPI_OpenFile
# define OSSL_NO_CONF_API 1
+# ifdef USE_WINSOCK2
+# include <winsock2.h>
+# else
+# include <winsock.h>
+# endif
#endif
#include <errno.h>
#include <openssl/err.h>
#include <openssl/asn1_mac.h>
#include <openssl/x509v3.h>
#include <openssl/ssl.h>
+#include <openssl/pkcs12.h>
+#include <openssl/pkcs7.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/conf.h>
#include <openssl/conf_api.h>
#undef X509_NAME
#undef PKCS7_SIGNER_INFO
-#if defined(HAVE_OPENSSL_ENGINE_H) && !defined(OPENSSL_NO_ENGINE)
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE)
# define OSSL_ENGINE_ENABLED
# include <openssl/engine.h>
#endif
@@ -51,18 +73,6 @@ extern "C" {
# define OSSL_OCSP_ENABLED
# include <openssl/ocsp.h>
#endif
-#if defined(_WIN32)
-# undef OpenFile
-#endif
-
-/*
- * OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
- */
-#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
-# undef RFILE
-#endif
-#include <ruby.h>
-#include <rubyio.h>
/*
* Common Module
@@ -113,11 +123,10 @@ VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl);
VALUE ossl_buf2str(char *buf, int len);
#define ossl_str_adjust(str, p) \
do{\
- int len = RSTRING(str)->len;\
- int newlen = (p) - (unsigned char*)RSTRING(str)->ptr;\
+ int len = RSTRING_LEN(str);\
+ int newlen = (p) - (unsigned char*)RSTRING_PTR(str);\
assert(newlen <= len);\
- RSTRING(str)->len = newlen;\
- RSTRING(str)->ptr[newlen] = 0;\
+ rb_str_set_len(str, newlen);\
}while(0)
/*
@@ -162,7 +171,7 @@ extern VALUE dOSSL;
if (dOSSL == Qtrue) { \
fprintf(stderr, "OSSL_DEBUG: "); \
fprintf(stderr, fmt, ##__VA_ARGS__); \
- fprintf(stderr, " [in %s (%s:%d)]\n", __func__, __FILE__, __LINE__); \
+ fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \
} \
} while (0)
@@ -196,7 +205,9 @@ void ossl_debug(const char *, ...);
#include "ossl_hmac.h"
#include "ossl_ns_spki.h"
#include "ossl_ocsp.h"
+#include "ossl_pkcs12.h"
#include "ossl_pkcs7.h"
+#include "ossl_pkcs5.h"
#include "ossl_pkey.h"
#include "ossl_rand.h"
#include "ossl_ssl.h"
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index f0d8dda9b8..8ceea95021 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -42,21 +42,19 @@ asn1time_to_time(ASN1_TIME *time)
} else {
tm.tm_year += 1900;
}
- tm.tm_mon -= 1;
break;
case V_ASN1_GENERALIZEDTIME:
if (sscanf(time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
&tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" );
}
- tm.tm_mon -= 1;
break;
default:
rb_warning("unknown time format");
return Qnil;
}
argv[0] = INT2NUM(tm.tm_year);
- argv[1] = INT2NUM(tm.tm_mon+1);
+ argv[1] = INT2NUM(tm.tm_mon);
argv[2] = INT2NUM(tm.tm_mday);
argv[3] = INT2NUM(tm.tm_hour);
argv[4] = INT2NUM(tm.tm_min);
@@ -77,6 +75,15 @@ time_to_time_t(VALUE time)
}
/*
+ * STRING conversion
+ */
+VALUE
+asn1str_to_str(ASN1_STRING *str)
+{
+ return rb_str_new(str->data, str->length);
+}
+
+/*
* ASN1_INTEGER conversions
* TODO: Make a decision what's the right way to do this.
*/
@@ -189,7 +196,7 @@ static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
static ASN1_BOOLEAN
obj_to_asn1bool(VALUE obj)
{
- return RTEST(obj) ? 255 : 0;
+ return RTEST(obj) ? 0xff : 0x100;
}
static ASN1_INTEGER*
@@ -207,7 +214,7 @@ obj_to_asn1bstr(VALUE obj, long unused_bits)
StringValue(obj);
if(!(bstr = ASN1_BIT_STRING_new()))
ossl_raise(eASN1Error, NULL);
- ASN1_BIT_STRING_set(bstr, RSTRING(obj)->ptr, RSTRING(obj)->len);
+ ASN1_BIT_STRING_set(bstr, RSTRING_PTR(obj), RSTRING_LEN(obj));
bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
@@ -222,7 +229,7 @@ obj_to_asn1str(VALUE obj)
StringValue(obj);
if(!(str = ASN1_STRING_new()))
ossl_raise(eASN1Error, NULL);
- ASN1_STRING_set(str, RSTRING(obj)->ptr, RSTRING(obj)->len);
+ ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LEN(obj));
return str;
}
@@ -246,8 +253,8 @@ obj_to_asn1obj(VALUE obj)
ASN1_OBJECT *a1obj;
StringValue(obj);
- a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 0);
- if(!a1obj) a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 1);
+ a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
+ if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
return a1obj;
@@ -288,7 +295,7 @@ obj_to_asn1derstr(VALUE obj)
str = ossl_to_der(obj);
if(!(a1str = ASN1_STRING_new()))
ossl_raise(eASN1Error, NULL);
- ASN1_STRING_set(a1str, RSTRING(str)->ptr, RSTRING(str)->len);
+ ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LEN(str));
return a1str;
}
@@ -438,7 +445,7 @@ decode_time(unsigned char* der, int length)
/********/
typedef struct {
- char *name;
+ const char *name;
VALUE *klass;
} ossl_asn1_info_t;
@@ -567,7 +574,7 @@ ossl_asn1_default_tag(VALUE obj)
return i;
}
}
- ossl_raise(eASN1Error, "not found universal tag for %s",
+ ossl_raise(eASN1Error, "universal tag for %s not found",
rb_class2name(CLASS_OF(obj)));
return -1; /* dummy */
@@ -650,7 +657,7 @@ ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
if(!SYMBOL_P(tag_class))
ossl_raise(eASN1Error, "invalid tag class");
if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
- ossl_raise(eASN1Error, "too large tag number for Universal");
+ ossl_raise(eASN1Error, "tag number for Universal too large");
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
ossl_asn1_set_tag_class(self, tag_class);
@@ -671,7 +678,7 @@ static VALUE
join_der(VALUE enumerable)
{
VALUE str = rb_str_new(0, 0);
- rb_iterate(rb_each, enumerable, join_der_i, str);
+ rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
return str;
}
@@ -692,13 +699,13 @@ ossl_asn1data_to_der(VALUE self)
tag = ossl_asn1_tag(self);
tag_class = ossl_asn1_tag_class(self);
- if((length = ASN1_object_size(1, RSTRING(value)->len, tag)) <= 0)
+ if((length = ASN1_object_size(1, RSTRING_LEN(value), tag)) <= 0)
ossl_raise(eASN1Error, NULL);
der = rb_str_new(0, length);
- p = RSTRING(der)->ptr;
- ASN1_put_object(&p, is_cons, RSTRING(value)->len, tag, tag_class);
- memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
- p += RSTRING(value)->len;
+ p = RSTRING_PTR(der);
+ ASN1_put_object(&p, is_cons, RSTRING_LEN(value), tag, tag_class);
+ memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
+ p += RSTRING_LEN(value);
ossl_str_adjust(der, p);
return der;
@@ -759,7 +766,7 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth,
if(tag_class == sUNIVERSAL &&
tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass){
VALUE klass = *ossl_asn1_info[tag].klass;
- long flag;
+ long flag = 0;
if(!rb_obj_is_kind_of(value, rb_cArray)){
switch(tag){
case V_ASN1_BOOLEAN:
@@ -813,13 +820,14 @@ ossl_asn1_traverse(VALUE self, VALUE obj)
{
unsigned char *p;
long offset = 0;
+ volatile VALUE tmp;
obj = ossl_to_der_if_possible(obj);
- StringValue(obj);
- p = RSTRING(obj)->ptr;
- ossl_asn1_decode0(&p, RSTRING(obj)->len, &offset, 0, 0, 1);
+ tmp = rb_str_new4(StringValue(obj));
+ p = RSTRING_PTR(tmp);
+ ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 1);
- return obj;
+ return Qnil;
}
static VALUE
@@ -828,11 +836,12 @@ ossl_asn1_decode(VALUE self, VALUE obj)
VALUE ret, ary;
unsigned char *p;
long offset = 0;
+ volatile VALUE tmp;
obj = ossl_to_der_if_possible(obj);
- StringValue(obj);
- p = RSTRING(obj)->ptr;
- ary = ossl_asn1_decode0(&p, RSTRING(obj)->len, &offset, 0, 1, 0);
+ tmp = rb_str_new4(StringValue(obj));
+ p = RSTRING_PTR(tmp);
+ ary = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 1, 0);
ret = rb_ary_entry(ary, 0);
return ret;
@@ -844,11 +853,12 @@ ossl_asn1_decode_all(VALUE self, VALUE obj)
VALUE ret;
unsigned char *p;
long offset = 0;
+ volatile VALUE tmp;
obj = ossl_to_der_if_possible(obj);
- StringValue(obj);
- p = RSTRING(obj)->ptr;
- ret = ossl_asn1_decode0(&p, RSTRING(obj)->len, &offset, 0, 0, 0);
+ tmp = rb_str_new4(StringValue(obj));
+ p = RSTRING_PTR(tmp);
+ ret = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 0);
return ret;
}
@@ -865,13 +875,13 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
if(NIL_P(tagging))
tagging = ID2SYM(sEXPLICIT);
if(!SYMBOL_P(tagging))
- ossl_raise(eASN1Error, "invelid tag default");
+ ossl_raise(eASN1Error, "invalid tag default");
if(NIL_P(tag_class))
tag_class = ID2SYM(sCONTEXT_SPECIFIC);
if(!SYMBOL_P(tag_class))
- ossl_raise(eASN1Error, "invelid tag class");
+ ossl_raise(eASN1Error, "invalid tag class");
if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
- ossl_raise(eASN1Error, "too large tag number for Universal");
+ ossl_raise(eASN1Error, "tag number for Universal too large");
}
else{
tag = INT2NUM(ossl_asn1_default_tag(self));
@@ -886,6 +896,30 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+static int
+ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
+{
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+ if(!a) return 0;
+ if(a->type == V_ASN1_BOOLEAN)
+ return i2d_ASN1_BOOLEAN(a->value.boolean, pp);
+#endif
+ return i2d_ASN1_TYPE(a, pp);
+}
+
+static void
+ossl_ASN1_TYPE_free(ASN1_TYPE *a)
+{
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+ if(!a) return;
+ if(a->type == V_ASN1_BOOLEAN){
+ OPENSSL_free(a);
+ return;
+ }
+#endif
+ ASN1_TYPE_free(a);
+}
+
static VALUE
ossl_asn1prim_to_der(VALUE self)
{
@@ -900,24 +934,24 @@ ossl_asn1prim_to_der(VALUE self)
explicit = ossl_asn1_is_explicit(self);
asn1 = ossl_asn1_get_asn1type(self);
- length = ASN1_object_size(1, i2d_ASN1_TYPE(asn1, NULL), tn);
+ length = ASN1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
if(!(buf = OPENSSL_malloc(length))){
- ASN1_TYPE_free(asn1);
+ ossl_ASN1_TYPE_free(asn1);
ossl_raise(eASN1Error, "cannot alloc buffer");
}
p = buf;
- if(tc == V_ASN1_UNIVERSAL) i2d_ASN1_TYPE(asn1, &p);
+ if(tc == V_ASN1_UNIVERSAL) ossl_i2d_ASN1_TYPE(asn1, &p);
else{
if(explicit){
- ASN1_put_object(&p, 1, i2d_ASN1_TYPE(asn1, NULL), tn, tc);
- i2d_ASN1_TYPE(asn1, &p);
+ ASN1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
+ ossl_i2d_ASN1_TYPE(asn1, &p);
}
else{
- i2d_ASN1_TYPE(asn1, &p);
+ ossl_i2d_ASN1_TYPE(asn1, &p);
*buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED);
}
}
- ASN1_TYPE_free(asn1);
+ ossl_ASN1_TYPE_free(asn1);
reallen = p - buf;
assert(reallen <= length);
str = ossl_buf2str(buf, reallen); /* buf will be free in ossl_buf2str */
@@ -926,7 +960,7 @@ ossl_asn1prim_to_der(VALUE self)
}
static VALUE
-ossl_asn1cons_to_der(self)
+ossl_asn1cons_to_der(VALUE self)
{
int tag, tn, tc, explicit;
long seq_len, length;
@@ -939,21 +973,21 @@ ossl_asn1cons_to_der(self)
explicit = ossl_asn1_is_explicit(self);
value = join_der(ossl_asn1_get_value(self));
- seq_len = ASN1_object_size(1, RSTRING(value)->len, tag);
+ seq_len = ASN1_object_size(1, RSTRING_LEN(value), tag);
length = ASN1_object_size(1, seq_len, tn);
str = rb_str_new(0, length);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(tc == V_ASN1_UNIVERSAL)
- ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
+ ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
else{
if(explicit){
ASN1_put_object(&p, 1, seq_len, tn, tc);
- ASN1_put_object(&p, 1, RSTRING(value)->len, tag, V_ASN1_UNIVERSAL);
+ ASN1_put_object(&p, 1, RSTRING_LEN(value), tag, V_ASN1_UNIVERSAL);
}
- else ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
+ else ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
}
- memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
- p += RSTRING(value)->len;
+ memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
+ p += RSTRING_LEN(value);
ossl_str_adjust(str, p);
return str;
@@ -973,7 +1007,7 @@ ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
StringValue(sn);
StringValue(ln);
- if(!OBJ_create(RSTRING(oid)->ptr, RSTRING(sn)->ptr, RSTRING(ln)->ptr))
+ if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
ossl_raise(eASN1Error, NULL);
return Qtrue;
@@ -1053,6 +1087,10 @@ Init_ossl_asn1()
VALUE ary;
int i;
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
sUNIVERSAL = rb_intern("UNIVERSAL");
sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
sAPPLICATION = rb_intern("APPLICATION");
@@ -1074,9 +1112,9 @@ Init_ossl_asn1()
}
cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
- rb_attr(cASN1Data, rb_intern("value"), 1, 1, Qtrue);
- rb_attr(cASN1Data, rb_intern("tag"), 1, 1, Qtrue);
- rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, Qtrue);
+ rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
+ rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
+ rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
@@ -1128,5 +1166,5 @@ do{\
rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
rb_define_alias(cASN1ObjectId, "short_name", "sn");
rb_define_alias(cASN1ObjectId, "long_name", "ln");
- rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, Qtrue);
+ rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
}
diff --git a/ext/openssl/ossl_asn1.h b/ext/openssl/ossl_asn1.h
index 919ede0f3b..8aad9f970d 100644
--- a/ext/openssl/ossl_asn1.h
+++ b/ext/openssl/ossl_asn1.h
@@ -18,6 +18,11 @@ VALUE asn1time_to_time(ASN1_TIME *);
time_t time_to_time_t(VALUE);
/*
+ * ASN1_STRING conversions
+ */
+VALUE asn1str_to_str(ASN1_STRING *);
+
+/*
* ASN1_INTEGER conversions
*/
VALUE asn1integer_to_num(ASN1_INTEGER *);
diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c
index 8e80f412ee..6db1fb9a62 100644
--- a/ext/openssl/ossl_bio.c
+++ b/ext/openssl/ossl_bio.c
@@ -9,6 +9,9 @@
* (See the file 'LICENCE'.)
*/
#include "ossl.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
BIO *
ossl_obj2bio(VALUE obj)
@@ -16,16 +19,29 @@ ossl_obj2bio(VALUE obj)
BIO *bio;
if (TYPE(obj) == T_FILE) {
- OpenFile *fptr;
+ rb_io_t *fptr;
+ FILE *fp;
+ int fd;
+
GetOpenFile(obj, fptr);
rb_io_check_readable(fptr);
- bio = BIO_new_fp(fptr->f, BIO_NOCLOSE);
- }
+ if ((fd = dup(FPTR_TO_FD(fptr))) < 0){
+ rb_sys_fail(0);
+ }
+ if (!(fp = fdopen(fd, "r"))){
+ close(fd);
+ rb_sys_fail(0);
+ }
+ if (!(bio = BIO_new_fp(fp, BIO_CLOSE))){
+ fclose(fp);
+ ossl_raise(eOSSLError, NULL);
+ }
+ }
else {
StringValue(obj);
- bio = BIO_new_mem_buf(RSTRING(obj)->ptr, RSTRING(obj)->len);
+ bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LEN(obj));
+ if (!bio) ossl_raise(eOSSLError, NULL);
}
- if (!bio) ossl_raise(eOSSLError, NULL);
return bio;
}
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index c3a371a008..6856476261 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -40,7 +40,7 @@ VALUE eBNError;
* Public
*/
VALUE
-ossl_bn_new(BIGNUM *bn)
+ossl_bn_new(const BIGNUM *bn)
{
BIGNUM *newbn;
VALUE obj;
@@ -100,6 +100,13 @@ ossl_bn_alloc(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * BN.new => aBN
+ * BN.new(bn) => aBN
+ * BN.new(string) => aBN
+ * BN.new(string, 0 | 2 | 10 | 16) => aBN
+ */
static VALUE
ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -107,11 +114,11 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
VALUE str, bs;
int base = 10;
- GetBN(self, bn);
-
if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) {
base = NUM2INT(bs);
}
+ StringValue(str);
+ GetBN(self, bn);
if (RTEST(rb_obj_is_kind_of(str, cBN))) {
BIGNUM *other;
@@ -121,27 +128,25 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
}
return self;
}
- str = rb_String(str);
- StringValue(str);
switch (base) {
case 0:
- if (!BN_mpi2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
+ if (!BN_mpi2bn(RSTRING_PTR(str), RSTRING_LEN(str), bn)) {
ossl_raise(eBNError, NULL);
}
break;
case 2:
- if (!BN_bin2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
+ if (!BN_bin2bn(RSTRING_PTR(str), RSTRING_LEN(str), bn)) {
ossl_raise(eBNError, NULL);
}
break;
case 10:
- if (!BN_dec2bn(&bn, RSTRING(str)->ptr)) {
+ if (!BN_dec2bn(&bn, RSTRING_PTR(str))) {
ossl_raise(eBNError, NULL);
}
break;
case 16:
- if (!BN_hex2bn(&bn, RSTRING(str)->ptr)) {
+ if (!BN_hex2bn(&bn, RSTRING_PTR(str))) {
ossl_raise(eBNError, NULL);
}
break;
@@ -151,6 +156,19 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * bn.to_s => string
+ * bn.to_s(base) => string
+ *
+ * === Parameters
+ * * +base+ - integer
+ * * * Valid values:
+ * * * * 0 - MPI
+ * * * * 2 - binary
+ * * * * 10 - the default
+ * * * * 16 - hex
+ */
static VALUE
ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
{
@@ -159,22 +177,21 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
int base = 10, len;
char *buf;
- GetBN(self, bn);
-
if (rb_scan_args(argc, argv, "01", &bs) == 1) {
base = NUM2INT(bs);
}
+ GetBN(self, bn);
switch (base) {
case 0:
len = BN_bn2mpi(bn, NULL);
str = rb_str_new(0, len);
- if (BN_bn2mpi(bn, RSTRING(str)->ptr) != len)
+ if (BN_bn2mpi(bn, RSTRING_PTR(str)) != len)
ossl_raise(eBNError, NULL);
break;
case 2:
len = BN_num_bytes(bn);
str = rb_str_new(0, len);
- if (BN_bn2bin(bn, RSTRING(str)->ptr) != len)
+ if (BN_bn2bin(bn, RSTRING_PTR(str)) != len)
ossl_raise(eBNError, NULL);
break;
case 10:
@@ -192,6 +209,10 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
return str;
}
+/*
+ * call-seq:
+ * bn.to_i => integer
+ */
static VALUE
ossl_bn_to_i(VALUE self)
{
@@ -236,6 +257,11 @@ ossl_bn_coerce(VALUE self, VALUE other)
}
#define BIGNUM_BOOL1(func) \
+ /* \
+ * call-seq: \
+ * bn.##func -> true | false \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self) \
{ \
@@ -251,6 +277,11 @@ BIGNUM_BOOL1(is_one);
BIGNUM_BOOL1(is_odd);
#define BIGNUM_1c(func) \
+ /* \
+ * call-seq: \
+ * bn.##func -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self) \
{ \
@@ -270,6 +301,11 @@ BIGNUM_BOOL1(is_odd);
BIGNUM_1c(sqr);
#define BIGNUM_2(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bn2) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE other) \
{ \
@@ -290,6 +326,11 @@ BIGNUM_2(add);
BIGNUM_2(sub);
#define BIGNUM_2c(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bn2) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE other) \
{ \
@@ -313,6 +354,10 @@ BIGNUM_2c(gcd);
BIGNUM_2c(mod_sqr);
BIGNUM_2c(mod_inverse);
+/*
+ * call-seq:
+ * bn1 / bn2 => [result, remainder]
+ */
static VALUE
ossl_bn_div(VALUE self, VALUE other)
{
@@ -340,6 +385,11 @@ ossl_bn_div(VALUE self, VALUE other)
}
#define BIGNUM_3c(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bn1, bn2) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
{ \
@@ -363,6 +413,11 @@ BIGNUM_3c(mod_mul);
BIGNUM_3c(mod_exp);
#define BIGNUM_BIT(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bit) -> self \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE bit) \
{ \
@@ -377,28 +432,38 @@ BIGNUM_BIT(set_bit);
BIGNUM_BIT(clear_bit);
BIGNUM_BIT(mask_bits);
+/*
+ * call-seq:
+ * bn.bit_set?(bit) => true | false
+ */
static VALUE
ossl_bn_is_bit_set(VALUE self, VALUE bit)
{
+ int b;
BIGNUM *bn;
+ b = NUM2INT(bit);
GetBN(self, bn);
-
- if (BN_is_bit_set(bn, NUM2INT(bit))) {
+ if (BN_is_bit_set(bn, b)) {
return Qtrue;
}
return Qfalse;
}
#define BIGNUM_SHIFT(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bits) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE bits) \
{ \
BIGNUM *bn, *result; \
int b; \
VALUE obj; \
- GetBN(self, bn); \
b = NUM2INT(bits); \
+ GetBN(self, bn); \
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
@@ -412,7 +477,32 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
BIGNUM_SHIFT(lshift);
BIGNUM_SHIFT(rshift);
+#define BIGNUM_SELF_SHIFT(func) \
+ /* \
+ * call-seq: \
+ * bn.##func!(bits) -> self \
+ * \
+ */ \
+ static VALUE \
+ ossl_bn_self_##func(VALUE self, VALUE bits) \
+ { \
+ BIGNUM *bn; \
+ int b; \
+ b = NUM2INT(bits); \
+ GetBN(self, bn); \
+ if (!BN_##func(bn, bn, b)) \
+ ossl_raise(eBNError, NULL); \
+ return self; \
+ }
+BIGNUM_SELF_SHIFT(lshift);
+BIGNUM_SELF_SHIFT(rshift);
+
#define BIGNUM_RAND(func) \
+ /* \
+ * call-seq: \
+ * BN.##func(bits [, fill [, odd]]) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \
{ \
@@ -425,7 +515,7 @@ BIGNUM_SHIFT(rshift);
bottom = (odd == Qtrue) ? 1 : 0; \
/* FALLTHROUGH */ \
case 2: \
- top = FIX2INT(fill); \
+ top = NUM2INT(fill); \
} \
b = NUM2INT(bits); \
if (!(result = BN_new())) { \
@@ -442,6 +532,11 @@ BIGNUM_RAND(rand);
BIGNUM_RAND(pseudo_rand);
#define BIGNUM_RAND_RANGE(func) \
+ /* \
+ * call-seq: \
+ * BN.##func(range) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_s_##func##_range(VALUE klass, VALUE range) \
{ \
@@ -460,6 +555,16 @@ BIGNUM_RAND(pseudo_rand);
BIGNUM_RAND_RANGE(rand);
BIGNUM_RAND_RANGE(pseudo_rand);
+/*
+ * call-seq:
+ * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn
+ *
+ * === Parameters
+ * * +bits+ - integer
+ * * +safe+ - boolean
+ * * +add+ - BN
+ * * +rem+ - BN
+ */
static VALUE
ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
{
@@ -475,12 +580,8 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
safe = 0;
}
if (!NIL_P(vadd)) {
- if (NIL_P(vrem)) {
- ossl_raise(rb_eArgError,
- "if ADD is specified, REM must be also given");
- }
add = GetBNPtr(vadd);
- rem = GetBNPtr(vrem);
+ rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem);
}
if (!(result = BN_new())) {
ossl_raise(eBNError, NULL);
@@ -491,10 +592,15 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
}
WrapBN(klass, obj, result);
- return obj;
+ return obj;
}
#define BIGNUM_NUM(func) \
+ /* \
+ * call-seq: \
+ * bn.##func -> integer \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self) \
{ \
@@ -524,6 +630,11 @@ ossl_bn_copy(VALUE self, VALUE other)
}
#define BIGNUM_CMP(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bn2) -> integer \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE other) \
{ \
@@ -543,6 +654,14 @@ ossl_bn_eql(VALUE self, VALUE other)
return Qfalse;
}
+/*
+ * call-seq:
+ * bn.prime? => true | false
+ * bn.prime?(checks) => true | false
+ *
+ * === Parameters
+ * * +checks+ - integer
+ */
static VALUE
ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
{
@@ -550,11 +669,10 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
VALUE vchecks;
int checks = BN_prime_checks;
- GetBN(self, bn);
-
if (rb_scan_args(argc, argv, "01", &vchecks) == 0) {
checks = NUM2INT(vchecks);
}
+ GetBN(self, bn);
switch (BN_is_prime(bn, checks, NULL, ossl_bn_ctx, NULL)) {
case 1:
return Qtrue;
@@ -567,6 +685,16 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
return Qnil;
}
+/*
+ * call-seq:
+ * bn.prime_fasttest? => true | false
+ * bn.prime_fasttest?(checks) => true | false
+ * bn.prime_fasttest?(checks, trial_div) => true | false
+ *
+ * === Parameters
+ * * +checks+ - integer
+ * * +trial_div+ - boolean
+ */
static VALUE
ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
{
@@ -574,13 +702,12 @@ ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
VALUE vchecks, vtrivdiv;
int checks = BN_prime_checks, do_trial_division = 1;
- GetBN(self, bn);
-
rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv);
if (!NIL_P(vchecks)) {
checks = NUM2INT(vchecks);
}
+ GetBN(self, bn);
/* handle true/false */
if (vtrivdiv == Qfalse) {
do_trial_division = 0;
@@ -604,6 +731,10 @@ ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
void
Init_ossl_bn()
{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
if (!(ossl_bn_ctx = BN_CTX_new())) {
ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
}
@@ -676,8 +807,10 @@ Init_ossl_bn()
rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1);
rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1);
rb_define_method(cBN, "<<", ossl_bn_lshift, 1);
- /* lshift1 - DON'T IMPL. */
rb_define_method(cBN, ">>", ossl_bn_rshift, 1);
+ rb_define_method(cBN, "lshift!", ossl_bn_self_lshift, 1);
+ rb_define_method(cBN, "rshift!", ossl_bn_self_rshift, 1);
+ /* lshift1 - DON'T IMPL. */
/* rshift1 - DON'T IMPL. */
/*
diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h
index 12aa484873..d6c396227b 100644
--- a/ext/openssl/ossl_bn.h
+++ b/ext/openssl/ossl_bn.h
@@ -14,9 +14,12 @@
extern VALUE cBN;
extern VALUE eBNError;
-VALUE ossl_bn_new(BIGNUM *);
+extern BN_CTX *ossl_bn_ctx;
+
+VALUE ossl_bn_new(const BIGNUM *);
BIGNUM *GetBNPtr(VALUE);
void Init_ossl_bn(void);
+
#endif /* _OSS_BN_H_ */
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 93b3f6ccf9..b680dc6e64 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -26,7 +26,6 @@
/*
* Classes
*/
-VALUE mCipher;
VALUE cCipher;
VALUE eCipherError;
@@ -54,7 +53,7 @@ ossl_cipher_new(const EVP_CIPHER *cipher)
ret = ossl_cipher_alloc(cCipher);
GetCipher(ret, ctx);
EVP_CIPHER_CTX_init(ctx);
- if (EVP_CipherInit(ctx, cipher, NULL, NULL, -1) != 1)
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
ossl_raise(eCipherError, NULL);
return ret;
@@ -79,10 +78,19 @@ ossl_cipher_alloc(VALUE klass)
VALUE obj;
MakeCipher(obj, klass, ctx);
+ EVP_CIPHER_CTX_init(ctx);
return obj;
}
+/*
+ * call-seq:
+ * Cipher.new(string) -> cipher
+ *
+ * The string must contain a valid cipher name like "AES-128-CBC" or "3DES".
+ *
+ * A list of cipher names is available by calling OpenSSL::Cipher.ciphers.
+ */
static VALUE
ossl_cipher_initialize(VALUE self, VALUE str)
{
@@ -90,16 +98,13 @@ ossl_cipher_initialize(VALUE self, VALUE str)
const EVP_CIPHER *cipher;
char *name;
- GetCipher(self, ctx);
-
name = StringValuePtr(str);
-
+ GetCipher(self, ctx);
if (!(cipher = EVP_get_cipherbyname(name))) {
- ossl_raise(rb_eRuntimeError, "Unsupported cipher algorithm (%s).", name);
+ ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name);
}
- EVP_CIPHER_CTX_init(ctx);
- if (EVP_CipherInit(ctx, cipher, NULL, NULL, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
+ ossl_raise(eCipherError, NULL);
return self;
}
@@ -113,143 +118,251 @@ ossl_cipher_copy(VALUE self, VALUE other)
GetCipher(self, ctx1);
SafeGetCipher(other, ctx2);
-
- memcpy(ctx1, ctx2, sizeof(EVP_CIPHER_CTX));
+ if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1)
+ ossl_raise(eCipherError, NULL);
return self;
}
+static void*
+add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
+{
+ rb_ary_push(ary, rb_str_new2(name->name));
+ return NULL;
+}
+
+/*
+ * call-seq:
+ * Cipher.ciphers -> array[string...]
+ *
+ * Returns the names of all available ciphers in an array.
+ */
+static VALUE
+ossl_s_ciphers(VALUE self)
+{
+#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
+ VALUE ary;
+
+ ary = rb_ary_new();
+ OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
+ (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary,
+ (void*)ary);
+
+ return ary;
+#else
+ rb_notimplement();
+#endif
+}
+
+/*
+ * call-seq:
+ * cipher.reset -> self
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1).
+ */
static VALUE
ossl_cipher_reset(VALUE self)
{
EVP_CIPHER_CTX *ctx;
GetCipher(self, ctx);
- if (EVP_CipherInit(ctx, NULL, NULL, NULL, -1) != 1)
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1) != 1)
ossl_raise(eCipherError, NULL);
return self;
}
static VALUE
-ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
+ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
{
EVP_CIPHER_CTX *ctx;
- unsigned char iv[EVP_MAX_IV_LENGTH], key[EVP_MAX_KEY_LENGTH];
+ unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL;
+ unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL;
VALUE pass, init_v;
- GetCipher(self, ctx);
-
- rb_scan_args(argc, argv, "02", &pass, &init_v);
-
- if (NIL_P(init_v)) {
- /*
- * TODO:
- * random IV generation!
- */
- memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
+ if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){
/*
- RAND_add(data,i,0); where from take data?
- if (RAND_pseudo_bytes(iv, 8) < 0) {
- ossl_raise(eCipherError, NULL);
- }
- */
- }
- else {
- init_v = rb_obj_as_string(init_v);
- if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) {
- memset(iv, 0, EVP_MAX_IV_LENGTH);
- memcpy(iv, RSTRING(init_v)->ptr, RSTRING(init_v)->len);
- }
- else {
- memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv));
+ * oops. this code mistakes salt for IV.
+ * We deprecated the arguments for this method, but we decided
+ * keeping this behaviour for backward compatibility.
+ */
+ char *cname = rb_class2name(rb_obj_class(self));
+ rb_warn("argumtents for %s#encrypt and %s#decrypt were deprecated; "
+ "use %s#pkcs5_keyivgen to derive key and IV",
+ cname, cname, cname);
+ StringValue(pass);
+ GetCipher(self, ctx);
+ if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
+ else{
+ StringValue(init_v);
+ if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) {
+ memset(iv, 0, EVP_MAX_IV_LENGTH);
+ memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v));
+ }
+ else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv));
}
+ EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
+ RSTRING_PTR(pass), RSTRING_LEN(pass), 1, key, NULL);
+ p_key = key;
+ p_iv = iv;
}
-
- if (EVP_CipherInit(ctx, NULL, NULL, NULL, 1) != 1) {
- ossl_raise(eCipherError, NULL);
+ else {
+ GetCipher(self, ctx);
}
-
- if (!NIL_P(pass)) {
- StringValue(pass);
-
- EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
- RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL);
- if (EVP_CipherInit(ctx, NULL, key, iv, -1) != 1) {
- ossl_raise(eCipherError, NULL);
- }
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) {
+ ossl_raise(eCipherError, NULL);
}
return self;
}
+/*
+ * call-seq:
+ * cipher.encrypt -> self
+ *
+ * Make sure to call .encrypt or .decrypt before using any of the following methods:
+ * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
+ */
+static VALUE
+ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
+{
+ return ossl_cipher_init(argc, argv, self, 1);
+}
+
+/*
+ * call-seq:
+ * cipher.decrypt -> self
+ *
+ * Make sure to call .encrypt or .decrypt before using any of the following methods:
+ * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
+ */
static VALUE
ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
{
- EVP_CIPHER_CTX *ctx;
- unsigned char iv[EVP_MAX_IV_LENGTH], key[EVP_MAX_KEY_LENGTH];
- VALUE pass, init_v;
-
- GetCipher(self, ctx);
- rb_scan_args(argc, argv, "02", &pass, &init_v);
+ return ossl_cipher_init(argc, argv, self, 0);
+}
- if (NIL_P(init_v)) {
- /*
- * TODO:
- * random IV generation!
- */
- memcpy(iv, "OpenSSL for Ruby rulez!", EVP_MAX_IV_LENGTH);
- }
- else {
- init_v = rb_obj_as_string(init_v);
- if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) {
- memset(iv, 0, EVP_MAX_IV_LENGTH);
- memcpy(iv, RSTRING(init_v)->ptr, RSTRING(init_v)->len);
- }
- else {
- memcpy(iv, RSTRING(init_v)->ptr, EVP_MAX_IV_LENGTH);
- }
+/*
+ * call-seq:
+ * cipher.pkcs5_keyivgen(pass [, salt [, iterations [, digest]]] ) -> nil
+ *
+ * Generates and sets the key/iv based on a password.
+ *
+ * WARNING: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40, or DES
+ * with MD5 or SHA1. Using anything else (like AES) will generate the key/iv using an
+ * OpenSSL specific method. Use a PKCS5 v2 key generation method instead.
+ *
+ * === Parameters
+ * +salt+ must be an 8 byte string if provided.
+ * +iterations+ is a integer with a default of 2048.
+ * +digest+ is a Digest object that defaults to 'MD5'
+ *
+ * A minimum of 1000 iterations is recommended.
+ *
+ */
+static VALUE
+ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+ const EVP_MD *digest;
+ VALUE vpass, vsalt, viter, vdigest;
+ unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL;
+ int iter;
+
+ rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest);
+ StringValue(vpass);
+ if(!NIL_P(vsalt)){
+ StringValue(vsalt);
+ if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
+ rb_raise(eCipherError, "salt must be an 8-octet string");
+ salt = RSTRING_PTR(vsalt);
}
+ iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
+ digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest);
+ GetCipher(self, ctx);
+ EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
+ RSTRING_PTR(vpass), RSTRING_LEN(vpass), iter, key, iv);
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1)
+ ossl_raise(eCipherError, NULL);
+ OPENSSL_cleanse(key, sizeof key);
+ OPENSSL_cleanse(iv, sizeof iv);
- if (EVP_CipherInit(ctx, NULL, NULL, NULL, 0) != 1) {
- ossl_raise(eCipherError, NULL);
- }
+ return Qnil;
+}
- if (!NIL_P(pass)) {
- StringValue(pass);
- EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
- RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL);
- if (EVP_CipherInit(ctx, NULL, key, iv, -1) != 1) {
- ossl_raise(eCipherError, NULL);
- }
- }
+/*
+ * call-seq:
+ * cipher << data -> string
+ *
+ * === Parameters
+ * +data+ is a nonempty string.
+ *
+ * This method is deprecated and not available in 1.9.x or later.
+ */
+static VALUE
+ossl_cipher_update_deprecated(VALUE self, VALUE data)
+{
+ char *cname;
- return self;
+ cname = rb_class2name(rb_obj_class(self));
+ rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname);
+ return rb_funcall(self, rb_intern("update"), 1, data);
}
+
+/*
+ * call-seq:
+ * cipher.update(data [, buffer]) -> string or buffer
+ *
+ * === Parameters
+ * +data+ is a nonempty string.
+ * +buffer+ is an optional string to store the result.
+ */
static VALUE
-ossl_cipher_update(VALUE self, VALUE data)
+ossl_cipher_update(int argc, VALUE *argv, VALUE self)
{
EVP_CIPHER_CTX *ctx;
char *in;
int in_len, out_len;
- VALUE str;
+ VALUE data, str;
+
+ rb_scan_args(argc, argv, "11", &data, &str);
- GetCipher(self, ctx);
StringValue(data);
- in = RSTRING(data)->ptr;
- in_len = RSTRING(data)->len;
- str = rb_str_new(0, in_len+EVP_CIPHER_CTX_block_size(ctx));
- if (!EVP_CipherUpdate(ctx, RSTRING(str)->ptr, &out_len, in, in_len))
+ in = RSTRING_PTR(data);
+ if ((in_len = RSTRING_LEN(data)) == 0)
+ rb_raise(rb_eArgError, "data must not be empty");
+ GetCipher(self, ctx);
+ out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
+
+ if (NIL_P(str)) {
+ str = rb_str_new(0, out_len);
+ } else {
+ StringValue(str);
+ rb_str_resize(str, out_len);
+ }
+
+ if (!EVP_CipherUpdate(ctx, RSTRING_PTR(str), &out_len, in, in_len))
ossl_raise(eCipherError, NULL);
- assert(out_len < RSTRING(str)->len);
- RSTRING(str)->len = out_len;
- RSTRING(str)->ptr[out_len] = 0;
+ assert(out_len < RSTRING_LEN(str));
+ rb_str_set_len(str, out_len);
return str;
}
+/*
+ * call-seq:
+ * cipher.final -> aString
+ *
+ * Returns the remaining data held in the cipher object. Further calls to update() or final() will return garbage.
+ *
+ * See EVP_CipherFinal_ex for further information.
+ */
static VALUE
ossl_cipher_final(VALUE self)
{
@@ -259,15 +372,20 @@ ossl_cipher_final(VALUE self)
GetCipher(self, ctx);
str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
- if (!EVP_CipherFinal(ctx, RSTRING(str)->ptr, &out_len))
+ if (!EVP_CipherFinal_ex(ctx, RSTRING_PTR(str), &out_len))
ossl_raise(eCipherError, NULL);
- assert(out_len <= RSTRING(str)->len);
- RSTRING(str)->len = out_len;
- RSTRING(str)->ptr[out_len] = 0;
+ assert(out_len <= RSTRING_LEN(str));
+ rb_str_set_len(str, out_len);
return str;
}
+/*
+ * call-seq:
+ * cipher.name -> string
+ *
+ * Returns the name of the cipher which may differ slightly from the original name provided.
+ */
static VALUE
ossl_cipher_name(VALUE self)
{
@@ -278,6 +396,14 @@ ossl_cipher_name(VALUE self)
return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx)));
}
+/*
+ * call-seq:
+ * cipher.key = string -> string
+ *
+ * Sets the cipher key.
+ *
+ * Only call this method after calling cipher.encrypt or cipher.decrypt.
+ */
static VALUE
ossl_cipher_set_key(VALUE self, VALUE key)
{
@@ -286,15 +412,23 @@ ossl_cipher_set_key(VALUE self, VALUE key)
StringValue(key);
GetCipher(self, ctx);
- if (RSTRING(key)->len < EVP_CIPHER_CTX_key_length(ctx))
+ if (RSTRING_LEN(key) < EVP_CIPHER_CTX_key_length(ctx))
ossl_raise(eCipherError, "key length too short");
- if (EVP_CipherInit(ctx, NULL, RSTRING(key)->ptr, NULL, -1) != 1)
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING_PTR(key), NULL, -1) != 1)
ossl_raise(eCipherError, NULL);
return key;
}
+/*
+ * call-seq:
+ * cipher.iv = string -> string
+ *
+ * Sets the cipher iv.
+ *
+ * Only call this method after calling cipher.encrypt or cipher.decrypt.
+ */
static VALUE
ossl_cipher_set_iv(VALUE self, VALUE iv)
{
@@ -303,25 +437,60 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
StringValue(iv);
GetCipher(self, ctx);
- if (RSTRING(iv)->len < EVP_CIPHER_CTX_iv_length(ctx))
+ if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx))
ossl_raise(eCipherError, "iv length too short");
- if (EVP_CipherInit(ctx, NULL, NULL, RSTRING(iv)->ptr, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING_PTR(iv), -1) != 1)
+ ossl_raise(eCipherError, NULL);
return iv;
}
+
+/*
+ * call-seq:
+ * cipher.key_length = integer -> integer
+ *
+ * Sets the key length of the cipher. If the cipher is a fixed length cipher then attempting to set the key
+ * length to any value other than the fixed value is an error.
+ *
+ * Under normal circumstances you do not need to call this method (and probably shouldn't).
+ *
+ * See EVP_CIPHER_CTX_set_key_length for further information.
+ */
+static VALUE
+ossl_cipher_set_key_length(VALUE self, VALUE key_length)
+{
+ int len = NUM2INT(key_length);
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+ if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return key_length;
+}
+
+/*
+ * call-seq:
+ * cipher.padding = integer -> integer
+ *
+ * Enables or disables padding. By default encryption operations are padded using standard block padding and the
+ * padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the
+ * total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur.
+ *
+ * See EVP_CIPHER_CTX_set_padding for further information.
+ */
static VALUE
ossl_cipher_set_padding(VALUE self, VALUE padding)
{
-#if defined(HAVE_ST_FLAGS)
+#if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING)
EVP_CIPHER_CTX *ctx;
+ int pad = NUM2INT(padding);
GetCipher(self, ctx);
-
- if (EVP_CIPHER_CTX_set_padding(ctx, NUM2INT(padding)) != 1)
- ossl_raise(eCipherError, NULL);
+ if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1)
+ ossl_raise(eCipherError, NULL);
#else
rb_notimplement();
#endif
@@ -340,43 +509,59 @@ CIPHER_0ARG_INT(key_length)
CIPHER_0ARG_INT(iv_length)
CIPHER_0ARG_INT(block_size)
+#if 0
+/*
+ * call-seq:
+ * cipher.key_length -> integer
+ *
+ */
+static VALUE ossl_cipher_key_length() { }
+/*
+ * call-seq:
+ * cipher.iv_length -> integer
+ *
+ */
+static VALUE ossl_cipher_iv_length() { }
+/*
+ * call-seq:
+ * cipher.block_size -> integer
+ *
+ */
+static VALUE ossl_cipher_block_size() { }
+#endif
+
/*
* INIT
*/
void
Init_ossl_cipher(void)
{
- mCipher = rb_define_module_under(mOSSL, "Cipher");
- eCipherError = rb_define_class_under(mOSSL, "CipherError", eOSSLError);
- cCipher = rb_define_class_under(mCipher, "Cipher", rb_cObject);
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+ cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
+ eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
rb_define_alloc_func(cCipher, ossl_cipher_alloc);
- rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
-
rb_define_copy_func(cCipher, ossl_cipher_copy);
-
+ rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0);
+ rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
rb_define_method(cCipher, "reset", ossl_cipher_reset, 0);
-
rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1);
rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1);
- rb_define_method(cCipher, "update", ossl_cipher_update, 1);
- rb_define_alias(cCipher, "<<", "update");
+ rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
+ rb_define_method(cCipher, "update", ossl_cipher_update, -1);
+#if RUBY_VERSION_CODE < 190
+ rb_define_method(cCipher, "<<", ossl_cipher_update_deprecated, 1);
+#endif
rb_define_method(cCipher, "final", ossl_cipher_final, 0);
-
rb_define_method(cCipher, "name", ossl_cipher_name, 0);
-
rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1);
+ rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1);
rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0);
-/*
- * TODO
- * int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
- */
rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1);
rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
-
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
-
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
-
-} /* Init_ossl_cipher */
+}
diff --git a/ext/openssl/ossl_cipher.h b/ext/openssl/ossl_cipher.h
index 63c7a875e8..bed4fa853b 100644
--- a/ext/openssl/ossl_cipher.h
+++ b/ext/openssl/ossl_cipher.h
@@ -11,7 +11,6 @@
#if !defined(_OSSL_CIPHER_H_)
#define _OSSL_CIPHER_H_
-extern VALUE mCipher;
extern VALUE cCipher;
extern VALUE eCipherError;
diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c
index 7e6f696d33..cc8e324029 100644
--- a/ext/openssl/ossl_config.c
+++ b/ext/openssl/ossl_config.c
@@ -119,8 +119,8 @@ ossl_config_copy(VALUE self, VALUE other)
VALUE str;
CONF *conf;
- GetConfig(other, conf);
str = rb_funcall(self, rb_intern("to_s"), 0);
+ GetConfig(other, conf);
parse_config(str, conf);
return self;
@@ -134,11 +134,11 @@ ossl_config_initialize(int argc, VALUE *argv, VALUE self)
char *filename;
VALUE path;
- GetConfig(self, conf);
rb_scan_args(argc, argv, "01", &path);
if(!NIL_P(path)){
SafeStringValue(path);
filename = StringValuePtr(path);
+ GetConfig(self, conf);
if (!NCONF_load(conf, filename, &eline)){
if (eline <= 0)
ossl_raise(eConfigError, "wrong config file %s", filename);
@@ -147,9 +147,12 @@ ossl_config_initialize(int argc, VALUE *argv, VALUE self)
}
}
#ifdef OSSL_NO_CONF_API
- else rb_raise(rb_eArgError, "wrong number of arguments(0 for 1)");
+ else rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
#else
- else _CONF_new_data(conf);
+ else {
+ GetConfig(self, conf);
+ _CONF_new_data(conf);
+ }
#endif
return self;
@@ -164,20 +167,20 @@ ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value)
CONF *conf;
CONF_VALUE *sv, *cv;
- GetConfig(self, conf);
StringValue(section);
StringValue(name);
StringValue(value);
- if(!(sv = _CONF_get_section(conf, RSTRING(section)->ptr))){
- if(!(sv = _CONF_new_section(conf, RSTRING(section)->ptr))){
+ GetConfig(self, conf);
+ if(!(sv = _CONF_get_section(conf, RSTRING_PTR(section)))){
+ if(!(sv = _CONF_new_section(conf, RSTRING_PTR(section)))){
ossl_raise(eConfigError, NULL);
}
}
if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){
ossl_raise(eConfigError, NULL);
}
- cv->name = BUF_strdup(RSTRING(name)->ptr);
- cv->value = BUF_strdup(RSTRING(value)->ptr);
+ cv->name = BUF_strdup(RSTRING_PTR(name));
+ cv->value = BUF_strdup(RSTRING_PTR(value));
if(!cv->name || !cv->value || !_CONF_add_string(conf, sv, cv)){
OPENSSL_free(cv->name);
OPENSSL_free(cv->value);
@@ -195,10 +198,10 @@ ossl_config_get_value(VALUE self, VALUE section, VALUE name)
CONF *conf;
char *str;
- GetConfig(self, conf);
StringValue(section);
StringValue(name);
- str = NCONF_get_string(conf, RSTRING(section)->ptr, RSTRING(name)->ptr);
+ GetConfig(self, conf);
+ str = NCONF_get_string(conf, RSTRING_PTR(section), RSTRING_PTR(name));
if(!str){
ERR_clear_error();
return Qnil;
@@ -242,8 +245,11 @@ set_conf_section_i(VALUE i, VALUE *arg)
static VALUE
ossl_config_set_section(VALUE self, VALUE section, VALUE hash)
{
- VALUE arg[2] = { self, section };
- rb_iterate(rb_each, hash, set_conf_section_i, (VALUE)arg);
+ VALUE arg[2];
+
+ arg[0] = self;
+ arg[1] = section;
+ rb_block_call(hash, rb_intern("each"), 0, 0, set_conf_section_i, (VALUE)arg);
return hash;
}
@@ -261,6 +267,7 @@ ossl_config_get_section(VALUE self, VALUE section)
VALUE hash;
hash = rb_hash_new();
+ StringValue(section);
GetConfig(self, conf);
if (!(sk = NCONF_get_section(conf, StringValuePtr(section)))) {
ERR_clear_error();
@@ -307,16 +314,7 @@ ossl_config_get_sections(VALUE self)
return ary;
}
-#else
-static VALUE
-ossl_config_get_sections(VALUE self)
-{
- rb_warn("Config::sections don't work with %s", OPENSSL_VERSION_TEXT);
- return rb_ary_new();
-}
-#endif
-#ifdef IMPLEMENT_LHASH_DOALL_ARG_FN
static void
dump_conf_value(CONF_VALUE *cv, VALUE str)
{
@@ -362,13 +360,61 @@ ossl_config_to_s(VALUE self)
return dump_conf(conf);
}
+
+static void
+each_conf_value(CONF_VALUE *cv, void* dummy)
+{
+ STACK_OF(CONF_VALUE) *sk;
+ CONF_VALUE *v;
+ VALUE section, name, value, args;
+ int i, num;
+
+ if (cv->name) return;
+ sk = (STACK_OF(CONF_VALUE)*)cv->value;
+ num = sk_CONF_VALUE_num(sk);
+ section = rb_str_new2(cv->section);
+ for(i = 0; i < num; i++){
+ v = sk_CONF_VALUE_value(sk, i);
+ name = v->name ? rb_str_new2(v->name) : Qnil;
+ value = v->value ? rb_str_new2(v->value) : Qnil;
+ args = rb_ary_new3(3, section, name, value);
+ rb_yield(args);
+ }
+}
+
+static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE*, void*);
+
+static VALUE
+ossl_config_each(VALUE self)
+{
+ CONF *conf;
+
+ GetConfig(self, conf);
+ lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(each_conf_value), (void*)NULL);
+
+ return self;
+}
#else
static VALUE
+ossl_config_get_sections(VALUE self)
+{
+ rb_warn("#sections don't work with %s", OPENSSL_VERSION_TEXT);
+ return rb_ary_new();
+}
+
+static VALUE
ossl_config_to_s(VALUE self)
{
- rb_warn("Config::to_s don't work with %s", OPENSSL_VERSION_TEXT);
+ rb_warn("#to_s don't work with %s", OPENSSL_VERSION_TEXT);
return rb_str_new(0, 0);
}
+
+static VALUE
+ossl_config_each(VALUE self)
+{
+ rb_warn("#each don't work with %s", OPENSSL_VERSION_TEXT);
+ return self;
+}
#endif
static VALUE
@@ -397,6 +443,7 @@ Init_ossl_config()
rb_define_const(cConfig, "DEFAULT_CONFIG_FILE",
rb_str_new2(CONF_get1_default_config_file()));
+ rb_include_module(cConfig, rb_mEnumerable);
rb_define_singleton_method(cConfig, "parse", ossl_config_s_parse, 1);
rb_define_alias(CLASS_OF(cConfig), "load", "new");
rb_define_alloc_func(cConfig, ossl_config_s_alloc);
@@ -410,5 +457,6 @@ Init_ossl_config()
rb_define_method(cConfig, "[]=", ossl_config_set_section, 2);
rb_define_method(cConfig, "sections", ossl_config_get_sections, 0);
rb_define_method(cConfig, "to_s", ossl_config_to_s, 0);
+ rb_define_method(cConfig, "each", ossl_config_each, 0);
rb_define_method(cConfig, "inspect", ossl_config_inspect, 0);
}
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index b117ddd30d..879d399fe7 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -24,7 +24,6 @@
/*
* Classes
*/
-VALUE mDigest;
VALUE cDigest;
VALUE eDigestError;
@@ -36,11 +35,23 @@ static VALUE ossl_digest_alloc(VALUE klass);
const EVP_MD *
GetDigestPtr(VALUE obj)
{
- EVP_MD_CTX *ctx;
+ const EVP_MD *md;
+
+ if (TYPE(obj) == T_STRING) {
+ const char *name = STR2CSTR(obj);
- SafeGetDigest(obj, ctx);
+ md = EVP_get_digestbyname(name);
+ if (!md)
+ ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
+ } else {
+ EVP_MD_CTX *ctx;
+
+ SafeGetDigest(obj, ctx);
- return EVP_MD_CTX_md(ctx); /*== ctx->digest*/
+ md = EVP_MD_CTX_md(ctx);
+ }
+
+ return md;
}
VALUE
@@ -51,8 +62,7 @@ ossl_digest_new(const EVP_MD *md)
ret = ossl_digest_alloc(cDigest);
GetDigest(ret, ctx);
- EVP_MD_CTX_init(ctx);
- EVP_DigestInit(ctx, md);
+ EVP_DigestInit_ex(ctx, md, NULL);
return ret;
}
@@ -70,12 +80,17 @@ ossl_digest_alloc(VALUE klass)
if (ctx == NULL)
ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx);
-
+
return obj;
}
VALUE ossl_digest_update(VALUE, VALUE);
+/*
+ * call-seq:
+ * Digest.new(string) -> digest
+ *
+ */
static VALUE
ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -84,18 +99,12 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
char *name;
VALUE type, data;
- GetDigest(self, ctx);
-
rb_scan_args(argc, argv, "11", &type, &data);
- name = StringValuePtr(type);
+ md = GetDigestPtr(type);
if (!NIL_P(data)) StringValue(data);
-
- md = EVP_get_digestbyname(name);
- if (!md) {
- ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
- }
- EVP_MD_CTX_init(ctx);
- EVP_DigestInit(ctx, md);
+
+ GetDigest(self, ctx);
+ EVP_DigestInit_ex(ctx, md, NULL);
if (!NIL_P(data)) return ossl_digest_update(self, data);
return self;
@@ -118,143 +127,105 @@ ossl_digest_copy(VALUE self, VALUE other)
return self;
}
+/*
+ * call-seq:
+ * digest.reset -> self
+ *
+ */
static VALUE
ossl_digest_reset(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
- EVP_DigestInit(ctx, EVP_MD_CTX_md(ctx));
+ EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL);
return self;
}
+/*
+ * call-seq:
+ * digest.update(string) -> aString
+ *
+ */
VALUE
ossl_digest_update(VALUE self, VALUE data)
{
EVP_MD_CTX *ctx;
- GetDigest(self, ctx);
StringValue(data);
- EVP_DigestUpdate(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ GetDigest(self, ctx);
+ EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
return self;
}
-static void
-digest_final(EVP_MD_CTX *ctx, char **buf, int *buf_len)
-{
- EVP_MD_CTX final;
-
- if (!EVP_MD_CTX_copy(&final, ctx)) {
- ossl_raise(eDigestError, NULL);
- }
- if (!(*buf = OPENSSL_malloc(EVP_MD_CTX_size(&final)))) {
- ossl_raise(eDigestError, "Cannot allocate mem for digest");
- }
- EVP_DigestFinal(&final, *buf, buf_len);
- EVP_MD_CTX_cleanup(&final);
-}
-
+/*
+ * call-seq:
+ * digest.finish -> aString
+ *
+ */
static VALUE
-ossl_digest_digest(VALUE self)
+ossl_digest_finish(int argc, VALUE *argv, VALUE self)
{
EVP_MD_CTX *ctx;
- char *buf;
- int buf_len;
- VALUE digest;
-
- GetDigest(self, ctx);
- digest_final(ctx, &buf, &buf_len);
- digest = ossl_buf2str(buf, buf_len);
-
- return digest;
-}
+ VALUE str;
-static VALUE
-ossl_digest_hexdigest(VALUE self)
-{
- EVP_MD_CTX *ctx;
- char *buf, *hexbuf;
- int buf_len;
- VALUE hexdigest;
+ rb_scan_args(argc, argv, "01", &str);
GetDigest(self, ctx);
- digest_final(ctx, &buf, &buf_len);
- if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
- OPENSSL_free(buf);
- ossl_raise(eDigestError, "Memory alloc error");
- }
- OPENSSL_free(buf);
- hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
-
- return hexdigest;
-}
-static VALUE
-ossl_digest_s_digest(VALUE klass, VALUE str, VALUE data)
-{
- VALUE obj = rb_class_new_instance(1, &str, klass);
-
- ossl_digest_update(obj, data);
-
- return ossl_digest_digest(obj);
-}
-
-static VALUE
-ossl_digest_s_hexdigest(VALUE klass, VALUE str, VALUE data)
-{
- VALUE obj = rb_class_new_instance(1, &str, klass);
+ if (NIL_P(str)) {
+ str = rb_str_new(NULL, EVP_MD_CTX_size(ctx));
+ } else {
+ StringValue(str);
+ rb_str_resize(str, EVP_MD_CTX_size(ctx));
+ }
- ossl_digest_update(obj, data);
+ EVP_DigestFinal_ex(ctx, RSTRING_PTR(str), NULL);
- return ossl_digest_hexdigest(obj);
+ return str;
}
+/*
+ * call-seq:
+ * digest.name -> string
+ *
+ */
static VALUE
-ossl_digest_equal(VALUE self, VALUE other)
+ossl_digest_name(VALUE self)
{
EVP_MD_CTX *ctx;
- VALUE str1, str2;
GetDigest(self, ctx);
- if (rb_obj_is_kind_of(other, cDigest) == Qtrue) {
- str2 = ossl_digest_digest(other);
- } else {
- StringValue(other);
- str2 = other;
- }
- if (RSTRING(str2)->len == EVP_MD_CTX_size(ctx)) {
- str1 = ossl_digest_digest(self);
- } else {
- str1 = ossl_digest_hexdigest(self);
- }
- if (RSTRING(str1)->len == RSTRING(str2)->len
- && rb_str_cmp(str1, str2) == 0) {
- return Qtrue;
- }
- return Qfalse;
+ return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
}
+/*
+ * call-seq:
+ * digest.digest_size -> integer
+ *
+ * Returns the output size of the digest.
+ */
static VALUE
-ossl_digest_name(VALUE self)
+ossl_digest_size(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
- return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
+ return INT2NUM(EVP_MD_CTX_size(ctx));
}
static VALUE
-ossl_digest_size(VALUE self)
+ossl_digest_block_length(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
- return INT2NUM(EVP_MD_CTX_size(ctx));
+ return INT2NUM(EVP_MD_CTX_block_size(ctx));
}
/*
@@ -263,31 +234,26 @@ ossl_digest_size(VALUE self)
void
Init_ossl_digest()
{
- mDigest = rb_define_module_under(mOSSL, "Digest");
-
- eDigestError = rb_define_class_under(mDigest, "DigestError", eOSSLError);
-
- cDigest = rb_define_class_under(mDigest, "Digest", rb_cObject);
+ rb_require("openssl");
+ rb_require("digest");
+
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
+ cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
+ eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError);
rb_define_alloc_func(cDigest, ossl_digest_alloc);
- rb_define_singleton_method(cDigest, "digest", ossl_digest_s_digest, 2);
- rb_define_singleton_method(cDigest, "hexdigest", ossl_digest_s_hexdigest, 2);
-
+
rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
- rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
-
rb_define_copy_func(cDigest, ossl_digest_copy);
-
- rb_define_method(cDigest, "digest", ossl_digest_digest, 0);
- rb_define_method(cDigest, "hexdigest", ossl_digest_hexdigest, 0);
- rb_define_alias(cDigest, "inspect", "hexdigest");
- rb_define_alias(cDigest, "to_s", "hexdigest");
-
+ rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
rb_define_method(cDigest, "update", ossl_digest_update, 1);
rb_define_alias(cDigest, "<<", "update");
-
- rb_define_method(cDigest, "==", ossl_digest_equal, 1);
-
+ rb_define_private_method(cDigest, "finish", ossl_digest_finish, -1);
+ rb_define_method(cDigest, "digest_length", ossl_digest_size, 0);
+ rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0);
+
rb_define_method(cDigest, "name", ossl_digest_name, 0);
- rb_define_method(cDigest, "size", ossl_digest_size, 0);
}
diff --git a/ext/openssl/ossl_digest.h b/ext/openssl/ossl_digest.h
index 8a1f7964f2..8cc5b1bc56 100644
--- a/ext/openssl/ossl_digest.h
+++ b/ext/openssl/ossl_digest.h
@@ -11,7 +11,6 @@
#if !defined(_OSSL_DIGEST_H_)
#define _OSSL_DIGEST_H_
-extern VALUE mDigest;
extern VALUE cDigest;
extern VALUE eDigestError;
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 91025941b9..cd835d1237 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -40,7 +40,7 @@ VALUE eEngineError;
*/
#define OSSL_ENGINE_LOAD_IF_MATCH(x) \
do{\
- if(!strcmp(#x, RSTRING(name)->ptr)){\
+ if(!strcmp(#x, RSTRING_PTR(name))){\
ENGINE_load_##x();\
return Qtrue;\
}\
@@ -55,9 +55,12 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
VALUE name;
rb_scan_args(argc, argv, "01", &name);
- if(NIL_P(name)) ENGINE_load_builtin_engines();
+ if(NIL_P(name)){
+ ENGINE_load_builtin_engines();
+ return Qtrue;
+ }
StringValue(name);
- OSSL_ENGINE_LOAD_IF_MATCH(openssl);
+#ifndef OPENSSL_NO_STATIC_ENGINE
OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
OSSL_ENGINE_LOAD_IF_MATCH(cswift);
OSSL_ENGINE_LOAD_IF_MATCH(chil);
@@ -67,10 +70,13 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
OSSL_ENGINE_LOAD_IF_MATCH(aep);
OSSL_ENGINE_LOAD_IF_MATCH(sureware);
OSSL_ENGINE_LOAD_IF_MATCH(4758cca);
+#endif
#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
#endif
- rb_raise(eEngineError, "no such engine `%s'", RSTRING(name)->ptr);
+ OSSL_ENGINE_LOAD_IF_MATCH(openssl);
+ rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name));
+ return Qnil;
#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
}
@@ -106,14 +112,15 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
StringValue(id);
ossl_engine_s_load(1, &id, klass);
- if(!(e = ENGINE_by_id(RSTRING(id)->ptr)))
+ if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
ossl_raise(eEngineError, NULL);
+ WrapEngine(klass, obj, e);
+ if(rb_block_given_p()) rb_yield(obj);
if(!ENGINE_init(e))
ossl_raise(eEngineError, NULL);
ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK,
0, NULL, (void(*)())ossl_pem_passwd_cb);
ERR_clear_error();
- WrapEngine(klass, obj, e);
return obj;
}
@@ -210,11 +217,11 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
{
ENGINE *e;
EVP_PKEY *pkey;
- VALUE id, data;
+ VALUE id, data, obj;
char *sid, *sdata;
- rb_scan_args(argc, argv, "11", &id, &data);
- sid = StringValuePtr(id);
+ rb_scan_args(argc, argv, "02", &id, &data);
+ sid = NIL_P(id) ? NULL : StringValuePtr(id);
sdata = NIL_P(data) ? NULL : StringValuePtr(data);
GetEngine(self, e);
#if OPENSSL_VERSION_NUMBER < 0x00907000L
@@ -223,8 +230,10 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
pkey = ENGINE_load_private_key(e, sid, NULL, sdata);
#endif
if (!pkey) ossl_raise(eEngineError, NULL);
+ obj = ossl_pkey_new(pkey);
+ OSSL_PKEY_SET_PRIVATE(obj);
- return ossl_pkey_new(pkey);
+ return obj;
}
static VALUE
@@ -235,8 +244,8 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
VALUE id, data;
char *sid, *sdata;
- rb_scan_args(argc, argv, "11", &id, &data);
- sid = StringValuePtr(id);
+ rb_scan_args(argc, argv, "02", &id, &data);
+ sid = NIL_P(id) ? NULL : StringValuePtr(id);
sdata = NIL_P(data) ? NULL : StringValuePtr(data);
GetEngine(self, e);
#if OPENSSL_VERSION_NUMBER < 0x00907000L
@@ -253,14 +262,67 @@ static VALUE
ossl_engine_set_default(VALUE self, VALUE flag)
{
ENGINE *e;
+ int f = NUM2INT(flag);
GetEngine(self, e);
- ENGINE_set_default(e, NUM2INT(flag));
+ ENGINE_set_default(e, f);
return Qtrue;
}
static VALUE
+ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
+{
+ ENGINE *e;
+ VALUE cmd, val;
+ int ret;
+
+ GetEngine(self, e);
+ rb_scan_args(argc, argv, "11", &cmd, &val);
+ StringValue(cmd);
+ if (!NIL_P(val)) StringValue(val);
+ ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd),
+ NIL_P(val) ? NULL : RSTRING_PTR(val), 0);
+ if (!ret) ossl_raise(eEngineError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_engine_cmd_flag_to_name(int flag)
+{
+ switch(flag){
+ case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC");
+ case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING");
+ case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT");
+ case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL");
+ default: return rb_str_new2("UNKNOWN");
+ }
+}
+
+static VALUE
+ossl_engine_get_cmds(VALUE self)
+{
+ ENGINE *e;
+ const ENGINE_CMD_DEFN *defn, *p;
+ VALUE ary, tmp;
+
+ GetEngine(self, e);
+ ary = rb_ary_new();
+ if ((defn = ENGINE_get_cmd_defns(e)) != NULL){
+ for (p = defn; p->cmd_num > 0; p++){
+ tmp = rb_ary_new();
+ rb_ary_push(tmp, rb_str_new2(p->cmd_name));
+ rb_ary_push(tmp, rb_str_new2(p->cmd_desc));
+ rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags));
+ rb_ary_push(ary, tmp);
+ }
+ }
+
+ return ary;
+}
+
+static VALUE
ossl_engine_inspect(VALUE self)
{
VALUE str;
@@ -300,6 +362,8 @@ Init_ossl_engine()
rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1);
rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1);
rb_define_method(cEngine, "set_default", ossl_engine_set_default, 1);
+ rb_define_method(cEngine, "ctrl_cmd", ossl_engine_ctrl_cmd, -1);
+ rb_define_method(cEngine, "cmds", ossl_engine_get_cmds, 0);
rb_define_method(cEngine, "inspect", ossl_engine_inspect, 0);
DefEngineConst(METHOD_RSA);
diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
index 0b4d8d9b54..ef77d6c427 100644
--- a/ext/openssl/ossl_hmac.c
+++ b/ext/openssl/ossl_hmac.c
@@ -41,8 +41,8 @@ VALUE eHMACError;
static void
ossl_hmac_free(HMAC_CTX *ctx)
{
- HMAC_CTX_cleanup(ctx);
- free(ctx);
+ HMAC_CTX_cleanup(ctx);
+ free(ctx);
}
static VALUE
@@ -52,19 +52,26 @@ ossl_hmac_alloc(VALUE klass)
VALUE obj;
MakeHMAC(obj, klass, ctx);
+ HMAC_CTX_init(ctx);
return obj;
}
+
+/*
+ * call-seq:
+ * HMAC.new(key, digest) -> hmac
+ *
+ */
static VALUE
ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
{
HMAC_CTX *ctx;
- GetHMAC(self, ctx);
StringValue(key);
- HMAC_CTX_init(ctx);
- HMAC_Init(ctx, RSTRING(key)->ptr, RSTRING(key)->len, GetDigestPtr(digest));
+ GetHMAC(self, ctx);
+ HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LEN(key),
+ GetDigestPtr(digest), NULL);
return self;
}
@@ -80,20 +87,23 @@ ossl_hmac_copy(VALUE self, VALUE other)
GetHMAC(self, ctx1);
SafeGetHMAC(other, ctx2);
- if (!HMAC_CTX_copy(ctx1, ctx2)) {
- ossl_raise(eHMACError, NULL);
- }
+ HMAC_CTX_copy(ctx1, ctx2);
return self;
}
+/*
+ * call-seq:
+ * hmac.update(string) -> self
+ *
+ */
static VALUE
ossl_hmac_update(VALUE self, VALUE data)
{
HMAC_CTX *ctx;
- GetHMAC(self, ctx);
StringValue(data);
- HMAC_Update(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ GetHMAC(self, ctx);
+ HMAC_Update(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
return self;
}
@@ -103,10 +113,9 @@ hmac_final(HMAC_CTX *ctx, char **buf, int *buf_len)
{
HMAC_CTX final;
- if (!HMAC_CTX_copy(&final, ctx)) {
- ossl_raise(eHMACError, NULL);
- }
+ HMAC_CTX_copy(&final, ctx);
if (!(*buf = OPENSSL_malloc(HMAC_size(&final)))) {
+ HMAC_CTX_cleanup(&final);
OSSL_Debug("Allocating %d mem", HMAC_size(&final));
ossl_raise(eHMACError, "Cannot allocate memory for hmac");
}
@@ -114,6 +123,11 @@ hmac_final(HMAC_CTX *ctx, char **buf, int *buf_len)
HMAC_CTX_cleanup(&final);
}
+/*
+ * call-seq:
+ * hmac.digest -> aString
+ *
+ */
static VALUE
ossl_hmac_digest(VALUE self)
{
@@ -129,6 +143,11 @@ ossl_hmac_digest(VALUE self)
return digest;
}
+/*
+ * call-seq:
+ * hmac.hexdigest -> aString
+ *
+ */
static VALUE
ossl_hmac_hexdigest(VALUE self)
{
@@ -149,6 +168,27 @@ ossl_hmac_hexdigest(VALUE self)
return hexdigest;
}
+/*
+ * call-seq:
+ * hmac.reset -> self
+ *
+ */
+static VALUE
+ossl_hmac_reset(VALUE self)
+{
+ HMAC_CTX *ctx;
+
+ GetHMAC(self, ctx);
+ HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * HMAC.digest(digest, key, data) -> aString
+ *
+ */
static VALUE
ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
{
@@ -157,12 +197,17 @@ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
StringValue(key);
StringValue(data);
- buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
- RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
+ buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LEN(key),
+ RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
return rb_str_new(buf, buf_len);
}
+/*
+ * call-seq:
+ * HMAC.digest(digest, key, data) -> aString
+ *
+ */
static VALUE
ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
{
@@ -173,8 +218,8 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
StringValue(key);
StringValue(data);
- buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
- RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
+ buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LEN(key),
+ RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
ossl_raise(eHMACError, "Cannot convert buf to hexbuf");
}
@@ -189,6 +234,10 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
void
Init_ossl_hmac()
{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);
@@ -200,6 +249,7 @@ Init_ossl_hmac()
rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
rb_define_copy_func(cHMAC, ossl_hmac_copy);
+ rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0);
rb_define_method(cHMAC, "update", ossl_hmac_update, 1);
rb_define_alias(cHMAC, "<<", "update");
rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0);
diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c
index 9aed773edc..738a203d93 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -56,20 +56,46 @@ ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
{
NETSCAPE_SPKI *spki;
VALUE buffer;
+ unsigned char *p;
if (rb_scan_args(argc, argv, "01", &buffer) == 0) {
return self;
}
- if (!(spki = NETSCAPE_SPKI_b64_decode(StringValuePtr(buffer), -1))) {
- ossl_raise(eSPKIError, NULL);
+ StringValue(buffer);
+ if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), -1))) {
+ p = RSTRING_PTR(buffer);
+ if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) {
+ ossl_raise(eSPKIError, NULL);
+ }
}
NETSCAPE_SPKI_free(DATA_PTR(self));
DATA_PTR(self) = spki;
+ ERR_clear_error();
return self;
}
static VALUE
+ossl_spki_to_der(VALUE self)
+{
+ NETSCAPE_SPKI *spki;
+ VALUE str;
+ long len;
+ unsigned char *p;
+
+ GetSPKI(self, spki);
+ if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0)
+ ossl_raise(eX509CertError, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING_PTR(str);
+ if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
+ ossl_raise(eX509CertError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+static VALUE
ossl_spki_to_pem(VALUE self)
{
NETSCAPE_SPKI *spki;
@@ -143,7 +169,7 @@ ossl_spki_get_challenge(VALUE self)
GetSPKI(self, spki);
if (spki->spkac->challenge->length <= 0) {
OSSL_Debug("Challenge.length <= 0?");
- return rb_str_new2(NULL);
+ return rb_str_new(0, 0);
}
return rb_str_new(spki->spkac->challenge->data,
@@ -155,10 +181,10 @@ ossl_spki_set_challenge(VALUE self, VALUE str)
{
NETSCAPE_SPKI *spki;
- GetSPKI(self, spki);
StringValue(str);
- if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING(str)->ptr,
- RSTRING(str)->len)) {
+ GetSPKI(self, spki);
+ if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str),
+ RSTRING_LEN(str))) {
ossl_raise(eSPKIError, NULL);
}
@@ -172,9 +198,9 @@ ossl_spki_sign(VALUE self, VALUE key, VALUE digest)
EVP_PKEY *pkey;
const EVP_MD *md;
- GetSPKI(self, spki);
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
md = GetDigestPtr(digest);
+ GetSPKI(self, spki);
if (!NETSCAPE_SPKI_sign(spki, pkey, md)) {
ossl_raise(eSPKIError, NULL);
}
@@ -217,6 +243,7 @@ Init_ossl_ns_spki()
rb_define_alloc_func(cSPKI, ossl_spki_alloc);
rb_define_method(cSPKI, "initialize", ossl_spki_initialize, -1);
+ rb_define_method(cSPKI, "to_der", ossl_spki_to_der, 0);
rb_define_method(cSPKI, "to_pem", ossl_spki_to_pem, 0);
rb_define_alias(cSPKI, "to_s", "to_pem");
rb_define_method(cSPKI, "to_text", ossl_spki_print, 0);
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index d1f1b84127..1e8e5903bd 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -109,9 +109,9 @@ ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
if(!NIL_P(arg)){
arg = ossl_to_der_if_possible(arg);
StringValue(arg);
- p = (unsigned char*)RSTRING(arg)->ptr;
+ p = (unsigned char*)RSTRING_PTR(arg);
if(!d2i_OCSP_REQUEST((OCSP_REQUEST**)&DATA_PTR(self), &p,
- RSTRING(arg)->len)){
+ RSTRING_LEN(arg))){
ossl_raise(eOCSPError, "cannot load DER encoded request");
}
}
@@ -127,12 +127,14 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
int ret;
rb_scan_args(argc, argv, "01", &val);
- GetOCSPReq(self, req);
- if(NIL_P(val))
+ if(NIL_P(val)) {
+ GetOCSPReq(self, req);
ret = OCSP_request_add1_nonce(req, NULL, -1);
+ }
else{
StringValue(val);
- ret = OCSP_request_add1_nonce(req, RSTRING(val)->ptr, RSTRING(val)->len);
+ GetOCSPReq(self, req);
+ ret = OCSP_request_add1_nonce(req, RSTRING_PTR(val), RSTRING_LEN(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -214,7 +216,6 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
int ret;
rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags);
- GetOCSPReq(self, req);
signer = GetX509CertPtr(signer_cert);
key = GetPrivPKeyPtr(signer_key);
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
@@ -223,6 +224,7 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
flags |= OCSP_NOCERTS;
}
else x509s = ossl_x509_ary2sk(certs);
+ GetOCSPReq(self, req);
ret = OCSP_request_sign(req, signer, key, EVP_sha1(), x509s, flg);
sk_X509_pop_free(x509s, X509_free);
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -240,10 +242,10 @@ ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
int flg, result;
rb_scan_args(argc, argv, "21", &certs, &store, &flags);
- GetOCSPReq(self, req);
x509st = GetX509StorePtr(store);
flg = NIL_P(flags) ? 0 : INT2NUM(flags);
x509s = ossl_x509_ary2sk(certs);
+ GetOCSPReq(self, req);
result = OCSP_request_verify(req, x509s, x509st, flg);
sk_X509_pop_free(x509s, X509_free);
if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL));
@@ -260,11 +262,10 @@ ossl_ocspreq_to_der(VALUE self)
long len;
GetOCSPReq(self, req);
-
if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0)
ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_OCSP_REQUEST(req, &p) <= 0)
ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
@@ -281,10 +282,11 @@ ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp)
OCSP_BASICRESP *bs;
OCSP_RESPONSE *res;
VALUE obj;
+ int st = NUM2INT(status);
if(NIL_P(basic_resp)) bs = NULL;
else GetOCSPBasicRes(basic_resp, bs); /* NO NEED TO DUP */
- if(!(res = OCSP_response_create(NUM2INT(status), bs)))
+ if(!(res = OCSP_response_create(st, bs)))
ossl_raise(eOCSPError, NULL);
WrapOCSPRes(klass, obj, res);
@@ -314,9 +316,9 @@ ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
if(!NIL_P(arg)){
arg = ossl_to_der_if_possible(arg);
StringValue(arg);
- p = RSTRING(arg)->ptr;
+ p = RSTRING_PTR(arg);
if(!d2i_OCSP_RESPONSE((OCSP_RESPONSE**)&DATA_PTR(self), &p,
- RSTRING(arg)->len)){
+ RSTRING_LEN(arg))){
ossl_raise(eOCSPError, "cannot load DER encoded response");
}
}
@@ -375,7 +377,7 @@ ossl_ocspres_to_der(VALUE self)
if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0)
ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_OCSP_RESPONSE(res, NULL) <= 0)
ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
@@ -426,13 +428,15 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
VALUE val;
int ret;
- GetOCSPBasicRes(self, bs);
rb_scan_args(argc, argv, "01", &val);
- if(NIL_P(val))
+ if(NIL_P(val)) {
+ GetOCSPBasicRes(self, bs);
ret = OCSP_basic_add1_nonce(bs, NULL, -1);
+ }
else{
StringValue(val);
- ret = OCSP_basic_add1_nonce(bs, RSTRING(val)->ptr, RSTRING(val)->len);
+ GetOCSPBasicRes(self, bs);
+ ret = OCSP_basic_add1_nonce(bs, RSTRING_PTR(val), RSTRING_LEN(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -452,15 +456,13 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
int error, i, rstatus = 0;
VALUE tmp;
- GetOCSPBasicRes(self, bs);
- SafeGetOCSPCertId(cid, id);
st = NUM2INT(status);
rsn = NIL_P(status) ? 0 : NUM2INT(reason);
if(!NIL_P(ext)){
/* All ary's members should be X509Extension */
Check_Type(ext, T_ARRAY);
- for (i = 0; i < RARRAY(ext)->len; i++)
- OSSL_Check_Kind(RARRAY(ext)->ptr[i], cX509Ext);
+ for (i = 0; i < RARRAY_LEN(ext); i++)
+ OSSL_Check_Kind(RARRAY_PTR(ext)[i], cX509Ext);
}
error = 0;
@@ -477,6 +479,8 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
if(rstatus) goto err;
nxt = X509_gmtime_adj(NULL, NUM2INT(tmp));
+ GetOCSPBasicRes(self, bs);
+ SafeGetOCSPCertId(cid, id);
if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){
error = 1;
goto err;
@@ -486,8 +490,8 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
X509_EXTENSION *x509ext;
sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free);
single->singleExtensions = NULL;
- for(i = 0; i < RARRAY(ext)->len; i++){
- x509ext = DupX509ExtPtr(RARRAY(ext)->ptr[i]);
+ for(i = 0; i < RARRAY_LEN(ext); i++){
+ x509ext = DupX509ExtPtr(RARRAY_PTR(ext)[i]);
if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
X509_EXTENSION_free(x509ext);
error = 1;
@@ -564,7 +568,6 @@ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
int ret;
rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags);
- GetOCSPBasicRes(self, bs);
signer = GetX509CertPtr(signer_cert);
key = GetPrivPKeyPtr(signer_key);
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
@@ -575,6 +578,7 @@ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
else{
x509s = ossl_x509_ary2sk(certs);
}
+ GetOCSPBasicRes(self, bs);
ret = OCSP_basic_sign(bs, signer, key, EVP_sha1(), x509s, flg);
sk_X509_pop_free(x509s, X509_free);
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -592,10 +596,10 @@ ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
int flg, result;
rb_scan_args(argc, argv, "21", &certs, &store, &flags);
- GetOCSPBasicRes(self, bs);
x509st = GetX509StorePtr(store);
flg = NIL_P(flags) ? 0 : INT2NUM(flags);
x509s = ossl_x509_ary2sk(certs);
+ GetOCSPBasicRes(self, bs);
result = OCSP_basic_verify(bs, x509s, x509st, flg);
sk_X509_pop_free(x509s, X509_free);
if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL));
@@ -625,11 +629,11 @@ ossl_ocspcid_initialize(VALUE self, VALUE subject, VALUE issuer)
OCSP_CERTID *id, *newid;
X509 *x509s, *x509i;
- GetOCSPCertId(self, id);
x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */
x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */
if(!(newid = OCSP_cert_to_id(NULL, x509s, x509i)))
ossl_raise(eOCSPError, NULL);
+ GetOCSPCertId(self, id);
OCSP_CERTID_free(id);
RDATA(self)->data = newid;
@@ -677,7 +681,7 @@ Init_ossl_ocsp()
{
mOCSP = rb_define_module_under(mOSSL, "OCSP");
- eOCSPError = rb_define_class_under(mOCSP, "OCSPError", rb_cObject);
+ eOCSPError = rb_define_class_under(mOCSP, "OCSPError", eOSSLError);
cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject);
rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc);
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
new file mode 100644
index 0000000000..2ec69ba8db
--- /dev/null
+++ b/ext/openssl/ossl_pkcs12.c
@@ -0,0 +1,210 @@
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ * $Id$
+ */
+#include "ossl.h"
+
+#define WrapPKCS12(klass, obj, p12) do { \
+ if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
+ obj = Data_Wrap_Struct(klass, 0, PKCS12_free, p12); \
+} while (0)
+
+#define GetPKCS12(obj, p12) do { \
+ Data_Get_Struct(obj, PKCS12, p12); \
+ if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
+} while (0)
+
+#define SafeGetPKCS12(obj, p12) do { \
+ OSSL_Check_Kind(obj, cPKCS12); \
+ GetPKCS12(obj, p12); \
+} while (0)
+
+#define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v))
+#define ossl_pkcs12_set_cert(o,v) rb_iv_set((o), "@certificate", (v))
+#define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v))
+#define ossl_pkcs12_get_key(o) rb_iv_get((o), "@key")
+#define ossl_pkcs12_get_cert(o) rb_iv_get((o), "@certificate")
+#define ossl_pkcs12_get_ca_certs(o) rb_iv_get((o), "@ca_certs")
+
+/*
+ * Classes
+ */
+VALUE cPKCS12;
+VALUE ePKCS12Error;
+
+/*
+ * Private
+ */
+static VALUE
+ossl_pkcs12_s_allocate(VALUE klass)
+{
+ PKCS12 *p12;
+ VALUE obj;
+
+ if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL);
+ WrapPKCS12(klass, obj, p12);
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
+ *
+ * === Parameters
+ * * +pass+ - string
+ * * +name+ - A string describing the key.
+ * * +key+ - Any PKey.
+ * * +cert+ - A X509::Certificate.
+ * * * The public_key portion of the certificate must contain a valid public key.
+ * * * The not_before and not_after fields must be filled in.
+ * * +ca+ - An optional array of X509::Certificate's.
+ * * +key_pbe+ - string
+ * * +cert_pbe+ - string
+ * * +key_iter+ - integer
+ * * +mac_iter+ - integer
+ * * +keytype+ - An integer representing an MSIE specific extension.
+ *
+ * Any optional arguments may be supplied as nil to preserve the OpenSSL defaults.
+ *
+ * See the OpenSSL documentation for PKCS12_create().
+ */
+static VALUE
+ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
+{
+ VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype;
+ VALUE obj;
+ char *passphrase, *friendlyname;
+ EVP_PKEY *key;
+ X509 *x509;
+ STACK_OF(X509) *x509s;
+ int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0;
+ PKCS12 *p12;
+
+ rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
+ passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
+ friendlyname = NIL_P(name) ? NULL : StringValuePtr(name);
+ key = GetPKeyPtr(pkey);
+ x509 = GetX509CertPtr(cert);
+ x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
+/* TODO: make a VALUE to nid function */
+ if (!NIL_P(key_nid)) {
+ if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef)
+ rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid));
+ }
+ if (!NIL_P(cert_nid)) {
+ if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef)
+ rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid));
+ }
+ if (!NIL_P(key_iter))
+ kiter = NUM2INT(key_iter);
+ if (!NIL_P(mac_iter))
+ miter = NUM2INT(mac_iter);
+ if (!NIL_P(keytype))
+ ktype = NUM2INT(keytype);
+
+ p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
+ nkey, ncert, kiter, miter, ktype);
+ sk_X509_pop_free(x509s, X509_free);
+ if(!p12) ossl_raise(ePKCS12Error, NULL);
+ WrapPKCS12(cPKCS12, obj, p12);
+
+ ossl_pkcs12_set_key(obj, pkey);
+ ossl_pkcs12_set_cert(obj, cert);
+ ossl_pkcs12_set_ca_certs(obj, ca);
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * PKCS12.new -> pkcs12
+ * PKCS12.new(str) -> pkcs12
+ * PKCS12.new(str, pass) -> pkcs12
+ *
+ * === Parameters
+ * * +str+ - Must be a DER encoded PKCS12 string.
+ * * +pass+ - string
+ */
+static VALUE
+ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
+{
+ BIO *in;
+ VALUE arg, pass, pkey, cert, ca;
+ char *passphrase;
+ EVP_PKEY *key;
+ X509 *x509;
+ STACK_OF(X509) *x509s = NULL;
+ int st = 0;
+
+ if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
+ passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
+ in = ossl_obj2bio(arg);
+ d2i_PKCS12_bio(in, (PKCS12 **)&DATA_PTR(self));
+ BIO_free(in);
+
+ pkey = cert = ca = Qnil;
+ if(!PKCS12_parse((PKCS12*)DATA_PTR(self), passphrase, &key, &x509, &x509s))
+ ossl_raise(ePKCS12Error, "PKCS12_parse");
+ pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
+ &st); /* NO DUP */
+ if(st) goto err;
+ cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st);
+ if(st) goto err;
+ if(x509s){
+ ca =
+ rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st);
+ if(st) goto err;
+ }
+
+ err:
+ X509_free(x509);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_pkcs12_set_key(self, pkey);
+ ossl_pkcs12_set_cert(self, cert);
+ ossl_pkcs12_set_ca_certs(self, ca);
+ if(st) rb_jump_tag(st);
+
+ return self;
+}
+
+static VALUE
+ossl_pkcs12_to_der(VALUE self)
+{
+ PKCS12 *p12;
+ VALUE str;
+ long len;
+ unsigned char *p;
+
+ GetPKCS12(self, p12);
+ if((len = i2d_PKCS12(p12, NULL)) <= 0)
+ ossl_raise(ePKCS12Error, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING_PTR(str);
+ if(i2d_PKCS12(p12, &p) <= 0)
+ ossl_raise(ePKCS12Error, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+void
+Init_ossl_pkcs12()
+{
+ /*
+ * Defines a file format commonly used to store private keys with
+ * accompanying public key certificates, protected with a password-based
+ * symmetric key.
+ */
+ cPKCS12 = rb_define_class_under(mOSSL, "PKCS12", rb_cObject);
+ ePKCS12Error = rb_define_class_under(cPKCS12, "PKCS12Error", eOSSLError);
+ rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
+
+ rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
+ rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
+ rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse);
+ rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
+ rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
+ rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
+}
diff --git a/ext/openssl/ossl_pkcs12.h b/ext/openssl/ossl_pkcs12.h
new file mode 100644
index 0000000000..24d25d00bb
--- /dev/null
+++ b/ext/openssl/ossl_pkcs12.h
@@ -0,0 +1,15 @@
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ * $Id$
+ */
+#if !defined(_OSSL_PKCS12_H_)
+#define _OSSL_PKCS12_H_
+
+extern VALUE cPKCS12;
+extern VALUE ePKCS12Error;
+
+void Init_ossl_pkcs12(void);
+
+#endif /* _OSSL_PKCS12_H_ */
+
diff --git a/ext/openssl/ossl_pkcs5.c b/ext/openssl/ossl_pkcs5.c
new file mode 100644
index 0000000000..007889fc94
--- /dev/null
+++ b/ext/openssl/ossl_pkcs5.c
@@ -0,0 +1,96 @@
+/*
+ * $Id$
+ * Copyright (C) 2007 Technorama Ltd. <oss-ruby@technorama.net>
+ */
+#include "ossl.h"
+
+VALUE mPKCS5;
+VALUE ePKCS5;
+
+/*
+ * call-seq:
+ * PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string
+ *
+ * === Parameters
+ * * +pass+ - string
+ * * +salt+ - string
+ * * +iter+ - integer - should be greater than 1000. 2000 is better.
+ * * +keylen+ - integer
+ * * +digest+ - a string or OpenSSL::Digest object.
+ *
+ * Available in OpenSSL 0.9.9?.
+ *
+ * Digests other than SHA1 may not be supported by other cryptography libraries.
+ */
+static VALUE
+ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen, VALUE digest)
+{
+#ifdef HAVE_PKCS5_PBKDF2_HMAC
+ VALUE str;
+ const EVP_MD *md;
+ int len = NUM2INT(keylen);
+
+ StringValue(pass);
+ StringValue(salt);
+ md = GetDigestPtr(digest);
+
+ str = rb_str_new(0, len);
+
+ if (PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LEN(pass), RSTRING_PTR(salt), RSTRING_LEN(salt), NUM2INT(iter), md, len, RSTRING_PTR(str)) != 1)
+ ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC");
+
+ return str;
+#else
+ rb_notimplement();
+#endif
+}
+
+
+/*
+ * call-seq:
+ * PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string
+ *
+ * === Parameters
+ * * +pass+ - string
+ * * +salt+ - string
+ * * +iter+ - integer - should be greater than 1000. 2000 is better.
+ * * +keylen+ - integer
+ *
+ * This method is available almost any version OpenSSL.
+ *
+ * Conforms to rfc2898.
+ */
+static VALUE
+ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen)
+{
+#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
+ VALUE str;
+ int len = NUM2INT(keylen);
+
+ StringValue(pass);
+ StringValue(salt);
+
+ str = rb_str_new(0, len);
+
+ if (PKCS5_PBKDF2_HMAC_SHA1(RSTRING_PTR(pass), RSTRING_LEN(pass), RSTRING_PTR(salt), RSTRING_LEN(salt), NUM2INT(iter), len, RSTRING_PTR(str)) != 1)
+ ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC_SHA1");
+
+ return str;
+#else
+ rb_notimplement();
+#endif
+}
+
+void
+Init_ossl_pkcs5()
+{
+ /*
+ * Password-based Encryption
+ *
+ */
+ mPKCS5 = rb_define_module_under(mOSSL, "PKCS5");
+ ePKCS5 = rb_define_class_under(mPKCS5, "PKCS5Error", eOSSLError);
+
+ rb_define_module_function(mPKCS5, "pbkdf2_hmac", ossl_pkcs5_pbkdf2_hmac, 5);
+ rb_define_module_function(mPKCS5, "pbkdf2_hmac_sha1", ossl_pkcs5_pbkdf2_hmac_sha1, 4);
+}
diff --git a/ext/openssl/ossl_pkcs5.h b/ext/openssl/ossl_pkcs5.h
new file mode 100644
index 0000000000..a3b132bc50
--- /dev/null
+++ b/ext/openssl/ossl_pkcs5.h
@@ -0,0 +1,6 @@
+#if !defined(_OSSL_PKCS5_H_)
+#define _OSSL_PKCS5_H_
+
+void Init_ossl_pkcs5(void);
+
+#endif /* _OSSL_PKCS5_H_ */
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index aaa12ac7d7..6918844779 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -44,6 +44,23 @@
GetPKCS7si(obj, p7si); \
} while (0)
+#define WrapPKCS7ri(klass, obj, p7ri) do { \
+ if (!p7ri) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, PKCS7_RECIP_INFO_free, p7ri); \
+} while (0)
+#define GetPKCS7ri(obj, p7ri) do { \
+ Data_Get_Struct(obj, PKCS7_RECIP_INFO, p7ri); \
+ if (!p7ri) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+ } \
+} while (0)
+#define SafeGetPKCS7ri(obj, p7ri) do { \
+ OSSL_Check_Kind(obj, cPKCS7Recipient); \
+ GetPKCS7ri(obj, p7ri); \
+} while (0)
+
#define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
#define ossl_pkcs7_set_data(o,v) rb_iv_set((o), "@data", (v))
@@ -54,9 +71,9 @@
/*
* Classes
*/
-VALUE mPKCS7;
VALUE cPKCS7;
VALUE cPKCS7Signer;
+VALUE cPKCS7Recipient;
VALUE ePKCS7Error;
/*
@@ -89,8 +106,35 @@ DupPKCS7SignerPtr(VALUE obj)
return pkcs7;
}
+static VALUE
+ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
+{
+ PKCS7_RECIP_INFO *pkcs7;
+ VALUE obj;
+
+ pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
+ if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
+ WrapPKCS7ri(cPKCS7Recipient, obj, pkcs7);
+
+ return obj;
+}
+
+static PKCS7_RECIP_INFO *
+DupPKCS7RecipientPtr(VALUE obj)
+{
+ PKCS7_RECIP_INFO *p7ri, *pkcs7;
+
+ SafeGetPKCS7ri(obj, p7ri);
+ if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ return pkcs7;
+}
+
/*
- * Private
+ * call-seq:
+ * PKCS7.read_smime(string) => pkcs7
*/
static VALUE
ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
@@ -112,6 +156,10 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
return ret;
}
+/*
+ * call-seq:
+ * PKCS7.write_smime(pkcs7 [, data [, flags]]) => string
+ */
static VALUE
ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
{
@@ -122,9 +170,9 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
int flg;
rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags);
- SafeGetPKCS7(pkcs7, p7);
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7);
+ SafeGetPKCS7(pkcs7, p7);
if(!NIL_P(data) && PKCS7_is_detached(p7))
flg |= PKCS7_DETACHED;
in = NIL_P(data) ? NULL : ossl_obj2bio(data);
@@ -143,6 +191,10 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
return str;
}
+/*
+ * call-seq:
+ * PKCS7.sign(cert, key, data, [, certs [, flags]]) => pkcs7
+ */
static VALUE
ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
{
@@ -182,6 +234,10 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
return ret;
}
+/*
+ * call-seq:
+ * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7
+ */
static VALUE
ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
{
@@ -243,6 +299,13 @@ ossl_pkcs7_alloc(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * PKCS7.new => pkcs7
+ * PKCS7.new(string) => pkcs7
+ *
+ * Many methods in this class aren't documented.
+ */
static VALUE
ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -291,7 +354,7 @@ static int
ossl_pkcs7_sym2typeid(VALUE sym)
{
int i, ret = Qnil;
- char *s;
+ const char *s;
static struct {
const char *name;
@@ -320,6 +383,10 @@ ossl_pkcs7_sym2typeid(VALUE sym)
return ret;
}
+/*
+ * call-seq:
+ * pkcs7.type = type => type
+ */
static VALUE
ossl_pkcs7_set_type(VALUE self, VALUE type)
{
@@ -332,6 +399,10 @@ ossl_pkcs7_set_type(VALUE self, VALUE type)
return type;
}
+/*
+ * call-seq:
+ * pkcs7.type => string or nil
+ */
static VALUE
ossl_pkcs7_get_type(VALUE self)
{
@@ -358,7 +429,7 @@ ossl_pkcs7_set_detached(VALUE self, VALUE flag)
GetPKCS7(self, p7);
if(flag != Qtrue && flag != Qfalse)
- ossl_raise(ePKCS7Error, "must secify a boolean");
+ ossl_raise(ePKCS7Error, "must specify a boolean");
if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0))
ossl_raise(ePKCS7Error, NULL);
@@ -400,8 +471,8 @@ ossl_pkcs7_add_signer(VALUE self, VALUE signer)
PKCS7 *pkcs7;
PKCS7_SIGNER_INFO *p7si;
- GetPKCS7(self, pkcs7);
p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */
+ GetPKCS7(self, pkcs7);
if (!PKCS7_add_signer(pkcs7, p7si)) {
PKCS7_SIGNER_INFO_free(p7si);
ossl_raise(ePKCS7Error, "Could not add signer.");
@@ -441,30 +512,50 @@ ossl_pkcs7_get_signer(VALUE self)
}
static VALUE
-ossl_pkcs7_add_recipient(VALUE self, VALUE cert)
+ossl_pkcs7_add_recipient(VALUE self, VALUE recip)
{
PKCS7 *pkcs7;
PKCS7_RECIP_INFO *ri;
- X509 *x509;
-
+
+ ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */
GetPKCS7(self, pkcs7);
- x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
- if (!(ri = PKCS7_RECIP_INFO_new())) {
- ossl_raise(ePKCS7Error, NULL);
- }
- if (!PKCS7_RECIP_INFO_set(ri, x509)) {
- PKCS7_RECIP_INFO_free(ri);
- ossl_raise(ePKCS7Error, NULL);
- }
if (!PKCS7_add_recipient_info(pkcs7, ri)) {
PKCS7_RECIP_INFO_free(ri);
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, "Could not add recipient.");
}
return self;
}
static VALUE
+ossl_pkcs7_get_recipient(VALUE self)
+{
+ PKCS7 *pkcs7;
+ STACK_OF(PKCS7_RECIP_INFO) *sk;
+ PKCS7_RECIP_INFO *si;
+ int num, i;
+ VALUE ary;
+
+ GetPKCS7(self, pkcs7);
+ if (PKCS7_type_is_enveloped(pkcs7))
+ sk = pkcs7->d.enveloped->recipientinfo;
+ else if (PKCS7_type_is_signedAndEnveloped(pkcs7))
+ sk = pkcs7->d.signed_and_enveloped->recipientinfo;
+ else sk = NULL;
+ if (!sk) return rb_ary_new();
+ if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) {
+ ossl_raise(ePKCS7Error, "Negative number of recipient!");
+ }
+ ary = rb_ary_new2(num);
+ for (i=0; i<num; i++) {
+ si = sk_PKCS7_RECIP_INFO_value(sk, i);
+ rb_ary_push(ary, ossl_pkcs7ri_new(si));
+ }
+
+ return ary;
+}
+
+static VALUE
ossl_pkcs7_add_certificate(VALUE self, VALUE cert)
{
PKCS7 *pkcs7;
@@ -519,7 +610,7 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
certs = pkcs7_get_certs_or_crls(self, 1);
while((cert = sk_X509_pop(certs))) X509_free(cert);
- rb_iterate(rb_each, ary, ossl_pkcs7_set_certs_i, self);
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);
return ary;
}
@@ -559,7 +650,7 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary)
crls = pkcs7_get_certs_or_crls(self, 0);
while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
- rb_iterate(rb_each, ary, ossl_pkcs7_set_crls_i, self);
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);
return ary;
}
@@ -582,9 +673,7 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
VALUE data;
const char *msg;
- GetPKCS7(self, p7);
rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags);
- x509st = GetX509StorePtr(store);
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self);
in = NIL_P(indata) ? NULL : ossl_obj2bio(indata);
@@ -596,6 +685,8 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
rb_jump_tag(status);
}
}
+ x509st = GetX509StorePtr(store);
+ GetPKCS7(self, p7);
if(!(out = BIO_new(BIO_s_mem()))){
BIO_free(in);
sk_X509_pop_free(x509s, X509_free);
@@ -603,8 +694,10 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
}
ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
BIO_free(in);
+ if (ok < 0) ossl_raise(ePKCS7Error, NULL);
msg = ERR_reason_error_string(ERR_get_error());
ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
+ ERR_clear_error();
data = ossl_membio2str(out);
ossl_pkcs7_set_data(self, data);
sk_X509_pop_free(x509s, X509_free);
@@ -624,10 +717,10 @@ ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self)
VALUE str;
rb_scan_args(argc, argv, "21", &pkey, &cert, &flags);
- GetPKCS7(self, p7);
key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */
x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
+ GetPKCS7(self, p7);
if(!(out = BIO_new(BIO_s_mem())))
ossl_raise(ePKCS7Error, NULL);
if(!PKCS7_decrypt(p7, key, x509, out, flg)){
@@ -647,13 +740,12 @@ ossl_pkcs7_add_data(VALUE self, VALUE data)
char buf[4096];
int len;
- in = out = NULL;
+ in = ossl_obj2bio(data);
GetPKCS7(self, pkcs7);
if(PKCS7_type_is_signed(pkcs7)){
if(!PKCS7_content_new(pkcs7, NID_pkcs7_data))
ossl_raise(ePKCS7Error, NULL);
}
- in = ossl_obj2bio(data);
if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
for(;;){
if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
@@ -686,7 +778,7 @@ ossl_pkcs7_to_der(VALUE self)
if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
ossl_raise(ePKCS7Error, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_PKCS7(pkcs7, &p) <= 0)
ossl_raise(ePKCS7Error, NULL);
ossl_str_adjust(str, p);
@@ -739,10 +831,10 @@ ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest)
X509 *x509;
const EVP_MD *md;
- GetPKCS7si(self, p7si);
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
md = GetDigestPtr(digest);
+ GetPKCS7si(self, p7si);
if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) {
ossl_raise(ePKCS7Error, NULL);
}
@@ -751,7 +843,7 @@ ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest)
}
static VALUE
-ossl_pkcs7si_get_name(VALUE self)
+ossl_pkcs7si_get_issuer(VALUE self)
{
PKCS7_SIGNER_INFO *p7si;
@@ -794,20 +886,79 @@ ossl_pkcs7si_get_signed_time(VALUE self)
}
/*
+ * RECIPIENT INFO
+ */
+static VALUE
+ossl_pkcs7ri_alloc(VALUE klass)
+{
+ PKCS7_RECIP_INFO *p7ri;
+ VALUE obj;
+
+ if (!(p7ri = PKCS7_RECIP_INFO_new())) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ WrapPKCS7ri(klass, obj, p7ri);
+
+ return obj;
+}
+
+static VALUE
+ossl_pkcs7ri_initialize(VALUE self, VALUE cert)
+{
+ PKCS7_RECIP_INFO *p7ri;
+ X509 *x509;
+
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
+ GetPKCS7ri(self, p7ri);
+ if (!PKCS7_RECIP_INFO_set(p7ri, x509)) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_pkcs7ri_get_issuer(VALUE self)
+{
+ PKCS7_RECIP_INFO *p7ri;
+
+ GetPKCS7ri(self, p7ri);
+
+ return ossl_x509name_new(p7ri->issuer_and_serial->issuer);
+}
+
+static VALUE
+ossl_pkcs7ri_get_serial(VALUE self)
+{
+ PKCS7_RECIP_INFO *p7ri;
+
+ GetPKCS7ri(self, p7ri);
+
+ return asn1integer_to_num(p7ri->issuer_and_serial->serial);
+}
+
+static VALUE
+ossl_pkcs7ri_get_enc_key(VALUE self)
+{
+ PKCS7_RECIP_INFO *p7ri;
+
+ GetPKCS7ri(self, p7ri);
+
+ return asn1str_to_str(p7ri->enc_key);
+}
+
+/*
* INIT
*/
void
Init_ossl_pkcs7()
{
- mPKCS7 = rb_define_module_under(mOSSL, "PKCS7");
-
- ePKCS7Error = rb_define_class_under(mPKCS7, "PKCS7Error", eOSSLError);
-
- cPKCS7 = rb_define_class_under(mPKCS7, "PKCS7", rb_cObject);
- rb_define_singleton_method(mPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
- rb_define_singleton_method(mPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
- rb_define_singleton_method(mPKCS7, "sign", ossl_pkcs7_s_sign, -1);
- rb_define_singleton_method(mPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
+ cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject);
+ ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError);
+ rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
+ rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
+ rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1);
+ rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse);
rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse);
rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc);
@@ -822,6 +973,7 @@ Init_ossl_pkcs7()
rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1);
rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0);
rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1);
+ rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0);
rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1);
rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1);
rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0);
@@ -836,14 +988,23 @@ Init_ossl_pkcs7()
rb_define_alias(cPKCS7, "to_s", "to_pem");
rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
- cPKCS7Signer = rb_define_class_under(mPKCS7, "Signer", rb_cObject);
+ cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject);
+ rb_define_const(cPKCS7, "Signer", cPKCS7Signer);
rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc);
rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3);
- rb_define_method(cPKCS7Signer, "name", ossl_pkcs7si_get_name,0);
+ rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0);
+ rb_define_alias(cPKCS7Signer, "name", "issuer");
rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
- rb_define_method(cPKCS7Signer, "signed_time", ossl_pkcs7si_get_signed_time,0);
+ rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
+
+ cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject);
+ rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc);
+ rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
+ rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0);
+ rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0);
+ rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
-#define DefPKCS7Const(x) rb_define_const(mPKCS7, #x, INT2NUM(PKCS7_##x))
+#define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x))
DefPKCS7Const(TEXT);
DefPKCS7Const(NOCERTS);
diff --git a/ext/openssl/ossl_pkcs7.h b/ext/openssl/ossl_pkcs7.h
index 9378397f25..371c421103 100644
--- a/ext/openssl/ossl_pkcs7.h
+++ b/ext/openssl/ossl_pkcs7.h
@@ -11,9 +11,9 @@
#if !defined(_OSSL_PKCS7_H_)
#define _OSSL_PKCS7_H_
-extern VALUE mPKCS7;
extern VALUE cPKCS7;
-extern VALUE cPKCS7SignerInfo;
+extern VALUE cPKCS7Signer;
+extern VALUE cPKCS7Recipient;
extern VALUE ePKCS7Error;
void Init_ossl_pkcs7(void);
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index dcae075ee8..b295cfc25e 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -55,6 +55,10 @@ ossl_pkey_new(EVP_PKEY *pkey)
case EVP_PKEY_DH:
return ossl_dh_new(pkey);
#endif
+#if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
+ case EVP_PKEY_EC:
+ return ossl_ec_new(pkey);
+#endif
default:
ossl_raise(ePKeyError, "unsupported key type");
}
@@ -68,7 +72,7 @@ ossl_pkey_new_from_file(VALUE filename)
EVP_PKEY *pkey;
SafeStringValue(filename);
- if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
+ if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
ossl_raise(ePKeyError, "%s", strerror(errno));
}
@@ -96,23 +100,34 @@ GetPrivPKeyPtr(VALUE obj)
{
EVP_PKEY *pkey;
- SafeGetPKey(obj, pkey);
- if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) { /* returns Qtrue */
+ if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
ossl_raise(rb_eArgError, "Private key is needed.");
}
+ SafeGetPKey(obj, pkey);
return pkey;
}
EVP_PKEY *
-DupPrivPKeyPtr(VALUE obj)
+DupPKeyPtr(VALUE obj)
{
EVP_PKEY *pkey;
SafeGetPKey(obj, pkey);
- if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) { /* returns Qtrue */
+ CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+
+ return pkey;
+}
+
+EVP_PKEY *
+DupPrivPKeyPtr(VALUE obj)
+{
+ EVP_PKEY *pkey;
+
+ if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
ossl_raise(rb_eArgError, "Private key is needed.");
}
+ SafeGetPKey(obj, pkey);
CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
return pkey;
@@ -145,26 +160,6 @@ ossl_pkey_initialize(VALUE self)
}
static VALUE
-ossl_pkey_to_der(VALUE self)
-{
- EVP_PKEY *pkey;
- VALUE str;
- long len;
- unsigned char *p;
-
- GetPKey(self, pkey);
- if((len = i2d_PUBKEY(pkey, NULL)) <= 0)
- ossl_raise(ePKeyError, NULL);
- str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
- if(len = i2d_PUBKEY(pkey, &p) <= 0)
- ossl_raise(ePKeyError, NULL);
- ossl_str_adjust(str, p);
-
- return str;
-}
-
-static VALUE
ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
{
EVP_PKEY *pkey;
@@ -172,19 +167,18 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
int buf_len;
VALUE str;
- GetPKey(self, pkey);
if (rb_funcall(self, id_private_q, 0, NULL) != Qtrue) {
ossl_raise(rb_eArgError, "Private key is needed.");
}
+ GetPKey(self, pkey);
EVP_SignInit(&ctx, GetDigestPtr(digest));
StringValue(data);
- EVP_SignUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ EVP_SignUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
- if (!EVP_SignFinal(&ctx, RSTRING(str)->ptr, &buf_len, pkey))
+ if (!EVP_SignFinal(&ctx, RSTRING_PTR(str), &buf_len, pkey))
ossl_raise(ePKeyError, NULL);
- assert(buf_len <= RSTRING(str)->len);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ assert(buf_len <= RSTRING_LEN(str));
+ rb_str_set_len(str, buf_len);
return str;
}
@@ -199,8 +193,8 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
EVP_VerifyInit(&ctx, GetDigestPtr(digest));
StringValue(sig);
StringValue(data);
- EVP_VerifyUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
- switch (EVP_VerifyFinal(&ctx, RSTRING(sig)->ptr, RSTRING(sig)->len, pkey)) {
+ EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
+ switch (EVP_VerifyFinal(&ctx, RSTRING_PTR(sig), RSTRING_LEN(sig), pkey)) {
case 0:
return Qfalse;
case 1:
@@ -217,6 +211,10 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
void
Init_ossl_pkey()
{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
mPKey = rb_define_module_under(mOSSL, "PKey");
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
@@ -226,17 +224,17 @@ Init_ossl_pkey()
rb_define_alloc_func(cPKey, ossl_pkey_alloc);
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
- rb_define_method(cPKey, "to_der", ossl_pkey_to_der, 0);
rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);
id_private_q = rb_intern("private?");
/*
- * INIT rsa, dsa
+ * INIT rsa, dsa, dh, ec
*/
Init_ossl_rsa();
Init_ossl_dsa();
Init_ossl_dh();
+ Init_ossl_ec();
}
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 189573546e..67ff1fddd0 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -16,11 +16,16 @@ extern VALUE cPKey;
extern VALUE ePKeyError;
extern ID id_private_q;
+#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
+#define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse)
+#define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue)
+
#define WrapPKey(klass, obj, pkey) do { \
if (!pkey) { \
rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \
} \
obj = Data_Wrap_Struct(klass, 0, EVP_PKEY_free, pkey); \
+ OSSL_PKEY_SET_PUBLIC(obj); \
} while (0)
#define GetPKey(obj, pkey) do {\
Data_Get_Struct(obj, EVP_PKEY, pkey);\
@@ -38,7 +43,7 @@ void ossl_generate_cb(int, int, void *);
VALUE ossl_pkey_new(EVP_PKEY *);
VALUE ossl_pkey_new_from_file(VALUE);
EVP_PKEY *GetPKeyPtr(VALUE);
-/*EVP_PKEY *DupPKeyPtr(VALUE);*/
+EVP_PKEY *DupPKeyPtr(VALUE);
EVP_PKEY *GetPrivPKeyPtr(VALUE);
EVP_PKEY *DupPrivPKeyPtr(VALUE);
void Init_ossl_pkey(void);
@@ -66,11 +71,30 @@ void Init_ossl_dsa(void);
*/
extern VALUE cDH;
extern VALUE eDHError;
+extern DH *OSSL_DEFAULT_DH_512;
+extern DH *OSSL_DEFAULT_DH_1024;
VALUE ossl_dh_new(EVP_PKEY *);
void Init_ossl_dh(void);
+/*
+ * EC
+ */
+extern VALUE cEC;
+extern VALUE eECError;
+extern VALUE cEC_GROUP;
+extern VALUE eEC_GROUP;
+extern VALUE cEC_POINT;
+extern VALUE eEC_POINT;
+VALUE ossl_ec_new(EVP_PKEY *);
+void Init_ossl_ec(void);
+
+
#define OSSL_PKEY_BN(keytype, name) \
+/* \
+ * call-seq: \
+ * key.##name -> aBN \
+ */ \
static VALUE ossl_##keytype##_get_##name(VALUE self) \
{ \
EVP_PKEY *pkey; \
@@ -82,6 +106,10 @@ static VALUE ossl_##keytype##_get_##name(VALUE self) \
return Qnil; \
return ossl_bn_new(bn); \
} \
+/* \
+ * call-seq: \
+ * key.##name = bn -> bn \
+ */ \
static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \
{ \
EVP_PKEY *pkey; \
@@ -104,10 +132,10 @@ static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \
return bignum; \
}
-#define DEF_OSSL_PKEY_BN(class, keytype, name) \
-do { \
+#define DEF_OSSL_PKEY_BN(class, keytype, name) \
+do { \
rb_define_method(class, #name, ossl_##keytype##_get_##name, 0); \
- rb_define_method(class, #name "=", ossl_##keytype##_set_##name, 1); \
+ rb_define_method(class, #name "=", ossl_##keytype##_set_##name, 1);\
} while (0)
#endif /* _OSSL_PKEY_H_ */
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index e4823a2ec7..02c3d99ed8 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -99,6 +99,15 @@ dh_generate(int size, int gen)
return dh;
}
+/*
+ * call-seq:
+ * DH.generate(size [, generator]) -> dh
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure.
+ * * +generator+ is a small number > 1, typically 2 or 5.
+ *
+ */
static VALUE
ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
{
@@ -107,9 +116,9 @@ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
VALUE size, gen, obj;
if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
- g = FIX2INT(gen);
+ g = NUM2INT(gen);
}
- dh = dh_generate(FIX2INT(size), g);
+ dh = dh_generate(NUM2INT(size), g);
obj = dh_instance(klass, dh);
if (obj == Qfalse) {
DH_free(dh);
@@ -119,6 +128,21 @@ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * DH.new([size [, generator] | string]) -> dh
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure.
+ * * +generator+ is a small number > 1, typically 2 or 5.
+ * * +string+ contains the DER or PEM encoded key.
+ *
+ * === Examples
+ * * DH.new -> dh
+ * * DH.new(1024) -> dh
+ * * DH.new(1024, 5) -> dh
+ * * DH.new(File.read('key.pem')) -> dh
+ */
static VALUE
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -129,10 +153,12 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
VALUE arg, gen;
GetPKey(self, pkey);
- rb_scan_args(argc, argv, "11", &arg, &gen);
- if (FIXNUM_P(arg)) {
+ if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
+ dh = DH_new();
+ }
+ else if (FIXNUM_P(arg)) {
if (!NIL_P(gen)) {
- g = FIX2INT(gen);
+ g = NUM2INT(gen);
}
if (!(dh = dh_generate(FIX2INT(arg), g))) {
ossl_raise(eDHError, NULL);
@@ -151,24 +177,31 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
}
if (!EVP_PKEY_assign_DH(pkey, dh)) {
DH_free(dh);
- ossl_raise(eRSAError, NULL);
+ ossl_raise(eDHError, NULL);
}
return self;
}
+/*
+ * call-seq:
+ * dh.public? -> true | false
+ *
+ */
static VALUE
ossl_dh_is_public(VALUE self)
{
EVP_PKEY *pkey;
GetPKeyDH(self, pkey);
- /*
- * Do we need to check dhp->dh->public_pkey?
- * return Qtrue;
- */
+
return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dh.private? -> true | false
+ *
+ */
static VALUE
ossl_dh_is_private(VALUE self)
{
@@ -179,6 +212,11 @@ ossl_dh_is_private(VALUE self)
return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dh.to_pem -> aString
+ *
+ */
static VALUE
ossl_dh_export(VALUE self)
{
@@ -200,6 +238,34 @@ ossl_dh_export(VALUE self)
}
/*
+ * call-seq:
+ * dh.to_der -> aString
+ *
+ */
+static VALUE
+ossl_dh_to_der(VALUE self)
+{
+ EVP_PKEY *pkey;
+ unsigned char *p;
+ long len;
+ VALUE str;
+
+ GetPKeyDH(self, pkey);
+ if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
+ ossl_raise(eDHError, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING_PTR(str);
+ if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
+ ossl_raise(eDHError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * dh.params -> hash
+ *
* Stores all parameters of key to the hash
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -223,6 +289,9 @@ ossl_dh_get_params(VALUE self)
}
/*
+ * call-seq:
+ * dh.to_text -> aString
+ *
* Prints all parameters of key to buffer
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -248,7 +317,10 @@ ossl_dh_to_text(VALUE self)
}
/*
- * Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
+ * call-seq:
+ * dh.public_key -> aDH
+ *
+ * Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
*/
static VALUE
ossl_dh_to_public_key(VALUE self)
@@ -268,6 +340,11 @@ ossl_dh_to_public_key(VALUE self)
return obj;
}
+/*
+ * call-seq:
+ * dh.check_params -> true | false
+ *
+ */
static VALUE
ossl_dh_check_params(VALUE self)
{
@@ -285,6 +362,11 @@ ossl_dh_check_params(VALUE self)
return codes == 0 ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dh.generate_key -> self
+ *
+ */
static VALUE
ossl_dh_generate_key(VALUE self)
{
@@ -299,6 +381,18 @@ ossl_dh_generate_key(VALUE self)
return self;
}
+/*
+ * call-seq:
+ * dh.compute_key(pub_bn) -> aString
+ *
+ * === Parameters
+ * * +pub_bn+ is a OpenSSL::BN.
+ *
+ * Returns aString containing a shared secret computed from the other parties public value.
+ *
+ * See DH_compute_key() for further information.
+ *
+ */
static VALUE
ossl_dh_compute_key(VALUE self, VALUE pub)
{
@@ -313,50 +407,126 @@ ossl_dh_compute_key(VALUE self, VALUE pub)
pub_key = GetBNPtr(pub);
len = DH_size(dh);
str = rb_str_new(0, len);
- if ((len = DH_compute_key(RSTRING(str)->ptr, pub_key, dh)) < 0) {
+ if ((len = DH_compute_key(RSTRING_PTR(str), pub_key, dh)) < 0) {
ossl_raise(eDHError, NULL);
}
- RSTRING(str)->len = len;
- RSTRING(str)->ptr[len] = 0;
+ rb_str_set_len(str, len);
return str;
}
+OSSL_PKEY_BN(dh, p);
+OSSL_PKEY_BN(dh, g);
+OSSL_PKEY_BN(dh, pub_key);
+OSSL_PKEY_BN(dh, priv_key);
+
+/*
+ * -----BEGIN DH PARAMETERS-----
+ * MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2
+ * zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC
+ * -----END DH PARAMETERS-----
+ */
+static unsigned char DEFAULT_DH_512_PRIM[] = {
+ 0xf4, 0xcd, 0x71, 0xe5, 0x8d, 0x18, 0x3f, 0x98,
+ 0x9f, 0x4f, 0x60, 0xb0, 0x02, 0x2e, 0xfe, 0x7c,
+ 0x09, 0xdf, 0x15, 0xc4, 0x1c, 0x71, 0x63, 0xba,
+ 0x04, 0xb8, 0x27, 0x94, 0x44, 0xc8, 0x93, 0xa8,
+ 0x48, 0x4c, 0xca, 0x6d, 0x7a, 0xae, 0x18, 0x4a,
+ 0x81, 0x91, 0xb6, 0xce, 0x4d, 0x8e, 0xf6, 0xe5,
+ 0x08, 0x04, 0x8c, 0x52, 0x8f, 0xe3, 0x4a, 0x31,
+ 0x44, 0x47, 0x19, 0xa1, 0x4a, 0xc8, 0x8b, 0xcb,
+};
+static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 };
+DH *OSSL_DEFAULT_DH_512 = NULL;
+
+/*
+ * -----BEGIN DH PARAMETERS-----
+ * MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
+ * AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR
+ * T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC
+ * -----END DH PARAMETERS-----
+ */
+static unsigned char DEFAULT_DH_1024_PRIM[] = {
+ 0x9d, 0x25, 0x39, 0x5c, 0xb4, 0x54, 0x8a, 0xff,
+ 0x25, 0xe6, 0xd6, 0x9f, 0x4c, 0xc3, 0xc1, 0x8d,
+ 0xa1, 0xfa, 0xba, 0x88, 0x4c, 0x53, 0xa9, 0x74,
+ 0xda, 0xfa, 0xba, 0x0b, 0x20, 0xbe, 0x40, 0xd7,
+ 0xba, 0xe7, 0x1d, 0x70, 0x28, 0x61, 0x60, 0x4c,
+ 0x49, 0x01, 0x5f, 0xd9, 0x0f, 0x60, 0x16, 0x3d,
+ 0xba, 0xd3, 0xa9, 0x5e, 0xfa, 0x98, 0x64, 0x60,
+ 0x26, 0x0e, 0x04, 0x75, 0xd8, 0x13, 0xd7, 0x31,
+ 0xb4, 0x8e, 0xad, 0xeb, 0x9c, 0x57, 0x4c, 0x8f,
+ 0x65, 0xf3, 0x90, 0x16, 0x31, 0xdc, 0x15, 0x6f,
+ 0x7d, 0x1d, 0x00, 0xae, 0x76, 0xf2, 0xd1, 0x11,
+ 0xd1, 0x4f, 0x88, 0x7b, 0x29, 0x9f, 0xf6, 0xce,
+ 0x68, 0xef, 0x57, 0xe7, 0x85, 0xf2, 0x40, 0x54,
+ 0x1c, 0x12, 0x40, 0xa2, 0x35, 0x25, 0xcf, 0x12,
+ 0xa3, 0xe1, 0x07, 0x8e, 0xdb, 0x1d, 0xb4, 0x14,
+ 0xff, 0x57, 0xe7, 0x19, 0x8d, 0x51, 0x77, 0x83
+};
+static unsigned char DEFAULT_DH_1024_GEN[] = { 0x02 };
+DH *OSSL_DEFAULT_DH_1024 = NULL;
+
+static DH*
+ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
+{
+ DH *dh;
+
+ if ((dh = DH_new()) == NULL) ossl_raise(eDHError, NULL);
+ dh->p = BN_bin2bn(p, plen, NULL);
+ dh->g = BN_bin2bn(g, glen, NULL);
+ if (dh->p == NULL || dh->g == NULL){
+ DH_free(dh);
+ ossl_raise(eDHError, NULL);
+ }
+
+ return dh;
+}
+
/*
* INIT
*/
void
Init_ossl_dh()
{
- eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
+#if 0 /* let rdoc know about mOSSL and mPKey */
+ mOSSL = rb_define_module("OpenSSL");
+ mPKey = rb_define_module_under(mOSSL, "PKey");
+#endif
+ eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
cDH = rb_define_class_under(mPKey, "DH", cPKey);
-
rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
-
rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
rb_define_method(cDH, "export", ossl_dh_export, 0);
rb_define_alias(cDH, "to_pem", "export");
rb_define_alias(cDH, "to_s", "export");
+ rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
-
rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1);
-
+ DEF_OSSL_PKEY_BN(cDH, dh, p);
+ DEF_OSSL_PKEY_BN(cDH, dh, g);
+ DEF_OSSL_PKEY_BN(cDH, dh, pub_key);
+ DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
rb_define_method(cDH, "params", ossl_dh_get_params, 0);
+
+ OSSL_DEFAULT_DH_512 = ossl_create_dh(
+ DEFAULT_DH_512_PRIM, sizeof(DEFAULT_DH_512_PRIM),
+ DEFAULT_DH_512_GEN, sizeof(DEFAULT_DH_512_GEN));
+ OSSL_DEFAULT_DH_1024 = ossl_create_dh(
+ DEFAULT_DH_1024_PRIM, sizeof(DEFAULT_DH_1024_PRIM),
+ DEFAULT_DH_1024_GEN, sizeof(DEFAULT_DH_1024_GEN));
}
#else /* defined NO_DH */
-# warning >>> OpenSSL is compiled without DH support <<<
-
void
Init_ossl_dh()
{
- rb_warning("OpenSSL is compiled without DH support");
}
#endif /* NO_DH */
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 8da71a0867..d9c7fcbe78 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -20,13 +20,7 @@
} while (0)
#define DSA_HAS_PRIVATE(dsa) ((dsa)->priv_key)
-
-#ifdef OSSL_ENGINE_ENABLED
-# define DSA_PRIVATE(dsa) (DSA_HAS_PRIVATE(dsa) || (dsa)->engine)
-#else
-# define DSA_PRIVATE(dsa) DSA_HAS_PRIVATE(dsa)
-#endif
-
+#define DSA_PRIVATE(obj,dsa) (DSA_HAS_PRIVATE(dsa)||OSSL_PKEY_IS_PRIVATE(obj))
/*
* Classes
@@ -105,10 +99,18 @@ dsa_generate(int size)
return dsa;
}
+/*
+ * call-seq:
+ * DSA.generate(size) -> dsa
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size.
+ *
+ */
static VALUE
ossl_dsa_s_generate(VALUE klass, VALUE size)
{
- DSA *dsa = dsa_generate(FIX2INT(size)); /* err handled by dsa_instance */
+ DSA *dsa = dsa_generate(NUM2INT(size)); /* err handled by dsa_instance */
VALUE obj = dsa_instance(klass, dsa);
if (obj == Qfalse) {
@@ -119,6 +121,22 @@ ossl_dsa_s_generate(VALUE klass, VALUE size)
return obj;
}
+/*
+ * call-seq:
+ * DSA.new([size | string [, pass]) -> dsa
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size.
+ * * +string+ contains a DER or PEM encoded key.
+ * * +pass+ is a string that contains a optional password.
+ *
+ * === Examples
+ * * DSA.new -> dsa
+ * * DSA.new(1024) -> dsa
+ * * DSA.new(File.read('dsa.pem')) -> dsa
+ * * DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa
+ *
+ */
static VALUE
ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -129,8 +147,10 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
VALUE arg, pass;
GetPKey(self, pkey);
- rb_scan_args(argc, argv, "11", &arg, &pass);
- if (FIXNUM_P(arg)) {
+ if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
+ dsa = DSA_new();
+ }
+ else if (FIXNUM_P(arg)) {
if (!(dsa = dsa_generate(FIX2INT(arg)))) {
ossl_raise(eDSAError, NULL);
}
@@ -140,18 +160,19 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(arg);
dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
- if (!dsa) { BIO_reset(in);
+ if (!dsa) {
+ BIO_reset(in);
dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
}
if (!dsa) {
BIO_reset(in);
dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
}
- if (!dsa) {
+ if (!dsa) {
BIO_reset(in);
dsa = d2i_DSAPrivateKey_bio(in, NULL);
}
- if (!dsa) {
+ if (!dsa) {
BIO_reset(in);
dsa = d2i_DSA_PUBKEY_bio(in, NULL);
}
@@ -166,6 +187,11 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * dsa.public? -> true | false
+ *
+ */
static VALUE
ossl_dsa_is_public(VALUE self)
{
@@ -173,13 +199,14 @@ ossl_dsa_is_public(VALUE self)
GetPKeyDSA(self, pkey);
- /*
- * Do we need to check dsap->dsa->public_pkey?
- * return Qtrue;
- */
return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dsa.private? -> true | false
+ *
+ */
static VALUE
ossl_dsa_is_private(VALUE self)
{
@@ -187,9 +214,22 @@ ossl_dsa_is_private(VALUE self)
GetPKeyDSA(self, pkey);
- return (DSA_PRIVATE(pkey->pkey.dsa)) ? Qtrue : Qfalse;
+ return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dsa.to_pem([cipher, password]) -> aString
+ *
+ * === Parameters
+ * +cipher+ is an OpenSSL::Cipher.
+ * +password+ is a string containing your password.
+ *
+ * === Examples
+ * * DSA.to_pem -> aString
+ * * DSA.to_pem(cipher, 'mypassword') -> aString
+ *
+ */
static VALUE
ossl_dsa_export(int argc, VALUE *argv, VALUE self)
{
@@ -228,6 +268,39 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
}
/*
+ * call-seq:
+ * dsa.to_der -> aString
+ *
+ */
+static VALUE
+ossl_dsa_to_der(VALUE self)
+{
+ EVP_PKEY *pkey;
+ int (*i2d_func)_((DSA*, unsigned char**));
+ unsigned char *p;
+ long len;
+ VALUE str;
+
+ GetPKeyDSA(self, pkey);
+ if(DSA_HAS_PRIVATE(pkey->pkey.dsa))
+ i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey;
+ else
+ i2d_func = i2d_DSA_PUBKEY;
+ if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
+ ossl_raise(eDSAError, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING_PTR(str);
+ if(i2d_func(pkey->pkey.dsa, &p) < 0)
+ ossl_raise(eDSAError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * dsa.params -> hash
+ *
* Stores all parameters of key to the hash
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -252,6 +325,9 @@ ossl_dsa_get_params(VALUE self)
}
/*
+ * call-seq:
+ * dsa.to_text -> aString
+ *
* Prints all parameters of key to buffer
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -277,6 +353,9 @@ ossl_dsa_to_text(VALUE self)
}
/*
+ * call-seq:
+ * dsa.public_key -> aDSA
+ *
* Makes new instance DSA PUBLIC_KEY from PRIVATE_KEY
*/
static VALUE
@@ -299,6 +378,11 @@ ossl_dsa_to_public_key(VALUE self)
#define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16)
+/*
+ * call-seq:
+ * dsa.syssign(string) -> aString
+ *
+ */
static VALUE
ossl_dsa_sign(VALUE self, VALUE data)
{
@@ -308,20 +392,24 @@ ossl_dsa_sign(VALUE self, VALUE data)
GetPKeyDSA(self, pkey);
StringValue(data);
- if (!DSA_PRIVATE(pkey->pkey.dsa)) {
+ if (!DSA_PRIVATE(self, pkey->pkey.dsa)) {
ossl_raise(eDSAError, "Private DSA key needed!");
}
str = rb_str_new(0, ossl_dsa_buf_size(pkey));
- if (!DSA_sign(0, RSTRING(data)->ptr, RSTRING(data)->len, RSTRING(str)->ptr,
+ if (!DSA_sign(0, RSTRING_PTR(data), RSTRING_LEN(data), RSTRING_PTR(str),
&buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */
ossl_raise(eDSAError, NULL);
}
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
+/*
+ * call-seq:
+ * dsa.sysverify(digest, sig) -> true | false
+ *
+ */
static VALUE
ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
{
@@ -332,8 +420,8 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
StringValue(digest);
StringValue(sig);
/* type is ignored (0) */
- ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len,
- RSTRING(sig)->ptr, RSTRING(sig)->len, pkey->pkey.dsa);
+ ret = DSA_verify(0, RSTRING_PTR(digest), RSTRING_LEN(digest),
+ RSTRING_PTR(sig), RSTRING_LEN(sig), pkey->pkey.dsa);
if (ret < 0) {
ossl_raise(eDSAError, NULL);
}
@@ -344,12 +432,23 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
return Qfalse;
}
+OSSL_PKEY_BN(dsa, p);
+OSSL_PKEY_BN(dsa, q);
+OSSL_PKEY_BN(dsa, g);
+OSSL_PKEY_BN(dsa, pub_key);
+OSSL_PKEY_BN(dsa, priv_key);
+
/*
* INIT
*/
void
Init_ossl_dsa()
{
+#if 0 /* let rdoc know about mOSSL and mPKey */
+ mOSSL = rb_define_module("OpenSSL");
+ mPKey = rb_define_module_under(mOSSL, "PKey");
+#endif
+
eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
@@ -363,20 +462,23 @@ Init_ossl_dsa()
rb_define_method(cDSA, "export", ossl_dsa_export, -1);
rb_define_alias(cDSA, "to_pem", "export");
rb_define_alias(cDSA, "to_s", "export");
+ rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
+ DEF_OSSL_PKEY_BN(cDSA, dsa, p);
+ DEF_OSSL_PKEY_BN(cDSA, dsa, q);
+ DEF_OSSL_PKEY_BN(cDSA, dsa, g);
+ DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key);
+ DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key);
+
rb_define_method(cDSA, "params", ossl_dsa_get_params, 0);
}
#else /* defined NO_DSA */
-# warning >>> OpenSSL is compiled without DSA support <<<
-
void
Init_ossl_dsa()
{
- rb_warning("OpenSSL is compiled without DSA support");
}
-
#endif /* NO_DSA */
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
new file mode 100644
index 0000000000..210054121d
--- /dev/null
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -0,0 +1,1582 @@
+/*
+ * Copyright (C) 2006-2007 Technorama Ltd. <oss-ruby@technorama.net>
+ */
+
+#include "ossl.h"
+
+#if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
+
+typedef struct {
+ EC_GROUP *group;
+ int dont_free;
+} ossl_ec_group;
+
+typedef struct {
+ EC_POINT *point;
+ int dont_free;
+} ossl_ec_point;
+
+
+#define EXPORT_PEM 0
+#define EXPORT_DER 1
+
+
+#define GetPKeyEC(obj, pkey) do { \
+ GetPKey(obj, pkey); \
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) { \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
+ } \
+} while (0)
+
+#define SafeGet_ec_group(obj, group) do { \
+ OSSL_Check_Kind(obj, cEC_GROUP); \
+ Data_Get_Struct(obj, ossl_ec_group, group); \
+} while(0)
+
+#define Get_EC_KEY(obj, key) do { \
+ EVP_PKEY *pkey; \
+ GetPKeyEC(obj, pkey); \
+ key = pkey->pkey.ec; \
+} while(0)
+
+#define Require_EC_KEY(obj, key) do { \
+ Get_EC_KEY(obj, key); \
+ if (key == NULL) \
+ rb_raise(eECError, "EC_KEY is not initialized"); \
+} while(0)
+
+#define SafeRequire_EC_KEY(obj, key) do { \
+ OSSL_Check_Kind(obj, cEC); \
+ Require_EC_KEY(obj, key); \
+} while (0)
+
+#define Get_EC_GROUP(obj, g) do { \
+ ossl_ec_group *ec_group; \
+ Data_Get_Struct(obj, ossl_ec_group, ec_group); \
+ if (ec_group == NULL) \
+ rb_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
+ g = ec_group->group; \
+} while(0)
+
+#define Require_EC_GROUP(obj, group) do { \
+ Get_EC_GROUP(obj, group); \
+ if (group == NULL) \
+ rb_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
+} while(0)
+
+#define SafeRequire_EC_GROUP(obj, group) do { \
+ OSSL_Check_Kind(obj, cEC_GROUP); \
+ Require_EC_GROUP(obj, group); \
+} while(0)
+
+#define Get_EC_POINT(obj, p) do { \
+ ossl_ec_point *ec_point; \
+ Data_Get_Struct(obj, ossl_ec_point, ec_point); \
+ if (ec_point == NULL) \
+ rb_raise(eEC_POINT, "missing ossl_ec_point structure"); \
+ p = ec_point->point; \
+} while(0)
+
+#define Require_EC_POINT(obj, point) do { \
+ Get_EC_POINT(obj, point); \
+ if (point == NULL) \
+ rb_raise(eEC_POINT, "EC_POINT is not initialized"); \
+} while(0)
+
+#define SafeRequire_EC_POINT(obj, point) do { \
+ OSSL_Check_Kind(obj, cEC_POINT); \
+ Require_EC_POINT(obj, point); \
+} while(0)
+
+VALUE cEC;
+VALUE eECError;
+VALUE cEC_GROUP;
+VALUE eEC_GROUP;
+VALUE cEC_POINT;
+VALUE eEC_POINT;
+
+static ID s_GFp;
+static ID s_GFp_simple;
+static ID s_GFp_mont;
+static ID s_GFp_nist;
+static ID s_GF2m;
+static ID s_GF2m_simple;
+
+static ID ID_uncompressed;
+static ID ID_compressed;
+static ID ID_hybrid;
+
+static VALUE ec_instance(VALUE klass, EC_KEY *ec)
+{
+ EVP_PKEY *pkey;
+ VALUE obj;
+
+ if (!ec) {
+ return Qfalse;
+ }
+ if (!(pkey = EVP_PKEY_new())) {
+ return Qfalse;
+ }
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
+ EVP_PKEY_free(pkey);
+ return Qfalse;
+ }
+ WrapPKey(klass, obj, pkey);
+
+ return obj;
+}
+
+VALUE ossl_ec_new(EVP_PKEY *pkey)
+{
+ VALUE obj;
+
+ if (!pkey) {
+ obj = ec_instance(cEC, EC_KEY_new());
+ } else {
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
+ ossl_raise(rb_eTypeError, "Not a EC key!");
+ }
+ WrapPKey(cEC, obj, pkey);
+ }
+ if (obj == Qfalse) {
+ ossl_raise(eECError, NULL);
+ }
+
+ return obj;
+}
+
+
+/* call-seq:
+ * OpenSSL::PKey::EC.new()
+ * OpenSSL::PKey::EC.new(ec_key)
+ * OpenSSL::PKey::EC.new(ec_group)
+ * OpenSSL::PKey::EC.new("secp112r1")
+ * OpenSSL::PKey::EC.new(pem_string)
+ * OpenSSL::PKey::EC.new(der_string)
+ *
+ * See the OpenSSL documentation for:
+ * EC_KEY_*
+ */
+static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ EC_KEY *ec = NULL;
+ VALUE arg, pass;
+ VALUE group = Qnil;
+
+ GetPKey(self, pkey);
+ if (pkey->pkey.ec)
+ rb_raise(eECError, "EC_KEY already initialized");
+
+ rb_scan_args(argc, argv, "02", &arg, &pass);
+
+ if (NIL_P(arg)) {
+ ec = EC_KEY_new();
+ } else {
+ if (rb_obj_is_kind_of(arg, cEC)) {
+ EC_KEY *other_ec = NULL;
+
+ SafeRequire_EC_KEY(arg, other_ec);
+ ec = EC_KEY_dup(other_ec);
+ } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
+ ec = EC_KEY_new();
+ group = arg;
+ } else {
+ BIO *in = ossl_obj2bio(arg);
+
+ ec = PEM_read_bio_ECPrivateKey(in, NULL, NULL, NULL);
+ if (!ec) {
+ BIO_reset(in);
+ ec = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
+ }
+ if (!ec) {
+ BIO_reset(in);
+ ec = d2i_ECPrivateKey_bio(in, NULL);
+ }
+ if (!ec) {
+ BIO_reset(in);
+ ec = d2i_EC_PUBKEY_bio(in, NULL);
+ }
+
+ BIO_free(in);
+
+ if (ec == NULL) {
+ const char *name = STR2CSTR(arg);
+ int nid = OBJ_sn2nid(name);
+
+ if (nid == NID_undef)
+ ossl_raise(eECError, "unknown curve name (%s)\n", name);
+
+ if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
+ ossl_raise(eECError, "unable to create curve (%s)\n", name);
+
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
+ }
+ }
+ }
+
+ if (ec == NULL)
+ ossl_raise(eECError, NULL);
+
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
+ EC_KEY_free(ec);
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
+ }
+
+ rb_iv_set(self, "@group", Qnil);
+
+ if (!NIL_P(group))
+ rb_funcall(self, rb_intern("group="), 1, arg);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * key.group => group
+ *
+ * Returns a constant <code>OpenSSL::EC::Group</code> that is tied to the key.
+ * Modifying the returned group can make the key invalid.
+ */
+static VALUE ossl_ec_key_get_group(VALUE self)
+{
+ VALUE group_v;
+ EC_KEY *ec;
+ ossl_ec_group *ec_group;
+ EC_GROUP *group;
+
+ Require_EC_KEY(self, ec);
+
+ group_v = rb_iv_get(self, "@group");
+ if (!NIL_P(group_v))
+ return group_v;
+
+ if ((group = (EC_GROUP *)EC_KEY_get0_group(ec)) != NULL) {
+ group_v = rb_obj_alloc(cEC_GROUP);
+ SafeGet_ec_group(group_v, ec_group);
+ ec_group->group = group;
+ ec_group->dont_free = 1;
+ rb_iv_set(group_v, "@key", self);
+ rb_iv_set(self, "@group", group_v);
+ return group_v;
+ }
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * key.group = group => group
+ *
+ * Returns the same object passed, not the group object associated with the key.
+ * If you wish to access the group object tied to the key call key.group after setting
+ * the group.
+ *
+ * Setting the group will immediately destroy any previously assigned group object.
+ * The group is internally copied by OpenSSL. Modifying the original group after
+ * assignment will not effect the internal key structure.
+ * (your changes may be lost). BE CAREFUL.
+ *
+ * EC_KEY_set_group calls EC_GROUP_free(key->group) then EC_GROUP_dup(), not EC_GROUP_copy.
+ * This documentation is accurate for OpenSSL 0.9.8b.
+ */
+static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v)
+{
+ VALUE old_group_v;
+ EC_KEY *ec;
+ EC_GROUP *group;
+
+ Require_EC_KEY(self, ec);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ old_group_v = rb_iv_get(self, "@group");
+ if (!NIL_P(old_group_v)) {
+ ossl_ec_group *old_ec_group;
+ SafeGet_ec_group(old_group_v, old_ec_group);
+
+ old_ec_group->group = NULL;
+ old_ec_group->dont_free = 0;
+ rb_iv_set(old_group_v, "@key", Qnil);
+ }
+
+ rb_iv_set(self, "@group", Qnil);
+
+ if (EC_KEY_set_group(ec, group) != 1)
+ ossl_raise(eECError, "EC_KEY_set_group");
+
+ return group_v;
+}
+
+/*
+ * call-seq:
+ * key.private_key => OpenSSL::BN
+ *
+ * See the OpenSSL documentation for EC_KEY_get0_private_key()
+ */
+static VALUE ossl_ec_key_get_private_key(VALUE self)
+{
+ EC_KEY *ec;
+ const BIGNUM *bn;
+
+ Require_EC_KEY(self, ec);
+
+ if ((bn = EC_KEY_get0_private_key(ec)) == NULL)
+ return Qnil;
+
+ return ossl_bn_new(bn);
+}
+
+/*
+ * call-seq:
+ * key.private_key = openssl_bn
+ *
+ * See the OpenSSL documentation for EC_KEY_set_private_key()
+ */
+static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
+{
+ EC_KEY *ec;
+ BIGNUM *bn = NULL;
+
+ Require_EC_KEY(self, ec);
+ if (!NIL_P(private_key))
+ bn = GetBNPtr(private_key);
+
+ switch (EC_KEY_set_private_key(ec, bn)) {
+ case 1:
+ break;
+ case 0:
+ if (bn == NULL)
+ break;
+ default:
+ ossl_raise(eECError, "EC_KEY_set_private_key");
+ }
+
+ return private_key;
+}
+
+
+static VALUE ossl_ec_point_dup(const EC_POINT *point, VALUE group_v)
+{
+ VALUE obj;
+ const EC_GROUP *group;
+ ossl_ec_point *new_point;
+
+ obj = rb_obj_alloc(cEC_POINT);
+ Data_Get_Struct(obj, ossl_ec_point, new_point);
+
+ SafeRequire_EC_GROUP(group_v, group);
+
+ new_point->point = EC_POINT_dup(point, group);
+ if (new_point->point == NULL)
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
+ rb_iv_set(obj, "@group", group_v);
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * key.public_key => OpenSSL::PKey::EC::Point
+ *
+ * See the OpenSSL documentation for EC_KEY_get0_public_key()
+ */
+static VALUE ossl_ec_key_get_public_key(VALUE self)
+{
+ EC_KEY *ec;
+ const EC_POINT *point;
+ VALUE group;
+
+ Require_EC_KEY(self, ec);
+
+ if ((point = EC_KEY_get0_public_key(ec)) == NULL)
+ return Qnil;
+
+ group = rb_funcall(self, rb_intern("group"), 0);
+ if (NIL_P(group))
+ ossl_raise(eECError, "EC_KEY_get0_get0_group (has public_key but no group???");
+
+ return ossl_ec_point_dup(point, group);
+}
+
+/*
+ * call-seq:
+ * key.public_key = ec_point
+ *
+ * See the OpenSSL documentation for EC_KEY_set_public_key()
+ */
+static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
+{
+ EC_KEY *ec;
+ EC_POINT *point = NULL;
+
+ Require_EC_KEY(self, ec);
+ if (!NIL_P(public_key))
+ SafeRequire_EC_POINT(public_key, point);
+
+ switch (EC_KEY_set_public_key(ec, point)) {
+ case 1:
+ break;
+ case 0:
+ if (point == NULL)
+ break;
+ default:
+ ossl_raise(eECError, "EC_KEY_set_public_key");
+ }
+
+ return public_key;
+}
+
+/*
+ * call-seq:
+ * key.public_key? => true or false
+ *
+ * Both public_key? and private_key? may return false at the same time unlike other PKey classes.
+ */
+static VALUE ossl_ec_key_is_public_key(VALUE self)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+
+ return (EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse);
+}
+
+/*
+ * call-seq:
+ * key.private_key? => true or false
+ *
+ * Both public_key? and private_key? may return false at the same time unlike other PKey classes.
+ */
+static VALUE ossl_ec_key_is_private_key(VALUE self)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+
+ return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse);
+}
+
+static VALUE ossl_ec_key_to_string(VALUE self, int format)
+{
+ EC_KEY *ec;
+ BIO *out;
+ int i = -1;
+ int private = 0;
+ EVP_CIPHER *cipher = NULL;
+ char *password = NULL;
+ VALUE str;
+
+ Require_EC_KEY(self, ec);
+
+ if (EC_KEY_get0_public_key(ec) == NULL)
+ rb_raise(eECError, "can't export - no public key set");
+
+ if (EC_KEY_check_key(ec) != 1)
+ ossl_raise(eECError, "can't export - EC_KEY_check_key failed");
+
+ if (EC_KEY_get0_private_key(ec))
+ private = 1;
+
+ if (!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(eECError, "BIO_new(BIO_s_mem())");
+
+ switch(format) {
+ case EXPORT_PEM:
+ if (private) {
+ if (cipher || password)
+/* BUG: finish cipher/password key export */
+ rb_notimplement();
+ i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
+ } else {
+ if (cipher || password)
+ rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+
+ i = PEM_write_bio_EC_PUBKEY(out, ec);
+ }
+
+ break;
+ case EXPORT_DER:
+ if (private) {
+ if (cipher || password)
+ rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+
+ i = i2d_ECPrivateKey_bio(out, ec);
+ } else {
+ if (cipher || password)
+ rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+
+ i = i2d_EC_PUBKEY_bio(out, ec);
+ }
+
+ break;
+ default:
+ BIO_free(out);
+ rb_raise(rb_eRuntimeError, "unknown format (internal error)");
+ }
+
+ if (i != 1) {
+ BIO_free(out);
+ ossl_raise(eECError, "outlen=%d", i);
+ }
+
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * key.to_pem => String
+ *
+ * See the OpenSSL documentation for PEM_write_bio_ECPrivateKey()
+ */
+static VALUE ossl_ec_key_to_pem(VALUE self)
+{
+ return ossl_ec_key_to_string(self, EXPORT_PEM);
+}
+
+/*
+ * call-seq:
+ * key.to_der => String
+ *
+ * See the OpenSSL documentation for i2d_ECPrivateKey_bio()
+ */
+static VALUE ossl_ec_key_to_der(VALUE self)
+{
+ return ossl_ec_key_to_string(self, EXPORT_DER);
+}
+
+/*
+ * call-seq:
+ * key.to_text => String
+ *
+ * See the OpenSSL documentation for EC_KEY_print()
+ */
+static VALUE ossl_ec_key_to_text(VALUE self)
+{
+ EC_KEY *ec;
+ BIO *out;
+ VALUE str;
+
+ Require_EC_KEY(self, ec);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eECError, "BIO_new(BIO_s_mem())");
+ }
+ if (!EC_KEY_print(out, ec, 0)) {
+ BIO_free(out);
+ ossl_raise(eECError, "EC_KEY_print");
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * key.generate_key => self
+ *
+ * See the OpenSSL documentation for EC_KEY_generate_key()
+ */
+static VALUE ossl_ec_key_generate_key(VALUE self)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+
+ if (EC_KEY_generate_key(ec) != 1)
+ ossl_raise(eECError, "EC_KEY_generate_key");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * key.check_key => true
+ *
+ * Raises an exception if the key is invalid.
+ *
+ * See the OpenSSL documentation for EC_KEY_check_key()
+ */
+static VALUE ossl_ec_key_check_key(VALUE self)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+
+ if (EC_KEY_check_key(ec) != 1)
+ ossl_raise(eECError, "EC_KEY_check_key");
+
+ return Qtrue;
+}
+
+/*
+ * call-seq:
+ * key.dh_compute_key(pubkey) => String
+ *
+ * See the OpenSSL documentation for ECDH_compute_key()
+ */
+static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey)
+{
+ EC_KEY *ec;
+ EC_POINT *point;
+ int buf_len;
+ VALUE str;
+
+ Require_EC_KEY(self, ec);
+ SafeRequire_EC_POINT(pubkey, point);
+
+/* BUG: need a way to figure out the maximum string size */
+ buf_len = 1024;
+ str = rb_str_new(0, buf_len);
+/* BUG: take KDF as a block */
+ buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL);
+ if (buf_len < 0)
+ ossl_raise(eECError, "ECDH_compute_key");
+
+ rb_str_resize(str, buf_len);
+
+ return str;
+}
+
+/* sign_setup */
+
+/*
+ * call-seq:
+ * key.dsa_sign_asn1(data) => String
+ *
+ * See the OpenSSL documentation for ECDSA_sign()
+ */
+static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
+{
+ EC_KEY *ec;
+ unsigned int buf_len;
+ VALUE str;
+
+ Require_EC_KEY(self, ec);
+ StringValue(data);
+
+ if (EC_KEY_get0_private_key(ec) == NULL)
+ ossl_raise(eECError, "Private EC key needed!");
+
+ str = rb_str_new(0, ECDSA_size(ec) + 16);
+ if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
+ ossl_raise(eECError, "ECDSA_sign");
+
+ rb_str_resize(str, buf_len);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * key.dsa_verify(data, sig) => true or false
+ *
+ * See the OpenSSL documentation for ECDSA_verify()
+ */
+static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+ StringValue(data);
+ StringValue(sig);
+
+ switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(sig), RSTRING_LEN(sig), ec)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: break;
+ }
+
+ ossl_raise(eECError, "ECDSA_verify");
+}
+
+static void ossl_ec_group_free(ossl_ec_group *ec_group)
+{
+ if (!ec_group->dont_free && ec_group->group)
+ EC_GROUP_clear_free(ec_group->group);
+ free(ec_group);
+}
+
+static VALUE ossl_ec_group_alloc(VALUE klass)
+{
+ ossl_ec_group *ec_group;
+ VALUE obj;
+
+ obj = Data_Make_Struct(klass, ossl_ec_group, 0, ossl_ec_group_free, ec_group);
+
+ return obj;
+}
+
+/* call-seq:
+ * OpenSSL::PKey::EC::Group.new("secp112r1")
+ * OpenSSL::PKey::EC::Group.new(ec_group)
+ * OpenSSL::PKey::EC::Group.new(pem_string)
+ * OpenSSL::PKey::EC::Group.new(der_string)
+ * OpenSSL::PKey::EC::Group.new(pem_file)
+ * OpenSSL::PKey::EC::Group.new(der_file)
+ * OpenSSL::PKey::EC::Group.new(:GFp_simple)
+ * OpenSSL::PKey::EC::Group.new(:GFp_mult)
+ * OpenSSL::PKey::EC::Group.new(:GFp_nist)
+ * OpenSSL::PKey::EC::Group.new(:GF2m_simple)
+ * OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b)
+ * OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b)
+ *
+ * See the OpenSSL documentation for EC_GROUP_*
+ */
+static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE arg1, arg2, arg3, arg4;
+ ossl_ec_group *ec_group;
+ EC_GROUP *group = NULL;
+
+ Data_Get_Struct(self, ossl_ec_group, ec_group);
+ if (ec_group->group != NULL)
+ rb_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
+
+ switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
+ case 1:
+ if (SYMBOL_P(arg1)) {
+ const EC_METHOD *method = NULL;
+ ID id = SYM2ID(arg1);
+
+ if (id == s_GFp_simple) {
+ method = EC_GFp_simple_method();
+ } else if (id == s_GFp_mont) {
+ method = EC_GFp_mont_method();
+ } else if (id == s_GFp_nist) {
+ method = EC_GFp_nist_method();
+ } else if (id == s_GF2m_simple) {
+ method = EC_GF2m_simple_method();
+ }
+
+ if (method) {
+ if ((group = EC_GROUP_new(method)) == NULL)
+ ossl_raise(eEC_GROUP, "EC_GROUP_new");
+ } else {
+ rb_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
+ }
+ } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
+ const EC_GROUP *arg1_group;
+
+ SafeRequire_EC_GROUP(arg1, arg1_group);
+ if ((group = EC_GROUP_dup(arg1_group)) == NULL)
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
+ } else {
+ BIO *in = ossl_obj2bio(arg1);
+
+ group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
+ if (!group) {
+ BIO_reset(in);
+ group = d2i_ECPKParameters_bio(in, NULL);
+ }
+
+ BIO_free(in);
+
+ if (!group) {
+ const char *name = STR2CSTR(arg1);
+ int nid = OBJ_sn2nid(name);
+
+ if (nid == NID_undef)
+ ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
+
+ group = EC_GROUP_new_by_curve_name(nid);
+ if (group == NULL)
+ ossl_raise(eEC_GROUP, "unable to create curve (%s)", name);
+
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+ EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
+ }
+ }
+
+ break;
+ case 4:
+ if (SYMBOL_P(arg1)) {
+ ID id = SYM2ID(arg1);
+ EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL;
+ const BIGNUM *p = GetBNPtr(arg2);
+ const BIGNUM *a = GetBNPtr(arg3);
+ const BIGNUM *b = GetBNPtr(arg4);
+
+ if (id == s_GFp) {
+ new_curve = EC_GROUP_new_curve_GFp;
+ } else if (id == s_GF2m) {
+ new_curve = EC_GROUP_new_curve_GF2m;
+ } else {
+ rb_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
+ }
+
+ if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
+ ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
+ } else {
+ rb_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
+ }
+
+ break;
+ default:
+ rb_raise(rb_eArgError, "wrong number of arguments");
+ }
+
+ if (group == NULL)
+ ossl_raise(eEC_GROUP, "");
+
+ ec_group->group = group;
+
+ return self;
+}
+
+/* call-seq:
+ * group1 == group2 => true | false
+ *
+ */
+static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
+{
+ EC_GROUP *group1 = NULL, *group2 = NULL;
+
+ Require_EC_GROUP(a, group1);
+ SafeRequire_EC_GROUP(b, group2);
+
+ if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1)
+ return Qfalse;
+
+ return Qtrue;
+}
+
+/* call-seq:
+ * group.generator => ec_point
+ *
+ * See the OpenSSL documentation for EC_GROUP_get0_generator()
+ */
+static VALUE ossl_ec_group_get_generator(VALUE self)
+{
+ VALUE point_obj;
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group), self);
+
+ return point_obj;
+}
+
+/* call-seq:
+ * group.set_generator(generator, order, cofactor) => self
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_generator()
+ */
+static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE order, VALUE cofactor)
+{
+ EC_GROUP *group = NULL;
+ const EC_POINT *point;
+ const BIGNUM *o, *co;
+
+ Require_EC_GROUP(self, group);
+ SafeRequire_EC_POINT(generator, point);
+ o = GetBNPtr(order);
+ co = GetBNPtr(cofactor);
+
+ if (EC_GROUP_set_generator(group, point, o, co) != 1)
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_generator");
+
+ return self;
+}
+
+/* call-seq:
+ * group.get_order => order_bn
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_order()
+ */
+static VALUE ossl_ec_group_get_order(VALUE self)
+{
+ VALUE bn_obj;
+ BIGNUM *bn;
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ bn_obj = ossl_bn_new(NULL);
+ bn = GetBNPtr(bn_obj);
+
+ if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_order");
+
+ return bn_obj;
+}
+
+/* call-seq:
+ * group.get_cofactor => cofactor_bn
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_cofactor()
+ */
+static VALUE ossl_ec_group_get_cofactor(VALUE self)
+{
+ VALUE bn_obj;
+ BIGNUM *bn;
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ bn_obj = ossl_bn_new(NULL);
+ bn = GetBNPtr(bn_obj);
+
+ if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_cofactor");
+
+ return bn_obj;
+}
+
+/* call-seq:
+ * group.curve_name => String
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_curve_name()
+ */
+static VALUE ossl_ec_group_get_curve_name(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ int nid;
+
+ Get_EC_GROUP(self, group);
+ if (group == NULL)
+ return Qnil;
+
+ nid = EC_GROUP_get_curve_name(group);
+
+/* BUG: an nid or asn1 object should be returned, maybe. */
+ return rb_str_new2(OBJ_nid2sn(nid));
+}
+
+/* call-seq:
+ * EC.builtin_curves => [[name, comment], ...]
+ *
+ * See the OpenSSL documentation for EC_builtin_curves()
+ */
+static VALUE ossl_s_builtin_curves(VALUE self)
+{
+ EC_builtin_curve *curves = NULL;
+ int n;
+ int crv_len = EC_get_builtin_curves(NULL, 0);
+ VALUE ary, ret;
+
+ curves = ALLOCA_N(EC_builtin_curve, crv_len);
+ if (curves == NULL)
+ return Qnil;
+ if (!EC_get_builtin_curves(curves, crv_len))
+ ossl_raise(rb_eRuntimeError, "EC_get_builtin_curves");
+
+ ret = rb_ary_new2(crv_len);
+
+ for (n = 0; n < crv_len; n++) {
+ const char *sname = OBJ_nid2sn(curves[n].nid);
+ const char *comment = curves[n].comment;
+
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, rb_str_new2(sname));
+ rb_ary_push(ary, comment ? rb_str_new2(comment) : Qnil);
+ rb_ary_push(ret, ary);
+ }
+
+ return ret;
+}
+
+/* call-seq:
+ * group.asn1_flag => Fixnum
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_asn1_flag()
+ */
+static VALUE ossl_ec_group_get_asn1_flag(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ int flag;
+
+ Require_EC_GROUP(self, group);
+
+ flag = EC_GROUP_get_asn1_flag(group);
+
+ return INT2FIX(flag);
+}
+
+/* call-seq:
+ * group.asn1_flag = Fixnum => Fixnum
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_asn1_flag()
+ */
+static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
+{
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ EC_GROUP_set_asn1_flag(group, NUM2INT(flag_v));
+
+ return flag_v;
+}
+
+/* call-seq:
+ * group.point_conversion_form => :uncompressed | :compressed | :hybrid
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_point_conversion_form()
+ */
+static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ point_conversion_form_t form;
+ VALUE ret;
+
+ Require_EC_GROUP(self, group);
+
+ form = EC_GROUP_get_point_conversion_form(group);
+
+ switch (form) {
+ case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break;
+ case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break;
+ case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break;
+ default: rb_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
+ }
+
+ return ID2SYM(ret);
+}
+
+/* call-seq:
+ * group.point_conversion_form = form => form
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_point_conversion_form()
+ */
+static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
+{
+ EC_GROUP *group = NULL;
+ point_conversion_form_t form;
+ ID form_id = SYM2ID(form_v);
+
+ Require_EC_GROUP(self, group);
+
+ if (form_id == ID_uncompressed) {
+ form = POINT_CONVERSION_UNCOMPRESSED;
+ } else if (form_id == ID_compressed) {
+ form = POINT_CONVERSION_COMPRESSED;
+ } else if (form_id == ID_hybrid) {
+ form = POINT_CONVERSION_HYBRID;
+ } else {
+ rb_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
+ }
+
+ EC_GROUP_set_point_conversion_form(group, form);
+
+ return form_v;
+}
+
+/* call-seq:
+ * group.seed => String or nil
+ *
+ * See the OpenSSL documentation for EC_GROUP_get0_seed()
+ */
+static VALUE ossl_ec_group_get_seed(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ size_t seed_len;
+
+ Require_EC_GROUP(self, group);
+
+ seed_len = EC_GROUP_get_seed_len(group);
+
+ if (seed_len == 0)
+ return Qnil;
+
+ return rb_str_new(EC_GROUP_get0_seed(group), seed_len);
+}
+
+/* call-seq:
+ * group.seed = seed => seed
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_seed()
+ */
+static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
+{
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+ StringValue(seed);
+
+ if (EC_GROUP_set_seed(group, RSTRING_PTR(seed), RSTRING_LEN(seed)) != RSTRING_LEN(seed))
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_seed");
+
+ return seed;
+}
+
+/* get/set curve GFp, GF2m */
+
+/* call-seq:
+ * group.degree => Fixnum
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_degree()
+ */
+static VALUE ossl_ec_group_get_degree(VALUE self)
+{
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ return INT2NUM(EC_GROUP_get_degree(group));
+}
+
+static VALUE ossl_ec_group_to_string(VALUE self, int format)
+{
+ EC_GROUP *group;
+ BIO *out;
+ int i = -1;
+ VALUE str;
+
+ Get_EC_GROUP(self, group);
+
+ if (!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
+
+ switch(format) {
+ case EXPORT_PEM:
+ i = PEM_write_bio_ECPKParameters(out, group);
+ break;
+ case EXPORT_DER:
+ i = i2d_ECPKParameters_bio(out, group);
+ break;
+ default:
+ BIO_free(out);
+ rb_raise(rb_eRuntimeError, "unknown format (internal error)");
+ }
+
+ if (i != 1) {
+ BIO_free(out);
+ ossl_raise(eECError, NULL);
+ }
+
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/* call-seq:
+ * group.to_pem => String
+ *
+ * See the OpenSSL documentation for PEM_write_bio_ECPKParameters()
+ */
+static VALUE ossl_ec_group_to_pem(VALUE self)
+{
+ return ossl_ec_group_to_string(self, EXPORT_PEM);
+}
+
+/* call-seq:
+ * group.to_der => String
+ *
+ * See the OpenSSL documentation for i2d_ECPKParameters_bio()
+ */
+static VALUE ossl_ec_group_to_der(VALUE self)
+{
+ return ossl_ec_group_to_string(self, EXPORT_DER);
+}
+
+/* call-seq:
+ * group.to_text => String
+ *
+ * See the OpenSSL documentation for ECPKParameters_print()
+ */
+static VALUE ossl_ec_group_to_text(VALUE self)
+{
+ EC_GROUP *group;
+ BIO *out;
+ VALUE str;
+
+ Require_EC_GROUP(self, group);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
+ }
+ if (!ECPKParameters_print(out, group, 0)) {
+ BIO_free(out);
+ ossl_raise(eEC_GROUP, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+
+static void ossl_ec_point_free(ossl_ec_point *ec_point)
+{
+ if (!ec_point->dont_free && ec_point->point)
+ EC_POINT_clear_free(ec_point->point);
+ free(ec_point);
+}
+
+static VALUE ossl_ec_point_alloc(VALUE klass)
+{
+ ossl_ec_point *ec_point;
+ VALUE obj;
+
+ obj = Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::PKey::EC::Point.new(point)
+ * OpenSSL::PKey::EC::Point.new(group)
+ * OpenSSL::PKey::EC::Point.new(group, bn)
+ *
+ * See the OpenSSL documentation for EC_POINT_*
+ */
+static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
+{
+ ossl_ec_point *ec_point;
+ EC_POINT *point = NULL;
+ VALUE arg1, arg2;
+ VALUE group_v = Qnil;
+ const EC_GROUP *group = NULL;
+
+ Data_Get_Struct(self, ossl_ec_point, ec_point);
+ if (ec_point->point)
+ rb_raise(eEC_POINT, "EC_POINT already initialized");
+
+ switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) {
+ case 1:
+ if (rb_obj_is_kind_of(arg1, cEC_POINT)) {
+ const EC_POINT *arg_point;
+
+ group_v = rb_iv_get(arg1, "@group");
+ SafeRequire_EC_GROUP(group_v, group);
+ SafeRequire_EC_POINT(arg1, arg_point);
+
+ point = EC_POINT_dup(arg_point, group);
+ } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
+ group_v = arg1;
+ SafeRequire_EC_GROUP(group_v, group);
+
+ point = EC_POINT_new(group);
+ } else {
+ rb_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
+ }
+
+ break;
+ case 2:
+ if (!rb_obj_is_kind_of(arg1, cEC_GROUP))
+ rb_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group");
+ group_v = arg1;
+ SafeRequire_EC_GROUP(group_v, group);
+
+ if (rb_obj_is_kind_of(arg2, cBN)) {
+ const BIGNUM *bn = GetBNPtr(arg2);
+
+ point = EC_POINT_bn2point(group, bn, NULL, ossl_bn_ctx);
+ } else {
+ BIO *in = ossl_obj2bio(arg1);
+
+/* BUG: finish me */
+
+ BIO_free(in);
+
+ if (point == NULL) {
+ ossl_raise(eEC_POINT, "unknown type for 2nd arg");
+ }
+ }
+ break;
+ default:
+ rb_raise(rb_eArgError, "wrong number of arguments");
+ }
+
+ if (point == NULL)
+ ossl_raise(eEC_POINT, NULL);
+
+ if (NIL_P(group_v))
+ rb_raise(rb_eRuntimeError, "missing group (internal error)");
+
+ ec_point->point = point;
+
+ rb_iv_set(self, "@group", group_v);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point1 == point2 => true | false
+ *
+ */
+static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
+{
+ EC_POINT *point1, *point2;
+ VALUE group_v1 = rb_iv_get(a, "@group");
+ VALUE group_v2 = rb_iv_get(b, "@group");
+ const EC_GROUP *group;
+
+ if (ossl_ec_group_eql(group_v1, group_v2) == Qfalse)
+ return Qfalse;
+
+ Require_EC_POINT(a, point1);
+ SafeRequire_EC_POINT(b, point2);
+ SafeRequire_EC_GROUP(group_v1, group);
+
+ if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1)
+ return Qfalse;
+
+ return Qtrue;
+}
+
+/*
+ * call-seq:
+ * point.infinity? => true | false
+ *
+ */
+static VALUE ossl_ec_point_is_at_infinity(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ switch (EC_POINT_is_at_infinity(group, point)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
+ }
+}
+
+/*
+ * call-seq:
+ * point.on_curve? => true | false
+ *
+ */
+static VALUE ossl_ec_point_is_on_curve(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
+ }
+}
+
+/*
+ * call-seq:
+ * point.make_affine! => self
+ *
+ */
+static VALUE ossl_ec_point_make_affine(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
+ ossl_raise(cEC_POINT, "EC_POINT_make_affine");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point.invert! => self
+ *
+ */
+static VALUE ossl_ec_point_invert(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
+ ossl_raise(cEC_POINT, "EC_POINT_invert");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point.set_to_infinity! => self
+ *
+ */
+static VALUE ossl_ec_point_set_to_infinity(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ if (EC_POINT_set_to_infinity(group, point) != 1)
+ ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point.to_bn => OpenSSL::BN
+ *
+ * See the OpenSSL documentation for EC_POINT_point2bn()
+ */
+static VALUE ossl_ec_point_to_bn(VALUE self)
+{
+ EC_POINT *point;
+ VALUE bn_obj;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+ point_conversion_form_t form;
+ BIGNUM *bn;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ form = EC_GROUP_get_point_conversion_form(group);
+
+ bn_obj = rb_obj_alloc(cBN);
+ bn = GetBNPtr(bn_obj);
+
+ if (EC_POINT_point2bn(group, point, form, bn, ossl_bn_ctx) == NULL)
+ ossl_raise(eEC_POINT, "EC_POINT_point2bn");
+
+ return bn_obj;
+}
+
+static void no_copy(VALUE klass)
+{
+ rb_undef_method(klass, "copy");
+ rb_undef_method(klass, "clone");
+ rb_undef_method(klass, "dup");
+ rb_undef_method(klass, "initialize_copy");
+}
+
+void Init_ossl_ec()
+{
+#ifdef DONT_NEED_RDOC_WORKAROUND
+ mOSSL = rb_define_module("OpenSSL");
+ mPKey = rb_define_module_under(mOSSL, "PKey");
+#endif
+
+ eECError = rb_define_class_under(mPKey, "ECError", ePKeyError);
+
+ cEC = rb_define_class_under(mPKey, "EC", cPKey);
+ cEC_GROUP = rb_define_class_under(cEC, "Group", rb_cObject);
+ cEC_POINT = rb_define_class_under(cEC, "Point", rb_cObject);
+ eEC_GROUP = rb_define_class_under(cEC_GROUP, "Error", eOSSLError);
+ eEC_POINT = rb_define_class_under(cEC_POINT, "Error", eOSSLError);
+
+ s_GFp = rb_intern("GFp");
+ s_GF2m = rb_intern("GF2m");
+ s_GFp_simple = rb_intern("GFp_simple");
+ s_GFp_mont = rb_intern("GFp_mont");
+ s_GFp_nist = rb_intern("GFp_nist");
+ s_GF2m_simple = rb_intern("GF2m_simple");
+
+ ID_uncompressed = rb_intern("uncompressed");
+ ID_compressed = rb_intern("compressed");
+ ID_hybrid = rb_intern("hybrid");
+
+#ifdef OPENSSL_EC_NAMED_CURVE
+ rb_define_const(cEC, "NAMED_CURVE", ULONG2NUM(OPENSSL_EC_NAMED_CURVE));
+#endif
+
+ rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
+
+ rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
+/* copy/dup/cmp */
+
+ rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
+ rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1);
+ rb_define_method(cEC, "private_key", ossl_ec_key_get_private_key, 0);
+ rb_define_method(cEC, "private_key=", ossl_ec_key_set_private_key, 1);
+ rb_define_method(cEC, "public_key", ossl_ec_key_get_public_key, 0);
+ rb_define_method(cEC, "public_key=", ossl_ec_key_set_public_key, 1);
+ rb_define_method(cEC, "private_key?", ossl_ec_key_is_private_key, 0);
+ rb_define_method(cEC, "public_key?", ossl_ec_key_is_public_key, 0);
+/* rb_define_method(cEC, "", ossl_ec_key_get_, 0);
+ rb_define_method(cEC, "=", ossl_ec_key_set_ 1);
+ set/get enc_flags
+ set/get _conv_from
+ set/get asn1_flag (can use ruby to call self.group.asn1_flag)
+ set/get precompute_mult
+*/
+ rb_define_method(cEC, "generate_key", ossl_ec_key_generate_key, 0);
+ rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
+
+ rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
+ rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
+ rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
+/* do_sign/do_verify */
+
+ rb_define_method(cEC, "to_pem", ossl_ec_key_to_pem, 0);
+ rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
+ rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);
+
+
+ rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
+ rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1);
+ rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1);
+ rb_define_alias(cEC_GROUP, "==", "eql?");
+/* copy/dup/cmp */
+
+ rb_define_method(cEC_GROUP, "generator", ossl_ec_group_get_generator, 0);
+ rb_define_method(cEC_GROUP, "set_generator", ossl_ec_group_set_generator, 3);
+ rb_define_method(cEC_GROUP, "order", ossl_ec_group_get_order, 0);
+ rb_define_method(cEC_GROUP, "cofactor", ossl_ec_group_get_cofactor, 0);
+
+ rb_define_method(cEC_GROUP, "curve_name", ossl_ec_group_get_curve_name, 0);
+/* rb_define_method(cEC_GROUP, "curve_name=", ossl_ec_group_set_curve_name, 1); */
+
+ rb_define_method(cEC_GROUP, "asn1_flag", ossl_ec_group_get_asn1_flag, 0);
+ rb_define_method(cEC_GROUP, "asn1_flag=", ossl_ec_group_set_asn1_flag, 1);
+
+ rb_define_method(cEC_GROUP, "point_conversion_form", ossl_ec_group_get_point_conversion_form, 0);
+ rb_define_method(cEC_GROUP, "point_conversion_form=", ossl_ec_group_set_point_conversion_form, 1);
+
+ rb_define_method(cEC_GROUP, "seed", ossl_ec_group_get_seed, 0);
+ rb_define_method(cEC_GROUP, "seed=", ossl_ec_group_set_seed, 1);
+
+/* get/set GFp, GF2m */
+
+ rb_define_method(cEC_GROUP, "degree", ossl_ec_group_get_degree, 0);
+
+/* check* */
+
+
+ rb_define_method(cEC_GROUP, "to_pem", ossl_ec_group_to_pem, 0);
+ rb_define_method(cEC_GROUP, "to_der", ossl_ec_group_to_der, 0);
+ rb_define_method(cEC_GROUP, "to_text", ossl_ec_group_to_text, 0);
+
+
+ rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc);
+ rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1);
+ rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0);
+ rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1);
+ rb_define_alias(cEC_POINT, "==", "eql?");
+
+ rb_define_method(cEC_POINT, "infinity?", ossl_ec_point_is_at_infinity, 0);
+ rb_define_method(cEC_POINT, "on_curve?", ossl_ec_point_is_on_curve, 0);
+ rb_define_method(cEC_POINT, "make_affine!", ossl_ec_point_make_affine, 0);
+ rb_define_method(cEC_POINT, "invert!", ossl_ec_point_invert, 0);
+ rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
+/* all the other methods */
+
+ rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
+
+ no_copy(cEC);
+ no_copy(cEC_GROUP);
+ no_copy(cEC_POINT);
+}
+
+#else /* defined NO_EC */
+void Init_ossl_ec()
+{
+}
+#endif /* NO_EC */
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 669e84efca..9ac69e7ded 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -20,12 +20,7 @@
} while (0)
#define RSA_HAS_PRIVATE(rsa) ((rsa)->p && (rsa)->q)
-
-#ifdef OSSL_ENGINE_ENABLED
-# define RSA_PRIVATE(rsa) (RSA_HAS_PRIVATE(rsa) || (rsa)->engine)
-#else
-# define RSA_PRIVATE(rsa) RSA_HAS_PRIVATE(rsa)
-#endif
+#define RSA_PRIVATE(obj,rsa) (RSA_HAS_PRIVATE(rsa)||OSSL_PKEY_IS_PRIVATE(obj))
/*
* Classes
@@ -89,9 +84,19 @@ rsa_generate(int size, int exp)
NULL);
}
+/*
+ * call-seq:
+ * RSA.generate(size [, exponent]) -> rsa
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure.
+ * * +exponent+ is an odd number normally 3, 17, or 65537.
+ *
+ */
static VALUE
ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
{
+/* why does this method exist? why can't initialize take an optional exponent? */
RSA *rsa;
VALUE size, exp;
VALUE obj;
@@ -109,6 +114,20 @@ ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * RSA.new([size | encoded_key] [, pass]) -> rsa
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size.
+ * * +encoded_key+ is a string containing PEM or DER encoded key.
+ * * +pass+ is an optional string with the password to decrypt the encoded key.
+ *
+ * === Examples
+ * * RSA.new(2048) -> rsa
+ * * RSA.new(File.read("rsa.pem")) -> rsa
+ * * RSA.new(File.read("rsa.pem"), "mypassword") -> rsa
+ */
static VALUE
ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -119,8 +138,10 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
VALUE arg, pass;
GetPKey(self, pkey);
- rb_scan_args(argc, argv, "11", &arg, &pass);
- if (FIXNUM_P(arg)) {
+ if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
+ rsa = RSA_new();
+ }
+ else if (FIXNUM_P(arg)) {
rsa = rsa_generate(FIX2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2INT(pass));
if (!rsa) ossl_raise(eRSAError, NULL);
}
@@ -160,6 +181,13 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * rsa.public? -> true
+ *
+ * The return value is always true since every private key is also a public key.
+ *
+ */
static VALUE
ossl_rsa_is_public(VALUE self)
{
@@ -167,22 +195,38 @@ ossl_rsa_is_public(VALUE self)
GetPKeyRSA(self, pkey);
/*
- * SURPRISE! :-))
- * Every key is public at the same time!
+ * This method should check for n and e. BUG.
*/
return Qtrue;
}
+/*
+ * call-seq:
+ * rsa.private? -> true | false
+ *
+ */
static VALUE
ossl_rsa_is_private(VALUE self)
{
EVP_PKEY *pkey;
GetPKeyRSA(self, pkey);
-
- return (RSA_PRIVATE(pkey->pkey.rsa)) ? Qtrue : Qfalse;
+
+ return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * rsa.to_pem([cipher, pass]) -> aString
+ *
+ * === Parameters
+ * * +cipher+ is a Cipher object.
+ * * +pass+ is a string.
+ *
+ * === Examples
+ * * rsa.to_pem -> aString
+ * * rsa.to_pem(cipher, pass) -> aString
+ */
static VALUE
ossl_rsa_export(int argc, VALUE *argv, VALUE self)
{
@@ -222,95 +266,153 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self)
return str;
}
+/*
+ * call-seq:
+ * rsa.to_der -> aString
+ *
+ */
+static VALUE
+ossl_rsa_to_der(VALUE self)
+{
+ EVP_PKEY *pkey;
+ int (*i2d_func)_((const RSA*, unsigned char**));
+ unsigned char *p;
+ long len;
+ VALUE str;
+
+ GetPKeyRSA(self, pkey);
+ if(RSA_HAS_PRIVATE(pkey->pkey.rsa))
+ i2d_func = i2d_RSAPrivateKey;
+ else
+ i2d_func = i2d_RSAPublicKey;
+ if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0)
+ ossl_raise(eRSAError, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING_PTR(str);
+ if(i2d_func(pkey->pkey.rsa, &p) < 0)
+ ossl_raise(eRSAError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
#define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16)
+/*
+ * call-seq:
+ * rsa.public_encrypt(string [, padding]) -> aString
+ *
+ */
static VALUE
-ossl_rsa_public_encrypt(VALUE self, VALUE buffer)
+ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- int buf_len;
- VALUE str;
-
+ int buf_len, pad;
+ VALUE str, buffer, padding;
+
GetPKeyRSA(self, pkey);
+ rb_scan_args(argc, argv, "11", &buffer, &padding);
+ pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
- RSA_PKCS1_PADDING);
+ buf_len = RSA_public_encrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
+ RSTRING_PTR(str), pkey->pkey.rsa,
+ pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
+/*
+ * call-seq:
+ * rsa.public_decrypt(string [, padding]) -> aString
+ *
+ */
static VALUE
-ossl_rsa_public_decrypt(VALUE self, VALUE buffer)
+ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- int buf_len;
- VALUE str;
+ int buf_len, pad;
+ VALUE str, buffer, padding;
GetPKeyRSA(self, pkey);
+ rb_scan_args(argc, argv, "11", &buffer, &padding);
+ pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
- RSA_PKCS1_PADDING);
- if(buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ buf_len = RSA_public_decrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
+ RSTRING_PTR(str), pkey->pkey.rsa,
+ pad);
+ if (buf_len < 0) ossl_raise(eRSAError, NULL);
+ rb_str_set_len(str, buf_len);
return str;
}
+/*
+ * call-seq:
+ * rsa.private_encrypt(string [, padding]) -> aString
+ *
+ */
static VALUE
-ossl_rsa_private_encrypt(VALUE self, VALUE buffer)
+ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- int buf_len;
- VALUE str;
-
+ int buf_len, pad;
+ VALUE str, buffer, padding;
+
GetPKeyRSA(self, pkey);
- if (!RSA_PRIVATE(pkey->pkey.rsa)) {
- ossl_raise(eRSAError, "PRIVATE key needed for this operation!");
+ if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
+ ossl_raise(eRSAError, "private key needed.");
}
+ rb_scan_args(argc, argv, "11", &buffer, &padding);
+ pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
- RSA_PKCS1_PADDING);
+ buf_len = RSA_private_encrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
+ RSTRING_PTR(str), pkey->pkey.rsa,
+ pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
+
+/*
+ * call-seq:
+ * rsa.private_decrypt(string [, padding]) -> aString
+ *
+ */
static VALUE
-ossl_rsa_private_decrypt(VALUE self, VALUE buffer)
+ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- int buf_len;
- VALUE str;
+ int buf_len, pad;
+ VALUE str, buffer, padding;
GetPKeyRSA(self, pkey);
- if (!RSA_PRIVATE(pkey->pkey.rsa)) {
- ossl_raise(eRSAError, "Private RSA key needed!");
+ if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
+ ossl_raise(eRSAError, "private key needed.");
}
+ rb_scan_args(argc, argv, "11", &buffer, &padding);
+ pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
- RSA_PKCS1_PADDING);
+ buf_len = RSA_private_decrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
+ RSTRING_PTR(str), pkey->pkey.rsa,
+ pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
/*
+ * call-seq:
+ * rsa.params -> hash
+ *
* Stores all parameters of key to the hash
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -338,6 +440,9 @@ ossl_rsa_get_params(VALUE self)
}
/*
+ * call-seq:
+ * rsa.to_text -> aString
+ *
* Prints all parameters of key to buffer
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (It's up to you)
@@ -363,6 +468,9 @@ ossl_rsa_to_text(VALUE self)
}
/*
+ * call-seq:
+ * rsa.public_key -> aRSA
+ *
* Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY
*/
static VALUE
@@ -385,7 +493,6 @@ ossl_rsa_to_public_key(VALUE self)
/*
* TODO: Test me
-extern BN_CTX *ossl_bn_ctx;
static VALUE
ossl_rsa_blinding_on(VALUE self)
@@ -424,9 +531,16 @@ OSSL_PKEY_BN(rsa, iqmp);
/*
* INIT
*/
+#define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x))
+
void
Init_ossl_rsa()
{
+#if 0 /* let rdoc know about mOSSL and mPKey */
+ mOSSL = rb_define_module("OpenSSL");
+ mPKey = rb_define_module_under(mOSSL, "PKey");
+#endif
+
eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError);
cRSA = rb_define_class_under(mPKey, "RSA", cPKey);
@@ -440,11 +554,12 @@ Init_ossl_rsa()
rb_define_method(cRSA, "export", ossl_rsa_export, -1);
rb_define_alias(cRSA, "to_pem", "export");
rb_define_alias(cRSA, "to_s", "export");
+ rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0);
- rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, 1);
- rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, 1);
- rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, 1);
- rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, 1);
+ rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
+ rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
+ rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
+ rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
DEF_OSSL_PKEY_BN(cRSA, rsa, n);
DEF_OSSL_PKEY_BN(cRSA, rsa, e);
@@ -457,6 +572,11 @@ Init_ossl_rsa()
rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
+ DefRSAConst(PKCS1_PADDING);
+ DefRSAConst(SSLV23_PADDING);
+ DefRSAConst(NO_PADDING);
+ DefRSAConst(PKCS1_OAEP_PADDING);
+
/*
* TODO: Test it
rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);
@@ -465,11 +585,9 @@ Init_ossl_rsa()
}
#else /* defined NO_RSA */
-# warning >>> OpenSSL is compiled without RSA support <<<
void
Init_ossl_rsa()
{
- rb_warning("OpenSSL is compiled without RSA support");
}
#endif /* NO_RSA */
diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c
index ec9883d70a..ad830fbc98 100644
--- a/ext/openssl/ossl_rand.c
+++ b/ext/openssl/ossl_rand.c
@@ -27,84 +27,150 @@ VALUE eRandomError;
/*
* Private
*/
+
+/*
+ * call-seq:
+ * seed(str) -> str
+ *
+ */
static VALUE
ossl_rand_seed(VALUE self, VALUE str)
{
StringValue(str);
- RAND_seed(RSTRING(str)->ptr, RSTRING(str)->len);
+ RAND_seed(RSTRING_PTR(str), RSTRING_LEN(str));
return str;
}
+/*
+ * call-seq:
+ * add(str, entropy) -> self
+ *
+ */
+static VALUE
+ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
+{
+ StringValue(str);
+ RAND_add(RSTRING_PTR(str), RSTRING_LEN(str), NUM2DBL(entropy));
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * load_random_file(filename) -> true
+ *
+ */
static VALUE
ossl_rand_load_file(VALUE self, VALUE filename)
{
SafeStringValue(filename);
- if(!RAND_load_file(RSTRING(filename)->ptr, -1)) {
+ if(!RAND_load_file(RSTRING_PTR(filename), -1)) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * write_random_file(filename) -> true
+ *
+ */
static VALUE
ossl_rand_write_file(VALUE self, VALUE filename)
{
SafeStringValue(filename);
- if (RAND_write_file(RSTRING(filename)->ptr) == -1) {
+ if (RAND_write_file(RSTRING_PTR(filename)) == -1) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * random_bytes(length) -> aString
+ *
+ */
static VALUE
ossl_rand_bytes(VALUE self, VALUE len)
{
VALUE str;
-
- str = rb_str_new(0, FIX2INT(len));
- if (!RAND_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
+ int n = NUM2INT(len);
+
+ str = rb_str_new(0, n);
+ if (!RAND_bytes(RSTRING_PTR(str), n)) {
ossl_raise(eRandomError, NULL);
}
return str;
}
+/*
+ * call-seq:
+ * pseudo_bytes(length) -> aString
+ *
+ */
static VALUE
ossl_rand_pseudo_bytes(VALUE self, VALUE len)
{
VALUE str;
+ int n = NUM2INT(len);
- str = rb_str_new(0, FIX2INT(len));
- if (!RAND_pseudo_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
+ str = rb_str_new(0, n);
+ if (!RAND_pseudo_bytes(RSTRING_PTR(str), n)) {
ossl_raise(eRandomError, NULL);
}
return str;
}
+/*
+ * call-seq:
+ * egd(filename) -> true
+ *
+ */
static VALUE
ossl_rand_egd(VALUE self, VALUE filename)
{
SafeStringValue(filename);
- if(!RAND_egd(RSTRING(filename)->ptr)) {
+ if(!RAND_egd(RSTRING_PTR(filename))) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * egd_bytes(filename, length) -> true
+ *
+ */
static VALUE
ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
{
+ long n = NUM2INT(len);
+
SafeStringValue(filename);
- if (!RAND_egd_bytes(RSTRING(filename)->ptr, FIX2INT(len))) {
+ if (!RAND_egd_bytes(RSTRING_PTR(filename), n)) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * status? => true | false
+ *
+ * Return true if the PRNG has been seeded with enough data, false otherwise.
+ */
+static VALUE
+ossl_rand_status(VALUE self)
+{
+ return RAND_status() ? Qtrue : Qfalse;
+}
+
#define DEFMETH(class, name, func, argc) \
rb_define_method(class, name, func, argc); \
rb_define_singleton_method(class, name, func, argc);
@@ -115,16 +181,22 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
void
Init_ossl_rand()
{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
mRandom = rb_define_module_under(mOSSL, "Random");
eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
DEFMETH(mRandom, "seed", ossl_rand_seed, 1);
+ DEFMETH(mRandom, "random_add", ossl_rand_add, 2);
DEFMETH(mRandom, "load_random_file", ossl_rand_load_file, 1);
DEFMETH(mRandom, "write_random_file", ossl_rand_write_file, 1);
DEFMETH(mRandom, "random_bytes", ossl_rand_bytes, 1);
DEFMETH(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
DEFMETH(mRandom, "egd", ossl_rand_egd, 1);
DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
+ DEFMETH(mRandom, "status?", ossl_rand_status, 0)
}
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index cff32582ed..01b86fec27 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -3,6 +3,7 @@
* 'OpenSSL for Ruby' project
* Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org>
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ * Copyright (C) 2001-2007 Technorama Ltd. <oss-ruby@technorama.net>
* All rights reserved.
*/
/*
@@ -30,9 +31,6 @@ VALUE eSSLError;
VALUE cSSLContext;
VALUE cSSLSocket;
-/*
- * SSLContext class
- */
#define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
#define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
#define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
@@ -45,6 +43,9 @@ VALUE cSSLSocket;
#define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v))
#define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v))
#define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v))
+#define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
+#define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v))
+#define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_get((o),"@session_id_context"(v))
#define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
#define ossl_sslctx_get_key(o) rb_iv_get((o),"@key")
@@ -58,13 +59,40 @@ VALUE cSSLSocket;
#define ossl_sslctx_get_options(o) rb_iv_get((o),"@options")
#define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store")
#define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert")
+#define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
+#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
+#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
-static char *ossl_sslctx_attrs[] = {
+static const char *ossl_sslctx_attrs[] = {
"cert", "key", "client_ca", "ca_file", "ca_path",
"timeout", "verify_mode", "verify_depth",
- "verify_callback", "options", "cert_store", "extra_chain_cert"
+ "verify_callback", "options", "cert_store", "extra_chain_cert",
+ "client_cert_cb", "tmp_dh_callback", "session_id_context",
+ "session_get_cb", "session_new_cb", "session_remove_cb",
};
+#define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
+#define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
+#define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close")
+#define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509")
+#define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
+#define ossl_ssl_get_tmp_dh(o) rb_iv_get((o),"@tmp_dh")
+
+#define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
+#define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
+#define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
+#define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v))
+#define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
+#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
+
+static const char *ossl_ssl_attr_readers[] = { "io", "context", };
+static const char *ossl_ssl_attrs[] = { "sync_close", };
+
+ID ID_callback_state;
+
+/*
+ * SSLContext class
+ */
struct {
const char *name;
SSL_METHOD *(*func)(void);
@@ -87,6 +115,9 @@ struct {
int ossl_ssl_ex_vcb_idx;
int ossl_ssl_ex_store_p;
+int ossl_ssl_ex_ptr_idx;
+int ossl_ssl_ex_client_cert_cb_idx;
+int ossl_ssl_ex_tmp_dh_callback_idx;
static void
ossl_sslctx_free(SSL_CTX *ctx)
@@ -111,24 +142,13 @@ ossl_sslctx_s_alloc(VALUE klass)
}
static VALUE
-ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
+ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
{
- VALUE ssl_method;
SSL_METHOD *method = NULL;
- SSL_CTX *ctx;
+ const char *s;
int i;
- char *s;
-
- Data_Get_Struct(self, SSL_CTX, ctx);
- for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
- char buf[32];
- snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
- rb_iv_set(self, buf, Qnil);
- }
- if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
- return self;
- }
+ SSL_CTX *ctx;
if(TYPE(ssl_method) == T_SYMBOL)
s = rb_id2name(SYM2ID(ssl_method));
else
@@ -142,13 +162,126 @@ ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
if (!method) {
ossl_raise(rb_eArgError, "unknown SSL method `%s'.", s);
}
+ Data_Get_Struct(self, SSL_CTX, ctx);
if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
ossl_raise(eSSLError, "SSL_CTX_set_ssl_version:");
}
+ return ssl_method;
+}
+
+/*
+ * call-seq:
+ * SSLContext.new => ctx
+ * SSLContext.new(:TLSv1) => ctx
+ * SSLContext.new("SSLv23_client") => ctx
+ *
+ * You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
+ */
+static VALUE
+ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE ssl_method;
+ int i;
+
+ for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
+ char buf[32];
+ snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
+ rb_iv_set(self, buf, Qnil);
+ }
+ if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
+ return self;
+ }
+ ossl_sslctx_set_ssl_version(self, ssl_method);
+
return self;
}
+static VALUE
+ossl_call_client_cert_cb(VALUE obj)
+{
+ VALUE cb, ary, cert, key;
+ SSL *ssl;
+
+ Data_Get_Struct(obj, SSL, ssl);
+ cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx);
+ if (NIL_P(cb)) return Qfalse;
+ ary = rb_funcall(cb, rb_intern("call"), 1, obj);
+ Check_Type(ary, T_ARRAY);
+ GetX509CertPtr(cert = rb_ary_entry(ary, 0));
+ GetPKeyPtr(key = rb_ary_entry(ary, 1));
+ ossl_ssl_set_x509(obj, cert);
+ ossl_ssl_set_key(obj, key);
+
+ return Qtrue;
+}
+
+static int
+ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
+{
+ VALUE obj;
+ int status, success;
+
+ obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ success = rb_protect((VALUE(*)_((VALUE)))ossl_call_client_cert_cb,
+ obj, &status);
+ if (status || !success) return 0;
+ *x509 = DupX509CertPtr(ossl_ssl_get_x509(obj));
+ *pkey = DupPKeyPtr(ossl_ssl_get_key(obj));
+
+ return 1;
+}
+
+#if !defined(OPENSSL_NO_DH)
+static VALUE
+ossl_call_tmp_dh_callback(VALUE *args)
+{
+ SSL *ssl;
+ VALUE cb, dh;
+ EVP_PKEY *pkey;
+
+ Data_Get_Struct(args[0], SSL, ssl);
+ cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx);
+ if (NIL_P(cb)) return Qfalse;
+ dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]);
+ pkey = GetPKeyPtr(dh);
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse;
+ ossl_ssl_set_tmp_dh(args[0], dh);
+
+ return Qtrue;
+}
+
+static DH*
+ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
+{
+ VALUE args[3];
+ int status, success;
+
+ args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ args[1] = INT2FIX(is_export);
+ args[2] = INT2FIX(keylength);
+ success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback,
+ (VALUE)args, &status);
+ if (status || !success) return NULL;
+
+ return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh;
+}
+
+static DH*
+ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
+{
+ rb_warning("using default DH parameters.");
+
+ switch(keylength){
+ case 512:
+ return OSSL_DEFAULT_DH_512;
+ case 1024:
+ return OSSL_DEFAULT_DH_1024;
+ }
+ return NULL;
+}
+#endif /* OPENSSL_NO_DH */
+
static int
ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
@@ -162,6 +295,143 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
}
static VALUE
+ossl_call_session_get_cb(VALUE ary)
+{
+ VALUE ssl_obj, sslctx_obj, cb, ret;
+
+ Check_Type(ary, T_ARRAY);
+ ssl_obj = rb_ary_entry(ary, 0);
+
+ sslctx_obj = rb_iv_get(ssl_obj, "@context");
+ if (NIL_P(sslctx_obj)) return Qnil;
+ cb = rb_iv_get(sslctx_obj, "@session_get_cb");
+ if (NIL_P(cb)) return Qnil;
+
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
+}
+
+/* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
+static SSL_SESSION *
+ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
+{
+ VALUE ary, ssl_obj, ret_obj;
+ SSL_SESSION *sess;
+ void *ptr;
+ int state = 0;
+
+ OSSL_Debug("SSL SESSION get callback entered");
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
+ return NULL;
+ ssl_obj = (VALUE)ptr;
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, ssl_obj);
+ rb_ary_push(ary, rb_str_new(buf, len));
+
+ ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_get_cb, ary, &state);
+ if (state) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
+ return NULL;
+ }
+ if (!rb_obj_is_instance_of(ret_obj, cSSLSession))
+ return NULL;
+
+ SafeGetSSLSession(ret_obj, sess);
+ *copy = 1;
+
+ return sess;
+}
+
+static VALUE
+ossl_call_session_new_cb(VALUE ary)
+{
+ VALUE ssl_obj, sslctx_obj, cb, ret;
+
+ Check_Type(ary, T_ARRAY);
+ ssl_obj = rb_ary_entry(ary, 0);
+
+ sslctx_obj = rb_iv_get(ssl_obj, "@context");
+ if (NIL_P(sslctx_obj)) return Qnil;
+ cb = rb_iv_get(sslctx_obj, "@session_new_cb");
+ if (NIL_P(cb)) return Qnil;
+
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
+}
+
+/* return 1 normal. return 0 removes the session */
+static int
+ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
+{
+ VALUE ary, ssl_obj, sess_obj, ret_obj;
+ void *ptr;
+ int state = 0;
+
+ OSSL_Debug("SSL SESSION new callback entered");
+
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
+ return 1;
+ ssl_obj = (VALUE)ptr;
+ sess_obj = rb_obj_alloc(cSSLSession);
+ CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ DATA_PTR(sess_obj) = sess;
+
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, ssl_obj);
+ rb_ary_push(ary, sess_obj);
+
+ ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
+ if (state) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
+ return 0; /* what should be returned here??? */
+ }
+
+ return RTEST(ret_obj) ? 1 : 0;
+}
+
+static VALUE
+ossl_call_session_remove_cb(VALUE ary)
+{
+ VALUE sslctx_obj, cb, ret;
+
+ Check_Type(ary, T_ARRAY);
+ sslctx_obj = rb_ary_entry(ary, 0);
+
+ cb = rb_iv_get(sslctx_obj, "@session_remove_cb");
+ if (NIL_P(cb)) return Qnil;
+
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
+}
+
+static void
+ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
+{
+ VALUE ary, sslctx_obj, sess_obj, ret_obj;
+ void *ptr;
+ int state = 0;
+
+ OSSL_Debug("SSL SESSION remove callback entered");
+
+ if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL)
+ return;
+ sslctx_obj = (VALUE)ptr;
+ sess_obj = rb_obj_alloc(cSSLSession);
+ CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ DATA_PTR(sess_obj) = sess;
+
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, sslctx_obj);
+ rb_ary_push(ary, sess_obj);
+
+ ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
+ if (state) {
+/*
+ the SSL_CTX is frozen, nowhere to save state.
+ there is no common accessor method to check it either.
+ rb_ivar_set(sslctx_obj, ID_callback_state, INT2NUM(state));
+*/
+ }
+}
+
+static VALUE
ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
{
X509 *x509;
@@ -176,6 +446,14 @@ ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
return i;
}
+/*
+ * call-seq:
+ * ctx.setup => Qtrue # first time
+ * ctx.setup => nil # thereafter
+ *
+ * This method is called automatically when a new SSLSocket is created.
+ * Normally you do not need to call this method (unless you are writing an extension in C).
+ */
static VALUE
ossl_sslctx_setup(VALUE self)
{
@@ -190,6 +468,16 @@ ossl_sslctx_setup(VALUE self)
if(OBJ_FROZEN(self)) return Qnil;
Data_Get_Struct(self, SSL_CTX, ctx);
+#if !defined(OPENSSL_NO_DH)
+ if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
+ }
+ else{
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
+ }
+#endif
+ SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self);
+
val = ossl_sslctx_get_cert_store(self);
if(!NIL_P(val)){
/*
@@ -205,7 +493,7 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_extra_cert(self);
if(!NIL_P(val)){
- rb_iterate(rb_each, val, ossl_sslctx_add_extra_chain_cert_i, self);
+ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
}
/* private key may be bundled in certificate file. */
@@ -230,8 +518,8 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_client_ca(self);
if(!NIL_P(val)){
if(TYPE(val) == T_ARRAY){
- for(i = 0; i < RARRAY(val)->len; i++){
- client_ca = GetX509CertPtr(RARRAY(val)->ptr[i]);
+ for(i = 0; i < RARRAY_LEN(val); i++){
+ client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]);
if (!SSL_CTX_add_client_CA(ctx, client_ca)){
/* Copies X509_NAME => FREE it. */
ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
@@ -259,6 +547,8 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_verify_mode(self);
verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
+ if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
+ SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
val = ossl_sslctx_get_timeout(self);
if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
@@ -270,6 +560,27 @@ ossl_sslctx_setup(VALUE self)
if(!NIL_P(val)) SSL_CTX_set_options(ctx, NUM2LONG(val));
rb_obj_freeze(self);
+ val = ossl_sslctx_get_sess_id_ctx(self);
+ if (!NIL_P(val)){
+ StringValue(val);
+ if (!SSL_CTX_set_session_id_context(ctx, RSTRING_PTR(val),
+ RSTRING_LEN(val))){
+ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
+ }
+ }
+
+ if (RTEST(rb_iv_get(self, "@session_get_cb"))) {
+ SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
+ OSSL_Debug("SSL SESSION get callback added");
+ }
+ if (RTEST(rb_iv_get(self, "@session_new_cb"))) {
+ SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
+ OSSL_Debug("SSL SESSION new callback added");
+ }
+ if (RTEST(rb_iv_get(self, "@session_remove_cb"))) {
+ SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
+ OSSL_Debug("SSL SESSION remove callback added");
+ }
return Qtrue;
}
@@ -289,6 +600,10 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
return ary;
}
+/*
+ * call-seq:
+ * ctx.ciphers => [[name, version, bits, alg_bits], ...]
+ */
static VALUE
ossl_sslctx_get_ciphers(VALUE self)
{
@@ -317,6 +632,12 @@ ossl_sslctx_get_ciphers(VALUE self)
return ary;
}
+/*
+ * call-seq:
+ * ctx.ciphers = "cipher1:cipher2:..."
+ * ctx.ciphers = [name, ...]
+ * ctx.ciphers = [[name, version, bits, alg_bits], ...]
+ */
static VALUE
ossl_sslctx_set_ciphers(VALUE self, VALUE v)
{
@@ -325,46 +646,197 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
int i;
rb_check_frozen(self);
- Data_Get_Struct(self, SSL_CTX, ctx);
- if(!ctx){
- ossl_raise(eSSLError, "SSL_CTX is not initialized.");
- return Qnil;
- }
-
- if (TYPE(v) == T_ARRAY) {
- str = rb_str_new2(NULL);
- for (i = 0; i < RARRAY(v)->len; i++) {
+ if (NIL_P(v))
+ return v;
+ else if (TYPE(v) == T_ARRAY) {
+ str = rb_str_new(0, 0);
+ for (i = 0; i < RARRAY_LEN(v); i++) {
elem = rb_ary_entry(v, i);
if (TYPE(elem) == T_ARRAY) elem = rb_ary_entry(elem, 0);
elem = rb_String(elem);
rb_str_append(str, elem);
- if (i < RARRAY(v)->len-1) rb_str_cat2(str, ":");
+ if (i < RARRAY_LEN(v)-1) rb_str_cat2(str, ":");
}
} else {
str = v;
StringValue(str);
}
- if (!SSL_CTX_set_cipher_list(ctx, RSTRING(str)->ptr)) {
- ossl_raise(eSSLError, "SSL_CTX_set_ciphers:");
+ Data_Get_Struct(self, SSL_CTX, ctx);
+ if(!ctx){
+ ossl_raise(eSSLError, "SSL_CTX is not initialized.");
+ return Qnil;
}
- return Qnil;
+ if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
+ ossl_raise(eSSLError, "SSL_CTX_set_cipher_list:");
+ }
+
+ return v;
}
+
/*
- * SSLSocket class
+ * call-seq:
+ * ctx.session_add(session) -> true | false
+ *
*/
-#define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
-#define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
-#define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close")
+static VALUE
+ossl_sslctx_session_add(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+ SSL_SESSION *sess;
-#define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
-#define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
-#define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
+ Data_Get_Struct(self, SSL_CTX, ctx);
+ SafeGetSSLSession(arg, sess);
-static char *ossl_ssl_attr_readers[] = { "io", "context", };
-static char *ossl_ssl_attrs[] = { "sync_close", };
+ return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
+}
+/*
+ * call-seq:
+ * ctx.session_remove(session) -> true | false
+ *
+ */
+static VALUE
+ossl_sslctx_session_remove(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+ SSL_SESSION *sess;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+ SafeGetSSLSession(arg, sess);
+
+ return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_mode -> integer
+ *
+ */
+static VALUE
+ossl_sslctx_get_session_cache_mode(VALUE self)
+{
+ SSL_CTX *ctx;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_mode=(integer) -> integer
+ *
+ */
+static VALUE
+ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));
+
+ return arg;
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_size -> integer
+ *
+ */
+static VALUE
+ossl_sslctx_get_session_cache_size(VALUE self)
+{
+ SSL_CTX *ctx;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_size=(integer) -> integer
+ *
+ */
+static VALUE
+ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));
+
+ return arg;
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_stats -> Hash
+ *
+ */
+static VALUE
+ossl_sslctx_get_session_cache_stats(VALUE self)
+{
+ SSL_CTX *ctx;
+ VALUE hash;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ hash = rb_hash_new();
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect")), LONG2NUM(SSL_CTX_sess_connect(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_good")), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_renegotiate")), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept")), LONG2NUM(SSL_CTX_sess_accept(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_good")), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_renegotiate")), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_hits")), LONG2NUM(SSL_CTX_sess_hits(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cb_hits")), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_misses")), LONG2NUM(SSL_CTX_sess_misses(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_full")), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("timeouts")), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
+
+ return hash;
+}
+
+
+/*
+ * call-seq:
+ * ctx.flush_sessions(time | nil) -> self
+ *
+ */
+static VALUE
+ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
+{
+ VALUE arg1;
+ SSL_CTX *ctx;
+ time_t tm = 0;
+ int cb_state;
+
+ rb_scan_args(argc, argv, "01", &arg1);
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ if (NIL_P(arg1)) {
+ tm = time(0);
+ } else if (rb_obj_is_instance_of(arg1, rb_cTime)) {
+ tm = NUM2LONG(rb_funcall(arg1, rb_intern("to_i"), 0));
+ } else {
+ rb_raise(rb_eArgError, "arg must be Time or nil");
+ }
+
+ SSL_CTX_flush_sessions(ctx, tm);
+
+ return self;
+}
+
+/*
+ * SSLSocket class
+ */
static void
ossl_ssl_shutdown(SSL *ssl)
{
@@ -387,6 +859,20 @@ ossl_ssl_s_alloc(VALUE klass)
return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL);
}
+/*
+ * call-seq:
+ * SSLSocket.new(io) => aSSLSocket
+ * SSLSocket.new(io, ctx) => aSSLSocket
+ *
+ * === Parameters
+ * * +io+ is a real ruby IO object. Not an IO like object that responds to read/write.
+ * * +ctx+ is an OpenSSLSSL::SSLContext.
+ *
+ * The OpenSSL::Buffering module provides additional IO methods.
+ *
+ * This method will freeze the SSLContext if one is provided;
+ * however, session management is still allowed in the frozen SSLContext.
+ */
static VALUE
ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -409,10 +895,10 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
static VALUE
ossl_ssl_setup(VALUE self)
{
- VALUE io, v_ctx;
+ VALUE io, v_ctx, cb;
SSL_CTX *ctx;
SSL *ssl;
- OpenFile *fptr;
+ rb_io_t *fptr;
Data_Get_Struct(self, SSL, ssl);
if(!ssl){
@@ -429,118 +915,197 @@ ossl_ssl_setup(VALUE self)
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
rb_io_check_writable(fptr);
- SSL_set_fd(ssl, TO_SOCKET(fileno(fptr->f)));
+ SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
+ SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
+ cb = ossl_sslctx_get_verify_cb(v_ctx);
+ SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
+ cb = ossl_sslctx_get_client_cert_cb(v_ctx);
+ SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
+ cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
+ SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
}
return Qtrue;
}
+#ifdef _WIN32
+#define ssl_get_error(ssl, ret) (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
+#else
+#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
+#endif
+
static VALUE
-ossl_ssl_connect(VALUE self)
+ossl_start_ssl(VALUE self, int (*func)(), const char *funcname)
{
SSL *ssl;
- VALUE cb;
+ rb_io_t *fptr;
+ int ret, ret2;
+ VALUE cb_state;
+
+ rb_ivar_set(self, ID_callback_state, Qnil);
- ossl_ssl_setup(self);
Data_Get_Struct(self, SSL, ssl);
- cb = ossl_sslctx_get_verify_cb(ossl_ssl_get_ctx(self));
- SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)cb);
- if (SSL_connect(ssl) <= 0) {
- ossl_raise(eSSLError, "SSL_connect:");
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
+ for(;;){
+ if((ret = func(ssl)) > 0) break;
+ switch((ret2 = ssl_get_error(ssl, ret))){
+ case SSL_ERROR_WANT_WRITE:
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
+ continue;
+ case SSL_ERROR_WANT_READ:
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
+ continue;
+ case SSL_ERROR_SYSCALL:
+ if (errno) rb_sys_fail(funcname);
+ ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
+ default:
+ ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
+ }
}
+ cb_state = rb_ivar_get(self, ID_callback_state);
+ if (!NIL_P(cb_state))
+ rb_jump_tag(NUM2INT(cb_state));
+
return self;
}
+/*
+ * call-seq:
+ * ssl.connect => self
+ */
static VALUE
-ossl_ssl_accept(VALUE self)
+ossl_ssl_connect(VALUE self)
{
- SSL *ssl;
- VALUE cb;
-
ossl_ssl_setup(self);
- Data_Get_Struct(self, SSL, ssl);
- cb = ossl_sslctx_get_verify_cb(ossl_ssl_get_ctx(self));
- SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)cb);
- if (SSL_accept(ssl) <= 0) {
- ossl_raise(eSSLError, "SSL_accept:");
- }
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect");
+}
- return self;
+/*
+ * call-seq:
+ * ssl.accept => self
+ */
+static VALUE
+ossl_ssl_accept(VALUE self)
+{
+ ossl_ssl_setup(self);
+ return ossl_start_ssl(self, SSL_accept, "SSL_accept");
}
+/*
+ * call-seq:
+ * ssl.sysread(length) => string
+ * ssl.sysread(length, buffer) => buffer
+ *
+ * === Parameters
+ * * +length+ is a positive integer.
+ * * +buffer+ is a string used to store the result.
+ */
static VALUE
-ossl_ssl_read(VALUE self, VALUE len)
+ossl_ssl_read(int argc, VALUE *argv, VALUE self)
{
SSL *ssl;
int ilen, nread = 0;
- VALUE str;
- OpenFile *fptr;
+ VALUE len, str;
+ rb_io_t *fptr;
- Data_Get_Struct(self, SSL, ssl);
+ rb_scan_args(argc, argv, "11", &len, &str);
ilen = NUM2INT(len);
- str = rb_str_new(0, ilen);
+ if(NIL_P(str)) str = rb_str_new(0, ilen);
+ else{
+ StringValue(str);
+ rb_str_modify(str);
+ rb_str_resize(str, ilen);
+ }
+ if(ilen == 0) return str;
+ Data_Get_Struct(self, SSL, ssl);
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
if (ssl) {
- nread = SSL_read(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
- if (nread < 0) {
- ossl_raise(eSSLError, "SSL_read:");
+ if(SSL_pending(ssl) <= 0)
+ rb_thread_wait_fd(FPTR_TO_FD(fptr));
+ for (;;){
+ nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
+ switch(ssl_get_error(ssl, nread)){
+ case SSL_ERROR_NONE:
+ goto end;
+ case SSL_ERROR_ZERO_RETURN:
+ rb_eof_error();
+ case SSL_ERROR_WANT_WRITE:
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
+ continue;
+ case SSL_ERROR_WANT_READ:
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
+ continue;
+ case SSL_ERROR_SYSCALL:
+ if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
+ rb_sys_fail(0);
+ default:
+ ossl_raise(eSSLError, "SSL_read:");
+ }
}
}
else {
+ ID id_sysread = rb_intern("sysread");
rb_warning("SSL session is not started yet.");
- GetOpenFile(ossl_ssl_get_io(self), fptr);
- rb_io_check_readable(fptr);
- TRAP_BEG;
- nread = read(fileno(fptr->f), RSTRING(str)->ptr, RSTRING(str)->len);
- TRAP_END;
- if(nread < 0) {
- ossl_raise(eSSLError, "read:%s", strerror(errno));
- }
+ return rb_funcall(ossl_ssl_get_io(self), id_sysread, 2, len, str);
}
- if (nread == 0) {
- ossl_raise(rb_eEOFError, "End of file reached");
- }
-
- RSTRING(str)->len = nread;
- RSTRING(str)->ptr[nread] = 0;
+ end:
+ rb_str_set_len(str, nread);
OBJ_TAINT(str);
return str;
}
+/*
+ * call-seq:
+ * ssl.syswrite(string) => integer
+ */
static VALUE
ossl_ssl_write(VALUE self, VALUE str)
{
SSL *ssl;
int nwrite = 0;
- OpenFile *fptr;
- FILE *fp;
+ rb_io_t *fptr;
- Data_Get_Struct(self, SSL, ssl);
StringValue(str);
+ Data_Get_Struct(self, SSL, ssl);
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
if (ssl) {
- nwrite = SSL_write(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
- if (nwrite <= 0) {
- ossl_raise(eSSLError, "SSL_write:");
+ for (;;){
+ nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
+ switch(ssl_get_error(ssl, nwrite)){
+ case SSL_ERROR_NONE:
+ goto end;
+ case SSL_ERROR_WANT_WRITE:
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
+ continue;
+ case SSL_ERROR_WANT_READ:
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
+ continue;
+ case SSL_ERROR_SYSCALL:
+ if (errno) rb_sys_fail(0);
+ default:
+ ossl_raise(eSSLError, "SSL_write:");
+ }
}
}
else {
+ ID id_syswrite = rb_intern("syswrite");
rb_warning("SSL session is not started yet.");
- GetOpenFile(ossl_ssl_get_io(self), fptr);
- rb_io_check_writable(fptr);
- fp = GetWriteFile(fptr);
- nwrite = write(fileno(fp), RSTRING(str)->ptr, RSTRING(str)->len);
- if (nwrite < 0) {
- ossl_raise(eSSLError, "write:%s", strerror(errno));
- }
+ return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str);
}
+ end:
return INT2NUM(nwrite);
}
+/*
+ * call-seq:
+ * ssl.sysclose => nil
+ */
static VALUE
ossl_ssl_close(VALUE self)
{
@@ -554,6 +1119,10 @@ ossl_ssl_close(VALUE self)
return Qnil;
}
+/*
+ * call-seq:
+ * ssl.cert => cert or nil
+ */
static VALUE
ossl_ssl_get_cert(VALUE self)
{
@@ -578,6 +1147,10 @@ ossl_ssl_get_cert(VALUE self)
return ossl_x509_new(cert);
}
+/*
+ * call-seq:
+ * ssl.peer_cert => cert or nil
+ */
static VALUE
ossl_ssl_get_peer_cert(VALUE self)
{
@@ -603,6 +1176,10 @@ ossl_ssl_get_peer_cert(VALUE self)
return obj;
}
+/*
+ * call-seq:
+ * ssl.peer_cert_chain => [cert, ...] or nil
+ */
static VALUE
ossl_ssl_get_peer_cert_chain(VALUE self)
{
@@ -629,6 +1206,10 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
return ary;
}
+/*
+ * call-seq:
+ * ssl.cipher => [name, version, bits, alg_bits]
+ */
static VALUE
ossl_ssl_get_cipher(VALUE self)
{
@@ -645,6 +1226,10 @@ ossl_ssl_get_cipher(VALUE self)
return ossl_ssl_cipher_to_ary(cipher);
}
+/*
+ * call-seq:
+ * ssl.state => string
+ */
static VALUE
ossl_ssl_get_state(VALUE self)
{
@@ -664,27 +1249,166 @@ ossl_ssl_get_state(VALUE self)
return ret;
}
+/*
+ * call-seq:
+ * ssl.pending => integer
+ */
+static VALUE
+ossl_ssl_pending(VALUE self)
+{
+ SSL *ssl;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ return INT2NUM(SSL_pending(ssl));
+}
+
+/*
+ * call-seq:
+ * ssl.session_reused? -> true | false
+ *
+ */
+static VALUE
+ossl_ssl_session_reused(VALUE self)
+{
+ SSL *ssl;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ switch(SSL_session_reused(ssl)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(eSSLError, "SSL_session_reused");
+ }
+}
+
+/*
+ * call-seq:
+ * ssl.session = session -> session
+ *
+ */
+static VALUE
+ossl_ssl_set_session(VALUE self, VALUE arg1)
+{
+ SSL *ssl;
+ SSL_SESSION *sess;
+
+/* why is ossl_ssl_setup delayed? */
+ ossl_ssl_setup(self);
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ SafeGetSSLSession(arg1, sess);
+
+ if (SSL_set_session(ssl, sess) != 1)
+ ossl_raise(eSSLError, "SSL_set_session");
+
+ return arg1;
+}
+
+static VALUE
+ossl_ssl_get_verify_result(VALUE self)
+{
+ SSL *ssl;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ return INT2FIX(SSL_get_verify_result(ssl));
+}
+
void
Init_ossl_ssl()
{
int i;
+ VALUE ary;
+
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
+ ID_callback_state = rb_intern("@callback_state");
ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_vcb_idx",0,0,0);
ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,"ossl_ssl_ex_store_p",0,0,0);
+ ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_ptr_idx",0,0,0);
+ ossl_ssl_ex_client_cert_cb_idx =
+ SSL_get_ex_new_index(0,"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
+ ossl_ssl_ex_tmp_dh_callback_idx =
+ SSL_get_ex_new_index(0,"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
mSSL = rb_define_module_under(mOSSL, "SSL");
eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
- /* class SSLContext */
+ Init_ossl_ssl_session();
+
+ /* class SSLContext
+ *
+ * The following attributes are available but don't show up in rdoc.
+ * All attributes must be set before calling SSLSocket.new(io, ctx).
+ * * ssl_version, cert, key, client_ca, ca_file, ca_path, timeout,
+ * * verify_mode, verify_depth client_cert_cb, tmp_dh_callback,
+ * * session_id_context, session_add_cb, session_new_cb, session_remove_cb
+ */
cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
for(i = 0; i < numberof(ossl_sslctx_attrs); i++)
rb_attr(cSSLContext, rb_intern(ossl_sslctx_attrs[i]), 1, 1, Qfalse);
+ rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
+ rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
- /* class SSLSocket */
+ rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
+
+
+ rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
+ rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
+ rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER));
+ rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR));
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE));
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL));
+ rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
+ rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
+ rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
+ rb_define_method(cSSLContext, "session_cache_mode=", ossl_sslctx_set_session_cache_mode, 1);
+ rb_define_method(cSSLContext, "session_cache_size", ossl_sslctx_get_session_cache_size, 0);
+ rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1);
+ rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0);
+ rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1);
+
+ ary = rb_ary_new2(numberof(ossl_ssl_method_tab));
+ for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
+ rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name)));
+ }
+ rb_obj_freeze(ary);
+ /* holds a list of available SSL/TLS methods */
+ rb_define_const(cSSLContext, "METHODS", ary);
+
+ /* class SSLSocket
+ *
+ * The following attributes are available but don't show up in rdoc.
+ * * io, context, sync_close
+ *
+ */
cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
for(i = 0; i < numberof(ossl_ssl_attr_readers); i++)
@@ -695,7 +1419,7 @@ Init_ossl_ssl()
rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
- rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, 1);
+ rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0);
rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0);
@@ -703,6 +1427,10 @@ Init_ossl_ssl()
rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
+ rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
+ rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
+ rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
+ rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x))
@@ -738,6 +1466,9 @@ Init_ossl_ssl()
ossl_ssl_def_const(OP_NO_SSLv2);
ossl_ssl_def_const(OP_NO_SSLv3);
ossl_ssl_def_const(OP_NO_TLSv1);
+#if defined(SSL_OP_NO_TICKET)
+ ossl_ssl_def_const(OP_NO_TICKET);
+#endif
ossl_ssl_def_const(OP_PKCS1_CHECK_1);
ossl_ssl_def_const(OP_PKCS1_CHECK_2);
ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG);
diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h
index 5929eef856..487f41216c 100644
--- a/ext/openssl/ossl_ssl.h
+++ b/ext/openssl/ossl_ssl.h
@@ -11,11 +11,26 @@
#if !defined(_OSSL_SSL_H_)
#define _OSSL_SSL_H_
+#define GetSSLSession(obj, sess) do { \
+ Data_Get_Struct(obj, SSL_SESSION, sess); \
+ if (!sess) { \
+ ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
+ } \
+} while (0)
+
+#define SafeGetSSLSession(obj, sess) do { \
+ OSSL_Check_Kind(obj, cSSLSession); \
+ GetSSLSession(obj, sess); \
+} while (0)
+
extern VALUE mSSL;
extern VALUE eSSLError;
extern VALUE cSSLSocket;
extern VALUE cSSLContext;
+extern VALUE cSSLSession;
void Init_ossl_ssl(void);
+void Init_ossl_ssl_session(void);
#endif /* _OSSL_SSL_H_ */
+
diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c
new file mode 100644
index 0000000000..63c2bbb87a
--- /dev/null
+++ b/ext/openssl/ossl_ssl_session.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2004-2007 Technorama Ltd. <oss-ruby@technorama.net>
+ */
+
+#include "ossl.h"
+
+#define GetSSLSession(obj, sess) do { \
+ Data_Get_Struct(obj, SSL_SESSION, sess); \
+ if (!sess) { \
+ ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
+ } \
+} while (0)
+
+#define SafeGetSSLSession(obj, sess) do { \
+ OSSL_Check_Kind(obj, cSSLSession); \
+ GetSSLSession(obj, sess); \
+} while (0)
+
+
+VALUE cSSLSession;
+static VALUE eSSLSession;
+
+static VALUE ossl_ssl_session_alloc(VALUE klass)
+{
+ return Data_Wrap_Struct(klass, 0, SSL_SESSION_free, NULL);
+}
+
+/*
+ * call-seq:
+ * Session.new(SSLSocket | string) => session
+ *
+ * === Parameters
+ * +SSLSocket+ is an OpenSSL::SSL::SSLSocket
+ * +string+ must be a DER or PEM encoded Session.
+*/
+static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
+{
+ SSL_SESSION *ctx = NULL;
+ VALUE obj;
+ unsigned char *p;
+
+ if (RDATA(self)->data)
+ ossl_raise(eSSLSession, "SSL Session already initialized");
+
+ if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
+ SSL *ssl;
+
+ Data_Get_Struct(arg1, SSL, ssl);
+
+ if (!ssl || (ctx = SSL_get1_session(ssl)) == NULL)
+ ossl_raise(eSSLSession, "no session available");
+ } else {
+ BIO *in = ossl_obj2bio(arg1);
+
+ ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
+
+ if (!ctx) {
+ BIO_reset(in);
+ ctx = d2i_SSL_SESSION_bio(in, NULL);
+ }
+
+ BIO_free(in);
+
+ if (!ctx)
+ ossl_raise(rb_eArgError, "unknown type");
+ }
+
+ /* should not happen */
+ if (ctx == NULL)
+ ossl_raise(eSSLSession, "ctx not set - internal error");
+
+ RDATA(self)->data = ctx;
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * session1 == session2 -> boolean
+ *
+*/
+static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
+{
+ SSL_SESSION *ctx1, *ctx2;
+
+ GetSSLSession(val1, ctx1);
+ SafeGetSSLSession(val2, ctx2);
+
+ switch (SSL_SESSION_cmp(ctx1, ctx2)) {
+ case 0: return Qtrue;
+ default: return Qfalse;
+ }
+}
+
+/*
+ * call-seq:
+ * session.time -> Time
+ *
+*/
+static VALUE ossl_ssl_session_get_time(VALUE self)
+{
+ SSL_SESSION *ctx;
+ time_t t;
+
+ GetSSLSession(self, ctx);
+
+ t = SSL_SESSION_get_time(ctx);
+
+ if (t == 0)
+ return Qnil;
+
+ return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t));
+}
+
+/*
+ * call-seq:
+ * session.timeout -> integer
+ *
+ * How long until the session expires in seconds.
+ *
+*/
+static VALUE ossl_ssl_session_get_timeout(VALUE self)
+{
+ SSL_SESSION *ctx;
+ time_t t;
+
+ GetSSLSession(self, ctx);
+
+ t = SSL_SESSION_get_timeout(ctx);
+
+ return ULONG2NUM(t);
+}
+
+#define SSLSESSION_SET_TIME(func) \
+ static VALUE ossl_ssl_session_set_##func(VALUE self, VALUE time_v) \
+ { \
+ SSL_SESSION *ctx; \
+ time_t t; \
+ \
+ GetSSLSession(self, ctx); \
+ \
+ if (rb_obj_is_instance_of(time_v, rb_cTime)) { \
+ time_v = rb_funcall(time_v, rb_intern("to_i"), 0); \
+ } else if (FIXNUM_P(time_v)) { \
+ ; \
+ } else { \
+ rb_raise(rb_eArgError, "unknown type"); \
+ } \
+ \
+ t = NUM2ULONG(time_v); \
+ \
+ SSL_SESSION_set_##func(ctx, t); \
+ \
+ return ossl_ssl_session_get_##func(self); \
+ }
+
+SSLSESSION_SET_TIME(time)
+SSLSESSION_SET_TIME(timeout)
+
+#ifdef HAVE_SSL_SESSION_GET_ID
+/*
+ * call-seq:
+ * session.id -> aString
+ *
+ * Returns the Session ID.
+*/
+static VALUE ossl_ssl_session_get_id(VALUE self)
+{
+ SSL_SESSION *ctx;
+ const unsigned char *p = NULL;
+ unsigned int i = 0;
+
+ GetSSLSession(self, ctx);
+
+ p = SSL_SESSION_get_id(ctx, &i);
+
+ return rb_str_new((const char *) p, i);
+}
+#endif
+
+/*
+ * call-seq:
+ * session.to_der -> aString
+ *
+ * Returns an ASN1 encoded String that contains the Session object.
+*/
+static VALUE ossl_ssl_session_to_der(VALUE self)
+{
+ SSL_SESSION *ctx;
+ unsigned char buf[1024*10], *p;
+ int len;
+
+ GetSSLSession(self, ctx);
+
+ p = buf;
+ len = i2d_SSL_SESSION(ctx, &p);
+
+ if (len <= 0)
+ ossl_raise(eSSLSession, "i2d_SSL_SESSION");
+ else if (len >= sizeof(buf))
+ ossl_raise(eSSLSession, "i2d_SSL_SESSION too large");
+
+ return rb_str_new((const char *) p, len);
+}
+
+/*
+ * call-seq:
+ * session.to_pem -> String
+ *
+ * Returns a PEM encoded String that contains the Session object.
+*/
+static VALUE ossl_ssl_session_to_pem(VALUE self)
+{
+ SSL_SESSION *ctx;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+ int i;
+
+ GetSSLSession(self, ctx);
+
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eSSLSession, "BIO_s_mem()");
+ }
+
+ if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
+ BIO_free(out);
+ ossl_raise(eSSLSession, "SSL_SESSION_print()");
+ }
+
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+
+/*
+ * call-seq:
+ * session.to_text -> String
+ *
+ * Shows everything in the Session object.
+*/
+static VALUE ossl_ssl_session_to_text(VALUE self)
+{
+ SSL_SESSION *ctx;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetSSLSession(self, ctx);
+
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eSSLSession, "BIO_s_mem()");
+ }
+
+ if (!SSL_SESSION_print(out, ctx)) {
+ BIO_free(out);
+ ossl_raise(eSSLSession, "SSL_SESSION_print()");
+ }
+
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+
+void Init_ossl_ssl_session(void)
+{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+ mSSL = rb_define_module_under(mOSSL, "SSL");
+#endif
+ cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
+ eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
+
+ rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
+ rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
+
+ rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
+
+ rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
+ rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
+ rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
+ rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
+
+#ifdef HAVE_SSL_SESSION_GET_ID
+ rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
+#else
+ rb_undef_method(cSSLSession, "id");
+#endif
+ rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
+ rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
+ rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
+}
diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c
index 576ad4c40a..ca1c59aba9 100644
--- a/ext/openssl/ossl_x509attr.c
+++ b/ext/openssl/ossl_x509attr.c
@@ -84,6 +84,10 @@ ossl_x509attr_alloc(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * Attribute.new(oid [, value]) => attr
+ */
static VALUE
ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -91,12 +95,13 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
X509_ATTRIBUTE *attr;
unsigned char *p;
+ GetX509Attr(self, attr);
if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
- GetX509Attr(self, attr);
oid = ossl_to_der_if_possible(oid);
StringValue(oid);
- p = RSTRING(oid)->ptr;
- if(!d2i_X509_ATTRIBUTE(&attr, &p, RSTRING(oid)->len)){
+ p = RSTRING_PTR(oid);
+ if(!d2i_X509_ATTRIBUTE((X509_ATTRIBUTE**)&DATA_PTR(self),
+ &p, RSTRING_LEN(oid))){
ossl_raise(eX509AttrError, NULL);
}
return self;
@@ -107,6 +112,10 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * attr.oid = string => string
+ */
static VALUE
ossl_x509attr_set_oid(VALUE self, VALUE oid)
{
@@ -114,16 +123,20 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid)
ASN1_OBJECT *obj;
char *s;
- GetX509Attr(self, attr);
s = StringValuePtr(oid);
obj = OBJ_txt2obj(s, 0);
if(!obj) obj = OBJ_txt2obj(s, 1);
if(!obj) ossl_raise(eX509AttrError, NULL);
+ GetX509Attr(self, attr);
X509_ATTRIBUTE_set1_object(attr, obj);
return oid;
}
+/*
+ * call-seq:
+ * attr.oid => string
+ */
static VALUE
ossl_x509attr_get_oid(VALUE self)
{
@@ -155,19 +168,23 @@ ossl_x509attr_get_oid(VALUE self)
# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0)
#endif
+/*
+ * call-seq:
+ * attr.value = asn1 => asn1
+ */
static VALUE
ossl_x509attr_set_value(VALUE self, VALUE value)
{
X509_ATTRIBUTE *attr;
ASN1_TYPE *a1type;
- GetX509Attr(self, attr);
if(!(a1type = ossl_asn1_get_asn1type(value)))
ossl_raise(eASN1Error, "could not get ASN1_TYPE");
if(ASN1_TYPE_get(a1type) == V_ASN1_SEQUENCE){
ASN1_TYPE_free(a1type);
ossl_raise(eASN1Error, "couldn't set SEQUENCE for attribute value.");
}
+ GetX509Attr(self, attr);
if(attr->value.set){
if(OSSL_X509ATTR_IS_SINGLE(attr)) ASN1_TYPE_free(attr->value.single);
else sk_ASN1_TYPE_free(attr->value.set);
@@ -178,6 +195,10 @@ ossl_x509attr_set_value(VALUE self, VALUE value)
return value;
}
+/*
+ * call-seq:
+ * attr.value => asn1
+ */
static VALUE
ossl_x509attr_get_value(VALUE self)
{
@@ -191,7 +212,7 @@ ossl_x509attr_get_value(VALUE self)
if(OSSL_X509ATTR_IS_SINGLE(attr)){
length = i2d_ASN1_TYPE(attr->value.single, NULL);
str = rb_str_new(0, length);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
i2d_ASN1_TYPE(attr->value.single, &p);
ossl_str_adjust(str, p);
}
@@ -199,7 +220,7 @@ ossl_x509attr_get_value(VALUE self)
length = i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, NULL,
i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
str = rb_str_new(0, length);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, &p,
i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
ossl_str_adjust(str, p);
@@ -209,6 +230,10 @@ ossl_x509attr_get_value(VALUE self)
return asn1;
}
+/*
+ * call-seq:
+ * attr.to_der => string
+ */
static VALUE
ossl_x509attr_to_der(VALUE self)
{
@@ -221,10 +246,10 @@ ossl_x509attr_to_der(VALUE self)
if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0)
ossl_raise(eX509AttrError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_X509_ATTRIBUTE(attr, &p) <= 0)
ossl_raise(eX509AttrError, NULL);
- RSTRING(str)->len = p - (unsigned char*)RSTRING(str)->ptr;
+ rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str));
return str;
}
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index 443a2ba4c3..b97f27ffa9 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -63,7 +63,7 @@ ossl_x509_new_from_file(VALUE filename)
VALUE obj;
SafeStringValue(filename);
- if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
+ if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
ossl_raise(eX509CertError, "%s", strerror(errno));
}
x509 = PEM_read_X509(fp, NULL, NULL, NULL);
@@ -125,6 +125,11 @@ ossl_x509_alloc(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * Certificate.new => cert
+ * Certificate.new(string) => cert
+ */
static VALUE
ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -169,6 +174,10 @@ ossl_x509_copy(VALUE self, VALUE other)
return self;
}
+/*
+ * call-seq:
+ * cert.to_der => string
+ */
static VALUE
ossl_x509_to_der(VALUE self)
{
@@ -181,7 +190,7 @@ ossl_x509_to_der(VALUE self)
if ((len = i2d_X509(x509, NULL)) <= 0)
ossl_raise(eX509CertError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if (i2d_X509(x509, &p) <= 0)
ossl_raise(eX509CertError, NULL);
ossl_str_adjust(str, p);
@@ -189,6 +198,10 @@ ossl_x509_to_der(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * cert.to_pem => string
+ */
static VALUE
ossl_x509_to_pem(VALUE self)
{
@@ -209,6 +222,10 @@ ossl_x509_to_pem(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * cert.to_text => string
+ */
static VALUE
ossl_x509_to_text(VALUE self)
{
@@ -252,6 +269,10 @@ ossl_x509_to_req(VALUE self)
}
#endif
+/*
+ * call-seq:
+ * cert.version => integer
+ */
static VALUE
ossl_x509_get_version(VALUE self)
{
@@ -262,16 +283,20 @@ ossl_x509_get_version(VALUE self)
return LONG2NUM(X509_get_version(x509));
}
+/*
+ * call-seq:
+ * cert.version = integer => integer
+ */
static VALUE
ossl_x509_set_version(VALUE self, VALUE version)
{
X509 *x509;
long ver;
- GetX509(self, x509);
if ((ver = NUM2LONG(version)) < 0) {
ossl_raise(eX509CertError, "version must be >= 0!");
}
+ GetX509(self, x509);
if (!X509_set_version(x509, ver)) {
ossl_raise(eX509CertError, NULL);
}
@@ -279,6 +304,10 @@ ossl_x509_set_version(VALUE self, VALUE version)
return version;
}
+/*
+ * call-seq:
+ * cert.serial => integer
+ */
static VALUE
ossl_x509_get_serial(VALUE self)
{
@@ -289,6 +318,10 @@ ossl_x509_get_serial(VALUE self)
return asn1integer_to_num(X509_get_serialNumber(x509));
}
+/*
+ * call-seq:
+ * cert.serial = integer => integer
+ */
static VALUE
ossl_x509_set_serial(VALUE self, VALUE num)
{
@@ -302,6 +335,10 @@ ossl_x509_set_serial(VALUE self, VALUE num)
return num;
}
+/*
+ * call-seq:
+ * cert.signature_algorithm => string
+ */
static VALUE
ossl_x509_get_signature_algorithm(VALUE self)
{
@@ -310,7 +347,6 @@ ossl_x509_get_signature_algorithm(VALUE self)
VALUE str;
GetX509(self, x509);
-
out = BIO_new(BIO_s_mem());
if (!out) ossl_raise(eX509CertError, NULL);
@@ -323,6 +359,10 @@ ossl_x509_get_signature_algorithm(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * cert.subject => name
+ */
static VALUE
ossl_x509_get_subject(VALUE self)
{
@@ -337,6 +377,10 @@ ossl_x509_get_subject(VALUE self)
return ossl_x509name_new(name);
}
+/*
+ * call-seq:
+ * cert.subject = name => name
+ */
static VALUE
ossl_x509_set_subject(VALUE self, VALUE subject)
{
@@ -350,6 +394,10 @@ ossl_x509_set_subject(VALUE self, VALUE subject)
return subject;
}
+/*
+ * call-seq:
+ * cert.issuer => name
+ */
static VALUE
ossl_x509_get_issuer(VALUE self)
{
@@ -364,6 +412,10 @@ ossl_x509_get_issuer(VALUE self)
return ossl_x509name_new(name);
}
+/*
+ * call-seq:
+ * cert.issuer = name => name
+ */
static VALUE
ossl_x509_set_issuer(VALUE self, VALUE issuer)
{
@@ -377,6 +429,10 @@ ossl_x509_set_issuer(VALUE self, VALUE issuer)
return issuer;
}
+/*
+ * call-seq:
+ * cert.not_before => time
+ */
static VALUE
ossl_x509_get_not_before(VALUE self)
{
@@ -391,14 +447,18 @@ ossl_x509_get_not_before(VALUE self)
return asn1time_to_time(asn1time);
}
+/*
+ * call-seq:
+ * cert.not_before = time => time
+ */
static VALUE
ossl_x509_set_not_before(VALUE self, VALUE time)
{
X509 *x509;
time_t sec;
- GetX509(self, x509);
sec = time_to_time_t(time);
+ GetX509(self, x509);
if (!X509_time_adj(X509_get_notBefore(x509), 0, &sec)) {
ossl_raise(eX509CertError, NULL);
}
@@ -406,6 +466,10 @@ ossl_x509_set_not_before(VALUE self, VALUE time)
return time;
}
+/*
+ * call-seq:
+ * cert.not_after => time
+ */
static VALUE
ossl_x509_get_not_after(VALUE self)
{
@@ -420,14 +484,18 @@ ossl_x509_get_not_after(VALUE self)
return asn1time_to_time(asn1time);
}
+/*
+ * call-seq:
+ * cert.not_before = time => time
+ */
static VALUE
ossl_x509_set_not_after(VALUE self, VALUE time)
{
X509 *x509;
time_t sec;
- GetX509(self, x509);
sec = time_to_time_t(time);
+ GetX509(self, x509);
if (!X509_time_adj(X509_get_notAfter(x509), 0, &sec)) {
ossl_raise(eX509CertError, NULL);
}
@@ -435,6 +503,10 @@ ossl_x509_set_not_after(VALUE self, VALUE time)
return time;
}
+/*
+ * call-seq:
+ * cert.public_key => key
+ */
static VALUE
ossl_x509_get_public_key(VALUE self)
{
@@ -449,6 +521,10 @@ ossl_x509_get_public_key(VALUE self)
return ossl_pkey_new(pkey); /* NO DUP - OK */
}
+/*
+ * call-seq:
+ * cert.public_key = key => key
+ */
static VALUE
ossl_x509_set_public_key(VALUE self, VALUE key)
{
@@ -462,6 +538,10 @@ ossl_x509_set_public_key(VALUE self, VALUE key)
return key;
}
+/*
+ * call-seq:
+ * cert.sign(key, digest) => self
+ */
static VALUE
ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
{
@@ -469,9 +549,9 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
EVP_PKEY *pkey;
const EVP_MD *md;
- GetX509(self, x509);
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
md = GetDigestPtr(digest);
+ GetX509(self, x509);
if (!X509_sign(x509, pkey, md)) {
ossl_raise(eX509CertError, NULL);
}
@@ -480,6 +560,9 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
}
/*
+ * call-seq:
+ * cert.verify(key) => true | false
+ *
* Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
*/
static VALUE
@@ -489,8 +572,8 @@ ossl_x509_verify(VALUE self, VALUE key)
EVP_PKEY *pkey;
int i;
- GetX509(self, x509);
pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
+ GetX509(self, x509);
if ((i = X509_verify(x509, pkey)) < 0) {
ossl_raise(eX509CertError, NULL);
}
@@ -502,6 +585,9 @@ ossl_x509_verify(VALUE self, VALUE key)
}
/*
+ * call-seq:
+ * cert.check_private_key(key)
+ *
* Checks if 'key' is PRIV key for this cert
*/
static VALUE
@@ -510,9 +596,9 @@ ossl_x509_check_private_key(VALUE self, VALUE key)
X509 *x509;
EVP_PKEY *pkey;
- GetX509(self, x509);
/* not needed private key, but should be */
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
+ GetX509(self, x509);
if (!X509_check_private_key(x509, pkey)) {
OSSL_Warning("Check private key:%s", OSSL_ErrMsg());
return Qfalse;
@@ -522,7 +608,8 @@ ossl_x509_check_private_key(VALUE self, VALUE key)
}
/*
- * Gets X509v3 extensions as array of X509Ext objects
+ * call-seq:
+ * cert.extensions => [extension...]
*/
static VALUE
ossl_x509_get_extensions(VALUE self)
@@ -547,7 +634,8 @@ ossl_x509_get_extensions(VALUE self)
}
/*
- * Sets X509_EXTENSIONs
+ * call-seq:
+ * cert.extensions = [ext...] => [ext...]
*/
static VALUE
ossl_x509_set_extensions(VALUE self, VALUE ary)
@@ -556,16 +644,16 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
X509_EXTENSION *ext;
int i;
- GetX509(self, x509);
Check_Type(ary, T_ARRAY);
/* All ary's members should be X509Extension */
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
}
+ GetX509(self, x509);
sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free);
x509->cert_info->extensions = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
X509_EXTENSION_free(ext);
@@ -577,6 +665,10 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
return ary;
}
+/*
+ * call-seq:
+ * cert.add_extension(extension) => extension
+ */
static VALUE
ossl_x509_add_extension(VALUE self, VALUE extension)
{
diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c
index a7746aa2b3..be9ddacf48 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -146,11 +146,10 @@ ossl_x509crl_set_version(VALUE self, VALUE version)
X509_CRL *crl;
long ver;
- GetX509CRL(self, crl);
-
if ((ver = NUM2LONG(version)) < 0) {
ossl_raise(eX509CRLError, "version must be >= 0!");
}
+ GetX509CRL(self, crl);
if (!X509_CRL_set_version(crl, ver)) {
ossl_raise(eX509CRLError, NULL);
}
@@ -167,7 +166,6 @@ ossl_x509crl_get_signature_algorithm(VALUE self)
VALUE str;
GetX509CRL(self, crl);
-
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eX509CRLError, NULL);
}
@@ -220,8 +218,8 @@ ossl_x509crl_set_last_update(VALUE self, VALUE time)
X509_CRL *crl;
time_t sec;
- GetX509CRL(self, crl);
sec = time_to_time_t(time);
+ GetX509CRL(self, crl);
if (!X509_time_adj(crl->crl->lastUpdate, 0, &sec)) {
ossl_raise(eX509CRLError, NULL);
}
@@ -245,8 +243,8 @@ ossl_x509crl_set_next_update(VALUE self, VALUE time)
X509_CRL *crl;
time_t sec;
- GetX509CRL(self, crl);
sec = time_to_time_t(time);
+ GetX509CRL(self, crl);
/* This must be some thinko in OpenSSL */
if (!(crl->crl->nextUpdate = X509_time_adj(crl->crl->nextUpdate, 0, &sec))){
ossl_raise(eX509CRLError, NULL);
@@ -287,16 +285,16 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary)
X509_REVOKED *rev;
int i;
- GetX509CRL(self, crl);
Check_Type(ary, T_ARRAY);
/* All ary members should be X509 Revoked */
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Rev);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Rev);
}
+ GetX509CRL(self, crl);
sk_X509_REVOKED_pop_free(crl->crl->revoked, X509_REVOKED_free);
crl->crl->revoked = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- rev = DupX509RevokedPtr(RARRAY(ary)->ptr[i]);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ rev = DupX509RevokedPtr(RARRAY_PTR(ary)[i]);
if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
ossl_raise(eX509CRLError, NULL);
}
@@ -461,16 +459,16 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary)
X509_EXTENSION *ext;
int i;
- GetX509CRL(self, crl);
Check_Type(ary, T_ARRAY);
/* All ary members should be X509 Extensions */
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
}
+ GetX509CRL(self, crl);
sk_X509_EXTENSION_pop_free(crl->crl->extensions, X509_EXTENSION_free);
crl->crl->extensions = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
X509_EXTENSION_free(ext);
ossl_raise(eX509CRLError, NULL);
diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c
index f0ce068d6b..aa9366f901 100644
--- a/ext/openssl/ossl_x509ext.c
+++ b/ext/openssl/ossl_x509ext.c
@@ -26,9 +26,12 @@
OSSL_Check_Kind(obj, cX509Ext); \
GetX509Ext(obj, ext); \
} while (0)
-
-#define MakeX509ExtFactory(klass, obj, ctx) \
- obj = Data_Make_Struct(klass, X509V3_CTX, 0, ossl_x509extfactory_free, ctx)
+#define MakeX509ExtFactory(klass, obj, ctx) do { \
+ if (!(ctx = OPENSSL_malloc(sizeof(X509V3_CTX)))) \
+ ossl_raise(rb_eRuntimeError, "CTX wasn't allocated!"); \
+ X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, 0); \
+ obj = Data_Wrap_Struct(klass, 0, ossl_x509extfactory_free, ctx); \
+} while (0)
#define GetX509ExtFactory(obj, ctx) do { \
Data_Get_Struct(obj, X509V3_CTX, ctx); \
if (!ctx) { \
@@ -214,22 +217,35 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
X509_EXTENSION *ext;
VALUE oid, value, critical, valstr, obj;
int nid;
+#ifdef HAVE_X509V3_EXT_NCONF_NID
+ VALUE rconf;
+ CONF *conf;
+#else
+ static LHASH *empty_lhash;
+#endif
- GetX509ExtFactory(self, ctx);
rb_scan_args(argc, argv, "21", &oid, &value, &critical);
StringValue(oid);
StringValue(value);
if(NIL_P(critical)) critical = Qfalse;
- nid = OBJ_ln2nid(RSTRING(oid)->ptr);
- if(!nid) nid = OBJ_sn2nid(RSTRING(oid)->ptr);
- if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING(oid)->ptr);
+ nid = OBJ_ln2nid(RSTRING_PTR(oid));
+ if(!nid) nid = OBJ_sn2nid(RSTRING_PTR(oid));
+ if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING_PTR(oid));
valstr = rb_str_new2(RTEST(critical) ? "critical," : "");
rb_str_append(valstr, value);
- ext = X509V3_EXT_conf_nid(NULL, ctx, nid, RSTRING(valstr)->ptr);
+ GetX509ExtFactory(self, ctx);
+#ifdef HAVE_X509V3_EXT_NCONF_NID
+ rconf = rb_iv_get(self, "@config");
+ conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf);
+ ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr));
+#else
+ if (!empty_lhash) empty_lhash = lh_new(NULL, NULL);
+ ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING_PTR(valstr));
+#endif
if (!ext){
ossl_raise(eX509ExtError, "%s = %s",
- RSTRING(oid)->ptr, RSTRING(value)->ptr);
+ RSTRING_PTR(oid), RSTRING_PTR(value));
}
WrapX509Ext(cX509Ext, obj, ext);
@@ -260,13 +276,13 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
unsigned char *p;
X509_EXTENSION *ext;
+ GetX509Ext(self, ext);
if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){
- /* evaluate oid as a DER string */
oid = ossl_to_der_if_possible(oid);
StringValue(oid);
- GetX509Ext(self, ext);
- p = RSTRING(oid)->ptr;
- if(!d2i_X509_EXTENSION(&ext, &p, RSTRING(oid)->len))
+ p = RSTRING_PTR(oid);
+ if(!d2i_X509_EXTENSION((X509_EXTENSION**)&DATA_PTR(self),
+ &p, RSTRING_LEN(oid)))
ossl_raise(eX509ExtError, NULL);
return self;
}
@@ -284,11 +300,11 @@ ossl_x509ext_set_oid(VALUE self, VALUE oid)
ASN1_OBJECT *obj;
char *s;
- GetX509Ext(self, ext);
s = StringValuePtr(oid);
obj = OBJ_txt2obj(s, 0);
if(!obj) obj = OBJ_txt2obj(s, 1);
if(!obj) ossl_raise(eX509ExtError, NULL);
+ GetX509Ext(self, ext);
X509_EXTENSION_set_object(ext, obj);
return oid;
@@ -301,21 +317,21 @@ ossl_x509ext_set_value(VALUE self, VALUE data)
ASN1_OCTET_STRING *asn1s;
char *s;
- GetX509Ext(self, ext);
data = ossl_to_der_if_possible(data);
StringValue(data);
- if(!(s = OPENSSL_malloc(RSTRING(data)->len)))
+ if(!(s = OPENSSL_malloc(RSTRING_LEN(data))))
ossl_raise(eX509ExtError, "malloc error");
- memcpy(s, RSTRING(data)->ptr, RSTRING(data)->len);
+ memcpy(s, RSTRING_PTR(data), RSTRING_LEN(data));
if(!(asn1s = ASN1_OCTET_STRING_new())){
free(s);
ossl_raise(eX509ExtError, NULL);
}
- if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING(data)->len)){
+ if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING_LEN(data))){
free(s);
ASN1_OCTET_STRING_free(asn1s);
ossl_raise(eX509ExtError, NULL);
}
+ GetX509Ext(self, ext);
X509_EXTENSION_set_data(ext, asn1s);
return data;
@@ -376,6 +392,7 @@ static VALUE
ossl_x509ext_get_critical(VALUE obj)
{
X509_EXTENSION *ext;
+
GetX509Ext(obj, ext);
return X509_EXTENSION_get_critical(ext) ? Qtrue : Qfalse;
}
@@ -392,7 +409,7 @@ ossl_x509ext_to_der(VALUE obj)
if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0)
ossl_raise(eX509ExtError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_X509_EXTENSION(ext, &p) < 0)
ossl_raise(eX509ExtError, NULL);
ossl_str_adjust(str, p);
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index 5964eec2ee..b4434d2a34 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -27,6 +27,11 @@
GetX509Name(obj, name); \
} while (0)
+#define OBJECT_TYPE_TEMPLATE \
+ rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE"))
+#define DEFAULT_OBJECT_TYPE \
+ rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE"))
+
/*
* Classes
*/
@@ -82,49 +87,92 @@ ossl_x509name_alloc(VALUE klass)
return obj;
}
+static int id_aref;
+static VALUE ossl_x509name_add_entry(int, VALUE*, VALUE);
+#define rb_aref(obj, key) rb_funcall(obj, id_aref, 1, key)
+
+static VALUE
+ossl_x509name_init_i(VALUE i, VALUE args)
+{
+ VALUE self = rb_ary_entry(args, 0);
+ VALUE template = rb_ary_entry(args, 1);
+ VALUE entry[3];
+
+ Check_Type(i, T_ARRAY);
+ entry[0] = rb_ary_entry(i, 0);
+ entry[1] = rb_ary_entry(i, 1);
+ entry[2] = rb_ary_entry(i, 2);
+ if(NIL_P(entry[2])) entry[2] = rb_aref(template, entry[0]);
+ if(NIL_P(entry[2])) entry[2] = DEFAULT_OBJECT_TYPE;
+ ossl_x509name_add_entry(3, entry, self);
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * X509::Name.new => name
+ * X509::Name.new(string) => name
+ * X509::Name.new(dn) => name
+ * X509::Name.new(dn, template) => name
+ */
static VALUE
ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
{
X509_NAME *name;
- int i, type;
- VALUE arg, str_type, item, key, value;
+ VALUE arg, template;
GetX509Name(self, name);
- if (rb_scan_args(argc, argv, "02", &arg, &str_type) == 0) {
+ if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) {
return self;
}
- if (argc == 1 && rb_respond_to(arg, ossl_s_to_der)){
- unsigned char *p;
- VALUE str = rb_funcall(arg, ossl_s_to_der, 0);
- StringValue(str);
- p = RSTRING(str)->ptr;
- if(!d2i_X509_NAME(&name, &p, RSTRING(str)->len))
- ossl_raise(eX509NameError, NULL);
- return self;
- }
- Check_Type(arg, T_ARRAY);
- type = NIL_P(str_type) ? V_ASN1_UTF8STRING : NUM2INT(str_type);
- for (i=0; i<RARRAY(arg)->len; i++) {
- item = RARRAY(arg)->ptr[i];
- Check_Type(item, T_ARRAY);
- if (RARRAY(item)->len != 2) {
- ossl_raise(rb_eArgError, "Unsupported structure.");
+ else {
+ VALUE tmp = rb_check_array_type(arg);
+ if (!NIL_P(tmp)) {
+ VALUE args;
+ if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
+ args = rb_ary_new3(2, self, template);
+ rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
}
- key = RARRAY(item)->ptr[0];
- value = RARRAY(item)->ptr[1];
- StringValue(key);
- StringValue(value);
- if (!X509_NAME_add_entry_by_txt(name, RSTRING(key)->ptr, type,
- RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) {
- ossl_raise(eX509NameError, NULL);
+ else{
+ unsigned char *p;
+ VALUE str = ossl_to_der_if_possible(arg);
+ StringValue(str);
+ p = RSTRING_PTR(str);
+ if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING_LEN(str))){
+ ossl_raise(eX509NameError, NULL);
+ }
}
}
return self;
}
+/*
+ * call-seq:
+ * name.add_entry(oid, value [, type]) => self
+ */
+static
+VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
+{
+ X509_NAME *name;
+ VALUE oid, value, type;
+
+ rb_scan_args(argc, argv, "21", &oid, &value, &type);
+ StringValue(oid);
+ StringValue(value);
+ if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
+ GetX509Name(self, name);
+ if (!X509_NAME_add_entry_by_txt(name, RSTRING_PTR(oid), NUM2INT(type),
+ RSTRING_PTR(value), RSTRING_LEN(value), -1, 0)) {
+ ossl_raise(eX509NameError, NULL);
+ }
+
+ return self;
+}
+
static VALUE
-ossl_x509name_to_s(VALUE self)
+ossl_x509name_to_s_old(VALUE self)
{
X509_NAME *name;
char *buf;
@@ -138,6 +186,39 @@ ossl_x509name_to_s(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * name.to_s => string
+ * name.to_s(integer) => string
+ */
+static VALUE
+ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
+{
+ X509_NAME *name;
+ VALUE flag, str;
+ BIO *out;
+ unsigned long iflag;
+
+ rb_scan_args(argc, argv, "01", &flag);
+ if (NIL_P(flag))
+ return ossl_x509name_to_s_old(self);
+ else iflag = NUM2ULONG(flag);
+ if (!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(eX509NameError, NULL);
+ GetX509Name(self, name);
+ if (!X509_NAME_print_ex(out, name, 0, iflag)){
+ BIO_free(out);
+ ossl_raise(eX509NameError, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * name.to_a => [[name, data, type], ...]
+ */
static VALUE
ossl_x509name_to_a(VALUE self)
{
@@ -146,7 +227,7 @@ ossl_x509name_to_a(VALUE self)
int i,entries;
char long_name[512];
const char *short_name;
- VALUE ary;
+ VALUE ary, ret;
GetX509Name(self, name);
entries = X509_NAME_entry_count(name);
@@ -154,7 +235,7 @@ ossl_x509name_to_a(VALUE self)
OSSL_Debug("name entries < 0!");
return rb_ary_new();
}
- ary = rb_ary_new2(entries);
+ ret = rb_ary_new2(entries);
for (i=0; i<entries; i++) {
if (!(entry = X509_NAME_get_entry(name, i))) {
ossl_raise(eX509NameError, NULL);
@@ -163,11 +244,12 @@ ossl_x509name_to_a(VALUE self)
ossl_raise(eX509NameError, NULL);
}
short_name = OBJ_nid2sn(OBJ_ln2nid(long_name));
-
- rb_ary_push(ary, rb_assoc_new(rb_str_new2(short_name),
- rb_str_new(entry->value->data, entry->value->length)));
+ ary = rb_ary_new3(3, rb_str_new2(short_name),
+ rb_str_new(entry->value->data, entry->value->length),
+ INT2FIX(entry->value->type));
+ rb_ary_push(ret, ary);
}
- return ary;
+ return ret;
}
static int
@@ -204,6 +286,10 @@ ossl_x509name_eql(VALUE self, VALUE other)
return (result == 0) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * name.hash => integer
+ */
static VALUE
ossl_x509name_hash(VALUE self)
{
@@ -217,6 +303,10 @@ ossl_x509name_hash(VALUE self)
return ULONG2NUM(hash);
}
+/*
+ * call-seq:
+ * name.to_der => string
+ */
static VALUE
ossl_x509name_to_der(VALUE self)
{
@@ -229,7 +319,7 @@ ossl_x509name_to_der(VALUE self)
if((len = i2d_X509_NAME(name, NULL)) <= 0)
ossl_raise(eX509NameError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_X509_NAME(name, &p) <= 0)
ossl_raise(eX509NameError, NULL);
ossl_str_adjust(str, p);
@@ -243,17 +333,40 @@ ossl_x509name_to_der(VALUE self)
void
Init_ossl_x509name()
{
- eX509NameError = rb_define_class_under(mX509, "NameError", eOSSLError);
+ VALUE utf8str, ptrstr, ia5str, hash;
+ id_aref = rb_intern("[]");
+ eX509NameError = rb_define_class_under(mX509, "NameError", eOSSLError);
cX509Name = rb_define_class_under(mX509, "Name", rb_cObject);
rb_define_alloc_func(cX509Name, ossl_x509name_alloc);
rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1);
- rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, 0);
+ rb_define_method(cX509Name, "add_entry", ossl_x509name_add_entry, -1);
+ rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, -1);
rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0);
rb_define_method(cX509Name, "cmp", ossl_x509name_cmp, 1);
rb_define_alias(cX509Name, "<=>", "cmp");
rb_define_method(cX509Name, "eql?", ossl_x509name_eql, 1);
rb_define_method(cX509Name, "hash", ossl_x509name_hash, 0);
rb_define_method(cX509Name, "to_der", ossl_x509name_to_der, 0);
+
+ utf8str = INT2NUM(V_ASN1_UTF8STRING);
+ ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING);
+ ia5str = INT2NUM(V_ASN1_IA5STRING);
+ rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
+ hash = rb_hash_new();
+ RHASH(hash)->ifnone = utf8str;
+ rb_hash_aset(hash, rb_str_new2("C"), ptrstr);
+ rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
+ rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
+ rb_hash_aset(hash, rb_str_new2("dnQualifier"), ptrstr);
+ rb_hash_aset(hash, rb_str_new2("DC"), ia5str);
+ rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
+ rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
+ rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash);
+
+ rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT));
+ rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253));
+ rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE));
+ rb_define_const(cX509Name, "MULTILINE", ULONG2NUM(XN_FLAG_MULTILINE));
}
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index c532739997..13a42dddaf 100644
--- a/ext/openssl/ossl_x509req.c
+++ b/ext/openssl/ossl_x509req.c
@@ -171,7 +171,7 @@ ossl_x509req_to_der(VALUE self)
if ((len = i2d_X509_REQ(req, NULL)) <= 0)
ossl_raise(eX509CertError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if (i2d_X509_REQ(req, &p) <= 0)
ossl_raise(eX509ReqError, NULL);
ossl_str_adjust(str, p);
@@ -240,10 +240,10 @@ ossl_x509req_set_version(VALUE self, VALUE version)
X509_REQ *req;
long ver;
- GetX509Req(self, req);
if ((ver = FIX2LONG(version)) < 0) {
ossl_raise(eX509ReqError, "version must be >= 0!");
}
+ GetX509Req(self, req);
if (!X509_REQ_set_version(req, ver)) {
ossl_raise(eX509ReqError, NULL);
}
@@ -402,15 +402,15 @@ ossl_x509req_set_attributes(VALUE self, VALUE ary)
int i;
VALUE item;
- GetX509Req(self, req);
Check_Type(ary, T_ARRAY);
- for (i=0;i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Attr);
+ for (i=0;i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Attr);
}
+ GetX509Req(self, req);
sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free);
req->req_info->attributes = NULL;
- for (i=0;i<RARRAY(ary)->len; i++) {
- item = RARRAY(ary)->ptr[i];
+ for (i=0;i<RARRAY_LEN(ary); i++) {
+ item = RARRAY_PTR(ary)[i];
attr = DupX509AttrPtr(item);
if (!X509_REQ_add1_attr(req, attr)) {
ossl_raise(eX509ReqError, NULL);
diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c
index 30ce75207f..d0f816bad4 100644
--- a/ext/openssl/ossl_x509revoked.c
+++ b/ext/openssl/ossl_x509revoked.c
@@ -129,8 +129,8 @@ ossl_x509revoked_set_time(VALUE self, VALUE time)
X509_REVOKED *rev;
time_t sec;
- GetX509Rev(self, rev);
sec = time_to_time_t(time);
+ GetX509Rev(self, rev);
if (!X509_time_adj(rev->revocationDate, 0, &sec)) {
ossl_raise(eX509RevError, NULL);
}
@@ -174,15 +174,15 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
int i;
VALUE item;
- GetX509Rev(self, rev);
Check_Type(ary, T_ARRAY);
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
}
+ GetX509Rev(self, rev);
sk_X509_EXTENSION_pop_free(rev->extensions, X509_EXTENSION_free);
rev->extensions = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- item = RARRAY(ary)->ptr[i];
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ item = RARRAY_PTR(ary)[i];
ext = DupX509ExtPtr(item);
if(!X509_REVOKED_add_ext(rev, ext, -1)) {
ossl_raise(eX509RevError, NULL);
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index 4c5f0624a9..769ce8a91a 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -118,11 +118,18 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
return cb;
}
+
+/*
+ * call-seq:
+ * X509::Store.new => store
+ *
+ */
static VALUE
ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
{
X509_STORE *store;
+/* BUG: This method takes any number of arguments but appears to ignore them. */
GetX509Store(self, store);
X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
ossl_x509store_set_vfy_cb(self, Qnil);
@@ -137,6 +144,7 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
rb_iv_set(self, "@error", Qnil);
rb_iv_set(self, "@error_string", Qnil);
rb_iv_set(self, "@chain", Qnil);
+ rb_iv_set(self, "@time", Qnil);
return self;
}
@@ -146,9 +154,10 @@ ossl_x509store_set_flags(VALUE self, VALUE flags)
{
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE *store;
+ long f = NUM2LONG(flags);
GetX509Store(self, store);
- X509_STORE_set_flags(store, NUM2LONG(flags));
+ X509_STORE_set_flags(store, f);
#else
rb_iv_set(self, "@flags", flags);
#endif
@@ -161,9 +170,10 @@ ossl_x509store_set_purpose(VALUE self, VALUE purpose)
{
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE *store;
+ long p = NUM2LONG(purpose);
GetX509Store(self, store);
- X509_STORE_set_purpose(store, NUM2LONG(purpose));
+ X509_STORE_set_purpose(store, p);
#else
rb_iv_set(self, "@purpose", purpose);
#endif
@@ -176,9 +186,10 @@ ossl_x509store_set_trust(VALUE self, VALUE trust)
{
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE *store;
+ long t = NUM2LONG(trust);
GetX509Store(self, store);
- X509_STORE_set_trust(store, NUM2LONG(trust));
+ X509_STORE_set_trust(store, t);
#else
rb_iv_set(self, "@trust", trust);
#endif
@@ -187,6 +198,13 @@ ossl_x509store_set_trust(VALUE self, VALUE trust)
}
static VALUE
+ossl_x509store_set_time(VALUE self, VALUE time)
+{
+ rb_iv_set(self, "@time", time);
+ return time;
+}
+
+static VALUE
ossl_x509store_add_file(VALUE self, VALUE file)
{
X509_STORE *store;
@@ -195,7 +213,7 @@ ossl_x509store_add_file(VALUE self, VALUE file)
if(file != Qnil){
Check_SafeStr(file);
- path = RSTRING(file)->ptr;
+ path = RSTRING_PTR(file);
}
GetX509Store(self, store);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
@@ -216,7 +234,7 @@ ossl_x509store_add_path(VALUE self, VALUE dir)
if(dir != Qnil){
Check_SafeStr(dir);
- path = RSTRING(dir)->ptr;
+ path = RSTRING_PTR(dir);
}
GetX509Store(self, store);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
@@ -229,6 +247,19 @@ ossl_x509store_add_path(VALUE self, VALUE dir)
}
static VALUE
+ossl_x509store_set_default_paths(VALUE self)
+{
+ X509_STORE *store;
+
+ GetX509Store(self, store);
+ if (X509_STORE_set_default_paths(store) != 1){
+ ossl_raise(eX509StoreError, NULL);
+ }
+
+ return Qnil;
+}
+
+static VALUE
ossl_x509store_add_cert(VALUE self, VALUE arg)
{
X509_STORE *store;
@@ -236,7 +267,9 @@ ossl_x509store_add_cert(VALUE self, VALUE arg)
cert = GetX509CertPtr(arg); /* NO NEED TO DUP */
GetX509Store(self, store);
- X509_STORE_add_cert(store, cert);
+ if (X509_STORE_add_cert(store, cert) != 1){
+ ossl_raise(eX509StoreError, NULL);
+ }
return self;
}
@@ -249,7 +282,9 @@ ossl_x509store_add_crl(VALUE self, VALUE arg)
crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */
GetX509Store(self, store);
- X509_STORE_add_crl(store, crl);
+ if (X509_STORE_add_crl(store, crl) != 1){
+ ossl_raise(eX509StoreError, NULL);
+ }
return self;
}
@@ -329,17 +364,22 @@ ossl_x509stctx_alloc(VALUE klass)
return obj;
}
+static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
+static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
+static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
+static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
+
static VALUE
ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
{
- VALUE store, cert, chain;
+ VALUE store, cert, chain, t;
X509_STORE_CTX *ctx;
X509_STORE *x509st;
X509 *x509 = NULL;
STACK_OF(X509) *x509s = NULL;
- GetX509StCtx(self, ctx);
rb_scan_args(argc, argv, "12", &store, &cert, &chain);
+ GetX509StCtx(self, ctx);
SafeGetX509Store(store, x509st);
if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
@@ -350,10 +390,12 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
}
#else
X509_STORE_CTX_init(ctx, x509st, x509, x509s);
- X509_STORE_CTX_set_flags(ctx, NUM2INT(rb_iv_get(store, "@flags")));
- X509_STORE_CTX_set_purpose(ctx, NUM2INT(rb_iv_get(store, "@purpose")));
- X509_STORE_CTX_set_trust(ctx, NUM2INT(rb_iv_get(store, "@trust")));
+ ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags"));
+ ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose"));
+ ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust"));
#endif
+ if (!NIL_P(t = rb_iv_get(store, "@time")))
+ ossl_x509stctx_set_time(self, t);
rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
rb_iv_set(self, "@cert", cert);
@@ -416,7 +458,7 @@ ossl_x509stctx_set_error(VALUE self, VALUE err)
X509_STORE_CTX *ctx;
GetX509StCtx(self, ctx);
- X509_STORE_CTX_set_error(ctx, FIX2INT(err));
+ X509_STORE_CTX_set_error(ctx, NUM2INT(err));
return err;
}
@@ -483,9 +525,10 @@ static VALUE
ossl_x509stctx_set_flags(VALUE self, VALUE flags)
{
X509_STORE_CTX *store;
+ long f = NUM2LONG(flags);
GetX509StCtx(self, store);
- X509_STORE_CTX_set_flags(store, NUM2LONG(flags));
+ X509_STORE_CTX_set_flags(store, f);
return flags;
}
@@ -494,9 +537,10 @@ static VALUE
ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
{
X509_STORE_CTX *store;
+ long p = NUM2LONG(purpose);
GetX509StCtx(self, store);
- X509_STORE_CTX_set_purpose(store, NUM2LONG(purpose));
+ X509_STORE_CTX_set_purpose(store, p);
return purpose;
}
@@ -505,14 +549,32 @@ static VALUE
ossl_x509stctx_set_trust(VALUE self, VALUE trust)
{
X509_STORE_CTX *store;
+ long t = NUM2LONG(trust);
GetX509StCtx(self, store);
- X509_STORE_CTX_set_trust(store, NUM2LONG(trust));
+ X509_STORE_CTX_set_trust(store, t);
return trust;
}
/*
+ * call-seq:
+ * storectx.time = time => time
+ */
+static VALUE
+ossl_x509stctx_set_time(VALUE self, VALUE time)
+{
+ X509_STORE_CTX *store;
+ long t;
+
+ t = NUM2LONG(rb_Integer(time));
+ GetX509StCtx(self, store);
+ X509_STORE_CTX_set_time(store, 0, t);
+
+ return time;
+}
+
+/*
* INIT
*/
void
@@ -533,8 +595,10 @@ Init_ossl_x509store()
rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1);
rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1);
rb_define_method(cX509Store, "trust=", ossl_x509store_set_trust, 1);
+ rb_define_method(cX509Store, "time=", ossl_x509store_set_time, 1);
rb_define_method(cX509Store, "add_path", ossl_x509store_add_path, 1);
rb_define_method(cX509Store, "add_file", ossl_x509store_add_file, 1);
+ rb_define_method(cX509Store, "set_default_paths", ossl_x509store_set_default_paths, 0);
rb_define_method(cX509Store, "add_cert", ossl_x509store_add_cert, 1);
rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1);
rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1);
@@ -555,5 +619,6 @@ Init_ossl_x509store()
rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1);
rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1);
rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1);
+ rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1);
}
diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h
index 4bd08890f8..64b76f26b4 100644
--- a/ext/openssl/ruby_missing.h
+++ b/ext/openssl/ruby_missing.h
@@ -9,10 +9,33 @@
* (See the file 'LICENCE'.)
*/
#if !defined(_OSSL_RUBY_MISSING_H_)
-#define _OSS_RUBY_MISSING_H_
+#define _OSSL_RUBY_MISSING_H_
#define rb_define_copy_func(klass, func) \
rb_define_method(klass, "initialize_copy", func, 1)
-#endif /* _OSS_RUBY_MISSING_H_ */
+#ifndef GetReadFile
+#define FPTR_TO_FD(fptr) (fptr->fd)
+#else
+#define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
+#endif
+
+#ifndef HAVE_RB_IO_T
+#define rb_io_t OpenFile
+#endif
+
+#ifndef HAVE_RB_STR_SET_LEN
+/* these methods should probably be backported to 1.8 */
+#define rb_str_set_len(str, length) do { \
+ RSTRING(str)->ptr[length] = 0; \
+ RSTRING(str)->len = length; \
+} while(0)
+#endif /* ! HAVE_RB_STR_SET_LEN */
+
+#ifndef HAVE_RB_BLOCK_CALL
+/* the openssl module doesn't use arg[3-4] and arg2 is always rb_each */
+#define rb_block_call(arg1, arg2, arg3, arg4, arg5, arg6) rb_iterate(rb_each, arg1, arg5, arg6)
+#endif /* ! HAVE_RB_BLOCK_CALL */
+
+#endif /* _OSSL_RUBY_MISSING_H_ */
diff --git a/ext/pty/MANIFEST b/ext/pty/MANIFEST
deleted file mode 100644
index 0535a5b7ef..0000000000
--- a/ext/pty/MANIFEST
+++ /dev/null
@@ -1,12 +0,0 @@
-MANIFEST
-README
-README.expect
-README.expect.ja
-README.ja
-depend
-expect_sample.rb
-extconf.rb
-lib/expect.rb
-pty.c
-script.rb
-shl.rb
diff --git a/ext/pty/expect_sample.rb b/ext/pty/expect_sample.rb
index bf8a2352fe..2a2e29f866 100644
--- a/ext/pty/expect_sample.rb
+++ b/ext/pty/expect_sample.rb
@@ -15,10 +15,6 @@ PTY.spawn("ftp ftp.ruby-lang.org") do |r_f,w_f,pid|
$expect_verbose = false
- r_f.expect(/^Name.*: /) do
- w_f.print "ftp\n"
- end
-
if !ENV['USER'].nil?
username = ENV['USER']
elsif !ENV['LOGNAME'].nil?
@@ -27,19 +23,16 @@ PTY.spawn("ftp ftp.ruby-lang.org") do |r_f,w_f,pid|
username = 'guest'
end
- r_f.expect('word:') do
- w_f.print username+"@\n"
- end
- r_f.expect("> ") do
- w_f.print "cd pub/ruby\n"
+ r_f.expect(/^(Name).*: |(word):|> /) do
+ w_f.puts($1 ? "ftp" : $2 ? "#{username}@" : "cd pub/ruby")
end
r_f.expect("> ") do
w_f.print "dir\n"
end
- r_f.expect("> ") do |output|
+ r_f.expect(/[^\-]> /) do |output|
for x in output[0].split("\n")
- if x =~ /(ruby.*\.tar\.gz)/ then
+ if x =~ /(ruby.*?\.tar\.gz)/ then
fnames.push $1
end
end
diff --git a/ext/pty/lib/expect.rb b/ext/pty/lib/expect.rb
index aa9ab895d3..08191b05b9 100644
--- a/ext/pty/lib/expect.rb
+++ b/ext/pty/lib/expect.rb
@@ -10,7 +10,7 @@ class IO
e_pat = pat
end
while true
- if IO.select([self],nil,nil,timeout).nil? then
+ if !IO.select([self],nil,nil,timeout) or eof? then
result = nil
break
end
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index 01382e881a..939335242f 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -6,7 +6,7 @@
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
-#if !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
+#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_LIBUTIL_H
@@ -38,11 +38,11 @@
#define DEVICELEN 16
#if !defined(HAVE_OPENPTY)
-#ifdef __hpux
-static
-char *MasterDevice = "/dev/ptym/pty%s",
- *SlaveDevice = "/dev/pty/tty%s",
- *deviceNo[] = {
+#if defined(__hpux)
+static const
+char MasterDevice[] = "/dev/ptym/pty%s",
+ SlaveDevice[] = "/dev/pty/tty%s",
+ *const deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
"q0","q1","q2","q3","q4","q5","q6","q7",
@@ -61,12 +61,11 @@ char *MasterDevice = "/dev/ptym/pty%s",
"w8","w9","wa","wb","wc","wd","we","wf",
0,
};
-#else /* NOT HPUX */
-#ifdef _IBMESA /* AIX/ESA */
-static
-char *MasterDevice = "/dev/ptyp%s",
- *SlaveDevice = "/dev/ttyp%s",
- *deviceNo[] = {
+#elif defined(_IBMESA) /* AIX/ESA */
+static const
+char MasterDevice[] = "/dev/ptyp%s",
+ SlaveDevice[] = "/dev/ttyp%s",
+ *const deviceNo[] = {
"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
"20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
@@ -84,11 +83,11 @@ char *MasterDevice = "/dev/ptyp%s",
"e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
"f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff",
};
-#else
-static
-char *MasterDevice = "/dev/pty%s",
- *SlaveDevice = "/dev/tty%s",
- *deviceNo[] = {
+#elif !defined(HAVE_PTSNAME)
+static const
+char MasterDevice[] = "/dev/pty%s",
+ SlaveDevice[] = "/dev/tty%s",
+ *const deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
"q0","q1","q2","q3","q4","q5","q6","q7",
@@ -99,14 +98,9 @@ char *MasterDevice = "/dev/pty%s",
"s8","s9","sa","sb","sc","sd","se","sf",
0,
};
-#endif /* _IBMESA */
-#endif /* HPUX */
+#endif
#endif /* !defined(HAVE_OPENPTY) */
-static char SlaveName[DEVICELEN];
-
-extern int errno;
-
#ifndef HAVE_SETEUID
# ifdef HAVE_SETREUID
# define seteuid(e) setreuid(-1, (e))
@@ -130,7 +124,7 @@ echild_status(self)
struct pty_info {
int fd;
- pid_t child_pid;
+ rb_pid_t child_pid;
VALUE thread;
};
@@ -143,7 +137,7 @@ raise_from_wait(state, info)
char buf[1024];
VALUE exc;
- snprintf(buf, sizeof(buf), "pty - %s: %d", state, info->child_pid);
+ snprintf(buf, sizeof(buf), "pty - %s: %ld", state, (long)info->child_pid);
exc = rb_exc_new2(eChildExited, buf);
rb_iv_set(exc, "status", rb_last_status);
rb_funcall(info->thread, rb_intern("raise"), 1, exc);
@@ -159,17 +153,15 @@ pty_syswait(info)
cpid = rb_waitpid(info->child_pid, &status, WUNTRACED);
if (cpid == -1) return Qnil;
-#if defined(IF_STOPPED)
- if (IF_STOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
-#elif defined(WIFSTOPPED)
- if (WIFSTOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
+#if defined(WIFSTOPPED)
+#elif defined(IF_STOPPED)
+#define WIFSTOPPED(status) IF_STOPPED(status)
#else
---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
#endif /* WIFSTOPPED | IF_STOPPED */
+ if (WIFSTOPPED(status)) { /* suspend */
+ raise_from_wait("stopped", info);
+ }
else if (kill(info->child_pid, 0) == 0) {
raise_from_wait("changed", info);
}
@@ -180,28 +172,32 @@ pty_syswait(info)
}
}
-static void getDevice _((int*, int*));
+static void getDevice _((int*, int*, char [DEVICELEN]));
struct exec_info {
int argc;
VALUE *argv;
};
+static VALUE pty_exec _((VALUE v));
+
static VALUE
-pty_exec(arg)
- struct exec_info *arg;
+pty_exec(v)
+ VALUE v;
{
+ struct exec_info *arg = (struct exec_info *)v;
return rb_f_exec(arg->argc, arg->argv);
}
static void
-establishShell(argc, argv, info)
+establishShell(argc, argv, info, SlaveName)
int argc;
VALUE *argv;
struct pty_info *info;
-{
- static int i,master,slave,currentPid;
- char *p,*getenv();
+ char SlaveName[DEVICELEN];
+{
+ int i,master,slave;
+ char *p, tmp, *getenv();
struct passwd *pwent;
VALUE v;
struct exec_info arg;
@@ -224,17 +220,16 @@ establishShell(argc, argv, info)
argc = 1;
argv = &v;
}
- getDevice(&master,&slave);
+ getDevice(&master, &slave, SlaveName);
info->thread = rb_thread_current();
- currentPid = getpid();
if((i = fork()) < 0) {
+ close(master);
+ close(slave);
rb_sys_fail("fork failed");
}
if(i == 0) { /* child */
- currentPid = getpid();
-
/*
* Set free from process group and controlling terminal
*/
@@ -246,7 +241,7 @@ establishShell(argc, argv, info)
if (setpgrp() == -1)
perror("setpgrp()");
# else /* SETGRP_VOID */
- if (setpgrp(0, currentPid) == -1)
+ if (setpgrp(0, getpid()) == -1)
rb_sys_fail("setpgrp()");
if ((i = open("/dev/tty", O_RDONLY)) < 0)
rb_sys_fail("/dev/tty");
@@ -275,6 +270,7 @@ establishShell(argc, argv, info)
}
close(master);
#endif
+ write(slave, "", 1);
dup2(slave,0);
dup2(slave,1);
dup2(slave,2);
@@ -290,6 +286,7 @@ establishShell(argc, argv, info)
_exit(1);
}
+ read(master, &tmp, 1);
close(slave);
info->child_pid = i;
@@ -306,43 +303,37 @@ pty_finalize_syswait(info)
return Qnil;
}
-#ifdef HAVE_OPENPTY
+static int
+get_device_once(master, slave, SlaveName, fail)
+ int *master, *slave, fail;
+ char SlaveName[DEVICELEN];
+{
+#if defined HAVE_OPENPTY
/*
* Use openpty(3) of 4.3BSD Reno and later,
* or the same interface function.
*/
-static void
-getDevice(master,slave)
- int *master,*slave;
-{
if (openpty(master, slave, SlaveName,
(struct termios *)0, (struct winsize *)0) == -1) {
+ if (!fail) return -1;
rb_raise(rb_eRuntimeError, "openpty() failed");
}
-}
-#else /* HAVE_OPENPTY */
-#ifdef HAVE__GETPTY
-static void
-getDevice(master,slave)
- int *master,*slave;
-{
+
+ return 0;
+#elif defined HAVE__GETPTY
char *name;
if (!(name = _getpty(master, O_RDWR, 0622, 0))) {
+ if (!fail) return -1;
rb_raise(rb_eRuntimeError, "_getpty() failed");
}
*slave = open(name, O_RDWR);
- strcpy(SlaveName, name);
-}
+ strncpy(SlaveName, name, sizeof SlaveName);
+
+ return 0;
#else /* HAVE__GETPTY */
-static void
-getDevice(master,slave)
- int *master,*slave;
-{
- char **p;
int i,j;
- char MasterName[DEVICELEN];
#ifdef HAVE_PTSNAME
char *pn;
@@ -362,11 +353,12 @@ getDevice(master,slave)
#if defined I_PUSH && !defined linux
if(ioctl(j, I_PUSH, "ptem") != -1) {
if(ioctl(j, I_PUSH, "ldterm") != -1) {
+ ioctl(j, I_PUSH, "ttcompat");
#endif
*master = i;
*slave = j;
- strcpy(SlaveName, pn);
- return;
+ strncpy(SlaveName, pn, sizeof SlaveName);
+ return 0;
#if defined I_PUSH && !defined linux
}
}
@@ -377,33 +369,41 @@ getDevice(master,slave)
}
close(i);
}
- rb_raise(rb_eRuntimeError, "Cannot get Master/Slave device");
+ if (!fail) rb_raise(rb_eRuntimeError, "can't get Master/Slave device");
+ return -1;
#else
+ char **p;
+ char MasterName[DEVICELEN];
+
for (p = deviceNo; *p != NULL; p++) {
- sprintf(MasterName,MasterDevice,*p);
+ snprintf(MasterName, sizeof MasterName, MasterDevice, *p);
if ((i = open(MasterName,O_RDWR,0)) >= 0) {
*master = i;
- sprintf(SlaveName,SlaveDevice,*p);
+ snprintf(SlaveName, sizeof SlaveName, SlaveDevice, *p);
if ((j = open(SlaveName,O_RDWR,0)) >= 0) {
*slave = j;
chown(SlaveName, getuid(), getgid());
chmod(SlaveName, 0622);
- return;
+ return 0;
}
close(i);
}
}
- rb_raise(rb_eRuntimeError, "Cannot get %s", SlaveName);
+ if (fail) rb_raise(rb_eRuntimeError, "can't get %s", SlaveName);
+ return -1;
+#endif
#endif
}
-#endif /* HAVE__GETPTY */
-#endif /* HAVE_OPENPTY */
static void
-freeDevice()
+getDevice(master, slave, slavename)
+ int *master, *slave;
+ char slavename[DEVICELEN];
{
- chmod(SlaveName, 0666);
- chown(SlaveName, 0, 0);
+ if (get_device_once(master, slave, slavename, 0)) {
+ rb_gc();
+ get_device_once(master, slave, slavename, 1);
+ }
}
/* ruby function: getpty */
@@ -416,14 +416,15 @@ pty_getpty(argc, argv, self)
VALUE res;
struct pty_info info;
struct pty_info thinfo;
- OpenFile *wfptr,*rfptr;
+ rb_io_t *wfptr,*rfptr;
VALUE rport = rb_obj_alloc(rb_cFile);
VALUE wport = rb_obj_alloc(rb_cFile);
-
+ char SlaveName[DEVICELEN];
+
MakeOpenFile(rport, rfptr);
MakeOpenFile(wport, wfptr);
- establishShell(argc, argv, &info);
+ establishShell(argc, argv, &info, SlaveName);
rfptr->mode = rb_io_mode_flags("r");
rfptr->f = fdopen(info.fd, "r");
diff --git a/ext/purelib.rb b/ext/purelib.rb
new file mode 100644
index 0000000000..dbe514c34a
--- /dev/null
+++ b/ext/purelib.rb
@@ -0,0 +1,10 @@
+nul = nil
+$:.each_with_index {|path, index|
+ if /\A(?:\.\/)*-\z/ =~ path
+ nul = index
+ break
+ end
+}
+if nul
+ $:[nul..-1] = ["."]
+end
diff --git a/ext/racc/cparse/MANIFEST b/ext/racc/cparse/MANIFEST
deleted file mode 100644
index 6827937750..0000000000
--- a/ext/racc/cparse/MANIFEST
+++ /dev/null
@@ -1,4 +0,0 @@
-MANIFEST
-cparse.c
-depend
-extconf.rb
diff --git a/ext/racc/cparse/cparse.c b/ext/racc/cparse/cparse.c
index c15aaf5900..18a26f670f 100644
--- a/ext/racc/cparse/cparse.c
+++ b/ext/racc/cparse/cparse.c
@@ -1,25 +1,24 @@
/*
- cparse.c -- racc runtime core
+ cparse.c -- Racc Runtime Core
- Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
+ Copyright (c) 1999-2006 Minero Aoki
This library is free software.
You can distribute/modify this program under the same terms of ruby.
- $raccId: cparse.c,v 1.3 2003/11/03 12:20:54 aamine Exp $
+ $originalId: cparse.c,v 1.8 2006/07/06 11:39:46 aamine Exp $
*/
#include "ruby.h"
-#include <stdio.h>
-
+#include "version.h"
/* -----------------------------------------------------------------------
Important Constants
----------------------------------------------------------------------- */
-#define RACC_VERSION "1.4.4"
+#define RACC_VERSION "1.4.5"
#define DEFAULT_TOKEN -1
#define ERROR_TOKEN 1
@@ -29,7 +28,6 @@
#define vERROR_TOKEN INT2FIX(ERROR_TOKEN)
#define vFINAL_TOKEN INT2FIX(FINAL_TOKEN)
-
/* -----------------------------------------------------------------------
File Local Variables
----------------------------------------------------------------------- */
@@ -41,8 +39,6 @@ static ID id_yydebug;
static ID id_nexttoken;
static ID id_onerror;
static ID id_noreduce;
-static ID id_catch;
-static VALUE sym_raccjump;
static ID id_errstatus;
static ID id_d_shift;
@@ -52,44 +48,41 @@ static ID id_d_read_token;
static ID id_d_next_state;
static ID id_d_e_pop;
-
/* -----------------------------------------------------------------------
Utils
----------------------------------------------------------------------- */
+/* For backward compatibility */
+#ifndef ID2SYM
+# define ID2SYM(i) ULONG2NUM(i)
+#endif
+#ifndef SYM2ID
+# define SYM2ID(v) ((ID)NUM2ULONG(v))
+#endif
+#ifndef SYMBOL_P
+# define SYMBOL_P(v) FIXNUM_P(v)
+#endif
+#ifndef LONG2NUM
+# define LONG2NUM(i) INT2NUM(i)
+#endif
+#if RUBY_VERSION_CODE >= 190
+# define HAVE_RB_BLOCK_CALL 1
+#endif
+
static ID value_to_id _((VALUE v));
static inline long num_to_long _((VALUE n));
-#ifdef ID2SYM
-# define id_to_value(i) ID2SYM(i)
-#else
-# define id_to_value(i) ULONG2NUM(i)
-#endif
-
static ID
-value_to_id(v)
- VALUE v;
+value_to_id(VALUE v)
{
-#ifndef SYMBOL_P
-# define SYMBOL_P(v) FIXNUM_P(v)
-#endif
if (! SYMBOL_P(v)) {
rb_raise(rb_eTypeError, "not symbol");
}
-#ifdef SYM2ID
return SYM2ID(v);
-#else
- return (ID)NUM2ULONG(v);
-#endif
}
-#ifndef LONG2NUM
-# define LONG2NUM(i) INT2NUM(i)
-#endif
-
static inline long
-num_to_long(n)
- VALUE n;
+num_to_long(VALUE n)
{
return NUM2LONG(n);
}
@@ -97,7 +90,6 @@ num_to_long(n)
#define AREF(s, idx) \
((0 <= idx && idx < RARRAY(s)->len) ? RARRAY(s)->ptr[idx] : Qnil)
-
/* -----------------------------------------------------------------------
Parser Stack Interfaces
----------------------------------------------------------------------- */
@@ -106,9 +98,7 @@ static VALUE get_stack_tail _((VALUE stack, long len));
static void cut_stack_tail _((VALUE stack, long len));
static VALUE
-get_stack_tail(stack, len)
- VALUE stack;
- long len;
+get_stack_tail(VALUE stack, long len)
{
if (len < 0) return Qnil; /* system error */
if (len > RARRAY(stack)->len) len = RARRAY(stack)->len;
@@ -116,9 +106,7 @@ get_stack_tail(stack, len)
}
static void
-cut_stack_tail(stack, len)
- VALUE stack;
- long len;
+cut_stack_tail(VALUE stack, long len)
{
while (len > 0) {
rb_ary_pop(stack);
@@ -135,7 +123,6 @@ cut_stack_tail(stack, len)
#define GET_TAIL(s, len) get_stack_tail(s, len)
#define CUT_TAIL(s, len) cut_stack_tail(s, len)
-
/* -----------------------------------------------------------------------
struct cparse_params
----------------------------------------------------------------------- */
@@ -193,7 +180,6 @@ struct cparse_params {
long i; /* table index */
};
-
/* -----------------------------------------------------------------------
Parser Main Routines
----------------------------------------------------------------------- */
@@ -203,15 +189,14 @@ static VALUE racc_yyparse _((VALUE parser, VALUE lexer, VALUE lexmid,
VALUE arg, VALUE sysdebug));
static void call_lexer _((struct cparse_params *v));
-static VALUE lexer_iter _((VALUE data));
static VALUE lexer_i _((VALUE block_args, VALUE data, VALUE self));
static VALUE assert_array _((VALUE a));
static long assert_integer _((VALUE n));
static VALUE assert_hash _((VALUE h));
-static void initialize_params _((struct cparse_params *v,
- VALUE parser, VALUE arg,
+static VALUE initialize_params _((VALUE vparams, VALUE parser, VALUE arg,
VALUE lexer, VALUE lexmid));
+static void cparse_params_mark _((void *ptr));
static void parse_main _((struct cparse_params *v,
VALUE tok, VALUE val, int resume));
@@ -219,7 +204,6 @@ static void extract_user_token _((struct cparse_params *v,
VALUE block_args, VALUE *tok, VALUE *val));
static void shift _((struct cparse_params* v, long act, VALUE tok, VALUE val));
static int reduce _((struct cparse_params* v, long act));
-static VALUE catch_iter _((VALUE dummy));
static VALUE reduce0 _((VALUE block_args, VALUE data, VALUE self));
#ifdef DEBUG
@@ -231,15 +215,16 @@ static VALUE reduce0 _((VALUE block_args, VALUE data, VALUE self));
#endif
static VALUE
-racc_cparse(parser, arg, sysdebug)
- VALUE parser, arg, sysdebug;
+racc_cparse(VALUE parser, VALUE arg, VALUE sysdebug)
{
- struct cparse_params params;
- struct cparse_params *v = &params;
+ volatile VALUE vparams;
+ struct cparse_params *v;
+ vparams = Data_Make_Struct(CparseParams, struct cparse_params,
+ cparse_params_mark, -1, v);
D_puts("starting cparse");
v->sys_debug = RTEST(sysdebug);
- initialize_params(v, parser, arg, Qnil, Qnil);
+ vparams = initialize_params(vparams, parser, arg, Qnil, Qnil);
v->lex_is_iterator = Qfalse;
parse_main(v, Qnil, Qnil, 0);
@@ -247,15 +232,16 @@ racc_cparse(parser, arg, sysdebug)
}
static VALUE
-racc_yyparse(parser, lexer, lexmid, arg, sysdebug)
- VALUE parser, lexer, lexmid, arg, sysdebug;
+racc_yyparse(VALUE parser, VALUE lexer, VALUE lexmid, VALUE arg, VALUE sysdebug)
{
- struct cparse_params params;
- struct cparse_params *v = &params;
+ volatile VALUE vparams;
+ struct cparse_params *v;
+ vparams = Data_Make_Struct(CparseParams, struct cparse_params,
+ cparse_params_mark, -1, v);
v->sys_debug = RTEST(sysdebug);
D_puts("start C yyparse");
- initialize_params(v, parser, arg, lexer, lexmid);
+ vparams = initialize_params(vparams, parser, arg, lexer, lexmid);
v->lex_is_iterator = Qtrue;
D_puts("params initialized");
parse_main(v, Qnil, Qnil, 0);
@@ -268,16 +254,15 @@ racc_yyparse(parser, lexer, lexmid, arg, sysdebug)
return v->retval;
}
+#ifdef HAVE_RB_BLOCK_CALL
static void
-call_lexer(v)
- struct cparse_params *v;
+call_lexer(struct cparse_params *v)
{
- rb_iterate(lexer_iter, v->value_v, lexer_i, v->value_v);
+ rb_block_call(v->lexer, v->lexmid, 0, NULL, lexer_i, v->value_v);
}
-
+#else
static VALUE
-lexer_iter(data)
- VALUE data;
+lexer_iter(VALUE data)
{
struct cparse_params *v;
@@ -286,9 +271,15 @@ lexer_iter(data)
return Qnil;
}
+static void
+call_lexer(struct cparse_params *v)
+{
+ rb_iterate(lexer_iter, v->value_v, lexer_i, v->value_v);
+}
+#endif
+
static VALUE
-lexer_i(block_args, data, self)
- VALUE block_args, data, self;
+lexer_i(VALUE block_args, VALUE data, VALUE self)
{
struct cparse_params *v;
VALUE tok, val;
@@ -304,35 +295,32 @@ lexer_i(block_args, data, self)
}
static VALUE
-assert_array(a)
- VALUE a;
+assert_array(VALUE a)
{
Check_Type(a, T_ARRAY);
return a;
}
static VALUE
-assert_hash(h)
- VALUE h;
+assert_hash(VALUE h)
{
Check_Type(h, T_HASH);
return h;
}
static long
-assert_integer(n)
- VALUE n;
+assert_integer(VALUE n)
{
return NUM2LONG(n);
}
-static void
-initialize_params(v, parser, arg, lexer, lexmid)
- struct cparse_params *v;
- VALUE parser, arg, lexer, lexmid;
+static VALUE
+initialize_params(VALUE vparams, VALUE parser, VALUE arg, VALUE lexer, VALUE lexmid)
{
- v->value_v = Data_Wrap_Struct(CparseParams, 0, 0, v);
+ struct cparse_params *v;
+ Data_Get_Struct(vparams, struct cparse_params, v);
+ v->value_v = vparams;
v->parser = parser;
v->lexer = lexer;
if (! NIL_P(lexmid))
@@ -377,13 +365,46 @@ initialize_params(v, parser, arg, lexer, lexmid)
v->fin = 0;
v->lex_is_iterator = Qfalse;
+
+ rb_iv_set(parser, "@vstack", v->vstack);
+ if (v->debug) {
+ rb_iv_set(parser, "@tstack", v->tstack);
+ }
+ else {
+ rb_iv_set(parser, "@tstack", Qnil);
+ }
+
+ return vparams;
}
static void
-extract_user_token(v, block_args, tok, val)
- struct cparse_params *v;
- VALUE block_args;
- VALUE *tok, *val;
+cparse_params_mark(void *ptr)
+{
+ struct cparse_params *v = (struct cparse_params*)ptr;
+
+ rb_gc_mark(v->value_v);
+ rb_gc_mark(v->parser);
+ rb_gc_mark(v->lexer);
+ rb_gc_mark(v->action_table);
+ rb_gc_mark(v->action_check);
+ rb_gc_mark(v->action_default);
+ rb_gc_mark(v->action_pointer);
+ rb_gc_mark(v->goto_table);
+ rb_gc_mark(v->goto_check);
+ rb_gc_mark(v->goto_default);
+ rb_gc_mark(v->goto_pointer);
+ rb_gc_mark(v->reduce_table);
+ rb_gc_mark(v->token_table);
+ rb_gc_mark(v->state);
+ rb_gc_mark(v->vstack);
+ rb_gc_mark(v->tstack);
+ rb_gc_mark(v->t);
+ rb_gc_mark(v->retval);
+}
+
+static void
+extract_user_token(struct cparse_params *v, VALUE block_args,
+ VALUE *tok, VALUE *val)
{
if (NIL_P(block_args)) {
/* EOF */
@@ -426,10 +447,7 @@ extract_user_token(v, block_args, tok, val)
} while (0)
static void
-parse_main(v, tok, val, resume)
- struct cparse_params *v;
- VALUE tok, val;
- int resume;
+parse_main(struct cparse_params *v, VALUE tok, VALUE val, int resume)
{
long i; /* table index */
long act; /* action type */
@@ -468,8 +486,10 @@ parse_main(v, tok, val, resume)
extract_user_token(v, tmp, &tok, &val);
}
/* convert token */
- tmp = rb_hash_aref(v->token_table, tok);
- v->t = NIL_P(tmp) ? vERROR_TOKEN : tmp;
+ v->t = rb_hash_aref(v->token_table, tok);
+ if (NIL_P(v->t)) {
+ v->t = vERROR_TOKEN;
+ }
D_printf("(act) t(k2)=%ld\n", NUM2LONG(v->t));
if (v->debug) {
rb_funcall(v->parser, id_d_read_token,
@@ -636,10 +656,7 @@ parse_main(v, tok, val, resume)
}
static void
-shift(v, act, tok, val)
- struct cparse_params *v;
- long act;
- VALUE tok, val;
+shift(struct cparse_params *v, long act, VALUE tok, VALUE val)
{
PUSH(v->vstack, val);
if (v->debug) {
@@ -652,33 +669,23 @@ shift(v, act, tok, val)
}
static int
-reduce(v, act)
- struct cparse_params *v;
- long act;
+reduce(struct cparse_params *v, long act)
{
VALUE code;
v->ruleno = -act * 3;
- code = rb_iterate(catch_iter, Qnil, reduce0, v->value_v);
+ code = rb_catch("racc_jump", reduce0, v->value_v);
v->errstatus = num_to_long(rb_ivar_get(v->parser, id_errstatus));
return NUM2INT(code);
}
static VALUE
-catch_iter(dummy)
- VALUE dummy;
-{
- return rb_funcall(rb_mKernel, id_catch, 1, sym_raccjump);
-}
-
-static VALUE
-reduce0(val, data, self)
- VALUE val, data, self;
+reduce0(VALUE val, VALUE data, VALUE self)
{
struct cparse_params *v;
VALUE reduce_to, reduce_len, method_id;
long len;
ID mid;
- VALUE tmp, tmp_t, tmp_v;
+ VALUE tmp, tmp_t = Qundef, tmp_v = Qundef;
long i, k1, k2;
VALUE goto_state;
@@ -733,7 +740,7 @@ reduce0(val, data, self)
/* calculate transition state */
if (RARRAY(v->state)->len == 0)
- rb_raise(RaccBug, "state stack unexpected empty");
+ rb_raise(RaccBug, "state stack unexpectedly empty");
k2 = num_to_long(LAST_I(v->state));
k1 = num_to_long(reduce_to) - v->nt_base;
D_printf("(goto) k1=%ld\n", k1);
@@ -777,13 +784,12 @@ reduce0(val, data, self)
goto transit;
}
-
/* -----------------------------------------------------------------------
Ruby Interface
----------------------------------------------------------------------- */
void
-Init_cparse()
+Init_cparse(void)
{
VALUE Racc, Parser;
ID id_racc = rb_intern("Racc");
@@ -801,7 +807,7 @@ Init_cparse()
rb_define_const(Parser, "Racc_Runtime_Core_Version_C",
rb_str_new2(RACC_VERSION));
rb_define_const(Parser, "Racc_Runtime_Core_Id_C",
- rb_str_new2("$raccId: cparse.c,v 1.3 2003/11/03 12:20:54 aamine Exp $"));
+ rb_str_new2("$originalId: cparse.c,v 1.8 2006/07/06 11:39:46 aamine Exp $"));
CparseParams = rb_define_class_under(Racc, "CparseParams", rb_cObject);
@@ -811,9 +817,7 @@ Init_cparse()
id_nexttoken = rb_intern("next_token");
id_onerror = rb_intern("on_error");
id_noreduce = rb_intern("_reduce_none");
- id_catch = rb_intern("catch");
id_errstatus = rb_intern("@racc_error_status");
- sym_raccjump = id_to_value(rb_intern("racc_jump"));
id_d_shift = rb_intern("racc_shift");
id_d_reduce = rb_intern("racc_reduce");
diff --git a/ext/readline/MANIFEST b/ext/readline/MANIFEST
deleted file mode 100644
index 4dd1d9e1a1..0000000000
--- a/ext/readline/MANIFEST
+++ /dev/null
@@ -1,6 +0,0 @@
-MANIFEST
-README
-README.ja
-depend
-extconf.rb
-readline.c
diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb
index b883de3e01..b820c0b32f 100644
--- a/ext/readline/extconf.rb
+++ b/ext/readline/extconf.rb
@@ -1,27 +1,64 @@
require "mkmf"
+$readline_headers = ["stdio.h"]
+
+def have_readline_header(header)
+ if have_header(header)
+ $readline_headers.push(header)
+ return true
+ else
+ return false
+ end
+end
+
+def have_readline_var(var)
+ return have_var(var, $readline_headers)
+end
+
+dir_config('curses')
+dir_config('ncurses')
+dir_config('termcap')
dir_config("readline")
+enable_libedit = enable_config("libedit")
have_library("user32", nil) if /cygwin/ === RUBY_PLATFORM
-have_library("ncurses", "tgetnum") or
- have_library("termcap", "tgetnum") or
+have_library("ncurses", "tgetnum") ||
+ have_library("termcap", "tgetnum") ||
have_library("curses", "tgetnum")
-if have_header("readline/readline.h") and
- have_header("readline/history.h") and
- have_library("readline", "readline")
- if have_func("rl_filename_completion_function")
- $CFLAGS += " -DREADLINE_42_OR_LATER"
+if enable_libedit
+ unless (have_readline_header("editline/readline.h") ||
+ have_readline_header("readline/readline.h")) &&
+ have_library("edit", "readline")
+ exit
end
- if have_func("rl_cleanup_after_signal")
- $CFLAGS += " -DREADLINE_40_OR_LATER"
+else
+ unless ((have_readline_header("readline/readline.h") &&
+ have_readline_header("readline/history.h")) &&
+ (have_library("readline", "readline") ||
+ have_library("edit", "readline"))) ||
+ (have_readline_header("editline/readline.h") &&
+ have_library("edit", "readline"))
+ exit
end
- if try_link(<<EOF, $libs)
-#include <stdio.h>
-#include <readline/readline.h>
-main() {rl_completion_append_character = 1;}
-EOF
- # this feature is implemented in readline-2.1 or later.
- $CFLAGS += " -DREADLINE_21_OR_LATER"
- end
- create_makefile("readline")
end
+
+have_func("rl_filename_completion_function")
+have_func("rl_username_completion_function")
+have_func("rl_completion_matches")
+have_readline_var("rl_deprep_term_function")
+have_readline_var("rl_completion_append_character")
+have_readline_var("rl_basic_word_break_characters")
+have_readline_var("rl_completer_word_break_characters")
+have_readline_var("rl_basic_quote_characters")
+have_readline_var("rl_completer_quote_characters")
+have_readline_var("rl_filename_quote_characters")
+have_readline_var("rl_attempted_completion_over")
+have_readline_var("rl_library_version")
+have_readline_var("rl_event_hook")
+have_func("rl_cleanup_after_signal")
+have_func("rl_clear_signals")
+have_func("rl_vi_editing_mode")
+have_func("rl_emacs_editing_mode")
+have_func("replace_history_entry")
+have_func("remove_history")
+create_makefile("readline")
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index cac0b1d11c..c9acaadac9 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -1,12 +1,23 @@
/* readline.c -- GNU Readline module
Copyright (C) 1997-2001 Shugo Maeda */
+#include "config.h"
#include <errno.h>
#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef HAVE_READLINE_READLINE_H
#include <readline/readline.h>
+#endif
+#ifdef HAVE_READLINE_HISTORY_H
#include <readline/history.h>
+#endif
+#ifdef HAVE_EDITLINE_READLINE_H
+#include <editline/readline.h>
+#endif
#include "ruby.h"
+#include "rubyio.h"
#include "rubysig.h"
#ifdef HAVE_UNISTD_H
@@ -19,20 +30,44 @@ static VALUE mReadline;
#define COMPLETION_PROC "completion_proc"
#define COMPLETION_CASE_FOLD "completion_case_fold"
+static ID completion_proc, completion_case_fold;
-#ifndef READLINE_42_OR_LATER
+#ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
# define rl_filename_completion_function filename_completion_function
+#endif
+#ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION
# define rl_username_completion_function username_completion_function
+#endif
+#ifndef HAVE_RL_COMPLETION_MATCHES
# define rl_completion_matches completion_matches
#endif
+static char **readline_attempted_completion_function(const char *text,
+ int start, int end);
+
+#ifdef HAVE_RL_EVENT_HOOK
+#ifdef DOSISH
+#define BUSY_WAIT 1
+#else
+#define BUSY_WAIT 0
+#endif
+
+static int readline_event(void);
static int
readline_event()
{
- CHECK_INTS;
+#if BUSY_WAIT
rb_thread_schedule();
+#else
+ fd_set rset;
+
+ FD_ZERO(&rset);
+ FD_SET(fileno(rl_instream), &rset);
+ rb_thread_select(fileno(rl_instream) + 1, &rset, NULL, NULL, NULL);
return 0;
+#endif
}
+#endif
static VALUE
readline_readline(argc, argv, self)
@@ -44,22 +79,33 @@ readline_readline(argc, argv, self)
char *prompt = NULL;
char *buff;
int status;
+ rb_io_t *ofp, *ifp;
+ rb_secure(4);
if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
- prompt = StringValuePtr(tmp);
+ SafeStringValue(tmp);
+ prompt = RSTRING(tmp)->ptr;
}
if (!isatty(0) && errno == EBADF) rb_raise(rb_eIOError, "stdin closed");
+ Check_Type(rb_stdout, T_FILE);
+ GetOpenFile(rb_stdout, ofp);
+ rl_outstream = GetWriteFile(ofp);
+ Check_Type(rb_stdin, T_FILE);
+ GetOpenFile(rb_stdin, ifp);
+ rl_instream = GetReadFile(ifp);
buff = (char*)rb_protect((VALUE(*)_((VALUE)))readline, (VALUE)prompt,
&status);
if (status) {
-#if defined READLINE_40_OR_LATER
+#if defined HAVE_RL_CLEANUP_AFTER_SIGNAL
/* restore terminal mode and signal handler*/
rl_cleanup_after_signal();
-#elif defined READLINE_21_OR_LATER
+#elif defined HAVE_RL_DEPREP_TERM_FUNCTION
/* restore terminal mode */
- (*rl_deprep_term_function)();
+ if (rl_deprep_term_function != NULL) /* NULL in libedit. [ruby-dev:29116] */
+ (*rl_deprep_term_function)();
+ else
#else
rl_deprep_terminal();
#endif
@@ -82,16 +128,18 @@ readline_s_set_completion_proc(self, proc)
VALUE self;
VALUE proc;
{
+ rb_secure(4);
if (!rb_respond_to(proc, rb_intern("call")))
- rb_raise(rb_eArgError, "argument have to respond to `call'");
- return rb_iv_set(mReadline, COMPLETION_PROC, proc);
+ rb_raise(rb_eArgError, "argument must respond to `call'");
+ return rb_ivar_set(mReadline, completion_proc, proc);
}
static VALUE
readline_s_get_completion_proc(self)
VALUE self;
{
- return rb_iv_get(mReadline, COMPLETION_PROC);
+ rb_secure(4);
+ return rb_attr_get(mReadline, completion_proc);
}
static VALUE
@@ -99,19 +147,21 @@ readline_s_set_completion_case_fold(self, val)
VALUE self;
VALUE val;
{
- return rb_iv_set(mReadline, COMPLETION_CASE_FOLD, val);
+ rb_secure(4);
+ return rb_ivar_set(mReadline, completion_case_fold, val);
}
static VALUE
readline_s_get_completion_case_fold(self)
VALUE self;
{
- return rb_iv_get(mReadline, COMPLETION_CASE_FOLD);
+ rb_secure(4);
+ return rb_attr_get(mReadline, completion_case_fold);
}
static char **
readline_attempted_completion_function(text, start, end)
- char *text;
+ const char *text;
int start;
int end;
{
@@ -120,11 +170,13 @@ readline_attempted_completion_function(text, start, end)
int case_fold;
int i, matches;
- proc = rb_iv_get(mReadline, COMPLETION_PROC);
+ proc = rb_attr_get(mReadline, completion_proc);
if (NIL_P(proc))
return NULL;
+#ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER
rl_attempted_completion_over = 1;
- case_fold = RTEST(rb_iv_get(mReadline, COMPLETION_CASE_FOLD));
+#endif
+ case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold));
ary = rb_funcall(proc, rb_intern("call"), 1, rb_tainted_str_new2(text));
if (TYPE(ary) != T_ARRAY)
ary = rb_Array(ary);
@@ -140,9 +192,9 @@ readline_attempted_completion_function(text, start, end)
result[matches + 1] = NULL;
if (matches == 1) {
- result[0] = result[1];
- result[1] = NULL;
- } else {
+ result[0] = strdup(result[1]);
+ }
+ else {
register int i = 1;
int low = 100000;
@@ -178,62 +230,83 @@ static VALUE
readline_s_vi_editing_mode(self)
VALUE self;
{
+#ifdef HAVE_RL_VI_EDITING_MODE
+ rb_secure(4);
rl_vi_editing_mode(1,0);
return Qnil;
+#else
+ rb_notimplement();
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_VI_EDITING_MODE */
}
static VALUE
readline_s_emacs_editing_mode(self)
VALUE self;
{
+#ifdef HAVE_RL_EMACS_EDITING_MODE
+ rb_secure(4);
rl_emacs_editing_mode(1,0);
return Qnil;
+#else
+ rb_notimplement();
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_EMACS_EDITING_MODE */
}
static VALUE
readline_s_set_completion_append_character(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
- if (NIL_P(str) || !StringValuePtr(str) || !RSTRING(str)->len) {
+#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
+ rb_secure(4);
+ if (NIL_P(str)) {
rl_completion_append_character = '\0';
- } else {
- rl_completion_append_character = RSTRING(str)->ptr[0];
}
-
+ else {
+ SafeStringValue(str);
+ if (RSTRING(str)->len == 0) {
+ rl_completion_append_character = '\0';
+ } else {
+ rl_completion_append_character = RSTRING(str)->ptr[0];
+ }
+ }
return self;
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_COMPLETION_APPEND_CHARACTER */
}
static VALUE
readline_s_get_completion_append_character(self)
VALUE self;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
VALUE str;
+ rb_secure(4);
if (rl_completion_append_character == '\0')
return Qnil;
str = rb_str_new("", 1);
RSTRING(str)->ptr[0] = rl_completion_append_character;
-
return str;
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_COMPLETION_APPEND_CHARACTER */
}
static VALUE
readline_s_set_basic_word_break_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
static char *basic_word_break_characters = NULL;
- StringValue(str);
+ rb_secure(4);
+ SafeStringValue(str);
if (basic_word_break_characters == NULL) {
basic_word_break_characters =
ALLOC_N(char, RSTRING(str)->len + 1);
@@ -245,34 +318,37 @@ readline_s_set_basic_word_break_characters(self, str)
RSTRING(str)->ptr, RSTRING(str)->len);
basic_word_break_characters[RSTRING(str)->len] = '\0';
rl_basic_word_break_characters = basic_word_break_characters;
-
return self;
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_BASIC_WORD_BREAK_CHARACTERS */
}
static VALUE
readline_s_get_basic_word_break_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
+ rb_secure(4);
if (rl_basic_word_break_characters == NULL)
return Qnil;
- return rb_str_new2(rl_basic_word_break_characters);
+ return rb_tainted_str_new2(rl_basic_word_break_characters);
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_BASIC_WORD_BREAK_CHARACTERS */
}
static VALUE
readline_s_set_completer_word_break_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
static char *completer_word_break_characters = NULL;
- StringValue(str);
+ rb_secure(4);
+ SafeStringValue(str);
if (completer_word_break_characters == NULL) {
completer_word_break_characters =
ALLOC_N(char, RSTRING(str)->len + 1);
@@ -284,34 +360,37 @@ readline_s_set_completer_word_break_characters(self, str)
RSTRING(str)->ptr, RSTRING(str)->len);
completer_word_break_characters[RSTRING(str)->len] = '\0';
rl_completer_word_break_characters = completer_word_break_characters;
-
return self;
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS */
}
static VALUE
readline_s_get_completer_word_break_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
+ rb_secure(4);
if (rl_completer_word_break_characters == NULL)
return Qnil;
- return rb_str_new2(rl_completer_word_break_characters);
+ return rb_tainted_str_new2(rl_completer_word_break_characters);
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS */
}
static VALUE
readline_s_set_basic_quote_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
static char *basic_quote_characters = NULL;
- StringValue(str);
+ rb_secure(4);
+ SafeStringValue(str);
if (basic_quote_characters == NULL) {
basic_quote_characters =
ALLOC_N(char, RSTRING(str)->len + 1);
@@ -327,30 +406,34 @@ readline_s_set_basic_quote_characters(self, str)
return self;
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_BASIC_QUOTE_CHARACTERS */
}
static VALUE
readline_s_get_basic_quote_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
+ rb_secure(4);
if (rl_basic_quote_characters == NULL)
return Qnil;
- return rb_str_new2(rl_basic_quote_characters);
+ return rb_tainted_str_new2(rl_basic_quote_characters);
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_BASIC_QUOTE_CHARACTERS */
}
static VALUE
readline_s_set_completer_quote_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
static char *completer_quote_characters = NULL;
- StringValue(str);
+ rb_secure(4);
+ SafeStringValue(str);
if (completer_quote_characters == NULL) {
completer_quote_characters =
ALLOC_N(char, RSTRING(str)->len + 1);
@@ -366,30 +449,34 @@ readline_s_set_completer_quote_characters(self, str)
return self;
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_COMPLETER_QUOTE_CHARACTERS */
}
static VALUE
readline_s_get_completer_quote_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
+ rb_secure(4);
if (rl_completer_quote_characters == NULL)
return Qnil;
- return rb_str_new2(rl_completer_quote_characters);
+ return rb_tainted_str_new2(rl_completer_quote_characters);
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_COMPLETER_QUOTE_CHARACTERS */
}
static VALUE
readline_s_set_filename_quote_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
static char *filename_quote_characters = NULL;
- StringValue(str);
+ rb_secure(4);
+ SafeStringValue(str);
if (filename_quote_characters == NULL) {
filename_quote_characters =
ALLOC_N(char, RSTRING(str)->len + 1);
@@ -405,37 +492,23 @@ readline_s_set_filename_quote_characters(self, str)
return self;
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_FILENAME_QUOTE_CHARACTERS */
}
static VALUE
readline_s_get_filename_quote_characters(self, str)
VALUE self, str;
{
-#ifdef READLINE_21_OR_LATER
+#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
+ rb_secure(4);
if (rl_filename_quote_characters == NULL)
return Qnil;
- return rb_str_new2(rl_filename_quote_characters);
+ return rb_tainted_str_new2(rl_filename_quote_characters);
#else
rb_notimplement();
-#endif /* READLINE_21_OR_LATER */
-}
-
-static VALUE
-rb_remove_history(index)
- int index;
-{
- HIST_ENTRY *entry;
- VALUE val;
-
- entry = remove_history(index);
- if (entry) {
- val = rb_tainted_str_new2(entry->line);
- free(entry->line);
- free(entry);
- return val;
- }
- return Qnil;
+ return Qnil; /* not reached */
+#endif /* HAVE_RL_FILENAME_QUOTE_CHARACTERS */
}
static VALUE
@@ -450,18 +523,19 @@ hist_get(self, index)
VALUE self;
VALUE index;
{
- HISTORY_STATE *state;
+ HIST_ENTRY *entry;
int i;
- state = history_get_history_state();
+ rb_secure(4);
i = NUM2INT(index);
if (i < 0) {
- i += state->length;
+ i += history_length;
}
- if (i < 0 || i > state->length - 1) {
- rb_raise(rb_eIndexError, "Invalid index");
+ entry = history_get(history_base + i);
+ if (entry == NULL) {
+ rb_raise(rb_eIndexError, "invalid index");
}
- return rb_tainted_str_new2(state->entries[i]->line);
+ return rb_tainted_str_new2(entry->line);
}
static VALUE
@@ -470,20 +544,25 @@ hist_set(self, index, str)
VALUE index;
VALUE str;
{
- HISTORY_STATE *state;
- VALUE s = str;
+#ifdef HAVE_REPLACE_HISTORY_ENTRY
+ HIST_ENTRY *entry;
int i;
- state = history_get_history_state();
+ rb_secure(4);
i = NUM2INT(index);
+ SafeStringValue(str);
if (i < 0) {
- i += state->length;
+ i += history_length;
}
- if (i < 0 || i > state->length - 1) {
- rb_raise(rb_eIndexError, "Invalid index");
+ entry = replace_history_entry(i, RSTRING(str)->ptr, NULL);
+ if (entry == NULL) {
+ rb_raise(rb_eIndexError, "invalid index");
}
- replace_history_entry(i, StringValuePtr(s), NULL);
return str;
+#else
+ rb_notimplement();
+ return Qnil; /* not reached */
+#endif
}
static VALUE
@@ -491,7 +570,9 @@ hist_push(self, str)
VALUE self;
VALUE str;
{
- add_history(StringValuePtr(str));
+ rb_secure(4);
+ SafeStringValue(str);
+ add_history(RSTRING(str)->ptr);
return self;
}
@@ -503,22 +584,45 @@ hist_push_method(argc, argv, self)
{
VALUE str;
+ rb_secure(4);
while (argc--) {
str = *argv++;
- add_history(StringValuePtr(str));
+ SafeStringValue(str);
+ add_history(RSTRING(str)->ptr);
}
return self;
}
static VALUE
+rb_remove_history(index)
+ int index;
+{
+#ifdef HAVE_REMOVE_HISTORY
+ HIST_ENTRY *entry;
+ VALUE val;
+
+ rb_secure(4);
+ entry = remove_history(index);
+ if (entry) {
+ val = rb_tainted_str_new2(entry->line);
+ free(entry->line);
+ free(entry);
+ return val;
+ }
+ return Qnil;
+#else
+ rb_notimplement();
+ return Qnil; /* not reached */
+#endif
+}
+
+static VALUE
hist_pop(self)
VALUE self;
{
- HISTORY_STATE *state;
-
- state = history_get_history_state();
- if (state->length > 0) {
- return rb_remove_history(state->length - 1);
+ rb_secure(4);
+ if (history_length > 0) {
+ return rb_remove_history(history_length - 1);
} else {
return Qnil;
}
@@ -528,10 +632,8 @@ static VALUE
hist_shift(self)
VALUE self;
{
- HISTORY_STATE *state;
-
- state = history_get_history_state();
- if (state->length > 0) {
+ rb_secure(4);
+ if (history_length > 0) {
return rb_remove_history(0);
} else {
return Qnil;
@@ -542,12 +644,15 @@ static VALUE
hist_each(self)
VALUE self;
{
- HISTORY_STATE *state;
+ HIST_ENTRY *entry;
int i;
- state = history_get_history_state();
- for (i = 0; i < state->length; i++) {
- rb_yield(rb_tainted_str_new2(state->entries[i]->line));
+ rb_secure(4);
+ for (i = 0; i < history_length; i++) {
+ entry = history_get(history_base + i);
+ if (entry == NULL)
+ break;
+ rb_yield(rb_tainted_str_new2(entry->line));
}
return self;
}
@@ -556,23 +661,16 @@ static VALUE
hist_length(self)
VALUE self;
{
- HISTORY_STATE *state;
-
- state = history_get_history_state();
- return INT2NUM(state->length);
+ rb_secure(4);
+ return INT2NUM(history_length);
}
static VALUE
hist_empty_p(self)
VALUE self;
{
- HISTORY_STATE *state;
-
- state = history_get_history_state();
- if (state->length == 0)
- return Qtrue;
- else
- return Qfalse;
+ rb_secure(4);
+ return history_length == 0 ? Qtrue : Qfalse;
}
static VALUE
@@ -580,15 +678,14 @@ hist_delete_at(self, index)
VALUE self;
VALUE index;
{
- HISTORY_STATE *state;
int i;
- state = history_get_history_state();
+ rb_secure(4);
i = NUM2INT(index);
if (i < 0)
- i += state->length;
- if (i < 0 || i > state->length - 1) {
- rb_raise(rb_eIndexError, "Invalid index");
+ i += history_length;
+ if (i < 0 || i > history_length - 1) {
+ rb_raise(rb_eIndexError, "invalid index");
}
return rb_remove_history(i);
}
@@ -657,6 +754,9 @@ Init_readline()
using_history();
+ completion_proc = rb_intern(COMPLETION_PROC);
+ completion_case_fold = rb_intern(COMPLETION_CASE_FOLD);
+
mReadline = rb_define_module("Readline");
rb_define_module_function(mReadline, "readline",
readline_readline, -1);
@@ -709,7 +809,6 @@ Init_readline()
rb_define_singleton_method(history,"each", hist_each, 0);
rb_define_singleton_method(history,"length", hist_length, 0);
rb_define_singleton_method(history,"size", hist_length, 0);
-
rb_define_singleton_method(history,"empty?", hist_empty_p, 0);
rb_define_singleton_method(history,"delete_at", hist_delete_at, 1);
rb_define_const(mReadline, "HISTORY", history);
@@ -723,21 +822,18 @@ Init_readline()
rb_define_singleton_method(ucomp, "call",
username_completion_proc_call, 1);
rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp);
-#if defined READLINE_21_OR_LATER
+#if defined HAVE_RL_LIBRARY_VERSION
rb_define_const(mReadline, "VERSION", rb_str_new2(rl_library_version));
#else
rb_define_const(mReadline, "VERSION",
rb_str_new2("2.0 or before version"));
#endif
-#if defined READLINE_42_OR_LATER
- rl_attempted_completion_function
- = (rl_completion_func_t *)readline_attempted_completion_function;
- rl_event_hook = (rl_hook_func_t *)readline_event;
-#else
- rl_attempted_completion_function
- = (CPPFunction *) readline_attempted_completion_function;
+ rl_attempted_completion_function = readline_attempted_completion_function;
+#ifdef HAVE_RL_EVENT_HOOK
rl_event_hook = readline_event;
#endif
+#ifdef HAVE_RL_CLEAR_SIGNALS
rl_clear_signals();
+#endif
}
diff --git a/ext/sdbm/MANIFEST b/ext/sdbm/MANIFEST
deleted file mode 100644
index 6e1dc6bebd..0000000000
--- a/ext/sdbm/MANIFEST
+++ /dev/null
@@ -1,7 +0,0 @@
-MANIFEST
-_sdbm.c
-depend
-extconf.rb
-init.c
-sdbm.h
-testsdbm.rb
diff --git a/ext/sdbm/_sdbm.c b/ext/sdbm/_sdbm.c
index d8bfae80b2..5b34824afc 100644
--- a/ext/sdbm/_sdbm.c
+++ b/ext/sdbm/_sdbm.c
@@ -71,7 +71,7 @@ static int duppair proto((char *, datum));
#include <stdio.h>
#include <stdlib.h>
-#ifdef MSDOS
+#ifdef DOSISH
#include <io.h>
#endif
#include <sys/types.h>
@@ -103,7 +103,7 @@ static int duppair proto((char *, datum));
/*
* externals
*/
-#if !defined sun && !defined MSDOS && !defined _WIN32 && !defined __CYGWIN__
+#if !defined sun && !defined MSDOS && !defined _WIN32 && !defined __CYGWIN__ && !defined(errno)
extern int errno;
#endif
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
index f473555840..acadc9b26a 100644
--- a/ext/sdbm/init.c
+++ b/ext/sdbm/init.c
@@ -31,9 +31,15 @@ closed_sdbm()
#define GetDBM(obj, dbmp) {\
Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp == 0) closed_sdbm();\
if (dbmp->di_dbm == 0) closed_sdbm();\
}
+#define GetDBM2(obj, data, dbm) {\
+ GetDBM(obj, data);\
+ (dbm) = dbmp->di_dbm;\
+}
+
static void
free_sdbm(dbmp)
struct dbmdata *dbmp;
@@ -56,6 +62,21 @@ fsdbm_close(obj)
return Qnil;
}
+static VALUE
+fsdbm_closed(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp == 0)
+ return Qtrue;
+ if (dbmp->di_dbm == 0)
+ return Qtrue;
+
+ return Qfalse;
+}
+
static VALUE fsdbm_alloc _((VALUE));
static VALUE
fsdbm_alloc(klass)
@@ -138,8 +159,7 @@ fsdbm_fetch(obj, keystr, ifnone)
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
value = sdbm_fetch(dbm, key);
if (value.dptr == 0) {
if (ifnone == Qnil && rb_block_given_p())
@@ -184,8 +204,7 @@ fsdbm_index(obj, valstr)
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
if (val.dsize == RSTRING(valstr)->len &&
@@ -227,18 +246,19 @@ fsdbm_select(argc, argv, obj)
struct dbmdata *dbmp;
if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc);
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
}
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- VALUE assoc;
+ VALUE assoc, v;
val = sdbm_fetch(dbm, key);
assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
rb_tainted_str_new(val.dptr, val.dsize));
- if (RTEST(rb_yield(assoc)))
- rb_ary_push(new, assoc);
+ v = rb_yield(assoc);
+ if (RTEST(v)) {
+ rb_ary_push(new, assoc);
+ }
+ GetDBM2(obj, dbmp, dbm);
}
}
else {
@@ -268,6 +288,14 @@ fsdbm_values_at(argc, argv, obj)
return new;
}
+static void
+fdbm_modify(obj)
+ VALUE obj;
+{
+ rb_secure(4);
+ if (OBJ_FROZEN(obj)) rb_error_frozen("SDBM");
+}
+
static VALUE
fsdbm_delete(obj, keystr)
VALUE obj, keystr;
@@ -277,13 +305,12 @@ fsdbm_delete(obj, keystr)
DBM *dbm;
VALUE valstr;
- rb_secure(4);
+ fdbm_modify(obj);
StringValue(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
dbmp->di_size = -1;
value = sdbm_fetch(dbm, key);
@@ -314,10 +341,8 @@ fsdbm_shift(obj)
DBM *dbm;
VALUE keystr, valstr;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ fdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
key = sdbm_firstkey(dbm);
if (!key.dptr) return Qnil;
val = sdbm_fetch(dbm, key);
@@ -342,9 +367,8 @@ fsdbm_delete_if(obj)
VALUE ret, ary = rb_ary_new();
int i, status = 0, n;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ fdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
n = dbmp->di_size;
dbmp->di_size = -1;
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
@@ -354,10 +378,12 @@ fsdbm_delete_if(obj)
ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
if (status != 0) break;
if (RTEST(ret)) rb_ary_push(ary, keystr);
+ GetDBM2(obj, dbmp, dbm);
}
for (i = 0; i < RARRAY(ary)->len; i++) {
keystr = RARRAY(ary)->ptr[i];
+ StringValue(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
if (sdbm_delete(dbm, key)) {
@@ -378,9 +404,8 @@ fsdbm_clear(obj)
struct dbmdata *dbmp;
DBM *dbm;
- rb_secure(4);
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ fdbm_modify(obj);
+ GetDBM2(obj, dbmp, dbm);
dbmp->di_size = -1;
while (key = sdbm_firstkey(dbm), key.dptr) {
if (sdbm_delete(dbm, key)) {
@@ -402,8 +427,7 @@ fsdbm_invert(obj)
VALUE keystr, valstr;
VALUE hash = rb_hash_new();
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
keystr = rb_tainted_str_new(key.dptr, key.dsize);
@@ -466,21 +490,18 @@ fsdbm_store(obj, keystr, valstr)
return Qnil;
}
- rb_secure(4);
- keystr = rb_obj_as_string(keystr);
+ fdbm_modify(obj);
+ StringValue(keystr);
+ StringValue(valstr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- if (NIL_P(valstr)) return fsdbm_delete(obj, keystr);
-
- valstr = rb_obj_as_string(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- GetDBM(obj, dbmp);
+ GetDBM2(obj, dbmp, dbm);
dbmp->di_size = -1;
- dbm = dbmp->di_dbm;
if (sdbm_store(dbm, key, val, DBM_REPLACE)) {
#ifdef HAVE_DBM_CLAERERR
sdbm_clearerr(dbm);
@@ -501,9 +522,8 @@ fsdbm_length(obj)
DBM *dbm;
int i = 0;
- GetDBM(obj, dbmp);
+ GetDBM2(obj, dbmp, dbm);
if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
- dbm = dbmp->di_dbm;
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
i++;
@@ -545,11 +565,11 @@ fsdbm_each_value(obj)
struct dbmdata *dbmp;
DBM *dbm;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
}
@@ -562,10 +582,10 @@ fsdbm_each_key(obj)
struct dbmdata *dbmp;
DBM *dbm;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
}
@@ -579,14 +599,13 @@ fsdbm_each_pair(obj)
struct dbmdata *dbmp;
VALUE keystr, valstr;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
keystr = rb_tainted_str_new(key.dptr, key.dsize);
valstr = rb_tainted_str_new(val.dptr, val.dsize);
rb_yield(rb_assoc_new(keystr, valstr));
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
@@ -601,9 +620,7 @@ fsdbm_keys(obj)
DBM *dbm;
VALUE ary;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
@@ -621,9 +638,7 @@ fsdbm_values(obj)
DBM *dbm;
VALUE ary;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
@@ -645,8 +660,7 @@ fsdbm_has_key(obj, keystr)
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
val = sdbm_fetch(dbm, key);
if (val.dptr) return Qtrue;
return Qfalse;
@@ -664,8 +678,7 @@ fsdbm_has_value(obj, valstr)
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
+ GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
if (val.dsize == RSTRING(valstr)->len &&
@@ -684,9 +697,7 @@ fsdbm_to_a(obj)
DBM *dbm;
VALUE ary;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
@@ -706,9 +717,7 @@ fsdbm_to_hash(obj)
DBM *dbm;
VALUE hash;
- GetDBM(obj, dbmp);
- dbm = dbmp->di_dbm;
-
+ GetDBM2(obj, dbmp, dbm);
hash = rb_hash_new();
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
@@ -738,6 +747,7 @@ Init_sdbm()
rb_define_method(rb_cDBM, "initialize", fsdbm_initialize, -1);
rb_define_method(rb_cDBM, "close", fsdbm_close, 0);
+ rb_define_method(rb_cDBM, "closed?", fsdbm_closed, 0);
rb_define_method(rb_cDBM, "[]", fsdbm_aref, 1);
rb_define_method(rb_cDBM, "fetch", fsdbm_fetch_m, -1);
rb_define_method(rb_cDBM, "[]=", fsdbm_store, 2);
diff --git a/ext/sdbm/testsdbm.rb b/ext/sdbm/testsdbm.rb
deleted file mode 100644
index 5a185fd5c4..0000000000
--- a/ext/sdbm/testsdbm.rb
+++ /dev/null
@@ -1,556 +0,0 @@
-require 'runit/testcase'
-require 'runit/cui/testrunner'
-
-if $".grep(/\bsdbm.so\b/).empty?
- begin
- require './sdbm'
- rescue LoadError
- require 'sdbm'
- end
-end
-
-def uname_s
- require 'rbconfig'
- case Config::CONFIG['host_os']
- when 'cygwin'
- require 'Win32API'
- uname = Win32API.new('cygwin1', 'uname', 'P', 'I')
- utsname = ' ' * 100
- raise 'cannot get system name' if uname.call(utsname) == -1
-
- utsname.unpack('A20' * 5)[0]
- else
- Config::CONFIG['host_os']
- end
-end
-
-SYSTEM = uname_s
-
-class TestSDBM < RUNIT::TestCase
- def setup
- @path = "tmptest_sdbm_"
- assert_instance_of(SDBM, @sdbm = SDBM.new(@path))
- end
- def teardown
- assert_nil(@sdbm.close)
- GC.start
- File.delete *Dir.glob("tmptest_sdbm*").to_a
- p Dir.glob("tmptest_sdbm*") if $DEBUG
- end
-
- def check_size(expect, sdbm=@sdbm)
- assert_equals(expect, sdbm.size)
- n = 0
- sdbm.each { n+=1 }
- assert_equals(expect, n)
- if expect == 0
- assert_equals(true, sdbm.empty?)
- else
- assert_equals(false, sdbm.empty?)
- end
- end
-
- def test_version
- assert(! SDBM.const_defined?(:VERSION))
- end
-
- def test_s_new_has_no_block
- # SDBM.new ignore the block
- foo = true
- assert_instance_of(SDBM, sdbm = SDBM.new("tmptest_sdbm") { foo = false })
- assert_equals(foo, true)
- assert_nil(sdbm.close)
- end
- def test_s_open_no_create
- assert_nil(sdbm = SDBM.open("tmptest_sdbm", nil))
- ensure
- sdbm.close if sdbm
- end
- def test_s_open_with_block
- assert_equals(SDBM.open("tmptest_sdbm") { :foo }, :foo)
- end
-=begin
- # Is it guaranteed on many OS?
- def test_s_open_lock_one_process
- # locking on one process
- assert_instance_of(SDBM, sdbm = SDBM.open("tmptest_sdbm", 0644))
- assert_exception(Errno::EWOULDBLOCK) {
- begin
- SDBM.open("tmptest_sdbm", 0644)
- rescue Errno::EAGAIN
- raise Errno::EWOULDBLOCK
- end
- }
- end
-=end
-
- def test_s_open_nolock
- # sdbm 1.8.0 specific
- if not defined? SDBM::NOLOCK
- return
- end
-
- fork() {
- assert_instance_of(SDBM, sdbm = SDBM.open("tmptest_sdbm", 0644,
- SDBM::NOLOCK))
- sleep 2
- }
- sleep 1
- begin
- sdbm2 = nil
- assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
- assert_instance_of(SDBM, sdbm2 = SDBM.open("tmptest_sdbm", 0644))
- }
- ensure
- Process.wait
- sdbm2.close if sdbm2
- end
-
- p Dir.glob("tmptest_sdbm*") if $DEBUG
-
- fork() {
- assert_instance_of(SDBM, sdbm = SDBM.open("tmptest_sdbm", 0644))
- sleep 2
- }
- begin
- sleep 1
- sdbm2 = nil
- assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
- # this test is failed on Cygwin98 (???)
- assert_instance_of(SDBM, sdbm2 = SDBM.open("tmptest_sdbm", 0644,
- SDBM::NOLOCK))
- }
- ensure
- Process.wait
- sdbm2.close if sdbm2
- end
- end
-
- def test_s_open_error
- assert_instance_of(SDBM, sdbm = SDBM.open("tmptest_sdbm", 0))
- assert_exception(Errno::EACCES) {
- SDBM.open("tmptest_sdbm", 0)
- }
- sdbm.close
- end
-
- def test_close
- assert_instance_of(SDBM, sdbm = SDBM.open("tmptest_sdbm"))
- assert_nil(sdbm.close)
-
- # closed SDBM file
- assert_exception(SDBMError) { sdbm.close }
- end
-
- def test_aref
- assert_equals('bar', @sdbm['foo'] = 'bar')
- assert_equals('bar', @sdbm['foo'])
-
- assert_nil(@sdbm['bar'])
- end
-
- def test_fetch
- assert_equals('bar', @sdbm['foo']='bar')
- assert_equals('bar', @sdbm.fetch('foo'))
-
- # key not found
- assert_exception(IndexError) {
- @sdbm.fetch('bar')
- }
-
- # test for `ifnone' arg
- assert_equals('baz', @sdbm.fetch('bar', 'baz'))
-
- # test for `ifnone' block
- assert_equals('foobar', @sdbm.fetch('bar') {|key| 'foo' + key })
- end
-
- def test_aset
- num = 0
- 2.times {|i|
- assert_equals('foo', @sdbm['foo'] = 'foo')
- assert_equals('foo', @sdbm['foo'])
- assert_equals('bar', @sdbm['foo'] = 'bar')
- assert_equals('bar', @sdbm['foo'])
-
- num += 1 if i == 0
- assert_equals(num, @sdbm.size)
-
- # assign nil
- assert_equals('', @sdbm['bar'] = '')
- assert_equals('', @sdbm['bar'])
-
- num += 1 if i == 0
- assert_equals(num, @sdbm.size)
-
- # empty string
- assert_equals('', @sdbm[''] = '')
- assert_equals('', @sdbm[''])
-
- num += 1 if i == 0
- assert_equals(num, @sdbm.size)
-
- # Fixnum
- assert_equals('200', @sdbm['100'] = '200')
- assert_equals('200', @sdbm['100'])
-
- num += 1 if i == 0
- assert_equals(num, @sdbm.size)
-
- # Big key and value
- assert_equals('y' * 100, @sdbm['x' * 100] = 'y' * 100)
- assert_equals('y' * 100, @sdbm['x' * 100])
-
- num += 1 if i == 0
- assert_equals(num, @sdbm.size)
- }
- end
-
- def test_index
- assert_equals('bar', @sdbm['foo'] = 'bar')
- assert_equals('foo', @sdbm.index('bar'))
- assert_nil(@sdbm['bar'])
- end
-
- def test_indexes
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
- assert_equals(values.reverse, @sdbm.indexes(*keys.reverse))
- end
-
- def test_values_at
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
- assert_equals(values.reverse, @sdbm.values_at(*keys.reverse))
- end
-
- def test_select_with_block
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
- ret = @sdbm.select {|k,v|
- assert_equals(k.upcase, v)
- k != "bar"
- }
- assert_equals([['baz', 'BAZ'], ['foo', 'FOO']],
- ret.sort)
- end
-
- def test_length
- num = 10
- assert_equals(0, @sdbm.size)
- num.times {|i|
- i = i.to_s
- @sdbm[i] = i
- }
- assert_equals(num, @sdbm.size)
-
- @sdbm.shift
-
- assert_equals(num - 1, @sdbm.size)
- end
-
- def test_empty?
- assert_equals(true, @sdbm.empty?)
- @sdbm['foo'] = 'FOO'
- assert_equals(false, @sdbm.empty?)
- end
-
- def test_each_pair
- n = 0
- @sdbm.each_pair { n += 1 }
- assert_equals(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- n = 0
- ret = @sdbm.each_pair {|key, val|
- assert_not_nil(i = keys.index(key))
- assert_equals(val, values[i])
-
- n += 1
- }
- assert_equals(keys.size, n)
- assert_equals(@sdbm, ret)
- end
-
- def test_each_value
- n = 0
- @sdbm.each_value { n += 1 }
- assert_equals(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- n = 0
- ret = @sdbm.each_value {|val|
- assert_not_nil(key = @sdbm.index(val))
- assert_not_nil(i = keys.index(key))
- assert_equals(val, values[i])
-
- n += 1
- }
- assert_equals(keys.size, n)
- assert_equals(@sdbm, ret)
- end
-
- def test_each_key
- n = 0
- @sdbm.each_key { n += 1 }
- assert_equals(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- n = 0
- ret = @sdbm.each_key {|key|
- assert_not_nil(i = keys.index(key))
- assert_equals(@sdbm[key], values[i])
-
- n += 1
- }
- assert_equals(keys.size, n)
- assert_equals(@sdbm, ret)
- end
-
- def test_keys
- assert_equals([], @sdbm.keys)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- assert_equals(keys.sort, @sdbm.keys.sort)
- assert_equals(values.sort, @sdbm.values.sort)
- end
-
- def test_values
- test_keys
- end
-
- def test_shift
- assert_nil(@sdbm.shift)
- assert_equals(0, @sdbm.size)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- ret_keys = []
- ret_values = []
- while ret = @sdbm.shift
- ret_keys.push ret[0]
- ret_values.push ret[1]
-
- assert_equals(keys.size - ret_keys.size, @sdbm.size)
- end
-
- assert_equals(keys.sort, ret_keys.sort)
- assert_equals(values.sort, ret_values.sort)
- end
-
- def test_delete
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- key = keys[1]
-
- assert_nil(@sdbm.delete(key))
- assert_equals(0, @sdbm.size)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- assert_equals('BAR', @sdbm.delete(key))
- assert_nil(@sdbm[key])
- assert_equals(2, @sdbm.size)
-
- assert_nil(@sdbm.delete(key))
- end
- def test_delete_with_block
- key = 'no called block'
- @sdbm[key] = 'foo'
- assert_equals('foo', @sdbm.delete(key) {|k| k.replace 'called block'})
- assert_equals('no called block', key)
- assert_equals(0, @sdbm.size)
-
- key = 'no called block'
- assert_equals(:blockval,
- @sdbm.delete(key) {|k| k.replace 'called block'; :blockval})
- assert_equals('called block', key)
- assert_equals(0, @sdbm.size)
- end
-
- def test_delete_if
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
-
- ret = @sdbm.delete_if {|key, val| key.to_i < 50}
- assert_equals(@sdbm, ret)
- check_size(50, @sdbm)
-
- ret = @sdbm.delete_if {|key, val| key.to_i >= 50}
- assert_equals(@sdbm, ret)
- check_size(0, @sdbm)
-
- # break
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
- check_size(100, @sdbm)
- n = 0;
- @sdbm.delete_if {|key, val|
- break if n > 50
- n+=1
- true
- }
- assert_equals(51, n)
- check_size(49, @sdbm)
-
- @sdbm.clear
-
- # raise
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
- check_size(100, @sdbm)
- n = 0;
- begin
- @sdbm.delete_if {|key, val|
- raise "runtime error" if n > 50
- n+=1
- true
- }
- rescue
- end
- assert_equals(51, n)
- check_size(49, @sdbm)
- end
-
- def test_reject
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
-
- hash = @sdbm.reject {|key, val| key.to_i < 50}
- assert_instance_of(Hash, hash)
- assert_equals(100, @sdbm.size)
-
- assert_equals(50, hash.size)
- hash.each_pair {|key,val|
- assert_equals(false, key.to_i < 50)
- assert_equals(key, val)
- }
-
- hash = @sdbm.reject {|key, val| key.to_i < 100}
- assert_instance_of(Hash, hash)
- assert_equals(true, hash.empty?)
- end
-
- def test_clear
- v = "1"
- 100.times {v = v.next; @sdbm[v] = v}
-
- assert_equals(@sdbm, @sdbm.clear)
-
- # validate SDBM#size
- i = 0
- @sdbm.each { i += 1 }
- assert_equals(@sdbm.size, i)
- assert_equals(0, i)
- end
-
- def test_invert
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
-
- hash = @sdbm.invert
- assert_instance_of(Hash, hash)
- assert_equals(100, hash.size)
- hash.each_pair {|key, val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_update
- hash = {}
- v = "0"
- 100.times {v = v.next; hash[v] = v}
-
- @sdbm["101"] = "101"
- @sdbm.update hash
- assert_equals(101, @sdbm.size)
- @sdbm.each_pair {|key, val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_replace
- hash = {}
- v = "0"
- 100.times {v = v.next; hash[v] = v}
-
- @sdbm["101"] = "101"
- @sdbm.replace hash
- assert_equals(100, @sdbm.size)
- @sdbm.each_pair {|key, val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_haskey?
- assert_equals('bar', @sdbm['foo']='bar')
- assert_equals(true, @sdbm.has_key?('foo'))
- assert_equals(false, @sdbm.has_key?('bar'))
- end
-
- def test_has_value?
- assert_equals('bar', @sdbm['foo']='bar')
- assert_equals(true, @sdbm.has_value?('bar'))
- assert_equals(false, @sdbm.has_value?('foo'))
- end
-
- def test_to_a
- v = "0"
- 100.times {v = v.next; @sdbm[v] = v}
-
- ary = @sdbm.to_a
- assert_instance_of(Array, ary)
- assert_equals(100, ary.size)
- ary.each {|key,val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-
- def test_to_hash
- v = "0"
- 100.times {v = v.next; @sdbm[v] = v}
-
- hash = @sdbm.to_hash
- assert_instance_of(Hash, hash)
- assert_equals(100, hash.size)
- hash.each {|key,val|
- assert_equals(key.to_i, val.to_i)
- }
- end
-end
-
-if $0 == __FILE__
- if ARGV.size == 0
- suite = RUNIT::TestSuite.new
- suite.add_test(TestSDBM.suite)
- else
- suite = RUNIT::TestSuite.new
- ARGV.each do |testmethod|
- suite.add_test(TestSDBM.new(testmethod))
- end
- end
-
- RUNIT::CUI::TestRunner.run(suite)
-end
diff --git a/ext/socket/MANIFEST b/ext/socket/MANIFEST
deleted file mode 100644
index 616d459d92..0000000000
--- a/ext/socket/MANIFEST
+++ /dev/null
@@ -1,8 +0,0 @@
-MANIFEST
-addrinfo.h
-depend
-extconf.rb
-getaddrinfo.c
-getnameinfo.c
-sockport.h
-socket.c
diff --git a/ext/socket/addrinfo.h b/ext/socket/addrinfo.h
index a22615ee00..e93adafba6 100644
--- a/ext/socket/addrinfo.h
+++ b/ext/socket/addrinfo.h
@@ -61,10 +61,15 @@
#undef NI_NUMERICSERV
#undef NI_DGRAM
+#undef addrinfo
#define addrinfo addrinfo__compat
+#undef getaddrinfo
#define getaddrinfo getaddrinfo__compat
+#undef getnameinfo
#define getnameinfo getnameinfo__compat
+#undef freehostent
#define freehostent freehostent__compat
+#undef freeaddrinfo
#define freeaddrinfo freeaddrinfo__compat
#ifndef __P
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index 4f7b49407f..8a13ddba73 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -4,11 +4,13 @@ case RUBY_PLATFORM
when /bccwin32/
test_func = "WSACleanup"
have_library("ws2_32", "WSACleanup")
- have_func("closesocket")
when /mswin32|mingw/
test_func = "WSACleanup"
- have_library("wsock32", "WSACleanup")
- have_func("closesocket")
+ if with_config("winsock2")
+ have_library("ws2_32", "WSACleanup")
+ else
+ have_library("wsock32", "WSACleanup")
+ end
when /cygwin/
test_func = "socket"
when /beos/
@@ -24,10 +26,21 @@ else
have_library("socket", "socket")
end
-$ipv6 = false
+unless $mswin or $bccwin or $mingw
+ headers = %w<sys/types.h netdb.h string.h sys/socket.h netinet/in.h>
+end
+if /solaris/ =~ RUBY_PLATFORM and !try_compile("")
+ # bug of gcc 3.0 on Solaris 8 ?
+ headers << "sys/feature_tests.h"
+end
+if have_header("arpa/inet.h")
+ headers << "arpa/inet.h"
+end
+
+ipv6 = false
default_ipv6 = /cygwin/ !~ RUBY_PLATFORM
if enable_config("ipv6", default_ipv6)
- if try_link(<<EOF)
+ if checking_for("ipv6") {try_link(<<EOF)}
#include <sys/types.h>
#include <sys/socket.h>
main()
@@ -35,160 +48,67 @@ main()
socket(AF_INET6, SOCK_STREAM, 0);
}
EOF
- $CFLAGS+=" -DENABLE_IPV6"
- $ipv6 = true
+ $defs << "-DENABLE_IPV6" << "-DINET6"
+ ipv6 = true
end
end
-$ipv6type = nil
-$ipv6lib = nil
-$ipv6libdir = nil
-$ipv6trylibc = nil
-if $ipv6
- if macro_defined?("IPV6_INRIA_VERSION", <<EOF)
-#include <netinet/in.h>
-EOF
- $ipv6type = "inria"
- $CFLAGS="-DINET6 "+$CFLAGS
- elsif macro_defined?("__KAME__", <<EOF)
-#include <netinet/in.h>
-EOF
- $ipv6type = "kame"
- $ipv6lib="inet6"
- $ipv6libdir="/usr/local/v6/lib"
- $ipv6trylibc=true
- $CFLAGS="-DINET6 "+$CFLAGS
- elsif File.directory? "/usr/inet6"
- $ipv6type = "linux"
- $ipv6lib="inet6"
- $ipv6libdir="/usr/inet6/lib"
- $CFLAGS="-DINET6 -I/usr/inet6/include "+$CFLAGS
- elsif macro_defined?("_TOSHIBA_INET6", <<EOF)
-#include <sys/param.h>
-EOF
- $ipv6type = "toshiba"
- $ipv6lib="inet6"
- $ipv6libdir="/usr/local/v6/lib"
- $CFLAGS="-DINET6 "+$CFLAGS
- elsif macro_defined?("__V6D__", <<EOF)
-#include </usr/local/v6/include/sys/v6config.h>
-EOF
- $ipv6type = "v6d"
- $ipv6lib="v6"
- $ipv6libdir="/usr/local/v6/lib"
- $CFLAGS="-DINET6 -I/usr/local/v6/include "+$CFLAGS
- elsif macro_defined?("_ZETA_MINAMI_INET6", <<EOF)
-#include <sys/param.h>
-EOF
- $ipv6type = "zeta"
- $ipv6lib="inet6"
- $ipv6libdir="/usr/local/v6/lib"
- $CFLAGS="-DINET6 "+$CFLAGS
- else
- $ipv6lib=with_config("ipv6-lib", nil)
- $ipv6libdir=with_config("ipv6-libdir", nil)
- $CFLAGS="-DINET6 "+$CFLAGS
+if ipv6
+ ipv6lib = nil
+ class << (fmt = "unknown")
+ def %(s) s || self end
end
-
- if $ipv6lib
- if File.directory? $ipv6libdir and File.exist? "#{$ipv6libdir}/lib#{$ipv6lib}.a"
- $LOCAL_LIBS = " -L#$ipv6libdir -l#$ipv6lib"
- elsif !$ipv6trylibc
- print <<EOS
+ idirs, ldirs = dir_config("inet6", %w[/usr/inet6 /usr/local/v6].find {|d| File.directory?(d)})
+ checking_for("ipv6 type", fmt) do
+ if have_macro("IPV6_INRIA_VERSION", "netinet/in.h")
+ "inria"
+ elsif have_macro("__KAME__", "netinet/in.h")
+ have_library(ipv6lib = "inet6")
+ "kame"
+ elsif have_macro("_TOSHIBA_INET6", "sys/param.h")
+ have_library(ipv6lib = "inet6") and "toshiba"
+ elsif have_macro("__V6D__", "sys/v6config.h")
+ have_library(ipv6lib = "v6") and "v6d"
+ elsif have_macro("_ZETA_MINAMI_INET6", "sys/param.h")
+ have_library(ipv6lib = "inet6") and "zeta"
+ elsif ipv6lib = with_config("ipv6-lib")
+ warn <<EOS
+--with-ipv6-lib and --with-ipv6-libdir option will be obsolete, use
+--with-inet6lib and --with-inet6-{include,lib} options instead.
+EOS
+ find_library(ipv6lib, nil, with_config("ipv6-libdir", ldirs)) and
+ ipv6lib
+ elsif have_library("inet6")
+ "inet6"
+ end
+ end or not ipv6lib or abort <<EOS
-Fatal: no #$ipv6lib library found. cannot continue.
-You need to fetch lib#{$ipv6lib}.a from appropriate
+Fatal: no #{ipv6lib} library found. cannot continue.
+You need to fetch lib#{ipv6lib}.a from appropriate
ipv6 kit and compile beforehand.
EOS
- exit
- end
- end
end
- if try_link(<<EOF)
-#ifdef _WIN32
-# include <windows.h>
-# include <winsock.h>
-#else
-# include <sys/types.h>
-# include <netdb.h>
-# include <string.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-#endif
-int
-main()
-{
- struct sockaddr_in sin;
-
- sin.sin_len;
- return 0;
-}
-EOF
- $CFLAGS="-DHAVE_SIN_LEN "+$CFLAGS
+if have_struct_member("struct sockaddr_in", "sin_len", headers)
+ $defs[-1] = "-DHAVE_SIN_LEN"
end
- if try_link(<<EOF)
-#ifdef _WIN32
-# include <windows.h>
-# include <winsock.h>
-#else
-# include <sys/types.h>
-# include <netdb.h>
-# include <string.h>
-# include <sys/socket.h>
-#endif
-int
-main()
-{
- struct sockaddr_storage ss;
-
- ss.ss_family;
- return 0;
-}
-EOF
- $CFLAGS="-DHAVE_SOCKADDR_STORAGE "+$CFLAGS
-else # doug's fix, NOW add -Dss_family... only if required!
-$CPPFLAGS += " -Dss_family=__ss_family -Dss_len=__ss_len"
- if try_link(<<EOF)
-#ifdef _WIN32
-# include <windows.h>
-# include <winsock.h>
-#else
-# include <sys/types.h>
-# include <netdb.h>
-# include <string.h>
-# include <sys/socket.h>
-#endif
-int
-main()
-{
- struct sockaddr_storage ss;
-
- ss.ss_family;
- return 0;
-}
-EOF
- $CFLAGS="-DHAVE_SOCKADDR_STORAGE "+$CFLAGS
-end
+# doug's fix, NOW add -Dss_family... only if required!
+[nil, " -Dss_family=__ss_family -Dss_len=__ss_len"].each do |flags|
+ if flags
+ cppflags = $CPPFLAGS
+ $CPPFLAGS += flags
+ end
+ if have_struct_member("struct sockaddr_storage", "ss_family", headers)
+ $defs[-1] = "-DHAVE_SOCKADDR_STORAGE"
+ break
+ elsif flags
+ $CPPFLAGS = cppflags
+ end
end
- if try_link(<<EOF)
-#include <sys/types.h>
-#include <netdb.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-int
-main()
-{
- struct sockaddr sa;
-
- sa.sa_len;
- return 0;
-}
-EOF
- $CFLAGS="-DHAVE_SA_LEN "+$CFLAGS
+if have_struct_member("struct sockaddr", "sa_len", headers)
+ $defs[-1] = "-DHAVE_SA_LEN "
end
have_header("netinet/tcp.h") if not /cygwin/ =~ RUBY_PLATFORM # for cygwin 1.1.5
@@ -199,13 +119,17 @@ if have_func("sendmsg") | have_func("recvmsg")
have_struct_member('struct msghdr', 'msg_accrights', ['sys/types.h', 'sys/socket.h'])
end
-$getaddr_info_ok = false
-if !enable_config("wide-getaddrinfo", false) and try_run(<<EOF)
-#include <sys/types.h>
-#include <netdb.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
+getaddr_info_ok = enable_config("wide-getaddrinfo") do
+ checking_for("wide getaddrinfo") {try_run(<<EOF)}
+#{cpp_include(headers)}
+#include <stdlib.h>
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
@@ -229,8 +153,17 @@ main()
}
for (ai = aitop; ai; ai = ai->ai_next) {
if (ai->ai_family == AF_LOCAL) continue;
- if (ai->ai_addr == NULL ||
- ai->ai_addrlen == 0 ||
+ if (ai->ai_addr == NULL)
+ goto bad;
+#if defined(_AIX)
+ if (ai->ai_family == AF_INET6 && passive) {
+ inet6++;
+ continue;
+ }
+ ai->ai_addr->sa_len = ai->ai_addrlen;
+ ai->ai_addr->sa_family = ai->ai_family;
+#endif
+ if (ai->ai_addrlen == 0 ||
getnameinfo(ai->ai_addr, ai->ai_addrlen,
straddr, sizeof(straddr), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
@@ -281,103 +214,57 @@ main()
if (aitop)
freeaddrinfo(aitop);
- exit(0);
+ exit(EXIT_SUCCESS);
bad:
if (aitop)
freeaddrinfo(aitop);
- exit(1);
+ exit(EXIT_FAILURE);
}
EOF
- $getaddr_info_ok = true
end
-if $ipv6 and not $getaddr_info_ok
- print <<EOS
+if ipv6 and not getaddr_info_ok
+ abort <<EOS
Fatal: --enable-ipv6 is specified, and your OS seems to support IPv6 feature.
But your getaddrinfo() and getnameinfo() are appeared to be broken. Sorry,
you cannot compile IPv6 socket classes with broken these functions.
You can try --enable-wide-getaddrinfo.
EOS
- exit
end
-
+
case with_config("lookup-order-hack", "UNSPEC")
when "INET"
- $CFLAGS="-DLOOKUP_ORDER_HACK_INET "+$CFLAGS
+ $defs << "-DLOOKUP_ORDER_HACK_INET"
when "INET6"
- $CFLAGS="-DLOOKUP_ORDER_HACK_INET6 "+$CFLAGS
+ $defs << "-DLOOKUP_ORDER_HACK_INET6"
when "UNSPEC"
# nothing special
else
- print <<EOS
+ abort <<EOS
Fatal: invalid value for --with-lookup-order-hack (expected INET, INET6 or UNSPEC)
EOS
- exit
end
$objs = ["socket.#{$OBJEXT}"]
-
-if $getaddr_info_ok and have_func("getaddrinfo", "netdb.h") and have_func("getnameinfo", "netdb.h")
- have_getaddrinfo = true
-else
- if try_link(<<EOF)
-#ifndef _WIN32
-# include <sys/types.h>
-# include <netdb.h>
-# include <string.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-#else
-# include <windows.h>
-# ifdef _WIN32_WCE
-# include <winsock.h>
-# else
-# include <winsock.h>
-# endif
-#endif
-int
-main()
-{
- struct in6_addr addr;
- unsigned char c;
- c = addr.s6_addr8;
- return 0;
-}
-EOF
- $CFLAGS="-DHAVE_ADDR8 "+$CFLAGS
- end
-end
-if have_getaddrinfo
- $CFLAGS="-DHAVE_GETADDRINFO "+$CFLAGS
-else
- $CFLAGS="-I. "+$CFLAGS
+unless getaddr_info_ok and have_func("getnameinfo", "netdb.h") and have_func("getaddrinfo", "netdb.h")
+ if have_struct_member("struct in6_addr", "s6_addr8", headers)
+ $defs[-1] = "-DHAVE_ADDR8"
+ end
+ $CPPFLAGS="-I. "+$CPPFLAGS
$objs += ["getaddrinfo.#{$OBJEXT}"]
$objs += ["getnameinfo.#{$OBJEXT}"]
have_func("inet_ntop") or have_func("inet_ntoa")
have_func("inet_pton") or have_func("inet_aton")
have_func("getservbyport")
- have_header("arpa/inet.h")
have_header("arpa/nameser.h")
have_header("resolv.h")
end
-if !try_link(<<EOF)
-#include <sys/types.h>
-#include <netdb.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-int
-main()
-{
- socklen_t len;
- return 0;
-}
-EOF
- $CFLAGS="-Dsocklen_t=int "+$CFLAGS
+unless have_type("socklen_t", headers)
+ $defs << "-Dsocklen_t=int"
end
have_header("sys/un.h")
@@ -386,14 +273,15 @@ have_header("sys/uio.h")
if have_func(test_func)
have_func("hsterror")
have_func("getipnodebyname") or have_func("gethostbyname2")
+ have_func("socketpair")
unless have_func("gethostname")
have_func("uname")
end
if enable_config("socks", ENV["SOCKS_SERVER"])
if have_library("socks5", "SOCKSinit")
- $CFLAGS+=" -DSOCKS5 -DSOCKS"
+ $defs << "-DSOCKS5" << "-DSOCKS"
elsif have_library("socks", "Rconnect")
- $CFLAGS+=" -DSOCKS"
+ $defs << "-DSOCKS"
end
end
create_makefile("socket")
diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c
index c05fbd57ba..9fb4ebcb06 100644
--- a/ext/socket/getaddrinfo.c
+++ b/ext/socket/getaddrinfo.c
@@ -40,7 +40,7 @@
#include "config.h"
#include <sys/types.h>
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__VMS)
#include <sys/param.h>
#if defined(__BEOS__)
# include <net/socket.h>
@@ -56,9 +56,17 @@
#endif
#include <netdb.h>
#if defined(HAVE_RESOLV_H)
+#ifdef _SX
+#include <stdio.h>
+#endif
#include <resolv.h>
#endif
#include <unistd.h>
+#elif defined(__VMS )
+#include <socket.h>
+#include <inet.h>
+#include <in.h>
+#include <netdb.h>
#else
#include <winsock2.h>
#include <io.h>
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
index a75f233a81..66f7e8818a 100644
--- a/ext/socket/getnameinfo.c
+++ b/ext/socket/getnameinfo.c
@@ -35,6 +35,7 @@
*/
#include "config.h"
+#include <stdio.h>
#include <sys/types.h>
#ifndef _WIN32
#if defined(__BEOS__)
@@ -56,7 +57,6 @@
#endif
#ifdef _WIN32
#include <winsock2.h>
-#include <stdio.h>
#define snprintf _snprintf
#endif
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 5cebe593bc..491823ad44 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -30,6 +30,7 @@
# include <net/socket.h>
#else
# include <sys/socket.h>
+# define pseudo_AF_FTIP pseudo_AF_RTIP /* workaround for NetBSD and etc. */
#endif
#include <netinet/in.h>
#ifdef HAVE_NETINET_IN_SYSTM_H
@@ -41,6 +42,9 @@
#ifdef HAVE_NETINET_UDP_H
# include <netinet/udp.h>
#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
#include <netdb.h>
#endif
#include <errno.h>
@@ -52,10 +56,16 @@
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
+#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
+#endif
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
@@ -64,6 +74,10 @@
#endif
#include "sockport.h"
+#if defined(__vms)
+#include <tcp.h>
+#endif
+
static int do_not_reverse_lookup = 0;
VALUE rb_cBasicSocket;
@@ -162,6 +176,64 @@ ruby_getaddrinfo(nodename, servname, hints, res)
#define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo((node),(serv),(hints),(res))
#endif
+#if defined(_AIX)
+static int
+ruby_getaddrinfo__aix(nodename, servname, hints, res)
+ char *nodename;
+ char *servname;
+ struct addrinfo *hints;
+ struct addrinfo **res;
+{
+ int error = getaddrinfo(nodename, servname, hints, res);
+ struct addrinfo *r;
+ if (error)
+ return error;
+ for (r = *res; r != NULL; r = r->ai_next) {
+ if (r->ai_addr->sa_family == 0)
+ r->ai_addr->sa_family = r->ai_family;
+ if (r->ai_addr->sa_len == 0)
+ r->ai_addr->sa_len = r->ai_addrlen;
+ }
+ return 0;
+}
+#undef getaddrinfo
+#define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
+static int
+ruby_getnameinfo__aix(sa, salen, host, hostlen, serv, servlen, flags)
+ const struct sockaddr *sa;
+ size_t salen;
+ char *host;
+ size_t hostlen;
+ char *serv;
+ size_t servlen;
+ int flags;
+{
+ struct sockaddr_in6 *sa6;
+ u_int32_t *a6;
+
+ if (sa->sa_family == AF_INET6) {
+ sa6 = (struct sockaddr_in6 *)sa;
+ a6 = sa6->sin6_addr.u6_addr.u6_addr32;
+
+ if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
+ strncpy(host, "::", hostlen);
+ snprintf(serv, servlen, "%d", sa6->sin6_port);
+ return 0;
+ }
+ }
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+#undef getnameinfo
+#define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
+ ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
+#ifndef CMSG_SPACE
+# define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
+#endif
+#ifndef CMSG_LEN
+# define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
+#endif
+#endif
+
#ifdef HAVE_CLOSESOCKET
#undef close
#define close closesocket
@@ -172,7 +244,7 @@ init_sock(sock, fd)
VALUE sock;
int fd;
{
- OpenFile *fp;
+ rb_io_t *fp;
MakeOpenFile(sock, fp);
fp->f = rb_fdopen(fd, "r");
@@ -187,7 +259,7 @@ static VALUE
bsock_s_for_fd(klass, fd)
VALUE klass, fd;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock = init_sock(rb_obj_alloc(klass), NUM2INT(fd));
GetOpenFile(sock, fptr);
@@ -203,7 +275,7 @@ bsock_shutdown(argc, argv, sock)
{
VALUE howto;
int how;
- OpenFile *fptr;
+ rb_io_t *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
@@ -228,7 +300,7 @@ static VALUE
bsock_close_read(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
@@ -247,7 +319,7 @@ static VALUE
bsock_close_write(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
@@ -262,12 +334,57 @@ bsock_close_write(sock)
return Qnil;
}
+/*
+ * Document-method: setsockopt
+ * call-seq: setsockopt(level, optname, optval)
+ *
+ * Sets a socket option. These are protocol and system specific, see your
+ * local sytem documentation for details.
+ *
+ * === Parameters
+ * * +level+ is an integer, usually one of the SOL_ constants such as
+ * Socket::SOL_SOCKET, or a protocol level.
+ * * +optname+ is an integer, usually one of the SO_ constants, such
+ * as Socket::SO_REUSEADDR.
+ * * +optval+ is the value of the option, it is passed to the underlying
+ * setsockopt() as a pointer to a certain number of bytes. How this is
+ * done depends on the type:
+ * - Fixnum: value is assigned to an int, and a pointer to the int is
+ * passed, with length of sizeof(int).
+ * - true or false: 1 or 0 (respectively) is assigned to an int, and the
+ * int is passed as for a Fixnum. Note that +false+ must be passed,
+ * not +nil+.
+ * - String: the string's data and length is passed to the socket.
+ *
+ * === Examples
+ *
+ * Some socket options are integers with boolean values, in this case
+ * #setsockopt could be called like this:
+ * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
+ *
+ * Some socket options are integers with numeric values, in this case
+ * #setsockopt could be called like this:
+ * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
+ *
+ * Option values may be structs. Passing them can be complex as it involves
+ * examining your system headers to determine the correct definition. An
+ * example is an +ip_mreq+, which may be defined in your system headers as:
+ * struct ip_mreq {
+ * struct in_addr imr_multiaddr;
+ * struct in_addr imr_interface;
+ * };
+ *
+ * In this case #setsockopt could be called like this:
+ * optval = IPAddr.new("224.0.0.251") + Socket::INADDR_ANY
+ * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
+ *
+*/
static VALUE
bsock_setsockopt(sock, lev, optname, val)
VALUE sock, lev, optname, val;
{
int level, option;
- OpenFile *fptr;
+ rb_io_t *fptr;
int i;
char *v;
int vlen;
@@ -275,6 +392,7 @@ bsock_setsockopt(sock, lev, optname, val)
rb_secure(2);
level = NUM2INT(lev);
option = NUM2INT(optname);
+
switch (TYPE(val)) {
case T_FIXNUM:
i = FIX2INT(val);
@@ -301,6 +419,46 @@ bsock_setsockopt(sock, lev, optname, val)
return INT2FIX(0);
}
+/*
+ * Document-method: getsockopt
+ * call-seq: getsockopt(level, optname)
+ *
+ * Gets a socket option. These are protocol and system specific, see your
+ * local sytem documentation for details. The option is returned as
+ * a String with the data being the binary value of the socket option.
+ *
+ * === Parameters
+ * * +level+ is an integer, usually one of the SOL_ constants such as
+ * Socket::SOL_SOCKET, or a protocol level.
+ * * +optname+ is an integer, usually one of the SO_ constants, such
+ * as Socket::SO_REUSEADDR.
+ *
+ * === Examples
+ *
+ * Some socket options are integers with boolean values, in this case
+ * #getsockopt could be called like this:
+ * optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
+ * optval = optval.unpack "i"
+ * reuseaddr = optval[0] == 0 ? false : true
+ *
+ * Some socket options are integers with numeric values, in this case
+ * #getsockopt could be called like this:
+ * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
+ * ipttl = optval.unpack("i")[0]
+ *
+ * Option values may be structs. Decoding them can be complex as it involves
+ * examining your system headers to determine the correct definition. An
+ * example is a +struct linger+, which may be defined in your system headers
+ * as:
+ * struct linger {
+ * int l_onoff;
+ * int l_linger;
+ * };
+ *
+ * In this case #getsockopt could be called like this:
+ * optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
+ * onoff, linger = optval.unpack "ii"
+*/
static VALUE
bsock_getsockopt(sock, lev, optname)
VALUE sock, lev, optname;
@@ -309,12 +467,13 @@ bsock_getsockopt(sock, lev, optname)
int level, option;
socklen_t len;
char *buf;
- OpenFile *fptr;
+ rb_io_t *fptr;
level = NUM2INT(lev);
option = NUM2INT(optname);
len = 256;
buf = ALLOCA_N(char,len);
+ GetOpenFile(sock, fptr);
GetOpenFile(sock, fptr);
if (getsockopt(fileno(fptr->f), level, option, buf, &len) < 0)
@@ -332,7 +491,7 @@ bsock_getsockname(sock)
{
char buf[1024];
socklen_t len = sizeof buf;
- OpenFile *fptr;
+ rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
@@ -346,7 +505,7 @@ bsock_getpeername(sock)
{
char buf[1024];
socklen_t len = sizeof buf;
- OpenFile *fptr;
+ rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
@@ -362,26 +521,30 @@ bsock_send(argc, argv, sock)
{
VALUE mesg, to;
VALUE flags;
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *f;
int fd, n;
rb_secure(4);
rb_scan_args(argc, argv, "21", &mesg, &flags, &to);
+ StringValue(mesg);
+ if (!NIL_P(to)) StringValue(to);
GetOpenFile(sock, fptr);
f = GetWriteFile(fptr);
fd = fileno(f);
rb_thread_fd_writable(fd);
- StringValue(mesg);
retry:
if (!NIL_P(to)) {
- StringValue(to);
+ TRAP_BEG;
n = sendto(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
(struct sockaddr*)RSTRING(to)->ptr, RSTRING(to)->len);
+ TRAP_END;
}
else {
+ TRAP_BEG;
n = send(fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags));
+ TRAP_END;
}
if (n < 0) {
if (rb_io_wait_writable(fd)) {
@@ -394,7 +557,7 @@ bsock_send(argc, argv, sock)
static VALUE ipaddr _((struct sockaddr*));
#ifdef HAVE_SYS_UN_H
-static VALUE unixaddr _((struct sockaddr_un*));
+static VALUE unixaddr _((struct sockaddr_un*, socklen_t));
#endif
enum sock_recv_type {
@@ -411,11 +574,12 @@ s_recvfrom(sock, argc, argv, from)
VALUE *argv;
enum sock_recv_type from;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE str;
char buf[1024];
socklen_t alen = sizeof buf;
VALUE len, flg;
+ long buflen;
long slen;
int fd, flags;
@@ -423,6 +587,7 @@ s_recvfrom(sock, argc, argv, from)
if (flg == Qnil) flags = 0;
else flags = NUM2INT(flg);
+ buflen = NUM2INT(len);
GetOpenFile(sock, fptr);
if (rb_read_pending(fptr->f)) {
@@ -430,14 +595,15 @@ s_recvfrom(sock, argc, argv, from)
}
fd = fileno(fptr->f);
- slen = NUM2INT(len);
- str = rb_tainted_str_new(0, slen);
+ str = rb_tainted_str_new(0, buflen);
retry:
+ rb_str_locktmp(str);
rb_thread_wait_fd(fd);
TRAP_BEG;
- slen = recvfrom(fd, RSTRING(str)->ptr, slen, flags, (struct sockaddr*)buf, &alen);
+ slen = recvfrom(fd, RSTRING(str)->ptr, buflen, flags, (struct sockaddr*)buf, &alen);
TRAP_END;
+ rb_str_unlocktmp(str);
if (slen < 0) {
if (rb_io_wait_readable(fd)) {
@@ -459,10 +625,14 @@ s_recvfrom(sock, argc, argv, from)
rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
}
#endif
- return rb_assoc_new(str, ipaddr((struct sockaddr*)buf));
+ if (alen && alen != sizeof(buf)) /* OSX doesn't return a 'from' result from recvfrom for connection-oriented sockets */
+ return rb_assoc_new(str, ipaddr((struct sockaddr*)buf));
+ else
+ return rb_assoc_new(str, Qnil);
+
#ifdef HAVE_SYS_UN_H
case RECV_UNIX:
- return rb_assoc_new(str, unixaddr((struct sockaddr_un*)buf));
+ return rb_assoc_new(str, unixaddr((struct sockaddr_un*)buf, alen));
#endif
case RECV_SOCKET:
return rb_assoc_new(str, rb_str_new(buf, alen));
@@ -472,6 +642,70 @@ s_recvfrom(sock, argc, argv, from)
}
static VALUE
+s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
+{
+ rb_io_t *fptr;
+ VALUE str;
+ char buf[1024];
+ socklen_t alen = sizeof buf;
+ VALUE len, flg;
+ long buflen;
+ long slen;
+ int fd, flags;
+ VALUE addr = Qnil;
+
+ rb_scan_args(argc, argv, "11", &len, &flg);
+
+ if (flg == Qnil) flags = 0;
+ else flags = NUM2INT(flg);
+ buflen = NUM2INT(len);
+
+#ifdef MSG_DONTWAIT
+ /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom.
+ It is not portable, though. */
+ flags |= MSG_DONTWAIT;
+#endif
+
+ GetOpenFile(sock, fptr);
+ if (rb_read_pending(fptr->f)) {
+ rb_raise(rb_eIOError, "recvfrom for buffered IO");
+ }
+ fd = fileno(fptr->f);
+
+ str = rb_tainted_str_new(0, buflen);
+
+ rb_io_check_closed(fptr);
+ rb_io_set_nonblock(fptr);
+ slen = recvfrom(fd, RSTRING(str)->ptr, buflen, flags, (struct sockaddr*)buf, &alen);
+
+ if (slen < 0) {
+ rb_sys_fail("recvfrom(2)");
+ }
+ if (slen < RSTRING(str)->len) {
+ RSTRING(str)->len = slen;
+ RSTRING(str)->ptr[slen] = '\0';
+ }
+ rb_obj_taint(str);
+ switch (from) {
+ case RECV_RECV:
+ return str;
+
+ case RECV_IP:
+ if (alen && alen != sizeof(buf)) /* connection-oriented socket may not return a from result */
+ addr = ipaddr((struct sockaddr*)buf);
+ break;
+
+ case RECV_SOCKET:
+ addr = rb_str_new(buf, alen);
+ break;
+
+ default:
+ rb_bug("s_recvfrom_nonblock called with bad value");
+ }
+ return rb_assoc_new(str, addr);
+}
+
+static VALUE
bsock_recv(argc, argv, sock)
int argc;
VALUE *argv;
@@ -480,6 +714,52 @@ bsock_recv(argc, argv, sock)
return s_recvfrom(sock, argc, argv, RECV_RECV);
}
+/*
+ * call-seq:
+ * basicsocket.recv_nonblock(maxlen) => mesg
+ * basicsocket.recv_nonblock(maxlen, flags) => mesg
+ *
+ * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
+ * O_NONBLOCK is set for the underlying file descriptor.
+ * _flags_ is zero or more of the +MSG_+ options.
+ * The result, _mesg_, is the data received.
+ *
+ * When recvfrom(2) returns 0, Socket#recv_nonblock returns
+ * an empty string as data.
+ * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
+ *
+ * === Parameters
+ * * +maxlen+ - the number of bytes to receive from the socket
+ * * +flags+ - zero or more of the +MSG_+ options
+ *
+ * === Example
+ * serv = TCPServer.new("127.0.0.1", 0)
+ * af, port, host, addr = serv.addr
+ * c = TCPSocket.new(addr, port)
+ * s = serv.accept
+ * c.send "aaa", 0
+ * IO.select([s])
+ * p s.recv_nonblock(10) #=> "aaa"
+ *
+ * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
+ * to _recv_nonblock_ fails.
+ *
+ * BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure,
+ * including Errno::EAGAIN.
+ *
+ * === See
+ * * Socket#recvfrom
+ */
+
+static VALUE
+bsock_recv_nonblock(argc, argv, sock)
+ int argc;
+ VALUE *argv;
+ VALUE sock;
+{
+ return s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
+}
+
static VALUE
bsock_do_not_rev_lookup()
{
@@ -560,7 +840,7 @@ host_str(host, hbuf, len)
return NULL;
}
else if (rb_obj_is_kind_of(host, rb_cInteger)) {
- long i = NUM2LONG(host);
+ unsigned long i = NUM2ULONG(host);
make_inetaddr(htonl(i), hbuf, len);
return hbuf;
@@ -596,7 +876,7 @@ port_str(port, pbuf, len)
return 0;
}
else if (FIXNUM_P(port)) {
- snprintf(pbuf, len, "%d", FIX2INT(port));
+ snprintf(pbuf, len, "%ld", FIX2LONG(port));
return pbuf;
}
else {
@@ -613,10 +893,10 @@ port_str(port, pbuf, len)
}
#ifndef NI_MAXHOST
-# define 1025
+# define NI_MAXHOST 1025
#endif
#ifndef NI_MAXSERV
-# define 32
+# define NI_MAXSERV 32
#endif
static struct addrinfo*
@@ -624,7 +904,8 @@ sock_addrinfo(host, port, socktype, flags)
VALUE host, port;
int socktype, flags;
{
- struct addrinfo hints, *hintsp, *res;
+ struct addrinfo hints;
+ struct addrinfo* res = NULL;
char *hostp, *portp;
int error;
char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
@@ -636,13 +917,11 @@ sock_addrinfo(host, port, socktype, flags)
socktype = SOCK_DGRAM;
}
- hintsp = &hints;
MEMZERO(&hints, struct addrinfo, 1);
- hints.ai_family = PF_UNSPEC;
- hints.ai_protocol = 0;
+ hints.ai_family = AF_UNSPEC;
hints.ai_socktype = socktype;
hints.ai_flags = flags;
- error = getaddrinfo(hostp, portp, hintsp, &res);
+ error = getaddrinfo(hostp, portp, &hints, &res);
if (error) {
if (hostp && hostp[strlen(hostp)-1] == '\n') {
rb_raise(rb_eSocket, "newline at the end of hostname");
@@ -650,6 +929,23 @@ sock_addrinfo(host, port, socktype, flags)
rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
}
+#if defined(__APPLE__) && defined(__MACH__)
+ {
+ struct addrinfo *r;
+ r = res;
+ while (r) {
+ if (! r->ai_socktype) r->ai_socktype = hints.ai_socktype;
+ if (! r->ai_protocol) {
+ if (r->ai_socktype == SOCK_DGRAM) {
+ r->ai_protocol = IPPROTO_UDP;
+ } else if (r->ai_socktype == SOCK_STREAM) {
+ r->ai_protocol = IPPROTO_TCP;
+ }
+ }
+ r = r->ai_next;
+ }
+ }
+#endif
return res;
}
@@ -688,13 +984,13 @@ ipaddr(sockaddr)
family = rb_str_new2(pbuf);
break;
}
+ addr1 = Qnil;
if (!do_not_reverse_lookup) {
error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
NULL, 0, 0);
- if (error) {
- rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
+ if (! error) {
+ addr1 = rb_str_new2(hbuf);
}
- addr1 = rb_str_new2(hbuf);
}
error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
@@ -702,7 +998,7 @@ ipaddr(sockaddr)
rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
}
addr2 = rb_str_new2(hbuf);
- if (do_not_reverse_lookup) {
+ if (addr1 == Qnil) {
addr1 = addr2;
}
port = INT2FIX(atoi(pbuf));
@@ -727,15 +1023,40 @@ ruby_socket(domain, type, proto)
return fd;
}
-static void
-thread_write_select(fd)
+static int
+wait_connectable(fd)
int fd;
{
- fd_set fds;
+ int sockerr;
+ socklen_t sockerrlen;
+ fd_set fds_w;
+ fd_set fds_e;
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- rb_thread_select(fd+1, 0, &fds, 0, 0);
+ for (;;) {
+ FD_ZERO(&fds_w);
+ FD_ZERO(&fds_e);
+
+ FD_SET(fd, &fds_w);
+ FD_SET(fd, &fds_e);
+
+ rb_thread_select(fd+1, 0, &fds_w, &fds_e, 0);
+
+ if (FD_ISSET(fd, &fds_w)) {
+ return 0;
+ }
+ else if (FD_ISSET(fd, &fds_e)) {
+ sockerrlen = sizeof(sockerr);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr,
+ &sockerrlen) == 0) {
+ if (sockerr == 0)
+ continue; /* workaround for winsock */
+ errno = sockerr;
+ }
+ return -1;
+ }
+ }
+
+ return 0;
}
#ifdef __CYGWIN__
@@ -764,11 +1085,16 @@ ruby_connect(fd, sockaddr, len, socks)
int mode;
#if WAIT_IN_PROGRESS > 0
int wait_in_progress = -1;
- int sockerr, sockerrlen;
+ int sockerr;
+ socklen_t sockerrlen;
#endif
#if defined(HAVE_FCNTL)
+# if defined(F_GETFL)
mode = fcntl(fd, F_GETFL, 0);
+# else
+ mode = 0;
+# endif
#ifdef O_NDELAY
# define NONBLOCKING O_NDELAY
@@ -817,7 +1143,11 @@ ruby_connect(fd, sockaddr, len, socks)
#if WAIT_IN_PROGRESS > 0
wait_in_progress = WAIT_IN_PROGRESS;
#endif
- thread_write_select(fd);
+ status = wait_connectable(fd);
+ if (status) {
+ break;
+ }
+ errno = 0;
continue;
#if WAIT_IN_PROGRESS > 0
@@ -893,7 +1223,7 @@ init_inetsock_internal(arg)
{
int type = arg->type;
struct addrinfo *res;
- int fd, status;
+ int fd, status = 0;
char *syscall;
arg->remote.res = sock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM,
@@ -916,7 +1246,7 @@ init_inetsock_internal(arg)
}
arg->fd = fd;
if (type == INET_SERVER) {
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__CYGWIN__)
status = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char*)&status, sizeof(status));
@@ -976,6 +1306,14 @@ init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type)
inetsock_cleanup, (VALUE)&arg);
}
+/*
+ * call-seq:
+ * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil)
+ *
+ * Opens a TCP connection to +remote_host+ on +remote_port+. If +local_host+
+ * and +local_port+ are specified, then those parameters are used on the local
+ * end to establish the connection.
+ */
static VALUE
tcp_init(argc, argv, sock)
int argc;
@@ -1012,7 +1350,7 @@ static VALUE
socks_s_close(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
@@ -1025,39 +1363,43 @@ socks_s_close(sock)
#endif
#endif
+struct hostent_arg {
+ VALUE host;
+ struct addrinfo* addr;
+ VALUE (*ipaddr)_((struct sockaddr*, size_t));
+};
+
static VALUE
-make_hostent(addr, ipaddr)
- struct addrinfo *addr;
- VALUE (*ipaddr) _((struct sockaddr*, size_t));
+make_hostent_internal(arg)
+ struct hostent_arg *arg;
{
+ VALUE host = arg->host;
+ struct addrinfo* addr = arg->addr;
+ VALUE (*ipaddr)_((struct sockaddr*, size_t)) = arg->ipaddr;
+
struct addrinfo *ai;
struct hostent *h;
VALUE ary, names;
char **pch;
+ const char* hostp;
+ char hbuf[NI_MAXHOST];
ary = rb_ary_new();
- rb_ary_push(ary, rb_str_new2(addr->ai_canonname));
-#if defined(HAVE_GETIPNODEBYNAME)
- {
- int error;
-
- h = getipnodebyname(addr->ai_canonname, addr->ai_family, AI_ALL, &error);
+ if (addr->ai_canonname) {
+ hostp = addr->ai_canonname;
}
-#elif defined(HAVE_GETHOSTBYNAME2)
- h = gethostbyname2(addr->ai_canonname, addr->ai_family);
-#else
- h = gethostbyname(addr->ai_canonname);
-#endif
- if (h) {
+ else {
+ hostp = host_str(host, hbuf, sizeof(hbuf));
+ }
+ rb_ary_push(ary, rb_str_new2(hostp));
+
+ if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) {
names = rb_ary_new();
if (h->h_aliases != NULL) {
for (pch = h->h_aliases; *pch; pch++) {
rb_ary_push(names, rb_str_new2(*pch));
}
}
-#if defined(HAVE_GETIPNODEBYNAME)
- freehostent(h);
-#endif
}
else {
names = rb_ary_new2(0);
@@ -1065,12 +1407,33 @@ make_hostent(addr, ipaddr)
rb_ary_push(ary, names);
rb_ary_push(ary, INT2NUM(addr->ai_family));
for (ai = addr; ai; ai = ai->ai_next) {
- rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
+ /* Pushing all addresses regardless of address family is not the
+ * behaviour expected of gethostbyname(). All the addresses in struct
+ * hostent->h_addr_list must be of the same family.
+ */
+ if(ai->ai_family == addr->ai_family) {
+ rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen));
+ }
}
return ary;
}
+static VALUE
+make_hostent(host, addr, ipaddr)
+ VALUE host;
+ struct addrinfo* addr;
+ VALUE (*ipaddr)_((struct sockaddr*, size_t));
+{
+ struct hostent_arg arg;
+
+ arg.host = host;
+ arg.addr = addr;
+ arg.ipaddr = ipaddr;
+ return rb_ensure(make_hostent_internal, (VALUE)&arg,
+ RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)addr);
+}
+
VALUE
tcp_sockaddr(addr, len)
struct sockaddr *addr;
@@ -1084,7 +1447,7 @@ tcp_s_gethostbyname(obj, host)
VALUE obj, host;
{
rb_secure(3);
- return make_hostent(sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), tcp_sockaddr);
+ return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), tcp_sockaddr);
}
static VALUE
@@ -1101,6 +1464,39 @@ tcp_svr_init(argc, argv, sock)
return init_inetsock(sock, Qnil, arg1, Qnil, Qnil, INET_SERVER);
}
+static void
+make_fd_nonblock(int fd)
+{
+ int flags;
+#ifdef F_GETFL
+ flags = fcntl(fd, F_GETFL);
+ if (flags == -1) {
+ rb_sys_fail(0);
+ }
+#else
+ flags = 0;
+#endif
+ flags |= O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) == -1) {
+ rb_sys_fail(0);
+ }
+}
+
+static VALUE
+s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
+{
+ int fd2;
+
+ rb_secure(3);
+ rb_io_set_nonblock(fptr);
+ fd2 = accept(fileno(fptr->f), (struct sockaddr*)sockaddr, len);
+ if (fd2 < 0) {
+ rb_sys_fail("accept(2)");
+ }
+ make_fd_nonblock(fd2);
+ return init_sock(rb_obj_alloc(klass), fd2);
+}
+
static VALUE
s_accept(klass, fd, sockaddr, len)
VALUE klass;
@@ -1129,6 +1525,8 @@ s_accept(klass, fd, sockaddr, len)
rb_gc();
retry = 1;
goto retry;
+ case EWOULDBLOCK:
+ break;
default:
if (!rb_io_wait_readable(fd)) break;
retry = 0;
@@ -1144,7 +1542,7 @@ static VALUE
tcp_accept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage from;
socklen_t fromlen;
@@ -1154,11 +1552,54 @@ tcp_accept(sock)
(struct sockaddr*)&from, &fromlen);
}
+/*
+ * call-seq:
+ * tcpserver.accept_nonblock => tcpsocket
+ *
+ * Accepts an incoming connection using accept(2) after
+ * O_NONBLOCK is set for the underlying file descriptor.
+ * It returns an accepted TCPSocket for the incoming connection.
+ *
+ * === Example
+ * require 'socket'
+ * serv = TCPServer.new(2202)
+ * begin
+ * sock = serv.accept_nonblock
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * IO.select([serv])
+ * retry
+ * end
+ * # sock is an accepted socket.
+ *
+ * Refer to Socket#accept for the exceptions that may be thrown if the call
+ * to TCPServer#accept_nonblock fails.
+ *
+ * TCPServer#accept_nonblock may raise any error corresponding to accept(2) failure,
+ * including Errno::EAGAIN.
+ *
+ * === See
+ * * TCPServer#accept
+ * * Socket#accept
+ */
+static VALUE
+tcp_accept_nonblock(sock)
+ VALUE sock;
+{
+ rb_io_t *fptr;
+ struct sockaddr_storage from;
+ socklen_t fromlen;
+
+ GetOpenFile(sock, fptr);
+ fromlen = sizeof(from);
+ return s_accept_nonblock(rb_cTCPSocket, fptr,
+ (struct sockaddr *)&from, &fromlen);
+}
+
static VALUE
tcp_sysaccept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage from;
socklen_t fromlen;
@@ -1189,7 +1630,7 @@ init_unixsock(sock, path, server)
{
struct sockaddr_un sockaddr;
int fd, status;
- OpenFile *fptr;
+ rb_io_t *fptr;
SafeStringValue(path);
fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0);
@@ -1199,8 +1640,11 @@ init_unixsock(sock, path, server)
MEMZERO(&sockaddr, struct sockaddr_un, 1);
sockaddr.sun_family = AF_UNIX;
- strncpy(sockaddr.sun_path, RSTRING(path)->ptr, sizeof(sockaddr.sun_path)-1);
- sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = '\0';
+ if (sizeof(sockaddr.sun_path) <= RSTRING(path)->len) {
+ rb_raise(rb_eArgError, "too long unix socket path (max: %dbytes)",
+ (int)sizeof(sockaddr.sun_path)-1);
+ }
+ strcpy(sockaddr.sun_path, StringValueCStr(path));
if (server) {
status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
@@ -1226,7 +1670,9 @@ init_unixsock(sock, path, server)
init_sock(sock, fd);
GetOpenFile(sock, fptr);
- fptr->path = strdup(RSTRING(path)->ptr);
+ if (server) {
+ fptr->path = strdup(RSTRING(path)->ptr);
+ }
return sock;
}
@@ -1236,7 +1682,7 @@ static VALUE
ip_addr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage addr;
socklen_t len = sizeof addr;
@@ -1251,7 +1697,7 @@ static VALUE
ip_peeraddr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage addr;
socklen_t len = sizeof addr;
@@ -1332,13 +1778,13 @@ static VALUE
udp_connect(sock, host, port)
VALUE sock, host, port;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct udp_arg arg;
VALUE ret;
rb_secure(3);
- GetOpenFile(sock, fptr);
arg.res = sock_addrinfo(host, port, SOCK_DGRAM, 0);
+ GetOpenFile(sock, fptr);
arg.fd = fileno(fptr->f);
ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)arg.res);
@@ -1350,12 +1796,12 @@ static VALUE
udp_bind(sock, host, port)
VALUE sock, host, port;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct addrinfo *res0, *res;
rb_secure(3);
- GetOpenFile(sock, fptr);
res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
+ GetOpenFile(sock, fptr);
for (res = res0; res; res = res->ai_next) {
if (bind(fileno(fptr->f), res->ai_addr, res->ai_addrlen) < 0) {
continue;
@@ -1375,7 +1821,7 @@ udp_send(argc, argv, sock)
VALUE sock;
{
VALUE mesg, flags, host, port;
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *f;
int n;
struct addrinfo *res0, *res;
@@ -1386,10 +1832,10 @@ udp_send(argc, argv, sock)
rb_secure(4);
rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port);
- GetOpenFile(sock, fptr);
+ StringValue(mesg);
res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
+ GetOpenFile(sock, fptr);
f = GetWriteFile(fptr);
- StringValue(mesg);
for (res = res0; res; res = res->ai_next) {
retry:
n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
@@ -1407,6 +1853,52 @@ udp_send(argc, argv, sock)
return INT2FIX(n);
}
+/*
+ * call-seq:
+ * udpsocket.recvfrom_nonblock(maxlen) => [mesg, sender_inet_addr]
+ * udpsocket.recvfrom_nonblock(maxlen, flags) => [mesg, sender_inet_addr]
+ *
+ * Receives up to _maxlen_ bytes from +udpsocket+ using recvfrom(2) after
+ * O_NONBLOCK is set for the underlying file descriptor.
+ * _flags_ is zero or more of the +MSG_+ options.
+ * The first element of the results, _mesg_, is the data received.
+ * The second element, _sender_inet_addr_, is an array to represent the sender address.
+ *
+ * When recvfrom(2) returns 0,
+ * Socket#recvfrom_nonblock returns an empty string as data.
+ * It means an empty packet.
+ *
+ * === Parameters
+ * * +maxlen+ - the number of bytes to receive from the socket
+ * * +flags+ - zero or more of the +MSG_+ options
+ *
+ * === Example
+ * require 'socket'
+ * s1 = UDPSocket.new
+ * s1.bind("127.0.0.1", 0)
+ * s2 = UDPSocket.new
+ * s2.bind("127.0.0.1", 0)
+ * s2.connect(*s1.addr.values_at(3,1))
+ * s1.connect(*s2.addr.values_at(3,1))
+ * s1.send "aaa", 0
+ * IO.select([s2])
+ * p s2.recvfrom_nonblock(10) #=> ["aaa", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]
+ *
+ * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
+ * to _recvfrom_nonblock_ fails.
+ *
+ * UDPSocket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
+ * including Errno::EAGAIN.
+ *
+ * === See
+ * * Socket#recvfrom
+ */
+static VALUE
+udp_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
+{
+ return s_recvfrom_nonblock(sock, argc, argv, RECV_IP);
+}
+
#ifdef HAVE_SYS_UN_H
static VALUE
unix_init(sock, path)
@@ -1415,11 +1907,20 @@ unix_init(sock, path)
return init_unixsock(sock, path, 0);
}
+static char *
+unixpath(struct sockaddr_un *sockaddr, socklen_t len)
+{
+ if (sockaddr->sun_path < (char*)sockaddr + len)
+ return sockaddr->sun_path;
+ else
+ return "";
+}
+
static VALUE
unix_path(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (fptr->path == 0) {
@@ -1427,7 +1928,7 @@ unix_path(sock)
socklen_t len = sizeof(addr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
rb_sys_fail(0);
- fptr->path = strdup(addr.sun_path);
+ fptr->path = strdup(unixpath(&addr, len));
}
return rb_str_new2(fptr->path);
}
@@ -1448,26 +1949,38 @@ unix_recvfrom(argc, argv, sock)
return s_recvfrom(sock, argc, argv, RECV_UNIX);
}
+#if defined(HAVE_ST_MSG_CONTROL) && defined(SCM_RIGHTS)
+#define FD_PASSING_BY_MSG_CONTROL 1
+#else
+#define FD_PASSING_BY_MSG_CONTROL 0
+#endif
+
+#if defined(HAVE_ST_MSG_ACCRIGHTS)
+#define FD_PASSING_BY_MSG_ACCRIGHTS 1
+#else
+#define FD_PASSING_BY_MSG_ACCRIGHTS 0
+#endif
+
static VALUE
unix_send_io(sock, val)
VALUE sock, val;
{
-#if defined(HAVE_SENDMSG) && (defined(HAVE_ST_MSG_CONTROL) || defined(HAVE_ST_MSG_ACCRIGHTS))
+#if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
int fd;
- OpenFile *fptr;
+ rb_io_t *fptr;
struct msghdr msg;
struct iovec vec[1];
char buf[1];
-#if defined(HAVE_ST_MSG_CONTROL)
+#if FD_PASSING_BY_MSG_CONTROL
struct {
struct cmsghdr hdr;
- int fd;
+ char pad[8+sizeof(int)+8];
} cmsg;
#endif
if (rb_obj_is_kind_of(val, rb_cIO)) {
- OpenFile *valfptr;
+ rb_io_t *valfptr;
GetOpenFile(val, valfptr);
fd = fileno(valfptr->f);
}
@@ -1475,7 +1988,7 @@ unix_send_io(sock, val)
fd = FIX2INT(val);
}
else {
- rb_raise(rb_eTypeError, "IO nor file descriptor");
+ rb_raise(rb_eTypeError, "neither IO nor file descriptor");
}
GetOpenFile(sock, fptr);
@@ -1490,14 +2003,15 @@ unix_send_io(sock, val)
msg.msg_iov = vec;
msg.msg_iovlen = 1;
-#if defined(HAVE_ST_MSG_CONTROL)
+#if FD_PASSING_BY_MSG_CONTROL
msg.msg_control = (caddr_t)&cmsg;
- msg.msg_controllen = sizeof(struct cmsghdr) + sizeof(int);
+ msg.msg_controllen = CMSG_LEN(sizeof(int));
msg.msg_flags = 0;
- cmsg.hdr.cmsg_len = sizeof(struct cmsghdr) + sizeof(int);
+ MEMZERO((char*)&cmsg, char, sizeof(cmsg));
+ cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
cmsg.hdr.cmsg_level = SOL_SOCKET;
cmsg.hdr.cmsg_type = SCM_RIGHTS;
- cmsg.fd = fd;
+ *(int *)CMSG_DATA(&cmsg.hdr) = fd;
#else
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof(fd);
@@ -1513,7 +2027,7 @@ unix_send_io(sock, val)
#endif
}
-#if defined(HAVE_RECVMSG) && (defined(HAVE_ST_MSG_CONTROL) || defined(HAVE_ST_MSG_ACCRIGHTS))
+#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
static void
thread_read_select(fd)
int fd;
@@ -1532,18 +2046,18 @@ unix_recv_io(argc, argv, sock)
VALUE *argv;
VALUE sock;
{
-#if defined(HAVE_RECVMSG) && (defined(HAVE_ST_MSG_CONTROL) || defined(HAVE_ST_MSG_ACCRIGHTS))
+#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
VALUE klass, mode;
- OpenFile *fptr;
+ rb_io_t *fptr;
struct msghdr msg;
struct iovec vec[2];
char buf[1];
int fd;
-#if defined(HAVE_ST_MSG_CONTROL)
+#if FD_PASSING_BY_MSG_CONTROL
struct {
struct cmsghdr hdr;
- int fd;
+ char pad[8+sizeof(int)+8];
} cmsg;
#endif
@@ -1565,14 +2079,14 @@ unix_recv_io(argc, argv, sock)
msg.msg_iov = vec;
msg.msg_iovlen = 1;
-#if defined(HAVE_ST_MSG_CONTROL)
+#if FD_PASSING_BY_MSG_CONTROL
msg.msg_control = (caddr_t)&cmsg;
- msg.msg_controllen = sizeof(struct cmsghdr) + sizeof(int);
+ msg.msg_controllen = CMSG_SPACE(sizeof(int));
msg.msg_flags = 0;
- cmsg.hdr.cmsg_len = sizeof(struct cmsghdr) + sizeof(int);
+ cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
cmsg.hdr.cmsg_level = SOL_SOCKET;
cmsg.hdr.cmsg_type = SCM_RIGHTS;
- cmsg.fd = -1;
+ *(int *)CMSG_DATA(&cmsg.hdr) = -1;
#else
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof(fd);
@@ -1582,21 +2096,37 @@ unix_recv_io(argc, argv, sock)
if (recvmsg(fileno(fptr->f), &msg, 0) == -1)
rb_sys_fail("recvmsg(2)");
- if (
-#if defined(HAVE_ST_MSG_CONTROL)
- msg.msg_controllen != sizeof(struct cmsghdr) + sizeof(int) ||
- cmsg.hdr.cmsg_len != sizeof(struct cmsghdr) + sizeof(int) ||
- cmsg.hdr.cmsg_level != SOL_SOCKET ||
- cmsg.hdr.cmsg_type != SCM_RIGHTS
+#if FD_PASSING_BY_MSG_CONTROL
+ if (msg.msg_controllen != CMSG_SPACE(sizeof(int))) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (msg_controllen=%d, %d expected)",
+ msg.msg_controllen, CMSG_SPACE(sizeof(int)));
+ }
+ if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (cmsg_len=%d, %d expected)",
+ cmsg.hdr.cmsg_len, CMSG_LEN(sizeof(int)));
+ }
+ if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (cmsg_level=%d, %d expected)",
+ cmsg.hdr.cmsg_level, SOL_SOCKET);
+ }
+ if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (cmsg_type=%d, %d expected)",
+ cmsg.hdr.cmsg_type, SCM_RIGHTS);
+ }
#else
- msg.msg_accrightslen != sizeof(fd)
-#endif
- ) {
- rb_raise(rb_eSocket, "File descriptor was not passed");
+ if (msg.msg_accrightslen != sizeof(fd)) {
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (accrightslen) : %d != %d",
+ msg.msg_accrightslen, sizeof(fd));
}
+#endif
-#if defined(HAVE_ST_MSG_CONTROL)
- fd = cmsg.fd;
+#if FD_PASSING_BY_MSG_CONTROL
+ fd = *(int *)CMSG_DATA(&cmsg.hdr);
#endif
if (klass == Qnil)
@@ -1622,7 +2152,7 @@ static VALUE
unix_accept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
@@ -1632,11 +2162,54 @@ unix_accept(sock)
(struct sockaddr*)&from, &fromlen);
}
+/*
+ * call-seq:
+ * unixserver.accept_nonblock => unixsocket
+ *
+ * Accepts an incoming connection using accept(2) after
+ * O_NONBLOCK is set for the underlying file descriptor.
+ * It returns an accepted UNIXSocket for the incoming connection.
+ *
+ * === Example
+ * require 'socket'
+ * serv = UNIXServer.new("/tmp/sock")
+ * begin
+ * sock = serv.accept_nonblock
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * IO.select([serv])
+ * retry
+ * end
+ * # sock is an accepted socket.
+ *
+ * Refer to Socket#accept for the exceptions that may be thrown if the call
+ * to UNIXServer#accept_nonblock fails.
+ *
+ * UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure,
+ * including Errno::EAGAIN.
+ *
+ * === See
+ * * UNIXServer#accept
+ * * Socket#accept
+ */
+static VALUE
+unix_accept_nonblock(sock)
+ VALUE sock;
+{
+ rb_io_t *fptr;
+ struct sockaddr_un from;
+ socklen_t fromlen;
+
+ GetOpenFile(sock, fptr);
+ fromlen = sizeof(from);
+ return s_accept_nonblock(rb_cUNIXSocket, fptr,
+ (struct sockaddr *)&from, &fromlen);
+}
+
static VALUE
unix_sysaccept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
@@ -1646,18 +2219,19 @@ unix_sysaccept(sock)
}
static VALUE
-unixaddr(sockaddr)
+unixaddr(sockaddr, len)
struct sockaddr_un *sockaddr;
+ socklen_t len;
{
return rb_assoc_new(rb_str_new2("AF_UNIX"),
- rb_str_new2(sockaddr->sun_path));
+ rb_str_new2(unixpath(sockaddr, len)));
}
static VALUE
unix_addr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un addr;
socklen_t len = sizeof addr;
@@ -1665,26 +2239,22 @@ unix_addr(sock)
if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
rb_sys_fail("getsockname(2)");
- if (len == 0)
- addr.sun_path[0] = '\0';
- return unixaddr(&addr);
+ return unixaddr(&addr, len);
}
static VALUE
unix_peeraddr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un addr;
socklen_t len = sizeof addr;
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
- rb_sys_fail("getsockname(2)");
- if (len == 0)
- addr.sun_path[0] = '\0';
- return unixaddr(&addr);
+ rb_sys_fail("getpeername(2)");
+ return unixaddr(&addr, len);
}
#endif
@@ -1693,10 +2263,13 @@ setup_domain_and_type(domain, dv, type, tv)
VALUE domain, type;
int *dv, *tv;
{
+ VALUE tmp;
char *ptr;
- if (TYPE(domain) == T_STRING) {
- SafeStringValue(domain);
+ tmp = rb_check_string_type(domain);
+ if (!NIL_P(tmp)) {
+ domain = tmp;
+ rb_check_safe_obj(domain);
ptr = RSTRING(domain)->ptr;
if (strcmp(ptr, "AF_INET") == 0)
*dv = AF_INET;
@@ -1739,13 +2312,15 @@ setup_domain_and_type(domain, dv, type, tv)
*dv = PF_IPX;
#endif
else
- rb_raise(rb_eSocket, "Unknown socket domain %s", ptr);
+ rb_raise(rb_eSocket, "unknown socket domain %s", ptr);
}
else {
*dv = NUM2INT(domain);
}
- if (TYPE(type) == T_STRING) {
- SafeStringValue(type);
+ tmp = rb_check_string_type(type);
+ if (!NIL_P(tmp)) {
+ type = tmp;
+ rb_check_safe_obj(type);
ptr = RSTRING(type)->ptr;
if (strcmp(ptr, "SOCK_STREAM") == 0)
*tv = SOCK_STREAM;
@@ -1768,7 +2343,7 @@ setup_domain_and_type(domain, dv, type, tv)
*tv = SOCK_PACKET;
#endif
else
- rb_raise(rb_eSocket, "Unknown socket type %s", ptr);
+ rb_raise(rb_eSocket, "unknown socket type %s", ptr);
}
else {
*tv = NUM2INT(type);
@@ -1794,16 +2369,18 @@ static VALUE
sock_s_socketpair(klass, domain, type, protocol)
VALUE klass, domain, type, protocol;
{
-#if !defined(_WIN32) && !defined(__BEOS__) && !defined(__EMX__) && !defined(__QNXNTO__)
- int d, t, sp[2];
+#if defined HAVE_SOCKETPAIR
+ int d, t, p, sp[2];
+ int ret;
setup_domain_and_type(domain, &d, type, &t);
- again:
- if (socketpair(d, t, NUM2INT(protocol), sp) < 0) {
- if (errno == EMFILE || errno == ENFILE) {
- rb_gc();
- goto again;
- }
+ p = NUM2INT(protocol);
+ ret = socketpair(d, t, p, sp);
+ if (ret < 0 && (errno == EMFILE || errno == ENFILE)) {
+ rb_gc();
+ ret = socketpair(d, t, p, sp);
+ }
+ if (ret < 0) {
rb_sys_fail("socketpair(2)");
}
@@ -1834,16 +2411,126 @@ unix_s_socketpair(argc, argv, klass)
}
#endif
+/*
+ * call-seq:
+ * socket.connect(server_sockaddr) => 0
+ *
+ * Requests a connection to be made on the given +server_sockaddr+. Returns 0 if
+ * successful, otherwise an exception is raised.
+ *
+ * === Parameter
+ * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
+ *
+ * === Example:
+ * # Pull down Google's web page
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' )
+ * socket.connect( sockaddr )
+ * socket.write( "GET / HTTP/1.0\r\n\r\n" )
+ * results = socket.read
+ *
+ * === Unix-based Exceptions
+ * On unix-based systems the following system exceptions may be raised if
+ * the call to _connect_ fails:
+ * * Errno::EACCES - search permission is denied for a component of the prefix
+ * path or write access to the +socket+ is denided
+ * * Errno::EADDRINUSE - the _sockaddr_ is already in use
+ * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
+ * local machine
+ * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for
+ * the address family of the specified +socket+
+ * * Errno::EALREADY - a connection is already in progress for the specified
+ * socket
+ * * Errno::EBADF - the +socket+ is not a valid file descriptor
+ * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
+ * refused the connection request
+ * * Errno::ECONNRESET - the remote host reset the connection request
+ * * Errno::EFAULT - the _sockaddr_ cannot be accessed
+ * * Errno::EHOSTUNREACH - the destination host cannot be reached (probably
+ * because the host is down or a remote router cannot reach it)
+ * * Errno::EINPROGRESS - the O_NONBLOCK is set for the +socket+ and the
+ * connection cnanot be immediately established; the connection will be
+ * established asynchronously
+ * * Errno::EINTR - the attempt to establish the connection was interrupted by
+ * delivery of a signal that was caught; the connection will be established
+ * asynchronously
+ * * Errno::EISCONN - the specified +socket+ is already connected
+ * * Errno::EINVAL - the address length used for the _sockaddr_ is not a valid
+ * length for the address family or there is an invalid family in _sockaddr_
+ * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
+ * PATH_MAX
+ * * Errno::ENETDOWN - the local interface used to reach the destination is down
+ * * Errno::ENETUNREACH - no route to the network is present
+ * * Errno::ENOBUFS - no buffer space is available
+ * * Errno::ENOSR - there were insufficient STREAMS resources available to
+ * complete the operation
+ * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
+ * * Errno::EOPNOTSUPP - the calling +socket+ is listening and cannot be connected
+ * * Errno::EPROTOTYPE - the _sockaddr_ has a different type than the socket
+ * bound to the specified peer address
+ * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
+ * was made.
+ *
+ * On unix-based systems if the address family of the calling +socket+ is
+ * AF_UNIX the follow exceptions may be raised if the call to _connect_
+ * fails:
+ * * Errno::EIO - an i/o error occured while reading from or writing to the
+ * file system
+ * * Errno::ELOOP - too many symbolic links were encountered in translating
+ * the pathname in _sockaddr_
+ * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
+ * characters, or an entired pathname exceeded PATH_MAX characters
+ * * Errno::ENOENT - a component of the pathname does not name an existing file
+ * or the pathname is an empty string
+ * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
+ * is not a directory
+ *
+ * === Windows Exceptions
+ * On Windows systems the following system exceptions may be raised if
+ * the call to _connect_ fails:
+ * * Errno::ENETDOWN - the network is down
+ * * Errno::EADDRINUSE - the socket's local address is already in use
+ * * Errno::EINTR - the socket was cancelled
+ * * Errno::EINPROGRESS - a blocking socket is in progress or the service provider
+ * is still processing a callback function. Or a nonblocking connect call is
+ * in progress on the +socket+.
+ * * Errno::EALREADY - see Errno::EINVAL
+ * * Errno::EADDRNOTAVAIL - the remote address is not a valid address, such as
+ * ADDR_ANY TODO check ADDRANY TO INADDR_ANY
+ * * Errno::EAFNOSUPPORT - addresses in the specified family cannot be used with
+ * with this +socket+
+ * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
+ * refused the connection request
+ * * Errno::EFAULT - the socket's internal address or address length parameter
+ * is too small or is not a valid part of the user space address
+ * * Errno::EINVAL - the +socket+ is a listening socket
+ * * Errno::EISCONN - the +socket+ is already connected
+ * * Errno::ENETUNREACH - the network cannot be reached from this host at this time
+ * * Errno::EHOSTUNREACH - no route to the network is present
+ * * Errno::ENOBUFS - no buffer space is available
+ * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
+ * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
+ * was made.
+ * * Errno::EWOULDBLOCK - the socket is marked as nonblocking and the
+ * connection cannot be completed immediately
+ * * Errno::EACCES - the attempt to connect the datagram socket to the
+ * broadcast address failed
+ *
+ * === See
+ * * connect manual pages on unix-based systems
+ * * connect function in Microsoft's Winsock functions reference
+ */
static VALUE
sock_connect(sock, addr)
VALUE sock, addr;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
int fd;
StringValue(addr);
- rb_str_modify(addr);
-
+ addr = rb_str_new4(addr);
GetOpenFile(sock, fptr);
fd = fileno(fptr->f);
if (ruby_connect(fd, (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len, 0) < 0) {
@@ -1853,15 +2540,149 @@ sock_connect(sock, addr)
return INT2FIX(0);
}
+/*
+ * call-seq:
+ * socket.connect_nonblock(server_sockaddr) => 0
+ *
+ * Requests a connection to be made on the given +server_sockaddr+ after
+ * O_NONBLOCK is set for the underlying file descriptor.
+ * Returns 0 if successful, otherwise an exception is raised.
+ *
+ * === Parameter
+ * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
+ *
+ * === Example:
+ * # Pull down Google's web page
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ * sockaddr = Socket.sockaddr_in(80, 'www.google.com')
+ * begin
+ * socket.connect_nonblock(sockaddr)
+ * rescue Errno::EINPROGRESS
+ * IO.select(nil, [socket])
+ * begin
+ * socket.connect_nonblock(sockaddr)
+ * rescue Errno::EISCONN
+ * end
+ * end
+ * socket.write("GET / HTTP/1.0\r\n\r\n")
+ * results = socket.read
+ *
+ * Refer to Socket#connect for the exceptions that may be thrown if the call
+ * to _connect_nonblock_ fails.
+ *
+ * Socket#connect_nonblock may raise any error corresponding to connect(2) failure,
+ * including Errno::EINPROGRESS.
+ *
+ * === See
+ * * Socket#connect
+ */
static VALUE
-sock_bind(sock, addr)
+sock_connect_nonblock(sock, addr)
VALUE sock, addr;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
+ int n;
StringValue(addr);
- rb_str_modify(addr);
+ addr = rb_str_new4(addr);
+ GetOpenFile(sock, fptr);
+ rb_io_set_nonblock(fptr);
+ n = connect(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len);
+ if (n < 0) {
+ rb_sys_fail("connect(2)");
+ }
+ return INT2FIX(n);
+}
+
+/*
+ * call-seq:
+ * socket.bind(server_sockaddr) => 0
+ *
+ * Binds to the given +struct+ sockaddr.
+ *
+ * === Parameter
+ * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
+ *
+ * === Example
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.bind( sockaddr )
+ *
+ * === Unix-based Exceptions
+ * On unix-based based systems the following system exceptions may be raised if
+ * the call to _bind_ fails:
+ * * Errno::EACCES - the specified _sockaddr_ is protected and the current
+ * user does not have permission to bind to it
+ * * Errno::EADDRINUSE - the specified _sockaddr_ is already in use
+ * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
+ * local machine
+ * * Errno::EAFNOSUPPORT - the specified _sockaddr_ isnot a valid address for
+ * the family of the calling +socket+
+ * * Errno::EBADF - the _sockaddr_ specified is not a valid file descriptor
+ * * Errno::EFAULT - the _sockaddr_ argument cannot be accessed
+ * * Errno::EINVAL - the +socket+ is already bound to an address, and the
+ * protocol does not support binding to the new _sockaddr_ or the +socket+
+ * has been shut down.
+ * * Errno::EINVAL - the address length is not a valid length for the address
+ * family
+ * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
+ * PATH_MAX
+ * * Errno::ENOBUFS - no buffer space is available
+ * * Errno::ENOSR - there were insufficient STREAMS resources available to
+ * complete the operation
+ * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
+ * * Errno::EOPNOTSUPP - the socket type of the +socket+ does not support
+ * binding to an address
+ *
+ * On unix-based based systems if the address family of the calling +socket+ is
+ * Socket::AF_UNIX the follow exceptions may be raised if the call to _bind_
+ * fails:
+ * * Errno::EACCES - search permission is denied for a component of the prefix
+ * path or write access to the +socket+ is denided
+ * * Errno::EDESTADDRREQ - the _sockaddr_ argument is a null pointer
+ * * Errno::EISDIR - same as Errno::EDESTADDRREQ
+ * * Errno::EIO - an i/o error occurred
+ * * Errno::ELOOP - too many symbolic links were encountered in translating
+ * the pathname in _sockaddr_
+ * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX
+ * characters, or an entired pathname exceeded PATH_MAX characters
+ * * Errno::ENOENT - a component of the pathname does not name an existing file
+ * or the pathname is an empty string
+ * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
+ * is not a directory
+ * * Errno::EROFS - the name would reside on a read only filesystem
+ *
+ * === Windows Exceptions
+ * On Windows systems the following system exceptions may be raised if
+ * the call to _bind_ fails:
+ * * Errno::ENETDOWN-- the network is down
+ * * Errno::EACCES - the attempt to connect the datagram socket to the
+ * broadcast address failed
+ * * Errno::EADDRINUSE - the socket's local address is already in use
+ * * Errno::EADDRNOTAVAIL - the specified address is not a valid address for this
+ * computer
+ * * Errno::EFAULT - the socket's internal address or address length parameter
+ * is too small or is not a valid part of the user space addressed
+ * * Errno::EINVAL - the +socket+ is already bound to an address
+ * * Errno::ENOBUFS - no buffer space is available
+ * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
+ *
+ * === See
+ * * bind manual pages on unix-based systems
+ * * bind function in Microsoft's Winsock functions reference
+ */
+static VALUE
+sock_bind(sock, addr)
+ VALUE sock, addr;
+{
+ rb_io_t *fptr;
+
+ StringValue(addr);
GetOpenFile(sock, fptr);
if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0)
rb_sys_fail("bind(2)");
@@ -1869,20 +2690,197 @@ sock_bind(sock, addr)
return INT2FIX(0);
}
+/*
+ * call-seq:
+ * socket.listen( int ) => 0
+ *
+ * Listens for connections, using the specified +int+ as the backlog. A call
+ * to _listen_ only applies if the +socket+ is of type SOCK_STREAM or
+ * SOCK_SEQPACKET.
+ *
+ * === Parameter
+ * * +backlog+ - the maximum length of the queue for pending connections.
+ *
+ * === Example 1
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.bind( sockaddr )
+ * socket.listen( 5 )
+ *
+ * === Example 2 (listening on an arbitary port, unix-based systems only):
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * socket.listen( 1 )
+ *
+ * === Unix-based Exceptions
+ * On unix based systems the above will work because a new +sockaddr+ struct
+ * is created on the address ADDR_ANY, for an arbitrary port number as handed
+ * off by the kernel. It will not work on Windows, because Windows requires that
+ * the +socket+ is bound by calling _bind_ before it can _listen_.
+ *
+ * If the _backlog_ amount exceeds the implementation-dependent maximum
+ * queue length, the implementation's maximum queue length will be used.
+ *
+ * On unix-based based systems the following system exceptions may be raised if the
+ * call to _listen_ fails:
+ * * Errno::EBADF - the _socket_ argument is not a valid file descriptor
+ * * Errno::EDESTADDRREQ - the _socket_ is not bound to a local address, and
+ * the protocol does not support listening on an unbound socket
+ * * Errno::EINVAL - the _socket_ is already connected
+ * * Errno::ENOTSOCK - the _socket_ argument does not refer to a socket
+ * * Errno::EOPNOTSUPP - the _socket_ protocol does not support listen
+ * * Errno::EACCES - the calling process does not have approriate privileges
+ * * Errno::EINVAL - the _socket_ has been shut down
+ * * Errno::ENOBUFS - insufficient resources are available in the system to
+ * complete the call
+ *
+ * === Windows Exceptions
+ * On Windows systems the following system exceptions may be raised if
+ * the call to _listen_ fails:
+ * * Errno::ENETDOWN - the network is down
+ * * Errno::EADDRINUSE - the socket's local address is already in use. This
+ * usually occurs during the execution of _bind_ but could be delayed
+ * if the call to _bind_ was to a partially wildcard address (involving
+ * ADDR_ANY) and if a specific address needs to be commmitted at the
+ * time of the call to _listen_
+ * * Errno::EINPROGRESS - a Windows Sockets 1.1 call is in progress or the
+ * service provider is still processing a callback function
+ * * Errno::EINVAL - the +socket+ has not been bound with a call to _bind_.
+ * * Errno::EISCONN - the +socket+ is already connected
+ * * Errno::EMFILE - no more socket descriptors are available
+ * * Errno::ENOBUFS - no buffer space is available
+ * * Errno::ENOTSOC - +socket+ is not a socket
+ * * Errno::EOPNOTSUPP - the referenced +socket+ is not a type that supports
+ * the _listen_ method
+ *
+ * === See
+ * * listen manual pages on unix-based systems
+ * * listen function in Microsoft's Winsock functions reference
+ */
static VALUE
sock_listen(sock, log)
VALUE sock, log;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
+ int backlog;
rb_secure(4);
+ backlog = NUM2INT(log);
GetOpenFile(sock, fptr);
- if (listen(fileno(fptr->f), NUM2INT(log)) < 0)
+ if (listen(fileno(fptr->f), backlog) < 0)
rb_sys_fail("listen(2)");
return INT2FIX(0);
}
+/*
+ * call-seq:
+ * socket.recvfrom(maxlen) => [mesg, sender_sockaddr]
+ * socket.recvfrom(maxlen, flags) => [mesg, sender_sockaddr]
+ *
+ * Receives up to _maxlen_ bytes from +socket+. _flags_ is zero or more
+ * of the +MSG_+ options. The first element of the results, _mesg_, is the data
+ * received. The second element, _sender_sockaddr_, contains protocol-specific information
+ * on the sender.
+ *
+ * === Parameters
+ * * +maxlen+ - the number of bytes to receive from the socket
+ * * +flags+ - zero or more of the +MSG_+ options
+ *
+ * === Example
+ * # In one file, start this first
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.bind( sockaddr )
+ * socket.listen( 5 )
+ * client, client_sockaddr = socket.accept
+ * data = client.recvfrom( 20 )[0].chomp
+ * puts "I only received 20 bytes '#{data}'"
+ * sleep 1
+ * socket.close
+ *
+ * # In another file, start this second
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.connect( sockaddr )
+ * socket.puts "Watch this get cut short!"
+ * socket.close
+ *
+ * === Unix-based Exceptions
+ * On unix-based based systems the following system exceptions may be raised if the
+ * call to _recvfrom_ fails:
+ * * Errno::EAGAIN - the +socket+ file descriptor is marked as O_NONBLOCK and no
+ * data is waiting to be received; or MSG_OOB is set and no out-of-band data
+ * is available and either the +socket+ file descriptor is marked as
+ * O_NONBLOCK or the +socket+ does not support blocking to wait for
+ * out-of-band-data
+ * * Errno::EWOULDBLOCK - see Errno::EAGAIN
+ * * Errno::EBADF - the +socket+ is not a valid file descriptor
+ * * Errno::ECONNRESET - a connection was forcibly closed by a peer
+ * * Errno::EFAULT - the socket's internal buffer, address or address length
+ * cannot be accessed or written
+ * * Errno::EINTR - a signal interupted _recvfrom_ before any data was available
+ * * Errno::EINVAL - the MSG_OOB flag is set and no out-of-band data is available
+ * * Errno::EIO - an i/o error occurred while reading from or writing to the
+ * filesystem
+ * * Errno::ENOBUFS - insufficient resources were available in the system to
+ * perform the operation
+ * * Errno::ENOMEM - insufficient memory was available to fulfill the request
+ * * Errno::ENOSR - there were insufficient STREAMS resources available to
+ * complete the operation
+ * * Errno::ENOTCONN - a receive is attempted on a connection-mode socket that
+ * is not connected
+ * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
+ * * Errno::EOPNOTSUPP - the specified flags are not supported for this socket type
+ * * Errno::ETIMEDOUT - the connection timed out during connection establishment
+ * or due to a transmission timeout on an active connection
+ *
+ * === Windows Exceptions
+ * On Windows systems the following system exceptions may be raised if
+ * the call to _recvfrom_ fails:
+ * * Errno::ENETDOWN - the network is down
+ * * Errno::EFAULT - the internal buffer and from parameters on +socket+ are not
+ * part of the user address space, or the internal fromlen parameter is
+ * too small to accomodate the peer address
+ * * Errno::EINTR - the (blocking) call was cancelled by an internal call to
+ * the WinSock function WSACancelBlockingCall
+ * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
+ * the service provider is still processing a callback function
+ * * Errno::EINVAL - +socket+ has not been bound with a call to _bind_, or an
+ * unknown flag was specified, or MSG_OOB was specified for a socket with
+ * SO_OOBINLINE enabled, or (for byte stream-style sockets only) the internal
+ * len parameter on +socket+ was zero or negative
+ * * Errno::EISCONN - +socket+ is already connected. The call to _recvfrom_ is
+ * not permitted with a connected socket on a socket that is connetion
+ * oriented or connectionless.
+ * * Errno::ENETRESET - the connection has been broken due to the keep-alive
+ * activity detecting a failure while the operation was in progress.
+ * * Errno::EOPNOTSUPP - MSG_OOB was specified, but +socket+ is not stream-style
+ * such as type SOCK_STREAM. OOB data is not supported in the communication
+ * domain associated with +socket+, or +socket+ is unidirectional and
+ * supports only send operations
+ * * Errno::ESHUTDOWN - +socket+ has been shutdown. It is not possible to
+ * call _recvfrom_ on a socket after _shutdown_ has been invoked.
+ * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and a call to
+ * _recvfrom_ would block.
+ * * Errno::EMSGSIZE - the message was too large to fit into the specified buffer
+ * and was truncated.
+ * * Errno::ETIMEDOUT - the connection has been dropped, because of a network
+ * failure or because the system on the other end went down without
+ * notice
+ * * Errno::ECONNRESET - the virtual circuit was reset by the remote side
+ * executing a hard or abortive close. The application should close the
+ * socket; it is no longer usable. On a UDP-datagram socket this error
+ * indicates a previous send operation resulted in an ICMP Port Unreachable
+ * message.
+ */
static VALUE
sock_recvfrom(argc, argv, sock)
int argc;
@@ -1892,11 +2890,157 @@ sock_recvfrom(argc, argv, sock)
return s_recvfrom(sock, argc, argv, RECV_SOCKET);
}
+/*
+ * call-seq:
+ * socket.recvfrom_nonblock(maxlen) => [mesg, sender_sockaddr]
+ * socket.recvfrom_nonblock(maxlen, flags) => [mesg, sender_sockaddr]
+ *
+ * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
+ * O_NONBLOCK is set for the underlying file descriptor.
+ * _flags_ is zero or more of the +MSG_+ options.
+ * The first element of the results, _mesg_, is the data received.
+ * The second element, _sender_sockaddr_, contains protocol-specific information
+ * on the sender.
+ *
+ * When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns
+ * an empty string as data.
+ * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
+ *
+ * === Parameters
+ * * +maxlen+ - the number of bytes to receive from the socket
+ * * +flags+ - zero or more of the +MSG_+ options
+ *
+ * === Example
+ * # In one file, start this first
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ * sockaddr = Socket.sockaddr_in(2200, 'localhost')
+ * socket.bind(sockaddr)
+ * socket.listen(5)
+ * client, client_sockaddr = socket.accept
+ * begin
+ * pair = client.recvfrom_nonblock(20)
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK
+ * IO.select([client])
+ * retry
+ * end
+ * data = pair[0].chomp
+ * puts "I only received 20 bytes '#{data}'"
+ * sleep 1
+ * socket.close
+ *
+ * # In another file, start this second
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ * sockaddr = Socket.sockaddr_in(2200, 'localhost')
+ * socket.connect(sockaddr)
+ * socket.puts "Watch this get cut short!"
+ * socket.close
+ *
+ * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
+ * to _recvfrom_nonblock_ fails.
+ *
+ * Socket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
+ * including Errno::EAGAIN.
+ *
+ * === See
+ * * Socket#recvfrom
+ */
+static VALUE
+sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
+{
+ return s_recvfrom_nonblock(sock, argc, argv, RECV_SOCKET);
+}
+
+/*
+ * call-seq:
+ * socket.accept => [ socket, string ]
+ *
+ * Accepts an incoming connection returning an array containing a new
+ * Socket object and a string holding the +struct+ sockaddr information about
+ * the caller.
+ *
+ * === Example
+ * # In one script, start this first
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.bind( sockaddr )
+ * socket.listen( 5 )
+ * client, client_sockaddr = socket.accept
+ * puts "The client said, '#{client.readline.chomp}'"
+ * client.puts "Hello from script one!"
+ * socket.close
+ *
+ * # In another script, start this second
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.connect( sockaddr )
+ * socket.puts "Hello from script 2."
+ * puts "The server said, '#{socket.readline.chomp}'"
+ * socket.close
+ *
+ * === Unix-based Exceptions
+ * On unix-based based systems the following system exceptions may be raised if the
+ * call to _accept_ fails:
+ * * Errno::EAGAIN - O_NONBLOCK is set for the +socket+ file descriptor and no
+ * connections are parent to be accepted
+ * * Errno::EWOULDBLOCK - same as Errno::EAGAIN
+ * * Errno::EBADF - the +socket+ is not a valid file descriptor
+ * * Errno::ECONNABORTED - a connection has been aborted
+ * * Errno::EFAULT - the socket's internal address or address length parameter
+ * cannot be access or written
+ * * Errno::EINTR - the _accept_ method was interrupted by a signal that was
+ * caught before a valid connection arrived
+ * * Errno::EINVAL - the +socket+ is not accepting connections
+ * * Errno::EMFILE - OPEN_MAX file descriptors are currently open in the calling
+ * process
+ * * Errno::ENOBUFS - no buffer space is available
+ * * Errno::ENOMEM - there was insufficient memory available to complete the
+ * operation
+ * * Errno::ENOSR - there was insufficient STREAMS resources available to
+ * complete the operation
+ * * Errno::ENFILE - the maximum number of file descriptors in the system are
+ * already open
+ * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
+ * * Errno::EOPNOTSUPP - the socket type for the calling +socket+ does not
+ * support accept connections
+ * * Errno::EPROTO - a protocol error has occurred
+ *
+ * === Windows Exceptions
+ * On Windows systems the following system exceptions may be raised if
+ * the call to _accept_ fails:
+ * * Errno::ECONNRESET - an incoming connection was indicated, but was
+ * terminated by the remote peer prior to accepting the connection
+ * * Errno::EFAULT - the socket's internal address or address length parameter
+ * is too small or is not a valid part of the user space address
+ * * Errno::EINVAL - the _listen_ method was not invoked prior to calling _accept_
+ * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
+ * the service provider is still processing a callback function
+ * * Errno::EMFILE - the queue is not empty, upong etry to _accept_ and there are
+ * no socket descriptors available
+ * * Errno::ENETDOWN - the network is down
+ * * Errno::ENOBUFS - no buffer space is available
+ * * Errno::ENOTSOCK - +socket+ is not a socket
+ * * Errno::EOPNOTSUPP - +socket+ is not a type that supports connection-oriented
+ * service.
+ * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and no connections are
+ * present to be accepted
+ *
+ * === See
+ * * accept manual pages on unix-based systems
+ * * accept function in Microsoft's Winsock functions reference
+ */
static VALUE
sock_accept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock2;
char buf[1024];
socklen_t len = sizeof buf;
@@ -1907,11 +3051,112 @@ sock_accept(sock)
return rb_assoc_new(sock2, rb_str_new(buf, len));
}
+/*
+ * call-seq:
+ * socket.accept_nonblock => [client_socket, client_sockaddr]
+ *
+ * Accepts an incoming connection using accept(2) after
+ * O_NONBLOCK is set for the underlying file descriptor.
+ * It returns an array containg the accpeted socket
+ * for the incoming connection, _client_socket_,
+ * and a string that contains the +struct+ sockaddr information
+ * about the caller, _client_sockaddr_.
+ *
+ * === Example
+ * # In one script, start this first
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ * sockaddr = Socket.sockaddr_in(2200, 'localhost')
+ * socket.bind(sockaddr)
+ * socket.listen(5)
+ * begin
+ * client_socket, client_sockaddr = socket.accept_nonblock
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * IO.select([socket])
+ * retry
+ * end
+ * puts "The client said, '#{client_socket.readline.chomp}'"
+ * client_socket.puts "Hello from script one!"
+ * socket.close
+ *
+ * # In another script, start this second
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ * sockaddr = Socket.sockaddr_in(2200, 'localhost')
+ * socket.connect(sockaddr)
+ * socket.puts "Hello from script 2."
+ * puts "The server said, '#{socket.readline.chomp}'"
+ * socket.close
+ *
+ * Refer to Socket#accept for the exceptions that may be thrown if the call
+ * to _accept_nonblock_ fails.
+ *
+ * Socket#accept_nonblock may raise any error corresponding to accept(2) failure,
+ * including Errno::EAGAIN.
+ *
+ * === See
+ * * Socket#accept
+ */
+static VALUE
+sock_accept_nonblock(sock)
+ VALUE sock;
+{
+ rb_io_t *fptr;
+ VALUE sock2;
+ char buf[1024];
+ socklen_t len = sizeof buf;
+
+ GetOpenFile(sock, fptr);
+ sock2 = s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)buf, &len);
+ return rb_assoc_new(sock2, rb_str_new(buf, len));
+}
+
+/*
+ * call-seq:
+ * socket.sysaccept => [client_socket_fd, client_sockaddr]
+ *
+ * Accepts an incoming connection returnings an array containg the (integer)
+ * file descriptor for the incoming connection, _client_socket_fd_,
+ * and a string that contains the +struct+ sockaddr information
+ * about the caller, _client_sockaddr_.
+ *
+ * === Example
+ * # In one script, start this first
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.bind( sockaddr )
+ * socket.listen( 5 )
+ * client_fd, client_sockaddr = socket.sysaccept
+ * client_socket = Socket.for_fd( client_fd )
+ * puts "The client said, '#{client_socket.readline.chomp}'"
+ * client_socket.puts "Hello from script one!"
+ * socket.close
+ *
+ * # In another script, start this second
+ * require 'socket'
+ * include Socket::Constants
+ * socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
+ * sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
+ * socket.connect( sockaddr )
+ * socket.puts "Hello from script 2."
+ * puts "The server said, '#{socket.readline.chomp}'"
+ * socket.close
+ *
+ * Refer to Socket#accept for the exceptions that may be thrown if the call
+ * to _sysaccept_ fails.
+ *
+ * === See
+ * * Socket#accept
+ */
static VALUE
sock_sysaccept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock2;
char buf[1024];
socklen_t len = sizeof buf;
@@ -1982,20 +3227,134 @@ make_addrinfo(res0)
return base;
}
+/* Returns a String containing the binary value of a struct sockaddr. */
VALUE
sock_sockaddr(addr, len)
struct sockaddr *addr;
size_t len;
{
- return rb_str_new((char*)addr, len);
+ char *ptr;
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
+ len = sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
+ len = sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
+ break;
+#endif
+ default:
+ rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family);
+ break;
+ }
+ return rb_str_new(ptr, len);
}
+/*
+ * Document-class: IPSocket
+ *
+ * IPSocket is the parent of TCPSocket and UDPSocket and implements
+ * functionality common to them.
+ *
+ * A number of APIs in IPSocket, Socket, and their descendants return an
+ * address as an array. The members of that array are:
+ * - address family: A string like "AF_INET" or "AF_INET6" if it is one of the
+ * commonly used families, the string "unknown:#" (where `#' is the address
+ * family number) if it is not one of the common ones. The strings map to
+ * the Socket::AF_* constants.
+ * - port: The port number.
+ * - name: Either the canonical name from looking the address up in the DNS, or
+ * the address in presentation format
+ * - address: The address in presentation format (a dotted decimal string for
+ * IPv4, a hex string for IPv6).
+ *
+ * The address and port can be used directly to create sockets and to bind or
+ * connect them to the address.
+ */
+
+/*
+ * Document-class: Socket
+ *
+ * Socket contains a number of generally useful singleton methods and
+ * constants, as well as offering low-level interfaces that can be used to
+ * develop socket applications using protocols other than TCP, UDP, and UNIX
+ * domain sockets.
+ */
+
+/*
+ * Document-method: gethostbyname
+ * call-seq: Socket.gethostbyname(host) => hostent
+ *
+ * Resolve +host+ and return name and address information for it, similarly to
+ * gethostbyname(3). +host+ can be a domain name or the presentation format of
+ * an address.
+ *
+ * Returns an array of information similar to that found in a +struct hostent+:
+ * - cannonical name: the cannonical name for host in the DNS, or a
+ * string representing the address
+ * - aliases: an array of aliases for the canonical name, there may be no aliases
+ * - address family: usually one of Socket::AF_INET or Socket::AF_INET6
+ * - address: a string, the binary value of the +struct sockaddr+ for this name, in
+ * the indicated address family
+ * - ...: if there are multiple addresses for this host, a series of
+ * strings/+struct sockaddr+s may follow, not all necessarily in the same
+ * address family. Note that the fact that they may not be all in the same
+ * address family is a departure from the behaviour of gethostbyname(3).
+ *
+ * Note: I believe that the fact that the multiple addresses returned are not
+ * necessarily in the same address family may be a bug, since if this function
+ * actually called gethostbyname(3), ALL the addresses returned in the trailing
+ * address list (h_addr_list from struct hostent) would be of the same address
+ * family! Examples from my system, OS X 10.3:
+ *
+ * ["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]
+ * and
+ * ["ensemble.local", [], 30, "\376\200\000\004\000\000\000\000\002\003\223\377\376\255\010\214", "\300\250{\232" ]
+ *
+ * Similar information can be returned by Socket.getaddrinfo if called as:
+ *
+ * Socket.getaddrinfo(+host+, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
+ *
+ * == Examples
+ *
+ * Socket.gethostbyname "example.com"
+ * => ["example.com", [], 2, "\300\000\"\246"]
+ *
+ * This name has no DNS aliases, and a single IPv4 address.
+ *
+ * Socket.gethostbyname "smtp.telus.net"
+ * => ["smtp.svc.telus.net", ["smtp.telus.net"], 2, "\307\271\334\371"]
+ *
+ * This name is an an alias so the canonical name is returned, as well as the
+ * alias and a single IPv4 address.
+ *
+ * Socket.gethostbyname "localhost"
+ * => ["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]
+ *
+ * This machine has no aliases, returns an IPv6 address, and has an additional IPv4 address.
+ *
+ * +host+ can also be an IP address in presentation format, in which case a
+ * reverse lookup is done on the address:
+ *
+ * Socket.gethostbyname("127.0.0.1")
+ * => ["localhost", [], 2, "\177\000\000\001"]
+ *
+ * Socket.gethostbyname("192.0.34.166")
+ * => ["www.example.com", [], 2, "\300\000\"\246"]
+ *
+ *
+ * == See
+ * See: Socket.getaddrinfo
+ */
static VALUE
sock_s_gethostbyname(obj, host)
VALUE obj, host;
{
rb_secure(3);
- return make_hostent(sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
+ return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
}
static VALUE
@@ -2020,7 +3379,7 @@ sock_s_gethostbyaddr(argc, argv)
t = AF_INET6;
}
#endif
- h = gethostbyaddr((char*)RSTRING(addr)->ptr, RSTRING(addr)->len, t);
+ h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, t);
if (h == NULL) {
#ifdef HAVE_HSTRERROR
extern int h_errno;
@@ -2050,22 +3409,33 @@ sock_s_gethostbyaddr(argc, argv)
return ary;
}
+/*
+ * Document-method: getservbyname
+ * call-seq: Socket.getservbyname(name, proto="tcp") => port
+ *
+ * +name+ is a service name ("ftp", "telnet", ...) and proto is a protocol name
+ * ("udp", "tcp", ...). '/etc/services' (or your system's equivalent) is
+ * searched for a service for +name+ and +proto+, and the port number is
+ * returned.
+ *
+ * Note that unlike Socket.getaddrinfo, +proto+ may not be specified using the
+ * Socket::SOCK_* constants, a string must must be used.
+ */
static VALUE
sock_s_getservbyaname(argc, argv)
int argc;
VALUE *argv;
{
- VALUE service, protocol;
- char *proto;
+ VALUE service, proto;
struct servent *sp;
int port;
- rb_scan_args(argc, argv, "11", &service, &protocol);
- if (NIL_P(protocol)) proto = "tcp";
- else proto = StringValuePtr(protocol);
-
+ rb_scan_args(argc, argv, "11", &service, &proto);
+ if (NIL_P(proto)) proto = rb_str_new2("tcp");
StringValue(service);
- sp = getservbyname((char*)RSTRING(service)->ptr, proto);
+ StringValue(proto);
+
+ sp = getservbyname(StringValueCStr(service), StringValueCStr(proto));
if (sp) {
port = ntohs(sp->s_port);
}
@@ -2075,12 +3445,126 @@ sock_s_getservbyaname(argc, argv)
port = strtoul(s, &end, 0);
if (*end != '\0') {
- rb_raise(rb_eSocket, "no such service %s/%s", s, proto);
+ rb_raise(rb_eSocket, "no such service %s/%s", s, RSTRING(proto)->ptr);
}
}
return INT2FIX(port);
}
+/*
+Documentation should explain the following:
+
+ $ pp Socket.getaddrinfo("", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
+ [["AF_INET", 1, "0.0.0.0", "0.0.0.0", 2, 1, 6]]
+
+ $ pp Socket.getaddrinfo(nil, 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
+ [["AF_INET6", 1, "::", "::", 30, 1, 6],
+ ["AF_INET", 1, "0.0.0.0", "0.0.0.0", 2, 1, 6]]
+
+ $ pp Socket.getaddrinfo("localhost", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
+ [["AF_INET6", 1, "localhost", "::1", 30, 1, 6],
+ ["AF_INET", 1, "localhost", "127.0.0.1", 2, 1, 6]]
+
+ $ pp Socket.getaddrinfo("ensemble.local.", 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
+ [["AF_INET", 1, "localhost", "192.168.123.154", 2, 1, 6]]
+
+Does it?
+
+API suggestion: this method has too many arguments, it would be backwards compatible and easier
+to understand if limit args were accepted as :family=>..., :flags=>...
+*/
+
+/*
+ * Document-method: getaddrinfo
+ * call-seq: Socket.getaddrinfo(host, service, family=nil, socktype=nil, protocol=nil, flags=nil) => addrinfo
+ *
+ * Return address information for +host+ and +port+. The remaining arguments
+ * are hints that limit the address information returned.
+ *
+ * This method corresponds closely to the POSIX.1g getaddrinfo() definition.
+ *
+ * === Parameters
+ * - +host+ is a host name or an address string (dotted decimal for IPv4, or a hex string
+ * for IPv6) for which to return information. A nil is also allowed, its meaning
+ * depends on +flags+, see below.
+ * - +service+ is a service name ("http", "ssh", ...), or
+ * a port number (80, 22, ...), see Socket.getservbyname for more
+ * information. A nil is also allowed, meaning zero.
+ * - +family+ limits the output to a specific address family, one of the
+ * Socket::AF_* constants. Socket::AF_INET (IPv4) and Socket::AF_INET6 (IPv6)
+ * are the most commonly used families. You will usually pass either nil or
+ * Socket::AF_UNSPEC, allowing the IPv6 information to be returned first if
+ * +host+ is reachable via IPv6, and IPv4 information otherwise. The two
+ * strings "AF_INET" or "AF_INET6" are also allowed, they are converted to
+ * their respective Socket::AF_* constants.
+ * - +socktype+ limits the output to a specific type of socket, one of the
+ * Socket::SOCK_* constants. Socket::SOCK_STREAM (for TCP) and
+ * Socket::SOCK_DGRAM (for UDP) are the most commonly used socket types. If
+ * nil, then information for all types of sockets supported by +service+ will
+ * be returned. You will usually know what type of socket you intend to
+ * create, and should pass that socket type in.
+ * - +protocol+ limits the output to a specific protocol numpber, one of the
+ * Socket::IPPROTO_* constants. It is usually implied by the socket type
+ * (Socket::SOCK_STREAM => Socket::IPPROTO_TCP, ...), if you pass other than
+ * nil you already know what this is for.
+ * - +flags+ is one of the Socket::AI_* constants. They mean:
+ * - Socket::AI_PASSIVE: when set, if +host+ is nil the 'any' address will be
+ * returned, Socket::INADDR_ANY or 0 for IPv4, "0::0" or "::" for IPv6. This
+ * address is suitable for use by servers that will bind their socket and do
+ * a passive listen, thus the name of the flag. Otherwise the local or
+ * loopback address will be returned, this is "127.0.0.1" for IPv4 and "::1'
+ * for IPv6.
+ * - ...
+ *
+ *
+ * === Returns
+ *
+ * Returns an array of arrays, where each subarray contains:
+ * - address family, a string like "AF_INET" or "AF_INET6"
+ * - port number, the port number for +service+
+ * - host name, either a canonical name for +host+, or it's address in presentation
+ * format if the address could not be looked up.
+ * - host IP, the address of +host+ in presentation format
+ * - address family, as a numeric value (one of the Socket::AF_* constants).
+ * - socket type, as a numeric value (one of the Socket::SOCK_* constants).
+ * - protocol number, as a numeric value (one of the Socket::IPPROTO_* constants).
+ *
+ * The first four values are identical to what is commonly returned as an
+ * address array, see IPSocket for more information.
+ *
+ * === Examples
+ *
+ * Not all input combinations are valid, and while there are many combinations,
+ * only a few cases are common.
+ *
+ * A typical client will call getaddrinfo with the +host+ and +service+ it
+ * wants to connect to. It knows that it will attempt to connect with either
+ * TCP or UDP, and specifies +socktype+ accordingly. It loops through all
+ * returned addresses, and try to connect to them in turn:
+ *
+ * addrinfo = Socket::getaddrinfo('www.example.com', 'www', nil, Socket::SOCK_STREAM)
+ * addrinfo.each do |af, port, name, addr|
+ * begin
+ * sock = TCPSocket.new(addr, port)
+ * # ...
+ * exit 1
+ * rescue
+ * end
+ * end
+ *
+ * With UDP you don't know if connect suceeded, but if communication fails,
+ * the next address can be tried.
+ *
+ * A typical server will call getaddrinfo with a +host+ of nil, the +service+
+ * it listens to, and a +flags+ of Socket::AI_PASSIVE. It will listen for
+ * connections on the first returned address:
+ * addrinfo = Socket::getaddrinfo(nil, 'www', nil, Socket::SOCK_STREAM, nil, Socket::AI_PASSIVE)
+ * af, port, name, addr = addrinfo.first
+ * sock = TCPServer(addr, port)
+ * while( client = s.accept )
+ * # ...
+ * end
+ */
static VALUE
sock_s_getaddrinfo(argc, argv)
int argc;
@@ -2106,7 +3590,7 @@ sock_s_getaddrinfo(argc, argv)
pptr = NULL;
}
else if (FIXNUM_P(port)) {
- snprintf(pbuf, sizeof(pbuf), "%d", FIX2INT(port));
+ snprintf(pbuf, sizeof(pbuf), "%ld", FIX2LONG(port));
pptr = pbuf;
}
else {
@@ -2157,7 +3641,7 @@ sock_s_getnameinfo(argc, argv)
int argc;
VALUE *argv;
{
- VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags;
+ VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp;
char *hptr, *pptr;
char hbuf[1024], pbuf[1024];
int fl;
@@ -2174,7 +3658,9 @@ sock_s_getnameinfo(argc, argv)
if (!NIL_P(flags)) {
fl = NUM2INT(flags);
}
- if (TYPE(sa) == T_STRING) {
+ tmp = rb_check_string_type(sa);
+ if (!NIL_P(tmp)) {
+ sa = tmp;
if (sizeof(ss) < RSTRING(sa)->len) {
rb_raise(rb_eTypeError, "sockaddr length too big");
}
@@ -2183,8 +3669,11 @@ sock_s_getnameinfo(argc, argv)
rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
}
sap = (struct sockaddr*)&ss;
+ goto call_nameinfo;
}
- else if (TYPE(sa) == T_ARRAY) {
+ tmp = rb_check_array_type(sa);
+ if (!NIL_P(tmp)) {
+ sa = tmp;
MEMZERO(&hints, struct addrinfo, 1);
if (RARRAY(sa)->len == 3) {
af = RARRAY(sa)->ptr[0];
@@ -2203,7 +3692,9 @@ sock_s_getnameinfo(argc, argv)
* 4th element holds numeric form, don't resolve.
* see ipaddr().
*/
+#ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
hints.ai_flags |= AI_NUMERICHOST;
+#endif
}
}
else {
@@ -2225,7 +3716,7 @@ sock_s_getnameinfo(argc, argv)
pptr = NULL;
}
else if (FIXNUM_P(port)) {
- snprintf(pbuf, sizeof(pbuf), "%d", NUM2INT(port));
+ snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
pptr = pbuf;
}
else {
@@ -2259,6 +3750,7 @@ sock_s_getnameinfo(argc, argv)
rb_raise(rb_eTypeError, "expecting String or Array");
}
+ call_nameinfo:
error = getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
pbuf, sizeof(pbuf), fl);
if (error) goto error_exit_name;
@@ -2310,6 +3802,17 @@ sock_s_unpack_sockaddr_in(self, addr)
VALUE host;
sockaddr = (struct sockaddr_in*)StringValuePtr(addr);
+ if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
+#ifdef INET6
+ && ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
+#endif
+ ) {
+#ifdef INET6
+ rb_raise(rb_eArgError, "not an AF_INET/AF_INET6 sockaddr");
+#else
+ rb_raise(rb_eArgError, "not an AF_INET sockaddr");
+#endif
+ }
host = make_ipaddr((struct sockaddr*)sockaddr);
OBJ_INFECT(host, addr);
return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
@@ -2321,11 +3824,17 @@ sock_s_pack_sockaddr_un(self, path)
VALUE self, path;
{
struct sockaddr_un sockaddr;
+ char *sun_path;
VALUE addr;
MEMZERO(&sockaddr, struct sockaddr_un, 1);
sockaddr.sun_family = AF_UNIX;
- strncpy(sockaddr.sun_path, StringValuePtr(path), sizeof(sockaddr.sun_path)-1);
+ sun_path = StringValueCStr(path);
+ if (sizeof(sockaddr.sun_path) <= strlen(sun_path)) {
+ rb_raise(rb_eArgError, "too long unix socket path (max: %dbytes)",
+ (int)sizeof(sockaddr.sun_path)-1);
+ }
+ strncpy(sockaddr.sun_path, sun_path, sizeof(sockaddr.sun_path)-1);
addr = rb_str_new((char*)&sockaddr, sizeof(sockaddr));
OBJ_INFECT(addr, path);
@@ -2337,15 +3846,24 @@ sock_s_unpack_sockaddr_un(self, addr)
VALUE self, addr;
{
struct sockaddr_un * sockaddr;
+ char *sun_path;
VALUE path;
sockaddr = (struct sockaddr_un*)StringValuePtr(addr);
- if (RSTRING(addr)->len != sizeof(struct sockaddr_un)) {
- rb_raise(rb_eTypeError, "sockaddr_un size differs - %ld required; %d given",
+ if (((struct sockaddr *)sockaddr)->sa_family != AF_UNIX) {
+ rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
+ }
+ if (sizeof(struct sockaddr_un) < RSTRING(addr)->len) {
+ rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
RSTRING(addr)->len, sizeof(struct sockaddr_un));
}
- /* xxx: should I check against sun_path size? */
- path = rb_str_new2(sockaddr->sun_path);
+ sun_path = unixpath(sockaddr, RSTRING(addr)->len);
+ if (sizeof(struct sockaddr_un) == RSTRING(addr)->len &&
+ sun_path == sockaddr->sun_path &&
+ sun_path + strlen(sun_path) == RSTRING(addr)->ptr + RSTRING(addr)->len) {
+ rb_raise(rb_eArgError, "sockaddr_un.sun_path not NUL terminated");
+ }
+ path = rb_str_new2(sun_path);
OBJ_INFECT(path, addr);
return path;
}
@@ -2362,6 +3880,31 @@ sock_define_const(name, value)
rb_define_const(mConst, name, INT2FIX(value));
}
+/*
+ * Class +Socket+ provides access to the underlying operating system
+ * socket implementations. It can be used to provide more operating system
+ * specific functionality than the protocol-specific socket classes but at the
+ * expense of greater complexity. In particular, the class handles addresses
+ * using +struct sockaddr+ structures packed into Ruby strings, which can be
+ * a joy to manipulate.
+ *
+ * === Exception Handling
+ * Ruby's implementation of +Socket+ causes an exception to be raised
+ * based on the error generated by the system dependent implementation.
+ * This is why the methods are documented in a way that isolate
+ * Unix-based system exceptions from Windows based exceptions. If more
+ * information on particular exception is needed please refer to the
+ * Unix manual pages or the Windows WinSock reference.
+ *
+ *
+ * === Documentation by
+ * * Zach Dennis
+ * * Sam Roberts
+ * * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
+ *
+ * Much material in this documentation is taken with permission from
+ * <em>Programming Ruby</em> from The Pragmatic Bookshelf.
+ */
void
Init_socket()
{
@@ -2385,6 +3928,7 @@ Init_socket()
rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
rb_define_method(rb_cBasicSocket, "send", bsock_send, -1);
rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
+ rb_define_method(rb_cBasicSocket, "recv_nonblock", bsock_recv_nonblock, -1);
rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
rb_define_global_const("IPsocket", rb_cIPSocket);
@@ -2410,6 +3954,7 @@ Init_socket()
rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
rb_define_global_const("TCPserver", rb_cTCPServer);
rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
+ rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, 0);
rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
rb_define_method(rb_cTCPServer, "listen", sock_listen, 1);
@@ -2420,6 +3965,7 @@ Init_socket()
rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
+ rb_define_method(rb_cUDPSocket, "recvfrom_nonblock", udp_recvfrom_nonblock, -1);
#ifdef HAVE_SYS_UN_H
rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket);
@@ -2438,6 +3984,7 @@ Init_socket()
rb_define_global_const("UNIXserver", rb_cUNIXServer);
rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1);
rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
+ rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, 0);
rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
rb_define_method(rb_cUNIXServer, "listen", sock_listen, 1);
#endif
@@ -2446,12 +3993,15 @@ Init_socket()
rb_define_method(rb_cSocket, "initialize", sock_initialize, 3);
rb_define_method(rb_cSocket, "connect", sock_connect, 1);
+ rb_define_method(rb_cSocket, "connect_nonblock", sock_connect_nonblock, 1);
rb_define_method(rb_cSocket, "bind", sock_bind, 1);
rb_define_method(rb_cSocket, "listen", sock_listen, 1);
rb_define_method(rb_cSocket, "accept", sock_accept, 0);
+ rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
+ rb_define_method(rb_cSocket, "recvfrom_nonblock", sock_recvfrom_nonblock, -1);
rb_define_singleton_method(rb_cSocket, "socketpair", sock_s_socketpair, 3);
rb_define_singleton_method(rb_cSocket, "pair", sock_s_socketpair, 3);
@@ -2511,12 +4061,201 @@ Init_socket()
sock_define_const("AF_UNSPEC", AF_UNSPEC);
sock_define_const("PF_UNSPEC", PF_UNSPEC);
#endif
-#ifdef AF_INET6
+#ifdef INET6
sock_define_const("AF_INET6", AF_INET6);
#endif
-#ifdef PF_INET6
+#ifdef INET6
sock_define_const("PF_INET6", PF_INET6);
#endif
+#ifdef AF_LOCAL
+ sock_define_const("AF_LOCAL", AF_LOCAL);
+#endif
+#ifdef PF_LOCAL
+ sock_define_const("PF_LOCAL", PF_LOCAL);
+#endif
+#ifdef AF_IMPLINK
+ sock_define_const("AF_IMPLINK", AF_IMPLINK);
+#endif
+#ifdef PF_IMPLINK
+ sock_define_const("PF_IMPLINK", PF_IMPLINK);
+#endif
+#ifdef AF_PUP
+ sock_define_const("AF_PUP", AF_PUP);
+#endif
+#ifdef PF_PUP
+ sock_define_const("PF_PUP", PF_PUP);
+#endif
+#ifdef AF_CHAOS
+ sock_define_const("AF_CHAOS", AF_CHAOS);
+#endif
+#ifdef PF_CHAOS
+ sock_define_const("PF_CHAOS", PF_CHAOS);
+#endif
+#ifdef AF_NS
+ sock_define_const("AF_NS", AF_NS);
+#endif
+#ifdef PF_NS
+ sock_define_const("PF_NS", PF_NS);
+#endif
+#ifdef AF_ISO
+ sock_define_const("AF_ISO", AF_ISO);
+#endif
+#ifdef PF_ISO
+ sock_define_const("PF_ISO", PF_ISO);
+#endif
+#ifdef AF_OSI
+ sock_define_const("AF_OSI", AF_OSI);
+#endif
+#ifdef PF_OSI
+ sock_define_const("PF_OSI", PF_OSI);
+#endif
+#ifdef AF_ECMA
+ sock_define_const("AF_ECMA", AF_ECMA);
+#endif
+#ifdef PF_ECMA
+ sock_define_const("PF_ECMA", PF_ECMA);
+#endif
+#ifdef AF_DATAKIT
+ sock_define_const("AF_DATAKIT", AF_DATAKIT);
+#endif
+#ifdef PF_DATAKIT
+ sock_define_const("PF_DATAKIT", PF_DATAKIT);
+#endif
+#ifdef AF_CCITT
+ sock_define_const("AF_CCITT", AF_CCITT);
+#endif
+#ifdef PF_CCITT
+ sock_define_const("PF_CCITT", PF_CCITT);
+#endif
+#ifdef AF_SNA
+ sock_define_const("AF_SNA", AF_SNA);
+#endif
+#ifdef PF_SNA
+ sock_define_const("PF_SNA", PF_SNA);
+#endif
+#ifdef AF_DEC
+ sock_define_const("AF_DEC", AF_DEC);
+#endif
+#ifdef PF_DEC
+ sock_define_const("PF_DEC", PF_DEC);
+#endif
+#ifdef AF_DLI
+ sock_define_const("AF_DLI", AF_DLI);
+#endif
+#ifdef PF_DLI
+ sock_define_const("PF_DLI", PF_DLI);
+#endif
+#ifdef AF_LAT
+ sock_define_const("AF_LAT", AF_LAT);
+#endif
+#ifdef PF_LAT
+ sock_define_const("PF_LAT", PF_LAT);
+#endif
+#ifdef AF_HYLINK
+ sock_define_const("AF_HYLINK", AF_HYLINK);
+#endif
+#ifdef PF_HYLINK
+ sock_define_const("PF_HYLINK", PF_HYLINK);
+#endif
+#ifdef AF_ROUTE
+ sock_define_const("AF_ROUTE", AF_ROUTE);
+#endif
+#ifdef PF_ROUTE
+ sock_define_const("PF_ROUTE", PF_ROUTE);
+#endif
+#ifdef AF_LINK
+ sock_define_const("AF_LINK", AF_LINK);
+#endif
+#ifdef PF_LINK
+ sock_define_const("PF_LINK", PF_LINK);
+#endif
+#ifdef AF_COIP
+ sock_define_const("AF_COIP", AF_COIP);
+#endif
+#ifdef PF_COIP
+ sock_define_const("PF_COIP", PF_COIP);
+#endif
+#ifdef AF_CNT
+ sock_define_const("AF_CNT", AF_CNT);
+#endif
+#ifdef PF_CNT
+ sock_define_const("PF_CNT", PF_CNT);
+#endif
+#ifdef AF_SIP
+ sock_define_const("AF_SIP", AF_SIP);
+#endif
+#ifdef PF_SIP
+ sock_define_const("PF_SIP", PF_SIP);
+#endif
+#ifdef AF_NDRV
+ sock_define_const("AF_NDRV", AF_NDRV);
+#endif
+#ifdef PF_NDRV
+ sock_define_const("PF_NDRV", PF_NDRV);
+#endif
+#ifdef AF_ISDN
+ sock_define_const("AF_ISDN", AF_ISDN);
+#endif
+#ifdef PF_ISDN
+ sock_define_const("PF_ISDN", PF_ISDN);
+#endif
+#ifdef AF_NATM
+ sock_define_const("AF_NATM", AF_NATM);
+#endif
+#ifdef PF_NATM
+ sock_define_const("PF_NATM", PF_NATM);
+#endif
+#ifdef AF_SYSTEM
+ sock_define_const("AF_SYSTEM", AF_SYSTEM);
+#endif
+#ifdef PF_SYSTEM
+ sock_define_const("PF_SYSTEM", PF_SYSTEM);
+#endif
+#ifdef AF_NETBIOS
+ sock_define_const("AF_NETBIOS", AF_NETBIOS);
+#endif
+#ifdef PF_NETBIOS
+ sock_define_const("PF_NETBIOS", PF_NETBIOS);
+#endif
+#ifdef AF_PPP
+ sock_define_const("AF_PPP", AF_PPP);
+#endif
+#ifdef PF_PPP
+ sock_define_const("PF_PPP", PF_PPP);
+#endif
+#ifdef AF_ATM
+ sock_define_const("AF_ATM", AF_ATM);
+#endif
+#ifdef PF_ATM
+ sock_define_const("PF_ATM", PF_ATM);
+#endif
+#ifdef AF_NETGRAPH
+ sock_define_const("AF_NETGRAPH", AF_NETGRAPH);
+#endif
+#ifdef PF_NETGRAPH
+ sock_define_const("PF_NETGRAPH", PF_NETGRAPH);
+#endif
+#ifdef AF_MAX
+ sock_define_const("AF_MAX", AF_MAX);
+#endif
+#ifdef PF_MAX
+ sock_define_const("PF_MAX", PF_MAX);
+#endif
+#ifdef AF_E164
+ sock_define_const("AF_E164", AF_E164);
+#endif
+#ifdef PF_XTP
+ sock_define_const("PF_XTP", PF_XTP);
+#endif
+#ifdef PF_RTIP
+ sock_define_const("PF_RTIP", PF_RTIP);
+#endif
+#ifdef PF_PIP
+ sock_define_const("PF_PIP", PF_PIP);
+#endif
+#ifdef PF_KEY
+ sock_define_const("PF_KEY", PF_KEY);
+#endif
sock_define_const("MSG_OOB", MSG_OOB);
#ifdef MSG_PEEK
@@ -2525,6 +4264,42 @@ Init_socket()
#ifdef MSG_DONTROUTE
sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE);
#endif
+#ifdef MSG_EOR
+ sock_define_const("MSG_EOR", MSG_EOR);
+#endif
+#ifdef MSG_TRUNC
+ sock_define_const("MSG_TRUNC", MSG_TRUNC);
+#endif
+#ifdef MSG_CTRUNC
+ sock_define_const("MSG_CTRUNC", MSG_CTRUNC);
+#endif
+#ifdef MSG_WAITALL
+ sock_define_const("MSG_WAITALL", MSG_WAITALL);
+#endif
+#ifdef MSG_DONTWAIT
+ sock_define_const("MSG_DONTWAIT", MSG_DONTWAIT);
+#endif
+#ifdef MSG_EOF
+ sock_define_const("MSG_EOF", MSG_EOF);
+#endif
+#ifdef MSG_FLUSH
+ sock_define_const("MSG_FLUSH", MSG_FLUSH);
+#endif
+#ifdef MSG_HOLD
+ sock_define_const("MSG_HOLD", MSG_HOLD);
+#endif
+#ifdef MSG_SEND
+ sock_define_const("MSG_SEND", MSG_SEND);
+#endif
+#ifdef MSG_HAVEMORE
+ sock_define_const("MSG_HAVEMORE", MSG_HAVEMORE);
+#endif
+#ifdef MSG_RCVMORE
+ sock_define_const("MSG_RCVMORE", MSG_RCVMORE);
+#endif
+#ifdef MSG_COMPAT
+ sock_define_const("MSG_COMPAT", MSG_COMPAT);
+#endif
sock_define_const("SOL_SOCKET", SOL_SOCKET);
#ifdef SOL_IP
@@ -2709,6 +4484,9 @@ Init_socket()
sock_define_const("SO_DEBUG", SO_DEBUG);
#endif
sock_define_const("SO_REUSEADDR", SO_REUSEADDR);
+#ifdef SO_REUSEPORT
+ sock_define_const("SO_REUSEPORT", SO_REUSEPORT);
+#endif
#ifdef SO_TYPE
sock_define_const("SO_TYPE", SO_TYPE);
#endif
@@ -2760,6 +4538,33 @@ Init_socket()
#ifdef SO_SNDTIMEO
sock_define_const("SO_SNDTIMEO", SO_SNDTIMEO);
#endif
+#ifdef SO_ACCEPTCONN
+ sock_define_const("SO_ACCEPTCONN", SO_ACCEPTCONN);
+#endif
+#ifdef SO_USELOOPBACK
+ sock_define_const("SO_USELOOPBACK", SO_USELOOPBACK);
+#endif
+#ifdef SO_ACCEPTFILTER
+ sock_define_const("SO_ACCEPTFILTER", SO_ACCEPTFILTER);
+#endif
+#ifdef SO_DONTTRUNC
+ sock_define_const("SO_DONTTRUNC", SO_DONTTRUNC);
+#endif
+#ifdef SO_WANTMORE
+ sock_define_const("SO_WANTMORE", SO_WANTMORE);
+#endif
+#ifdef SO_WANTOOBFLAG
+ sock_define_const("SO_WANTOOBFLAG", SO_WANTOOBFLAG);
+#endif
+#ifdef SO_NREAD
+ sock_define_const("SO_NREAD", SO_NREAD);
+#endif
+#ifdef SO_NKE
+ sock_define_const("SO_NKE", SO_NKE);
+#endif
+#ifdef SO_NOSIGPIPE
+ sock_define_const("SO_NOSIGPIPE", SO_NOSIGPIPE);
+#endif
#ifdef SO_SECURITY_AUTHENTICATION
sock_define_const("SO_SECURITY_AUTHENTICATION", SO_SECURITY_AUTHENTICATION);
diff --git a/ext/stringio/MANIFEST b/ext/stringio/MANIFEST
deleted file mode 100644
index 4f3a7dc6d0..0000000000
--- a/ext/stringio/MANIFEST
+++ /dev/null
@@ -1,4 +0,0 @@
-MANIFEST
-README
-stringio.c
-depend
diff --git a/ext/stringio/extconf.rb b/ext/stringio/extconf.rb
new file mode 100644
index 0000000000..8fc84b3735
--- /dev/null
+++ b/ext/stringio/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('stringio')
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index 725b5be192..71b7b69f71 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -14,9 +14,14 @@
#include "ruby.h"
#include "rubyio.h"
+#include "re.h"
+#if defined(HAVE_FCNTL_H) || defined(_WIN32)
+#include <fcntl.h>
+#elif defined(HAVE_SYS_FCNTL_H)
+#include <sys/fcntl.h>
+#endif
-#define STRIO_APPEND 4
-#define STRIO_EOF 8
+#define STRIO_EOF FMODE_SYNC
struct StringIO {
VALUE string;
@@ -74,7 +79,7 @@ check_strio(self)
{
Check_Type(self, T_DATA);
if (!IS_STRIO(self)) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected String::IO)",
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected StringIO)",
rb_class2name(CLASS_OF(self)));
}
return DATA_PTR(self);
@@ -94,9 +99,9 @@ get_strio(self)
#define StringIO(obj) get_strio(obj)
-#define CLOSED(ptr) NIL_P((ptr)->string)
-#define READABLE(ptr) (!CLOSED(ptr) && ((ptr)->flags & FMODE_READABLE))
-#define WRITABLE(ptr) (!CLOSED(ptr) && ((ptr)->flags & FMODE_WRITABLE))
+#define CLOSED(ptr) (!((ptr)->flags & FMODE_READWRITE))
+#define READABLE(ptr) ((ptr)->flags & FMODE_READABLE)
+#define WRITABLE(ptr) ((ptr)->flags & FMODE_WRITABLE)
static struct StringIO*
readable(ptr)
@@ -132,6 +137,7 @@ check_modifiable(ptr)
static VALUE strio_s_allocate _((VALUE));
static VALUE strio_s_open _((int, VALUE *, VALUE));
+static void strio_init _((int, VALUE *, struct StringIO *));
static VALUE strio_initialize _((int, VALUE *, VALUE));
static VALUE strio_finalize _((VALUE));
static VALUE strio_self _((VALUE));
@@ -157,6 +163,7 @@ static VALUE strio_rewind _((VALUE));
static VALUE strio_seek _((int, VALUE *, VALUE));
static VALUE strio_get_sync _((VALUE));
static VALUE strio_each_byte _((VALUE));
+static VALUE strio_each_char _((VALUE));
static VALUE strio_getc _((VALUE));
static VALUE strio_ungetc _((VALUE, VALUE));
static VALUE strio_readchar _((VALUE));
@@ -183,6 +190,13 @@ strio_s_allocate(klass)
return Data_Wrap_Struct(klass, strio_mark, strio_free, 0);
}
+/*
+ * call-seq: StringIO.open(string=""[, mode]) {|strio| ...}
+ *
+ * Equivalent to StringIO.new except that when it is called with a block, it
+ * yields with the new instance and closes it, and returns the result which
+ * returned from the block.
+ */
static VALUE
strio_s_open(argc, argv, klass)
int argc;
@@ -194,6 +208,11 @@ strio_s_open(argc, argv, klass)
return rb_ensure(rb_yield, obj, strio_finalize, obj);
}
+/*
+ * call-seq: StringIO.new(string=""[, mode])
+ *
+ * Creates new StringIO instance from with _string_ and _mode_.
+ */
static VALUE
strio_initialize(argc, argv, self)
int argc;
@@ -201,30 +220,43 @@ strio_initialize(argc, argv, self)
VALUE self;
{
struct StringIO *ptr = check_strio(self);
- VALUE string, mode;
- const char* m;
if (!ptr) {
DATA_PTR(self) = ptr = strio_alloc();
}
rb_call_super(0, 0);
+ strio_init(argc, argv, ptr);
+ return self;
+}
+
+static void
+strio_init(argc, argv, ptr)
+ int argc;
+ VALUE *argv;
+ struct StringIO *ptr;
+{
+ VALUE string, mode;
+ int trunc = Qfalse;
+
switch (rb_scan_args(argc, argv, "02", &string, &mode)) {
case 2:
- StringValue(mode);
+ if (FIXNUM_P(mode)) {
+ int flags = FIX2INT(mode);
+ ptr->flags = rb_io_modenum_flags(flags);
+ trunc = flags & O_TRUNC;
+ }
+ else {
+ const char *m = StringValueCStr(mode);
+ ptr->flags = rb_io_mode_flags(m);
+ trunc = *m == 'w';
+ }
StringValue(string);
- if (!(m = RSTRING(mode)->ptr)) m = "";
- ptr->flags = rb_io_mode_flags(m);
if ((ptr->flags & FMODE_WRITABLE) && OBJ_FROZEN(string)) {
errno = EACCES;
rb_sys_fail(0);
}
- switch (*m) {
- case 'a':
- ptr->flags |= STRIO_APPEND;
- break;
- case 'w':
+ if (trunc) {
rb_str_resize(string, 0);
- break;
}
break;
case 1:
@@ -237,7 +269,6 @@ strio_initialize(argc, argv, self)
break;
}
ptr->string = string;
- return self;
}
static VALUE
@@ -250,6 +281,9 @@ strio_finalize(self)
return self;
}
+/*
+ * Returns +false+. Just for compatibility to IO.
+ */
static VALUE
strio_false(self)
VALUE self;
@@ -258,6 +292,9 @@ strio_false(self)
return Qfalse;
}
+/*
+ * Returns +nil+. Just for compatibility to IO.
+ */
static VALUE
strio_nil(self)
VALUE self;
@@ -266,6 +303,9 @@ strio_nil(self)
return Qnil;
}
+/*
+ * Returns *strio* itself. Just for compatibility to IO.
+ */
static VALUE
strio_self(self)
VALUE self;
@@ -274,6 +314,9 @@ strio_self(self)
return self;
}
+/*
+ * Returns 0. Just for compatibility to IO.
+ */
static VALUE
strio_0(self)
VALUE self;
@@ -282,6 +325,9 @@ strio_0(self)
return INT2FIX(0);
}
+/*
+ * Returns the argument unchanged. Just for compatibility to IO.
+ */
static VALUE
strio_first(self, arg)
VALUE self, arg;
@@ -290,6 +336,9 @@ strio_first(self, arg)
return arg;
}
+/*
+ * Raises NotImplementedError.
+ */
static VALUE
strio_unimpl(argc, argv, self)
int argc;
@@ -301,6 +350,11 @@ strio_unimpl(argc, argv, self)
return Qnil; /* not reached */
}
+/*
+ * call-seq: strio.string -> string
+ *
+ * Returns underlying String object, the subject of IO.
+ */
static VALUE
strio_get_string(self)
VALUE self;
@@ -308,6 +362,12 @@ strio_get_string(self)
return StringIO(self)->string;
}
+/*
+ * call-seq:
+ * strio.string = string -> string
+ *
+ * Changes underlying String object, the subject of IO.
+ */
static VALUE
strio_set_string(self, string)
VALUE self, string;
@@ -316,15 +376,20 @@ strio_set_string(self, string)
if (!OBJ_TAINTED(self)) rb_secure(4);
ptr->flags &= ~FMODE_READWRITE;
- if (!NIL_P(string)) {
- StringValue(string);
- ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
- }
+ StringValue(string);
+ ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
ptr->pos = 0;
ptr->lineno = 0;
return ptr->string = string;
}
+/*
+ * call-seq:
+ * strio.close -> nil
+ *
+ * Closes strio. The *strio* is unavailable for any further data
+ * operations; an +IOError+ is raised if such an attempt is made.
+ */
static VALUE
strio_close(self)
VALUE self;
@@ -333,11 +398,17 @@ strio_close(self)
if (CLOSED(ptr)) {
rb_raise(rb_eIOError, "closed stream");
}
- ptr->string = Qnil;
ptr->flags &= ~FMODE_READWRITE;
- return self;
+ return Qnil;
}
+/*
+ * call-seq:
+ * strio.close_read -> nil
+ *
+ * Closes the read end of a StringIO. Will raise an +IOError+ if the
+ * *strio* is not readable.
+ */
static VALUE
strio_close_read(self)
VALUE self;
@@ -346,12 +417,17 @@ strio_close_read(self)
if (!READABLE(ptr)) {
rb_raise(rb_eIOError, "closing non-duplex IO for reading");
}
- if (!((ptr->flags &= ~FMODE_READABLE) & FMODE_READWRITE)) {
- ptr->string = Qnil;
- }
- return self;
+ ptr->flags &= ~FMODE_READABLE;
+ return Qnil;
}
+/*
+ * call-seq:
+ * strio.close_write -> nil
+ *
+ * Closes the write end of a StringIO. Will raise an +IOError+ if the
+ * *strio* is not writeable.
+ */
static VALUE
strio_close_write(self)
VALUE self;
@@ -360,12 +436,16 @@ strio_close_write(self)
if (!WRITABLE(ptr)) {
rb_raise(rb_eIOError, "closing non-duplex IO for writing");
}
- if (!((ptr->flags &= ~FMODE_WRITABLE) & FMODE_READWRITE)) {
- ptr->string = Qnil;
- }
- return self;
+ ptr->flags &= ~FMODE_WRITABLE;
+ return Qnil;
}
+/*
+ * call-seq:
+ * strio.closed? -> true or false
+ *
+ * Returns +true+ if *strio* is completely closed, +false+ otherwise.
+ */
static VALUE
strio_closed(self)
VALUE self;
@@ -375,6 +455,12 @@ strio_closed(self)
return Qtrue;
}
+/*
+ * call-seq:
+ * strio.closed_read? -> true or false
+ *
+ * Returns +true+ if *strio* is not readable, +false+ otherwise.
+ */
static VALUE
strio_closed_read(self)
VALUE self;
@@ -384,6 +470,12 @@ strio_closed_read(self)
return Qtrue;
}
+/*
+ * call-seq:
+ * strio.closed_write? -> true or false
+ *
+ * Returns +true+ if *strio* is not writable, +false+ otherwise.
+ */
static VALUE
strio_closed_write(self)
VALUE self;
@@ -393,6 +485,14 @@ strio_closed_write(self)
return Qtrue;
}
+/*
+ * call-seq:
+ * strio.eof -> true or false
+ * strio.eof? -> true or false
+ *
+ * Returns true if *strio* is at end of file. The stringio must be
+ * opened for reading or an +IOError+ will be raised.
+ */
static VALUE
strio_eof(self)
VALUE self;
@@ -402,6 +502,7 @@ strio_eof(self)
return Qtrue;
}
+/* :nodoc: */
static VALUE
strio_copy(copy, orig)
VALUE copy, orig;
@@ -420,6 +521,16 @@ strio_copy(copy, orig)
return copy;
}
+/*
+ * call-seq:
+ * strio.lineno -> integer
+ *
+ * Returns the current line number in *strio*. The stringio must be
+ * opened for reading. +lineno+ counts the number of times +gets+ is
+ * called, rather than the number of newlines encountered. The two
+ * values will differ if +gets+ is called with a separator other than
+ * newline. See also the <code>$.</code> variable.
+ */
static VALUE
strio_get_lineno(self)
VALUE self;
@@ -427,6 +538,13 @@ strio_get_lineno(self)
return LONG2NUM(StringIO(self)->lineno);
}
+/*
+ * call-seq:
+ * strio.lineno = integer -> integer
+ *
+ * Manually sets the current line number to the given value.
+ * <code>$.</code> is updated only on the next read.
+ */
static VALUE
strio_set_lineno(self, lineno)
VALUE self, lineno;
@@ -435,14 +553,26 @@ strio_set_lineno(self, lineno)
return lineno;
}
+/* call-seq: strio.binmode -> true */
#define strio_binmode strio_self
+/* call-seq: strio.fcntl */
#define strio_fcntl strio_unimpl
+/* call-seq: strio.flush -> strio */
#define strio_flush strio_self
+/* call-seq: strio.fsync -> 0 */
#define strio_fsync strio_0
+/*
+ * call-seq:
+ * strio.reopen(other_StrIO) -> strio
+ * strio.reopen(string, mode) -> strio
+ *
+ * Reinitializes *strio* with the given <i>other_StrIO</i> or _string_
+ * and _mode_ (see StringIO#new).
+ */
static VALUE
strio_reopen(argc, argv, self)
int argc;
@@ -453,9 +583,17 @@ strio_reopen(argc, argv, self)
if (argc == 1 && TYPE(*argv) != T_STRING) {
return strio_copy(self, *argv);
}
- return strio_initialize(argc, argv, self);
+ strio_init(argc, argv, StringIO(self));
+ return self;
}
+/*
+ * call-seq:
+ * strio.pos -> integer
+ * strio.tell -> integer
+ *
+ * Returns the current offset (in bytes) of *strio*.
+ */
static VALUE
strio_get_pos(self)
VALUE self;
@@ -463,6 +601,12 @@ strio_get_pos(self)
return LONG2NUM(StringIO(self)->pos);
}
+/*
+ * call-seq:
+ * strio.pos = integer -> integer
+ *
+ * Seeks to the given position (in bytes) in *strio*.
+ */
static VALUE
strio_set_pos(self, pos)
VALUE self;
@@ -474,9 +618,17 @@ strio_set_pos(self, pos)
error_inval(0);
}
ptr->pos = p;
+ ptr->flags &= ~STRIO_EOF;
return pos;
}
+/*
+ * call-seq:
+ * strio.rewind -> 0
+ *
+ * Positions *strio* to the beginning of input, resetting
+ * +lineno+ to zero.
+ */
static VALUE
strio_rewind(self)
VALUE self;
@@ -488,6 +640,13 @@ strio_rewind(self)
return INT2FIX(0);
}
+/*
+ * call-seq:
+ * strio.seek(amount, whence=SEEK_SET) -> 0
+ *
+ * Seeks to a given offset _amount_ in the stream according to
+ * the value of _whence_ (see IO#seek).
+ */
static VALUE
strio_seek(argc, argv, self)
int argc;
@@ -500,6 +659,9 @@ strio_seek(argc, argv, self)
rb_scan_args(argc, argv, "11", NULL, &whence);
offset = NUM2LONG(argv[0]);
+ if (CLOSED(ptr)) {
+ rb_raise(rb_eIOError, "closed stream");
+ }
switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
case 0:
break;
@@ -510,7 +672,7 @@ strio_seek(argc, argv, self)
offset += RSTRING(ptr->string)->len;
break;
default:
- rb_raise(rb_eArgError, "invalid whence %ld", NUM2LONG(whence));
+ error_inval("invalid whence");
}
if (offset < 0) {
error_inval(0);
@@ -520,6 +682,12 @@ strio_seek(argc, argv, self)
return INT2FIX(0);
}
+/*
+ * call-seq:
+ * strio.sync -> true
+ *
+ * Returns +true+ always.
+ */
static VALUE
strio_get_sync(self)
VALUE self;
@@ -528,22 +696,38 @@ strio_get_sync(self)
return Qtrue;
}
+/* call-seq: strio.sync = boolean -> boolean */
#define strio_set_sync strio_first
#define strio_tell strio_get_pos
+/*
+ * call-seq:
+ * strio.each_byte {|byte| block } -> strio
+ *
+ * See IO#each_byte.
+ */
static VALUE
strio_each_byte(self)
VALUE self;
{
struct StringIO *ptr = readable(StringIO(self));
- while (ptr->pos < RSTRING(ptr->string)->len) {
- char c = RSTRING(ptr->string)->ptr[ptr->pos++];
+
+ RETURN_ENUMERATOR(self, 0, 0);
+
+ while (ptr->pos < RSTRING_LEN(ptr->string)) {
+ char c = RSTRING_PTR(ptr->string)[ptr->pos++];
rb_yield(CHR2FIX(c));
}
- return Qnil;
+ return self;
}
+/*
+ * call-seq:
+ * strio.getc -> fixnum or nil
+ *
+ * See IO#getc.
+ */
static VALUE
strio_getc(self)
VALUE self;
@@ -558,6 +742,35 @@ strio_getc(self)
return CHR2FIX(c);
}
+static void
+strio_extend(ptr, pos, len)
+ struct StringIO *ptr;
+ long pos, len;
+{
+ long olen;
+
+ check_modifiable(ptr);
+ olen = RSTRING(ptr->string)->len;
+ if (pos + len > olen) {
+ rb_str_resize(ptr->string, pos + len);
+ if (pos > olen)
+ MEMZERO(RSTRING(ptr->string)->ptr + olen, char, pos - olen);
+ }
+ else {
+ rb_str_modify(ptr->string);
+ }
+}
+
+/*
+ * call-seq:
+ * strio.ungetc(integer) -> nil
+ *
+ * Pushes back one character (passed as a parameter) onto *strio*
+ * such that a subsequent buffered read will return it. Pushing back
+ * behind the beginning of the buffer string is not possible. Nothing
+ * will be done if such an attempt is made.
+ * In other case, there is no limitation for multiple pushbacks.
+ */
static VALUE
strio_ungetc(self, ch)
VALUE self, ch;
@@ -566,27 +779,35 @@ strio_ungetc(self, ch)
int cc = NUM2INT(ch);
long len, pos = ptr->pos;
- if (cc != EOF && pos > 0) {
- if ((len = RSTRING(ptr->string)->len) < pos ||
- (unsigned char)RSTRING(ptr->string)->ptr[pos - 1] !=
- (unsigned char)cc) {
- check_modifiable(ptr);
- if (len < pos) {
- rb_str_resize(ptr->string, pos);
- MEMZERO(RSTRING(ptr->string)->ptr + len, char, pos - len - 1);
- }
- else {
- rb_str_modify(ptr->string);
+ if (cc != EOF) {
+ len = RSTRING(ptr->string)->len;
+ if (pos == 0) {
+ char *p;
+ rb_str_resize(ptr->string, len + 1);
+ p = RSTRING(ptr->string)->ptr;
+ memmove(p + 1, p, len);
+ }
+ else {
+ if (len < pos-- ||
+ (unsigned char)RSTRING(ptr->string)->ptr[pos] !=
+ (unsigned char)cc) {
+ strio_extend(ptr, pos, 1);
}
- RSTRING(ptr->string)->ptr[pos - 1] = cc;
- OBJ_INFECT(ptr->string, self);
+ --ptr->pos;
}
- --ptr->pos;
+ RSTRING(ptr->string)->ptr[pos] = cc;
+ OBJ_INFECT(ptr->string, self);
ptr->flags &= ~STRIO_EOF;
}
return Qnil;
}
+/*
+ * call-seq:
+ * strio.readchar -> fixnum
+ *
+ * See IO#readchar.
+ */
static VALUE
strio_readchar(self)
VALUE self;
@@ -596,6 +817,41 @@ strio_readchar(self)
return c;
}
+/*
+ * call-seq:
+ * strio.each_char {|char| block } -> strio
+ *
+ * See IO#each_char.
+ */
+static VALUE
+strio_each_char(self)
+ VALUE self;
+{
+ struct StringIO *sio;
+ VALUE str;
+ const char *ptr;
+ size_t len;
+
+ RETURN_ENUMERATOR(self, 0, 0);
+
+ sio = readable(StringIO(self));
+ str = sio->string;
+ ptr = RSTRING_PTR(str);
+ len = RSTRING_LEN(str);
+
+ while (sio->pos < len) {
+ int pos = sio->pos;
+ char c = ptr[pos];
+ int n = mbclen(c);
+
+ if (len < pos + n) n = len - pos;
+
+ sio->pos += n;
+ rb_yield(rb_str_substr(str, pos, n));
+ }
+ return self;
+}
+
static void
bm_init_skip(skip, pat, m)
long *skip;
@@ -673,8 +929,7 @@ strio_getline(argc, argv, ptr)
}
}
s = p;
- while (p = memchr(p, '\n', e - p)) {
- if (p == e) break;
+ while ((p = memchr(p, '\n', e - p)) && (p != e)) {
if (*++p == '\n') {
e = p;
break;
@@ -683,7 +938,7 @@ strio_getline(argc, argv, ptr)
str = rb_str_substr(ptr->string, s - RSTRING(ptr->string)->ptr, e - s);
}
else if (n == 1) {
- if (p = memchr(s, RSTRING(str)->ptr[0], e - s)) {
+ if ((p = memchr(s, RSTRING(str)->ptr[0], e - s)) != 0) {
e = p + 1;
}
str = rb_str_substr(ptr->string, ptr->pos, e - s);
@@ -714,6 +969,12 @@ strio_getline(argc, argv, ptr)
return str;
}
+/*
+ * call-seq:
+ * strio.gets(sep_string=$/) -> string or nil
+ *
+ * See IO#gets.
+ */
static VALUE
strio_gets(argc, argv, self)
int argc;
@@ -726,17 +987,30 @@ strio_gets(argc, argv, self)
return str;
}
+/*
+ * call-seq:
+ * strio.readline(sep_string=$/) -> string
+ *
+ * See IO#readline.
+ */
static VALUE
strio_readline(argc, argv, self)
int argc;
VALUE *argv;
VALUE self;
{
- VALUE line = strio_getline(argc, argv, readable(StringIO(self)));
+ VALUE line = strio_gets(argc, argv, self);
if (NIL_P(line)) rb_eof_error();
return line;
}
+/*
+ * call-seq:
+ * strio.each(sep_string=$/) {|line| block } -> strio
+ * strio.each_line(sep_string=$/) {|line| block } -> strio
+ *
+ * See IO#each.
+ */
static VALUE
strio_each(argc, argv, self)
int argc;
@@ -746,12 +1020,20 @@ strio_each(argc, argv, self)
struct StringIO *ptr = StringIO(self);
VALUE line;
+ RETURN_ENUMERATOR(self, argc, argv);
+
while (!NIL_P(line = strio_getline(argc, argv, readable(ptr)))) {
rb_yield(line);
}
return self;
}
+/*
+ * call-seq:
+ * strio.readlines(sep_string=$/) -> array
+ *
+ * See IO#readlines.
+ */
static VALUE
strio_readlines(argc, argv, self)
int argc;
@@ -766,31 +1048,37 @@ strio_readlines(argc, argv, self)
return ary;
}
+/*
+ * call-seq:
+ * strio.write(string) -> integer
+ * strio.syswrite(string) -> integer
+ *
+ * Appends the given string to the underlying buffer string of *strio*.
+ * The stream must be opened for writing. If the argument is not a
+ * string, it will be converted to a string using <code>to_s</code>.
+ * Returns the number of bytes written. See IO#write.
+ */
static VALUE
strio_write(self, str)
VALUE self, str;
{
struct StringIO *ptr = writable(StringIO(self));
- long len;
+ long len, olen;
if (TYPE(str) != T_STRING)
str = rb_obj_as_string(str);
len = RSTRING(str)->len;
if (!len) return INT2FIX(0);
check_modifiable(ptr);
- if (ptr->flags & STRIO_APPEND) {
- ptr->pos = RSTRING(ptr->string)->len;
+ olen = RSTRING(ptr->string)->len;
+ if (ptr->flags & FMODE_APPEND) {
+ ptr->pos = olen;
}
- if (ptr->pos == RSTRING(ptr->string)->len) {
+ if (ptr->pos == olen) {
rb_str_cat(ptr->string, RSTRING(str)->ptr, len);
}
else {
- if (ptr->pos + len > RSTRING(ptr->string)->len) {
- rb_str_resize(ptr->string, ptr->pos + len);
- }
- else {
- rb_str_modify(ptr->string);
- }
+ strio_extend(ptr, ptr->pos, len);
rb_str_update(ptr->string, ptr->pos, len, str);
}
OBJ_INFECT(ptr->string, self);
@@ -798,36 +1086,70 @@ strio_write(self, str)
return LONG2NUM(len);
}
+/*
+ * call-seq:
+ * strio << obj -> strio
+ *
+ * See IO#<<.
+ */
#define strio_addstr rb_io_addstr
+/*
+ * call-seq:
+ * strio.print() -> nil
+ * strio.print(obj, ...) -> nil
+ *
+ * See IO#print.
+ */
#define strio_print rb_io_print
+/*
+ * call-seq:
+ * strio.printf(format_string [, obj, ...] ) -> nil
+ *
+ * See IO#printf.
+ */
#define strio_printf rb_io_printf
+/*
+ * call-seq:
+ * strio.putc(obj) -> obj
+ *
+ * See IO#putc.
+ */
static VALUE
strio_putc(self, ch)
VALUE self, ch;
{
struct StringIO *ptr = writable(StringIO(self));
int c = NUM2CHR(ch);
+ long olen;
check_modifiable(ptr);
- if (ptr->flags & STRIO_APPEND) {
- ptr->pos = RSTRING(ptr->string)->len;
- }
- if (ptr->pos >= RSTRING(ptr->string)->len) {
- rb_str_resize(ptr->string, ptr->pos + 1);
- }
- else {
- rb_str_modify(ptr->string);
+ olen = RSTRING(ptr->string)->len;
+ if (ptr->flags & FMODE_APPEND) {
+ ptr->pos = olen;
}
+ strio_extend(ptr, ptr->pos, 1);
RSTRING(ptr->string)->ptr[ptr->pos++] = c;
OBJ_INFECT(ptr->string, self);
return ch;
}
+/*
+ * call-seq:
+ * strio.puts(obj, ...) -> nil
+ *
+ * See IO#puts.
+ */
#define strio_puts rb_io_puts
+/*
+ * call-seq:
+ * strio.read([length [, buffer]]) -> string, buffer, or nil
+ *
+ * See IO#read.
+ */
static VALUE
strio_read(argc, argv, self)
int argc;
@@ -835,46 +1157,79 @@ strio_read(argc, argv, self)
VALUE self;
{
struct StringIO *ptr = readable(StringIO(self));
- VALUE str;
- long len;
+ VALUE str = Qnil;
+ long len, olen;
switch (argc) {
+ case 2:
+ str = argv[1];
+ StringValue(str);
+ rb_str_modify(str);
case 1:
if (!NIL_P(argv[0])) {
- len = NUM2LONG(argv[0]);
+ len = olen = NUM2LONG(argv[0]);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
if (len > 0 && ptr->pos >= RSTRING(ptr->string)->len) {
ptr->flags |= STRIO_EOF;
+ if (!NIL_P(str)) rb_str_resize(str, 0);
return Qnil;
}
else if (ptr->flags & STRIO_EOF) {
+ if (!NIL_P(str)) rb_str_resize(str, 0);
return Qnil;
}
break;
}
/* fall through */
case 0:
- len = RSTRING(ptr->string)->len - ptr->pos;
- if (len == 0 && ptr->pos == RSTRING(ptr->string)->len) {
- if (ptr->flags & STRIO_EOF) return Qnil;
+ olen = -1;
+ len = RSTRING(ptr->string)->len;
+ if (len <= ptr->pos) {
ptr->flags |= STRIO_EOF;
+ if (NIL_P(str)) {
+ str = rb_str_new(0, 0);
+ }
+ else {
+ rb_str_resize(str, 0);
+ }
+ return str;
+ }
+ else {
+ len -= ptr->pos;
}
break;
default:
- rb_raise(rb_eArgError, "wrong number arguments (%d for 0)", argc);
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
}
- str = rb_str_substr(ptr->string, ptr->pos, len);
if (NIL_P(str)) {
- ptr->flags |= STRIO_EOF;
+ str = rb_str_substr(ptr->string, ptr->pos, len);
}
else {
- ptr->pos += RSTRING(str)->len;
+ long rest = RSTRING(ptr->string)->len - ptr->pos;
+ if (len > rest) len = rest;
+ rb_str_resize(str, len);
+ MEMCPY(RSTRING(str)->ptr, RSTRING(ptr->string)->ptr + ptr->pos, char, len);
+ }
+ if (NIL_P(str)) {
+ if (!(ptr->flags & STRIO_EOF)) str = rb_str_new(0, 0);
+ len = 0;
}
+ else {
+ ptr->pos += len = RSTRING(str)->len;
+ }
+ if (olen < 0 || olen > len) ptr->flags |= STRIO_EOF;
return str;
}
+/*
+ * call-seq:
+ * strio.sysread(integer[, outbuf]) -> string
+ *
+ * Similar to #read, but raises +EOFError+ at end of string instead of
+ * returning +nil+, as well as IO#sysread does.
+ */
static VALUE
strio_sysread(argc, argv, self)
int argc;
@@ -882,7 +1237,7 @@ strio_sysread(argc, argv, self)
VALUE self;
{
VALUE val = strio_read(argc, argv, self);
- if (NIL_P(val)) {
+ if (NIL_P(val) || RSTRING(val)->len == 0) {
rb_eof_error();
}
return val;
@@ -890,14 +1245,29 @@ strio_sysread(argc, argv, self)
#define strio_syswrite strio_write
+/* call-seq: strio.path -> nil */
#define strio_path strio_nil
+/*
+ * call-seq:
+ * strio.isatty -> nil
+ * strio.tty? -> nil
+ *
+ */
#define strio_isatty strio_false
+/* call-seq: strio.pid -> nil */
#define strio_pid strio_nil
+/* call-seq: strio.fileno -> nil */
#define strio_fileno strio_nil
+/*
+ * call-seq:
+ * strio.size -> integer
+ *
+ * Returns the size of the buffer string.
+ */
static VALUE
strio_size(self)
VALUE self;
@@ -909,19 +1279,33 @@ strio_size(self)
return ULONG2NUM(RSTRING(string)->len);
}
+/*
+ * call-seq:
+ * strio.truncate(integer) -> 0
+ *
+ * Truncates the buffer string to at most _integer_ bytes. The *strio*
+ * must be opened for writing.
+ */
static VALUE
strio_truncate(self, len)
VALUE self, len;
{
VALUE string = writable(StringIO(self))->string;
long l = NUM2LONG(len);
+ long plen = RSTRING(string)->len;
if (l < 0) {
error_inval("negative legnth");
}
rb_str_resize(string, l);
+ if (plen < l) {
+ MEMZERO(RSTRING(string)->ptr + plen, char, l - plen);
+ }
return len;
}
+/*
+ * Pseudo I/O on String object.
+ */
void
Init_stringio()
{
@@ -961,11 +1345,17 @@ Init_stringio()
rb_define_method(StringIO, "path", strio_path, 0);
rb_define_method(StringIO, "each", strio_each, -1);
- rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
rb_define_method(StringIO, "each_line", strio_each, -1);
+ rb_define_method(StringIO, "lines", strio_each, -1);
+ rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
+ rb_define_method(StringIO, "bytes", strio_each_byte, 0);
+ rb_define_method(StringIO, "each_char", strio_each_char, 0);
+ rb_define_method(StringIO, "chars", strio_each_char, 0);
rb_define_method(StringIO, "getc", strio_getc, 0);
+ rb_define_method(StringIO, "getbyte", strio_getc, 0);
rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
rb_define_method(StringIO, "readchar", strio_readchar, 0);
+ rb_define_method(StringIO, "readbyte", strio_readchar, 0);
rb_define_method(StringIO, "gets", strio_gets, -1);
rb_define_method(StringIO, "readline", strio_readline, -1);
rb_define_method(StringIO, "readlines", strio_readlines, -1);
diff --git a/ext/strscan/MANIFEST b/ext/strscan/MANIFEST
deleted file mode 100644
index 5fdf598f2c..0000000000
--- a/ext/strscan/MANIFEST
+++ /dev/null
@@ -1,4 +0,0 @@
-MANIFEST
-strscan.c
-extconf.rb
-depend
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c
index 7169c2e163..b5ee20282c 100644
--- a/ext/strscan/strscan.c
+++ b/ext/strscan/strscan.c
@@ -1,26 +1,15 @@
/*
+ $Id$
- strscan.c
-
- Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
+ Copyright (c) 1999-2006 Minero Aoki
This program is free software.
You can distribute/modify this program under the terms of
the Ruby License. For details, see the file COPYING.
-
- $Id$
-
*/
-
#include "ruby.h"
#include "re.h"
-#include "version.h"
-
-#if (RUBY_VERSION_CODE < 150)
-# define rb_eRangeError rb_eArgError
-# define rb_obj_freeze(obj) rb_str_freeze(obj)
-#endif
#define STRSCAN_VERSION "0.7.0"
@@ -52,10 +41,10 @@ struct strscanner
#define MATCHED(s) (s)->flags |= FLAG_MATCHED
#define CLEAR_MATCH_STATUS(s) (s)->flags &= ~FLAG_MATCHED
-#define S_PTR(s) (RSTRING((s)->str)->ptr)
+#define S_PBEG(s) (RSTRING((s)->str)->ptr)
#define S_LEN(s) (RSTRING((s)->str)->len)
-#define S_END(s) (S_PTR(s) + S_LEN(s))
-#define CURPTR(s) (S_PTR(s) + (s)->curr)
+#define S_PEND(s) (S_PBEG(s) + S_LEN(s))
+#define CURPTR(s) (S_PBEG(s) + (s)->curr)
#define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
#define EOS_P(s) ((s)->curr >= RSTRING(p->str)->len)
@@ -73,15 +62,19 @@ static VALUE infect _((VALUE str, struct strscanner *p));
static VALUE extract_range _((struct strscanner *p, long beg_i, long end_i));
static VALUE extract_beg_len _((struct strscanner *p, long beg_i, long len));
+static void check_strscan _((VALUE obj));
static void strscan_mark _((struct strscanner *p));
static void strscan_free _((struct strscanner *p));
static VALUE strscan_s_allocate _((VALUE klass));
static VALUE strscan_initialize _((int argc, VALUE *argv, VALUE self));
+static VALUE strscan_init_copy _((VALUE vself, VALUE vorig));
static VALUE strscan_s_mustc _((VALUE self));
static VALUE strscan_terminate _((VALUE self));
+static VALUE strscan_clear _((VALUE self));
static VALUE strscan_get_string _((VALUE self));
static VALUE strscan_set_string _((VALUE self, VALUE str));
+static VALUE strscan_concat _((VALUE self, VALUE str));
static VALUE strscan_get_pos _((VALUE self));
static VALUE strscan_set_pos _((VALUE self, VALUE pos));
static VALUE strscan_do_scan _((VALUE self, VALUE regex,
@@ -100,9 +93,13 @@ static VALUE strscan_search_full _((VALUE self, VALUE re,
static void adjust_registers_to_matched _((struct strscanner *p));
static VALUE strscan_getch _((VALUE self));
static VALUE strscan_get_byte _((VALUE self));
+static VALUE strscan_getbyte _((VALUE self));
static VALUE strscan_peek _((VALUE self, VALUE len));
+static VALUE strscan_peep _((VALUE self, VALUE len));
static VALUE strscan_unscan _((VALUE self));
+static VALUE strscan_bol_p _((VALUE self));
static VALUE strscan_eos_p _((VALUE self));
+static VALUE strscan_empty_p _((VALUE self));
static VALUE strscan_rest_p _((VALUE self));
static VALUE strscan_matched_p _((VALUE self));
static VALUE strscan_matched _((VALUE self));
@@ -114,63 +111,57 @@ static VALUE strscan_rest _((VALUE self));
static VALUE strscan_rest_size _((VALUE self));
static VALUE strscan_inspect _((VALUE self));
-static char* inspect_before _((struct strscanner *p, char *buf));
-static char* inspect_after _((struct strscanner *p, char *buf));
+static VALUE inspect1 _((struct strscanner *p));
+static VALUE inspect2 _((struct strscanner *p));
/* =======================================================================
Utils
======================================================================= */
static VALUE
-infect(str, p)
- VALUE str;
- struct strscanner *p;
+infect(VALUE str, struct strscanner *p)
{
OBJ_INFECT(str, p->str);
return str;
}
static VALUE
-extract_range(p, beg_i, end_i)
- struct strscanner *p;
- long beg_i, end_i;
+extract_range(struct strscanner *p, long beg_i, long end_i)
{
- return infect(rb_str_new(S_PTR(p) + beg_i, end_i - beg_i), p);
+ if (beg_i > S_LEN(p)) return Qnil;
+ if (end_i > S_LEN(p))
+ end_i = S_LEN(p);
+ return infect(rb_str_new(S_PBEG(p) + beg_i, end_i - beg_i), p);
}
static VALUE
-extract_beg_len(p, beg_i, len)
- struct strscanner *p;
- long beg_i, len;
+extract_beg_len(struct strscanner *p, long beg_i, long len)
{
- return infect(rb_str_new(S_PTR(p) + beg_i, len), p);
+ if (beg_i > S_LEN(p)) return Qnil;
+ if (beg_i + len > S_LEN(p))
+ len = S_LEN(p) - beg_i;
+ return infect(rb_str_new(S_PBEG(p) + beg_i, len), p);
}
-
/* =======================================================================
Constructor
======================================================================= */
-
static void
-strscan_mark(p)
- struct strscanner *p;
+strscan_mark(struct strscanner *p)
{
rb_gc_mark(p->str);
}
static void
-strscan_free(p)
- struct strscanner *p;
+strscan_free(struct strscanner *p)
{
re_free_registers(&(p->regs));
- memset(p, sizeof(struct strscanner), 0);
free(p);
}
static VALUE
-strscan_s_allocate(klass)
- VALUE klass;
+strscan_s_allocate(VALUE klass)
{
struct strscanner *p;
@@ -182,40 +173,81 @@ strscan_s_allocate(klass)
return Data_Wrap_Struct(klass, strscan_mark, strscan_free, p);
}
+/*
+ * call-seq: StringScanner.new(string, dup = false)
+ *
+ * Creates a new StringScanner object to scan over the given +string+.
+ * +dup+ argument is obsolete and not used now.
+ */
static VALUE
-strscan_initialize(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+strscan_initialize(int argc, VALUE *argv, VALUE self)
{
struct strscanner *p;
VALUE str, need_dup;
Data_Get_Struct(self, struct strscanner, p);
- if (rb_scan_args(argc, argv, "11", &str, &need_dup) == 1)
- need_dup = Qtrue;
+ rb_scan_args(argc, argv, "11", &str, &need_dup);
StringValue(str);
- p->str = RTEST(need_dup) ? rb_str_dup(str) : str;
- rb_obj_freeze(p->str);
+ p->str = str;
return self;
}
+static void
+check_strscan(VALUE obj)
+{
+ if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RUBY_DATA_FUNC)strscan_mark) {
+ rb_raise(rb_eTypeError,
+ "wrong argument type %s (expected StringScanner)",
+ rb_obj_classname(obj));
+ }
+}
+
+/*
+ * call-seq:
+ * dup
+ * clone
+ *
+ * Duplicates a StringScanner object.
+ */
+static VALUE
+strscan_init_copy(VALUE vself, VALUE vorig)
+{
+ struct strscanner *self, *orig;
+
+ Data_Get_Struct(vself, struct strscanner, self);
+ check_strscan(vorig);
+ Data_Get_Struct(vorig, struct strscanner, orig);
+ if (self != orig) {
+ self->flags = orig->flags;
+ self->str = orig->str;
+ self->prev = orig->prev;
+ self->curr = orig->curr;
+ re_copy_registers(&self->regs, &orig->regs);
+ }
+ return vself;
+}
/* =======================================================================
Instance Methods
======================================================================= */
+/*
+ * call-seq: StringScanner.must_C_version
+ *
+ * This method is defined for backward compatibility.
+ */
static VALUE
-strscan_s_mustc(self)
- VALUE self;
+strscan_s_mustc(VALUE self)
{
return self;
}
+/*
+ * Reset the scan pointer (index 0) and clear matching data.
+ */
static VALUE
-strscan_reset(self)
- VALUE self;
+strscan_reset(VALUE self)
{
struct strscanner *p;
@@ -225,9 +257,15 @@ strscan_reset(self)
return self;
}
+/*
+ * call-seq:
+ * terminate
+ * clear
+ *
+ * Set the scan pointer to the end of the string and clear matching data.
+ */
static VALUE
-strscan_terminate(self)
- VALUE self;
+strscan_terminate(VALUE self)
{
struct strscanner *p;
@@ -237,9 +275,22 @@ strscan_terminate(self)
return self;
}
+/*
+ * Equivalent to #terminate.
+ * This method is obsolete; use #terminate instead.
+ */
+static VALUE
+strscan_clear(VALUE self)
+{
+ rb_warning("StringScanner#clear is obsolete; use #terminate instead");
+ return strscan_terminate(self);
+}
+
+/*
+ * Returns the string being scanned.
+ */
static VALUE
-strscan_get_string(self)
- VALUE self;
+strscan_get_string(VALUE self)
{
struct strscanner *p;
@@ -247,9 +298,14 @@ strscan_get_string(self)
return p->str;
}
+/*
+ * call-seq: string=(str)
+ *
+ * Changes the string being scanned to +str+ and resets the scanner.
+ * Returns +str+.
+ */
static VALUE
-strscan_set_string(self, str)
- VALUE self, str;
+strscan_set_string(VALUE self, VALUE str)
{
struct strscanner *p;
@@ -262,9 +318,47 @@ strscan_set_string(self, str)
return str;
}
+/*
+ * call-seq:
+ * concat(str)
+ * <<(str)
+ *
+ * Appends +str+ to the string being scanned.
+ * This method does not affect scan pointer.
+ *
+ * s = StringScanner.new("Fri Dec 12 1975 14:39")
+ * s.scan(/Fri /)
+ * s << " +1000 GMT"
+ * s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
+ * s.scan(/Dec/) # -> "Dec"
+ */
+static VALUE
+strscan_concat(VALUE self, VALUE str)
+{
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ StringValue(str);
+ rb_str_append(p->str, str);
+ return self;
+}
+
+/*
+ * Returns the position of the scan pointer. In the 'reset' position, this
+ * value is zero. In the 'terminated' position (i.e. the string is exhausted),
+ * this value is the length of the string.
+ *
+ * In short, it's a 0-based index into the string.
+ *
+ * s = StringScanner.new('test string')
+ * s.pos # -> 0
+ * s.scan_until /str/ # -> "test str"
+ * s.pos # -> 8
+ * s.terminate # -> #<StringScanner fin>
+ * s.pos # -> 11
+ */
static VALUE
-strscan_get_pos(self)
- VALUE self;
+strscan_get_pos(VALUE self)
{
struct strscanner *p;
@@ -272,9 +366,17 @@ strscan_get_pos(self)
return INT2FIX(p->curr);
}
+/*
+ * call-seq: pos=(n)
+ *
+ * Modify the scan pointer.
+ *
+ * s = StringScanner.new('test string')
+ * s.pos = 7 # -> 7
+ * s.rest # -> "ring"
+ */
static VALUE
-strscan_set_pos(self, v)
- VALUE self, v;
+strscan_set_pos(VALUE self, VALUE v)
{
struct strscanner *p;
long i;
@@ -288,14 +390,8 @@ strscan_set_pos(self, v)
return INT2NUM(i);
}
-
-/* I should implement this function? */
-#define strscan_prepare_re(re) /* none */
-
static VALUE
-strscan_do_scan(self, regex, succptr, getstr, headonly)
- VALUE self, regex;
- int succptr, getstr, headonly;
+strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly)
{
struct strscanner *p;
int ret;
@@ -304,7 +400,10 @@ strscan_do_scan(self, regex, succptr, getstr, headonly)
GET_SCANNER(self, p);
CLEAR_MATCH_STATUS(p);
- strscan_prepare_re(regex);
+ if (S_RESTLEN(p) < 0) {
+ return Qnil;
+ }
+ rb_kcode_set_option(regex);
if (headonly) {
ret = re_match(RREGEXP(regex)->ptr,
CURPTR(p), S_RESTLEN(p),
@@ -318,6 +417,7 @@ strscan_do_scan(self, regex, succptr, getstr, headonly)
S_RESTLEN(p),
&(p->regs));
}
+ rb_kcode_reset_option();
if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
if (ret < 0) {
@@ -338,81 +438,201 @@ strscan_do_scan(self, regex, succptr, getstr, headonly)
}
}
+/*
+ * call-seq: scan(pattern) => String
+ *
+ * Tries to match with +pattern+ at the current position. If there's a match,
+ * the scanner advances the "scan pointer" and returns the matched string.
+ * Otherwise, the scanner returns +nil+.
+ *
+ * s = StringScanner.new('test string')
+ * p s.scan(/\w+/) # -> "test"
+ * p s.scan(/\w+/) # -> nil
+ * p s.scan(/\s+/) # -> " "
+ * p s.scan(/\w+/) # -> "string"
+ * p s.scan(/./) # -> nil
+ *
+ */
static VALUE
-strscan_scan(self, re)
- VALUE self, re;
+strscan_scan(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 1, 1, 1);
}
+/*
+ * call-seq: match?(pattern)
+ *
+ * Tests whether the given +pattern+ is matched from the current scan pointer.
+ * Returns the length of the match, or +nil+. The scan pointer is not advanced.
+ *
+ * s = StringScanner.new('test string')
+ * p s.match?(/\w+/) # -> 4
+ * p s.match?(/\w+/) # -> 4
+ * p s.match?(/\s+/) # -> nil
+ */
static VALUE
-strscan_match_p(self, re)
- VALUE self, re;
+strscan_match_p(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 0, 1);
}
+/*
+ * call-seq: skip(pattern)
+ *
+ * Attempts to skip over the given +pattern+ beginning with the scan pointer.
+ * If it matches, the scan pointer is advanced to the end of the match, and the
+ * length of the match is returned. Otherwise, +nil+ is returned.
+ *
+ * It's similar to #scan, but without returning the matched string.
+ *
+ * s = StringScanner.new('test string')
+ * p s.skip(/\w+/) # -> 4
+ * p s.skip(/\w+/) # -> nil
+ * p s.skip(/\s+/) # -> 1
+ * p s.skip(/\w+/) # -> 6
+ * p s.skip(/./) # -> nil
+ *
+ */
static VALUE
-strscan_skip(self, re)
- VALUE self, re;
+strscan_skip(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 1, 0, 1);
}
+/*
+ * call-seq: check(pattern)
+ *
+ * This returns the value that #scan would return, without advancing the scan
+ * pointer. The match register is affected, though.
+ *
+ * s = StringScanner.new("Fri Dec 12 1975 14:39")
+ * s.check /Fri/ # -> "Fri"
+ * s.pos # -> 0
+ * s.matched # -> "Fri"
+ * s.check /12/ # -> nil
+ * s.matched # -> nil
+ *
+ * Mnemonic: it "checks" to see whether a #scan will return a value.
+ */
static VALUE
-strscan_check(self, re)
- VALUE self, re;
+strscan_check(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 1, 1);
}
+/*
+ * call-seq: scan_full(pattern, return_string_p, advance_pointer_p)
+ *
+ * Tests whether the given +pattern+ is matched from the current scan pointer.
+ * Returns the matched string if +return_string_p+ is true.
+ * Advances the scan pointer if +advance_pointer_p+ is true.
+ * The match register is affected.
+ *
+ * "full" means "#scan with full parameters".
+ */
static VALUE
-strscan_scan_full(self, re, s, f)
- VALUE self, re, s, f;
+strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
}
+/*
+ * call-seq: scan_until(pattern)
+ *
+ * Scans the string _until_ the +pattern+ is matched. Returns the substring up
+ * to and including the end of the match, advancing the scan pointer to that
+ * location. If there is no match, +nil+ is returned.
+ *
+ * s = StringScanner.new("Fri Dec 12 1975 14:39")
+ * s.scan_until(/1/) # -> "Fri Dec 1"
+ * s.pre_match # -> "Fri Dec "
+ * s.scan_until(/XYZ/) # -> nil
+ */
static VALUE
-strscan_scan_until(self, re)
- VALUE self, re;
+strscan_scan_until(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 1, 1, 0);
}
+/*
+ * call-seq: exist?(pattern)
+ *
+ * Looks _ahead_ to see if the +pattern+ exists _anywhere_ in the string,
+ * without advancing the scan pointer. This predicates whether a #scan_until
+ * will return a value.
+ *
+ * s = StringScanner.new('test string')
+ * s.exist? /s/ # -> 3
+ * s.scan /test/ # -> "test"
+ * s.exist? /s/ # -> 6
+ * s.exist? /e/ # -> nil
+ */
static VALUE
-strscan_exist_p(self, re)
- VALUE self, re;
+strscan_exist_p(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 0, 0);
}
+/*
+ * call-seq: skip_until(pattern)
+ *
+ * Advances the scan pointer until +pattern+ is matched and consumed. Returns
+ * the number of bytes advanced, or +nil+ if no match was found.
+ *
+ * Look ahead to match +pattern+, and advance the scan pointer to the _end_
+ * of the match. Return the number of characters advanced, or +nil+ if the
+ * match was unsuccessful.
+ *
+ * It's similar to #scan_until, but without returning the intervening string.
+ *
+ * s = StringScanner.new("Fri Dec 12 1975 14:39")
+ * s.skip_until /12/ # -> 10
+ * s #
+ */
static VALUE
-strscan_skip_until(self, re)
- VALUE self, re;
+strscan_skip_until(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 1, 0, 0);
}
+/*
+ * call-seq: check_until(pattern)
+ *
+ * This returns the value that #scan_until would return, without advancing the
+ * scan pointer. The match register is affected, though.
+ *
+ * s = StringScanner.new("Fri Dec 12 1975 14:39")
+ * s.check_until /12/ # -> "Fri Dec 12"
+ * s.pos # -> 0
+ * s.matched # -> 12
+ *
+ * Mnemonic: it "checks" to see whether a #scan_until will return a value.
+ */
static VALUE
-strscan_check_until(self, re)
- VALUE self, re;
+strscan_check_until(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 1, 0);
}
+/*
+ * call-seq: search_full(pattern, return_string_p, advance_pointer_p)
+ *
+ * Scans the string _until_ the +pattern+ is matched.
+ * Returns the matched string if +return_string_p+ is true, otherwise
+ * returns the number of bytes advanced.
+ * Advances the scan pointer if +advance_pointer_p+, otherwise not.
+ * This method does affect the match register.
+ */
static VALUE
-strscan_search_full(self, re, s, f)
- VALUE self, re, s, f;
+strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
}
/* DANGEROUS; need to synchronize with regex.c */
static void
-adjust_registers_to_matched(p)
- struct strscanner *p;
+adjust_registers_to_matched(struct strscanner *p)
{
if (p->regs.allocated == 0) {
p->regs.beg = ALLOC_N(int, RE_NREGS);
@@ -424,9 +644,23 @@ adjust_registers_to_matched(p)
p->regs.end[0] = p->curr - p->prev;
}
+/*
+ * Scans one character and returns it.
+ * This method is multi-byte character sensitive.
+ * See also #get_byte.
+ *
+ * s = StringScanner.new('ab')
+ * s.getch # => "a"
+ * s.getch # => "b"
+ * s.getch # => nil
+ *
+ * $KCODE = 'EUC'
+ * s = StringScanner.new("\244\242")
+ * s.getch # => "\244\242" # Japanese hira-kana "A" in EUC-JP
+ * s.getch # => nil
+ */
static VALUE
-strscan_getch(self)
- VALUE self;
+strscan_getch(VALUE self)
{
struct strscanner *p;
long len;
@@ -435,10 +669,10 @@ strscan_getch(self)
CLEAR_MATCH_STATUS(p);
if (EOS_P(p))
return Qnil;
-
len = mbclen(*CURPTR(p));
- if (p->curr + len > S_LEN(p))
+ if (p->curr + len > S_LEN(p)) {
len = S_LEN(p) - p->curr;
+ }
p->prev = p->curr;
p->curr += len;
MATCHED(p);
@@ -447,17 +681,31 @@ strscan_getch(self)
p->prev + p->regs.end[0]);
}
+/*
+ * Scans one byte and returns it.
+ * This method is NOT multi-byte character sensitive.
+ * See also #getch.
+ *
+ * s = StringScanner.new('ab')
+ * s.get_byte # => "a"
+ * s.get_byte # => "b"
+ * s.get_byte # => nil
+ *
+ * s = StringScanner.new("\244\242")
+ * s.get_byte # => "\244"
+ * s.get_byte # => "\242"
+ * s.get_byte # => nil
+ */
static VALUE
-strscan_get_byte(self)
- VALUE self;
+strscan_get_byte(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
CLEAR_MATCH_STATUS(p);
- if (EOS_P(p))
+ if (EOS_P(p)) {
return Qnil;
-
+ }
p->prev = p->curr;
p->curr++;
MATCHED(p);
@@ -466,85 +714,178 @@ strscan_get_byte(self)
p->prev + p->regs.end[0]);
}
+/*
+ * Equivalent to #get_byte.
+ * This method is obsolete; use #get_byte instead.
+ */
+static VALUE
+strscan_getbyte(VALUE self)
+{
+ rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
+ return strscan_get_byte(self);
+}
+/*
+ * call-seq: peek(len)
+ *
+ * Extracts a string corresponding to <tt>string[pos,len]</tt>, without
+ * advancing the scan pointer.
+ *
+ * s = StringScanner.new('test string')
+ * s.peek(7) # => "test st"
+ * s.peek(7) # => "test st"
+ *
+ */
static VALUE
-strscan_peek(self, vlen)
- VALUE self, vlen;
+strscan_peek(VALUE self, VALUE vlen)
{
struct strscanner *p;
long len;
GET_SCANNER(self, p);
-
len = NUM2LONG(vlen);
- if (EOS_P(p))
+ if (EOS_P(p)) {
return infect(rb_str_new("", 0), p);
-
- if (p->curr + len > S_LEN(p))
+ }
+ if (p->curr + len > S_LEN(p)) {
len = S_LEN(p) - p->curr;
+ }
return extract_beg_len(p, p->curr, len);
}
+/*
+ * Equivalent to #peek.
+ * This method is obsolete; use #peek instead.
+ */
+static VALUE
+strscan_peep(VALUE self, VALUE vlen)
+{
+ rb_warning("StringScanner#peep is obsolete; use #peek instead");
+ return strscan_peek(self, vlen);
+}
+/*
+ * Set the scan pointer to the previous position. Only one previous position is
+ * remembered, and it changes with each scanning operation.
+ *
+ * s = StringScanner.new('test string')
+ * s.scan(/\w+/) # => "test"
+ * s.unscan
+ * s.scan(/../) # => "te"
+ * s.scan(/\d/) # => nil
+ * s.unscan # ScanError: unscan failed: previous match had failed
+ */
static VALUE
-strscan_unscan(self)
- VALUE self;
+strscan_unscan(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
- if (! MATCHED_P(p))
- rb_raise(ScanError, "cannot unscan: prev match had failed");
-
+ if (! MATCHED_P(p)) {
+ rb_raise(ScanError, "unscan failed: previous match had failed");
+ }
p->curr = p->prev;
CLEAR_MATCH_STATUS(p);
return self;
}
-
+/*
+ * Returns +true+ iff the scan pointer is at the beginning of the line.
+ *
+ * s = StringScanner.new("test\ntest\n")
+ * s.bol? # => true
+ * s.scan(/te/)
+ * s.bol? # => false
+ * s.scan(/st\n/)
+ * s.bol? # => true
+ * s.terminate
+ * s.bol? # => true
+ */
static VALUE
-strscan_eos_p(self)
- VALUE self;
+strscan_bol_p(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
- if (EOS_P(p))
- return Qtrue;
- else
- return Qfalse;
+ if (CURPTR(p) > S_PEND(p)) return Qnil;
+ if (p->curr == 0) return Qtrue;
+ return (*(CURPTR(p) - 1) == '\n') ? Qtrue : Qfalse;
}
+/*
+ * Returns +true+ if the scan pointer is at the end of the string.
+ *
+ * s = StringScanner.new('test string')
+ * p s.eos? # => false
+ * s.scan(/test/)
+ * p s.eos? # => false
+ * s.terminate
+ * p s.eos? # => true
+ */
static VALUE
-strscan_rest_p(self)
- VALUE self;
+strscan_eos_p(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
- if (EOS_P(p))
- return Qfalse;
- else
- return Qtrue;
+ return EOS_P(p) ? Qtrue : Qfalse;
}
+/*
+ * Equivalent to #eos?.
+ * This method is obsolete, use #eos? instead.
+ */
+static VALUE
+strscan_empty_p(VALUE self)
+{
+ rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
+ return strscan_eos_p(self);
+}
+
+/*
+ * Returns true iff there is more data in the string. See #eos?.
+ * This method is obsolete; use #eos? instead.
+ *
+ * s = StringScanner.new('test string')
+ * s.eos? # These two
+ * s.rest? # are opposites.
+ */
+static VALUE
+strscan_rest_p(VALUE self)
+{
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ return EOS_P(p) ? Qfalse : Qtrue;
+}
+/*
+ * Returns +true+ iff the last match was successful.
+ *
+ * s = StringScanner.new('test string')
+ * s.match?(/\w+/) # => 4
+ * s.matched? # => true
+ * s.match?(/\d+/) # => nil
+ * s.matched? # => false
+ */
static VALUE
-strscan_matched_p(self)
- VALUE self;
+strscan_matched_p(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
- if (MATCHED_P(p))
- return Qtrue;
- else
- return Qfalse;
+ return MATCHED_P(p) ? Qtrue : Qfalse;
}
+/*
+ * Returns the last matched string.
+ *
+ * s = StringScanner.new('test string')
+ * s.match?(/\w+/) # -> 4
+ * s.matched # -> "test"
+ */
static VALUE
-strscan_matched(self)
- VALUE self;
+strscan_matched(VALUE self)
{
struct strscanner *p;
@@ -555,9 +896,18 @@ strscan_matched(self)
p->prev + p->regs.end[0]);
}
+/*
+ * Returns the size of the most recent match (see #matched), or +nil+ if there
+ * was no recent match.
+ *
+ * s = StringScanner.new('test string')
+ * s.check /\w+/ # -> "test"
+ * s.matched_size # -> 4
+ * s.check /\d+/ # -> nil
+ * s.matched_size # -> nil
+ */
static VALUE
-strscan_matched_size(self)
- VALUE self;
+strscan_matched_size(VALUE self)
{
struct strscanner *p;
@@ -567,9 +917,33 @@ strscan_matched_size(self)
return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
}
+/*
+ * Equivalent to #matched_size.
+ * This method is obsolete; use #matched_size instead.
+ */
+static VALUE
+strscan_matchedsize(VALUE self)
+{
+ rb_warning("StringScanner#matchedsize is obsolete; use #matched_size instead");
+ return strscan_matched_size(self);
+}
+
+/*
+ * call-seq: [](n)
+ *
+ * Return the n-th subgroup in the most recent match.
+ *
+ * s = StringScanner.new("Fri Dec 12 1975 14:39")
+ * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
+ * s[0] # -> "Fri Dec 12 "
+ * s[1] # -> "Fri"
+ * s[2] # -> "Dec"
+ * s[3] # -> "12"
+ * s.post_match # -> "1975 14:39"
+ * s.pre_match # -> ""
+ */
static VALUE
-strscan_aref(self, idx)
- VALUE self, idx;
+strscan_aref(VALUE self, VALUE idx)
{
struct strscanner *p;
long i;
@@ -588,9 +962,17 @@ strscan_aref(self, idx)
p->prev + p->regs.end[i]);
}
+/*
+ * Return the <i><b>pre</b>-match</i> (in the regular expression sense) of the last scan.
+ *
+ * s = StringScanner.new('test string')
+ * s.scan(/\w+/) # -> "test"
+ * s.scan(/\s+/) # -> " "
+ * s.pre_match # -> "test"
+ * s.post_match # -> "string"
+ */
static VALUE
-strscan_pre_match(self)
- VALUE self;
+strscan_pre_match(VALUE self)
{
struct strscanner *p;
@@ -600,9 +982,17 @@ strscan_pre_match(self)
return extract_range(p, 0, p->prev + p->regs.beg[0]);
}
+/*
+ * Return the <i><b>post</b>-match</i> (in the regular expression sense) of the last scan.
+ *
+ * s = StringScanner.new('test string')
+ * s.scan(/\w+/) # -> "test"
+ * s.scan(/\s+/) # -> " "
+ * s.pre_match # -> "test"
+ * s.post_match # -> "string"
+ */
static VALUE
-strscan_post_match(self)
- VALUE self;
+strscan_post_match(VALUE self)
{
struct strscanner *p;
@@ -612,10 +1002,12 @@ strscan_post_match(self)
return extract_range(p, p->prev + p->regs.end[0], S_LEN(p));
}
-
+/*
+ * Returns the "rest" of the string (i.e. everything after the scan pointer).
+ * If there is no more data (eos? = true), it returns <tt>""</tt>.
+ */
static VALUE
-strscan_rest(self)
- VALUE self;
+strscan_rest(VALUE self)
{
struct strscanner *p;
@@ -626,9 +1018,11 @@ strscan_rest(self)
return extract_range(p, p->curr, S_LEN(p));
}
+/*
+ * <tt>s.rest_size</tt> is equivalent to <tt>s.rest.size</tt>.
+ */
static VALUE
-strscan_rest_size(self)
- VALUE self;
+strscan_rest_size(VALUE self)
{
struct strscanner *p;
long i;
@@ -642,19 +1036,38 @@ strscan_rest_size(self)
return INT2FIX(i);
}
+/*
+ * <tt>s.restsize</tt> is equivalent to <tt>s.rest_size</tt>.
+ * This method is obsolete; use #rest_size instead.
+ */
+static VALUE
+strscan_restsize(VALUE self)
+{
+ rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
+ return strscan_rest_size(self);
+}
#define INSPECT_LENGTH 5
#define BUFSIZE 256
+/*
+ * Returns a string that represents the StringScanner object, showing:
+ * - the current position
+ * - the size of the string
+ * - the characters surrounding the scan pointer
+ *
+ * s = StringScanner.new("Fri Dec 12 1975 14:39")
+ * s.inspect # -> '#<StringScanner 0/21 @ "Fri D...">'
+ * s.scan_until /12/ # -> "Fri Dec 12"
+ * s.inspect # -> '#<StringScanner 10/21 "...ec 12" @ " 1975...">'
+ */
static VALUE
-strscan_inspect(self)
- VALUE self;
+strscan_inspect(VALUE self)
{
struct strscanner *p;
char buf[BUFSIZE];
- char buf_before[16];
- char buf_after[16];
long len;
+ VALUE a, b;
Data_Get_Struct(self, struct strscanner, p);
if (NIL_P(p->str)) {
@@ -667,24 +1080,32 @@ strscan_inspect(self)
rb_class2name(CLASS_OF(self)));
return infect(rb_str_new(buf, len), p);
}
- len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld %s@%s>",
+ if (p->curr == 0) {
+ b = inspect2(p);
+ len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld @ %s>",
+ rb_class2name(CLASS_OF(self)),
+ p->curr, S_LEN(p),
+ RSTRING(b)->ptr);
+ return infect(rb_str_new(buf, len), p);
+ }
+ a = inspect1(p);
+ b = inspect2(p);
+ len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld %s @ %s>",
rb_class2name(CLASS_OF(self)),
p->curr, S_LEN(p),
- inspect_before(p, buf_before),
- inspect_after(p, buf_after));
+ RSTRING(a)->ptr,
+ RSTRING(b)->ptr);
return infect(rb_str_new(buf, len), p);
}
-static char*
-inspect_before(p, buf)
- struct strscanner *p;
- char *buf;
+static VALUE
+inspect1(struct strscanner *p)
{
+ char buf[BUFSIZE];
char *bp = buf;
long len;
- if (p->curr == 0) return "";
- *bp++ = '"';
+ if (p->curr == 0) return rb_str_new2("");
if (p->curr > INSPECT_LENGTH) {
strcpy(bp, "..."); bp += 3;
len = INSPECT_LENGTH;
@@ -693,22 +1114,17 @@ inspect_before(p, buf)
len = p->curr;
}
memcpy(bp, CURPTR(p) - len, len); bp += len;
- *bp++ = '"';
- *bp++ = ' ';
- *bp++ = '\0';
- return buf;
+ return rb_str_dump(rb_str_new(buf, bp - buf));
}
-static char*
-inspect_after(p, buf)
- struct strscanner *p;
- char *buf;
+static VALUE
+inspect2(struct strscanner *p)
{
+ char buf[BUFSIZE];
char *bp = buf;
long len;
- *bp++ = ' ';
- *bp++ = '"';
+ if (EOS_P(p)) return rb_str_new2("");
len = S_LEN(p) - p->curr;
if (len > INSPECT_LENGTH) {
len = INSPECT_LENGTH;
@@ -718,29 +1134,127 @@ inspect_after(p, buf)
else {
memcpy(bp, CURPTR(p), len); bp += len;
}
- *bp++ = '"';
- *bp++ = '\0';
- return buf;
+ return rb_str_dump(rb_str_new(buf, bp - buf));
}
/* =======================================================================
Ruby Interface
======================================================================= */
+/*
+ * Document-class: StringScanner
+ *
+ * StringScanner provides for lexical scanning operations on a String. Here is
+ * an example of its usage:
+ *
+ * s = StringScanner.new('This is an example string')
+ * s.eos? # -> false
+ *
+ * p s.scan(/\w+/) # -> "This"
+ * p s.scan(/\w+/) # -> nil
+ * p s.scan(/\s+/) # -> " "
+ * p s.scan(/\s+/) # -> nil
+ * p s.scan(/\w+/) # -> "is"
+ * s.eos? # -> false
+ *
+ * p s.scan(/\s+/) # -> " "
+ * p s.scan(/\w+/) # -> "an"
+ * p s.scan(/\s+/) # -> " "
+ * p s.scan(/\w+/) # -> "example"
+ * p s.scan(/\s+/) # -> " "
+ * p s.scan(/\w+/) # -> "string"
+ * s.eos? # -> true
+ *
+ * p s.scan(/\s+/) # -> nil
+ * p s.scan(/\w+/) # -> nil
+ *
+ * Scanning a string means remembering the position of a <i>scan pointer</i>,
+ * which is just an index. The point of scanning is to move forward a bit at
+ * a time, so matches are sought after the scan pointer; usually immediately
+ * after it.
+ *
+ * Given the string "test string", here are the pertinent scan pointer
+ * positions:
+ *
+ * t e s t s t r i n g
+ * 0 1 2 ... 1
+ * 0
+ *
+ * When you #scan for a pattern (a regular expression), the match must occur
+ * at the character after the scan pointer. If you use #scan_until, then the
+ * match can occur anywhere after the scan pointer. In both cases, the scan
+ * pointer moves <i>just beyond</i> the last character of the match, ready to
+ * scan again from the next character onwards. This is demonstrated by the
+ * example above.
+ *
+ * == Method Categories
+ *
+ * There are other methods besides the plain scanners. You can look ahead in
+ * the string without actually scanning. You can access the most recent match.
+ * You can modify the string being scanned, reset or terminate the scanner,
+ * find out or change the position of the scan pointer, skip ahead, and so on.
+ *
+ * === Advancing the Scan Pointer
+ *
+ * - #getch
+ * - #get_byte
+ * - #scan
+ * - #scan_until
+ * - #skip
+ * - #skip_until
+ *
+ * === Looking Ahead
+ *
+ * - #check
+ * - #check_until
+ * - #exist?
+ * - #match?
+ * - #peek
+ *
+ * === Finding Where we Are
+ *
+ * - #beginning_of_line? (#bol?)
+ * - #eos?
+ * - #rest?
+ * - #rest_size
+ * - #pos
+ *
+ * === Setting Where we Are
+ *
+ * - #reset
+ * - #terminate
+ * - #pos=
+ *
+ * === Match Data
+ *
+ * - #matched
+ * - #matched?
+ * - #matched_size
+ * - []
+ * - #pre_match
+ * - #post_match
+ *
+ * === Miscellaneous
+ *
+ * - <<
+ * - #concat
+ * - #string
+ * - #string=
+ * - #unscan
+ *
+ * There are aliases to several of the methods.
+ */
void
-Init_strscan()
+Init_strscan(void)
{
ID id_scanerr = rb_intern("ScanError");
- volatile VALUE tmp;
-
- if (rb_const_defined(rb_cObject, id_scanerr)) {
- ScanError = rb_const_get(rb_cObject, id_scanerr);
- }
- else {
- ScanError = rb_define_class_id(id_scanerr, rb_eStandardError);
- }
+ VALUE tmp;
StringScanner = rb_define_class("StringScanner", rb_cObject);
+ ScanError = rb_define_class_under(StringScanner, "Error", rb_eStandardError);
+ if (!rb_const_defined(rb_cObject, id_scanerr)) {
+ rb_const_set(rb_cObject, id_scanerr, ScanError);
+ }
tmp = rb_str_new2(STRSCAN_VERSION);
rb_obj_freeze(tmp);
rb_const_set(StringScanner, rb_intern("Version"), tmp);
@@ -750,12 +1264,15 @@ Init_strscan()
rb_define_alloc_func(StringScanner, strscan_s_allocate);
rb_define_private_method(StringScanner, "initialize", strscan_initialize, -1);
+ rb_define_private_method(StringScanner, "initialize_copy", strscan_init_copy, 1);
rb_define_singleton_method(StringScanner, "must_C_version", strscan_s_mustc, 0);
rb_define_method(StringScanner, "reset", strscan_reset, 0);
rb_define_method(StringScanner, "terminate", strscan_terminate, 0);
- rb_define_method(StringScanner, "clear", strscan_terminate, 0);
+ rb_define_method(StringScanner, "clear", strscan_clear, 0);
rb_define_method(StringScanner, "string", strscan_get_string, 0);
rb_define_method(StringScanner, "string=", strscan_set_string, 1);
+ rb_define_method(StringScanner, "concat", strscan_concat, 1);
+ rb_define_method(StringScanner, "<<", strscan_concat, 1);
rb_define_method(StringScanner, "pos", strscan_get_pos, 0);
rb_define_method(StringScanner, "pos=", strscan_set_pos, 1);
rb_define_method(StringScanner, "pointer", strscan_get_pos, 0);
@@ -775,27 +1292,29 @@ Init_strscan()
rb_define_method(StringScanner, "getch", strscan_getch, 0);
rb_define_method(StringScanner, "get_byte", strscan_get_byte, 0);
- rb_define_method(StringScanner, "getbyte", strscan_get_byte, 0);
+ rb_define_method(StringScanner, "getbyte", strscan_getbyte, 0);
rb_define_method(StringScanner, "peek", strscan_peek, 1);
- rb_define_method(StringScanner, "peep", strscan_peek, 1);
+ rb_define_method(StringScanner, "peep", strscan_peep, 1);
rb_define_method(StringScanner, "unscan", strscan_unscan, 0);
+ rb_define_method(StringScanner, "beginning_of_line?", strscan_bol_p, 0);
+ rb_alias(StringScanner, rb_intern("bol?"), rb_intern("beginning_of_line?"));
rb_define_method(StringScanner, "eos?", strscan_eos_p, 0);
- rb_define_method(StringScanner, "empty?", strscan_eos_p, 0);
+ rb_define_method(StringScanner, "empty?", strscan_empty_p, 0);
rb_define_method(StringScanner, "rest?", strscan_rest_p, 0);
rb_define_method(StringScanner, "matched?", strscan_matched_p, 0);
rb_define_method(StringScanner, "matched", strscan_matched, 0);
rb_define_method(StringScanner, "matched_size", strscan_matched_size, 0);
- rb_define_method(StringScanner, "matchedsize", strscan_matched_size, 0);
+ rb_define_method(StringScanner, "matchedsize", strscan_matchedsize, 0);
rb_define_method(StringScanner, "[]", strscan_aref, 1);
rb_define_method(StringScanner, "pre_match", strscan_pre_match, 0);
rb_define_method(StringScanner, "post_match", strscan_post_match, 0);
rb_define_method(StringScanner, "rest", strscan_rest, 0);
rb_define_method(StringScanner, "rest_size", strscan_rest_size, 0);
- rb_define_method(StringScanner, "restsize", strscan_rest_size, 0);
+ rb_define_method(StringScanner, "restsize", strscan_restsize, 0);
rb_define_method(StringScanner, "inspect", strscan_inspect, 0);
}
diff --git a/ext/syck/MANIFEST b/ext/syck/MANIFEST
deleted file mode 100644
index bb126fa530..0000000000
--- a/ext/syck/MANIFEST
+++ /dev/null
@@ -1,15 +0,0 @@
-MANIFEST
-extconf.rb
-bytecode.c
-emitter.c
-gram.c
-gram.h
-handler.c
-implicit.c
-node.c
-rubyext.c
-syck.c
-syck.h
-token.c
-yaml2byte.c
-yamlbyte.h
diff --git a/ext/syck/bytecode.c b/ext/syck/bytecode.c
index df15658a73..567aaf52a8 100644
--- a/ext/syck/bytecode.c
+++ b/ext/syck/bytecode.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.5 on Sun Nov 23 14:51:02 2003 */
+/* Generated by re2c 0.9.10 on Mon Sep 19 23:21:26 2005 */
#line 1 "bytecode.re"
/*
* bytecode.re
@@ -8,8 +8,8 @@
*
* Copyright (C) 2003 why the lucky stiff
*/
-#include "syck.h"
#include "ruby.h"
+#include "syck.h"
#include "gram.h"
#define QUOTELEN 128
@@ -89,7 +89,7 @@ char *get_inline( SyckParser *parser );
#define ENSURE_YAML_IOPEN(last_lvl, lvl_type, to_len, reset) \
if ( last_lvl->spaces < to_len ) \
{ \
- if ( last_lvl->status == syck_lvl_inline ) \
+ if ( last_lvl->status == syck_lvl_iseq || last_lvl->status == syck_lvl_imap ) \
{ \
goto Document; \
} \
@@ -135,7 +135,6 @@ int
sycklex_bytecode_utf8( YYSTYPE *sycklval, SyckParser *parser )
{
SyckLevel *lvl;
- int doc_level = 0;
syck_parser_ptr = parser;
if ( YYCURSOR == NULL )
{
@@ -149,7 +148,7 @@ sycklex_bytecode_utf8( YYSTYPE *sycklval, SyckParser *parser )
return t;
}
-#line 173
+#line 172 "bytecode.re"
lvl = CURRENT_LEVEL();
@@ -158,20 +157,22 @@ sycklex_bytecode_utf8( YYSTYPE *sycklval, SyckParser *parser )
goto Document;
}
-Header:
+/* Header: */
YYTOKEN = YYCURSOR;
+
+#line 165 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
goto yy0;
-yy1: ++YYCURSOR;
+ ++YYCURSOR;
yy0:
if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy2;
+ case 0x00: goto yy2;
case 'D': goto yy3;
default: goto yy5;
}
@@ -182,21 +183,23 @@ yy2: YYCURSOR = YYMARKER;
yy3: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '\n': goto yy6;
- case '\r': goto yy8;
+ case 0x0A: goto yy6;
+ case 0x0D: goto yy8;
default: goto yy4;
}
yy4:
-#line 200
- { YYPOS(0);
+#line 199 "bytecode.re"
+{ YYPOS(0);
goto Document;
}
+#line 195 "<stdout>"
yy5: yych = *++YYCURSOR;
goto yy4;
-yy6: yych = *++YYCURSOR;
+yy6: ++YYCURSOR;
+ goto yy7;
yy7:
-#line 187
- { if ( lvl->status == syck_lvl_header )
+#line 186 "bytecode.re"
+{ if ( lvl->status == syck_lvl_header )
{
CHK_NL(YYCURSOR);
goto Directive;
@@ -208,13 +211,14 @@ yy7:
return 0;
}
}
-yy8: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy6;
+#line 214 "<stdout>"
+yy8: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy6;
default: goto yy2;
}
}
-#line 204
+#line 203 "bytecode.re"
Document:
@@ -227,18 +231,19 @@ Document:
YYTOKEN = YYCURSOR;
+
+#line 235 "<stdout>"
{
YYCTYPE yych;
- unsigned int yyaccept;
goto yy9;
-yy10: ++YYCURSOR;
+ ++YYCURSOR;
yy9:
if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy30;
- case '\n': goto yy27;
- case '\r': goto yy29;
+ case 0x00: goto yy30;
+ case 0x0A: goto yy27;
+ case 0x0D: goto yy29;
case 'A': goto yy19;
case 'D': goto yy12;
case 'E': goto yy16;
@@ -253,62 +258,69 @@ yy9:
}
yy11:yy12: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy41;
- case '\r': goto yy44;
+ case 0x0A: goto yy41;
+ case 0x0D: goto yy44;
default: goto yy11;
}
yy13: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy41;
- case '\r': goto yy43;
+ case 0x0A: goto yy41;
+ case 0x0D: goto yy43;
default: goto yy11;
}
yy14: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy38;
- case '\r': goto yy40;
+ case 0x0A: goto yy38;
+ case 0x0D: goto yy40;
default: goto yy11;
}
yy15: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy35;
- case '\r': goto yy37;
+ case 0x0A: goto yy35;
+ case 0x0D: goto yy37;
default: goto yy11;
}
yy16: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy32;
- case '\r': goto yy34;
+ case 0x0A: goto yy32;
+ case 0x0D: goto yy34;
default: goto yy11;
}
-yy17: yych = *++YYCURSOR;
+yy17: ++YYCURSOR;
+ goto yy18;
yy18:
-#line 289
- { ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_str);
+#line 288 "bytecode.re"
+{ ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_str);
goto Scalar;
}
-yy19: yych = *++YYCURSOR;
+#line 296 "<stdout>"
+yy19: ++YYCURSOR;
+ goto yy20;
yy20:
-#line 293
- { ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_open);
+#line 292 "bytecode.re"
+{ ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_open);
sycklval->name = get_inline( parser );
syck_hdlr_remove_anchor( parser, sycklval->name );
CHK_NL(YYCURSOR);
return YAML_ANCHOR;
}
-yy21: yych = *++YYCURSOR;
+#line 307 "<stdout>"
+yy21: ++YYCURSOR;
+ goto yy22;
yy22:
-#line 300
- { ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_str);
+#line 299 "bytecode.re"
+{ ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_str);
sycklval->name = get_inline( parser );
POP_LEVEL();
if ( *( YYCURSOR - 1 ) == '\n' ) YYCURSOR--;
return YAML_ALIAS;
}
-yy23: yych = *++YYCURSOR;
+#line 318 "<stdout>"
+yy23: ++YYCURSOR;
+ goto yy24;
yy24:
-#line 307
- { char *qstr;
+#line 306 "bytecode.re"
+{ char *qstr;
ADD_BYTE_LEVEL(lvl, lvl->spaces + 1, syck_lvl_open);
qstr = get_inline( parser );
CHK_NL(YYCURSOR);
@@ -367,14 +379,18 @@ yy24:
sycklval->name = qstr;
return YAML_TAGURI;
}
-yy25: yych = *++YYCURSOR;
+#line 382 "<stdout>"
+yy25: ++YYCURSOR;
+ goto yy26;
yy26:
-#line 367
- { goto Comment; }
-yy27: yych = *++YYCURSOR;
+#line 366 "bytecode.re"
+{ goto Comment; }
+#line 388 "<stdout>"
+yy27: ++YYCURSOR;
+ goto yy28;
yy28:
-#line 369
- { CHK_NL(YYCURSOR);
+#line 368 "bytecode.re"
+{ CHK_NL(YYCURSOR);
if ( lvl->status == syck_lvl_seq )
{
return YAML_INDENT;
@@ -386,22 +402,26 @@ yy28:
}
goto Document;
}
+#line 405 "<stdout>"
yy29: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy27;
+ case 0x0A: goto yy27;
default: goto yy11;
}
-yy30: yych = *++YYCURSOR;
+yy30: ++YYCURSOR;
+ goto yy31;
yy31:
-#line 382
- { ENSURE_YAML_IEND(lvl, -1);
+#line 381 "bytecode.re"
+{ ENSURE_YAML_IEND(lvl, -1);
YYPOS(0);
return 0;
}
-yy32: yych = *++YYCURSOR;
+#line 419 "<stdout>"
+yy32: ++YYCURSOR;
+ goto yy33;
yy33:
-#line 253
- { if ( lvl->status == syck_lvl_seq && lvl->ncount == 0 )
+#line 252 "bytecode.re"
+{ if ( lvl->status == syck_lvl_seq && lvl->ncount == 0 )
{
lvl->ncount++;
YYPOS(0);
@@ -436,15 +456,17 @@ yy33:
CHK_NL(YYCURSOR);
return YAML_IEND;
}
+#line 459 "<stdout>"
yy34: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy32;
+ case 0x0A: goto yy32;
default: goto yy11;
}
-yy35: yych = *++YYCURSOR;
+yy35: ++YYCURSOR;
+ goto yy36;
yy36:
-#line 238
- { int complex = 0;
+#line 237 "bytecode.re"
+{ int complex = 0;
if ( lvl->ncount % 2 == 0 && ( lvl->status == syck_lvl_map || lvl->status == syck_lvl_seq ) )
{
complex = 1;
@@ -458,15 +480,17 @@ yy36:
}
return YAML_IOPEN;
}
+#line 483 "<stdout>"
yy37: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy35;
+ case 0x0A: goto yy35;
default: goto yy11;
}
-yy38: yych = *++YYCURSOR;
+yy38: ++YYCURSOR;
+ goto yy39;
yy39:
-#line 223
- { int complex = 0;
+#line 222 "bytecode.re"
+{ int complex = 0;
if ( lvl->ncount % 2 == 0 && ( lvl->status == syck_lvl_map || lvl->status == syck_lvl_seq ) )
{
complex = 1;
@@ -480,48 +504,53 @@ yy39:
}
return YAML_IOPEN;
}
+#line 507 "<stdout>"
yy40: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy38;
+ case 0x0A: goto yy38;
default: goto yy11;
}
-yy41: yych = *++YYCURSOR;
+yy41: ++YYCURSOR;
+ goto yy42;
yy42:
-#line 218
- { ENSURE_YAML_IEND(lvl, -1);
+#line 217 "bytecode.re"
+{ ENSURE_YAML_IEND(lvl, -1);
YYPOS(0);
return 0;
}
+#line 521 "<stdout>"
yy43: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy41;
+ case 0x0A: goto yy41;
default: goto yy11;
}
-yy44: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy41;
+yy44: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy41;
default: goto yy11;
}
}
-#line 387
+#line 386 "bytecode.re"
}
Directive:
{
- YYTOKTMP = YYCURSOR;
+ YYTOKEN = YYCURSOR;
+
+#line 543 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
goto yy45;
-yy46: ++YYCURSOR;
+ ++YYCURSOR;
yy45:
if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy47;
+ case 0x00: goto yy47;
case 'V': goto yy48;
default: goto yy50;
}
@@ -610,15 +639,17 @@ yy48: yyaccept = 0;
default: goto yy49;
}
yy49:
-#line 400
- { YYCURSOR = YYTOKTMP;
+#line 399 "bytecode.re"
+{ YYCURSOR = YYTOKEN;
return YAML_DOCSEP;
}
+#line 646 "<stdout>"
yy50: yych = *++YYCURSOR;
goto yy49;
yy51: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
+ goto yy52;
yy52: switch(yych){
case '.':
case '/':
@@ -776,11 +807,12 @@ yy53: yych = *++YYCURSOR;
default: goto yy47;
}
yy54: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
+ goto yy55;
yy55: switch(yych){
- case '\n': goto yy56;
- case '\r': goto yy58;
+ case 0x0A: goto yy56;
+ case 0x0D: goto yy58;
case '.':
case '/':
case '0':
@@ -858,59 +890,66 @@ yy55: switch(yych){
case 'z': goto yy54;
default: goto yy47;
}
-yy56: yych = *++YYCURSOR;
+yy56: ++YYCURSOR;
+ goto yy57;
yy57:
-#line 397
- { CHK_NL(YYCURSOR);
+#line 396 "bytecode.re"
+{ CHK_NL(YYCURSOR);
goto Directive; }
-yy58: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy56;
+#line 899 "<stdout>"
+yy58: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy56;
default: goto yy47;
}
}
-#line 403
+#line 402 "bytecode.re"
}
Comment:
{
- YYTOKTMP = YYCURSOR;
+ YYTOKEN = YYCURSOR;
+
+#line 916 "<stdout>"
{
YYCTYPE yych;
- unsigned int yyaccept;
goto yy59;
-yy60: ++YYCURSOR;
+ ++YYCURSOR;
yy59:
if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy61;
- case '\n': goto yy62;
- case '\r': goto yy64;
+ case 0x00: goto yy61;
+ case 0x0A: goto yy62;
+ case 0x0D: goto yy64;
default: goto yy66;
}
-yy61:yy62: yych = *++YYCURSOR;
+yy61:yy62: ++YYCURSOR;
+ goto yy63;
yy63:
-#line 413
- { CHK_NL(YYCURSOR);
+#line 412 "bytecode.re"
+{ CHK_NL(YYCURSOR);
goto Document; }
-yy64: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy67;
+#line 936 "<stdout>"
+yy64: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy67;
default: goto yy65;
}
yy65:
-#line 416
- { goto Comment; }
+#line 415 "bytecode.re"
+{ goto Comment; }
+#line 945 "<stdout>"
yy66: yych = *++YYCURSOR;
goto yy65;
-yy67: yych = *++YYCURSOR;
+yy67: ++YYCURSOR;
+ yych = *YYCURSOR;
goto yy63;
}
-#line 418
+#line 417 "bytecode.re"
}
@@ -927,48 +966,53 @@ Scalar:
Scalar2:
tok = YYCURSOR;
+
+#line 970 "<stdout>"
{
YYCTYPE yych;
- unsigned int yyaccept;
goto yy68;
-yy69: ++YYCURSOR;
+ ++YYCURSOR;
yy68:
if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy74;
- case '\n': goto yy70;
- case '\r': goto yy72;
+ case 0x00: goto yy74;
+ case 0x0A: goto yy70;
+ case 0x0D: goto yy72;
default: goto yy76;
}
-yy70: yych = *++YYCURSOR;
- switch(yych){
+yy70: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
case 'C': goto yy78;
case 'N': goto yy80;
case 'Z': goto yy83;
default: goto yy71;
}
yy71:
-#line 462
- { YYCURSOR = tok;
+#line 461 "bytecode.re"
+{ YYCURSOR = tok;
goto ScalarEnd;
}
-yy72: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy77;
+#line 996 "<stdout>"
+yy72: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy77;
default: goto yy73;
}
yy73:
-#line 470
- { CAT(str, cap, idx, tok[0]);
+#line 469 "bytecode.re"
+{ CAT(str, cap, idx, tok[0]);
goto Scalar2;
}
-yy74: yych = *++YYCURSOR;
+#line 1007 "<stdout>"
+yy74: ++YYCURSOR;
+ goto yy75;
yy75:
-#line 466
- { YYCURSOR = tok;
+#line 465 "bytecode.re"
+{ YYCURSOR = tok;
goto ScalarEnd;
}
+#line 1015 "<stdout>"
yy76: yych = *++YYCURSOR;
goto yy73;
yy77: yych = *++YYCURSOR;
@@ -978,14 +1022,17 @@ yy77: yych = *++YYCURSOR;
case 'Z': goto yy83;
default: goto yy71;
}
-yy78: yych = *++YYCURSOR;
+yy78: ++YYCURSOR;
+ goto yy79;
yy79:
-#line 436
- { CHK_NL(tok+1);
+#line 435 "bytecode.re"
+{ CHK_NL(tok+1);
goto Scalar2; }
+#line 1031 "<stdout>"
yy80: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
+ goto yy81;
yy81: switch(yych){
case '0':
case '1':
@@ -1000,8 +1047,8 @@ yy81: switch(yych){
default: goto yy82;
}
yy82:
-#line 439
- { CHK_NL(tok+1);
+#line 438 "bytecode.re"
+{ CHK_NL(tok+1);
if ( tok + 2 < YYCURSOR )
{
char *count = tok + 2;
@@ -1018,15 +1065,18 @@ yy82:
}
goto Scalar2;
}
-yy83: yych = *++YYCURSOR;
+#line 1068 "<stdout>"
+yy83: ++YYCURSOR;
+ goto yy84;
yy84:
-#line 457
- { CHK_NL(tok+1);
+#line 456 "bytecode.re"
+{ CHK_NL(tok+1);
CAT(str, cap, idx, '\0');
goto Scalar2;
}
+#line 1077 "<stdout>"
}
-#line 474
+#line 473 "bytecode.re"
ScalarEnd:
@@ -1060,47 +1110,54 @@ Inline:
{
tok = YYCURSOR;
+
+#line 1114 "<stdout>"
{
YYCTYPE yych;
- unsigned int yyaccept;
goto yy85;
-yy86: ++YYCURSOR;
+ ++YYCURSOR;
yy85:
if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy91;
- case '\n': goto yy87;
- case '\r': goto yy89;
+ case 0x00: goto yy91;
+ case 0x0A: goto yy87;
+ case 0x0D: goto yy89;
default: goto yy93;
}
-yy87: yych = *++YYCURSOR;
+yy87: ++YYCURSOR;
+ goto yy88;
yy88:
-#line 509
- { CHK_NL(YYCURSOR);
+#line 508 "bytecode.re"
+{ CHK_NL(YYCURSOR);
return str; }
-yy89: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy94;
+#line 1134 "<stdout>"
+yy89: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy94;
default: goto yy90;
}
yy90:
-#line 516
- { CAT(str, cap, idx, tok[0]);
+#line 515 "bytecode.re"
+{ CAT(str, cap, idx, tok[0]);
goto Inline;
}
-yy91: yych = *++YYCURSOR;
+#line 1145 "<stdout>"
+yy91: ++YYCURSOR;
+ goto yy92;
yy92:
-#line 512
- { YYCURSOR = tok;
+#line 511 "bytecode.re"
+{ YYCURSOR = tok;
return str;
}
+#line 1153 "<stdout>"
yy93: yych = *++YYCURSOR;
goto yy90;
-yy94: yych = *++YYCURSOR;
+yy94: ++YYCURSOR;
+ yych = *YYCURSOR;
goto yy88;
}
-#line 520
+#line 519 "bytecode.re"
}
diff --git a/ext/syck/depend b/ext/syck/depend
new file mode 100644
index 0000000000..3eec4de72a
--- /dev/null
+++ b/ext/syck/depend
@@ -0,0 +1,12 @@
+ruby_headers = $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h \
+ $(hdrdir)/missing.h $(hdrdir)/intern.h $(hdrdir)/st.h
+bytecode.o: bytecode.c syck.h gram.h $(ruby_headers)
+emitter.o: emitter.c syck.h $(ruby_headers)
+gram.o: gram.c syck.h $(hdrdir)/st.h
+handler.o: handler.c syck.h $(ruby_headers)
+implicit.o: implicit.c syck.h $(ruby_headers)
+node.o: node.c syck.h $(ruby_headers)
+rubyext.o: rubyext.c syck.h $(ruby_headers)
+syck.o: syck.c syck.h $(ruby_headers)
+token.o: token.c syck.h gram.h $(ruby_headers)
+yaml2byte.o: yaml2byte.c syck.h yamlbyte.h $(ruby_headers)
diff --git a/ext/syck/emitter.c b/ext/syck/emitter.c
index 1cc0ea5075..9c8ab8d49b 100644
--- a/ext/syck/emitter.c
+++ b/ext/syck/emitter.c
@@ -9,24 +9,20 @@
* All Base64 code from Ruby's pack.c.
* Ruby is Copyright (C) 1993-2003 Yukihiro Matsumoto
*/
+#include "ruby.h"
+
#include <stdio.h>
#include <string.h>
#include "syck.h"
-#include "ruby.h"
#define DEFAULT_ANCHOR_FORMAT "id%03d"
+const char hex_table[] =
+"0123456789ABCDEF";
static char b64_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-struct adjust_arg {
- /* Position to start adjusting */
- long startpos;
- /* Adjusting by an offset */
- int offset;
-};
-
/*
* Built-in base64 (from Ruby's pack.c)
*/
@@ -35,7 +31,7 @@ syck_base64enc( char *s, long len )
{
long i = 0;
int padding = '=';
- char *buff = S_ALLOCA_N(char, len * 4 / 3 + 6);
+ char *buff = S_ALLOC_N(char, len * 4 / 3 + 6);
while (len >= 3) {
buff[i++] = b64_table[077 & (*s >> 2)];
@@ -115,25 +111,29 @@ syck_new_emitter()
SyckEmitter *e;
e = S_ALLOC( SyckEmitter );
e->headless = 0;
- e->seq_map = 0;
e->use_header = 0;
e->use_version = 0;
e->sort_keys = 0;
e->anchor_format = NULL;
e->explicit_typing = 0;
e->best_width = 80;
- e->block_style = block_arbitrary;
+ e->style = scalar_none;
e->stage = doc_open;
e->indent = 2;
e->level = -1;
- e->ignore_id = 0;
e->anchors = NULL;
e->markers = NULL;
+ e->anchored = NULL;
e->bufsize = SYCK_BUFFERSIZE;
e->buffer = NULL;
e->marker = NULL;
e->bufpos = 0;
- e->handler = NULL;
+ e->emitter_handler = NULL;
+ e->output_handler = NULL;
+ e->lvl_idx = 0;
+ e->lvl_capa = ALLOC_CT;
+ e->levels = S_ALLOC_N( SyckLevel, e->lvl_capa );
+ syck_emitter_reset_levels( e );
e->bonus = NULL;
return e;
}
@@ -145,13 +145,6 @@ syck_st_free_anchors( char *key, char *name, char *arg )
return ST_CONTINUE;
}
-int
-syck_st_free_markers( char *key, SyckEmitterNode *n, char *arg )
-{
- S_FREE( n );
- return ST_CONTINUE;
-}
-
void
syck_emitter_st_free( SyckEmitter *e )
{
@@ -165,27 +158,94 @@ syck_emitter_st_free( SyckEmitter *e )
e->anchors = NULL;
}
+ if ( e->anchored != NULL )
+ {
+ st_free_table( e->anchored );
+ e->anchored = NULL;
+ }
+
/*
* Free the markers tables
*/
if ( e->markers != NULL )
{
- st_foreach( e->markers, syck_st_free_markers, 0 );
st_free_table( e->markers );
e->markers = NULL;
}
}
+SyckLevel *
+syck_emitter_current_level( SyckEmitter *e )
+{
+ return &e->levels[e->lvl_idx-1];
+}
+
+SyckLevel *
+syck_emitter_parent_level( SyckEmitter *e )
+{
+ return &e->levels[e->lvl_idx-2];
+}
+
+void
+syck_emitter_pop_level( SyckEmitter *e )
+{
+ ASSERT( e != NULL );
+
+ /* The root level should never be popped */
+ if ( e->lvl_idx <= 1 ) return;
+
+ e->lvl_idx -= 1;
+ free( e->levels[e->lvl_idx].domain );
+}
+
+void
+syck_emitter_add_level( SyckEmitter *e, int len, enum syck_level_status status )
+{
+ ASSERT( e != NULL );
+ if ( e->lvl_idx + 1 > e->lvl_capa )
+ {
+ e->lvl_capa += ALLOC_CT;
+ S_REALLOC_N( e->levels, SyckLevel, e->lvl_capa );
+ }
+
+ ASSERT( len > e->levels[e->lvl_idx-1].spaces );
+ e->levels[e->lvl_idx].spaces = len;
+ e->levels[e->lvl_idx].ncount = 0;
+ e->levels[e->lvl_idx].domain = syck_strndup( e->levels[e->lvl_idx-1].domain, strlen( e->levels[e->lvl_idx-1].domain ) );
+ e->levels[e->lvl_idx].status = status;
+ e->levels[e->lvl_idx].anctag = 0;
+ e->lvl_idx += 1;
+}
+
+void
+syck_emitter_reset_levels( SyckEmitter *e )
+{
+ while ( e->lvl_idx > 1 )
+ {
+ syck_emitter_pop_level( e );
+ }
+
+ if ( e->lvl_idx < 1 )
+ {
+ e->lvl_idx = 1;
+ e->levels[0].spaces = -1;
+ e->levels[0].ncount = 0;
+ e->levels[0].domain = syck_strndup( "", 0 );
+ e->levels[0].anctag = 0;
+ }
+ e->levels[0].status = syck_lvl_header;
+}
+
void
-syck_emitter_ignore_id( SyckEmitter *e, SYMID id )
+syck_emitter_handler( SyckEmitter *e, SyckEmitterHandler hdlr )
{
- e->ignore_id = id;
+ e->emitter_handler = hdlr;
}
void
-syck_emitter_handler( SyckEmitter *e, SyckOutputHandler hdlr )
+syck_output_handler( SyckEmitter *e, SyckOutputHandler hdlr )
{
- e->handler = hdlr;
+ e->output_handler = hdlr;
}
void
@@ -195,6 +255,9 @@ syck_free_emitter( SyckEmitter *e )
* Free tables
*/
syck_emitter_st_free( e );
+ syck_emitter_reset_levels( e );
+ S_FREE( e->levels[0].domain );
+ S_FREE( e->levels );
if ( e->buffer != NULL )
{
S_FREE( e->buffer );
@@ -232,9 +295,18 @@ syck_emitter_write( SyckEmitter *e, char *str, long len )
* Flush if at end of buffer
*/
at = e->marker - e->buffer;
- if ( len + at > e->bufsize )
+ if ( len + at >= e->bufsize )
{
syck_emitter_flush( e, 0 );
+ for (;;) {
+ long rest = e->bufsize - (e->marker - e->buffer);
+ if (len <= rest) break;
+ S_MEMCPY( e->marker, str, char, rest );
+ e->marker += rest;
+ str += rest;
+ len -= rest;
+ syck_emitter_flush( e, 0 );
+ }
}
/*
@@ -266,169 +338,905 @@ syck_emitter_flush( SyckEmitter *e, long check_room )
}
/*
+ * Commit buffer.
+ */
+ if ( check_room > e->marker - e->buffer )
+ {
+ check_room = e->marker - e->buffer;
+ }
+ (e->output_handler)( e, e->buffer, check_room );
+ e->bufpos += check_room;
+ e->marker -= check_room;
+}
+
+/*
+ * Start emitting from the given node, check for anchoring and then
+ * issue the callback to the emitter handler.
+ */
+void
+syck_emit( SyckEmitter *e, st_data_t n )
+{
+ SYMID oid;
+ char *anchor_name = NULL;
+ int indent = 0;
+ long x = 0;
+ SyckLevel *lvl = syck_emitter_current_level( e );
+
+ /*
* Determine headers.
*/
- if ( ( e->stage == doc_open && ( e->headless == 0 || e->use_header == 1 ) ) ||
- e->stage == doc_need_header )
+ if ( e->stage == doc_open && ( e->headless == 0 || e->use_header == 1 ) )
{
if ( e->use_version == 1 )
{
char *header = S_ALLOC_N( char, 64 );
S_MEMZERO( header, char, 64 );
sprintf( header, "--- %%YAML:%d.%d ", SYCK_YAML_MAJOR, SYCK_YAML_MINOR );
- (e->handler)( e, header, strlen( header ) );
+ syck_emitter_write( e, header, strlen( header ) );
S_FREE( header );
}
else
{
- (e->handler)( e, "--- ", 4 );
+ syck_emitter_write( e, "--- ", 4 );
}
e->stage = doc_processing;
}
- /*
- * Commit buffer.
- */
- if ( check_room > e->marker - e->buffer )
+ /* Add new level */
+ if ( lvl->spaces >= 0 ) {
+ indent = lvl->spaces + e->indent;
+ }
+ syck_emitter_add_level( e, indent, syck_lvl_open );
+ lvl = syck_emitter_current_level( e );
+
+ /* Look for anchor */
+ if ( e->anchors != NULL &&
+ st_lookup( e->markers, n, (st_data_t *)&oid ) &&
+ st_lookup( e->anchors, (st_data_t)oid, (st_data_t *)&anchor_name ) )
{
- check_room = e->marker - e->buffer;
+ if ( e->anchored == NULL )
+ {
+ e->anchored = st_init_numtable();
+ }
+
+ if ( ! st_lookup( e->anchored, (st_data_t)anchor_name, (st_data_t *)&x ) )
+ {
+ char *an = S_ALLOC_N( char, strlen( anchor_name ) + 3 );
+ sprintf( an, "&%s ", anchor_name );
+ syck_emitter_write( e, an, strlen( anchor_name ) + 2 );
+ free( an );
+
+ x = 1;
+ st_insert( e->anchored, (st_data_t)anchor_name, (st_data_t)x );
+ lvl->anctag = 1;
+ }
+ else
+ {
+ char *an = S_ALLOC_N( char, strlen( anchor_name ) + 2 );
+ sprintf( an, "*%s", anchor_name );
+ syck_emitter_write( e, an, strlen( anchor_name ) + 1 );
+ free( an );
+
+ goto end_emit;
+ }
+ }
+
+ (e->emitter_handler)( e, n );
+
+ /* Pop the level */
+end_emit:
+ syck_emitter_pop_level( e );
+ if ( e->lvl_idx == 1 ) {
+ syck_emitter_write( e, "\n", 1 );
+ e->headless = 0;
+ e->stage = doc_open;
}
- (e->handler)( e, e->buffer, check_room );
- e->bufpos += check_room;
- e->marker -= check_room;
}
/*
- * Emit a simple, unquoted string.
+ * Determine what tag needs to be written, based on the taguri of the node
+ * and the implicit tag which would be assigned to this node. If a tag is
+ * required, write the tag.
*/
-void
-syck_emitter_simple( SyckEmitter *e, char *str, long len )
+void syck_emit_tag( SyckEmitter *e, char *tag, char *ignore )
+{
+ SyckLevel *lvl;
+ if ( tag == NULL ) return;
+ if ( ignore != NULL && syck_tagcmp( tag, ignore ) == 0 && e->explicit_typing == 0 ) return;
+ lvl = syck_emitter_current_level( e );
+
+ /* implicit */
+ if ( strlen( tag ) == 0 ) {
+ syck_emitter_write( e, "! ", 2 );
+
+ /* global types */
+ } else if ( strncmp( tag, "tag:", 4 ) == 0 ) {
+ int taglen = strlen( tag );
+ syck_emitter_write( e, "!", 1 );
+ if ( strncmp( tag + 4, YAML_DOMAIN, strlen( YAML_DOMAIN ) ) == 0 ) {
+ int skip = 4 + strlen( YAML_DOMAIN ) + 1;
+ syck_emitter_write( e, tag + skip, taglen - skip );
+ } else {
+ char *subd = tag + 4;
+ while ( *subd != ':' && *subd != '\0' ) subd++;
+ if ( *subd == ':' ) {
+ if ( subd - tag > ( strlen( YAML_DOMAIN ) + 5 ) &&
+ strncmp( subd - strlen( YAML_DOMAIN ), YAML_DOMAIN, strlen( YAML_DOMAIN ) ) == 0 ) {
+ syck_emitter_write( e, tag + 4, subd - strlen( YAML_DOMAIN ) - ( tag + 4 ) - 1 );
+ syck_emitter_write( e, "/", 1 );
+ syck_emitter_write( e, subd + 1, ( tag + taglen ) - ( subd + 1 ) );
+ } else {
+ syck_emitter_write( e, tag + 4, subd - ( tag + 4 ) );
+ syck_emitter_write( e, "/", 1 );
+ syck_emitter_write( e, subd + 1, ( tag + taglen ) - ( subd + 1 ) );
+ }
+ } else {
+ /* TODO: Invalid tag (no colon after domain) */
+ return;
+ }
+ }
+ syck_emitter_write( e, " ", 1 );
+
+ /* private types */
+ } else if ( strncmp( tag, "x-private:", 10 ) == 0 ) {
+ syck_emitter_write( e, "!!", 2 );
+ syck_emitter_write( e, tag + 10, strlen( tag ) - 10 );
+ syck_emitter_write( e, " ", 1 );
+ }
+ lvl->anctag = 1;
+}
+
+/*
+ * Emit a newline and an appropriately spaced indent.
+ */
+void syck_emit_indent( SyckEmitter *e )
{
- e->seq_map = 0;
- syck_emitter_write( e, str, len );
+ int i;
+ SyckLevel *lvl = syck_emitter_current_level( e );
+ if ( e->bufpos == 0 && ( e->marker - e->buffer ) == 0 ) return;
+ if ( lvl->spaces >= 0 ) {
+ char *spcs = S_ALLOC_N( char, lvl->spaces + 2 );
+
+ spcs[0] = '\n'; spcs[lvl->spaces + 1] = '\0';
+ for ( i = 0; i < lvl->spaces; i++ ) spcs[i+1] = ' ';
+ syck_emitter_write( e, spcs, lvl->spaces + 1 );
+ free( spcs );
+ }
}
+/* Clear the scan */
+#define SCAN_NONE 0
+/* All printable characters? */
+#define SCAN_NONPRINT 1
+/* Any indented lines? */
+#define SCAN_INDENTED 2
+/* Larger than the requested width? */
+#define SCAN_WIDE 4
+/* Opens or closes with whitespace? */
+#define SCAN_WHITEEDGE 8
+/* Contains a newline */
+#define SCAN_NEWLINE 16
+/* Contains a single quote */
+#define SCAN_SINGLEQ 32
+/* Contains a double quote */
+#define SCAN_DOUBLEQ 64
+/* Starts with a token */
+#define SCAN_INDIC_S 128
+/* Contains a flow indicator */
+#define SCAN_INDIC_C 256
+/* Ends without newlines */
+#define SCAN_NONL_E 512
+/* Ends with many newlines */
+#define SCAN_MANYNL_E 1024
+/* Contains flow map indicators */
+#define SCAN_FLOWMAP 2048
+/* Contains flow seq indicators */
+#define SCAN_FLOWSEQ 4096
+/* Contains a valid doc separator */
+#define SCAN_DOCSEP 8192
+
/*
- * Shift the offsets of all applicable anchors
+ * Basic printable test for LATIN-1 characters.
*/
int
-syck_adjust_anchors( char *key, SyckEmitterNode *n, struct adjust_arg *arg )
+syck_scan_scalar( int req_width, char *cursor, long len )
{
- if ( arg->startpos < n->pos )
+ long i = 0, start = 0;
+ int flags = SCAN_NONE;
+
+ if ( len < 1 ) return flags;
+
+ /* c-indicators from the spec */
+ if ( cursor[0] == '[' || cursor[0] == ']' ||
+ cursor[0] == '{' || cursor[0] == '}' ||
+ cursor[0] == '!' || cursor[0] == '*' ||
+ cursor[0] == '&' || cursor[0] == '|' ||
+ cursor[0] == '>' || cursor[0] == '\'' ||
+ cursor[0] == '"' || cursor[0] == '#' ||
+ cursor[0] == '%' || cursor[0] == '@' ||
+ cursor[0] == '&' ) {
+ flags |= SCAN_INDIC_S;
+ }
+ if ( ( cursor[0] == '-' || cursor[0] == ':' ||
+ cursor[0] == '?' || cursor[0] == ',' ) &&
+ ( len == 1 || cursor[1] == ' ' || cursor[1] == '\n' ) )
{
- n->pos += arg->offset;
+ flags |= SCAN_INDIC_S;
}
- return ST_CONTINUE;
-}
+ /* whitespace edges */
+ if ( cursor[len-1] != '\n' ) {
+ flags |= SCAN_NONL_E;
+ } else if ( len > 1 && cursor[len-2] == '\n' ) {
+ flags |= SCAN_MANYNL_E;
+ }
+ if (
+ ( len > 0 && ( cursor[0] == ' ' || cursor[0] == '\t' ) ) ||
+ ( len > 1 && ( cursor[len-1] == ' ' || cursor[len-1] == '\t' ) )
+ ) {
+ flags |= SCAN_WHITEEDGE;
+ }
+
+ /* opening doc sep */
+ if ( len >= 3 && strncmp( cursor, "---", 3 ) == 0 )
+ flags |= SCAN_DOCSEP;
+
+ /* scan string */
+ for ( i = 0; i < len; i++ ) {
+
+ if ( ! ( cursor[i] == 0x9 ||
+ cursor[i] == 0xA ||
+ cursor[i] == 0xD ||
+ ( cursor[i] >= 0x20 && cursor[i] <= 0x7E ) )
+ ) {
+ flags |= SCAN_NONPRINT;
+ }
+ else if ( cursor[i] == '\n' ) {
+ flags |= SCAN_NEWLINE;
+ if ( len - i >= 3 && strncmp( &cursor[i+1], "---", 3 ) == 0 )
+ flags |= SCAN_DOCSEP;
+ if ( cursor[i+1] == ' ' || cursor[i+1] == '\t' )
+ flags |= SCAN_INDENTED;
+ if ( req_width > 0 && i - start > req_width )
+ flags |= SCAN_WIDE;
+ start = i;
+ }
+ else if ( cursor[i] == '\'' )
+ {
+ flags |= SCAN_SINGLEQ;
+ }
+ else if ( cursor[i] == '"' )
+ {
+ flags |= SCAN_DOUBLEQ;
+ }
+ else if ( cursor[i] == ']' )
+ {
+ flags |= SCAN_FLOWSEQ;
+ }
+ else if ( cursor[i] == '}' )
+ {
+ flags |= SCAN_FLOWMAP;
+ }
+ /* remember, if plain collections get implemented, to add nb-plain-flow-char */
+ else if ( ( cursor[i] == ' ' && cursor[i+1] == '#' ) ||
+ ( cursor[i] == ':' &&
+ ( cursor[i+1] == ' ' || cursor[i+1] == '\n' || i == len - 1 ) ) )
+ {
+ flags |= SCAN_INDIC_C;
+ }
+ else if ( cursor[i] == ',' &&
+ ( cursor[i+1] == ' ' || cursor[i+1] == '\n' || i == len - 1 ) )
+ {
+ flags |= SCAN_FLOWMAP;
+ flags |= SCAN_FLOWSEQ;
+ }
+ }
+
+ /* printf( "---STR---\n%s\nFLAGS: %d\n", cursor, flags ); */
+ return flags;
+}
/*
- * call on start of an object's marshalling
- * (handles anchors, returns an alias)
+ * All scalars should be emitted through this function, which determines an appropriate style,
+ * tag and indent.
*/
-char *
-syck_emitter_start_obj( SyckEmitter *e, SYMID oid )
+void syck_emit_scalar( SyckEmitter *e, char *tag, enum scalar_style force_style, int force_indent, int force_width,
+ char keep_nl, char *str, long len )
{
- SyckEmitterNode *n = NULL;
- char *anchor_name = NULL;
+ enum scalar_style favor_style = scalar_literal;
+ SyckLevel *parent = syck_emitter_parent_level( e );
+ SyckLevel *lvl = syck_emitter_current_level( e );
+ int scan = 0;
+ char *implicit;
+
+ if ( str == NULL ) str = "";
- e->level++;
- if ( oid != e->ignore_id )
+ /* No empty nulls as map keys */
+ if ( len == 0 && ( parent->status == syck_lvl_map || parent->status == syck_lvl_imap ) &&
+ parent->ncount % 2 == 1 && syck_tagcmp( tag, "tag:yaml.org,2002:null" ) == 0 )
{
- /*
- * Look for anchors
- */
- if ( e->markers == NULL )
+ str = "~";
+ len = 1;
+ }
+
+ scan = syck_scan_scalar( force_width, str, len );
+ implicit = syck_match_implicit( str, len );
+
+ /* quote strings which default to implicits */
+ implicit = syck_taguri( YAML_DOMAIN, implicit, strlen( implicit ) );
+ if ( syck_tagcmp( tag, implicit ) != 0 && syck_tagcmp( tag, "tag:yaml.org,2002:str" ) == 0 ) {
+ force_style = scalar_2quote;
+ } else {
+ /* complex key */
+ if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 &&
+ ( !( tag == NULL ||
+ ( implicit != NULL && syck_tagcmp( tag, implicit ) == 0 && e->explicit_typing == 0 ) ) ) )
{
- e->markers = st_init_numtable();
+ syck_emitter_write( e, "? ", 2 );
+ parent->status = syck_lvl_mapx;
}
+ syck_emit_tag( e, tag, implicit );
+ }
+ S_FREE( implicit );
- /*
- * Markers table initially marks the string position of the
- * object. Doesn't yet create an anchor, simply notes the
- * position.
- */
- if ( ! st_lookup( e->markers, (st_data_t)oid, (st_data_t *)&n ) )
+ /* if still arbitrary, sniff a good block style. */
+ if ( force_style == scalar_none ) {
+ if ( scan & SCAN_NEWLINE ) {
+ force_style = scalar_literal;
+ } else {
+ force_style = scalar_plain;
+ }
+ }
+
+ if ( e->style == scalar_fold ) {
+ favor_style = scalar_fold;
+ }
+
+ /* Determine block style */
+ if ( scan & SCAN_NONPRINT ) {
+ force_style = scalar_2quote;
+ } else if ( scan & SCAN_WHITEEDGE ) {
+ force_style = scalar_2quote;
+ } else if ( force_style != scalar_fold && ( scan & SCAN_INDENTED ) ) {
+ force_style = scalar_literal;
+ } else if ( force_style == scalar_plain && ( scan & SCAN_NEWLINE ) ) {
+ force_style = favor_style;
+ } else if ( force_style == scalar_plain && parent->status == syck_lvl_iseq && ( scan & SCAN_FLOWSEQ ) ) {
+ force_style = scalar_2quote;
+ } else if ( force_style == scalar_plain && parent->status == syck_lvl_imap && ( scan & SCAN_FLOWMAP ) ) {
+ force_style = scalar_2quote;
+ /* } else if ( force_style == scalar_fold && ( ! ( scan & SCAN_WIDE ) ) ) {
+ force_style = scalar_literal; */
+ } else if ( force_style == scalar_plain && ( scan & SCAN_INDIC_S || scan & SCAN_INDIC_C ) ) {
+ if ( scan & SCAN_NEWLINE ) {
+ force_style = favor_style;
+ } else {
+ force_style = scalar_2quote;
+ }
+ }
+
+ if ( force_indent > 0 ) {
+ lvl->spaces = parent->spaces + force_indent;
+ } else if ( scan & SCAN_DOCSEP ) {
+ lvl->spaces = parent->spaces + e->indent;
+ }
+
+ /* For now, all ambiguous keys are going to be double-quoted */
+ if ( ( parent->status == syck_lvl_map || parent->status == syck_lvl_mapx ) && parent->ncount % 2 == 1 ) {
+ if ( force_style != scalar_plain ) {
+ force_style = scalar_2quote;
+ }
+ }
+
+ /* If the parent is an inline, double quote anything complex */
+ if ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) {
+ if ( force_style != scalar_plain && force_style != scalar_1quote ) {
+ force_style = scalar_2quote;
+ }
+ }
+
+ /* Fix the ending newlines */
+ if ( scan & SCAN_NONL_E ) {
+ keep_nl = NL_CHOMP;
+ } else if ( scan & SCAN_MANYNL_E ) {
+ keep_nl = NL_KEEP;
+ }
+
+ /* Write the text node */
+ switch ( force_style )
+ {
+ case scalar_1quote:
+ syck_emit_1quoted( e, force_width, str, len );
+ break;
+
+ case scalar_none:
+ case scalar_2quote:
+ syck_emit_2quoted( e, force_width, str, len );
+ break;
+
+ case scalar_fold:
+ syck_emit_folded( e, force_width, keep_nl, str, len );
+ break;
+
+ case scalar_literal:
+ syck_emit_literal( e, keep_nl, str, len );
+ break;
+
+ case scalar_plain:
+ syck_emitter_write( e, str, len );
+ break;
+ }
+
+ if ( parent->status == syck_lvl_mapx )
+ {
+ syck_emitter_write( e, "\n", 1 );
+ }
+}
+
+void
+syck_emitter_escape( SyckEmitter *e, char *src, long len )
+{
+ int i;
+ for( i = 0; i < len; i++ )
+ {
+ if( (src[i] < 0x20) || (0x7E < src[i]) )
{
- /*
- * Store all markers
- */
- n = S_ALLOC( SyckEmitterNode );
- n->is_shortcut = 0;
- n->indent = e->level * e->indent;
- n->pos = e->bufpos + ( e->marker - e->buffer );
- st_insert( e->markers, (st_data_t)oid, (st_data_t)n );
+ syck_emitter_write( e, "\\", 1 );
+ if( '\0' == src[i] )
+ syck_emitter_write( e, "0", 1 );
+ else
+ {
+ syck_emitter_write( e, "x", 1 );
+ syck_emitter_write( e, (char *)hex_table + ((src[i] & 0xF0) >> 4), 1 );
+ syck_emitter_write( e, (char *)hex_table + (src[i] & 0x0F), 1 );
+ }
}
else
{
- if ( e->anchors == NULL )
- {
- e->anchors = st_init_numtable();
+ syck_emitter_write( e, src + i, 1 );
+ if( '\\' == src[i] )
+ syck_emitter_write( e, "\\", 1 );
+ }
+ }
+}
+
+/*
+ * Outputs a single-quoted block.
+ */
+void syck_emit_1quoted( SyckEmitter *e, int width, char *str, long len )
+{
+ char do_indent = 0;
+ char *mark = str;
+ char *start = str;
+ char *end = str;
+ syck_emitter_write( e, "'", 1 );
+ while ( mark < str + len ) {
+ if ( do_indent ) {
+ syck_emit_indent( e );
+ do_indent = 0;
+ }
+ switch ( *mark ) {
+ case '\'': syck_emitter_write( e, "'", 1 ); break;
+
+ case '\n':
+ end = mark + 1;
+ if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) {
+ syck_emitter_write( e, "\n\n", 2 );
+ } else {
+ syck_emitter_write( e, "\n", 1 );
+ }
+ do_indent = 1;
+ start = mark + 1;
+ break;
+
+ case ' ':
+ if ( width > 0 && *start != ' ' && mark - end > width ) {
+ do_indent = 1;
+ end = mark + 1;
+ } else {
+ syck_emitter_write( e, " ", 1 );
+ }
+ break;
+
+ default:
+ syck_emitter_write( e, mark, 1 );
+ break;
+ }
+ mark++;
+ }
+ syck_emitter_write( e, "'", 1 );
+}
+
+/*
+ * Outputs a double-quoted block.
+ */
+void syck_emit_2quoted( SyckEmitter *e, int width, char *str, long len )
+{
+ char do_indent = 0;
+ char *mark = str;
+ char *start = str;
+ char *end = str;
+ syck_emitter_write( e, "\"", 1 );
+ while ( mark < str + len ) {
+ if ( do_indent > 0 ) {
+ if ( do_indent == 2 ) {
+ syck_emitter_write( e, "\\", 1 );
}
+ syck_emit_indent( e );
+ do_indent = 0;
+ }
+ switch ( *mark ) {
- if ( ! st_lookup( e->anchors, (st_data_t)oid, (st_data_t *)&anchor_name ) )
- {
- int idx = 0;
- /*
- * Second time hitting this object, let's give it an anchor
- */
- idx = e->anchors->num_entries + 1;
-
- /*
- * Create the anchor tag
- */
- if ( n->pos >= e->bufpos )
- {
- int alen;
- struct adjust_arg *args = S_ALLOC( struct adjust_arg );
- char *start = e->buffer + ( n->pos - e->bufpos );
-
- char *anc = ( e->anchor_format == NULL ? DEFAULT_ANCHOR_FORMAT : e->anchor_format );
- anchor_name = S_ALLOC_N( char, strlen( anc ) + 10 );
- S_MEMZERO( anchor_name, char, strlen( anc ) + 10 );
- sprintf( anchor_name, anc, idx );
-
- /*
- * Need to flush the buffer some, if there is not room for the anchor.
- */
- alen = strlen( anchor_name ) + 2;
- syck_emitter_flush( e, alen );
-
- /*
- * Write the anchor into the buffer
- */
- S_MEMMOVE( start + alen, start, char, e->marker - start );
- S_MEMCPY( start + 1, anchor_name, char, strlen( anchor_name ) );
- start[0] = '&';
- start[alen - 1] = ' ';
- e->marker += alen;
-
- /*
- * Cycle through anchors, modify for the size of the anchor.
- */
- args->startpos = n->pos;
- args->offset = alen;
- st_foreach( e->markers, syck_adjust_anchors, (st_data_t)args );
- S_FREE( args );
-
- /*
- * Insert into anchors table
- */
- st_insert( e->anchors, (st_data_t)oid, (st_data_t)anchor_name );
+ /* Escape sequences allowed within double quotes. */
+ case '"': syck_emitter_write( e, "\\\"", 2 ); break;
+ case '\\': syck_emitter_write( e, "\\\\", 2 ); break;
+ case '\0': syck_emitter_write( e, "\\0", 2 ); break;
+ case '\a': syck_emitter_write( e, "\\a", 2 ); break;
+ case '\b': syck_emitter_write( e, "\\b", 2 ); break;
+ case '\f': syck_emitter_write( e, "\\f", 2 ); break;
+ case '\r': syck_emitter_write( e, "\\r", 2 ); break;
+ case '\t': syck_emitter_write( e, "\\t", 2 ); break;
+ case '\v': syck_emitter_write( e, "\\v", 2 ); break;
+ case 0x1b: syck_emitter_write( e, "\\e", 2 ); break;
+
+ case '\n':
+ end = mark + 1;
+ syck_emitter_write( e, "\\n", 2 );
+ do_indent = 2;
+ start = mark + 1;
+ if ( start < str + len && ( *start == ' ' || *start == '\n' ) ) {
+ do_indent = 0;
+ }
+ break;
+
+ case ' ':
+ if ( width > 0 && *start != ' ' && mark - end > width ) {
+ do_indent = 1;
+ end = mark + 1;
+ } else {
+ syck_emitter_write( e, " ", 1 );
}
+ break;
+
+ default:
+ syck_emitter_escape( e, mark, 1 );
+ break;
+ }
+ mark++;
+ }
+ syck_emitter_write( e, "\"", 1 );
+}
+
+/*
+ * Outputs a literal block.
+ */
+void syck_emit_literal( SyckEmitter *e, char keep_nl, char *str, long len )
+{
+ char *mark = str;
+ char *start = str;
+ char *end = str;
+ syck_emitter_write( e, "|", 1 );
+ if ( keep_nl == NL_CHOMP ) {
+ syck_emitter_write( e, "-", 1 );
+ } else if ( keep_nl == NL_KEEP ) {
+ syck_emitter_write( e, "+", 1 );
+ }
+ syck_emit_indent( e );
+ while ( mark < str + len ) {
+ if ( *mark == '\n' ) {
+ end = mark;
+ if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) end += 1;
+ syck_emitter_write( e, start, end - start );
+ if ( mark + 1 == str + len ) {
+ if ( keep_nl != NL_KEEP ) syck_emitter_write( e, "\n", 1 );
+ } else {
+ syck_emit_indent( e );
}
+ start = mark + 1;
+ }
+ mark++;
+ }
+ end = str + len;
+ if ( start < end ) {
+ syck_emitter_write( e, start, end - start );
+ }
+}
+
+/*
+ * Outputs a folded block.
+ */
+void syck_emit_folded( SyckEmitter *e, int width, char keep_nl, char *str, long len )
+{
+ char *mark = str;
+ char *start = str;
+ char *end = str;
+ syck_emitter_write( e, ">", 1 );
+ if ( keep_nl == NL_CHOMP ) {
+ syck_emitter_write( e, "-", 1 );
+ } else if ( keep_nl == NL_KEEP ) {
+ syck_emitter_write( e, "+", 1 );
+ }
+ syck_emit_indent( e );
+ if ( width <= 0 ) width = e->best_width;
+ while ( mark < str + len ) {
+ switch ( *mark ) {
+ case '\n':
+ syck_emitter_write( e, end, mark - end );
+ end = mark + 1;
+ if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) {
+ syck_emitter_write( e, "\n", 1 );
+ }
+ if ( mark + 1 == str + len ) {
+ if ( keep_nl != NL_KEEP ) syck_emitter_write( e, "\n", 1 );
+ } else {
+ syck_emit_indent( e );
+ }
+ start = mark + 1;
+ break;
+ case ' ':
+ if ( *start != ' ' ) {
+ if ( mark - end > width ) {
+ syck_emitter_write( e, end, mark - end );
+ syck_emit_indent( e );
+ end = mark + 1;
+ }
+ }
+ break;
}
+ mark++;
+ }
+ if ( end < mark ) {
+ syck_emitter_write( e, end, mark - end );
}
+}
- return anchor_name;
+/*
+ * Begins emission of a sequence.
+ */
+void syck_emit_seq( SyckEmitter *e, char *tag, enum seq_style style )
+{
+ SyckLevel *parent = syck_emitter_parent_level( e );
+ SyckLevel *lvl = syck_emitter_current_level( e );
+ syck_emit_tag( e, tag, "tag:yaml.org,2002:seq" );
+ if ( style == seq_inline || ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) ) {
+ syck_emitter_write( e, "[", 1 );
+ lvl->status = syck_lvl_iseq;
+ } else {
+ /* complex key */
+ if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 ) {
+ syck_emitter_write( e, "? ", 2 );
+ parent->status = syck_lvl_mapx;
+ }
+ lvl->status = syck_lvl_seq;
+ }
}
/*
- * call on completion of an object's marshalling
+ * Begins emission of a mapping.
*/
-void
-syck_emitter_end_obj( SyckEmitter *e )
+void syck_emit_map( SyckEmitter *e, char *tag, enum map_style style )
+{
+ SyckLevel *parent = syck_emitter_parent_level( e );
+ SyckLevel *lvl = syck_emitter_current_level( e );
+ syck_emit_tag( e, tag, "tag:yaml.org,2002:map" );
+ if ( style == map_inline || ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) ) {
+ syck_emitter_write( e, "{", 1 );
+ lvl->status = syck_lvl_imap;
+ } else {
+ /* complex key */
+ if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 ) {
+ syck_emitter_write( e, "? ", 2 );
+ parent->status = syck_lvl_mapx;
+ }
+ lvl->status = syck_lvl_map;
+ }
+}
+
+/*
+ * Handles emitting of a collection item (for both
+ * sequences and maps)
+ */
+void syck_emit_item( SyckEmitter *e, st_data_t n )
+{
+ SyckLevel *lvl = syck_emitter_current_level( e );
+ switch ( lvl->status )
+ {
+ case syck_lvl_seq:
+ {
+ SyckLevel *parent = syck_emitter_parent_level( e );
+
+ /* seq-in-map shortcut -- the lvl->anctag check should be unneccesary but
+ * there is a nasty shift/reduce in the parser on this point and
+ * i'm not ready to tickle it. */
+ if ( lvl->anctag == 0 && parent->status == syck_lvl_map && lvl->ncount == 0 ) {
+ lvl->spaces = parent->spaces;
+ }
+
+ /* seq-in-seq shortcut */
+ else if ( lvl->anctag == 0 && parent->status == syck_lvl_seq && lvl->ncount == 0 ) {
+ int spcs = ( lvl->spaces - parent->spaces ) - 2;
+ if ( spcs >= 0 ) {
+ int i = 0;
+ for ( i = 0; i < spcs; i++ ) {
+ syck_emitter_write( e, " ", 1 );
+ }
+ syck_emitter_write( e, "- ", 2 );
+ break;
+ }
+ }
+
+ syck_emit_indent( e );
+ syck_emitter_write( e, "- ", 2 );
+ }
+ break;
+
+ case syck_lvl_iseq:
+ {
+ if ( lvl->ncount > 0 ) {
+ syck_emitter_write( e, ", ", 2 );
+ }
+ }
+ break;
+
+ case syck_lvl_map:
+ {
+ SyckLevel *parent = syck_emitter_parent_level( e );
+
+ /* map-in-seq shortcut */
+ if ( lvl->anctag == 0 && parent->status == syck_lvl_seq && lvl->ncount == 0 ) {
+ int spcs = ( lvl->spaces - parent->spaces ) - 2;
+ if ( spcs >= 0 ) {
+ int i = 0;
+ for ( i = 0; i < spcs; i++ ) {
+ syck_emitter_write( e, " ", 1 );
+ }
+ break;
+ }
+ }
+
+ if ( lvl->ncount % 2 == 0 ) {
+ syck_emit_indent( e );
+ } else {
+ syck_emitter_write( e, ": ", 2 );
+ }
+ }
+ break;
+
+ case syck_lvl_mapx:
+ {
+ if ( lvl->ncount % 2 == 0 ) {
+ syck_emit_indent( e );
+ lvl->status = syck_lvl_map;
+ } else {
+ int i;
+ if ( lvl->spaces > 0 ) {
+ char *spcs = S_ALLOC_N( char, lvl->spaces + 1 );
+
+ spcs[lvl->spaces] = '\0';
+ for ( i = 0; i < lvl->spaces; i++ ) spcs[i] = ' ';
+ syck_emitter_write( e, spcs, lvl->spaces );
+ S_FREE( spcs );
+ }
+ syck_emitter_write( e, ": ", 2 );
+ }
+ }
+ break;
+
+ case syck_lvl_imap:
+ {
+ if ( lvl->ncount > 0 ) {
+ if ( lvl->ncount % 2 == 0 ) {
+ syck_emitter_write( e, ", ", 2 );
+ } else {
+ syck_emitter_write( e, ": ", 2 );
+ }
+ }
+ }
+ break;
+
+ default: break;
+ }
+ lvl->ncount++;
+
+ syck_emit( e, n );
+}
+
+/*
+ * Closes emission of a collection.
+ */
+void syck_emit_end( SyckEmitter *e )
{
- e->level--;
+ SyckLevel *lvl = syck_emitter_current_level( e );
+ SyckLevel *parent = syck_emitter_parent_level( e );
+ switch ( lvl->status )
+ {
+ case syck_lvl_seq:
+ if ( lvl->ncount == 0 ) {
+ syck_emitter_write( e, "[]\n", 3 );
+ } else if ( parent->status == syck_lvl_mapx ) {
+ syck_emitter_write( e, "\n", 1 );
+ }
+ break;
+
+ case syck_lvl_iseq:
+ syck_emitter_write( e, "]\n", 1 );
+ break;
+
+ case syck_lvl_map:
+ if ( lvl->ncount == 0 ) {
+ syck_emitter_write( e, "{}\n", 3 );
+ } else if ( lvl->ncount % 2 == 1 ) {
+ syck_emitter_write( e, ":\n", 1 );
+ } else if ( parent->status == syck_lvl_mapx ) {
+ syck_emitter_write( e, "\n", 1 );
+ }
+ break;
+
+ case syck_lvl_imap:
+ syck_emitter_write( e, "}\n", 1 );
+ break;
+
+ default: break;
+ }
+}
+
+/*
+ * Fill markers table with emitter nodes in the
+ * soon-to-be-emitted tree.
+ */
+SYMID
+syck_emitter_mark_node( SyckEmitter *e, st_data_t n )
+{
+ SYMID oid = 0;
+ char *anchor_name = NULL;
+
+ /*
+ * Ensure markers table is initialized.
+ */
+ if ( e->markers == NULL )
+ {
+ e->markers = st_init_numtable();
+ }
+
+ /*
+ * Markers table initially marks the string position of the
+ * object. Doesn't yet create an anchor, simply notes the
+ * position.
+ */
+ if ( ! st_lookup( e->markers, n, (st_data_t *)&oid ) )
+ {
+ /*
+ * Store all markers
+ */
+ oid = e->markers->num_entries + 1;
+ st_insert( e->markers, n, (st_data_t)oid );
+ }
+ else
+ {
+ if ( e->anchors == NULL )
+ {
+ e->anchors = st_init_numtable();
+ }
+
+ if ( ! st_lookup( e->anchors, (st_data_t)oid, (st_data_t *)&anchor_name ) )
+ {
+ int idx = 0;
+ char *anc = ( e->anchor_format == NULL ? DEFAULT_ANCHOR_FORMAT : e->anchor_format );
+
+ /*
+ * Second time hitting this object, let's give it an anchor
+ */
+ idx = e->anchors->num_entries + 1;
+ anchor_name = S_ALLOC_N( char, strlen( anc ) + 10 );
+ S_MEMZERO( anchor_name, char, strlen( anc ) + 10 );
+ sprintf( anchor_name, anc, idx );
+
+ /*
+ * Insert into anchors table
+ */
+ st_insert( e->anchors, (st_data_t)oid, (st_data_t)anchor_name );
+ }
+ }
+ return oid;
}
diff --git a/ext/syck/gram.c b/ext/syck/gram.c
index 5bdd025629..615a594f61 100644
--- a/ext/syck/gram.c
+++ b/ext/syck/gram.c
@@ -1,7 +1,7 @@
-/* A Bison parser, made from gram.y, by GNU bison 1.75. */
+/* A Bison parser, made by GNU Bison 1.875d. */
/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -34,10 +34,13 @@
USER NAME SPACE" below. */
/* Identify Bison output. */
-#define YYBISON 1
+#define YYBISON 1
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
/* Pure parsers. */
-#define YYPURE 1
+#define YYPURE 1
/* Using locations. */
#define YYLSP_NEEDED 0
@@ -95,9 +98,21 @@
#include "syck.h"
+void apply_seq_in_map( SyckParser *parser, SyckNode *n );
+
#define YYPARSE_PARAM parser
#define YYLEX_PARAM parser
+#define NULL_NODE(parser, node) \
+ SyckNode *node = syck_new_str( "", scalar_plain ); \
+ if ( ((SyckParser *)parser)->taguri_expansion == 1 ) \
+ { \
+ node->type_id = syck_taguri( YAML_DOMAIN, "null", 4 ); \
+ } \
+ else \
+ { \
+ node->type_id = syck_strndup( "null", 4 ); \
+ }
/* Enabling traces. */
@@ -113,52 +128,49 @@
# define YYERROR_VERBOSE 0
#endif
-#ifndef YYSTYPE
-#line 23 "gram.y"
-typedef union {
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#line 35 "gram.y"
+typedef union YYSTYPE {
SYMID nodeId;
SyckNode *nodeData;
char *name;
-} yystype;
-/* Line 193 of /usr/local/share/bison/yacc.c. */
-#line 125 "y.tab.c"
-# define YYSTYPE yystype
+} YYSTYPE;
+/* Line 191 of yacc.c. */
+#line 140 "gram.c"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
-#ifndef YYLTYPE
-typedef struct yyltype
-{
- int first_line;
- int first_column;
- int last_line;
- int last_column;
-} yyltype;
-# define YYLTYPE yyltype
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
+
/* Copy the second part of user declarations. */
-int sycklex( YYSTYPE *, SyckParser * );
-/* Line 213 of /usr/local/share/bison/yacc.c. */
-#line 146 "y.tab.c"
+/* Line 214 of yacc.c. */
+#line 152 "gram.c"
#if ! defined (yyoverflow) || YYERROR_VERBOSE
+# ifndef YYFREE
+# define YYFREE free
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# endif
+
/* The parser invokes alloca or malloc; define the necessary symbols. */
-# if YYSTACK_USE_ALLOCA
-# define YYSTACK_ALLOC alloca
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# define YYSTACK_ALLOC alloca
+# endif
# else
-# ifndef YYSTACK_USE_ALLOCA
-# if defined (alloca) || defined (_ALLOCA_H)
-# define YYSTACK_ALLOC alloca
-# else
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# endif
+# if defined (alloca) || defined (_ALLOCA_H)
+# define YYSTACK_ALLOC alloca
+# else
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
# endif
# endif
# endif
@@ -171,36 +183,36 @@ int sycklex( YYSTYPE *, SyckParser * );
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# endif
-# define YYSTACK_ALLOC malloc
-# define YYSTACK_FREE free
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
# endif
#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
#if (! defined (yyoverflow) \
&& (! defined (__cplusplus) \
- || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- short yyss;
+ short int yyss;
YYSTYPE yyvs;
};
/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (short) + sizeof (YYSTYPE)) \
- + YYSTACK_GAP_MAX)
+ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
/* Copy COUNT objects from FROM to TO. The source and destination do
not overlap. */
# ifndef YYCOPY
-# if 1 < __GNUC__
+# if defined (__GNUC__) && 1 < __GNUC__
# define YYCOPY(To, From, Count) \
__builtin_memcpy (To, From, (Count) * sizeof (*(From)))
# else
@@ -209,7 +221,7 @@ union yyalloc
{ \
register YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
+ (To)[yyi] = (From)[yyi]; \
} \
while (0)
# endif
@@ -226,7 +238,7 @@ union yyalloc
YYSIZE_T yynewbytes; \
YYCOPY (&yyptr->Stack, Stack, yysize); \
Stack = &yyptr->Stack; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
while (0)
@@ -236,28 +248,29 @@ union yyalloc
#if defined (__STDC__) || defined (__cplusplus)
typedef signed char yysigned_char;
#else
- typedef short yysigned_char;
+ typedef short int yysigned_char;
#endif
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 38
-#define YYLAST 414
+#define YYFINAL 52
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 396
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 23
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 25
+#define YYNNTS 29
/* YYNRULES -- Number of rules. */
-#define YYNRULES 69
+#define YYNRULES 79
/* YYNRULES -- Number of states. */
-#define YYNSTATES 121
+#define YYNSTATES 128
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 269
-#define YYTRANSLATE(X) \
- ((unsigned)(X) <= YYMAXUTOK ? yytranslate[X] : YYUNDEFTOK)
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
static const unsigned char yytranslate[] =
@@ -297,50 +310,54 @@ static const unsigned char yytranslate[] =
static const unsigned char yyprhs[] =
{
0, 0, 3, 5, 8, 9, 11, 13, 15, 18,
- 22, 26, 28, 31, 32, 34, 37, 39, 41, 43,
- 46, 49, 52, 55, 58, 60, 62, 64, 67, 70,
- 72, 74, 76, 78, 80, 84, 87, 89, 93, 96,
- 100, 103, 107, 110, 112, 116, 119, 123, 126, 128,
- 132, 136, 140, 144, 147, 151, 154, 158, 161, 165,
- 167, 173, 175, 179, 183, 186, 190, 194, 197, 199
+ 21, 24, 28, 30, 32, 36, 37, 40, 43, 46,
+ 49, 51, 54, 56, 58, 60, 63, 66, 69, 72,
+ 75, 77, 79, 81, 85, 87, 89, 91, 93, 95,
+ 99, 103, 106, 110, 113, 117, 120, 124, 127, 129,
+ 133, 136, 140, 143, 145, 149, 151, 153, 157, 161,
+ 165, 168, 172, 175, 179, 182, 184, 188, 190, 194,
+ 196, 200, 204, 207, 211, 215, 218, 220, 224, 226
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yysigned_char yyrhs[] =
{
- 24, 0, -1, 33, -1, 11, 27, -1, -1, 32,
- -1, 26, -1, 33, -1, 3, 26, -1, 28, 32,
- 31, -1, 28, 26, 31, -1, 25, -1, 28, 29,
- -1, -1, 12, -1, 28, 13, -1, 14, -1, 13,
- -1, 14, -1, 30, 31, -1, 5, 32, -1, 6,
- 32, -1, 7, 32, -1, 3, 32, -1, 4, -1,
- 8, -1, 9, -1, 5, 33, -1, 6, 33, -1,
- 10, -1, 34, -1, 38, -1, 40, -1, 46, -1,
- 28, 36, 29, -1, 15, 27, -1, 37, -1, 5,
- 30, 36, -1, 5, 36, -1, 6, 30, 36, -1,
- 6, 36, -1, 3, 30, 36, -1, 3, 36, -1,
- 35, -1, 37, 30, 35, -1, 37, 30, -1, 17,
- 39, 18, -1, 17, 18, -1, 25, -1, 39, 21,
- 25, -1, 28, 41, 29, -1, 28, 44, 29, -1,
- 5, 30, 44, -1, 5, 41, -1, 6, 30, 44,
- -1, 6, 41, -1, 3, 30, 44, -1, 3, 41,
- -1, 32, 16, 27, -1, 42, -1, 22, 25, 30,
- 16, 27, -1, 43, -1, 44, 30, 35, -1, 44,
- 30, 43, -1, 44, 30, -1, 25, 16, 27, -1,
- 19, 47, 20, -1, 19, 20, -1, 45, -1, 47,
- 21, 45, -1
+ 24, 0, -1, 25, -1, 11, 27, -1, -1, 33,
+ -1, 26, -1, 34, -1, 5, 26, -1, 6, 26,
+ -1, 3, 26, -1, 29, 26, 32, -1, 25, -1,
+ 28, -1, 29, 28, 30, -1, -1, 7, 28, -1,
+ 5, 28, -1, 6, 28, -1, 3, 28, -1, 12,
+ -1, 29, 13, -1, 14, -1, 13, -1, 14, -1,
+ 31, 32, -1, 5, 33, -1, 6, 33, -1, 7,
+ 33, -1, 3, 33, -1, 4, -1, 8, -1, 9,
+ -1, 29, 33, 32, -1, 10, -1, 35, -1, 39,
+ -1, 42, -1, 49, -1, 29, 37, 30, -1, 29,
+ 38, 30, -1, 15, 27, -1, 5, 31, 38, -1,
+ 5, 37, -1, 6, 31, 38, -1, 6, 37, -1,
+ 3, 31, 38, -1, 3, 37, -1, 36, -1, 38,
+ 31, 36, -1, 38, 31, -1, 17, 40, 18, -1,
+ 17, 18, -1, 41, -1, 40, 21, 41, -1, 25,
+ -1, 48, -1, 29, 43, 30, -1, 29, 47, 30,
+ -1, 5, 31, 47, -1, 5, 43, -1, 6, 31,
+ 47, -1, 6, 43, -1, 3, 31, 47, -1, 3,
+ 43, -1, 33, -1, 22, 25, 31, -1, 27, -1,
+ 44, 16, 45, -1, 46, -1, 47, 31, 36, -1,
+ 47, 31, 46, -1, 47, 31, -1, 25, 16, 27,
+ -1, 19, 50, 20, -1, 19, 20, -1, 51, -1,
+ 50, 21, 51, -1, 25, -1, 48, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const unsigned short yyrline[] =
+static const unsigned short int yyrline[] =
{
- 0, 44, 44, 48, 52, 58, 59, 62, 63, 72,
- 76, 82, 83, 96, 114, 115, 118, 121, 124, 125,
- 133, 138, 143, 151, 155, 163, 176, 183, 188, 193,
- 194, 195, 196, 197, 203, 209, 215, 216, 221, 226,
- 231, 236, 240, 246, 250, 255, 264, 268, 274, 278,
- 288, 293, 300, 305, 310, 315, 320, 324, 330, 345,
- 346, 354, 355, 367, 374, 383, 391, 395, 401, 402
+ 0, 56, 56, 60, 65, 70, 71, 74, 75, 80,
+ 85, 94, 100, 101, 104, 109, 113, 121, 126, 131,
+ 145, 146, 149, 152, 155, 156, 164, 169, 174, 182,
+ 186, 194, 207, 208, 218, 219, 220, 221, 222, 228,
+ 232, 238, 244, 249, 254, 259, 264, 268, 274, 278,
+ 283, 292, 296, 302, 306, 313, 314, 320, 325, 332,
+ 337, 342, 347, 352, 356, 362, 363, 369, 379, 396,
+ 397, 409, 417, 426, 434, 438, 444, 445, 454, 461
};
#endif
@@ -349,23 +366,24 @@ static const unsigned short yyrline[] =
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "YAML_ANCHOR", "YAML_ALIAS",
- "YAML_TRANSFER", "YAML_TAGURI", "YAML_ITRANSFER", "YAML_WORD",
- "YAML_PLAIN", "YAML_BLOCK", "YAML_DOCSEP", "YAML_IOPEN", "YAML_INDENT",
- "YAML_IEND", "'-'", "':'", "'['", "']'", "'{'", "'}'", "','", "'?'",
- "$accept", "doc", "atom", "ind_rep", "atom_or_empty", "indent_open",
- "indent_end", "indent_sep", "indent_flex_end", "word_rep", "struct_rep",
- "implicit_seq", "basic_seq", "top_imp_seq", "in_implicit_seq",
- "inline_seq", "in_inline_seq", "implicit_map", "top_imp_map",
- "basic_mapping", "complex_mapping", "in_implicit_map", "basic_mapping2",
- "inline_map", "in_inline_map", 0
+ "$end", "error", "$undefined", "YAML_ANCHOR", "YAML_ALIAS",
+ "YAML_TRANSFER", "YAML_TAGURI", "YAML_ITRANSFER", "YAML_WORD",
+ "YAML_PLAIN", "YAML_BLOCK", "YAML_DOCSEP", "YAML_IOPEN", "YAML_INDENT",
+ "YAML_IEND", "'-'", "':'", "'['", "']'", "'{'", "'}'", "','", "'?'",
+ "$accept", "doc", "atom", "ind_rep", "atom_or_empty", "empty",
+ "indent_open", "indent_end", "indent_sep", "indent_flex_end", "word_rep",
+ "struct_rep", "implicit_seq", "basic_seq", "top_imp_seq",
+ "in_implicit_seq", "inline_seq", "in_inline_seq", "inline_seq_atom",
+ "implicit_map", "top_imp_map", "complex_key", "complex_value",
+ "complex_mapping", "in_implicit_map", "basic_mapping", "inline_map",
+ "in_inline_map", "inline_map_atom", 0
};
#endif
# ifdef YYPRINT
/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
token YYLEX-NUM. */
-static const unsigned short yytoknum[] =
+static const unsigned short int yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 45, 58, 91, 93, 123,
@@ -377,24 +395,26 @@ static const unsigned short yytoknum[] =
static const unsigned char yyr1[] =
{
0, 23, 24, 24, 24, 25, 25, 26, 26, 26,
- 26, 27, 27, 27, 28, 28, 29, 30, 31, 31,
- 32, 32, 32, 32, 32, 32, 32, 33, 33, 33,
- 33, 33, 33, 33, 34, 35, 36, 36, 36, 36,
- 36, 36, 36, 37, 37, 37, 38, 38, 39, 39,
- 40, 40, 41, 41, 41, 41, 41, 41, 42, 43,
- 43, 44, 44, 44, 44, 45, 46, 46, 47, 47
+ 26, 26, 27, 27, 28, 28, 28, 28, 28, 28,
+ 29, 29, 30, 31, 32, 32, 33, 33, 33, 33,
+ 33, 33, 33, 33, 34, 34, 34, 34, 34, 35,
+ 35, 36, 37, 37, 37, 37, 37, 37, 38, 38,
+ 38, 39, 39, 40, 40, 41, 41, 42, 42, 43,
+ 43, 43, 43, 43, 43, 44, 44, 45, 46, 47,
+ 47, 47, 47, 48, 49, 49, 50, 50, 51, 51
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const unsigned char yyr2[] =
{
- 0, 2, 1, 2, 0, 1, 1, 1, 2, 3,
- 3, 1, 2, 0, 1, 2, 1, 1, 1, 2,
- 2, 2, 2, 2, 1, 1, 1, 2, 2, 1,
- 1, 1, 1, 1, 3, 2, 1, 3, 2, 3,
- 2, 3, 2, 1, 3, 2, 3, 2, 1, 3,
- 3, 3, 3, 2, 3, 2, 3, 2, 3, 1,
- 5, 1, 3, 3, 2, 3, 3, 2, 1, 3
+ 0, 2, 1, 2, 0, 1, 1, 1, 2, 2,
+ 2, 3, 1, 1, 3, 0, 2, 2, 2, 2,
+ 1, 2, 1, 1, 1, 2, 2, 2, 2, 2,
+ 1, 1, 1, 3, 1, 1, 1, 1, 1, 3,
+ 3, 2, 3, 2, 3, 2, 3, 2, 1, 3,
+ 2, 3, 2, 1, 3, 1, 1, 3, 3, 3,
+ 2, 3, 2, 3, 2, 1, 3, 1, 3, 1,
+ 3, 3, 2, 3, 3, 2, 1, 3, 1, 1
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -402,171 +422,167 @@ static const unsigned char yyr2[] =
means the default is an error. */
static const unsigned char yydefact[] =
{
- 4, 0, 0, 29, 13, 14, 0, 0, 0, 0,
- 2, 30, 31, 32, 33, 27, 28, 0, 24, 0,
- 0, 0, 25, 26, 11, 6, 3, 0, 5, 7,
- 47, 48, 0, 0, 67, 0, 68, 0, 1, 0,
- 0, 0, 15, 13, 0, 0, 43, 0, 36, 0,
- 59, 61, 0, 8, 23, 0, 20, 21, 0, 0,
- 22, 0, 0, 0, 16, 0, 12, 0, 46, 0,
- 13, 66, 0, 17, 0, 42, 57, 0, 38, 53,
- 0, 40, 55, 35, 0, 13, 34, 45, 50, 51,
- 64, 18, 0, 10, 9, 49, 65, 69, 0, 0,
- 0, 41, 56, 37, 52, 39, 54, 0, 58, 44,
- 62, 63, 19, 0, 0, 0, 13, 0, 0, 0,
- 60
+ 4, 0, 30, 0, 0, 0, 31, 32, 34, 15,
+ 20, 0, 0, 0, 2, 6, 0, 5, 7, 35,
+ 36, 37, 38, 10, 29, 8, 26, 9, 27, 0,
+ 0, 0, 0, 28, 15, 15, 15, 15, 12, 3,
+ 13, 15, 52, 55, 0, 53, 56, 75, 78, 79,
+ 0, 76, 1, 0, 0, 0, 21, 15, 0, 0,
+ 65, 48, 0, 0, 0, 0, 69, 0, 0, 19,
+ 17, 18, 15, 15, 15, 16, 15, 15, 15, 15,
+ 0, 15, 51, 0, 74, 0, 23, 0, 47, 64,
+ 0, 43, 60, 0, 45, 62, 41, 0, 24, 0,
+ 11, 33, 22, 39, 40, 50, 57, 15, 58, 72,
+ 14, 73, 54, 77, 65, 46, 63, 42, 59, 44,
+ 61, 66, 25, 49, 67, 68, 70, 71
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yysigned_char yydefgoto[] =
{
- -1, 8, 24, 25, 26, 32, 66, 90, 93, 28,
- 29, 11, 46, 75, 48, 12, 33, 13, 49, 50,
- 51, 52, 36, 14, 37
+ -1, 13, 38, 15, 39, 40, 16, 103, 99, 101,
+ 17, 18, 19, 61, 62, 63, 20, 44, 45, 21,
+ 64, 65, 125, 66, 67, 46, 22, 50, 51
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -68
-static const short yypact[] =
+#define YYPACT_NINF -97
+static const short int yypact[] =
{
- 133, 177, 177, -68, 352, -68, 335, 283, 27, 223,
- -68, -68, -68, -68, -68, -68, -68, 352, -68, 369,
- 369, 97, -68, -68, -68, -68, -68, 154, -68, -68,
- -68, -68, 203, -12, -68, 17, -68, 46, -68, 386,
- 386, 386, -68, 352, 352, 25, -68, 30, 33, 30,
- -68, -68, 67, -68, -68, 97, -68, -68, 97, 97,
- -68, 301, 318, 318, -68, 107, -68, 37, -68, 352,
- 352, -68, 352, -68, 243, -68, -68, 243, -68, -68,
- 243, -68, -68, -68, 33, 352, -68, 40, -68, -68,
- 263, -68, 107, -68, -68, -68, -68, -68, 399, 399,
- 399, -68, 33, -68, 33, -68, 33, 42, -68, -68,
- -68, -68, -68, 84, 84, 84, 352, 9, 9, 9,
- -68
+ 250, 318, -97, 318, 318, 374, -97, -97, -97, 335,
+ -97, 267, 232, 7, -97, -97, 192, -97, -97, -97,
+ -97, -97, -97, -97, -97, -97, -97, -97, -97, 374,
+ 374, 374, 352, -97, 335, 335, 335, 384, -97, -97,
+ -97, 212, -97, 10, 0, -97, -97, -97, 10, -97,
+ -4, -97, -97, 284, 284, 284, -97, 335, 318, 30,
+ 30, -97, -2, 36, -2, 16, -97, 36, 30, -97,
+ -97, -97, 384, 384, 384, -97, 363, 301, 301, 301,
+ -2, 335, -97, 318, -97, 318, -97, 158, -97, -97,
+ 158, -97, -97, 158, -97, -97, -97, 24, -97, 30,
+ -97, -97, -97, -97, -97, 26, -97, 335, -97, 158,
+ -97, -97, -97, -97, -97, 24, 24, 24, 24, 24,
+ 24, -97, -97, -97, -97, -97, -97, -97
};
/* YYPGOTO[NTERM-NUM]. */
static const yysigned_char yypgoto[] =
{
- -68, -68, 10, -9, -38, 0, -7, 86, -56, 56,
- 29, -68, -62, -6, -68, -68, -68, -68, -2, -68,
- -26, -67, -3, -68, -68
+ -97, -97, 8, 81, -56, 109, 33, -53, 74, -54,
+ -1, -97, -97, -96, -31, -32, -97, -97, -44, -97,
+ 77, -97, -97, -52, 9, -6, -97, -97, -29
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, parse error. */
+ If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -1
static const unsigned char yytable[] =
{
- 9, 9, 9, 47, 27, 83, 68, 102, 53, 69,
- 104, 94, 117, 106, 118, 119, 31, 35, 65, 9,
- 9, 47, 73, 65, 43, 109, 47, 38, 110, 10,
- 15, 16, 96, 70, 78, 81, 112, 76, 79, 82,
- 86, 85, 88, 27, 64, 89, 73, 108, 15, 16,
- 73, 91, 53, 85, 84, 43, 78, 81, 116, 76,
- 79, 82, 9, 9, 111, 45, 71, 72, 101, 97,
- 27, 103, 0, 54, 105, 56, 57, 60, 120, 95,
- 73, 64, 35, 67, 0, 27, 0, 117, 67, 118,
- 119, 15, 16, 78, 81, 54, 56, 57, 0, 43,
- 55, 18, 58, 59, 21, 22, 23, 101, 103, 105,
- 0, 54, 78, 81, 56, 57, 27, 54, 56, 57,
- 73, 91, 0, 0, 0, 74, 77, 80, 0, 0,
- 45, 0, 0, 45, 87, 0, 45, 0, 1, 2,
- 0, 0, 0, 3, 4, 5, 45, 74, 77, 80,
- 6, 92, 7, 92, 54, 56, 57, 61, 18, 62,
- 63, 21, 22, 23, 3, 0, 5, 42, 64, 43,
- 107, 6, 0, 7, 0, 0, 44, 0, 92, 0,
- 0, 0, 1, 2, 113, 114, 115, 3, 0, 5,
- 0, 0, 0, 0, 6, 0, 7, 0, 0, 0,
- 0, 0, 0, 113, 114, 115, 61, 18, 62, 63,
- 21, 22, 23, 3, 0, 5, 42, 0, 43, 0,
- 6, 0, 7, 0, 0, 44, 39, 18, 40, 41,
- 21, 22, 23, 0, 0, 0, 42, 0, 43, 0,
- 0, 0, 0, 0, 0, 44, 98, 18, 99, 100,
- 21, 22, 23, 0, 0, 0, 0, 0, 43, 0,
- 0, 0, 0, 0, 0, 44, 55, 18, 58, 59,
- 21, 22, 23, 0, 0, 0, 0, 0, 43, 0,
- 0, 0, 0, 0, 0, 44, 17, 18, 19, 20,
- 21, 22, 23, 3, 0, 5, 0, 0, 0, 0,
- 6, 0, 7, 34, 61, 18, 62, 63, 21, 22,
- 23, 3, 0, 5, 73, 0, 43, 0, 6, 0,
- 7, 39, 18, 62, 63, 21, 22, 23, 3, 0,
- 5, 73, 0, 43, 0, 6, 0, 7, 17, 18,
- 19, 20, 21, 22, 23, 3, 0, 5, 0, 0,
- 0, 0, 6, 30, 7, 17, 18, 19, 20, 21,
- 22, 23, 3, 0, 5, 0, 0, 0, 0, 6,
- 0, 7, 55, 18, 19, 20, 21, 22, 23, 3,
- 0, 5, 0, 0, 0, 0, 6, 0, 7, 39,
- 18, 40, 41, 21, 22, 23, 0, 0, 0, 73,
- 0, 43, 98, 18, 99, 100, 21, 22, 23, 0,
- 0, 0, 73, 0, 43
+ 24, 96, 26, 28, 33, 100, 49, 52, 14, 123,
+ 104, 106, 102, 126, 108, 60, 84, 85, 82, 43,
+ 48, 83, 88, 91, 94, 111, 81, 110, 24, 26,
+ 28, 68, 107, 24, 26, 28, 33, 86, 32, 112,
+ 60, 57, 41, 86, 98, 122, 88, 91, 94, 86,
+ 102, 124, 24, 26, 28, 115, 113, 127, 117, 0,
+ 0, 119, 32, 32, 32, 32, 97, 41, 41, 41,
+ 76, 24, 26, 28, 41, 68, 24, 26, 28, 49,
+ 0, 0, 23, 0, 25, 27, 114, 0, 0, 114,
+ 41, 43, 114, 48, 0, 0, 116, 59, 0, 118,
+ 0, 0, 120, 0, 0, 76, 76, 76, 114, 76,
+ 41, 41, 41, 0, 41, 23, 25, 27, 0, 0,
+ 32, 0, 59, 32, 0, 0, 32, 87, 90, 93,
+ 89, 92, 95, 0, 23, 25, 27, 105, 0, 0,
+ 41, 109, 32, 69, 70, 71, 75, 0, 0, 0,
+ 80, 87, 90, 93, 89, 92, 95, 0, 23, 25,
+ 27, 29, 2, 30, 31, 5, 6, 7, 0, 0,
+ 10, 121, 0, 57, 0, 0, 0, 0, 0, 0,
+ 58, 69, 70, 71, 0, 80, 69, 70, 71, 105,
+ 109, 105, 109, 105, 109, 53, 2, 54, 55, 5,
+ 6, 7, 8, 0, 10, 56, 0, 57, 0, 11,
+ 0, 12, 0, 0, 58, 77, 2, 78, 79, 37,
+ 6, 7, 8, 0, 10, 56, 0, 57, 0, 11,
+ 0, 12, 0, 0, 58, 1, 2, 3, 4, 5,
+ 6, 7, 8, 0, 10, 0, 0, 0, 0, 11,
+ 0, 12, 47, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 0, 0, 0, 0, 11, 0, 12,
+ 1, 2, 3, 4, 5, 6, 7, 8, 0, 10,
+ 0, 0, 0, 0, 11, 42, 12, 53, 2, 54,
+ 55, 5, 6, 7, 8, 0, 10, 86, 0, 0,
+ 0, 11, 0, 12, 77, 2, 78, 79, 37, 6,
+ 7, 8, 0, 10, 86, 0, 0, 0, 11, 0,
+ 12, 1, 2, 3, 4, 5, 6, 7, 8, 0,
+ 10, 0, 0, 0, 0, 11, 0, 12, 34, 2,
+ 35, 36, 37, 6, 7, 8, 0, 10, 0, 0,
+ 0, 0, 11, 0, 12, 29, 2, 30, 31, 5,
+ 6, 7, 0, 0, 10, 56, 72, 2, 73, 74,
+ 37, 6, 7, 0, 0, 10, 56, 29, 2, 30,
+ 31, 5, 6, 7, 0, 0, 10, 72, 2, 73,
+ 74, 37, 6, 7, 0, 0, 10
};
static const yysigned_char yycheck[] =
{
- 0, 1, 2, 9, 4, 43, 18, 74, 17, 21,
- 77, 67, 3, 80, 5, 6, 6, 7, 27, 19,
- 20, 27, 13, 32, 15, 87, 32, 0, 90, 0,
- 1, 2, 70, 16, 40, 41, 92, 39, 40, 41,
- 47, 16, 49, 43, 14, 52, 13, 85, 19, 20,
- 13, 14, 61, 16, 44, 15, 62, 63, 16, 61,
- 62, 63, 62, 63, 90, 9, 20, 21, 74, 72,
- 70, 77, -1, 17, 80, 19, 20, 21, 116, 69,
- 13, 14, 72, 27, -1, 85, -1, 3, 32, 5,
- 6, 62, 63, 99, 100, 39, 40, 41, -1, 15,
- 3, 4, 5, 6, 7, 8, 9, 113, 114, 115,
- -1, 55, 118, 119, 58, 59, 116, 61, 62, 63,
- 13, 14, -1, -1, -1, 39, 40, 41, -1, -1,
- 74, -1, -1, 77, 48, -1, 80, -1, 5, 6,
- -1, -1, -1, 10, 11, 12, 90, 61, 62, 63,
- 17, 65, 19, 67, 98, 99, 100, 3, 4, 5,
- 6, 7, 8, 9, 10, -1, 12, 13, 14, 15,
- 84, 17, -1, 19, -1, -1, 22, -1, 92, -1,
- -1, -1, 5, 6, 98, 99, 100, 10, -1, 12,
- -1, -1, -1, -1, 17, -1, 19, -1, -1, -1,
- -1, -1, -1, 117, 118, 119, 3, 4, 5, 6,
- 7, 8, 9, 10, -1, 12, 13, -1, 15, -1,
- 17, -1, 19, -1, -1, 22, 3, 4, 5, 6,
- 7, 8, 9, -1, -1, -1, 13, -1, 15, -1,
- -1, -1, -1, -1, -1, 22, 3, 4, 5, 6,
- 7, 8, 9, -1, -1, -1, -1, -1, 15, -1,
- -1, -1, -1, -1, -1, 22, 3, 4, 5, 6,
- 7, 8, 9, -1, -1, -1, -1, -1, 15, -1,
- -1, -1, -1, -1, -1, 22, 3, 4, 5, 6,
- 7, 8, 9, 10, -1, 12, -1, -1, -1, -1,
- 17, -1, 19, 20, 3, 4, 5, 6, 7, 8,
- 9, 10, -1, 12, 13, -1, 15, -1, 17, -1,
+ 1, 57, 3, 4, 5, 59, 12, 0, 0, 105,
+ 63, 64, 14, 109, 67, 16, 20, 21, 18, 11,
+ 12, 21, 53, 54, 55, 81, 16, 80, 29, 30,
+ 31, 32, 16, 34, 35, 36, 37, 13, 5, 83,
+ 41, 15, 9, 13, 14, 99, 77, 78, 79, 13,
+ 14, 107, 53, 54, 55, 87, 85, 109, 90, -1,
+ -1, 93, 29, 30, 31, 32, 58, 34, 35, 36,
+ 37, 72, 73, 74, 41, 76, 77, 78, 79, 85,
+ -1, -1, 1, -1, 3, 4, 87, -1, -1, 90,
+ 57, 83, 93, 85, -1, -1, 87, 16, -1, 90,
+ -1, -1, 93, -1, -1, 72, 73, 74, 109, 76,
+ 77, 78, 79, -1, 81, 34, 35, 36, -1, -1,
+ 87, -1, 41, 90, -1, -1, 93, 53, 54, 55,
+ 53, 54, 55, -1, 53, 54, 55, 63, -1, -1,
+ 107, 67, 109, 34, 35, 36, 37, -1, -1, -1,
+ 41, 77, 78, 79, 77, 78, 79, -1, 77, 78,
+ 79, 3, 4, 5, 6, 7, 8, 9, -1, -1,
+ 12, 97, -1, 15, -1, -1, -1, -1, -1, -1,
+ 22, 72, 73, 74, -1, 76, 77, 78, 79, 115,
+ 116, 117, 118, 119, 120, 3, 4, 5, 6, 7,
+ 8, 9, 10, -1, 12, 13, -1, 15, -1, 17,
+ -1, 19, -1, -1, 22, 3, 4, 5, 6, 7,
+ 8, 9, 10, -1, 12, 13, -1, 15, -1, 17,
+ -1, 19, -1, -1, 22, 3, 4, 5, 6, 7,
+ 8, 9, 10, -1, 12, -1, -1, -1, -1, 17,
+ -1, 19, 20, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, -1, -1, -1, -1, 17, -1, 19,
+ 3, 4, 5, 6, 7, 8, 9, 10, -1, 12,
+ -1, -1, -1, -1, 17, 18, 19, 3, 4, 5,
+ 6, 7, 8, 9, 10, -1, 12, 13, -1, -1,
+ -1, 17, -1, 19, 3, 4, 5, 6, 7, 8,
+ 9, 10, -1, 12, 13, -1, -1, -1, 17, -1,
19, 3, 4, 5, 6, 7, 8, 9, 10, -1,
- 12, 13, -1, 15, -1, 17, -1, 19, 3, 4,
+ 12, -1, -1, -1, -1, 17, -1, 19, 3, 4,
5, 6, 7, 8, 9, 10, -1, 12, -1, -1,
- -1, -1, 17, 18, 19, 3, 4, 5, 6, 7,
- 8, 9, 10, -1, 12, -1, -1, -1, -1, 17,
- -1, 19, 3, 4, 5, 6, 7, 8, 9, 10,
- -1, 12, -1, -1, -1, -1, 17, -1, 19, 3,
- 4, 5, 6, 7, 8, 9, -1, -1, -1, 13,
- -1, 15, 3, 4, 5, 6, 7, 8, 9, -1,
- -1, -1, 13, -1, 15
+ -1, -1, 17, -1, 19, 3, 4, 5, 6, 7,
+ 8, 9, -1, -1, 12, 13, 3, 4, 5, 6,
+ 7, 8, 9, -1, -1, 12, 13, 3, 4, 5,
+ 6, 7, 8, 9, -1, -1, 12, 3, 4, 5,
+ 6, 7, 8, 9, -1, -1, 12
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const unsigned char yystos[] =
{
- 0, 5, 6, 10, 11, 12, 17, 19, 24, 28,
- 33, 34, 38, 40, 46, 33, 33, 3, 4, 5,
- 6, 7, 8, 9, 25, 26, 27, 28, 32, 33,
- 18, 25, 28, 39, 20, 25, 45, 47, 0, 3,
- 5, 6, 13, 15, 22, 32, 35, 36, 37, 41,
- 42, 43, 44, 26, 32, 3, 32, 32, 5, 6,
- 32, 3, 5, 6, 14, 26, 29, 32, 18, 21,
- 16, 20, 21, 13, 30, 36, 41, 30, 36, 41,
- 30, 36, 41, 27, 25, 16, 29, 30, 29, 29,
- 30, 14, 30, 31, 31, 25, 27, 45, 3, 5,
- 6, 36, 44, 36, 44, 36, 44, 30, 27, 35,
- 35, 43, 31, 30, 30, 30, 16, 3, 5, 6,
- 27
+ 0, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 17, 19, 24, 25, 26, 29, 33, 34, 35,
+ 39, 42, 49, 26, 33, 26, 33, 26, 33, 3,
+ 5, 6, 29, 33, 3, 5, 6, 7, 25, 27,
+ 28, 29, 18, 25, 40, 41, 48, 20, 25, 48,
+ 50, 51, 0, 3, 5, 6, 13, 15, 22, 26,
+ 33, 36, 37, 38, 43, 44, 46, 47, 33, 28,
+ 28, 28, 3, 5, 6, 28, 29, 3, 5, 6,
+ 28, 16, 18, 21, 20, 21, 13, 31, 37, 43,
+ 31, 37, 43, 31, 37, 43, 27, 25, 14, 31,
+ 32, 32, 14, 30, 30, 31, 30, 16, 30, 31,
+ 30, 27, 41, 51, 33, 38, 47, 38, 47, 38,
+ 47, 31, 32, 36, 27, 45, 36, 46
};
#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
@@ -587,12 +603,13 @@ static const unsigned char yystos[] =
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY -2
+#define YYEMPTY (-2)
#define YYEOF 0
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrlab1
+#define YYERROR goto yyerrorlab
+
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
@@ -608,13 +625,13 @@ do \
{ \
yychar = (Token); \
yylval = (Value); \
- yychar1 = YYTRANSLATE (yychar); \
+ yytoken = YYTRANSLATE (yychar); \
YYPOPSTACK; \
goto yybackup; \
} \
else \
{ \
- yyerror ("syntax error: cannot back up"); \
+ yyerror ("syntax error: cannot back up");\
YYERROR; \
} \
while (0)
@@ -626,19 +643,19 @@ while (0)
are run). */
#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- Current.first_line = Rhs[1].first_line; \
- Current.first_column = Rhs[1].first_column; \
- Current.last_line = Rhs[N].last_line; \
- Current.last_column = Rhs[N].last_column;
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ ((Current).first_line = (Rhs)[1].first_line, \
+ (Current).first_column = (Rhs)[1].first_column, \
+ (Current).last_line = (Rhs)[N].last_line, \
+ (Current).last_column = (Rhs)[N].last_column)
#endif
/* YYLEX -- calling `yylex' with the right arguments. */
#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
#else
-# define YYLEX yylex (&yylval)
+# define YYLEX yylex (&yylval)
#endif
/* Enable debugging if requested. */
@@ -654,19 +671,93 @@ do { \
if (yydebug) \
YYFPRINTF Args; \
} while (0)
+
# define YYDSYMPRINT(Args) \
do { \
if (yydebug) \
yysymprint Args; \
} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yysymprint (stderr, \
+ Token, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short int *bottom, short int *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ short int *bottom;
+ short int *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+ int yyrule;
+#endif
+{
+ int yyi;
+ unsigned int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ yyrule - 1, yylno);
+ /* Print the symbols being reduced, and their result. */
+ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (Rule); \
+} while (0)
+
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
int yydebug;
#else /* !YYDEBUG */
# define YYDPRINTF(Args)
# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */
+
/* YYINITDEPTH -- initial size of the parser's stacks. */
#ifndef YYINITDEPTH
# define YYINITDEPTH 200
@@ -679,7 +770,7 @@ int yydebug;
SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
evaluated with infinite-precision integer arithmetic. */
-#if YYMAXDEPTH == 0
+#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
# undef YYMAXDEPTH
#endif
@@ -745,102 +836,111 @@ yystpcpy (yydest, yysrc)
#if YYDEBUG
-/*-----------------------------.
-| Print this symbol on YYOUT. |
-`-----------------------------*/
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
-static void
#if defined (__STDC__) || defined (__cplusplus)
-yysymprint (FILE* yyout, int yytype, YYSTYPE yyvalue)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
#else
-yysymprint (yyout, yytype, yyvalue)
- FILE* yyout;
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
int yytype;
- YYSTYPE yyvalue;
+ YYSTYPE *yyvaluep;
#endif
{
/* Pacify ``unused variable'' warnings. */
- (void) yyvalue;
+ (void) yyvaluep;
if (yytype < YYNTOKENS)
{
- YYFPRINTF (yyout, "token %s (", yytname[yytype]);
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
# ifdef YYPRINT
- YYPRINT (yyout, yytoknum[yytype], yyvalue);
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
# endif
}
else
- YYFPRINTF (yyout, "nterm %s (", yytname[yytype]);
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
switch (yytype)
{
default:
break;
}
- YYFPRINTF (yyout, ")");
+ YYFPRINTF (yyoutput, ")");
}
-#endif /* YYDEBUG. */
-
+#endif /* ! YYDEBUG */
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
-static void
#if defined (__STDC__) || defined (__cplusplus)
-yydestruct (int yytype, YYSTYPE yyvalue)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
#else
-yydestruct (yytype, yyvalue)
+static void
+yydestruct (yytype, yyvaluep)
int yytype;
- YYSTYPE yyvalue;
+ YYSTYPE *yyvaluep;
#endif
{
/* Pacify ``unused variable'' warnings. */
- (void) yyvalue;
+ (void) yyvaluep;
switch (yytype)
{
+
default:
break;
}
}
-
-/* The user can define YYPARSE_PARAM as the name of an argument to be passed
- into yyparse. The argument should have type void *.
- It should actually point to an object.
- Grammar actions can access the variable by casting it
- to the proper pointer type. */
+/* Prevent warnings from -Wmissing-prototypes. */
#ifdef YYPARSE_PARAM
# if defined (__STDC__) || defined (__cplusplus)
-# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
-# define YYPARSE_PARAM_DECL
+int yyparse (void *YYPARSE_PARAM);
# else
-# define YYPARSE_PARAM_ARG YYPARSE_PARAM
-# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+int yyparse ();
# endif
-#else /* !YYPARSE_PARAM */
-# define YYPARSE_PARAM_ARG
-# define YYPARSE_PARAM_DECL
-#endif /* !YYPARSE_PARAM */
-
-/* Prevent warning if -Wstrict-prototypes. */
-#ifdef __GNUC__
-# ifdef YYPARSE_PARAM
-int yyparse (void *);
-# else
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
int yyparse (void);
-# endif
+#else
+int yyparse ();
#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
int
-yyparse (YYPARSE_PARAM_ARG)
- YYPARSE_PARAM_DECL
+yyparse ()
+
+#endif
+#endif
{
/* The lookahead symbol. */
int yychar;
@@ -848,7 +948,7 @@ int yychar;
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;
-/* Number of parse errors so far. */
+/* Number of syntax errors so far. */
int yynerrs;
register int yystate;
@@ -857,7 +957,7 @@ int yynerrs;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
/* Lookahead token as an internal (translated) token number. */
- int yychar1 = 0;
+ int yytoken = 0;
/* Three stacks and their tools:
`yyss': related to states,
@@ -868,9 +968,9 @@ int yynerrs;
to reallocate them elsewhere. */
/* The state stack. */
- short yyssa[YYINITDEPTH];
- short *yyss = yyssa;
- register short *yyssp;
+ short int yyssa[YYINITDEPTH];
+ short int *yyss = yyssa;
+ register short int *yyssp;
/* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH];
@@ -907,6 +1007,7 @@ int yynerrs;
yyssp = yyss;
yyvsp = yyvs;
+
goto yysetstate;
/*------------------------------------------------------------.
@@ -921,7 +1022,7 @@ int yynerrs;
yysetstate:
*yyssp = yystate;
- if (yyssp >= yyss + yystacksize - 1)
+ if (yyss + yystacksize - 1 <= yyssp)
{
/* Get the current used size of the three stacks, in elements. */
YYSIZE_T yysize = yyssp - yyss + 1;
@@ -932,7 +1033,7 @@ int yynerrs;
these so that the &'s don't force the real ones into
memory. */
YYSTYPE *yyvs1 = yyvs;
- short *yyss1 = yyss;
+ short int *yyss1 = yyss;
/* Each stack pointer address is followed by the size of the
@@ -953,14 +1054,14 @@ int yynerrs;
goto yyoverflowlab;
# else
/* Extend the stack our own way. */
- if (yystacksize >= YYMAXDEPTH)
+ if (YYMAXDEPTH <= yystacksize)
goto yyoverflowlab;
yystacksize *= 2;
- if (yystacksize > YYMAXDEPTH)
+ if (YYMAXDEPTH < yystacksize)
yystacksize = YYMAXDEPTH;
{
- short *yyss1 = yyss;
+ short int *yyss1 = yyss;
union yyalloc *yyptr =
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
@@ -982,7 +1083,7 @@ int yynerrs;
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
(unsigned long int) yystacksize));
- if (yyssp >= yyss + yystacksize - 1)
+ if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
}
@@ -1007,39 +1108,28 @@ yybackup:
/* Not known => get a lookahead token if don't already have one. */
- /* yychar is either YYEMPTY or YYEOF
- or a valid token in external form. */
-
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
yychar = YYLEX;
}
- /* Convert token to internal form (in yychar1) for indexing tables with. */
-
- if (yychar <= 0) /* This means end of input. */
+ if (yychar <= YYEOF)
{
- yychar1 = 0;
- yychar = YYEOF; /* Don't call YYLEX any more. */
-
+ yychar = yytoken = YYEOF;
YYDPRINTF ((stderr, "Now at end of input.\n"));
}
else
{
- yychar1 = YYTRANSLATE (yychar);
-
- /* We have to keep this `#if YYDEBUG', since we use variables
- which are defined only if `YYDEBUG' is set. */
- YYDPRINTF ((stderr, "Next token is "));
- YYDSYMPRINT ((stderr, yychar1, yylval));
- YYDPRINTF ((stderr, "\n"));
+ yytoken = YYTRANSLATE (yychar);
+ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
}
- /* If the proper action on seeing token YYCHAR1 is to reduce or to
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
detect an error, take that action. */
- yyn += yychar1;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1)
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
goto yydefault;
yyn = yytable[yyn];
if (yyn <= 0)
@@ -1054,8 +1144,7 @@ yybackup:
YYACCEPT;
/* Shift the lookahead token. */
- YYDPRINTF ((stderr, "Shifting token %d (%s), ",
- yychar, yytname[yychar1]));
+ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
/* Discard the token being shifted unless it is eof. */
if (yychar != YYEOF)
@@ -1101,48 +1190,48 @@ yyreduce:
yyval = yyvsp[1-yylen];
-
-#if YYDEBUG
- /* We have to keep this `#if YYDEBUG', since we use variables which
- are defined only if `YYDEBUG' is set. */
- if (yydebug)
- {
- int yyi;
-
- YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
- yyn - 1, yyrline[yyn]);
-
- /* Print the symbols being reduced, and their result. */
- for (yyi = yyprhs[yyn]; yyrhs[yyi] >= 0; yyi++)
- YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
- YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
- }
-#endif
+ YY_REDUCE_PRINT (yyn);
switch (yyn)
{
case 2:
-#line 45 "gram.y"
+#line 57 "gram.y"
{
((SyckParser *)parser)->root = syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData );
}
break;
case 3:
-#line 49 "gram.y"
+#line 61 "gram.y"
{
((SyckParser *)parser)->root = syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData );
}
break;
case 4:
-#line 53 "gram.y"
+#line 65 "gram.y"
{
((SyckParser *)parser)->eof = 1;
}
break;
case 8:
-#line 64 "gram.y"
+#line 76 "gram.y"
+ {
+ syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
+ yyval.nodeData = yyvsp[0].nodeData;
+ }
+ break;
+
+ case 9:
+#line 81 "gram.y"
+ {
+ syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
+ yyval.nodeData = yyvsp[0].nodeData;
+ }
+ break;
+
+ case 10:
+#line 86 "gram.y"
{
/*
* _Anchors_: The language binding must keep a separate symbol table
@@ -1153,70 +1242,85 @@ yyreduce:
}
break;
- case 9:
-#line 73 "gram.y"
+ case 11:
+#line 95 "gram.y"
{
yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 10:
-#line 77 "gram.y"
+ case 14:
+#line 105 "gram.y"
{
- yyval.nodeData = yyvsp[-1].nodeData;
- }
+ yyval.nodeData = yyvsp[-1].nodeData;
+ }
break;
- case 12:
-#line 84 "gram.y"
+ case 15:
+#line 109 "gram.y"
{
- SyckNode *n = syck_new_str( "" );
- if ( ((SyckParser *)parser)->taguri_expansion == 1 )
- {
- n->type_id = syck_taguri( YAML_DOMAIN, "null", 4 );
- }
- else
+ NULL_NODE( parser, n );
+ yyval.nodeData = n;
+ }
+ break;
+
+ case 16:
+#line 114 "gram.y"
+ {
+ if ( ((SyckParser *)parser)->implicit_typing == 1 )
{
- n->type_id = syck_strndup( "null", 4 );
+ try_tag_implicit( yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
}
- yyval.nodeData = n;
+ yyval.nodeData = yyvsp[0].nodeData;
+ }
+ break;
+
+ case 17:
+#line 122 "gram.y"
+ {
+ syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
+ yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 13:
-#line 97 "gram.y"
+ case 18:
+#line 127 "gram.y"
{
- SyckNode *n = syck_new_str( "" );
- if ( ((SyckParser *)parser)->taguri_expansion == 1 )
- {
- n->type_id = syck_taguri( YAML_DOMAIN, "null", 4 );
- }
- else
- {
- n->type_id = syck_strndup( "null", 4 );
- }
- yyval.nodeData = n;
+ syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
+ yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 20:
-#line 134 "gram.y"
+ case 19:
+#line 132 "gram.y"
+ {
+ /*
+ * _Anchors_: The language binding must keep a separate symbol table
+ * for anchors. The actual ID in the symbol table is returned to the
+ * higher nodes, though.
+ */
+ yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-1].name, yyvsp[0].nodeData );
+ }
+ break;
+
+ case 26:
+#line 165 "gram.y"
{
syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 21:
-#line 139 "gram.y"
+ case 27:
+#line 170 "gram.y"
{
syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 22:
-#line 144 "gram.y"
+ case 28:
+#line 175 "gram.y"
{
if ( ((SyckParser *)parser)->implicit_typing == 1 )
{
@@ -1226,15 +1330,15 @@ yyreduce:
}
break;
- case 23:
-#line 152 "gram.y"
+ case 29:
+#line 183 "gram.y"
{
yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-1].name, yyvsp[0].nodeData );
}
break;
- case 24:
-#line 156 "gram.y"
+ case 30:
+#line 187 "gram.y"
{
/*
* _Aliases_: The anchor symbol table is scanned for the anchor name.
@@ -1244,8 +1348,8 @@ yyreduce:
}
break;
- case 25:
-#line 164 "gram.y"
+ case 31:
+#line 195 "gram.y"
{
SyckNode *n = yyvsp[0].nodeData;
if ( ((SyckParser *)parser)->taguri_expansion == 1 )
@@ -1260,216 +1364,212 @@ yyreduce:
}
break;
- case 27:
-#line 184 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
- yyval.nodeData = yyvsp[0].nodeData;
+ case 33:
+#line 209 "gram.y"
+ {
+ yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 28:
-#line 189 "gram.y"
- {
- syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
- yyval.nodeData = yyvsp[0].nodeData;
- }
+ case 39:
+#line 229 "gram.y"
+ {
+ yyval.nodeData = yyvsp[-1].nodeData;
+ }
break;
- case 34:
-#line 204 "gram.y"
+ case 40:
+#line 233 "gram.y"
{
yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 35:
-#line 210 "gram.y"
+ case 41:
+#line 239 "gram.y"
{
yyval.nodeId = syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData );
}
break;
- case 37:
-#line 217 "gram.y"
+ case 42:
+#line 245 "gram.y"
{
syck_add_transfer( yyvsp[-2].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 38:
-#line 222 "gram.y"
+ case 43:
+#line 250 "gram.y"
{
syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 39:
-#line 227 "gram.y"
+ case 44:
+#line 255 "gram.y"
{
syck_add_transfer( yyvsp[-2].name, yyvsp[0].nodeData, 0 );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 40:
-#line 232 "gram.y"
+ case 45:
+#line 260 "gram.y"
{
syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 41:
-#line 237 "gram.y"
+ case 46:
+#line 265 "gram.y"
{
yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-2].name, yyvsp[0].nodeData );
}
break;
- case 42:
-#line 241 "gram.y"
+ case 47:
+#line 269 "gram.y"
{
yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-1].name, yyvsp[0].nodeData );
}
break;
- case 43:
-#line 247 "gram.y"
+ case 48:
+#line 275 "gram.y"
{
yyval.nodeData = syck_new_seq( yyvsp[0].nodeId );
}
break;
- case 44:
-#line 251 "gram.y"
+ case 49:
+#line 279 "gram.y"
{
syck_seq_add( yyvsp[-2].nodeData, yyvsp[0].nodeId );
yyval.nodeData = yyvsp[-2].nodeData;
}
break;
- case 45:
-#line 256 "gram.y"
+ case 50:
+#line 284 "gram.y"
{
yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 46:
-#line 265 "gram.y"
+ case 51:
+#line 293 "gram.y"
{
yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 47:
-#line 269 "gram.y"
+ case 52:
+#line 297 "gram.y"
{
yyval.nodeData = syck_alloc_seq();
}
break;
- case 48:
-#line 275 "gram.y"
+ case 53:
+#line 303 "gram.y"
{
yyval.nodeData = syck_new_seq( syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ) );
}
break;
- case 49:
-#line 279 "gram.y"
+ case 54:
+#line 307 "gram.y"
{
syck_seq_add( yyvsp[-2].nodeData, syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ) );
yyval.nodeData = yyvsp[-2].nodeData;
}
break;
- case 50:
-#line 289 "gram.y"
+ case 57:
+#line 321 "gram.y"
{
apply_seq_in_map( (SyckParser *)parser, yyvsp[-1].nodeData );
yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 51:
-#line 294 "gram.y"
+ case 58:
+#line 326 "gram.y"
{
apply_seq_in_map( (SyckParser *)parser, yyvsp[-1].nodeData );
yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 52:
-#line 301 "gram.y"
+ case 59:
+#line 333 "gram.y"
{
syck_add_transfer( yyvsp[-2].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 53:
-#line 306 "gram.y"
+ case 60:
+#line 338 "gram.y"
{
syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, ((SyckParser *)parser)->taguri_expansion );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 54:
-#line 311 "gram.y"
+ case 61:
+#line 343 "gram.y"
{
syck_add_transfer( yyvsp[-2].name, yyvsp[0].nodeData, 0 );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 55:
-#line 316 "gram.y"
+ case 62:
+#line 348 "gram.y"
{
syck_add_transfer( yyvsp[-1].name, yyvsp[0].nodeData, 0 );
yyval.nodeData = yyvsp[0].nodeData;
}
break;
- case 56:
-#line 321 "gram.y"
+ case 63:
+#line 353 "gram.y"
{
yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-2].name, yyvsp[0].nodeData );
}
break;
- case 57:
-#line 325 "gram.y"
+ case 64:
+#line 357 "gram.y"
{
yyval.nodeData = syck_hdlr_add_anchor( (SyckParser *)parser, yyvsp[-1].name, yyvsp[0].nodeData );
}
break;
- case 58:
-#line 331 "gram.y"
+ case 66:
+#line 364 "gram.y"
{
- yyval.nodeData = syck_new_map(
- syck_hdlr_add_node( (SyckParser *)parser, yyvsp[-2].nodeData ),
- syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ) );
+ yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 60:
-#line 347 "gram.y"
+ case 68:
+#line 380 "gram.y"
{
yyval.nodeData = syck_new_map(
- syck_hdlr_add_node( (SyckParser *)parser, yyvsp[-3].nodeData ),
+ syck_hdlr_add_node( (SyckParser *)parser, yyvsp[-2].nodeData ),
syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ) );
}
break;
- case 62:
-#line 356 "gram.y"
- {
+ case 70:
+#line 398 "gram.y"
+ {
if ( yyvsp[-2].nodeData->shortcut == NULL )
{
yyvsp[-2].nodeData->shortcut = syck_new_seq( yyvsp[0].nodeId );
@@ -1482,25 +1582,26 @@ yyreduce:
}
break;
- case 63:
-#line 368 "gram.y"
- {
+ case 71:
+#line 410 "gram.y"
+ {
apply_seq_in_map( (SyckParser *)parser, yyvsp[-2].nodeData );
syck_map_update( yyvsp[-2].nodeData, yyvsp[0].nodeData );
syck_free_node( yyvsp[0].nodeData );
+ yyvsp[0].nodeData = NULL;
yyval.nodeData = yyvsp[-2].nodeData;
}
break;
- case 64:
-#line 375 "gram.y"
- {
+ case 72:
+#line 418 "gram.y"
+ {
yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 65:
-#line 384 "gram.y"
+ case 73:
+#line 427 "gram.y"
{
yyval.nodeData = syck_new_map(
syck_hdlr_add_node( (SyckParser *)parser, yyvsp[-2].nodeData ),
@@ -1508,49 +1609,51 @@ yyreduce:
}
break;
- case 66:
-#line 392 "gram.y"
+ case 74:
+#line 435 "gram.y"
{
yyval.nodeData = yyvsp[-1].nodeData;
}
break;
- case 67:
-#line 396 "gram.y"
+ case 75:
+#line 439 "gram.y"
{
yyval.nodeData = syck_alloc_map();
}
break;
- case 69:
-#line 403 "gram.y"
+ case 77:
+#line 446 "gram.y"
{
syck_map_update( yyvsp[-2].nodeData, yyvsp[0].nodeData );
syck_free_node( yyvsp[0].nodeData );
+ yyvsp[0].nodeData = NULL;
yyval.nodeData = yyvsp[-2].nodeData;
}
break;
+ case 78:
+#line 455 "gram.y"
+ {
+ NULL_NODE( parser, n );
+ yyval.nodeData = syck_new_map(
+ syck_hdlr_add_node( (SyckParser *)parser, yyvsp[0].nodeData ),
+ syck_hdlr_add_node( (SyckParser *)parser, n ) );
+ }
+ break;
+
}
-/* Line 1016 of /usr/local/share/bison/yacc.c. */
-#line 1538 "y.tab.c"
+/* Line 1010 of yacc.c. */
+#line 1651 "gram.c"
yyvsp -= yylen;
yyssp -= yylen;
-#if YYDEBUG
- if (yydebug)
- {
- short *yyssp1 = yyss - 1;
- YYFPRINTF (stderr, "state stack now");
- while (yyssp1 != yyssp)
- YYFPRINTF (stderr, " %d", *++yyssp1);
- YYFPRINTF (stderr, "\n");
- }
-#endif
+ YY_STACK_PRINT (yyss, yyssp);
*++yyvsp = yyval;
@@ -1585,88 +1688,118 @@ yyerrlab:
{
YYSIZE_T yysize = 0;
int yytype = YYTRANSLATE (yychar);
+ const char* yyprefix;
char *yymsg;
- int yyx, yycount;
+ int yyx;
- yycount = 0;
/* Start YYX at -YYN if negative to avoid negative indexes in
YYCHECK. */
- for (yyx = yyn < 0 ? -yyn : 0;
- yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 0;
+
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- yysize += yystrlen (yytname[yyx]) + 15, yycount++;
- yysize += yystrlen ("parse error, unexpected ") + 1;
- yysize += yystrlen (yytname[yytype]);
+ {
+ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+ yycount += 1;
+ if (yycount == 5)
+ {
+ yysize = 0;
+ break;
+ }
+ }
+ yysize += (sizeof ("syntax error, unexpected ")
+ + yystrlen (yytname[yytype]));
yymsg = (char *) YYSTACK_ALLOC (yysize);
if (yymsg != 0)
{
- char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
yyp = yystpcpy (yyp, yytname[yytype]);
if (yycount < 5)
{
- yycount = 0;
- for (yyx = yyn < 0 ? -yyn : 0;
- yyx < (int) (sizeof (yytname) / sizeof (char *));
- yyx++)
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
{
- const char *yyq = ! yycount ? ", expecting " : " or ";
- yyp = yystpcpy (yyp, yyq);
+ yyp = yystpcpy (yyp, yyprefix);
yyp = yystpcpy (yyp, yytname[yyx]);
- yycount++;
+ yyprefix = " or ";
}
}
yyerror (yymsg);
YYSTACK_FREE (yymsg);
}
else
- yyerror ("parse error; also virtual memory exhausted");
+ yyerror ("syntax error; also virtual memory exhausted");
}
else
#endif /* YYERROR_VERBOSE */
- yyerror ("parse error");
+ yyerror ("syntax error");
}
- goto yyerrlab1;
-/*----------------------------------------------------.
-| yyerrlab1 -- error raised explicitly by an action. |
-`----------------------------------------------------*/
-yyerrlab1:
+
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
error, discard it. */
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
+ if (yychar <= YYEOF)
{
- /* Pop the error token. */
- YYPOPSTACK;
- /* Pop the rest of the stack. */
- while (yyssp > yyss)
- {
- YYDPRINTF ((stderr, "Error: popping "));
- YYDSYMPRINT ((stderr,
- yystos[*yyssp],
- *yyvsp));
- YYDPRINTF ((stderr, "\n"));
- yydestruct (yystos[*yyssp], *yyvsp);
- YYPOPSTACK;
- }
- YYABORT;
+ /* If at end of input, pop the error token,
+ then the rest of the stack, then return failure. */
+ if (yychar == YYEOF)
+ for (;;)
+ {
+ YYPOPSTACK;
+ if (yyssp == yyss)
+ YYABORT;
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[*yyssp], yyvsp);
+ }
}
+ else
+ {
+ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+ yydestruct (yytoken, &yylval);
+ yychar = YYEMPTY;
- YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
- yychar, yytname[yychar1]));
- yydestruct (yychar1, yylval);
- yychar = YYEMPTY;
+ }
}
/* Else will try to reuse lookahead token after shifting the error
token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+#ifdef __GNUC__
+ /* Pacify GCC when the user code never invokes YYERROR and the label
+ yyerrorlab therefore never appears in user code. */
+ if (0)
+ goto yyerrorlab;
+#endif
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
yyerrstatus = 3; /* Each real token shifted decrements this. */
for (;;)
@@ -1687,26 +1820,11 @@ yyerrlab1:
if (yyssp == yyss)
YYABORT;
- YYDPRINTF ((stderr, "Error: popping "));
- YYDSYMPRINT ((stderr,
- yystos[*yyssp], *yyvsp));
- YYDPRINTF ((stderr, "\n"));
-
- yydestruct (yystos[yystate], *yyvsp);
- yyvsp--;
- yystate = *--yyssp;
-
-
-#if YYDEBUG
- if (yydebug)
- {
- short *yyssp1 = yyss - 1;
- YYFPRINTF (stderr, "Error: state stack now");
- while (yyssp1 != yyssp)
- YYFPRINTF (stderr, " %d", *++yyssp1);
- YYFPRINTF (stderr, "\n");
- }
-#endif
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[yystate], yyvsp);
+ YYPOPSTACK;
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
}
if (yyn == YYFINAL)
@@ -1754,7 +1872,7 @@ yyreturn:
}
-#line 410 "gram.y"
+#line 464 "gram.y"
void
diff --git a/ext/syck/gram.h b/ext/syck/gram.h
index d1e577b0ee..547149ab4b 100644
--- a/ext/syck/gram.h
+++ b/ext/syck/gram.h
@@ -1,7 +1,7 @@
-/* A Bison parser, made from gram.y, by GNU bison 1.75. */
+/* A Bison parser, made by GNU Bison 1.875d. */
/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,9 +23,6 @@
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
-#ifndef BISON_Y_TAB_H
-# define BISON_Y_TAB_H
-
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -62,20 +59,21 @@
-#ifndef YYSTYPE
-#line 23 "gram.y"
-typedef union {
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#line 35 "gram.y"
+typedef union YYSTYPE {
SYMID nodeId;
SyckNode *nodeData;
char *name;
-} yystype;
-/* Line 1281 of /usr/local/share/bison/yacc.c. */
-#line 74 "y.tab.h"
-# define YYSTYPE yystype
+} YYSTYPE;
+/* Line 1285 of yacc.c. */
+#line 71 "gram.h"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
#endif
-#endif /* not BISON_Y_TAB_H */
diff --git a/ext/syck/handler.c b/ext/syck/handler.c
index eddc6465af..56fe838fbd 100644
--- a/ext/syck/handler.c
+++ b/ext/syck/handler.c
@@ -7,8 +7,8 @@
* Copyright (C) 2003 why the lucky stiff
*/
-#include "syck.h"
#include "ruby.h"
+#include "syck.h"
SYMID
syck_hdlr_add_node( SyckParser *p, SyckNode *n )
@@ -31,6 +31,8 @@ syck_hdlr_add_node( SyckParser *p, SyckNode *n )
SyckNode *
syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
{
+ SyckNode *ntmp = NULL;
+
n->anchor = a;
if ( p->bad_anchors != NULL )
{
@@ -48,6 +50,13 @@ syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
{
p->anchors = st_init_strtable();
}
+ if ( st_lookup( p->anchors, (st_data_t)a, (st_data_t *)&ntmp ) )
+ {
+ if ( ntmp != (void *)1 )
+ {
+ syck_free_node( ntmp );
+ }
+ }
st_insert( p->anchors, (st_data_t)a, (st_data_t)n );
return n;
}
@@ -55,10 +64,19 @@ syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
void
syck_hdlr_remove_anchor( SyckParser *p, char *a )
{
+ char *atmp = a;
+ SyckNode *ntmp;
if ( p->anchors == NULL )
{
p->anchors = st_init_strtable();
}
+ if ( st_delete( p->anchors, (st_data_t *)&atmp, (st_data_t *)&ntmp ) )
+ {
+ if ( ntmp != (void *)1 )
+ {
+ syck_free_node( ntmp );
+ }
+ }
st_insert( p->anchors, (st_data_t)a, (st_data_t)1 );
}
diff --git a/ext/syck/implicit.c b/ext/syck/implicit.c
index 1dfeac3953..d356faf7d9 100644
--- a/ext/syck/implicit.c
+++ b/ext/syck/implicit.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.5 on Thu Oct 16 14:12:57 2003 */
+/* Generated by re2c 0.9.10 on Mon Sep 19 21:46:50 2005 */
#line 1 "implicit.re"
/*
* implicit.re
@@ -9,8 +9,8 @@
* Copyright (C) 2003 why the lucky stiff
*/
-#include "syck.h"
#include "ruby.h"
+#include "syck.h"
#define YYCTYPE char
#define YYCURSOR cursor
@@ -36,6 +36,7 @@ try_tag_implicit( SyckNode *n, int taguri )
tid = "map";
break;
}
+ if ( n->type_id != NULL ) S_FREE( n->type_id );
if ( taguri == 1 )
{
n->type_id = syck_taguri( YAML_DOMAIN, tid, strlen( tid ) );
@@ -50,16 +51,18 @@ char *syck_match_implicit( char *str, size_t len )
cursor = str;
limit = str + len;
+
+#line 55 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
goto yy0;
-yy1: ++YYCURSOR;
+ ++YYCURSOR;
yy0:
if((YYLIMIT - YYCURSOR) < 26) YYFILL(26);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy6;
+ case 0x00: goto yy6;
case '+': goto yy16;
case '-': goto yy17;
case '.': goto yy20;
@@ -78,99 +81,103 @@ yy0:
case 'F': goto yy15;
case 'N': goto yy5;
case 'O': goto yy13;
- case 'T': goto yy9;
- case 'Y': goto yy11;
+ case 'T': goto yy11;
+ case 'Y': goto yy9;
case 'f': goto yy14;
case 'n': goto yy4;
case 'o': goto yy12;
- case 't': goto yy8;
- case 'y': goto yy10;
+ case 't': goto yy10;
+ case 'y': goto yy8;
case '~': goto yy2;
default: goto yy23;
}
-yy2: yych = *++YYCURSOR;
- if(yych <= '\000') goto yy6;
+yy2: ++YYCURSOR;
+ if((yych = *YYCURSOR) <= 0x00) goto yy6;
+ goto yy3;
yy3:
-#line 116
- { return "str"; }
+#line 123 "implicit.re"
+{ return "str"; }
+#line 100 "<stdout>"
yy4: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'o': goto yy163;
- case 'u': goto yy191;
+ case 'o': goto yy172;
+ case 'u': goto yy200;
default: goto yy3;
}
yy5: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'O': case 'o': goto yy163;
- case 'U': goto yy186;
- case 'u': goto yy187;
+ case 'O': case 'o': goto yy172;
+ case 'U': goto yy195;
+ case 'u': goto yy196;
default: goto yy3;
}
-yy6: yych = *++YYCURSOR;
+yy6: ++YYCURSOR;
+ goto yy7;
yy7:
-#line 82
- { return "null"; }
+#line 85 "implicit.re"
+{ return "null"; }
+#line 121 "<stdout>"
yy8: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'r': goto yy184;
+ case 'e': goto yy194;
default: goto yy3;
}
yy9: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'R': goto yy180;
- case 'r': goto yy181;
+ case 'E': goto yy192;
+ case 'e': goto yy193;
default: goto yy3;
}
yy10: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'e': goto yy179;
+ case 'r': goto yy190;
default: goto yy3;
}
yy11: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'E': goto yy177;
- case 'e': goto yy178;
+ case 'R': goto yy186;
+ case 'r': goto yy187;
default: goto yy3;
}
yy12: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'f': goto yy176;
- case 'n': goto yy173;
+ case 'f': goto yy185;
+ case 'n': goto yy182;
default: goto yy3;
}
yy13: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'F': goto yy171;
- case 'N': case 'n': goto yy173;
- case 'f': goto yy172;
+ case 'F': goto yy180;
+ case 'N': case 'n': goto yy182;
+ case 'f': goto yy181;
default: goto yy3;
}
yy14: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'a': goto yy168;
+ case 'a': goto yy177;
default: goto yy3;
}
yy15: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'A': goto yy159;
- case 'a': goto yy160;
+ case 'A': goto yy168;
+ case 'a': goto yy169;
default: goto yy3;
}
yy16: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '.': goto yy158;
- case '0': goto yy149;
+ case '.': goto yy167;
+ case '0': goto yy158;
case '1':
case '2':
case '3':
@@ -185,8 +192,8 @@ yy16: yyaccept = 0;
yy17: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '.': goto yy148;
- case '0': goto yy149;
+ case '.': goto yy157;
+ case '0': goto yy158;
case '1':
case '2':
case '3':
@@ -201,9 +208,9 @@ yy17: yyaccept = 0;
yy18: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '\000': goto yy51;
- case ',': goto yy133;
- case '.': goto yy49;
+ case 0x00: goto yy52;
+ case ',': goto yy142;
+ case '.': goto yy50;
case '0':
case '1':
case '2':
@@ -211,18 +218,19 @@ yy18: yyaccept = 0;
case '4':
case '5':
case '6':
- case '7': goto yy131;
+ case '7': goto yy140;
case '8':
- case '9': goto yy132;
- case 'x': goto yy135;
+ case '9': goto yy141;
+ case ':': goto yy49;
+ case 'x': goto yy144;
default: goto yy3;
}
yy19: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '\000': goto yy51;
+ case 0x00: goto yy52;
case ',': goto yy47;
- case '.': goto yy49;
+ case '.': goto yy50;
case '0':
case '1':
case '2':
@@ -233,6 +241,7 @@ yy19: yyaccept = 0;
case '7':
case '8':
case '9': goto yy46;
+ case ':': goto yy49;
default: goto yy3;
}
yy20: yyaccept = 0;
@@ -245,7 +254,7 @@ yy20: yyaccept = 0;
default: goto yy3;
}
yy21: yych = *++YYCURSOR;
- if(yych <= '\000') goto yy28;
+ if(yych <= 0x00) goto yy28;
goto yy3;
yy22: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
@@ -256,19 +265,24 @@ yy22: yyaccept = 0;
yy23: yych = *++YYCURSOR;
goto yy3;
yy24: yych = *++YYCURSOR;
- if(yych <= '\000') goto yy26;
+ if(yych <= 0x00) goto yy26;
+ goto yy25;
yy25: YYCURSOR = YYMARKER;
switch(yyaccept){
case 0: goto yy3;
}
-yy26: yych = *++YYCURSOR;
+yy26: ++YYCURSOR;
+ goto yy27;
yy27:
-#line 114
- { return "merge"; }
-yy28: yych = *++YYCURSOR;
+#line 121 "implicit.re"
+{ return "merge"; }
+#line 279 "<stdout>"
+yy28: ++YYCURSOR;
+ goto yy29;
yy29:
-#line 112
- { return "default"; }
+#line 119 "implicit.re"
+{ return "default"; }
+#line 285 "<stdout>"
yy30: yych = *++YYCURSOR;
switch(yych){
case 'a': goto yy45;
@@ -302,11 +316,14 @@ yy35: yych = *++YYCURSOR;
default: goto yy25;
}
yy36: yych = *++YYCURSOR;
- if(yych >= '\001') goto yy25;
-yy37: yych = *++YYCURSOR;
+ if(yych >= 0x01) goto yy25;
+ goto yy37;
+yy37: ++YYCURSOR;
+ goto yy38;
yy38:
-#line 98
- { return "float#inf"; }
+#line 105 "implicit.re"
+{ return "float#inf"; }
+#line 326 "<stdout>"
yy39: yych = *++YYCURSOR;
switch(yych){
case 'f': goto yy36;
@@ -323,11 +340,14 @@ yy41: yych = *++YYCURSOR;
default: goto yy25;
}
yy42: yych = *++YYCURSOR;
- if(yych >= '\001') goto yy25;
-yy43: yych = *++YYCURSOR;
+ if(yych >= 0x01) goto yy25;
+ goto yy43;
+yy43: ++YYCURSOR;
+ goto yy44;
yy44:
-#line 102
- { return "float#nan"; }
+#line 109 "implicit.re"
+{ return "float#nan"; }
+#line 350 "<stdout>"
yy45: yych = *++YYCURSOR;
switch(yych){
case 'n': goto yy42;
@@ -344,14 +364,15 @@ yy46: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy65;
+ case '9': goto yy74;
default: goto yy48;
}
yy47: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
+ goto yy48;
yy48: switch(yych){
- case '\000': goto yy51;
+ case 0x00: goto yy52;
case ',': case '0':
case '1':
case '2':
@@ -362,16 +383,34 @@ yy48: switch(yych){
case '7':
case '8':
case '9': goto yy47;
- case '.': goto yy49;
+ case '.': goto yy50;
+ case ':': goto yy49;
default: goto yy25;
}
yy49: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy50: switch(yych){
- case '\000': goto yy55;
- case ',': goto yy53;
- case '.': goto yy57;
+ switch(yych){
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5': goto yy66;
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy67;
+ default: goto yy25;
+ }
+yy50: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ yych = *YYCURSOR;
+ goto yy51;
+yy51: switch(yych){
+ case 0x00: goto yy56;
+ case ',': goto yy54;
+ case '.': goto yy58;
case '0':
case '1':
case '2':
@@ -381,19 +420,22 @@ yy50: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy49;
- case 'E': case 'e': goto yy59;
+ case '9': goto yy50;
+ case 'E': case 'e': goto yy60;
default: goto yy25;
}
-yy51: yych = *++YYCURSOR;
-yy52:
-#line 92
- { return "int"; }
-yy53: ++YYCURSOR;
+yy52: ++YYCURSOR;
+ goto yy53;
+yy53:
+#line 97 "implicit.re"
+{ return "int"; }
+#line 432 "<stdout>"
+yy54: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy54: switch(yych){
- case '\000': goto yy55;
+ goto yy55;
+yy55: switch(yych){
+ case 0x00: goto yy56;
case ',': case '0':
case '1':
case '2':
@@ -403,17 +445,20 @@ yy54: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy53;
+ case '9': goto yy54;
default: goto yy25;
}
-yy55: yych = *++YYCURSOR;
-yy56:
-#line 94
- { return "float#fix"; }
-yy57: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+yy56: ++YYCURSOR;
+ goto yy57;
+yy57:
+#line 99 "implicit.re"
+{ return "float#fix"; }
+#line 456 "<stdout>"
+yy58: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
yych = *YYCURSOR;
-yy58: switch(yych){
+ goto yy59;
+yy59: switch(yych){
case '.': case '0':
case '1':
case '2':
@@ -423,23 +468,24 @@ yy58: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy57;
- case 'E': case 'e': goto yy59;
+ case '9': goto yy58;
+ case 'E': case 'e': goto yy60;
default: goto yy25;
}
-yy59: yych = *++YYCURSOR;
+yy60: yych = *++YYCURSOR;
switch(yych){
- case '+': case '-': goto yy60;
+ case '+': case '-': goto yy61;
default: goto yy25;
}
-yy60: yych = *++YYCURSOR;
- if(yych <= '\000') goto yy25;
- goto yy62;
-yy61: ++YYCURSOR;
+yy61: yych = *++YYCURSOR;
+ if(yych <= 0x00) goto yy25;
+ goto yy63;
+yy62: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy62: switch(yych){
- case '\000': goto yy63;
+ goto yy63;
+yy63: switch(yych){
+ case 0x00: goto yy64;
case '0':
case '1':
case '2':
@@ -449,14 +495,74 @@ yy62: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy61;
+ case '9': goto yy62;
+ default: goto yy25;
+ }
+yy64: ++YYCURSOR;
+ goto yy65;
+yy65:
+#line 101 "implicit.re"
+{ return "float#exp"; }
+#line 506 "<stdout>"
+yy66: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ switch(yych){
+ case 0x00: goto yy70;
+ case '.': goto yy68;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy67;
+ case ':': goto yy49;
+ default: goto yy25;
+ }
+yy67: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ switch(yych){
+ case 0x00: goto yy70;
+ case '.': goto yy68;
+ case ':': goto yy49;
+ default: goto yy25;
+ }
+yy68: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy69;
+yy69: switch(yych){
+ case 0x00: goto yy72;
+ case ',': case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy68;
default: goto yy25;
}
-yy63: yych = *++YYCURSOR;
-yy64:
-#line 96
- { return "float#exp"; }
-yy65: yych = *++YYCURSOR;
+yy70: ++YYCURSOR;
+ goto yy71;
+yy71:
+#line 95 "implicit.re"
+{ return "int#base60"; }
+#line 558 "<stdout>"
+yy72: ++YYCURSOR;
+ goto yy73;
+yy73:
+#line 103 "implicit.re"
+{ return "float#base60"; }
+#line 564 "<stdout>"
+yy74: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -467,15 +573,15 @@ yy65: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy66;
+ case '9': goto yy75;
default: goto yy48;
}
-yy66: yych = *++YYCURSOR;
+yy75: yych = *++YYCURSOR;
switch(yych){
- case '-': goto yy67;
+ case '-': goto yy76;
default: goto yy48;
}
-yy67: yych = *++YYCURSOR;
+yy76: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -486,10 +592,10 @@ yy67: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy68;
+ case '9': goto yy77;
default: goto yy25;
}
-yy68: yych = *++YYCURSOR;
+yy77: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -500,15 +606,15 @@ yy68: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy69;
+ case '9': goto yy78;
default: goto yy25;
}
-yy69: yych = *++YYCURSOR;
+yy78: yych = *++YYCURSOR;
switch(yych){
- case '-': goto yy70;
+ case '-': goto yy79;
default: goto yy25;
}
-yy70: yych = *++YYCURSOR;
+yy79: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -519,10 +625,10 @@ yy70: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy71;
+ case '9': goto yy80;
default: goto yy25;
}
-yy71: yych = *++YYCURSOR;
+yy80: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -533,12 +639,12 @@ yy71: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy72;
+ case '9': goto yy81;
default: goto yy25;
}
-yy72: yych = *++YYCURSOR;
+yy81: yych = *++YYCURSOR;
switch(yych){
- case '\000': goto yy73;
+ case 0x00: goto yy82;
case '0':
case '1':
case '2':
@@ -549,15 +655,17 @@ yy72: yych = *++YYCURSOR;
case '7':
case '8':
case '9': goto yy25;
- case 'T': goto yy75;
- case 't': goto yy76;
- default: goto yy78;
- }
-yy73: yych = *++YYCURSOR;
-yy74:
-#line 104
- { return "timestamp#ymd"; }
-yy75: yych = *++YYCURSOR;
+ case 'T': goto yy84;
+ case 't': goto yy85;
+ default: goto yy87;
+ }
+yy82: ++YYCURSOR;
+ goto yy83;
+yy83:
+#line 111 "implicit.re"
+{ return "timestamp#ymd"; }
+#line 667 "<stdout>"
+yy84: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -568,10 +676,10 @@ yy75: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy117;
+ case '9': goto yy126;
default: goto yy25;
}
-yy76: yych = *++YYCURSOR;
+yy85: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -582,14 +690,15 @@ yy76: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy99;
+ case '9': goto yy108;
default: goto yy25;
}
-yy77: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+yy86: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 9) YYFILL(9);
yych = *YYCURSOR;
-yy78: switch(yych){
- case '\t': case ' ': goto yy77;
+ goto yy87;
+yy87: switch(yych){
+ case 0x09: case ' ': goto yy86;
case '0':
case '1':
case '2':
@@ -599,10 +708,10 @@ yy78: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy79;
+ case '9': goto yy88;
default: goto yy25;
}
-yy79: yych = *++YYCURSOR;
+yy88: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -613,15 +722,15 @@ yy79: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy80;
+ case '9': goto yy89;
default: goto yy25;
}
-yy80: yych = *++YYCURSOR;
+yy89: yych = *++YYCURSOR;
switch(yych){
- case ':': goto yy81;
+ case ':': goto yy90;
default: goto yy25;
}
-yy81: yych = *++YYCURSOR;
+yy90: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -632,10 +741,10 @@ yy81: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy82;
+ case '9': goto yy91;
default: goto yy25;
}
-yy82: yych = *++YYCURSOR;
+yy91: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -646,15 +755,15 @@ yy82: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy83;
+ case '9': goto yy92;
default: goto yy25;
}
-yy83: yych = *++YYCURSOR;
+yy92: yych = *++YYCURSOR;
switch(yych){
- case ':': goto yy84;
+ case ':': goto yy93;
default: goto yy25;
}
-yy84: yych = *++YYCURSOR;
+yy93: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -665,10 +774,10 @@ yy84: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy85;
+ case '9': goto yy94;
default: goto yy25;
}
-yy85: yych = *++YYCURSOR;
+yy94: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -679,20 +788,21 @@ yy85: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy86;
+ case '9': goto yy95;
default: goto yy25;
}
-yy86: yych = *++YYCURSOR;
+yy95: yych = *++YYCURSOR;
switch(yych){
- case '\t': case ' ': goto yy89;
- case '.': goto yy87;
+ case 0x09: case ' ': goto yy98;
+ case '.': goto yy96;
default: goto yy25;
}
-yy87: ++YYCURSOR;
+yy96: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy88: switch(yych){
- case '\t': case ' ': goto yy89;
+ goto yy97;
+yy97: switch(yych){
+ case 0x09: case ' ': goto yy98;
case '0':
case '1':
case '2':
@@ -702,22 +812,23 @@ yy88: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy87;
+ case '9': goto yy96;
default: goto yy25;
}
-yy89: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+yy98: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
yych = *YYCURSOR;
-yy90: switch(yych){
- case '\t': case ' ': goto yy89;
- case '+': case '-': goto yy92;
- case 'Z': goto yy91;
+ goto yy99;
+yy99: switch(yych){
+ case 0x09: case ' ': goto yy98;
+ case '+': case '-': goto yy101;
+ case 'Z': goto yy100;
default: goto yy25;
}
-yy91: yych = *++YYCURSOR;
- if(yych <= '\000') goto yy96;
+yy100: yych = *++YYCURSOR;
+ if(yych <= 0x00) goto yy105;
goto yy25;
-yy92: yych = *++YYCURSOR;
+yy101: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -728,10 +839,10 @@ yy92: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy93;
+ case '9': goto yy102;
default: goto yy25;
}
-yy93: yych = *++YYCURSOR;
+yy102: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -742,16 +853,16 @@ yy93: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy94;
+ case '9': goto yy103;
default: goto yy25;
}
-yy94: yych = *++YYCURSOR;
+yy103: yych = *++YYCURSOR;
switch(yych){
- case '\000': goto yy96;
- case ':': goto yy95;
+ case 0x00: goto yy105;
+ case ':': goto yy104;
default: goto yy25;
}
-yy95: yych = *++YYCURSOR;
+yy104: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -762,14 +873,16 @@ yy95: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy98;
+ case '9': goto yy107;
default: goto yy25;
}
-yy96: yych = *++YYCURSOR;
-yy97:
-#line 108
- { return "timestamp#spaced"; }
-yy98: yych = *++YYCURSOR;
+yy105: ++YYCURSOR;
+ goto yy106;
+yy106:
+#line 115 "implicit.re"
+{ return "timestamp#spaced"; }
+#line 884 "<stdout>"
+yy107: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -780,10 +893,10 @@ yy98: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy91;
+ case '9': goto yy100;
default: goto yy25;
}
-yy99: yych = *++YYCURSOR;
+yy108: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -794,15 +907,15 @@ yy99: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy100;
+ case '9': goto yy109;
default: goto yy25;
}
-yy100: yych = *++YYCURSOR;
+yy109: yych = *++YYCURSOR;
switch(yych){
- case ':': goto yy101;
+ case ':': goto yy110;
default: goto yy25;
}
-yy101: yych = *++YYCURSOR;
+yy110: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -813,10 +926,10 @@ yy101: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy102;
+ case '9': goto yy111;
default: goto yy25;
}
-yy102: yych = *++YYCURSOR;
+yy111: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -827,15 +940,15 @@ yy102: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy103;
+ case '9': goto yy112;
default: goto yy25;
}
-yy103: yych = *++YYCURSOR;
+yy112: yych = *++YYCURSOR;
switch(yych){
- case ':': goto yy104;
+ case ':': goto yy113;
default: goto yy25;
}
-yy104: yych = *++YYCURSOR;
+yy113: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -846,10 +959,10 @@ yy104: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy105;
+ case '9': goto yy114;
default: goto yy25;
}
-yy105: yych = *++YYCURSOR;
+yy114: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -860,12 +973,12 @@ yy105: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy106;
+ case '9': goto yy115;
default: goto yy25;
}
-yy106: yych = *++YYCURSOR;
+yy115: yych = *++YYCURSOR;
switch(yych){
- case '.': goto yy107;
+ case '.': goto yy116;
case '0':
case '1':
case '2':
@@ -876,13 +989,14 @@ yy106: yych = *++YYCURSOR;
case '7':
case '8':
case '9': goto yy25;
- default: goto yy108;
+ default: goto yy117;
}
-yy107: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+yy116: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
yych = *YYCURSOR;
-yy108: switch(yych){
- case '+': case '-': goto yy110;
+ goto yy117;
+yy117: switch(yych){
+ case '+': case '-': goto yy119;
case '0':
case '1':
case '2':
@@ -892,14 +1006,14 @@ yy108: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy107;
- case 'Z': goto yy109;
+ case '9': goto yy116;
+ case 'Z': goto yy118;
default: goto yy25;
}
-yy109: yych = *++YYCURSOR;
- if(yych <= '\000') goto yy114;
+yy118: yych = *++YYCURSOR;
+ if(yych <= 0x00) goto yy123;
goto yy25;
-yy110: yych = *++YYCURSOR;
+yy119: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -910,10 +1024,10 @@ yy110: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy111;
+ case '9': goto yy120;
default: goto yy25;
}
-yy111: yych = *++YYCURSOR;
+yy120: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -924,16 +1038,16 @@ yy111: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy112;
+ case '9': goto yy121;
default: goto yy25;
}
-yy112: yych = *++YYCURSOR;
+yy121: yych = *++YYCURSOR;
switch(yych){
- case '\000': goto yy114;
- case ':': goto yy113;
+ case 0x00: goto yy123;
+ case ':': goto yy122;
default: goto yy25;
}
-yy113: yych = *++YYCURSOR;
+yy122: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -944,14 +1058,16 @@ yy113: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy116;
+ case '9': goto yy125;
default: goto yy25;
}
-yy114: yych = *++YYCURSOR;
-yy115:
-#line 106
- { return "timestamp#iso8601"; }
-yy116: yych = *++YYCURSOR;
+yy123: ++YYCURSOR;
+ goto yy124;
+yy124:
+#line 113 "implicit.re"
+{ return "timestamp#iso8601"; }
+#line 1069 "<stdout>"
+yy125: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -962,10 +1078,10 @@ yy116: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy109;
+ case '9': goto yy118;
default: goto yy25;
}
-yy117: yych = *++YYCURSOR;
+yy126: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -976,15 +1092,15 @@ yy117: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy118;
+ case '9': goto yy127;
default: goto yy25;
}
-yy118: yych = *++YYCURSOR;
+yy127: yych = *++YYCURSOR;
switch(yych){
- case ':': goto yy119;
+ case ':': goto yy128;
default: goto yy25;
}
-yy119: yych = *++YYCURSOR;
+yy128: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -995,10 +1111,10 @@ yy119: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy120;
+ case '9': goto yy129;
default: goto yy25;
}
-yy120: yych = *++YYCURSOR;
+yy129: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1009,15 +1125,15 @@ yy120: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy121;
+ case '9': goto yy130;
default: goto yy25;
}
-yy121: yych = *++YYCURSOR;
+yy130: yych = *++YYCURSOR;
switch(yych){
- case ':': goto yy122;
+ case ':': goto yy131;
default: goto yy25;
}
-yy122: yych = *++YYCURSOR;
+yy131: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1028,10 +1144,10 @@ yy122: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy123;
+ case '9': goto yy132;
default: goto yy25;
}
-yy123: yych = *++YYCURSOR;
+yy132: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1042,12 +1158,12 @@ yy123: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy124;
+ case '9': goto yy133;
default: goto yy25;
}
-yy124: yych = *++YYCURSOR;
+yy133: yych = *++YYCURSOR;
switch(yych){
- case '.': goto yy125;
+ case '.': goto yy134;
case '0':
case '1':
case '2':
@@ -1058,15 +1174,16 @@ yy124: yych = *++YYCURSOR;
case '7':
case '8':
case '9': goto yy25;
- case 'Z': goto yy127;
- default: goto yy126;
+ case 'Z': goto yy136;
+ default: goto yy135;
}
-yy125: ++YYCURSOR;
+yy134: ++YYCURSOR;
if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
yych = *YYCURSOR;
-yy126: switch(yych){
- case '+': case '-': goto yy110;
- case '0': goto yy125;
+ goto yy135;
+yy135: switch(yych){
+ case '+': case '-': goto yy119;
+ case '0': goto yy134;
case '1':
case '2':
case '3':
@@ -1075,20 +1192,22 @@ yy126: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy129;
- case 'Z': goto yy109;
+ case '9': goto yy138;
+ case 'Z': goto yy118;
default: goto yy25;
}
-yy127: yych = *++YYCURSOR;
- if(yych >= '\001') goto yy25;
-yy128: yych = *++YYCURSOR;
- goto yy115;
-yy129: ++YYCURSOR;
+yy136: yych = *++YYCURSOR;
+ if(yych >= 0x01) goto yy25;
+ goto yy137;
+yy137: yych = *++YYCURSOR;
+ goto yy124;
+yy138: ++YYCURSOR;
if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
yych = *YYCURSOR;
-yy130: switch(yych){
- case '+': case '-': goto yy110;
- case '0': goto yy125;
+ goto yy139;
+yy139: switch(yych){
+ case '+': case '-': goto yy119;
+ case '0': goto yy134;
case '1':
case '2':
case '3':
@@ -1097,11 +1216,11 @@ yy130: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy129;
- case 'Z': goto yy127;
+ case '9': goto yy138;
+ case 'Z': goto yy136;
default: goto yy25;
}
-yy131: yych = *++YYCURSOR;
+yy140: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1110,12 +1229,12 @@ yy131: yych = *++YYCURSOR;
case '4':
case '5':
case '6':
- case '7': goto yy146;
+ case '7': goto yy155;
case '8':
- case '9': goto yy144;
- default: goto yy134;
+ case '9': goto yy153;
+ default: goto yy143;
}
-yy132: yych = *++YYCURSOR;
+yy141: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1126,14 +1245,15 @@ yy132: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy144;
- default: goto yy143;
+ case '9': goto yy153;
+ default: goto yy152;
}
-yy133: ++YYCURSOR;
+yy142: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy134: switch(yych){
- case '\000': goto yy140;
+ goto yy143;
+yy143: switch(yych){
+ case 0x00: goto yy149;
case ',': case '0':
case '1':
case '2':
@@ -1141,20 +1261,22 @@ yy134: switch(yych){
case '4':
case '5':
case '6':
- case '7': goto yy133;
- case '.': goto yy49;
+ case '7': goto yy142;
+ case '.': goto yy50;
case '8':
- case '9': goto yy142;
+ case '9': goto yy151;
+ case ':': goto yy49;
default: goto yy25;
}
-yy135: yych = *++YYCURSOR;
- if(yych <= '\000') goto yy25;
- goto yy137;
-yy136: ++YYCURSOR;
+yy144: yych = *++YYCURSOR;
+ if(yych <= 0x00) goto yy25;
+ goto yy146;
+yy145: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy137: switch(yych){
- case '\000': goto yy138;
+ goto yy146;
+yy146: switch(yych){
+ case 0x00: goto yy147;
case ',': case '0':
case '1':
case '2':
@@ -1174,21 +1296,26 @@ yy137: switch(yych){
case 'c':
case 'd':
case 'e':
- case 'f': goto yy136;
- default: goto yy25;
- }
-yy138: yych = *++YYCURSOR;
-yy139:
-#line 88
- { return "int#hex"; }
-yy140: yych = *++YYCURSOR;
-yy141:
-#line 90
- { return "int#oct"; }
-yy142: ++YYCURSOR;
+ case 'f': goto yy145;
+ default: goto yy25;
+ }
+yy147: ++YYCURSOR;
+ goto yy148;
+yy148:
+#line 91 "implicit.re"
+{ return "int#hex"; }
+#line 1307 "<stdout>"
+yy149: ++YYCURSOR;
+ goto yy150;
+yy150:
+#line 93 "implicit.re"
+{ return "int#oct"; }
+#line 1313 "<stdout>"
+yy151: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy143: switch(yych){
+ goto yy152;
+yy152: switch(yych){
case ',': case '0':
case '1':
case '2':
@@ -1198,11 +1325,12 @@ yy143: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy142;
- case '.': goto yy49;
+ case '9': goto yy151;
+ case '.': goto yy50;
+ case ':': goto yy49;
default: goto yy25;
}
-yy144: yych = *++YYCURSOR;
+yy153: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1213,15 +1341,15 @@ yy144: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy145;
- default: goto yy143;
+ case '9': goto yy154;
+ default: goto yy152;
}
-yy145: yych = *++YYCURSOR;
+yy154: yych = *++YYCURSOR;
switch(yych){
- case '-': goto yy67;
- default: goto yy143;
+ case '-': goto yy76;
+ default: goto yy152;
}
-yy146: yych = *++YYCURSOR;
+yy155: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1230,222 +1358,256 @@ yy146: yych = *++YYCURSOR;
case '4':
case '5':
case '6':
- case '7': goto yy147;
+ case '7': goto yy156;
case '8':
- case '9': goto yy145;
- default: goto yy134;
- }
-yy147: yych = *++YYCURSOR;
- switch(yych){
- case '-': goto yy67;
- default: goto yy134;
- }
-yy148: yych = *++YYCURSOR;
- switch(yych){
- case 'I': goto yy151;
- case 'i': goto yy150;
- default: goto yy25;
- }
-yy149: yych = *++YYCURSOR;
- switch(yych){
- case '\000': goto yy51;
- case 'x': goto yy135;
- default: goto yy134;
- }
-yy150: yych = *++YYCURSOR;
- switch(yych){
- case 'n': goto yy157;
- default: goto yy25;
- }
-yy151: yych = *++YYCURSOR;
- switch(yych){
- case 'N': goto yy152;
- case 'n': goto yy153;
- default: goto yy25;
- }
-yy152: yych = *++YYCURSOR;
- switch(yych){
- case 'F': goto yy154;
- default: goto yy25;
+ case '9': goto yy154;
+ default: goto yy143;
}
-yy153: yych = *++YYCURSOR;
+yy156: yych = *++YYCURSOR;
switch(yych){
- case 'f': goto yy154;
- default: goto yy25;
+ case '-': goto yy76;
+ default: goto yy143;
}
-yy154: yych = *++YYCURSOR;
- if(yych >= '\001') goto yy25;
-yy155: yych = *++YYCURSOR;
-yy156:
-#line 100
- { return "float#neginf"; }
yy157: yych = *++YYCURSOR;
switch(yych){
- case 'f': goto yy154;
+ case 'I': goto yy160;
+ case 'i': goto yy159;
default: goto yy25;
}
yy158: yych = *++YYCURSOR;
switch(yych){
- case 'I': goto yy33;
- case 'i': goto yy32;
- default: goto yy25;
+ case 0x00: goto yy52;
+ case 'x': goto yy144;
+ default: goto yy143;
}
yy159: yych = *++YYCURSOR;
switch(yych){
- case 'L': goto yy166;
+ case 'n': goto yy166;
default: goto yy25;
}
yy160: yych = *++YYCURSOR;
switch(yych){
- case 'l': goto yy161;
+ case 'N': goto yy161;
+ case 'n': goto yy162;
default: goto yy25;
}
yy161: yych = *++YYCURSOR;
switch(yych){
- case 's': goto yy162;
+ case 'F': goto yy163;
default: goto yy25;
}
yy162: yych = *++YYCURSOR;
switch(yych){
- case 'e': goto yy163;
+ case 'f': goto yy163;
default: goto yy25;
}
yy163: yych = *++YYCURSOR;
- if(yych >= '\001') goto yy25;
-yy164: yych = *++YYCURSOR;
+ if(yych >= 0x01) goto yy25;
+ goto yy164;
+yy164: ++YYCURSOR;
+ goto yy165;
yy165:
-#line 86
- { return "bool#no"; }
+#line 107 "implicit.re"
+{ return "float#neginf"; }
+#line 1412 "<stdout>"
yy166: yych = *++YYCURSOR;
switch(yych){
- case 'S': goto yy167;
+ case 'f': goto yy163;
default: goto yy25;
}
yy167: yych = *++YYCURSOR;
switch(yych){
- case 'E': goto yy163;
+ case 'I': goto yy33;
+ case 'i': goto yy32;
default: goto yy25;
}
yy168: yych = *++YYCURSOR;
switch(yych){
- case 'l': goto yy169;
+ case 'L': goto yy175;
default: goto yy25;
}
yy169: yych = *++YYCURSOR;
switch(yych){
- case 's': goto yy170;
+ case 'l': goto yy170;
default: goto yy25;
}
yy170: yych = *++YYCURSOR;
switch(yych){
- case 'e': goto yy163;
+ case 's': goto yy171;
default: goto yy25;
}
yy171: yych = *++YYCURSOR;
switch(yych){
- case 'F': goto yy163;
+ case 'e': goto yy172;
default: goto yy25;
}
yy172: yych = *++YYCURSOR;
+ if(yych >= 0x01) goto yy25;
+ goto yy173;
+yy173: ++YYCURSOR;
+ goto yy174;
+yy174:
+#line 89 "implicit.re"
+{ return "bool#no"; }
+#line 1452 "<stdout>"
+yy175: yych = *++YYCURSOR;
switch(yych){
- case 'f': goto yy163;
+ case 'S': goto yy176;
default: goto yy25;
}
-yy173: yych = *++YYCURSOR;
- if(yych >= '\001') goto yy25;
-yy174: yych = *++YYCURSOR;
-yy175:
-#line 84
- { return "bool#yes"; }
yy176: yych = *++YYCURSOR;
switch(yych){
- case 'f': goto yy163;
+ case 'E': goto yy172;
default: goto yy25;
}
yy177: yych = *++YYCURSOR;
switch(yych){
- case 'S': goto yy173;
+ case 'l': goto yy178;
default: goto yy25;
}
yy178: yych = *++YYCURSOR;
switch(yych){
- case 's': goto yy173;
+ case 's': goto yy179;
default: goto yy25;
}
yy179: yych = *++YYCURSOR;
switch(yych){
- case 's': goto yy173;
+ case 'e': goto yy172;
default: goto yy25;
}
yy180: yych = *++YYCURSOR;
switch(yych){
- case 'U': goto yy183;
+ case 'F': goto yy172;
default: goto yy25;
}
yy181: yych = *++YYCURSOR;
switch(yych){
- case 'u': goto yy182;
+ case 'f': goto yy172;
default: goto yy25;
}
yy182: yych = *++YYCURSOR;
+ if(yych >= 0x01) goto yy25;
+ goto yy183;
+yy183: ++YYCURSOR;
+ goto yy184;
+yy184:
+#line 87 "implicit.re"
+{ return "bool#yes"; }
+#line 1496 "<stdout>"
+yy185: yych = *++YYCURSOR;
switch(yych){
- case 'e': goto yy173;
+ case 'f': goto yy172;
default: goto yy25;
}
-yy183: yych = *++YYCURSOR;
+yy186: yych = *++YYCURSOR;
switch(yych){
- case 'E': goto yy173;
+ case 'U': goto yy189;
default: goto yy25;
}
-yy184: yych = *++YYCURSOR;
+yy187: yych = *++YYCURSOR;
switch(yych){
- case 'u': goto yy185;
+ case 'u': goto yy188;
default: goto yy25;
}
-yy185: yych = *++YYCURSOR;
+yy188: yych = *++YYCURSOR;
switch(yych){
- case 'e': goto yy173;
+ case 'e': goto yy182;
default: goto yy25;
}
-yy186: yych = *++YYCURSOR;
+yy189: yych = *++YYCURSOR;
switch(yych){
- case 'L': goto yy190;
+ case 'E': goto yy182;
default: goto yy25;
}
-yy187: yych = *++YYCURSOR;
+yy190: yych = *++YYCURSOR;
switch(yych){
- case 'l': goto yy188;
+ case 'u': goto yy191;
default: goto yy25;
}
-yy188: yych = *++YYCURSOR;
+yy191: yych = *++YYCURSOR;
switch(yych){
- case 'l': goto yy189;
+ case 'e': goto yy182;
default: goto yy25;
}
-yy189: yych = *++YYCURSOR;
- if(yych <= '\000') goto yy6;
- goto yy25;
-yy190: yych = *++YYCURSOR;
+yy192: yych = *++YYCURSOR;
switch(yych){
- case 'L': goto yy189;
+ case 'S': goto yy182;
default: goto yy25;
}
-yy191: yych = *++YYCURSOR;
+yy193: yych = *++YYCURSOR;
switch(yych){
- case 'l': goto yy192;
+ case 's': goto yy182;
default: goto yy25;
}
-yy192: yych = *++YYCURSOR;
+yy194: yych = *++YYCURSOR;
+ switch(yych){
+ case 's': goto yy182;
+ default: goto yy25;
+ }
+yy195: yych = *++YYCURSOR;
switch(yych){
- case 'l': goto yy189;
+ case 'L': goto yy199;
+ default: goto yy25;
+ }
+yy196: yych = *++YYCURSOR;
+ switch(yych){
+ case 'l': goto yy197;
+ default: goto yy25;
+ }
+yy197: yych = *++YYCURSOR;
+ switch(yych){
+ case 'l': goto yy198;
+ default: goto yy25;
+ }
+yy198: yych = *++YYCURSOR;
+ if(yych <= 0x00) goto yy6;
+ goto yy25;
+yy199: yych = *++YYCURSOR;
+ switch(yych){
+ case 'L': goto yy198;
+ default: goto yy25;
+ }
+yy200: yych = *++YYCURSOR;
+ switch(yych){
+ case 'l': goto yy201;
+ default: goto yy25;
+ }
+yy201: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 'l': goto yy198;
default: goto yy25;
}
}
-#line 118
+#line 125 "implicit.re"
}
+/* Remove ending fragment and compare types */
+int
+syck_tagcmp( char *tag1, char *tag2 )
+{
+ if ( tag1 == tag2 ) return 1;
+ if ( tag1 == NULL || tag2 == NULL ) return 0;
+ else {
+ int i;
+ char *othorpe;
+ char *tmp1 = syck_strndup( tag1, strlen( tag1 ) );
+ char *tmp2 = syck_strndup( tag2, strlen( tag2 ) );
+ othorpe = strstr( tmp1, "#" );
+ if ( othorpe != NULL ) {
+ othorpe[0] = '\0';
+ }
+ othorpe = strstr( tmp2, "#" );
+ if ( othorpe != NULL ) {
+ othorpe[0] = '\0';
+ }
+ i = strcmp( tmp1, tmp2 );
+ S_FREE( tmp1 ); S_FREE( tmp2 );
+ return i;
+ }
+}
+
char *
syck_type_id_to_uri( char *type_id )
{
@@ -1454,17 +1616,19 @@ syck_type_id_to_uri( char *type_id )
cursor = type_id;
limit = type_id + strlen( type_id );
+
+#line 1620 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
- goto yy193;
-yy194: ++YYCURSOR;
-yy193:
- if((YYLIMIT - YYCURSOR) < 21) YYFILL(21);
+ goto yy202;
+ ++YYCURSOR;
+yy202:
+ if((YYLIMIT - YYCURSOR) < 11) YYFILL(11);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy195;
- case '!': goto yy199;
+ case 0x00: goto yy204;
+ case '!': goto yy208;
case '0':
case '1':
case '2':
@@ -1520,22 +1684,22 @@ yy193:
case 's': case 'u':
case 'v':
case 'w': case 'y':
- case 'z': goto yy201;
- case 't': goto yy196;
- case 'x': goto yy198;
- default: goto yy202;
+ case 'z': goto yy210;
+ case 't': goto yy205;
+ case 'x': goto yy207;
+ default: goto yy211;
}
-yy195: YYCURSOR = YYMARKER;
+yy204: YYCURSOR = YYMARKER;
switch(yyaccept){
- case 0: goto yy197;
+ case 0: goto yy206;
}
-yy196: yyaccept = 0;
+yy205: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case ',': goto yy207;
- case '-': goto yy203;
- case '.': goto yy208;
- case '/': goto yy209;
+ case ',': goto yy216;
+ case '-': goto yy212;
+ case '.': goto yy217;
+ case '/': goto yy218;
case '0':
case '1':
case '2':
@@ -1594,14 +1758,15 @@ yy196: yyaccept = 0;
case 'w':
case 'x':
case 'y':
- case 'z': goto yy205;
- case 'a': goto yy237;
- default: goto yy197;
- }
-yy197:
-#line 170
- { return syck_taguri( YAML_DOMAIN, type_id, strlen( type_id ) ); }
-yy198: yyaccept = 0;
+ case 'z': goto yy214;
+ case 'a': goto yy246;
+ default: goto yy206;
+ }
+yy206:
+#line 202 "implicit.re"
+{ return syck_taguri( YAML_DOMAIN, type_id, strlen( type_id ) ); }
+#line 1768 "<stdout>"
+yy207: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
case ',': case '.':
@@ -1665,21 +1830,23 @@ yy198: yyaccept = 0;
case 'w':
case 'x':
case 'y':
- case 'z': goto yy206;
- case '-': goto yy227;
- default: goto yy197;
+ case 'z': goto yy215;
+ case '-': goto yy236;
+ default: goto yy206;
}
-yy199: yych = *++YYCURSOR;
-yy200:
-#line 144
- { return syck_xprivate( type_id + 1, strlen( type_id ) - 1 ); }
-yy201: yyaccept = 0;
+yy208: ++YYCURSOR;
+ goto yy209;
+yy209:
+#line 176 "implicit.re"
+{ return syck_xprivate( type_id + 1, strlen( type_id ) - 1 ); }
+#line 1842 "<stdout>"
+yy210: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case ',': goto yy207;
- case '-': goto yy203;
- case '.': goto yy208;
- case '/': goto yy209;
+ case ',': goto yy216;
+ case '-': goto yy212;
+ case '.': goto yy217;
+ case '/': goto yy218;
case '0':
case '1':
case '2':
@@ -1739,16 +1906,17 @@ yy201: yyaccept = 0;
case 'w':
case 'x':
case 'y':
- case 'z': goto yy205;
- default: goto yy197;
+ case 'z': goto yy214;
+ default: goto yy206;
}
-yy202: yych = *++YYCURSOR;
- goto yy197;
-yy203: ++YYCURSOR;
+yy211: yych = *++YYCURSOR;
+ goto yy206;
+yy212: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy204: switch(yych){
- case '-': goto yy203;
+ goto yy213;
+yy213: switch(yych){
+ case '-': goto yy212;
case '0':
case '1':
case '2':
@@ -1808,17 +1976,18 @@ yy204: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy205;
- default: goto yy195;
+ case 'z': goto yy214;
+ default: goto yy204;
}
-yy205: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+yy214: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
-yy206: switch(yych){
- case ',': goto yy207;
- case '-': goto yy203;
- case '.': goto yy208;
- case '/': goto yy209;
+ goto yy215;
+yy215: switch(yych){
+ case ',': goto yy216;
+ case '-': goto yy212;
+ case '.': goto yy217;
+ case '/': goto yy218;
case '0':
case '1':
case '2':
@@ -1878,10 +2047,10 @@ yy206: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy205;
- default: goto yy195;
+ case 'z': goto yy214;
+ default: goto yy204;
}
-yy207: yych = *++YYCURSOR;
+yy216: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1892,10 +2061,10 @@ yy207: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy215;
- default: goto yy195;
+ case '9': goto yy224;
+ default: goto yy204;
}
-yy208: ++YYCURSOR;
+yy217: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
switch(yych){
@@ -1958,13 +2127,14 @@ yy208: ++YYCURSOR;
case 'w':
case 'x':
case 'y':
- case 'z': goto yy211;
- default: goto yy195;
+ case 'z': goto yy220;
+ default: goto yy204;
}
-yy209: yych = *++YYCURSOR;
-yy210:
-#line 146
- { char *domain = S_ALLOC_N( char, ( YYCURSOR - type_id ) + 15 );
+yy218: ++YYCURSOR;
+ goto yy219;
+yy219:
+#line 178 "implicit.re"
+{ char *domain = S_ALLOC_N( char, ( YYCURSOR - type_id ) + 15 );
char *uri;
domain[0] = '\0';
@@ -1976,14 +2146,16 @@ yy210:
S_FREE( domain );
return uri;
}
-yy211: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+#line 2149 "<stdout>"
+yy220: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 12) YYFILL(12);
yych = *YYCURSOR;
-yy212: switch(yych){
- case ',': goto yy207;
- case '-': goto yy213;
- case '.': goto yy208;
- case '/': goto yy209;
+ goto yy221;
+yy221: switch(yych){
+ case ',': goto yy216;
+ case '-': goto yy222;
+ case '.': goto yy217;
+ case '/': goto yy218;
case '0':
case '1':
case '2':
@@ -2043,14 +2215,15 @@ yy212: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy211;
- default: goto yy195;
+ case 'z': goto yy220;
+ default: goto yy204;
}
-yy213: ++YYCURSOR;
+yy222: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy214: switch(yych){
- case '-': goto yy213;
+ goto yy223;
+yy223: switch(yych){
+ case '-': goto yy222;
case '0':
case '1':
case '2':
@@ -2110,10 +2283,10 @@ yy214: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy211;
- default: goto yy195;
+ case 'z': goto yy220;
+ default: goto yy204;
}
-yy215: yych = *++YYCURSOR;
+yy224: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2124,10 +2297,10 @@ yy215: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy216;
- default: goto yy195;
+ case '9': goto yy225;
+ default: goto yy204;
}
-yy216: yych = *++YYCURSOR;
+yy225: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2138,10 +2311,10 @@ yy216: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy217;
- default: goto yy195;
+ case '9': goto yy226;
+ default: goto yy204;
}
-yy217: yych = *++YYCURSOR;
+yy226: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2152,16 +2325,16 @@ yy217: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy218;
- default: goto yy195;
+ case '9': goto yy227;
+ default: goto yy204;
}
-yy218: yych = *++YYCURSOR;
+yy227: yych = *++YYCURSOR;
switch(yych){
- case '-': goto yy219;
- case '/': goto yy220;
- default: goto yy195;
+ case '-': goto yy228;
+ case '/': goto yy229;
+ default: goto yy204;
}
-yy219: yych = *++YYCURSOR;
+yy228: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2172,13 +2345,14 @@ yy219: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy222;
- default: goto yy195;
+ case '9': goto yy231;
+ default: goto yy204;
}
-yy220: yych = *++YYCURSOR;
-yy221:
-#line 159
- { char *domain = S_ALLOC_N( char, YYCURSOR - type_id );
+yy229: ++YYCURSOR;
+ goto yy230;
+yy230:
+#line 191 "implicit.re"
+{ char *domain = S_ALLOC_N( char, YYCURSOR - type_id );
char *uri;
domain[0] = '\0';
@@ -2188,7 +2362,8 @@ yy221:
S_FREE( domain );
return uri;
}
-yy222: yych = *++YYCURSOR;
+#line 2365 "<stdout>"
+yy231: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2199,16 +2374,16 @@ yy222: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy223;
- default: goto yy195;
+ case '9': goto yy232;
+ default: goto yy204;
}
-yy223: yych = *++YYCURSOR;
+yy232: yych = *++YYCURSOR;
switch(yych){
- case '-': goto yy224;
- case '/': goto yy220;
- default: goto yy195;
+ case '-': goto yy233;
+ case '/': goto yy229;
+ default: goto yy204;
}
-yy224: yych = *++YYCURSOR;
+yy233: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2219,10 +2394,10 @@ yy224: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy225;
- default: goto yy195;
+ case '9': goto yy234;
+ default: goto yy204;
}
-yy225: yych = *++YYCURSOR;
+yy234: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2233,109 +2408,112 @@ yy225: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy226;
- default: goto yy195;
+ case '9': goto yy235;
+ default: goto yy204;
}
-yy226: yych = *++YYCURSOR;
+yy235: yych = *++YYCURSOR;
switch(yych){
- case '/': goto yy220;
- default: goto yy195;
+ case '/': goto yy229;
+ default: goto yy204;
}
-yy227: yych = *++YYCURSOR;
+yy236: yych = *++YYCURSOR;
switch(yych){
- case 'p': goto yy228;
- default: goto yy204;
+ case 'p': goto yy237;
+ default: goto yy213;
}
-yy228: yych = *++YYCURSOR;
+yy237: yych = *++YYCURSOR;
switch(yych){
- case ',': goto yy207;
- case '.': goto yy208;
- case '/': goto yy209;
- case 'r': goto yy229;
- default: goto yy204;
+ case ',': goto yy216;
+ case '.': goto yy217;
+ case '/': goto yy218;
+ case 'r': goto yy238;
+ default: goto yy213;
}
-yy229: yych = *++YYCURSOR;
+yy238: yych = *++YYCURSOR;
switch(yych){
- case ',': goto yy207;
- case '.': goto yy208;
- case '/': goto yy209;
- case 'i': goto yy230;
- default: goto yy204;
+ case ',': goto yy216;
+ case '.': goto yy217;
+ case '/': goto yy218;
+ case 'i': goto yy239;
+ default: goto yy213;
}
-yy230: yych = *++YYCURSOR;
+yy239: yych = *++YYCURSOR;
switch(yych){
- case ',': goto yy207;
- case '.': goto yy208;
- case '/': goto yy209;
- case 'v': goto yy231;
- default: goto yy204;
+ case ',': goto yy216;
+ case '.': goto yy217;
+ case '/': goto yy218;
+ case 'v': goto yy240;
+ default: goto yy213;
}
-yy231: yych = *++YYCURSOR;
+yy240: yych = *++YYCURSOR;
switch(yych){
- case ',': goto yy207;
- case '.': goto yy208;
- case '/': goto yy209;
- case 'a': goto yy232;
- default: goto yy204;
+ case ',': goto yy216;
+ case '.': goto yy217;
+ case '/': goto yy218;
+ case 'a': goto yy241;
+ default: goto yy213;
}
-yy232: yych = *++YYCURSOR;
+yy241: yych = *++YYCURSOR;
switch(yych){
- case ',': goto yy207;
- case '.': goto yy208;
- case '/': goto yy209;
- case 't': goto yy233;
- default: goto yy204;
+ case ',': goto yy216;
+ case '.': goto yy217;
+ case '/': goto yy218;
+ case 't': goto yy242;
+ default: goto yy213;
}
-yy233: yych = *++YYCURSOR;
+yy242: yych = *++YYCURSOR;
switch(yych){
- case ',': goto yy207;
- case '.': goto yy208;
- case '/': goto yy209;
- case 'e': goto yy234;
- default: goto yy204;
+ case ',': goto yy216;
+ case '.': goto yy217;
+ case '/': goto yy218;
+ case 'e': goto yy243;
+ default: goto yy213;
}
-yy234: yych = *++YYCURSOR;
+yy243: yych = *++YYCURSOR;
switch(yych){
- case ',': goto yy207;
- case '.': goto yy208;
- case '/': goto yy209;
- case ':': goto yy235;
- default: goto yy204;
+ case ',': goto yy216;
+ case '.': goto yy217;
+ case '/': goto yy218;
+ case ':': goto yy244;
+ default: goto yy213;
}
-yy235: yych = *++YYCURSOR;
-yy236:
-#line 142
- { return type_id; }
-yy237: yych = *++YYCURSOR;
+yy244: ++YYCURSOR;
+ goto yy245;
+yy245:
+#line 174 "implicit.re"
+{ return syck_strndup( type_id, strlen( type_id ) ); }
+#line 2485 "<stdout>"
+yy246: yych = *++YYCURSOR;
switch(yych){
- case ',': goto yy207;
- case '.': goto yy208;
- case '/': goto yy209;
- case 'g': goto yy238;
- default: goto yy204;
+ case ',': goto yy216;
+ case '.': goto yy217;
+ case '/': goto yy218;
+ case 'g': goto yy247;
+ default: goto yy213;
}
-yy238: yych = *++YYCURSOR;
+yy247: yych = *++YYCURSOR;
switch(yych){
- case ',': goto yy207;
- case '.': goto yy208;
- case '/': goto yy209;
- case ':': goto yy239;
- default: goto yy204;
+ case ',': goto yy216;
+ case '.': goto yy217;
+ case '/': goto yy218;
+ case ':': goto yy248;
+ default: goto yy213;
}
-yy239: yych = *++YYCURSOR;
+yy248: yych = *++YYCURSOR;
switch(yych){
case ',':
case '-':
- case '.': goto yy195;
- default: goto yy241;
+ case '.': goto yy204;
+ default: goto yy250;
}
-yy240: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+yy249: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
-yy241: switch(yych){
- case ',': goto yy244;
- case '-': goto yy242;
- case '.': goto yy245;
+ goto yy250;
+yy250: switch(yych){
+ case ',': goto yy253;
+ case '-': goto yy251;
+ case '.': goto yy254;
case '0':
case '1':
case '2':
@@ -2395,14 +2573,15 @@ yy241: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy240;
- default: goto yy195;
+ case 'z': goto yy249;
+ default: goto yy204;
}
-yy242: ++YYCURSOR;
+yy251: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy243: switch(yych){
- case '-': goto yy242;
+ goto yy252;
+yy252: switch(yych){
+ case '-': goto yy251;
case '0':
case '1':
case '2':
@@ -2462,10 +2641,10 @@ yy243: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy240;
- default: goto yy195;
+ case 'z': goto yy249;
+ default: goto yy204;
}
-yy244: yych = *++YYCURSOR;
+yy253: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2476,10 +2655,10 @@ yy244: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy250;
- default: goto yy195;
+ case '9': goto yy259;
+ default: goto yy204;
}
-yy245: ++YYCURSOR;
+yy254: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
switch(yych){
@@ -2542,16 +2721,17 @@ yy245: ++YYCURSOR;
case 'w':
case 'x':
case 'y':
- case 'z': goto yy246;
- default: goto yy195;
+ case 'z': goto yy255;
+ default: goto yy204;
}
-yy246: ++YYCURSOR;
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+yy255: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 12) YYFILL(12);
yych = *YYCURSOR;
-yy247: switch(yych){
- case ',': goto yy244;
- case '-': goto yy248;
- case '.': goto yy245;
+ goto yy256;
+yy256: switch(yych){
+ case ',': goto yy253;
+ case '-': goto yy257;
+ case '.': goto yy254;
case '0':
case '1':
case '2':
@@ -2611,14 +2791,15 @@ yy247: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy246;
- default: goto yy195;
+ case 'z': goto yy255;
+ default: goto yy204;
}
-yy248: ++YYCURSOR;
+yy257: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy249: switch(yych){
- case '-': goto yy248;
+ goto yy258;
+yy258: switch(yych){
+ case '-': goto yy257;
case '0':
case '1':
case '2':
@@ -2678,10 +2859,10 @@ yy249: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy246;
- default: goto yy195;
+ case 'z': goto yy255;
+ default: goto yy204;
}
-yy250: yych = *++YYCURSOR;
+yy259: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2692,10 +2873,10 @@ yy250: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy251;
- default: goto yy195;
+ case '9': goto yy260;
+ default: goto yy204;
}
-yy251: yych = *++YYCURSOR;
+yy260: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2706,10 +2887,10 @@ yy251: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy252;
- default: goto yy195;
+ case '9': goto yy261;
+ default: goto yy204;
}
-yy252: yych = *++YYCURSOR;
+yy261: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2720,16 +2901,16 @@ yy252: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy253;
- default: goto yy195;
+ case '9': goto yy262;
+ default: goto yy204;
}
-yy253: yych = *++YYCURSOR;
+yy262: yych = *++YYCURSOR;
switch(yych){
- case '-': goto yy254;
- case ':': goto yy255;
- default: goto yy195;
+ case '-': goto yy263;
+ case ':': goto yy264;
+ default: goto yy204;
}
-yy254: yych = *++YYCURSOR;
+yy263: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2740,14 +2921,16 @@ yy254: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy257;
- default: goto yy195;
+ case '9': goto yy266;
+ default: goto yy204;
}
-yy255: yych = *++YYCURSOR;
-yy256:
-#line 140
- { return type_id; }
-yy257: yych = *++YYCURSOR;
+yy264: ++YYCURSOR;
+ goto yy265;
+yy265:
+#line 172 "implicit.re"
+{ return syck_strndup( type_id, strlen( type_id ) ); }
+#line 2932 "<stdout>"
+yy266: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2758,16 +2941,16 @@ yy257: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy258;
- default: goto yy195;
+ case '9': goto yy267;
+ default: goto yy204;
}
-yy258: yych = *++YYCURSOR;
+yy267: yych = *++YYCURSOR;
switch(yych){
- case '-': goto yy259;
- case ':': goto yy255;
- default: goto yy195;
+ case '-': goto yy268;
+ case ':': goto yy264;
+ default: goto yy204;
}
-yy259: yych = *++YYCURSOR;
+yy268: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2778,10 +2961,10 @@ yy259: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy260;
- default: goto yy195;
+ case '9': goto yy269;
+ default: goto yy204;
}
-yy260: yych = *++YYCURSOR;
+yy269: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2792,17 +2975,16 @@ yy260: yych = *++YYCURSOR;
case '6':
case '7':
case '8':
- case '9': goto yy261;
- default: goto yy195;
+ case '9': goto yy270;
+ default: goto yy204;
}
-yy261: yych = *++YYCURSOR;
- switch(yych){
- case ':': goto yy255;
- default: goto yy195;
+yy270: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case ':': goto yy264;
+ default: goto yy204;
}
}
-#line 172
+#line 204 "implicit.re"
}
-
diff --git a/ext/syck/node.c b/ext/syck/node.c
index f999700554..28fc78c077 100644
--- a/ext/syck/node.c
+++ b/ext/syck/node.c
@@ -7,8 +7,8 @@
* Copyright (C) 2003 why the lucky stiff
*/
-#include "syck.h"
#include "ruby.h"
+#include "syck.h"
/*
* Node allocation functions
@@ -33,9 +33,15 @@ syck_free_node( SyckNode *n )
{
syck_free_members( n );
if ( n->type_id != NULL )
+ {
S_FREE( n->type_id );
+ n->type_id = NULL;
+ }
if ( n->anchor != NULL )
+ {
S_FREE( n->anchor );
+ n->anchor = NULL;
+ }
S_FREE( n );
}
@@ -46,6 +52,7 @@ syck_alloc_map()
struct SyckMap *m;
m = S_ALLOC( struct SyckMap );
+ m->style = map_none;
m->idx = 0;
m->capa = ALLOC_CT;
m->keys = S_ALLOC_N( SYMID, m->capa );
@@ -64,6 +71,7 @@ syck_alloc_seq()
struct SyckSeq *s;
s = S_ALLOC( struct SyckSeq );
+ s->style = seq_none;
s->idx = 0;
s->capa = ALLOC_CT;
s->items = S_ALLOC_N( SYMID, s->capa );
@@ -83,6 +91,7 @@ syck_alloc_str()
s = S_ALLOC( struct SyckStr );
s->len = 0;
s->ptr = NULL;
+ s->style = scalar_none;
n = syck_alloc_node( syck_str_kind );
n->data.str = s;
@@ -91,19 +100,20 @@ syck_alloc_str()
}
SyckNode *
-syck_new_str( char *str )
+syck_new_str( char *str, enum scalar_style style )
{
- return syck_new_str2( str, strlen( str ) );
+ return syck_new_str2( str, strlen( str ), style );
}
SyckNode *
-syck_new_str2( char *str, long len )
+syck_new_str2( char *str, long len, enum scalar_style style )
{
SyckNode *n;
n = syck_alloc_str();
n->data.str->ptr = S_ALLOC_N( char, len + 1 );
n->data.str->len = len;
+ n->data.str->style = style;
memcpy( n->data.str->ptr, str, len );
n->data.str->ptr[len] = '\0';
@@ -111,6 +121,28 @@ syck_new_str2( char *str, long len )
}
void
+syck_replace_str( SyckNode *n, char *str, enum scalar_style style )
+{
+ syck_replace_str2( n, str, strlen( str ), style );
+}
+
+void
+syck_replace_str2( SyckNode *n, char *str, long len, enum scalar_style style )
+{
+ if ( n->data.str != NULL )
+ {
+ S_FREE( n->data.str->ptr );
+ n->data.str->ptr = NULL;
+ n->data.str->len = 0;
+ }
+ n->data.str->ptr = S_ALLOC_N( char, len + 1 );
+ n->data.str->len = len;
+ n->data.str->style = style;
+ memcpy( n->data.str->ptr, str, len );
+ n->data.str->ptr[len] = '\0';
+}
+
+void
syck_str_blow_away_commas( SyckNode *n )
{
char *go, *end;
@@ -147,6 +179,22 @@ syck_new_map( SYMID key, SYMID value )
}
void
+syck_map_empty( SyckNode *n )
+{
+ struct SyckMap *m;
+ ASSERT( n != NULL );
+ ASSERT( n->data.list != NULL );
+
+ S_FREE( n->data.pairs->keys );
+ S_FREE( n->data.pairs->values );
+ m = n->data.pairs;
+ m->idx = 0;
+ m->capa = ALLOC_CT;
+ m->keys = S_ALLOC_N( SYMID, m->capa );
+ m->values = S_ALLOC_N( SYMID, m->capa );
+}
+
+void
syck_map_add( SyckNode *map, SYMID key, SYMID value )
{
struct SyckMap *m;
@@ -256,6 +304,20 @@ syck_new_seq( SYMID value )
}
void
+syck_seq_empty( SyckNode *n )
+{
+ struct SyckSeq *s;
+ ASSERT( n != NULL );
+ ASSERT( n->data.list != NULL );
+
+ S_FREE( n->data.list->items );
+ s = n->data.list;
+ s->idx = 0;
+ s->capa = ALLOC_CT;
+ s->items = S_ALLOC_N( SYMID, s->capa );
+}
+
+void
syck_seq_add( SyckNode *arr, SYMID value )
{
struct SyckSeq *s;
@@ -283,6 +345,17 @@ syck_seq_count( SyckNode *seq )
return seq->data.list->idx;
}
+void
+syck_seq_assign( SyckNode *seq, long idx, SYMID id )
+{
+ struct SyckSeq *s;
+
+ ASSERT( map != NULL );
+ s = seq->data.list;
+ ASSERT( m != NULL );
+ s->items[idx] = id;
+}
+
SYMID
syck_seq_read( SyckNode *seq, long idx )
{
@@ -297,27 +370,38 @@ syck_seq_read( SyckNode *seq, long idx )
void
syck_free_members( SyckNode *n )
{
+ if ( n == NULL ) return;
+
switch ( n->kind )
{
case syck_str_kind:
- if ( n->data.str->ptr != NULL )
+ if ( n->data.str != NULL )
{
S_FREE( n->data.str->ptr );
n->data.str->ptr = NULL;
n->data.str->len = 0;
S_FREE( n->data.str );
+ n->data.str = NULL;
}
break;
case syck_seq_kind:
- S_FREE( n->data.list->items );
- S_FREE( n->data.list );
+ if ( n->data.list != NULL )
+ {
+ S_FREE( n->data.list->items );
+ S_FREE( n->data.list );
+ n->data.list = NULL;
+ }
break;
case syck_map_kind:
- S_FREE( n->data.pairs->keys );
- S_FREE( n->data.pairs->values );
- S_FREE( n->data.pairs );
+ if ( n->data.pairs != NULL )
+ {
+ S_FREE( n->data.pairs->keys );
+ S_FREE( n->data.pairs->values );
+ S_FREE( n->data.pairs );
+ n->data.pairs = NULL;
+ }
break;
}
}
diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c
index 589033507d..76e8279601 100644
--- a/ext/syck/rubyext.c
+++ b/ext/syck/rubyext.c
@@ -1,10 +1,11 @@
+/* -*- indent-tabs-mode: nil -*- */
/*
* rubyext.c
*
* $Author$
* $Date$
*
- * Copyright (C) 2003 why the lucky stiff
+ * Copyright (C) 2003-2005 why the lucky stiff
*/
#include "ruby.h"
@@ -15,23 +16,23 @@
typedef struct RVALUE {
union {
#if 0
- struct {
- unsigned long flags; /* always 0 for freed obj */
- struct RVALUE *next;
- } free;
+ struct {
+ unsigned long flags; /* always 0 for freed obj */
+ struct RVALUE *next;
+ } free;
#endif
- struct RBasic basic;
- struct RObject object;
- struct RClass klass;
- /*struct RFloat flonum;*/
- /*struct RString string;*/
- struct RArray array;
- /*struct RRegexp regexp;*/
- struct RHash hash;
- /*struct RData data;*/
- struct RStruct rstruct;
- /*struct RBignum bignum;*/
- /*struct RFile file;*/
+ struct RBasic basic;
+ struct RObject object;
+ struct RClass klass;
+ /*struct RFloat flonum;*/
+ /*struct RString string;*/
+ struct RArray array;
+ /*struct RRegexp regexp;*/
+ struct RHash hash;
+ /*struct RData data;*/
+ struct RStruct rstruct;
+ /*struct RBignum bignum;*/
+ /*struct RFile file;*/
} as;
} RVALUE;
@@ -48,11 +49,13 @@ typedef struct {
/*
* symbols and constants
*/
-static ID s_new, s_utc, s_at, s_to_f, s_to_i, s_read, s_binmode, s_call, s_transfer, s_update, s_dup, s_match, s_keys, s_to_str, s_unpack, s_tr_bang, s_anchors, s_default_set;
+static ID s_new, s_utc, s_at, s_to_f, s_to_i, s_read, s_binmode, s_call, s_cmp, s_transfer, s_update, s_dup, s_haskey, s_match, s_keys, s_unpack, s_tr_bang, s_default_set, s_tag_read_class, s_tag_subclasses, s_resolver, s_push, s_emitter, s_level, s_detect_implicit, s_node_import, s_out, s_input, s_intern, s_transform, s_yaml_new, s_yaml_initialize, s_node_export, s_to_yaml, s_write, s_set_resolver;
+static ID s_tags, s_domain, s_kind, s_name, s_options, s_type_id, s_type_id_set, s_style, s_style_set, s_value, s_value_set;
static VALUE sym_model, sym_generic, sym_input, sym_bytecode;
static VALUE sym_scalar, sym_seq, sym_map;
-VALUE cDate, cParser, cLoader, cNode, cPrivateType, cDomainType, cBadAlias, cDefaultKey, cMergeKey, cEmitter;
-VALUE oDefaultLoader;
+static VALUE sym_1quote, sym_2quote, sym_fold, sym_literal, sym_plain, sym_inline;
+static VALUE cDate, cNode, cMap, cSeq, cScalar, cOut, cParser, cResolver, cPrivateType, cDomainType, cYObject, cBadAlias, cDefaultKey, cMergeKey, cEmitter;
+static VALUE oDefaultResolver, oGenericResolver;
/*
* my private collection of numerical oddities.
@@ -67,24 +70,35 @@ static VALUE syck_node_transform( VALUE );
/*
* handler prototypes
*/
-SYMID rb_syck_parse_handler _((SyckParser *, SyckNode *));
SYMID rb_syck_load_handler _((SyckParser *, SyckNode *));
void rb_syck_err_handler _((SyckParser *, char *));
SyckNode * rb_syck_bad_anchor_handler _((SyckParser *, char *));
void rb_syck_output_handler _((SyckEmitter *, char *, long));
+void rb_syck_emitter_handler _((SyckEmitter *, st_data_t));
+int syck_parser_assign_io _((SyckParser *, VALUE *));
+VALUE syck_scalar_alloc _((VALUE class));
+VALUE syck_seq_alloc _((VALUE class));
+VALUE syck_map_alloc _((VALUE class));
struct parser_xtra {
VALUE data; /* Borrowed this idea from marshal.c to fix [ruby-core:8067] problem */
VALUE proc;
+ VALUE resolver;
int taint;
};
+struct emitter_xtra {
+ VALUE oid;
+ VALUE data;
+ VALUE port;
+};
+
/*
* Convert YAML to bytecode
*/
VALUE
rb_syck_compile(self, port)
- VALUE self, port;
+ VALUE self, port;
{
SYMID oid;
int taint;
@@ -93,7 +107,7 @@ rb_syck_compile(self, port)
bytestring_t *sav;
SyckParser *parser = syck_new_parser();
- taint = syck_parser_assign_io(parser, port);
+ taint = syck_parser_assign_io(parser, &port);
syck_parser_handler( parser, syck_yaml2byte_handler );
syck_parser_error_handler( parser, NULL );
syck_parser_implicit_typing( parser, 0 );
@@ -101,7 +115,7 @@ rb_syck_compile(self, port)
oid = syck_parse( parser );
syck_lookup_sym( parser, oid, (char **)&sav );
- ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 );
+ ret = S_ALLOCA_N( char, strlen( sav->buffer ) + 3 );
ret[0] = '\0';
strcat( ret, "D\n" );
strcat( ret, sav->buffer );
@@ -135,6 +149,7 @@ rb_syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
VALUE str2 = rb_funcall2(src, s_read, 1, &n);
if (!NIL_P(str2))
{
+ StringValue(str2);
len = RSTRING(str2)->len;
memcpy( buf + skip, RSTRING(str2)->ptr, len );
}
@@ -149,15 +164,16 @@ rb_syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
* (returns tainted? boolean)
*/
int
-syck_parser_assign_io(parser, port)
- SyckParser *parser;
- VALUE port;
+syck_parser_assign_io(parser, pport)
+ SyckParser *parser;
+ VALUE *pport;
{
int taint = Qtrue;
- if (rb_respond_to(port, s_to_str)) {
- taint = OBJ_TAINTED(port); /* original taintedness */
- StringValue(port); /* possible conversion */
- syck_parser_str( parser, RSTRING(port)->ptr, RSTRING(port)->len, NULL );
+ VALUE tmp, port = *pport;
+ if (!NIL_P(tmp = rb_check_string_type(port))) {
+ taint = OBJ_TAINTED(port); /* original taintedness */
+ port = tmp;
+ syck_parser_str( parser, RSTRING(port)->ptr, RSTRING(port)->len, NULL );
}
else if (rb_respond_to(port, s_read)) {
if (rb_respond_to(port, s_binmode)) {
@@ -168,6 +184,7 @@ syck_parser_assign_io(parser, port)
else {
rb_raise(rb_eTypeError, "instance of IO needed");
}
+ *pport = port;
return taint;
}
@@ -191,63 +208,85 @@ syck_get_hash_aref(hsh, key)
* creating timestamps
*/
SYMID
-rb_syck_mktime(str)
+rb_syck_mktime(str, len)
char *str;
+ long len;
{
VALUE time;
char *ptr = str;
- VALUE year, mon, day, hour, min, sec, usec;
+ VALUE year = INT2FIX(0);
+ VALUE mon = INT2FIX(0);
+ VALUE day = INT2FIX(0);
+ VALUE hour = INT2FIX(0);
+ VALUE min = INT2FIX(0);
+ VALUE sec = INT2FIX(0);
+ long usec;
/* Year*/
- ptr[4] = '\0';
- year = INT2FIX(strtol(ptr, NULL, 10));
+ if ( ptr[0] != '\0' && len > 0 ) {
+ year = INT2FIX(strtol(ptr, NULL, 10));
+ }
/* Month*/
ptr += 4;
- while ( !isdigit( *ptr ) ) ptr++;
- mon = INT2FIX(strtol(ptr, NULL, 10));
+ if ( ptr[0] != '\0' && len > ptr - str ) {
+ while ( !ISDIGIT( *ptr ) ) ptr++;
+ mon = INT2FIX(strtol(ptr, NULL, 10));
+ }
/* Day*/
ptr += 2;
- while ( !isdigit( *ptr ) ) ptr++;
- day = INT2FIX(strtol(ptr, NULL, 10));
+ if ( ptr[0] != '\0' && len > ptr - str ) {
+ while ( !ISDIGIT( *ptr ) ) ptr++;
+ day = INT2FIX(strtol(ptr, NULL, 10));
+ }
/* Hour*/
ptr += 2;
- while ( !isdigit( *ptr ) ) ptr++;
- hour = INT2FIX(strtol(ptr, NULL, 10));
+ if ( ptr[0] != '\0' && len > ptr - str ) {
+ while ( !ISDIGIT( *ptr ) ) ptr++;
+ hour = INT2FIX(strtol(ptr, NULL, 10));
+ }
/* Minute */
ptr += 2;
- while ( !isdigit( *ptr ) ) ptr++;
- min = INT2FIX(strtol(ptr, NULL, 10));
+ if ( ptr[0] != '\0' && len > ptr - str ) {
+ while ( !ISDIGIT( *ptr ) ) ptr++;
+ min = INT2FIX(strtol(ptr, NULL, 10));
+ }
/* Second */
ptr += 2;
- while ( !isdigit( *ptr ) ) ptr++;
- sec = INT2FIX(strtol(ptr, NULL, 10));
+ if ( ptr[0] != '\0' && len > ptr - str ) {
+ while ( !ISDIGIT( *ptr ) ) ptr++;
+ sec = INT2FIX(strtol(ptr, NULL, 10));
+ }
/* Millisecond */
ptr += 2;
- if ( *ptr == '.' )
+ if ( len > ptr - str && *ptr == '.' )
{
- usec = INT2FIX( strtod( ptr, NULL ) * 1000000 );
+ char padded[] = "000000";
+ char *end = ptr + 1;
+ char *p = end;
+ while ( isdigit( *end ) ) end++;
+ if (end - p < sizeof(padded)) {
+ MEMCPY(padded, ptr + 1, char, end - (ptr + 1));
+ p = padded;
+ }
+ usec = strtol(p, NULL, 10);
}
else
{
- usec = INT2FIX( 0 );
+ usec = 0;
}
- /* Make UTC time*/
- time = rb_funcall(rb_cTime, s_utc, 7, year, mon, day, hour, min, sec, usec);
-
/* Time Zone*/
- while ( *ptr != 'Z' && *ptr != '+' && *ptr != '-' && *ptr != '\0' ) ptr++;
- if ( *ptr == '-' || *ptr == '+' )
+ while ( len > ptr - str && *ptr != 'Z' && *ptr != '+' && *ptr != '-' && *ptr != '\0' ) ptr++;
+ if ( len > ptr - str && ( *ptr == '-' || *ptr == '+' ) )
{
- double tz_offset = 0;
- double utc_time = 0;
- tz_offset += strtod(ptr, NULL) * 3600;
+ time_t tz_offset = strtol(ptr, NULL, 10) * 3600;
+ time_t tmp;
while ( *ptr != ':' && *ptr != '\0' ) ptr++;
if ( *ptr == ':' )
@@ -255,81 +294,24 @@ rb_syck_mktime(str)
ptr += 1;
if ( tz_offset < 0 )
{
- tz_offset -= strtod(ptr, NULL) * 60;
+ tz_offset -= strtol(ptr, NULL, 10) * 60;
}
else
{
- tz_offset += strtod(ptr, NULL) * 60;
+ tz_offset += strtol(ptr, NULL, 10) * 60;
}
}
/* Make TZ time*/
- utc_time = NUM2DBL(rb_funcall(time, s_to_f, 0));
- utc_time -= tz_offset;
- time = rb_funcall(rb_cTime, s_at, 1, rb_float_new(utc_time));
+ time = rb_funcall(rb_cTime, s_utc, 6, year, mon, day, hour, min, sec);
+ tmp = NUM2LONG(rb_funcall(time, s_to_i, 0)) - tz_offset;
+ return rb_funcall(rb_cTime, s_at, 2, LONG2NUM(tmp), LONG2NUM(usec));
}
-
- return time;
-}
-
-/*
- * {generic mode} node handler
- * - Loads data into Node classes
- */
-SYMID
-rb_syck_parse_handler(p, n)
- SyckParser *p;
- SyckNode *n;
-{
- VALUE t, obj, v = Qnil;
- int i;
- struct parser_xtra *bonus;
-
- obj = rb_obj_alloc(cNode);
- if ( n->type_id != NULL )
- {
- t = rb_str_new2(n->type_id);
- rb_iv_set(obj, "@type_id", t);
- }
-
- switch (n->kind)
+ else
{
- case syck_str_kind:
- rb_iv_set(obj, "@kind", sym_scalar);
- v = rb_str_new( n->data.str->ptr, n->data.str->len );
- break;
-
- case syck_seq_kind:
- rb_iv_set(obj, "@kind", sym_seq);
- v = rb_ary_new2( n->data.list->idx );
- for ( i = 0; i < n->data.list->idx; i++ )
- {
- rb_ary_store( v, i, syck_seq_read( n, i ) );
- }
- break;
-
- case syck_map_kind:
- rb_iv_set(obj, "@kind", sym_map);
- v = rb_hash_new();
- for ( i = 0; i < n->data.pairs->idx; i++ )
- {
- VALUE key = syck_node_transform( syck_map_read( n, map_key, i ) );
- VALUE val = rb_ary_new();
- rb_ary_push(val, syck_map_read( n, map_key, i ));
- rb_ary_push(val, syck_map_read( n, map_value, i ));
-
- rb_hash_aset( v, key, val );
- }
- break;
+ /* Make UTC time*/
+ return rb_funcall(rb_cTime, s_utc, 7, year, mon, day, hour, min, sec, LONG2NUM(usec));
}
-
- bonus = (struct parser_xtra *)p->bonus;
- if ( bonus->taint) OBJ_TAINT( obj );
- if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, v);
-
- rb_iv_set(obj, "@value", v);
- rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj);
- return obj;
}
/*
@@ -340,57 +322,13 @@ VALUE
syck_merge_i( entry, hsh )
VALUE entry, hsh;
{
- if ( rb_obj_is_kind_of( entry, rb_cHash ) )
- {
- rb_funcall( hsh, s_update, 1, entry );
- }
- return Qnil;
-}
-
-/*
- * build a syck node from a Ruby VALUE
- */
-SyckNode *
-rb_new_syck_node( obj, type_id )
- VALUE obj, type_id;
-{
- long i = 0;
- SyckNode *n = NULL;
-
- if (rb_respond_to(obj, s_to_str))
+ VALUE tmp;
+ if ( !NIL_P(tmp = rb_check_convert_type(entry, T_HASH, "Hash", "to_hash")) )
{
- StringValue(obj); /* possible conversion */
- n = syck_alloc_str();
- n->data.str->ptr = RSTRING(obj)->ptr;
- n->data.str->len = RSTRING(obj)->len;
+ entry = tmp;
+ rb_funcall( hsh, s_update, 1, entry );
}
- else if ( rb_obj_is_kind_of( obj, rb_cArray ) )
- {
- n = syck_alloc_seq();
- for ( i = 0; i < RARRAY(obj)->len; i++ )
- {
- syck_seq_add(n, rb_ary_entry(obj, i));
- }
- }
- else if ( rb_obj_is_kind_of( obj, rb_cHash ) )
- {
- VALUE keys;
- n = syck_alloc_map();
- keys = rb_funcall( obj, s_keys, 0 );
- for ( i = 0; i < RARRAY(keys)->len; i++ )
- {
- VALUE key = rb_ary_entry(keys, i);
- syck_map_add(n, key, rb_hash_aref(obj, key));
- }
- }
-
- if ( n!= NULL && rb_respond_to( type_id, s_to_str ) )
- {
- StringValue(type_id);
- n->type_id = syck_strndup( RSTRING(type_id)->ptr, RSTRING(type_id)->len );
- }
-
- return n;
+ return Qnil;
}
/*
@@ -406,11 +344,16 @@ yaml_org_handler( n, ref )
long i = 0;
VALUE obj = Qnil;
+ if ( type_id != NULL && strncmp( type_id, "tag:yaml.org,2002:", 18 ) == 0 )
+ {
+ type_id += 18;
+ }
+
switch (n->kind)
{
case syck_str_kind:
transferred = 1;
- if ( type_id == NULL || strcmp( type_id, "str" ) == 0 )
+ if ( type_id == NULL )
{
obj = rb_str_new( n->data.str->ptr, n->data.str->len );
}
@@ -436,17 +379,69 @@ yaml_org_handler( n, ref )
}
else if ( strcmp( type_id, "int#hex" ) == 0 )
{
+ syck_str_blow_away_commas( n );
obj = rb_cstr2inum( n->data.str->ptr, 16 );
}
else if ( strcmp( type_id, "int#oct" ) == 0 )
{
+ syck_str_blow_away_commas( n );
obj = rb_cstr2inum( n->data.str->ptr, 8 );
}
+ else if ( strcmp( type_id, "int#base60" ) == 0 )
+ {
+ char *ptr, *end;
+ long sixty = 1;
+ long total = 0;
+ syck_str_blow_away_commas( n );
+ ptr = n->data.str->ptr;
+ end = n->data.str->ptr + n->data.str->len;
+ while ( end > ptr )
+ {
+ long bnum = 0;
+ char *colon = end - 1;
+ while ( colon >= ptr && *colon != ':' )
+ {
+ colon--;
+ }
+ if ( colon >= ptr && *colon == ':' ) *colon = '\0';
+
+ bnum = strtol( colon + 1, NULL, 10 );
+ total += bnum * sixty;
+ sixty *= 60;
+ end = colon;
+ }
+ obj = INT2FIX(total);
+ }
else if ( strncmp( type_id, "int", 3 ) == 0 )
{
syck_str_blow_away_commas( n );
obj = rb_cstr2inum( n->data.str->ptr, 10 );
}
+ else if ( strcmp( type_id, "float#base60" ) == 0 )
+ {
+ char *ptr, *end;
+ long sixty = 1;
+ double total = 0.0;
+ syck_str_blow_away_commas( n );
+ ptr = n->data.str->ptr;
+ end = n->data.str->ptr + n->data.str->len;
+ while ( end > ptr )
+ {
+ double bnum = 0;
+ char *colon = end - 1;
+ while ( colon >= ptr && *colon != ':' )
+ {
+ colon--;
+ }
+ if ( colon >= ptr && *colon == ':' ) *colon = '\0';
+
+ bnum = strtod( colon + 1, NULL );
+ total += bnum * sixty;
+ sixty *= 60;
+ end = colon;
+ }
+ obj = rb_float_new( total );
+ }
else if ( strcmp( type_id, "float#nan" ) == 0 )
{
obj = rb_float_new( S_nan() );
@@ -468,11 +463,11 @@ yaml_org_handler( n, ref )
}
else if ( strcmp( type_id, "timestamp#iso8601" ) == 0 )
{
- obj = rb_syck_mktime( n->data.str->ptr );
+ obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
}
else if ( strcmp( type_id, "timestamp#spaced" ) == 0 )
{
- obj = rb_syck_mktime( n->data.str->ptr );
+ obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
}
else if ( strcmp( type_id, "timestamp#ymd" ) == 0 )
{
@@ -485,28 +480,48 @@ yaml_org_handler( n, ref )
/* Month*/
ptr += 4;
- while ( !isdigit( *ptr ) ) ptr++;
+ while ( !ISDIGIT( *ptr ) ) ptr++;
mon = INT2FIX(strtol(ptr, NULL, 10));
/* Day*/
ptr += 2;
- while ( !isdigit( *ptr ) ) ptr++;
+ while ( !ISDIGIT( *ptr ) ) ptr++;
day = INT2FIX(strtol(ptr, NULL, 10));
+ if ( !cDate ) {
+ /*
+ * Load Date module
+ */
+ rb_require( "date" );
+ cDate = rb_const_get( rb_cObject, rb_intern("Date") );
+ }
+
obj = rb_funcall( cDate, s_new, 3, year, mon, day );
}
else if ( strncmp( type_id, "timestamp", 9 ) == 0 )
{
- obj = rb_syck_mktime( n->data.str->ptr );
+ obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
+ }
+ else if ( strncmp( type_id, "merge", 5 ) == 0 )
+ {
+ obj = rb_funcall( cMergeKey, s_new, 0 );
+ }
+ else if ( strncmp( type_id, "default", 7 ) == 0 )
+ {
+ obj = rb_funcall( cDefaultKey, s_new, 0 );
+ }
+ else if ( n->data.str->style == scalar_plain &&
+ n->data.str->len > 1 &&
+ strncmp( n->data.str->ptr, ":", 1 ) == 0 )
+ {
+ obj = rb_funcall( oDefaultResolver, s_transfer, 2,
+ rb_str_new2( "tag:ruby.yaml.org,2002:sym" ),
+ rb_str_new( n->data.str->ptr + 1, n->data.str->len - 1 ) );
+ }
+ else if ( strcmp( type_id, "str" ) == 0 )
+ {
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
}
- else if ( strncmp( type_id, "merge", 5 ) == 0 )
- {
- obj = rb_funcall( cMergeKey, s_new, 0 );
- }
- else if ( strncmp( type_id, "default", 7 ) == 0 )
- {
- obj = rb_funcall( cDefaultKey, s_new, 0 );
- }
else
{
transferred = 0;
@@ -534,46 +549,48 @@ yaml_org_handler( n, ref )
obj = rb_hash_new();
for ( i = 0; i < n->data.pairs->idx; i++ )
{
- VALUE k = syck_map_read( n, map_key, i );
- VALUE v = syck_map_read( n, map_value, i );
- int skip_aset = 0;
-
- /*
- * Handle merge keys
- */
- if ( rb_obj_is_kind_of( k, cMergeKey ) )
- {
- if ( rb_obj_is_kind_of( v, rb_cHash ) )
- {
- VALUE dup = rb_funcall( v, s_dup, 0 );
- rb_funcall( dup, s_update, 1, obj );
- obj = dup;
- skip_aset = 1;
- }
- else if ( rb_obj_is_kind_of( v, rb_cArray ) )
- {
- VALUE end = rb_ary_pop( v );
- if ( rb_obj_is_kind_of( end, rb_cHash ) )
- {
- VALUE dup = rb_funcall( end, s_dup, 0 );
- v = rb_ary_reverse( v );
- rb_ary_push( v, obj );
- rb_iterate( rb_each, v, syck_merge_i, dup );
- obj = dup;
- skip_aset = 1;
- }
- }
- }
+ VALUE k = syck_map_read( n, map_key, i );
+ VALUE v = syck_map_read( n, map_value, i );
+ int skip_aset = 0;
+
+ /*
+ * Handle merge keys
+ */
+ if ( rb_obj_is_kind_of( k, cMergeKey ) )
+ {
+ VALUE tmp;
+ if ( !NIL_P(tmp = rb_check_convert_type(v, T_HASH, "Hash", "to_hash")) )
+ {
+ VALUE dup = rb_funcall( tmp, s_dup, 0 );
+ rb_funcall( dup, s_update, 1, obj );
+ obj = dup;
+ skip_aset = 1;
+ }
+ else if ( !NIL_P(tmp = rb_check_array_type(v)) )
+ {
+ VALUE end = rb_ary_pop( tmp );
+ VALUE tmph = rb_check_convert_type(end, T_HASH, "Hash", "to_hash");
+ if ( !NIL_P(tmph) )
+ {
+ VALUE dup = rb_funcall( tmph, s_dup, 0 );
+ tmp = rb_ary_reverse( tmp );
+ rb_ary_push( tmp, obj );
+ rb_iterate( rb_each, tmp, syck_merge_i, dup );
+ obj = dup;
+ skip_aset = 1;
+ }
+ }
+ }
else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
{
rb_funcall( obj, s_default_set, 1, v );
skip_aset = 1;
}
- if ( ! skip_aset )
- {
- rb_hash_aset( obj, k, v );
- }
+ if ( ! skip_aset )
+ {
+ rb_hash_aset( obj, k, v );
+ }
}
break;
}
@@ -582,6 +599,8 @@ yaml_org_handler( n, ref )
return transferred;
}
+static void syck_node_mark( SyckNode *n );
+
/*
* {native mode} node handler
* - Converts data into native Ruby types
@@ -592,30 +611,30 @@ rb_syck_load_handler(p, n)
SyckNode *n;
{
VALUE obj = Qnil;
- struct parser_xtra *bonus;
+ struct parser_xtra *bonus = (struct parser_xtra *)p->bonus;
+ VALUE resolver = bonus->resolver;
+ if ( NIL_P( resolver ) )
+ {
+ resolver = oDefaultResolver;
+ }
/*
- * Attempt common transfers
+ * Create node,
*/
- int transferred = yaml_org_handler(n, &obj);
- if ( transferred == 0 && n->type_id != NULL )
- {
- obj = rb_funcall( oDefaultLoader, s_transfer, 2, rb_str_new2( n->type_id ), obj );
- }
+ obj = rb_funcall( resolver, s_node_import, 1, Data_Wrap_Struct( cNode, NULL, NULL, n ) );
/*
* ID already set, let's alter the symbol table to accept the new object
*/
- if (n->id > 0)
+ if (n->id > 0 && !NIL_P(obj))
{
MEMCPY((void *)n->id, (void *)obj, RVALUE, 1);
MEMZERO((void *)obj, RVALUE, 1);
obj = n->id;
}
- bonus = (struct parser_xtra *)p->bonus;
if ( bonus->taint) OBJ_TAINT( obj );
- if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, obj);
+ if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, obj);
rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj);
return obj;
@@ -660,30 +679,43 @@ rb_syck_bad_anchor_handler(p, a)
* data loaded based on the model requested.
*/
void
-syck_set_model( parser, input, model )
- SyckParser *parser;
- VALUE input, model;
-{
- if ( model == sym_generic )
- {
- syck_parser_handler( parser, rb_syck_parse_handler );
- syck_parser_implicit_typing( parser, 1 );
- syck_parser_taguri_expansion( parser, 1 );
- }
- else
- {
- syck_parser_handler( parser, rb_syck_load_handler );
- syck_parser_implicit_typing( parser, 1 );
- syck_parser_taguri_expansion( parser, 0 );
- }
+syck_set_model( p, input, model )
+ VALUE p, input, model;
+{
+ SyckParser *parser;
+ Data_Get_Struct(p, SyckParser, parser);
+ syck_parser_handler( parser, rb_syck_load_handler );
+ /* WARN: gonna be obsoleted soon!! */
+ if ( model == sym_generic )
+ {
+ rb_funcall( p, s_set_resolver, 1, oGenericResolver );
+ }
+ syck_parser_implicit_typing( parser, 1 );
+ syck_parser_taguri_expansion( parser, 1 );
+
+ if ( NIL_P( input ) )
+ {
+ input = rb_ivar_get( p, s_input );
+ }
if ( input == sym_bytecode )
{
syck_parser_set_input_type( parser, syck_bytecode_utf8 );
}
+ else
+ {
+ syck_parser_set_input_type( parser, syck_yaml_utf8 );
+ }
syck_parser_error_handler( parser, rb_syck_err_handler );
syck_parser_bad_anchor_handler( parser, rb_syck_bad_anchor_handler );
}
+static int
+syck_st_mark_nodes( char *key, SyckNode *n, char *arg )
+{
+ if ( n != (void *)1 ) syck_node_mark( n );
+ return ST_CONTINUE;
+}
+
/*
* mark parser nodes
*/
@@ -691,45 +723,76 @@ static void
syck_mark_parser(parser)
SyckParser *parser;
{
- rb_gc_mark(parser->root);
- rb_gc_mark(parser->root_on_error);
+ struct parser_xtra *bonus = (struct parser_xtra *)parser->bonus;
+ rb_gc_mark_maybe(parser->root);
+ rb_gc_mark_maybe(parser->root_on_error);
+ rb_gc_mark( bonus->data );
+ rb_gc_mark( bonus->proc );
+ rb_gc_mark( bonus->resolver );
+
+ if ( parser->anchors != NULL )
+ {
+ st_foreach( parser->anchors, syck_st_mark_nodes, 0 );
+ }
+ if ( parser->bad_anchors != NULL )
+ {
+ st_foreach( parser->bad_anchors, syck_st_mark_nodes, 0 );
+ }
}
/*
- * YAML::Syck::Parser.new
+ * Free the parser and any bonus attachment.
*/
+void
+rb_syck_free_parser(p)
+ SyckParser *p;
+{
+ S_FREE( p->bonus );
+ syck_free_parser(p);
+}
+
+/*
+ * YAML::Syck::Parser.allocate
+ */
+VALUE syck_parser_s_alloc _((VALUE));
VALUE
-syck_parser_new(argc, argv, class)
- int argc;
- VALUE *argv;
- VALUE class;
+syck_parser_s_alloc(class)
+ VALUE class;
{
- VALUE pobj, options, init_argv[1];
+ VALUE pobj;
SyckParser *parser = syck_new_parser();
- rb_scan_args(argc, argv, "01", &options);
- pobj = Data_Wrap_Struct( class, syck_mark_parser, syck_free_parser, parser );
+ parser->bonus = S_ALLOC( struct parser_xtra );
+ S_MEMZERO( parser->bonus, struct parser_xtra, 1 );
+
+ pobj = Data_Wrap_Struct( class, syck_mark_parser, rb_syck_free_parser, parser );
syck_parser_set_root_on_error( parser, Qnil );
- if ( ! rb_obj_is_instance_of( options, rb_cHash ) )
- {
- options = rb_hash_new();
- }
- init_argv[0] = options;
- rb_obj_call_init(pobj, 1, init_argv);
- return pobj;
+ return pobj;
}
/*
- * YAML::Syck::Parser.initialize( options )
+ * YAML::Syck::Parser.initialize( resolver, options )
*/
static VALUE
-syck_parser_initialize( self, options )
- VALUE self, options;
+syck_parser_initialize(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- rb_iv_set(self, "@options", options);
- return self;
+ VALUE options;
+ if (rb_scan_args(argc, argv, "01", &options) == 0)
+ {
+ options = rb_hash_new();
+ }
+ else
+ {
+ Check_Type(options, T_HASH);
+ }
+ rb_ivar_set(self, s_options, options);
+ rb_ivar_set(self, s_input, Qnil);
+ return self;
}
/*
@@ -739,13 +802,14 @@ static VALUE
syck_parser_bufsize_set( self, size )
VALUE self, size;
{
- SyckParser *parser;
+ SyckParser *parser;
- Data_Get_Struct(self, SyckParser, parser);
if ( rb_respond_to( size, s_to_i ) ) {
- parser->bufsize = NUM2INT(rb_funcall(size, s_to_i, 0));
+ int n = NUM2INT(rb_funcall(size, s_to_i, 0));
+ Data_Get_Struct(self, SyckParser, parser);
+ parser->bufsize = n;
}
- return self;
+ return self;
}
/*
@@ -755,10 +819,10 @@ static VALUE
syck_parser_bufsize_get( self )
VALUE self;
{
- SyckParser *parser;
+ SyckParser *parser;
- Data_Get_Struct(self, SyckParser, parser);
- return INT2FIX( parser->bufsize );
+ Data_Get_Struct(self, SyckParser, parser);
+ return INT2FIX( parser->bufsize );
}
/*
@@ -768,26 +832,25 @@ VALUE
syck_parser_load(argc, argv, self)
int argc;
VALUE *argv;
- VALUE self;
+ VALUE self;
{
VALUE port, proc, model, input;
- SyckParser *parser;
- struct parser_xtra bonus;
- volatile VALUE hash; /* protect from GC */
+ SyckParser *parser;
+ struct parser_xtra *bonus;
rb_scan_args(argc, argv, "11", &port, &proc);
- Data_Get_Struct(self, SyckParser, parser);
- input = rb_hash_aref( rb_iv_get( self, "@options" ), sym_input );
- model = rb_hash_aref( rb_iv_get( self, "@options" ), sym_model );
- syck_set_model( parser, input, model );
+ input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
+ model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
+ Data_Get_Struct(self, SyckParser, parser);
+ syck_set_model( self, input, model );
- bonus.taint = syck_parser_assign_io(parser, port);
- bonus.data = hash = rb_hash_new();
- if ( NIL_P( proc ) ) bonus.proc = 0;
- else bonus.proc = proc;
-
- parser->bonus = (void *)&bonus;
+ bonus = (struct parser_xtra *)parser->bonus;
+ bonus->taint = syck_parser_assign_io(parser, &port);
+ bonus->data = rb_hash_new();
+ bonus->resolver = rb_attr_get( self, s_resolver );
+ if ( NIL_P( proc ) ) bonus->proc = 0;
+ else bonus->proc = proc;
return syck_parse( parser );
}
@@ -799,155 +862,379 @@ VALUE
syck_parser_load_documents(argc, argv, self)
int argc;
VALUE *argv;
- VALUE self;
+ VALUE self;
{
VALUE port, proc, v, input, model;
- SyckParser *parser;
- struct parser_xtra bonus;
- volatile VALUE hash;
+ SyckParser *parser;
+ struct parser_xtra *bonus;
rb_scan_args(argc, argv, "1&", &port, &proc);
- Data_Get_Struct(self, SyckParser, parser);
- input = rb_hash_aref( rb_iv_get( self, "@options" ), sym_input );
- model = rb_hash_aref( rb_iv_get( self, "@options" ), sym_model );
- syck_set_model( parser, input, model );
+ input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
+ model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
+ Data_Get_Struct(self, SyckParser, parser);
+ syck_set_model( self, input, model );
- bonus.taint = syck_parser_assign_io(parser, port);
+ bonus = (struct parser_xtra *)parser->bonus;
+ bonus->taint = syck_parser_assign_io(parser, &port);
+ bonus->resolver = rb_attr_get( self, s_resolver );
+ bonus->proc = 0;
+
while ( 1 )
- {
+ {
/* Reset hash for tracking nodes */
- bonus.data = hash = rb_hash_new();
- bonus.proc = 0;
- parser->bonus = (void *)&bonus;
+ bonus->data = rb_hash_new();
/* Parse a document */
- v = syck_parse( parser );
+ v = syck_parse( parser );
if ( parser->eof == 1 )
{
break;
}
/* Pass document to block */
- rb_funcall( proc, s_call, 1, v );
- }
+ rb_funcall( proc, s_call, 1, v );
+ }
return Qnil;
}
/*
- * YAML::Syck::Loader.initialize
+ * YAML::Syck::Parser#set_resolver
+ */
+VALUE
+syck_parser_set_resolver( self, resolver )
+ VALUE self, resolver;
+{
+ rb_ivar_set( self, s_resolver, resolver );
+ return self;
+}
+
+/*
+ * YAML::Syck::Resolver.initialize
*/
static VALUE
-syck_loader_initialize( self )
+syck_resolver_initialize( self )
VALUE self;
{
- VALUE families;
-
- rb_iv_set(self, "@families", rb_hash_new() );
- rb_iv_set(self, "@private_types", rb_hash_new() );
- rb_iv_set(self, "@anchors", rb_hash_new() );
- families = rb_iv_get(self, "@families");
-
- rb_hash_aset(families, rb_str_new2( YAML_DOMAIN ), rb_hash_new());
- rb_hash_aset(families, rb_str_new2( RUBY_DOMAIN ), rb_hash_new());
-
- return self;
+ rb_ivar_set(self, s_tags, rb_hash_new());
+ return self;
}
/*
- * Add type family, used by add_*_type methods.
+ * YAML::Syck::Resolver#add_type
*/
VALUE
-syck_loader_add_type_family( self, domain, type_re, proc )
- VALUE self, domain, type_re, proc;
+syck_resolver_add_type( self, taguri, cls )
+ VALUE self, taguri, cls;
{
- VALUE families, domain_types;
-
- families = rb_iv_get(self, "@families");
- domain_types = syck_get_hash_aref(families, domain);
- rb_hash_aset( domain_types, type_re, proc );
+ VALUE tags = rb_attr_get(self, s_tags);
+ rb_hash_aset( tags, taguri, cls );
return Qnil;
}
/*
- * YAML::Syck::Loader.add_domain_type
+ * YAML::Syck::Resolver#use_types_at
*/
VALUE
-syck_loader_add_domain_type( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
+syck_resolver_use_types_at( self, hsh )
+ VALUE self, hsh;
{
- VALUE domain, type_re, proc;
-
- rb_scan_args(argc, argv, "2&", &domain, &type_re, &proc);
- syck_loader_add_type_family( self, domain, type_re, proc );
+ rb_ivar_set( self, s_tags, hsh );
return Qnil;
}
+/*
+ * YAML::Syck::Resolver#detect_implicit
+ */
+VALUE
+syck_resolver_detect_implicit( self, val )
+ VALUE self, val;
+{
+ return rb_str_new2( "" );
+}
/*
- * YAML::Syck::Loader.add_builtin_type
+ * YAML::Syck::Resolver#node_import
*/
VALUE
-syck_loader_add_builtin_type( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
+syck_resolver_node_import( self, node )
+ VALUE self, node;
{
- VALUE type_re, proc;
+ SyckNode *n;
+ VALUE obj;
+ int i = 0;
+ Data_Get_Struct(node, SyckNode, n);
+
+ switch (n->kind)
+ {
+ case syck_str_kind:
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
+ break;
+
+ case syck_seq_kind:
+ obj = rb_ary_new2( n->data.list->idx );
+ for ( i = 0; i < n->data.list->idx; i++ )
+ {
+ rb_ary_store( obj, i, syck_seq_read( n, i ) );
+ }
+ break;
+
+ case syck_map_kind:
+ obj = rb_hash_new();
+ for ( i = 0; i < n->data.pairs->idx; i++ )
+ {
+ VALUE k = syck_map_read( n, map_key, i );
+ VALUE v = syck_map_read( n, map_value, i );
+ int skip_aset = 0;
+
+ /*
+ * Handle merge keys
+ */
+ if ( rb_obj_is_kind_of( k, cMergeKey ) )
+ {
+ if ( rb_obj_is_kind_of( v, rb_cHash ) )
+ {
+ VALUE dup = rb_funcall( v, s_dup, 0 );
+ rb_funcall( dup, s_update, 1, obj );
+ obj = dup;
+ skip_aset = 1;
+ }
+ else if ( rb_obj_is_kind_of( v, rb_cArray ) )
+ {
+ VALUE end = rb_ary_pop( v );
+ if ( rb_obj_is_kind_of( end, rb_cHash ) )
+ {
+ VALUE dup = rb_funcall( end, s_dup, 0 );
+ v = rb_ary_reverse( v );
+ rb_ary_push( v, obj );
+ rb_iterate( rb_each, v, syck_merge_i, dup );
+ obj = dup;
+ skip_aset = 1;
+ }
+ }
+ }
+ else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
+ {
+ rb_funcall( obj, s_default_set, 1, v );
+ skip_aset = 1;
+ }
+
+ if ( ! skip_aset )
+ {
+ rb_hash_aset( obj, k, v );
+ }
+ }
+ break;
+ }
+
+ if ( n->type_id != NULL )
+ {
+ obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
+ }
+ return obj;
+}
- rb_scan_args(argc, argv, "1&", &type_re, &proc);
- syck_loader_add_type_family( self, rb_str_new2( YAML_DOMAIN ), type_re, proc );
+/*
+ * Set instance variables
+ */
+VALUE
+syck_set_ivars( vars, obj )
+ VALUE vars, obj;
+{
+ VALUE ivname = rb_ary_entry( vars, 0 );
+ char *ivn;
+ StringValue( ivname );
+ ivn = S_ALLOCA_N( char, RSTRING(ivname)->len + 2 );
+ ivn[0] = '@';
+ ivn[1] = '\0';
+ strncat( ivn, RSTRING(ivname)->ptr, RSTRING(ivname)->len );
+ rb_iv_set( obj, ivn, rb_ary_entry( vars, 1 ) );
return Qnil;
}
/*
- * YAML::Syck::Loader.add_ruby_type
+ * YAML::Syck::Resolver#const_find
*/
VALUE
-syck_loader_add_ruby_type( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
+syck_const_find( const_name )
+ VALUE const_name;
{
- VALUE type_re, proc;
+ VALUE tclass = rb_cObject;
+ VALUE tparts = rb_str_split( const_name, "::" );
+ int i = 0;
+ for ( i = 0; i < RARRAY(tparts)->len; i++ ) {
+ VALUE tpart = rb_to_id( rb_ary_entry( tparts, i ) );
+ if ( !rb_const_defined( tclass, tpart ) ) return Qnil;
+ tclass = rb_const_get( tclass, tpart );
+ }
+ return tclass;
+}
- rb_scan_args(argc, argv, "1&", &type_re, &proc);
- syck_loader_add_type_family( self, rb_str_new2( RUBY_DOMAIN ), type_re, proc );
- return Qnil;
+/*
+ * YAML::Syck::Resolver#transfer
+ */
+VALUE
+syck_resolver_transfer( self, type, val )
+ VALUE self, type, val;
+{
+ if (NIL_P(type) || RSTRING(StringValue(type))->len == 0)
+ {
+ type = rb_funcall( self, s_detect_implicit, 1, val );
+ }
+
+ if ( ! (NIL_P(type) || RSTRING(StringValue(type))->len == 0) )
+ {
+ VALUE str_xprivate = rb_str_new2( "x-private" );
+ VALUE colon = rb_str_new2( ":" );
+ VALUE tags = rb_attr_get(self, s_tags);
+ VALUE target_class = rb_hash_aref( tags, type );
+ VALUE subclass = target_class;
+ VALUE obj = Qnil;
+
+ /*
+ * Should no tag match exactly, check for subclass format
+ */
+ if ( NIL_P( target_class ) )
+ {
+ VALUE subclass_parts = rb_ary_new();
+ VALUE parts = rb_str_split( type, ":" );
+
+ while ( RARRAY(parts)->len > 1 )
+ {
+ VALUE partial;
+ rb_ary_unshift( subclass_parts, rb_ary_pop( parts ) );
+ partial = rb_ary_join( parts, colon );
+ target_class = rb_hash_aref( tags, partial );
+ if ( NIL_P( target_class ) )
+ {
+ rb_str_append( partial, colon );
+ target_class = rb_hash_aref( tags, partial );
+ }
+
+ /*
+ * Possible subclass found, see if it supports subclassing
+ */
+ if ( ! NIL_P( target_class ) )
+ {
+ subclass = target_class;
+ if ( RARRAY(subclass_parts)->len > 0 && rb_respond_to( target_class, s_tag_subclasses ) &&
+ RTEST( rb_funcall( target_class, s_tag_subclasses, 0 ) ) )
+ {
+ VALUE subclass_v;
+ subclass = rb_ary_join( subclass_parts, colon );
+ subclass = rb_funcall( target_class, s_tag_read_class, 1, subclass );
+ subclass_v = syck_const_find( subclass );
+
+ if ( subclass_v != Qnil )
+ {
+ subclass = subclass_v;
+ }
+ else if ( rb_cObject == target_class && subclass_v == Qnil )
+ {
+ target_class = cYObject;
+ type = subclass;
+ subclass = cYObject;
+ }
+ else /* workaround for SEGV. real fix please */
+ {
+ rb_raise( rb_eTypeError, "invalid subclass" );
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ /* rb_raise(rb_eTypeError, "invalid typing scheme: %s given",
+ * scheme);
+ */
+
+ if ( rb_respond_to( target_class, s_call ) )
+ {
+ obj = rb_funcall( target_class, s_call, 2, type, val );
+ }
+ else
+ {
+ if ( rb_respond_to( target_class, s_yaml_new ) )
+ {
+ obj = rb_funcall( target_class, s_yaml_new, 3, subclass, type, val );
+ }
+ else if ( !NIL_P( target_class ) )
+ {
+ if ( subclass == rb_cBignum )
+ {
+ obj = rb_str2inum( val, 10 ); /* for yaml dumped by 1.8.3 [ruby-core:6159] */
+ }
+ else
+ {
+ obj = rb_obj_alloc( subclass );
+ }
+
+ if ( rb_respond_to( obj, s_yaml_initialize ) )
+ {
+ rb_funcall( obj, s_yaml_initialize, 2, type, val );
+ }
+ else if ( !NIL_P( obj ) && rb_obj_is_instance_of( val, rb_cHash ) )
+ {
+ rb_iterate( rb_each, val, syck_set_ivars, obj );
+ }
+ }
+ else
+ {
+ VALUE parts = rb_str_split( type, ":" );
+ VALUE scheme = rb_ary_shift( parts );
+ if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
+ {
+ VALUE name = rb_ary_join( parts, colon );
+ obj = rb_funcall( cPrivateType, s_new, 2, name, val );
+ }
+ else
+ {
+ VALUE domain = rb_ary_shift( parts );
+ VALUE name = rb_ary_join( parts, colon );
+ obj = rb_funcall( cDomainType, s_new, 3, domain, name, val );
+ }
+ }
+ }
+ val = obj;
+ }
+
+ return val;
}
/*
- * YAML::Syck::Loader.add_private_type
+ * YAML::Syck::Resolver#tagurize
*/
VALUE
-syck_loader_add_private_type( argc, argv, self )
- int argc;
- VALUE *argv;
- VALUE self;
+syck_resolver_tagurize( self, val )
+ VALUE self, val;
{
- VALUE type_re, proc, priv_types;
+ VALUE tmp = rb_check_string_type(val);
- rb_scan_args(argc, argv, "1&", &type_re, &proc);
+ if ( !NIL_P(tmp) )
+ {
+ char *taguri = syck_type_id_to_uri( RSTRING(tmp)->ptr );
+ val = rb_str_new2( taguri );
+ S_FREE( taguri );
+ }
- priv_types = rb_iv_get(self, "@private_types");
- rb_hash_aset( priv_types, type_re, proc );
- return Qnil;
+ return val;
}
/*
- * YAML::Syck::Loader#detect
+ * YAML::Syck::DefaultResolver#detect_implicit
*/
VALUE
-syck_loader_detect_implicit( self, val )
+syck_defaultresolver_detect_implicit( self, val )
VALUE self, val;
{
char *type_id;
+ VALUE tmp = rb_check_string_type(val);
- if ( TYPE(val) == T_STRING )
+ if ( !NIL_P(tmp) )
{
+ val = tmp;
type_id = syck_match_implicit( RSTRING(val)->ptr, RSTRING(val)->len );
return rb_str_new2( type_id );
}
@@ -956,129 +1243,98 @@ syck_loader_detect_implicit( self, val )
}
/*
- * iterator to search a type hash for a match.
+ * YAML::Syck::DefaultResolver#node_import
*/
-static VALUE
-transfer_find_i(entry, col)
- VALUE entry, col;
-{
- VALUE key = rb_ary_entry( entry, 0 );
- VALUE tid = rb_ary_entry( col, 0 );
- if ( rb_respond_to( key, s_match ) )
- {
- VALUE match = rb_funcall( key, rb_intern("match"), 1, tid );
- if ( ! NIL_P( match ) )
- {
- rb_ary_push( col, rb_ary_entry( entry, 1 ) );
- rb_iter_break();
- }
- }
- return Qnil;
+VALUE
+syck_defaultresolver_node_import( self, node )
+ VALUE self, node;
+{
+ SyckNode *n;
+ VALUE obj;
+ Data_Get_Struct( node, SyckNode, n );
+ if ( !yaml_org_handler( n, &obj ) )
+ {
+ obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
+ }
+ return obj;
}
/*
- * YAML::Syck::Loader#transfer
+ * YAML::Syck::GenericResolver#node_import
*/
VALUE
-syck_loader_transfer( self, type, val )
- VALUE self, type, val;
+syck_genericresolver_node_import( self, node )
+ VALUE self, node;
{
- char *taguri = NULL;
+ SyckNode *n;
+ int i = 0;
+ VALUE t = Qnil, obj = Qnil, v = Qnil, style = Qnil;
+ Data_Get_Struct(node, SyckNode, n);
- if (NIL_P(type) || !RSTRING(type)->ptr || RSTRING(type)->len == 0)
- {
- /*
- * Empty transfer, detect type
- */
- if ( TYPE(val) == T_STRING )
- {
- StringValue(val);
- taguri = syck_match_implicit( RSTRING(val)->ptr, RSTRING(val)->len );
- taguri = syck_taguri( YAML_DOMAIN, taguri, strlen( taguri ) );
- }
- }
- else
+ if ( n->type_id != NULL )
{
- taguri = syck_type_id_to_uri( RSTRING(type)->ptr );
+ t = rb_str_new2(n->type_id);
}
- if ( taguri != NULL )
+ switch (n->kind)
{
- int transferred = 0;
- VALUE scheme, name, type_hash, domain = Qnil, type_proc = Qnil;
- VALUE type_uri = rb_str_new2( taguri );
- VALUE str_taguri = rb_str_new2("tag");
- VALUE str_xprivate = rb_str_new2("x-private");
- VALUE str_yaml_domain = rb_str_new2(YAML_DOMAIN);
- VALUE parts = rb_str_split( type_uri, ":" );
-
- scheme = rb_ary_shift( parts );
-
- if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
- {
- name = rb_ary_join( parts, rb_str_new2( ":" ) );
- type_hash = rb_iv_get(self, "@private_types");
- }
- else if ( rb_str_cmp( scheme, str_taguri ) == 0 )
+ case syck_str_kind:
{
- domain = rb_ary_shift( parts );
- name = rb_ary_join( parts, rb_str_new2( ":" ) );
- type_hash = rb_iv_get(self, "@families");
- type_hash = rb_hash_aref(type_hash, domain);
-
- /*
- * Route yaml.org types through the transfer
- * method here in this extension
- */
- if ( rb_str_cmp( domain, str_yaml_domain ) == 0 )
+ v = rb_str_new( n->data.str->ptr, n->data.str->len );
+ if ( n->data.str->style == scalar_1quote )
{
- SyckNode *n = rb_new_syck_node(val, name);
- if ( n != NULL )
- {
- transferred = yaml_org_handler(n, &val);
- S_FREE( n );
- }
+ style = sym_1quote;
+ }
+ else if ( n->data.str->style == scalar_2quote )
+ {
+ style = sym_2quote;
+ }
+ else if ( n->data.str->style == scalar_fold )
+ {
+ style = sym_fold;
+ }
+ else if ( n->data.str->style == scalar_literal )
+ {
+ style = sym_literal;
+ }
+ else if ( n->data.str->style == scalar_plain )
+ {
+ style = sym_plain;
}
-
- }
- else
- {
- rb_raise(rb_eTypeError, "invalid typing scheme: %s given",
- scheme);
+ obj = rb_funcall( cScalar, s_new, 3, t, v, style );
}
+ break;
- if ( ! transferred )
- {
- if ( rb_obj_is_instance_of( type_hash, rb_cHash ) )
+ case syck_seq_kind:
+ v = rb_ary_new2( syck_seq_count( n ) );
+ for ( i = 0; i < syck_seq_count( n ); i++ )
{
- type_proc = rb_hash_aref( type_hash, name );
- if ( NIL_P( type_proc ) )
- {
- VALUE col = rb_ary_new();
- rb_ary_push( col, name );
- rb_iterate(rb_each, type_hash, transfer_find_i, col );
- name = rb_ary_shift( col );
- type_proc = rb_ary_shift( col );
- }
+ rb_ary_store( v, i, syck_seq_read( n, i ) );
}
-
- if ( rb_respond_to( type_proc, s_call ) )
+ if ( n->data.list->style == seq_inline )
{
- val = rb_funcall(type_proc, s_call, 2, type_uri, val);
- }
- else if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
+ style = sym_inline;
+ }
+ obj = rb_funcall( cSeq, s_new, 3, t, v, style );
+ rb_iv_set(obj, "@kind", sym_seq);
+ break;
+
+ case syck_map_kind:
+ v = rb_hash_new();
+ for ( i = 0; i < syck_map_count( n ); i++ )
{
- val = rb_funcall(cPrivateType, s_new, 2, name, val);
+ rb_hash_aset( v, syck_map_read( n, map_key, i ), syck_map_read( n, map_value, i ) );
}
- else
+ if ( n->data.pairs->style == map_inline )
{
- val = rb_funcall(cDomainType, s_new, 3, domain, name, val);
- }
- transferred = 1;
- }
+ style = sym_inline;
+ }
+ obj = rb_funcall( cMap, s_new, 3, t, v, style );
+ rb_iv_set(obj, "@kind", sym_map);
+ break;
}
- return val;
+ return obj;
}
/*
@@ -1093,11 +1349,24 @@ syck_badalias_initialize( self, val )
}
/*
- * YAML::Syck::DomainType.initialize
+ * YAML::Syck::BadAlias.<=>
+ */
+VALUE
+syck_badalias_cmp( alias1, alias2 )
+ VALUE alias1, alias2;
+{
+ VALUE str1 = rb_ivar_get( alias1, s_name );
+ VALUE str2 = rb_ivar_get( alias2, s_name );
+ VALUE val = rb_funcall( str1, s_cmp, 1, str2 );
+ return val;
+}
+
+/*
+ * YAML::DomainType.initialize
*/
VALUE
syck_domaintype_initialize( self, domain, type_id, val )
- VALUE self, type_id, val;
+ VALUE self, domain, type_id, val;
{
rb_iv_set( self, "@domain", domain );
rb_iv_set( self, "@type_id", type_id );
@@ -1106,7 +1375,19 @@ syck_domaintype_initialize( self, domain, type_id, val )
}
/*
- * YAML::Syck::PrivateType.initialize
+ * YAML::Object.initialize
+ */
+VALUE
+syck_yobject_initialize( self, klass, ivars )
+ VALUE self, klass, ivars;
+{
+ rb_iv_set( self, "@class", klass );
+ rb_iv_set( self, "@ivars", ivars );
+ return self;
+}
+
+/*
+ * YAML::PrivateType.initialize
*/
VALUE
syck_privatetype_initialize( self, type_id, val )
@@ -1118,35 +1399,390 @@ syck_privatetype_initialize( self, type_id, val )
}
/*
- * YAML::Syck::Node.initialize
+ * Mark node contents.
+ */
+static void
+syck_node_mark( n )
+ SyckNode *n;
+{
+ int i;
+ rb_gc_mark_maybe( n->id );
+ switch ( n->kind )
+ {
+ case syck_seq_kind:
+ for ( i = 0; i < n->data.list->idx; i++ )
+ {
+ rb_gc_mark( syck_seq_read( n, i ) );
+ }
+ break;
+
+ case syck_map_kind:
+ for ( i = 0; i < n->data.pairs->idx; i++ )
+ {
+ rb_gc_mark( syck_map_read( n, map_key, i ) );
+ rb_gc_mark( syck_map_read( n, map_value, i ) );
+ }
+ break;
+ }
+#if 0 /* maybe needed */
+ if ( n->shortcut ) syck_node_mark( n->shortcut ); /* caution: maybe cyclic */
+#endif
+}
+
+/*
+ * YAML::Syck::Scalar.allocate
*/
VALUE
-syck_node_initialize( self, type_id, val )
- VALUE self, type_id, val;
+syck_scalar_alloc( class )
+ VALUE class;
{
- rb_iv_set( self, "@type_id", type_id );
+ SyckNode *node = syck_alloc_str();
+ VALUE obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
+ node->id = obj;
+ return obj;
+}
+
+/*
+ * YAML::Syck::Scalar.initialize
+ */
+VALUE
+syck_scalar_initialize( self, type_id, val, style )
+ VALUE self, type_id, val, style;
+{
+ rb_iv_set( self, "@kind", sym_scalar );
+ rb_funcall( self, s_type_id_set, 1, type_id );
+ rb_funcall( self, s_value_set, 1, val );
+ rb_funcall( self, s_style_set, 1, style );
+ return self;
+}
+
+/*
+ * YAML::Syck::Scalar.style=
+ */
+VALUE
+syck_scalar_style_set( self, style )
+ VALUE self, style;
+{
+ SyckNode *node;
+ Data_Get_Struct( self, SyckNode, node );
+
+ if ( NIL_P( style ) )
+ {
+ node->data.str->style = scalar_none;
+ }
+ else if ( style == sym_1quote )
+ {
+ node->data.str->style = scalar_1quote;
+ }
+ else if ( style == sym_2quote )
+ {
+ node->data.str->style = scalar_2quote;
+ }
+ else if ( style == sym_fold )
+ {
+ node->data.str->style = scalar_fold;
+ }
+ else if ( style == sym_literal )
+ {
+ node->data.str->style = scalar_literal;
+ }
+ else if ( style == sym_plain )
+ {
+ node->data.str->style = scalar_plain;
+ }
+
+ rb_iv_set( self, "@style", style );
+ return self;
+}
+
+/*
+ * YAML::Syck::Scalar.value=
+ */
+VALUE
+syck_scalar_value_set( self, val )
+ VALUE self, val;
+{
+ SyckNode *node;
+ Data_Get_Struct( self, SyckNode, node );
+
+ StringValue( val );
+ node->data.str->ptr = syck_strndup( RSTRING(val)->ptr, RSTRING(val)->len );
+ node->data.str->len = RSTRING(val)->len;
+ node->data.str->style = scalar_none;
+
rb_iv_set( self, "@value", val );
+ return val;
+}
+
+/*
+ * YAML::Syck::Seq.allocate
+ */
+VALUE
+syck_seq_alloc( class )
+ VALUE class;
+{
+ SyckNode *node;
+ VALUE obj;
+ node = syck_alloc_seq();
+ obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
+ node->id = obj;
+ return obj;
+}
+
+/*
+ * YAML::Syck::Seq.initialize
+ */
+VALUE
+syck_seq_initialize( self, type_id, val, style )
+ VALUE self, type_id, val, style;
+{
+ SyckNode *node;
+ Data_Get_Struct( self, SyckNode, node );
+
+ rb_iv_set( self, "@kind", sym_seq );
+ rb_funcall( self, s_type_id_set, 1, type_id );
+ rb_funcall( self, s_value_set, 1, val );
+ rb_funcall( self, s_style_set, 1, style );
return self;
}
+/*
+ * YAML::Syck::Seq.value=
+ */
VALUE
-syck_node_thash( entry, t )
- VALUE entry, t;
+syck_seq_value_set( self, val )
+ VALUE self, val;
{
- VALUE key, val;
- key = rb_ary_entry( entry, 0 );
- val = syck_node_transform( rb_ary_entry( rb_ary_entry( entry, 1 ), 1 ) );
- rb_hash_aset( t, key, val );
- return Qnil;
+ SyckNode *node;
+ Data_Get_Struct( self, SyckNode, node );
+
+ val = rb_check_array_type( val );
+ if ( !NIL_P( val ) ) {
+ int i;
+ syck_seq_empty( node );
+ for ( i = 0; i < RARRAY( val )->len; i++ )
+ {
+ syck_seq_add( node, rb_ary_entry(val, i) );
+ }
+ }
+
+ rb_iv_set( self, "@value", val );
+ return val;
}
+/*
+ * YAML::Syck::Seq.add
+ */
VALUE
-syck_node_ahash( entry, t )
- VALUE entry, t;
+syck_seq_add_m( self, val )
+ VALUE self, val;
{
- VALUE val = syck_node_transform( entry );
- rb_ary_push( t, val );
- return Qnil;
+ SyckNode *node;
+ VALUE emitter = rb_ivar_get( self, s_emitter );
+ Data_Get_Struct( self, SyckNode, node );
+
+ if ( rb_respond_to( emitter, s_node_export ) ) {
+ val = rb_funcall( emitter, s_node_export, 1, val );
+ }
+ syck_seq_add( node, val );
+ rb_ary_push( rb_ivar_get( self, s_value ), val );
+
+ return self;
+}
+
+/*
+ * YAML::Syck::Seq.style=
+ */
+VALUE
+syck_seq_style_set( self, style )
+ VALUE self, style;
+{
+ SyckNode *node;
+ Data_Get_Struct( self, SyckNode, node );
+
+ if ( style == sym_inline )
+ {
+ node->data.list->style = seq_inline;
+ }
+ else
+ {
+ node->data.list->style = seq_none;
+ }
+
+ rb_iv_set( self, "@style", style );
+ return self;
+}
+
+/*
+ * YAML::Syck::Map.allocate
+ */
+VALUE
+syck_map_alloc( class )
+ VALUE class;
+{
+ SyckNode *node;
+ VALUE obj;
+ node = syck_alloc_map();
+ obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
+ node->id = obj;
+ return obj;
+}
+
+/*
+ * YAML::Syck::Map.initialize
+ */
+VALUE
+syck_map_initialize( self, type_id, val, style )
+ VALUE self, type_id, val, style;
+{
+ SyckNode *node;
+ Data_Get_Struct( self, SyckNode, node );
+
+ if ( !NIL_P( val ) )
+ {
+ VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
+ VALUE keys;
+ int i;
+ if ( NIL_P(hsh) )
+ {
+ rb_raise( rb_eTypeError, "wrong argument type" );
+ }
+
+ keys = rb_funcall( hsh, s_keys, 0 );
+ for ( i = 0; i < RARRAY(keys)->len; i++ )
+ {
+ VALUE key = rb_ary_entry(keys, i);
+ syck_map_add( node, key, rb_hash_aref(hsh, key) );
+ }
+ }
+
+ rb_iv_set( self, "@kind", sym_seq );
+ rb_funcall( self, s_type_id_set, 1, type_id );
+ rb_funcall( self, s_value_set, 1, val );
+ rb_funcall( self, s_style_set, 1, style );
+ return self;
+}
+
+/*
+ * YAML::Syck::Map.value=
+ */
+VALUE
+syck_map_value_set( self, val )
+ VALUE self, val;
+{
+ SyckNode *node;
+ Data_Get_Struct( self, SyckNode, node );
+
+ if ( !NIL_P( val ) )
+ {
+ VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
+ VALUE keys;
+ int i;
+ if ( NIL_P(hsh) )
+ {
+ rb_raise( rb_eTypeError, "wrong argument type" );
+ }
+
+ syck_map_empty( node );
+ keys = rb_funcall( hsh, s_keys, 0 );
+ for ( i = 0; i < RARRAY(keys)->len; i++ )
+ {
+ VALUE key = rb_ary_entry(keys, i);
+ syck_map_add( node, key, rb_hash_aref(hsh, key) );
+ }
+ }
+
+ rb_iv_set( self, "@value", val );
+ return val;
+}
+
+/*
+ * YAML::Syck::Map.add
+ */
+VALUE
+syck_map_add_m( self, key, val )
+ VALUE self, key, val;
+{
+ SyckNode *node;
+ VALUE emitter = rb_ivar_get( self, s_emitter );
+ Data_Get_Struct( self, SyckNode, node );
+
+ if ( rb_respond_to( emitter, s_node_export ) ) {
+ key = rb_funcall( emitter, s_node_export, 1, key );
+ val = rb_funcall( emitter, s_node_export, 1, val );
+ }
+ syck_map_add( node, key, val );
+ rb_hash_aset( rb_ivar_get( self, s_value ), key, val );
+
+ return self;
+}
+
+/*
+ * YAML::Syck::Map.style=
+ */
+VALUE
+syck_map_style_set( self, style )
+ VALUE self, style;
+{
+ SyckNode *node;
+ Data_Get_Struct( self, SyckNode, node );
+
+ if ( style == sym_inline )
+ {
+ node->data.pairs->style = map_inline;
+ }
+ else
+ {
+ node->data.pairs->style = map_none;
+ }
+
+ rb_iv_set( self, "@style", style );
+ return self;
+}
+
+/*
+ * Cloning method for all node types
+ */
+VALUE
+syck_node_init_copy( copy, orig )
+ VALUE copy, orig;
+{
+ SyckNode *copy_n;
+ SyckNode *orig_n;
+
+ if ( copy == orig )
+ return copy;
+
+ if ( TYPE( orig ) != T_DATA )
+ {
+ rb_raise( rb_eTypeError, "wrong argument type" );
+ }
+
+ Data_Get_Struct( orig, SyckNode, orig_n );
+ Data_Get_Struct( copy, SyckNode, copy_n );
+ MEMCPY( copy_n, orig_n, SyckNode, 1 );
+ return copy;
+}
+
+/*
+ * YAML::Syck::Node#type_id=
+ */
+VALUE
+syck_node_type_id_set( self, type_id )
+ VALUE self, type_id;
+{
+ SyckNode *node;
+ Data_Get_Struct( self, SyckNode, node );
+
+ S_FREE( node->type_id );
+
+ if ( !NIL_P( type_id ) ) {
+ StringValue( type_id );
+ node->type_id = syck_strndup( RSTRING(type_id)->ptr, RSTRING(type_id)->len );
+ }
+
+ rb_iv_set( self, "@type_id", type_id );
+ return type_id;
}
/*
@@ -1156,24 +1792,100 @@ VALUE
syck_node_transform( self )
VALUE self;
{
- VALUE t = Qnil;
- VALUE type_id = rb_iv_get( self, "@type_id" );
- VALUE val = rb_iv_get( self, "@value" );
- if ( rb_obj_is_instance_of( val, rb_cHash ) )
+ VALUE t;
+ SyckNode *n;
+ SyckNode *orig_n;
+ Data_Get_Struct(self, SyckNode, orig_n);
+ t = Data_Wrap_Struct( cNode, syck_node_mark, syck_free_node, 0 );
+
+ switch (orig_n->kind)
+ {
+ case syck_map_kind:
+ {
+ int i;
+ DATA_PTR(t) = n = syck_alloc_map();
+ for ( i = 0; i < orig_n->data.pairs->idx; i++ )
+ {
+ syck_map_add( n, rb_funcall( syck_map_read( orig_n, map_key, i ), s_transform, 0 ),
+ rb_funcall( syck_map_read( orig_n, map_value, i ), s_transform, 0 ) );
+ }
+ }
+ break;
+
+ case syck_seq_kind:
+ {
+ int i;
+ DATA_PTR(t) = n = syck_alloc_seq();
+ for ( i = 0; i < orig_n->data.list->idx; i++ )
+ {
+ syck_seq_add( n, rb_funcall( syck_seq_read( orig_n, i ), s_transform, 0 ) );
+ }
+ }
+ break;
+
+ case syck_str_kind:
+ DATA_PTR(t) = n = syck_new_str2( orig_n->data.str->ptr, orig_n->data.str->len, orig_n->data.str->style );
+ break;
+ }
+
+ if ( orig_n->type_id != NULL )
{
- t = rb_hash_new();
- rb_iterate( rb_each, val, syck_node_thash, t );
+ n->type_id = syck_strndup( orig_n->type_id, strlen( orig_n->type_id ) );
}
- else if ( rb_obj_is_instance_of( val, rb_cArray ) )
+ if ( orig_n->anchor != NULL )
{
- t = rb_ary_new();
- rb_iterate( rb_each, val, syck_node_ahash, t );
+ n->anchor = syck_strndup( orig_n->anchor, strlen( orig_n->anchor ) );
}
- else
+ n->id = t;
+ return rb_funcall( oDefaultResolver, s_node_import, 1, t );
+}
+
+/*
+ * Emitter callback: assembles YAML document events from
+ * Ruby symbols. This is a brilliant way to do it.
+ * No one could possibly object.
+ */
+void
+rb_syck_emitter_handler(e, data)
+ SyckEmitter *e;
+ st_data_t data;
+{
+ SyckNode *n;
+ Data_Get_Struct((VALUE)data, SyckNode, n);
+
+ switch (n->kind)
{
- t = val;
+ case syck_map_kind:
+ {
+ int i;
+ syck_emit_map( e, n->type_id, n->data.pairs->style );
+ for ( i = 0; i < n->data.pairs->idx; i++ )
+ {
+ syck_emit_item( e, syck_map_read( n, map_key, i ) );
+ syck_emit_item( e, syck_map_read( n, map_value, i ) );
+ }
+ syck_emit_end( e );
+ }
+ break;
+
+ case syck_seq_kind:
+ {
+ int i;
+ syck_emit_seq( e, n->type_id, n->data.list->style );
+ for ( i = 0; i < n->data.list->idx; i++ )
+ {
+ syck_emit_item( e, syck_seq_read( n, i ) );
+ }
+ syck_emit_end( e );
+ }
+ break;
+
+ case syck_str_kind:
+ {
+ syck_emit_scalar( e, n->type_id, n->data.str->style, 0, 0, 0, n->data.str->ptr, n->data.str->len );
+ }
+ break;
}
- return rb_funcall( oDefaultLoader, s_transfer, 2, type_id, t );
}
/*
@@ -1185,8 +1897,9 @@ rb_syck_output_handler( emitter, str, len )
char *str;
long len;
{
- VALUE dest = (VALUE)emitter->bonus;
- if ( rb_respond_to( dest, s_to_str ) ) {
+ struct emitter_xtra *bonus = (struct emitter_xtra *)emitter->bonus;
+ VALUE dest = bonus->port;
+ if (TYPE(dest) == T_STRING) {
rb_str_cat( dest, str, len );
} else {
rb_io_write( dest, rb_str_new( str, len ) );
@@ -1194,151 +1907,246 @@ rb_syck_output_handler( emitter, str, len )
}
/*
+ * Helper function for marking nodes in the anchor
+ * symbol table.
+ */
+void
+syck_out_mark( emitter, node )
+ VALUE emitter, node;
+{
+ SyckEmitter *emitterPtr;
+ struct emitter_xtra *bonus;
+ Data_Get_Struct(emitter, SyckEmitter, emitterPtr);
+ bonus = (struct emitter_xtra *)emitterPtr->bonus;
+ rb_ivar_set( node, s_emitter, emitter );
+ /* syck_emitter_mark_node( emitterPtr, (st_data_t)node ); */
+ if ( !NIL_P( bonus->oid ) ) {
+ rb_hash_aset( bonus->data, bonus->oid, node );
+ }
+}
+
+/*
* Mark emitter values.
*/
static void
syck_mark_emitter(emitter)
SyckEmitter *emitter;
{
- rb_gc_mark(emitter->ignore_id);
- if ( emitter->bonus != NULL )
- {
- rb_gc_mark( (VALUE)emitter->bonus );
- }
+ struct emitter_xtra *bonus = (struct emitter_xtra *)emitter->bonus;
+ rb_gc_mark( bonus->oid );
+ rb_gc_mark( bonus->data );
+ rb_gc_mark( bonus->port );
}
/*
- * YAML::Syck::Emitter.new
+ * Free the emitter and any bonus attachment.
*/
+void
+rb_syck_free_emitter(e)
+ SyckEmitter *e;
+{
+ S_FREE( e->bonus );
+ syck_free_emitter(e);
+}
+
+/*
+ * YAML::Syck::Emitter.allocate
+ */
+VALUE syck_emitter_s_alloc _((VALUE));
VALUE
-syck_emitter_new(argc, argv, class)
- int argc;
- VALUE *argv;
- VALUE class;
+syck_emitter_s_alloc(class)
+ VALUE class;
{
- VALUE pobj, options, init_argv[1];
+ VALUE pobj;
SyckEmitter *emitter = syck_new_emitter();
- syck_emitter_ignore_id( emitter, Qnil );
- syck_emitter_handler( emitter, rb_syck_output_handler );
- emitter->bonus = (void *)rb_str_new2( "" );
+ emitter->bonus = S_ALLOC( struct emitter_xtra );
+ S_MEMZERO( emitter->bonus, struct emitter_xtra, 1 );
- rb_scan_args(argc, argv, "01", &options);
- pobj = Data_Wrap_Struct( class, syck_mark_emitter, syck_free_emitter, emitter );
+ pobj = Data_Wrap_Struct( class, syck_mark_emitter, rb_syck_free_emitter, emitter );
+ syck_emitter_handler( emitter, rb_syck_emitter_handler );
+ syck_output_handler( emitter, rb_syck_output_handler );
- if ( ! rb_obj_is_instance_of( options, rb_cHash ) )
- {
- options = rb_hash_new();
- }
- init_argv[0] = options;
- rb_obj_call_init(pobj, 1, init_argv);
- return pobj;
+ rb_ivar_set( pobj, s_out, rb_funcall( cOut, s_new, 1, pobj ) );
+ return pobj;
}
/*
- * YAML::Syck::Emitter.initialize( options )
+ * YAML::Syck::Emitter.reset( options )
*/
-static VALUE
-syck_emitter_initialize( self, options )
- VALUE self, options;
+VALUE
+syck_emitter_reset( argc, argv, self )
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- rb_iv_set(self, "@options", options);
- return self;
+ VALUE options, tmp;
+ SyckEmitter *emitter;
+ struct emitter_xtra *bonus;
+
+ Data_Get_Struct(self, SyckEmitter, emitter);
+ bonus = (struct emitter_xtra *)emitter->bonus;
+
+ bonus->oid = Qnil;
+ bonus->port = rb_str_new2( "" );
+ bonus->data = rb_hash_new();
+
+ if (rb_scan_args(argc, argv, "01", &options) == 0)
+ {
+ options = rb_hash_new();
+ rb_ivar_set(self, s_options, options);
+ }
+ else if ( !NIL_P(tmp = rb_check_string_type(options)) )
+ {
+ bonus->port = tmp;
+ }
+ else if ( rb_respond_to( options, s_write ) )
+ {
+ bonus->port = options;
+ }
+ else
+ {
+ Check_Type(options, T_HASH);
+ rb_ivar_set(self, s_options, options);
+ }
+
+ emitter->headless = 0;
+ rb_ivar_set(self, s_level, INT2FIX(0));
+ rb_ivar_set(self, s_resolver, Qnil);
+ return self;
}
/*
- * YAML::Syck::Emitter.level
+ * YAML::Syck::Emitter.emit( object_id ) { |out| ... }
*/
VALUE
-syck_emitter_level_m( self )
+syck_emitter_emit( argc, argv, self )
+ int argc;
+ VALUE *argv;
VALUE self;
{
+ VALUE oid, proc;
SyckEmitter *emitter;
+ struct emitter_xtra *bonus;
+ SYMID symple;
+ int level = FIX2INT(rb_ivar_get(self, s_level)) + 1;
+ rb_ivar_set(self, s_level, INT2FIX(level));
+
+ rb_scan_args(argc, argv, "1&", &oid, &proc);
+ Data_Get_Struct(self, SyckEmitter, emitter);
+ bonus = (struct emitter_xtra *)emitter->bonus;
+
+ /* Calculate anchors, normalize nodes, build a simpler symbol table */
+ bonus->oid = oid;
+ if ( !NIL_P( oid ) && RTEST( rb_funcall( bonus->data, s_haskey, 1, oid ) ) ) {
+ symple = rb_hash_aref( bonus->data, oid );
+ } else {
+ symple = rb_funcall( proc, s_call, 1, rb_ivar_get( self, s_out ) );
+ }
+ syck_emitter_mark_node( emitter, (st_data_t)symple );
+
+ /* Second pass, build emitted string */
+ level -= 1;
+ rb_ivar_set(self, s_level, INT2FIX(level));
+ if ( level == 0 )
+ {
+ syck_emit(emitter, (st_data_t)symple);
+ syck_emitter_flush(emitter, 0);
- Data_Get_Struct(self, SyckEmitter, emitter);
- return LONG2NUM( emitter->level );
+ return bonus->port;
+ }
+
+ return symple;
}
/*
- * YAML::Syck::Emitter.flush
+ * YAML::Syck::Emitter#node_export
*/
VALUE
-syck_emitter_flush_m( self )
- VALUE self;
+syck_emitter_node_export( self, node )
+ VALUE self, node;
{
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- syck_emitter_flush( emitter, 0 );
- return self;
+ return rb_funcall( node, s_to_yaml, 1, self );
}
/*
- * YAML::Syck::Emitter.write( str )
+ * YAML::Syck::Emitter#set_resolver
*/
VALUE
-syck_emitter_write_m( self, str )
- VALUE self, str;
+syck_emitter_set_resolver( self, resolver )
+ VALUE self, resolver;
{
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- syck_emitter_write( emitter, RSTRING(str)->ptr, RSTRING(str)->len );
+ rb_ivar_set( self, s_resolver, resolver );
return self;
}
/*
- * YAML::Syck::Emitter.simple( str )
+ * YAML::Syck::Out::initialize
*/
VALUE
-syck_emitter_simple_write( self, str )
- VALUE self, str;
+syck_out_initialize( self, emitter )
+ VALUE self, emitter;
{
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- syck_emitter_simple( emitter, RSTRING(str)->ptr, RSTRING(str)->len );
+ rb_ivar_set( self, s_emitter, emitter );
return self;
}
/*
- * YAML::Syck::Emitter.start_object( object_id )
+ * YAML::Syck::Out::map
*/
VALUE
-syck_emitter_start_object( self, oid )
- VALUE self, oid;
+syck_out_map( argc, argv, self )
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- char *anchor_name;
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- anchor_name = syck_emitter_start_obj( emitter, oid );
-
- if ( anchor_name == NULL )
- {
- return Qnil;
+ VALUE type_id, style, map;
+ if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
+ style = Qnil;
}
-
- return rb_str_new2( anchor_name );
+ map = rb_funcall( cMap, s_new, 3, type_id, rb_hash_new(), style );
+ syck_out_mark( rb_ivar_get( self, s_emitter ), map );
+ rb_yield( map );
+ return map;
}
/*
- * YAML::Syck::Emitter.end_object( object_id )
+ * YAML::Syck::Out::seq
*/
VALUE
-syck_emitter_end_object( self, oid )
- VALUE self, oid;
+syck_out_seq( argc, argv, self )
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- SyckEmitter *emitter;
-
- Data_Get_Struct(self, SyckEmitter, emitter);
- syck_emitter_end_obj( emitter );
+ VALUE type_id, style, seq;
+ if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
+ style = Qnil;
+ }
+ seq = rb_funcall( cSeq, s_new, 3, type_id, rb_ary_new(), style );
+ syck_out_mark( rb_ivar_get( self, s_emitter ), seq );
+ rb_yield( seq );
+ return seq;
+}
- if ( emitter->level < 0 )
- {
- syck_emitter_flush( emitter, 0 );
+/*
+ * YAML::Syck::Out::scalar
+syck_out_scalar( self, type_id, str, style )
+ VALUE self, type_id, str, style;
+ */
+VALUE
+syck_out_scalar( argc, argv, self )
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE type_id, str, style, scalar;
+ if (rb_scan_args(argc, argv, "21", &type_id, &str, &style) == 2) {
+ style = Qnil;
}
- return (VALUE)emitter->bonus;
+ scalar = rb_funcall( cScalar, s_new, 3, type_id, str, style );
+ syck_out_mark( rb_ivar_get( self, s_emitter ), scalar );
+ return scalar;
}
/*
@@ -1352,129 +2160,208 @@ Init_syck()
rb_define_const( rb_syck, "VERSION", rb_str_new2( SYCK_VERSION ) );
rb_define_module_function( rb_syck, "compile", rb_syck_compile, 1 );
- /*
- * Global symbols
- */
+ /*
+ * Global symbols
+ */
s_new = rb_intern("new");
s_utc = rb_intern("utc");
s_at = rb_intern("at");
s_to_f = rb_intern("to_f");
s_to_i = rb_intern("to_i");
s_read = rb_intern("read");
- s_anchors = rb_intern("anchors");
s_binmode = rb_intern("binmode");
s_transfer = rb_intern("transfer");
s_call = rb_intern("call");
- s_update = rb_intern("update");
- s_dup = rb_intern("dup");
+ s_cmp = rb_intern("<=>");
+ s_intern = rb_intern("intern");
+ s_update = rb_intern("update");
+ s_detect_implicit = rb_intern("detect_implicit");
+ s_dup = rb_intern("dup");
s_default_set = rb_intern("default=");
- s_match = rb_intern("match");
- s_keys = rb_intern("keys");
- s_to_str = rb_intern("to_str");
- s_tr_bang = rb_intern("tr!");
+ s_match = rb_intern("match");
+ s_push = rb_intern("push");
+ s_haskey = rb_intern("has_key?");
+ s_keys = rb_intern("keys");
+ s_node_import = rb_intern("node_import");
+ s_tr_bang = rb_intern("tr!");
s_unpack = rb_intern("unpack");
-
- sym_model = ID2SYM(rb_intern("Model"));
- sym_generic = ID2SYM(rb_intern("Generic"));
- sym_input = ID2SYM(rb_intern("Input"));
- sym_bytecode = ID2SYM(rb_intern("Bytecode"));
+ s_write = rb_intern("write");
+ s_tag_read_class = rb_intern( "yaml_tag_read_class" );
+ s_tag_subclasses = rb_intern( "yaml_tag_subclasses?" );
+ s_emitter = rb_intern( "emitter" );
+ s_set_resolver = rb_intern( "set_resolver" );
+ s_node_export = rb_intern( "node_export" );
+ s_to_yaml = rb_intern( "to_yaml" );
+ s_transform = rb_intern( "transform" );
+ s_yaml_new = rb_intern("yaml_new");
+ s_yaml_initialize = rb_intern("yaml_initialize");
+
+ s_tags = rb_intern("@tags");
+ s_name = rb_intern("@name");
+ s_options = rb_intern("@options");
+ s_kind = rb_intern("@kind");
+ s_type_id = rb_intern("@type_id");
+ s_type_id_set = rb_intern("type_id=");
+ s_resolver = rb_intern("@resolver");
+ s_level = rb_intern( "@level" );
+ s_style = rb_intern("@style");
+ s_style_set = rb_intern("style=");
+ s_value = rb_intern("@value");
+ s_value_set = rb_intern("value=");
+ s_out = rb_intern("@out");
+ s_input = rb_intern("@input");
+
+ sym_model = ID2SYM(rb_intern("Model"));
+ sym_generic = ID2SYM(rb_intern("Generic"));
+ sym_bytecode = ID2SYM(rb_intern("bytecode"));
sym_map = ID2SYM(rb_intern("map"));
sym_scalar = ID2SYM(rb_intern("scalar"));
sym_seq = ID2SYM(rb_intern("seq"));
+ sym_1quote = ID2SYM(rb_intern("quote1"));
+ sym_2quote = ID2SYM(rb_intern("quote2"));
+ sym_fold = ID2SYM(rb_intern("fold"));
+ sym_literal = ID2SYM(rb_intern("literal"));
+ sym_plain = ID2SYM(rb_intern("plain"));
+ sym_inline = ID2SYM(rb_intern("inline"));
/*
- * Load Date module
+ * Define YAML::Syck::Resolver class
*/
- rb_require( "date" );
- cDate = rb_funcall( rb_cObject, rb_intern("const_get"), 1, rb_str_new2("Date") );
-
- /*
- * Define YAML::Syck::Loader class
- */
- cLoader = rb_define_class_under( rb_syck, "Loader", rb_cObject );
- rb_define_attr( cLoader, "families", 1, 1 );
- rb_define_attr( cLoader, "private_types", 1, 1 );
- rb_define_attr( cLoader, "anchors", 1, 1 );
- rb_define_method( cLoader, "initialize", syck_loader_initialize, 0 );
- rb_define_method( cLoader, "add_domain_type", syck_loader_add_domain_type, -1 );
- rb_define_method( cLoader, "add_builtin_type", syck_loader_add_builtin_type, -1 );
- rb_define_method( cLoader, "add_ruby_type", syck_loader_add_ruby_type, -1 );
- rb_define_method( cLoader, "add_private_type", syck_loader_add_private_type, -1 );
- rb_define_method( cLoader, "bufsize=", syck_parser_bufsize_set, 1 );
- rb_define_method( cLoader, "bufsize", syck_parser_bufsize_get, 0 );
- rb_define_method( cLoader, "detect_implicit", syck_loader_detect_implicit, 1 );
- rb_define_method( cLoader, "transfer", syck_loader_transfer, 2 );
-
- oDefaultLoader = rb_funcall( cLoader, rb_intern( "new" ), 0 );
- rb_define_const( rb_syck, "DefaultLoader", oDefaultLoader );
+ cResolver = rb_define_class_under( rb_syck, "Resolver", rb_cObject );
+ rb_define_attr( cResolver, "tags", 1, 1 );
+ rb_define_method( cResolver, "initialize", syck_resolver_initialize, 0 );
+ rb_define_method( cResolver, "add_type", syck_resolver_add_type, 2 );
+ rb_define_method( cResolver, "use_types_at", syck_resolver_use_types_at, 1 );
+ rb_define_method( cResolver, "detect_implicit", syck_resolver_detect_implicit, 1 );
+ rb_define_method( cResolver, "transfer", syck_resolver_transfer, 2 );
+ rb_define_method( cResolver, "node_import", syck_resolver_node_import, 1 );
+ rb_define_method( cResolver, "tagurize", syck_resolver_tagurize, 1 );
+
+ rb_global_variable( &oDefaultResolver );
+ oDefaultResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
+ rb_define_singleton_method( oDefaultResolver, "node_import", syck_defaultresolver_node_import, 1 );
+ rb_define_singleton_method( oDefaultResolver, "detect_implicit", syck_defaultresolver_detect_implicit, 1 );
+ rb_define_const( rb_syck, "DefaultResolver", oDefaultResolver );
+ rb_global_variable( &oGenericResolver );
+ oGenericResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
+ rb_define_singleton_method( oGenericResolver, "node_import", syck_genericresolver_node_import, 1 );
+ rb_define_const( rb_syck, "GenericResolver", oGenericResolver );
/*
* Define YAML::Syck::Parser class
*/
cParser = rb_define_class_under( rb_syck, "Parser", rb_cObject );
rb_define_attr( cParser, "options", 1, 1 );
- rb_define_singleton_method( cParser, "new", syck_parser_new, -1 );
- rb_define_method(cParser, "initialize", syck_parser_initialize, 1);
+ rb_define_attr( cParser, "resolver", 1, 1 );
+ rb_define_attr( cParser, "input", 1, 1 );
+ rb_define_alloc_func( cParser, syck_parser_s_alloc );
+ rb_define_method(cParser, "initialize", syck_parser_initialize, -1 );
+ rb_define_method(cParser, "bufsize=", syck_parser_bufsize_set, 1 );
+ rb_define_method(cParser, "bufsize", syck_parser_bufsize_get, 0 );
rb_define_method(cParser, "load", syck_parser_load, -1);
rb_define_method(cParser, "load_documents", syck_parser_load_documents, -1);
+ rb_define_method(cParser, "set_resolver", syck_parser_set_resolver, 1);
/*
* Define YAML::Syck::Node class
*/
cNode = rb_define_class_under( rb_syck, "Node", rb_cObject );
- rb_define_attr( cNode, "kind", 1, 1 );
- rb_define_attr( cNode, "type_id", 1, 1 );
- rb_define_attr( cNode, "value", 1, 1 );
- rb_define_attr( cNode, "anchor", 1, 1 );
- rb_define_method( cNode, "initialize", syck_node_initialize, 2);
+ rb_define_method( cNode, "initialize_copy", syck_node_init_copy, 1 );
+ rb_define_attr( cNode, "emitter", 1, 1 );
+ rb_define_attr( cNode, "resolver", 1, 1 );
+ rb_define_attr( cNode, "kind", 1, 0 );
+ rb_define_attr( cNode, "type_id", 1, 0 );
+ rb_define_attr( cNode, "value", 1, 0 );
+ rb_define_method( cNode, "type_id=", syck_node_type_id_set, 1 );
rb_define_method( cNode, "transform", syck_node_transform, 0);
/*
- * Define YAML::Syck::PrivateType class
+ * Define YAML::Syck::Scalar, YAML::Syck::Seq, YAML::Syck::Map --
+ * all are the publicly usable variants of YAML::Syck::Node
+ */
+ cScalar = rb_define_class_under( rb_syck, "Scalar", cNode );
+ rb_define_alloc_func( cScalar, syck_scalar_alloc );
+ rb_define_method( cScalar, "initialize", syck_scalar_initialize, 3 );
+ rb_define_method( cScalar, "value=", syck_scalar_value_set, 1 );
+ rb_define_method( cScalar, "style=", syck_scalar_style_set, 1 );
+ cSeq = rb_define_class_under( rb_syck, "Seq", cNode );
+ rb_define_alloc_func( cSeq, syck_seq_alloc );
+ rb_define_method( cSeq, "initialize", syck_seq_initialize, 3 );
+ rb_define_method( cSeq, "value=", syck_seq_value_set, 1 );
+ rb_define_method( cSeq, "add", syck_seq_add_m, 1 );
+ rb_define_method( cSeq, "style=", syck_seq_style_set, 1 );
+ cMap = rb_define_class_under( rb_syck, "Map", cNode );
+ rb_define_alloc_func( cMap, syck_map_alloc );
+ rb_define_method( cMap, "initialize", syck_map_initialize, 3 );
+ rb_define_method( cMap, "value=", syck_map_value_set, 1 );
+ rb_define_method( cMap, "add", syck_map_add_m, 2 );
+ rb_define_method( cMap, "style=", syck_map_style_set, 1 );
+
+ /*
+ * Define YAML::PrivateType class
*/
- cPrivateType = rb_define_class_under( rb_syck, "PrivateType", rb_cObject );
+ cPrivateType = rb_define_class_under( rb_yaml, "PrivateType", rb_cObject );
rb_define_attr( cPrivateType, "type_id", 1, 1 );
rb_define_attr( cPrivateType, "value", 1, 1 );
rb_define_method( cPrivateType, "initialize", syck_privatetype_initialize, 2);
/*
- * Define YAML::Syck::DomainType class
+ * Define YAML::DomainType class
*/
- cDomainType = rb_define_class_under( rb_syck, "DomainType", rb_cObject );
+ cDomainType = rb_define_class_under( rb_yaml, "DomainType", rb_cObject );
rb_define_attr( cDomainType, "domain", 1, 1 );
rb_define_attr( cDomainType, "type_id", 1, 1 );
rb_define_attr( cDomainType, "value", 1, 1 );
rb_define_method( cDomainType, "initialize", syck_domaintype_initialize, 3);
/*
+ * Define YAML::Object class
+ */
+ cYObject = rb_define_class_under( rb_yaml, "Object", rb_cObject );
+ rb_define_attr( cYObject, "class", 1, 1 );
+ rb_define_attr( cYObject, "ivars", 1, 1 );
+ rb_define_method( cYObject, "initialize", syck_yobject_initialize, 2);
+ rb_define_method( cYObject, "yaml_initialize", syck_yobject_initialize, 2);
+
+ /*
* Define YAML::Syck::BadAlias class
*/
cBadAlias = rb_define_class_under( rb_syck, "BadAlias", rb_cObject );
rb_define_attr( cBadAlias, "name", 1, 1 );
rb_define_method( cBadAlias, "initialize", syck_badalias_initialize, 1);
+ rb_define_method( cBadAlias, "<=>", syck_badalias_cmp, 1);
+ rb_include_module( cBadAlias, rb_const_get( rb_cObject, rb_intern("Comparable") ) );
- /*
- * Define YAML::Syck::MergeKey class
- */
- cMergeKey = rb_define_class_under( rb_syck, "MergeKey", rb_cObject );
+ /*
+ * Define YAML::Syck::MergeKey class
+ */
+ cMergeKey = rb_define_class_under( rb_syck, "MergeKey", rb_cObject );
- /*
- * Define YAML::Syck::DefaultKey class
- */
- cDefaultKey = rb_define_class_under( rb_syck, "DefaultKey", rb_cObject );
+ /*
+ * Define YAML::Syck::DefaultKey class
+ */
+ cDefaultKey = rb_define_class_under( rb_syck, "DefaultKey", rb_cObject );
+
+ /*
+ * Define YAML::Syck::Out classes
+ */
+ cOut = rb_define_class_under( rb_syck, "Out", rb_cObject );
+ rb_define_attr( cOut, "emitter", 1, 1 );
+ rb_define_method( cOut, "initialize", syck_out_initialize, 1 );
+ rb_define_method( cOut, "map", syck_out_map, -1 );
+ rb_define_method( cOut, "seq", syck_out_seq, -1 );
+ rb_define_method( cOut, "scalar", syck_out_scalar, -1 );
/*
* Define YAML::Syck::Emitter class
*/
cEmitter = rb_define_class_under( rb_syck, "Emitter", rb_cObject );
- rb_define_singleton_method( cEmitter, "new", syck_emitter_new, -1 );
- rb_define_method( cEmitter, "initialize", syck_emitter_initialize, 1 );
- rb_define_method( cEmitter, "level", syck_emitter_level_m, 0 );
- rb_define_method( cEmitter, "write", syck_emitter_write_m, 1 );
- rb_define_method( cEmitter, "<<", syck_emitter_write_m, 1 );
- rb_define_method( cEmitter, "simple", syck_emitter_simple_write, 1 );
- rb_define_method( cEmitter, "flush", syck_emitter_flush_m, 0 );
- rb_define_method( cEmitter, "start_object", syck_emitter_start_object, 1 );
- rb_define_method( cEmitter, "end_object", syck_emitter_end_object, 0 );
+ rb_define_attr( cEmitter, "level", 1, 1 );
+ rb_define_alloc_func( cEmitter, syck_emitter_s_alloc );
+ rb_define_method( cEmitter, "initialize", syck_emitter_reset, -1 );
+ rb_define_method( cEmitter, "reset", syck_emitter_reset, -1 );
+ rb_define_method( cEmitter, "emit", syck_emitter_emit, -1 );
+ rb_define_method( cEmitter, "set_resolver", syck_emitter_set_resolver, 1);
+ rb_define_method( cEmitter, "node_export", syck_emitter_node_export, 1);
}
diff --git a/ext/syck/syck.c b/ext/syck/syck.c
index 8f46e85ae0..a83c8813c1 100644
--- a/ext/syck/syck.c
+++ b/ext/syck/syck.c
@@ -6,11 +6,12 @@
*
* Copyright (C) 2003 why the lucky stiff
*/
+#include "ruby.h"
+
#include <stdio.h>
#include <string.h>
#include "syck.h"
-#include "ruby.h"
void syck_parser_pop_level( SyckParser * );
@@ -88,7 +89,7 @@ syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
}
if ( beg < str->ptr )
{
- len = ( str->ptr - beg ) + 1;
+ len = ( str->ptr - beg );
S_MEMCPY( buf + skip, beg, char, len );
}
len += skip;
@@ -158,6 +159,7 @@ syck_new_parser()
{
SyckParser *p;
p = S_ALLOC( SyckParser );
+ S_MEMZERO( p, SyckParser, 1 );
p->lvl_capa = ALLOC_CT;
p->levels = S_ALLOC_N( SyckLevel, p->lvl_capa );
p->input_type = syck_yaml_utf8;
@@ -198,7 +200,8 @@ syck_lookup_sym( SyckParser *p, SYMID id, char **data )
int
syck_st_free_nodes( char *key, SyckNode *n, char *arg )
{
- syck_free_node( n );
+ if ( n != (void *)1 ) syck_free_node( n );
+ n = NULL;
return ST_CONTINUE;
}
@@ -206,15 +209,6 @@ void
syck_st_free( SyckParser *p )
{
/*
- * Free the adhoc symbol table
- */
- if ( p->syms != NULL )
- {
- st_free_table( p->syms );
- p->syms = NULL;
- }
-
- /*
* Free the anchor tables
*/
if ( p->anchors != NULL )
@@ -236,6 +230,15 @@ void
syck_free_parser( SyckParser *p )
{
/*
+ * Free the adhoc symbol table
+ */
+ if ( p->syms != NULL )
+ {
+ st_free_table( p->syms );
+ p->syms = NULL;
+ }
+
+ /*
* Free tables, levels
*/
syck_st_free( p );
@@ -407,12 +410,10 @@ syck_move_tokens( SyckParser *p )
return 0;
skip = p->limit - p->token;
- if ( skip < 1 )
- return 0;
-
if ( ( count = p->token - p->buffer ) )
{
- S_MEMMOVE( p->buffer, p->token, char, skip );
+ if (skip > 0)
+ S_MEMMOVE( p->buffer, p->token, char, skip );
p->token = p->buffer;
p->marker -= count;
p->cursor -= count;
diff --git a/ext/syck/syck.h b/ext/syck/syck.h
index 0383c5ad47..e7d07e9c0d 100644
--- a/ext/syck/syck.h
+++ b/ext/syck/syck.h
@@ -13,10 +13,11 @@
#define SYCK_YAML_MAJOR 1
#define SYCK_YAML_MINOR 0
-#define SYCK_VERSION "0.42"
+#define SYCK_VERSION "0.60"
#define YAML_DOMAIN "yaml.org,2002"
#include <stdio.h>
+#include <stdlib.h>
#include <ctype.h>
#include "st.h"
@@ -51,7 +52,7 @@ extern "C" {
#define S_ALLOC_N(type,n) (type*)malloc(sizeof(type)*(n))
#define S_ALLOC(type) (type*)malloc(sizeof(type))
#define S_REALLOC_N(var,type,n) (var)=(type*)realloc((char*)(var),sizeof(type)*(n))
-#define S_FREE(n) free(n); n = NULL;
+#define S_FREE(n) if (n) { free(n); n = NULL; }
#define S_ALLOCA_N(type,n) (type*)alloca(sizeof(type)*(n))
@@ -63,12 +64,16 @@ extern "C" {
#define BLOCK_FOLD 10
#define BLOCK_LIT 20
#define BLOCK_PLAIN 30
-#define NL_CHOMP 130
-#define NL_KEEP 140
+#define NL_CHOMP 40
+#define NL_KEEP 50
/*
* Node definitions
*/
+#ifndef ST_DATA_T_DEFINED
+typedef long st_data_t;
+#endif
+
#define SYMID unsigned long
typedef struct _syck_node SyckNode;
@@ -84,6 +89,25 @@ enum map_part {
map_value
};
+enum map_style {
+ map_none,
+ map_inline
+};
+
+enum seq_style {
+ seq_none,
+ seq_inline
+};
+
+enum scalar_style {
+ scalar_none,
+ scalar_1quote,
+ scalar_2quote,
+ scalar_fold,
+ scalar_literal,
+ scalar_plain
+};
+
/*
* Node metadata struct
*/
@@ -99,6 +123,7 @@ struct _syck_node {
union {
/* Storage for map data */
struct SyckMap {
+ enum map_style style;
SYMID *keys;
SYMID *values;
long capa;
@@ -106,12 +131,14 @@ struct _syck_node {
} *pairs;
/* Storage for sequence data */
struct SyckSeq {
+ enum seq_style style;
SYMID *items;
long capa;
long idx;
} *list;
/* Storage for string data */
struct SyckStr {
+ enum scalar_style style;
char *ptr;
long len;
} *str;
@@ -154,9 +181,13 @@ enum syck_level_status {
syck_lvl_map,
syck_lvl_block,
syck_lvl_str,
- syck_lvl_inline,
+ syck_lvl_iseq,
+ syck_lvl_imap,
syck_lvl_end,
- syck_lvl_pause
+ syck_lvl_pause,
+ syck_lvl_anctag,
+ syck_lvl_mapx,
+ syck_lvl_seqx
};
/*
@@ -177,9 +208,16 @@ struct _syck_str {
};
struct _syck_level {
+ /* Indent */
int spaces;
+ /* Counts nodes emitted at this level, useful for parsing
+ * keys and pairs in bytecode */
int ncount;
+ /* Does node have anchors or tags? */
+ int anctag;
+ /* Domain prefixing at the given level */
char *domain;
+ /* Keeps a node status */
enum syck_level_status status;
};
@@ -222,6 +260,7 @@ struct _syck_parser {
SyckLevel *levels;
int lvl_idx;
int lvl_capa;
+ /* Pointer for extension's use */
void *bonus;
};
@@ -232,27 +271,19 @@ typedef struct _syck_emitter SyckEmitter;
typedef struct _syck_emitter_node SyckEmitterNode;
typedef void (*SyckOutputHandler)(SyckEmitter *, char *, long);
+typedef void (*SyckEmitterHandler)(SyckEmitter *, st_data_t);
enum doc_stage {
doc_open,
- doc_need_header,
doc_processing
};
-enum block_styles {
- block_arbitrary,
- block_fold,
- block_literal
-};
-
/*
* Emitter struct
*/
struct _syck_emitter {
/* Headerless doc flag */
int headless;
- /* Sequence map shortcut flag */
- int seq_map;
/* Force header? */
int use_header;
/* Force version? */
@@ -266,7 +297,7 @@ struct _syck_emitter {
/* Best width on folded scalars */
int best_width;
/* Use literal[1] or folded[2] blocks on all text? */
- enum block_styles block_style;
+ enum scalar_style style;
/* Stage of written document */
enum doc_stage stage;
/* Level counter */
@@ -276,15 +307,21 @@ struct _syck_emitter {
/* Object ignore ID */
SYMID ignore_id;
/* Symbol table for anchors */
- st_table *markers, *anchors;
+ st_table *markers, *anchors, *anchored;
/* Custom buffer size */
size_t bufsize;
/* Buffer */
char *buffer, *marker;
/* Absolute position of the buffer */
long bufpos;
+ /* Handler for emitter nodes */
+ SyckEmitterHandler emitter_handler;
/* Handler for output */
- SyckOutputHandler handler;
+ SyckOutputHandler output_handler;
+ /* Levels of indentation */
+ SyckLevel *levels;
+ int lvl_idx;
+ int lvl_capa;
/* Pointer for extension's use */
void *bonus;
};
@@ -311,6 +348,7 @@ SyckNode *syck_hdlr_get_anchor( SyckParser *, char * );
void syck_add_transfer( char *, SyckNode *, int );
char *syck_xprivate( char *, int );
char *syck_taguri( char *, char *, int );
+int syck_tagcmp( char *, char * );
int syck_add_sym( SyckParser *, char * );
int syck_lookup_sym( SyckParser *, SYMID, char ** );
int syck_try_implicit( SyckNode * );
@@ -327,23 +365,42 @@ long syck_io_str_read( char *, SyckIoStr *, long, long );
char *syck_base64enc( char *, long );
char *syck_base64dec( char *, long );
SyckEmitter *syck_new_emitter();
+SYMID syck_emitter_mark_node( SyckEmitter *, st_data_t );
void syck_emitter_ignore_id( SyckEmitter *, SYMID );
-void syck_emitter_handler( SyckEmitter *, SyckOutputHandler );
+void syck_output_handler( SyckEmitter *, SyckOutputHandler );
+void syck_emitter_handler( SyckEmitter *, SyckEmitterHandler );
void syck_free_emitter( SyckEmitter * );
void syck_emitter_clear( SyckEmitter * );
-void syck_emitter_simple( SyckEmitter *, char *, long );
void syck_emitter_write( SyckEmitter *, char *, long );
+void syck_emitter_escape( SyckEmitter *, char *, long );
void syck_emitter_flush( SyckEmitter *, long );
-char *syck_emitter_start_obj( SyckEmitter *, SYMID );
-void syck_emitter_end_obj( SyckEmitter * );
+void syck_emit( SyckEmitter *, st_data_t );
+void syck_emit_scalar( SyckEmitter *, char *, enum scalar_style, int, int, char, char *, long );
+void syck_emit_1quoted( SyckEmitter *, int, char *, long );
+void syck_emit_2quoted( SyckEmitter *, int, char *, long );
+void syck_emit_folded( SyckEmitter *, int, char, char *, long );
+void syck_emit_literal( SyckEmitter *, char, char *, long );
+void syck_emit_seq( SyckEmitter *, char *, enum seq_style );
+void syck_emit_item( SyckEmitter *, st_data_t );
+void syck_emit_map( SyckEmitter *, char *, enum map_style );
+void syck_emit_end( SyckEmitter * );
+void syck_emit_tag( SyckEmitter *, char *, char * );
+void syck_emit_indent( SyckEmitter * );
+SyckLevel *syck_emitter_current_level( SyckEmitter * );
+SyckLevel *syck_emitter_parent_level( SyckEmitter * );
+void syck_emitter_pop_level( SyckEmitter * );
+void syck_emitter_add_level( SyckEmitter *, int, enum syck_level_status );
+void syck_emitter_reset_levels( SyckEmitter * );
SyckParser *syck_new_parser();
void syck_free_parser( SyckParser * );
void syck_parser_set_root_on_error( SyckParser *, SYMID );
void syck_parser_implicit_typing( SyckParser *, int );
void syck_parser_taguri_expansion( SyckParser *, int );
+int syck_scan_scalar( int, char *, long );
void syck_parser_handler( SyckParser *, SyckNodeHandler );
void syck_parser_error_handler( SyckParser *, SyckErrorHandler );
void syck_parser_bad_anchor_handler( SyckParser *, SyckBadAnchorHandler );
+void syck_parser_set_input_type( SyckParser *, enum syck_parser_input );
void syck_parser_file( SyckParser *, FILE *, SyckIoFileRead );
void syck_parser_str( SyckParser *, char *, long, SyckIoStrRead );
void syck_parser_str_auto( SyckParser *, char *, SyckIoStrRead );
@@ -353,7 +410,6 @@ void syck_parser_pop_level( SyckParser * );
void free_any_io( SyckParser * );
long syck_parser_read( SyckParser * );
long syck_parser_readlen( SyckParser *, long );
-void syck_parser_init( SyckParser *, int );
SYMID syck_parse( SyckParser * );
void syck_default_error_handler( SyckParser *, char * );
SYMID syck_yaml2byte_handler( SyckParser *, SyckNode * );
@@ -367,31 +423,33 @@ SyckNode *syck_alloc_seq();
SyckNode *syck_alloc_str();
void syck_free_node( SyckNode * );
void syck_free_members( SyckNode * );
-SyckNode *syck_new_str( char * );
-SyckNode *syck_new_str2( char *, long );
+SyckNode *syck_new_str( char *, enum scalar_style );
+SyckNode *syck_new_str2( char *, long, enum scalar_style );
+void syck_replace_str( SyckNode *, char *, enum scalar_style );
+void syck_replace_str2( SyckNode *, char *, long, enum scalar_style );
void syck_str_blow_away_commas( SyckNode * );
char *syck_str_read( SyckNode * );
SyckNode *syck_new_map( SYMID, SYMID );
+void syck_map_empty( SyckNode * );
void syck_map_add( SyckNode *, SYMID, SYMID );
SYMID syck_map_read( SyckNode *, enum map_part, long );
void syck_map_assign( SyckNode *, enum map_part, long, SYMID );
long syck_map_count( SyckNode * );
void syck_map_update( SyckNode *, SyckNode * );
SyckNode *syck_new_seq( SYMID );
+void syck_seq_empty( SyckNode * );
void syck_seq_add( SyckNode *, SYMID );
+void syck_seq_assign( SyckNode *, long, SYMID );
SYMID syck_seq_read( SyckNode *, long );
long syck_seq_count( SyckNode * );
-void apply_seq_in_map( SyckParser *, SyckNode * );
-
/*
* Lexer prototypes
*/
void syckerror( char * );
-
-#ifndef ST_DATA_T_DEFINED
-typedef long st_data_t;
-#endif
+int syckparse( void * );
+union YYSTYPE;
+int sycklex( union YYSTYPE *, SyckParser * );
#if defined(__cplusplus)
} /* extern "C" { */
diff --git a/ext/syck/token.c b/ext/syck/token.c
index f9e0601e52..3c6cd1a9cf 100644
--- a/ext/syck/token.c
+++ b/ext/syck/token.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.5 on Tue Nov 25 12:10:28 2003 */
+/* Generated by re2c 0.9.10 on Tue Sep 20 17:46:17 2005 */
#line 1 "token.re"
/*
* token.re
@@ -8,8 +8,8 @@
*
* Copyright (C) 2003 why the lucky stiff
*/
-#include "syck.h"
#include "ruby.h"
+#include "syck.h"
#include "gram.h"
/*
@@ -40,7 +40,7 @@
/*
* Track line numbers
*/
-#define NEWLINE(ptr) YYLINEPTR = ptr + 1; if ( YYLINEPTR > YYLINECTPTR ) { YYLINE++; YYLINECTPTR = YYLINEPTR; }
+#define NEWLINE(ptr) YYLINEPTR = ptr + newline_len(ptr); if ( YYLINEPTR > YYLINECTPTR ) { YYLINE++; YYLINECTPTR = YYLINEPTR; }
/*
* I like seeing the level operations as macros...
@@ -61,7 +61,7 @@
#define ENSURE_YAML_IOPEN(last_lvl, to_len, reset) \
if ( last_lvl->spaces < to_len ) \
{ \
- if ( last_lvl->status == syck_lvl_inline ) \
+ if ( last_lvl->status == syck_lvl_iseq || last_lvl->status == syck_lvl_imap ) \
{ \
goto Document; \
} \
@@ -122,6 +122,7 @@
YYCURSOR = YYTOKEN; \
n->data.str->ptr = qstr; \
n->data.str->len = qidx; \
+ n->data.str->style = scalar_plain; \
sycklval->nodeData = n; \
if ( parser->implicit_typing == 1 ) \
{ \
@@ -130,6 +131,25 @@
return YAML_PLAIN; \
}
+/* concat the inline characters to the plain scalar */
+#define PLAIN_NOT_INL() \
+ if ( *(YYCURSOR - 1) == ' ' || is_newline( YYCURSOR - 1 ) ) \
+ { \
+ YYCURSOR--; \
+ } \
+ QUOTECATS(qstr, qcapa, qidx, YYTOKEN, YYCURSOR - YYTOKEN); \
+ goto Plain2;
+
+/* trim spaces off the end in case of indent */
+#define PLAIN_IS_INL() \
+ char *walker = qstr + qidx - 1; \
+ while ( walker > qstr && ( *walker == '\n' || *walker == ' ' || *walker == '\t' ) ) \
+ { \
+ qidx--; \
+ walker[0] = '\0'; \
+ walker--; \
+ }
+
/*
* Keep or chomp block?
* * Use only in "ScalarBlock" section *
@@ -137,16 +157,28 @@
#define RETURN_YAML_BLOCK() \
{ \
SyckNode *n = syck_alloc_str(); \
- n->type_id = syck_strndup( "str", 3 ); \
+ if ( ((SyckParser *)parser)->taguri_expansion == 1 ) \
+ { \
+ n->type_id = syck_taguri( YAML_DOMAIN, "str", 3 ); \
+ } \
+ else \
+ { \
+ n->type_id = syck_strndup( "str", 3 ); \
+ } \
n->data.str->ptr = qstr; \
n->data.str->len = qidx; \
+ if ( blockType == BLOCK_LIT ) { \
+ n->data.str->style = scalar_literal; \
+ } else { \
+ n->data.str->style = scalar_fold; \
+ } \
if ( qidx > 0 ) \
{ \
if ( nlDoWhat != NL_KEEP ) \
{ \
char *fc = n->data.str->ptr + n->data.str->len - 1; \
while ( is_newline( fc ) ) fc--; \
- if ( nlDoWhat != NL_CHOMP ) \
+ if ( nlDoWhat != NL_CHOMP && fc < n->data.str->ptr + n->data.str->len - 1 ) \
fc += 1; \
n->data.str->len = fc - n->data.str->ptr + 1; \
} \
@@ -186,7 +218,7 @@
{ \
SyckLevel *lvl_deep = CURRENT_LEVEL(); \
indt_len = lvl_deep->spaces; \
- if ( indt_len == YYTOKEN - YYLINEPTR ) \
+ if ( lvl_deep->status == syck_lvl_seq || ( indt_len == YYCURSOR - YYLINEPTR && lvl_deep->status != syck_lvl_map ) ) \
{ \
SyckLevel *lvl_over; \
parser->lvl_idx--; \
@@ -205,7 +237,9 @@ SyckParser *syck_parser_ptr = NULL;
* Accessory funcs later in this file.
*/
void eat_comments( SyckParser * );
+char escape_seq( char );
int is_newline( char *ptr );
+int newline_len( char *ptr );
int sycklex_yaml_utf8( YYSTYPE *, SyckParser * );
int sycklex_bytecode_utf8( YYSTYPE *, SyckParser * );
int syckwrap();
@@ -234,6 +268,7 @@ sycklex( YYSTYPE *sycklval, SyckParser *parser )
case syck_bytecode_utf8:
return sycklex_bytecode_utf8( sycklval, parser );
}
+ return YAML_DOCSEP;
}
/*
@@ -256,7 +291,7 @@ sycklex_yaml_utf8( YYSTYPE *sycklval, SyckParser *parser )
return t;
}
-#line 274
+#line 315 "token.re"
if ( YYLINEPTR != YYCURSOR )
@@ -268,19 +303,21 @@ Header:
YYTOKEN = YYCURSOR;
+
+#line 307 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
goto yy0;
-yy1: ++YYCURSOR;
+ ++YYCURSOR;
yy0:
if((YYLIMIT - YYCURSOR) < 5) YYFILL(5);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy7;
- case '\n': goto yy9;
- case '\r': goto yy11;
- case ' ': goto yy12;
+ case 0x00: goto yy7;
+ case 0x09: case ' ': goto yy12;
+ case 0x0A: goto yy9;
+ case 0x0D: goto yy11;
case '#': goto yy5;
case '-': goto yy2;
case '.': goto yy4;
@@ -293,73 +330,83 @@ yy2: yyaccept = 0;
default: goto yy3;
}
yy3:
-#line 333
- { YYPOS(0);
+#line 374 "token.re"
+{ YYPOS(0);
goto Document;
}
+#line 337 "<stdout>"
yy4: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
case '.': goto yy21;
default: goto yy3;
}
-yy5: yych = *++YYCURSOR;
+yy5: ++YYCURSOR;
+ goto yy6;
yy6:
-#line 315
- { eat_comments( parser );
+#line 356 "token.re"
+{ eat_comments( parser );
goto Header;
}
-yy7: yych = *++YYCURSOR;
+#line 351 "<stdout>"
+yy7: ++YYCURSOR;
+ goto yy8;
yy8:
-#line 319
- { SyckLevel *lvl = CURRENT_LEVEL();
+#line 360 "token.re"
+{ SyckLevel *lvl = CURRENT_LEVEL();
ENSURE_YAML_IEND(lvl, -1);
YYPOS(0);
return 0;
}
+#line 361 "<stdout>"
yy9: yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
goto yy18;
yy10:
-#line 325
- { GOBBLE_UP_YAML_INDENT( doc_level, YYTOKEN );
+#line 366 "token.re"
+{ GOBBLE_UP_YAML_INDENT( doc_level, YYTOKEN );
goto Header;
}
+#line 370 "<stdout>"
yy11: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy17;
+ case 0x0A: goto yy17;
default: goto yy3;
}
-yy12: yych = *++YYCURSOR;
+yy12: ++YYCURSOR;
+ yych = *YYCURSOR;
goto yy16;
yy13:
-#line 329
- { doc_level = YYCURSOR - YYLINEPTR;
+#line 370 "token.re"
+{ doc_level = YYCURSOR - YYLINEPTR;
goto Header;
}
+#line 384 "<stdout>"
yy14: yych = *++YYCURSOR;
goto yy3;
yy15: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
+ goto yy16;
yy16: switch(yych){
- case ' ': goto yy15;
+ case 0x09: case ' ': goto yy15;
default: goto yy13;
}
yy17: yyaccept = 1;
YYMARKER = ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
+ goto yy18;
yy18: switch(yych){
- case '\n': case ' ': goto yy17;
- case '\r': goto yy19;
+ case 0x0A: case ' ': goto yy17;
+ case 0x0D: goto yy19;
default: goto yy10;
}
yy19: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
switch(yych){
- case '\n': goto yy17;
+ case 0x0A: goto yy17;
default: goto yy20;
}
yy20: YYCURSOR = YYMARKER;
@@ -374,15 +421,16 @@ yy21: yych = *++YYCURSOR;
}
yy22: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy23;
- case '\r': goto yy27;
+ case 0x0A: goto yy23;
+ case 0x0D: goto yy27;
case ' ': goto yy25;
default: goto yy20;
}
-yy23: yych = *++YYCURSOR;
+yy23: ++YYCURSOR;
+ goto yy24;
yy24:
-#line 301
- { SyckLevel *lvl = CURRENT_LEVEL();
+#line 342 "token.re"
+{ SyckLevel *lvl = CURRENT_LEVEL();
if ( lvl->status == syck_lvl_header )
{
goto Header;
@@ -395,16 +443,18 @@ yy24:
}
return 0;
}
+#line 446 "<stdout>"
yy25: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
+ goto yy26;
yy26: switch(yych){
case ' ': goto yy25;
default: goto yy24;
}
yy27: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy23;
+ case 0x0A: goto yy23;
default: goto yy20;
}
yy28: yych = *++YYCURSOR;
@@ -414,15 +464,16 @@ yy28: yych = *++YYCURSOR;
}
yy29: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy30;
- case '\r': goto yy34;
+ case 0x0A: goto yy30;
+ case 0x0D: goto yy34;
case ' ': goto yy32;
default: goto yy20;
}
-yy30: yych = *++YYCURSOR;
+yy30: ++YYCURSOR;
+ goto yy31;
yy31:
-#line 287
- { SyckLevel *lvl = CURRENT_LEVEL();
+#line 328 "token.re"
+{ SyckLevel *lvl = CURRENT_LEVEL();
if ( lvl->status == syck_lvl_header )
{
YYPOS(3);
@@ -435,20 +486,22 @@ yy31:
return 0;
}
}
+#line 489 "<stdout>"
yy32: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
+ goto yy33;
yy33: switch(yych){
case ' ': goto yy32;
default: goto yy31;
}
-yy34: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy30;
+yy34: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy30;
default: goto yy20;
}
}
-#line 337
+#line 378 "token.re"
Document:
@@ -461,38 +514,41 @@ Document:
YYTOKEN = YYCURSOR;
+
+#line 518 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
goto yy35;
-yy36: ++YYCURSOR;
+ ++YYCURSOR;
yy35:
if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy60;
- case '\n': goto yy37;
- case '\r': goto yy39;
- case ' ': goto yy58;
- case '!': goto yy49;
- case '"': goto yy53;
- case '#': goto yy56;
- case '&': goto yy47;
- case '\'': goto yy51;
- case '*': goto yy48;
- case ',': case ':': goto yy45;
- case '-': case '?': goto yy46;
- case '>': case '|': goto yy55;
- case '[': case '{': goto yy41;
- case ']': case '}': goto yy43;
- default: goto yy62;
+ case 0x00: goto yy62;
+ case 0x09: case ' ': goto yy60;
+ case 0x0A: goto yy37;
+ case 0x0D: goto yy39;
+ case '!': goto yy51;
+ case '"': goto yy55;
+ case '#': goto yy58;
+ case '&': goto yy49;
+ case '\'': goto yy53;
+ case '*': goto yy50;
+ case ',': case ':': goto yy47;
+ case '-': case '?': goto yy48;
+ case '>': case '|': goto yy57;
+ case '[': goto yy41;
+ case ']': case '}': goto yy45;
+ case '{': goto yy43;
+ default: goto yy64;
}
yy37: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy90;
+ goto yy92;
yy38:
-#line 351
- { /* Isolate spaces */
+#line 392 "token.re"
+{ /* Isolate spaces */
int indt_len;
GOBBLE_UP_YAML_INDENT( indt_len, YYTOKEN );
lvl = CURRENT_LEVEL();
@@ -504,6 +560,12 @@ yy38:
goto Document;
}
+ /* Ignore indentation inside inlines */
+ if ( lvl->status == syck_lvl_iseq || lvl->status == syck_lvl_imap )
+ {
+ goto Document;
+ }
+
/* Check for open indent */
ENSURE_YAML_IEND(lvl, indt_len);
ENSURE_YAML_IOPEN(lvl, indt_len, 0);
@@ -513,47 +575,63 @@ yy38:
}
return YAML_INDENT;
}
-yy39: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy89;
+#line 578 "<stdout>"
+yy39: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy91;
default: goto yy40;
}
yy40:
-#line 445
- { ENSURE_YAML_IOPEN(lvl, doc_level, 1);
+#line 497 "token.re"
+{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
goto Plain;
}
-yy41: yych = *++YYCURSOR;
+#line 589 "<stdout>"
+yy41: ++YYCURSOR;
+ goto yy42;
yy42:
-#line 373
- { ENSURE_YAML_IOPEN(lvl, doc_level, 1);
+#line 420 "token.re"
+{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
lvl = CURRENT_LEVEL();
- ADD_LEVEL(lvl->spaces + 1, syck_lvl_inline);
+ ADD_LEVEL(lvl->spaces + 1, syck_lvl_iseq);
return YYTOKEN[0];
}
-yy43: yych = *++YYCURSOR;
+#line 599 "<stdout>"
+yy43: ++YYCURSOR;
+ goto yy44;
yy44:
-#line 379
- { POP_LEVEL();
+#line 426 "token.re"
+{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
+ lvl = CURRENT_LEVEL();
+ ADD_LEVEL(lvl->spaces + 1, syck_lvl_imap);
+ return YYTOKEN[0];
+ }
+#line 609 "<stdout>"
+yy45: ++YYCURSOR;
+ goto yy46;
+yy46:
+#line 432 "token.re"
+{ POP_LEVEL();
return YYTOKEN[0];
}
-yy45: yyaccept = 1;
+#line 617 "<stdout>"
+yy47: yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '\n': goto yy84;
- case '\r': goto yy88;
- case ' ': goto yy86;
+ case 0x0A: goto yy86;
+ case 0x0D: goto yy90;
+ case ' ': goto yy88;
default: goto yy40;
}
-yy46: yyaccept = 1;
+yy48: yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '\n': goto yy79;
- case '\r': goto yy83;
- case ' ': goto yy81;
+ case 0x0A: goto yy81;
+ case 0x0D: goto yy85;
+ case ' ': goto yy83;
default: goto yy40;
}
-yy47: yych = *++YYCURSOR;
+yy49: yych = *++YYCURSOR;
switch(yych){
case '-': case '0':
case '1':
@@ -614,10 +692,10 @@ yy47: yych = *++YYCURSOR;
case 'w':
case 'x':
case 'y':
- case 'z': goto yy76;
+ case 'z': goto yy78;
default: goto yy40;
}
-yy48: yych = *++YYCURSOR;
+yy50: yych = *++YYCURSOR;
switch(yych){
case '-': case '0':
case '1':
@@ -678,30 +756,35 @@ yy48: yych = *++YYCURSOR;
case 'w':
case 'x':
case 'y':
- case 'z': goto yy73;
+ case 'z': goto yy75;
default: goto yy40;
}
-yy49: yych = *++YYCURSOR;
-yy50:
-#line 418
- { ENSURE_YAML_IOPEN(lvl, doc_level, 1);
- goto TransferMethod; }
-yy51: yych = *++YYCURSOR;
+yy51: ++YYCURSOR;
+ goto yy52;
yy52:
-#line 421
- { ENSURE_YAML_IOPEN(lvl, doc_level, 1);
- goto SingleQuote; }
-yy53: yych = *++YYCURSOR;
+#line 471 "token.re"
+{ goto TransferMethod; }
+#line 767 "<stdout>"
+yy53: ++YYCURSOR;
+ goto yy54;
yy54:
-#line 424
- { ENSURE_YAML_IOPEN(lvl, doc_level, 1);
+#line 473 "token.re"
+{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
+ goto SingleQuote; }
+#line 774 "<stdout>"
+yy55: ++YYCURSOR;
+ goto yy56;
+yy56:
+#line 476 "token.re"
+{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
goto DoubleQuote; }
-yy55: yyaccept = 1;
+#line 781 "<stdout>"
+yy57: yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '\n': goto yy68;
- case '\r': goto yy72;
- case ' ': goto yy70;
+ case 0x0A: goto yy70;
+ case 0x0D: goto yy74;
+ case ' ': goto yy72;
case '+': case '-': case '0':
case '1':
case '2':
@@ -711,43 +794,51 @@ yy55: yyaccept = 1;
case '6':
case '7':
case '8':
- case '9': goto yy65;
+ case '9': goto yy67;
default: goto yy40;
}
-yy56: yych = *++YYCURSOR;
-yy57:
-#line 434
- { eat_comments( parser );
+yy58: ++YYCURSOR;
+ goto yy59;
+yy59:
+#line 486 "token.re"
+{ eat_comments( parser );
goto Document;
}
-yy58: yych = *++YYCURSOR;
- goto yy64;
-yy59:
-#line 438
- { goto Document; }
-yy60: yych = *++YYCURSOR;
+#line 807 "<stdout>"
+yy60: ++YYCURSOR;
+ yych = *YYCURSOR;
+ goto yy66;
yy61:
-#line 440
- { ENSURE_YAML_IEND(lvl, -1);
+#line 490 "token.re"
+{ goto Document; }
+#line 814 "<stdout>"
+yy62: ++YYCURSOR;
+ goto yy63;
+yy63:
+#line 492 "token.re"
+{ ENSURE_YAML_IEND(lvl, -1);
YYPOS(0);
return 0;
}
-yy62: yych = *++YYCURSOR;
+#line 823 "<stdout>"
+yy64: yych = *++YYCURSOR;
goto yy40;
-yy63: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
-yy64: switch(yych){
- case ' ': goto yy63;
- default: goto yy59;
- }
yy65: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
+ goto yy66;
yy66: switch(yych){
- case '\n': goto yy68;
- case '\r': goto yy72;
- case ' ': goto yy70;
+ case 0x09: case ' ': goto yy65;
+ default: goto yy61;
+ }
+yy67: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ goto yy68;
+yy68: switch(yych){
+ case 0x0A: goto yy70;
+ case 0x0D: goto yy74;
+ case ' ': goto yy72;
case '+': case '-': case '0':
case '1':
case '2':
@@ -757,39 +848,43 @@ yy66: switch(yych){
case '6':
case '7':
case '8':
- case '9': goto yy65;
- default: goto yy67;
+ case '9': goto yy67;
+ default: goto yy69;
}
-yy67: YYCURSOR = YYMARKER;
+yy69: YYCURSOR = YYMARKER;
switch(yyaccept){
case 0: goto yy38;
case 1: goto yy40;
}
-yy68: yych = *++YYCURSOR;
-yy69:
-#line 427
- { if ( is_newline( YYCURSOR - 1 ) )
+yy70: ++YYCURSOR;
+ goto yy71;
+yy71:
+#line 479 "token.re"
+{ if ( is_newline( YYCURSOR - 1 ) )
{
YYCURSOR--;
}
goto ScalarBlock;
}
-yy70: ++YYCURSOR;
+#line 869 "<stdout>"
+yy72: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy71: switch(yych){
- case ' ': goto yy70;
- default: goto yy69;
+ goto yy73;
+yy73: switch(yych){
+ case ' ': goto yy72;
+ default: goto yy71;
}
-yy72: yych = *++YYCURSOR;
+yy74: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy68;
- default: goto yy67;
+ case 0x0A: goto yy70;
+ default: goto yy69;
}
-yy73: ++YYCURSOR;
+yy75: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy74: switch(yych){
+ goto yy76;
+yy76: switch(yych){
case '-': case '0':
case '1':
case '2':
@@ -849,19 +944,21 @@ yy74: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy73;
- default: goto yy75;
+ case 'z': goto yy75;
+ default: goto yy77;
}
-yy75:
-#line 413
- { ENSURE_YAML_IOPEN(lvl, doc_level, 1);
+yy77:
+#line 466 "token.re"
+{ ENSURE_YAML_IOPEN(lvl, doc_level, 1);
sycklval->name = syck_strndup( YYTOKEN + 1, YYCURSOR - YYTOKEN - 1 );
return YAML_ALIAS;
}
-yy76: ++YYCURSOR;
+#line 956 "<stdout>"
+yy78: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy77: switch(yych){
+ goto yy79;
+yy79: switch(yych){
case '-': case '0':
case '1':
case '2':
@@ -921,13 +1018,12 @@ yy77: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy76;
- default: goto yy78;
+ case 'z': goto yy78;
+ default: goto yy80;
}
-yy78:
-#line 401
- { ENSURE_YAML_IOPEN(lvl, doc_level, 1);
- sycklval->name = syck_strndup( YYTOKEN + 1, YYCURSOR - YYTOKEN - 1 );
+yy80:
+#line 455 "token.re"
+{ sycklval->name = syck_strndup( YYTOKEN + 1, YYCURSOR - YYTOKEN - 1 );
/*
* Remove previous anchors of the same name. Since the parser will likely
@@ -937,70 +1033,79 @@ yy78:
syck_hdlr_remove_anchor(parser, sycklval->name);
return YAML_ANCHOR;
}
-yy79: yych = *++YYCURSOR;
-yy80:
-#line 387
- { ENSURE_YAML_IOPEN(lvl, YYTOKEN - YYLINEPTR, 1);
+#line 1036 "<stdout>"
+yy81: ++YYCURSOR;
+ goto yy82;
+yy82:
+#line 441 "token.re"
+{ ENSURE_YAML_IOPEN(lvl, YYTOKEN - YYLINEPTR, 1);
FORCE_NEXT_TOKEN(YAML_IOPEN);
- if ( is_newline( YYCURSOR ) || is_newline( YYCURSOR - 1 ) )
+ if ( *YYCURSOR == '#' || is_newline( YYCURSOR ) || is_newline( YYCURSOR - 1 ) )
{
YYCURSOR--;
- ADD_LEVEL((YYTOKEN + 1) - YYLINEPTR, syck_lvl_doc);
+ ADD_LEVEL((YYTOKEN + 1) - YYLINEPTR, syck_lvl_seq);
}
- else
+ else /* spaces followed by content uses the space as indentation */
{
- ADD_LEVEL(YYCURSOR - YYLINEPTR, syck_lvl_doc);
+ ADD_LEVEL(YYCURSOR - YYLINEPTR, syck_lvl_seq);
}
return YYTOKEN[0];
}
-yy81: ++YYCURSOR;
+#line 1054 "<stdout>"
+yy83: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy82: switch(yych){
- case ' ': goto yy81;
- default: goto yy80;
+ goto yy84;
+yy84: switch(yych){
+ case ' ': goto yy83;
+ default: goto yy82;
}
-yy83: yych = *++YYCURSOR;
+yy85: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy79;
- default: goto yy67;
+ case 0x0A: goto yy81;
+ default: goto yy69;
}
-yy84: yych = *++YYCURSOR;
-yy85:
-#line 383
- { YYPOS(1);
+yy86: ++YYCURSOR;
+ goto yy87;
+yy87:
+#line 436 "token.re"
+{ if ( *YYTOKEN == ':' && lvl->status != syck_lvl_imap ) lvl->status = syck_lvl_map;
+ YYPOS(1);
return YYTOKEN[0];
}
-yy86: ++YYCURSOR;
+#line 1076 "<stdout>"
+yy88: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy87: switch(yych){
- case ' ': goto yy86;
- default: goto yy85;
+ goto yy89;
+yy89: switch(yych){
+ case ' ': goto yy88;
+ default: goto yy87;
}
-yy88: yych = *++YYCURSOR;
+yy90: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy84;
- default: goto yy67;
+ case 0x0A: goto yy86;
+ default: goto yy69;
}
-yy89: yyaccept = 0;
+yy91: yyaccept = 0;
YYMARKER = ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy90: switch(yych){
- case '\n': case ' ': goto yy89;
- case '\r': goto yy91;
+ goto yy92;
+yy92: switch(yych){
+ case 0x0A: case ' ': goto yy91;
+ case 0x0D: goto yy93;
default: goto yy38;
}
-yy91: ++YYCURSOR;
+yy93: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
switch(yych){
- case '\n': goto yy89;
- default: goto yy67;
+ case 0x0A: goto yy91;
+ default: goto yy69;
}
}
-#line 449
+#line 501 "token.re"
}
@@ -1008,25 +1113,27 @@ Directive:
{
YYTOKTMP = YYCURSOR;
+
+#line 1117 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
- goto yy92;
-yy93: ++YYCURSOR;
-yy92:
+ goto yy94;
+ ++YYCURSOR;
+yy94:
if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy94;
- case ' ': goto yy97;
- case '%': goto yy95;
- default: goto yy99;
+ case 0x00: goto yy96;
+ case 0x09: case ' ': goto yy99;
+ case '%': goto yy97;
+ default: goto yy101;
}
-yy94: YYCURSOR = YYMARKER;
+yy96: YYCURSOR = YYMARKER;
switch(yyaccept){
- case 0: goto yy96;
+ case 0: goto yy98;
}
-yy95: yyaccept = 0;
+yy97: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
case '.':
@@ -1103,32 +1210,37 @@ yy95: yyaccept = 0;
case 'w':
case 'x':
case 'y':
- case 'z': goto yy102;
- default: goto yy96;
+ case 'z': goto yy104;
+ default: goto yy98;
}
-yy96:
-#line 462
- { YYCURSOR = YYTOKTMP;
+yy98:
+#line 514 "token.re"
+{ YYCURSOR = YYTOKTMP;
return YAML_DOCSEP;
}
-yy97: yych = *++YYCURSOR;
- goto yy101;
-yy98:
-#line 460
- { goto Directive; }
-yy99: yych = *++YYCURSOR;
- goto yy96;
-yy100: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+#line 1221 "<stdout>"
+yy99: ++YYCURSOR;
yych = *YYCURSOR;
-yy101: switch(yych){
- case ' ': goto yy100;
- default: goto yy98;
- }
+ goto yy103;
+yy100:
+#line 512 "token.re"
+{ goto Directive; }
+#line 1228 "<stdout>"
+yy101: yych = *++YYCURSOR;
+ goto yy98;
yy102: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
+ goto yy103;
yy103: switch(yych){
+ case 0x09: case ' ': goto yy102;
+ default: goto yy100;
+ }
+yy104: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ goto yy105;
+yy105: switch(yych){
case '.':
case '/':
case '0':
@@ -1201,11 +1313,11 @@ yy103: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy102;
- case ':': goto yy104;
- default: goto yy94;
+ case 'z': goto yy104;
+ case ':': goto yy106;
+ default: goto yy96;
}
-yy104: yych = *++YYCURSOR;
+yy106: yych = *++YYCURSOR;
switch(yych){
case '.':
case '/':
@@ -1281,13 +1393,14 @@ yy104: yych = *++YYCURSOR;
case 'w':
case 'x':
case 'y':
- case 'z': goto yy105;
- default: goto yy94;
+ case 'z': goto yy107;
+ default: goto yy96;
}
-yy105: ++YYCURSOR;
+yy107: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy106: switch(yych){
+ goto yy108;
+yy108: switch(yych){
case '.':
case '/':
case '0':
@@ -1362,14 +1475,15 @@ yy106: switch(yych){
case 'w':
case 'x':
case 'y':
- case 'z': goto yy105;
- default: goto yy107;
+ case 'z': goto yy107;
+ default: goto yy109;
}
-yy107:
-#line 458
- { goto Directive; }
+yy109:
+#line 510 "token.re"
+{ goto Directive; }
+#line 1484 "<stdout>"
}
-#line 465
+#line 517 "token.re"
}
@@ -1391,30 +1505,34 @@ Plain2:
Plain3:
+
+#line 1509 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
- goto yy108;
-yy109: ++YYCURSOR;
-yy108:
+ goto yy110;
+ ++YYCURSOR;
+yy110:
if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy120;
- case '\n': goto yy110;
- case '\r': goto yy112;
- case ' ': goto yy118;
+ case 0x00: goto yy124;
+ case 0x09: goto yy126;
+ case 0x0A: goto yy112;
+ case 0x0D: goto yy114;
+ case ' ': goto yy122;
case ',': goto yy117;
- case ':': goto yy114;
- case ']': case '}': goto yy115;
- default: goto yy122;
+ case ':': goto yy116;
+ case ']': goto yy120;
+ case '}': goto yy118;
+ default: goto yy127;
}
-yy110: yyaccept = 0;
+yy112: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy136;
-yy111:
-#line 488
- { int indt_len, nl_count = 0;
+ goto yy142;
+yy113:
+#line 540 "token.re"
+{ int indt_len, nl_count = 0;
SyckLevel *lvl;
char *tok = YYTOKEN;
GOBBLE_UP_YAML_INDENT( indt_len, tok );
@@ -1427,8 +1545,12 @@ yy111:
while ( YYTOKEN < YYCURSOR )
{
- if ( is_newline( YYTOKEN++ ) )
+ int nl_len = newline_len( YYTOKEN++ );
+ if ( nl_len )
+ {
nl_count++;
+ YYTOKEN += nl_len - 1;
+ }
}
if ( nl_count <= 1 )
{
@@ -1445,119 +1567,170 @@ yy111:
goto Plain2;
}
-yy112: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy135;
- default: goto yy113;
- }
-yy113:
-#line 542
- { QUOTECATS(qstr, qcapa, qidx, YYTOKEN, YYCURSOR - YYTOKEN);
+#line 1570 "<stdout>"
+yy114: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy141;
+ default: goto yy115;
+ }
+yy115:
+#line 627 "token.re"
+{ QUOTECATS(qstr, qcapa, qidx, YYTOKEN, YYCURSOR - YYTOKEN);
goto Plain2;
}
-yy114: yyaccept = 1;
+#line 1581 "<stdout>"
+yy116: yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '\n': goto yy130;
- case '\r': goto yy134;
- case ' ': goto yy132;
- default: goto yy113;
+ case 0x0A: goto yy136;
+ case 0x0D: goto yy140;
+ case ' ': goto yy138;
+ default: goto yy115;
}
-yy115: yych = *++YYCURSOR;
-yy116:
-#line 522
- { if ( plvl->status != syck_lvl_inline )
- {
- if ( *(YYCURSOR - 1) == ' ' || is_newline( YYCURSOR - 1 ) )
- {
- YYCURSOR--;
- }
- QUOTECATS(qstr, qcapa, qidx, YYTOKEN, YYCURSOR - YYTOKEN);
- goto Plain2;
- }
- RETURN_IMPLICIT();
- }
yy117: yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '\n': goto yy125;
- case '\r': goto yy128;
- case ' ': goto yy126;
- default: goto yy113;
- }
-yy118: yych = *++YYCURSOR;
- switch(yych){
- case '#': goto yy123;
- default: goto yy119;
+ case 0x0A: goto yy130;
+ case 0x0D: goto yy134;
+ case ' ': goto yy132;
+ default: goto yy115;
}
+yy118: ++YYCURSOR;
+ goto yy119;
yy119:
-#line 540
- { goto Plain3; }
-yy120: yych = *++YYCURSOR;
+#line 589 "token.re"
+{ if ( plvl->status != syck_lvl_imap )
+ {
+ PLAIN_NOT_INL();
+ }
+ else
+ {
+ PLAIN_IS_INL();
+ }
+ RETURN_IMPLICIT();
+ }
+#line 1612 "<stdout>"
+yy120: ++YYCURSOR;
+ goto yy121;
yy121:
-#line 538
- { RETURN_IMPLICIT(); }
-yy122: yych = *++YYCURSOR;
- goto yy113;
-yy123: yych = *++YYCURSOR;
-yy124:
-#line 534
- { eat_comments( parser );
+#line 600 "token.re"
+{ if ( plvl->status != syck_lvl_iseq )
+ {
+ PLAIN_NOT_INL();
+ }
+ else
+ {
+ PLAIN_IS_INL();
+ }
RETURN_IMPLICIT();
}
-yy125: yych = *++YYCURSOR;
- goto yy116;
-yy126: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
-yy127: switch(yych){
- case ' ': goto yy126;
- default: goto yy116;
- }
-yy128: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy125;
- default: goto yy129;
- }
-yy129: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy111;
- case 1: goto yy113;
- }
-yy130: yych = *++YYCURSOR;
+#line 1627 "<stdout>"
+yy122: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case '#': goto yy128;
+ default: goto yy123;
+ }
+yy123:
+#line 617 "token.re"
+{ if ( qidx == 0 )
+ {
+ goto Plain2;
+ }
+ else
+ {
+ goto Plain3;
+ }
+ }
+#line 1644 "<stdout>"
+yy124: ++YYCURSOR;
+ goto yy125;
+yy125:
+#line 615 "token.re"
+{ RETURN_IMPLICIT(); }
+#line 1650 "<stdout>"
+yy126: yych = *++YYCURSOR;
+ goto yy123;
+yy127: yych = *++YYCURSOR;
+ goto yy115;
+yy128: ++YYCURSOR;
+ goto yy129;
+yy129:
+#line 611 "token.re"
+{ eat_comments( parser );
+ RETURN_IMPLICIT();
+ }
+#line 1662 "<stdout>"
+yy130: ++YYCURSOR;
+ goto yy131;
yy131:
-#line 520
- { RETURN_IMPLICIT(); }
+#line 578 "token.re"
+{ if ( plvl->status != syck_lvl_iseq && plvl->status != syck_lvl_imap )
+ {
+ PLAIN_NOT_INL();
+ }
+ else
+ {
+ PLAIN_IS_INL();
+ }
+ RETURN_IMPLICIT();
+ }
+#line 1677 "<stdout>"
yy132: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
+ goto yy133;
yy133: switch(yych){
case ' ': goto yy132;
default: goto yy131;
}
yy134: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy130;
- default: goto yy129;
+ case 0x0A: goto yy130;
+ default: goto yy135;
+ }
+yy135: YYCURSOR = YYMARKER;
+ switch(yyaccept){
+ case 0: goto yy113;
+ case 1: goto yy115;
+ }
+yy136: ++YYCURSOR;
+ goto yy137;
+yy137:
+#line 576 "token.re"
+{ RETURN_IMPLICIT(); }
+#line 1701 "<stdout>"
+yy138: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy139;
+yy139: switch(yych){
+ case ' ': goto yy138;
+ default: goto yy137;
+ }
+yy140: yych = *++YYCURSOR;
+ switch(yych){
+ case 0x0A: goto yy136;
+ default: goto yy135;
}
-yy135: yyaccept = 0;
+yy141: yyaccept = 0;
YYMARKER = ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy136: switch(yych){
- case '\n': case ' ': goto yy135;
- case '\r': goto yy137;
- default: goto yy111;
+ goto yy142;
+yy142: switch(yych){
+ case 0x0A: case ' ': goto yy141;
+ case 0x0D: goto yy143;
+ default: goto yy113;
}
-yy137: ++YYCURSOR;
+yy143: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
switch(yych){
- case '\n': goto yy135;
- default: goto yy129;
+ case 0x0A: goto yy141;
+ default: goto yy135;
}
}
-#line 546
+#line 631 "token.re"
}
@@ -1570,27 +1743,29 @@ SingleQuote:
SingleQuote2:
YYTOKEN = YYCURSOR;
+
+#line 1747 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
- goto yy138;
-yy139: ++YYCURSOR;
-yy138:
+ goto yy144;
+ ++YYCURSOR;
+yy144:
if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy146;
- case '\n': goto yy140;
- case '\r': goto yy142;
- case '\'': goto yy144;
- default: goto yy147;
+ case 0x00: goto yy152;
+ case 0x0A: goto yy146;
+ case 0x0D: goto yy148;
+ case '\'': goto yy150;
+ default: goto yy153;
}
-yy140: yyaccept = 0;
+yy146: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy151;
-yy141:
-#line 560
- { int indt_len;
+ goto yy157;
+yy147:
+#line 645 "token.re"
+{ int indt_len;
int nl_count = 0;
SyckLevel *lvl;
GOBBLE_UP_YAML_INDENT( indt_len, YYTOKEN );
@@ -1607,8 +1782,12 @@ yy141:
while ( YYTOKEN < YYCURSOR )
{
- if ( is_newline( YYTOKEN++ ) )
+ int nl_len = newline_len( YYTOKEN++ );
+ if ( nl_len )
+ {
nl_count++;
+ YYTOKEN += nl_len - 1;
+ }
}
if ( nl_count <= 1 )
{
@@ -1625,24 +1804,26 @@ yy141:
goto SingleQuote2;
}
-yy142: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy150;
- default: goto yy143;
+#line 1807 "<stdout>"
+yy148: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy156;
+ default: goto yy149;
}
-yy143:
-#line 615
- { QUOTECAT(qstr, qcapa, qidx, *(YYCURSOR - 1));
+yy149:
+#line 712 "token.re"
+{ QUOTECAT(qstr, qcapa, qidx, *(YYCURSOR - 1));
goto SingleQuote2;
}
-yy144: yych = *++YYCURSOR;
- switch(yych){
- case '\'': goto yy148;
- default: goto yy145;
- }
-yy145:
-#line 600
- { SyckLevel *lvl;
+#line 1818 "<stdout>"
+yy150: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case '\'': goto yy154;
+ default: goto yy151;
+ }
+yy151:
+#line 689 "token.re"
+{ SyckLevel *lvl;
SyckNode *n = syck_alloc_str();
lvl = CURRENT_LEVEL();
@@ -1650,44 +1831,56 @@ yy145:
{
POP_LEVEL();
}
- n->type_id = syck_strndup( "str", 3 );
+ if ( ((SyckParser *)parser)->taguri_expansion == 1 )
+ {
+ n->type_id = syck_taguri( YAML_DOMAIN, "str", 3 );
+ }
+ else
+ {
+ n->type_id = syck_strndup( "str", 3 );
+ }
n->data.str->ptr = qstr;
n->data.str->len = qidx;
+ n->data.str->style = scalar_1quote;
sycklval->nodeData = n;
return YAML_PLAIN;
}
-yy146: yych = *++YYCURSOR;
- goto yy145;
-yy147: yych = *++YYCURSOR;
- goto yy143;
-yy148: yych = *++YYCURSOR;
-yy149:
-#line 596
- { QUOTECAT(qstr, qcapa, qidx, '\'');
+#line 1848 "<stdout>"
+yy152: yych = *++YYCURSOR;
+ goto yy151;
+yy153: yych = *++YYCURSOR;
+ goto yy149;
+yy154: ++YYCURSOR;
+ goto yy155;
+yy155:
+#line 685 "token.re"
+{ QUOTECAT(qstr, qcapa, qidx, '\'');
goto SingleQuote2;
}
-yy150: yyaccept = 0;
+#line 1860 "<stdout>"
+yy156: yyaccept = 0;
YYMARKER = ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy151: switch(yych){
- case '\n': case ' ': goto yy150;
- case '\r': goto yy152;
- default: goto yy141;
+ goto yy157;
+yy157: switch(yych){
+ case 0x0A: case ' ': goto yy156;
+ case 0x0D: goto yy158;
+ default: goto yy147;
}
-yy152: ++YYCURSOR;
+yy158: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
switch(yych){
- case '\n': goto yy150;
- default: goto yy153;
+ case 0x0A: goto yy156;
+ default: goto yy159;
}
-yy153: YYCURSOR = YYMARKER;
+yy159: YYCURSOR = YYMARKER;
switch(yyaccept){
- case 0: goto yy141;
+ case 0: goto yy147;
}
}
-#line 619
+#line 716 "token.re"
}
@@ -1704,28 +1897,30 @@ DoubleQuote2:
YYTOKEN = YYCURSOR;
+
+#line 1901 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
- goto yy154;
-yy155: ++YYCURSOR;
-yy154:
+ goto yy160;
+ ++YYCURSOR;
+yy160:
if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy161;
- case '\n': goto yy156;
- case '\r': goto yy158;
- case '"': goto yy163;
- case '\\': goto yy160;
- default: goto yy164;
- }
-yy156: yyaccept = 0;
+ case 0x00: goto yy167;
+ case 0x0A: goto yy162;
+ case 0x0D: goto yy164;
+ case '"': goto yy169;
+ case '\\': goto yy166;
+ default: goto yy170;
+ }
+yy162: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy178;
-yy157:
-#line 637
- { int indt_len;
+ goto yy184;
+yy163:
+#line 734 "token.re"
+{ int indt_len;
int nl_count = 0;
SyckLevel *lvl;
GOBBLE_UP_YAML_INDENT( indt_len, YYTOKEN );
@@ -1744,8 +1939,12 @@ yy157:
{
while ( YYTOKEN < YYCURSOR )
{
- if ( is_newline( YYTOKEN++ ) )
+ int nl_len = newline_len( YYTOKEN++ );
+ if ( nl_len )
+ {
nl_count++;
+ YYTOKEN += nl_len - 1;
+ }
}
if ( nl_count <= 1 )
{
@@ -1764,32 +1963,35 @@ yy157:
keep_nl = 1;
goto DoubleQuote2;
}
-yy158: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy177;
- default: goto yy159;
- }
-yy159:
-#line 722
- { QUOTECAT(qstr, qcapa, qidx, *(YYCURSOR - 1));
+#line 1966 "<stdout>"
+yy164: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy183;
+ default: goto yy165;
+ }
+yy165:
+#line 820 "token.re"
+{ QUOTECAT(qstr, qcapa, qidx, *(YYCURSOR - 1));
goto DoubleQuote2;
}
-yy160: yyaccept = 1;
+#line 1977 "<stdout>"
+yy166: yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case '\n': goto yy168;
- case '\r': goto yy170;
- case ' ': goto yy165;
- case '"': case '\\': case 'a':
+ case 0x0A: goto yy174;
+ case 0x0D: goto yy176;
+ case ' ': goto yy171;
+ case '"': case '0': case '\\': case 'a':
case 'b': case 'e':
- case 'f': case 'n': case 'r': case 't': case 'v': goto yy172;
- case 'x': goto yy171;
- default: goto yy159;
- }
-yy161: yych = *++YYCURSOR;
-yy162:
-#line 707
- { SyckLevel *lvl;
+ case 'f': case 'n': case 'r': case 't': case 'v': goto yy178;
+ case 'x': goto yy177;
+ default: goto yy165;
+ }
+yy167: ++YYCURSOR;
+ goto yy168;
+yy168:
+#line 797 "token.re"
+{ SyckLevel *lvl;
SyckNode *n = syck_alloc_str();
lvl = CURRENT_LEVEL();
@@ -1797,43 +1999,55 @@ yy162:
{
POP_LEVEL();
}
- n->type_id = syck_strndup( "str", 3 );
+ if ( ((SyckParser *)parser)->taguri_expansion == 1 )
+ {
+ n->type_id = syck_taguri( YAML_DOMAIN, "str", 3 );
+ }
+ else
+ {
+ n->type_id = syck_strndup( "str", 3 );
+ }
n->data.str->ptr = qstr;
n->data.str->len = qidx;
+ n->data.str->style = scalar_2quote;
sycklval->nodeData = n;
return YAML_PLAIN;
}
-yy163: yych = *++YYCURSOR;
- goto yy162;
-yy164: yych = *++YYCURSOR;
- goto yy159;
-yy165: ++YYCURSOR;
- if(YYLIMIT == YYCURSOR) YYFILL(1);
+#line 2016 "<stdout>"
+yy169: yych = *++YYCURSOR;
+ goto yy168;
+yy170: yych = *++YYCURSOR;
+ goto yy165;
+yy171: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
-yy166: switch(yych){
- case '\n': goto yy168;
- case '\r': goto yy170;
- case ' ': goto yy165;
- default: goto yy167;
- }
-yy167: YYCURSOR = YYMARKER;
+ goto yy172;
+yy172: switch(yych){
+ case 0x0A: goto yy174;
+ case 0x0D: goto yy176;
+ case ' ': goto yy171;
+ default: goto yy173;
+ }
+yy173: YYCURSOR = YYMARKER;
switch(yyaccept){
- case 0: goto yy157;
- case 1: goto yy159;
- }
-yy168: yych = *++YYCURSOR;
-yy169:
-#line 702
- { keep_nl = 0;
+ case 0: goto yy163;
+ case 1: goto yy165;
+ }
+yy174: ++YYCURSOR;
+ goto yy175;
+yy175:
+#line 792 "token.re"
+{ keep_nl = 0;
YYCURSOR--;
goto DoubleQuote2;
}
-yy170: yych = *++YYCURSOR;
+#line 2044 "<stdout>"
+yy176: yych = *++YYCURSOR;
switch(yych){
- case '\n': goto yy168;
- default: goto yy167;
+ case 0x0A: goto yy174;
+ default: goto yy173;
}
-yy171: yych = *++YYCURSOR;
+yy177: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1854,28 +2068,19 @@ yy171: yych = *++YYCURSOR;
case 'c':
case 'd':
case 'e':
- case 'f': goto yy174;
- default: goto yy167;
- }
-yy172: yych = *++YYCURSOR;
-yy173:
-#line 677
- { char ch = *( YYCURSOR - 1 );
- switch ( ch )
- {
- case 'a': ch = 7; break;
- case 'b': ch = '\010'; break;
- case 'e': ch = '\033'; break;
- case 'f': ch = '\014'; break;
- case 'n': ch = '\n'; break;
- case 'r': ch = '\015'; break;
- case 't': ch = '\t'; break;
- case 'v': ch = '\013'; break;
- }
- QUOTECAT(qstr, qcapa, qidx, ch);
+ case 'f': goto yy180;
+ default: goto yy173;
+ }
+yy178: ++YYCURSOR;
+ goto yy179;
+yy179:
+#line 778 "token.re"
+{ char ch = *( YYCURSOR - 1 );
+ QUOTECAT(qstr, qcapa, qidx, escape_seq( ch ));
goto DoubleQuote2;
}
-yy174: yych = *++YYCURSOR;
+#line 2082 "<stdout>"
+yy180: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -1896,13 +2101,14 @@ yy174: yych = *++YYCURSOR;
case 'c':
case 'd':
case 'e':
- case 'f': goto yy175;
- default: goto yy167;
+ case 'f': goto yy181;
+ default: goto yy173;
}
-yy175: yych = *++YYCURSOR;
-yy176:
-#line 693
- { long ch;
+yy181: ++YYCURSOR;
+ goto yy182;
+yy182:
+#line 783 "token.re"
+{ long ch;
char *chr_text = syck_strndup( YYTOKEN, 4 );
chr_text[0] = '0';
ch = strtol( chr_text, NULL, 16 );
@@ -1910,24 +2116,26 @@ yy176:
QUOTECAT(qstr, qcapa, qidx, ch);
goto DoubleQuote2;
}
-yy177: yyaccept = 0;
+#line 2119 "<stdout>"
+yy183: yyaccept = 0;
YYMARKER = ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy178: switch(yych){
- case '\n': case ' ': goto yy177;
- case '\r': goto yy179;
- default: goto yy157;
+ goto yy184;
+yy184: switch(yych){
+ case 0x0A: case ' ': goto yy183;
+ case 0x0D: goto yy185;
+ default: goto yy163;
}
-yy179: ++YYCURSOR;
+yy185: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
switch(yych){
- case '\n': goto yy177;
- default: goto yy167;
+ case 0x0A: goto yy183;
+ default: goto yy173;
}
}
-#line 726
+#line 824 "token.re"
}
@@ -1940,30 +2148,29 @@ TransferMethod:
TransferMethod2:
YYTOKTMP = YYCURSOR;
+
+#line 2152 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
- goto yy180;
-yy181: ++YYCURSOR;
-yy180:
+ goto yy186;
+ ++YYCURSOR;
+yy186:
if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy182;
- case '\n': goto yy183;
- case '\r': goto yy186;
- case ' ': goto yy185;
- case '\\': goto yy188;
- default: goto yy189;
- }
-yy182: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy187;
- }
-yy183: yych = *++YYCURSOR;
-yy184:
-#line 740
- { SyckLevel *lvl;
+ case 0x00: goto yy188;
+ case 0x0A: goto yy190;
+ case 0x0D: goto yy192;
+ case ' ': goto yy191;
+ case '\\': goto yy194;
+ default: goto yy195;
+ }
+yy188: ++YYCURSOR;
+ goto yy189;
+yy189:
+#line 838 "token.re"
+{ SyckLevel *lvl;
YYCURSOR = YYTOKTMP;
if ( YYCURSOR == YYTOKEN + 1 )
{
@@ -2012,27 +2219,34 @@ yy184:
return YAML_TRANSFER;
}
-yy185: yych = *++YYCURSOR;
- goto yy196;
-yy186: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy194;
- default: goto yy187;
+#line 2222 "<stdout>"
+yy190: yych = *++YYCURSOR;
+ goto yy189;
+yy191: yych = *++YYCURSOR;
+ goto yy204;
+yy192: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy188;
+ default: goto yy193;
}
-yy187:
-#line 802
- { QUOTECAT(qstr, qcapa, qidx, *(YYCURSOR - 1));
+yy193:
+#line 905 "token.re"
+{ QUOTECAT(qstr, qcapa, qidx, *(YYCURSOR - 1));
goto TransferMethod2;
}
-yy188: yyaccept = 0;
+#line 2237 "<stdout>"
+yy194: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
switch(yych){
- case 'x': goto yy190;
- default: goto yy187;
+ case '"': case '0': case '\\': case 'a':
+ case 'b': case 'e':
+ case 'f': case 'n': case 'r': case 't': case 'v': goto yy198;
+ case 'x': goto yy196;
+ default: goto yy193;
}
-yy189: yych = *++YYCURSOR;
- goto yy187;
-yy190: yych = *++YYCURSOR;
+yy195: yych = *++YYCURSOR;
+ goto yy193;
+yy196: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2053,10 +2267,23 @@ yy190: yych = *++YYCURSOR;
case 'c':
case 'd':
case 'e':
- case 'f': goto yy191;
- default: goto yy182;
+ case 'f': goto yy200;
+ default: goto yy197;
}
-yy191: yych = *++YYCURSOR;
+yy197: YYCURSOR = YYMARKER;
+ switch(yyaccept){
+ case 0: goto yy193;
+ }
+yy198: ++YYCURSOR;
+ goto yy199;
+yy199:
+#line 891 "token.re"
+{ char ch = *( YYCURSOR - 1 );
+ QUOTECAT(qstr, qcapa, qidx, escape_seq( ch ));
+ goto TransferMethod2;
+ }
+#line 2285 "<stdout>"
+yy200: yych = *++YYCURSOR;
switch(yych){
case '0':
case '1':
@@ -2077,13 +2304,14 @@ yy191: yych = *++YYCURSOR;
case 'c':
case 'd':
case 'e':
- case 'f': goto yy192;
- default: goto yy182;
+ case 'f': goto yy201;
+ default: goto yy197;
}
-yy192: yych = *++YYCURSOR;
-yy193:
-#line 793
- { long ch;
+yy201: ++YYCURSOR;
+ goto yy202;
+yy202:
+#line 896 "token.re"
+{ long ch;
char *chr_text = syck_strndup( YYTOKTMP, 4 );
chr_text[0] = '0';
ch = strtol( chr_text, NULL, 16 );
@@ -2091,17 +2319,17 @@ yy193:
QUOTECAT(qstr, qcapa, qidx, ch);
goto TransferMethod2;
}
-yy194: yych = *++YYCURSOR;
- goto yy184;
-yy195: ++YYCURSOR;
+#line 2322 "<stdout>"
+yy203: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy196: switch(yych){
- case ' ': goto yy195;
- default: goto yy184;
+ goto yy204;
+yy204: switch(yych){
+ case ' ': goto yy203;
+ default: goto yy189;
}
}
-#line 807
+#line 910 "token.re"
}
@@ -2116,8 +2344,7 @@ ScalarBlock:
int forceIndent = -1;
char *yyt = YYTOKEN;
SyckLevel *lvl = CURRENT_LEVEL();
- int parentIndent;
- GET_TRUE_YAML_INDENT(parentIndent);
+ int parentIndent = -1;
switch ( *yyt )
{
@@ -2137,7 +2364,7 @@ ScalarBlock:
}
else if ( isdigit( *yyt ) )
{
- forceIndent = strtol( yyt, NULL, 10 ) + parentIndent;
+ forceIndent = strtol( yyt, NULL, 10 );
}
}
@@ -2147,44 +2374,52 @@ ScalarBlock:
ScalarBlock2:
YYTOKEN = YYCURSOR;
+
+#line 2378 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
- goto yy197;
-yy198: ++YYCURSOR;
-yy197:
- if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ goto yy205;
+ ++YYCURSOR;
+yy205:
+ if((YYLIMIT - YYCURSOR) < 5) YYFILL(5);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy205;
- case '\n': goto yy199;
- case '\r': goto yy201;
- case '#': goto yy203;
- default: goto yy207;
- }
-yy199: yyaccept = 0;
+ case 0x00: goto yy213;
+ case 0x0A: goto yy207;
+ case 0x0D: goto yy209;
+ case '#': goto yy211;
+ case '-': goto yy215;
+ default: goto yy216;
+ }
+yy207: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy209;
-yy200:
-#line 854
- { char *pacer;
+ goto yy226;
+yy208:
+#line 956 "token.re"
+{ char *pacer;
char *tok = YYTOKEN;
int indt_len = 0, nl_count = 0, fold_nl = 0, nl_begin = 0;
GOBBLE_UP_YAML_INDENT( indt_len, tok );
lvl = CURRENT_LEVEL();
- if ( indt_len > parentIndent && lvl->status != syck_lvl_block )
- {
- int new_spaces = forceIndent > 0 ? forceIndent : indt_len;
- ADD_LEVEL( new_spaces, syck_lvl_block );
- lastIndent = indt_len - new_spaces;
- nl_begin = 1;
- lvl = CURRENT_LEVEL();
- }
- else if ( lvl->status != syck_lvl_block )
+ if ( lvl->status != syck_lvl_block )
{
- YYCURSOR = YYTOKEN;
- RETURN_YAML_BLOCK();
+ GET_TRUE_YAML_INDENT(parentIndent);
+ if ( forceIndent > 0 ) forceIndent += parentIndent;
+ if ( indt_len > parentIndent )
+ {
+ int new_spaces = forceIndent > 0 ? forceIndent : indt_len;
+ ADD_LEVEL( new_spaces, syck_lvl_block );
+ lastIndent = indt_len - new_spaces;
+ nl_begin = 1;
+ lvl = CURRENT_LEVEL();
+ }
+ else
+ {
+ YYCURSOR = YYTOKEN;
+ RETURN_YAML_BLOCK();
+ }
}
/*
@@ -2199,8 +2434,12 @@ yy200:
pacer = YYTOKEN;
while ( pacer < YYCURSOR )
{
- if ( is_newline( pacer++ ) )
+ int nl_len = newline_len( pacer++ );
+ if ( nl_len )
+ {
nl_count++;
+ pacer += nl_len - 1;
+ }
}
if ( fold_nl == 1 || nl_begin == 1 )
@@ -2232,20 +2471,23 @@ yy200:
}
goto ScalarBlock2;
}
-yy201: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy208;
- default: goto yy202;
- }
-yy202:
-#line 940
- { QUOTECAT(qstr, qcapa, qidx, *YYTOKEN);
+#line 2474 "<stdout>"
+yy209: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy225;
+ default: goto yy210;
+ }
+yy210:
+#line 1070 "token.re"
+{ QUOTECAT(qstr, qcapa, qidx, *YYTOKEN);
goto ScalarBlock2;
}
-yy203: yych = *++YYCURSOR;
-yy204:
-#line 921
- { lvl = CURRENT_LEVEL();
+#line 2485 "<stdout>"
+yy211: ++YYCURSOR;
+ goto yy212;
+yy212:
+#line 1032 "token.re"
+{ lvl = CURRENT_LEVEL();
if ( lvl->status != syck_lvl_block )
{
eat_comments( parser );
@@ -2257,37 +2499,96 @@ yy204:
}
goto ScalarBlock2;
}
-yy205: yych = *++YYCURSOR;
-yy206:
-#line 935
- { YYCURSOR--;
+#line 2502 "<stdout>"
+yy213: ++YYCURSOR;
+ goto yy214;
+yy214:
+#line 1046 "token.re"
+{ YYCURSOR--;
POP_LEVEL();
RETURN_YAML_BLOCK();
}
-yy207: yych = *++YYCURSOR;
- goto yy202;
-yy208: yyaccept = 0;
+#line 2511 "<stdout>"
+yy215: yyaccept = 1;
+ yych = *(YYMARKER = ++YYCURSOR);
+ switch(yych){
+ case '-': goto yy217;
+ default: goto yy210;
+ }
+yy216: yych = *++YYCURSOR;
+ goto yy210;
+yy217: yych = *++YYCURSOR;
+ switch(yych){
+ case '-': goto yy219;
+ default: goto yy218;
+ }
+yy218: YYCURSOR = YYMARKER;
+ switch(yyaccept){
+ case 0: goto yy208;
+ case 1: goto yy210;
+ }
+yy219: yych = *++YYCURSOR;
+ switch(yych){
+ case 0x0A: goto yy220;
+ case 0x0D: goto yy224;
+ case ' ': goto yy222;
+ default: goto yy218;
+ }
+yy220: ++YYCURSOR;
+ goto yy221;
+yy221:
+#line 1051 "token.re"
+{ if ( YYTOKEN == YYLINEPTR )
+ {
+ if ( blockType == BLOCK_FOLD && qidx > 0 )
+ {
+ qidx -= 1;
+ }
+ QUOTECAT(qstr, qcapa, qidx, '\n');
+ POP_LEVEL();
+ YYCURSOR = YYTOKEN;
+ RETURN_YAML_BLOCK();
+ }
+ else
+ {
+ QUOTECAT(qstr, qcapa, qidx, *YYTOKEN);
+ YYCURSOR = YYTOKEN + 1;
+ goto ScalarBlock2;
+ }
+ }
+#line 2559 "<stdout>"
+yy222: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy223;
+yy223: switch(yych){
+ case ' ': goto yy222;
+ default: goto yy221;
+ }
+yy224: yych = *++YYCURSOR;
+ switch(yych){
+ case 0x0A: goto yy220;
+ default: goto yy218;
+ }
+yy225: yyaccept = 0;
YYMARKER = ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy209: switch(yych){
- case '\n': case ' ': goto yy208;
- case '\r': goto yy210;
- default: goto yy200;
+ goto yy226;
+yy226: switch(yych){
+ case 0x0A: case ' ': goto yy225;
+ case 0x0D: goto yy227;
+ default: goto yy208;
}
-yy210: ++YYCURSOR;
+yy227: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
switch(yych){
- case '\n': goto yy208;
- default: goto yy211;
- }
-yy211: YYCURSOR = YYMARKER;
- switch(yyaccept){
- case 0: goto yy200;
+ case 0x0A: goto yy225;
+ default: goto yy218;
}
}
-#line 945
+#line 1075 "token.re"
}
@@ -2302,76 +2603,106 @@ Comment:
{
YYTOKEN = YYCURSOR;
+
+#line 2607 "<stdout>"
{
YYCTYPE yych;
unsigned int yyaccept;
- goto yy212;
-yy213: ++YYCURSOR;
-yy212:
+ goto yy228;
+ ++YYCURSOR;
+yy228:
if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
switch(yych){
- case '\000': goto yy214;
- case '\n': goto yy216;
- case '\r': goto yy217;
- default: goto yy219;
- }
-yy214: yych = *++YYCURSOR;
-yy215:
-#line 961
- { YYCURSOR = YYTOKEN;
+ case 0x00: goto yy230;
+ case 0x0A: goto yy232;
+ case 0x0D: goto yy233;
+ default: goto yy235;
+ }
+yy230: ++YYCURSOR;
+ goto yy231;
+yy231:
+#line 1091 "token.re"
+{ YYCURSOR = YYTOKEN;
return;
}
-yy216: yyaccept = 0;
+#line 2629 "<stdout>"
+yy232: yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy221;
-yy217: yych = *++YYCURSOR;
- switch(yych){
- case '\n': goto yy220;
- default: goto yy218;
- }
-yy218:
-#line 965
- { goto Comment;
+ goto yy237;
+yy233: ++YYCURSOR;
+ switch((yych = *YYCURSOR)) {
+ case 0x0A: goto yy236;
+ default: goto yy234;
+ }
+yy234:
+#line 1095 "token.re"
+{ goto Comment;
}
-yy219: yych = *++YYCURSOR;
- goto yy218;
-yy220: yyaccept = 0;
+#line 2642 "<stdout>"
+yy235: yych = *++YYCURSOR;
+ goto yy234;
+yy236: yyaccept = 0;
YYMARKER = ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
-yy221: switch(yych){
- case '\n': goto yy220;
- case '\r': goto yy222;
- default: goto yy215;
+ goto yy237;
+yy237: switch(yych){
+ case 0x0A: goto yy236;
+ case 0x0D: goto yy238;
+ default: goto yy231;
}
-yy222: ++YYCURSOR;
+yy238: ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
switch(yych){
- case '\n': goto yy220;
- default: goto yy223;
+ case 0x0A: goto yy236;
+ default: goto yy239;
}
-yy223: YYCURSOR = YYMARKER;
+yy239: YYCURSOR = YYMARKER;
switch(yyaccept){
- case 0: goto yy215;
+ case 0: goto yy231;
}
}
-#line 968
+#line 1098 "token.re"
}
}
+char
+escape_seq( char ch )
+{
+ switch ( ch )
+ {
+ case '0': return '\0';
+ case 'a': return 7;
+ case 'b': return '\010';
+ case 'e': return '\033';
+ case 'f': return '\014';
+ case 'n': return '\n';
+ case 'r': return '\015';
+ case 't': return '\t';
+ case 'v': return '\013';
+ default: return ch;
+ }
+}
+
int
is_newline( char *ptr )
{
+ return newline_len( ptr );
+}
+
+int
+newline_len( char *ptr )
+{
if ( *ptr == '\n' )
return 1;
if ( *ptr == '\r' && *( ptr + 1 ) == '\n' )
- return 1;
+ return 2;
return 0;
}
diff --git a/ext/syck/yaml2byte.c b/ext/syck/yaml2byte.c
index d55d1083b4..821a3cd5b5 100644
--- a/ext/syck/yaml2byte.c
+++ b/ext/syck/yaml2byte.c
@@ -1,5 +1,5 @@
/*
- * ybext.c
+ * yaml2byte.c
*
* $Author$
* $Date$
@@ -9,11 +9,11 @@
* WARNING WARNING WARNING --- THIS IS *NOT JUST* PLAYING
* ANYMORE! -- WHY HAS EMBRACED THIS AS THE REAL THING!
*/
+#include "ruby.h"
#include <syck.h>
#include <assert.h>
#define YAMLBYTE_UTF8
#include "yamlbyte.h"
-#include "ruby.h"
#include <stdio.h>
#define TRACE0(a) \
@@ -145,6 +145,7 @@ syck_yaml2byte_handler(p, n)
strcat( type_tag, "!" );
strcat( type_tag, n->type_id );
bytestring_append( val, YAMLBYTE_TRANSFER, type_tag, NULL);
+ S_FREE(type_tag);
}
}
switch (n->kind)
@@ -226,12 +227,17 @@ syck_yaml2byte(char *yamlstr)
syck_parser_implicit_typing( parser, 1 );
syck_parser_taguri_expansion( parser, 1 );
oid = syck_parse( parser );
- syck_lookup_sym( parser, oid, (char **)&sav );
- ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 );
- ret[0] = '\0';
- strcat( ret, "D\n" );
- strcat( ret, sav->buffer );
+ if ( syck_lookup_sym( parser, oid, (char **)&sav ) == 1 ) {
+ ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 );
+ ret[0] = '\0';
+ strcat( ret, "D\n" );
+ strcat( ret, sav->buffer );
+ }
+ else
+ {
+ ret = NULL;
+ }
syck_free_parser( parser );
return ret;
diff --git a/ext/syslog/MANIFEST b/ext/syslog/MANIFEST
deleted file mode 100644
index b5306034b7..0000000000
--- a/ext/syslog/MANIFEST
+++ /dev/null
@@ -1,6 +0,0 @@
-MANIFEST
-extconf.rb
-syslog.c
-syslog.txt
-test.rb
-depend
diff --git a/ext/syslog/syslog.c b/ext/syslog/syslog.c
index ce386eda30..ecc49318f7 100644
--- a/ext/syslog/syslog.c
+++ b/ext/syslog/syslog.c
@@ -22,6 +22,7 @@ static void syslog_write(int pri, int argc, VALUE *argv)
{
VALUE str;
+ rb_secure(4);
if (argc < 1) {
rb_raise(rb_eArgError, "no log message supplied");
}
@@ -38,6 +39,7 @@ static void syslog_write(int pri, int argc, VALUE *argv)
/* Syslog module methods */
static VALUE mSyslog_close(VALUE self)
{
+ rb_secure(4);
if (!syslog_opened) {
rb_raise(rb_eRuntimeError, "syslog not opened");
}
@@ -132,6 +134,7 @@ static VALUE mSyslog_get_mask(VALUE self)
static VALUE mSyslog_set_mask(VALUE self, VALUE mask)
{
+ rb_secure(4);
if (!syslog_opened) {
rb_raise(rb_eRuntimeError, "must open syslog before setting log mask");
}
@@ -146,7 +149,7 @@ static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self)
VALUE pri;
if (argc < 2) {
- rb_raise(rb_eArgError, "wrong # of arguments(%d for 2+)", argc);
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 2+)", argc);
}
argc--;
diff --git a/ext/syslog/syslog.txt b/ext/syslog/syslog.txt
index 9aed35133d..35bd4cb057 100644
--- a/ext/syslog/syslog.txt
+++ b/ext/syslog/syslog.txt
@@ -7,7 +7,10 @@ Amos Gouaux, University of Texas at Dallas
<amos+ruby@utdallas.edu>
&
Akinori MUSHA
-<knu@ruby-lang.org>
+<knu@iDaemons.org>
+
+Contact:
+ - Akinori MUSHA <knu@iDaemons.org> (current maintainer)
** Syslog(Module)
diff --git a/ext/tcltklib/MANIFEST b/ext/tcltklib/MANIFEST
deleted file mode 100644
index e06547a6aa..0000000000
--- a/ext/tcltklib/MANIFEST
+++ /dev/null
@@ -1,19 +0,0 @@
-MANIFEST
-README.1st
-README.euc
-MANUAL.euc
-MANUAL.eng
-tcltklib.c
-stubs.c
-depend
-extconf.rb
-lib/tcltk.rb
-demo/lines0.tcl
-demo/lines1.rb
-demo/lines2.rb
-demo/safeTk.rb
-sample/sample0.rb
-sample/sample1.rb
-sample/sample2.rb
-sample/maru.gif
-sample/batsu.gif
diff --git a/ext/tcltklib/MANUAL.eng b/ext/tcltklib/MANUAL.eng
deleted file mode 100644
index a037d18d41..0000000000
--- a/ext/tcltklib/MANUAL.eng
+++ /dev/null
@@ -1,264 +0,0 @@
-(tof)
- 2003/10/17 Hidetoshi NAGAI
-
-This document discribes about the 'tcltklib' library. Although there
-is the 'tcltk' library (tcltk.rb) under this directory, no description
-in this document (because it is not maintained recently).
-
-==============================================================
-module TclTklib
- : Defines methods to do operations which are independed on
- : Tcl/Tk interpreters
-
- module TclTkLib::EventFlag
- : Defines flags to define taget events on 'do_one_event' methos.
- : When to give, please use bit-operator (e.g. WINDOW | DONT_WAIT).
-
- [constants]
- NONE
- : Is 0. It means "there is no target". But on the real
- : operation, it is same to ALL.
-
- WINDOW
- : 'window' event is processed.
-
- FILE
- : 'file' event is processed.
-
- TIMER
- : 'timer' event is processed.
-
- IDLE
- : 'idle' operation (e.g. 're-draw'; the operations when the
- : other kinds of events doesn't occur) is processed.
-
- ALL
- : All kinds of events are processed.
- : Same to 'WINDOW | FILE | TIMER | IDLE'.
-
- DONT_WAIT
- : Without this flag, 'do_one_event' waits the occurence of
- : a target event. With this flag, doesn't wait and returns
- : false if there is no target event for processing.
-
- [module methods]
- mainloop(check_root = true)
- : Starts the eventloop. If 'check_root' is true, this method
- : doesn't return when a root widget exists.
- : If 'check_root' is false, doen't return by the other
- : reasons than exceptions.
-
- mainloop_watchdog(check_root = true)
- : On the normal eventloop, some kinds of callback operations
- : cause deadlock. To avoid some of such deadlocks, this
- : method starts an eventloop and a watchdog-thread.
-
- do_one_event(flag = TclTkLib::EventFlag::ALL |
- TclTkLib::EventFlag::DONT_WAIT)
- : Do one event for processing. When processed an event,
- : returns true.
- : If NOT set DONT_WAIT flag, this method waits occurrence of
- : a target event.
- : If set DONT_WAIT flag and no event for processing, returns
- : false immediately.
- : If $SAFE >= 4, or $SAFE >= 1 and the flag is tainted,
- : force to set DONT_WAIT flag.
-
- set_eventloop_tick(timer_tick)
- : Define the interval of thread-switching with an integer
- : value of mili-seconds.
- : Default timer_tick is 0. It means that thread-switching
- : is based on the count of processed events.
- : ( see 'set_eventloop_weight' method )
- : However, if the eventloop thread is the only thread,
- : timer_tick cannt be set to 0. If 0, then is set to 100 ms
- : automatically (see NO_THREAD_INTERRUPT_TIME on tcltklib.c).
- : On $SAFE >= 4, cannot call this method.
-
- get_eventloop_tick
- : Get current value of 'timer_tick'
-
- set_no_event_wait(no_event_wait)
- : Define sleeping time of the eventloop when two or more
- : thread are running and there is no event for processing.
- : Default value is 20 (ms).
- : If the eventloop thread is the only thread, this value is
- : invalid.
- : On $SAFE >= 4, cannot call this method.
-
- get_no_event_wait
- : Get current value of 'no_event_wait'.
-
- set_eventloop_weight(loop_max, no_event_tick)
- : Define the weight parameters for the eventloop thread.
- : That is invalid when the eventloop is the only thread.
- : 'loop_max' is the max events for thread-switching.
- : 'no_event_tick' is the increment value of the event count
- : when no event for processing (And then, the eventloop thead
- : sleeps 'no_event_wait' mili-seconds).
- : 'loop_max == 800' and 'no_event_tick == 10' are defalut.
- : On $SAFE >= 4, cannot call this method.
-
- get_eventloop_weight
- : Get current values of 'loop_max' and 'no_event_tick'.
-
- mainloop_abort_on_exception=(bool)
- : Define whether the eventloop stops on exception or not.
- : If true (default value), stops on exception.
- : If false, show a warinig message but ignore the exception.
- : If nil, no warning message and ignore the excepsion.
- : This parameter is sometimes useful when multiple Tk
- : interpreters are working. Because the only one eventloop
- : admins all Tk interpreters, sometimes exception on a
- : interpreter kills the eventloop thread. Even if such
- : situation, when abort_on_exception == false or nil,
- : the eventloop ignores the exception and continue to working.
- : On $SAFE >= 4, cannot call this method.
-
- mainloop_abort_on_exception
- : Get current status of that.
-
- num_of_mainwindows
- : Returns the number of main-windows (root-widget).
- : Because there is only one main-window for one Tk interpreter,
- : the value is same to the number of interpreters which has
- : available Tk functions.
-
-
-class TclTkIp
- [class methods]
- new(ip_name=nil, options='')
- : Generate an instance of TclTkIp class.
- : If 'ip_name' argument is given as a string, it is the name
- : of the Tk interpreter which is shown by 'winfo interps'
- : command.
- : 'options' argument accepts a string which is the command
- : line options of wish; such as '-geometry' or '-use'.
- : The information is used to generate the root widget of the
- : interpreter.
- : ( e.g. TclTkIp.new('FOO', '-geometry 500x200 -use 0x2200009') )
- : If is given nil or falsr for the 'option' argument, generates
- : the Tcl interpreter without Tk library. Then the interpreter
- : doesn't need GUI environment. Therefore, even if a window
- : system doesn't exist or cannot be used, Ruby can control the
- : Tcl interpreter and the extention libraries loaded on the
- : interpreter.
-
- [instance methods]
- create_slave(name, safe=false)
- : Create a slave interpreter.
- : The parent of the interpreter is the receiver of this method.
- : The name of the slave interpreter is given by 'name' argument.
- : The 'safe' argument decides whether the slave interpreter is
- : created as a safe interpreter or not. If true, create a safe
- : interpreter. Default is false. However, if the parent
- : interpreter is a safe interpreter, the created interpreter is
- : a safe interpreter (ignore 'safe' argument value).
- : If $SAFE >= 4, can create a safe interpreter only.
-
- make_safe
- : Make the interpreter to the safe interpreter, and returns
- : self. If fail, raise RuntimeError.
-
- safe?
- : Check whether the interpreter is the safe interpreter.
- : If is the safe interpreter, returns true.
-
- delete
- : Delete the interpreter.
- : The deleted interpreter doesn't accept command and then
- : raise an exception.
-
- deleted?
- : Check whether the interpreter is already deleted.
- : If deleted, returns true.
-
- restart
- : Restart Tk part of the interpreter.
- : Use this when you need Tk functions after destroying the
- : root widget.
- : On $SAFE >= 4, cannot call this method.
-
- _eval(str)
- _invoke(*args)
- : Estimates the arguments as a command on the Tk interpreter.
- : The argument of _eval is a script of Tcl/Tk.
- : Each argument of _invoke is a token of one command line of
- : Tcl/Tk.
- : Because the operation of _invoke doesn't through the
- : command line parser of Tk interpreter, the cost of
- : estimation is smaller than _eval. However, auto_load
- : mechanism of the Tk interpreter doesn't work on _invoke.
- : So _invoke can call only the command which already
- : registered on the interpreter by 'load' command and so on.
- : On _eval command, auto_load mechanism words. So if succeed
- : to _eval and regist the command once, after that, the
- : command can be called by _invoke.
-
- _toUTF8(str, encoding)
- _fromUTF8(str, encoding)
- : Call the function (which is internal function of Tcl/Tk) to
- : convert to/from a UTF8 string.
-
- _thread_vwait(var_name)
- _thread_tkwait(mode, target)
- : 'vwait' or 'tkwait' with thread support.
- : The difference from normal 'vwait' or 'tkwait' command is
- : doing independent wait from the vwait stack when they are
- : called on the other thread than the eventloop thread.
- : In the case of Tcl/Tk's vwait / tkwait, if 2nd vwait /
- : tkwait is called on waiting for 1st vwait / tkwait,
- : returns the order of [2nd]->[1st] regardless of the order
- : of when the wait condition was fulfilled.
- : If _thread_vwait / _thread_tkwait is called on the
- : eventloop thread, there is no difference from vwait /
- : tkwait. But if called on the other thread than the
- : eventloop, stops the thread. And when the wait condition
- : is fulfilled, the thread restarts. The meaning of
- : "independent from the vwait stack" is that the timing of
- : restarting is independent from the waiting status of the
- : other threads. That is, even if the eventloop thread is
- : waiting by vwait and is not fulfilled the condition,
- : _thread_vwait completes the waiting when its waiting
- : condition is fulfilled and the thread which stopped by
- : _thread_vwait can continue the operation.
-
- _return_value
- : Get the last result value on the interpreter.
-
- mainloop
- mainloop_watchdog
- : If on the slave interpreter, never start an eventloop and
- : returns nil.
- : With the exception that, same to the TclTkLib module method
- : with the same name.
-
- do_one_event
- : With the exception that the argument is forced to set
- : DONT_WAIT flag on the slave interpreter, same to
- : TclTkLib#do_one_event.
-
- set_eventloop_tick
- get_eventloop_tick
- set_no_event_wait
- get_no_event_wait
- set_eventloop_weight
- get_eventloop_weight
- mainloop_abort_on_exception
- mainloop_abort_on_exception=
- : With the exception that it is ignored to set value on the
- : slave interpreter, same to the TclTkLib module method with
- : the same name.
-
-class TkCallbackBreak < StandardError
-class TkCallbackContinue < StandardError
- : They are exception classes to break or continue the Tk callback
- : operation.
- : If raise TkCallbackBreak on the callback procedure, Ruby returns
- : 'break' code to Tk interpreter (Then the Tk interpreter will
- : break the operation for the current event).
- : If raise TkCallbackContinue, returns 'continue' code (Then the Tk
- : interpreter will break the operateion for the current bindtag and
- : starts the operation for the next buindtag for the current event).
-
-(eof)
diff --git a/ext/tcltklib/MANUAL.euc b/ext/tcltklib/MANUAL.euc
deleted file mode 100644
index 9f9c77da02..0000000000
--- a/ext/tcltklib/MANUAL.euc
+++ /dev/null
@@ -1,408 +0,0 @@
-(tof)
- 2003/10/17 Hidetoshi NAGAI
-
-Ëܥɥ­¥å¥á¥ó¥È¤Ë¤Ï¸Å¤¤ tcltk ¥é¥¤¥Ö¥é¥ê¡¤tcltklib ¥é¥¤¥Ö¥é¥ê¤ÎÀâÌÀ
-¤¬´Þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¤¬¡¤¤½¤Îµ­½ÒÆâÍÆ¤Ï¸Å¤¤¤â¤Î¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
-
-tcltk ¥é¥¤¥Ö¥é¥ê¡Êtcltk.rb¡Ë¤Ï¸½ºß¤Ç¤Ï¥á¥ó¥Æ¥Ê¥ó¥¹¤¬»ö¼Â¾å¹Ô¤ï¤ì¤Æ
-¤¤¤Ê¤¤¤¿¤á¡¤¸Å¤¤¥É¥­¥å¥á¥ó¥È¤ÎÀâÌÀ¤¬¤½¤Î¤Þ¤ÞÍ­¸ú¤Ç¤¹¡¥¤½¤ì¤ËÂФ·¡¤
-tcltklib ¥é¥¤¥Ö¥é¥ê¤Ë¤Ä¤¤¤Æ¤Ï¡¤¸½ºß¤Î Ruby/Tk¡Êtk.rb °Ê²¼¤Î¥é¥¤¥Ö¥é
-¥ê·²¡Ë¤ò²ÔƯ¤µ¤»¤ë¤¿¤á¤ÎÃæ¿´¤È¤·¤Æ¥á¥ó¥Æ¥Ê¥ó¥¹¤µ¤ì¤Æ¤¤¤ë¤¿¤á¡¤¾¯¡¹
-°ã¤¤¤¬À¸¤¸¤Æ¤¤¤Þ¤¹¡¥
-
-¤½¤³¤Ç¡¤¤Þ¤º¸Å¤¤ÀâÌÀʸ½ñ¤ò¼¨¤·¤¿¸å¡¤¸½ºß¤Î tcltklib ¥é¥¤¥Ö¥é¥ê¤Ë¤Ä
-¤¤¤Æ¤ÎÀâÌÀ¤ò²Ã¤¨¤Þ¤¹¡¥
-
-°Ê²¼¤¬¥é¥¤¥Ö¥é¥ê¤Î¸Å¤¤ÀâÌÀʸ½ñ¤Ç¤¹¡¥
-==============================================================
- MANUAL.euc
- Sep. 19, 1997 Y. Shigehiro
-
-°Ê²¼, ¡Ötcl/tk¡×¤È¤¤¤¦É½µ­¤Ï, tclsh ¤ä wish ¤ò¼Â¸½¤·¤Æ¤¤¤ë, °ìÈ̤Ǥ¤¤¦
-¤È¤³¤í¤Î tcl/tk ¤ò»Ø¤·¤Þ¤¹. ¡Ötcltk ¥é¥¤¥Ö¥é¥ê¡×, ¡Ötcltklib ¥é¥¤¥Ö¥é
-¥ê¡×¤È¤¤¤¦É½µ­¤Ï, Ëܥѥ屡¼¥¸¤Ë´Þ¤Þ¤ì¤ë ruby ÍѤΥ饤¥Ö¥é¥ê¤ò»Ø¤·¤Þ¤¹.
-
-<< tcltk ¥é¥¤¥Ö¥é¥ê >>
-
-tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë¤¿¤á¤Î¹â(Ãæ?)¿å½à¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òÄó
-¶¡¤·¤Þ¤¹.
-
-¤³¤Î¥é¥¤¥Ö¥é¥ê¤Ï ruby ¤«¤é tcl/tk ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë¤¿¤á¤Î¤â¤Î¤Ç, Æâ
-Éô¤Ç tcltklib ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ·¤Æ¤¤¤Þ¤¹.
-
-[ÀâÌÀ]
-
-tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤Ç¤Ï, ¥¦¥£¥¸¥§¥Ã¥È¤Ë²¿¤«»Ø¼¨¤òÁ÷¤ë¤Ë¤Ï, ¥¦¥£¥¸¥§¥Ã
-¥È̾¤Ë³¤¤¤Æ¥Ñ¥é¥á¡¼¥¿¤ò½ñ¤­¤Þ¤¹. ¤·¤¿¤¬¤Ã¤Æ, ¥¦¥£¥¸¥§¥Ã¥È¤¬¥ª¥Ö¥¸¥§¥¯
-¥È¤Ç¤¢¤ê, ¤½¤ì¤ËÂФ·¤Æ¥á¥½¥Ã¥É¤òÁ÷¤Ã¤Æ¤¤¤ë, ¤È¤ß¤Ê¤¹¤³¤È¤¬¤Ç¤­¤Þ¤¹. ¤µ
-¤Æ, tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤Ç¤Ï, ÁȤ߹þ¤ß¥³¥Þ¥ó¥É¤â, Á°½Ò¤Î¥¦¥£¥¸¥§¥Ã¥È¤È
-Ʊ¤¸¤è¤¦¤Ê½ñ¼°¤ÎÌ¿Îá¤Ç¼Â¹Ô¤µ¤ì¤Þ¤¹. ¤¹¤Ê¤ï¤Á, ¥³¥Þ¥ó¥É¤â¥ª¥Ö¥¸¥§¥¯¥È¤Ç
-¤¢¤ë¤È¹Í¤¨¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹.
-
-¤³¤Î¤è¤¦¤Ê¹Í¤¨¤Ë´ð¤Å¤­, tcltk ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï, tcl/tk ¤Î¥³¥Þ¥ó¥É¤ä¥¦¥£
-¥¸¥§¥Ã¥È¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Þ¤¹. ¥ª¥Ö¥¸¥§¥¯¥È¤ËÂФ¹¤ë¥á¥½¥Ã
-¥É¸Æ¤Ó½Ð¤·¤Ï, e() ¥á¥½¥Ã¥É¤Ë¤è¤ê¼Â¹Ô¤µ¤ì¤Þ¤¹. Î㤨¤Ð, tcl/tk ¤Î info
-¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë ruby ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤¬ info ¤È¤¤¤¦Ì¾Á°¤Ç¤¢¤ë¤È¤¹¤ë¤È,
-tcl/tk ¤Î
- info commands
-¤È¤¤¤¦Ì¿Îá¤Ï tcltk ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï
- info.e("commands")
-¤Èµ­½Ò¤µ¤ì¤Þ¤¹. ¤Þ¤¿, ¡Ö.¡×¤È¤¤¤¦¥¦¥£¥¸¥§¥Ã¥È (wish ¼Â¹Ô»þ¤Ë¼«Æ°Åª¤ËÀ¸
-À®¤µ¤ì¤ë¥ë¡¼¥È¥¦¥£¥¸¥§¥Ã¥È) ¤ËÂбþ¤¹¤ë ruby ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤¬ root ¤È¤¤
-¤¦Ì¾Á°¤Ç¤¢¤ë¤È¤¹¤ë¤È,
- . configure -height 300 -width 300
-¤È¤¤¤¦ tcl/tk ¤ÎÌ¿Îá¤Ï
- root.e("configure -height 300 -width 300")
-¤Èµ­½Ò¤µ¤ì¤Þ¤¹. ¤³¤Î¤è¤¦¤Êµ­½Ò¤Ï, ¸«¤¿¤á¤Ë¤ÏÈþ¤·¤¯¤¢¤ê¤Þ¤»¤ó¤¬, ¤½¤·¤Æ,
-¥¹¥¯¥ê¥×¥È¤òÆÉ¤à¿Í¤Ë¤Ï¸«¤Å¤é¤¤¤«¤âÃΤì¤Þ¤»¤ó¤¬, ¼ÂºÝ¤Ë¥¹¥¯¥ê¥×¥È¤ò½ñ¤¤
-¤Æ¤ß¤ë¤ÈͽÁÛ³°¤Ë¼ê·Ú¤Ç¤¹.
-
-[»ÈÍÑË¡]
-
-1. ¥é¥¤¥Ö¥é¥ê¤òÆÉ¤ß¹þ¤à.
- require "tcltk"
-
-2. tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤òÀ¸À®¤¹¤ë.
- ip = TclTkInterpreter.new()
-
-3. tcl/tk ¤Î¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÊÑ¿ô¤ËÂåÆþ¤·¤Æ¤ª¤¯.
- # ¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤¬Æþ¤Ã¤¿ Hash ¤ò¼è¤ê½Ð¤¹.
- c = ip.commands()
- # »È¤¤¤¿¤¤¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò¸ÄÊ̤ÎÊÑ¿ô¤ËÂåÆþ¤¹¤ë.
- bind, button, info, wm = c.indexes("bind", "button", "info", "wm")
-
-4. ɬÍפʽèÍý¤ò¹Ô¤¦.
- ¾Ü¤·¤¯¤Ï, ¥µ¥ó¥×¥ë¤ò»²¾È¤Î¤³¤È.
-
-5. ½àÈ÷¤¬¤Ç¤­¤¿¤é, ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ËÆþ¤ë.
- TclTk.mainloop()
-
-(( °Ê²¼, ¥â¥¸¥å¡¼¥ë, ¥¯¥é¥¹Åù¤ÎÀâÌÀ¤ò½ñ¤¯Í½Äê.))
-
-
-
-<< tcltklib ¥é¥¤¥Ö¥é¥ê >>
-
-tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë¤¿¤á¤ÎÄã¿å½à¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òÄ󶡤·¤Þ
-¤¹.
-
-¥³¥ó¥Ñ¥¤¥ë/¼Â¹Ô¤Ë¤Ï, tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤¬É¬ÍפǤ¹.
-
-[ÀâÌÀ]
-
-¤³¤Î¥é¥¤¥Ö¥é¥ê¤òÍѤ¤¤ë¤È, ruby ¤«¤é tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤǤ­¤Þ
-¤¹. ¶ñÂÎŪ¤Ë¤Ï, ruby ¥¤¥ó¥¿¥×¥ê¥¿¤«¤é tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤ò¸Æ¤Ó½Ð¤¹¤³
-¤È¤¬¤Ç¤­¤Þ¤¹. ¤µ¤é¤Ë, ¤½¤Î(ruby ¥¤¥ó¥¿¥×¥ê¥¿¤«¤é¸Æ¤Ó½Ð¤·¤¿) tcl/tk ¥¤
-¥ó¥¿¥×¥ê¥¿¤«¤é, µÕ¤Ë ruby ¥¤¥ó¥¿¥×¥ê¥¿¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ¤¹.
-
-[»ÈÍÑË¡]
-
-require "tcltklib" ¤¹¤ë¤È, °Ê²¼¤Î¥â¥¸¥å¡¼¥ë, ¥¯¥é¥¹¤¬ÍøÍѲÄǽ¤Ç¤¹.
-
-¥â¥¸¥å¡¼¥ë TclTkLib
- tcl/tk ¥é¥¤¥Ö¥é¥ê¤ò¸Æ¤Ó½Ð¤¹¥á¥½¥Ã¥É¤ò½¸¤á¤¿¥â¥¸¥å¡¼¥ë¤Ç¤¹. ¤¿¤À¤·,
- tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿´Ø·¸¤Î¥á¥½¥Ã¥É¤Ï¥¯¥é¥¹ TclTkIp ¤Ë¤¢¤ê¤Þ¤¹.
-
- ¥â¥¸¥å¡¼¥ë¥á¥½¥Ã¥É mainloop()
- Tk_MainLoop ¤ò¼Â¹Ô¤·¤Þ¤¹. Á´¤Æ¤Î tk ¤Î¥¦¥¤¥ó¥É¥¦¤¬Ìµ¤¯¤Ê¤ë¤È½ªÎ»
- ¤·¤Þ¤¹(Î㤨¤Ð, tcl/tk ¤Ç½ñ¤¯¤È¤³¤í¤Î "destroy ." ¤ò¤·¤¿¾ì¹çÅù).
- °ú¿ô: ̵¤·
- Ìá¤êÃÍ: nil
-
-¥¯¥é¥¹ TclTkIp
- ¥¤¥ó¥¹¥¿¥ó¥¹¤¬ tcl/tk ¤Î¥¤¥ó¥¿¥×¥ê¥¿¤ËÂбþ¤·¤Þ¤¹. tcl/tk ¤Î¥é¥¤¥Ö
- ¥é¥ê¤Î»ÅÍÍÄ̤ê, ¥¤¥ó¥¹¥¿¥ó¥¹¤òÊ£¿ô¸ÄÀ¸À®¤·¤Æ¤âÀµ¤·¤¯Æ°ºî¤·¤Þ¤¹(¤½
- ¤ó¤Ê¤³¤È¤ò¤¹¤ëɬÍפϤ¢¤Þ¤ê̵¤¤¤Ï¤º¤Ç¤¹¤¬). ¥¤¥ó¥¿¥×¥ê¥¿¤Ï wish ¤Î
- tcl/tk ¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤­¤Þ¤¹. ¤µ¤é¤Ë, °Ê²¼¤Î¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤­¤Þ
- ¤¹.
- ¥³¥Þ¥ó¥É ruby
- °ú¿ô¤ò ruby ¤Ç¼Â¹Ô¤·¤Þ¤¹(ruby_eval_string ¤ò¼Â¹Ô¤·¤Þ¤¹). °ú¿ô
- ¤Ï 1 ¤Ä¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó. Ìá¤êÃÍ¤Ï ruby ¤Î¼Â¹Ô·ë²Ì¤Ç¤¹.
- ruby ¤Î¼Â¹Ô·ë²Ì¤Ï nil ¤« String ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó.
-
- ¥¯¥é¥¹¥á¥½¥Ã¥É new()
- TclTkIp ¥¯¥é¥¹¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤·¤Þ¤¹
- °ú¿ô: ̵¤·
- Ìá¤êÃÍ (TclTkIp): À¸À®¤µ¤ì¤¿¥¤¥ó¥¹¥¿¥ó¥¹
-
- ¥á¥½¥Ã¥É _eval(script)
- ¥¤¥ó¥¿¥×¥ê¥¿¤Ç script ¤òɾ²Á¤·¤Þ¤¹(Tcl_Eval ¤ò¼Â¹Ô¤·¤Þ¤¹). Á°½Ò
- ¤Î¤è¤¦¤Ë, ruby ¥³¥Þ¥ó¥É¤Ë¤è¤ê script Æâ¤«¤é ruby ¥¹¥¯¥ê¥×¥È¤ò¼Â
- ¹Ô¤Ç¤­¤Þ¤¹.
- °ú¿ô: script (String) - ¥¤¥ó¥¿¥×¥ê¥¿¤Çɾ²Á¤¹¤ë¥¹¥¯¥ê¥×¥Èʸ»úÎó
- Ìá¤êÃÍ (String): ɾ²Á·ë²Ì ((Tcl_Interp *)->result)
-
- ¥á¥½¥Ã¥É _return_value()
- ľÁ°¤Î Tcl_Eval ¤ÎÌá¤êÃͤòÊÖ¤·¤Þ¤¹. 0(TCL_OK) ¤ÇÀµ¾ï½ªÎ»¤Ç¤¹.
- °ú¿ô: ̵¤·
- Ìá¤êÃÍ (Fixnum): ľÁ°¤Î Tcl_Eval() ¤¬ÊÖ¤·¤¿ÃÍ.
-
-==============================================================
-
-°Ê²¼¤¬Ëܥɥ­¥å¥á¥ó¥ÈºîÀ®»þÅÀ¤Ç¤Î tcltklib ¥é¥¤¥Ö¥é¥ê¤ÎÀâÌÀ¤Ç¤¹¡¥
-==============================================================
-¥â¥¸¥å¡¼¥ë TclTkLib
- : ¸Ä¡¹¤Î Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ë°Í¸¤·¤Ê¤¤½èÍý ( == ¥¤¥Ù¥ó¥È¥ë¡¼
- : ¥×¤Ë´Ø¤¹¤ë½èÍý ) ¤ò¸Æ¤Ó½Ð¤¹¥á¥½¥Ã¥É¤òÄêµÁ¤·¤¿¥â¥¸¥å¡¼¥ë¡¥
-
- ¥â¥¸¥å¡¼¥ë TclTkLib::EventFlag
- : do_one_event ¤ò¸Æ¤Ó½Ð¤¹ºÝ¤Î½èÍýÂоݥ¤¥Ù¥ó¥È¤ò»ØÄꤹ¤ë¤¿¤á¤Î
- : ¥Õ¥é¥° ( WINDOW|DONT_WAIT ¤È¤¤¤¦¤è¤¦¤Ë¥Ó¥Ã¥È±é»»»Ò¤ÇÏ¢·ë¤·¤Æ
- : »ØÄê ) ¤òÄê¿ô¤È¤·¤ÆÄêµÁ¤·¤¿¥â¥¸¥å¡¼¥ë¡¥°Ê²¼¤ÎÄê¿ô¤¬´Þ¤Þ¤ì¤ë¡¥
-
- Äê¿ô NONE
- : ÃÍ¤Ï 0 ¤Ç¡¤ÃͤȤ·¤Æ¤Ï¤¤¤«¤Ê¤ë¼ïÎà¤Î¥¤¥Ù¥ó¥È¤â»ØÄꤷ¤Æ¤¤¤Ê¤¤
- : ¤³¤È¤Ë¤Ê¤ë¤¬¡¤¼ÂºÝ¤Î½èÍý¾å¤Ï ALL ¤ÈƱ¤¸¤È¤·¤Æ°·¤ï¤ì¤ë¡¥
-
- Äê¿ô WINDOW
- : window ¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
-
- Äê¿ô FILE
- : file ¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
-
- Äê¿ô TIMER
- : timer ¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
-
- Äê¿ô IDLE
- : ¥¢¥¤¥É¥ë¥ë¡¼¥×½èÍý ( ºÆÉÁ²è¤Ê¤É¡¤Â¾¤Î¼ïÎà¤Î¥¤¥Ù¥ó¥È¤¬È¯À¸
- : ¤·¤Æ¤¤¤Ê¤¤¤È¤­¤Ë¹Ô¤ï¤ì¤ë½èÍý ) ¤ò½èÍýÂоݤȤ¹¤ë
-
- Äê¿ô ALL
- : ¤¹¤Ù¤Æ¤Î¼ïÎà¤Î¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
- : WINDOW|FILE|TIMER|IDLE ¤ÈƱ¤¸
-
- Äê¿ô DONT_WAIT
- : ½èÍýÂоݥ¤¥Ù¥ó¥È¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¡¤¥¤¥Ù¥ó¥ÈȯÀ¸¤òÂÔ¤¿¤º
- : ¤Ë do_one_event ¤ò½ªÎ» ( false ¤òÊÖ¤¹ ) ¤¹¤ë
-
- ¥â¥¸¥å¡¼¥ë¥á¥½¥Ã¥É
- mainloop(check_root = true)
- : ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òµ¯Æ°¤¹¤ë¡¥check_root ¤¬ true ¤Ç¤¢¤ì¤Ð¡¤
- : root widget ¤¬Â¸ºß¤¹¤ë¸Â¤ê¡¤¤³¤Î¥á¥½¥Ã¥É¤Ï½ªÎ»¤·¤Ê¤¤¡¥
- : check_root ¤¬ false ¤Î¾ì¹ç¤Ï¡¤root widget ¤¬¾ÃÌǤ·¤Æ¤â
- : ¤³¤Î¥á¥½¥Ã¥É¤Ï½ªÎ»¤·¤Ê¤¤ ( root widget ¤¬¾ÃÌǤ·¤Æ¤â¡¤
- : WINDOW °Ê³°¤Î¥¤¥Ù¥ó¥È¤ÏȯÀ¸¤·¤¦¤ë¤¿¤á )¡¥½ªÎ»¤Ë¤Ï¡¤³°Éô
- : ¤«¤é¤ÎƯ¤­³Ý¤± ( ¥¹¥ì¥Ã¥É¤ò³èÍѤ¹¤ë¤Ê¤É ) ¤¬É¬Íס¥
-
- mainloop_watchdog(check_root = true)
- : Ä̾ï¤Î¥¤¥Ù¥ó¥È¥ë¡¼¥×¤Ç¤Ï¡¤¥¤¥Ù¥ó¥È½èÍý¤ÎÆâÍÆ¤Ë¤è¤Ã¤Æ¤Ï
- : ¥Ç¥Ã¥É¥í¥Ã¥¯¤ò°ú¤­µ¯¤³¤¹²ÄǽÀ­¤¬¤¢¤ë (Î㤨¤Ð¥¤¥Ù¥ó¥È¤Ë
- : ÂФ¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯½èÍýÃæ¤Ç widget Áàºî¤ò¤·¡¤¤½¤Î½ªÎ»¤ò
- : ÂԤĤʤÉ)¡¥¤³¤Î¥á¥½¥Ã¥É¤Ï¡¤¤½¤¦¤·¤¿¥Ç¥Ã¥É¥í¥Ã¥¯¤ò²óÈò¤¹
- : ¤ë¤¿¤á¤Î´Æ»ë¥¹¥ì¥Ã¥ÉÉÕ¤­¤Ç¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òµ¯Æ°¤¹¤ë
- : ( ´Æ»ë¥¹¥ì¥Ã¥É¤òÀ¸À®¤·¤¿¸å¤Ë¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¼Â¹Ô¤¹¤ë )¡¥
- : °ú¿ô¤Î°ÕÌ£¤Ï mainloop ¤ÈƱ¤¸¤Ç¤¢¤ë¡¥
-
- do_one_event(flag = TclTkLib::EventFlag::ALL |
- TclTkLib::EventFlag::DONT_WAIT)
- : ½èÍýÂÔ¤Á¤Î¥¤¥Ù¥ó¥È 1 ¸Ä¤ò¼Â¹Ô¤¹¤ë¡¥
- : ¥¤¥Ù¥ó¥È¤ò½èÍý¤·¤¿¾ì¹ç¤Ï true ¤òÊÖ¤¹¡¥
- : ¥Õ¥é¥°¤Ç DONT_WAIT ¤ò»ØÄꤷ¤Æ¤¤¤Ê¤¤¾ì¹ç¡¤¥Õ¥é¥°¤Ç½èÍýÂÐ
- : ¾Ý¤È¤Ê¤Ã¤Æ¤¤¤ë¼ïÎà¤Î¥¤¥Ù¥ó¥È¤¬È¯À¸¤¹¤ë¤Þ¤ÇÂÔ¤Á³¤±¤ë¡¥
- : DONT_WAIT ¤ò»ØÄꤷ¤Æ¤¤¤¿¾ì¹ç¡¤½èÍýÂоݥ¤¥Ù¥ó¥È¤¬¤Ê¤¯¤Æ¤â
- : ¤¹¤°¤Ë½ªÎ»¤· false ¤òÊÖ¤¹¡¥
- : $SAFE >= 4 ¤«¡¤$SAFE >= 1 ¤«¤Ä flag ¤¬±øÀ÷¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð
- : flag ¤Ë¤Ï DONT_WAIT ¤¬¶¯À©Åª¤ËÉÕ¤±¤é¤ì¤ë¡¥
-
- set_eventloop_tick(timer_tick)
- : ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ÈƱ»þ¤ËÊÌ¥¹¥ì¥Ã¥É¤¬²ÔƯ¤·¤Æ¤¤¤ë¾ì¹ç¤Ë¡¤»þ
- : ´Ö¤Ë´ð¤Å¤¤¤¿¶¯À©Åª¤Ê¥¹¥ì¥Ã¥É¥¹¥¤¥Ã¥Á¥ó¥°¤ò¤É¤ÎÄøÅÙ¤ÎÉÑÅÙ
- : ( »þ´Ö´Ö³Ö ) ¤ÇȯÀ¸¤µ¤»¤ë¤«¤ò¥ß¥êÉÃñ°Ì¤ÎÀ°¿ôÃͤǻØÄꤹ¤ë¡¥
- : 0 ¤ò»ØÄꤹ¤ë¤È¡¤¤³¤Î¶¯À©Åª¤Ê¥¹¥¤¥Ã¥Á¥ó¥°¤Ï¹Ô¤ï¤ì¤Ê¤¤¡¥
- : ɸ½à¤Ç¤Ï 0 ¤ËÀßÄꤵ¤ì¤Æ¤ª¤ê¡¤¥¤¥Ù¥ó¥È½èÍý¿ô¤Ë´ð¤Å¤¯¥¹¥¤¥Ã
- : ¥Á¥ó¥°¤À¤±¤¬¹Ô¤ï¤ì¤ë ( see set_eventloop_weight )¡¥
- : ¤¿¤À¤·¡¤²ÔƯ¤·¤Æ¤¤¤ë¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤À¤±¤Î¾ì¹ç¡¤
- : timer_tick ¤ò 0 ¤ËÀßÄꤹ¤ë¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡¥¤â¤·ÀßÄꤵ¤ì¤Æ
- : ¤¤¤¿¤é¡¤100 ms ( see NO_THREAD_INTERRUPT_TIME ) ¤Ë¼«Æ°Àß
- : Äꤵ¤ì¤ë¡¥
- : ¾ÜºÙ¤ÊÀâÌÀ¤Ïά¤¹¤¬¡¤¤³¤ì¤Ï CPU ¥Ñ¥ï¡¼¤òÀáÌ󤷤ĤİÂÁ´¤Ç
- : °ÂÄꤷ¤¿Æ°ºî¤ò¼Â¸½¤¹¤ë¤¿¤á¤Ë¼ÂÁõ¤·¤¿»ÅÍͤǤ¢¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- get_eventloop_tick
- : timer_tick ¤Î¸½ºßÃͤòÊÖ¤¹¡¥
-
- set_no_event_wait(no_event_wait)
- : Ê£¿ô¤Î¥¹¥ì¥Ã¥É¤¬²ÔƯ¤·¤Æ¤¤¤ë¾ì¹ç¤Ç¡¤½èÍýÂÔ¤Á¥¤¥Ù¥ó¥È¤¬Á´
- : ¤¯Â¸ºß¤·¤Ê¤«¤Ã¤¿ºÝ¤Ë sleep ¾õÂÖ¤ËÆþ¤ë»þ´ÖŤò»ØÄꤹ¤ë¡¥
- : ²ÔƯ¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤À¤±¤Î¾ì¹ç¤Ë¤Ï°ÕÌ£¤ò¤Ê¤µ¤Ê¤¤¡¥
- : ¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï 20 (ms)
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- get_no_event_wait
- : no_event_wait ¤Î¸½ºßÃͤòÊÖ¤¹¡¥
-
- set_eventloop_weight(loop_max, no_event_tick)
- : Ê£¿ô¤Î¥¹¥ì¥Ã¥É¤¬²ÔƯ¤·¤Æ¤¤¤ëºÝ¤Ë Ruby/Tk ¤Î¥¤¥Ù¥ó¥È¥ë¡¼
- : ¥×¤Ë³ä¤êÅö¤Æ¤ëÈæ½Å¤òÄê¤á¤ë¤¿¤á¤Î¥Ñ¥é¥á¡¼¥¿¤òÀßÄꤹ¤ë¡¥
- : ²ÔƯ¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤À¤±¤Î¾ì¹ç¤Ë¤Ï°ÕÌ£¤ò¤Ê¤µ¤Ê¤¤¡¥
- : °ìÅ٤Υ¹¥ì¥Ã¥ÉÀÚ¤êÂØ¤¨¤Î´Ö¤Ë½èÍý¤¹¤ë¥¤¥Ù¥ó¥È¤ÎºÇÂç¿ô¤È¡¤
- : ½èÍýÂÔ¤Á¤Î¥¤¥Ù¥ó¥È¤¬Â¸ºß¤·¤Ê¤¤ºÝ¤Î²Ã»»¿ô¤È¤òÀßÄꤹ¤ë¡¥
- : ½èÍýÂÔ¤Á¥¤¥Ù¥ó¥È¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ï no_event_wait ( see
- : set_no_event_wait ) ¤À¤±¤Î´Ö sleep ¾õÂÖ¤ËÆþ¤ë¡¥
- : ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¤½¤ì¤¾¤ì 800 ²ó¤È 10 ²ó¡¤¤Ä¤Þ¤ê¡¤800 ¸Ä¤Î¥¤
- : ¥Ù¥ó¥È (¥¢¥¤¥É¥ë¥¤¥Ù¥ó¥È¤ò´Þ¤à) ¤ò½èÍý¤¹¤ë¤È¤«¡¤¥¤¥Ù¥ó¥È
- : ¤¬Á´¤¯È¯À¸¤·¤Ê¤¤¤Þ¤Þ¤Ë 80 ²ó¤Î½èÍýÂÔ¤Á¥¤¥Ù¥ó¥È¸¡ºº¤¬´°Î»
- : ¤¹¤ë¤È¤«¤Ç¥«¥¦¥ó¥È¤¬ 800 °Ê¾å¤Ë¤Ê¤ë¤È¥¹¥ì¥Ã¥É¥¹¥¤¥Ã¥Á¥ó¥°
- : ¤¬È¯À¸¤¹¤ë¤³¤È¤Ë¤Ê¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- get_eventloop_weight
- : ¸½ºß¤Î loop_max ¤È no_event_tick ¤È¤ÎÃͤòÊÖ¤¹¡¥
- : ( see set_eventloop_wait )
-
- mainloop_abort_on_exception=(bool)
- : Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤ÇÎã³°¤òȯÀ¸¤·¤¿ºÝ¤Ë¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò
- : ¥¨¥é¡¼Ää»ß¤µ¤»¤ë¤«¤É¤¦¤«¤ò»ØÄꤹ¤ë¡¥true ¤ò»ØÄꤷ¤¿¾ì¹ç¤Ï
- : ¥¨¥é¡¼Ää»ß¤¹¤ë¤¬¡¤false ¤Î¾ì¹ç¤ÏÎã³°¤ò̵»ë¤·¤Æ¥¤¥Ù¥ó¥È¥ë¡¼
- : ¥×¤ò·Ñ³¤¹¤ë¡¥¤µ¤é¤Ë nil ¤Î¾ì¹ç¤Ï·Ù¹ð¥â¡¼¥É¤Ç¤Ê¤¤¸Â¤ê¤Ï¥¨
- : ¥é¡¼¥á¥Ã¥»¡¼¥¸¤Î½ÐÎϤ¹¤é¾Êά¤·¤Æ¡¤Îã³°¤ò̵»ë¤¹¤ë¡¥
- : ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï true ¤ËÀßÄꤵ¤ì¤Æ¤¤¤ë¡¥
- : £±¸Ä¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤À¤±¤ò»È¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¥¨¥é¡¼»þ¤Ë¤½¤Î
- : ¤Þ¤ÞÄä»ß¤·¤Æ¤âÄ̾ï¤ÏÌäÂê¤Ê¤¤¤¬¡¤Ê£¿ô¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬Æ±»þ
- : ¤Ëưºî¤·¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤é¤ò´ÉÍý¤¹¤ë¥¤¥Ù¥ó¥È¥ë¡¼¥×¤Ï£±
- : ¸Ä¤À¤±¤Ç¤¢¤ë¤¿¤á¡¤¤¤¤º¤ì¤«¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î¥¨¥é¡¼¤¬¸¶°ø¤Ç¡¤
- : ¾¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î½èÍý·Ñ³¤¬ÉÔ²Äǽ¤Ë¤Ê¤ë¤³¤È¤¬¤¢¤ë¡¥¤½¤Î
- : ¤è¤¦¤Ê¾ì¹ç¤Ç¤â¥¨¥é¡¼¤ò̵»ë¤·¤Æ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤¬²ÔƯ¤ò³¤±¤ë
- : ¤³¤È¤Ç¡¤Â¾¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬Àµ¾ï¤Ëưºî¤·Â³¤±¤ë¤³¤È¤¬¤Ç¤­¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- mainloop_abort_on_exception
- : Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤ÇÎã³°¤òȯÀ¸¤·¤¿ºÝ¤Ë¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¥¨
- : ¥é¡¼Ää»ß¤µ¤»¤ë¤«¤É¤¦¤«¤ÎÀßÄê¾õÂÖ¤ò true/false ¤ÇÆÀ¤ë¡¥
-
- num_of_mainwindows
- : ¸½ºß¤Î¥á¥¤¥ó¥¦¥£¥ó¥É¥¦ (¥ë¡¼¥È¥¦¥£¥¸¥§¥Ã¥È) ¤Î¿ô¤òÊÖ¤¹¡¥
- : ¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤Ï°ì¤Ä¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ËÉÕ¤­ºÇÂç°ì¤Ä¤Ç¤¢¤ë
- : ¤Î¤Ç¡¤¤³¤ÎÃͤϸ½ºß Tk ¤Îµ¡Ç½¤¬Í­¸ú¤Ç¤¢¤ë¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ÎÁí
- : ¿ô¤ËÅù¤·¤¤¡¥
-
-
-¥¯¥é¥¹ TclTkIp
- ¥¯¥é¥¹¥á¥½¥Ã¥É
- new(ip_name=nil, options='')
- : TclTkIp ¥¯¥é¥¹¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤¹¤ë¡¥
- : ip_name ¤Ëʸ»úÎó¤òÍ¿¤¨¤¿¾ì¹ç¤Ï¡¤¤½¤ì¤¬ winfo interps ¤Ê¤É¤Ç
- : ɽ¼¨¤µ¤ì¤ë̾Á°¤Ë¤Ê¤ë¡¥
- : options ¤Ë¤Ï¡¤-geometry ¤ä -use ¤Ê¤É¡¤wish ¤Î¥³¥Þ¥ó¥É¥é¥¤¥ó
- : °ú¿ô¤È¤·¤ÆÍ¿¤¨¤ë¥ª¥×¥·¥ç¥ó¤ÈƱÍͤξðÊó¤òʸ»úÎó¤È¤·¤ÆÍ¿¤¨¤ë¡¥
- : Í¿¤¨¤é¤ì¤¿¾ðÊó¤Ï¡¤root widget À¸À®¤ÎºÝ¤ËÍѤ¤¤é¤ì¤ë¡¥
- : ( e.g. TclTkIp.new('FOO', '-geometry 500x200 -use 0x2200009') )
- : ¤â¤· options ¤Ë´º¤¨¤Æ nil ¤Þ¤¿¤Ï false ¤òÍ¿¤¨¤¿¾ì¹ç¡¤Tk ¥é¥¤
- : ¥Ö¥é¥ê¤¬Æ³Æþ¤µ¤ì¤Æ¤¤¤Ê¤¤ (¤Ä¤Þ¤ê¤Ï Tcl ¤Î¤ß¤Î) ¥¤¥ó¥¿¡¼¥×¥ê
- : ¥¿¤òÀ¸À®¤¹¤ë¡¥¤³¤Î¾ì¹ç¤Ï GUI ´Ä¶­¤ÏɬÍפʤ¤¤¿¤á¡¤¥¦¥¤¥ó¥É¥¦
- : ¥·¥¹¥Æ¥à¤¬Â¸ºß¤·¤Ê¤¤¡¤¤Þ¤¿¤Ï»ÈÍѤǤ­¤Ê¤¤´Ä¶­¤Ç¤â Tcl ¥¤¥ó¥¿¡¼
- : ¥×¥ê¥¿¤òÀ¸À®¤·¡¤Tcl ¤ä¤½¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò³èÍѤ¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡¥
-
- ¥¤¥ó¥¹¥¿¥ó¥¹¥á¥½¥Ã¥É
- create_slave(name, safe=false)
- : ¥ì¥·¡¼¥Ð¤ò¿Æ¤È¤¹¤ë name ¤È¤¤¤¦Ì¾Á°¤Î¥¹¥ì¡¼¥Ö¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò
- : À¸À®¤¹¤ë¡¥
- : safe ¤Ë¤ÏÀ¸À®¤¹¤ë¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤È¤¹¤ë
- : ¤«¤ò»ØÄꤹ¤ë¡¥¥Ç¥Õ¥©¥ë¥È¤Ï false ¤È¤¤¤¦¤³¤È¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¬¡¤
- : ¤¿¤È¤¨ÌÀ³Î¤Ë false ¤ò»ØÄꤷ¤Æ¤¤¤¿¤È¤·¤Æ¤â¡¤¿Æ¤È¤Ê¤ë¥¤¥ó¥¿¡¼
- : ¥×¥ê¥¿¤¬ safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ç¤¢¤ì¤Ð¡¤¤½¤ÎÀßÄê¤ò°ú¤­·Ñ¤¤¤Ç
- : safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤È¤·¤ÆÀ¸À®¤µ¤ì¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¡¤safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿°Ê³°¤ÎÀ¸À®¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- make_safe
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ËÊѹ¹¤¹¤ë¡¥
- : Ìá¤êÃͤϥ쥷¡¼¥Ð¤Ç¤¢¤ë¥¤¥ó¥¿¡¼¥×¥ê¥¿¼«¿È¤Ç¤¢¤ë¡¥
- : ¼ºÇÔ¤·¤¿¾ì¹ç¤Ï RuntimeError ¤ÎÎã³°¤òȯÀ¸¤¹¤ë¡¥
-
- safe?
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ç¤¢¤ë¤«¤òÄ´¤Ù¤ë¡¥
- : safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ç¤¢¤ì¤Ð true ¤òÊÖ¤¹¡¥
-
- delete
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò delete ¤¹¤ë¡¥
- : delete ¤µ¤ì¤¿¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¡¤°Ê¸å°ìÀÚ¤ÎÁàºî¤¬¤Ç¤­¤Ê¤¯¤Ê¤ê¡¤
- : ¥³¥Þ¥ó¥É¤òÁ÷¤Ã¤Æ¤âÎã³°¤òȯÀ¸¤¹¤ë¤è¤¦¤Ë¤Ê¤ë¡¥
-
- deleted?
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬¤¹¤Ç¤Ë delete ¤µ¤ì¤Æ¤¤¤ë¤«¤òÄ´¤Ù¤ë¡¥
- : delete ºÑ¤ß¤Ç¥³¥Þ¥ó¥É¤ò¼õ¤±ÉÕ¤±¤Ê¤¤¾õÂ֤ˤʤäƤ¤¤ë¤Ê¤é¤Ð
- : true ¤òÊÖ¤¹¡¥
-
- restart
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î Tk Éôʬ¤Î½é´ü²½¡¤ºÆµ¯Æ°¤ò¹Ô¤¦¡¥
- : °ìö root widget ¤òÇ˲õ¤·¤¿¸å¤ËºÆÅÙ Tk ¤Îµ¡Ç½¤¬É¬ÍפÈ
- : ¤Ê¤Ã¤¿¾ì¹ç¤ËÍѤ¤¤ë¡¥
- : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
-
- _eval(str)
- _invoke(*args)
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤Çɾ²Á¤ò¹Ô¤¦¡¥
- : _eval ¤Ïɾ²Á¥¹¥¯¥ê¥×¥È¤¬°ì¤Ä¤Îʸ»úÎó¤Ç¤¢¤ë¤³¤È¤ËÂФ·¡¤
- : _invoke ¤Ïɾ²Á¥¹¥¯¥ê¥×¥È¤Î token ¤´¤È¤Ë°ì¤Ä¤Î°ú¿ô¤È¤Ê
- : ¤ë¤è¤¦¤ËÍ¿¤¨¤ë¡¥
- : _invoke ¤ÎÊý¤Ï Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î»ú¶ç²òÀÏ´ï¤òÍѤ¤
- : ¤Ê¤¤¤¿¤á¡¤É¾²Á¤ÎÉé²Ù¤¬¤è¤ê¾¯¤Ê¤¯¤Æ¤¹¤à¡¥¤¿¤À¤·¡¤¤½¤ÎÂå
- : ¤ï¤ê¤Ë auto_load ¤Î¤è¤¦¤Êµ¡¹½¤ÏƯ¤«¤º¡¤load Åù¤Ë¤è¤Ã¤Æ
- : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤Ë´û¤ËÅÐÏ¿ºÑ¤ß¤Î¥³¥Þ¥ó¥É¤·¤«¸Æ
- : ¤Ó½Ð¤¹¤³¤È¤¬¤Ç¤­¤Ê¤¤¡¥
- : _eval ¤Ç¤Ï auto_load µ¡¹½¤¬Æ¯¤¯¤¿¤á¡¤°ìÅÙ _eval ¤ò¼Â¹Ô
- : ¤·¤ÆÅÐÏ¿¤ËÀ®¸ù¤·¤µ¤¨¤¹¤ì¤Ð¡¤°Ê¹ß¤Ï _invoke ¤Ç¤âÍøÍѤÇ
- : ¤­¤ë¤è¤¦¤Ë¤Ê¤ë¡¥
-
- _toUTF8(str, encoding)
- _fromUTF8(str, encoding)
- : Tcl/Tk ¤¬Æâ¢¤·¤Æ¤¤¤ë UTF8 ÊÑ´¹½èÍý¤ò¸Æ¤Ó½Ð¤¹¡¥
-
- _thread_vwait(var_name)
- _thread_tkwait(mode, target)
- : ¥¹¥ì¥Ã¥ÉÂбþ¤Î vwait ¤¢¤ë¤¤¤Ï tkwait ÁêÅö¤Î¥á¥½¥Ã¥É¡¥
- : Ä̾ï¤Î vwait ¤¢¤ë¤¤¤Ï tkwait ¥³¥Þ¥ó¥É¤È°Û¤Ê¤ë¤Î¤Ï¡¤¥¤¥Ù¥ó
- : ¥È¥ë¡¼¥×¤È¤Ï°Û¤Ê¤ë¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ó½Ð¤·¤¿¾ì¹ç¤Ë vwait Åù¤Î
- : ¥¹¥¿¥Ã¥¯¤È¤ÏÆÈΩ¤Ë¾ò·ï¤ÎÀ®Î©ÂÔ¤Á¤¬¤Ê¤µ¤ì¤ë¤³¤È¤Ç¤¢¤ë¡¥
- : Ä̾ï¤Î vwait / tkwait ¤Ç¤Ï¡¤vwait / tkwait (1) ¤ÎÂÔ¤Á¤ÎÅÓ
- : Ãæ¤Ç¤µ¤é¤Ë vwait / tkwait (2) ¤¬¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤ÂÔ¤Á¤ÎÂоÝ
- : ¤È¤Ê¤Ã¤Æ¤¤¤ë¾ò·ï¤ÎÀ®Î©½ç½ø¤¬¤É¤¦¤¢¤ì¡¤(2)->(1) ¤Î½ç¤ÇÂÔ¤Á
- : ¤ò½ªÎ»¤·¤ÆÌá¤Ã¤Æ¤¯¤ë¡¥
- : _thread_vwait / _thread_tkwait ¤Ï¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×¤Î¥¹¥ì¥Ã
- : ¥É¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤ÏÄ̾ï¤Î vwait / tkwait ¤ÈƱÍÍ¤ËÆ°ºî¤¹¤ë
- : ¤¬¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×°Ê³°¤Î¥¹¥ì¥Ã¥É¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¤Ï¤½¤Î¥¹
- : ¥ì¥Ã¥É¤òÄä»ß¤µ¤»¤ÆÂÔ¤Á¤ËÆþ¤ê¡¤¾ò·ï¤¬À®Î©¤·¤¿»þ¤Ë¥¹¥ì¥Ã¥É
- : ¤Î¼Â¹Ô¤òºÆ³«¤¹¤ë¡¥¡Övwait Åù¤ÎÂÔ¤Á¥¹¥¿¥Ã¥¯¤È¤ÏÆÈΩ¡×¤È¤¤
- : ¤¦°ÕÌ£¤Ï¡¤¤³¤ÎºÆ³«¤Î¥¿¥¤¥ß¥ó¥°¤¬Â¾¤Î¥¹¥ì¥Ã¥É¤Ç¤ÎÂÔ¤Á¾õ¶·
- : ¤È¤Ï̵´Ø·¸¤È¤¤¤¦¤³¤È¤Ç¤¢¤ë¡¥¤Ä¤Þ¤ê¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×Åù¤Î¾
- : ¤Î¥¹¥ì¥Ã¥É¤Ç vwait Åù¤ÇÂÔ¤Á¤Î¾õÂ֤ˤ¢¤Ã¤¿¤È¤·¤Æ¤â¤½¤Î´°Î»
- : ¤òÂԤĤ³¤È¤Ê¤¯¡¤¼«¤é¤ÎÂÔ¤Á¾ò·ï¤¬À®Î©¼¡Â衤½èÍý¤ò·Ñ³¤¹¤ë
- : ¤³¤È¤Ë¤Ê¤ë¡¥
-
- _return_value
- : ľÁ°¤Î Tcl/Tk ¾å¤Ç¤Îɾ²Á¤Î¼Â¹Ô·ë²Ì¤È¤·¤Æ¤ÎÌá¤êÃͤòÊÖ¤¹¡¥
-
- mainloop
- mainloop_watchdog
- : ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤Ï¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òµ¯Æ°¤»¤º¤Ë nil ¤òÊÖ¤¹¡¥
- : ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
-
- do_one_event
- : ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤Ï°ú¿ô¤Î¥¤¥Ù¥ó¥È¥Õ¥é¥°¤Ë DONT_WAIT ¤¬
- : ¶¯À©Åª¤ËÄɲ䵤ì¤ë (¥¤¥Ù¥ó¥ÈÂÔ¤Á¤Ç¥¹¥ê¡¼¥×¤¹¤ë¤³¤È¤Ï¶Ø»ß)¡¥
- : ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
-
- set_eventloop_tick
- get_eventloop_tick
- set_no_event_wait
- get_no_event_wait
- set_eventloop_weight
- get_eventloop_weight
- mainloop_abort_on_exception
- mainloop_abort_on_exception=
- : ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤ÏÃͤÎÀßÄ꤬µö¤µ¤ì¤Ê¤¤ (̵»ë¤µ¤ì¤ë)¡¥
- : ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
-
-¥¯¥é¥¹ TkCallbackBreak < StandardError
-¥¯¥é¥¹ TkCallbackContinue < StandardError
- : ¤³¤ì¤é¤Ï¥¤¥Ù¥ó¥È¥³¡¼¥ë¥Ð¥Ã¥¯¤Ë¤ª¤¤¤Æ¡¤¥³¡¼¥ë¥Ð¥Ã¥¯½èÍý¤òŬÀÚ¤ËÃæ
- : ÃǤ·¤¿¤ê¡¤¼¡¤Î¥Ð¥¤¥ó¥É¥¿¥°¤Î¥Ð¥¤¥ó¥Ç¥£¥ó¥°½èÍý¤Ë¿Ê¤á¤¿¤ê¤¹¤ë¤³¤È
- : ¤ò²Äǽ¤Ë¤¹¤ë¤¿¤á¤ÎÎã³°¥¯¥é¥¹¤Ç¤¢¤ë¡¥
- : ¥³¡¼¥ë¥Ð¥Ã¥¯¤Ç break ¤ä continue ¤ò¼Â¸½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤¥³¡¼¥ë¥Ð¥Ã¥¯
- : ¤Ç¤¢¤ë Ruby ¼ê³¤­¤¬ Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿Â¦¤ËŬÀڤʥ꥿¡¼¥ó¥³¡¼
- : ¥É¤òÊÖ¤¹É¬Íפ¬¤¢¤ë¡¥Ruby ¤Î¼ê³¤­¤¬ÉáÄ̤ËÃͤòÊÖ¤¹¤Î¤Ç¤Ï¡¤¤½¤ì¤¬Éá
- : Ä̤ÎÌá¤êÃͤǤ¢¤ë¤Î¤«Èݤ«¤ò¶èÊ̤¬¤Ç¤­¤Ê¤¤¤¿¤á¡¤Î㳰ȯÀ¸¤òÍøÍѤ·¤¿
- : ¼ÂÁõ¤ò¹Ô¤Ã¤Æ¤¤¤ë¡¥
-
-(eof)
diff --git a/ext/tcltklib/README.1st b/ext/tcltklib/README.1st
deleted file mode 100644
index 510dd1c2cd..0000000000
--- a/ext/tcltklib/README.1st
+++ /dev/null
@@ -1,41 +0,0 @@
-To compile 'tcltklib', you must have Tcl/Tk libraries on your environment.
-Although 'extconf.rb' script searches Tcl/Tk libraries and header files,
-sometimes fails to find them. And then, 'tcltklib' cannot be compiled. If
-Tcl/Tk libraries or header files are installed but are not found, you can
-give the information by arguments of the 'configure' script. Please give
-some or all of the following options.
-
- --with-tcllib=<libname> (e.g. libtcl8.3.so ==> --with-tcllib=tcl8.3)
- --with-tklib=<libname> (e.g. libtk8.3.so ==> --with-tklib=tk8.3)
-
- --enable_tcltk_stubs (if you force to enable stubs)
-
- --with-tcl-dir=<path>
- equal to "--with-tcl-include=<path>/include --with-tcl-lib=<path>/lib"
-
- --with-tk-dir=<path>
- equal to "--with-tk-include=<path>/include --with-tk-lib=<path>/lib"
-
- --with-tcl-include=<dir> the directry containts 'tcl.h'
- --with-tk-include=<dir> the directry containts 'tk.h'
-
- --with-tcl-lib=<dir> the directry containts 'libtcl<version>.so'
- --with-tk-lib=<dir> the directry containts 'libtk<version>.so'
-
-If you forgot to give the options when do 'configure' on toplevel
-directry of Ruby sources, please try something like as the followings.
-
- $ cd ext/tcltklib
- $ rm Makefile
- $ CONFIGURE_ARGS='--with-tcl-include=/usr/local/include/tcl8.3/ --with-tcllib=tcl8.3 --with-tklib=tk8.3 --enable-tcltk_stubs' ruby extconf.rb
-
-
- *** ATTENTION ***
-When your Tcl/Tk libraries are compiled with "pthread support",
-Ruby/Tk may cause "Hang-up" or "Segmentation Fault" frequently.
-If you have such a trouble, please try to use the '--enable-pthread'
-option of the 'configure' command and re-compile Ruby sources.
-It may help you to avoid this trouble.
-
-==========================================================
- Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tcltklib/depend b/ext/tcltklib/depend
deleted file mode 100644
index 2cd9c400f7..0000000000
--- a/ext/tcltklib/depend
+++ /dev/null
@@ -1,2 +0,0 @@
-tcltklib.o: tcltklib.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
-stubs.o: stubs.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/tcltklib/extconf.rb b/ext/tcltklib/extconf.rb
deleted file mode 100644
index 575bf78034..0000000000
--- a/ext/tcltklib/extconf.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# extconf.rb for tcltklib
-
-require 'mkmf'
-
-if RUBY_PLATFORM !~ /mswin32|mingw|cygwin|bccwin32/
- have_library("nsl", "t_open")
- have_library("socket", "socket")
- have_library("dl", "dlopen")
- have_library("m", "log")
-end
-
-dir_config("tk")
-dir_config("tcl")
-dir_config("X11")
-
-tklib = with_config("tklib")
-tcllib = with_config("tcllib")
-stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs")
-
-def find_tcl(tcllib, stubs)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
- func = stubs ? "Tcl_InitStubs" : "Tcl_FindExecutable"
- if tcllib
- find_library(tcllib, func, *paths)
- elsif find_library("tcl", func, *paths)
- true
- else
- %w[8.4 8.3 8.2 8.0 7.6].find { |ver|
- find_library("tcl#{ver}", func, *paths) or
- find_library("tcl#{ver.delete('.')}", func, *paths)
- }
- end
-end
-
-def find_tk(tklib, stubs)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
- func = stubs ? "Tk_InitStubs" : "Tk_Init"
- if tklib
- find_library(tklib, func, *paths)
- elsif find_library("tk", func, *paths)
- true
- else
- %w[8.4 8.3 8.2 8.0 4.2].find { |ver|
- find_library("tk#{ver}", func, *paths) or
- find_library("tk#{ver.delete('.')}", func, *paths)
- }
- end
-end
-
-if have_header("tcl.h") && have_header("tk.h") &&
- (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM || find_library("X11", "XOpenDisplay",
- "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib")) &&
- find_tcl(tcllib, stubs) &&
- find_tk(tklib, stubs)
- $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs
- $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM
- create_makefile("tcltklib")
-end
diff --git a/ext/tcltklib/lib/tcltk.rb b/ext/tcltklib/lib/tcltk.rb
deleted file mode 100644
index a6bc773b96..0000000000
--- a/ext/tcltklib/lib/tcltk.rb
+++ /dev/null
@@ -1,367 +0,0 @@
-# tof
-
-#### tcltk library, more direct manipulation of tcl/tk
-#### Sep. 5, 1997 Y. Shigehiro
-
-require "tcltklib"
-
-################
-
-# module TclTk: collection of tcl/tk utilities (supplies namespace.)
-module TclTk
-
- # initialize Hash to hold unique symbols and such
- @namecnt = {}
-
- # initialize Hash to hold callbacks
- @callback = {}
-end
-
-# TclTk.mainloop(): call TclTkLib.mainloop()
-def TclTk.mainloop()
- print("mainloop: start\n") if $DEBUG
- TclTkLib.mainloop()
- print("mainloop: end\n") if $DEBUG
-end
-
-# TclTk.deletecallbackkey(ca): remove callback from TclTk module
-# this does not remove callbacks from tcl/tk interpreter
-# without calling this method, TclTkInterpreter will not be GCed
-# ca: callback(TclTkCallback)
-def TclTk.deletecallbackkey(ca)
- print("deletecallbackkey: ", ca.to_s(), "\n") if $DEBUG
- @callback.delete(ca.to_s)
-end
-
-# TclTk.dcb(ca, wid, W): call TclTk.deletecallbackkey() for each callbacks
-# in an array.
-# this is for callback for top-level <Destroy>
-# ca: array of callbacks(TclTkCallback)
-# wid: top-level widget(TclTkWidget)
-# w: information about window given by %W(String)
-def TclTk.dcb(ca, wid, w)
- if wid.to_s() == w
- ca.each{|i|
- TclTk.deletecallbackkey(i)
- }
- end
-end
-
-# TclTk._addcallback(ca): register callback
-# ca: callback(TclTkCallback)
-def TclTk._addcallback(ca)
- print("_addcallback: ", ca.to_s(), "\n") if $DEBUG
- @callback[ca.to_s()] = ca
-end
-
-# TclTk._callcallback(key, arg): invoke registered callback
-# key: key to select callback (to_s value of the TclTkCallback)
-# arg: parameter from tcl/tk interpreter
-def TclTk._callcallback(key, arg)
- print("_callcallback: ", @callback[key].inspect, "\n") if $DEBUG
- @callback[key]._call(arg)
- # throw out callback value
- # should return String to satisfy rb_eval_string()
- return ""
-end
-
-# TclTk._newname(prefix): generate unique name(String)
-# prefix: prefix of the unique name
-def TclTk._newname(prefix)
- # generated name counter is stored in @namecnt
- if !@namecnt.key?(prefix)
- # first appearing prefix, initialize
- @namecnt[prefix] = 1
- else
- # already appeared prefix, generate next name
- @namecnt[prefix] += 1
- end
- return "#{prefix}#{@namecnt[prefix]}"
-end
-
-################
-
-# class TclTkInterpreter: tcl/tk interpreter
-class TclTkInterpreter
-
- # initialize():
- def initialize()
- # generate interpreter object
- @ip = TclTkIp.new()
-
- # add ruby_fmt command to tcl interpreter
- # ruby_fmt command format arguments by `format' and call `ruby' command
- # (notice ruby command receives only one argument)
- if $DEBUG
- @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt $args\" ; set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }")
- else
- @ip._eval("proc ruby_fmt {fmt args} { set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }")
- end
-
- # @ip._get_eval_string(*args): generate string to evaluate in tcl interpreter
- # *args: script which is going to be evaluated under tcl/tk
- def @ip._get_eval_string(*args)
- argstr = ""
- args.each{|arg|
- argstr += " " if argstr != ""
- # call to_eval if it is defined
- if (arg.respond_to?(:to_eval))
- argstr += arg.to_eval()
- else
- # call to_s unless defined
- argstr += arg.to_s()
- end
- }
- return argstr
- end
-
- # @ip._eval_args(*args): evaluate string under tcl/tk interpreter
- # returns result string.
- # *args: script which is going to be evaluated under tcl/tk
- def @ip._eval_args(*args)
- # calculate the string to eval in the interpreter
- argstr = _get_eval_string(*args)
-
- # evaluate under the interpreter
- print("_eval: \"", argstr, "\"") if $DEBUG
- res = _eval(argstr)
- if $DEBUG
- print(" -> \"", res, "\"\n")
- elsif _return_value() != 0
- print(res, "\n")
- end
- fail(%Q/can't eval "#{argstr}"/) if _return_value() != 0 #'
- return res
- end
-
- # generate tcl/tk command object and register in the hash
- @commands = {}
- # for all commands registered in tcl/tk interpreter:
- @ip._eval("info command").split(/ /).each{|comname|
- if comname =~ /^[.]/
- # if command is a widget (path), generate TclTkWidget,
- # and register it in the hash
- @commands[comname] = TclTkWidget.new(@ip, comname)
- else
- # otherwise, generate TclTkCommand
- @commands[comname] = TclTkCommand.new(@ip, comname)
- end
- }
- end
-
- # commands(): returns hash of the tcl/tk commands
- def commands()
- return @commands
- end
-
- # rootwidget(): returns root widget(TclTkWidget)
- def rootwidget()
- return @commands["."]
- end
-
- # _tcltkip(): returns @ip(TclTkIp)
- def _tcltkip()
- return @ip
- end
-
- # method_missing(id, *args): execute undefined method as tcl/tk command
- # id: method symbol
- # *args: method arguments
- def method_missing(id, *args)
- # if command named by id registered, then execute it
- if @commands.key?(id.id2name)
- return @commands[id.id2name].e(*args)
- else
- # otherwise, exception
- super
- end
- end
-end
-
-# class TclTkObject: base class of the tcl/tk objects
-class TclTkObject
-
- # initialize(ip, exp):
- # ip: interpreter(TclTkIp)
- # exp: tcl/tk representation
- def initialize(ip, exp)
- fail("type is not TclTkIp") if !ip.kind_of?(TclTkIp)
- @ip = ip
- @exp = exp
- end
-
- # to_s(): returns tcl/tk representation
- def to_s()
- return @exp
- end
-end
-
-# class TclTkCommand: tcl/tk commands
-# you should not call TclTkCommand.new()
-# commands are created by TclTkInterpreter:initialize()
-class TclTkCommand < TclTkObject
-
- # e(*args): execute command. returns String (e is for exec or eval)
- # *args: command arguments
- def e(*args)
- return @ip._eval_args(to_s(), *args)
- end
-end
-
-# class TclTkLibCommand: tcl/tk commands in the library
-class TclTkLibCommand < TclTkCommand
-
- # initialize(ip, name):
- # ip: interpreter(TclTkInterpreter)
- # name: command name (String)
- def initialize(ip, name)
- super(ip._tcltkip, name)
- end
-end
-
-# class TclTkVariable: tcl/tk variable
-class TclTkVariable < TclTkObject
-
- # initialize(interp, dat):
- # interp: interpreter(TclTkInterpreter)
- # dat: the value to set(String)
- # if nil, not initialize variable
- def initialize(interp, dat)
- # auto-generate tcl/tk representation (variable name)
- exp = TclTk._newname("v_")
- # initialize TclTkObject
- super(interp._tcltkip(), exp)
- # safe this for `set' command
- @set = interp.commands()["set"]
- # set value
- set(dat) if dat
- end
-
- # although you can set/refer variable by using set in tcl/tk,
- # we provide the method for accessing variables
-
- # set(data): set tcl/tk variable using `set'
- # data: new value
- def set(data)
- @set.e(to_s(), data.to_s())
- end
-
- # get(): read tcl/tk variable(String) using `set'
- def get()
- return @set.e(to_s())
- end
-end
-
-# class TclTkWidget: tcl/tk widget
-class TclTkWidget < TclTkCommand
-
- # initialize(*args):
- # *args: parameters
- def initialize(*args)
- if args[0].kind_of?(TclTkIp)
- # in case the 1st argument is TclTkIp:
-
- # Wrap tcl/tk widget by TclTkWidget
- # (used in TclTkInterpreter#initialize())
-
- # need two arguments
- fail("illegal # of parameter") if args.size != 2
-
- # ip: interpreter(TclTkIp)
- # exp: tcl/tk representation
- ip, exp = args
-
- # initialize TclTkObject
- super(ip, exp)
- elsif args[0].kind_of?(TclTkInterpreter)
- # in case 1st parameter is TclTkInterpreter:
-
- # generate new widget from parent widget
-
- # interp: interpreter(TclTkInterpreter)
- # parent: parent widget
- # command: widget generating tk command(label Åù)
- # *args: argument to the command
- interp, parent, command, *args = args
-
- # generate widget name
- exp = parent.to_s()
- exp += "." if exp !~ /[.]$/
- exp += TclTk._newname("w_")
- # initialize TclTkObject
- super(interp._tcltkip(), exp)
- # generate widget
- res = @ip._eval_args(command, exp, *args)
-# fail("can't create Widget") if res != exp
- # for tk_optionMenu, it is legal res != exp
- else
- fail("first parameter is not TclTkInterpreter")
- end
- end
-end
-
-# class TclTkCallback: tcl/tk callbacks
-class TclTkCallback < TclTkObject
-
- # initialize(interp, pr, arg):
- # interp: interpreter(TclTkInterpreter)
- # pr: callback procedure(Proc)
- # arg: string to pass as block parameters of pr
- # bind command of tcl/tk uses % replacement for parameters
- # pr can receive replaced data using block parameter
- # its format is specified by arg string
- # You should not specify arg for the command like
- # scrollbar with -command option, which receives parameters
- # without specifying any replacement
- def initialize(interp, pr, arg = nil)
- # auto-generate tcl/tk representation (variable name)
- exp = TclTk._newname("c_")
- # initialize TclTkObject
- super(interp._tcltkip(), exp)
- # save parameters
- @pr = pr
- @arg = arg
- # register in the module
- TclTk._addcallback(self)
- end
-
- # to_eval(): retuens string representation for @ip._eval_args
- def to_eval()
- if @arg
- # bind replaces %s before calling ruby_fmt, so %%s is used
- s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%%s")} #{@arg}}/
- else
- s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%s")}}/
- end
-
- return s
- end
-
- # _call(arg): invoke callback
- # arg: callback parameter
- def _call(arg)
- @pr.call(arg)
- end
-end
-
-# class TclTkImage: tcl/tk images
-class TclTkImage < TclTkCommand
-
- # initialize(interp, t, *args):
- # generating image is done by TclTkImage.new()
- # destrying is done by image delete (inconsistent, sigh)
- # interp: interpreter(TclTkInterpreter)
- # t: image type (photo, bitmap, etc.)
- # *args: command argument
- def initialize(interp, t, *args)
- # auto-generate tcl/tk representation
- exp = TclTk._newname("i_")
- # initialize TclTkObject
- super(interp._tcltkip(), exp)
- # generate image
- res = @ip._eval_args("image create", t, exp, *args)
- fail("can't create Image") if res != exp
- end
-end
-
-# eof
diff --git a/ext/tcltklib/sample/sample1.rb b/ext/tcltklib/sample/sample1.rb
deleted file mode 100644
index 21ee0f29d5..0000000000
--- a/ext/tcltklib/sample/sample1.rb
+++ /dev/null
@@ -1,634 +0,0 @@
-#! /usr/local/bin/ruby -d
-#! /usr/local/bin/ruby
-# -d ¥ª¥×¥·¥ç¥ó¤òÉÕ¤±¤ë¤È, ¥Ç¥Ð¥Ã¥°¾ðÊó¤òɽ¼¨¤¹¤ë.
-
-# tcltk ¥é¥¤¥Ö¥é¥ê¤Î¥µ¥ó¥×¥ë
-
-# ¤Þ¤º, ¥é¥¤¥Ö¥é¥ê¤ò require ¤¹¤ë.
-require "tcltk"
-
-# °Ê²¼¤Ï, Test1 ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Î initialize() ¤Ç,
-# tcl/tk ¤Ë´Ø¤¹¤ë½èÍý¤ò¹Ô¤¦Îã¤Ç¤¢¤ë.
-# ɬ¤º¤·¤â¤½¤Î¤è¤¦¤Ë¤¹¤ëɬÍפÏ̵¤¯,
-# (¤â¤·, ¤½¤¦¤·¤¿¤±¤ì¤Ð) class ¤Î³°¤Ç tcl/tk ¤Ë´Ø¤¹¤ë½èÍý¤ò¹Ô¤Ã¤Æ¤âÎɤ¤.
-
-class Test1
- # ½é´ü²½(¥¤¥ó¥¿¥×¥ê¥¿¤òÀ¸À®¤·¤Æ¥¦¥£¥¸¥§¥Ã¥È¤òÀ¸À®¤¹¤ë).
- def initialize()
-
- #### »È¤¦Á°¤Î¤ª¤Þ¤¸¤Ê¤¤
-
- # ¥¤¥ó¥¿¥×¥ê¥¿¤ÎÀ¸À®.
- ip = TclTkInterpreter.new()
- # ¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò c ¤ËÀßÄꤷ¤Æ¤ª¤¯.
- c = ip.commands()
- # »ÈÍѤ¹¤ë¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ÏÊÑ¿ô¤ËÆþ¤ì¤Æ¤ª¤¯.
- append, bind, button, destroy, incr, info, label, place, set, wm =
- c.indexes(
- "append", "bind", "button", "destroy", "incr", "info", "label", "place",
- "set", "wm")
-
- #### tcl/tk ¤Î¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkCommand)¤ÎÁàºî
-
- # ¼Â¹Ô¤¹¤ë»þ¤Ï, e() ¥á¥½¥Ã¥É¤ò»È¤¦.
- # (°Ê²¼¤Ï, tcl/tk ¤Ë¤ª¤±¤ë info command r* ¤ò¼Â¹Ô.)
- print info.e("command", "r*"), "\n"
- # °ú¿ô¤Ï, ¤Þ¤È¤á¤¿Ê¸»úÎó¤Ë¤·¤Æ¤âƱ¤¸.
- print info.e("command r*"), "\n"
- # ÊÑ¿ô¤òÍѤ¤¤Ê¤¯¤È¤â¼Â¹Ô¤Ç¤­¤ë¤¬, ¸«¤¿¤á¤¬°­¤¤.
- print c["info"].e("command", "r*"), "\n"
- # ¥¤¥ó¥¿¥×¥ê¥¿¤Î¥á¥½¥Ã¥É¤È¤·¤Æ¤â¼Â¹Ô¤Ç¤­¤ë¤¬, ¸úΨ¤¬°­¤¤.
- print ip.info("command", "r*"), "\n"
-
- ####
-
- # °Ê²¼, À¸À®¤·¤¿¥ª¥Ö¥¸¥§¥¯¥È¤ÏÊÑ¿ô¤ËÂåÆþ¤·¤Æ¤ª¤«¤Ê¤¤¤È
- # GC ¤ÎÂоݤˤʤäƤ·¤Þ¤¦.
-
- #### tcl/tk ¤ÎÊÑ¿ô¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkVariable)¤ÎÁàºî
-
- # À¸À®¤ÈƱ»þ¤ËÃͤòÀßÄꤹ¤ë.
- v1 = TclTkVariable.new(ip, "20")
- # ÆÉ¤ß½Ð¤·¤Ï get ¥á¥½¥Ã¥É¤ò»È¤¦.
- print v1.get(), "\n"
- # ÀßÄê¤Ï set ¥á¥½¥Ã¥É¤ò»È¤¦.
- v1.set(40)
- print v1.get(), "\n"
- # set ¥³¥Þ¥ó¥É¤ò»È¤Ã¤ÆÆÉ¤ß½Ð¤·, ÀßÄê¤Ï²Äǽ¤À¤¬¸«¤¿¤á¤¬°­¤¤.
- # e() ¥á¥½¥Ã¥ÉÅù¤Î°ú¿ô¤ËľÀÜ TclTkObject ¤ä¿ôÃͤò½ñ¤¤¤Æ¤âÎɤ¤.
- set.e(v1, 30)
- print set.e(v1), "\n"
- # tcl/tk ¤Î¥³¥Þ¥ó¥É¤ÇÊÑ¿ô¤òÁàºî¤Ç¤­¤ë.
- incr.e(v1)
- print v1.get(), "\n"
- append.e(v1, 10)
- print v1.get(), "\n"
-
- #### tcl/tk ¤Î¥¦¥£¥¸¥§¥Ã¥È¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkWidget)¤ÎÁàºî
-
- # ¥ë¡¼¥È¥¦¥£¥¸¥§¥Ã¥È¤ò¼è¤ê½Ð¤¹.
- root = ip.rootwidget()
- # ¥¦¥£¥¸¥§¥Ã¥È¤ÎÁàºî.
- root.e("configure -height 300 -width 300")
- # ¥¿¥¤¥È¥ë¤òÉÕ¤±¤ë¤È¤­¤Ï wm ¤ò»È¤¦.
- wm.e("title", root, $0)
- # ¿Æ¥¦¥£¥¸¥§¥Ã¥È¤È¥³¥Þ¥ó¥É¤ò»ØÄꤷ¤Æ, ¥¦¥£¥¸¥§¥Ã¥È¤òºî¤ë.
- l1 = TclTkWidget.new(ip, root, label, "-text {type `x' to print}")
- # place ¤¹¤ë¤Èɽ¼¨¤µ¤ì¤ë.
- place.e(l1, "-x 0 -rely 0.0 -relwidth 1 -relheight 0.1")
- # ¥³¥Þ¥ó¥É̾¤Ïʸ»úÎó¤Ç»ØÄꤷ¤Æ¤âÎɤ¤¤¬, ¸«¤¿¤á¤¬°­¤¤.
- # (¥³¥Þ¥ó¥É̾¤ÏÆÈΩ¤·¤¿°ú¿ô¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.)
- l2 = TclTkWidget.new(ip, root, "label")
- # ¥¦¥£¥¸¥§¥Ã¥È¤ÎÁàºî.
- l2.e("configure -text {type `q' to exit}")
- place.e(l2, "-x 0 -rely 0.1 -relwidth 1 -relheight 0.1")
-
- #### tcl/tk ¤Î¥³¡¼¥ë¥Ð¥Ã¥¯¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkCallback)¤ÎÁàºî
-
- # ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÀ¸À®¤¹¤ë.
- c1 = TclTkCallback.new(ip, proc{sample(ip, root)})
- # ¥³¡¼¥ë¥Ð¥Ã¥¯¤ò»ý¤Ä¥¦¥£¥¸¥§¥Ã¥È¤òÀ¸À®¤¹¤ë.
- b1 = TclTkWidget.new(ip, root, button, "-text sample -command", c1)
- place.e(b1, "-x 0 -rely 0.2 -relwidth 1 -relheight 0.1")
- # ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òÈ´¤±¤ë¤Ë¤Ï destroy.e(root) ¤¹¤ë.
- c2 = TclTkCallback.new(ip, proc{destroy.e(root)})
- b2 = TclTkWidget.new(ip, root, button, "-text exit -command", c2)
- place.e(b2, "-x 0 -rely 0.3 -relwidth 1 -relheight 0.1")
-
- #### ¥¤¥Ù¥ó¥È¤Î¥Ð¥¤¥ó¥É
- # script ¤ÎÄɲà (bind tag sequence +script) ¤Ïº£¤Î¤È¤³¤í¤Ç¤­¤Ê¤¤.
- # (¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤ÎÀßÄ꤬¤¦¤Þ¤¯¤¤¤«¤Ê¤¤.)
-
- # ´ðËÜŪ¤Ë¤Ï¥¦¥£¥¸¥§¥Ã¥È¤ËÂФ¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯¤ÈƱ¤¸.
- c3 = TclTkCallback.new(ip, proc{print("q pressed\n"); destroy.e(root)})
- bind.e(root, "q", c3)
- # bind ¥³¥Þ¥ó¥É¤Ç % ÃÖ´¹¤Ë¤è¤ê¥Ñ¥é¥á¡¼¥¿¤ò¼õ¤±¼è¤ê¤¿¤¤¤È¤­¤Ï,
- # proc{} ¤Î¸å¤í¤Ëʸ»úÎó¤Ç»ØÄꤹ¤ë¤È,
- # ÃÖ´¹·ë²Ì¤ò¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤òÄ̤·¤Æ¼õ¤±¼è¤ë¤³¤È¤¬¤Ç¤­¤ë.
- # ¤¿¤À¤· proc{} ¤Î¸å¤í¤Îʸ»úÎó¤Ï,
- # bind ¥³¥Þ¥ó¥É¤ËÍ¿¤¨¤ë¥³¡¼¥ë¥Ð¥Ã¥¯°Ê³°¤Ç»ØÄꤷ¤Æ¤Ï¤¤¤±¤Ê¤¤.
- c4 = TclTkCallback.new(ip, proc{|i| print("#{i} pressed\n")}, "%A")
- bind.e(root, "x", c4)
- # TclTkCallback ¤ò GC ¤ÎÂоݤˤ·¤¿¤±¤ì¤Ð,
- # dcb() (¤Þ¤¿¤Ï deletecallbackkeys()) ¤¹¤ëɬÍפ¬¤¢¤ë.
- cb = [c1, c2, c3, c4]
- c5 = TclTkCallback.new(ip, proc{|w| TclTk.dcb(cb, root, w)}, "%W")
- bind.e(root, "<Destroy>", c5)
- cb.push(c5)
-
- #### tcl/tk ¤Î¥¤¥á¡¼¥¸¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkImage)¤ÎÁàºî
-
- # ¥Ç¡¼¥¿¤ò»ØÄꤷ¤ÆÀ¸À®¤¹¤ë.
- i1 = TclTkImage.new(ip, "photo", "-file maru.gif")
- # ¥é¥Ù¥ë¤ËÄ¥¤êÉÕ¤±¤Æ¤ß¤ë.
- l3 = TclTkWidget.new(ip, root, label, "-relief raised -image", i1)
- place.e(l3, "-x 0 -rely 0.4 -relwidth 0.2 -relheight 0.2")
- # ¶õ¤Î¥¤¥á¡¼¥¸¤òÀ¸À®¤·¤Æ¸å¤ÇÁàºî¤¹¤ë.
- i2 = TclTkImage.new(ip, "photo")
- # ¥¤¥á¡¼¥¸¤òÁàºî¤¹¤ë.
- i2.e("copy", i1)
- i2.e("configure -gamma 0.5")
- l4 = TclTkWidget.new(ip, root, label, "-relief raised -image", i2)
- place.e(l4, "-relx 0.2 -rely 0.4 -relwidth 0.2 -relheight 0.2")
-
- ####
- end
-
- # ¥µ¥ó¥×¥ë¤Î¤¿¤á¤Î¥¦¥£¥¸¥§¥Ã¥È¤òÀ¸À®¤¹¤ë.
- def sample(ip, parent)
- bind, button, destroy, grid, toplevel, wm = ip.commands().indexes(
- "bind", "button", "destroy", "grid", "toplevel", "wm")
-
- ## toplevel
-
- # ¿·¤·¤¤¥¦¥¤¥ó¥É¥¦¤ò³«¤¯¤Ë¤Ï, toplevel ¤ò»È¤¦.
- t1 = TclTkWidget.new(ip, parent, toplevel)
- # ¥¿¥¤¥È¥ë¤òÉÕ¤±¤Æ¤ª¤¯
- wm.e("title", t1, "sample")
-
- # ¥¦¥£¥¸¥§¥Ã¥È¤¬Ç˲õ¤µ¤ì¤¿¤È¤­, ¥³¡¼¥ë¥Ð¥Ã¥¯¤¬ GC ¤ÎÂоݤˤʤë¤è¤¦¤Ë¤¹¤ë.
- cb = []
- cb.push(c = TclTkCallback.new(ip, proc{|w| TclTk.dcb(cb, t1, w)}, "%W"))
- bind.e(t1, "<Destroy>", c)
-
- # ¥Ü¥¿¥ó¤ÎÀ¸À®.
- wid = []
- # toplevel ¥¦¥£¥¸¥§¥Ã¥È¤òÇ˲õ¤¹¤ë¤Ë¤Ï destroy ¤¹¤ë.
- cb.push(c = TclTkCallback.new(ip, proc{destroy.e(t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text close -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_label(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text label -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_button(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text button -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_checkbutton(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text checkbutton -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_radiobutton(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text radiobutton -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_scale(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text scale -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_entry(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text entry -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_text(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text text -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_raise(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text raise/lower -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_modal(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text message/modal -command",
- c))
- cb.push(c = TclTkCallback.new(ip, proc{test_menu(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text menu -command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_listbox(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text listbox/scrollbar",
- "-command", c))
- cb.push(c = TclTkCallback.new(ip, proc{test_canvas(ip, t1)}))
- wid.push(TclTkWidget.new(ip, t1, button, "-text canvas -command", c))
-
- # grid ¤Çɽ¼¨¤¹¤ë.
- ro = co = 0
- wid.each{|w|
- grid.e(w, "-row", ro, "-column", co, "-sticky news")
- ro += 1
- if ro == 7
- ro = 0
- co += 1
- end
- }
- end
-
- # inittoplevel(ip, parent, title)
- # °Ê²¼¤Î½èÍý¤ò¤Þ¤È¤á¤Æ¹Ô¤¦.
- # 1. toplevel ¥¦¥£¥¸¥§¥Ã¥È¤òºîÀ®¤¹¤ë.
- # 2. ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÅÐÏ¿¤¹¤ëÇÛÎó¤òÍѰդ·, toplevel ¥¦¥£¥¸¥§¥Ã¥È¤Î
- # <Destroy> ¥¤¥Ù¥ó¥È¤Ë¥³¡¼¥ë¥Ð¥Ã¥¯¤òºï½ü¤¹¤ë¼ê³¤­¤òÅÐÏ¿¤¹¤ë.
- # 3. ¥¯¥í¡¼¥º¥Ü¥¿¥ó¤òºî¤ë.
- # ºîÀ®¤·¤¿ toplevel ¥¦¥£¥¸¥§¥Ã¥È, ¥¯¥í¡¼¥º¥Ü¥¿¥ó, ¥³¡¼¥ë¥Ð¥Ã¥¯ÅÐÏ¿ÍÑÊÑ¿ô
- # ¤òÊÖ¤¹.
- # ip: ¥¤¥ó¥¿¥×¥ê¥¿
- # parent: ¿Æ¥¦¥£¥¸¥§¥Ã¥È
- # title: toplevel ¥¦¥£¥¸¥§¥Ã¥È¤Î¥¦¥¤¥ó¥É¥¦¤Î¥¿¥¤¥È¥ë
- def inittoplevel(ip, parent, title)
- bind, button, destroy, toplevel, wm = ip.commands().indexes(
- "bind", "button", "destroy", "toplevel", "wm")
-
- # ¿·¤·¤¤¥¦¥¤¥ó¥É¥¦¤ò³«¤¯¤Ë¤Ï, toplevel ¤ò»È¤¦.
- t1 = TclTkWidget.new(ip, parent, toplevel)
- # ¥¿¥¤¥È¥ë¤òÉÕ¤±¤Æ¤ª¤¯
- wm.e("title", t1, title)
-
- # ¥¦¥£¥¸¥§¥Ã¥È¤¬Ç˲õ¤µ¤ì¤¿¤È¤­, ¥³¡¼¥ë¥Ð¥Ã¥¯¤¬ GC ¤ÎÂоݤˤʤë¤è¤¦¤Ë¤¹¤ë.
- cb = []
- cb.push(c = TclTkCallback.new(ip, proc{|w| TclTk.dcb(cb, t1, w)}, "%W"))
- bind.e(t1, "<Destroy>", c)
- # close ¥Ü¥¿¥ó¤òºî¤Ã¤Æ¤ª¤¯.
- # toplevel ¥¦¥£¥¸¥§¥Ã¥È¤òÇ˲õ¤¹¤ë¤Ë¤Ï destroy ¤¹¤ë.
- cb.push(c = TclTkCallback.new(ip, proc{destroy.e(t1)}))
- b1 = TclTkWidget.new(ip, t1, button, "-text close -command", c)
-
- return t1, b1, cb
- end
-
- # label ¤Î¥µ¥ó¥×¥ë.
- def test_label(ip, parent)
- button, global, label, pack = ip.commands().indexes(
- "button", "global", "label", "pack")
- t1, b1, cb = inittoplevel(ip, parent, "label")
-
- ## label
-
- # ¤¤¤í¤¤¤í¤Ê·Á¤Î¥é¥Ù¥ë.
- l1 = TclTkWidget.new(ip, t1, label, "-text {default(flat)}")
- l2 = TclTkWidget.new(ip, t1, label, "-text raised -relief raised")
- l3 = TclTkWidget.new(ip, t1, label, "-text sunken -relief sunken")
- l4 = TclTkWidget.new(ip, t1, label, "-text groove -relief groove")
- l5 = TclTkWidget.new(ip, t1, label, "-text ridge -relief ridge")
- l6 = TclTkWidget.new(ip, t1, label, "-bitmap error")
- l7 = TclTkWidget.new(ip, t1, label, "-bitmap questhead")
-
- # pack ¤·¤Æ¤âɽ¼¨¤µ¤ì¤ë.
- pack.e(b1, l1, l2, l3, l4, l5, l6, l7, "-pady 3")
-
- ## -textvariable
-
- # tcltk ¥é¥¤¥Ö¥é¥ê¤Î¼ÂÁõ¤Ç¤Ï, ¥³¡¼¥ë¥Ð¥Ã¥¯¤Ï tcl/tk ¤Î``¼ê³¤­''¤òÄ̤·¤Æ
- # ¸Æ¤Ð¤ì¤ë. ¤·¤¿¤¬¤Ã¤Æ, ¥³¡¼¥ë¥Ð¥Ã¥¯¤ÎÃæ¤Ç(Âç°è)ÊÑ¿ô¤Ë¥¢¥¯¥»¥¹¤¹¤ë¤È¤­¤Ï,
- # global ¤¹¤ëɬÍפ¬¤¢¤ë.
- # global ¤¹¤ëÁ°¤ËÊÑ¿ô¤ËÃͤòÀßÄꤷ¤Æ¤·¤Þ¤¦¤È¥¨¥é¡¼¤Ë¤Ê¤ë¤Î¤Ç,
- # tcl/tk ¤Ë¤ª¤±¤ëɽ¸½·Á¤À¤±À¸À®¤·¤Æ, ¼ÂºÝ¤ËÃͤòÀßÄꤷ¤Ê¤¤¤è¤¦¤Ë,
- # 2 ÈÖÌܤΰú¿ô¤Ë¤Ï nil ¤òÍ¿¤¨¤ë.
- v1 = TclTkVariable.new(ip, nil)
- global.e(v1)
- v1.set(100)
- # -textvariable ¤ÇÊÑ¿ô¤òÀßÄꤹ¤ë.
- l6 = TclTkWidget.new(ip, t1, label, "-textvariable", v1)
- # ¥³¡¼¥ë¥Ð¥Ã¥¯¤ÎÃæ¤«¤éÊÑ¿ô¤òÁàºî¤¹¤ë.
- cb.push(c = TclTkCallback.new(ip, proc{
- global.e(v1); v1.set(v1.get().to_i + 10)}))
- b2 = TclTkWidget.new(ip, t1, button, "-text +10 -command", c)
- cb.push(c = TclTkCallback.new(ip, proc{
- global.e(v1); v1.set(v1.get().to_i - 10)}))
- b3 = TclTkWidget.new(ip, t1, button, "-text -10 -command", c)
- pack.e(l6, b2, b3)
- end
-
- # button ¤Î¥µ¥ó¥×¥ë.
- def test_button(ip, parent)
- button, pack = ip.commands().indexes("button", "pack")
- t1, b1, cb = inittoplevel(ip, parent, "button")
-
- ## button
-
- # ¥³¡¼¥ë¥Ð¥Ã¥¯Æâ¤Ç»²¾È¤¹¤ëÊÑ¿ô¤ÏÀè¤ËÀë¸À¤·¤Æ¤ª¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.
- b3 = b4 = nil
- cb.push(c = TclTkCallback.new(ip, proc{b3.e("flash"); b4.e("flash")}))
- b2 = TclTkWidget.new(ip, t1, button, "-text flash -command", c)
- cb.push(c = TclTkCallback.new(ip, proc{b2.e("configure -state normal")}))
- b3 = TclTkWidget.new(ip, t1, button, "-text normal -command", c)
- cb.push(c = TclTkCallback.new(ip, proc{b2.e("configure -state disabled")}))
- b4 = TclTkWidget.new(ip, t1, button, "-text disable -command", c)
- pack.e(b1, b2, b3, b4)
- end
-
- # checkbutton ¤Î¥µ¥ó¥×¥ë.
- def test_checkbutton(ip, parent)
- checkbutton, global, pack = ip.commands().indexes(
- "checkbutton", "global", "pack")
- t1, b1, cb = inittoplevel(ip, parent, "checkbutton")
-
- ## checkbutton
-
- v1 = TclTkVariable.new(ip, nil)
- global.e(v1)
- # -variable ¤ÇÊÑ¿ô¤òÀßÄꤹ¤ë.
- ch1 = TclTkWidget.new(ip, t1, checkbutton, "-onvalue on -offvalue off",
- "-textvariable", v1, "-variable", v1)
- pack.e(b1, ch1)
- end
-
- # radiobutton ¤Î¥µ¥ó¥×¥ë.
- def test_radiobutton(ip, parent)
- global, label, pack, radiobutton = ip.commands().indexes(
- "global", "label", "pack", "radiobutton")
- t1, b1, cb = inittoplevel(ip, parent, "radiobutton")
-
- ## radiobutton
-
- v1 = TclTkVariable.new(ip, nil)
- global.e(v1)
- # ¥Ì¥ë¥¹¥È¥ê¥ó¥°¤Ï "{}" ¤Ç»ØÄꤹ¤ë.
- v1.set("{}")
- l1 = TclTkWidget.new(ip, t1, label, "-textvariable", v1)
- # -variable ¤ÇƱ¤¸ÊÑ¿ô¤ò»ØÄꤹ¤ë¤ÈƱ¤¸¥°¥ë¡¼¥×¤Ë¤Ê¤ë.
- ra1 = TclTkWidget.new(ip, t1, radiobutton,
- "-text radio1 -value r1 -variable", v1)
- ra2 = TclTkWidget.new(ip, t1, radiobutton,
- "-text radio2 -value r2 -variable", v1)
- cb.push(c = TclTkCallback.new(ip, proc{global.e(v1); v1.set("{}")}))
- ra3 = TclTkWidget.new(ip, t1, radiobutton,
- "-text clear -value r3 -variable", v1, "-command", c)
- pack.e(b1, l1, ra1, ra2, ra3)
- end
-
- # scale ¤Î¥µ¥ó¥×¥ë.
- def test_scale(ip, parent)
- global, pack, scale = ip.commands().indexes(
- "global", "pack", "scale")
- t1, b1, cb = inittoplevel(ip, parent, "scale")
-
- ## scale
-
- v1 = TclTkVariable.new(ip, nil)
- global.e(v1)
- v1.set(219)
- # ¥³¡¼¥ë¥Ð¥Ã¥¯Æâ¤Ç»²¾È¤¹¤ëÊÑ¿ô¤ÏÀè¤ËÀë¸À¤·¤Æ¤ª¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.
- sca1 = nil
- cb.push(c = TclTkCallback.new(ip, proc{global.e(v1); v = v1.get();
- sca1.e("configure -background", format("#%02x%02x%02x", v, v, v))}))
- sca1 = TclTkWidget.new(ip, t1, scale,
- "-label scale -orient h -from 0 -to 255 -variable", v1, "-command", c)
- pack.e(b1, sca1)
- end
-
- # entry ¤Î¥µ¥ó¥×¥ë.
- def test_entry(ip, parent)
- button, entry, global, pack = ip.commands().indexes(
- "button", "entry", "global", "pack")
- t1, b1, cb = inittoplevel(ip, parent, "entry")
-
- ## entry
-
- v1 = TclTkVariable.new(ip, nil)
- global.e(v1)
- # ¥Ì¥ë¥¹¥È¥ê¥ó¥°¤Ï "{}" ¤Ç»ØÄꤹ¤ë.
- v1.set("{}")
- en1 = TclTkWidget.new(ip, t1, entry, "-textvariable", v1)
- cb.push(c = TclTkCallback.new(ip, proc{
- global.e(v1); print(v1.get(), "\n"); v1.set("{}")}))
- b2 = TclTkWidget.new(ip, t1, button, "-text print -command", c)
- pack.e(b1, en1, b2)
- end
-
- # text ¤Î¥µ¥ó¥×¥ë.
- def test_text(ip, parent)
- button, pack, text = ip.commands().indexes(
- "button", "pack", "text")
- t1, b1, cb = inittoplevel(ip, parent, "text")
-
- ## text
-
- te1 = TclTkWidget.new(ip, t1, text)
- cb.push(c = TclTkCallback.new(ip, proc{
- # 1 ¹ÔÌܤΠ0 ʸ»úÌܤ«¤éºÇ¸å¤Þ¤Ç¤òɽ¼¨¤·, ºï½ü¤¹¤ë.
- print(te1.e("get 1.0 end")); te1.e("delete 1.0 end")}))
- b2 = TclTkWidget.new(ip, t1, button, "-text print -command", c)
- pack.e(b1, te1, b2)
- end
-
- # raise/lower ¤Î¥µ¥ó¥×¥ë.
- def test_raise(ip, parent)
- button, frame, lower, pack, raise = ip.commands().indexes(
- "button", "frame", "lower", "pack", "raise")
- t1, b1, cb = inittoplevel(ip, parent, "raise/lower")
-
- ## raise/lower
-
- # button ¤ò±£¤¹¥Æ¥¹¥È¤Î¤¿¤á¤Ë, frame ¤ò»È¤¦.
- f1 = TclTkWidget.new(ip, t1, frame)
- # ¥³¡¼¥ë¥Ð¥Ã¥¯Æâ¤Ç»²¾È¤¹¤ëÊÑ¿ô¤ÏÀè¤ËÀë¸À¤·¤Æ¤ª¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.
- b2 = nil
- cb.push(c = TclTkCallback.new(ip, proc{raise.e(f1, b2)}))
- b2 = TclTkWidget.new(ip, t1, button, "-text raise -command", c)
- cb.push(c = TclTkCallback.new(ip, proc{lower.e(f1, b2)}))
- b3 = TclTkWidget.new(ip, t1, button, "-text lower -command", c)
- lower.e(f1, b3)
-
- pack.e(b2, b3, "-in", f1)
- pack.e(b1, f1)
- end
-
- # modal ¤Ê¥¦¥£¥¸¥§¥Ã¥È¤Î¥µ¥ó¥×¥ë.
- def test_modal(ip, parent)
- button, frame, message, pack, tk_chooseColor, tk_getOpenFile,
- tk_messageBox = ip.commands().indexes(
- "button", "frame", "message", "pack", "tk_chooseColor",
- "tk_getOpenFile", "tk_messageBox")
- # ºÇ½é¤Ë load ¤µ¤ì¤Æ¤¤¤Ê¤¤¥é¥¤¥Ö¥é¥ê¤Ï ip.commands() ¤Ë¸ºß¤·¤Ê¤¤¤Î¤Ç,
- # TclTkLibCommand ¤òÀ¸À®¤¹¤ëɬÍפ¬¤¢¤ë.
- tk_dialog = TclTkLibCommand.new(ip, "tk_dialog")
- t1, b1, cb = inittoplevel(ip, parent, "message/modal")
-
- ## message
-
- mes = "¤³¤ì¤Ï message ¥¦¥£¥¸¥§¥Ã¥È¤Î¥Æ¥¹¥È¤Ç¤¹."
- mes += "°Ê²¼¤Ï modal ¤Ê¥¦¥£¥¸¥§¥Ã¥È¤Î¥Æ¥¹¥È¤Ç¤¹."
- me1 = TclTkWidget.new(ip, t1, message, "-text {#{mes}}")
-
- ## modal
-
- # tk_messageBox
- cb.push(c = TclTkCallback.new(ip, proc{
- print tk_messageBox.e("-type yesnocancel -message messageBox",
- "-icon error -default cancel -title messageBox"), "\n"}))
- b2 = TclTkWidget.new(ip, t1, button, "-text messageBox -command", c)
- # tk_dialog
- cb.push(c = TclTkCallback.new(ip, proc{
- # ¥¦¥£¥¸¥§¥Ã¥È̾¤òÀ¸À®¤¹¤ë¤¿¤á¤Ë¥À¥ß¡¼¤Î frame ¤òÀ¸À®.
- print tk_dialog.e(TclTkWidget.new(ip, t1, frame),
- "dialog dialog error 2 yes no cancel"), "\n"}))
- b3 = TclTkWidget.new(ip, t1, button, "-text dialog -command", c)
- # tk_chooseColor
- cb.push(c = TclTkCallback.new(ip, proc{
- print tk_chooseColor.e("-title chooseColor"), "\n"}))
- b4 = TclTkWidget.new(ip, t1, button, "-text chooseColor -command", c)
- # tk_getOpenFile
- cb.push(c = TclTkCallback.new(ip, proc{
- print tk_getOpenFile.e("-defaultextension .rb",
- "-filetypes {{{Ruby Script} {.rb}} {{All Files} {*}}}",
- "-title getOpenFile"), "\n"}))
- b5 = TclTkWidget.new(ip, t1, button, "-text getOpenFile -command", c)
-
- pack.e(b1, me1, b2, b3, b4, b5)
- end
-
- # menu ¤Î¥µ¥ó¥×¥ë.
- def test_menu(ip, parent)
- global, menu, menubutton, pack = ip.commands().indexes(
- "global", "menu", "menubutton", "pack")
- tk_optionMenu = TclTkLibCommand.new(ip, "tk_optionMenu")
- t1, b1, cb = inittoplevel(ip, parent, "menu")
-
- ## menu
-
- # menubutton ¤òÀ¸À®¤¹¤ë.
- mb1 = TclTkWidget.new(ip, t1, menubutton, "-text menu")
- # menu ¤òÀ¸À®¤¹¤ë.
- me1 = TclTkWidget.new(ip, mb1, menu)
- # mb1 ¤«¤é me1 ¤¬µ¯Æ°¤µ¤ì¤ë¤è¤¦¤Ë¤¹¤ë.
- mb1.e("configure -menu", me1)
-
- # cascade ¤Çµ¯Æ°¤µ¤ì¤ë menu ¤òÀ¸À®¤¹¤ë.
- me11 = TclTkWidget.new(ip, me1, menu)
- # radiobutton ¤Î¥µ¥ó¥×¥ë.
- v1 = TclTkVariable.new(ip, nil); global.e(v1); v1.set("r1")
- me11.e("add radiobutton -label radio1 -value r1 -variable", v1)
- me11.e("add radiobutton -label radio2 -value r2 -variable", v1)
- me11.e("add radiobutton -label radio3 -value r3 -variable", v1)
- # cascade ¤Ë¤è¤ê mb11 ¤¬µ¯Æ°¤µ¤ì¤ë¤è¤¦¤Ë¤¹¤ë.
- me1.e("add cascade -label cascade -menu", me11)
-
- # checkbutton ¤Î¥µ¥ó¥×¥ë.
- v2 = TclTkVariable.new(ip, nil); global.e(v2); v2.set("none")
- me1.e("add checkbutton -label check -variable", v2)
- # separator ¤Î¥µ¥ó¥×¥ë.
- me1.e("add separator")
- # command ¤Î¥µ¥ó¥×¥ë.
- v3 = nil
- cb.push(c = TclTkCallback.new(ip, proc{
- global.e(v1, v2, v3); print "v1: ", v1.get(), ", v2: ", v2.get(),
- ", v3: ", v3.get(), "\n"}))
- me1.e("add command -label print -command", c)
-
- ## tk_optionMenu
-
- v3 = TclTkVariable.new(ip, nil); global.e(v3); v3.set("opt2")
- om1 = TclTkWidget.new(ip, t1, tk_optionMenu, v3, "opt1 opt2 opt3 opt4")
-
- pack.e(b1, mb1, om1, "-side left")
- end
-
- # listbox ¤Î¥µ¥ó¥×¥ë.
- def test_listbox(ip, parent)
- clipboard, frame, grid, listbox, lower, menu, menubutton, pack, scrollbar,
- selection = ip.commands().indexes(
- "clipboard", "frame", "grid", "listbox", "lower", "menu", "menubutton",
- "pack", "scrollbar", "selection")
- t1, b1, cb = inittoplevel(ip, parent, "listbox")
-
- ## listbox/scrollbar
-
- f1 = TclTkWidget.new(ip, t1, frame)
- # ¥³¡¼¥ë¥Ð¥Ã¥¯Æâ¤Ç»²¾È¤¹¤ëÊÑ¿ô¤ÏÀè¤ËÀë¸À¤·¤Æ¤ª¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.
- li1 = sc1 = sc2 = nil
- # ¼Â¹Ô»þ¤Ë, ¸å¤í¤Ë¥Ñ¥é¥á¡¼¥¿¤¬¤Ä¤¯¥³¡¼¥ë¥Ð¥Ã¥¯¤Ï,
- # ¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤Ç¤½¤Î¥Ñ¥é¥á¡¼¥¿¤ò¼õ¤±¼è¤ë¤³¤È¤¬¤Ç¤­¤ë.
- # (Ê£¿ô¤Î¥Ñ¥é¥á¡¼¥¿¤Ï¤Ò¤È¤Ä¤Îʸ»úÎó¤Ë¤Þ¤È¤á¤é¤ì¤ë.)
- cb.push(c1 = TclTkCallback.new(ip, proc{|i| li1.e("xview", i)}))
- cb.push(c2 = TclTkCallback.new(ip, proc{|i| li1.e("yview", i)}))
- cb.push(c3 = TclTkCallback.new(ip, proc{|i| sc1.e("set", i)}))
- cb.push(c4 = TclTkCallback.new(ip, proc{|i| sc2.e("set", i)}))
- # listbox
- li1 = TclTkWidget.new(ip, f1, listbox,
- "-xscrollcommand", c3, "-yscrollcommand", c4,
- "-selectmode extended -exportselection true")
- for i in 1..20
- li1.e("insert end {line #{i} line #{i} line #{i} line #{i} line #{i}}")
- end
- # scrollbar
- sc1 = TclTkWidget.new(ip, f1, scrollbar, "-orient horizontal -command", c1)
- sc2 = TclTkWidget.new(ip, f1, scrollbar, "-orient vertical -command", c2)
-
- ## selection/clipboard
-
- mb1 = TclTkWidget.new(ip, t1, menubutton, "-text edit")
- me1 = TclTkWidget.new(ip, mb1, menu)
- mb1.e("configure -menu", me1)
- cb.push(c = TclTkCallback.new(ip, proc{
- # clipboard ¤ò¥¯¥ê¥¢.
- clipboard.e("clear")
- # selection ¤«¤éʸ»úÎó¤òÆÉ¤ß¹þ¤ß clipboard ¤ËÄɲ乤ë.
- clipboard.e("append {#{selection.e('get')}}")}))
- me1.e("add command -label {selection -> clipboard} -command",c)
- cb.push(c = TclTkCallback.new(ip, proc{
- # li1 ¤ò¥¯¥ê¥¢.
- li1.e("delete 0 end")
- # clipboard ¤«¤éʸ»úÎó¤ò¼è¤ê½Ð¤·, 1 ¹Ô¤º¤Ä
- selection.e("get -selection CLIPBOARD").split(/\n/).each{|line|
- # li1 ¤ËÁÞÆþ¤¹¤ë.
- li1.e("insert end {#{line}}")}}))
- me1.e("add command -label {clipboard -> listbox} -command",c)
-
- grid.e(li1, "-row 0 -column 0 -sticky news")
- grid.e(sc1, "-row 1 -column 0 -sticky ew")
- grid.e(sc2, "-row 0 -column 1 -sticky ns")
- grid.e("rowconfigure", f1, "0 -weight 100")
- grid.e("columnconfigure", f1, "0 -weight 100")
- f2 = TclTkWidget.new(ip, t1, frame)
- lower.e(f2, b1)
- pack.e(b1, mb1, "-in", f2, "-side left")
- pack.e(f2, f1)
- end
-
- # canvas ¤Î¥µ¥ó¥×¥ë.
- def test_canvas(ip, parent)
- canvas, lower, pack = ip.commands().indexes("canvas", "lower", "pack")
- t1, b1, cb = inittoplevel(ip, parent, "canvas")
-
- ## canvas
-
- ca1 = TclTkWidget.new(ip, t1, canvas, "-width 400 -height 300")
- lower.e(ca1, b1)
- # rectangle ¤òºî¤ë.
- idr = ca1.e("create rectangle 10 10 20 20")
- # oval ¤òºî¤ë.
- ca1.e("create oval 60 10 100 50")
- # polygon ¤òºî¤ë.
- ca1.e("create polygon 110 10 110 30 140 10")
- # line ¤òºî¤ë.
- ca1.e("create line 150 10 150 30 190 10")
- # arc ¤òºî¤ë.
- ca1.e("create arc 200 10 250 50 -start 0 -extent 90 -style pieslice")
- # i1 ¤ÏËÜÅö¤Ï, ¤É¤³¤«¤ÇÇ˲õ¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤¬, ÌÌÅݤʤΤÇÊü¤Ã¤Æ¤¢¤ë.
- i1 = TclTkImage.new(ip, "photo", "-file maru.gif")
- # image ¤òºî¤ë.
- ca1.e("create image 100 100 -image", i1)
- # bitmap ¤òºî¤ë.
- ca1.e("create bitmap 260 50 -bitmap questhead")
- # text ¤òºî¤ë.
- ca1.e("create text 320 50 -text {drag rectangle}")
- # window ¤òºî¤ë(¥¯¥í¡¼¥º¥Ü¥¿¥ó).
- ca1.e("create window 200 200 -window", b1)
-
- # bind ¤Ë¤è¤ê rectangle ¤ò drag ¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë.
- cb.push(c = TclTkCallback.new(ip, proc{|i|
- # i ¤Ë x ¤È y ¤ò¼õ¤±¼è¤ë¤Î¤Ç, ¼è¤ê½Ð¤¹.
- x, y = i.split(/ /); x = x.to_f; y = y.to_f
- # ºÂɸ¤òÊѹ¹¤¹¤ë.
- ca1.e("coords current #{x - 5} #{y - 5} #{x + 5} #{y + 5}")},
- # x, y ºÂɸ¤ò¶õÇò¤Ç¶èÀڤ俤â¤Î¤ò¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤ØÅϤ¹¤è¤¦¤Ë»ØÄê.
- "%x %y"))
- # rectangle ¤Ë bind ¤¹¤ë.
- ca1.e("bind", idr, "<B1-Motion>", c)
-
- pack.e(ca1)
- end
-end
-
-# test driver
-
-if ARGV.size == 0
- print "#{$0} n ¤Ç, n ¸Ä¤Î¥¤¥ó¥¿¥×¥ê¥¿¤òµ¯Æ°¤·¤Þ¤¹.\n"
- n = 1
-else
- n = ARGV[0].to_i
-end
-
-print "start\n"
-ip = []
-
-# ¥¤¥ó¥¿¥×¥ê¥¿, ¥¦¥£¥¸¥§¥Ã¥ÈÅù¤ÎÀ¸À®.
-for i in 1 .. n
- ip.push(Test1.new())
-end
-
-# ÍѰդ¬¤Ç¤­¤¿¤é¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ËÆþ¤ë.
-TclTk.mainloop()
-print "exit from mainloop\n"
-
-# ¥¤¥ó¥¿¥×¥ê¥¿¤¬ GC ¤µ¤ì¤ë¤«¤Î¥Æ¥¹¥È.
-ip = []
-print "GC.start\n" if $DEBUG
-GC.start() if $DEBUG
-print "end\n"
-
-exit
-
-# end
diff --git a/ext/tcltklib/sample/sample2.rb b/ext/tcltklib/sample/sample2.rb
deleted file mode 100644
index 969d8de09a..0000000000
--- a/ext/tcltklib/sample/sample2.rb
+++ /dev/null
@@ -1,449 +0,0 @@
-#!/usr/local/bin/ruby
-#----------------------> pretty simple othello game <-----------------------
-# othello.rb
-#
-# version 0.3
-# maeda shugo (shuto@po.aianet.ne.jp)
-#---------------------------------------------------------------------------
-
-# Sep. 17, 1997 modified by Y. Shigehiro for tcltk library
-# maeda shugo (shugo@po.aianet.ne.jp) »á¤Ë¤è¤ë
-# (ruby/tk ¤Ç½ñ¤«¤ì¤Æ¤¤¤¿) ruby ¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à
-# http://www.aianet.or.jp/~shugo/ruby/othello.rb.gz
-# ¤ò tcltk ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤Ë, µ¡³£Åª¤ËÊѹ¹¤·¤Æ¤ß¤Þ¤·¤¿.
-#
-# ¤Ê¤ë¤Ù¤¯¥ª¥ê¥¸¥Ê¥ë¤ÈƱ¤¸¤Ë¤Ê¤ë¤è¤¦¤Ë¤·¤Æ¤¢¤ê¤Þ¤¹.
-
-require "observer"
-require "tcltk"
-$ip = TclTkInterpreter.new()
-$root = $ip.rootwidget()
-$button, $canvas, $checkbutton, $frame, $label, $pack, $update, $wm =
- $ip.commands().indexes(
- "button", "canvas", "checkbutton", "frame", "label", "pack", "update", "wm")
-
-class Othello
-
- EMPTY = 0
- BLACK = 1
- WHITE = - BLACK
-
- attr :in_com_turn
- attr :game_over
-
- class Board
-
- include Observable
-
- DIRECTIONS = [
- [-1, -1], [-1, 0], [-1, 1],
- [ 0, -1], [ 0, 1],
- [ 1, -1], [ 1, 0], [ 1, 1]
- ]
-
- attr :com_disk, TRUE
-
- def initialize(othello)
- @othello = othello
- reset
- end
-
- def notify_observers(*arg)
- if @observer_peers != nil
- super(*arg)
- end
- end
-
- def reset
- @data = [
- [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
- [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
- [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
- [EMPTY, EMPTY, EMPTY, WHITE, BLACK, EMPTY, EMPTY, EMPTY],
- [EMPTY, EMPTY, EMPTY, BLACK, WHITE, EMPTY, EMPTY, EMPTY],
- [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
- [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
- [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY]
- ]
- changed
- notify_observers
- end
-
- def man_disk
- return - @com_disk
- end
-
- def other_disk(disk)
- return - disk
- end
-
- def get_disk(row, col)
- return @data[row][col]
- end
-
- def reverse_to(row, col, my_disk, dir_y, dir_x)
- y = row
- x = col
- begin
- y += dir_y
- x += dir_x
- if y < 0 || x < 0 || y > 7 || x > 7 ||
- @data[y][x] == EMPTY
- return
- end
- end until @data[y][x] == my_disk
- begin
- @data[y][x] = my_disk
- changed
- notify_observers(y, x)
- y -= dir_y
- x -= dir_x
- end until y == row && x == col
- end
-
- def put_disk(row, col, disk)
- @data[row][col] = disk
- changed
- notify_observers(row, col)
- DIRECTIONS.each do |dir|
- reverse_to(row, col, disk, *dir)
- end
- end
-
- def count_disk(disk)
- num = 0
- @data.each do |rows|
- rows.each do |d|
- if d == disk
- num += 1
- end
- end
- end
- return num
- end
-
- def count_point_to(row, col, my_disk, dir_y, dir_x)
- return 0 if @data[row][col] != EMPTY
- count = 0
- loop do
- row += dir_y
- col += dir_x
- break if row < 0 || col < 0 || row > 7 || col > 7
- case @data[row][col]
- when my_disk
- return count
- when other_disk(my_disk)
- count += 1
- when EMPTY
- break
- end
- end
- return 0
- end
-
- def count_point(row, col, my_disk)
- count = 0
- DIRECTIONS.each do |dir|
- count += count_point_to(row, col, my_disk, *dir)
- end
- return count
- end
-
- def corner?(row, col)
- return (row == 0 && col == 0) ||
- (row == 0 && col == 7) ||
- (row == 7 && col == 0) ||
- (row == 7 && col == 7)
- end
-
- def search(my_disk)
- max = 0
- max_row = nil
- max_col = nil
- for row in 0 .. 7
- for col in 0 .. 7
- buf = count_point(row, col, my_disk)
- if (corner?(row, col) && buf > 0) || max < buf
- max = buf
- max_row = row
- max_col = col
- end
- end
- end
- return max_row, max_col
- end
- end #--------------------------> class Board ends here
-
- class BoardView < TclTkWidget
-
- BACK_GROUND_COLOR = "DarkGreen"
- HILIT_BG_COLOR = "green"
- BORDER_COLOR = "black"
- BLACK_COLOR = "black"
- WHITE_COLOR = "white"
- STOP_COLOR = "red"
-
- attr :left
- attr :top
- attr :right
- attr :bottom
-
- class Square
-
- attr :oval, TRUE
- attr :row
- attr :col
-
- def initialize(view, row, col)
- @view = view
- @id = @view.e("create rectangle", *view.tk_rect(view.left + col,
- view.top + row,
- view.left + col + 1,
- view.top + row + 1))
- @row = row
- @col = col
- @view.e("itemconfigure", @id,
- "-width 0.5m -outline #{BORDER_COLOR}")
- @view.e("bind", @id, "<Any-Enter>", TclTkCallback.new($ip, proc{
- if @oval == nil
- view.e("itemconfigure", @id, "-fill #{HILIT_BG_COLOR}")
- end
- }))
- @view.e("bind", @id, "<Any-Leave>", TclTkCallback.new($ip, proc{
- view.e("itemconfigure", @id, "-fill #{BACK_GROUND_COLOR}")
- }))
- @view.e("bind", @id, "<ButtonRelease-1>", TclTkCallback.new($ip,
- proc{
- view.click_square(self)
- }))
- end
-
- def blink(color)
- @view.e("itemconfigure", @id, "-fill #{color}")
- $update.e()
- sleep(0.1)
- @view.e("itemconfigure", @id, "-fill #{BACK_GROUND_COLOR}")
- end
- end #-----------------------> class Square ends here
-
- def initialize(othello, board)
- super($ip, $root, $canvas)
- @othello = othello
- @board = board
- @board.add_observer(self)
-
- @squares = Array.new(8)
- for i in 0 .. 7
- @squares[i] = Array.new(8)
- end
- @left = 1
- @top = 0.5
- @right = @left + 8
- @bottom = @top + 8
-
- i = self.e("create rectangle", *tk_rect(@left, @top, @right, @bottom))
- self.e("itemconfigure", i,
- "-width 1m -outline #{BORDER_COLOR} -fill #{BACK_GROUND_COLOR}")
-
- for row in 0 .. 7
- for col in 0 .. 7
- @squares[row][col] = Square.new(self, row, col)
- end
- end
-
- update
- end
-
- def tk_rect(left, top, right, bottom)
- return left.to_s + "c", top.to_s + "c",
- right.to_s + "c", bottom.to_s + "c"
- end
-
- def clear
- each_square do |square|
- if square.oval != nil
- self.e("delete", square.oval)
- square.oval = nil
- end
- end
- end
-
- def draw_disk(row, col, disk)
- if disk == EMPTY
- if @squares[row][col].oval != nil
- self.e("delete", @squares[row][col].oval)
- @squares[row][col].oval = nil
- end
- return
- end
-
- $update.e()
- sleep(0.05)
- oval = @squares[row][col].oval
- if oval == nil
- oval = self.e("create oval", *tk_rect(@left + col + 0.2,
- @top + row + 0.2,
- @left + col + 0.8,
- @top + row + 0.8))
- @squares[row][col].oval = oval
- end
- case disk
- when BLACK
- color = BLACK_COLOR
- when WHITE
- color = WHITE_COLOR
- else
- fail format("Unknown disk type: %d", disk)
- end
- self.e("itemconfigure", oval, "-outline #{color} -fill #{color}")
- end
-
- def update(row = nil, col = nil)
- if row && col
- draw_disk(row, col, @board.get_disk(row, col))
- else
- each_square do |square|
- draw_disk(square.row, square.col,
- @board.get_disk(square.row, square.col))
- end
- end
- @othello.show_point
- end
-
- def each_square
- @squares.each do |rows|
- rows.each do |square|
- yield(square)
- end
- end
- end
-
- def click_square(square)
- if @othello.in_com_turn || @othello.game_over ||
- @board.count_point(square.row,
- square.col,
- @board.man_disk) == 0
- square.blink(STOP_COLOR)
- return
- end
- @board.put_disk(square.row, square.col, @board.man_disk)
- @othello.com_turn
- end
-
- private :draw_disk
- public :update
- end #----------------------> class BoardView ends here
-
- def initialize
- @msg_label = TclTkWidget.new($ip, $root, $label)
- $pack.e(@msg_label)
-
- @board = Board.new(self)
- @board_view = BoardView.new(self, @board)
- #### added by Y. Shigehiro
- ## board_view ¤ÎÂ礭¤µ¤òÀßÄꤹ¤ë.
- x1, y1, x2, y2 = @board_view.e("bbox all").split(/ /).collect{|i| i.to_f}
- @board_view.e("configure -width", x2 - x1)
- @board_view.e("configure -height", y2 - y1)
- ## scrollregion ¤òÀßÄꤹ¤ë.
- @board_view.e("configure -scrollregion {", @board_view.e("bbox all"),
- "}")
- #### ¤³¤³¤Þ¤Ç
- $pack.e(@board_view, "-fill both -expand true")
-
- panel = TclTkWidget.new($ip, $root, $frame)
-
- @play_black = TclTkWidget.new($ip, panel, $checkbutton,
- "-text {com is black} -command", TclTkCallback.new($ip, proc{
- switch_side
- }))
- $pack.e(@play_black, "-side left")
-
- quit = TclTkWidget.new($ip, panel, $button, "-text Quit -command",
- TclTkCallback.new($ip, proc{
- exit
- }))
- $pack.e(quit, "-side right -fill x")
-
- reset = TclTkWidget.new($ip, panel, $button, "-text Reset -command",
- TclTkCallback.new($ip, proc{
- reset_game
- }))
- $pack.e(reset, "-side right -fill x")
-
- $pack.e(panel, "-side bottom -fill x")
-
-# root = Tk.root
- $wm.e("title", $root, "Othello")
- $wm.e("iconname", $root, "Othello")
-
- @board.com_disk = WHITE
- @game_over = FALSE
-
- TclTk.mainloop
- end
-
- def switch_side
- if @in_com_turn
- @play_black.e("toggle")
- else
- @board.com_disk = @board.man_disk
- com_turn unless @game_over
- end
- end
-
- def reset_game
- if @board.com_disk == BLACK
- @board.com_disk = WHITE
- @play_black.e("toggle")
- end
- @board_view.clear
- @board.reset
- $wm.e("title", $root, "Othello")
- @game_over = FALSE
- end
-
- def com_turn
- @in_com_turn = TRUE
- $update.e()
- sleep(0.5)
- begin
- com_disk = @board.count_disk(@board.com_disk)
- man_disk = @board.count_disk(@board.man_disk)
- if @board.count_disk(EMPTY) == 0
- if man_disk == com_disk
- $wm.e("title", $root, "{Othello - Draw!}")
- elsif man_disk > com_disk
- $wm.e("title", $root, "{Othello - You Win!}")
- else
- $wm.e("title", $root, "{Othello - You Loose!}")
- end
- @game_over = TRUE
- break
- elsif com_disk == 0
- $wm.e("title", $root, "{Othello - You Win!}")
- @game_over = TRUE
- break
- elsif man_disk == 0
- $wm.e("title", $root, "{Othello - You Loose!}")
- @game_over = TRUE
- break
- end
- row, col = @board.search(@board.com_disk)
- break if row == nil || col == nil
- @board.put_disk(row, col, @board.com_disk)
- end while @board.search(@board.man_disk) == [nil, nil]
- @in_com_turn = FALSE
- end
-
- def show_point
- black = @board.count_disk(BLACK)
- white = @board.count_disk(WHITE)
- @msg_label.e("configure -text",
- %Q/{#{format("BLACK: %.2d WHITE: %.2d", black, white)}}/)
- end
-end #----------------------> class Othello ends here
-
-Othello.new
-
-#----------------------------------------------> othello.rb ends here
diff --git a/ext/tcltklib/stubs.c b/ext/tcltklib/stubs.c
deleted file mode 100644
index 56cc8ca921..0000000000
--- a/ext/tcltklib/stubs.c
+++ /dev/null
@@ -1,97 +0,0 @@
-int ruby_tcltk_stubs();
-
-#if defined USE_TCL_STUBS && defined USE_TK_STUBS
-#include "ruby.h"
-
-#if defined _WIN32 || defined __CYGWIN__
-# include "util.h"
-# include <windows.h>
- typedef HINSTANCE DL_HANDLE;
-# define DL_OPEN LoadLibrary
-# define DL_SYM GetProcAddress
-# define TCL_INDEX 4
-# define TK_INDEX 3
-# define TCL_NAME "tcl89%s"
-# define TK_NAME "tk89%s"
-# undef DLEXT
-# define DLEXT ".dll"
-#elif defined HAVE_DLOPEN
-# include <dlfcn.h>
- typedef void *DL_HANDLE;
-# define DL_OPEN(file) dlopen(file, RTLD_LAZY|RTLD_GLOBAL)
-# define DL_SYM dlsym
-# define TCL_INDEX 8
-# define TK_INDEX 7
-# define TCL_NAME "libtcl8.9%s"
-# define TK_NAME "libtk8.9%s"
-#endif
-
-#include <tcl.h>
-#include <tk.h>
-
-int
-ruby_tcltk_stubs()
-{
- DL_HANDLE tcl_dll;
- DL_HANDLE tk_dll;
- Tcl_Interp *(*p_Tcl_CreateInterp)();
- int (*p_Tk_Init) _((Tcl_Interp *));
- Tcl_Interp *tcl_ip;
- int n;
- char *ruby_tcl_dll = 0;
- char *ruby_tk_dll = 0;
- char tcl_name[20];
- char tk_name[20];
-
- ruby_tcl_dll = getenv("RUBY_TCL_DLL");
-#if defined _WIN32
- if (ruby_tcl_dll) ruby_tcl_dll = ruby_strdup(ruby_tcl_dll);
-#endif
- ruby_tk_dll = getenv("RUBY_TK_DLL");
- if (ruby_tcl_dll && ruby_tk_dll) {
- tcl_dll = (DL_HANDLE)DL_OPEN(ruby_tcl_dll);
- tk_dll = (DL_HANDLE)DL_OPEN(ruby_tk_dll);
- } else {
- snprintf(tcl_name, sizeof tcl_name, TCL_NAME, DLEXT);
- snprintf(tk_name, sizeof tk_name, TK_NAME, DLEXT);
- /* examine from 8.9 to 8.1 */
- for (n = '9'; n > '0'; n--) {
- tcl_name[TCL_INDEX] = n;
- tk_name[TK_INDEX] = n;
- tcl_dll = (DL_HANDLE)DL_OPEN(tcl_name);
- tk_dll = (DL_HANDLE)DL_OPEN(tk_name);
- if (tcl_dll && tk_dll)
- break;
- }
- }
-
-#if defined _WIN32
- if (ruby_tcl_dll) ruby_xfree(ruby_tcl_dll);
-#endif
-
- if (!tcl_dll || !tk_dll)
- return -1;
-
- p_Tcl_CreateInterp = (Tcl_Interp *(*)())DL_SYM(tcl_dll, "Tcl_CreateInterp");
- if (!p_Tcl_CreateInterp)
- return -2;
-
- tcl_ip = (*p_Tcl_CreateInterp)();
- if (!tcl_ip)
- return -3;
-
- p_Tk_Init = (int (*) _((Tcl_Interp *)))DL_SYM(tk_dll, "Tk_Init");
- if (!p_Tk_Init)
- return -4;
- (*p_Tk_Init)(tcl_ip);
-
- if (!Tcl_InitStubs(tcl_ip, "8.1", 0))
- return -5;
- if (!Tk_InitStubs(tcl_ip, "8.1", 0))
- return -6;
-
- Tcl_DeleteInterp(tcl_ip);
-
- return 0;
-}
-#endif
diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c
deleted file mode 100644
index 50c654d814..0000000000
--- a/ext/tcltklib/tcltklib.c
+++ /dev/null
@@ -1,2396 +0,0 @@
-/*
- * tcltklib.c
- * Aug. 27, 1997 Y. Shigehiro
- * Oct. 24, 1997 Y. Matsumoto
- */
-
-#include "ruby.h"
-#include "rubysig.h"
-#undef EXTERN /* avoid conflict with tcl.h of tcl8.2 or before */
-#include <stdio.h>
-#ifdef HAVE_STDARG_PROTOTYPES
-#include <stdarg.h>
-#define va_init_list(a,b) va_start(a,b)
-#else
-#include <varargs.h>
-#define va_init_list(a,b) va_start(a)
-#endif
-#include <string.h>
-#include <tcl.h>
-#include <tk.h>
-
-#ifdef __MACOS__
-# include <tkMac.h>
-# include <Quickdraw.h>
-#endif
-
-#if TCL_MAJOR_VERSION >= 8
-# ifndef CONST84
-# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 4 /* Tcl8.0.x -- 8.4b1 */
-# define CONST84
-# else /* unknown (maybe TCL_VERSION >= 8.5) */
-# ifdef CONST
-# define CONST84 CONST
-# else
-# define CONST84
-# endif
-# endif
-# endif
-#endif
-
-/* for ruby_debug */
-
-#define DUMP1(ARG1) if (ruby_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);}
-#define DUMP2(ARG1, ARG2) if (ruby_debug) { fprintf(stderr, "tcltklib: ");\
-fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); }
-/*
-#define DUMP1(ARG1)
-#define DUMP2(ARG1, ARG2)
-*/
-
-/* for callback break & continue */
-static VALUE eTkCallbackBreak;
-static VALUE eTkCallbackContinue;
-
-static VALUE ip_invoke_real _((int, VALUE*, VALUE));
-static VALUE ip_invoke _((int, VALUE*, VALUE));
-
-/* from tkAppInit.c */
-
-#if !defined __MINGW32__
-/*
- * The following variable is a special hack that is needed in order for
- * Sun shared libraries to be used for Tcl.
- */
-
-extern int matherr();
-int *tclDummyMathPtr = (int *) matherr;
-#endif
-
-/*---- module TclTkLib ----*/
-
-struct invoke_queue {
- Tcl_Event ev;
- int argc;
- VALUE *argv;
- VALUE obj;
- int done;
- int safe_level;
- VALUE *result;
- VALUE thread;
-};
-
-struct eval_queue {
- Tcl_Event ev;
- VALUE str;
- VALUE obj;
- int done;
- int safe_level;
- VALUE *result;
- VALUE thread;
-};
-
-static VALUE eventloop_thread;
-static VALUE watchdog_thread;
-Tcl_Interp *current_interp;
-
-/*
- * 'event_loop_max' is a maximum events which the eventloop processes in one
- * term of thread scheduling. 'no_event_tick' is the count-up value when
- * there are no event for processing.
- * 'timer_tick' is a limit of one term of thread scheduling.
- * If 'timer_tick' == 0, then not use the timer for thread scheduling.
- */
-#define DEFAULT_EVENT_LOOP_MAX 800/*counts*/
-#define DEFAULT_NO_EVENT_TICK 10/*counts*/
-#define DEFAULT_NO_EVENT_WAIT 20/*milliseconds ( 1 -- 999 ) */
-#define WATCHDOG_INTERVAL 10/*milliseconds ( 1 -- 999 ) */
-#define DEFAULT_TIMER_TICK 0/*milliseconds ( 0 -- 999 ) */
-#define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */
-
-static int event_loop_max = DEFAULT_EVENT_LOOP_MAX;
-static int no_event_tick = DEFAULT_NO_EVENT_TICK;
-static int no_event_wait = DEFAULT_NO_EVENT_WAIT;
-static int timer_tick = DEFAULT_TIMER_TICK;
-static int req_timer_tick = DEFAULT_TIMER_TICK;
-static int run_timer_flag = 0;
-
-static int event_loop_wait_event = 0;
-static int event_loop_abort_on_exc = 1;
-static int loop_counter = 0;
-
-static int check_rootwidget_flag = 0;
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_ruby _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
-#else
-static int ip_ruby _((ClientData, Tcl_Interp *, int, char **));
-#endif
-
-/*---- class TclTkIp ----*/
-struct tcltkip {
- Tcl_Interp *ip; /* the interpreter */
- int return_value; /* return value */
-};
-
-static struct tcltkip *
-get_ip(self)
- VALUE self;
-{
- struct tcltkip *ptr;
-
- Data_Get_Struct(self, struct tcltkip, ptr);
- if (ptr == 0) {
- rb_raise(rb_eTypeError, "uninitialized TclTkIp");
- }
- return ptr;
-}
-
-/* Tk_ThreadTimer */
-static Tcl_TimerToken timer_token = (Tcl_TimerToken)NULL;
-
-/* timer callback */
-static void _timer_for_tcl _((ClientData));
-static void
-_timer_for_tcl(clientData)
- ClientData clientData;
-{
- /* struct invoke_queue *q, *tmp; */
- /* VALUE thread; */
-
- DUMP1("called timer_for_tcl");
- Tk_DeleteTimerHandler(timer_token);
-
- run_timer_flag = 1;
-
- if (timer_tick > 0) {
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
- } else {
- timer_token = (Tcl_TimerToken)NULL;
- }
-
- /* rb_thread_schedule(); */
- /* tick_counter += event_loop_max; */
-}
-
-static VALUE
-set_eventloop_tick(self, tick)
- VALUE self;
- VALUE tick;
-{
- int ttick = NUM2INT(tick);
-
- rb_secure(4);
-
- if (ttick < 0) {
- rb_raise(rb_eArgError,
- "timer-tick parameter must be 0 or positive number");
- }
-
- /* delete old timer callback */
- Tk_DeleteTimerHandler(timer_token);
-
- timer_tick = req_timer_tick = ttick;
- if (timer_tick > 0) {
- /* start timer callback */
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
- } else {
- timer_token = (Tcl_TimerToken)NULL;
- }
-
- return tick;
-}
-
-static VALUE
-get_eventloop_tick(self)
- VALUE self;
-{
- return INT2NUM(timer_tick);
-}
-
-static VALUE
-ip_set_eventloop_tick(self, tick)
- VALUE self;
- VALUE tick;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return get_eventloop_tick(self);
- }
- return set_eventloop_tick(self, tick);
-}
-
-static VALUE
-ip_get_eventloop_tick(self)
- VALUE self;
-{
- return get_eventloop_tick(self);
-}
-
-static VALUE
-set_no_event_wait(self, wait)
- VALUE self;
- VALUE wait;
-{
- int t_wait = NUM2INT(wait);
-
- rb_secure(4);
-
- if (t_wait <= 0) {
- rb_raise(rb_eArgError,
- "no_event_wait parameter must be positive number");
- }
-
- no_event_wait = t_wait;
-
- return wait;
-}
-
-static VALUE
-get_no_event_wait(self)
- VALUE self;
-{
- return INT2NUM(no_event_wait);
-}
-
-static VALUE
-ip_set_no_event_wait(self, wait)
- VALUE self;
- VALUE wait;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return get_no_event_wait(self);
- }
- return set_no_event_wait(self, wait);
-}
-
-static VALUE
-ip_get_no_event_wait(self)
- VALUE self;
-{
- return get_no_event_wait(self);
-}
-
-static VALUE
-set_eventloop_weight(self, loop_max, no_event)
- VALUE self;
- VALUE loop_max;
- VALUE no_event;
-{
- int lpmax = NUM2INT(loop_max);
- int no_ev = NUM2INT(no_event);
-
- rb_secure(4);
-
- if (lpmax <= 0 || no_ev <= 0) {
- rb_raise(rb_eArgError, "weight parameters must be positive numbers");
- }
-
- event_loop_max = lpmax;
- no_event_tick = no_ev;
-
- return rb_ary_new3(2, loop_max, no_event);
-}
-
-static VALUE
-get_eventloop_weight(self)
- VALUE self;
-{
- return rb_ary_new3(2, INT2NUM(event_loop_max), INT2NUM(no_event_tick));
-}
-
-static VALUE
-ip_set_eventloop_weight(self, loop_max, no_event)
- VALUE self;
- VALUE loop_max;
- VALUE no_event;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return get_eventloop_weight(self);
- }
- return set_eventloop_weight(self, loop_max, no_event);
-}
-
-static VALUE
-ip_get_eventloop_weight(self)
- VALUE self;
-{
- return get_eventloop_weight(self);
-}
-
-static VALUE
-lib_evloop_abort_on_exc(self)
- VALUE self;
-{
- if (event_loop_abort_on_exc > 0) {
- return Qtrue;
- } else if (event_loop_abort_on_exc == 0) {
- return Qfalse;
- } else {
- return Qnil;
- }
-}
-
-static VALUE
-ip_evloop_abort_on_exc(self)
- VALUE self;
-{
- return lib_evloop_abort_on_exc(self);
-}
-
-static VALUE
-lib_evloop_abort_on_exc_set(self, val)
- VALUE self, val;
-{
- rb_secure(4);
- if (RTEST(val)) {
- event_loop_abort_on_exc = 1;
- } else if (val == Qnil) {
- event_loop_abort_on_exc = -1;
- } else {
- event_loop_abort_on_exc = 0;
- }
- return lib_evloop_abort_on_exc(self);
-}
-
-static VALUE
-ip_evloop_abort_on_exc_set(self, val)
- VALUE self, val;
-{
- struct tcltkip *ptr = get_ip(self);
-
- rb_secure(4);
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return lib_evloop_abort_on_exc(self);
- }
- return lib_evloop_abort_on_exc_set(self, val);
-}
-
-static VALUE
-lib_num_of_mainwindows(self)
- VALUE self;
-{
- return INT2FIX(Tk_GetNumMainWindows());
-}
-
-static int
-lib_eventloop_core(check_root, check_var)
- int check_root;
- int *check_var;
-{
- VALUE current = eventloop_thread;
- int found_event = 1;
- struct timeval t;
-
- t.tv_sec = (time_t)0;
- t.tv_usec = (time_t)(no_event_wait*1000.0);
-
- Tk_DeleteTimerHandler(timer_token);
- run_timer_flag = 0;
- if (timer_tick > 0) {
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
- } else {
- timer_token = (Tcl_TimerToken)NULL;
- }
-
- for(;;) {
- if (rb_thread_alone()) {
- DUMP1("no other thread");
- event_loop_wait_event = 0;
-
- if (timer_tick == 0) {
- timer_tick = NO_THREAD_INTERRUPT_TIME;
- timer_token = Tk_CreateTimerHandler(timer_tick,
- _timer_for_tcl,
- (ClientData)0);
- }
-
- if (check_var != (int *)NULL) {
- if (*check_var || !found_event) {
- return found_event;
- }
- }
-
- found_event = Tcl_DoOneEvent(TCL_ALL_EVENTS);
-
- if (loop_counter++ > 30000) {
- loop_counter = 0;
- }
-
- if (run_timer_flag) {
- /*
- DUMP1("timer interrupt");
- run_timer_flag = 0;
- DUMP1("call rb_trap_exec()");
- rb_trap_exec();
- */
- DUMP1("check Root Widget");
- if (check_root && Tk_GetNumMainWindows() == 0) {
- run_timer_flag = 0;
- rb_trap_exec();
- return 1;
- }
- }
-
- } else {
- int tick_counter;
-
- DUMP1("there are other threads");
- event_loop_wait_event = 1;
-
- found_event = 1;
-
- timer_tick = req_timer_tick;
- tick_counter = 0;
- while(tick_counter < event_loop_max) {
- if (check_var != (int *)NULL) {
- if (*check_var || !found_event) {
- return found_event;
- }
- }
-
- if (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT)) {
- tick_counter++;
- } else {
- tick_counter += no_event_tick;
-
- DUMP1("check Root Widget");
- if (check_root && Tk_GetNumMainWindows() == 0) {
- return 1;
- }
-
- rb_thread_wait_for(t);
- }
-
- if (loop_counter++ > 30000) {
- loop_counter = 0;
- }
-
- if (watchdog_thread != 0 && eventloop_thread != current) {
- return 1;
- }
-
- if (run_timer_flag) {
- /*
- DUMP1("timer interrupt");
- run_timer_flag = 0;
- */
- break; /* switch to other thread */
- }
- }
-
- DUMP1("check Root Widget");
- if (check_root && Tk_GetNumMainWindows() == 0) {
- return 1;
- }
- }
-
- /* rb_thread_schedule(); */
- if (run_timer_flag) {
- run_timer_flag = 0;
- rb_trap_exec();
- } else {
- DUMP1("thread scheduling");
- if (is_ruby_native_thread()) {
- rb_thread_schedule();
- }
- }
- }
- return 1;
-}
-
-VALUE
-lib_eventloop_main(check_rootwidget)
- VALUE check_rootwidget;
-{
- check_rootwidget_flag = RTEST(check_rootwidget);
-
- if (lib_eventloop_core(check_rootwidget_flag, (int *)NULL)) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-VALUE
-lib_eventloop_ensure(parent_evloop)
- VALUE parent_evloop;
-{
- Tk_DeleteTimerHandler(timer_token);
- timer_token = (Tcl_TimerToken)NULL;
- DUMP2("eventloop-ensure: current-thread : %lx\n", rb_thread_current());
- DUMP2("eventloop-ensure: eventloop-thread : %lx\n", eventloop_thread);
- if (eventloop_thread == rb_thread_current()) {
- DUMP2("eventloop-thread -> %lx\n", parent_evloop);
- eventloop_thread = parent_evloop;
- }
- return Qnil;
-}
-
-static VALUE
-lib_eventloop_launcher(check_rootwidget)
- VALUE check_rootwidget;
-{
- VALUE parent_evloop = eventloop_thread;
-
- eventloop_thread = rb_thread_current();
-
- if (ruby_debug) {
- fprintf(stderr, "tcltklib: eventloop-thread : %lx -> %lx\n",
- parent_evloop, eventloop_thread);
- }
-
- return rb_ensure(lib_eventloop_main, check_rootwidget,
- lib_eventloop_ensure, parent_evloop);
-}
-
-/* execute Tk_MainLoop */
-static VALUE
-lib_mainloop(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE check_rootwidget;
-
- if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
- check_rootwidget = Qtrue;
- } else if (RTEST(check_rootwidget)) {
- check_rootwidget = Qtrue;
- } else {
- check_rootwidget = Qfalse;
- }
-
- return lib_eventloop_launcher(check_rootwidget);
-}
-
-static VALUE
-ip_mainloop(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return Qnil;
- }
- return lib_mainloop(argc, argv, self);
-}
-
-VALUE
-lib_watchdog_core(check_rootwidget)
- VALUE check_rootwidget;
-{
- VALUE evloop;
- int prev_val = -1;
- int chance = 0;
- int check = RTEST(check_rootwidget);
- struct timeval t0, t1;
-
- t0.tv_sec = (time_t)0;
- t0.tv_usec = (time_t)((NO_THREAD_INTERRUPT_TIME)*1000.0);
- t1.tv_sec = (time_t)0;
- t1.tv_usec = (time_t)((WATCHDOG_INTERVAL)*1000.0);
-
- /* check other watchdog thread */
- if (watchdog_thread != 0) {
- if (RTEST(rb_funcall(watchdog_thread, rb_intern("stop?"), 0))) {
- rb_funcall(watchdog_thread, rb_intern("kill"), 0);
- } else {
- return Qnil;
- }
- }
- watchdog_thread = rb_thread_current();
-
- /* watchdog start */
- do {
- if (eventloop_thread == 0
- || (loop_counter == prev_val
- && RTEST(rb_funcall(eventloop_thread, rb_intern("stop?"), 0))
- && ++chance >= 3 )
- ) {
- /* start new eventloop thread */
- DUMP2("eventloop thread %lx is sleeping or dead",
- eventloop_thread);
- evloop = rb_thread_create(lib_eventloop_launcher,
- (void*)&check_rootwidget);
- DUMP2("create new eventloop thread %lx", evloop);
- loop_counter = -1;
- chance = 0;
- rb_thread_run(evloop);
- } else {
- loop_counter = prev_val;
- chance = 0;
- if (event_loop_wait_event) {
- rb_thread_wait_for(t0);
- } else {
- rb_thread_wait_for(t1);
- }
- /* rb_thread_schedule(); */
- }
- } while(!check || Tk_GetNumMainWindows() != 0);
-
- return Qnil;
-}
-
-VALUE
-lib_watchdog_ensure(arg)
- VALUE arg;
-{
- eventloop_thread = 0; /* stop eventloops */
- return Qnil;
-}
-
-static VALUE
-lib_mainloop_watchdog(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE check_rootwidget;
-
- if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
- check_rootwidget = Qtrue;
- } else if (RTEST(check_rootwidget)) {
- check_rootwidget = Qtrue;
- } else {
- check_rootwidget = Qfalse;
- }
-
- return rb_ensure(lib_watchdog_core, check_rootwidget,
- lib_watchdog_ensure, Qnil);
-}
-
-static VALUE
-ip_mainloop_watchdog(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return Qnil;
- }
- return lib_mainloop_watchdog(argc, argv, self);
-}
-
-static VALUE
-lib_do_one_event_core(argc, argv, self, is_ip)
- int argc;
- VALUE *argv;
- VALUE self;
- int is_ip;
-{
- VALUE vflags;
- int flags;
- int found_event;
-
- if (rb_scan_args(argc, argv, "01", &vflags) == 0) {
- flags = TCL_ALL_EVENTS | TCL_DONT_WAIT;
- } else {
- Check_Type(vflags, T_FIXNUM);
- flags = FIX2INT(vflags);
- }
-
- if (rb_safe_level() >= 4 || (rb_safe_level() >=1 && OBJ_TAINTED(vflags))) {
- flags |= TCL_DONT_WAIT;
- }
-
- if (is_ip) {
- /* check IP */
- struct tcltkip *ptr = get_ip(self);
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- flags |= TCL_DONT_WAIT;
- }
- }
-
- found_event = Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
-
- if (found_event) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-static VALUE
-lib_do_one_event(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- return lib_do_one_event_core(argc, argv, self, 0);
-}
-
-static VALUE
-ip_do_one_event(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- return lib_do_one_event_core(argc, argv, self, 0);
-}
-
-
-/* Tcl command `ruby' */
-static VALUE
-ip_ruby_eval_rescue(failed, einfo)
- VALUE *failed;
- VALUE einfo;
-{
- *failed = einfo;
- return Qnil;
-}
-
-struct eval_body_arg {
- char *string;
- VALUE failed;
-};
-
-static VALUE
-ip_ruby_eval_body(arg)
- struct eval_body_arg *arg;
-{
- rb_trap_immediate = 0;
- return rb_rescue2(rb_eval_string, (VALUE)arg->string,
- ip_ruby_eval_rescue, (VALUE)&(arg->failed),
- rb_eStandardError, rb_eScriptError, rb_eSystemExit,
- (VALUE)0);
-}
-
-static VALUE
-ip_ruby_eval_ensure(trapflag)
- VALUE trapflag;
-{
- rb_trap_immediate = NUM2INT(trapflag);
- return Qnil;
-}
-
-static int
-#if TCL_MAJOR_VERSION >= 8
-ip_ruby(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- Tcl_Obj *CONST argv[];
-#else
-ip_ruby(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
-#endif
-{
- VALUE res;
- int old_trapflag;
- struct eval_body_arg arg;
- int dummy;
-
- /* ruby command has 1 arg. */
- if (argc != 2) {
- rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
- }
-
- /* get C string from Tcl object */
-#if TCL_MAJOR_VERSION >= 8
- arg.string = Tcl_GetStringFromObj(argv[1], &dummy);
-#else
- arg.string = argv[1];
-#endif
- arg.failed = 0;
-
- /* evaluate the argument string by ruby */
- DUMP2("rb_eval_string(%s)", arg);
- old_trapflag = rb_trap_immediate;
- res = rb_ensure(ip_ruby_eval_body, (VALUE)&arg,
- ip_ruby_eval_ensure, INT2FIX(old_trapflag));
-
- /* status check */
- if (arg.failed) {
- VALUE eclass = CLASS_OF(arg.failed);
- DUMP1("(rb_eval_string result) failed");
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, StringValuePtr(arg.failed), (char*)NULL);
- if (eclass == eTkCallbackBreak) {
- return TCL_BREAK;
- } else if (eclass == eTkCallbackContinue) {
- return TCL_CONTINUE;
- } else if (eclass == rb_eSystemExit) {
- Tcl_Eval(interp, "destroy .");
- rb_raise(rb_eSystemExit, StringValuePtr(arg.failed));
- } else {
- return TCL_ERROR;
- }
- }
-
- /* result must be string or nil */
- if (NIL_P(res)) {
- DUMP1("(rb_eval_string result) nil");
- Tcl_ResetResult(interp);
- return TCL_OK;
- }
-
- /* copy result to the tcl interpreter */
- DUMP2("(rb_eval_string result) %s", StringValuePtr(res));
- DUMP1("Tcl_AppendResult");
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, StringValuePtr(res), (char *)NULL);
-
- return TCL_OK;
-}
-
-
-/**************************/
-/* based on tclEvent.c */
-/**************************/
-static char *VwaitVarProc _((ClientData, Tcl_Interp *, CONST84 char *,
- CONST84 char *, int));
-static char *
-VwaitVarProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST84 char *name1; /* Name of variable. */
- CONST84 char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
-{
- int *donePtr = (int *) clientData;
-
- *donePtr = 1;
- return (char *) NULL;
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rbVwaitObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rbVwaitObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else
-static int ip_rbVwaitCommand _((ClientData, Tcl_Interp *, int, char *[]));
-static int
-ip_rbVwaitCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- int done, foundEvent;
- char *nameString;
- int dummy;
-
- DUMP1("Ruby's 'vwait' is called");
- if (objc != 2) {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "name");
-#else
-#if TCL_MAJOR_VERSION >= 8
- /* nameString = Tcl_GetString(objv[0]); */
- nameString = Tcl_GetStringFromObj(objv[0], &dummy);
-#else
- nameString = objv[0];
-#endif
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- nameString, " name\"", (char *) NULL);
-#endif
- return TCL_ERROR;
- }
-#if TCL_MAJOR_VERSION >= 8
- /* nameString = Tcl_GetString(objv[1]); */
- nameString = Tcl_GetStringFromObj(objv[1], &dummy);
-#else
- nameString = objv[1];
-#endif
-
- if (Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- VwaitVarProc, (ClientData) &done) != TCL_OK) {
- return TCL_ERROR;
- };
- done = 0;
- foundEvent = lib_eventloop_core(/* not check root-widget */0, &done);
- Tcl_UntraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- VwaitVarProc, (ClientData) &done);
-
- /*
- * Clear out the interpreter's result, since it may have been set
- * by event handlers.
- */
-
- Tcl_ResetResult(interp);
- if (!foundEvent) {
- Tcl_AppendResult(interp, "can't wait for variable \"", nameString,
- "\": would wait forever", (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-
-/**************************/
-/* based on tkCmd.c */
-/**************************/
-static char *WaitVariableProc _((ClientData, Tcl_Interp *, CONST84 char *,
- CONST84 char *, int));
-static char *
-WaitVariableProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST84 char *name1; /* Name of variable. */
- CONST84 char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
-{
- int *donePtr = (int *) clientData;
-
- *donePtr = 1;
- return (char *) NULL;
-}
-
-static void WaitVisibilityProc _((ClientData, XEvent *));
-static void
-WaitVisibilityProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to integer to set to 1. */
- XEvent *eventPtr; /* Information about event (not used). */
-{
- int *donePtr = (int *) clientData;
-
- if (eventPtr->type == VisibilityNotify) {
- *donePtr = 1;
- }
- if (eventPtr->type == DestroyNotify) {
- *donePtr = 2;
- }
-}
-
-static void WaitWindowProc _((ClientData, XEvent *));
-static void
-WaitWindowProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to integer to set to 1. */
- XEvent *eventPtr; /* Information about event. */
-{
- int *donePtr = (int *) clientData;
-
- if (eventPtr->type == DestroyNotify) {
- *donePtr = 1;
- }
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rbTkWaitObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rbTkWaitObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else
-static int ip_rbTkWaitCommand _((ClientData, Tcl_Interp *, int, char *[]));
-static int
-ip_rbTkWaitCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- Tk_Window tkwin = (Tk_Window) clientData;
- int done, index;
- static CONST char *optionStrings[] = { "variable", "visibility", "window",
- (char *) NULL };
- enum options { TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW };
- char *nameString;
- int dummy;
-
- DUMP1("Ruby's 'tkwait' is called");
-
- if (objc != 3) {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "variable|visibility|window name");
-#else
-#if TCL_MAJOR_VERSION >= 8
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], &dummy),
- " variable|visibility|window name\"",
- (char *) NULL);
-#else
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- objv[0], " variable|visibility|window name\"",
- (char *) NULL);
-#endif
-#endif
- return TCL_ERROR;
- }
-
-#if TCL_MAJOR_VERSION >= 8
- if (Tcl_GetIndexFromObj(interp, objv[1],
- (CONST84 char **)optionStrings,
- "option", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
-#else
- {
- int c = objv[1][0];
- size_t length = strlen(objv[1]);
-
- if ((c == 'v') && (strncmp(objv[1], "variable", length) == 0)
- && (length >= 2)) {
- index = TKWAIT_VARIABLE;
- } else if ((c == 'v') && (strncmp(objv[1], "visibility", length) == 0)
- && (length >= 2)) {
- index = TKWAIT_VISIBILITY;
- } else if ((c == 'w') && (strncmp(objv[1], "window", length) == 0)) {
- index = TKWAIT_WINDOW;
- } else {
- Tcl_AppendResult(interp, "bad option \"", objv[1],
- "\": must be variable, visibility, or window",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
-#endif
-
-#if TCL_MAJOR_VERSION >= 8
- /* nameString = Tcl_GetString(objv[2]); */
- nameString = Tcl_GetStringFromObj(objv[2], &dummy);
-#else
- nameString = objv[2];
-#endif
-
- switch ((enum options) index) {
- case TKWAIT_VARIABLE: {
- if (Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- WaitVariableProc, (ClientData) &done) != TCL_OK) {
- return TCL_ERROR;
- }
- done = 0;
- lib_eventloop_core(check_rootwidget_flag, &done);
- Tcl_UntraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- WaitVariableProc, (ClientData) &done);
- break;
- }
-
- case TKWAIT_VISIBILITY: {
- Tk_Window window;
-
- window = Tk_NameToWindow(interp, nameString, tkwin);
- if (window == NULL) {
- return TCL_ERROR;
- }
- Tk_CreateEventHandler(window,
- VisibilityChangeMask|StructureNotifyMask,
- WaitVisibilityProc, (ClientData) &done);
- done = 0;
- lib_eventloop_core(check_rootwidget_flag, &done);
- if (done != 1) {
- /*
- * Note that we do not delete the event handler because it
- * was deleted automatically when the window was destroyed.
- */
-
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "window \"", nameString,
- "\" was deleted before its visibility changed",
- (char *) NULL);
- return TCL_ERROR;
- }
- Tk_DeleteEventHandler(window,
- VisibilityChangeMask|StructureNotifyMask,
- WaitVisibilityProc, (ClientData) &done);
- break;
- }
-
- case TKWAIT_WINDOW: {
- Tk_Window window;
-
- window = Tk_NameToWindow(interp, nameString, tkwin);
- if (window == NULL) {
- return TCL_ERROR;
- }
- Tk_CreateEventHandler(window, StructureNotifyMask,
- WaitWindowProc, (ClientData) &done);
- done = 0;
- lib_eventloop_core(check_rootwidget_flag, &done);
- /*
- * Note: there's no need to delete the event handler. It was
- * deleted automatically when the window was destroyed.
- */
- break;
- }
- }
-
- /*
- * Clear out the interpreter's result, since it may have been set
- * by event handlers.
- */
-
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-/****************************/
-/* vwait/tkwait with thread */
-/****************************/
-struct th_vwait_param {
- VALUE thread;
- int done;
-};
-
-static char *rb_threadVwaitProc _((ClientData, Tcl_Interp *, CONST84 char *,
- CONST84 char *, int));
-static char *
-rb_threadVwaitProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST84 char *name1; /* Name of variable. */
- CONST84 char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
-{
- struct th_vwait_param *param = (struct th_vwait_param *) clientData;
-
- param->done = 1;
- rb_thread_run(param->thread);
-
- return (char *)NULL;
-}
-
-static void rb_threadWaitVisibilityProc _((ClientData, XEvent *));
-static void
-rb_threadWaitVisibilityProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to integer to set to 1. */
- XEvent *eventPtr; /* Information about event (not used). */
-{
- struct th_vwait_param *param = (struct th_vwait_param *) clientData;
-
- if (eventPtr->type == VisibilityNotify) {
- param->done = 1;
- }
- if (eventPtr->type == DestroyNotify) {
- param->done = 2;
- }
-}
-
-static void rb_threadWaitWindowProc _((ClientData, XEvent *));
-static void
-rb_threadWaitWindowProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to integer to set to 1. */
- XEvent *eventPtr; /* Information about event. */
-{
- struct th_vwait_param *param = (struct th_vwait_param *) clientData;
-
- if (eventPtr->type == DestroyNotify) {
- param->done = 1;
- }
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rb_threadVwaitObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rb_threadVwaitObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else
-static int ip_rb_threadVwaitCommand _((ClientData, Tcl_Interp *, int,
- char *[]));
-static int
-ip_rb_threadVwaitCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- struct th_vwait_param *param;
- char *nameString;
- int dummy;
-
- DUMP1("Ruby's 'thread_vwait' is called");
-
- if (eventloop_thread == rb_thread_current()) {
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("call ip_rbVwaitObjCmd");
- return ip_rbVwaitObjCmd(clientData, interp, objc, objv);
-#else
- DUMP1("call ip_rbVwaitCommand");
- return ip_rbVwaitCommand(clientData, interp, objc, objv);
-#endif
- }
-
- if (objc != 2) {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "name");
-#else
-#if TCL_MAJOR_VERSION >= 8
- /* nameString = Tcl_GetString(objv[0]); */
- nameString = Tcl_GetStringFromObj(objv[0], &dummy);
-#else
- nameString = objv[0];
-#endif
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- nameString, " name\"", (char *) NULL);
-#endif
- return TCL_ERROR;
- }
-#if TCL_MAJOR_VERSION >= 8
- /* nameString = Tcl_GetString(objv[1]); */
- nameString = Tcl_GetStringFromObj(objv[1], &dummy);
-#else
- nameString = objv[1];
-#endif
-
- param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param));
- param->thread = rb_thread_current();
- param->done = 0;
-
- if (Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param) != TCL_OK) {
- return TCL_ERROR;
- };
-
- if (!param->done) {
- rb_thread_stop();
- }
-
- Tcl_UntraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param);
-
- Tcl_Free((char *)param);
-
- return TCL_OK;
-}
-
-#if TCL_MAJOR_VERSION >= 8
-static int ip_rb_threadTkWaitObjCmd _((ClientData, Tcl_Interp *, int,
- Tcl_Obj *CONST []));
-static int
-ip_rb_threadTkWaitObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
-#else
-static int ip_rb_threadTkWaitCommand _((ClientData, Tcl_Interp *, int,
- char *[]));
-static int
-ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- char *objv[];
-#endif
-{
- struct th_vwait_param *param;
- Tk_Window tkwin = (Tk_Window) clientData;
- int index;
- static CONST char *optionStrings[] = { "variable", "visibility", "window",
- (char *) NULL };
- enum options { TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW };
- char *nameString;
- int dummy;
-
- DUMP1("Ruby's 'thread_tkwait' is called");
-
- if (eventloop_thread == rb_thread_current()) {
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("call ip_rbTkWaitObjCmd");
- return ip_rbTkWaitObjCmd(clientData, interp, objc, objv);
-#else
- DUMP1("call rb_VwaitCommand");
- return ip_rbTkWaitCommand(clientData, interp, objc, objv);
-#endif
- }
-
- if (objc != 3) {
-#ifdef Tcl_WrongNumArgs
- Tcl_WrongNumArgs(interp, 1, objv, "variable|visibility|window name");
-#else
-#if TCL_MAJOR_VERSION >= 8
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetStringFromObj(objv[0], &dummy),
- " variable|visibility|window name\"",
- (char *) NULL);
-#else
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- objv[0], " variable|visibility|window name\"",
- (char *) NULL);
-#endif
-#endif
- return TCL_ERROR;
- }
-
-#if TCL_MAJOR_VERSION >= 8
- if (Tcl_GetIndexFromObj(interp, objv[1],
- (CONST84 char **)optionStrings,
- "option", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
-#else
- {
- int c = objv[1][0];
- size_t length = strlen(objv[1]);
-
- if ((c == 'v') && (strncmp(objv[1], "variable", length) == 0)
- && (length >= 2)) {
- index = TKWAIT_VARIABLE;
- } else if ((c == 'v') && (strncmp(objv[1], "visibility", length) == 0)
- && (length >= 2)) {
- index = TKWAIT_VISIBILITY;
- } else if ((c == 'w') && (strncmp(objv[1], "window", length) == 0)) {
- index = TKWAIT_WINDOW;
- } else {
- Tcl_AppendResult(interp, "bad option \"", objv[1],
- "\": must be variable, visibility, or window",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
-#endif
-
-#if TCL_MAJOR_VERSION >= 8
- /* nameString = Tcl_GetString(objv[2]); */
- nameString = Tcl_GetStringFromObj(objv[2], &dummy);
-#else
- nameString = objv[2];
-#endif
-
- param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param));
- param->thread = rb_thread_current();
- param->done = 0;
-
- switch ((enum options) index) {
- case TKWAIT_VARIABLE: {
- if (Tcl_TraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param) != TCL_OK) {
- return TCL_ERROR;
- };
-
- if (!param->done) {
- rb_thread_stop();
- }
-
- Tcl_UntraceVar(interp, nameString,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- rb_threadVwaitProc, (ClientData) param);
- break;
- }
-
- case TKWAIT_VISIBILITY: {
- Tk_Window window;
-
- window = Tk_NameToWindow(interp, nameString, tkwin);
- if (window == NULL) {
- return TCL_ERROR;
- }
- Tk_CreateEventHandler(window,
- VisibilityChangeMask|StructureNotifyMask,
- rb_threadWaitVisibilityProc, (ClientData) param);
- if (!param->done) {
- rb_thread_stop();
- }
- if (param->done != 1) {
- /*
- * Note that we do not delete the event handler because it
- * was deleted automatically when the window was destroyed.
- */
-
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "window \"", nameString,
- "\" was deleted before its visibility changed",
- (char *) NULL);
- return TCL_ERROR;
- }
- Tk_DeleteEventHandler(window,
- VisibilityChangeMask|StructureNotifyMask,
- rb_threadWaitVisibilityProc, (ClientData) param);
- break;
- }
-
- case TKWAIT_WINDOW: {
- Tk_Window window;
-
- window = Tk_NameToWindow(interp, nameString, tkwin);
- if (window == NULL) {
- return TCL_ERROR;
- }
- Tk_CreateEventHandler(window, StructureNotifyMask,
- rb_threadWaitWindowProc, (ClientData) param);
- if (!param->done) {
- rb_thread_stop();
- }
- /*
- * Note: there's no need to delete the event handler. It was
- * deleted automatically when the window was destroyed.
- */
- break;
- }
- }
-
- Tcl_Free((char *)param);
-
- /*
- * Clear out the interpreter's result, since it may have been set
- * by event handlers.
- */
-
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-static VALUE
-ip_thread_vwait(self, var)
- VALUE self;
- VALUE var;
-{
- VALUE argv[2];
-
- argv[0] = rb_str_new2("thread_vwait");
- argv[1] = var;
- return ip_invoke_real(2, argv, self);
-}
-
-static VALUE
-ip_thread_tkwait(self, mode, target)
- VALUE self;
- VALUE mode;
- VALUE target;
-{
- VALUE argv[3];
-
- argv[0] = rb_str_new2("thread_tkwait");
- argv[1] = mode;
- argv[2] = target;
- return ip_invoke_real(3, argv, self);
-}
-
-
-/* destroy interpreter */
-static void
-ip_free(ptr)
- struct tcltkip *ptr;
-{
- DUMP1("Tcl_DeleteInterp");
- if (ptr) {
- Tcl_Release((ClientData)ptr->ip);
- Tcl_DeleteInterp(ptr->ip);
- free(ptr);
- }
-}
-
-/* create and initialize interpreter */
-static VALUE ip_alloc _((VALUE));
-static VALUE
-ip_alloc(self)
- VALUE self;
-{
- return Data_Wrap_Struct(self, 0, ip_free, 0);
-}
-
-static VALUE
-ip_init(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- struct tcltkip *ptr; /* tcltkip data struct */
- VALUE argv0, opts;
- int cnt;
- int with_tk = 1;
-
- /* create object */
- Data_Get_Struct(self, struct tcltkip, ptr);
- ptr = ALLOC(struct tcltkip);
- DATA_PTR(self) = ptr;
- ptr->return_value = 0;
-
- /* from Tk_Main() */
- DUMP1("Tcl_CreateInterp");
- ptr->ip = Tcl_CreateInterp();
- Tcl_Preserve((ClientData)ptr->ip);
- current_interp = ptr->ip;
-
- /* from Tcl_AppInit() */
- DUMP1("Tcl_Init");
- if (Tcl_Init(ptr->ip) == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
- }
-
- /* set variables */
- cnt = rb_scan_args(argc, argv, "02", &argv0, &opts);
- switch(cnt) {
- case 2:
- /* options */
- if (opts == Qnil || opts == Qfalse) {
- /* without Tk */
- with_tk = 0;
- } else {
- Tcl_SetVar(ptr->ip, "argv", StringValuePtr(opts), 0);
- }
- case 1:
- /* argv0 */
- if (argv0 != Qnil) {
- Tcl_SetVar(ptr->ip, "argv0", StringValuePtr(argv0), 0);
- }
- case 0:
- /* no args */
- ;
- }
-
- /* from Tcl_AppInit() */
- if (with_tk) {
- DUMP1("Tk_Init");
- if (Tk_Init(ptr->ip) == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
- }
- DUMP1("Tcl_StaticPackage(\"Tk\")");
-#if TCL_MAJOR_VERSION >= 8
- Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit);
-#else
- Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
- (Tcl_PackageInitProc *) NULL);
-#endif
- }
-
- /* add ruby command to the interpreter */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"ruby\")");
- Tcl_CreateObjCommand(ptr->ip, "ruby", ip_ruby, (ClientData)NULL,
- (Tcl_CmdDeleteProc *)NULL);
-#else
- DUMP1("Tcl_CreateCommand(\"ruby\")");
- Tcl_CreateCommand(ptr->ip, "ruby", ip_ruby, (ClientData)NULL,
- (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- /* replace 'vwait' command */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"vwait\")");
- Tcl_CreateObjCommand(ptr->ip, "vwait", ip_rbVwaitObjCmd,
- (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
-#else
- DUMP1("Tcl_CreateCommand(\"vwait\")");
- Tcl_CreateCommand(ptr->ip, "vwait", ip_rbVwaitCommand,
- (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- /* replace 'tkwait' command */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"tkwait\")");
- Tcl_CreateObjCommand(ptr->ip, "tkwait", ip_rbTkWaitObjCmd,
- (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
-#else
- DUMP1("Tcl_CreateCommand(\"tkwait\")");
- Tcl_CreateCommand(ptr->ip, "tkwait", ip_rbTkWaitCommand,
- (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- /* add 'thread_vwait' command */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"thread_vwait\")");
- Tcl_CreateObjCommand(ptr->ip, "thread_vwait", ip_rb_threadVwaitObjCmd,
- (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
-#else
- DUMP1("Tcl_CreateCommand(\"thread_vwait\")");
- Tcl_CreateCommand(ptr->ip, "thread_vwait", ip_rb_threadVwaitCommand,
- (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- /* add 'thread_tkwait' command */
-#if TCL_MAJOR_VERSION >= 8
- DUMP1("Tcl_CreateObjCommand(\"thread_tkwait\")");
- Tcl_CreateObjCommand(ptr->ip, "thread_tkwait", ip_rb_threadTkWaitObjCmd,
- (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
-#else
- DUMP1("Tcl_CreateCommand(\"thread_tkwait\")");
- Tcl_CreateCommand(ptr->ip, "thread_tkwait", ip_rb_threadTkWaitCommand,
- (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
-#endif
-
- return self;
-}
-
-static VALUE
-ip_create_slave(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- struct tcltkip *master = get_ip(self);
- struct tcltkip *slave = ALLOC(struct tcltkip);
- VALUE name;
- VALUE safemode;
- int safe;
-
- /* safe-mode check */
- if (rb_scan_args(argc, argv, "11", &name, &safemode) == 1) {
- safemode = Qfalse;
- }
- if (Tcl_IsSafe(master->ip) == 1) {
- safe = 1;
- } else if (safemode == Qfalse || safemode == Qnil) {
- safe = 0;
- rb_secure(4);
- } else {
- safe = 1;
- }
-
- /* create slave-ip */
- if ((slave->ip = Tcl_CreateSlave(master->ip, StringValuePtr(name), safe))
- == NULL) {
- rb_raise(rb_eRuntimeError, "fail to create the new slave interpreter");
- }
- Tcl_Preserve((ClientData)slave->ip);
- slave->return_value = 0;
-
- return Data_Wrap_Struct(CLASS_OF(self), 0, ip_free, slave);
-}
-
-/* make ip "safe" */
-static VALUE
-ip_make_safe(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (Tcl_MakeSafe(ptr->ip) == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
- }
-
- return self;
-}
-
-/* is safe? */
-static VALUE
-ip_is_safe_p(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (Tcl_IsSafe(ptr->ip)) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-/* delete interpreter */
-static VALUE
-ip_delete(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- Tcl_DeleteInterp(ptr->ip);
-
- return Qnil;
-}
-
-/* is deleted? */
-static VALUE
-ip_is_deleted_p(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- if (Tcl_InterpDeleted(ptr->ip)) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-}
-
-
-/* eval string in tcl by Tcl_Eval() */
-static VALUE
-ip_eval_real(self, str)
- VALUE self;
- VALUE str;
-{
- char *s;
- char *buf; /* Tcl_Eval requires re-writable string region */
- struct tcltkip *ptr = get_ip(self);
-
- /* call Tcl_Eval() */
- s = StringValuePtr(str);
- buf = ALLOCA_N(char, strlen(s)+1);
- strcpy(buf, s);
- DUMP2("Tcl_Eval(%s)", buf);
- ptr->return_value = Tcl_Eval(ptr->ip, buf);
- if (ptr->return_value == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
- }
- DUMP2("(TCL_Eval result) %d", ptr->return_value);
-
- /* pass back the result (as string) */
- /* return(rb_str_new2(ptr->ip->result)); */
- return(rb_tainted_str_new2(ptr->ip->result));
-}
-
-static VALUE
-evq_safelevel_handler(arg, evq)
- VALUE arg;
- VALUE evq;
-{
- struct eval_queue *q;
-
- Data_Get_Struct(evq, struct eval_queue, q);
- DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
- rb_set_safe_level(q->safe_level);
- return ip_eval_real(q->obj, q->str);
-}
-
-int eval_queue_handler _((Tcl_Event *, int));
-int
-eval_queue_handler(evPtr, flags)
- Tcl_Event *evPtr;
- int flags;
-{
- struct eval_queue *q = (struct eval_queue *)evPtr;
-
- DUMP2("do_eval_queue_handler : evPtr = %lx", evPtr);
- DUMP2("eval queue_thread : %lx", rb_thread_current());
- DUMP2("added by thread : %lx", q->thread);
-
- if (q->done) {
- DUMP1("processed by another event-loop");
- return 0;
- } else {
- DUMP1("process it on current event-loop");
- }
-
- /* process it */
- q->done = 1;
-
- /* check safe-level */
- if (rb_safe_level() != q->safe_level) {
- *(q->result)
- = rb_funcall(rb_proc_new(evq_safelevel_handler,
- Data_Wrap_Struct(rb_cData,0,0,q)),
- rb_intern("call"), 0);
- } else {
- DUMP2("call eval_real (for caller thread:%lx)", q->thread);
- DUMP2("call eval_real (current thread:%lx)", rb_thread_current());
- *(q->result) = ip_eval_real(q->obj, q->str);
- }
-
- /* back to caller */
- DUMP2("back to caller (caller thread:%lx)", q->thread);
- DUMP2(" (current thread:%lx)", rb_thread_current());
- rb_thread_run(q->thread);
- DUMP1("finish back to caller");
-
- /* end of handler : remove it */
- return 1;
-}
-
-static VALUE
-ip_eval(self, str)
- VALUE self;
- VALUE str;
-{
- struct eval_queue *tmp;
- VALUE current = rb_thread_current();
- VALUE result;
- VALUE *alloc_result;
- Tcl_QueuePosition position;
-
- if (eventloop_thread == 0 || current == eventloop_thread) {
- if (eventloop_thread) {
- DUMP2("eval from current eventloop %lx", current);
- } else {
- DUMP2("eval from thread:%lx but no eventloop", current);
- }
- result = ip_eval_real(self, str);
- if (rb_obj_is_kind_of(result, rb_eException)) {
- rb_exc_raise(result);
- }
- return result;
- }
-
- DUMP2("eval from thread %lx (NOT current eventloop)", current);
-
- /* allocate memory (protected from Tcl_ServiceEvent) */
- alloc_result = ALLOC(VALUE);
-
- /* allocate memory (freed by Tcl_ServiceEvent) */
- tmp = (struct eval_queue *)Tcl_Alloc(sizeof(struct eval_queue));
-
- /* construct event data */
- tmp->done = 0;
- tmp->obj = self;
- tmp->str = str;
- tmp->result = alloc_result;
- tmp->thread = current;
- tmp->safe_level = rb_safe_level();
- tmp->ev.proc = eval_queue_handler;
- position = TCL_QUEUE_TAIL;
-
- /* add the handler to Tcl event queue */
- DUMP1("add handler");
- Tcl_QueueEvent(&(tmp->ev), position);
-
- /* wait for the handler to be processed */
- DUMP2("wait for handler (current thread:%lx)", current);
- rb_thread_stop();
- DUMP2("back from handler (current thread:%lx)", current);
-
- /* get result & free allocated memory */
- result = *alloc_result;
- free(alloc_result);
- if (rb_obj_is_kind_of(result, rb_eException)) {
- rb_exc_raise(result);
- }
-
- return result;
-}
-
-
-/* restart Tk */
-static VALUE
-lib_restart(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- rb_secure(4);
-
- /* destroy the root wdiget */
- /* ptr->return_value = Tcl_Eval(ptr->ip, "destroy ."); */
- ptr->return_value = FIX2INT(ip_eval(self, "destroy ."));
- /* ignore ERROR */
- DUMP2("(TCL_Eval result) %d", ptr->return_value);
- Tcl_ResetResult(ptr->ip);
-
- /* execute Tk_Init of Tk_SafeInit */
-#if TCL_MAJOR_VERSION >= 8
- if (Tcl_IsSafe(ptr->ip)) {
- DUMP1("Tk_SafeInit");
- if (Tk_SafeInit(ptr->ip) == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
- }
- } else {
- DUMP1("Tk_Init");
- if (Tk_Init(ptr->ip) == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
- }
- }
-#else
- DUMP1("Tk_Init");
- if (Tk_Init(ptr->ip) == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
- }
-#endif
-
- return Qnil;
-}
-
-
-static VALUE
-ip_restart(self)
- VALUE self;
-{
- struct tcltkip *ptr = get_ip(self);
-
- rb_secure(4);
- if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
- /* slave IP */
- return Qnil;
- }
- return lib_restart(self);
-}
-
-static VALUE
-ip_toUTF8(self, str, encodename)
- VALUE self;
- VALUE str;
- VALUE encodename;
-{
-#ifdef TCL_UTF_MAX
- Tcl_Interp *interp;
- Tcl_Encoding encoding;
- Tcl_DString dstr;
- struct tcltkip *ptr;
- char *buf;
-
- ptr = get_ip(self);
- interp = ptr->ip;
-
- StringValue(encodename);
- StringValue(str);
- encoding = Tcl_GetEncoding(interp, RSTRING(encodename)->ptr);
- if (!RSTRING(str)->len) return str;
- buf = ALLOCA_N(char,strlen(RSTRING(str)->ptr)+1);
- strcpy(buf, RSTRING(str)->ptr);
-
- Tcl_DStringInit(&dstr);
- Tcl_DStringFree(&dstr);
- Tcl_ExternalToUtfDString(encoding,buf,strlen(buf),&dstr);
- /* str = rb_str_new2(Tcl_DStringValue(&dstr)); */
- str = rb_tainted_str_new2(Tcl_DStringValue(&dstr));
-
- Tcl_FreeEncoding(encoding);
- Tcl_DStringFree(&dstr);
-#endif
- return str;
-}
-
-static VALUE
-ip_fromUTF8(self, str, encodename)
- VALUE self;
- VALUE str;
- VALUE encodename;
-{
-#ifdef TCL_UTF_MAX
- Tcl_Interp *interp;
- Tcl_Encoding encoding;
- Tcl_DString dstr;
- struct tcltkip *ptr;
- char *buf;
-
- ptr = get_ip(self);
- interp = ptr->ip;
-
- StringValue(encodename);
- StringValue(str);
- encoding = Tcl_GetEncoding(interp,RSTRING(encodename)->ptr);
- if (!RSTRING(str)->len) return str;
- buf = ALLOCA_N(char,strlen(RSTRING(str)->ptr)+1);
- strcpy(buf,RSTRING(str)->ptr);
-
- Tcl_DStringInit(&dstr);
- Tcl_DStringFree(&dstr);
- Tcl_UtfToExternalDString(encoding,buf,strlen(buf),&dstr);
- /* str = rb_str_new2(Tcl_DStringValue(&dstr)); */
- str = rb_tainted_str_new2(Tcl_DStringValue(&dstr));
-
- Tcl_FreeEncoding(encoding);
- Tcl_DStringFree(&dstr);
-
-#endif
- return str;
-}
-
-
-static VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-create_ip_exc(VALUE interp, VALUE exc, const char *fmt, ...)
-#else
-create_ip_exc(interp, exc, fmt, va_alist)
- VALUE interp:
- VALUE exc;
- const char *fmt;
- va_dcl
-#endif
-{
- va_list args;
- char buf[BUFSIZ];
- VALUE einfo;
-
- va_init_list(args,fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
- buf[BUFSIZ - 1] = '\0';
- va_end(args);
- einfo = rb_exc_new2(exc, buf);
- rb_iv_set(einfo, "interp", interp);
- Tcl_ResetResult(get_ip(interp)->ip);
- return einfo;
-}
-
-
-static VALUE
-ip_invoke_real(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE v;
- struct tcltkip *ptr; /* tcltkip data struct */
- int i;
- Tcl_CmdInfo info;
- char *cmd, *s;
- char **av = (char **)NULL;
-#if TCL_MAJOR_VERSION >= 8
- Tcl_Obj **ov = (Tcl_Obj **)NULL;
- Tcl_Obj *resultPtr;
-#endif
-
- DUMP2("invoke_real called by thread:%lx", rb_thread_current());
- /* get the command name string */
- v = argv[0];
- cmd = StringValuePtr(v);
-
- /* get the data struct */
- ptr = get_ip(obj);
-
- /* ip is deleted? */
- if (Tcl_InterpDeleted(ptr->ip)) {
- return rb_tainted_str_new2("");
- }
-
- /* map from the command name to a C procedure */
- DUMP2("call Tcl_GetCommandInfo, %s", cmd);
- if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) {
- DUMP1("error Tcl_GetCommandInfo");
- /* if (event_loop_abort_on_exc || cmd[0] != '.') { */
- if (event_loop_abort_on_exc > 0) {
- /*rb_ip_raise(obj,rb_eNameError,"invalid command name `%s'",cmd);*/
- return create_ip_exc(obj, rb_eNameError,
- "invalid command name `%s'", cmd);
- } else {
- if (event_loop_abort_on_exc < 0) {
- rb_warning("invalid command name `%s' (ignore)", cmd);
- } else {
- rb_warn("invalid command name `%s' (ignore)", cmd);
- }
- Tcl_ResetResult(ptr->ip);
- return rb_tainted_str_new2("");
- }
- }
- DUMP1("end Tcl_GetCommandInfo");
-
- /* memory allocation for arguments of this command */
-#if TCL_MAJOR_VERSION >= 8
- if (info.isNativeObjectProc) {
- /* object interface */
- ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1);
- for (i = 0; i < argc; ++i) {
- v = argv[i];
- s = StringValuePtr(v);
- ov[i] = Tcl_NewStringObj(s, RSTRING(v)->len);
- Tcl_IncrRefCount(ov[i]);
- }
- ov[argc] = (Tcl_Obj *)NULL;
- }
- else
-#endif
- {
- /* string interface */
- av = (char **)ALLOCA_N(char *, argc+1);
- for (i = 0; i < argc; ++i) {
- v = argv[i];
- s = StringValuePtr(v);
- av[i] = ALLOCA_N(char, strlen(s)+1);
- strcpy(av[i], s);
- }
- av[argc] = (char *)NULL;
- }
-
- Tcl_ResetResult(ptr->ip);
-
- /* Invoke the C procedure */
-#if TCL_MAJOR_VERSION >= 8
- if (info.isNativeObjectProc) {
- int dummy;
- ptr->return_value = (*info.objProc)(info.objClientData,
- ptr->ip, argc, ov);
-
- /* get the string value from the result object */
- resultPtr = Tcl_GetObjResult(ptr->ip);
- Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &dummy),
- TCL_VOLATILE);
-
- for (i=0; i<argc; i++) {
- Tcl_DecrRefCount(ov[i]);
- }
- }
- else
-#endif
- {
- TRAP_BEG;
-#if TCL_MAJOR_VERSION >= 8
- ptr->return_value = (*info.proc)(info.clientData, ptr->ip,
- argc, (CONST84 char **)av);
-#else /* TCL_MAJOR_VERSION < 8 */
- ptr->return_value = (*info.proc)(info.clientData, ptr->ip, argc, av);
-#endif
- TRAP_END;
- }
-
- /* exception on mainloop */
- if (ptr->return_value == TCL_ERROR) {
- if (event_loop_abort_on_exc > 0 && !Tcl_InterpDeleted(ptr->ip)) {
- /*rb_ip_raise(obj, rb_eRuntimeError, "%s", ptr->ip->result);*/
- return create_ip_exc(obj, rb_eRuntimeError, "%s", ptr->ip->result);
- } else {
- if (event_loop_abort_on_exc < 0) {
- rb_warning("%s (ignore)", ptr->ip->result);
- } else {
- rb_warn("%s (ignore)", ptr->ip->result);
- }
- Tcl_ResetResult(ptr->ip);
- return rb_tainted_str_new2("");
- }
- }
-
- /* pass back the result (as string) */
- /* return rb_str_new2(ptr->ip->result); */
- return rb_tainted_str_new2(ptr->ip->result);
-}
-
-VALUE
-ivq_safelevel_handler(arg, ivq)
- VALUE arg;
- VALUE ivq;
-{
- struct invoke_queue *q;
-
- Data_Get_Struct(ivq, struct invoke_queue, q);
- DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
- rb_set_safe_level(q->safe_level);
- return ip_invoke_real(q->argc, q->argv, q->obj);
-}
-
-int invoke_queue_handler _((Tcl_Event *, int));
-int
-invoke_queue_handler(evPtr, flags)
- Tcl_Event *evPtr;
- int flags;
-{
- struct invoke_queue *q = (struct invoke_queue *)evPtr;
-
- DUMP2("do_invoke_queue_handler : evPtr = %lx", evPtr);
- DUMP2("invoke queue_thread : %lx", rb_thread_current());
- DUMP2("added by thread : %lx", q->thread);
-
- if (q->done) {
- DUMP1("processed by another event-loop");
- return 0;
- } else {
- DUMP1("process it on current event-loop");
- }
-
- /* process it */
- q->done = 1;
-
- /* check safe-level */
- if (rb_safe_level() != q->safe_level) {
- *(q->result)
- = rb_funcall(rb_proc_new(ivq_safelevel_handler,
- Data_Wrap_Struct(rb_cData,0,0,q)),
- rb_intern("call"), 0);
- } else {
- DUMP2("call invoke_real (for caller thread:%lx)", q->thread);
- DUMP2("call invoke_real (current thread:%lx)", rb_thread_current());
- *(q->result) = ip_invoke_real(q->argc, q->argv, q->obj);
- }
-
- /* back to caller */
- DUMP2("back to caller (caller thread:%lx)", q->thread);
- DUMP2(" (current thread:%lx)", rb_thread_current());
- rb_thread_run(q->thread);
- DUMP1("finish back to caller");
-
- /* end of handler : remove it */
- return 1;
-}
-
-static VALUE
-ip_invoke(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- struct invoke_queue *tmp;
- VALUE current = rb_thread_current();
- VALUE result;
- VALUE *alloc_argv, *alloc_result;
- Tcl_QueuePosition position;
-
- if (argc < 1) {
- rb_raise(rb_eArgError, "command name missing");
- }
- if (eventloop_thread == 0 || current == eventloop_thread) {
- if (eventloop_thread) {
- DUMP2("invoke from current eventloop %lx", current);
- } else {
- DUMP2("invoke from thread:%lx but no eventloop", current);
- }
- result = ip_invoke_real(argc, argv, obj);
- if (rb_obj_is_kind_of(result, rb_eException)) {
- rb_exc_raise(result);
- }
- return result;
- }
-
- DUMP2("invoke from thread %lx (NOT current eventloop)", current);
-
- /* allocate memory (protected from Tcl_ServiceEvent) */
- alloc_argv = ALLOC_N(VALUE,argc);
- MEMCPY(alloc_argv, argv, VALUE, argc);
- alloc_result = ALLOC(VALUE);
-
- /* allocate memory (freed by Tcl_ServiceEvent) */
- tmp = (struct invoke_queue *)Tcl_Alloc(sizeof(struct invoke_queue));
-
- /* construct event data */
- tmp->done = 0;
- tmp->obj = obj;
- tmp->argc = argc;
- tmp->argv = alloc_argv;
- tmp->result = alloc_result;
- tmp->thread = current;
- tmp->safe_level = rb_safe_level();
- tmp->ev.proc = invoke_queue_handler;
- position = TCL_QUEUE_TAIL;
-
- /* add the handler to Tcl event queue */
- DUMP1("add handler");
- Tcl_QueueEvent(&(tmp->ev), position);
-
- /* wait for the handler to be processed */
- DUMP2("wait for handler (current thread:%lx)", current);
- rb_thread_stop();
- DUMP2("back from handler (current thread:%lx)", current);
-
- /* get result & free allocated memory */
- result = *alloc_result;
- free(alloc_argv);
- free(alloc_result);
- if (rb_obj_is_kind_of(result, rb_eException)) {
- rb_exc_raise(result);
- }
-
- return result;
-}
-
-/* get return code from Tcl_Eval() */
-static VALUE
-ip_retval(self)
- VALUE self;
-{
- struct tcltkip *ptr; /* tcltkip data struct */
-
- /* get the data strcut */
- ptr = get_ip(self);
-
- return (INT2FIX(ptr->return_value));
-}
-
-#ifdef __MACOS__
-static void
-_macinit()
-{
- tcl_macQdPtr = &qd; /* setup QuickDraw globals */
- Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
-}
-#endif
-
-/*---- initialization ----*/
-void
-Init_tcltklib()
-{
- VALUE lib = rb_define_module("TclTkLib");
- VALUE ip = rb_define_class("TclTkIp", rb_cObject);
-
- VALUE ev_flag = rb_define_module_under(lib, "EventFlag");
-
-#if defined USE_TCL_STUBS && defined USE_TK_STUBS
- extern int ruby_tcltk_stubs();
- int ret = ruby_tcltk_stubs();
- if (ret)
- rb_raise(rb_eLoadError, "tcltklib: tcltk_stubs init error(%d)", ret);
-#endif
-
- rb_define_const(ev_flag, "NONE", INT2FIX(0));
- rb_define_const(ev_flag, "WINDOW", INT2FIX(TCL_WINDOW_EVENTS));
- rb_define_const(ev_flag, "FILE", INT2FIX(TCL_FILE_EVENTS));
- rb_define_const(ev_flag, "TIMER", INT2FIX(TCL_TIMER_EVENTS));
- rb_define_const(ev_flag, "IDLE", INT2FIX(TCL_IDLE_EVENTS));
- rb_define_const(ev_flag, "ALL", INT2FIX(TCL_ALL_EVENTS));
- rb_define_const(ev_flag, "DONT_WAIT", INT2FIX(TCL_DONT_WAIT));
-
- eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError);
- eTkCallbackContinue = rb_define_class("TkCallbackContinue",
- rb_eStandardError);
-
- rb_define_module_function(lib, "mainloop", lib_mainloop, -1);
- rb_define_module_function(lib, "mainloop_watchdog",
- lib_mainloop_watchdog, -1);
- rb_define_module_function(lib, "do_one_event", lib_do_one_event, -1);
- rb_define_module_function(lib, "mainloop_abort_on_exception",
- lib_evloop_abort_on_exc, 0);
- rb_define_module_function(lib, "mainloop_abort_on_exception=",
- lib_evloop_abort_on_exc_set, 1);
- rb_define_module_function(lib, "set_eventloop_tick",set_eventloop_tick,1);
- rb_define_module_function(lib, "get_eventloop_tick",get_eventloop_tick,0);
- rb_define_module_function(lib, "set_no_event_wait", set_no_event_wait, 1);
- rb_define_module_function(lib, "get_no_event_wait", get_no_event_wait, 0);
- rb_define_module_function(lib, "set_eventloop_weight",
- set_eventloop_weight, 2);
- rb_define_module_function(lib, "get_eventloop_weight",
- get_eventloop_weight, 0);
- rb_define_module_function(lib, "num_of_mainwindows",
- lib_num_of_mainwindows, 0);
-
- rb_define_alloc_func(ip, ip_alloc);
- rb_define_method(ip, "initialize", ip_init, -1);
- rb_define_method(ip, "create_slave", ip_create_slave, -1);
- rb_define_method(ip, "make_safe", ip_make_safe, 0);
- rb_define_method(ip, "safe?", ip_is_safe_p, 0);
- rb_define_method(ip, "delete", ip_delete, 0);
- rb_define_method(ip, "deleted?", ip_is_deleted_p, 0);
- rb_define_method(ip, "_eval", ip_eval, 1);
- rb_define_method(ip, "_toUTF8",ip_toUTF8, 2);
- rb_define_method(ip, "_fromUTF8",ip_fromUTF8, 2);
- rb_define_method(ip, "_thread_vwait", ip_thread_vwait, 1);
- rb_define_method(ip, "_thread_tkwait", ip_thread_tkwait, 2);
- rb_define_method(ip, "_invoke", ip_invoke, -1);
- rb_define_method(ip, "_return_value", ip_retval, 0);
-
- rb_define_method(ip, "mainloop", ip_mainloop, -1);
- rb_define_method(ip, "mainloop_watchdog", ip_mainloop_watchdog, -1);
- rb_define_method(ip, "do_one_event", ip_do_one_event, -1);
- rb_define_method(ip, "mainloop_abort_on_exception",
- ip_evloop_abort_on_exc, 0);
- rb_define_method(ip, "mainloop_abort_on_exception=",
- ip_evloop_abort_on_exc_set, 1);
- rb_define_method(ip, "set_eventloop_tick", ip_set_eventloop_tick, 1);
- rb_define_method(ip, "get_eventloop_tick", ip_get_eventloop_tick, 0);
- rb_define_method(ip, "set_no_event_wait", ip_set_no_event_wait, 1);
- rb_define_method(ip, "get_no_event_wait", ip_get_no_event_wait, 0);
- rb_define_method(ip, "set_eventloop_weight", ip_set_eventloop_weight, 2);
- rb_define_method(ip, "get_eventloop_weight", ip_get_eventloop_weight, 0);
- rb_define_method(ip, "restart", ip_restart, 0);
-
- eventloop_thread = 0;
- watchdog_thread = 0;
-
-#ifdef __MACOS__
- _macinit();
-#endif
-
- /*---- initialize tcl/tk libraries ----*/
- /* from Tk_Main() */
- DUMP1("Tcl_FindExecutable");
- Tcl_FindExecutable(RSTRING(rb_argv0)->ptr);
-}
-
-/* eof */
diff --git a/ext/thread/extconf.rb b/ext/thread/extconf.rb
new file mode 100644
index 0000000000..2f984efc6d
--- /dev/null
+++ b/ext/thread/extconf.rb
@@ -0,0 +1,9 @@
+require 'mkmf'
+
+enable_config('fastthread', true) or exit
+
+if with_config('mem-pools', true)
+ $CPPFLAGS << ' -DUSE_MEM_POOLS'
+end
+
+create_makefile("thread")
diff --git a/ext/thread/lib/thread.rb b/ext/thread/lib/thread.rb
new file mode 100644
index 0000000000..6c533aba39
--- /dev/null
+++ b/ext/thread/lib/thread.rb
@@ -0,0 +1,5 @@
+unless defined? Thread
+ fail "Thread not available for this ruby interpreter"
+end
+
+require 'thread.so'
diff --git a/ext/thread/thread.c b/ext/thread/thread.c
new file mode 100644
index 0000000000..68f172220a
--- /dev/null
+++ b/ext/thread/thread.c
@@ -0,0 +1,1182 @@
+/*
+ * Optimized Ruby Mutex implementation, loosely based on thread.rb by
+ * Yukihiro Matsumoto <matz@ruby-lang.org>
+ *
+ * Copyright 2006-2007 MenTaLguY <mental@rydia.net>
+ *
+ * RDoc taken from original.
+ *
+ * This file is made available under the same terms as Ruby.
+ */
+
+#include <ruby.h>
+#include <intern.h>
+#include <rubysig.h>
+
+static VALUE rb_cMutex;
+static VALUE rb_cConditionVariable;
+static VALUE rb_cQueue;
+static VALUE rb_cSizedQueue;
+
+static VALUE set_critical(VALUE value);
+
+static VALUE
+thread_exclusive(VALUE (*func)(ANYARGS), VALUE arg)
+{
+ VALUE critical = rb_thread_critical;
+
+ rb_thread_critical = 1;
+ return rb_ensure(func, arg, set_critical, (VALUE)critical);
+}
+
+/*
+ * call-seq:
+ * Thread.exclusive { block } => obj
+ *
+ * Wraps a block in Thread.critical, restoring the original value
+ * upon exit from the critical section, and returns the value of the
+ * block.
+ */
+
+static VALUE
+rb_thread_exclusive(void)
+{
+ return thread_exclusive(rb_yield, Qundef);
+}
+
+typedef struct _Entry {
+ VALUE value;
+ struct _Entry *next;
+} Entry;
+
+typedef struct _List {
+ Entry *entries;
+ Entry *last_entry;
+ Entry *entry_pool;
+ unsigned long size;
+} List;
+
+static void
+init_list(List *list)
+{
+ list->entries = NULL;
+ list->last_entry = NULL;
+ list->entry_pool = NULL;
+ list->size = 0;
+}
+
+static void
+mark_list(List *list)
+{
+ Entry *entry;
+ for (entry = list->entries; entry; entry = entry->next) {
+ rb_gc_mark(entry->value);
+ }
+}
+
+static void
+free_entries(Entry *first)
+{
+ Entry *next;
+ while (first) {
+ next = first->next;
+ xfree(first);
+ first = next;
+ }
+}
+
+static void
+finalize_list(List *list)
+{
+ free_entries(list->entries);
+ free_entries(list->entry_pool);
+}
+
+static void
+push_list(List *list, VALUE value)
+{
+ Entry *entry;
+
+ if (list->entry_pool) {
+ entry = list->entry_pool;
+ list->entry_pool = entry->next;
+ } else {
+ entry = ALLOC(Entry);
+ }
+
+ entry->value = value;
+ entry->next = NULL;
+
+ if (list->last_entry) {
+ list->last_entry->next = entry;
+ } else {
+ list->entries = entry;
+ }
+ list->last_entry = entry;
+
+ ++list->size;
+}
+
+static void
+push_multiple_list(List *list, VALUE *values, unsigned count)
+{
+ unsigned i;
+ for (i = 0; i < count; i++) {
+ push_list(list, values[i]);
+ }
+}
+
+static void
+recycle_entries(List *list, Entry *first_entry, Entry *last_entry)
+{
+#ifdef USE_MEM_POOLS
+ last_entry->next = list->entry_pool;
+ list->entry_pool = first_entry;
+#else
+ last_entry->next = NULL;
+ free_entries(first_entry);
+#endif
+}
+
+static VALUE
+shift_list(List *list)
+{
+ Entry *entry;
+ VALUE value;
+
+ entry = list->entries;
+ if (!entry) return Qnil;
+
+ list->entries = entry->next;
+ if (entry == list->last_entry) {
+ list->last_entry = NULL;
+ }
+
+ --list->size;
+
+ value = entry->value;
+ recycle_entries(list, entry, entry);
+
+ return value;
+}
+
+static void
+remove_one(List *list, VALUE value)
+{
+ Entry **ref;
+ Entry *prev;
+ Entry *entry;
+
+ for (ref = &list->entries, prev = NULL, entry = list->entries;
+ entry != NULL;
+ ref = &entry->next, prev = entry, entry = entry->next) {
+ if (entry->value == value) {
+ *ref = entry->next;
+ list->size--;
+ if (!entry->next) {
+ list->last_entry = prev;
+ }
+ recycle_entries(list, entry, entry);
+ break;
+ }
+ }
+}
+
+static void
+clear_list(List *list)
+{
+ if (list->last_entry) {
+ recycle_entries(list, list->entries, list->last_entry);
+ list->entries = NULL;
+ list->last_entry = NULL;
+ list->size = 0;
+ }
+}
+
+static VALUE
+array_from_list(List const *list)
+{
+ VALUE ary;
+ Entry *entry;
+ ary = rb_ary_new();
+ for (entry = list->entries; entry; entry = entry->next) {
+ rb_ary_push(ary, entry->value);
+ }
+ return ary;
+}
+
+static VALUE
+wake_thread(VALUE thread)
+{
+ return rb_thread_wakeup_alive(thread);
+}
+
+static VALUE
+run_thread(VALUE thread)
+{
+ thread = wake_thread(thread);
+ if (RTEST(thread) && !rb_thread_critical)
+ rb_thread_schedule();
+ return thread;
+}
+
+static VALUE
+wake_one(List *list)
+{
+ VALUE waking;
+
+ waking = Qnil;
+ while (list->entries && !RTEST(waking)) {
+ waking = wake_thread(shift_list(list));
+ }
+
+ return waking;
+}
+
+static VALUE
+wake_all(List *list)
+{
+ while (list->entries) {
+ wake_one(list);
+ }
+ return Qnil;
+}
+
+static VALUE
+wait_list_inner(List *list)
+{
+ push_list(list, rb_thread_current());
+ rb_thread_stop();
+ return Qnil;
+}
+
+static VALUE
+wait_list_cleanup(List *list)
+{
+ /* cleanup in case of spurious wakeups */
+ remove_one(list, rb_thread_current());
+ return Qnil;
+}
+
+static VALUE
+wait_list(List *list)
+{
+ return rb_ensure(wait_list_inner, (VALUE)list, wait_list_cleanup, (VALUE)list);
+}
+
+static void
+kill_waiting_threads(List *waiting)
+{
+ Entry *entry;
+
+ for (entry = waiting->entries; entry; entry = entry->next) {
+ rb_thread_kill(entry->value);
+ }
+}
+
+/*
+ * Document-class: Mutex
+ *
+ * Mutex implements a simple semaphore that can be used to coordinate access to
+ * shared data from multiple concurrent threads.
+ *
+ * Example:
+ *
+ * require 'thread'
+ * semaphore = Mutex.new
+ *
+ * a = Thread.new {
+ * semaphore.synchronize {
+ * # access shared resource
+ * }
+ * }
+ *
+ * b = Thread.new {
+ * semaphore.synchronize {
+ * # access shared resource
+ * }
+ * }
+ *
+ */
+
+typedef struct _Mutex {
+ VALUE owner;
+ List waiting;
+} Mutex;
+
+#define MUTEX_LOCKED_P(mutex) (RTEST((mutex)->owner) && rb_thread_alive_p((mutex)->owner))
+
+static void
+mark_mutex(Mutex *mutex)
+{
+ rb_gc_mark(mutex->owner);
+ mark_list(&mutex->waiting);
+}
+
+static void
+finalize_mutex(Mutex *mutex)
+{
+ finalize_list(&mutex->waiting);
+}
+
+static void
+free_mutex(Mutex *mutex)
+{
+ kill_waiting_threads(&mutex->waiting);
+ finalize_mutex(mutex);
+ xfree(mutex);
+}
+
+static void
+init_mutex(Mutex *mutex)
+{
+ mutex->owner = Qnil;
+ init_list(&mutex->waiting);
+}
+
+/*
+ * Document-method: new
+ * call-seq: Mutex.new
+ *
+ * Creates a new Mutex
+ *
+ */
+
+static VALUE
+rb_mutex_alloc(VALUE klass)
+{
+ Mutex *mutex;
+ mutex = ALLOC(Mutex);
+ init_mutex(mutex);
+ return Data_Wrap_Struct(klass, mark_mutex, free_mutex, mutex);
+}
+
+/*
+ * Document-method: locked?
+ * call-seq: locked?
+ *
+ * Returns +true+ if this lock is currently held by some thread.
+ *
+ */
+
+static VALUE
+rb_mutex_locked_p(VALUE self)
+{
+ Mutex *mutex;
+ Data_Get_Struct(self, Mutex, mutex);
+ return MUTEX_LOCKED_P(mutex) ? Qtrue : Qfalse;
+}
+
+/*
+ * Document-method: try_lock
+ * call-seq: try_lock
+ *
+ * Attempts to obtain the lock and returns immediately. Returns +true+ if the
+ * lock was granted.
+ *
+ */
+
+static VALUE
+rb_mutex_try_lock(VALUE self)
+{
+ Mutex *mutex;
+
+ Data_Get_Struct(self, Mutex, mutex);
+
+ if (MUTEX_LOCKED_P(mutex))
+ return Qfalse;
+
+ mutex->owner = rb_thread_current();
+ return Qtrue;
+}
+
+/*
+ * Document-method: lock
+ * call-seq: lock
+ *
+ * Attempts to grab the lock and waits if it isn't available.
+ *
+ */
+
+static VALUE
+lock_mutex(Mutex *mutex)
+{
+ VALUE current;
+ current = rb_thread_current();
+
+ rb_thread_critical = 1;
+
+ if (!MUTEX_LOCKED_P(mutex)) {
+ mutex->owner = current;
+ }
+ else {
+ do {
+ wait_list(&mutex->waiting);
+ rb_thread_critical = 1;
+ if (!MUTEX_LOCKED_P(mutex)) {
+ mutex->owner = current;
+ break;
+ }
+ } while (mutex->owner != current);
+ }
+
+ rb_thread_critical = 0;
+ return Qnil;
+}
+
+static VALUE
+rb_mutex_lock(VALUE self)
+{
+ Mutex *mutex;
+ Data_Get_Struct(self, Mutex, mutex);
+ lock_mutex(mutex);
+ return self;
+}
+
+/*
+ * Document-method: unlock
+ *
+ * Releases the lock. Returns +nil+ if ref wasn't locked.
+ *
+ */
+
+static VALUE
+unlock_mutex_inner(Mutex *mutex)
+{
+ VALUE waking;
+
+ if (mutex->owner != rb_thread_current()) {
+ rb_raise(rb_eThreadError, "not owner");
+ }
+
+ waking = wake_one(&mutex->waiting);
+ mutex->owner = waking;
+
+ return waking;
+}
+
+static VALUE
+set_critical(VALUE value)
+{
+ rb_thread_critical = (int)value;
+ return Qundef;
+}
+
+static VALUE
+unlock_mutex(Mutex *mutex)
+{
+ VALUE waking = thread_exclusive(unlock_mutex_inner, (VALUE)mutex);
+
+ if (!RTEST(waking)) {
+ return Qfalse;
+ }
+
+ run_thread(waking);
+
+ return Qtrue;
+}
+
+static VALUE
+rb_mutex_unlock(VALUE self)
+{
+ Mutex *mutex;
+ Data_Get_Struct(self, Mutex, mutex);
+
+ if (RTEST(unlock_mutex(mutex))) {
+ return self;
+ } else {
+ return Qnil;
+ }
+}
+
+/*
+ * Document-method: exclusive_unlock
+ * call-seq: exclusive_unlock { ... }
+ *
+ * If the mutex is locked, unlocks the mutex, wakes one waiting thread, and
+ * yields in a critical section.
+ *
+ */
+
+static VALUE
+rb_mutex_exclusive_unlock_inner(Mutex *mutex)
+{
+ VALUE waking;
+ waking = unlock_mutex_inner(mutex);
+ rb_yield(Qundef);
+ return waking;
+}
+
+static VALUE
+rb_mutex_exclusive_unlock(VALUE self)
+{
+ Mutex *mutex;
+ VALUE waking;
+ Data_Get_Struct(self, Mutex, mutex);
+
+ waking = thread_exclusive(rb_mutex_exclusive_unlock_inner, (VALUE)mutex);
+
+ if (!RTEST(waking)) {
+ return Qnil;
+ }
+
+ run_thread(waking);
+
+ return self;
+}
+
+/*
+ * Document-method: synchronize
+ * call-seq: synchronize { ... }
+ *
+ * Obtains a lock, runs the block, and releases the lock when the block
+ * completes. See the example under Mutex.
+ *
+ */
+
+static VALUE
+rb_mutex_synchronize(VALUE self)
+{
+ rb_mutex_lock(self);
+ return rb_ensure(rb_yield, Qundef, rb_mutex_unlock, self);
+}
+
+/*
+ * Document-class: ConditionVariable
+ *
+ * ConditionVariable objects augment class Mutex. Using condition variables,
+ * it is possible to suspend while in the middle of a critical section until a
+ * resource becomes available.
+ *
+ * Example:
+ *
+ * require 'thread'
+ *
+ * mutex = Mutex.new
+ * resource = ConditionVariable.new
+ *
+ * a = Thread.new {
+ * mutex.synchronize {
+ * # Thread 'a' now needs the resource
+ * resource.wait(mutex)
+ * # 'a' can now have the resource
+ * }
+ * }
+ *
+ * b = Thread.new {
+ * mutex.synchronize {
+ * # Thread 'b' has finished using the resource
+ * resource.signal
+ * }
+ * }
+ *
+ */
+
+typedef struct _ConditionVariable {
+ List waiting;
+} ConditionVariable;
+
+static void
+mark_condvar(ConditionVariable *condvar)
+{
+ mark_list(&condvar->waiting);
+}
+
+static void
+finalize_condvar(ConditionVariable *condvar)
+{
+ finalize_list(&condvar->waiting);
+}
+
+static void
+free_condvar(ConditionVariable *condvar)
+{
+ kill_waiting_threads(&condvar->waiting);
+ finalize_condvar(condvar);
+ xfree(condvar);
+}
+
+static void
+init_condvar(ConditionVariable *condvar)
+{
+ init_list(&condvar->waiting);
+}
+
+/*
+ * Document-method: new
+ * call-seq: ConditionVariable.new
+ *
+ * Creates a new ConditionVariable
+ *
+ */
+
+static VALUE
+rb_condvar_alloc(VALUE klass)
+{
+ ConditionVariable *condvar;
+
+ condvar = ALLOC(ConditionVariable);
+ init_condvar(condvar);
+
+ return Data_Wrap_Struct(klass, mark_condvar, free_condvar, condvar);
+}
+
+/*
+ * Document-method: wait
+ * call-seq: wait
+ *
+ * Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
+ *
+ */
+
+static void
+wait_condvar(ConditionVariable *condvar, Mutex *mutex)
+{
+ VALUE waking;
+
+ rb_thread_critical = 1;
+ if (rb_thread_current() != mutex->owner) {
+ rb_thread_critical = 0;
+ rb_raise(rb_eThreadError, "not owner of the synchronization mutex");
+ }
+ waking = unlock_mutex_inner(mutex);
+ if (RTEST(waking)) {
+ wake_thread(waking);
+ }
+ rb_ensure(wait_list, (VALUE)&condvar->waiting, lock_mutex, (VALUE)mutex);
+}
+
+static VALUE
+legacy_exclusive_unlock(VALUE mutex)
+{
+ return rb_funcall(mutex, rb_intern("exclusive_unlock"), 0);
+}
+
+typedef struct {
+ ConditionVariable *condvar;
+ VALUE mutex;
+} legacy_wait_args;
+
+static VALUE
+legacy_wait(VALUE unused, legacy_wait_args *args)
+{
+ wait_list(&args->condvar->waiting);
+ rb_funcall(args->mutex, rb_intern("lock"), 0);
+ return Qnil;
+}
+
+static VALUE
+rb_condvar_wait(VALUE self, VALUE mutex_v)
+{
+ ConditionVariable *condvar;
+ Data_Get_Struct(self, ConditionVariable, condvar);
+
+ if (CLASS_OF(mutex_v) != rb_cMutex) {
+ /* interoperate with legacy mutex */
+ legacy_wait_args args;
+ args.condvar = condvar;
+ args.mutex = mutex_v;
+ rb_iterate(legacy_exclusive_unlock, mutex_v, legacy_wait, (VALUE)&args);
+ } else {
+ Mutex *mutex;
+ Data_Get_Struct(mutex_v, Mutex, mutex);
+ wait_condvar(condvar, mutex);
+ }
+
+ return self;
+}
+
+/*
+ * Document-method: broadcast
+ * call-seq: broadcast
+ *
+ * Wakes up all threads waiting for this condition.
+ *
+ */
+
+static VALUE
+rb_condvar_broadcast(VALUE self)
+{
+ ConditionVariable *condvar;
+
+ Data_Get_Struct(self, ConditionVariable, condvar);
+
+ thread_exclusive(wake_all, (VALUE)&condvar->waiting);
+ rb_thread_schedule();
+
+ return self;
+}
+
+/*
+ * Document-method: signal
+ * call-seq: signal
+ *
+ * Wakes up the first thread in line waiting for this condition.
+ *
+ */
+
+static void
+signal_condvar(ConditionVariable *condvar)
+{
+ VALUE waking = thread_exclusive(wake_one, (VALUE)&condvar->waiting);
+
+ if (RTEST(waking)) {
+ run_thread(waking);
+ }
+}
+
+static VALUE
+rb_condvar_signal(VALUE self)
+{
+ ConditionVariable *condvar;
+ Data_Get_Struct(self, ConditionVariable, condvar);
+ signal_condvar(condvar);
+ return self;
+}
+
+/*
+ * Document-class: Queue
+ *
+ * This class provides a way to synchronize communication between threads.
+ *
+ * Example:
+ *
+ * require 'thread'
+ *
+ * queue = Queue.new
+ *
+ * producer = Thread.new do
+ * 5.times do |i|
+ * sleep rand(i) # simulate expense
+ * queue << i
+ * puts "#{i} produced"
+ * end
+ * end
+ *
+ * consumer = Thread.new do
+ * 5.times do |i|
+ * value = queue.pop
+ * sleep rand(i/2) # simulate expense
+ * puts "consumed #{value}"
+ * end
+ * end
+ *
+ * consumer.join
+ *
+ */
+
+typedef struct _Queue {
+ Mutex mutex;
+ ConditionVariable value_available;
+ ConditionVariable space_available;
+ List values;
+ unsigned long capacity;
+} Queue;
+
+static void
+mark_queue(Queue *queue)
+{
+ mark_mutex(&queue->mutex);
+ mark_condvar(&queue->value_available);
+ mark_condvar(&queue->space_available);
+ mark_list(&queue->values);
+}
+
+static void
+finalize_queue(Queue *queue)
+{
+ finalize_mutex(&queue->mutex);
+ finalize_condvar(&queue->value_available);
+ finalize_condvar(&queue->space_available);
+ finalize_list(&queue->values);
+}
+
+static void
+free_queue(Queue *queue)
+{
+ kill_waiting_threads(&queue->mutex.waiting);
+ kill_waiting_threads(&queue->space_available.waiting);
+ kill_waiting_threads(&queue->value_available.waiting);
+ finalize_queue(queue);
+ xfree(queue);
+}
+
+static void
+init_queue(Queue *queue)
+{
+ init_mutex(&queue->mutex);
+ init_condvar(&queue->value_available);
+ init_condvar(&queue->space_available);
+ init_list(&queue->values);
+ queue->capacity = 0;
+}
+
+/*
+ * Document-method: new
+ * call-seq: new
+ *
+ * Creates a new queue.
+ *
+ */
+
+static VALUE
+rb_queue_alloc(VALUE klass)
+{
+ Queue *queue;
+ queue = ALLOC(Queue);
+ init_queue(queue);
+ return Data_Wrap_Struct(klass, mark_queue, free_queue, queue);
+}
+
+static VALUE
+rb_queue_marshal_load(VALUE self, VALUE data)
+{
+ Queue *queue;
+ VALUE array;
+ Data_Get_Struct(self, Queue, queue);
+
+ array = rb_marshal_load(data);
+ if (TYPE(array) != T_ARRAY) {
+ rb_raise(rb_eTypeError, "expected Array of queue data");
+ }
+ if (RARRAY(array)->len < 1) {
+ rb_raise(rb_eArgError, "missing capacity value");
+ }
+ queue->capacity = NUM2ULONG(rb_ary_shift(array));
+ push_multiple_list(&queue->values, RARRAY(array)->ptr, (unsigned)RARRAY(array)->len);
+
+ return self;
+}
+
+static VALUE
+rb_queue_marshal_dump(VALUE self)
+{
+ Queue *queue;
+ VALUE array;
+ Data_Get_Struct(self, Queue, queue);
+
+ array = array_from_list(&queue->values);
+ rb_ary_unshift(array, ULONG2NUM(queue->capacity));
+ return rb_marshal_dump(array, Qnil);
+}
+
+/*
+ * Document-method: clear
+ * call-seq: clear
+ *
+ * Removes all objects from the queue.
+ *
+ */
+
+static VALUE
+rb_queue_clear(VALUE self)
+{
+ Queue *queue;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ clear_list(&queue->values);
+ signal_condvar(&queue->space_available);
+ unlock_mutex(&queue->mutex);
+
+ return self;
+}
+
+/*
+ * Document-method: empty?
+ * call-seq: empty?
+ *
+ * Returns +true+ if the queue is empty.
+ *
+ */
+
+static VALUE
+rb_queue_empty_p(VALUE self)
+{
+ Queue *queue;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ result = queue->values.size == 0 ? Qtrue : Qfalse;
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: length
+ * call-seq: length
+ *
+ * Returns the length of the queue.
+ *
+ */
+
+static VALUE
+rb_queue_length(VALUE self)
+{
+ Queue *queue;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ result = ULONG2NUM(queue->values.size);
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: num_waiting
+ * call-seq: num_waiting
+ *
+ * Returns the number of threads waiting on the queue.
+ *
+ */
+
+static VALUE
+rb_queue_num_waiting(VALUE self)
+{
+ Queue *queue;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ result = ULONG2NUM(queue->value_available.waiting.size +
+ queue->space_available.waiting.size);
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: pop
+ * call_seq: pop(non_block=false)
+ *
+ * Retrieves data from the queue. If the queue is empty, the calling thread is
+ * suspended until data is pushed onto the queue. If +non_block+ is true, the
+ * thread isn't suspended, and an exception is raised.
+ *
+ */
+
+static VALUE
+rb_queue_pop(int argc, VALUE *argv, VALUE self)
+{
+ Queue *queue;
+ int should_block;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ if (argc == 0) {
+ should_block = 1;
+ } else if (argc == 1) {
+ should_block = !RTEST(argv[0]);
+ } else {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
+ }
+
+ lock_mutex(&queue->mutex);
+ if (!queue->values.entries && !should_block) {
+ unlock_mutex(&queue->mutex);
+ rb_raise(rb_eThreadError, "queue empty");
+ }
+
+ while (!queue->values.entries) {
+ wait_condvar(&queue->value_available, &queue->mutex);
+ }
+
+ result = shift_list(&queue->values);
+ if (queue->capacity && queue->values.size < queue->capacity) {
+ signal_condvar(&queue->space_available);
+ }
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: push
+ * call-seq: push(obj)
+ *
+ * Pushes +obj+ to the queue.
+ *
+ */
+
+static VALUE
+rb_queue_push(VALUE self, VALUE value)
+{
+ Queue *queue;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ while (queue->capacity && queue->values.size >= queue->capacity) {
+ wait_condvar(&queue->space_available, &queue->mutex);
+ }
+ push_list(&queue->values, value);
+ signal_condvar(&queue->value_available);
+ unlock_mutex(&queue->mutex);
+
+ return self;
+}
+
+/*
+ * Document-class: SizedQueue
+ *
+ * This class represents queues of specified size capacity. The push operation
+ * may be blocked if the capacity is full.
+ *
+ * See Queue for an example of how a SizedQueue works.
+ *
+ */
+
+/*
+ * Document-method: new
+ * call-seq: new
+ *
+ * Creates a fixed-length queue with a maximum size of +max+.
+ *
+ */
+
+/*
+ * Document-method: max
+ * call-seq: max
+ *
+ * Returns the maximum size of the queue.
+ *
+ */
+
+static VALUE
+rb_sized_queue_max(VALUE self)
+{
+ Queue *queue;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ result = ULONG2NUM(queue->capacity);
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: max=
+ * call-seq: max=(size)
+ *
+ * Sets the maximum size of the queue.
+ *
+ */
+
+static VALUE
+rb_sized_queue_max_set(VALUE self, VALUE value)
+{
+ Queue *queue;
+ unsigned long new_capacity;
+ unsigned long difference;
+ Data_Get_Struct(self, Queue, queue);
+
+ new_capacity = NUM2ULONG(value);
+
+ if (new_capacity < 1) {
+ rb_raise(rb_eArgError, "value must be positive");
+ }
+
+ lock_mutex(&queue->mutex);
+ if (queue->capacity && new_capacity > queue->capacity) {
+ difference = new_capacity - queue->capacity;
+ } else {
+ difference = 0;
+ }
+ queue->capacity = new_capacity;
+ for (; difference > 0; --difference) {
+ signal_condvar(&queue->space_available);
+ }
+ unlock_mutex(&queue->mutex);
+
+ return self;
+}
+
+/*
+ * Document-method: push
+ * call-seq: push(obj)
+ *
+ * Pushes +obj+ to the queue. If there is no space left in the queue, waits
+ * until space becomes available.
+ *
+ */
+
+/*
+ * Document-method: pop
+ * call-seq: pop(non_block=false)
+ *
+ * Retrieves data from the queue and runs a waiting thread, if any.
+ *
+ */
+
+/* for marshalling mutexes and condvars */
+
+static VALUE
+dummy_load(VALUE self, VALUE string)
+{
+ return Qnil;
+}
+
+static VALUE
+dummy_dump(VALUE self)
+{
+ return rb_str_new2("");
+}
+
+void
+Init_thread(void)
+{
+ rb_define_singleton_method(rb_cThread, "exclusive", rb_thread_exclusive, 0);
+
+ rb_cMutex = rb_define_class("Mutex", rb_cObject);
+ rb_define_alloc_func(rb_cMutex, rb_mutex_alloc);
+ rb_define_method(rb_cMutex, "marshal_load", dummy_load, 1);
+ rb_define_method(rb_cMutex, "marshal_dump", dummy_dump, 0);
+ rb_define_method(rb_cMutex, "locked?", rb_mutex_locked_p, 0);
+ rb_define_method(rb_cMutex, "try_lock", rb_mutex_try_lock, 0);
+ rb_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
+ rb_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
+ rb_define_method(rb_cMutex, "exclusive_unlock", rb_mutex_exclusive_unlock, 0);
+ rb_define_method(rb_cMutex, "synchronize", rb_mutex_synchronize, 0);
+
+ rb_cConditionVariable = rb_define_class("ConditionVariable", rb_cObject);
+ rb_define_alloc_func(rb_cConditionVariable, rb_condvar_alloc);
+ rb_define_method(rb_cConditionVariable, "marshal_load", dummy_load, 1);
+ rb_define_method(rb_cConditionVariable, "marshal_dump", dummy_dump, 0);
+ rb_define_method(rb_cConditionVariable, "wait", rb_condvar_wait, 1);
+ rb_define_method(rb_cConditionVariable, "broadcast", rb_condvar_broadcast, 0);
+ rb_define_method(rb_cConditionVariable, "signal", rb_condvar_signal, 0);
+
+ rb_cQueue = rb_define_class("Queue", rb_cObject);
+ rb_define_alloc_func(rb_cQueue, rb_queue_alloc);
+ rb_define_method(rb_cQueue, "marshal_load", rb_queue_marshal_load, 1);
+ rb_define_method(rb_cQueue, "marshal_dump", rb_queue_marshal_dump, 0);
+ rb_define_method(rb_cQueue, "clear", rb_queue_clear, 0);
+ rb_define_method(rb_cQueue, "empty?", rb_queue_empty_p, 0);
+ rb_define_method(rb_cQueue, "length", rb_queue_length, 0);
+ rb_define_method(rb_cQueue, "num_waiting", rb_queue_num_waiting, 0);
+ rb_define_method(rb_cQueue, "pop", rb_queue_pop, -1);
+ rb_define_method(rb_cQueue, "push", rb_queue_push, 1);
+ rb_alias(rb_cQueue, rb_intern("enq"), rb_intern("push"));
+ rb_alias(rb_cQueue, rb_intern("<<"), rb_intern("push"));
+ rb_alias(rb_cQueue, rb_intern("deq"), rb_intern("pop"));
+ rb_alias(rb_cQueue, rb_intern("shift"), rb_intern("pop"));
+ rb_alias(rb_cQueue, rb_intern("size"), rb_intern("length"));
+
+ rb_cSizedQueue = rb_define_class("SizedQueue", rb_cQueue);
+ rb_define_method(rb_cSizedQueue, "initialize", rb_sized_queue_max_set, 1);
+ rb_define_method(rb_cSizedQueue, "num_waiting", rb_queue_num_waiting, 0);
+ rb_define_method(rb_cSizedQueue, "pop", rb_queue_pop, -1);
+ rb_define_method(rb_cSizedQueue, "push", rb_queue_push, 1);
+ rb_define_method(rb_cSizedQueue, "max", rb_sized_queue_max, 0);
+ rb_define_method(rb_cSizedQueue, "max=", rb_sized_queue_max_set, 1);
+ rb_alias(rb_cSizedQueue, rb_intern("enq"), rb_intern("push"));
+ rb_alias(rb_cSizedQueue, rb_intern("<<"), rb_intern("push"));
+ rb_alias(rb_cSizedQueue, rb_intern("deq"), rb_intern("pop"));
+ rb_alias(rb_cSizedQueue, rb_intern("shift"), rb_intern("pop"));
+}
+
diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib
new file mode 100644
index 0000000000..8c5d01a954
--- /dev/null
+++ b/ext/tk/ChangeLog.tkextlib
@@ -0,0 +1,924 @@
+2008-05-12 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tkDND/shape.rb: wrong package name.
+
+--------------< ... some changes ... >------------------
+
+2007-05-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tcllib/tablelist.rb: fix typo.
+
+ * ext/tk/lib/tkextlib/tile/dialog.rb: forget to give an argument.
+
+ * ext/tk/lib/tkextlib/version.rb: update RELEASE_DATE.
+
+2007-01-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/iwidgets/checkbox.rb: wrong number of arguments
+ [ruby-Bugs-7776].
+
+ * ext/tk/lib/tkextlib/iwidgets/radiobox.rb: ditto.
+
+ * ext/tk/lib/tkextlib/blt/tile/checkbutton.rb: change primary name
+ of class [ruby-dev:30080].
+
+ * ext/tk/lib/tkextlib/blt/tile/radiobutton.rb: ditto.
+
+2006-11-07 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile/treeview.rb : minor bug fix.
+
+ * lib/tkextlib/blt/table.rb: fix bugs which forbade use of
+ '::blt::table' command. Now, probably, it'll works properly.
+
+2006-11-06 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/version.rb: keep release date of tkextlib on
+ "Tk::Tkextlib_RELEASE_DATE".
+
+ * lib/tkextlib/tile/treeview.rb : support Tile 0.7.8.
+ Now, you can handle tree items as objects.
+
+2006-10-04 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile.rb, lib/tkextlib/tile/* : support Tile 0.7.6.
+
+2006-10-03 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/SUPPORT_STATUS: [ruby-talk:211939] check links
+ of extensions.
+
+ * lib/tkextlib/blt/container.rb: define instance methods properly.
+
+ * lib/tkextlib/tile/tcombobox.rb: bug fix [ruby-talk:213003].
+
+ * lib/tkextlib/tile/tnotebook.rb: ditto.
+
+ * lib/tkextlib/tile/treeview.rb: ditto.
+
+ * lib/tkextlib/tile/sizegrip.rb: [new] add 'ttk::sizegrip' widget.
+
+2006-08-31 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt.rb: double dashes (--) option doesn't work
+ properly on some versions of BLT (wrong description on the
+ manual of `blt::bgexec'?).
+
+2005-12-11 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/SUPPORT_STATUS: update to support libraries in
+ ActiveTcl8.4.12.0.
+
+ * lib/tkextlib/tile/tnotebook.rb: add Tk::Tile::TNotebook#insert.
+
+ * sample/tkextlib/tile/demo.rb: improve the look of a part of the demo.
+
+2005-11-25 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * sample/tkextlib/tile/demo.rb: bug fix
+
+ * sample/tkextlib/tile/themes/*: add some themes (blue,
+ keramik, and plastik; require Tile-0.5 or later).
+
+2005-11-22 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile.rb: bug fix (Tk::Tile::USE_TTK_NAMESPACE
+ is not defined).
+
+2005-11-19 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * sample/tkextlib/treectrl/demo.rb: remove dependency on Ruby's
+ version (1.8 or 1.9).
+
+2005-10-23 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/*: update to support ActiveTcl8.4.11.2
+
+ * lib/tkextlib/trofs/*: support Trofs 0.4.3
+
+ * lib/tkextlib/tile/*: support Tile 0.7.2
+
+ * lib/tkextlib/vu/*: support vu 2.3.0
+
+ * lib/tkextlib/tcllib/*: support Tcllib 1.8 (Tklib 0.3 part only)
+
+ * lib/tkextlib/*: improve conversion of option values
+
+2005-10-04 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tktable/tktable.rb: border_* instance methods
+ don't call 'border' subcommands.
+
+2005-08-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt/component.rb: didn't check
+ __item_ruby2val_optkeys().
+
+2005-08-09 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt/barchart.rb: support to treat tkvariable-type
+ configure options.
+
+ * lib/tkextlib/blt/component.rb: ditto.
+
+ * lib/tkextlib/blt/dragdrop.rb: ditto.
+
+ * lib/tkextlib/blt/treeview.rb: ditto.
+
+ * lib/tkextlib/bwidget/button.rb: ditto.
+
+ * lib/tkextlib/bwidget/entry.rb: ditto.
+
+ * lib/tkextlib/bwidget/label.rb: ditto.
+
+ * lib/tkextlib/bwidget/labelentry.rb: ditto.
+
+ * lib/tkextlib/bwidget/labelframe.rb: ditto.
+
+ * lib/tkextlib/bwidget/mainframe.rb: ditto.
+
+ * lib/tkextlib/bwidget/passwddlg.rb: ditto.
+
+ * lib/tkextlib/bwidget/spinbox.rb: ditto.
+
+ * lib/tkextlib/bwidget/tree.rb: ditto.
+
+ * lib/tkextlib/iwidgets/calendar.rb: ditto.
+
+ * lib/tkextlib/iwidgets/entryfield.rb: ditto.
+
+ * lib/tkextlib/iwidgets/hierarchy.rb: ditto.
+
+ * lib/tkextlib/iwidgets/labeledframe.rb: ditto.
+
+ * lib/tkextlib/iwidgets/labeledwidget.rb: ditto.
+
+ * lib/tkextlib/iwidgets/menubar.rb: ditto.
+
+ * lib/tkextlib/iwidgets/scrolledlistbox.rb: ditto.
+
+ * lib/tkextlib/iwidgets/spinner.rb: ditto.
+
+ * lib/tkextlib/iwidgets/toolbar.rb: ditto.
+
+ * lib/tkextlib/tkimg/pixmap.rb: ditto.
+
+ * lib/tkextlib/tktable/tktable.rb: ditto.
+
+2005-08-06 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/tile/demo.rb: use Tk::Tile::Scale#variable.
+
+2005-08-04 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/tile/demo.rb: followed previous changes.
+
+2005-08-04 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile/t*.rb: aliased class names starting with 'T'
+ to non 'T' ones. (ie. Tk::Tile::TButton -> Tk::Tile::Button)
+ [ruby-dev:26724]
+
+ * lib/tkextlib/tile.rb: ditto. (autoload support)
+
+2005-08-04 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/tile/demo.rb: fixed: Tk::Tile::TProgressbar is
+ supported on tile 0.6 or later, not tile 0.5.
+
+ * sample/tkextlib/tile/demo.rb: updated scales demo to use
+ Tk::Tile::TProgressbar for tile 0.6 or later.
+
+ * sample/tkextlib/tile/demo.rb: set some TkVariable default values.
+
+2005-08-03 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile/treeview.rb: Tk::Tile::Treeview#headingconfigure
+ is now working and more. [ruby-dev:26716]
+
+ * sample/tkextlib/tile/demo.rb: use Tk::Tile::Treeview#headingconfigure instead of direct Tk.tk_call.
+
+2005-08-02 ocean <ocean@ruby-lang.org>
+
+ * lib/tkextlib/tile/tprogressbar.rb: Tk::Tile::TProgressbar#start
+ takes optional argument `interval'.
+
+ * sample/tkextlib/tile/demo.rb: emulate Tk::Tile::TProgressbar
+ with Tk::Tile::TProgress in tile 0.4. (repeating buttons demo)
+
+2005-08-02 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/tile/demo.rb: added repeating buttons demo.
+
+ * sample/tkextlib/tile/repeater.tcl: ditto. (new file)
+
+2005-08-01 ocean <ocean@ruby-lang.org>
+
+ * lib/tkextlib/tile.rb: fixed autoload for Treeview.
+
+ * lib/tkextlib/tile/treeview.rb: replaced `ary2tk_list(items)' with
+ `*items'.
+
+ * sample/tkextlib/tile/demo.rb: added treeview demo. (tile 0.5 or
+ later is required) [ruby-dev:26668]
+
+2005-08-01 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/tile/demo.rb: added combobox demo.
+
+2005-07-27 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/tile/demo.rb: fixed typo.
+
+2005-06-16 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/SUPPOPRT_STATUS: add RELEASE_DATE information.
+
+ * lib/tkextlib/tile/style.rb: add "style element options <elem>"
+ command support.
+
+2005-06-08 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/ICONS/icons.rb: fail to create instances of
+ Tk::ICONS [ruby-dev:26305].
+
+2005-06-07 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/tile/themes/kroc.{rb,tcl}: also support tile 0.4.
+
+2005-06-07 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/tile/themes/kroc.{rb,tcl}: support tile 0.5 or later.
+ ("pixmap" element constructor replaced by "image")
+
+2005-06-05 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * sample/tkextlib/tile/demo.rb: fix TypeError & create Console
+
+2005-05-30 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt.rb: add PACKAGE_NAME information of Tcl/Tk
+ Extension.
+
+ * lib/tkextlib/bwidget.rb: ditto.
+
+ * lib/tkextlib/iwidgets.rb: ditto.
+
+ * lib/tkextlib/tile.rb: ditto.
+
+ * lib/tkextlib/tkimg.rb: ditto.
+
+ * lib/tkextlib/vu.rb: ditto.
+
+ * lib/tkextlib/ICONS/icons.rb: ditto.
+
+ * lib/tkextlib/itcl/incr_tcl.rb: ditto.
+
+ * lib/tkextlib/itk/incr_tk.rb: ditto.
+
+ * lib/tkextlib/tcllib/autoscroll.rb: ditto.
+
+ * lib/tkextlib/tcllib/ctext.rb: ditto.
+
+ * lib/tkextlib/tcllib/cursor.rb: ditto.
+
+ * lib/tkextlib/tcllib/datefield.rb: ditto.
+
+ * lib/tkextlib/tcllib/ico.rb: ditto.
+
+ * lib/tkextlib/tcllib/ip_entry.rb: ditto.
+
+ * lib/tkextlib/tcllib/plotchart.rb: ditto.
+
+ * lib/tkextlib/tcllib/style.rb: ditto.
+
+ * lib/tkextlib/tcllib/tkpiechart.rb: ditto.
+
+ * lib/tkextlib/tclx/tclx.rb: ditto.
+
+ * lib/tkextlib/tkDND/shape.rb: ditto.
+
+ * lib/tkextlib/tkDND/tkdnd.rb: ditto.
+
+ * lib/tkextlib/tkHTML/htmlwidget.rb: ditto.
+
+ * lib/tkextlib/tkimg/bmp.rb: ditto.
+
+ * lib/tkextlib/tkimg/gif.rb: ditto.
+
+ * lib/tkextlib/tkimg/ico.rb: ditto.
+
+ * lib/tkextlib/tkimg/jpeg.rb: ditto.
+
+ * lib/tkextlib/tkimg/pcx.rb: ditto.
+
+ * lib/tkextlib/tkimg/pixmap.rb: ditto.
+
+ * lib/tkextlib/tkimg/png.rb: ditto.
+
+ * lib/tkextlib/tkimg/ppm.rb: ditto.
+
+ * lib/tkextlib/tkimg/ps.rb: ditto.
+
+ * lib/tkextlib/tkimg/sgi.rb: ditto.
+
+ * lib/tkextlib/tkimg/sun.rb: ditto.
+
+ * lib/tkextlib/tkimg/tga.rb: ditto.
+
+ * lib/tkextlib/tkimg/tiff.rb: ditto.
+
+ * lib/tkextlib/tkimg/window.rb: ditto.
+
+ * lib/tkextlib/tkimg/xbm.rb: ditto.
+
+ * lib/tkextlib/tkimg/xpm.rb: ditto.
+
+ * lib/tkextlib/tktable/tktable.rb: ditto.
+
+ * lib/tkextlib/tktrans/tktrans.rb: ditto.
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: ditto.
+
+ * lib/tkextlib/winico/winico.rb: ditto.
+
+2005-05-25 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/iwidgets/scrolledlistbox.rb: follow the change
+ of tk.rb. modify to attend encoding.
+
+ * lib/tkextlib/iwidgets/scrolledtext.rb: ditto.
+
+ * lib/tkextlib/iwidgets/scrolledcanvas.rb: bug fix on
+ TkCanvas#delete when given non-TkcItem arguments.
+
+2005-05-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt/winop.rb: fix typo
+
+2005-05-08 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/vu/pie.rb: fix typo
+
+2005-04-10 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/mailwasher.rb: fixed typo. [ruby-dev:26008]
+
+2005-04-09 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * sample/tkextlib/tile/demo.rb: new demo of Tile extension.
+
+ * sample/tkextlib/tile/iconlib.tcl: part of the demo.
+
+ * sample/tkextlib/tile/toolbutton.tcl: ditto.
+
+ * sample/tkextlib/tile/readme.txt: document of the demo.
+
+ * sample/tkextlib/tile/Orig_LICENSE.txt: ditto.
+
+ * sample/tkextlib/tile/themes/kroc.tcl: sample theme written with Tcl.
+
+ * sample/tkextlib/tile/themes/pkgIndex.tcl: pkgIndex of kroc.tcl.
+
+ * sample/tkextlib/tile/themes/kroc.rb: Kroc theme written with Ruby.
+
+ * sample/tkextlib/tile/themes/kroc/button-h.gif: images for Kroc theme.
+
+ * sample/tkextlib/tile/themes/kroc/button-n.gif: ditto.
+
+ * sample/tkextlib/tile/themes/kroc/button-p.gif: ditto.
+
+ * sample/tkextlib/tile/themes/kroc/check-hc.gif: ditto.
+
+ * sample/tkextlib/tile/themes/kroc/check-hu.gif: ditto.
+
+ * sample/tkextlib/tile/themes/kroc/check-nc.gif: ditto.
+
+ * sample/tkextlib/tile/themes/kroc/check-nu.gif: ditto.
+
+ * sample/tkextlib/tile/themes/kroc/radio-hc.gif: ditto.
+
+ * sample/tkextlib/tile/themes/kroc/radio-hu.gif: ditto.
+
+ * sample/tkextlib/tile/themes/kroc/radio-nc.gif: ditto.
+
+ * sample/tkextlib/tile/themes/kroc/radio-nu.gif: ditto.
+
+ * lib/tkextlib/tile.rb: bug fix (tested on the new demo).
+
+ * lib/tkextlib/tile/style.rb: ditto.
+
+ * lib/tkextlib/tile/tbutton.rb: ditto.
+
+ * lib/tkextlib/tile/tcheckbutton.rb: ditto.
+
+ * lib/tkextlib/tile/tcombobox.rb: ditto.
+
+ * lib/tkextlib/tile/tentry.rb: ditto.
+
+ * lib/tkextlib/tile/tframe.rb: ditto.
+
+ * lib/tkextlib/tile/tlabel.rb: ditto.
+
+ * lib/tkextlib/tile/tlabelframe.rb: ditto.
+
+ * lib/tkextlib/tile/tmenubutton.rb: ditto.
+
+ * lib/tkextlib/tile/tnotebook.rb: ditto.
+
+ * lib/tkextlib/tile/tprogressbar.rb: ditto.
+
+ * lib/tkextlib/tile/tradiobutton.rb: ditto.
+
+ * lib/tkextlib/tile/treeview.rb: ditto.
+
+ * lib/tkextlib/tile/tscrollbar.rb: ditto.
+
+ * lib/tkextlib/tile/tseparator.rb: ditto.
+
+ * lib/tkextlib/tile/tsquare.rb: ditto.
+
+ * lib/tkextlib/tile/tpaned.rb: new library
+
+ * lib/tkextlib/tile/tscale.rb: ditto.
+
+ * lib/tkextlib/SUPPORT_STATUS: update support status of Tile extension.
+
+ * lib/tkextlib/tcllib/ctext.rb: use TkCommandNames on create_self().
+
+ * lib/tkextlib/tcllib/datefield.rb: ditto.
+
+ * lib/tkextlib/tcllib/ip_entry.rb: ditto.
+
+ * lib/tkextlib/tkHTML/htmlwidget.rb: ditto.
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: ditto.
+
+2005-04-09 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/explorer.rb: File.executable? returns true
+ even if it's plain text file. (this function only checks access right)
+
+2005-04-09 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/{help,www-options}.rb: fixed typo.
+ (click or resize column header)
+
+2005-04-09 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/imovie.rb: fixed typo. (click on clip title)
+
+2005-04-08 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/random.rb: fixed typo. (drop node outside of
+ widget, or reenter widget while draggging)
+
+2005-04-08 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/outlook-newgrounp.rb: image had disappered when
+ node was selected.
+
+2005-04-08 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/{random,outlook-newgroup}.rb:
+ tk::treectrl uses 'afterId' not 'afterID'.
+
+ * sample/tkextlib/treectrl/{random,outlook-newgroup}.rb:
+ item_firstchild can return empty string. (drop node to leaf node)
+
+ * sample/tkextlib/treectrl/random.rb: Enumerable#find didn't work properly
+ because tried to compare String with Integer. (drag node and leave widget)
+
+ * sample/tkextlib/treectrl/random.rb: and some fixes.
+
+2005-04-08 ocean <ocean@ruby-lang.org>
+
+ * lib/tkextlib/treectrl/tktreectrl.rb (selection_clear): fixed typo.
+
+ * sample/tkextlib/treectrl/random.rb: node deselection now works.
+
+ * sample/tkextlib/treectrl/demo.rb: fixed typo. (popup menu on column header)
+
+2005-04-08 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/help.rb: fixed typo. (wrong color)
+
+2005-04-08 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/random.rb: fixed typo. (wrong itemheight)
+
+ * sample/tkextlib/treectrl/outlook-newgroup.rb: ditto.
+
+ * sample/tkextlib/treectrl/explorer.rb: ditto.
+
+ * sample/tkextlib/treectrl/help.rb: ditto.
+
+2005-04-07 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/*.rb: some speed up... cache the result of
+ version checking.
+
+2005-04-07 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: performance tuning by calling
+ tk_send_without_enc. [ruby-dev:25997]
+
+2005-04-04 ocean <ocean@ruby-lang.org>
+
+ * lib/tkextlib/tktable/tktable.rb: added Tk::TkTable#selection_present.
+
+2005-04-02 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: support TreeCtrl's cvs head.
+
+2005-04-02 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt/component.rb: add TreeCtrl#legend_window_create().
+
+ * sample/tkextlib/blt/graph6.rb: use legend_window_create().
+
+ * lib/tkextlib/blt/tree.rb: forget to call tagid().
+
+ * lib/tkextlib/blt/treeview.rb: ditto.
+
+2005-04-01 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * sample/tkextlib/treectrl/demo.rb: bridge the gap of
+ Hash#index or Hash#key between ruby 1.8 and 1.9
+
+2005-04-01 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt/component.rb: bug fix on treatment of
+ component objects.
+
+ * sample/tkextlib/blt/graph6.rb: a new sample script.
+
+2005-03-31 ocean <ocean@ruby-lang.org>
+
+ * sample/tkextlib/treectrl/demo.rb: should use Hash#index.
+
+ * sample/tkextlib/treectrl/demo.rb: TkImage was not
+ cached properly.
+
+ * sample/tkextlib/treectrl/random.rb: fixed typo.
+
+2005-03-31 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * sample/tkextlib/iwidgets/sample/hierarchy.rb: show basename
+ only [ruby-dev:25970]
+
+ * sample/tkextlib/treectrl/demo.rb: add check for existence of
+ 'backgroundimage' option.
+
+ * sample/tkextlib/treectrl/bitmaps.rb: ditto.
+
+ * sample/tkextlib/treectrl/outlook-newgroup.rb: lack of '%I'
+ event callback argument.
+
+2005-03-31 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * sample/tkextlib/iwidgets/sample/hierarchy.rb: fail to treat
+ Japanese (i18n?) filenames.
+
+2005-03-30 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * sample/tkextlib/bwidget/tree.rb: use 'return' in the Proc object.
+
+ * sample/tkextlib/tkHTML/hv.rb: ditto.
+
+ * sample/tkextlib/tkHTML/ss.rb: ditto.
+
+ * sample/tkextlib/tktable/basic.rb: ditto.
+
+ * sample/tkextlib/tktable/command.rb: ditto.
+
+ * sample/tkextlib/tktable/debug.rb: ditto.
+
+ * sample/tkextlib/tktable/maxsize.rb: ditto.
+
+ * sample/tkextlib/treectrl/demo.rb: ditto.
+
+2005-03-29 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt/component.rb: cannot create elements except
+ default type of element.
+
+ * lib/tkextlib/blt/barchart.rb: ditto.
+
+ * lib/tkextlib/blt/graph.rb: ditto.
+
+ * lib/tkextlib/blt/stripchart.rb: ditto.
+
+ * lib/tkextlib/blt/component.rb: axis command option gets
+ proper object type of arguments.
+
+ * sample/tkextlib/blt/calendar.rb: new sample.
+
+ * sample/tkextlib/blt/pareto.rb: ditto.
+
+2005-03-28 ocean <ocean@ruby-lang.org>
+
+ * lib/tkextlib/iwidgets/notebook.rb: fixed typo.
+
+2005-03-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt.rb: add commands for zooming.
+
+ * lib/tkextlib/blt/bitmap.rb (new_with_name): add for using
+ given name.
+
+ * lib/tkextlib/blt/busy.rb: bug fix on Tk::BLT::Busy::Shild class.
+
+ * lib/tkextlib/blt/component.rb: typo fix.
+
+ * lib/tkextlib/blt/component.rb: fix lack of *_create methods
+
+ * lib/tkextlib/blt/component.rb: proper call on xaxis_* and so on.
+
+ * lib/tkextlib/blt/htext.rb: add TkVariable object to access
+ special Tcl variables.
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: typo fix.
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: proper treatment
+ of 'font' option of element_configure.
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: bug fix on item_sort.
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: add methods to
+ call TreeCtrl commands for bindings.
+
+ * sample/tkextlib/blt/*: add some sample scripts.
+
+ * sample/tkextlib/treectrl/*: add some sample scripts.
+
+2005-03-18 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: bug fix and define some
+ classes for components of Tk::TreeCtrl
+
+2005-03-17 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: call wrong method in
+ Tk::TreeCtrl#*_configinfo and current_*_configinfo method
+
+2005-03-16 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/SUPPORT_STATUS: change the status of TkImg
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: bug fix and support
+ TkTreeCtrl-1.1
+
+ * lib/tkextlib/SUPPORT_STATUS: change the supported version of
+ TkTreeCtrl
+
+2005-03-15 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * sample/tkextlib/tkimg: add sample
+
+2005-03-06 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/SUPPORT_STATUS: add version info of each extension
+
+2005-03-05 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile.rb: lack of "autoload TProgressbar"
+
+2005-03-05 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile.rb: support tile-0.6
+
+ * lib/tkextlib/tile/tbutton.rb: ditto
+
+ * lib/tkextlib/tile/tcheckbutton.rb: ditto
+
+ * lib/tkextlib/tile/tlabel.rb: ditto
+
+ * lib/tkextlib/tile/tmenubutton.rb: ditto
+
+ * lib/tkextlib/tile/tnotebook.rb: ditto
+
+ * lib/tkextlib/tile/tradiobutton.rb: ditto
+
+ * lib/tkextlib/tile/tcombobox.rb: [new] ditto
+
+ * lib/tkextlib/tile/tentry.rb: [new] ditto
+
+ * lib/tkextlib/tile/tframe.rb: [new] ditto
+
+ * lib/tkextlib/tile/tlabelframe.rb: [new] ditto
+
+ * lib/tkextlib/tile/tprogressbar.rb: [new] ditto
+
+ * lib/tkextlib/tile/treeview.rb: [new] ditto
+
+ * lib/tkextlib/tile/tscrollbar.rb: [new] ditto
+
+ * lib/tkextlib/tile/tseparator.rb: [new] ditto
+
+ * lib/tkextlib/tile/tsquare.rb: [new] ditto
+
+2005-02-20 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tclx/tclx.rb: warning TclX's 'signal' command.
+
+2005-01-25 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt/component.rb: bug fix. cannot accept
+ a callback ID string for a command argument. [ruby-dev:25479]
+
+ * lib/tkextlib/blt/tabset.rb: ditto
+
+ * lib/tkextlib/blt/treeview.rb: ditto
+
+ * lib/tkextlib/bwidget/labelentry.rb: ditto
+
+ * lib/tkextlib/bwidget/listbox.rb: ditto
+
+ * lib/tkextlib/bwidget/notebook.rb: ditto
+
+ * lib/tkextlib/bwidget/spinbox.rb: ditto
+
+ * lib/tkextlib/bwidget/tree.rb: ditto
+
+ * lib/tkextlib/itk/incr_tk.rb: ditto
+
+ * lib/tkextlib/iwidgets/scrolledcanvas.rb: ditto
+
+ * lib/tkextlib/tkDND/tkdnd.rb: ditto
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: ditto
+
+ * sample/tkextlib/tkHTML/ss.rb: local variable scope bug fix
+ [ruby-dev:25479]
+
+ * sample/tkextlib/vu/vu_demo.rb: rename from vu.rb; avoid the bug on
+ Windows version of Tcl/Tk. The trouble based on the bug occurs when
+ the script name (without extension) is a same name as a Tcl/Tk's
+ library file name (without extension) required in the script.
+
+2004-12-24 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt: add BLT extension support
+
+2004-12-16 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/bwidget/labelentry.rb: use TkCore.callback_obj?()
+
+ * lib/tkextlib/bwidget/listbox.rb: ditto
+
+ * lib/tkextlib/bwidget/notebook.rb: ditto
+
+ * lib/tkextlib/bwidget/spinbox.rb: ditto
+
+ * lib/tkextlib/itk/incr_tk.rb: ditto
+
+ * lib/tkextlib/iwidgets/scrolledcanvas.rb: ditto
+
+ * lib/tkextlib/tkDND/tkdnd.rb: ditto
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: ditto
+
+ * lib/tkextlib/winico/winico.rb: ditto
+
+2004-12-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile/style.rb: 'theme_use' method bug fix
+
+2004-12-08 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/bwidget/notebook.rb: raise method cannot return
+ the raised page.
+
+ * lib/tkextlib/bwidget/labelentry.rb: bind methods accept
+ subst_args + block
+
+ * lib/tkextlib/bwidget/listbox.rb: ditto
+
+ * lib/tkextlib/bwidget/notebook.rb: ditto
+
+ * lib/tkextlib/bwidget/spinbox.rb: ditto
+
+ * lib/tkextlib/bwidget/tree.rb: ditto
+
+ * lib/tkextlib/itk/incr_tk.rb: ditto
+
+ * lib/tkextlib/iwidgets/scrolledcanvas.rb: ditto
+
+ * lib/tkextlib/tkDND/tkdnd.rb: ditto
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: ditto
+
+2004-11-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/bwidget/notebook.rb: uses epath
+
+ * lib/tkextlib/bwidget/widget.rb: ditto
+
+ * lib/tkextlib/tktable/tktable.rb: ditto
+
+ * lib/tkextlib/tcllib/cursor.rb: ditto, and bug fix
+
+2004-11-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile/style.rb: bug fix
+
+2004-11-07 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/iwidgets/scrolledcanvas.rb: bind-event methods
+ accept multi substitution arguments.
+
+ * lib/tkextlib/tktable/tktable.rb: ditto.
+
+ * lib/tkextlib/treectrl/tktreectrl.rb: ditto
+
+2004-11-03 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/SUPPORT_STATUS: BLT moves to 'plan to support'
+ from 'not determined'
+
+ * lib/tkextlib/itk/incr_tk.rb: __cget_cmd and __config_cmd are
+ private methods
+
+ * lib/tkextlib/tcllib/autoscroll.rb: extend TkCore
+
+ * lib/tkextlib/tcllib/cursor.rb: ditto.
+
+ * lib/tkextlib/tcllib/plotchart.rb: ditto.
+
+ * lib/tkextlib/tcllib/style.rb: ditto.
+
+ * lib/tkextlib/tile/style.rb: ditto.
+
+ * lib/tkextlib/tkDND/shape.rb: ditto.
+
+2004-10-24 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/bwidget/tree.rb: bug fix on Windows
+
+2004-10-16 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tcllib/ico.rb: new library (Tk::Tcllib:ICO)
+
+ * lib/tkextlib/tcllib.rb: add Tk::Tcllib::ICO (based on tcllib 1.7)
+
+2004-10-06 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/bwidget.rb (BWidget.grab): bug fix
+
+ * lib/tkextlib/tcllib.rb: typo fix
+
+2004-07-28 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/add winico support
+
+2004-07-23 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/add TclX support (partially; infox command and
+ XPG/3 MsgCat only)
+
+2004-07-15 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * bug fix
+
+ * support TkTable extension
+
+2004-07-12 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * bug fix
+
+ * support Iwidgets extension
+
+2004-07-10 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * bug fix
+
+ * add more part of [incr Widget] support (about 65%? are complete)
+
+ * use Tk::ValidateConfigure.__def_validcmd() method
+ (new function to define validatecommand methods easier)
+
+ * tcllib.rb : avoid the loading trouble that almost all part of
+ the extension is not available when some libraries are invalid.
+
+2004-07-09 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * add some part of [incr Widget] support (about 50%? are complete)
+
+2004-07-07 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * add [incr Tck], [incr Tk] support
+
+2004-07-06 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * support BWidget extension
+
+ * add BWidget extension demo
+
+ * add ICONS extension demo
+
+ * many bug fix
+
+2004-07-01 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * 1st release of tkextlib ( to support Tcl/Tk extensions )
diff --git a/ext/tk/MANIFEST b/ext/tk/MANIFEST
deleted file mode 100644
index 96f7e744f7..0000000000
--- a/ext/tk/MANIFEST
+++ /dev/null
@@ -1,202 +0,0 @@
-MANIFEST
-README.1st
-extconf.rb
-depend
-tkutil.c
-lib/README
-lib/multi-tk.rb
-lib/tk.rb
-lib/tkafter.rb
-lib/tkbgerror.rb
-lib/tkcanvas.rb
-lib/tkclass.rb
-lib/tkconsole.rb
-lib/tkdialog.rb
-lib/tkentry.rb
-lib/tkfont.rb
-lib/tkmacpkg.rb
-lib/tkmenubar.rb
-lib/tkmngfocus.rb
-lib/tkpalette.rb
-lib/tkscrollbox.rb
-lib/tktext.rb
-lib/tkvirtevent.rb
-lib/tkwinpkg.rb
-sample/safe-tk.rb
-sample/tkballoonhelp.rb
-sample/tkbiff.rb
-sample/tkbrowse.rb
-sample/tkcombobox.rb
-sample/tkdialog.rb
-sample/tkfrom.rb
-sample/tkhello.rb
-sample/tkline.rb
-sample/tkmenubutton.rb
-sample/tkmultilistbox.rb
-sample/tkoptdb-safeTk.rb
-sample/tkoptdb.rb
-sample/tktextframe.rb
-sample/resource.ja
-sample/resource.en
-sample/tktimer.rb
-sample/tktimer2.rb
-sample/tktimer3.rb
-sample/demos-en/ChangeLog
-sample/demos-en/ChangeLog.prev
-sample/demos-en/README
-sample/demos-en/README.tkencoding
-sample/demos-en/arrow.rb
-sample/demos-en/bind.rb
-sample/demos-en/bitmap.rb
-sample/demos-en/browse1
-sample/demos-en/browse2
-sample/demos-en/button.rb
-sample/demos-en/check.rb
-sample/demos-en/clrpick.rb
-sample/demos-en/colors.rb
-sample/demos-en/cscroll.rb
-sample/demos-en/ctext.rb
-sample/demos-en/dialog1.rb
-sample/demos-en/dialog2.rb
-sample/demos-en/doc.org/README
-sample/demos-en/doc.org/README.JP
-sample/demos-en/doc.org/README.tk80
-sample/demos-en/doc.org/license.terms
-sample/demos-en/doc.org/license.terms.tk80
-sample/demos-en/entry1.rb
-sample/demos-en/entry2.rb
-sample/demos-en/entry3.rb
-sample/demos-en/filebox.rb
-sample/demos-en/floor.rb
-sample/demos-en/form.rb
-sample/demos-en/hello
-sample/demos-en/hscale.rb
-sample/demos-en/icon.rb
-sample/demos-en/image1.rb
-sample/demos-en/image2.rb
-sample/demos-en/image3.rb
-sample/demos-en/images/earth.gif
-sample/demos-en/images/earthris.gif
-sample/demos-en/images/face.xbm
-sample/demos-en/images/flagdown.xbm
-sample/demos-en/images/flagup.xbm
-sample/demos-en/images/gray25.xbm
-sample/demos-en/images/grey.25
-sample/demos-en/images/grey.5
-sample/demos-en/images/letters.xbm
-sample/demos-en/images/noletter.xbm
-sample/demos-en/images/pattern.xbm
-sample/demos-en/images/tcllogo.gif
-sample/demos-en/images/teapot.ppm
-sample/demos-en/items.rb
-sample/demos-en/ixset
-sample/demos-en/ixset2
-sample/demos-en/label.rb
-sample/demos-en/labelframe.rb
-sample/demos-en/menu.rb
-sample/demos-en/menu84.rb
-sample/demos-en/menubu.rb
-sample/demos-en/msgbox.rb
-sample/demos-en/patch_1.1c1
-sample/demos-en/paned1.rb
-sample/demos-en/paned2.rb
-sample/demos-en/plot.rb
-sample/demos-en/puzzle.rb
-sample/demos-en/radio.rb
-sample/demos-en/radio2.rb
-sample/demos-en/rmt
-sample/demos-en/rolodex
-sample/demos-en/rolodex-j
-sample/demos-en/ruler.rb
-sample/demos-en/sayings.rb
-sample/demos-en/search.rb
-sample/demos-en/spin.rb
-sample/demos-en/square
-sample/demos-en/states.rb
-sample/demos-en/style.rb
-sample/demos-en/tcolor
-sample/demos-en/tcolor.bak
-sample/demos-en/text.rb
-sample/demos-en/timer
-sample/demos-en/tkencoding.rb
-sample/demos-en/twind.rb
-sample/demos-en/unicodeout.rb
-sample/demos-en/vscale.rb
-sample/demos-en/widget
-sample/demos-jp/README
-sample/demos-jp/arrow.rb
-sample/demos-jp/bind.rb
-sample/demos-jp/bitmap.rb
-sample/demos-jp/browse1
-sample/demos-jp/browse2
-sample/demos-jp/button.rb
-sample/demos-jp/check.rb
-sample/demos-jp/clrpick.rb
-sample/demos-jp/colors.rb
-sample/demos-jp/cscroll.rb
-sample/demos-jp/ctext.rb
-sample/demos-jp/dialog1.rb
-sample/demos-jp/dialog2.rb
-sample/demos-jp/doc.org/README
-sample/demos-jp/doc.org/README.JP
-sample/demos-jp/doc.org/README.tk80
-sample/demos-jp/doc.org/license.terms
-sample/demos-jp/doc.org/license.terms.tk80
-sample/demos-jp/entry1.rb
-sample/demos-jp/entry2.rb
-sample/demos-jp/entry3.rb
-sample/demos-jp/filebox.rb
-sample/demos-jp/floor.rb
-sample/demos-jp/form.rb
-sample/demos-jp/hello
-sample/demos-jp/hscale.rb
-sample/demos-jp/icon.rb
-sample/demos-jp/image1.rb
-sample/demos-jp/image2.rb
-sample/demos-jp/image3.rb
-sample/demos-jp/images/earth.gif
-sample/demos-jp/images/earthris.gif
-sample/demos-jp/images/face.bmp
-sample/demos-jp/images/flagdown.bmp
-sample/demos-jp/images/flagup.bmp
-sample/demos-jp/images/gray25.bmp
-sample/demos-jp/images/grey.25
-sample/demos-jp/images/grey.5
-sample/demos-jp/images/letters.bmp
-sample/demos-jp/images/noletter.bmp
-sample/demos-jp/images/pattern.bmp
-sample/demos-jp/images/tcllogo.gif
-sample/demos-jp/images/teapot.ppm
-sample/demos-jp/items.rb
-sample/demos-jp/ixset
-sample/demos-jp/ixset2
-sample/demos-jp/label.rb
-sample/demos-jp/labelframe.rb
-sample/demos-jp/menu.rb
-sample/demos-jp/menu8x.rb
-sample/demos-jp/menu84.rb
-sample/demos-jp/menubu.rb
-sample/demos-jp/msgbox.rb
-sample/demos-jp/paned1.rb
-sample/demos-jp/paned2.rb
-sample/demos-jp/plot.rb
-sample/demos-jp/puzzle.rb
-sample/demos-jp/radio.rb
-sample/demos-jp/radio2.rb
-sample/demos-jp/rmt
-sample/demos-jp/rolodex
-sample/demos-jp/rolodex-j
-sample/demos-jp/ruler.rb
-sample/demos-jp/sayings.rb
-sample/demos-jp/search.rb
-sample/demos-jp/spin.rb
-sample/demos-jp/square
-sample/demos-jp/states.rb
-sample/demos-jp/style.rb
-sample/demos-jp/tcolor
-sample/demos-jp/text.rb
-sample/demos-jp/timer
-sample/demos-jp/twind.rb
-sample/demos-jp/unicodeout.rb
-sample/demos-jp/vscale.rb
-sample/demos-jp/widget
diff --git a/ext/tk/MANUAL_tcltklib.eng b/ext/tk/MANUAL_tcltklib.eng
new file mode 100644
index 0000000000..6fa775b7de
--- /dev/null
+++ b/ext/tk/MANUAL_tcltklib.eng
@@ -0,0 +1,469 @@
+(tof)
+ 2005/07/05 Hidetoshi NAGAI
+
+This document discribes about the 'tcltklib' library. Although there
+is the 'tcltk' library (tcltk.rb) under this directory, no description
+in this document (because it is not maintained recently).
+
+==============================================================
+module TclTklib
+ : Defines methods to do operations which are independed on
+ : Tcl/Tk interpreters
+
+ module TclTkLib::EventFlag
+ : Defines flags to define taget events on 'do_one_event' methos.
+ : When to give, please use bit-operator (e.g. WINDOW | DONT_WAIT).
+
+ [constants]
+ NONE
+ : Is 0. It means "there is no target". But on the real
+ : operation, it is same to ALL.
+
+ WINDOW
+ : 'window' event is processed.
+
+ FILE
+ : 'file' event is processed.
+
+ TIMER
+ : 'timer' event is processed.
+
+ IDLE
+ : 'idle' operation (e.g. 're-draw'; the operations when the
+ : other kinds of events doesn't occur) is processed.
+
+ ALL
+ : All kinds of events are processed.
+ : Same to 'WINDOW | FILE | TIMER | IDLE'.
+
+ DONT_WAIT
+ : Without this flag, 'do_one_event' waits the occurence of
+ : a target event. With this flag, doesn't wait and returns
+ : false if there is no target event for processing.
+
+ module TclTkLib::VarAccessFlag
+ : Defines flags to give '_get_variable' and so on. When to give,
+ : please use bit-operator (e.g. GLOBAL_ONLY | LEAVE_ERR_MSG ).
+
+ [constants]
+ NONE
+ : Is 0. It means "set no flag".
+
+ GLOBAL_ONLY
+ : (site Tcl/Tk's man page)
+ : Under normal circumstances the procedures look up
+ : variables as follows: If a procedure call is active
+ : in interp, a variable is looked up at the current
+ : level of procedure call. Otherwise, a variable is
+ : looked up first in the current namespace, then in
+ : the global namespace. However, if this bit is set
+ : in flags then the variable is looked up only in the
+ : global namespace even if there is a procedure call
+ : active. If both GLOBAL_ONLY and NAMESPACE_ONLY are
+ : given, GLOBAL_ONLY is ignored.
+ :
+ : *** ATTENTION ***
+ : Tcl7.6 doesn't have namespaces. So NAMESPACE_ONLY
+ : is defined as 0, and then GLOBAL_ONLY is available
+ : even if flag is (GLOBAL_ONLY | NAMESPACE_ONLY).
+
+ NAMESPACE_ONLY
+ : (site Tcl/Tk's man page)
+ : Under normal circumstances the procedures look up
+ : variables as follows: If a procedure call is active
+ : in interp, a variable is looked up at the current
+ : level of procedure call. Otherwise, a variable is
+ : looked up first in the current namespace, then in
+ : the global namespace. However, if this bit is set
+ : in flags then the variable is looked up only in the
+ : current namespace even if there is a procedure call
+ : active.
+ :
+ : *** ATTENTION ***
+ : Tcl7.6 doesn't have namespaces. So NAMESPACE_ONLY
+ : is defined as 0.
+
+ LEAVE_ERR_MSG
+ : (site Tcl/Tk's man page)
+ : If an error is returned and this bit is set in flags,
+ : then an error message will be left in the interpreter's
+ : result, where it can be retrieved with Tcl_GetObjResult
+ : or Tcl_GetStringResult. If this flag bit isn't set then
+ : no error message is left and the interpreter's result
+ : will not be modified.
+
+ APPEND_VALUE
+ : (site Tcl/Tk's man page)
+ : If this bit is set then newValue is appended to the
+ : current value, instead of replacing it. If the variable
+ : is currently undefined, then this bit is ignored.
+
+ LIST_ELEMENT
+ : (site Tcl/Tk's man page)
+ : If this bit is set, then newValue is converted to a
+ : valid Tcl list element before setting (or appending
+ : to) the variable. A separator space is appended before
+ : the new list element unless the list element is going
+ : to be the first element in a list or sublist (i.e. the
+ : variable's current value is empty, or contains the
+ : single character ``{'', or ends in `` }'').
+
+ PARSE_VARNAME
+ : (site Tcl/Tk's man page)
+ : If this bit is set when calling _set_variable and so
+ : on, var_name argument may contain both an array and an
+ : element name: if the name contains an open parenthesis
+ : and ends with a close parenthesis, then the value
+ : between the parentheses is treated as an element name
+ : (which can have any string value) and the characters
+ : before the first open parenthesis are treated as the
+ : name of an array variable. If the flag PARSE_VARNAME
+ : is given, index_name argument should be 'nil' since the
+ : array and element names are taken from var_name.
+ :
+ : *** ATTENTION ***
+ : Tcl7.6 doesn't have this flag. So PARSE_VARNAME is
+ : defined as 0.
+
+ module TclTkLib::RELEASE_TYPE
+ : Defines release type number of Tcl/Tk
+
+ ALPHA
+ : ALPHA release
+
+ BETA
+ : BETA release
+
+ FINAL
+ : FINAL release
+
+ [module methods]
+ get_version()
+ : return an array of major, minor, release-type number,
+ : number, release-type name, and patchlevel of current
+ : Tcl/Tk library.
+
+ mainloop(check_root = true)
+ : Starts the eventloop. If 'check_root' is true, this method
+ : doesn't return when a root widget exists.
+ : If 'check_root' is false, doen't return by the other
+ : reasons than exceptions.
+
+ mainloop_thread?
+ : Returns whether the current thread executes the eventloop.
+ : If true, the eventloop is working on the current thread.
+ : If no eventloop is working, this method returns nil.
+ : And if the other thread executes the eventloop, returns false.
+ :
+ : *** ATTENTION ***
+ : When this methods returns false, it is dangerous to call a Tk
+ : interpreter directly.
+
+ mainloop_watchdog(check_root = true)
+ : On the normal eventloop, some kinds of callback operations
+ : cause deadlock. To avoid some of such deadlocks, this
+ : method starts an eventloop and a watchdog-thread.
+
+ do_one_event(flag = TclTkLib::EventFlag::ALL |
+ TclTkLib::EventFlag::DONT_WAIT)
+ : Do one event for processing. When processed an event,
+ : returns true.
+ : If NOT set DONT_WAIT flag, this method waits occurrence of
+ : a target event.
+ : If set DONT_WAIT flag and no event for processing, returns
+ : false immediately.
+ : If $SAFE >= 4, or $SAFE >= 1 and the flag is tainted,
+ : force to set DONT_WAIT flag.
+
+ set_eventloop_tick(timer_tick)
+ : Define the interval of thread-switching with an integer
+ : value of mili-seconds.
+ : Default timer_tick is 0. It means that thread-switching
+ : is based on the count of processed events.
+ : ( see 'set_eventloop_weight' method )
+ : However, if the eventloop thread is the only thread,
+ : timer_tick cannt be set to 0. If 0, then is set to 100 ms
+ : automatically (see NO_THREAD_INTERRUPT_TIME on tcltklib.c).
+ : On $SAFE >= 4, cannot call this method.
+
+ get_eventloop_tick
+ : Get current value of 'timer_tick'
+
+ set_no_event_wait(no_event_wait)
+ : Define sleeping time of the eventloop when two or more
+ : thread are running and there is no event for processing.
+ : Default value is 20 (ms).
+ : If the eventloop thread is the only thread, this value is
+ : invalid.
+ : On $SAFE >= 4, cannot call this method.
+
+ get_no_event_wait
+ : Get current value of 'no_event_wait'.
+
+ set_eventloop_weight(loop_max, no_event_tick)
+ : Define the weight parameters for the eventloop thread.
+ : That is invalid when the eventloop is the only thread.
+ : 'loop_max' is the max events for thread-switching.
+ : 'no_event_tick' is the increment value of the event count
+ : when no event for processing (And then, the eventloop thead
+ : sleeps 'no_event_wait' mili-seconds).
+ : 'loop_max == 800' and 'no_event_tick == 10' are defalut.
+ : On $SAFE >= 4, cannot call this method.
+
+ get_eventloop_weight
+ : Get current values of 'loop_max' and 'no_event_tick'.
+
+ mainloop_abort_on_exception=(bool)
+ : Define whether the eventloop stops on exception or not.
+ : If true (default value), stops on exception.
+ : If false, show a warinig message but ignore the exception.
+ : If nil, no warning message and ignore the excepsion.
+ : This parameter is sometimes useful when multiple Tk
+ : interpreters are working. Because the only one eventloop
+ : admins all Tk interpreters, sometimes exception on a
+ : interpreter kills the eventloop thread. Even if such
+ : situation, when abort_on_exception == false or nil,
+ : the eventloop ignores the exception and continue to working.
+ : On $SAFE >= 4, cannot call this method.
+
+ mainloop_abort_on_exception
+ : Get current status of that.
+
+ num_of_mainwindows
+ : Returns the number of main-windows (root-widget).
+ : Because there is only one main-window for one Tk interpreter,
+ : the value is same to the number of interpreters which has
+ : available Tk functions.
+
+ _merge_tklist(str, str, ... )
+ : Get a Tcl's list string from arguments with a Tcl/Tk's
+ : library function. Each arguemnt is converted to a valid
+ : Tcl list element.
+
+ _conv_listelement(str)
+ : Convert the argument to a valid Tcl list element with
+ : Tcl/Tk's library function.
+
+ _toUTF8(str, encoding=nil)
+ _fromUTF8(str, encoding=nil)
+ : Call the function (which is internal function of Tcl/Tk) to
+ : convert to/from a UTF8 string.
+
+ _subst_UTF_backslash(str)
+ _subst_Tcl_backslash(str)
+ : Substitute backslash sequence with Tcl's rule (include \uhhhh;
+ : give a sixteen-bit hexadecimal value for Unicode character).
+ : _subst_Tcl_backslash method parses all backslash sequence.
+ : _subst_UTF_backslash method parses \uhhhh only.
+
+ encoding_system
+ encoding_system=(encoding)
+ : Get and set Tcl's system encoding.
+
+ encoding
+ encoding=(encoding)
+ : alias of encoding_system / encoding_system=
+ : ( probably, Ruby/Tk's tk.rb will override them )
+
+
+class TclTkIp
+ [class methods]
+ new(ip_name=nil, options='')
+ : Generate an instance of TclTkIp class.
+ : If 'ip_name' argument is given as a string, it is the name
+ : of the Tk interpreter which is shown by 'winfo interps'
+ : command.
+ : 'options' argument accepts a string which is the command
+ : line options of wish; such as '-geometry' or '-use'.
+ : The information is used to generate the root widget of the
+ : interpreter.
+ : ( e.g. TclTkIp.new('FOO', '-geometry 500x200 -use 0x2200009') )
+ : If is given nil or falsr for the 'option' argument, generates
+ : the Tcl interpreter without Tk library. Then the interpreter
+ : doesn't need GUI environment. Therefore, even if a window
+ : system doesn't exist or cannot be used, Ruby can control the
+ : Tcl interpreter and the extention libraries loaded on the
+ : interpreter.
+
+ [instance methods]
+ create_slave(name, safe=false)
+ : Create a slave interpreter.
+ : The parent of the interpreter is the receiver of this method.
+ : The name of the slave interpreter is given by 'name' argument.
+ : The 'safe' argument decides whether the slave interpreter is
+ : created as a safe interpreter or not. If true, create a safe
+ : interpreter. Default is false. However, if the parent
+ : interpreter is a safe interpreter, the created interpreter is
+ : a safe interpreter (ignore 'safe' argument value).
+ : If $SAFE >= 4, can create a safe interpreter only.
+
+ make_safe
+ : Make the interpreter to the safe interpreter, and returns
+ : self. If fail, raise RuntimeError.
+
+ safe?
+ : Check whether the interpreter is the safe interpreter.
+ : If is the safe interpreter, returns true.
+
+ allow_ruby_exit?
+ : Return the mode whether 'exit' function of ruby or 'exit'
+ : command of Tcl/Tk can quit the ruby process or not on the
+ : interpreter. If false, such a command quit the interpreter
+ : only.
+ : The default value for a master interpreter is true, and
+ : for a slave interpreter is false.
+
+ allow_ruby_exit=(mode)
+ : Change the mode of 'allow_ruby_exit?'.
+ : If $SAFE >= 4 or the interpreter is a "safe" interpreter,
+ : this is not permitted (raise an exception).
+
+ delete
+ : Delete the interpreter.
+ : The deleted interpreter doesn't accept command and then
+ : raise an exception.
+
+ deleted?
+ : Check whether the interpreter is already deleted.
+ : If deleted, returns true.
+
+ has_mainwindow?
+ : Check whether the interpreter has a MainWindow (root widget).
+ : If has, returns true. If doesn't, returns false.
+ : If IP is already deleted, returns nil.
+
+ restart
+ : Restart Tk part of the interpreter.
+ : Use this when you need Tk functions after destroying the
+ : root widget.
+ : On $SAFE >= 4, cannot call this method.
+
+ _eval(str)
+ _invoke(*args)
+ : Estimates the arguments as a command on the Tk interpreter.
+ : The argument of _eval is a script of Tcl/Tk.
+ : Each argument of _invoke is a token of one command line of
+ : Tcl/Tk.
+ : Because the operation of _invoke doesn't through the
+ : command line parser of Tk interpreter, the cost of
+ : estimation is smaller than _eval. However, auto_load
+ : mechanism of the Tk interpreter doesn't work on _invoke.
+ : So _invoke can call only the command which already
+ : registered on the interpreter by 'load' command and so on.
+ : On _eval command, auto_load mechanism words. So if succeed
+ : to _eval and regist the command once, after that, the
+ : command can be called by _invoke.
+
+ _toUTF8(str, encoding=nil)
+ _fromUTF8(str, encoding=nil)
+ : Call the function (which is internal function of Tcl/Tk) to
+ : convert to/from a UTF8 string.
+
+ _thread_vwait(var_name)
+ _thread_tkwait(mode, target)
+ : 'vwait' or 'tkwait' with thread support.
+ : The difference from normal 'vwait' or 'tkwait' command is
+ : doing independent wait from the vwait stack when they are
+ : called on the other thread than the eventloop thread.
+ : In the case of Tcl/Tk's vwait / tkwait, if 2nd vwait /
+ : tkwait is called on waiting for 1st vwait / tkwait,
+ : returns the order of [2nd]->[1st] regardless of the order
+ : of when the wait condition was fulfilled.
+ : If _thread_vwait / _thread_tkwait is called on the
+ : eventloop thread, there is no difference from vwait /
+ : tkwait. But if called on the other thread than the
+ : eventloop, stops the thread. And when the wait condition
+ : is fulfilled, the thread restarts. The meaning of
+ : "independent from the vwait stack" is that the timing of
+ : restarting is independent from the waiting status of the
+ : other threads. That is, even if the eventloop thread is
+ : waiting by vwait and is not fulfilled the condition,
+ : _thread_vwait completes the waiting when its waiting
+ : condition is fulfilled and the thread which stopped by
+ : _thread_vwait can continue the operation.
+
+ _return_value
+ : Get the last result value on the interpreter.
+
+ _get_variable(var_name, flag)
+ _get_variable2(var_name, index_name, flag)
+ : Get the current value of a variable. If specified a
+ : index_name (see also the PARSE_VARNAME flag), get the
+ : value of the index_name element.
+
+ _set_variable(var_name, value, flag)
+ _set_variable2(var_name, index_name, value, flag)
+ : Create or modify a variable. If specified a index_name
+ : (see also the PARSE_VARNAME flag), create or modify the
+ : index_name element.
+
+ _unset_variable(var_name)
+ _unset_variable2(var_name, index_name)
+ : Remove a variable. If specified a index_name (see also
+ : the PARSE_VARNAME flag), remove the index_name element.
+
+ _get_global_var(var_name)
+ _get_global_var2(var_name, index_name)
+ _set_global_var(var_name, value)
+ _set_global_var2(var_name, index_name, value)
+ _unset_global_var(var_name)
+ _unset_global_var2(var_name, index_name)
+ : Call the associated method with the flag argument
+ : (GLOBAL_ONLY | LEAVE_ERR_MSG).
+
+ _split_tklist(str)
+ : Split the argument with Tcl/Tk's library function and
+ : get an array as a list of Tcl list elements.
+
+ _merge_tklist(str, str, ... )
+ : Get a Tcl's list string from arguments with a Tcl/Tk's
+ : library function. Each arguemnt is converted to a valid
+ : Tcl list element.
+
+ _conv_listelement(str)
+ : Convert the argument to a valid Tcl list element with
+ : Tcl/Tk's library function.
+
+ mainloop
+ mainloop_watchdog
+ : If on the slave interpreter, never start an eventloop and
+ : returns nil.
+ : With the exception that, same to the TclTkLib module method
+ : with the same name.
+
+ do_one_event
+ : With the exception that the argument is forced to set
+ : DONT_WAIT flag on the slave interpreter, same to
+ : TclTkLib#do_one_event.
+
+ set_eventloop_tick
+ get_eventloop_tick
+ set_no_event_wait
+ get_no_event_wait
+ set_eventloop_weight
+ get_eventloop_weight
+ mainloop_abort_on_exception
+ mainloop_abort_on_exception=
+ : With the exception that it is ignored to set value on the
+ : slave interpreter, same to the TclTkLib module method with
+ : the same name.
+
+ encoding_table
+ : For Ruby m17n. Return encoding relation table between Ruby's
+ : Encoding object and Tcl's encoding name.
+
+class TkCallbackBreak < StandardError
+class TkCallbackContinue < StandardError
+ : They are exception classes to break or continue the Tk callback
+ : operation.
+ : If raise TkCallbackBreak on the callback procedure, Ruby returns
+ : 'break' code to Tk interpreter (Then the Tk interpreter will
+ : break the operation for the current event).
+ : If raise TkCallbackContinue, returns 'continue' code (Then the Tk
+ : interpreter will break the operateion for the current bindtag and
+ : starts the operation for the next buindtag for the current event).
+ : However, current tcltklib supports Ruby's 'break' and 'next' to
+ : get the same effect. That is, those classes are obsolete. Those
+ : exist for backward compatibility.
+
+(eof)
diff --git a/ext/tk/MANUAL_tcltklib.eucj b/ext/tk/MANUAL_tcltklib.eucj
new file mode 100644
index 0000000000..7df42997b4
--- /dev/null
+++ b/ext/tk/MANUAL_tcltklib.eucj
@@ -0,0 +1,579 @@
+(tof)
+ 2005/07/05 Hidetoshi NAGAI
+
+Ëܥɥ­¥å¥á¥ó¥È¤Ë¤Ï¸Å¤¤ tcltk ¥é¥¤¥Ö¥é¥ê¡¤tcltklib ¥é¥¤¥Ö¥é¥ê¤ÎÀâÌÀ
+¤¬´Þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¤¬¡¤¤½¤Îµ­½ÒÆâÍÆ¤Ï¸Å¤¤¤â¤Î¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+
+tcltk ¥é¥¤¥Ö¥é¥ê¡Êtcltk.rb¡Ë¤Ï¸½ºß¤Ç¤Ï¥á¥ó¥Æ¥Ê¥ó¥¹¤¬»ö¼Â¾å¹Ô¤ï¤ì¤Æ
+¤¤¤Ê¤¤¤¿¤á¡¤¸Å¤¤¥É¥­¥å¥á¥ó¥È¤ÎÀâÌÀ¤¬¤½¤Î¤Þ¤ÞÍ­¸ú¤Ç¤¹¡¥¤½¤ì¤ËÂФ·¡¤
+tcltklib ¥é¥¤¥Ö¥é¥ê¤Ë¤Ä¤¤¤Æ¤Ï¡¤¸½ºß¤Î Ruby/Tk¡Êtk.rb °Ê²¼¤Î¥é¥¤¥Ö¥é
+¥ê·²¡Ë¤ò²ÔƯ¤µ¤»¤ë¤¿¤á¤ÎÃæ¿´¤È¤·¤Æ¥á¥ó¥Æ¥Ê¥ó¥¹¤µ¤ì¤Æ¤¤¤ë¤¿¤á¡¤¾¯¡¹
+°ã¤¤¤¬À¸¤¸¤Æ¤¤¤Þ¤¹¡¥
+
+¤½¤³¤Ç¡¤¤Þ¤º¸Å¤¤ÀâÌÀʸ½ñ¤ò¼¨¤·¤¿¸å¡¤¸½ºß¤Î tcltklib ¥é¥¤¥Ö¥é¥ê¤Ë¤Ä
+¤¤¤Æ¤ÎÀâÌÀ¤ò²Ã¤¨¤Þ¤¹¡¥
+
+°Ê²¼¤¬¥é¥¤¥Ö¥é¥ê¤Î¸Å¤¤ÀâÌÀʸ½ñ¤Ç¤¹¡¥
+==============================================================
+ MANUAL.euc
+ Sep. 19, 1997 Y. Shigehiro
+
+°Ê²¼, ¡Ötcl/tk¡×¤È¤¤¤¦É½µ­¤Ï, tclsh ¤ä wish ¤ò¼Â¸½¤·¤Æ¤¤¤ë, °ìÈ̤Ǥ¤¤¦
+¤È¤³¤í¤Î tcl/tk ¤ò»Ø¤·¤Þ¤¹. ¡Ötcltk ¥é¥¤¥Ö¥é¥ê¡×, ¡Ötcltklib ¥é¥¤¥Ö¥é
+¥ê¡×¤È¤¤¤¦É½µ­¤Ï, Ëܥѥ屡¼¥¸¤Ë´Þ¤Þ¤ì¤ë ruby ÍѤΥ饤¥Ö¥é¥ê¤ò»Ø¤·¤Þ¤¹.
+
+<< tcltk ¥é¥¤¥Ö¥é¥ê >>
+
+tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë¤¿¤á¤Î¹â(Ãæ?)¿å½à¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òÄó
+¶¡¤·¤Þ¤¹.
+
+¤³¤Î¥é¥¤¥Ö¥é¥ê¤Ï ruby ¤«¤é tcl/tk ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë¤¿¤á¤Î¤â¤Î¤Ç, Æâ
+Éô¤Ç tcltklib ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ·¤Æ¤¤¤Þ¤¹.
+
+[ÀâÌÀ]
+
+tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤Ç¤Ï, ¥¦¥£¥¸¥§¥Ã¥È¤Ë²¿¤«»Ø¼¨¤òÁ÷¤ë¤Ë¤Ï, ¥¦¥£¥¸¥§¥Ã
+¥È̾¤Ë³¤¤¤Æ¥Ñ¥é¥á¡¼¥¿¤ò½ñ¤­¤Þ¤¹. ¤·¤¿¤¬¤Ã¤Æ, ¥¦¥£¥¸¥§¥Ã¥È¤¬¥ª¥Ö¥¸¥§¥¯
+¥È¤Ç¤¢¤ê, ¤½¤ì¤ËÂФ·¤Æ¥á¥½¥Ã¥É¤òÁ÷¤Ã¤Æ¤¤¤ë, ¤È¤ß¤Ê¤¹¤³¤È¤¬¤Ç¤­¤Þ¤¹. ¤µ
+¤Æ, tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤Ç¤Ï, ÁȤ߹þ¤ß¥³¥Þ¥ó¥É¤â, Á°½Ò¤Î¥¦¥£¥¸¥§¥Ã¥È¤È
+Ʊ¤¸¤è¤¦¤Ê½ñ¼°¤ÎÌ¿Îá¤Ç¼Â¹Ô¤µ¤ì¤Þ¤¹. ¤¹¤Ê¤ï¤Á, ¥³¥Þ¥ó¥É¤â¥ª¥Ö¥¸¥§¥¯¥È¤Ç
+¤¢¤ë¤È¹Í¤¨¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹.
+
+¤³¤Î¤è¤¦¤Ê¹Í¤¨¤Ë´ð¤Å¤­, tcltk ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï, tcl/tk ¤Î¥³¥Þ¥ó¥É¤ä¥¦¥£
+¥¸¥§¥Ã¥È¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Þ¤¹. ¥ª¥Ö¥¸¥§¥¯¥È¤ËÂФ¹¤ë¥á¥½¥Ã
+¥É¸Æ¤Ó½Ð¤·¤Ï, e() ¥á¥½¥Ã¥É¤Ë¤è¤ê¼Â¹Ô¤µ¤ì¤Þ¤¹. Î㤨¤Ð, tcl/tk ¤Î info
+¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë ruby ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤¬ info ¤È¤¤¤¦Ì¾Á°¤Ç¤¢¤ë¤È¤¹¤ë¤È,
+tcl/tk ¤Î
+ info commands
+¤È¤¤¤¦Ì¿Îá¤Ï tcltk ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï
+ info.e("commands")
+¤Èµ­½Ò¤µ¤ì¤Þ¤¹. ¤Þ¤¿, ¡Ö.¡×¤È¤¤¤¦¥¦¥£¥¸¥§¥Ã¥È (wish ¼Â¹Ô»þ¤Ë¼«Æ°Åª¤ËÀ¸
+À®¤µ¤ì¤ë¥ë¡¼¥È¥¦¥£¥¸¥§¥Ã¥È) ¤ËÂбþ¤¹¤ë ruby ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤¬ root ¤È¤¤
+¤¦Ì¾Á°¤Ç¤¢¤ë¤È¤¹¤ë¤È,
+ . configure -height 300 -width 300
+¤È¤¤¤¦ tcl/tk ¤ÎÌ¿Îá¤Ï
+ root.e("configure -height 300 -width 300")
+¤Èµ­½Ò¤µ¤ì¤Þ¤¹. ¤³¤Î¤è¤¦¤Êµ­½Ò¤Ï, ¸«¤¿¤á¤Ë¤ÏÈþ¤·¤¯¤¢¤ê¤Þ¤»¤ó¤¬, ¤½¤·¤Æ,
+¥¹¥¯¥ê¥×¥È¤òÆÉ¤à¿Í¤Ë¤Ï¸«¤Å¤é¤¤¤«¤âÃΤì¤Þ¤»¤ó¤¬, ¼ÂºÝ¤Ë¥¹¥¯¥ê¥×¥È¤ò½ñ¤¤
+¤Æ¤ß¤ë¤ÈͽÁÛ³°¤Ë¼ê·Ú¤Ç¤¹.
+
+[»ÈÍÑË¡]
+
+1. ¥é¥¤¥Ö¥é¥ê¤òÆÉ¤ß¹þ¤à.
+ require "tcltk"
+
+2. tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤òÀ¸À®¤¹¤ë.
+ ip = TclTkInterpreter.new()
+
+3. tcl/tk ¤Î¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÊÑ¿ô¤ËÂåÆþ¤·¤Æ¤ª¤¯.
+ # ¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤¬Æþ¤Ã¤¿ Hash ¤ò¼è¤ê½Ð¤¹.
+ c = ip.commands()
+ # »È¤¤¤¿¤¤¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò¸ÄÊ̤ÎÊÑ¿ô¤ËÂåÆþ¤¹¤ë.
+ bind, button, info, wm = c.indexes("bind", "button", "info", "wm")
+
+4. ɬÍפʽèÍý¤ò¹Ô¤¦.
+ ¾Ü¤·¤¯¤Ï, ¥µ¥ó¥×¥ë¤ò»²¾È¤Î¤³¤È.
+
+5. ½àÈ÷¤¬¤Ç¤­¤¿¤é, ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ËÆþ¤ë.
+ TclTk.mainloop()
+
+(( °Ê²¼, ¥â¥¸¥å¡¼¥ë, ¥¯¥é¥¹Åù¤ÎÀâÌÀ¤ò½ñ¤¯Í½Äê.))
+
+
+
+<< tcltklib ¥é¥¤¥Ö¥é¥ê >>
+
+tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë¤¿¤á¤ÎÄã¿å½à¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òÄ󶡤·¤Þ
+¤¹.
+
+¥³¥ó¥Ñ¥¤¥ë/¼Â¹Ô¤Ë¤Ï, tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤¬É¬ÍפǤ¹.
+
+[ÀâÌÀ]
+
+¤³¤Î¥é¥¤¥Ö¥é¥ê¤òÍѤ¤¤ë¤È, ruby ¤«¤é tcl/tk ¤Î C ¥é¥¤¥Ö¥é¥ê¤òÍøÍѤǤ­¤Þ
+¤¹. ¶ñÂÎŪ¤Ë¤Ï, ruby ¥¤¥ó¥¿¥×¥ê¥¿¤«¤é tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿¤ò¸Æ¤Ó½Ð¤¹¤³
+¤È¤¬¤Ç¤­¤Þ¤¹. ¤µ¤é¤Ë, ¤½¤Î(ruby ¥¤¥ó¥¿¥×¥ê¥¿¤«¤é¸Æ¤Ó½Ð¤·¤¿) tcl/tk ¥¤
+¥ó¥¿¥×¥ê¥¿¤«¤é, µÕ¤Ë ruby ¥¤¥ó¥¿¥×¥ê¥¿¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ¤¹.
+
+[»ÈÍÑË¡]
+
+require "tcltklib" ¤¹¤ë¤È, °Ê²¼¤Î¥â¥¸¥å¡¼¥ë, ¥¯¥é¥¹¤¬ÍøÍѲÄǽ¤Ç¤¹.
+
+¥â¥¸¥å¡¼¥ë TclTkLib
+ tcl/tk ¥é¥¤¥Ö¥é¥ê¤ò¸Æ¤Ó½Ð¤¹¥á¥½¥Ã¥É¤ò½¸¤á¤¿¥â¥¸¥å¡¼¥ë¤Ç¤¹. ¤¿¤À¤·,
+ tcl/tk ¥¤¥ó¥¿¥×¥ê¥¿´Ø·¸¤Î¥á¥½¥Ã¥É¤Ï¥¯¥é¥¹ TclTkIp ¤Ë¤¢¤ê¤Þ¤¹.
+
+ ¥â¥¸¥å¡¼¥ë¥á¥½¥Ã¥É mainloop()
+ Tk_MainLoop ¤ò¼Â¹Ô¤·¤Þ¤¹. Á´¤Æ¤Î tk ¤Î¥¦¥¤¥ó¥É¥¦¤¬Ìµ¤¯¤Ê¤ë¤È½ªÎ»
+ ¤·¤Þ¤¹(Î㤨¤Ð, tcl/tk ¤Ç½ñ¤¯¤È¤³¤í¤Î "destroy ." ¤ò¤·¤¿¾ì¹çÅù).
+ °ú¿ô: ̵¤·
+ Ìá¤êÃÍ: nil
+
+¥¯¥é¥¹ TclTkIp
+ ¥¤¥ó¥¹¥¿¥ó¥¹¤¬ tcl/tk ¤Î¥¤¥ó¥¿¥×¥ê¥¿¤ËÂбþ¤·¤Þ¤¹. tcl/tk ¤Î¥é¥¤¥Ö
+ ¥é¥ê¤Î»ÅÍÍÄ̤ê, ¥¤¥ó¥¹¥¿¥ó¥¹¤òÊ£¿ô¸ÄÀ¸À®¤·¤Æ¤âÀµ¤·¤¯Æ°ºî¤·¤Þ¤¹(¤½
+ ¤ó¤Ê¤³¤È¤ò¤¹¤ëɬÍפϤ¢¤Þ¤ê̵¤¤¤Ï¤º¤Ç¤¹¤¬). ¥¤¥ó¥¿¥×¥ê¥¿¤Ï wish ¤Î
+ tcl/tk ¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤­¤Þ¤¹. ¤µ¤é¤Ë, °Ê²¼¤Î¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤­¤Þ
+ ¤¹.
+ ¥³¥Þ¥ó¥É ruby
+ °ú¿ô¤ò ruby ¤Ç¼Â¹Ô¤·¤Þ¤¹(ruby_eval_string ¤ò¼Â¹Ô¤·¤Þ¤¹). °ú¿ô
+ ¤Ï 1 ¤Ä¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó. Ìá¤êÃÍ¤Ï ruby ¤Î¼Â¹Ô·ë²Ì¤Ç¤¹.
+ ruby ¤Î¼Â¹Ô·ë²Ì¤Ï nil ¤« String ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó.
+
+ ¥¯¥é¥¹¥á¥½¥Ã¥É new()
+ TclTkIp ¥¯¥é¥¹¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤·¤Þ¤¹
+ °ú¿ô: ̵¤·
+ Ìá¤êÃÍ (TclTkIp): À¸À®¤µ¤ì¤¿¥¤¥ó¥¹¥¿¥ó¥¹
+
+ ¥á¥½¥Ã¥É _eval(script)
+ ¥¤¥ó¥¿¥×¥ê¥¿¤Ç script ¤òɾ²Á¤·¤Þ¤¹(Tcl_Eval ¤ò¼Â¹Ô¤·¤Þ¤¹). Á°½Ò
+ ¤Î¤è¤¦¤Ë, ruby ¥³¥Þ¥ó¥É¤Ë¤è¤ê script Æâ¤«¤é ruby ¥¹¥¯¥ê¥×¥È¤ò¼Â
+ ¹Ô¤Ç¤­¤Þ¤¹.
+ °ú¿ô: script (String) - ¥¤¥ó¥¿¥×¥ê¥¿¤Çɾ²Á¤¹¤ë¥¹¥¯¥ê¥×¥Èʸ»úÎó
+ Ìá¤êÃÍ (String): ɾ²Á·ë²Ì ((Tcl_Interp *)->result)
+
+ ¥á¥½¥Ã¥É _return_value()
+ ľÁ°¤Î Tcl_Eval ¤ÎÌá¤êÃͤòÊÖ¤·¤Þ¤¹. 0(TCL_OK) ¤ÇÀµ¾ï½ªÎ»¤Ç¤¹.
+ °ú¿ô: ̵¤·
+ Ìá¤êÃÍ (Fixnum): ľÁ°¤Î Tcl_Eval() ¤¬ÊÖ¤·¤¿ÃÍ.
+
+==============================================================
+
+°Ê²¼¤¬Ëܥɥ­¥å¥á¥ó¥ÈºîÀ®»þÅÀ¤Ç¤Î tcltklib ¥é¥¤¥Ö¥é¥ê¤ÎÀâÌÀ¤Ç¤¹¡¥
+==============================================================
+¥â¥¸¥å¡¼¥ë TclTkLib
+ : ¸Ä¡¹¤Î Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ë°Í¸¤·¤Ê¤¤½èÍý ( == ¥¤¥Ù¥ó¥È¥ë¡¼
+ : ¥×¤Ë´Ø¤¹¤ë½èÍý ) ¤ò¸Æ¤Ó½Ð¤¹¥á¥½¥Ã¥É¤òÄêµÁ¤·¤¿¥â¥¸¥å¡¼¥ë¡¥
+
+ ¥â¥¸¥å¡¼¥ë TclTkLib::EventFlag
+ : do_one_event ¤ò¸Æ¤Ó½Ð¤¹ºÝ¤Î½èÍýÂоݥ¤¥Ù¥ó¥È¤ò»ØÄꤹ¤ë¤¿¤á¤Î
+ : ¥Õ¥é¥° ( WINDOW|DONT_WAIT ¤È¤¤¤¦¤è¤¦¤Ë¥Ó¥Ã¥È±é»»»Ò¤ÇÏ¢·ë¤·¤Æ
+ : »ØÄê ) ¤òÄê¿ô¤È¤·¤ÆÄêµÁ¤·¤¿¥â¥¸¥å¡¼¥ë¡¥°Ê²¼¤ÎÄê¿ô¤¬´Þ¤Þ¤ì¤ë¡¥
+
+ Äê¿ô NONE
+ : ÃÍ¤Ï 0 ¤Ç¡¤ÃͤȤ·¤Æ¤Ï¤¤¤«¤Ê¤ë¼ïÎà¤Î¥¤¥Ù¥ó¥È¤â»ØÄꤷ¤Æ¤¤¤Ê¤¤
+ : ¤³¤È¤Ë¤Ê¤ë¤¬¡¤¼ÂºÝ¤Î½èÍý¾å¤Ï ALL ¤ÈƱ¤¸¤È¤·¤Æ°·¤ï¤ì¤ë¡¥
+
+ Äê¿ô WINDOW
+ : window ¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
+
+ Äê¿ô FILE
+ : file ¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
+
+ Äê¿ô TIMER
+ : timer ¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
+
+ Äê¿ô IDLE
+ : ¥¢¥¤¥É¥ë¥ë¡¼¥×½èÍý ( ºÆÉÁ²è¤Ê¤É¡¤Â¾¤Î¼ïÎà¤Î¥¤¥Ù¥ó¥È¤¬È¯À¸
+ : ¤·¤Æ¤¤¤Ê¤¤¤È¤­¤Ë¹Ô¤ï¤ì¤ë½èÍý ) ¤ò½èÍýÂоݤȤ¹¤ë
+
+ Äê¿ô ALL
+ : ¤¹¤Ù¤Æ¤Î¼ïÎà¤Î¥¤¥Ù¥ó¥È¤ò½èÍýÂоݤȤ¹¤ë
+ : WINDOW|FILE|TIMER|IDLE ¤ÈƱ¤¸
+
+ Äê¿ô DONT_WAIT
+ : ½èÍýÂоݥ¤¥Ù¥ó¥È¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¡¤¥¤¥Ù¥ó¥ÈȯÀ¸¤òÂÔ¤¿¤º
+ : ¤Ë do_one_event ¤ò½ªÎ» ( false ¤òÊÖ¤¹ ) ¤¹¤ë
+
+ ¥â¥¸¥å¡¼¥ë TclTkLib::VarAccessFlag
+ : _get_variable ¤Ê¤É¤Ç¤Î¥Õ¥é¥°¤ò»ØÄꤹ¤ë¤¿¤á¤Î¤â¤Î¡¥¥Õ¥é¥°¤Ë
+ : ¤Ï°Ê²¼¤ÎÄê¿ô¤ò OR ¤ÇÏ¢·ë¤·¤ÆÍ¿¤¨¤ë¡¥
+
+ Äê¿ô NONE
+ : ÃÍ¤Ï 0 ¤Ç¡¤²¿¤â¥Õ¥é¥°¤ò»ØÄꤷ¤Æ¤¤¤Ê¤¤¤Î¤ËÅù¤·¤¤¡¥
+
+ Äê¿ô GLOBAL_ONLY
+ : Ä̾ÊÑ¿ô¤Î¸¡º÷¤Ï¤Þ¤º¼ê³¤­¸Æ¤Ó½Ð¤·¤ò¹Ô¤Ã¤¿¥ì¥Ù¥ë¤Ç¸¡
+ : º÷¤·¡¤¼¡¤Ë¸½ºß¤Î̾Á°¶õ´Ö¤Ç¸¡º÷¡¤ºÇ¸å¤Ë¥°¥í¡¼¥Ð¥ë¶õ´Ö¤Ç
+ : ¸¡º÷¤ò¹Ô¤¦¡¥¤·¤«¤·¡¤¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¥°
+ : ¥í¡¼¥Ð¥ë¶õ´Ö¤Ç¤Î¤ß¸¡º÷¤¹¤ë¡¥
+ : ¤â¤· GLOBAL_ONLY ¤È NAMESPACE_ONLY ¤È¤¬Î¾Êý»ØÄꤵ¤ì¤¿¾ì
+ : ¹ç¤Ë¤Ï¡¤GLOBAL_ONLY ¤Î»ØÄê¤Ï̵»ë¤µ¤ì¤ë¡¥
+
+ Äê¿ô NAMESPACE_ONLY
+ : ¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¸½ºß¤Î̾Á°¶õ´Ö¤Ç¤Î¤ßÊÑ
+ : ¿ô¤Î¸¡º÷¤ò¹Ô¤¦¡¥GLOBAL_ONLY ¤ÎÀâÌÀ¤â»²¾È¤¹¤ë¤³¤È¡¥
+
+ Äê¿ô LEAVE_ERR_MSG
+ : ÊÑ¿ô¥¢¥¯¥»¥¹¤Ë¤ª¤¤¤Æ¥¨¥é¡¼¤¬È¯À¸¤·¤¿¾ì¹ç¡¤¤³¤Î¥Õ¥é¥°¤¬
+ : »ØÄꤵ¤ì¤Æ¤¤¤ì¤Ð¡¤¼Â¹Ô·ë²Ì¤È¤·¤Æ Tcl ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ë¥¨
+ : ¥é¡¼¥á¥Ã¥»¡¼¥¸¤¬»Ä¤µ¤ì¤ë¡¥¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±
+ : ¤ì¤Ð¡¤¥¨¥é¡¼¥á¥Ã¥»¡¼¥¸¤Ï°ìÀڻĤµ¤ì¤Ê¤¤¡¥
+
+ Äê¿ô APPEND_VALUE
+ : ¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤Æ¤¤¤¿¾ì¹ç¡¤ÊÑ¿ô¤ÎÃͤòÃÖ¤­´¹¤¨¤Î¤Ç
+ : ¤Ï¤Ê¤¯¡¤¸½ºß¤ÎÃͤËÂåÆþÃͤ¬Äɲà (append; ʸ»úÎóÏ¢·ë) ¤µ
+ : ¤ì¤ë¡¥ÊÑ¿ô¤¬Ì¤ÄêµÁ¤¢¤Ã¤¿¾ì¹ç¡¤¤³¤Î¥Õ¥é¥°¤Ï̵»ë¤µ¤ì¤ë¡¥
+
+ Äê¿ô LIST_ELEMENT
+ : ¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ¤ì¤Æ¤¤¤¿¾ì¹ç¡¤ÂåÆþÃͤϤޤº Tcl ¤Î¥ê¥¹
+ : ¥ÈÍ×ÁǤȤ·¤ÆÅ¬ÀڤȤʤë¤è¤¦¤ËÊÑ´¹¤µ¤ì¤ë¡¥ÂåÆþÃͤ¬¥ê¥¹¥È
+ : (¤Þ¤¿¤Ï¥µ¥Ö¥ê¥¹¥È) ¤ÎºÇ½é¤ÎÍ×ÁǤȤʤë¤Î¤Ç¤Ê¤¤¸Â¤ê¡¤ÂåÆþ
+ : ÃͤÎľÁ°¤Ë¤Ï¶õÇòʸ»ú¤¬Äɲ䵤ì¤ë¡¥
+
+ Äê¿ô PARSE_VARNAME
+ : _set_variable ¤Ê¤É¤Î¸Æ¤Ó½Ð¤·¤Ë¤ª¤¤¤Æ¤³¤Î¥Õ¥é¥°¤¬»ØÄꤵ
+ : ¤ì¤Æ¤¤¤¿¾ì¹ç¡¤var_name °ú¿ô¤¬Ï¢ÁÛÇÛÎó̾¤ÈÍ×ÁÇ̾¤È¤òξÊý
+ : ´Þ¤à²ÄǽÀ­¤¬¤¢¤ë (³«¤­³ç¸Ì¤ò´Þ¤ß¡¤ÊĤ¸³ç¸Ì¤Ç½ª¤ï¤ë) ¤³
+ : ¤È¤ò¼¨¤¹¡¥¤½¤Î¾ì¹ç¡¤³ç¸Ì¤Î´Ö¤¬Í×ÁÇ̾»ØÄꡤºÇ½é¤Î³«¤­³ç
+ : ¸Ì¤Þ¤Ç¤¬Ï¢ÁÛÇÛÎó̾¤È¤·¤Æ°·¤ï¤ì¤ë¡¥_set_variable2 ¤Ê¤É¤Ç
+ : ¤³¤Î¥Õ¥é¥°¤ò»ØÄꤹ¤ë¾ì¹ç¡¤Ï¢ÁÛÇÛÎó̾¤ÈÍ×ÁÇ̾¤Ï var_name
+ : ¤«¤éÃê½Ð¤µ¤ì¤ë¤Ï¤º¤Ç¤¢¤ë¤«¤é¡¤index_name °ú¿ô¤Ï nil ¤È
+ : ¤»¤Í¤Ð¤Ê¤é¤Ê¤¤¡¥
+
+ ¥â¥¸¥å¡¼¥ë TclTkLib::RELEASE_TYPE
+ : Tcl/Tk ¤Î¥ê¥ê¡¼¥¹¥¿¥¤¥×ÈÖ¹æ¤ÎÄêµÁ
+
+ Äê¿ô ALPHA
+ : ALPHA ¥ê¥ê¡¼¥¹
+
+ Äê¿ô BETA
+ : BETA ¥ê¥ê¡¼¥¹
+
+ Äê¿ô FINAL
+ : FINAL ¥ê¥ê¡¼¥¹
+
+ ¥â¥¸¥å¡¼¥ë¥á¥½¥Ã¥É
+ get_version()
+ : Tcl/Tk ¤Î major, minor, release-type ÈÖ¹æ, release-type ̾,
+ : patchlevel ¤òÇÛÎó¤Ë¤·¤ÆÊÖ¤¹¡¥
+
+ mainloop(check_root = true)
+ : ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òµ¯Æ°¤¹¤ë¡¥check_root ¤¬ true ¤Ç¤¢¤ì¤Ð¡¤
+ : root widget ¤¬Â¸ºß¤¹¤ë¸Â¤ê¡¤¤³¤Î¥á¥½¥Ã¥É¤Ï½ªÎ»¤·¤Ê¤¤¡¥
+ : check_root ¤¬ false ¤Î¾ì¹ç¤Ï¡¤root widget ¤¬¾ÃÌǤ·¤Æ¤â
+ : ¤³¤Î¥á¥½¥Ã¥É¤Ï½ªÎ»¤·¤Ê¤¤ ( root widget ¤¬¾ÃÌǤ·¤Æ¤â¡¤
+ : WINDOW °Ê³°¤Î¥¤¥Ù¥ó¥È¤ÏȯÀ¸¤·¤¦¤ë¤¿¤á )¡¥½ªÎ»¤Ë¤Ï¡¤³°Éô
+ : ¤«¤é¤ÎƯ¤­³Ý¤± ( ¥¹¥ì¥Ã¥É¤ò³èÍѤ¹¤ë¤Ê¤É ) ¤¬É¬Íס¥
+
+ mainloop_thread?
+ : ¥«¥ì¥ó¥È¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¼Â¹Ô¤·¤Æ¤¤¤ë¥¹¥ì¥Ã¥É
+ : ¤«¤É¤¦¤«¤òÊÖ¤¹¡¥
+ : ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¼Â¹Ô¤·¤Æ¤¤¤ë¥¹¥ì¥Ã¥É¤Ç¤¢¤ì¤Ð true ¤ò¡¤
+ : ¤É¤Î¥¹¥ì¥Ã¥É¤Ç¤â¥¤¥Ù¥ó¥È¥ë¡¼¥×¤¬¼Â¹Ô¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï
+ : nil ¤ò¡¤Â¾¤Î¥¹¥ì¥Ã¥É¤Ç¥¤¥Ù¥ó¥È¥ë¡¼¥×¤¬¼Â¹Ô¤µ¤ì¤Æ¤¤¤ë¾ì
+ : ¹ç¤Ï false ¤òÊÖ¤¹¡¥
+ : false ¤ÎºÝ¤Ë Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤òľÀÜ¸Æ¤Ö¤Î¤Ï´í¸±¤Ç¤¢¤ë¡¥
+
+ mainloop_watchdog(check_root = true)
+ : Ä̾ï¤Î¥¤¥Ù¥ó¥È¥ë¡¼¥×¤Ç¤Ï¡¤¥¤¥Ù¥ó¥È½èÍý¤ÎÆâÍÆ¤Ë¤è¤Ã¤Æ¤Ï
+ : ¥Ç¥Ã¥É¥í¥Ã¥¯¤ò°ú¤­µ¯¤³¤¹²ÄǽÀ­¤¬¤¢¤ë (Î㤨¤Ð¥¤¥Ù¥ó¥È¤Ë
+ : ÂФ¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯½èÍýÃæ¤Ç widget Áàºî¤ò¤·¡¤¤½¤Î½ªÎ»¤ò
+ : ÂԤĤʤÉ)¡¥¤³¤Î¥á¥½¥Ã¥É¤Ï¡¤¤½¤¦¤·¤¿¥Ç¥Ã¥É¥í¥Ã¥¯¤ò²óÈò¤¹
+ : ¤ë¤¿¤á¤Î´Æ»ë¥¹¥ì¥Ã¥ÉÉÕ¤­¤Ç¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òµ¯Æ°¤¹¤ë
+ : ( ´Æ»ë¥¹¥ì¥Ã¥É¤òÀ¸À®¤·¤¿¸å¤Ë¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¼Â¹Ô¤¹¤ë )¡¥
+ : °ú¿ô¤Î°ÕÌ£¤Ï mainloop ¤ÈƱ¤¸¤Ç¤¢¤ë¡¥
+
+ do_one_event(flag = TclTkLib::EventFlag::ALL |
+ TclTkLib::EventFlag::DONT_WAIT)
+ : ½èÍýÂÔ¤Á¤Î¥¤¥Ù¥ó¥È 1 ¸Ä¤ò¼Â¹Ô¤¹¤ë¡¥
+ : ¥¤¥Ù¥ó¥È¤ò½èÍý¤·¤¿¾ì¹ç¤Ï true ¤òÊÖ¤¹¡¥
+ : ¥Õ¥é¥°¤Ç DONT_WAIT ¤ò»ØÄꤷ¤Æ¤¤¤Ê¤¤¾ì¹ç¡¤¥Õ¥é¥°¤Ç½èÍýÂÐ
+ : ¾Ý¤È¤Ê¤Ã¤Æ¤¤¤ë¼ïÎà¤Î¥¤¥Ù¥ó¥È¤¬È¯À¸¤¹¤ë¤Þ¤ÇÂÔ¤Á³¤±¤ë¡¥
+ : DONT_WAIT ¤ò»ØÄꤷ¤Æ¤¤¤¿¾ì¹ç¡¤½èÍýÂоݥ¤¥Ù¥ó¥È¤¬¤Ê¤¯¤Æ¤â
+ : ¤¹¤°¤Ë½ªÎ»¤· false ¤òÊÖ¤¹¡¥
+ : $SAFE >= 4 ¤«¡¤$SAFE >= 1 ¤«¤Ä flag ¤¬±øÀ÷¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð
+ : flag ¤Ë¤Ï DONT_WAIT ¤¬¶¯À©Åª¤ËÉÕ¤±¤é¤ì¤ë¡¥
+
+ set_eventloop_tick(timer_tick)
+ : ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ÈƱ»þ¤ËÊÌ¥¹¥ì¥Ã¥É¤¬²ÔƯ¤·¤Æ¤¤¤ë¾ì¹ç¤Ë¡¤»þ
+ : ´Ö¤Ë´ð¤Å¤¤¤¿¶¯À©Åª¤Ê¥¹¥ì¥Ã¥É¥¹¥¤¥Ã¥Á¥ó¥°¤ò¤É¤ÎÄøÅÙ¤ÎÉÑÅÙ
+ : ( »þ´Ö´Ö³Ö ) ¤ÇȯÀ¸¤µ¤»¤ë¤«¤ò¥ß¥êÉÃñ°Ì¤ÎÀ°¿ôÃͤǻØÄꤹ¤ë¡¥
+ : 0 ¤ò»ØÄꤹ¤ë¤È¡¤¤³¤Î¶¯À©Åª¤Ê¥¹¥¤¥Ã¥Á¥ó¥°¤Ï¹Ô¤ï¤ì¤Ê¤¤¡¥
+ : ɸ½à¤Ç¤Ï 0 ¤ËÀßÄꤵ¤ì¤Æ¤ª¤ê¡¤¥¤¥Ù¥ó¥È½èÍý¿ô¤Ë´ð¤Å¤¯¥¹¥¤¥Ã
+ : ¥Á¥ó¥°¤À¤±¤¬¹Ô¤ï¤ì¤ë ( see set_eventloop_weight )¡¥
+ : ¤¿¤À¤·¡¤²ÔƯ¤·¤Æ¤¤¤ë¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤À¤±¤Î¾ì¹ç¡¤
+ : timer_tick ¤ò 0 ¤ËÀßÄꤹ¤ë¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡¥¤â¤·ÀßÄꤵ¤ì¤Æ
+ : ¤¤¤¿¤é¡¤100 ms ( see NO_THREAD_INTERRUPT_TIME ) ¤Ë¼«Æ°Àß
+ : Äꤵ¤ì¤ë¡¥
+ : ¾ÜºÙ¤ÊÀâÌÀ¤Ïά¤¹¤¬¡¤¤³¤ì¤Ï CPU ¥Ñ¥ï¡¼¤òÀáÌ󤷤ĤİÂÁ´¤Ç
+ : °ÂÄꤷ¤¿Æ°ºî¤ò¼Â¸½¤¹¤ë¤¿¤á¤Ë¼ÂÁõ¤·¤¿»ÅÍͤǤ¢¤ë¡¥
+ : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
+
+ get_eventloop_tick
+ : timer_tick ¤Î¸½ºßÃͤòÊÖ¤¹¡¥
+
+ set_no_event_wait(no_event_wait)
+ : Ê£¿ô¤Î¥¹¥ì¥Ã¥É¤¬²ÔƯ¤·¤Æ¤¤¤ë¾ì¹ç¤Ç¡¤½èÍýÂÔ¤Á¥¤¥Ù¥ó¥È¤¬Á´
+ : ¤¯Â¸ºß¤·¤Ê¤«¤Ã¤¿ºÝ¤Ë sleep ¾õÂÖ¤ËÆþ¤ë»þ´ÖŤò»ØÄꤹ¤ë¡¥
+ : ²ÔƯ¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤À¤±¤Î¾ì¹ç¤Ë¤Ï°ÕÌ£¤ò¤Ê¤µ¤Ê¤¤¡¥
+ : ¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¤Ï 20 (ms)
+ : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
+
+ get_no_event_wait
+ : no_event_wait ¤Î¸½ºßÃͤòÊÖ¤¹¡¥
+
+ set_eventloop_weight(loop_max, no_event_tick)
+ : Ê£¿ô¤Î¥¹¥ì¥Ã¥É¤¬²ÔƯ¤·¤Æ¤¤¤ëºÝ¤Ë Ruby/Tk ¤Î¥¤¥Ù¥ó¥È¥ë¡¼
+ : ¥×¤Ë³ä¤êÅö¤Æ¤ëÈæ½Å¤òÄê¤á¤ë¤¿¤á¤Î¥Ñ¥é¥á¡¼¥¿¤òÀßÄꤹ¤ë¡¥
+ : ²ÔƯ¥¹¥ì¥Ã¥É¤¬¥¤¥Ù¥ó¥È¥ë¡¼¥×¤À¤±¤Î¾ì¹ç¤Ë¤Ï°ÕÌ£¤ò¤Ê¤µ¤Ê¤¤¡¥
+ : °ìÅ٤Υ¹¥ì¥Ã¥ÉÀÚ¤êÂØ¤¨¤Î´Ö¤Ë½èÍý¤¹¤ë¥¤¥Ù¥ó¥È¤ÎºÇÂç¿ô¤È¡¤
+ : ½èÍýÂÔ¤Á¤Î¥¤¥Ù¥ó¥È¤¬Â¸ºß¤·¤Ê¤¤ºÝ¤Î²Ã»»¿ô¤È¤òÀßÄꤹ¤ë¡¥
+ : ½èÍýÂÔ¤Á¥¤¥Ù¥ó¥È¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ï no_event_wait ( see
+ : set_no_event_wait ) ¤À¤±¤Î´Ö sleep ¾õÂÖ¤ËÆþ¤ë¡¥
+ : ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¤½¤ì¤¾¤ì 800 ²ó¤È 10 ²ó¡¤¤Ä¤Þ¤ê¡¤800 ¸Ä¤Î¥¤
+ : ¥Ù¥ó¥È (¥¢¥¤¥É¥ë¥¤¥Ù¥ó¥È¤ò´Þ¤à) ¤ò½èÍý¤¹¤ë¤È¤«¡¤¥¤¥Ù¥ó¥È
+ : ¤¬Á´¤¯È¯À¸¤·¤Ê¤¤¤Þ¤Þ¤Ë 80 ²ó¤Î½èÍýÂÔ¤Á¥¤¥Ù¥ó¥È¸¡ºº¤¬´°Î»
+ : ¤¹¤ë¤È¤«¤Ç¥«¥¦¥ó¥È¤¬ 800 °Ê¾å¤Ë¤Ê¤ë¤È¥¹¥ì¥Ã¥É¥¹¥¤¥Ã¥Á¥ó¥°
+ : ¤¬È¯À¸¤¹¤ë¤³¤È¤Ë¤Ê¤ë¡¥
+ : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
+
+ get_eventloop_weight
+ : ¸½ºß¤Î loop_max ¤È no_event_tick ¤È¤ÎÃͤòÊÖ¤¹¡¥
+ : ( see set_eventloop_wait )
+
+ mainloop_abort_on_exception=(bool)
+ : Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤ÇÎã³°¤òȯÀ¸¤·¤¿ºÝ¤Ë¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò
+ : ¥¨¥é¡¼Ää»ß¤µ¤»¤ë¤«¤É¤¦¤«¤ò»ØÄꤹ¤ë¡¥true ¤ò»ØÄꤷ¤¿¾ì¹ç¤Ï
+ : ¥¨¥é¡¼Ää»ß¤¹¤ë¤¬¡¤false ¤Î¾ì¹ç¤ÏÎã³°¤ò̵»ë¤·¤Æ¥¤¥Ù¥ó¥È¥ë¡¼
+ : ¥×¤ò·Ñ³¤¹¤ë¡¥¤µ¤é¤Ë nil ¤Î¾ì¹ç¤Ï·Ù¹ð¥â¡¼¥É¤Ç¤Ê¤¤¸Â¤ê¤Ï¥¨
+ : ¥é¡¼¥á¥Ã¥»¡¼¥¸¤Î½ÐÎϤ¹¤é¾Êά¤·¤Æ¡¤Îã³°¤ò̵»ë¤¹¤ë¡¥
+ : ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï true ¤ËÀßÄꤵ¤ì¤Æ¤¤¤ë¡¥
+ : £±¸Ä¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤À¤±¤ò»È¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¥¨¥é¡¼»þ¤Ë¤½¤Î
+ : ¤Þ¤ÞÄä»ß¤·¤Æ¤âÄ̾ï¤ÏÌäÂê¤Ê¤¤¤¬¡¤Ê£¿ô¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬Æ±»þ
+ : ¤Ëưºî¤·¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤é¤ò´ÉÍý¤¹¤ë¥¤¥Ù¥ó¥È¥ë¡¼¥×¤Ï£±
+ : ¸Ä¤À¤±¤Ç¤¢¤ë¤¿¤á¡¤¤¤¤º¤ì¤«¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î¥¨¥é¡¼¤¬¸¶°ø¤Ç¡¤
+ : ¾¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î½èÍý·Ñ³¤¬ÉÔ²Äǽ¤Ë¤Ê¤ë¤³¤È¤¬¤¢¤ë¡¥¤½¤Î
+ : ¤è¤¦¤Ê¾ì¹ç¤Ç¤â¥¨¥é¡¼¤ò̵»ë¤·¤Æ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤¬²ÔƯ¤ò³¤±¤ë
+ : ¤³¤È¤Ç¡¤Â¾¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬Àµ¾ï¤Ëưºî¤·Â³¤±¤ë¤³¤È¤¬¤Ç¤­¤ë¡¥
+ : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
+
+ mainloop_abort_on_exception
+ : Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤ÇÎã³°¤òȯÀ¸¤·¤¿ºÝ¤Ë¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ò¥¨
+ : ¥é¡¼Ää»ß¤µ¤»¤ë¤«¤É¤¦¤«¤ÎÀßÄê¾õÂÖ¤ò true/false ¤ÇÆÀ¤ë¡¥
+
+ num_of_mainwindows
+ : ¸½ºß¤Î¥á¥¤¥ó¥¦¥£¥ó¥É¥¦ (¥ë¡¼¥È¥¦¥£¥¸¥§¥Ã¥È) ¤Î¿ô¤òÊÖ¤¹¡¥
+ : ¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤Ï°ì¤Ä¤Î¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ËÉÕ¤­ºÇÂç°ì¤Ä¤Ç¤¢¤ë
+ : ¤Î¤Ç¡¤¤³¤ÎÃͤϸ½ºß Tk ¤Îµ¡Ç½¤¬Í­¸ú¤Ç¤¢¤ë¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ÎÁí
+ : ¿ô¤ËÅù¤·¤¤¡¥
+
+ _merge_tklist(str, str, ... )
+ : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤°ú¿ô¤Îʸ»úÎ󤬤½¤ì¤¾¤ì
+ : Àµ¤·¤¯°ì¤Ä¤Î¥ê¥¹¥ÈÍ×ÁǤȤʤë¤è¤¦¤ËÏ¢·ë¤·¤¿Ê¸»úÎó¤òÊÖ¤¹¡¥
+
+ _conv_listelement(str)
+ : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤°ú¿ô¤Îʸ»úÎó¤¬ Tcl ¤Î
+ : °ì¤Ä¤Î¥ê¥¹¥ÈÍ×ÁǤȤ·¤ÆÅ¬ÀÚ¤Êɽ¸½¤Ë¤Ê¤ë¤è¤¦¤ËÊÑ´¹¤·¤¿Ê¸
+ : »úÎó¤òÊÖ¤¹¡¥
+
+ _toUTF8(str, encoding=nil)
+ _fromUTF8(str, encoding=nil)
+ : Tcl/Tk ¤¬Æâ¢¤·¤Æ¤¤¤ë UTF8 ÊÑ´¹½èÍý¤ò¸Æ¤Ó½Ð¤¹¡¥
+
+ _subst_UTF_backslash(str)
+ _subst_Tcl_backslash(str)
+ : Tcl ¤Î¥ë¡¼¥ë¤Ç¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥åµ­Ë¡ ( \uhhhh ¤Ë¤è¤ë
+ : Unicode ʸ»úɽ¸½¤ò´Þ¤à ) ¤ò²òÀϤ¹¤ë¡¥
+ : _subst_Tcl_backslash ¤Ï¤¹¤Ù¤Æ¤Î¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥åµ­Ë¡¤ò
+ : ÃÖ¤­´¹¤¨¤ë¤Î¤ËÂФ·¡¤_subst_UTF_backslash ¤Ï \uhhhh
+ : ¤Ë¤è¤ë Unicode ʸ»úɽ¸½¤À¤±¤òÃÖ¤­´¹¤¨¤ë¡¥
+
+ encoding_system
+ encoding_system=(encoding)
+ : Tcl ¤Î system encoding ¤Î³ÍÆÀ¤ª¤è¤ÓÀßÄê
+
+ encoding
+ encoding=(encoding)
+ : encoding_system / encoding_system= ¤Î alias
+ : ( Ruby/Tk ¤Î tk.rb ¤Ç¤ÏÃÖ¤­´¹¤¨¤é¤ì¤ëͽÄê¤Î¤â¤Î¡¥)
+
+
+¥¯¥é¥¹ TclTkIp
+ ¥¯¥é¥¹¥á¥½¥Ã¥É
+ new(ip_name=nil, options='')
+ : TclTkIp ¥¯¥é¥¹¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÀ¸À®¤¹¤ë¡¥
+ : ip_name ¤Ëʸ»úÎó¤òÍ¿¤¨¤¿¾ì¹ç¤Ï¡¤¤½¤ì¤¬ winfo interps ¤Ê¤É¤Ç
+ : ɽ¼¨¤µ¤ì¤ë̾Á°¤Ë¤Ê¤ë¡¥
+ : options ¤Ë¤Ï¡¤-geometry ¤ä -use ¤Ê¤É¡¤wish ¤Î¥³¥Þ¥ó¥É¥é¥¤¥ó
+ : °ú¿ô¤È¤·¤ÆÍ¿¤¨¤ë¥ª¥×¥·¥ç¥ó¤ÈƱÍͤξðÊó¤òʸ»úÎó¤È¤·¤ÆÍ¿¤¨¤ë¡¥
+ : Í¿¤¨¤é¤ì¤¿¾ðÊó¤Ï¡¤root widget À¸À®¤ÎºÝ¤ËÍѤ¤¤é¤ì¤ë¡¥
+ : ( e.g. TclTkIp.new('FOO', '-geometry 500x200 -use 0x2200009') )
+ : ¤â¤· options ¤Ë´º¤¨¤Æ nil ¤Þ¤¿¤Ï false ¤òÍ¿¤¨¤¿¾ì¹ç¡¤Tk ¥é¥¤
+ : ¥Ö¥é¥ê¤¬Æ³Æþ¤µ¤ì¤Æ¤¤¤Ê¤¤ (¤Ä¤Þ¤ê¤Ï Tcl ¤Î¤ß¤Î) ¥¤¥ó¥¿¡¼¥×¥ê
+ : ¥¿¤òÀ¸À®¤¹¤ë¡¥¤³¤Î¾ì¹ç¤Ï GUI ´Ä¶­¤ÏɬÍפʤ¤¤¿¤á¡¤¥¦¥¤¥ó¥É¥¦
+ : ¥·¥¹¥Æ¥à¤¬Â¸ºß¤·¤Ê¤¤¡¤¤Þ¤¿¤Ï»ÈÍѤǤ­¤Ê¤¤´Ä¶­¤Ç¤â Tcl ¥¤¥ó¥¿¡¼
+ : ¥×¥ê¥¿¤òÀ¸À®¤·¡¤Tcl ¤ä¤½¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò³èÍѤ¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡¥
+
+ ¥¤¥ó¥¹¥¿¥ó¥¹¥á¥½¥Ã¥É
+ create_slave(name, safe=false)
+ : ¥ì¥·¡¼¥Ð¤ò¿Æ¤È¤¹¤ë name ¤È¤¤¤¦Ì¾Á°¤Î¥¹¥ì¡¼¥Ö¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò
+ : À¸À®¤¹¤ë¡¥
+ : safe ¤Ë¤ÏÀ¸À®¤¹¤ë¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤È¤¹¤ë
+ : ¤«¤ò»ØÄꤹ¤ë¡¥¥Ç¥Õ¥©¥ë¥È¤Ï false ¤È¤¤¤¦¤³¤È¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¬¡¤
+ : ¤¿¤È¤¨ÌÀ³Î¤Ë false ¤ò»ØÄꤷ¤Æ¤¤¤¿¤È¤·¤Æ¤â¡¤¿Æ¤È¤Ê¤ë¥¤¥ó¥¿¡¼
+ : ¥×¥ê¥¿¤¬ safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ç¤¢¤ì¤Ð¡¤¤½¤ÎÀßÄê¤ò°ú¤­·Ñ¤¤¤Ç
+ : safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤È¤·¤ÆÀ¸À®¤µ¤ì¤ë¡¥
+ : $SAFE >= 4 ¤Ç¤Ï¡¤safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿°Ê³°¤ÎÀ¸À®¤¬¶Ø»ß¤µ¤ì¤ë¡¥
+
+ make_safe
+ : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ËÊѹ¹¤¹¤ë¡¥
+ : Ìá¤êÃͤϥ쥷¡¼¥Ð¤Ç¤¢¤ë¥¤¥ó¥¿¡¼¥×¥ê¥¿¼«¿È¤Ç¤¢¤ë¡¥
+ : ¼ºÇÔ¤·¤¿¾ì¹ç¤Ï RuntimeError ¤ÎÎã³°¤òȯÀ¸¤¹¤ë¡¥
+
+ safe?
+ : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬ safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ç¤¢¤ë¤«¤òÄ´¤Ù¤ë¡¥
+ : safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ç¤¢¤ì¤Ð true ¤òÊÖ¤¹¡¥
+
+ allow_ruby_exit?
+ : ÂоݤȤʤ륤¥ó¥¿¡¼¥×¥ê¥¿¾å¤Îɾ²Á¤Ç¡¤ruby ¤Î exit ´Ø¿ô¤Þ¤¿¤Ï
+ : Tcl/Tk ¾å¤Î exit ¥³¥Þ¥ó¥É¤Ë¤è¤Ã¤Æ ruby ¼«ÂΤò½ªÎ»¤µ¤»¤ë¤³¤È
+ : ¤òµö¤¹¤«¤É¤¦¤«¤òÊÖ¤¹¡¥
+ : µö¤µ¤Ê¤¤¾ì¹ç¤ÏÂоݤΥ¤¥ó¥¿¡¼¥×¥ê¥¿¤À¤±¤¬½ªÎ»¤¹¤ë¡¥
+ : ¥Þ¥¹¥¿¡¼¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï true¡¤¥¹¥ì¡¼¥Ö¥¤¥ó¥¿¡¼
+ : ¥×¥ê¥¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ¤Ï false ¤Ç¤¢¤ë¡¥
+
+ allow_ruby_exit=(mode)
+ : ÂоݤȤʤ륤¥ó¥¿¡¼¥×¥ê¥¿¤Î allow_ruby_exit? ¤Î¾õÂÖ¤òÊѹ¹¤¹¤ë¡¥
+ : $SAFE >= 4 ¤Þ¤¿¤Ï¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬ safe ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î¾ì¹ç¤Ï
+ : Êѹ¹¤¬µö¤µ¤ì¤Ê¤¤ (Îã³°¤òȯÀ¸)¡¥
+
+ delete
+ : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤ò delete ¤¹¤ë¡¥
+ : delete ¤µ¤ì¤¿¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¡¤°Ê¸å°ìÀÚ¤ÎÁàºî¤¬¤Ç¤­¤Ê¤¯¤Ê¤ê¡¤
+ : ¥³¥Þ¥ó¥É¤òÁ÷¤Ã¤Æ¤âÎã³°¤òȯÀ¸¤¹¤ë¤è¤¦¤Ë¤Ê¤ë¡¥
+
+ deleted?
+ : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬¤¹¤Ç¤Ë delete ¤µ¤ì¤Æ¤¤¤ë¤«¤òÄ´¤Ù¤ë¡¥
+ : delete ºÑ¤ß¤Ç¥³¥Þ¥ó¥É¤ò¼õ¤±ÉÕ¤±¤Ê¤¤¾õÂ֤ˤʤäƤ¤¤ë¤Ê¤é¤Ð
+ : true ¤òÊÖ¤¹¡¥
+
+ has_mainwindow?
+ : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ë¥á¥¤¥ó¥¦¥£¥ó¥É¥¦ (root widget) ¤¬
+ : ¸ºß¤¹¤ì¤Ð true ¤ò¡¤Â¸ºß¤·¤Ê¤±¤ì¤Ð false ¤òÊÖ¤¹¡¥
+ : ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤¬´û¤Ë delete ºÑ¤ß¤Ç¤¢¤ì¤Ð nil ¤òÊÖ¤¹¡¥
+
+ restart
+ : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î Tk Éôʬ¤Î½é´ü²½¡¤ºÆµ¯Æ°¤ò¹Ô¤¦¡¥
+ : °ìö root widget ¤òÇ˲õ¤·¤¿¸å¤ËºÆÅÙ Tk ¤Îµ¡Ç½¤¬É¬ÍפÈ
+ : ¤Ê¤Ã¤¿¾ì¹ç¤ËÍѤ¤¤ë¡¥
+ : $SAFE >= 4 ¤Ç¤Ï¼Â¹Ô¤¬¶Ø»ß¤µ¤ì¤ë¡¥
+
+ _eval(str)
+ _invoke(*args)
+ : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤Çɾ²Á¤ò¹Ô¤¦¡¥
+ : _eval ¤Ïɾ²Á¥¹¥¯¥ê¥×¥È¤¬°ì¤Ä¤Îʸ»úÎó¤Ç¤¢¤ë¤³¤È¤ËÂФ·¡¤
+ : _invoke ¤Ïɾ²Á¥¹¥¯¥ê¥×¥È¤Î token ¤´¤È¤Ë°ì¤Ä¤Î°ú¿ô¤È¤Ê
+ : ¤ë¤è¤¦¤ËÍ¿¤¨¤ë¡¥
+ : _invoke ¤ÎÊý¤Ï Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Î»ú¶ç²òÀÏ´ï¤òÍѤ¤
+ : ¤Ê¤¤¤¿¤á¡¤É¾²Á¤ÎÉé²Ù¤¬¤è¤ê¾¯¤Ê¤¯¤Æ¤¹¤à¡¥¤¿¤À¤·¡¤¤½¤ÎÂå
+ : ¤ï¤ê¤Ë auto_load ¤Î¤è¤¦¤Êµ¡¹½¤ÏƯ¤«¤º¡¤load Åù¤Ë¤è¤Ã¤Æ
+ : Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿¾å¤Ë´û¤ËÅÐÏ¿ºÑ¤ß¤Î¥³¥Þ¥ó¥É¤·¤«¸Æ
+ : ¤Ó½Ð¤¹¤³¤È¤¬¤Ç¤­¤Ê¤¤¡¥
+ : _eval ¤Ç¤Ï auto_load µ¡¹½¤¬Æ¯¤¯¤¿¤á¡¤°ìÅÙ _eval ¤ò¼Â¹Ô
+ : ¤·¤ÆÅÐÏ¿¤ËÀ®¸ù¤·¤µ¤¨¤¹¤ì¤Ð¡¤°Ê¹ß¤Ï _invoke ¤Ç¤âÍøÍѤÇ
+ : ¤­¤ë¤è¤¦¤Ë¤Ê¤ë¡¥
+
+ _toUTF8(str, encoding=nil)
+ _fromUTF8(str, encoding=nil)
+ : Tcl/Tk ¤¬Æâ¢¤·¤Æ¤¤¤ë UTF8 ÊÑ´¹½èÍý¤ò¸Æ¤Ó½Ð¤¹¡¥
+
+ _thread_vwait(var_name)
+ _thread_tkwait(mode, target)
+ : ¥¹¥ì¥Ã¥ÉÂбþ¤Î vwait ¤¢¤ë¤¤¤Ï tkwait ÁêÅö¤Î¥á¥½¥Ã¥É¡¥
+ : Ä̾ï¤Î vwait ¤¢¤ë¤¤¤Ï tkwait ¥³¥Þ¥ó¥É¤È°Û¤Ê¤ë¤Î¤Ï¡¤¥¤¥Ù¥ó
+ : ¥È¥ë¡¼¥×¤È¤Ï°Û¤Ê¤ë¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ó½Ð¤·¤¿¾ì¹ç¤Ë vwait Åù¤Î
+ : ¥¹¥¿¥Ã¥¯¤È¤ÏÆÈΩ¤Ë¾ò·ï¤ÎÀ®Î©ÂÔ¤Á¤¬¤Ê¤µ¤ì¤ë¤³¤È¤Ç¤¢¤ë¡¥
+ : Ä̾ï¤Î vwait / tkwait ¤Ç¤Ï¡¤vwait / tkwait (1) ¤ÎÂÔ¤Á¤ÎÅÓ
+ : Ãæ¤Ç¤µ¤é¤Ë vwait / tkwait (2) ¤¬¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤ÂÔ¤Á¤ÎÂоÝ
+ : ¤È¤Ê¤Ã¤Æ¤¤¤ë¾ò·ï¤ÎÀ®Î©½ç½ø¤¬¤É¤¦¤¢¤ì¡¤(2)->(1) ¤Î½ç¤ÇÂÔ¤Á
+ : ¤ò½ªÎ»¤·¤ÆÌá¤Ã¤Æ¤¯¤ë¡¥
+ : _thread_vwait / _thread_tkwait ¤Ï¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×¤Î¥¹¥ì¥Ã
+ : ¥É¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤ÏÄ̾ï¤Î vwait / tkwait ¤ÈƱÍÍ¤ËÆ°ºî¤¹¤ë
+ : ¤¬¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×°Ê³°¤Î¥¹¥ì¥Ã¥É¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¤Ï¤½¤Î¥¹
+ : ¥ì¥Ã¥É¤òÄä»ß¤µ¤»¤ÆÂÔ¤Á¤ËÆþ¤ê¡¤¾ò·ï¤¬À®Î©¤·¤¿»þ¤Ë¥¹¥ì¥Ã¥É
+ : ¤Î¼Â¹Ô¤òºÆ³«¤¹¤ë¡¥¡Övwait Åù¤ÎÂÔ¤Á¥¹¥¿¥Ã¥¯¤È¤ÏÆÈΩ¡×¤È¤¤
+ : ¤¦°ÕÌ£¤Ï¡¤¤³¤ÎºÆ³«¤Î¥¿¥¤¥ß¥ó¥°¤¬Â¾¤Î¥¹¥ì¥Ã¥É¤Ç¤ÎÂÔ¤Á¾õ¶·
+ : ¤È¤Ï̵´Ø·¸¤È¤¤¤¦¤³¤È¤Ç¤¢¤ë¡¥¤Ä¤Þ¤ê¡¤¥¤¥Ù¥ó¥È¥ë¡¼¥×Åù¤Î¾
+ : ¤Î¥¹¥ì¥Ã¥É¤Ç vwait Åù¤ÇÂÔ¤Á¤Î¾õÂ֤ˤ¢¤Ã¤¿¤È¤·¤Æ¤â¤½¤Î´°Î»
+ : ¤òÂԤĤ³¤È¤Ê¤¯¡¤¼«¤é¤ÎÂÔ¤Á¾ò·ï¤¬À®Î©¼¡Â衤½èÍý¤ò·Ñ³¤¹¤ë
+ : ¤³¤È¤Ë¤Ê¤ë¡¥
+
+ _return_value
+ : ľÁ°¤Î Tcl/Tk ¾å¤Ç¤Îɾ²Á¤Î¼Â¹Ô·ë²Ì¤È¤·¤Æ¤ÎÌá¤êÃͤòÊÖ¤¹¡¥
+
+ _get_variable(var_name, flag)
+ _get_variable2(var_name, index_name, flag)
+ : Tcl/Tk ¾å¤Î var ¤È¤¤¤¦ÊÑ¿ô̾¤ÎÊÑ¿ô¤ÎÃͤòÊÖ¤¹¡¥
+ : ¤â¤· index_name ¤¬»ØÄê (PARSE_VARNAME ¥Õ¥é¥°¤ÎÀâÌÀ¤â»²¾È)
+ : ¤µ¤ì¤¿¾ì¹ç¤ÏÏ¢ÁÛÇÛÎó var_name ¤Î index_name ¤ÎÍ×ÁǤòÊÖ¤¹¡¥
+ : flag ¤Ë¤ÏÊÑ¿ô¤ò¸¡º÷¤¹¤ëºÝ¤Î¾ò·ï¤ò»ØÄꤹ¤ë¡¥flag ¤ËÍ¿¤¨¤ë
+ : Ãͤϥ⥸¥å¡¼¥ë TclTkLib::VarAccessFlag ¤ò»²¾È¤¹¤ë¤³¤È¡¥
+
+ _set_variable(var_name, value, flag)
+ _set_variable2(var_name, index_name, value, flag)
+ : Tcl/Tk ¾å¤Î var ¤È¤¤¤¦ÊÑ¿ô̾¤ÎÊÑ¿ô¤ËÃͤòÀßÄꤹ¤ë¡¥
+ : ¤â¤· index_name ¤¬»ØÄê (PARSE_VARNAME ¥Õ¥é¥°¤ÎÀâÌÀ¤â»²¾È)
+ : ¤µ¤ì¤¿¾ì¹ç¤ÏÏ¢ÁÛÇÛÎó var_name ¤Î index_name ¤ÎÍ×ÁǤòÀßÄê
+ : ¤¹¤ë¡¥
+ : flag ¤Ë¤ÏÊÑ¿ô¤ò¸¡º÷¤¹¤ëºÝ¤Î¾ò·ï¤ò»ØÄꤹ¤ë¡¥flag ¤ËÍ¿¤¨¤ë
+ : Ãͤϥ⥸¥å¡¼¥ë TclTkLib::VarAccessFlag ¤ò»²¾È¤¹¤ë¤³¤È¡¥
+
+ _unset_variable(var_name)
+ _unset_variable2(var_name, index_name)
+ : Tcl/Tk ¾å¤Î var_name ¤È¤¤¤¦ÊÑ¿ô̾¤ÎÊÑ¿ô¤ò¾Ãµî¤¹¤ë¡¥
+ : ¤â¤· index_name ¤¬»ØÄê (PARSE_VARNAME ¥Õ¥é¥°¤ÎÀâÌÀ¤â»²¾È)
+ : ¤µ¤ì¤¿¾ì¹ç¤ÏÏ¢ÁÛÇÛÎó var_name ¤«¤é index_name ¤ÎÍ×ÁǤÀ¤±
+ : ¤ò¾Ãµî¤¹¤ë¡¥
+
+ _get_global_var(var_name)
+ _get_global_var2(var_name, index_name)
+ _set_global_var(var_name, value)
+ _set_global_var2(var_name, index_name, value)
+ _unset_global_var(var_name)
+ _unset_global_var2(var_name, index_name)
+ : ¤½¤ì¤¾¤ì¡¤Âбþ¤¹¤ëÊÑ¿ô¥¢¥¯¥»¥¹¥á¥½¥Ã¥É¤Î flag ¤ËÂФ·¤Æ
+ : (GLOBAL_ONLY | LEAVE_ERR_MSG) ¤òÍ¿¤¨¤¿¤â¤Î¡¥
+
+ _split_tklist(str)
+ : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤Ê¸»úÎó str ¤ò¥ê¥¹¥È¤Ë
+ : ʬ³ä¤¹¤ë (ʸ»úÎó¤ÎÇÛÎó¤È¤·¤ÆÊÖ¤¹)¡¥
+
+ _merge_tklist(str, str, ... )
+ : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤°ú¿ô¤Îʸ»úÎ󤬤½¤ì¤¾¤ì
+ : Àµ¤·¤¯°ì¤Ä¤Î¥ê¥¹¥ÈÍ×ÁǤȤʤë¤è¤¦¤ËÏ¢·ë¤·¤¿Ê¸»úÎó¤òÊÖ¤¹¡¥
+
+ _conv_listelement(str)
+ : Tcl/Tk ¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ò»È¤Ã¤Æ¡¤°ú¿ô¤Îʸ»úÎó¤¬ Tcl ¤Î
+ : °ì¤Ä¤Î¥ê¥¹¥ÈÍ×ÁǤȤ·¤ÆÅ¬ÀÚ¤Êɽ¸½¤Ë¤Ê¤ë¤è¤¦¤ËÊÑ´¹¤·¤¿Ê¸
+ : »úÎó¤òÊÖ¤¹¡¥
+
+ mainloop
+ mainloop_watchdog
+ : ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤Ï¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òµ¯Æ°¤»¤º¤Ë nil ¤òÊÖ¤¹¡¥
+ : ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
+
+ do_one_event
+ : ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤Ï°ú¿ô¤Î¥¤¥Ù¥ó¥È¥Õ¥é¥°¤Ë DONT_WAIT ¤¬
+ : ¶¯À©Åª¤ËÄɲ䵤ì¤ë (¥¤¥Ù¥ó¥ÈÂÔ¤Á¤Ç¥¹¥ê¡¼¥×¤¹¤ë¤³¤È¤Ï¶Ø»ß)¡¥
+ : ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
+
+ set_eventloop_tick
+ get_eventloop_tick
+ set_no_event_wait
+ get_no_event_wait
+ set_eventloop_weight
+ get_eventloop_weight
+ mainloop_abort_on_exception
+ mainloop_abort_on_exception=
+ : ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤ÏÃͤÎÀßÄ꤬µö¤µ¤ì¤Ê¤¤ (̵»ë¤µ¤ì¤ë)¡¥
+ : ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
+
+ encoding_table
+ : Ruby m17n ÍÑ¤Ë Ruby ¤È Tk ¤È¤Î´Ö¤Î encoding Âбþɽ¤òÊÖ¤¹¡¥
+
+¥¯¥é¥¹ TkCallbackBreak < StandardError
+¥¯¥é¥¹ TkCallbackContinue < StandardError
+ : ¤³¤ì¤é¤Ï¥¤¥Ù¥ó¥È¥³¡¼¥ë¥Ð¥Ã¥¯¤Ë¤ª¤¤¤Æ¡¤¥³¡¼¥ë¥Ð¥Ã¥¯½èÍý¤òŬÀÚ¤ËÃæ
+ : ÃǤ·¤¿¤ê¡¤¼¡¤Î¥Ð¥¤¥ó¥É¥¿¥°¤Î¥Ð¥¤¥ó¥Ç¥£¥ó¥°½èÍý¤Ë¿Ê¤á¤¿¤ê¤¹¤ë¤³¤È
+ : ¤ò²Äǽ¤Ë¤¹¤ë¤¿¤á¤ÎÎã³°¥¯¥é¥¹¤Ç¤¢¤ë¡¥
+ : ¥³¡¼¥ë¥Ð¥Ã¥¯¤Ç break ¤ä continue ¤ò¼Â¸½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤¥³¡¼¥ë¥Ð¥Ã¥¯
+ : ¤Ç¤¢¤ë Ruby ¼ê³¤­¤¬ Tcl/Tk ¥¤¥ó¥¿¡¼¥×¥ê¥¿Â¦¤ËŬÀڤʥ꥿¡¼¥ó¥³¡¼
+ : ¥É¤òÊÖ¤¹É¬Íפ¬¤¢¤ë¡¥Ruby ¤Î¼ê³¤­¤¬ÉáÄ̤ËÃͤòÊÖ¤¹¤Î¤Ç¤Ï¡¤¤½¤ì¤¬Éá
+ : Ä̤ÎÌá¤êÃͤǤ¢¤ë¤Î¤«Èݤ«¤ò¶èÊ̤¬¤Ç¤­¤Ê¤¤¤¿¤á¡¤Î㳰ȯÀ¸¤òÍøÍѤ·¤¿
+ : ¼ÂÁõ¤ò¹Ô¤Ã¤Æ¤¤¤ë¡¥
+ : ¤¿¤À¤·¸½ºß¤Ç¤Ï¡¤¥³¡¼¥ë¥Ð¥Ã¥¯¼ê³¤­¤ò Ruby ¤Î break, next ¤Ç½ªÎ»¤¹
+ : ¤ë¤³¤È¤ÇƱÅù¤Î·ë²Ì¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡¥¤½¤ì¤æ¤¨¡¤
+ : ¤³¤ì¤é¤ÏɬÍפʤ¤¤â¤Î¤Ç¤Ï¤¢¤ë¤¬¡¤¸ß´¹À­¤Î¤¿¤á¤Ë»Ä¤·¤Æ¤¢¤ë¡¥
+
+(eof)
diff --git a/ext/tk/README.1st b/ext/tk/README.1st
index ff92fdd8a3..fce5b0242b 100644
--- a/ext/tk/README.1st
+++ b/ext/tk/README.1st
@@ -1,21 +1,19 @@
-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.
-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
-installed properly.
+If you want to use Ruby/Tk (tk.rb and so on), you must have tcltklib.so
+which is working correctly. When you have some troubles on compiling,
+please read README.tcltklib and README.ActiveTcl.
+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 installed properly.
--------------------------------------------
( the following is written in EUC-JP )
-Ruby/Tk (tk.rb ¤Ê¤É) ¤ò»È¤¤¤¿¤¤¾ì¹ç¤Ë¤Ï¡¤tcltklib.so ¤¬Àµ¤·¤¯
-ư¤¤¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡¥¤â¤· require "tcltklib" ¤Ë¼ºÇÔ¤¹¤ë
-¤è¤¦¤Ê¤é¡¤tcltklib.so ¤¬Â¸ºß¤·¤Æ¤¤¤Ê¤¤¤Î¤«¤â¤·¤ì¤Þ¤»¤ó¡¥
-¤¿¤È¤¨ Ruby ¤Î¥é¥¤¥Ö¥é¥ê¥Ç¥£¥ì¥¯¥È¥ê¤Ë tcltklib.so ¤¬Â¸ºß¤·¤Æ
-¤¤¤¿¤È¤·¤Æ¤â¡¤¼Â¹Ô´Ä¶­¤Ë Tcl/Tk ¥é¥¤¥Ö¥é¥ê (libtcl8.4.so ¤Ê¤É)
-¤¬¤Ê¤±¤ì¤Ðµ¡Ç½¤·¤Þ¤»¤ó¡¥Tcl/Tk ¤¬Àµ¤·¤¯¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤ë¤«
-¤É¤¦¤«¤â¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡¥
+Ruby/Tk (tk.rb ¤Ê¤É) ¤ò»È¤¤¤¿¤¤¾ì¹ç¤Ë¤Ï¡¤tcltklib.so ¤¬Àµ¤·¤¯Æ°¤¤¤Æ¤¤¤Ê
+¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡¥¥³¥ó¥Ñ¥¤¥ë»þ¤Ë²¿¤«ÌäÂ꤬À¸¤¸¤¿¾ì¹ç¤Ï¡¤README.tcltklib
+¤ä README.ActiveTcl ¤ò¸«¤Æ¤¯¤À¤µ¤¤¡¥
+¤¿¤È¤¨ Ruby ¤Î¥é¥¤¥Ö¥é¥ê¥Ç¥£¥ì¥¯¥È¥ê¤Ë tcltklib.so ¤¬Â¸ºß¤·¤Æ¤¤¤¿¤È¤·¤Æ
+¤â¡¤¼Â¹Ô´Ä¶­¤Ë Tcl/Tk ¥é¥¤¥Ö¥é¥ê (libtcl8.4.so ¤Ê¤É) ¤¬¤Ê¤±¤ì¤Ðµ¡Ç½¤·¤Þ
+¤»¤ó¡¥Tcl/Tk ¤¬Àµ¤·¤¯¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤ë¤«¤â¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡¥
==========================================================
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tk/README.ActiveTcl b/ext/tk/README.ActiveTcl
new file mode 100644
index 0000000000..3afb3f4cf6
--- /dev/null
+++ b/ext/tk/README.ActiveTcl
@@ -0,0 +1,49 @@
+ActiveTcl is ActiveState's quality-assured distribution of Tcl.
+
+# see <http://www.activestate.com/Products/ActiveTcl/>
+# <http://www.tcl.tk/>
+
+If you want to use ActiveTcl binary package as the Tcl/Tk libraries,
+please use the following configure options.
+
+ --with-tcl-dir=<ActiveTcl_root>
+ --with-tk-dir=<ActiveTcl_root>
+
+And use the followings if you need.
+
+ --with-tcllib=<libname>
+ --with-tklib=<libname>
+ --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=tclstub8.4 \
+ --with-tklib=tkstub8.4 \
+ --enable-tcltk-stubs
+
+It depends on your environment that you have to add the directory of
+ActiveTcl's libraries to your library path when execute Ruby/Tk.
+One of the way is to add entries to TCLLIBPATH environment variable,
+and one of the others add to LD_LIBRARY_PATH environment variable
+
+Probably, using TCLLIBPATH is better. The value is appended at the
+head of Tcl's 'auto_path' variable. You can see the value of the
+variable by using 'Tk::AUTO_PATH.value' or 'Tk::AUTO_PATH.list'.
+
+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
+-------------------------------------------------------------------------
+Based on it, the Tcl interpreter changes auto_path variable's value.
+
+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/tk/README.fork b/ext/tk/README.fork
new file mode 100644
index 0000000000..707d78fc12
--- /dev/null
+++ b/ext/tk/README.fork
@@ -0,0 +1,34 @@
+Ruby/Tk does NOT support forking the process on which Tk interpreter
+is running (unless NEVER control Tk interpreter under the forked child
+process). In the library 'tk.rb', a Tk interpreter is initialized.
+Therefore, if you want running Tk under a child process, please call
+"require 'tk'" in the child process.
+
+# If do fork and exec(<new Ruby/Tk>) on the child process, you can
+# control Ruby/Tk interpreter on the child process by 'send' command
+# of Tcl/Tk. About this, please see Tk.appsend and Tk.rb_appsend, or
+# 'remote-tk.rb' and the sample 'sample/remote-ip_sample.rb'.
+
+For example, the following sample1 will NOT work, and sample2 will
+work properly.
+
+---<sample1: NOT work>---------------------------------------
+require 'tk' ## init Tk interpreter under parent process
+
+exit! if fork ## exit parent process
+
+## child process
+TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
+Tk.mainloop
+-------------------------------------------------------------
+
+---<sample2: will work>--------------------------------------
+exit! if fork ## exit main process
+
+## child process
+require 'tk' ## init Tk interpreter under child process
+TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
+Tk.mainloop
+-------------------------------------------------------------
+
+ 2004/05/22 Hidetoshi NAGAI
diff --git a/ext/tk/README.macosx-aqua b/ext/tk/README.macosx-aqua
new file mode 100644
index 0000000000..25a8ed827c
--- /dev/null
+++ b/ext/tk/README.macosx-aqua
@@ -0,0 +1,67 @@
+
+ *** for MacOS X Aqua (Tcl/Tk Aqua) users ***
+
+First of all, please read README.tcltklib to use Tcl/Tk Aqua Framework.
+
+With Tcl/Tk Aqua libraries, current tcltklib somtimes freezes when
+using Aqua specific dialogs (e.g. Tk.messageBox).
+This is a known bug of Ruby-1.8.4 release.
+
+When you meet the trouble on your GUI, you'll be able to avoid the trouble
+by Tcl/Tk's traditional dialogs.
+If you want to do that, please call some of the following bits of script
+after "reqruie 'tk'".
+
+=================================================================
+# use a traditional dialog for Tk.chooseColor()
+Tk.ip_eval(<<'EOS')
+ proc ::tk_chooseColor {args} {
+ return [eval tk::dialog::color:: $args]
+ }
+EOS
+
+# use a traditional dialog for Tk.getOpenFile() and Tk.getMultipleOpenFile()
+Tk.ip_eval(<<'EOS')
+ proc ::tk_getOpenFile {args} {
+ if {$::tk_strictMotif} {
+ return [eval tk::MotifFDialog open $args]
+ } else {
+ return [eval ::tk::dialog::file:: open $args]
+ }
+ }
+EOS
+
+# use a traditional dialog for Tk.getSaveFile() and Tk.getMultipleSaveFile()
+Tk.ip_eval(<<'EOS')
+ proc ::tk_getSaveFile {args} {
+ if {$::tk_strictMotif} {
+ return [eval tk::MotifFDialog save $args]
+ } else {
+ return [eval ::tk::dialog::file:: save $args]
+ }
+ }
+EOS
+
+# use a traditional dialog for Tk.messageBox()
+Tk.ip_eval(<<'EOS')
+ proc ::tk_messageBox {args} {
+ return [eval tk::MessageBox $args]
+ }
+EOS
+
+# use a traditional dialog for Tk.chooseDirectory()
+Tk.ip_eval(<<'EOS')
+ proc ::tk_chooseDirectory {args} {
+ return [eval ::tk::dialog::file::chooseDir:: $args]
+ }
+EOS
+=================================================================
+
+Each of them replaces the platform specific dialog command to the
+traditional one.
+
+If you use some MultiTkIp objects, probably, you'll have to call the
+bits of script for each MultiTkIp object.
+
+--
+Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tk/README.tcltklib b/ext/tk/README.tcltklib
new file mode 100644
index 0000000000..8c6dd5178f
--- /dev/null
+++ b/ext/tk/README.tcltklib
@@ -0,0 +1,85 @@
+To compile 'tcltklib', you must have Tcl/Tk libraries on your environment.
+Although 'extconf.rb' script searches Tcl/Tk libraries and header files,
+sometimes fails to find them. And then, 'tcltklib' cannot be compiled. If
+Tcl/Tk libraries or header files are installed but are not found, you can
+give the information by arguments of the 'configure' script. Please give
+some or all of the following options.
+
+ --with-tcltkversion=<version>
+ force version of Tcl/Tk libaray
+ (e.g. libtcl8.4g.so ==> --with-tcltkversion=8.4g)
+
+ --with-tcllib=<libname> (e.g. libtcl8.4.so ==> --with-tcllib=tcl8.4)
+ --with-tklib=<libname> (e.g. libtk8.4.so ==> --with-tklib=tk8.4)
+
+ --enable-tcltk-stubs (if you force to enable stubs)
+
+ --with-tcl-dir=<path>
+ equal to "--with-tcl-include=<path>/include --with-tcl-lib=<path>/lib"
+
+ --with-tk-dir=<path>
+ equal to "--with-tk-include=<path>/include --with-tk-lib=<path>/lib"
+
+ --with-tcl-include=<dir> the directry contains 'tcl.h'
+ --with-tk-include=<dir> the directry contains 'tk.h'
+
+ --with-tcl-lib=<dir> the directry contains 'libtcl<version>.so'
+ --with-tk-lib=<dir> the directry contains 'libtk<version>.so'
+
+ --enable-mac-tcltk-framework (MacOS X) use Tcl/Tk framework
+ (Obsolete. Please use '--enable-tcltk-framework'.)
+
+ --enable-tcltk-framework use Tcl/Tk framework
+
+ --with-tcltk-framework=<dir> the directory contains Tcl/Tk framework;
+ "<dir>/Tcl.framework" and "<dir>/Tk.framework".
+ When this option is given, it is assumed that
+ --enable-tcltk-framework option is given also.
+
+ --with-tcl-framework-header=<dir>
+ Tcl framework headers directory
+ (e.g. "/Library/Frameworks/Tcl.framework/Headers")
+
+ --with-tk-framework-header=<dir>
+ Tk framework headers directory
+ (e.g. "/Library/Frameworks/Tk.framework/Headers")
+
+
+ --with-X11 / --without-X11 use / not use the X Window System
+
+ --with-X11-dir=<path>
+ equal to "--with-X11-include=<path>/include --with-X11-lib=<path>/lib"
+
+ --with-X11-include=<dir> the directry contais X11 header files
+ --with-X11-lib=<dir> the directry contais X11 libraries
+
+
+If you forgot to give the options when do 'configure' on toplevel
+directry of Ruby sources, please try something like as the followings.
+
+ $ cd ext/tcltklib
+ $ rm Makefile
+ $ CONFIGURE_ARGS='--with-tcl-include=/usr/local/include/tcl8.4/ --with-tcllib=tcl8.4 --with-tklib=tk8.4' ruby extconf.rb
+
+
+ *** ATTENTION ***
+When your Tcl/Tk libraries are compiled with "pthread support",
+Ruby/Tk may cause "Hang-up" or "Segmentation Fault" frequently.
+If you have such a trouble, please try to use the '--enable-pthread'
+option of the 'configure' command and re-compile Ruby sources.
+It may help you to avoid this trouble. The following configure
+options may be useful.
+
+ --enable-tcl-thread/--disable-tcl-thread
+ --with-tclConfig-file=<path of 'tclConfig.sh'>
+
+It is not need that 'tclConfig.sh' is a normal Tcl/Tk's tclConfig.sh.
+But the file is expected to include the line "TCL_THREADS=0" or "...=1".
+When no "TCL_THREADS=?" line, if Tcl version is 7.x or 8.0 which is
+given by "TCL_MAJOR_VERSION=?" line and "TCL_MINOR_VERSION=?" line,
+then --disable-tcl-thread is expected. Else, ignore the 'tclConfig.sh'.
+If --enable-tcl-thread or --disable-tcl-thread option is given, then
+--with-tclConfig-file option is ignored.
+
+==========================================================
+ Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tk/depend b/ext/tk/depend
index fd63e230f0..2cd9c400f7 100644
--- a/ext/tk/depend
+++ b/ext/tk/depend
@@ -1 +1,2 @@
-tkutil.o: tkutil.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
+tcltklib.o: tcltklib.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
+stubs.o: stubs.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb
index f769b06e30..4807ea7b40 100644
--- a/ext/tk/extconf.rb
+++ b/ext/tk/extconf.rb
@@ -1,2 +1,412 @@
+# extconf.rb for tcltklib
+
require 'mkmf'
-create_makefile("tkutil")
+
+#is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM)
+is_win32 = (/mswin|mingw|cygwin|bccwin|wince/ =~ RUBY_PLATFORM)
+#is_macosx = (/darwin/ =~ RUBY_PLATFORM)
+
+def find_framework(tcl_hdr, tk_hdr)
+ if framework_dir = with_config("tcltk-framework")
+ paths = [framework_dir]
+ else
+ unless tcl_hdr || tk_hdr ||
+ enable_config("tcltk-framework", false) ||
+ enable_config("mac-tcltk-framework", false)
+ return false
+ end
+ paths = ["/Library/Frameworks", "/System/Library/Frameworks"]
+ end
+
+ checking_for('Tcl/Tk Framework') {
+ paths.find{|dir|
+ dir.strip!
+ dir.chomp!('/')
+ (tcl_hdr || FileTest.directory?(dir + "/Tcl.framework/") ) &&
+ (tk_hdr || FileTest.directory?(dir + "/Tk.framework/") )
+ }
+ }
+end
+
+tcl_framework_header = with_config("tcl-framework-header")
+tk_framework_header = with_config("tk-framework-header")
+
+tcltk_framework = find_framework(tcl_framework_header, tk_framework_header)
+
+unless is_win32
+ have_library("nsl", "t_open")
+ have_library("socket", "socket")
+ have_library("dl", "dlopen")
+ have_library("m", "log")
+end
+
+tk_idir, tk_ldir = dir_config("tk")
+tcl_idir, tcl_ldir = dir_config("tcl")
+x11_idir, x11_ldir = dir_config("X11")
+
+tk_ldir2 = with_config("tk-lib")
+tcl_ldir2 = with_config("tcl-lib")
+x11_ldir2 = with_config("X11-lib")
+
+tk_ldir_list = [tk_ldir2, tk_ldir]
+tcl_ldir_list = [tcl_ldir2, tcl_ldir]
+
+tklib = with_config("tklib")
+tcllib = with_config("tcllib")
+stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs")
+
+tcltk_version = with_config("tcltkversion")
+
+use_X = with_config("X11", (! is_win32))
+
+def check_tcltk_version(version)
+ return [nil, nil] unless version
+
+ version = version.strip
+
+ tclver = version.dup
+ tkver = version.dup
+
+ major = dot = minor = dot = plvl = ext = nil
+
+ if version =~ /^(\d)(\.?)(\d)(\.?)(\d*)(.*)$/
+ major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6
+ dot = ! minor_dot.empty?
+ if plvl_dot.empty? && ! plvl.empty?
+ minor << plvl
+ end
+ elsif version =~ /^(\d)(\.?)(\d?)(.*)$/
+ major = $1; minor_dot = $2; minor = $3; ext = $4
+ dot = ! minor_dot.empty?
+ else # unknown -> believe user
+ return [tclver, tkver]
+ end
+
+ # check Tcl7.6 / Tk4.2 ?
+ if major == "7" # Tcl7.6 ( not support Tclversion < 7.6 )
+ # Tk4.2
+ tkver = "4" + ((dot)? ".": "") + ((minor.empty)? "": "2") + ext
+ elsif major == "4" # Tk4.2 ( not support Tkversion < 4.2 )
+ # Tcl7.6
+ tclver = "7" + ((dot)? ".": "") + ((minor.empty)? "": "6") + ext
+ end
+
+ [tclver, tkver]
+end
+
+def find_tcl(tcllib, stubs, version, *opt_paths)
+ default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+ default_paths << "/Tcl/lib" # default for ActiveTcl
+
+ if (paths = opt_paths.compact).empty?
+ paths = default_paths
+ end
+
+ if stubs
+ func = "Tcl_InitStubs"
+ lib = "tclstub"
+ else
+ func = "Tcl_FindExecutable"
+ lib = "tcl"
+ end
+
+ if version && ! version.empty?
+ versions = [version]
+ else
+ versions = %w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6]
+ end
+
+ if tcllib
+ st = find_library(tcllib, func, *paths)
+ else
+ st = versions.find { |ver|
+ find_library("#{lib}#{ver}", func, *paths) or
+ find_library("#{lib}#{ver.delete('.')}", func, *paths) or
+ find_library("#{lib}#{ver}g", func, *paths) or
+ find_library("#{lib}#{ver.delete('.')}g", func, *paths) or
+ find_library("tcl#{ver}", func, *paths) or
+ find_library("tcl#{ver.delete('.')}", func, *paths) or
+ find_library("tcl#{ver}g", func, *paths) or
+ find_library("tcl#{ver.delete('.')}g", func, *paths)
+ } || (!version && find_library(lib, func, *paths))
+ end
+
+ unless st
+ puts("Warning:: cannot find Tcl library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.")
+ end
+ st
+end
+
+def find_tk(tklib, stubs, version, *opt_paths)
+ default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+ default_paths << "/Tcl/lib" # default for ActiveTcl
+
+ if (paths = opt_paths.compact).empty?
+ paths = default_paths
+ end
+
+ if stubs
+ func = "Tk_InitStubs"
+ lib = "tkstub"
+ else
+ func = "Tk_Init"
+ lib = "tk"
+ end
+
+ if version && ! version.empty?
+ versions = [version]
+ else
+ versions = %w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2]
+ end
+
+ if tklib
+ st = find_library(tklib, func, *paths)
+ else
+ st = versions.find { |ver|
+ find_library("#{lib}#{ver}", func, *paths) or
+ find_library("#{lib}#{ver.delete('.')}", func, *paths) or
+ find_library("#{lib}#{ver}g", func, *paths) or
+ find_library("#{lib}#{ver.delete('.')}g", func, *paths) or
+ find_library("tk#{ver}", func, *paths) or
+ find_library("tk#{ver.delete('.')}", func, *paths) or
+ find_library("tk#{ver}g", func, *paths) or
+ find_library("tk#{ver.delete('.')}g", func, *paths)
+ } || (!version && find_library(lib, func, *paths))
+ end
+
+ unless st
+ puts("Warning:: cannot find Tk library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.")
+ end
+ st
+end
+
+def find_X11(*opt_paths)
+ default_paths =
+ [ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ]
+ paths = opt_paths.compact.concat(default_paths)
+ st = find_library("X11", "XOpenDisplay", *paths)
+ unless st
+ puts("Warning:: cannot find X11 library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options. If your Tcl/Tk don't require X11, please try --without-X11.")
+ end
+ st
+end
+
+def pthread_check()
+ tcl_major_ver = nil
+ tcl_minor_ver = nil
+
+ # Is tcl-thread given by user ?
+ case enable_config("tcl-thread")
+ when true
+ tcl_enable_thread = true
+ when false
+ tcl_enable_thread = false
+ else
+ tcl_enable_thread = nil
+ end
+
+ if (tclConfig = with_config("tclConfig-file"))
+ if tcl_enable_thread == true
+ puts("Warning: --with-tclConfig-file option is ignored, because --enable-tcl-thread option is given.")
+ elsif tcl_enable_thread == false
+ puts("Warning: --with-tclConfig-file option is ignored, because --disable-tcl-thread option is given.")
+ else
+ # tcl-thread is unknown and tclConfig.sh is given
+ begin
+ open(tclConfig, "r") do |cfg|
+ while line = cfg.gets()
+ if line =~ /^\s*TCL_THREADS=(0|1)/
+ tcl_enable_thread = ($1 == "1")
+ break
+ end
+
+ if line =~ /^\s*TCL_MAJOR_VERSION=("|')(\d+)\1/
+ tcl_major_ver = $2
+ if tcl_major_ver =~ /^[1-7]$/
+ tcl_enable_thread = false
+ break
+ end
+ if tcl_major_ver == "8" && tcl_minor_ver == "0"
+ tcl_enable_thread = false
+ break
+ end
+ end
+
+ if line =~ /^\s*TCL_MINOR_VERSION=("|')(\d+)\1/
+ tcl_minor_ver = $2
+ if tcl_major_ver == "8" && tcl_minor_ver == "0"
+ tcl_enable_thread = false
+ break
+ end
+ end
+ end
+ end
+
+ if tcl_enable_thread == nil
+ # not find definition
+ if tcl_major_ver
+ puts("Warning: '#{tclConfig}' doesn't include TCL_THREADS definition.")
+ else
+ puts("Warning: '#{tclConfig}' may not be a tclConfig file.")
+ end
+ tclConfig = false
+ end
+ rescue Exception
+ puts("Warning: fail to read '#{tclConfig}'!! --> ignore the file")
+ tclConfig = false
+ end
+ end
+ end
+
+ if tcl_enable_thread == nil && !tclConfig
+ # tcl-thread is unknown and tclConfig is unavailable
+ begin
+ try_run_available = try_run("int main() { exit(0); }")
+ rescue Exception
+ # cannot try_run. Is CROSS-COMPILE environment?
+ puts(%Q'\
+*****************************************************************************
+**
+** PTHREAD SUPPORT CHECK WARNING:
+**
+** We cannot check the consistency of pthread support between Ruby
+** and the Tcl/Tk library in your environment (are you perhaps
+** cross-compiling?). If pthread support for these 2 packages is
+** inconsistent you may find you get errors when running Ruby/Tk
+** (e.g. hangs or segmentation faults). We strongly recommend
+** you to check the consistency manually.
+**
+*****************************************************************************
+')
+ return true
+ end
+ end
+
+ if tcl_enable_thread == nil
+ # tcl-thread is unknown
+ if try_run(<<EOF)
+#include <tcl.h>
+int main() {
+ Tcl_Interp *ip;
+ ip = Tcl_CreateInterp();
+ exit((Tcl_Eval(ip, "set tcl_platform(threaded)") == TCL_OK)? 0: 1);
+}
+EOF
+ tcl_enable_thread = true
+ elsif try_run(<<EOF)
+#include <tcl.h>
+static Tcl_ThreadDataKey dataKey;
+int main() { exit((Tcl_GetThreadData(&dataKey, 1) == dataKey)? 1: 0); }
+EOF
+ tcl_enable_thread = true
+ else
+ tcl_enable_thread = false
+ end
+ end
+
+ # check pthread mode
+ if (macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"'))
+ # ruby -> enable
+ unless tcl_enable_thread
+ # ruby -> enable && tcl -> disable
+ puts(%Q'\
+*****************************************************************************
+**
+** PTHREAD SUPPORT MODE WARNING:
+**
+** Ruby is compiled with --enable-pthread, but your Tcl/Tk library
+** seems to be compiled without pthread support. Although you can
+** create the tcltklib library, this combination may cause errors
+** (e.g. hangs or segmentation faults). If you have no reason to
+** keep the current pthread support status, we recommend you reconfigure
+** and recompile the libraries so that both or neither support pthreads.
+**
+** If you want change the status of pthread support, please recompile
+** Ruby without "--enable-pthread" configure option or recompile Tcl/Tk
+** with "--enable-threads" configure option (if your Tcl/Tk is later
+** than or equal to Tcl/Tk 8.1).
+**
+*****************************************************************************
+')
+ end
+
+ # ruby -> enable && tcl -> enable/disable
+ if tcl_enable_thread
+ $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1'
+ else
+ $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0'
+ end
+
+ return true
+
+ else
+ # ruby -> disable
+ if tcl_enable_thread
+ # ruby -> disable && tcl -> enable
+ puts(%Q'\
+*****************************************************************************
+**
+** PTHREAD SUPPORT MODE ERROR:
+**
+** Ruby is not compiled with --enable-pthread, but your Tcl/Tk
+** library seems to be compiled with pthread support. This
+** combination may cause frequent hang or segmentation fault
+** errors when Ruby/Tk is working. We recommend that you NEVER
+** create the library with such a combination of pthread support.
+**
+** Please recompile Ruby with the "--enable-pthread" configure option
+** or recompile Tcl/Tk with the "--disable-threads" configure option.
+**
+*****************************************************************************
+')
+ $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1'
+ return false
+ else
+ # ruby -> disable && tcl -> disable
+ $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0'
+ return true
+ end
+ end
+end
+
+tclver, tkver = check_tcltk_version(tcltk_version)
+
+if have_header("tcl.h") && have_header("tk.h") &&
+ ( tcltk_framework ||
+ ( ( !use_X || find_X11(x11_ldir2, x11_ldir) ) &&
+ find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) &&
+ find_tk(tklib, stubs, tkver, *tk_ldir_list) ) )
+ $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs
+ $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM
+
+ if tcltk_framework
+ if tcl_framework_header
+ $CPPFLAGS += " -I#{tcl_framework_header}"
+ else
+ $CPPFLAGS += " -I#{tcltk_framework}/Tcl.framework/Headers"
+ end
+
+ if tk_framework_header
+ $CPPFLAGS += " -I#{tk_framework_header}"
+ else
+ $CPPFLAGS += " -I#{tcltk_framework}/Tk.framework/Headers"
+ end
+
+ $LDFLAGS += ' -framework Tk -framework Tcl'
+ end
+
+ if stubs or pthread_check
+ # create Makefile
+
+ # for SUPPORT_STATUS
+ $INSTALLFILES ||= []
+ $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"]
+
+ have_func("rb_hash_lookup", "ruby.h")
+
+ # create
+ $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"]
+ $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"]
+ create_makefile("tcltklib")
+ end
+end
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/multi-tk.rb b/ext/tk/lib/multi-tk.rb
index b6c800177f..ec718678f0 100644
--- a/ext/tk/lib/multi-tk.rb
+++ b/ext/tk/lib/multi-tk.rb
@@ -1,10 +1,15 @@
#
-# multi-tk.rb - supports multi Tk interpreters
-# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+# multi-tk.rb - supports multi Tk interpreters
+# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
require 'tcltklib'
+require 'tkutil'
require 'thread'
+if defined? Tk
+ fail RuntimeError,"'multi-tk' library must be required before requiring 'tk'"
+end
+
################################################
# ignore exception on the mainloop?
@@ -13,11 +18,83 @@ TclTkLib.mainloop_abort_on_exception = true
# TclTkLib.mainloop_abort_on_exception = nil
+################################################
+# add ThreadGroup check to TclTkIp.new
+class << TclTkIp
+ alias __new__ new
+ private :__new__
+
+ def new(*args)
+ if Thread.current.group != ThreadGroup::Default
+ raise SecurityError, 'only ThreadGroup::Default can call TclTkIp.new'
+ end
+ __new__(*args)
+ end
+end
+
+
+################################################
+# use pseudo-toplevel feature of MultiTkIp ?
+if (!defined?(Use_PseudoToplevel_Feature_of_MultiTkIp) ||
+ Use_PseudoToplevel_Feature_of_MultiTkIp)
+ module MultiTkIp_PseudoToplevel_Evaluable
+ #def pseudo_toplevel_eval(body = Proc.new)
+ # Thread.current[:TOPLEVEL] = self
+ # begin
+ # body.call
+ # ensure
+ # Thread.current[:TOPLEVEL] = nil
+ # end
+ #end
+
+ def pseudo_toplevel_evaluable?
+ @pseudo_toplevel_evaluable
+ end
+
+ def pseudo_toplevel_evaluable=(mode)
+ @pseudo_toplevel_evaluable = (mode)? true: false
+ end
+
+ def self.extended(mod)
+ mod.__send__(:extend_object, mod)
+ mod.instance_variable_set('@pseudo_toplevel_evaluable', true)
+ end
+ end
+
+ class Object
+ alias __method_missing_alias_for_MultiTkIp__ method_missing
+ private :__method_missing_alias_for_MultiTkIp__
+
+ def method_missing(id, *args)
+ begin
+ has_top = (top = MultiTkIp.__getip.__pseudo_toplevel) &&
+ top.respond_to?(:pseudo_toplevel_evaluable?) &&
+ top.pseudo_toplevel_evaluable? &&
+ top.respond_to?(id)
+ rescue Exception => e
+ has_top = false
+ end
+
+ if has_top
+ top.__send__(id, *args)
+ else
+ __method_missing_alias_for_MultiTkIp__(id, *args)
+ end
+ end
+ end
+else
+ # dummy
+ module MultiTkIp_PseudoToplevel_Evaluable
+ def pseudo_toplevel_evaluable?
+ false
+ end
+ end
+end
################################################
# exceptiopn to treat the return value from IP
class MultiTkIp_OK < Exception
- def self.send(thred, ret=nil)
+ def self.send(thread, ret=nil)
thread.raise self.new(ret)
end
@@ -35,59 +112,209 @@ MultiTkIp_OK.freeze
################################################
# methods for construction
class MultiTkIp
- SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze
+ BASE_DIR = File.dirname(__FILE__)
+
+ WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class
+ WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class
+
+ (@@SLAVE_IP_ID = ['slave'.freeze, '0'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ @@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
- @@IP_TABLE = {}.taint
+ @@INIT_IP_ENV = [].taint unless defined?(@@INIT_IP_ENV) # table of Procs
+ @@ADD_TK_PROCS = [].taint unless defined?(@@ADD_TK_PROCS) # table of [name, args, body]
- @@INIT_IP_ENV = [].taint # table of Procs
- @@ADD_TK_PROCS = [].taint # table of [name, args, body]
+ @@TK_TABLE_LIST = [].taint unless defined?(@@TK_TABLE_LIST)
- @@TK_TABLE_LIST = [].taint
+ unless defined?(@@TK_CMD_TBL)
+ @@TK_CMD_TBL = Object.new.taint
- @@TK_CMD_TBL = {}.taint
+ # @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint)
+ @@TK_CMD_TBL.instance_variable_set('@tbl', Hash.new{|hash,key|
+ fail IndexError,
+ "unknown command ID '#{key}'"
+ }.taint)
+
+ class << @@TK_CMD_TBL
+ allow = [
+ '__send__', '__id__', 'freeze', 'inspect', 'kind_of?', 'object_id',
+ '[]', '[]=', 'delete', 'each', 'has_key?'
+ ]
+ instance_methods.each{|m| undef_method(m) unless allow.index(m.to_s)}
+
+ def kind_of?(klass)
+ @tbl.kind_of?(klass)
+ end
+
+ def inspect
+ if Thread.current.group == ThreadGroup::Default
+ @tbl.inspect
+ else
+ ip = MultiTkIp.__getip
+ @tbl.reject{|idx, ent| ent.respond_to?(:ip) && ent.ip != ip}.inspect
+ end
+ end
+
+ def [](idx)
+ return unless (ent = @tbl[idx])
+ if Thread.current.group == ThreadGroup::Default
+ ent
+ elsif ent.respond_to?(:ip)
+ (ent.ip == MultiTkIp.__getip)? ent: nil
+ else
+ ent
+ end
+ end
+
+ def []=(idx,val)
+ if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
+ fail SecurityError,"cannot change the entried command"
+ end
+ @tbl[idx] = val
+ end
+
+ def delete(idx, &blk)
+ # if gets an entry, is permited to delete
+ if self[idx]
+ @tbl.delete(idx)
+ elsif blk
+ blk.call(idx)
+ else
+ nil
+ end
+ end
+
+ def each(&blk)
+ if Thread.current.group == ThreadGroup::Default
+ @tbl.each(&blk)
+ else
+ ip = MultiTkIp.__getip
+ @tbl.each{|idx, ent|
+ blk.call(idx, ent) unless ent.respond_to?(:ip) && ent.ip != ip
+ }
+ end
+ self
+ end
+
+ def has_key?(k)
+ @tbl.has_key?(k)
+ end
+ alias include? has_key?
+ alias key? has_key?
+ alias member? has_key?
+ end
+
+ @@TK_CMD_TBL.freeze
+ end
######################################
- @@CB_ENTRY_CLASS = Class.new{|c|
+ @@CB_ENTRY_CLASS = Class.new(TkCallbackEntry){
def initialize(ip, cmd)
@ip = ip
@cmd = cmd
+ self.freeze
end
attr_reader :ip, :cmd
+ def inspect
+ cmd.inspect
+ end
def call(*args)
- begin
- unless @ip.deleted?
- @ip.cb_eval(@cmd, *args)
- end
- rescue TkCallbackBreak, TkCallbackContinue
- fail
- rescue Exception
+ unless @ip.deleted?
+ current = Thread.current
+ backup_ip = current['callback_ip']
+ current['callback_ip'] = @ip
+ begin
+ ret = @ip.cb_eval(@cmd, *args)
+ fail ret if ret.kind_of?(Exception)
+ ret
+ rescue TkCallbackBreak, TkCallbackContinue => e
+ fail e
+ rescue SecurityError => e
+ # in 'exit', 'exit!', and 'abort' : security error --> delete IP
+ if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
+ @ip.delete
+ elsif @ip.safe?
+ if @ip.respond_to?(:cb_error)
+ @ip.cb_error(e)
+ else
+ nil # ignore
+ end
+ else
+ fail e
+ end
+ rescue Exception => e
+ fail e if e.message =~ /^TkCallback/
+
+ if @ip.safe?
+ if @ip.respond_to?(:cb_error)
+ @ip.cb_error(e)
+ else
+ nil # ignore
+ end
+ else
+ fail e
+ end
+ ensure
+ current['callback_ip'] = backup_ip
+ end
end
end
}.freeze
######################################
- def _keys2opts(keys)
- keys.collect{|k,v| "-#{k} #{v}"}.join(' ')
+ def _keys2opts(src_keys)
+ return nil if src_keys == nil
+ keys = {}; src_keys.each{|k, v| keys[k.to_s] = v}
+ #keys.collect{|k,v| "-#{k} #{v}"}.join(' ')
+ keys.collect{|k,v| "-#{k} #{TclTkLib._conv_listelement(TkComm::_get_eval_string(v))}"}.join(' ')
end
private :_keys2opts
def _check_and_return(thread, exception, wait=0)
- return nil unless thread
+ unless thread
+ unless exception.kind_of?(MultiTkIp_OK)
+ msg = "#{exception.class}: #{exception.message}"
+
+ if @interp.deleted?
+ warn("Warning (#{self}): " + msg)
+ return nil
+ end
+
+ if safe?
+ warn("Warning (#{self}): " + msg) if $DEBUG
+ return nil
+ end
+
+ begin
+ @interp._eval_without_enc(@interp._merge_tklist('bgerror', msg))
+ rescue Exception => e
+ warn("Warning (#{self}): " + msg)
+ end
+ end
+ return nil
+ end
if wait == 0
# no wait
- thread.raise exception
+ Thread.pass
+ if thread.stop?
+ thread.raise exception
+ end
return thread
end
# wait to stop the caller thread
wait.times{
if thread.stop?
- # ready to send exception
- thread.raise exception
- return thread
+ # ready to send exception
+ thread.raise exception
+ return thread
end
# wait
@@ -101,81 +328,378 @@ class MultiTkIp
######################################
+ def set_cb_error(cmd = Proc.new)
+ @cb_error_proc[0] = cmd
+ end
+
+ def cb_error(e)
+ if @cb_error_proc[0].respond_to?(:call)
+ @cb_error_proc[0].call(e)
+ end
+ end
+
+ ######################################
+
def set_safe_level(safe)
- @cmd_queue.enq([@system, 'set_safe_level', safe])
- self
+ if safe > @safe_level[0]
+ @safe_level[0] = safe
+ @cmd_queue.enq([@system, 'set_safe_level', safe])
+ end
+ @safe_level[0]
+ end
+ def safe_level=(safe)
+ set_safe_level(safe)
end
def self.set_safe_level(safe)
__getip.set_safe_level(safe)
- self
+ end
+ def self.safe_level=(safe)
+ self.set_safe_level(safe)
+ end
+ def safe_level
+ @safe_level[0]
+ end
+ def self.safe_level
+ __getip.safe_level
+ end
+
+ def wait_on_mainloop?
+ @wait_on_mainloop[0]
+ end
+ def wait_on_mainloop=(bool)
+ @wait_on_mainloop[0] = bool
+ end
+
+ def running_mainloop?
+ @wait_on_mainloop[1] > 0
+ end
+
+ def _destroy_slaves_of_slaveIP(ip)
+ unless ip.deleted?
+ # ip._split_tklist(ip._invoke('interp', 'slaves')).each{|name|
+ ip._split_tklist(ip._invoke_without_enc('interp', 'slaves')).each{|name|
+ name = _fromUTF8(name)
+ begin
+ # ip._eval_without_enc("#{name} eval {foreach i [after info] {after cancel $i}}")
+ after_ids = ip._eval_without_enc("#{name} eval {after info}")
+ ip._eval_without_enc("#{name} eval {foreach i {#{after_ids}} {after cancel $i}}")
+ rescue Exception
+ end
+ begin
+ # ip._invoke('interp', 'eval', name, 'destroy', '.')
+ ip._invoke(name, 'eval', 'destroy', '.')
+ rescue Exception
+ end
+
+ # safe_base?
+ if ip._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
+ begin
+ ip._eval_without_enc("::safe::interpDelete #{name}")
+ rescue Exception
+ end
+ end
+=begin
+ if ip._invoke('interp', 'exists', name) == '1'
+ begin
+ ip._invoke(name, 'eval', 'exit')
+ rescue Exception
+ end
+ end
+=end
+ unless ip.deleted?
+ if ip._invoke('interp', 'exists', name) == '1'
+ begin
+ ip._invoke('interp', 'delete', name)
+ rescue Exception
+ end
+ end
+ end
+ }
+ end
+ end
+
+ def _receiver_eval_proc_core(safe_level, thread, cmd, *args)
+ begin
+ #ret = proc{$SAFE = safe_level; cmd.call(*args)}.call
+ #ret = cmd.call(safe_level, *args)
+ normal_ret = false
+ ret = catch(:IRB_EXIT) do # IRB hack
+ retval = cmd.call(safe_level, *args)
+ normal_ret = true
+ retval
+ end
+ unless normal_ret
+ # catch IRB_EXIT
+ exit(ret)
+ end
+ ret
+ rescue SystemExit => e
+ # delete IP
+ unless @interp.deleted?
+ @slave_ip_tbl.each{|name, subip|
+ _destroy_slaves_of_slaveIP(subip)
+ begin
+ # subip._eval_without_enc("foreach i [after info] {after cancel $i}")
+ after_ids = subip._eval_without_enc("after info")
+ subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
+ rescue Exception
+ end
+=begin
+ begin
+ subip._invoke('destroy', '.') unless subip.deleted?
+ rescue Exception
+ end
+=end
+ # safe_base?
+ if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
+ begin
+ @interp._eval_without_enc("::safe::interpDelete #{name}")
+ rescue Exception
+ else
+ next if subip.deleted?
+ end
+ end
+ if subip.respond_to?(:safe_base?) && subip.safe_base? &&
+ !subip.deleted?
+ # do 'exit' to call the delete_hook procedure
+ begin
+ subip._eval_without_enc('exit')
+ rescue Exception
+ end
+ else
+ begin
+ subip.delete unless subip.deleted?
+ rescue Exception
+ end
+ end
+ }
+
+ begin
+ # @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
+ after_ids = @interp._eval_without_enc("after info")
+ @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
+ rescue Exception
+ end
+ begin
+ @interp._invoke('destroy', '.') unless @interp.deleted?
+ rescue Exception
+ end
+ if @safe_base && !@interp.deleted?
+ # do 'exit' to call the delete_hook procedure
+ @interp._eval_without_enc('exit')
+ else
+ @interp.delete unless @interp.deleted?
+ end
+ end
+
+ if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
+ _check_and_return(thread, MultiTkIp_OK.new($3 == 'exit'))
+ else
+ _check_and_return(thread, MultiTkIp_OK.new(nil))
+ end
+
+ # if master? && !safe? && allow_ruby_exit?
+ if !@interp.deleted? && master? && !safe? && allow_ruby_exit?
+=begin
+ ObjectSpace.each_object(TclTkIp){|obj|
+ obj.delete unless obj.deleted?
+ }
+=end
+ #exit(e.status)
+ fail e
+ end
+ # break
+
+ rescue SecurityError => e
+ # in 'exit', 'exit!', and 'abort' : security error --> delete IP
+ if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
+ ret = ($3 == 'exit')
+ unless @interp.deleted?
+ @slave_ip_tbl.each{|name, subip|
+ _destroy_slaves_of_slaveIP(subip)
+ begin
+ # subip._eval_without_enc("foreach i [after info] {after cancel $i}")
+ after_ids = subip._eval_without_enc("after info")
+ subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
+ rescue Exception
+ end
+=begin
+ begin
+ subip._invoke('destroy', '.') unless subip.deleted?
+ rescue Exception
+ end
+=end
+ # safe_base?
+ if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
+ begin
+ @interp._eval_without_enc("::safe::interpDelete #{name}")
+ rescue Exception
+ else
+ next if subip.deleted?
+ end
+ end
+ if subip.respond_to?(:safe_base?) && subip.safe_base? &&
+ !subip.deleted?
+ # do 'exit' to call the delete_hook procedure
+ begin
+ subip._eval_without_enc('exit')
+ rescue Exception
+ end
+ else
+ begin
+ subip.delete unless subip.deleted?
+ rescue Exception
+ end
+ end
+ }
+
+ begin
+ # @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
+ after_ids = @interp._eval_without_enc("after info")
+ @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
+ rescue Exception
+ end
+=begin
+ begin
+ @interp._invoke('destroy', '.') unless @interp.deleted?
+ rescue Exception
+ end
+=end
+ if @safe_base && !@interp.deleted?
+ # do 'exit' to call the delete_hook procedure
+ @interp._eval_without_enc('exit')
+ else
+ @interp.delete unless @interp.deleted?
+ end
+ end
+ _check_and_return(thread, MultiTkIp_OK.new(ret))
+ # break
+
+ else
+ # raise security error
+ _check_and_return(thread, e)
+ end
+
+ rescue Exception => e
+ # raise exception
+ begin
+ bt = _toUTF8(e.backtrace.join("\n"))
+ if MultiTkIp::WITH_ENCODING
+ bt.force_encoding('utf-8')
+ else
+ bt.instance_variable_set(:@encoding, 'utf-8')
+ end
+ rescue Exception
+ bt = e.backtrace.join("\n")
+ end
+ begin
+ @interp._set_global_var('errorInfo', bt)
+ rescue Exception
+ end
+ _check_and_return(thread, e)
+
+ else
+ # no exception
+ _check_and_return(thread, MultiTkIp_OK.new(ret))
+ end
+ end
+
+ def _receiver_eval_proc(last_thread, safe_level, thread, cmd, *args)
+ if thread
+ Thread.new{
+ last_thread.join if last_thread
+ unless @interp.deleted?
+ _receiver_eval_proc_core(safe_level, thread, cmd, *args)
+ end
+ }
+ else
+ Thread.new{
+ unless @interp.deleted?
+ _receiver_eval_proc_core(safe_level, thread, cmd, *args)
+ end
+ }
+ last_thread
+ end
+ end
+
+ private :_receiver_eval_proc, :_receiver_eval_proc_core
+
+ def _receiver_mainloop(check_root)
+ if @evloop_thread[0] && @evloop_thread[0].alive?
+ @evloop_thread[0]
+ else
+ @evloop_thread[0] = Thread.new{
+ while !@interp.deleted?
+ #if check_root
+ # inf = @interp._invoke_without_enc('info', 'command', '.')
+ # break if !inf.kind_of?(String) || inf != '.'
+ #end
+ break if check_root && !@interp.has_mainwindow?
+ sleep 0.5
+ end
+ }
+ @evloop_thread[0]
+ end
end
- def _create_receiver_and_watchdog()
+ def _create_receiver_and_watchdog(lvl = $SAFE)
+ lvl = $SAFE if lvl < $SAFE
+
# command-procedures receiver
- receiver = Thread.new{
- safe_level = $SAFE
+ receiver = Thread.new(lvl){|safe_level|
+ last_thread = {}
+
loop do
- thread, cmd, *args = @cmd_queue.deq
- if thread == @system
- # control command
- case cmd
- when 'set_safe_level'
- begin
- safe_level = args[0] if safe_level < args[0]
- rescue Exception
- nil
- end
- else
- # ignore
- end
-
- else
- # procedure
- begin
- ret = proc{$SAFE = safe_level; cmd.call(*args)}.call
- rescue SystemExit
- # delete IP
- unless @interp.deleted?
- if @interp._invoke('info', 'command', '.') != ""
- @interp._invoke('destroy', '.')
- end
- @interp.delete
- end
- _check_and_return(thread, MultiTkIp_OK.new(nil))
- break
- rescue Exception => e
- # raise exception
- _check_and_return(thread, e)
- else
- # no exception
- _check_and_return(thread, MultiTkIp_OK.new(ret))
- end
- end
+ break if @interp.deleted?
+ thread, cmd, *args = @cmd_queue.deq
+ if thread == @system
+ # control command
+ case cmd
+ when 'set_safe_level'
+ begin
+ safe_level = args[0] if safe_level < args[0]
+ rescue Exception
+ end
+ when 'call_mainloop'
+ thread = args.shift
+ _check_and_return(thread,
+ MultiTkIp_OK.new(_receiver_mainloop(*args)))
+ else
+ # ignore
+ end
+
+ else
+ # procedure
+ last_thread[thread] = _receiver_eval_proc(last_thread[thread],
+ safe_level, thread,
+ cmd, *args)
+ end
end
}
# watchdog of receiver
watchdog = Thread.new{
begin
- loop do
- sleep 1
- break unless receiver.alive?
- end
+ loop do
+ sleep 1
+ receiver.kill if @interp.deleted?
+ break unless receiver.alive?
+ end
rescue Exception
- # ignore all kind of Exception
+ # ignore all kind of Exception
end
# receiver is dead
loop do
- thread, cmd, *args = @cmd_queue.deq
- next unless thread
- if thread.alive?
- if @interp.deleted?
- thread.raise RuntimeError, 'the interpreter is already deleted'
- else
- thread.raise RuntimeError,
- 'the interpreter no longer receives command procedures'
- end
- end
+ thread, cmd, *args = @cmd_queue.deq
+ next unless thread
+ if thread.alive?
+ if @interp.deleted?
+ thread.raise RuntimeError, 'the interpreter is already deleted'
+ else
+ thread.raise RuntimeError,
+ 'the interpreter no longer receives command procedures'
+ end
+ end
end
}
@@ -186,6 +710,11 @@ class MultiTkIp
######################################
+ unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
+ ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!!
+ RUN_EVENTLOOP_ON_MAIN_THREAD = false
+ end
+
if self.const_defined? :DEFAULT_MASTER_NAME
name = DEFAULT_MASTER_NAME.to_s
else
@@ -200,28 +729,72 @@ class MultiTkIp
@@DEFAULT_MASTER = self.allocate
@@DEFAULT_MASTER.instance_eval{
- @encoding = [].taint
-
@tk_windows = {}.taint
@tk_table_list = [].taint
@slave_ip_tbl = {}.taint
+ @slave_ip_top = {}.taint
+
+ @evloop_thread = [].taint
+
unless keys.kind_of? Hash
fail ArgumentError, "expecting a Hash object for the 2nd argument"
end
- @interp = TclTkIp.new(name, _keys2opts(keys))
+ if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
+ @interp = TclTkIp.new(name, _keys2opts(keys))
+ else ### Ruby 1.9 !!!!!!!!!!!
+ @interp_thread = Thread.new{
+ current = Thread.current
+ current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys))
+ #sleep
+ current[:mutex] = mutex = Mutex.new
+ current[:root_check] = cond_var = ConditionVariable.new
+
+ begin
+ current[:status] = interp.mainloop(true)
+ rescue Exception=>e
+ current[:status] = e
+ ensure
+ mutex.synchronize{ cond_var.broadcast }
+ end
+ current[:status] = interp.mainloop(false)
+ }
+ until @interp_thread[:interp]
+ Thread.pass
+ end
+ # INTERP_THREAD.run
+ @interp = @interp_thread[:interp]
+
+ def self.mainloop(check_root = true)
+ begin
+ TclTkLib.set_eventloop_window_mode(true)
+ @interp_thread.value
+ ensure
+ TclTkLib.set_eventloop_window_mode(false)
+ end
+ end
+ end
+
@ip_name = nil
+ @callback_status = [].taint
+
@system = Object.new
+ @wait_on_mainloop = [true, 0].taint
+
@threadgroup = Thread.current.group
+ @safe_base = false
+
+ @safe_level = [$SAFE]
+
@cmd_queue = Queue.new
- @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog()
+ @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0])
@threadgroup.add @cmd_receiver
@threadgroup.add @receiver_watchdog
@@ -230,7 +803,144 @@ class MultiTkIp
@@IP_TABLE[ThreadGroup::Default] = self
@@IP_TABLE[@threadgroup] = self
+
+ #################################
+
+ @pseudo_toplevel = [false, nil]
+
+ def self.__pseudo_toplevel
+ Thread.current.group == ThreadGroup::Default &&
+ MultiTkIp.__getip == @@DEFAULT_MASTER &&
+ self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1]
+ end
+
+ def self.__pseudo_toplevel=(m)
+ unless (Thread.current.group == ThreadGroup::Default &&
+ MultiTkIp.__getip == @@DEFAULT_MASTER)
+ fail SecurityError, "no permission to manipulate"
+ end
+
+ # if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?)
+ if m.respond_to?(:pseudo_toplevel_evaluable?)
+ @pseudo_toplevel[0] = true
+ @pseudo_toplevel[1] = m
+ else
+ fail ArgumentError, 'fail to set pseudo-toplevel'
+ end
+ self
+ end
+
+ def self.__pseudo_toplevel_evaluable?
+ begin
+ @pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable?
+ rescue Exception
+ false
+ end
+ end
+
+ def self.__pseudo_toplevel_evaluable=(mode)
+ unless (Thread.current.group == ThreadGroup::Default &&
+ MultiTkIp.__getip == @@DEFAULT_MASTER)
+ fail SecurityError, "no permission to manipulate"
+ end
+
+ @pseudo_toplevel[0] = (mode)? true: false
+ end
+
+ #################################
+
+ @assign_request = Class.new(Exception){
+ def self.new(target, ret)
+ obj = super()
+ obj.target = target
+ obj.ret = ret
+ obj
+ end
+ attr_accessor :target, :ret
+ }
+
+ @assign_thread = Thread.new{
+ loop do
+ begin
+ Thread.stop
+ rescue @assign_request=>req
+ begin
+ req.ret[0] = req.target.instance_eval{
+ @cmd_receiver, @receiver_watchdog =
+ _create_receiver_and_watchdog(@safe_level[0])
+ @threadgroup.add @cmd_receiver
+ @threadgroup.add @receiver_watchdog
+ @threadgroup.enclose
+ true
+ }
+ rescue Exception=>e
+ begin
+ req.ret[0] = e
+ rescue Exception
+ # ignore
+ end
+ end
+ rescue Exception
+ # ignore
+ end
+ end
+ }
+
+ def self.assign_receiver_and_watchdog(target)
+ ret = [nil]
+ @assign_thread.raise(@assign_request.new(target, ret))
+ while ret[0] == nil
+ unless @assign_thread.alive?
+ raise RuntimeError, 'lost the thread to assign a receiver and a watchdog thread'
+ end
+ end
+ if ret[0].kind_of?(Exception)
+ raise ret[0]
+ else
+ ret[0]
+ end
+ end
+
+ #################################
+
+ @init_ip_env_queue = Queue.new
+ Thread.new{
+ current = Thread.current
+ loop {
+ mtx, cond, ret, table, script = @init_ip_env_queue.deq
+ begin
+ ret[0] = table.each{|tg, ip| ip._init_ip_env(script) }
+ rescue Exception => e
+ ret[0] = e
+ ensure
+ mtx.synchronize{ cond.signal }
+ end
+ mtx = cond = ret = table = script = nil # clear variables for GC
+ }
+ }
+
+ def self.__init_ip_env__(table, script)
+ ret = []
+ mtx = (Thread.current[:MultiTk_ip_Mutex] ||= Mutex.new)
+ cond = (Thread.current[:MultiTk_ip_CondVar] ||= ConditionVariable.new)
+ mtx.synchronize{
+ @init_ip_env_queue.enq([mtx, cond, ret, table, script])
+ cond.wait(mtx)
+ }
+ if ret[0].kind_of?(Exception)
+ raise ret[0]
+ else
+ ret[0]
+ end
+ end
+
+ #################################
+
+ class << self
+ undef :instance_eval
+ end
}
+
@@DEFAULT_MASTER.freeze # defend against modification
######################################
@@ -239,28 +949,28 @@ class MultiTkIp
# trust if on ThreadGroup::Default or @@DEFAULT_MASTER's ThreadGroup
if @@IP_TABLE[Thread.current.group] == @@DEFAULT_MASTER
begin
- class << subclass
- self.methods.each{|m|
- begin
- unless m == '__id__' || m == '__send__' || m == 'freeze'
- undef_method(m)
- end
- rescue Exception
- # ignore all exceptions
- end
- }
- end
+ class << subclass
+ self.methods.each{|m|
+ begin
+ unless m == '__id__' || m == '__send__' || m == 'freeze'
+ undef_method(m)
+ end
+ rescue Exception
+ # ignore all exceptions
+ end
+ }
+ end
ensure
- subclass.freeze
- fail SecurityError,
- "cannot create subclass of MultiTkIp on a untrusted ThreadGroup"
+ subclass.freeze
+ fail SecurityError,
+ "cannot create subclass of MultiTkIp on a untrusted ThreadGroup"
end
end
end
######################################
- SAFE_OPT_LIST = [
+ @@SAFE_OPT_LIST = [
'accessPath'.freeze,
'statics'.freeze,
'nested'.freeze,
@@ -274,25 +984,32 @@ class MultiTkIp
tk_opts = {}
keys.each{|k,v|
- if k.to_s == 'name'
- name = v
- elsif k.to_s == 'safe'
- safe = v
- elsif SAFE_OPT_LIST.member?(k.to_s)
- safe_opts[k] = v
+ k_str = k.to_s
+ if k_str == 'name'
+ name = v
+ elsif k_str == 'safe'
+ safe = v
+ elsif @@SAFE_OPT_LIST.member?(k_str)
+ safe_opts[k_str] = v
else
- tk_opts[k] = v
+ tk_opts[k_str] = v
end
}
- [name, safe, safe_opts, tk_opts]
+ if keys['without_tk'] || keys[:without_tk]
+ [name, safe, safe_opts, nil]
+ else
+ [name, safe, safe_opts, tk_opts]
+ end
end
private :_parse_slaveopts
def _create_slave_ip_name
- name = SLAVE_IP_ID.join
- SLAVE_IP_ID[1].succ!
- name
+ @@SLAVE_IP_ID.mutex.synchronize{
+ name = @@SLAVE_IP_ID.join('')
+ @@SLAVE_IP_ID[1].succ!
+ name.freeze
+ }
end
private :_create_slave_ip_name
@@ -306,15 +1023,15 @@ class MultiTkIp
# check 'display'
if !new_keys.key?('display')
begin
- #new_keys['display'] = @interp._invoke('winfo screen .')
- new_keys['display'] = @interp._invoke('winfo', 'screen', '.')
+ #new_keys['display'] = @interp._invoke('winfo screen .')
+ new_keys['display'] = @interp._invoke('winfo', 'screen', '.')
rescue
- if ENV[DISPLAY]
- new_keys['display'] = ENV[DISPLAY]
- elsif !new_keys.key?('use')
- warn "Warning: no screen info or ENV[DISPLAY], so use ':0.0'"
- new_keys['display'] = ':0.0'
- end
+ if ENV[DISPLAY]
+ new_keys['display'] = ENV[DISPLAY]
+ elsif !new_keys.key?('use')
+ warn "Warning: no screen info or ENV[DISPLAY], so use ':0.0'"
+ new_keys['display'] = ':0.0'
+ end
end
end
@@ -323,30 +1040,30 @@ class MultiTkIp
# given 'use'
case new_keys['use']
when TkWindow
- new_keys['use'] = TkWinfo.id(new_keys['use'])
- #assoc_display = @interp._eval('winfo screen .')
- assoc_display = @interp._invoke('winfo', 'screen', '.')
+ new_keys['use'] = TkWinfo.id(new_keys['use'])
+ #assoc_display = @interp._eval('winfo screen .')
+ assoc_display = @interp._invoke('winfo', 'screen', '.')
when /^\..*/
- new_keys['use'] = @interp._invoke('winfo', 'id', new_keys['use'])
- assoc_display = @interp._invoke('winfo', 'screen', new_keys['use'])
+ new_keys['use'] = @interp._invoke('winfo', 'id', new_keys['use'])
+ assoc_display = @interp._invoke('winfo', 'screen', new_keys['use'])
else
- begin
- pathname = @interp._invoke('winfo', 'pathname', new_keys['use'])
- assco_display = @interp._invoke('winfo', 'screen', pathname)
- rescue
- assoc_display = new_keys['display']
- end
+ begin
+ pathname = @interp._invoke('winfo', 'pathname', new_keys['use'])
+ assoc_display = @interp._invoke('winfo', 'screen', pathname)
+ rescue
+ assoc_display = new_keys['display']
+ end
end
# match display?
if assoc_display != new_keys['display']
- if optkeys.keys?(:display) || optkeys.keys?('display')
- fail RuntimeError,
- "conflicting 'display'=>#{new_keys['display']} " +
- "and display '#{assoc_display}' on 'use'=>#{new_keys['use']}"
- else
- new_keys['display'] = assoc_display
- end
+ if optkeys.key?(:display) || optkeys.key?('display')
+ fail RuntimeError,
+ "conflicting 'display'=>#{new_keys['display']} " +
+ "and display '#{assoc_display}' on 'use'=>#{new_keys['use']}"
+ else
+ new_keys['display'] = assoc_display
+ end
end
end
@@ -374,8 +1091,8 @@ class MultiTkIp
# create toplevel widget
begin
top = TkToplevel.new(toplevel_keys)
- rescue NameError
- fail unless @interp.safe?
+ rescue NameError => e
+ fail e unless @interp.safe?
fail SecurityError, "unable create toplevel on the safe interpreter"
end
msg = "Untrusted Ruby/Tk applet (#{slave_name})"
@@ -388,28 +1105,36 @@ class MultiTkIp
# procedure to delete slave interpreter
slave_delete_proc = proc{
unless slave_ip.deleted?
- if slave_ip._invoke('info', 'command', '.') != ""
- slave_ip._invoke('destroy', '.')
- end
- slave_ip.delete
+ #if slave_ip._invoke('info', 'command', '.') != ""
+ # slave_ip._invoke('destroy', '.')
+ #end
+ #slave_ip.delete
+ slave_ip._eval_without_enc('exit')
+ end
+ begin
+ top.destroy if top.winfo_exist?
+ rescue
+ # ignore
end
}
tag = TkBindTag.new.bind('Destroy', slave_delete_proc)
+ top.bindtags = top.bindtags.unshift(tag)
+
# create control frame
TkFrame.new(top, :bg=>'red', :borderwidth=>3, :relief=>'ridge') {|fc|
fc.bindtags = fc.bindtags.unshift(tag)
TkFrame.new(fc, :bd=>0){|f|
- TkButton.new(f,
- :text=>'Delete', :bd=>1, :padx=>2, :pady=>0,
- :highlightthickness=>0, :command=>slave_delete_proc
- ).pack(:side=>:right, :fill=>:both)
- f.pack(:side=>:right, :fill=>:both, :expand=>true)
+ TkButton.new(f,
+ :text=>'Delete', :bd=>1, :padx=>2, :pady=>0,
+ :highlightthickness=>0, :command=>slave_delete_proc
+ ).pack(:side=>:right, :fill=>:both)
+ f.pack(:side=>:right, :fill=>:both, :expand=>true)
}
TkLabel.new(fc, :text=>msg, :padx=>2, :pady=>0,
- :anchor=>:w).pack(:side=>:left, :fill=>:both, :expand=>true)
+ :anchor=>:w).pack(:side=>:left, :fill=>:both, :expand=>true)
fc.pack(:side=>:bottom, :fill=>:x)
}
@@ -418,30 +1143,60 @@ class MultiTkIp
dup_keys['fill'] = :both unless dup_keys.key?('fill')
dup_keys['expand'] = true unless dup_keys.key?('expand')
c = TkFrame.new(top, :container=>true).pack(dup_keys)
+ c.bind('Destroy', proc{top.destroy})
# return keys
loadTk_keys['use'] = TkWinfo.id(c)
- loadTk_keys
+ [loadTk_keys, top.path]
end
private :__create_safetk_frame
def __create_safe_slave_obj(safe_opts, app_name, tk_opts)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
# safe interpreter
- # at present, not enough support for '-deleteHook' option
ip_name = _create_slave_ip_name
slave_ip = @interp.create_slave(ip_name, true)
- @interp._eval("::safe::interpInit #{ip_name} "+_keys2opts(safe_opts))
- tk_opts = __check_safetk_optkeys(tk_opts)
- unless tk_opts.key?('use')
- tk_opts = __create_safetk_frame(slave_ip, ip_name, app_name, tk_opts)
+ @slave_ip_tbl[ip_name] = slave_ip
+ def slave_ip.safe_base?
+ true
end
+
+ @interp._eval("::safe::interpInit #{ip_name}")
+
slave_ip._invoke('set', 'argv0', app_name) if app_name.kind_of?(String)
- @interp._eval("::safe::loadTk #{ip_name} #{_keys2opts(tk_opts)}")
- @slave_ip_tbl[ip_name] = slave_ip
+
+ if tk_opts
+ tk_opts = __check_safetk_optkeys(tk_opts)
+ if tk_opts.key?('use')
+ @slave_ip_top[ip_name] = ''
+ else
+ tk_opts, top_path = __create_safetk_frame(slave_ip, ip_name, app_name,
+ tk_opts)
+ @slave_ip_top[ip_name] = top_path
+ end
+ @interp._eval("::safe::loadTk #{ip_name} #{_keys2opts(tk_opts)}")
+ else
+ @slave_ip_top[ip_name] = nil
+ end
+
+ if safe_opts.key?('deleteHook') || safe_opts.key?(:deleteHook)
+ @interp._eval("::safe::interpConfigure #{ip_name} " +
+ _keys2opts(safe_opts))
+ else
+ @interp._eval("::safe::interpConfigure #{ip_name} " +
+ _keys2opts(safe_opts) + '-deleteHook {' +
+ TkComm._get_eval_string(proc{|slave|
+ self._default_delete_hook(slave)
+ }) + '}')
+ end
+
[slave_ip, ip_name]
end
def __create_trusted_slave_obj(name, keys)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
ip_name = _create_slave_ip_name
slave_ip = @interp.create_slave(ip_name, false)
slave_ip._invoke('set', 'argv0', name) if name.kind_of?(String)
@@ -454,6 +1209,8 @@ class MultiTkIp
######################################
def _create_slave_object(keys={})
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
ip = MultiTkIp.new_slave(self, keys={})
@slave_ip_tbl[ip.name] = ip
end
@@ -469,7 +1226,11 @@ class MultiTkIp
fail SecurityError, "cannot create a master-ip at level #{$SAFE}"
end
- if !master.master? && master.safe?
+ if master.deleted? && safeip == nil
+ fail RuntimeError, "cannot create a slave of a deleted interpreter"
+ end
+
+ if !master.deleted? && !master.master? && master.safe?
fail SecurityError, "safe-slave-ip cannot create a new interpreter"
end
@@ -481,70 +1242,174 @@ class MultiTkIp
fail ArgumentError, "expecting a Hash object for the 2nd argument"
end
- @encoding = []
@tk_windows = {}
@tk_table_list = []
@slave_ip_tbl = {}
+ @slave_ip_top = {}
+ @cb_error_proc = []
+ @evloop_thread = []
- @encoding.taint unless @encoding.tainted?
@tk_windows.taint unless @tk_windows.tainted?
@tk_table_list.taint unless @tk_table_list.tainted?
@slave_ip_tbl.taint unless @slave_ip_tbl.tainted?
+ @slave_ip_top.taint unless @slave_ip_top.tainted?
+ @cb_error_proc.taint unless @cb_error_proc.tainted?
+ @evloop_thread.taint unless @evloop_thread.tainted?
+
+ @callback_status = []
name, safe, safe_opts, tk_opts = _parse_slaveopts(keys)
+ safe = 4 if safe && !safe.kind_of?(Fixnum)
+
+ @safe_base = false
+
if safeip == nil
# create master-ip
- @interp = TclTkIp.new(name, _keys2opts(tk_opts))
+ unless WITH_RUBY_VM
+ @interp = TclTkIp.new(name, _keys2opts(tk_opts))
+ else ### Ruby 1.9 !!!!!!!!!!!
+ @interp_thread = Thread.new{
+ Thread.current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts))
+ #sleep
+ TclTkLib.mainloop(true)
+ }
+ until @interp_thread[:interp]
+ Thread.pass
+ end
+ # INTERP_THREAD.run
+ @interp = @interp_thread[:interp]
+ end
+
@ip_name = nil
+ if safe
+ safe = $SAFE if safe < $SAFE
+ @safe_level = [safe]
+ else
+ @safe_level = [$SAFE]
+ end
else
# create slave-ip
if safeip || master.safe?
- @interp, @ip_name = master.__create_safe_slave_obj(safe_opts,
- name, tk_opts)
+ @safe_base = true
+ @interp, @ip_name = master.__create_safe_slave_obj(safe_opts,
+ name, tk_opts)
+ # @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!!
+ @interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!!
+ if safe
+ safe = master.safe_level if safe < master.safe_level
+ @safe_level = [safe]
+ else
+ @safe_level = [4]
+ end
else
- @interp, @ip_name = master.__create_trusted_slave_obj(name, tk_opts)
+ @interp, @ip_name = master.__create_trusted_slave_obj(name, tk_opts)
+ # @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!!
+ @interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!!
+ if safe
+ safe = master.safe_level if safe < master.safe_level
+ @safe_level = [safe]
+ else
+ @safe_level = [master.safe_level]
+ end
end
@set_alias_proc = proc{|name|
- master._invoke('interp', 'alias', @ip_name, name, '', name)
+ master._invoke('interp', 'alias', @ip_name, name, '', name)
}.freeze
end
@system = Object.new
+ @wait_on_mainloop = [true, 0].taint
+ # @wait_on_mainloop = [false, 0].taint
+
@threadgroup = ThreadGroup.new
+ @pseudo_toplevel = [false, nil]
+
@cmd_queue = Queue.new
- @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog()
+=begin
+ @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0])
@threadgroup.add @cmd_receiver
@threadgroup.add @receiver_watchdog
@threadgroup.enclose
+=end
+ @@DEFAULT_MASTER.assign_receiver_and_watchdog(self)
@@IP_TABLE[@threadgroup] = self
- _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
@@TK_TABLE_LIST.size.times{
(tbl = {}).tainted? || tbl.taint
@tk_table_list << tbl
}
+ _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
+
+ class << self
+ undef :instance_eval
+ end
+
+ # dummy call for initialization
+ self.eval_proc{ Tk.tk_call('set', 'tcl_patchLevel') }
self.freeze # defend against modification
end
+
+ ######################################
+
+ def _default_delete_hook(slave)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @slave_ip_tbl.delete(slave)
+ top = @slave_ip_top.delete(slave)
+ if top.kind_of?(String)
+ # call default hook of safetk.tcl (ignore exceptions)
+ if top == ''
+ begin
+ @interp._eval("::safe::disallowTk #{slave}")
+ rescue
+ warn("Waring: fail to call '::safe::disallowTk'") if $DEBUG
+ end
+ else # toplevel path
+ begin
+ @interp._eval("::safe::tkDelete {} #{top} #{slave}")
+ rescue
+ warn("Waring: fail to call '::safe::tkDelete'") if $DEBUG
+ begin
+ @interp._eval("destroy #{top}")
+ rescue
+ warn("Waring: fail to destroy toplevel") if $DEBUG
+ end
+ end
+ end
+ end
+ end
+
end
# get target IP
class MultiTkIp
+ def self._ip_id_
+ __getip._ip_id_
+ end
+ def _ip_id_
+ # for RemoteTkIp
+ ''
+ end
+
def self.__getip
- if Thread.current.group == ThreadGroup::Default
+ current = Thread.current
+ if TclTkLib.mainloop_thread? != false && current['callback_ip']
+ return current['callback_ip']
+ end
+ if current.group == ThreadGroup::Default
@@DEFAULT_MASTER
else
- ip = @@IP_TABLE[Thread.current.group]
+ ip = @@IP_TABLE[current.group]
unless ip
- fail SecurityError,
- "cannot call Tk methods on #{Thread.current.inspect}"
+ fail SecurityError,
+ "cannot call Tk methods on #{Thread.current.inspect}"
end
ip
end
@@ -557,24 +1422,76 @@ class << MultiTkIp
alias __new new
private :__new
- def new_master(keys={}, &b)
+ def new_master(safe=nil, keys={})
+ if MultiTkIp::WITH_RUBY_VM
+ #### TODO !!!!!!
+ fail RuntimeError,
+ 'sorry, still not support multiple master-interpreters on Ruby VM'
+ end
+
+ if safe.kind_of?(Hash)
+ keys = safe
+ elsif safe.kind_of?(Integer)
+ raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash)
+ if !keys.key?(:safe) && !keys.key?('safe')
+ keys[:safe] = safe
+ end
+ elsif safe == nil
+ # do nothing
+ else
+ raise ArgumentError, "unexpected argument(s)"
+ end
+
ip = __new(__getip, nil, keys)
- ip.eval_proc(&b) if b
+ #ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given?
+ if block_given?
+ Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)}
+ end
ip
end
alias new new_master
- def new_slave(keys={}, &b)
+ def new_slave(safe=nil, keys={})
+ if safe.kind_of?(Hash)
+ keys = safe
+ elsif safe.kind_of?(Integer)
+ raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash)
+ if !keys.key?(:safe) && !keys.key?('safe')
+ keys[:safe] = safe
+ end
+ elsif safe == nil
+ # do nothing
+ else
+ raise ArgumentError, "unexpected argument(s)"
+ end
+
ip = __new(__getip, false, keys)
- ip.eval_proc(&b) if b
+ # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given?
+ if block_given?
+ Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)}
+ end
ip
end
- alias new_trusted_slave new_master
+ alias new_trusted_slave new_slave
+
+ def new_safe_slave(safe=4, keys={})
+ if safe.kind_of?(Hash)
+ keys = safe
+ elsif safe.kind_of?(Integer)
+ raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash)
+ if !keys.key?(:safe) && !keys.key?('safe')
+ keys[:safe] = safe
+ end
+ else
+ raise ArgumentError, "unexpected argument(s)"
+ end
- def new_safe_slave(keys={},&b)
ip = __new(__getip, true, keys)
- ip.eval_proc(&b) if b
+ # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given?
+ if block_given?
+ Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)}
+ end
ip
end
alias new_safeTk new_safe_slave
@@ -585,13 +1502,21 @@ end
class MultiTkIp
def inspect
s = self.to_s.chop!
- if master?
- s << ':master'
- else
- if @interp.safe?
- s << ':safe-slave'
+ if self.manipulable?
+ if master?
+ if @interp.deleted?
+ s << ':deleted-master'
+ else
+ s << ':master'
+ end
else
- s << ':trusted-slave'
+ if @interp.deleted?
+ s << ':deleted-slave'
+ elsif @interp.safe?
+ s << ':safe-slave'
+ else
+ s << ':trusted-slave'
+ end
end
end
s << '>'
@@ -612,9 +1537,11 @@ class MultiTkIp
not master?
end
def self.slave?
+ not self.master?
end
def alive?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
begin
return false unless @cmd_receiver.alive?
return false if @interp.deleted?
@@ -648,19 +1575,34 @@ class MultiTkIp
end
def slaves(all = false)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp','slaves').split.map!{|name|
if @slave_ip_tbl.key?(name)
- @slave_ip_tbl[name]
+ @slave_ip_tbl[name]
elsif all
- name
+ name
else
- nil
+ nil
end
}.compact!
end
def self.slaves(all = false)
__getip.slaves(all)
end
+
+ def manipulable?
+ return true if (Thread.current.group == ThreadGroup::Default)
+ ip = MultiTkIp.__getip
+ (ip == self) || ip._is_master_of?(@interp)
+ end
+ def self.manipulable?
+ true
+ end
+
+ def _is_master_of?(tcltkip_obj)
+ tcltkip_obj.slave_of?(@interp)
+ end
+ protected :_is_master_of?
end
@@ -688,7 +1630,7 @@ class MultiTkIp
end
def _init_ip_env(script)
- script.call(self)
+ self.eval_proc{script.call(self)}
end
def _add_tk_procs(name, args, body)
@@ -699,13 +1641,30 @@ class MultiTkIp
}
end
+ def _remove_tk_procs(*names)
+ return if slave?
+ names.each{|name|
+ name = name.to_s
+
+ return if @interp.deleted?
+ @interp._invoke('rename', name, '')
+
+ return if @interp.deleted?
+ @interp._invoke('interp', 'slaves').split.each{|slave|
+ return if @interp.deleted?
+ @interp._invoke('interp', 'alias', slave, name, '') rescue nil
+ }
+ }
+ end
+
def _init_ip_internal(init_ip_env, add_tk_procs)
- init_ip_env.each{|script| script.call(self)}
+ #init_ip_env.each{|script| self.eval_proc{script.call(self)}}
+ init_ip_env.each{|script| self._init_ip_env(script)}
add_tk_procs.each{|name, args, body|
if master?
- @interp._invoke('proc', name, args, body) if args && body
+ @interp._invoke('proc', name, args, body) if args && body
else
- @set_alias_proc.call(name)
+ @set_alias_proc.call(name)
end
}
end
@@ -724,17 +1683,34 @@ class MultiTkIp
__getip._tk_table_list[id]
end
def self.create_table
- #if __getip.slave?
- # raise SecurityError, "slave-IP has no permission creating a new table"
- #end
+ if __getip.slave?
+ begin
+ raise SecurityError, "slave-IP has no permission creating a new table"
+ rescue SecurityError => e
+ #p e.backtrace
+ # Is called on a Ruby/Tk library?
+ caller_info = e.backtrace[1]
+ if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:}
+ # Probably, caller is a Ruby/Tk library --> allow creating
+ else
+ raise e
+ end
+ end
+ end
+
id = @@TK_TABLE_LIST.size
obj = Object.new
@@TK_TABLE_LIST << obj
- obj.instance_eval <<-EOD
+ obj.instance_variable_set(:@id, id)
+ obj.instance_variable_set(:@mutex, Mutex.new)
+ obj.instance_eval{
+ def self.mutex
+ @mutex
+ end
def self.method_missing(m, *args)
- MultiTkIp.tk_object_table(#{id}).send(m, *args)
+ MultiTkIp.tk_object_table(@id).__send__(m, *args)
end
- EOD
+ }
obj.freeze
@@IP_TABLE.each{|tg, ip| ip._add_new_tables }
return obj
@@ -742,15 +1718,48 @@ class MultiTkIp
def self.init_ip_env(script = Proc.new)
@@INIT_IP_ENV << script
- @@IP_TABLE.each{|tg, ip|
- ip._init_ip_env(script)
- }
+ if __getip.slave?
+ begin
+ raise SecurityError, "slave-IP has no permission initializing IP env"
+ rescue SecurityError => e
+ #p e.backtrace
+ # Is called on a Ruby/Tk library?
+ caller_info = e.backtrace[1]
+ if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:}
+ # Probably, caller is a Ruby/Tk library --> allow creating
+ else
+ raise e
+ end
+ end
+ end
+
+ # @@IP_TABLE.each{|tg, ip|
+ # ip._init_ip_env(script)
+ # }
+ @@DEFAULT_MASTER.__init_ip_env__(@@IP_TABLE, script)
end
def self.add_tk_procs(name, args=nil, body=nil)
- @@ADD_TK_PROCS << [name, args, body]
+ if name.kind_of?(Array) # => an array of [name, args, body]
+ name.each{|param| self.add_tk_procs(*param)}
+ else
+ name = name.to_s
+ @@ADD_TK_PROCS << [name, args, body]
+ @@IP_TABLE.each{|tg, ip|
+ ip._add_tk_procs(name, args, body)
+ }
+ end
+ end
+
+ def self.remove_tk_procs(*names)
+ names.each{|name|
+ name = name.to_s
+ @@ADD_TK_PROCS.delete_if{|elem|
+ elem.kind_of?(Array) && elem[0].to_s == name
+ }
+ }
@@IP_TABLE.each{|tg, ip|
- ip._add_tk_procs(name, args, body)
+ ip._remove_tk_procs(*names)
}
end
@@ -762,54 +1771,186 @@ end
# for callback operation
class MultiTkIp
+ def self.cb_entry_class
+ @@CB_ENTRY_CLASS
+ end
def self.get_cb_entry(cmd)
@@CB_ENTRY_CLASS.new(__getip, cmd).freeze
end
+=begin
+ def cb_eval(cmd, *args)
+ #self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) }
+ #ret = self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) }
+ ret = self.eval_callback(*args){|safe, *params|
+ $SAFE=safe if $SAFE < safe
+ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
+ }
+ if ret.kind_of?(Exception)
+ raise ret
+ end
+ ret
+ end
+=end
def cb_eval(cmd, *args)
- self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) }
+ self.eval_callback(*args){|safe, *params|
+ $SAFE=safe if $SAFE < safe
+ # TkUtil.eval_cmd(cmd, *params)
+ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
+ }
end
+=begin
+ def cb_eval(cmd, *args)
+ @callback_status[0] ||= TkVariable.new
+ @callback_status[1] ||= TkVariable.new
+ st, val = @callback_status
+ th = Thread.new{
+ self.eval_callback(*args){|safe, *params|
+ #p [status, val, safe, *params]
+ $SAFE=safe if $SAFE < safe
+ begin
+ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
+ rescue TkCallbackContinue
+ st.value = 4
+ rescue TkCallbackBreak
+ st.value = 3
+ rescue TkCallbackReturn
+ st.value = 2
+ rescue Exception => e
+ val.value = e.message
+ st.value = 1
+ else
+ st.value = 0
+ end
+ }
+ }
+ begin
+ st.wait
+ status = st.numeric
+ retval = val.value
+ rescue => e
+ fail e
+ end
+
+ if status == 1
+ fail RuntimeError, retval
+ elsif status == 2
+ fail TkCallbackReturn, "Tk callback returns 'return' status"
+ elsif status == 3
+ fail TkCallbackBreak, "Tk callback returns 'break' status"
+ elsif status == 4
+ fail TkCallbackContinue, "Tk callback returns 'continue' status"
+ else
+ ''
+ end
+ end
+=end
+
end
+# pseudo-toplevel operation support
+class MultiTkIp
+ # instance method
+ def __pseudo_toplevel
+ ip = MultiTkIp.__getip
+ (ip == @@DEFAULT_MASTER || ip == self) &&
+ self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1]
+ end
+
+ def __pseudo_toplevel=(m)
+ unless (Thread.current.group == ThreadGroup::Default &&
+ MultiTkIp.__getip == @@DEFAULT_MASTER)
+ fail SecurityError, "no permission to manipulate"
+ end
+
+ # if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?)
+ if m.respond_to?(:pseudo_toplevel_evaluable?)
+ @pseudo_toplevel[0] = true
+ @pseudo_toplevel[1] = m
+ else
+ fail ArgumentError, 'fail to set pseudo-toplevel'
+ end
+ self
+ end
+
+ def __pseudo_toplevel_evaluable?
+ begin
+ @pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable?
+ rescue Exception
+ false
+ end
+ end
+
+ def __pseudo_toplevel_evaluable=(mode)
+ unless (Thread.current.group == ThreadGroup::Default &&
+ MultiTkIp.__getip == @@DEFAULT_MASTER)
+ fail SecurityError, "no permission to manipulate"
+ end
+
+ @pseudo_toplevel[0] = (mode)? true: false
+ end
+end
# evaluate a procedure on the proper interpreter
class MultiTkIp
# instance method
def eval_proc_core(req_val, cmd, *args)
- # cmd string ==> proc
- if cmd.kind_of?(String)
- xcmd = cmd
- xargs = args
- cmd = proc{ TkComm._get_eval_string(TkUtil.eval_cmd(xcmd, *xargs)) }
- args = []
- end
-
# check
- unless cmd.kind_of?(Proc)
- raise RuntimeError, "A Proc object is expected for the 'cmd' argument"
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ unless cmd.kind_of?(Proc) || cmd.kind_of?(Method)
+ raise RuntimeError, "A Proc/Method object is expected for the 'cmd' argument"
end
# on IP thread
- if (@cmd_receiver == Thread.current)
+ if @cmd_receiver == Thread.current ||
+ (!req_val && TclTkLib.mainloop_thread? != false) # callback
begin
- ret = cmd.call(*args)
- rescue SystemExit
- # exit IP
- warn("Warning: "+ $! + " on " + self.inspect) if $DEBUG
- self.delete
- ret = nil
+ ret = cmd.call(safe_level, *args)
+ rescue SystemExit => e
+ # exit IP
+ warn("Warning: "+ $! + " on " + self.inspect) if $DEBUG
+ begin
+ self._eval_without_enc('exit')
+ rescue Exception
+ end
+ self.delete
+ ret = nil
rescue Exception => e
- warn("Warning: " + e.class.inspect +
- ((e.message.length > 0)? ' "' + e.message + '"': '') +
- " on " + self.inspect)
- ret = nil
+ if $DEBUG
+ warn("Warning: " + e.class.inspect +
+ ((e.message.length > 0)? ' "' + e.message + '"': '') +
+ " on " + self.inspect)
+ end
+=begin
+ begin
+ bt = _toUTF8(e.backtrace.join("\n"))
+ bt.instance_variable_set(:@encoding, 'utf-8')
+ rescue Exception
+ bt = e.backtrace.join("\n")
+ end
+ begin
+ @interp._set_global_var('errorInfo', bt)
+ rescue Exception
+ end
+=end
+ ret = e
end
return ret
end
-
+
# send cmd to the proc-queue
unless req_val
- @cmd_queue.enq([nil, cmd, *args])
+ begin
+ @cmd_queue.enq([nil, cmd, *args])
+ rescue Exception => e
+ # ignore
+ if $DEBUG
+ warn("Warning: " + e.class.inspect +
+ ((e.message.length > 0)? ' "' + e.message + '"': '') +
+ " on " + self.inspect)
+ end
+ return e
+ end
return nil
end
@@ -820,38 +1961,209 @@ class MultiTkIp
rescue MultiTkIp_OK => ret
# return value
return ret.value
- rescue SystemExit
+ rescue SystemExit => e
# exit IP
warn("Warning: " + $! + " on " + self.inspect) if $DEBUG
- self.delete
+ begin
+ self._eval_without_enc('exit')
+ rescue Exception
+ end
+ if !self.deleted? && !safe? && allow_ruby_exit?
+ self.delete
+ fail e
+ else
+ self.delete
+ end
rescue Exception => e
- # others --> warning
- warn("Warning: " + e.class.inspect +
- ((e.message.length > 0)? ' "' + e.message + '"': '') +
- " on " + self.inspect)
+ if $DEBUG
+ warn("Warning: " + e.class.inspect +
+ ((e.message.length > 0)? ' "' + e.message + '"': '') +
+ " on " + self.inspect)
+ end
+ return e
end
return nil
end
private :eval_proc_core
- def eval_callback(cmd = Proc.new, *args)
- eval_proc_core(false, cmd, *args)
+ def eval_callback(*args)
+ if block_given?
+ cmd = Proc.new
+ else
+ cmd = args.shift
+ end
+ current = Thread.current
+ backup_ip = current['callback_ip']
+ current['callback_ip'] = self
+ begin
+ eval_proc_core(false, cmd, *args)
+ ensure
+ current['callback_ip'] = backup_ip
+ end
end
- def eval_proc(cmd = Proc.new, *args)
- eval_proc_core(true, cmd, *args)
+ def eval_proc(*args)
+ # The scope of the eval-block of 'eval_proc' method is different from
+ # the external. If you want to pass local values to the eval-block,
+ # use arguments of eval_proc method. They are passed to block-arguments.
+ if block_given?
+ cmd = Proc.new
+ else
+ unless (cmd = args.shift)
+ fail ArgumentError, "A Proc or Method object is expected for 1st argument"
+ end
+ end
+ if TclTkLib.mainloop_thread? == true
+ # call from eventloop
+ current = Thread.current
+ backup_ip = current['callback_ip']
+ current['callback_ip'] = self
+ begin
+ eval_proc_core(false,
+ proc{|safe, *params|
+ $SAFE=safe if $SAFE < safe
+ cmd.call(*params)
+ }, *args)
+ ensure
+ current['callback_ip'] = backup_ip
+ end
+ else
+ eval_proc_core(true,
+ proc{|safe, *params|
+ $SAFE=safe if $SAFE < safe
+ Thread.new(*params, &cmd).value
+ },
+ *args)
+ end
end
alias call eval_proc
- alias eval_string eval_proc
+
+ def bg_eval_proc(*args)
+ if block_given?
+ cmd = Proc.new
+ else
+ unless (cmd = args.shift)
+ fail ArgumentError, "A Proc or Method object is expected for 1st argument"
+ end
+ end
+ Thread.new{
+ eval_proc(cmd, *args)
+=begin
+ eval_proc_core(false,
+ proc{|safe, *params|
+ $SAFE=safe if $SAFE < safe
+ Thread.new(*params, &cmd).value
+ },
+ safe_level, *args)
+=end
+ }
+ end
+ alias background_eval_proc bg_eval_proc
+ alias thread_eval_proc bg_eval_proc
+ alias bg_call bg_eval_proc
+ alias background_call bg_eval_proc
+
+ def eval_string(cmd, *eval_args)
+ # cmd string ==> proc
+ unless cmd.kind_of?(String)
+ raise RuntimeError, "A String object is expected for the 'cmd' argument"
+ end
+
+ eval_proc_core(true,
+ proc{|safe|
+ Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd,
+ *eval_args)
+ })
+ end
+ alias eval_str eval_string
+
+ def bg_eval_string(cmd, *eval_args)
+ # cmd string ==> proc
+ unless cmd.kind_of?(String)
+ raise RuntimeError, "A String object is expected for the 'cmd' argument"
+ end
+ Thread.new{
+ eval_proc_core(true,
+ proc{|safe|
+ Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd,
+ *eval_args)
+ })
+ }
+ end
+ alias background_eval_string bg_eval_string
+ alias bg_eval_str bg_eval_string
+ alias background_eval_str bg_eval_string
+
+ def eval(*args, &blk)
+ if block_given?
+ eval_proc(*args, &blk)
+ elsif args[0]
+ if args[0].respond_to?(:call)
+ eval_proc(*args)
+ else
+ eval_string(*args)
+ end
+ else
+ fail ArgumentError, "no argument to eval"
+ end
+ end
+
+ def bg_eval(*args, &blk)
+ if block_given?
+ bg_eval_proc(*args, &blk)
+ elsif args[0]
+ if args[0].respond_to?(:call)
+ bg_eval_proc(*args)
+ else
+ bg_eval_string(*args)
+ end
+ else
+ fail ArgumentError, "no argument to eval"
+ end
+ end
+ alias background_eval bg_eval
end
+
class << MultiTkIp
# class method
- def eval_proc(cmd = Proc.new, *args)
+ def eval_proc(*args, &blk)
# class ==> interp object
- __getip.eval_proc(cmd, *args)
+ __getip.eval_proc(*args, &blk)
end
alias call eval_proc
- alias eval_string eval_proc
+
+ def bg_eval_proc(*args, &blk)
+ # class ==> interp object
+ __getip.bg_eval_proc(*args, &blk)
+ end
+ alias background_eval_proc bg_eval_proc
+ alias thread_eval_proc bg_eval_proc
+ alias bg_call bg_eval_proc
+ alias background_call bg_eval_proc
+
+ def eval_string(cmd, *eval_args)
+ # class ==> interp object
+ __getip.eval_string(cmd, *eval_args)
+ end
+ alias eval_str eval_string
+
+ def bg_eval_string(cmd, *eval_args)
+ # class ==> interp object
+ __getip.bg_eval_string(cmd, *eval_args)
+ end
+ alias background_eval_string bg_eval_string
+ alias bg_eval_str bg_eval_string
+ alias background_eval_str bg_eval_string
+
+ def eval(*args, &blk)
+ # class ==> interp object
+ __getip.eval(*args, &blk)
+ end
+ def bg_eval(*args, &blk)
+ # class ==> interp object
+ __getip.bg_eval(*args, &blk)
+ end
+ alias background_eval bg_eval
end
@@ -868,10 +2180,12 @@ class << MultiTkIp
__getip.do_one_event(flag)
end
def mainloop_abort_on_exception
- __getip.mainloop_abort_on_exception
+ # __getip.mainloop_abort_on_exception
+ TclTkLib.mainloop_abort_on_exception
end
def mainloop_abort_on_exception=(mode)
- __getip.mainloop_abort_on_exception=(mode)
+ # __getip.mainloop_abort_on_exception=(mode)
+ TclTkLib.mainloop_abort_on_exception=(mode)
end
def set_eventloop_tick(tick)
__getip.set_eventloop_tick(tick)
@@ -896,7 +2210,7 @@ end
# class methods to delegate to TclTkIp
class << MultiTkIp
def method_missing(id, *args)
- __getip.send(id, *args)
+ __getip.__send__(id, *args)
end
def make_safe
@@ -907,7 +2221,58 @@ class << MultiTkIp
__getip.safe?
end
- def restart
+ def safe_base?
+ begin
+ __getip.safe_base?
+ rescue
+ false
+ end
+ end
+
+ def allow_ruby_exit?
+ __getip.allow_ruby_exit?
+ end
+
+ def allow_ruby_exit= (mode)
+ __getip.allow_ruby_exit = mode
+ end
+
+ def delete
+ __getip.delete
+ end
+
+ def deleted?
+ __getip.deleted?
+ end
+
+ def has_mainwindow?
+ __getip.has_mainwindow?
+ end
+
+ def invalid_namespace?
+ __getip.invalid_namespace?
+ end
+
+ def abort(msg = nil)
+ __getip.abort(msg)
+ end
+
+ def exit(st = true)
+ __getip.exit(st)
+ end
+
+ def exit!(st = false)
+ __getip.exit!(st)
+ end
+
+ def restart(app_name = nil, keys = {})
+ init_ip_internal
+
+ __getip._invoke('set', 'argv0', app_name) if app_name
+ if keys.kind_of?(Hash)
+ __getip._invoke('set', 'argv', _keys2opts(keys))
+ end
+
__getip.restart
end
@@ -919,11 +2284,27 @@ class << MultiTkIp
__getip._invoke(*args)
end
- def _toUTF8(str, encoding)
+ def _eval_without_enc(str)
+ __getip._eval_without_enc(str)
+ end
+
+ def _invoke_without_enc(*args)
+ __getip._invoke_without_enc(*args)
+ end
+
+ def _eval_with_enc(str)
+ __getip._eval_with_enc(str)
+ end
+
+ def _invoke_with_enc(*args)
+ __getip._invoke_with_enc(*args)
+ end
+
+ def _toUTF8(str, encoding=nil)
__getip._toUTF8(str, encoding)
end
- def _fromUTF8(str, encoding)
+ def _fromUTF8(str, encoding=nil)
__getip._fromUTF8(str, encoding)
end
@@ -938,6 +2319,62 @@ class << MultiTkIp
def _return_value
__getip._return_value
end
+
+ def _get_variable(var, flag)
+ __getip._get_variable(var, flag)
+ end
+ def _get_variable2(var, idx, flag)
+ __getip._get_variable2(var, idx, flag)
+ end
+ def _set_variable(var, value, flag)
+ __getip._set_variable(var, value, flag)
+ end
+ def _set_variable2(var, idx, value, flag)
+ __getip._set_variable2(var, idx, value, flag)
+ end
+ def _unset_variable(var, flag)
+ __getip._unset_variable(var, flag)
+ end
+ def _unset_variable2(var, idx, flag)
+ __getip._unset_variable2(var, idx, flag)
+ end
+
+ def _get_global_var(var)
+ __getip._get_global_var(var)
+ end
+ def _get_global_var2(var, idx)
+ __getip._get_global_var2(var, idx)
+ end
+ def _set_global_var(var, value)
+ __getip._set_global_var(var, value)
+ end
+ def _set_global_var2(var, idx, value)
+ __getip._set_global_var2(var, idx, value)
+ end
+ def _unset_global_var(var)
+ __getip._unset_global_var(var)
+ end
+ def _unset_global_var2(var, idx)
+ __getip._unset_global_var2(var, idx)
+ end
+
+ def _make_menu_embeddable(menu_path)
+ __getip._make_menu_embeddable(menu_path)
+ end
+
+ def _split_tklist(str)
+ __getip._split_tklist(str)
+ end
+ def _merge_tklist(*args)
+ __getip._merge_tklist(*args)
+ end
+ def _conv_listelement(arg)
+ __getip._conv_listelement(arg)
+ end
+
+ def _create_console
+ __getip._create_console
+ end
end
@@ -952,12 +2389,12 @@ class << TclTkLib
def do_one_event(flag = TclTkLib::EventFlag::ALL)
MultiTkIp.do_one_event(flag)
end
- def mainloop_abort_on_exception
- MultiTkIp.mainloop_abort_on_exception
- end
- def mainloop_abort_on_exception=(mode)
- MultiTkIp.mainloop_abort_on_exception=(mode)
- end
+ #def mainloop_abort_on_exception
+ # MultiTkIp.mainloop_abort_on_exception
+ #end
+ #def mainloop_abort_on_exception=(mode)
+ # MultiTkIp.mainloop_abort_on_exception=(mode)
+ #end
def set_eventloop_tick(tick)
MultiTkIp.set_eventloop_tick(tick)
end
@@ -976,8 +2413,15 @@ class << TclTkLib
def get_eventloop_weight
MultiTkIp.get_eventloop_weight
end
- def restart
- MultiTkIp.restart
+ def restart(*args)
+ MultiTkIp.restart(*args)
+ end
+
+ def _merge_tklist(*args)
+ MultiTkIp._merge_tklist(*args)
+ end
+ def _conv_listelement(arg)
+ MultiTkIp._conv_listelement(arg)
end
end
@@ -985,81 +2429,402 @@ end
# depend on TclTkIp
class MultiTkIp
def mainloop(check_root = true, restart_on_dead = true)
- return self if self.slave?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ if WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!!
+ return @interp_thread.value if @interp_thread
+ end
+
+ #return self if self.slave?
+ #return self if self != @@DEFAULT_MASTER
+ if self != @@DEFAULT_MASTER
+ if @wait_on_mainloop[0]
+ begin
+ @wait_on_mainloop[1] += 1
+ if $SAFE >= 4
+ _receiver_mainloop(check_root).join
+ else
+ @cmd_queue.enq([@system, 'call_mainloop',
+ Thread.current, check_root])
+ Thread.stop
+ end
+ rescue MultiTkIp_OK => ret
+ # return value
+ if ret.value.kind_of?(Thread)
+ return ret.value.value
+ else
+ return ret.value
+ end
+ rescue SystemExit => e
+ # exit IP
+ warn("Warning: " + $! + " on " + self.inspect) if $DEBUG
+ begin
+ self._eval_without_enc('exit')
+ rescue Exception
+ end
+ self.delete
+ rescue StandardError => e
+ if $DEBUG
+ warn("Warning: " + e.class.inspect +
+ ((e.message.length > 0)? ' "' + e.message + '"': '') +
+ " on " + self.inspect)
+ end
+ return e
+ rescue Exception => e
+ return e
+ ensure
+ @wait_on_mainloop[1] -= 1
+ end
+ end
+ return
+ end
+
unless restart_on_dead
- @interp.mainloop(check_root)
- else
+ @wait_on_mainloop[1] += 1
+=begin
begin
- loop do
- break unless self.alive?
- if check_root
- begin
- break if TclTkLib.num_of_mainwindows == 0
- rescue Exception
- break
- end
- end
- @interp.mainloop(check_root)
- end
- rescue StandardError
- if TclTkLib.mainloop_abort_on_exception != nil
- STDERR.print("Warning: Tk mainloop on ", @interp.inspect,
- " receives ", $!.class.inspect,
- " exception (ignore) : ", $!.message, "\n");
- end
- retry
+ @interp.mainloop(check_root)
+ rescue StandardError => e
+ if $DEBUG
+ warn("Warning: " + e.class.inspect +
+ ((e.message.length > 0)? ' "' + e.message + '"': '') +
+ " on " + self.inspect)
+ end
+ end
+=end
+ begin
+ @interp.mainloop(check_root)
+ ensure
+ @wait_on_mainloop[1] -= 1
+ end
+ else
+ loop do
+ break unless self.alive?
+ if check_root
+ begin
+ break if TclTkLib.num_of_mainwindows == 0
+ rescue StandardError
+ break
+ end
+ end
+ break if @interp.deleted?
+ begin
+ @wait_on_mainloop[1] += 1
+ @interp.mainloop(check_root)
+ rescue StandardError => e
+ if TclTkLib.mainloop_abort_on_exception != nil
+ #STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
+ # " exception (ignore) : ", $!.message, "\n");
+ if $DEBUG
+ warn("Warning: Tk mainloop receives " << e.class.inspect <<
+ " exception (ignore) : " << e.message);
+ end
+ end
+ #raise e
+ rescue Exception => e
+=begin
+ if TclTkLib.mainloop_abort_on_exception != nil
+ #STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
+ # " exception (ignore) : ", $!.message, "\n");
+ if $DEBUG
+ warn("Warning: Tk mainloop receives " << e.class.inspect <<
+ " exception (ignore) : " << e.message);
+ end
+ end
+=end
+ raise e
+ ensure
+ @wait_on_mainloop[1] -= 1
+ Thread.pass # avoid eventloop conflict
+ end
end
end
self
end
def make_safe
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.make_safe
end
def safe?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.safe?
end
+ def safe_base?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @safe_base
+ end
+
+ def allow_ruby_exit?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.allow_ruby_exit?
+ end
+
+ def allow_ruby_exit= (mode)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.allow_ruby_exit = mode
+ end
+
def delete
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @slave_ip_tbl.each{|name, subip|
+ _destroy_slaves_of_slaveIP(subip)
+=begin
+ begin
+ subip._invoke('destroy', '.') unless subip.deleted?
+ rescue Exception
+ end
+=end
+ begin
+ # subip._eval_without_enc("foreach i [after info] {after cancel $i}")
+ unless subip.deleted?
+ after_ids = subip._eval_without_enc("after info")
+ subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
+ end
+ rescue Exception
+ end
+
+ # safe_base?
+ if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
+ begin
+ @interp._eval_without_enc("::safe::interpDelete #{name}")
+ rescue Exception
+ else
+ next if subip.deleted?
+ end
+ end
+ if subip.respond_to?(:safe_base?) && subip.safe_base? &&
+ !subip.deleted?
+ # do 'exit' to call the delete_hook procedure
+ begin
+ subip._eval_without_enc('exit')
+ rescue Exception
+ end
+ else
+ begin
+ subip.delete unless subip.deleted?
+ rescue Exception
+ end
+ end
+ }
+
+ begin
+ # @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
+ after_ids = @interp._eval_without_enc("after info")
+ @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
+ rescue Exception
+ end
+
+ begin
+ @interp._invoke('destroy', '.') unless @interp.deleted?
+ rescue Exception
+ end
+
+ if @safe_base && !@interp.deleted?
+ # do 'exit' to call the delete_hook procedure
+ @interp._eval_without_enc('exit')
+ end
@interp.delete
+ self
end
def deleted?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.deleted?
end
- def restart
+ def has_mainwindow?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.has_mainwindow?
+ end
+
+ def invalid_namespace?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.invalid_namespace?
+ end
+
+ def abort(msg = nil)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ if master? && !safe? && allow_ruby_exit?
+ if msg
+ Kernel.abort(msg)
+ else
+ Kernel.abort
+ end
+ else
+ # ignore msg
+ delete
+ 1
+ end
+ end
+
+ def exit(st = true)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ if master? && !safe? && allow_ruby_exit?
+ Kernel.exit(st)
+ else
+ delete
+ st
+ end
+ end
+
+ def exit!(st = false)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ if master? && !safe? && allow_ruby_exit?
+ Kernel.exit!(st)
+ else
+ delete
+ st
+ end
+ end
+
+ def restart(app_name = nil, keys = {})
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
+
+ @interp._invoke('set', 'argv0', app_name) if app_name
+ if keys.kind_of?(Hash)
+ @interp._invoke('set', 'argv', _keys2opts(keys))
+ end
+
@interp.restart
end
+ def __eval(str)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.__eval(str)
+ end
+
+ def __invoke(*args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.__invoke(*args)
+ end
+
def _eval(str)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._eval(str)
end
def _invoke(*args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke(*args)
end
- def _toUTF8(str, encoding)
+ def _eval_without_enc(str)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._eval_without_enc(str)
+ end
+
+ def _invoke_without_enc(*args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._invoke_without_enc(*args)
+ end
+
+ def _eval_with_enc(str)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._eval_with_enc(str)
+ end
+
+ def _invoke_with_enc(*args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._invoke_with_enc(*args)
+ end
+
+ def _toUTF8(str, encoding=nil)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._toUTF8(str, encoding)
end
- def _fromUTF8(str, encoding)
+ def _fromUTF8(str, encoding=nil)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._fromUTF8(str, encoding)
end
def _thread_vwait(var)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._thread_vwait(var)
end
def _thread_tkwait(mode, target)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._thread_tkwait(mode, target)
end
def _return_value
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._return_value
end
+
+ def _get_variable(var, flag)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._get_variable(var, flag)
+ end
+ def _get_variable2(var, idx, flag)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._get_variable2(var, idx, flag)
+ end
+ def _set_variable(var, value, flag)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._set_variable(var, value, flag)
+ end
+ def _set_variable2(var, idx, value, flag)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._set_variable2(var, idx, value, flag)
+ end
+ def _unset_variable(var, flag)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._unset_variable(var, flag)
+ end
+ def _unset_variable2(var, idx, flag)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._unset_variable2(var, idx, flag)
+ end
+
+ def _get_global_var(var)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._get_global_var(var)
+ end
+ def _get_global_var2(var, idx)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._get_global_var2(var, idx)
+ end
+ def _set_global_var(var, value)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._set_global_var(var, value)
+ end
+ def _set_global_var2(var, idx, value)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._set_global_var2(var, idx, value)
+ end
+ def _unset_global_var(var)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._unset_global_var(var)
+ end
+ def _unset_global_var2(var, idx)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._unset_global_var2(var, idx)
+ end
+
+ def _make_menu_embeddable(menu_path)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._make_menu_embeddable(menu_path)
+ end
+
+ def _split_tklist(str)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._split_tklist(str)
+ end
+ def _merge_tklist(*args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._merge_tklist(*args)
+ end
+ def _conv_listelement(arg)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._conv_listelement(arg)
+ end
end
@@ -1078,9 +2843,10 @@ class MultiTkIp
i = -1
brace = 1
str.each_byte {|c|
+ c = c.chr
i += 1
- brace += 1 if c == ?{
- brace -= 1 if c == ?}
+ brace += 1 if c == '{'
+ brace -= 1 if c == '}'
break if brace == 0
}
if i == 0
@@ -1090,7 +2856,8 @@ class MultiTkIp
else
list.push str[0..i-1]
end
- list += tk_split_simplelist(str[i+1..-1])
+ #list += _lst2ary(str[i+1..-1])
+ list.concat(_lst2ary(str[i+1..-1]))
list
end
private :_lst2ary
@@ -1101,12 +2868,13 @@ class MultiTkIp
elsif slave.kind_of?(String)
slave
else
- cmd_name.to_s
+ slave.to_s
end
end
private :_slavearg
def alias_info(slave, cmd_name)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
_lst2ary(@interp._invoke('interp', 'alias', _slavearg(slave), cmd_name))
end
def self.alias_info(slave, cmd_name)
@@ -1114,6 +2882,7 @@ class MultiTkIp
end
def alias_delete(slave, cmd_name)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'alias', _slavearg(slave), cmd_name, '')
self
end
@@ -1123,8 +2892,9 @@ class MultiTkIp
end
def def_alias(slave, new_cmd, org_cmd, *args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
ret = @interp._invoke('interp', 'alias', _slavearg(slave), new_cmd,
- '', org_cmd, *args)
+ '', org_cmd, *args)
(ret == new_cmd)? self: nil
end
def self.def_alias(slave, new_cmd, org_cmd, *args)
@@ -1133,6 +2903,7 @@ class MultiTkIp
end
def aliases(slave = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
_lst2ary(@interp._invoke('interp', 'aliases', _slavearg(slave)))
end
def self.aliases(slave = '')
@@ -1140,6 +2911,7 @@ class MultiTkIp
end
def delete_slaves(*args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
slaves = args.collect{|s| _slavearg(s)}
@interp._invoke('interp', 'delete', *slaves) if slaves.size > 0
self
@@ -1150,6 +2922,7 @@ class MultiTkIp
end
def exist?(slave = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
ret = @interp._invoke('interp', 'exists', _slavearg(slave))
(ret == '1')? true: false
end
@@ -1158,6 +2931,7 @@ class MultiTkIp
end
def delete_cmd(slave, cmd)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
slave_invoke = @interp._invoke('list', 'rename', cmd, '')
@interp._invoke('interp', 'eval', _slavearg(slave), slave_invoke)
self
@@ -1168,6 +2942,7 @@ class MultiTkIp
end
def expose_cmd(slave, cmd, aliasname = nil)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
if aliasname
@interp._invoke('interp', 'expose', _slavearg(slave), cmd, aliasname)
else
@@ -1181,6 +2956,7 @@ class MultiTkIp
end
def hide_cmd(slave, cmd, aliasname = nil)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
if aliasname
@interp._invoke('interp', 'hide', _slavearg(slave), cmd, aliasname)
else
@@ -1194,6 +2970,7 @@ class MultiTkIp
end
def hidden_cmds(slave = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
_lst2ary(@interp._invoke('interp', 'hidden', _slavearg(slave)))
end
def self.hidden_cmds(slave = '')
@@ -1201,21 +2978,66 @@ class MultiTkIp
end
def invoke_hidden(slave, cmd, *args)
- @interp._invoke('interp', 'invokehidden', _slavearg(slave), cmd, *args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ else
+ keys = []
+ end
+ keys << _slavearg(slave)
+ if Tk::TCL_MAJOR_VERSION > 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
+ keys << '--'
+ end
+ keys << cmd
+ keys.concat(args)
+ @interp._invoke('interp', 'invokehidden', *keys)
end
def self.invoke_hidden(slave, cmd, *args)
__getip.invoke_hidden(slave, cmd, *args)
end
def invoke_hidden_on_global(slave, cmd, *args)
- @interp._invoke('interp', 'invokehidden', _slavearg(slave),
- '-global', cmd, *args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ else
+ keys = []
+ end
+ keys << _slavearg(slave)
+ keys << '-global'
+ if Tk::TCL_MAJOR_VERSION > 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
+ keys << '--'
+ end
+ keys << cmd
+ keys.concat(args)
+ @interp._invoke('interp', 'invokehidden', *keys)
end
def self.invoke_hidden_on_global(slave, cmd, *args)
__getip.invoke_hidden_on_global(slave, cmd, *args)
end
+ def invoke_hidden_on_namespace(slave, ns, cmd, *args)
+ # for Tcl8.5 or later
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ else
+ keys = []
+ end
+ keys << _slavearg(slave)
+ keys << '-namespace' << TkComm._get_eval_string(ns)
+ keys << '--' << cmd
+ keys.concat(args)
+ @interp._invoke('interp', 'invokehidden', *keys)
+ end
+ def self.invoke_hidden_on_namespace(slave, ns, cmd, *args)
+ __getip.invoke_hidden_on_namespace(slave, ns, cmd, *args)
+ end
+
def mark_trusted(slave = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'marktrusted', _slavearg(slave))
self
end
@@ -1224,7 +3046,75 @@ class MultiTkIp
self
end
+ def set_bgerror_handler(cmd = Proc.new, slave = nil, &b)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ unless TkComm._callback_entry?(cmd)
+ if !slave && b
+ slave = cmd
+ cmd = Proc.new(&b)
+ end
+ end
+ slave = '' unless slave
+
+ @interp._invoke('interp', 'bgerror', _slavearg(slave), cmd)
+ end
+ def self.bgerror(cmd = Proc.new, slave = nil, &b)
+ __getip.bgerror(cmd, slave, &b)
+ end
+
+ def get_bgerror_handler(slave = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ procedure(@interp._invoke('interp', 'bgerror', _slavearg(slave)))
+ end
+ def self.bgerror(slave = '')
+ __getip.bgerror(slave)
+ end
+
+ def set_limit(limit_type, slave = '', opts = {})
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._invoke('interp', 'limit', _slavearg(slave), limit_type, opts)
+ end
+ def self.set_limit(limit_type, slave = '', opts = {})
+ __getip.set_limit(limit_type, slave, opts)
+ end
+
+ def get_limit(limit_type, slave = '', slot = nil)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ if slot
+ num_or_str(@interp._invoke('interp', 'limit', _slavearg(slave),
+ limit_type, slot))
+ else
+ l = @interp._split_tklist(@interp._invoke_without_enc('interp', 'limit',
+ _slavearg(slave),
+ limit_type))
+ l.map!{|s| _fromUTF8(s)}
+ r = {}
+ until l.empty?
+ key = l.shift[1..-1]
+ val = l.shift
+ val = num_or_str(val) if val
+ r[key] = val
+ end
+ r
+ end
+ end
+ def self.get_limit(limit_type, slave = '', slot = nil)
+ __getip.get_limit(limit_type, slave, slot)
+ end
+
+ def recursion_limit(slave = '', limit = None)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ number(@interp._invoke('interp', 'recursionlimit',
+ _slavearg(slave), limit))
+ end
+ def self.recursion_limit(slave = '', limit = None)
+ __getip.recursion_limit(slave)
+ end
+
def alias_target(aliascmd, slave = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'target', _slavearg(slave), aliascmd)
end
def self.alias_target(aliascmd, slave = '')
@@ -1232,6 +3122,7 @@ class MultiTkIp
end
def share_stdin(dist, src = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'share', src, 'stdin', dist)
self
end
@@ -1241,6 +3132,7 @@ class MultiTkIp
end
def share_stdout(dist, src = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'share', src, 'stdout', dist)
self
end
@@ -1250,6 +3142,7 @@ class MultiTkIp
end
def share_stderr(dist, src = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'share', src, 'stderr', dist)
self
end
@@ -1259,6 +3152,7 @@ class MultiTkIp
end
def transfer_stdin(dist, src = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'transfer', src, 'stdin', dist)
self
end
@@ -1268,6 +3162,7 @@ class MultiTkIp
end
def transfer_stdout(dist, src = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'transfer', src, 'stdout', dist)
self
end
@@ -1277,6 +3172,7 @@ class MultiTkIp
end
def transfer_stderr(dist, src = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'transfer', src, 'stderr', dist)
self
end
@@ -1286,6 +3182,7 @@ class MultiTkIp
end
def share_stdio(dist, src = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'share', src, 'stdin', dist)
@interp._invoke('interp', 'share', src, 'stdout', dist)
@interp._invoke('interp', 'share', src, 'stderr', dist)
@@ -1297,6 +3194,7 @@ class MultiTkIp
end
def transfer_stdio(dist, src = '')
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp._invoke('interp', 'transfer', src, 'stdin', dist)
@interp._invoke('interp', 'transfer', src, 'stdout', dist)
@interp._invoke('interp', 'transfer', src, 'stderr', dist)
@@ -1309,46 +3207,162 @@ class MultiTkIp
end
+# Safe Base :: manipulating safe interpreter
+class MultiTkIp
+ def safeip_configure(slot, value=None)
+ # use for '-noStatics' option ==> {statics=>false}
+ # for '-nestedLoadOk' option ==> {nested=>true}
+ if slot.kind_of?(Hash)
+ ip = MultiTkIp.__getip
+ ip._eval('::safe::interpConfigure ' + @ip_name + ' ' + _keys2opts(slot))
+ else
+ ip._eval('::safe::interpConfigure ' + @ip_name + ' ' +
+ "-#{slot} #{_get_eval_string(value)}")
+ end
+ self
+ end
+
+ def safeip_configinfo(slot = nil)
+ ip = MultiTkIp.__getip
+ ret = {}
+ if slot
+ conf = _lst2ary(ip._eval("::safe::interpConfigure " +
+ @ip_name + " -#{slot}"))
+ if conf[0] == '-deleteHook'
+=begin
+ if conf[1] =~ /^rb_out\S* (c(_\d+_)?\d+)/
+ ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
+=end
+ if conf[1] =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
+ ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$4]
+ else
+ ret[conf[0][1..-1]] = conf[1]
+ end
+ else
+ ret[conf[0][1..-1]] = conf[1]
+ end
+ else
+ Hash[*_lst2ary(ip._eval("::safe::interpConfigure " +
+ @ip_name))].each{|k, v|
+ if k == '-deleteHook'
+=begin
+ if v =~ /^rb_out\S* (c(_\d+_)?\d+)/
+ ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
+=end
+ if v =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
+ ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$4]
+ else
+ ret[k[1..-1]] = v
+ end
+ else
+ ret[k[1..-1]] = v
+ end
+ }
+ end
+ ret
+ end
+
+ def safeip_delete
+ ip = MultiTkIp.__getip
+ ip._eval("::safe::interpDelete " + @ip_name)
+ end
+
+ def safeip_add_to_access_path(dir)
+ ip = MultiTkIp.__getip
+ ip._eval("::safe::interpAddToAccessPath #{@ip_name} #{dir}")
+ end
+
+ def safeip_find_in_access_path(dir)
+ ip = MultiTkIp.__getip
+ ip._eval("::safe::interpFindInAccessPath #{@ip_name} #{dir}")
+ end
+
+ def safeip_set_log_cmd(cmd = Proc.new)
+ ip = MultiTkIp.__getip
+ ip._eval("::safe::setLogCmd #{@ip_name} #{_get_eval_string(cmd)}")
+ end
+end
+
+
# encoding convert
+class << MultiTkIp
+ def encoding_table
+ __getip.encoding_table
+ end
+end
class MultiTkIp
- # from tkencoding.rb by ttate@jaist.ac.jp
- alias __eval _eval
- alias __invoke _invoke
+ def encoding_table
+ @interp.encoding_table
+ end
+
+ def force_default_encoding=(mode)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.force_default_encoding = mode
+ end
+ def force_default_encoding?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.force_default_encoding?
+ end
- def encoding
- @encoding[0]
+ def default_encoding=(enc)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.default_encoding = enc
end
+
def encoding=(enc)
- @encoding[0] = enc
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.encoding = enc
end
-
- def _eval(cmd)
- if @encoding[0] != nil
- _fromUTF8(__eval(_toUTF8(cmd, @encoding[0])), @encoding[0])
- else
- __eval(cmd)
- end
+ def encoding_name
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.encoding_name
+ end
+ def encoding_obj
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.encoding_obj
end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
- def _invoke(*cmds)
- if defined?(@encoding[0]) && @encoding[0] != nil
- cmds = cmds.collect{|cmd| _toUTF8(cmd, @encoding[0])}
- _fromUTF8(__invoke(*cmds), @encoding[0])
- else
- __invoke(*cmds)
- end
+ def encoding_convertfrom(str, enc=None)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.encoding_convertfrom(str, enc)
end
+ alias encoding_convert_from encoding_convertfrom
+
+ def encoding_convertto(str, enc=None)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.encoding_convertto(str, enc)
+ end
+ alias encoding_convert_to encoding_convertto
end
# remove methods for security
+if MultiTkIp::WITH_RUBY_VM &&
+ ! MultiTkIp::RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
+ class MultiTkIp
+ INTERP_THREAD = @@DEFAULT_MASTER.instance_variable_get('@interp_thread')
+ INTERP_MUTEX = INTERP_THREAD[:mutex]
+ INTERP_ROOT_CHECK = INTERP_THREAD[:root_check]
+ end
+ module TkCore
+ INTERP_THREAD = MultiTkIp::INTERP_THREAD
+ INTERP_MUTEX = MultiTkIp::INTERP_MUTEX
+ INTERP_ROOT_CHECK = MultiTkIp::INTERP_ROOT_CHECK
+ end
+ class MultiTkIp
+ remove_const(:INTERP_THREAD)
+ remove_const(:INTERP_MUTEX)
+ remove_const(:INTERP_ROOT_CHECK)
+ end
+end
+
class MultiTkIp
- undef_method :instance_eval
+ # undef_method :instance_eval
undef_method :instance_variable_get
undef_method :instance_variable_set
end
-
-
# end of MultiTkIp definition
# defend against modification
diff --git a/ext/tk/lib/remote-tk.rb b/ext/tk/lib/remote-tk.rb
new file mode 100644
index 0000000000..70115a60aa
--- /dev/null
+++ b/ext/tk/lib/remote-tk.rb
@@ -0,0 +1,526 @@
+#
+# remote-tk.rb - supports to control remote Tk interpreters
+# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+if defined? MultiTkIp
+ fail RuntimeError, "'remote-tk' library must be required before requiring 'multi-tk'"
+end
+
+class MultiTkIp; end
+class RemoteTkIp < MultiTkIp; end
+
+class MultiTkIp
+ @@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
+ @@TK_TABLE_LIST = [].taint unless defined?(@@TK_TABLE_LIST)
+ def self._IP_TABLE; @@IP_TABLE; end
+ def self._TK_TABLE_LIST; @@TK_TABLE_LIST; end
+
+ @flag = true
+ def self._DEFAULT_MASTER
+ # work only once
+ if @flag
+ @flag = nil
+ @@DEFAULT_MASTER
+ else
+ nil
+ end
+ end
+end
+class RemoteTkIp
+ @@IP_TABLE = MultiTkIp._IP_TABLE unless defined?(@@IP_TABLE)
+ @@TK_TABLE_LIST = MultiTkIp._TK_TABLE_LIST unless defined?(@@TK_TABLE_LIST)
+end
+class << MultiTkIp
+ undef _IP_TABLE
+ undef _TK_TABLE_LIST
+end
+
+require 'multi-tk'
+
+class RemoteTkIp
+ if defined?(@@DEFAULT_MASTER)
+ MultiTkIp._DEFAULT_MASTER
+ else
+ @@DEFAULT_MASTER = MultiTkIp._DEFAULT_MASTER
+ end
+end
+
+
+###############################
+
+class << RemoteTkIp
+ undef new_master, new_slave, new_safe_slave
+ undef new_trusted_slave, new_safeTk
+
+ def new(*args, &b)
+ ip = __new(*args)
+ ip.eval_proc(&b) if b
+ ip
+ end
+end
+
+class RemoteTkIp
+ def initialize(remote_ip, displayof=nil, timeout=5)
+ if $SAFE >= 4
+ fail SecurityError, "cannot access another interpreter at level #{$SAFE}"
+ end
+
+ @interp = MultiTkIp.__getip
+ if @interp.safe?
+ fail SecurityError, "safe-IP cannot create RemoteTkIp"
+ end
+
+
+ @interp.allow_ruby_exit = false
+ @appname = @interp._invoke('tk', 'appname')
+ @remote = remote_ip.to_s.dup.freeze
+ if displayof.kind_of?(TkWindow)
+ @displayof = displayof.path.dup.freeze
+ else
+ @displayof = nil
+ end
+ if self.deleted?
+ fail RuntimeError, "no Tk application named \"#{@remote}\""
+ end
+
+ @tk_windows = {}
+ @tk_table_list = []
+ @slave_ip_tbl = {}
+ @slave_ip_top = {}
+
+ @tk_windows.taint unless @tk_windows.tainted?
+ @tk_table_list.taint unless @tk_table_list.tainted?
+ @slave_ip_tbl.taint unless @slave_ip_tbl.tainted?
+ @slave_ip_top.taint unless @slave_ip_top.tainted?
+
+ @system = Object.new
+
+ @threadgroup = ThreadGroup.new
+
+ @safe_level = [$SAFE]
+
+ @wait_on_mainloop = [true, 0]
+
+ @cmd_queue = Queue.new
+
+=begin
+ @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog()
+
+ @threadgroup.add @cmd_receiver
+ @threadgroup.add @receiver_watchdog
+
+ @threadgroup.enclose
+=end
+ @@DEFAULT_MASTER.assign_receiver_and_watchdog(self)
+
+ @@IP_TABLE[@threadgroup] = self
+ @@TK_TABLE_LIST.size.times{
+ (tbl = {}).tainted? || tbl.taint
+ @tk_table_list << tbl
+ }
+
+ @ret_val = TkVariable.new
+ if timeout > 0 && ! _available_check(timeout)
+ fail RuntimeError, "cannot create connection"
+ end
+ @ip_id = _create_connection
+
+ class << self
+ undef :instance_eval
+ end
+
+ self.freeze # defend against modification
+ end
+
+ def manipulable?
+ return true if (Thread.current.group == ThreadGroup::Default)
+ MultiTkIp.__getip == @interp && ! @interp.safe?
+ end
+ def self.manipulable?
+ true
+ end
+
+ def _is_master_of?(tcltkip_obj)
+ tcltkip_obj == @interp
+ end
+ protected :_is_master_of?
+
+ def _ip_id_
+ @ip_id
+ end
+
+ def _available_check(timeout = 5)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ return nil if timeout < 1
+ @ret_val.value = ''
+ @interp._invoke('send', '-async', @remote,
+ 'send', '-async', Tk.appname,
+ "set #{@ret_val.id} ready")
+ Tk.update
+ if @ret_val != 'ready'
+ (1..(timeout*5)).each{
+ sleep 0.2
+ Tk.update
+ break if @ret_val == 'ready'
+ }
+ end
+ @ret_val.value == 'ready'
+ end
+ private :_available_check
+
+ def _create_connection
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ ip_id = '_' + @interp._invoke('send', @remote, <<-'EOS') + '_'
+ if {[catch {set _rubytk_control_ip_id_} ret] != 0} {
+ set _rubytk_control_ip_id_ 0
+ } else {
+ set _rubytk_control_ip_id_ [expr $ret + 1]
+ }
+ return $_rubytk_control_ip_id_
+ EOS
+
+ @interp._invoke('send', @remote, <<-EOS)
+ proc rb_out#{ip_id} args {
+ send #{@appname} rb_out \$args
+ }
+ EOS
+
+ ip_id
+ end
+ private :_create_connection
+
+ def _appsend(enc_mode, async, *cmds)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ p ['_appsend', [@remote, @displayof], enc_mode, async, cmds] if $DEBUG
+ if $SAFE >= 4
+ fail SecurityError, "cannot send commands at level 4"
+ elsif $SAFE >= 1 && cmds.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted commands at level #{$SAFE}"
+ end
+
+ cmds = @interp._merge_tklist(*TkUtil::_conv_args([], enc_mode, *cmds))
+ if @displayof
+ if async
+ @interp.__invoke('send', '-async', '-displayof', @displayof,
+ '--', @remote, *cmds)
+ else
+ @interp.__invoke('send', '-displayof', @displayof,
+ '--', @remote, *cmds)
+ end
+ else
+ if async
+ @interp.__invoke('send', '-async', '--', @remote, *cmds)
+ else
+ @interp.__invoke('send', '--', @remote, *cmds)
+ end
+ end
+ end
+ private :_appsend
+
+ def ready?(timeout=5)
+ if timeout < 0
+ fail ArgumentError, "timeout must be positive number"
+ end
+ _available_check(timeout)
+ end
+
+ def is_rubytk?
+ return false if _appsend(false, false, 'info', 'command', 'ruby') == ""
+ [ _appsend(false, false, 'ruby', 'RUBY_VERSION'),
+ _appsend(false, false, 'set', 'tk_patchLevel') ]
+ end
+
+ def appsend(async, *args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
+ if @displayof
+ Tk.appsend_displayof(@remote, @displayof, async, *args)
+ else
+ Tk.appsend(@remote, async, *args)
+ end
+ end
+
+ def rb_appsend(async, *args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
+ if @displayof
+ Tk.rb_appsend_displayof(@remote, @displayof, async, *args)
+ else
+ Tk.rb_appsend(@remote, async, *args)
+ end
+ end
+
+ def create_slave(name, safe=false)
+ if safe
+ safe_opt = ''
+ else
+ safe_opt = '-safe'
+ end
+ _appsend(false, false, "interp create #{safe_opt} -- #{name}")
+ end
+
+ def make_safe
+ fail RuntimeError, 'cannot change safe mode of the remote interpreter'
+ end
+
+ def safe?
+ _appsend(false, false, 'interp issafe')
+ end
+
+ def safe_base?
+ false
+ end
+
+ def allow_ruby_exit?
+ false
+ end
+
+ def allow_ruby_exit= (mode)
+ fail RuntimeError, 'cannot change mode of the remote interpreter'
+ end
+
+ def delete
+ _appsend(false, true, 'exit')
+ end
+
+ def deleted?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ if @displayof
+ lst = @interp._invoke_without_enc('winfo', 'interps',
+ '-displayof', @displayof)
+ else
+ lst = @interp._invoke_without_enc('winfo', 'interps')
+ end
+ # unless @interp._split_tklist(lst).index(@remote)
+ unless @interp._split_tklist(lst).index(_toUTF8(@remote))
+ true
+ else
+ false
+ end
+ end
+
+ def has_mainwindow?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ begin
+ inf = @interp._invoke_without_enc('info', 'command', '.')
+ rescue Exception
+ return nil
+ end
+ if !inf.kind_of?(String) || inf != '.'
+ false
+ else
+ true
+ end
+ end
+
+ def invalid_namespace?
+ false
+ end
+
+ def restart
+ fail RuntimeError, 'cannot restart the remote interpreter'
+ end
+
+ def __eval(str)
+ _appsend(false, false, str)
+ end
+ def _eval(str)
+ _appsend(nil, false, str)
+ end
+ def _eval_without_enc(str)
+ _appsend(false, false, str)
+ end
+ def _eval_with_enc(str)
+ _appsend(true, false, str)
+ end
+
+ def _invoke(*args)
+ _appsend(nil, false, *args)
+ end
+
+ def __invoke(*args)
+ _appsend(false, false, *args)
+ end
+ def _invoke(*args)
+ _appsend(nil, false, *args)
+ end
+ def _invoke_without_enc(*args)
+ _appsend(false, false, *args)
+ end
+ def _invoke_with_enc(*args)
+ _appsend(true, false, *args)
+ end
+
+ def _toUTF8(str, encoding=nil)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._toUTF8(str, encoding)
+ end
+
+ def _fromUTF8(str, encoding=nil)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._fromUTF8(str, encoding)
+ end
+
+ def _thread_vwait(var_name)
+ _appsend(false, 'thread_vwait', varname)
+ end
+
+ def _thread_tkwait(mode, target)
+ _appsend(false, 'thread_tkwait', mode, target)
+ end
+
+ def _return_value
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._return_value
+ end
+
+ def _get_variable(var_name, flag)
+ # ignore flag
+ _appsend(false, 'set', TkComm::_get_eval_string(var_name))
+ end
+ def _get_variable2(var_name, index_name, flag)
+ # ignore flag
+ _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})")
+ end
+
+ def _set_variable(var_name, value, flag)
+ # ignore flag
+ _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value))
+ end
+ def _set_variable2(var_name, index_name, value, flag)
+ # ignore flag
+ _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value))
+ end
+
+ def _unset_variable(var_name, flag)
+ # ignore flag
+ _appsend(false, 'unset', TkComm::_get_eval_string(var_name))
+ end
+ def _unset_variable2(var_name, index_name, flag)
+ # ignore flag
+ _appsend(false, 'unset', "#{var_name}(#{index_name})")
+ end
+
+ def _get_global_var(var_name)
+ _appsend(false, 'set', TkComm::_get_eval_string(var_name))
+ end
+ def _get_global_var2(var_name, index_name)
+ _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})")
+ end
+
+ def _set_global_var(var_name, value)
+ _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value))
+ end
+ def _set_global_var2(var_name, index_name, value)
+ _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value))
+ end
+
+ def _unset_global_var(var_name)
+ _appsend(false, 'unset', TkComm::_get_eval_string(var_name))
+ end
+ def _unset_global_var2(var_name, index_name)
+ _appsend(false, 'unset', "#{var_name}(#{index_name})")
+ end
+
+ def _split_tklist(str)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._split_tklist(str)
+ end
+
+ def _merge_tklist(*args)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._merge_tklist(*args)
+ end
+
+ def _conv_listelement(str)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp._conv_listelement(str)
+ end
+
+ def _create_console
+ fail RuntimeError, 'not support "_create_console" on the remote interpreter'
+ end
+
+ def mainloop
+ fail RuntimeError, 'not support "mainloop" on the remote interpreter'
+ end
+ def mainloop_watchdog
+ fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter'
+ end
+ def do_one_evant(flag = nil)
+ fail RuntimeError, 'not support "do_one_event" on the remote interpreter'
+ end
+ def mainloop_abort_on_exception
+ fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter'
+ end
+ def mainloop_abort_on_exception=(mode)
+ fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter'
+ end
+ def set_eventloop_tick(*args)
+ fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter'
+ end
+ def get_eventloop_tick
+ fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter'
+ end
+ def set_no_event_wait(*args)
+ fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter'
+ end
+ def get_no_event_wait
+ fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter'
+ end
+ def set_eventloop_weight(*args)
+ fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter'
+ end
+ def get_eventloop_weight
+ fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter'
+ end
+end
+
+class << RemoteTkIp
+ def mainloop(*args)
+ fail RuntimeError, 'not support "mainloop" on the remote interpreter'
+ end
+ def mainloop_watchdog(*args)
+ fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter'
+ end
+ def do_one_evant(flag = nil)
+ fail RuntimeError, 'not support "do_one_event" on the remote interpreter'
+ end
+ def mainloop_abort_on_exception
+ fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter'
+ end
+ def mainloop_abort_on_exception=(mode)
+ fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter'
+ end
+ def set_eventloop_tick(*args)
+ fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter'
+ end
+ def get_eventloop_tick
+ fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter'
+ end
+ def set_no_event_wait(*args)
+ fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter'
+ end
+ def get_no_event_wait
+ fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter'
+ end
+ def set_eventloop_weight(*args)
+ fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter'
+ end
+ def get_eventloop_weight
+ fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter'
+ end
+end
diff --git a/ext/tk/lib/tcltk.rb b/ext/tk/lib/tcltk.rb
new file mode 100644
index 0000000000..7f6f41605d
--- /dev/null
+++ b/ext/tk/lib/tcltk.rb
@@ -0,0 +1,367 @@
+# tof
+
+#### tcltk library, more direct manipulation of tcl/tk
+#### Sep. 5, 1997 Y. Shigehiro
+
+require "tcltklib"
+
+################
+
+# module TclTk: collection of tcl/tk utilities (supplies namespace.)
+module TclTk
+
+ # initialize Hash to hold unique symbols and such
+ @namecnt = {}
+
+ # initialize Hash to hold callbacks
+ @callback = {}
+end
+
+# TclTk.mainloop(): call TclTkLib.mainloop()
+def TclTk.mainloop()
+ print("mainloop: start\n") if $DEBUG
+ TclTkLib.mainloop()
+ print("mainloop: end\n") if $DEBUG
+end
+
+# TclTk.deletecallbackkey(ca): remove callback from TclTk module
+# this does not remove callbacks from tcl/tk interpreter
+# without calling this method, TclTkInterpreter will not be GCed
+# ca: callback(TclTkCallback)
+def TclTk.deletecallbackkey(ca)
+ print("deletecallbackkey: ", ca.to_s(), "\n") if $DEBUG
+ @callback.delete(ca.to_s)
+end
+
+# TclTk.dcb(ca, wid, W): call TclTk.deletecallbackkey() for each callbacks
+# in an array.
+# this is for callback for top-level <Destroy>
+# ca: array of callbacks(TclTkCallback)
+# wid: top-level widget(TclTkWidget)
+# w: information about window given by %W(String)
+def TclTk.dcb(ca, wid, w)
+ if wid.to_s() == w
+ ca.each{|i|
+ TclTk.deletecallbackkey(i)
+ }
+ end
+end
+
+# TclTk._addcallback(ca): register callback
+# ca: callback(TclTkCallback)
+def TclTk._addcallback(ca)
+ print("_addcallback: ", ca.to_s(), "\n") if $DEBUG
+ @callback[ca.to_s()] = ca
+end
+
+# TclTk._callcallback(key, arg): invoke registered callback
+# key: key to select callback (to_s value of the TclTkCallback)
+# arg: parameter from tcl/tk interpreter
+def TclTk._callcallback(key, arg)
+ print("_callcallback: ", @callback[key].inspect, "\n") if $DEBUG
+ @callback[key]._call(arg)
+ # throw out callback value
+ # should return String to satisfy rb_eval_string()
+ return ""
+end
+
+# TclTk._newname(prefix): generate unique name(String)
+# prefix: prefix of the unique name
+def TclTk._newname(prefix)
+ # generated name counter is stored in @namecnt
+ if !@namecnt.key?(prefix)
+ # first appearing prefix, initialize
+ @namecnt[prefix] = 1
+ else
+ # already appeared prefix, generate next name
+ @namecnt[prefix] += 1
+ end
+ return "#{prefix}#{@namecnt[prefix]}"
+end
+
+################
+
+# class TclTkInterpreter: tcl/tk interpreter
+class TclTkInterpreter
+
+ # initialize():
+ def initialize()
+ # generate interpreter object
+ @ip = TclTkIp.new()
+
+ # add ruby_fmt command to tcl interpreter
+ # ruby_fmt command format arguments by `format' and call `ruby' command
+ # (notice ruby command receives only one argument)
+ if $DEBUG
+ @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt $args\" ; set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }")
+ else
+ @ip._eval("proc ruby_fmt {fmt args} { set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }")
+ end
+
+ # @ip._get_eval_string(*args): generate string to evaluate in tcl interpreter
+ # *args: script which is going to be evaluated under tcl/tk
+ def @ip._get_eval_string(*args)
+ argstr = ""
+ args.each{|arg|
+ argstr += " " if argstr != ""
+ # call to_eval if it is defined
+ if (arg.respond_to?(:to_eval))
+ argstr += arg.to_eval()
+ else
+ # call to_s unless defined
+ argstr += arg.to_s()
+ end
+ }
+ return argstr
+ end
+
+ # @ip._eval_args(*args): evaluate string under tcl/tk interpreter
+ # returns result string.
+ # *args: script which is going to be evaluated under tcl/tk
+ def @ip._eval_args(*args)
+ # calculate the string to eval in the interpreter
+ argstr = _get_eval_string(*args)
+
+ # evaluate under the interpreter
+ print("_eval: \"", argstr, "\"") if $DEBUG
+ res = _eval(argstr)
+ if $DEBUG
+ print(" -> \"", res, "\"\n")
+ elsif _return_value() != 0
+ print(res, "\n")
+ end
+ fail(%Q/can't eval "#{argstr}"/) if _return_value() != 0 #'
+ return res
+ end
+
+ # generate tcl/tk command object and register in the hash
+ @commands = {}
+ # for all commands registered in tcl/tk interpreter:
+ @ip._eval("info command").split(/ /).each{|comname|
+ if comname =~ /^[.]/
+ # if command is a widget (path), generate TclTkWidget,
+ # and register it in the hash
+ @commands[comname] = TclTkWidget.new(@ip, comname)
+ else
+ # otherwise, generate TclTkCommand
+ @commands[comname] = TclTkCommand.new(@ip, comname)
+ end
+ }
+ end
+
+ # commands(): returns hash of the tcl/tk commands
+ def commands()
+ return @commands
+ end
+
+ # rootwidget(): returns root widget(TclTkWidget)
+ def rootwidget()
+ return @commands["."]
+ end
+
+ # _tcltkip(): returns @ip(TclTkIp)
+ def _tcltkip()
+ return @ip
+ end
+
+ # method_missing(id, *args): execute undefined method as tcl/tk command
+ # id: method symbol
+ # *args: method arguments
+ def method_missing(id, *args)
+ # if command named by id registered, then execute it
+ if @commands.key?(id.id2name)
+ return @commands[id.id2name].e(*args)
+ else
+ # otherwise, exception
+ super
+ end
+ end
+end
+
+# class TclTkObject: base class of the tcl/tk objects
+class TclTkObject
+
+ # initialize(ip, exp):
+ # ip: interpreter(TclTkIp)
+ # exp: tcl/tk representation
+ def initialize(ip, exp)
+ fail("type is not TclTkIp") if !ip.kind_of?(TclTkIp)
+ @ip = ip
+ @exp = exp
+ end
+
+ # to_s(): returns tcl/tk representation
+ def to_s()
+ return @exp
+ end
+end
+
+# class TclTkCommand: tcl/tk commands
+# you should not call TclTkCommand.new()
+# commands are created by TclTkInterpreter:initialize()
+class TclTkCommand < TclTkObject
+
+ # e(*args): execute command. returns String (e is for exec or eval)
+ # *args: command arguments
+ def e(*args)
+ return @ip._eval_args(to_s(), *args)
+ end
+end
+
+# class TclTkLibCommand: tcl/tk commands in the library
+class TclTkLibCommand < TclTkCommand
+
+ # initialize(ip, name):
+ # ip: interpreter(TclTkInterpreter)
+ # name: command name (String)
+ def initialize(ip, name)
+ super(ip._tcltkip, name)
+ end
+end
+
+# class TclTkVariable: tcl/tk variable
+class TclTkVariable < TclTkObject
+
+ # initialize(interp, dat):
+ # interp: interpreter(TclTkInterpreter)
+ # dat: the value to set(String)
+ # if nil, not initialize variable
+ def initialize(interp, dat)
+ # auto-generate tcl/tk representation (variable name)
+ exp = TclTk._newname("v_")
+ # initialize TclTkObject
+ super(interp._tcltkip(), exp)
+ # safe this for `set' command
+ @set = interp.commands()["set"]
+ # set value
+ set(dat) if dat
+ end
+
+ # although you can set/refer variable by using set in tcl/tk,
+ # we provide the method for accessing variables
+
+ # set(data): set tcl/tk variable using `set'
+ # data: new value
+ def set(data)
+ @set.e(to_s(), data.to_s())
+ end
+
+ # get(): read tcl/tk variable(String) using `set'
+ def get()
+ return @set.e(to_s())
+ end
+end
+
+# class TclTkWidget: tcl/tk widget
+class TclTkWidget < TclTkCommand
+
+ # initialize(*args):
+ # *args: parameters
+ def initialize(*args)
+ if args[0].kind_of?(TclTkIp)
+ # in case the 1st argument is TclTkIp:
+
+ # Wrap tcl/tk widget by TclTkWidget
+ # (used in TclTkInterpreter#initialize())
+
+ # need two arguments
+ fail("invalid # of parameter") if args.size != 2
+
+ # ip: interpreter(TclTkIp)
+ # exp: tcl/tk representation
+ ip, exp = args
+
+ # initialize TclTkObject
+ super(ip, exp)
+ elsif args[0].kind_of?(TclTkInterpreter)
+ # in case 1st parameter is TclTkInterpreter:
+
+ # generate new widget from parent widget
+
+ # interp: interpreter(TclTkInterpreter)
+ # parent: parent widget
+ # command: widget generating tk command(label Åù)
+ # *args: argument to the command
+ interp, parent, command, *args = args
+
+ # generate widget name
+ exp = parent.to_s()
+ exp += "." if exp !~ /[.]$/
+ exp += TclTk._newname("w_")
+ # initialize TclTkObject
+ super(interp._tcltkip(), exp)
+ # generate widget
+ res = @ip._eval_args(command, exp, *args)
+# fail("can't create Widget") if res != exp
+ # for tk_optionMenu, it is legal res != exp
+ else
+ fail("first parameter is not TclTkInterpreter")
+ end
+ end
+end
+
+# class TclTkCallback: tcl/tk callbacks
+class TclTkCallback < TclTkObject
+
+ # initialize(interp, pr, arg):
+ # interp: interpreter(TclTkInterpreter)
+ # pr: callback procedure(Proc)
+ # arg: string to pass as block parameters of pr
+ # bind command of tcl/tk uses % replacement for parameters
+ # pr can receive replaced data using block parameter
+ # its format is specified by arg string
+ # You should not specify arg for the command like
+ # scrollbar with -command option, which receives parameters
+ # without specifying any replacement
+ def initialize(interp, pr, arg = nil)
+ # auto-generate tcl/tk representation (variable name)
+ exp = TclTk._newname("c_")
+ # initialize TclTkObject
+ super(interp._tcltkip(), exp)
+ # save parameters
+ @pr = pr
+ @arg = arg
+ # register in the module
+ TclTk._addcallback(self)
+ end
+
+ # to_eval(): retuens string representation for @ip._eval_args
+ def to_eval()
+ if @arg
+ # bind replaces %s before calling ruby_fmt, so %%s is used
+ s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%%s")} #{@arg}}/
+ else
+ s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%s")}}/
+ end
+
+ return s
+ end
+
+ # _call(arg): invoke callback
+ # arg: callback parameter
+ def _call(arg)
+ @pr.call(arg)
+ end
+end
+
+# class TclTkImage: tcl/tk images
+class TclTkImage < TclTkCommand
+
+ # initialize(interp, t, *args):
+ # generating image is done by TclTkImage.new()
+ # destrying is done by image delete (inconsistent, sigh)
+ # interp: interpreter(TclTkInterpreter)
+ # t: image type (photo, bitmap, etc.)
+ # *args: command argument
+ def initialize(interp, t, *args)
+ # auto-generate tcl/tk representation
+ exp = TclTk._newname("i_")
+ # initialize TclTkObject
+ super(interp._tcltkip(), exp)
+ # generate image
+ res = @ip._eval_args("image create", t, exp, *args)
+ fail("can't create Image") if res != exp
+ end
+end
+
+# eof
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index 69c214175a..c5d5b804d2 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -1,34 +1,60 @@
#
-# tk.rb - Tk interface module using tcltklib
-# $Date$
-# by Yukihiro Matsumoto <matz@netlab.jp>
+# tk.rb - Tk interface module using tcltklib
+# by Yukihiro Matsumoto <matz@netlab.jp>
# use Shigehiro's tcltklib
-require "tcltklib"
-require "tkutil"
+require 'tcltklib'
+require 'tkutil'
+# autoload
+require 'tk/autoload'
+
+# for Mutex
+require 'thread'
+
+class TclTkIp
+ # backup original (without encoding) _eval and _invoke
+ alias _eval_without_enc _eval
+ alias _invoke_without_enc _invoke
+
+ def _ip_id_
+ # for RemoteTkIp
+ ''
+ end
+end
+
+# define TkComm module (step 1: basic functions)
module TkComm
+ include TkUtil
+ extend TkUtil
+
WidgetClassNames = {}.taint
+ TkExtlibAutoloadModule = [].taint
- None = Object.new
- def None.to_s
- 'None'
- end
- None.freeze
+ # None = Object.new ### --> definition is moved to TkUtil module
+ # def None.to_s
+ # 'None'
+ # end
+ # None.freeze
#Tk_CMDTBL = {}
#Tk_WINDOWS = {}
- Tk_IDs = ["00000".taint, "00000".taint].freeze # [0]-cmdid, [1]-winid
+ Tk_IDs = ["00000".taint, "00000".taint] # [0]-cmdid, [1]-winid
+ Tk_IDs.instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
# for backward compatibility
Tk_CMDTBL = Object.new
def Tk_CMDTBL.method_missing(id, *args)
- TkCore::INTERP.tk_cmd_tbl.send(id, *args)
+ TkCore::INTERP.tk_cmd_tbl.__send__(id, *args)
end
Tk_CMDTBL.freeze
Tk_WINDOWS = Object.new
def Tk_WINDOWS.method_missing(id, *args)
- TkCore::INTERP.tk_windows.send(id, *args)
+ TkCore::INTERP.tk_windows.__send__(id, *args)
end
Tk_WINDOWS.freeze
@@ -36,6 +62,21 @@ module TkComm
@cmdtbl = [].taint
}
+ unless const_defined?(:GET_CONFIGINFO_AS_ARRAY)
+ # GET_CONFIGINFO_AS_ARRAY = false => returns a Hash { opt =>val, ... }
+ # true => returns an Array [[opt,val], ... ]
+ # val is a list which includes resource info.
+ GET_CONFIGINFO_AS_ARRAY = true
+ end
+ unless const_defined?(:GET_CONFIGINFOwoRES_AS_ARRAY)
+ # for configinfo without resource info; list of [opt, value] pair
+ # false => returns a Hash { opt=>val, ... }
+ # true => returns an Array [[opt,val], ... ]
+ GET_CONFIGINFOwoRES_AS_ARRAY = true
+ end
+ # *** ATTENTION ***
+ # 'current_configinfo' method always returns a Hash under all cases of above.
+
def error_at
frames = caller()
frames.delete_if do |c|
@@ -50,7 +91,7 @@ module TkComm
begin
#tk_class = TkCore::INTERP._invoke('winfo', 'class', path)
- tk_class = Tk.ip_invoke('winfo', 'class', path)
+ tk_class = Tk.ip_invoke_without_enc('winfo', 'class', path)
rescue
return path
end
@@ -60,17 +101,66 @@ module TkComm
# gen_class_name = ruby_class_name + 'GeneratedOnTk'
gen_class_name = ruby_class_name
classname_def = ''
- elsif Object.const_defined?('Tk' + tk_class)
- ruby_class_name = 'Tk' + tk_class
+ else # ruby_class == nil
+ mods = TkExtlibAutoloadModule.find_all{|m| m.const_defined?(tk_class)}
+ mods.each{|mod|
+ begin
+ mod.const_get(tk_class) # auto_load
+ break if (ruby_class = WidgetClassNames[tk_class])
+ rescue LoadError
+ # ignore load error
+ end
+ }
+
+ unless ruby_class
+ std_class = 'Tk' << tk_class
+ if Object.const_defined?(std_class)
+ Object.const_get(std_class) # auto_load
+ ruby_class = WidgetClassNames[tk_class]
+ end
+ end
+
+ if ruby_class
+ # found
+ ruby_class_name = ruby_class.name
+ gen_class_name = ruby_class_name
+ classname_def = ''
+ else
+ # unknown
+ ruby_class_name = 'TkWindow'
+ gen_class_name = 'TkWidget_' + tk_class
+ classname_def = "WidgetClassName = '#{tk_class}'.freeze"
+ end
+ end
+
+###################################
+=begin
+ if ruby_class = WidgetClassNames[tk_class]
+ ruby_class_name = ruby_class.name
# gen_class_name = ruby_class_name + 'GeneratedOnTk'
gen_class_name = ruby_class_name
classname_def = ''
else
- ruby_class_name = 'TkWindow'
- # gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk'
- gen_class_name = 'TkWidget_' + tk_class
- classname_def = "WidgetClassName = '#{tk_class}'.freeze"
+ mod = TkExtlibAutoloadModule.find{|m| m.const_defined?(tk_class)}
+ if mod
+ ruby_class_name = mod.name + '::' + tk_class
+ gen_class_name = ruby_class_name
+ classname_def = ''
+ elsif Object.const_defined?('Tk' + tk_class)
+ ruby_class_name = 'Tk' + tk_class
+ # gen_class_name = ruby_class_name + 'GeneratedOnTk'
+ gen_class_name = ruby_class_name
+ classname_def = ''
+ else
+ ruby_class_name = 'TkWindow'
+ # gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk'
+ gen_class_name = 'TkWidget_' + tk_class
+ classname_def = "WidgetClassName = '#{tk_class}'.freeze"
+ end
end
+=end
+
+=begin
unless Object.const_defined? gen_class_name
Object.class_eval "class #{gen_class_name}<#{ruby_class_name}
#{classname_def}
@@ -78,142 +168,365 @@ 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
- def tk_tcl2ruby(val)
- if val =~ /^rb_out (c\d+)/
+ def _at(x,y=nil)
+ if y
+ "@#{Integer(x)},#{Integer(y)}"
+ else
+ "@#{Integer(x)}"
+ end
+ end
+ module_function :_at
+
+ def tk_tcl2ruby(val, enc_mode = false, listobj = true)
+=begin
+ if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
#return Tk_CMDTBL[$1]
return TkCore::INTERP.tk_cmd_tbl[$1]
+ #cmd_obj = TkCore::INTERP.tk_cmd_tbl[$1]
+ #if cmd_obj.kind_of?(Proc) || cmd_obj.kind_of?(Method)
+ # cmd_obj
+ #else
+ # cmd_obj.cmd
+ #end
end
- if val.include? ?\s
- return val.split.collect{|v| tk_tcl2ruby(v)}
+=end
+ if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
+ return TkCore::INTERP.tk_cmd_tbl[$4]
end
+ #if val.include? ?\s
+ # return val.split.collect{|v| tk_tcl2ruby(v)}
+ #end
case val
- when /^@font/
+ when /\A@font\S+\z/
TkFont.get_obj(val)
- when /^-?\d+$/
+ when /\A-?\d+\z/
val.to_i
- when /^\./
+ when /\A\.\S*\z/
#Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
TkCore::INTERP.tk_windows[val]?
TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
- when /^i\d+$/
- TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
- when / /
- val.split.collect{|elt|
- tk_tcl2ruby(elt)
+ when /\Ai(_\d+_)?\d+\z/
+ TkImage::Tk_IMGTBL.mutex.synchronize{
+ TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
}
- when /^-?\d+\.?\d*(e[-+]?\d+)?$/
+ when /\A-?\d+\.?\d*(e[-+]?\d+)?\z/
val.to_f
+ when /\\ /
+ val.gsub(/\\ /, ' ')
+ when /[^\\] /
+ if listobj
+ #tk_split_escstr(val).collect{|elt|
+ # tk_tcl2ruby(elt, enc_mode, listobj)
+ #}
+ val = _toUTF8(val) unless enc_mode
+ tk_split_escstr(val, false, false).collect{|elt|
+ tk_tcl2ruby(elt, true, listobj)
+ }
+ elsif enc_mode
+ _fromUTF8(val)
+ else
+ val
+ end
else
- val
+ if enc_mode
+ _fromUTF8(val)
+ else
+ val
+ end
end
end
- def tk_split_list(str)
+ private :tk_tcl2ruby
+ module_function :tk_tcl2ruby
+ #private_class_method :tk_tcl2ruby
+
+unless const_defined?(:USE_TCLs_LIST_FUNCTIONS)
+ USE_TCLs_LIST_FUNCTIONS = true
+end
+
+if USE_TCLs_LIST_FUNCTIONS
+ ###########################################################################
+ # use Tcl function version of split_list
+ ###########################################################################
+
+ def tk_split_escstr(str, src_enc=true, dst_enc=true)
+ str = _toUTF8(str) if src_enc
+ if dst_enc
+ TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
+ else
+ TkCore::INTERP._split_tklist(str)
+ end
+ end
+
+ def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
+ # return [] if str == ""
+ # list = TkCore::INTERP._split_tklist(str)
+ str = _toUTF8(str) if src_enc
+
+ if depth == 0
+ return "" if str == ""
+ list = [str]
+ else
+ return [] if str == ""
+ list = TkCore::INTERP._split_tklist(str)
+ end
+ if list.size == 1
+ # tk_tcl2ruby(list[0], nil, false)
+ tk_tcl2ruby(list[0], dst_enc, false)
+ else
+ list.collect{|token| tk_split_sublist(token, depth - 1, false, dst_enc)}
+ end
+ end
+
+ def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
return [] if str == ""
- idx = str.index('{')
- while idx and idx > 0 and str[idx-1] == ?\\
- idx = str.index('{', idx+1)
- end
- unless idx
- list = tk_tcl2ruby(str)
- unless Array === list
- list = [list]
- end
- return list
- end
-
- list = tk_tcl2ruby(str[0,idx])
- list = [] if list == ""
- str = str[idx+1..-1]
- i = -1
- brace = 1
- str.each_byte {|c|
- i += 1
- brace += 1 if c == ?{
- brace -= 1 if c == ?}
- break if brace == 0
+ str = _toUTF8(str) if src_enc
+ TkCore::INTERP._split_tklist(str).map!{|token|
+ tk_split_sublist(token, depth - 1, false, dst_enc)
}
- if str.size == i + 1
- return tk_split_list(str[0, i])
+ end
+
+ def tk_split_simplelist(str, src_enc=true, dst_enc=true)
+ #lst = TkCore::INTERP._split_tklist(str)
+ #if (lst.size == 1 && lst =~ /^\{.*\}$/)
+ # TkCore::INTERP._split_tklist(str[1..-2])
+ #else
+ # lst
+ #end
+
+ str = _toUTF8(str) if src_enc
+ if dst_enc
+ TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
+ else
+ TkCore::INTERP._split_tklist(str)
end
- if str[0, i] == ' '
- list.push ' '
+ end
+
+ def array2tk_list(ary, enc=nil)
+ return "" if ary.size == 0
+
+ sys_enc = TkCore::INTERP.encoding
+ sys_enc = TclTkLib.encoding_system unless sys_enc
+
+ dst_enc = (enc == nil)? sys_enc: enc
+
+ dst = ary.collect{|e|
+ if e.kind_of? Array
+ s = array2tk_list(e, enc)
+ elsif e.kind_of? Hash
+ tmp_ary = []
+ #e.each{|k,v| tmp_ary << k << v }
+ e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
+ s = array2tk_list(tmp_ary, enc)
+ else
+ s = _get_eval_string(e, enc)
+ end
+
+ if dst_enc != true && dst_enc != false
+ if (s_enc = s.instance_variable_get(:@encoding))
+ s_enc = s_enc.to_s
+ elsif TkCore::WITH_ENCODING
+ s_enc = s.encoding.name
+ else
+ s_enc = sys_enc
+ end
+ dst_enc = true if s_enc != dst_enc
+ end
+
+ s
+ }
+
+ if sys_enc && dst_enc
+ dst.map!{|s| _toUTF8(s)}
+ ret = TkCore::INTERP._merge_tklist(*dst)
+ if TkCore::WITH_ENCODING
+ if dst_enc.kind_of?(String)
+ ret = _fromUTF8(ret, dst_enc)
+ ret.force_encoding(dst_enc)
+ else
+ ret.force_encoding('utf-8')
+ end
+ else # without encoding
+ if dst_enc.kind_of?(String)
+ ret = _fromUTF8(ret, dst_enc)
+ ret.instance_variable_set(:@encoding, dst_enc)
+ else
+ ret.instance_variable_set(:@encoding, 'utf-8')
+ end
+ end
+ ret
else
- list.push tk_split_list(str[0, i])
+ TkCore::INTERP._merge_tklist(*dst)
end
- list += tk_split_list(str[i+1..-1])
- list
end
- def tk_split_simplelist(str)
+else
+ ###########################################################################
+ # use Ruby script version of split_list (traditional methods)
+ ###########################################################################
+
+ def tk_split_escstr(str, src_enc=true, dst_enc=true)
return [] if str == ""
- idx = str.index('{')
- while idx and idx > 0 and str[idx-1] == ?\\
- idx = str.index('{', idx+1)
- end
- return str.split unless idx
-
- list = str[0,idx].split
- str = str[idx+1..-1]
- i = -1
- brace = 1
- str.each_byte {|c|
- i += 1
- brace += 1 if c == ?{
- brace -= 1 if c == ?}
- break if brace == 0
+ list = []
+ token = nil
+ escape = false
+ brace = 0
+ str.split('').each {|c|
+ brace += 1 if c == '{' && !escape
+ brace -= 1 if c == '}' && !escape
+ if brace == 0 && c == ' ' && !escape
+ list << token.gsub(/^\{(.*)\}$/, '\1') if token
+ token = nil
+ else
+ token = (token || "") << c
+ end
+ escape = (c == '\\' && !escape)
}
- if i == 0
- list.push ''
- elsif str[0, i] == ' '
- list.push ' '
+ list << token.gsub(/^\{(.*)\}$/, '\1') if token
+ list
+ end
+
+ def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
+ #return [] if str == ""
+ #return [tk_split_sublist(str[1..-2])] if str =~ /^\{.*\}$/
+ #list = tk_split_escstr(str)
+ if depth == 0
+ return "" if str == ""
+ str = str[1..-2] if str =~ /^\{.*\}$/
+ list = [str]
else
- list.push str[0..i-1]
+ return [] if str == []
+ return [tk_split_sublist(str[1..-2], depth - 1)] if str =~ /^\{.*\}$/
+ list = tk_split_escstr(str)
+ end
+ if list.size == 1
+ tk_tcl2ruby(list[0], nil, false)
+ else
+ list.collect{|token| tk_split_sublist(token, depth - 1)}
end
- list += tk_split_simplelist(str[i+1..-1])
- list
end
- private :tk_tcl2ruby, :tk_split_list, :tk_split_simplelist
- def _symbolkey2str(keys)
- h = {}
- keys.each{|key,value| h[key.to_s] = value}
- h
+ def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
+ return [] if str == ""
+ tk_split_escstr(str).collect{|token|
+ tk_split_sublist(token, depth - 1)
+ }
end
- private :_symbolkey2str
- def hash_kv(keys)
- conf = []
- if keys and keys != None
- for k, v in keys
- conf.push("-#{k}")
- conf.push(v)
+ def tk_split_simplelist(str, src_enc=true, dst_enc=true)
+ return [] if str == ""
+ list = []
+ token = nil
+ escape = false
+ brace = 0
+ str.split('').each {|c|
+ if c == '\\' && !escape
+ escape = true
+ token = (token || "") << c if brace > 0
+ next
+ end
+ brace += 1 if c == '{' && !escape
+ brace -= 1 if c == '}' && !escape
+ if brace == 0 && c == ' ' && !escape
+ list << token.gsub(/^\{(.*)\}$/, '\1') if token
+ token = nil
+ else
+ token = (token || "") << c
end
- end
- conf
+ escape = false
+ }
+ list << token.gsub(/^\{(.*)\}$/, '\1') if token
+ list
end
- private :hash_kv
- module_function :hash_kv
- def array2tk_list(ary)
+ def array2tk_list(ary, enc=nil)
ary.collect{|e|
if e.kind_of? Array
- "{#{array2tk_list(e)}}"
+ "{#{array2tk_list(e, enc)}}"
elsif e.kind_of? Hash
- "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}"
+ # "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}"
+ e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
+ array2tk_list(tmp_ary, enc)
else
- s = _get_eval_string(e)
- (s.index(/\s/) || s.size == 0)? "{#{s}}": s
+ s = _get_eval_string(e, enc)
+ (s.index(/\s/) || s.size == 0)? "{#{s}}": s
end
}.join(" ")
end
+end
+
+ private :tk_split_escstr, :tk_split_sublist
+ private :tk_split_list, :tk_split_simplelist
private :array2tk_list
+
+ module_function :tk_split_escstr, :tk_split_sublist
+ module_function :tk_split_list, :tk_split_simplelist
module_function :array2tk_list
+ private_class_method :tk_split_escstr, :tk_split_sublist
+ private_class_method :tk_split_list, :tk_split_simplelist
+# private_class_method :array2tk_list
+
+=begin
+ ### --> definition is moved to TkUtil module
+ def _symbolkey2str(keys)
+ h = {}
+ keys.each{|key,value| h[key.to_s] = value}
+ h
+ end
+ private :_symbolkey2str
+ module_function :_symbolkey2str
+=end
+
+=begin
+ ### --> definition is moved to TkUtil module
+ # def hash_kv(keys, enc_mode = nil, conf = [], flat = false)
+ def hash_kv(keys, enc_mode = nil, conf = nil)
+ # Hash {key=>val, key=>val, ... } or Array [ [key, val], [key, val], ... ]
+ # ==> Array ['-key', val, '-key', val, ... ]
+ dst = []
+ if keys and keys != None
+ keys.each{|k, v|
+ #dst.push("-#{k}")
+ dst.push('-' + k.to_s)
+ if v != None
+ # v = _get_eval_string(v, enc_mode) if (enc_mode || flat)
+ v = _get_eval_string(v, enc_mode) if enc_mode
+ dst.push(v)
+ end
+ }
+ end
+ if conf
+ conf + dst
+ else
+ dst
+ end
+ end
+ private :hash_kv
+ module_function :hash_kv
+=end
+
+=begin
+ ### --> definition is moved to TkUtil module
def bool(val)
case val
when "1", 1, 'yes', 'true'
@@ -222,6 +535,7 @@ module TkComm
false
end
end
+
def number(val)
case val
when /^-?\d+$/
@@ -229,24 +543,32 @@ module TkComm
when /^-?\d+\.?\d*(e[-+]?\d+)?$/
val.to_f
else
- fail(ArgumentError,
- Kernel.format('invalid value for Number:"%s"', val.to_s))
+ fail(ArgumentError, "invalid value for Number:'#{val}'")
end
end
def string(val)
if val == "{}"
''
- elsif val[0] == ?{
+ elsif val[0] == ?{ && val[-1] == ?}
val[1..-2]
else
val
end
end
- def list(val)
- tk_split_list(val)
+ def num_or_str(val)
+ begin
+ number(val)
+ rescue ArgumentError
+ string(val)
+ end
end
- def simplelist(val)
- tk_split_simplelist(val)
+=end
+
+ def list(val, depth=0, enc=true)
+ tk_split_list(val, depth, enc, enc)
+ end
+ def simplelist(val, src_enc=true, dst_enc=true)
+ tk_split_simplelist(val, src_enc, dst_enc)
end
def window(val)
if val =~ /^\./
@@ -257,30 +579,80 @@ module TkComm
nil
end
end
+ def image_obj(val)
+ if val =~ /^i(_\d+_)?\d+$/
+ TkImage::Tk_IMGTBL.mutex.synchronize{
+ TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ }
+ else
+ val
+ end
+ end
def procedure(val)
- if val =~ /^rb_out (c\d+)/
+=begin
+ if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
#Tk_CMDTBL[$1]
#TkCore::INTERP.tk_cmd_tbl[$1]
TkCore::INTERP.tk_cmd_tbl[$1].cmd
+=end
+ if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
+ return TkCore::INTERP.tk_cmd_tbl[$4].cmd
else
#nil
val
end
end
- private :bool, :number, :string, :list, :simplelist, :window, :procedure
- module_function :bool, :number, :string, :list, :simplelist
- module_function :window, :procedure
+ private :bool, :number, :string, :num_or_str
+ private :list, :simplelist, :window, :procedure
+ module_function :bool, :number, :num_or_str, :string
+ module_function :list, :simplelist, :window, :image_obj, :procedure
+
+ def subst(str, *opts)
+ # opts := :nobackslashes | :nocommands | novariables
+ tk_call('subst',
+ *(opts.collect{|opt|
+ opt = opt.to_s
+ (opt[0] == ?-)? opt: '-' << opt
+ } << str))
+ end
- def _get_eval_string(str)
+ def _toUTF8(str, encoding = nil)
+ TkCore::INTERP._toUTF8(str, encoding)
+ end
+ def _fromUTF8(str, encoding = nil)
+ TkCore::INTERP._fromUTF8(str, encoding)
+ end
+ private :_toUTF8, :_fromUTF8
+ module_function :_toUTF8, :_fromUTF8
+
+ def _callback_entry_class?(cls)
+ cls <= Proc || cls <= Method || cls <= TkCallbackEntry
+ end
+ private :_callback_entry_class?
+ module_function :_callback_entry_class?
+
+ def _callback_entry?(obj)
+ obj.kind_of?(Proc) || obj.kind_of?(Method) || obj.kind_of?(TkCallbackEntry)
+ end
+ private :_callback_entry?
+ module_function :_callback_entry?
+
+=begin
+ ### --> definition is moved to TkUtil module
+ def _get_eval_string(str, enc_mode = nil)
return nil if str == None
- if str.kind_of?(String)
- # do nothing
+ if str.kind_of?(TkObject)
+ str = str.path
+ elsif str.kind_of?(String)
+ str = _toUTF8(str) if enc_mode
elsif str.kind_of?(Symbol)
str = str.id2name
+ str = _toUTF8(str) if enc_mode
elsif str.kind_of?(Hash)
- str = hash_kv(str).join(" ")
+ str = hash_kv(str, enc_mode).join(" ")
elsif str.kind_of?(Array)
str = array2tk_list(str)
+ str = _toUTF8(str) if enc_mode
elsif str.kind_of?(Proc)
str = install_cmd(str)
elsif str == nil
@@ -291,60 +663,179 @@ module TkComm
str = "1"
elsif (str.respond_to?(:to_eval))
str = str.to_eval()
+ str = _toUTF8(str) if enc_mode
else
str = str.to_s() || ''
unless str.kind_of? String
- fail RuntimeError, "fail to convert the object to a string"
+ fail RuntimeError, "fail to convert the object to a string"
end
- str
+ str = _toUTF8(str) if enc_mode
end
return str
end
+=end
+=begin
+ def _get_eval_string(obj, enc_mode = nil)
+ case obj
+ when Numeric
+ obj.to_s
+ when String
+ (enc_mode)? _toUTF8(obj): obj
+ when Symbol
+ (enc_mode)? _toUTF8(obj.id2name): obj.id2name
+ when TkObject
+ obj.path
+ when Hash
+ hash_kv(obj, enc_mode).join(' ')
+ when Array
+ (enc_mode)? _toUTF8(array2tk_list(obj)): array2tk_list(obj)
+ when Proc, Method, TkCallbackEntry
+ install_cmd(obj)
+ when false
+ '0'
+ when true
+ '1'
+ when nil
+ ''
+ when None
+ nil
+ else
+ if (obj.respond_to?(:to_eval))
+ (enc_mode)? _toUTF8(obj.to_eval): obj.to_eval
+ else
+ begin
+ obj = obj.to_s || ''
+ rescue
+ fail RuntimeError, "fail to convert object '#{obj}' to string"
+ end
+ (enc_mode)? _toUTF8(obj): obj
+ end
+ end
+ end
private :_get_eval_string
module_function :_get_eval_string
+=end
+
+=begin
+ ### --> definition is moved to TkUtil module
+ def _get_eval_enc_str(obj)
+ return obj if obj == None
+ _get_eval_string(obj, true)
+ end
+ private :_get_eval_enc_str
+ module_function :_get_eval_enc_str
+=end
- def ruby2tcl(v)
+=begin
+ ### --> obsolete
+ def ruby2tcl(v, enc_mode = nil)
if v.kind_of?(Hash)
v = hash_kv(v)
v.flatten!
- v.collect{|e|ruby2tcl(e)}
+ v.collect{|e|ruby2tcl(e, enc_mode)}
else
- _get_eval_string(v)
+ _get_eval_string(v, enc_mode)
end
end
private :ruby2tcl
+=end
+
+=begin
+ ### --> definition is moved to TkUtil module
+ def _conv_args(args, enc_mode, *src_args)
+ conv_args = []
+ src_args.each{|arg|
+ conv_args << _get_eval_string(arg, enc_mode) unless arg == None
+ # if arg.kind_of?(Hash)
+ # arg.each{|k, v|
+ # args << '-' + k.to_s
+ # args << _get_eval_string(v, enc_mode)
+ # }
+ # elsif arg != None
+ # args << _get_eval_string(arg, enc_mode)
+ # end
+ }
+ args + conv_args
+ end
+ private :_conv_args
+=end
def _curr_cmd_id
#id = format("c%.4d", Tk_IDs[0])
- id = "c" + TkComm::Tk_IDs[0]
+ id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0]
end
def _next_cmd_id
- id = _curr_cmd_id
- #Tk_IDs[0] += 1
- TkComm::Tk_IDs[0].succ!
- id
+ TkComm::Tk_IDs.mutex.synchronize{
+ id = _curr_cmd_id
+ #Tk_IDs[0] += 1
+ TkComm::Tk_IDs[0].succ!
+ id
+ }
end
private :_curr_cmd_id, :_next_cmd_id
module_function :_curr_cmd_id, :_next_cmd_id
- def install_cmd(cmd)
+ def TkComm.install_cmd(cmd, local_cmdtbl=nil)
return '' if cmd == ''
+ begin
+ ns = TkCore::INTERP._invoke_without_enc('namespace', 'current')
+ ns = nil if ns == '::' # for backward compatibility
+ rescue
+ # probably, Tcl7.6
+ ns = nil
+ end
id = _next_cmd_id
#Tk_CMDTBL[id] = cmd
- TkCore::INTERP.tk_cmd_tbl[id] = TkCore::INTERP.get_cb_entry(cmd)
+ if cmd.kind_of?(TkCallbackEntry)
+ TkCore::INTERP.tk_cmd_tbl[id] = cmd
+ else
+ TkCore::INTERP.tk_cmd_tbl[id] = TkCore::INTERP.get_cb_entry(cmd)
+ end
@cmdtbl = [] unless defined? @cmdtbl
@cmdtbl.taint unless @cmdtbl.tainted?
@cmdtbl.push id
- return Kernel.format("rb_out %s", id);
+
+ if local_cmdtbl && local_cmdtbl.kind_of?(Array)
+ begin
+ local_cmdtbl << id
+ rescue Exception
+ # ignore
+ end
+ end
+
+ #return Kernel.format("rb_out %s", id);
+ if ns
+ 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id
+ else
+ 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id
+ end
end
- def uninstall_cmd(id)
- id = $1 if /rb_out (c\d+)/ =~ id
+ def TkComm.uninstall_cmd(id, local_cmdtbl=nil)
+ #id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id
+ id = $4 if id =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
+
+ if local_cmdtbl && local_cmdtbl.kind_of?(Array)
+ begin
+ local_cmdtbl.delete(id)
+ rescue Exception
+ # ignore
+ end
+ end
+ @cmdtbl.delete(id)
+
#Tk_CMDTBL.delete(id)
TkCore::INTERP.tk_cmd_tbl.delete(id)
end
- private :install_cmd, :uninstall_cmd
- module_function :install_cmd
+ # private :install_cmd, :uninstall_cmd
+ # module_function :install_cmd, :uninstall_cmd
+ def install_cmd(cmd)
+ TkComm.install_cmd(cmd, @cmdtbl)
+ end
+ def uninstall_cmd(id)
+ TkComm.uninstall_cmd(id, @cmdtbl)
+ end
+=begin
def install_win(ppath,name=nil)
if !name or name == ''
#name = format("w%.4d", Tk_IDs[1])
@@ -362,6 +853,31 @@ module TkComm
#Tk_WINDOWS[@path] = self
TkCore::INTERP.tk_windows[@path] = self
end
+=end
+ def install_win(ppath,name=nil)
+ if name
+ if name == ''
+ raise ArgumentError, "invalid wiget-name '#{name}'"
+ end
+ if name[0] == ?.
+ @path = '' + name
+ @path.freeze
+ return TkCore::INTERP.tk_windows[@path] = self
+ end
+ else
+ Tk_IDs.mutex.synchronize{
+ name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
+ Tk_IDs[1].succ!
+ }
+ end
+ if !ppath or ppath == '.'
+ @path = '.' + name
+ else
+ @path = ppath + '.' + name
+ end
+ @path.freeze
+ TkCore::INTERP.tk_windows[@path] = self
+ end
def uninstall_win()
#Tk_WINDOWS.delete(@path)
@@ -369,163 +885,22 @@ module TkComm
end
private :install_win, :uninstall_win
- class Event
- module TypeNum
- KeyPress = 2
- KeyRelease = 3
- ButtonPress = 4
- ButtonRelease = 5
- MotionNotify = 6
- EnterNotify = 7
- LeaveNotify = 8
- FocusIn = 9
- FocusOut = 10
- KeymapNotify = 11
- Expose = 12
- GraphicsExpose = 13
- NoExpose = 14
- VisibilityNotify = 15
- CreateNotify = 16
- DestroyNotify = 17
- UnmapNotify = 18
- MapNotify = 19
- MapRequest = 20
- ReparentNotify = 21
- ConfigureNotify = 22
- ConfigureRequest = 23
- GravityNotify = 24
- ResizeRequest = 25
- CirculateNotify = 26
- CirculateRequest = 27
- PropertyNotify = 28
- SelectionClear = 29
- SelectionRequest = 30
- SelectionNotify = 31
- ColormapNotify = 32
- ClientMessage = 33
- MappingNotify = 34
- end
-
- EV_KEY = '#abcdfhikmopstwxyABDEKNRSTWXY'
- EV_TYPE = 'nsnnsbnsnsbsxnnnnsnnbsnssnwnn'
-
- def self.scan_args(arg_str, arg_val)
- arg_cnv = []
- arg_str.strip.split(/\s+/).each_with_index{|kwd,idx|
- if kwd =~ /^%(.)$/
- if num = EV_KEY.index($1)
- case EV_TYPE[num]
- when ?n
- begin
- val = TkComm::number(arg_val[idx])
- rescue ArgumentError
- # ignore --> no convert
- val = TkComm::string(arg_val[idx])
- end
- arg_cnv << val
- when ?s
- arg_cnv << TkComm::string(arg_val[idx])
- when ?b
- arg_cnv << TkComm::bool(arg_val[idx])
- when ?w
- arg_cnv << TkComm::window(arg_val[idx])
- when ?x
- begin
- arg_cnv << TkComm::number(arg_val[idx])
- rescue ArgumentError
- arg_cnv << arg_val[idx]
- end
- else
- arg_cnv << arg_val[idx]
- end
- else
- arg_cnv << arg_val[idx]
- end
- else
- arg_cnv << arg_val[idx]
- end
- }
- arg_cnv
- end
-
- def initialize(seq,a,b,c,d,f,h,i,k,m,o,p,s,t,w,x,y,
- aa,bb,dd,ee,kk,nn,rr,ss,tt,ww,xx,yy)
- @serial = seq
- @above = a
- @num = b
- @count = c
- @detail = d
- @focus = f
- @height = h
- @win_hex = i
- @keycode = k
- @mode = m
- @override = o
- @place = p
- @state = s
- @time = t
- @width = w
- @x = x
- @y = y
- @char = aa
- @borderwidth = bb
- @wheel_delta = dd
- @send_event = ee
- @keysym = kk
- @keysym_num = nn
- @rootwin_id = rr
- @subwindow = ss
- @type = tt
- @widget = ww
- @x_root = xx
- @y_root = yy
- end
- attr :serial
- attr :above
- attr :num
- attr :count
- attr :detail
- attr :focus
- attr :height
- attr :win_hex
- attr :keycode
- attr :mode
- attr :override
- attr :place
- attr :state
- attr :time
- attr :width
- attr :x
- attr :y
- attr :char
- attr :borderwidth
- attr :wheel_delta
- attr :send_event
- attr :keysym
- attr :keysym_num
- attr :rootwin_id
- attr :subwindow
- attr :type
- attr :widget
- attr :x_root
- attr :y_root
- end
-
- def install_bind(cmd, args=nil)
- if args
- id = install_cmd(proc{|*arg|
- TkUtil.eval_cmd(cmd, *Event.scan_args(args, arg))
- })
- id + " " + args
+ def _epath(win)
+ if win.kind_of?(TkObject)
+ win.epath
+ elsif win.respond_to?(:epath)
+ win.epath
else
- args = ' %# %a %b %c %d %f %h %i %k %m %o %p %s %t %w %x %y' +
- ' %A %B %D %E %K %N %R %S %T %W %X %Y'
- id = install_cmd(proc{|*arg|
- TkUtil.eval_cmd(cmd, Event.new(*Event.scan_args(args, arg)))
- })
- id + args
+ win
end
end
+ private :_epath
+end
+
+# define TkComm module (step 2: event binding)
+module TkComm
+ include TkEvent
+ extend TkEvent
def tk_event_sequence(context)
if context.kind_of? TkVirtualEvent
@@ -533,11 +908,11 @@ module TkComm
end
if context.kind_of? Array
context = context.collect{|ev|
- if ev.kind_of? TkVirtualEvent
- ev.path
- else
- ev
- end
+ if ev.kind_of? TkVirtualEvent
+ ev.path
+ else
+ ev
+ end
}.join("><")
end
if /,/ =~ context
@@ -547,64 +922,125 @@ module TkComm
end
end
- def _bind_core(mode, what, context, cmd, args=nil)
- id = install_bind(cmd, args) if cmd
+ def _bind_core(mode, what, context, cmd, *args)
+ id = install_bind(cmd, *args) if cmd
begin
- tk_call(*(what + ["<#{tk_event_sequence(context)}>", mode + id]))
+ tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
+ mode + id]))
rescue
uninstall_cmd(id) if cmd
fail
end
end
- def _bind(what, context, cmd, args=nil)
- _bind_core('', what, context, cmd, args)
+ def _bind(what, context, cmd, *args)
+ _bind_core('', what, context, cmd, *args)
end
- def _bind_append(what, context, cmd, args=nil)
- _bind_core('+', what, context, cmd, args)
+ def _bind_append(what, context, cmd, *args)
+ _bind_core('+', what, context, cmd, *args)
end
def _bind_remove(what, context)
- tk_call(*(what + ["<#{tk_event_sequence(context)}>", '']))
+ tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", '']))
end
def _bindinfo(what, context=nil)
if context
- tk_call(*what+["<#{tk_event_sequence(context)}>"]).collect {|cmdline|
- if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
- #[Tk_CMDTBL[$1], $2]
- [TkCore::INTERP.tk_cmd_tbl[$1], $2]
- else
- cmdline
- end
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]).each_line
+ else
+ enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"])
+ end
+ enum_obj.collect {|cmdline|
+=begin
+ if cmdline =~ /^rb_out\S* (c(?:_\d+_)?\d+)\s+(.*)$/
+ #[Tk_CMDTBL[$1], $2]
+ [TkCore::INTERP.tk_cmd_tbl[$1], $2]
+=end
+ if cmdline =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
+ [TkCore::INTERP.tk_cmd_tbl[$4], $5]
+ else
+ cmdline
+ end
}
else
- tk_split_simplelist(tk_call(*what)).collect!{|seq|
- l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
- case (subseq)
- when /^<<[^<>]+>>$/
- TkVirtualEvent.getobj(subseq[1..-2])
- when /^<[^<>]+>$/
- subseq[1..-2]
- else
- subseq.split('')
- end
- }.flatten
- (l.size == 1) ? l[0] : l
+ tk_split_simplelist(tk_call_without_enc(*what)).collect!{|seq|
+ l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
+ case (subseq)
+ when /^<<[^<>]+>>$/
+ TkVirtualEvent.getobj(subseq[1..-2])
+ when /^<[^<>]+>$/
+ subseq[1..-2]
+ else
+ subseq.split('')
+ end
+ }.flatten
+ (l.size == 1) ? l[0] : l
}
end
end
- private :install_bind, :tk_event_sequence,
- :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo
- def bind(tagOrClass, context, cmd=Proc.new, args=nil)
- _bind(["bind", tagOrClass], context, cmd, args)
+ def _bind_core_for_event_class(klass, mode, what, context, cmd, *args)
+ id = install_bind_for_event_class(klass, cmd, *args) if cmd
+ begin
+ tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
+ mode + id]))
+ rescue
+ uninstall_cmd(id) if cmd
+ fail
+ end
+ end
+
+ def _bind_for_event_class(klass, what, context, cmd, *args)
+ _bind_core_for_event_class(klass, '', what, context, cmd, *args)
+ end
+
+ def _bind_append_for_event_class(klass, what, context, cmd, *args)
+ _bind_core_for_event_class(klass, '+', what, context, cmd, *args)
+ end
+
+ def _bind_remove_for_event_class(klass, what, context)
+ _bind_remove(what, context)
+ end
+
+ def _bindinfo_for_event_class(klass, what, context=nil)
+ _bindinfo(what, context)
+ end
+
+ private :tk_event_sequence
+ private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo
+ private :_bind_core_for_event_class, :_bind_for_event_class,
+ :_bind_append_for_event_class, :_bind_remove_for_event_class,
+ :_bindinfo_for_event_class
+
+ #def bind(tagOrClass, context, cmd=Proc.new, *args)
+ # _bind(["bind", tagOrClass], context, cmd, *args)
+ # tagOrClass
+ #end
+ def bind(tagOrClass, context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind(["bind", tagOrClass], context, cmd, *args)
tagOrClass
end
- def bind_append(tagOrClass, context, cmd=Proc.new, args=nil)
- _bind_append(["bind", tagOrClass], context, cmd, args)
+ #def bind_append(tagOrClass, context, cmd=Proc.new, *args)
+ # _bind_append(["bind", tagOrClass], context, cmd, *args)
+ # tagOrClass
+ #end
+ def bind_append(tagOrClass, context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append(["bind", tagOrClass], context, cmd, *args)
tagOrClass
end
@@ -617,13 +1053,33 @@ module TkComm
_bindinfo(['bind', tagOrClass], context)
end
- def bind_all(context, cmd=Proc.new, args=nil)
- _bind(['bind', 'all'], context, cmd, args)
+ #def bind_all(context, cmd=Proc.new, *args)
+ # _bind(['bind', 'all'], context, cmd, *args)
+ # TkBindTag::ALL
+ #end
+ def bind_all(context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind(['bind', 'all'], context, cmd, *args)
TkBindTag::ALL
end
- def bind_append_all(context, cmd=Proc.new, args=nil)
- _bind_append(['bind', 'all'], context, cmd, args)
+ #def bind_append_all(context, cmd=Proc.new, *args)
+ # _bind_append(['bind', 'all'], context, cmd, *args)
+ # TkBindTag::ALL
+ #end
+ def bind_append_all(context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append(['bind', 'all'], context, cmd, *args)
TkBindTag::ALL
end
@@ -635,53 +1091,88 @@ module TkComm
def bindinfo_all(context=nil)
_bindinfo(['bind', 'all'], context)
end
-
- def pack(*args)
- TkPack.configure(*args)
- end
-
- def grid(*args)
- TkGrid.configure(*args)
- end
-
- def update(idle=nil)
- if idle
- tk_call 'update', 'idletasks'
- else
- tk_call 'update'
- end
- end
-
end
+
module TkCore
include TkComm
extend TkComm
+ WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class
+ WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class
+
+ unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
+ ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!!
+ RUN_EVENTLOOP_ON_MAIN_THREAD = false
+ end
+
unless self.const_defined? :INTERP
if self.const_defined? :IP_NAME
name = IP_NAME.to_s
else
- name = nil
+ #name = nil
+ name = $0
end
if self.const_defined? :IP_OPTS
if IP_OPTS.kind_of?(Hash)
- opts = hash_kv(IP_OPTS).join(' ')
+ opts = hash_kv(IP_OPTS).join(' ')
else
- opts = IP_OPTS.to_s
+ opts = IP_OPTS.to_s
end
else
opts = ''
end
- INTERP = TclTkIp.new(name, opts)
+ if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
+ INTERP = TclTkIp.new(name, opts)
+ else
+ INTERP_MUTEX = Mutex.new
+ INTERP_ROOT_CHECK = ConditionVariable.new
+ INTERP_THREAD = Thread.new{
+ begin
+ Thread.current[:interp] = interp = TclTkIp.new(name, opts)
+ rescue => e
+ Thread.current[:interp] = e
+ raise e
+ end
+ Thread.current[:status] = nil
+ #sleep
+
+ begin
+ Thread.current[:status] = TclTkLib.mainloop(true)
+ rescue Exception=>e
+ Thread.current[:status] = e
+ ensure
+ INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast }
+ end
+ Thread.current[:status] = TclTkLib.mainloop(false)
+ }
+
+ until INTERP_THREAD[:interp]
+ Thread.pass
+ end
+ # INTERP_THREAD.run
+ raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception
+
+ INTERP = INTERP_THREAD[:interp]
+ end
def INTERP.__getip
self
end
INTERP.instance_eval{
- @tk_cmd_tbl = {}.taint
+ # @tk_cmd_tbl = {}.taint
+ @tk_cmd_tbl = Hash.new{|hash, key|
+ fail IndexError, "unknown command ID '#{key}'"
+ }.taint
+ def @tk_cmd_tbl.[]=(idx,val)
+ if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
+ fail SecurityError,"cannot change the entried command"
+ end
+ super(idx,val)
+ end
+
@tk_windows = {}.taint
@tk_table_list = [].taint
@@ -689,18 +1180,32 @@ module TkCore
@init_ip_env = [].taint # table of Procs
@add_tk_procs = [].taint # table of [name, args, body]
- @cb_entry_class = Class.new{|c|
- def initialize(ip, cmd)
- @ip = ip
- @cmd = cmd
- end
- attr_reader :ip, :cmd
- def call(*args)
- @ip.cb_eval(@cmd, *args)
- end
- }
+ @cb_entry_class = Class.new(TkCallbackEntry){
+ class << self
+ def inspect
+ sprintf("#<Class(TkCallbackEntry):%0x>", self.__id__)
+ end
+ alias to_s inspect
+ end
+
+ def initialize(ip, cmd)
+ @ip = ip
+ @cmd = cmd
+ end
+ attr_reader :ip, :cmd
+ def call(*args)
+ @ip.cb_eval(@cmd, *args)
+ end
+ def inspect
+ sprintf("#<cb_entry:%0x>", self.__id__)
+ end
+ alias to_s inspect
+ }.freeze
}
+ def INTERP.cb_entry_class
+ @cb_entry_class
+ end
def INTERP.tk_cmd_tbl
@tk_cmd_tbl
end
@@ -708,6 +1213,19 @@ module TkCore
@tk_windows
end
+ class Tk_OBJECT_TABLE
+ def initialize(id)
+ @id = id
+ @mutex = Mutex.new
+ end
+ def mutex
+ @mutex
+ end
+ def method_missing(m, *args, &b)
+ TkCore::INTERP.tk_object_table(@id).__send__(m, *args, &b)
+ end
+ end
+
def INTERP.tk_object_table(id)
@tk_table_list[id]
end
@@ -715,20 +1233,21 @@ module TkCore
id = @tk_table_list.size
(tbl = {}).tainted? || tbl.taint
@tk_table_list << tbl
- obj = Object.new
- obj.instance_eval <<-EOD
- def self.method_missing(m, *args)
- TkCore::INTERP.tk_object_table(#{id}).send(m, *args)
- end
- EOD
- return obj
+# obj = Object.new
+# obj.instance_eval <<-EOD
+# def self.method_missing(m, *args)
+# TkCore::INTERP.tk_object_table(#{id}).send(m, *args)
+# end
+# EOD
+# return obj
+ Tk_OBJECT_TABLE.new(id)
end
def INTERP.get_cb_entry(cmd)
@cb_entry_class.new(__getip, cmd).freeze
end
def INTERP.cb_eval(cmd, *args)
- TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args))
+ TkUtil._get_eval_string(TkUtil.eval_cmd(cmd, *args))
end
def INTERP.init_ip_env(script = Proc.new)
@@ -736,8 +1255,22 @@ module TkCore
script.call(self)
end
def INTERP.add_tk_procs(name, args = nil, body = nil)
- @add_tk_procs << [name, args, body]
- self._invoke('proc', name, args, body) if args && body
+ if name.kind_of?(Array)
+ name.each{|param| self.add_tk_procs(*param)}
+ else
+ name = name.to_s
+ @add_tk_procs << [name, args, body]
+ self._invoke('proc', name, args, body) if args && body
+ end
+ end
+ def INTERP.remove_tk_procs(*names)
+ names.each{|name|
+ name = name.to_s
+ @add_tk_procs.delete_if{|elem|
+ elem.kind_of?(Array) && elem[0].to_s == name
+ }
+ self._invoke('rename', name, '')
+ }
end
def INTERP.init_ip_internal
ip = self
@@ -746,15 +1279,90 @@ module TkCore
end
end
+ WIDGET_DESTROY_HOOK = '<WIDGET_DESTROY_HOOK>'
+ INTERP._invoke_without_enc('event', 'add',
+ "<#{WIDGET_DESTROY_HOOK}>", '<Destroy>')
+ INTERP._invoke_without_enc('bind', 'all', "<#{WIDGET_DESTROY_HOOK}>",
+ install_cmd(proc{|path|
+ unless TkCore::INTERP.deleted?
+ begin
+ if (widget=TkCore::INTERP.tk_windows[path])
+ if widget.respond_to?(:__destroy_hook__)
+ widget.__destroy_hook__
+ end
+ end
+ rescue Exception=>e
+ p e if $DEBUG
+ end
+ end
+ }) << ' %W')
+
+ INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '',
+ "catch { bind all <#{WIDGET_DESTROY_HOOK}> {} }")
+
+ INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL')
+ if [regexp {^::} $ns] {
+ set cmd {namespace eval $ns {ruby_cmd TkCore callback} $args}
+ } else {
+ set cmd {eval {ruby_cmd TkCore callback} $ns $args}
+ }
+ if {[set st [catch $cmd ret]] != 0} {
+ #return -code $st $ret
+ set idx [string first "\n\n" $ret]
+ if {$idx > 0} {
+ return -code $st \
+ -errorinfo [string range $ret [expr $idx + 2] \
+ [string length $ret]] \
+ [string range $ret 0 [expr $idx - 1]]
+ } else {
+ return -code $st $ret
+ }
+ } else {
+ return $ret
+ }
+ EOL
+=begin
INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
- regsub -all {!} $args {\\!} args
- regsub -all "{" $args "\\{" args
+ if {[set st [catch {eval {ruby_cmd TkCore callback} $args} ret]] != 0} {
+ #return -code $st $ret
+ set idx [string first "\n\n" $ret]
+ if {$idx > 0} {
+ return -code $st \
+ -errorinfo [string range $ret [expr $idx + 2] \
+ [string length $ret]] \
+ [string range $ret 0 [expr $idx - 1]]
+ } else {
+ return -code $st $ret
+ }
+ } else {
+ return $ret
+ }
+ EOL
+=end
+=begin
+ INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
+ #regsub -all {\\} $args {\\\\} args
+ #regsub -all {!} $args {\\!} args
+ #regsub -all "{" $args "\\{" args
+ regsub -all {(\\|!|\{|\})} $args {\\\1} args
if {[set st [catch {ruby [format "TkCore.callback %%Q!%s!" $args]} ret]] != 0} {
- return -code $st $ret
- } {
- return $ret
+ #return -code $st $ret
+ set idx [string first "\n\n" $ret]
+ if {$idx > 0} {
+ return -code $st \
+ -errorinfo [string range $ret [expr $idx + 2] \
+ [string length $ret]] \
+ [string range $ret 0 [expr $idx - 1]]
+ } else {
+ return -code $st $ret
+ }
+ } else {
+ return $ret
}
EOL
+=end
+
+ at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) }
EventFlag = TclTkLib::EventFlag
@@ -766,128 +1374,207 @@ module TkCore
fail TkCallbackContinue, "Tk callback returns 'continue' status"
end
- def TkCore.callback(arg)
- # arg = tk_split_list(arg)
- arg = tk_split_simplelist(arg)
- #_get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg))
- #_get_eval_string(TkUtil.eval_cmd(TkCore::INTERP.tk_cmd_tbl[arg.shift],
- # *arg))
- cb_obj = TkCore::INTERP.tk_cmd_tbl[arg.shift]
- unless $DEBUG
- cb_obj.call(*arg)
- else
- begin
- raise 'check backtrace'
- rescue
- # ignore backtrace before 'callback'
- pos = -($!.backtrace.size)
+ def callback_return
+ fail TkCallbackReturn, "Tk callback returns 'return' status"
+ end
+
+ def TkCore.callback(*arg)
+ begin
+ if TkCore::INTERP.tk_cmd_tbl.kind_of?(Hash)
+ #TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
+ normal_ret = false
+ ret = catch(:IRB_EXIT) do # IRB hack
+ retval = TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
+ normal_ret = true
+ retval
+ end
+ unless normal_ret
+ # catch IRB_EXIT
+ exit(ret)
+ end
+ ret
end
+ rescue SystemExit=>e
+ exit(e.status)
+ rescue Interrupt=>e
+ fail(e)
+ rescue Exception => e
begin
- cb_obj.call(*arg)
- rescue
- trace = $!.backtrace
- raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" +
- "\tfrom #{trace[1..pos].join("\n\tfrom ")}"
+ msg = _toUTF8(e.class.inspect) + ': ' +
+ _toUTF8(e.message) + "\n" +
+ "\n---< backtrace of Ruby side >-----\n" +
+ _toUTF8(e.backtrace.join("\n")) +
+ "\n---< backtrace of Tk side >-------"
+ if TkCore::WITH_ENCODING
+ msg.force_encoding('utf-8')
+ else
+ msg.instance_variable_set(:@encoding, 'utf-8')
+ end
+ rescue Exception
+ msg = e.class.inspect + ': ' + e.message + "\n" +
+ "\n---< backtrace of Ruby side >-----\n" +
+ e.backtrace.join("\n") +
+ "\n---< backtrace of Tk side >-------"
end
+ # TkCore::INTERP._set_global_var('errorInfo', msg)
+ # fail(e)
+ fail(e, msg)
end
end
+=begin
+ def TkCore.callback(arg_str)
+ # arg = tk_split_list(arg_str)
+ arg = tk_split_simplelist(arg_str)
+ #_get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg))
+ #_get_eval_string(TkUtil.eval_cmd(TkCore::INTERP.tk_cmd_tbl[arg.shift],
+ # *arg))
+ # TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
+ begin
+ TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
+ rescue Exception => e
+ raise(e, e.class.inspect + ': ' + e.message + "\n" +
+ "\n---< backtrace of Ruby side >-----\n" +
+ e.backtrace.join("\n") +
+ "\n---< backtrace of Tk side >-------")
+ end
+#=begin
+# cb_obj = TkCore::INTERP.tk_cmd_tbl[arg.shift]
+# unless $DEBUG
+# cb_obj.call(*arg)
+# else
+# begin
+# raise 'check backtrace'
+# rescue
+# # ignore backtrace before 'callback'
+# pos = -($!.backtrace.size)
+# end
+# begin
+# cb_obj.call(*arg)
+# rescue
+# trace = $!.backtrace
+# raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" +
+# "\tfrom #{trace[1..pos].join("\n\tfrom ")}"
+# end
+# end
+#=end
+ end
+=end
def load_cmd_on_ip(tk_cmd)
bool(tk_call('auto_load', tk_cmd))
end
def after(ms, cmd=Proc.new)
+ cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret})
+ after_id = tk_call_without_enc("after",ms,cmdid)
+ after_id.instance_variable_set('@cmdid', cmdid)
+ after_id
+ end
+=begin
+ def after(ms, cmd=Proc.new)
+ crit_bup = Thread.critical
+ Thread.critical = true
+
myid = _curr_cmd_id
- cmdid = install_cmd(cmd)
- tk_call("after",ms,cmdid)
+ cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
+
+ Thread.critical = crit_bup
+
+ tk_call_without_enc("after",ms,cmdid) # return id
# return
# if false #defined? Thread
# Thread.start do
-# ms = Float(ms)/1000
-# ms = 10 if ms == 0
-# sleep ms/1000
-# cmd.call
+# ms = Float(ms)/1000
+# ms = 10 if ms == 0
+# sleep ms/1000
+# cmd.call
# end
# else
# cmdid = install_cmd(cmd)
# tk_call("after",ms,cmdid)
# end
end
+=end
def after_idle(cmd=Proc.new)
- myid = _curr_cmd_id
- cmdid = install_cmd(cmd)
- tk_call('after','idle',cmdid)
- end
-
- def clock_clicks(ms=nil)
- if ms
- tk_call('clock','clicks','-milliseconds').to_i
- else
- tk_call('clock','clicks').to_i
- end
+ cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret})
+ after_id = tk_call_without_enc('after','idle',cmdid)
+ after_id.instance_variable_set('@cmdid', cmdid)
+ after_id
end
+=begin
+ def after_idle(cmd=Proc.new)
+ crit_bup = Thread.critical
+ Thread.critical = true
- def clock_format(clk, form=nil)
- if form
- tk_call('clock','format',clk,'-format',form).to_i
- else
- tk_call('clock','format',clk).to_i
- end
- end
+ myid = _curr_cmd_id
+ cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
- def clock_formatGMT(clk, form=nil)
- if form
- tk_call('clock','format',clk,'-format',form,'-gmt','1').to_i
- else
- tk_call('clock','format',clk,'-gmt','1').to_i
- end
- end
+ Thread.critical = crit_bup
- def clock_scan(str, base=nil)
- if base
- tk_call('clock','scan',str,'-base',base).to_i
- else
- tk_call('clock','scan',str).to_i
- end
+ tk_call_without_enc('after','idle',cmdid)
end
+=end
- def clock_scanGMT(str, base=nil)
- if base
- tk_call('clock','scan',str,'-base',base,'-gmt','1').to_i
- else
- tk_call('clock','scan',str,'-gmt','1').to_i
+ def after_cancel(afterId)
+ tk_call_without_enc('after','cancel',afterId)
+ if (cmdid = afterId.instance_variable_get('@cmdid'))
+ afterId.instance_variable_set('@cmdid', nil)
+ uninstall_cmd(cmdid)
end
- end
-
- def clock_seconds
- tk_call('clock','seconds').to_i
+ afterId
end
def windowingsystem
- tk_call('tk', 'windowingsystem')
+ tk_call_without_enc('tk', 'windowingsystem')
end
def scaling(scale=nil)
if scale
- tk_call('tk', 'scaling', scale)
+ tk_call_without_enc('tk', 'scaling', scale)
else
- Float(number(tk_call('tk', 'scaling')))
+ Float(number(tk_call_without_enc('tk', 'scaling')))
end
end
def scaling_displayof(win, scale=nil)
if scale
- tk_call('tk', 'scaling', '-displayof', win, scale)
+ tk_call_without_enc('tk', 'scaling', '-displayof', win, scale)
else
- Float(number(tk_call('tk', '-displayof', win, 'scaling')))
+ Float(number(tk_call_without_enc('tk', '-displayof', win, 'scaling')))
end
end
+ def inactive
+ Integer(tk_call_without_enc('tk', 'inactive'))
+ end
+ def inactive_displayof(win)
+ Integer(tk_call_without_enc('tk', 'inactive', '-displayof', win))
+ end
+ def reset_inactive
+ tk_call_without_enc('tk', 'inactive', 'reset')
+ end
+ def reset_inactive_displayof(win)
+ tk_call_without_enc('tk', 'inactive', '-displayof', win, 'reset')
+ end
+
def appname(name=None)
tk_call('tk', 'appname', name)
end
+ def appsend_deny
+ tk_call('rename', 'send', '')
+ end
+
def appsend(interp, async, *args)
+ if $SAFE >= 4
+ fail SecurityError, "cannot send Tk commands at level 4"
+ elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
+ end
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
if async
tk_call('send', '-async', '--', interp, *args)
else
@@ -896,13 +1583,34 @@ module TkCore
end
def rb_appsend(interp, async, *args)
- args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
- args.push(').to_s"')
- appsend(interp, async, 'ruby "(', *args)
+ if $SAFE >= 4
+ fail SecurityError, "cannot send Ruby commands at level 4"
+ elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
+ end
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
+ #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
+ args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
+ # args.push(').to_s"')
+ # appsend(interp, async, 'ruby "(', *args)
+ args.push('}.call)"')
+ appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args)
end
def appsend_displayof(interp, win, async, *args)
+ if $SAFE >= 4
+ fail SecurityError, "cannot send Tk commands at level 4"
+ elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
+ end
win = '.' if win == nil
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
if async
tk_call('send', '-async', '-displayof', win, '--', interp, *args)
else
@@ -911,9 +1619,22 @@ module TkCore
end
def rb_appsend_displayof(interp, win, async, *args)
- args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
- args.push(').to_s"')
- appsend_displayof(interp, win, async, 'ruby "(', *args)
+ if $SAFE >= 4
+ fail SecurityError, "cannot send Ruby commands at level 4"
+ elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
+ end
+ win = '.' if win == nil
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
+ #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
+ args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
+ # args.push(').to_s"')
+ # appsend_displayof(interp, win, async, 'ruby "(', *args)
+ args.push('}.call)"')
+ appsend(interp, win, async, 'ruby "TkComm._get_eval_string(proc{', *args)
end
def info(*args)
@@ -921,7 +1642,48 @@ module TkCore
end
def mainloop(check_root = true)
- TclTkLib.mainloop(check_root)
+ if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
+ TclTkLib.mainloop(check_root)
+ else ### Ruby 1.9 !!!!!
+ begin
+ TclTkLib.set_eventloop_window_mode(true)
+ if check_root
+ INTERP_MUTEX.synchronize{
+ INTERP_ROOT_CHECK.wait(INTERP_MUTEX)
+ status = INTERP_THREAD[:status]
+ if status
+ INTERP_THREAD[:status] = nil
+ raise status if status.kind_of?(Exception)
+ end
+ }
+ else
+ INTERP_THREAD.value
+ end
+ ensure
+ TclTkLib.set_eventloop_window_mode(false)
+ end
+ end
+ end
+
+ def mainloop_thread?
+ # true : current thread is mainloop
+ # nil : there is no mainloop
+ # false : mainloop is running on the other thread
+ # ( At then, it is dangerous to call Tk interpreter directly. )
+ if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
+ ### Ruby 1.9 !!!!!!!!!!!
+ TclTkLib.mainloop_thread?
+ else
+ Thread.current == INTERP_THREAD
+ end
+ end
+
+ def mainloop_exist?
+ TclTkLib.mainloop_thread? != nil
+ end
+
+ def is_mainloop?
+ TclTkLib.mainloop_thread? == true
end
def mainloop_watchdog(check_root = true)
@@ -970,171 +1732,238 @@ module TkCore
nil
end
- def event_generate(window, context, keys=nil)
- window = window.path if window.kind_of? TkObject
- if keys
- tk_call('event', 'generate', window,
- "<#{tk_event_sequence(context)}>", *hash_kv(keys))
+ def event_generate(win, context, keys=nil)
+ #win = win.path if win.kind_of?(TkObject)
+ if context.kind_of?(TkEvent::Event)
+ context.generate(win, ((keys)? keys: {}))
+ elsif keys
+ tk_call_without_enc('event', 'generate', win,
+ "<#{tk_event_sequence(context)}>",
+ *hash_kv(keys, true))
else
- tk_call('event', 'generate', window, "<#{tk_event_sequence(context)}>")
+ tk_call_without_enc('event', 'generate', win,
+ "<#{tk_event_sequence(context)}>")
end
+ nil
end
def messageBox(keys)
- tk_call 'tk_messageBox', *hash_kv(keys)
+ tk_call('tk_messageBox', *hash_kv(keys))
end
def getOpenFile(keys = nil)
- tk_call 'tk_getOpenFile', *hash_kv(keys)
+ tk_call('tk_getOpenFile', *hash_kv(keys))
+ end
+ def getMultipleOpenFile(keys = nil)
+ simplelist(tk_call('tk_getOpenFile', '-multiple', '1', *hash_kv(keys)))
end
def getSaveFile(keys = nil)
- tk_call 'tk_getSaveFile', *hash_kv(keys)
+ tk_call('tk_getSaveFile', *hash_kv(keys))
+ end
+ def getMultipleSaveFile(keys = nil)
+ simplelist(tk_call('tk_getSaveFile', '-multiple', '1', *hash_kv(keys)))
end
def chooseColor(keys = nil)
- tk_call 'tk_chooseColor', *hash_kv(keys)
+ tk_call('tk_chooseColor', *hash_kv(keys))
end
def chooseDirectory(keys = nil)
- tk_call 'tk_chooseDirectory', *hash_kv(keys)
+ tk_call('tk_chooseDirectory', *hash_kv(keys))
end
- def ip_eval(cmd_string)
- res = INTERP._eval(cmd_string)
+ def _ip_eval_core(enc_mode, cmd_string)
+ case enc_mode
+ when nil
+ res = INTERP._eval(cmd_string)
+ when false
+ res = INTERP._eval_without_enc(cmd_string)
+ when true
+ res = INTERP._eval_with_enc(cmd_string)
+ end
if INTERP._return_value() != 0
fail RuntimeError, res, error_at
end
return res
end
+ private :_ip_eval_core
- def ip_invoke(*args)
- res = INTERP._invoke(*args)
+ def ip_eval(cmd_string)
+ _ip_eval_core(nil, cmd_string)
+ end
+
+ def ip_eval_without_enc(cmd_string)
+ _ip_eval_core(false, cmd_string)
+ end
+
+ def ip_eval_with_enc(cmd_string)
+ _ip_eval_core(true, cmd_string)
+ end
+
+ def _ip_invoke_core(enc_mode, *args)
+ case enc_mode
+ when false
+ res = INTERP._invoke_without_enc(*args)
+ when nil
+ res = INTERP._invoke(*args)
+ when true
+ res = INTERP._invoke_with_enc(*args)
+ end
if INTERP._return_value() != 0
fail RuntimeError, res, error_at
end
return res
end
+ private :_ip_invoke_core
- def tk_call(*args)
- puts args.inspect if $DEBUG
- args.collect! {|x|ruby2tcl(x)}
- args.compact!
- args.flatten!
- print "=> ", args.join(" ").inspect, "\n" if $DEBUG
+ def ip_invoke(*args)
+ _ip_invoke_core(nil, *args)
+ end
+
+ def ip_invoke_without_enc(*args)
+ _ip_invoke_core(false, *args)
+ end
+
+ def ip_invoke_with_enc(*args)
+ _ip_invoke_core(true, *args)
+ end
+
+ def _tk_call_core(enc_mode, *args)
+ ### puts args.inspect if $DEBUG
+ #args.collect! {|x|ruby2tcl(x, enc_mode)}
+ #args.compact!
+ #args.flatten!
+ args = _conv_args([], enc_mode, *args)
+ puts 'invoke args => ' + args.inspect if $DEBUG
+ ### print "=> ", args.join(" ").inspect, "\n" if $DEBUG
begin
# res = INTERP._invoke(*args).taint
- res = INTERP._invoke(*args) # _invoke returns a TAINTED string
+ # res = INTERP._invoke(enc_mode, *args)
+ res = _ip_invoke_core(enc_mode, *args)
+ # >>>>> _invoke returns a TAINTED string <<<<<
rescue NameError => err
-# err = $!
+ # err = $!
begin
args.unshift "unknown"
#res = INTERP._invoke(*args).taint
- res = INTERP._invoke(*args) # _invoke returns a TAINTED string
+ #res = INTERP._invoke(enc_mode, *args)
+ res = _ip_invoke_core(enc_mode, *args)
+ # >>>>> _invoke returns a TAINTED string <<<<<
rescue StandardError => err2
- fail err2 unless /^invalid command/ =~ err2
- fail err
+ fail err2 unless /^invalid command/ =~ err2.message
+ fail err
end
end
if INTERP._return_value() != 0
fail RuntimeError, res, error_at
end
- print "==> ", res.inspect, "\n" if $DEBUG
+ ### print "==> ", res.inspect, "\n" if $DEBUG
return res
end
-end
-
-module TkPackage
- include TkCore
- extend TkPackage
+ private :_tk_call_core
- TkCommandNames = ['package'.freeze].freeze
-
- def add_path(path)
- Tk::AUTO_PATH.value = Tk::AUTO_PATH.to_a << path
+ def tk_call(*args)
+ _tk_call_core(nil, *args)
end
- def forget(package)
- tk_call('package', 'forget', package)
- nil
+ def tk_call_without_enc(*args)
+ _tk_call_core(false, *args)
end
- def names
- tk_split_simplelist(tk_call('package', 'names'))
+ def tk_call_with_enc(*args)
+ _tk_call_core(true, *args)
end
- def provide(package, version=nil)
- if version
- tk_call('package', 'provide', package, version)
- nil
+ def _tk_call_to_list_core(depth, arg_enc, val_enc, *args)
+ args = _conv_args([], arg_enc, *args)
+ val = _tk_call_core(false, *args)
+ if !depth.kind_of?(Integer) || depth == 0
+ tk_split_simplelist(val, false, val_enc)
else
- tk_call('package', 'provide', package)
+ tk_split_list(val, depth, false, val_enc)
end
end
+ #private :_tk_call_to_list_core
- def present(package, version=None)
- tk_call('package', 'present', package, version)
+ def tk_call_to_list(*args)
+ _tk_call_to_list_core(-1, nil, true, *args)
end
- def present_exact(package, version)
- tk_call('package', 'present', '-exact', package, version)
+ def tk_call_to_list_without_enc(*args)
+ _tk_call_to_list_core(-1, false, false, *args)
end
- def require(package, version=None)
- tk_call('package', 'require', package, version)
+ def tk_call_to_list_with_enc(*args)
+ _tk_call_to_list_core(-1, true, true, *args)
end
- def require_exact(package, version)
- tk_call('package', 'require', '-exact', package, version)
+ def tk_call_to_simplelist(*args)
+ _tk_call_to_list_core(0, nil, true, *args)
end
- def versions(package)
- tk_split_simplelist(tk_call('package', 'versions', package))
+ def tk_call_to_simplelist_without_enc(*args)
+ _tk_call_to_list_core(0, false, false, *args)
end
- def vcompare(version1, version2)
- Integer(tk_call('package', 'vcompare', version1, version2))
- end
-
- def vsatisfies(version1, version2)
- bool(tk_call('package', 'vsatisfies', version1, version2))
+ def tk_call_to_simplelist_with_enc(*args)
+ _tk_call_to_list_core(0, true, true, *args)
end
end
+
module Tk
include TkCore
extend Tk
- TCL_VERSION = INTERP._invoke("info", "tclversion").freeze
- TCL_PATCHLEVEL = INTERP._invoke("info", "patchlevel").freeze
+ 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
- TK_VERSION = INTERP._invoke("set", "tk_version").freeze
- TK_PATCHLEVEL = INTERP._invoke("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("info", "commands", "kanji") != "").freeze
+ JAPANIZED_TK = (INTERP._invoke_without_enc("info", "commands",
+ "kanji") != "").freeze
def Tk.const_missing(sym)
case(sym)
when :TCL_LIBRARY
+ INTERP._invoke_without_enc('global', 'tcl_library')
INTERP._invoke("set", "tcl_library").freeze
when :TK_LIBRARY
+ INTERP._invoke_without_enc('global', 'tk_library')
INTERP._invoke("set", "tk_library").freeze
when :LIBRARY
INTERP._invoke("info", "library").freeze
#when :PKG_PATH, :PACKAGE_PATH, :TCL_PACKAGE_PATH
+ # INTERP._invoke_without_enc('global', 'tcl_pkgPath')
# tk_split_simplelist(INTERP._invoke('set', 'tcl_pkgPath'))
#when :LIB_PATH, :LIBRARY_PATH, :TCL_LIBRARY_PATH
+ # INTERP._invoke_without_enc('global', 'tcl_libPath')
# tk_split_simplelist(INTERP._invoke('set', 'tcl_libPath'))
when :PLATFORM, :TCL_PLATFORM
- Hash[*tk_split_simplelist(INTERP._invoke('array', 'get',
- 'tcl_platform'))]
+ if $SAFE >= 4
+ fail SecurityError, "can't get #{sym} when $SAFE >= 4"
+ end
+ INTERP._invoke_without_enc('global', 'tcl_platform')
+ Hash[*tk_split_simplelist(INTERP._invoke_without_enc('array', 'get',
+ 'tcl_platform'))]
when :ENV
+ INTERP._invoke_without_enc('global', 'env')
Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'env'))]
#when :AUTO_PATH #<===
@@ -1144,26 +1973,28 @@ module Tk
# tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath'))
when :AUTO_INDEX
+ INTERP._invoke_without_enc('global', 'auto_index')
Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'auto_index'))]
when :PRIV, :PRIVATE, :TK_PRIV
priv = {}
- if INTERP._invoke('info', 'vars', 'tk::Priv') != ""
- var_nam = 'tk::Priv'
+ if INTERP._invoke_without_enc('info', 'vars', 'tk::Priv') != ""
+ var_nam = 'tk::Priv'
else
- var_nam = 'tkPriv'
+ var_nam = 'tkPriv'
end
+ INTERP._invoke_without_enc('global', var_nam)
Hash[*tk_split_simplelist(INTERP._invoke('array', 'get',
- var_nam))].each{|k,v|
- k.freeze
- case v
- when /^-?\d+$/
- priv[k] = v.to_i
- when /^-?\d+\.?\d*(e[-+]?\d+)?$/
- priv[k] = v.to_f
- else
- priv[k] = v.freeze
- end
+ var_nam))].each{|k,v|
+ k.freeze
+ case v
+ when /^-?\d+$/
+ priv[k] = v.to_i
+ when /^-?\d+\.?\d*(e[-+]?\d+)?$/
+ priv[k] = v.to_f
+ else
+ priv[k] = v.freeze
+ end
}
priv
@@ -1172,48 +2003,263 @@ module Tk
end
end
+ def Tk.errorInfo
+ INTERP._invoke_without_enc('global', 'errorInfo')
+ INTERP._invoke_without_enc('set', 'errorInfo')
+ end
+
+ def Tk.errorCode
+ INTERP._invoke_without_enc('global', 'errorCode')
+ code = tk_split_simplelist(INTERP._invoke_without_enc('set', 'errorCode'))
+ case code[0]
+ when 'CHILDKILLED', 'CHILDSTATUS', 'CHILDSUSP'
+ begin
+ pid = Integer(code[1])
+ code[1] = pid
+ rescue
+ end
+ end
+ code
+ end
+
+ def Tk.has_mainwindow?
+ INTERP.has_mainwindow?
+ end
+
def root
- TkRoot.new
+ Tk::Root.new
+ end
+
+ def Tk.load_tclscript(file, enc=nil)
+ if enc
+ # TCL_VERSION >= 8.5
+ tk_call('source', '-encoding', enc, file)
+ else
+ tk_call('source', file)
+ end
+ end
+
+ def Tk.load_tcllibrary(file, pkg_name=None, interp=None)
+ tk_call('load', file, pkg_name, interp)
+ end
+
+ def Tk.unload_tcllibrary(*args)
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ nocomp = (keys['nocomplain'])? '-nocomplain': None
+ keeplib = (keys['keeplibrary'])? '-keeplibrary': None
+ tk_call('unload', nocomp, keeplib, '--', *args)
+ else
+ tk_call('unload', *args)
+ end
+ end
+
+ def Tk.pkgconfig_list(mod)
+ # Tk8.5 feature
+ if mod.kind_of?(Module)
+ if mod.respond_to?(:package_name)
+ pkgname = mod.package_name
+ elsif mod.const_defined?(:PACKAGE_NAME)
+ pkgname = mod::PACKAGE_NAME
+ else
+ fail NotImplementedError, 'may not be a module for a Tcl extension'
+ end
+ else
+ pkgname = mod.to_s
+ end
+
+ pkgname = '::' << pkgname unless pkgname =~ /^::/
+
+ tk_split_list(tk_call(pkgname + '::pkgconfig', 'list'))
+ end
+
+ def Tk.pkgconfig_get(mod, key)
+ # Tk8.5 feature
+ if mod.kind_of?(Module)
+ if mod.respond_to?(:package_name)
+ pkgname = mod.package_name
+ else
+ fail NotImplementedError, 'may not be a module for a Tcl extension'
+ end
+ else
+ pkgname = mod.to_s
+ end
+
+ pkgname = '::' << pkgname unless pkgname =~ /^::/
+
+ tk_call(pkgname + '::pkgconfig', 'get', key)
+ end
+
+ def Tk.tcl_pkgconfig_list
+ # Tk8.5 feature
+ Tk.pkgconfig_list('::tcl')
+ end
+
+ def Tk.tcl_pkgconfig_get(key)
+ # Tk8.5 feature
+ Tk.pkgconfig_get('::tcl', key)
+ end
+
+ def Tk.tk_pkgconfig_list
+ # Tk8.5 feature
+ Tk.pkgconfig_list('::tk')
+ end
+
+ def Tk.tk_pkgconfig_get(key)
+ # Tk8.5 feature
+ Tk.pkgconfig_get('::tk', key)
end
def Tk.bell(nice = false)
if nice
- tk_call 'bell', '-nice'
+ tk_call_without_enc('bell', '-nice')
else
- tk_call 'bell'
+ tk_call_without_enc('bell')
end
+ nil
end
def Tk.bell_on_display(win, nice = false)
if nice
- tk_call('bell', '-displayof', win, '-nice')
+ tk_call_without_enc('bell', '-displayof', win, '-nice')
else
- tk_call('bell', '-displayof', win)
+ tk_call_without_enc('bell', '-displayof', win)
end
+ nil
end
def Tk.destroy(*wins)
- tk_call('destroy', *wins)
+ #tk_call_without_enc('destroy', *wins)
+ tk_call_without_enc('destroy', *(wins.collect{|win|
+ if win.kind_of?(TkWindow)
+ win.epath
+ else
+ win
+ end
+ }))
end
def Tk.exit
- tk_call('destroy', '.')
+ tk_call_without_enc('destroy', '.')
+ end
+
+ ################################################
+
+ def Tk.sleep(ms = nil, id = nil)
+ if id
+ var = (id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)
+ else
+ var = TkVariable.new
+ end
+
+ var.value = tk_call_without_enc('after', ms, proc{ var.value = 0 }) if ms
+ var.thread_wait
+ ms
end
- def Tk.current_grabs
- tk_split_list(tk_call('grab', 'current'))
+ def Tk.wakeup(id)
+ ((id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)).value = 0
+ nil
+ end
+
+ ################################################
+
+ def Tk.pack(*args)
+ TkPack.configure(*args)
+ end
+ def Tk.pack_forget(*args)
+ TkPack.forget(*args)
+ end
+ def Tk.unpack(*args)
+ TkPack.forget(*args)
+ end
+
+ def Tk.grid(*args)
+ TkGrid.configure(*args)
+ end
+ def Tk.grid_forget(*args)
+ TkGrid.forget(*args)
+ end
+ def Tk.ungrid(*args)
+ TkGrid.forget(*args)
+ end
+
+ def Tk.place(*args)
+ TkPlace.configure(*args)
+ end
+ def Tk.place_forget(*args)
+ TkPlace.forget(*args)
+ end
+ def Tk.unplace(*args)
+ TkPlace.forget(*args)
+ end
+
+ def Tk.update(idle=nil)
+ if idle
+ tk_call_without_enc('update', 'idletasks')
+ else
+ tk_call_without_enc('update')
+ end
+ end
+ def Tk.update_idletasks
+ update(true)
+ end
+ def update(idle=nil)
+ # only for backward compatibility (This never be recommended to use)
+ Tk.update(idle)
+ self
+ end
+
+ # NOTE::
+ # If no eventloop-thread is running, "thread_update" method is same
+ # to "update" method. Else, "thread_update" method waits to complete
+ # idletask operation on the eventloop-thread.
+ def Tk.thread_update(idle=nil)
+ if idle
+ tk_call_without_enc('thread_update', 'idletasks')
+ else
+ tk_call_without_enc('thread_update')
+ end
+ end
+ def Tk.thread_update_idletasks
+ thread_update(true)
+ end
+
+ def Tk.lower_window(win, below=None)
+ tk_call('lower', _epath(win), _epath(below))
+ nil
+ end
+ def Tk.raise_window(win, above=None)
+ tk_call('raise', _epath(win), _epath(above))
+ nil
+ end
+
+ def Tk.current_grabs(win = nil)
+ if win
+ window(tk_call_without_enc('grab', 'current', win))
+ else
+ tk_split_list(tk_call_without_enc('grab', 'current'))
+ end
end
def Tk.focus(display=nil)
if display == nil
- window(tk_call('focus'))
+ window(tk_call_without_enc('focus'))
+ else
+ window(tk_call_without_enc('focus', '-displayof', display))
+ end
+ end
+
+ def Tk.focus_to(win, force=false)
+ if force
+ tk_call_without_enc('focus', '-force', win)
else
- window(tk_call('focus', '-displayof', display))
+ tk_call_without_enc('focus', win)
end
end
def Tk.focus_lastfor(win)
- window(tk_call('focus', '-lastfor', win))
+ window(tk_call_without_enc('focus', '-lastfor', win))
end
def Tk.focus_next(win)
@@ -1224,8 +2270,8 @@ module Tk
TkManageFocus.prev(win)
end
- def Tk.strictMotif(bool=None)
- bool(tk_call('set', 'tk_strictMotif', bool))
+ def Tk.strictMotif(mode=None)
+ bool(tk_call_without_enc('set', 'tk_strictMotif', mode))
end
def Tk.show_kinsoku(mode='both')
@@ -1258,286 +2304,12 @@ module Tk
end
end
- def Tk.toUTF8(str,encoding)
- INTERP._toUTF8(str,encoding)
+ def Tk.toUTF8(str, encoding = nil)
+ _toUTF8(str, encoding)
end
- def Tk.fromUTF8(str,encoding)
- INTERP._fromUTF8(str,encoding)
- end
-
- module Scrollable
- def xscrollcommand(cmd=Proc.new)
- configure_cmd 'xscrollcommand', cmd
- end
- def yscrollcommand(cmd=Proc.new)
- configure_cmd 'yscrollcommand', cmd
- end
- def xview(*index)
- v = tk_send('xview', *index)
- list(v) if index.size == 0
- end
- def yview(*index)
- v = tk_send('yview', *index)
- list(v) if index.size == 0
- end
- def xscrollbar(bar=nil)
- if bar
- @xscrollbar = bar
- @xscrollbar.orient 'horizontal'
- self.xscrollcommand {|*arg| @xscrollbar.set(*arg)}
- @xscrollbar.command {|*arg| self.xview(*arg)}
- end
- @xscrollbar
- end
- def yscrollbar(bar=nil)
- if bar
- @yscrollbar = bar
- @yscrollbar.orient 'vertical'
- self.yscrollcommand {|*arg| @yscrollbar.set(*arg)}
- @yscrollbar.command {|*arg| self.yview(*arg)}
- end
- @yscrollbar
- end
- end
-
- module Wm
- include TkComm
-
- TkCommandNames = ['wm'.freeze].freeze
-
- def aspect(*args)
- w = tk_call('wm', 'aspect', path, *args)
- if args.length == 0
- list(w)
- else
- self
- end
- end
- def attributes(slot=nil,value=None)
- if slot == nil
- lst = tk_split_list(tk_call('wm', 'attributes', path))
- info = {}
- while key = lst.shift
- info[key[1..-1]] = lst.shift
- end
- info
- elsif slot.kind_of? Hash
- tk_call('wm', 'attributes', path, *hash_kv(slot))
- self
- elsif value == None
- tk_call('wm', 'attributes', path, "-#{slot}")
- else
- tk_call('wm', 'attributes', path, "-#{slot}", value)
- self
- end
- end
- def client(name=None)
- if name == None
- tk_call 'wm', 'client', path
- else
- name = '' if name == nil
- tk_call 'wm', 'client', path, name
- self
- end
- end
- def colormapwindows(*args)
- r = tk_call('wm', 'colormapwindows', path, *args)
- if args.size == 0
- list(r)
- else
- self
- end
- end
- def wm_command(value=nil)
- if value
- tk_call('wm', 'command', path, value)
- self
- else
- procedure(tk_call('wm', 'command', path))
- end
- end
- def deiconify(ex = true)
- tk_call('wm', 'deiconify', path) if ex
- self
- end
- def focusmodel(mode = nil)
- if mode
- tk_call 'wm', 'focusmodel', path, mode
- self
- else
- tk_call 'wm', 'focusmodel', path
- end
- end
- def frame
- tk_call('wm', 'frame', path)
- end
- def geometry(geom=nil)
- if geom
- tk_call('wm', 'geometry', path, geom)
- self
- else
- tk_call('wm', 'geometry', path)
- end
- end
- def grid(*args)
- w = tk_call('wm', 'grid', path, *args)
- if args.size == 0
- list(w)
- else
- self
- end
- end
- def group(*args)
- w = tk_call('wm', 'group', path, *args)
- if args.size == 0
- window(w)
- else
- self
- end
- end
- def iconbitmap(bmp=nil)
- if bmp
- tk_call 'wm', 'iconbitmap', path, bmp
- self
- else
- tk_call 'wm', 'iconbitmap', path
- end
- end
- def iconify(ex = true)
- tk_call('wm', 'iconify', path) if ex
- self
- end
- def iconmask(bmp=nil)
- if bmp
- tk_call 'wm', 'iconmask', path, bmp
- self
- else
- tk_call 'wm', 'iconmask', path
- end
- end
- def iconname(name=nil)
- if name
- tk_call 'wm', 'iconname', path, name
- self
- else
- tk_call 'wm', 'iconname', path
- end
- end
- def iconposition(*args)
- w = tk_call('wm', 'iconposition', path, *args)
- if args.size == 0
- list(w)
- else
- self
- end
- end
- def iconwindow(*args)
- w = tk_call('wm', 'iconwindow', path, *args)
- if args.size == 0
- window(w)
- else
- self
- end
- end
- def maxsize(*args)
- w = tk_call('wm', 'maxsize', path, *args)
- if args.size == 0
- list(w)
- else
- self
- end
- end
- def minsize(*args)
- w = tk_call('wm', 'minsize', path, *args)
- if args.size == 0
- list(w)
- else
- self
- end
- end
- def overrideredirect(bool=None)
- if bool == None
- bool(tk_call('wm', 'overrideredirect', path))
- else
- tk_call 'wm', 'overrideredirect', path, bool
- self
- end
- end
- def positionfrom(who=None)
- if who == None
- r = tk_call('wm', 'positionfrom', path)
- (r == "")? nil: r
- else
- tk_call('wm', 'positionfrom', path, who)
- self
- end
- end
- def protocol(name=nil, cmd=nil)
- if cmd
- tk_call('wm', 'protocol', path, name, cmd)
- self
- elsif name
- result = tk_call('wm', 'protocol', path, name)
- (result == "")? nil : tk_tcl2ruby(result)
- else
- tk_split_simplelist(tk_call('wm', 'protocol', path))
- end
- end
- def resizable(*args)
- w = tk_call('wm', 'resizable', path, *args)
- if args.length == 0
- list(w).collect{|e| bool(e)}
- else
- self
- end
- end
- def sizefrom(who=None)
- if who == None
- r = tk_call('wm', 'sizefrom', path)
- (r == "")? nil: r
- else
- tk_call('wm', 'sizefrom', path, who)
- self
- end
- end
- def stackorder
- list(tk_call('wm', 'stackorder', path))
- end
- def stackorder_isabove(win)
- bool(tk_call('wm', 'stackorder', path, 'isabove', win))
- end
- def stackorder_isbelow(win)
- bool(tk_call('wm', 'stackorder', path, 'isbelow', win))
- end
- def state(state=nil)
- if state
- tk_call 'wm', 'state', path, state
- self
- else
- tk_call 'wm', 'state', path
- end
- end
- def title(str=nil)
- if str
- tk_call('wm', 'title', path, str)
- self
- else
- tk_call('wm', 'title', path)
- end
- end
- def transient(master=nil)
- if master
- tk_call('wm', 'transient', path, master)
- self
- else
- window(tk_call('wm', 'transient', path, master))
- end
- end
- def withdraw(ex = true)
- tk_call('wm', 'withdraw', path) if ex
- self
- end
+ def Tk.fromUTF8(str, encoding = nil)
+ _fromUTF8(str, encoding)
end
end
@@ -1545,45 +2317,20 @@ end
# string with Tcl's encoding
###########################################
module Tk
- class EncodedString < String
- @@enc_buf = '__rb_encoding_buffer__'
-
- def self.tk_escape(str)
- s = '"' + str.gsub(/[\[\]$"]/, '\\\\\&') + '"'
- TkCore::INTERP.__eval(Kernel.format('global %s; set %s %s',
- @@enc_buf, @@enc_buf, s))
- end
-
- def self.new(str, enc = Tk.encoding_system)
- obj = super(self.tk_escape(str))
- obj.instance_eval{@enc = enc}
- obj
- end
-
- def self.new_without_escape(str, enc = Tk.encoding_system)
- obj = super(str)
- obj.instance_eval{@enc = enc}
- obj
- end
-
- def encoding
- @enc
- end
+ def Tk.subst_utf_backslash(str)
+ Tk::EncodedString.subst_utf_backslash(str)
end
- def Tk.EncodedString(str, enc = Tk.encoding_system)
- Tk::EncodedString.new(str, enc)
+ def Tk.subst_tk_backslash(str)
+ Tk::EncodedString.subst_tk_backslash(str)
end
-
- class UTF8_String < EncodedString
- def self.new(str)
- super(str, 'utf-8')
- end
- def self.new_without_escape(str)
- super(str, 'utf-8')
- end
+ def Tk.utf_to_backslash_sequence(str)
+ Tk::EncodedString.utf_to_backslash_sequence(str)
end
- def Tk.UTF8_String(str)
- Tk::UTF8_String.new(str)
+ def Tk.utf_to_backslash(str)
+ Tk::EncodedString.utf_to_backslash_sequence(str)
+ end
+ def Tk.to_backslash_sequence(str)
+ Tk::EncodedString.to_backslash_sequence(str)
end
end
@@ -1591,2180 +2338,2335 @@ end
###########################################
# convert kanji string to/from utf-8
###########################################
-if /^8\.[1-9]/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK
- class TclTkIp
- # from tkencoding.rb by ttate@jaist.ac.jp
- alias __eval _eval
- alias __invoke _invoke
-
- attr_accessor :encoding
-
- def _eval(cmd)
- if defined? @encoding
- if cmd.kind_of?(Tk::EncodedString)
- _fromUTF8(__eval(_toUTF8(cmd, cmd.encoding)), @encoding)
- else
- _fromUTF8(__eval(_toUTF8(cmd, @encoding)), @encoding)
- end
- else
- __eval(cmd)
- end
- end
-
- def _invoke(*cmds)
- if defined? @encoding
- cmds = cmds.collect{|cmd|
- if cmd.kind_of?(Tk::EncodedString)
- _toUTF8(cmd, cmd.encoding)
- else
- _toUTF8(cmd, @encoding)
- end
- }
- _fromUTF8(__invoke(*cmds), @encoding)
- else
- __invoke(*cmds)
- end
- end
- end
-
+if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
module Tk
module Encoding
extend Encoding
TkCommandNames = ['encoding'.freeze].freeze
- def encoding=(name)
- TkCore::INTERP.encoding = name
- end
+ #############################################
- def encoding
- TkCore::INTERP.encoding
- end
+ if TkCore::WITH_ENCODING ### Ruby 1.9
+ RubyEncoding = ::Encoding
- def encoding_names
- tk_split_simplelist(tk_call('encoding', 'names'))
- end
+ # for saving GC cost
+ #ENCNAMES_CMD = ['encoding'.freeze, 'names'.freeze]
+ BINARY_NAME = 'binary'.freeze
+ UTF8_NAME = 'utf-8'.freeze
+ DEFAULT_EXTERNAL_NAME = RubyEncoding.default_external.name.freeze
- def encoding_system
- tk_call('encoding', 'system')
- end
+ BINARY = RubyEncoding.find(BINARY_NAME)
+ UNKNOWN = RubyEncoding.find('ASCII-8BIT')
- def encoding_system=(enc)
- tk_call('encoding', 'system', enc)
- end
+ ### start of creating ENCODING_TABLE
+ ENCODING_TABLE = TkCore::INTERP.encoding_table
+=begin
+ ENCODING_TABLE = {
+ 'binary' => BINARY,
+ # 'UNKNOWN-8BIT' => UNKNOWN,
+ }
- def encoding_convertfrom(str, enc=None)
- TkCore::INTERP.__invoke('encoding', 'convertfrom', enc, str)
- end
- alias encoding_convert_from encoding_convertfrom
+ list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
+ ENCNAMES_CMD[1])
+ TkCore::INTERP._split_tklist(list).each{|name|
+ begin
+ enc = RubyEncoding.find(name)
+ rescue ArgumentError
+ case name
+ when 'identity'
+ enc = BINARY
+ when 'shiftjis'
+ enc = RubyEncoding.find('Shift_JIS')
+ when 'unicode'
+ enc = RubyEncoding.find('UTF-8')
+ #if Tk.tk_call('set', 'tcl_platform(byteOrder)') =='littleEndian'
+ # enc = RubyEncoding.find('UTF-16LE')
+ #else
+ # enc = RubyEncoding.find('UTF-16BE')
+ #end
+ when 'symbol'
+ # single byte data
+ enc = RubyEncoding.find('ASCII-8BIT') ### ???
+ else
+ # unsupported on Ruby, but supported on Tk
+ enc = TkCore::INTERP.create_dummy_encoding_for_tk(name)
+ end
+ end
+ ENCODING_TABLE[name.freeze] = enc
+ }
+=end
+=begin
+ def ENCODING_TABLE.get_name(enc)
+ orig_enc = enc
+
+ # unles enc, use system default
+ # 1st: Ruby/Tk default encoding
+ # 2nd: Tcl/Tk default encoding
+ # 3rd: Ruby's default_external
+ enc ||= TkCore::INTERP.encoding
+ enc ||= TclTkLib.encoding_system
+ enc ||= DEFAULT_EXTERNAL_NAME
+
+ if enc.kind_of?(RubyEncoding)
+ # Ruby's Encoding object
+ if (name = self.key(enc))
+ return name
+ end
+
+ # Is it new ?
+ list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
+ ENCNAMES_CMD[1])
+ TkComm.simplelist(list).each{|name|
+ if ((enc == RubyEncoding.find(name)) rescue false)
+ # new relation!! update table
+ self[name.freeze] = enc
+ return name
+ end
+ }
+ else
+ # String or Symbol ?
+ if self[name = enc.to_s]
+ return name
+ end
+
+ # Is it new ?
+ if (enc_obj = (RubyEncoding.find(name) rescue false))
+ list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
+ ENCNAMES_CMD[1])
+ if TkComm.simplelist(list).index(name)
+ # Tk's encoding name ?
+ self[name.freeze] = enc_obj # new relation!! update table
+ return name
+ else
+ # Ruby's encoding name ?
+ if (name = self.key(enc_obj))
+ return name
+ end
+ end
+ end
+ end
+
+ fail ArgumentError, "unsupported Tk encoding '#{orig_enc}'"
+ end
+
+ def ENCODING_TABLE.get_obj(enc)
+ # returns the encoding object.
+ # If 'enc' is the encoding name on Tk only, it returns nil.
+ ((obj = self[self.get_name(enc)]).kind_of?(RubyEncoding))? obj: nil
+ end
+=end
+ ### end of creating ENCODING_TABLE
- def encoding_convertto(str, enc=None)
- TkCore::INTERP.__invoke('encoding', 'convertto', enc, str)
end
- alias encoding_convert_to encoding_convertto
- end
- extend Encoding
- end
+ #############################################
- # estimate encoding
- case $KCODE
- when /^e/i # EUC
- Tk.encoding = 'euc-jp'
- when /^s/i # SJIS
- Tk.encoding = 'shiftjis'
- when /^u/i # UTF8
- Tk.encoding = 'utf-8'
- else # NONE
- begin
- Tk.encoding = Tk.encoding_system
- rescue StandardError, NameError
- Tk.encoding = 'utf-8'
- end
- end
+ if TkCore::WITH_ENCODING
+ ################################
+ ### Ruby 1.9
+ ################################
+ def force_default_encoding(mode)
+ TkCore::INTERP.force_default_encoding = mode
+ end
-else
- # dummy methods
- class TclTkIp
- alias __eval _eval
- alias __invoke _invoke
- end
+ def force_default_encoding?
+ TkCore::INTERP.force_default_encoding?
+ end
- module Tk
- module Encoding
- extend Encoding
+ def default_encoding=(enc)
+ TkCore::INTERP.default_encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
- def encoding=(name)
- nil
- end
- def encoding
- nil
- end
- def encoding_names
- nil
- end
- def encoding_system
- nil
- end
- def encoding_system=(enc)
- nil
- end
+ def encoding=(enc)
+ TkCore::INTERP.encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
- def encoding_convertfrom(str, enc=None)
- str
- end
- alias encoding_convert_from encoding_convertfrom
+ def encoding_name
+ Tk::Encoding::ENCODING_TABLE.get_name(TkCore::INTERP.encoding)
+ end
+ def encoding_obj
+ Tk::Encoding::ENCODING_TABLE.get_obj(TkCore::INTERP.encoding)
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
+
+ def tk_encoding_names
+ TkComm.simplelist(TkCore::INTERP._invoke_without_enc(Tk::Encoding::ENCNAMES_CMD[0], Tk::Encoding::ENCNAMES_CMD[1]))
+ end
+ def encoding_names
+ self.tk_encoding_names.find_all{|name|
+ Tk::Encoding::ENCODING_TABLE.get_name(name) rescue false
+ }
+ end
+ def encoding_objs
+ self.tk_encoding_names.map!{|name|
+ Tk::Encoding::ENCODING_TABLE.get_obj(name) rescue nil
+ }.compact
+ end
- def encoding_convertto(str, enc=None)
- str
- end
- alias encoding_convert_to encoding_convertto
- end
+ def encoding_system=(enc)
+ TclTkLib.encoding_system = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
- extend Encoding
- end
-end
+ def encoding_system_name
+ Tk::Encoding::ENCODING_TABLE.get_name(TclTkLib.encoding_system)
+ end
+ def encoding_system_obj
+ Tk::Encoding::ENCODING_TABLE.get_obj(TclTkLib.encoding_system)
+ end
+ alias encoding_system encoding_system_name
-module TkBindCore
- def bind(context, cmd=Proc.new, args=nil)
- Tk.bind(self, context, cmd, args)
- end
+ ################################
+ else
+ ################################
+ ### Ruby 1.8-
+ ################################
+ def force_default_encoding=(mode)
+ true
+ end
- def bind_append(context, cmd=Proc.new, args=nil)
- Tk.bind_append(self, context, cmd, args)
- end
+ def force_default_encoding?
+ true
+ end
- def bind_remove(context)
- Tk.bind_remove(self, context)
- end
+ def default_encoding=(enc)
+ TkCore::INTERP.default_encoding = enc
+ end
- def bindinfo(context=nil)
- Tk.bindinfo(self, context)
- end
-end
+ def encoding=(enc)
+ TkCore::INTERP.encoding = enc
+ end
-class TkBindTag
- include TkBindCore
+ def encoding_obj
+ TkCore::INTERP.encoding
+ end
+ def encoding_name
+ TkCore::INTERP.encoding
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
- #BTagID_TBL = {}
- BTagID_TBL = TkCore::INTERP.create_table
- Tk_BINDTAG_ID = ["btag".freeze, "00000".taint].freeze
+ def tk_encoding_names
+ TkComm.simplelist(Tk.tk_call('encoding', 'names'))
+ end
+ def encoding_objs
+ self.tk_encoding_names
+ end
+ def encoding_names
+ self.tk_encoding_names
+ end
- TkCore::INTERP.init_ip_env{ BTagID_TBL.clear }
+ def encoding_system=(enc)
+ TclTkLib.encoding_system = enc
+ end
- def TkBindTag.id2obj(id)
- BTagID_TBL[id]? BTagID_TBL[id]: id
- end
+ def encoding_system_name
+ TclTkLib.encoding_system
+ end
+ def encoding_system_obj
+ TclTkLib.encoding_system
+ end
+ alias encoding_system encoding_system_name
- def TkBindTag.new_by_name(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
- self.new(*args, &b).instance_eval{
- BTagID_TBL.delete @id
- @id = name
- BTagID_TBL[@id] = self
- }
- end
+ ################################
+ end
- def initialize(*args, &b)
- @id = Tk_BINDTAG_ID.join
- Tk_BINDTAG_ID[1].succ!
- BTagID_TBL[@id] = self
- bind(*args, &b) if args != []
- end
+ def encoding_convertfrom(str, enc=nil)
+ enc = encoding_system_name unless enc
+ str = str.dup
+ if TkCore::WITH_ENCODING
+ if str.kind_of?(Tk::EncodedString)
+ str.__instance_variable_set('@encoding', nil)
+ else
+ str.instance_variable_set('@encoding', nil)
+ end
+ str.force_encoding('binary')
+ else
+ str.instance_variable_set('@encoding', 'binary')
+ end
+ ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertfrom',
+ enc, str)
+ if TkCore::WITH_ENCODING
+ ret.force_encoding('utf-8')
+ else
+ Tk::UTF8_String.new(ret)
+ end
+ ret
+ end
+ alias encoding_convert_from encoding_convertfrom
- ALL = self.new_by_name('all')
+ def encoding_convertto(str, enc=nil)
+ # str must be a UTF-8 string
+ enc = encoding_system_name unless enc
+ ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertto',
+ enc, str)
+ #ret.instance_variable_set('@encoding', 'binary')
+ if TkCore::WITH_ENCODING
+ #ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj('binary'))
+ ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc))
+ end
+ ret
+ end
+ alias encoding_convert_to encoding_convertto
- def name
- @id
- end
+ def encoding_dirs
+ # Tcl8.5 feature
+ TkComm.simplelist(Tk.tk_call_without_enc('encoding', 'dirs'))
+ end
- def to_eval
- @id
- end
+ def encoding_dirs=(dir_list) # an array or a Tcl's list string
+ # Tcl8.5 feature
+ Tk.tk_call_without_enc('encoding', 'dirs', dir_list)
+ end
+ end
- def inspect
- Kernel.format "#<TkBindTag: %s>", @id
+ extend Encoding
end
-end
-class TkBindTagAll<TkBindTag
- def TkBindTagAll.new(*args, &b)
- $stderr.puts "Warning: TkBindTagALL is obsolete. Use TkBindTag::ALL\n"
+ class TclTkIp
+ def force_default_encoding=(mode)
+ @force_default_encoding = (mode)? true: false
+ end
- TkBindTag::ALL.bind(*args, &b) if args != []
- TkBindTag::ALL
- end
-end
+ def force_default_encoding?
+ @force_default_encoding ||= false
+ end
-class TkDatabaseClass<TkBindTag
- def self.new(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
- super(name, *args, &b)
- end
+ def default_encoding=(name)
+ name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING
+ @encoding = name
+ end
- def initialize(name, *args, &b)
- @id = name
- BTagID_TBL[@id] = self
- bind(*args, &b) if args != []
- end
+ # from tkencoding.rb by ttate@jaist.ac.jp
+ #attr_accessor :encoding
+ def encoding=(name)
+ self.force_default_encoding = true # for comaptibility
+ self.default_encoding = name
+ end
- def inspect
- Kernel.format "#<TkDatabaseClass: %s>", @id
- end
-end
+ def encoding_name
+ (@encoding)? @encoding.dup: nil
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
-class TkVariable
- include Tk
- extend TkCore
+ def encoding_obj
+ if Tk::WITH_ENCODING
+ Tk::Encoding.tcl2rb_encoding(@encoding)
+ else
+ (@encoding)? @encoding.dup: nil
+ end
+ end
+
+ alias __toUTF8 _toUTF8
+ alias __fromUTF8 _fromUTF8
+
+ if Object.const_defined?(:Encoding) && ::Encoding.class == Class
+ # with Encoding (Ruby 1.9+)
+ #
+ # use functions on Tcl as default.
+ # but when unsupported encoding on Tcl, use methods on Ruby.
+ #
+ def _toUTF8(str, enc = nil)
+ if enc
+ # use given encoding
+ begin
+ enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ rescue
+ # unknown encoding for Tk -> try to convert encoding on Ruby
+ str = str.dup.force_encoding(enc)
+ str.encode!(Tk::Encoding::UTF8_NAME) # modify self !!
+ return str # if no error, probably succeed converting
+ end
+ end
- include Comparable
+ enc_name ||= str.instance_variable_get(:@encoding)
- #TkCommandNames = ['tkwait'.freeze].freeze
- TkCommandNames = ['vwait'.freeze].freeze
+ enc_name ||=
+ Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
- #TkVar_CB_TBL = {}
- #TkVar_ID_TBL = {}
- TkVar_CB_TBL = TkCore::INTERP.create_table
- TkVar_ID_TBL = TkCore::INTERP.create_table
- Tk_VARIABLE_ID = ["v".freeze, "00000".taint].freeze
+ unless enc_name
+ # str.encoding isn't supported by Tk -> try to convert on Ruby
+ begin
+ return str.encode(Tk::Encoding::UTF8_NAME) # new string
+ rescue
+ # error -> ignore, try to use default encoding of Ruby/Tk
+ end
+ end
- TkCore::INTERP.add_tk_procs('rb_var', 'args',
- "ruby [format \"TkVariable.callback %%Q!%s!\" $args]")
+ #enc_name ||=
+ # Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding) rescue nil
+ enc_name ||= Tk::Encoding::ENCODING_TABLE.get_name(nil)
- def TkVariable.callback(args)
- name1,name2,op = tk_split_list(args)
- if TkVar_CB_TBL[name1]
- _get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
- else
- ''
- end
- end
+ # is 'binary' encoding?
+ if enc_name == Tk::Encoding::BINARY_NAME
+ return str.dup.force_encoding(Tk::Encoding::BINARY_NAME)
+ end
- def initialize(val="")
- @id = Tk_VARIABLE_ID.join
- Tk_VARIABLE_ID[1].succ!
- TkVar_ID_TBL[@id] = self
+ # force default encoding?
+ if ! str.kind_of?(Tk::EncodedString) && self.force_default_encoding?
+ enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.default_encoding)
+ end
- @trace_var = nil
- @trace_elem = nil
- @trace_opts = nil
+ encstr = __toUTF8(str, enc_name)
+ encstr.force_encoding(Tk::Encoding::UTF8_NAME)
+ encstr
+ end
+ def _fromUTF8(str, enc = nil)
+ # str must be UTF-8 or binary.
+ enc_name = str.instance_variable_get(:@encoding)
+ enc_name ||=
+ Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
-=begin
- if val == []
- # INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)',
- # @id, @id, @id))
- elsif val.kind_of?(Array)
- a = []
- # val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
- # s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"'
- val.each_with_index{|e,i| a.push(i); a.push(e)}
- s = '"' + array2tk_list(a).gsub(/[\[\]$"]/, '\\\\\&') + '"'
- INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
- elsif val.kind_of?(Hash)
- s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
- .gsub(/[\[\]$"]/, '\\\\\&') + '"'
- INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
+ # is 'binary' encoding?
+ if enc_name == Tk::Encoding::BINARY_NAME
+ return str.dup.force_encoding(Tk::Encoding::BINARY_NAME)
+ end
+
+ # get target encoding name (if enc == nil, use default encoding)
+ begin
+ enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ rescue
+ # then, enc != nil
+ # unknown encoding for Tk -> try to convert encoding on Ruby
+ str = str.dup.force_encoding(Tk::Encoding::UTF8_NAME)
+ str.encode!(enc) # modify self !!
+ return str # if no error, probably succeed converting
+ end
+
+ encstr = __fromUTF8(str, enc_name)
+ encstr.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc_name))
+ encstr
+ end
+ ###
else
- s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
- INTERP._eval(format('global %s; set %s %s', @id, @id, s))
+ # without Encoding (Ruby 1.8)
+ def _toUTF8(str, encoding = nil)
+ __toUTF8(str, encoding)
+ end
+ def _fromUTF8(str, encoding = nil)
+ __fromUTF8(str, encoding)
+ end
+ ###
end
-=end
- if val.kind_of?(Hash)
- s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
- .gsub(/[\[\]$"]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; array set %s %s', @id, @id, s))
- else
- s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
+
+ alias __eval _eval
+ alias __invoke _invoke
+
+ def _eval(cmd)
+ _fromUTF8(__eval(_toUTF8(cmd)))
end
- end
- def wait(on_thread = false, check_root = false)
- if $SAFE >= 4
- fail SecurityError, "can't wait variable at $SAFE >= 4"
+ def _invoke(*cmds)
+ _fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)})))
end
- if on_thread
- if check_root
- INTERP._thread_tkwait('variable', @id)
+
+ alias _eval_with_enc _eval
+ alias _invoke_with_enc _invoke
+
+=begin
+ #### --> definition is moved to TclTkIp module
+
+ def _toUTF8(str, encoding = nil)
+ # decide encoding
+ if encoding
+ encoding = encoding.to_s
+ elsif str.kind_of?(Tk::EncodedString) && str.encoding != nil
+ encoding = str.encoding.to_s
+ elsif str.instance_variable_get(:@encoding)
+ encoding = str.instance_variable_get(:@encoding).to_s
+ elsif defined?(@encoding) && @encoding != nil
+ encoding = @encoding.to_s
else
- INTERP._thread_vwait(@id)
+ encoding = __invoke('encoding', 'system')
end
- else
- if check_root
- INTERP._invoke('tkwait', 'variable', @id)
+
+ # convert
+ case encoding
+ when 'utf-8', 'binary'
+ str
else
- INTERP._invoke('vwait', @id)
+ __toUTF8(str, encoding)
end
end
- end
- def eventloop_wait(check_root = false)
- wait(false, check_root)
- end
- def thread_wait(check_root = false)
- wait(true, check_root)
- end
- def tkwait(on_thread = true)
- wait(on_thread, true)
- end
- def eventloop_tkwait
- wait(false, true)
- end
- def thread_tkwait
- wait(true, true)
- end
- def id
- @id
- end
+ def _fromUTF8(str, encoding = nil)
+ unless encoding
+ if defined?(@encoding) && @encoding != nil
+ encoding = @encoding.to_s
+ else
+ encoding = __invoke('encoding', 'system')
+ end
+ end
- def value
- begin
- INTERP._eval(Kernel.format('global %s; set %s', @id, @id))
- rescue
- if INTERP._eval(Kernel.format('global %s; array exists %s',
- @id, @id)) != "1"
- fail
+ if str.kind_of?(Tk::EncodedString)
+ if str.encoding == 'binary'
+ str
+ else
+ __fromUTF8(str, encoding)
+ end
+ elsif str.instance_variable_get(:@encoding).to_s == 'binary'
+ str
else
- Hash[*tk_split_simplelist(INTERP._eval(Kernel.format('global %s; array get %s', @id, @id)))]
+ __fromUTF8(str, encoding)
end
end
- end
+=end
- def value=(val)
- begin
- s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
- rescue
- if INTERP._eval(Kernel.format('global %s; array exists %s',
- @id, @id)) != "1"
- fail
+=begin
+ def _eval(cmd)
+ if defined?(@encoding) && @encoding != 'utf-8'
+ ret = if cmd.kind_of?(Tk::EncodedString)
+ case cmd.encoding
+ when 'utf-8', 'binary'
+ __eval(cmd)
+ else
+ __eval(_toUTF8(cmd, cmd.encoding))
+ end
+ elsif cmd.instance_variable_get(:@encoding) == 'binary'
+ __eval(cmd)
+ else
+ __eval(_toUTF8(cmd, @encoding))
+ end
+ if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary'
+ ret
+ else
+ _fromUTF8(ret, @encoding)
+ end
else
- if val == []
- INTERP._eval(Kernel.format('global %s; unset %s; set %s(0) 0; unset %s(0)', @id, @id, @id, @id))
- elsif val.kind_of?(Array)
- a = []
- val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
- s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; unset %s; array set %s %s',
- @id, @id, @id, s))
- elsif val.kind_of?(Hash)
- s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
- .gsub(/[\[\]$"]/, '\\\\\&') + '"'
- INTERP._eval(Kernel.format('global %s; unset %s; array set %s %s',
- @id, @id, @id, s))
- else
- fail
- end
+ __eval(cmd)
end
end
- end
- def [](index)
- INTERP._eval(Kernel.format('global %s; set %s(%s)',
- @id, @id, _get_eval_string(index)))
- end
-
- def []=(index,val)
- INTERP._eval(Kernel.format('global %s; set %s(%s) %s', @id, @id,
- _get_eval_string(index), _get_eval_string(val)))
- end
-
- def numeric
- number(value)
- end
- def numeric=(val)
- case val
- when Numeric
- self.value=(val)
- when TkVariable
- self.value=(val.numeric)
- else
- raise ArgumentError, "Numeric is expected"
+ def _invoke(*cmds)
+ if defined?(@encoding) && @encoding != 'utf-8'
+ cmds = cmds.collect{|cmd|
+ if cmd.kind_of?(Tk::EncodedString)
+ case cmd.encoding
+ when 'utf-8', 'binary'
+ cmd
+ else
+ _toUTF8(cmd, cmd.encoding)
+ end
+ elsif cmd.instance_variable_get(:@encoding) == 'binary'
+ cmd
+ else
+ _toUTF8(cmd, @encoding)
+ end
+ }
+ ret = __invoke(*cmds)
+ if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary'
+ ret
+ else
+ _fromUTF8(ret, @encoding)
+ end
+ else
+ __invoke(*cmds)
+ end
end
+=end
end
- def to_i
- number(value).to_i
- end
-
- def to_f
- number(value).to_f
- end
-
- def to_s
- string(value).to_s
- end
-
- def to_sym
- value.intern
- end
-
- def list
- tk_split_list(value)
- end
- alias to_a list
+ module TclTkLib
+ class << self
+ def force_default_encoding=(mode)
+ TkCore::INTERP.force_default_encoding = mode
+ end
- def list=(val)
- case val
- when Array
- self.value=(val)
- when TkVariable
- self.value=(val.list)
- else
- raise ArgumentError, "Array is expected"
- end
- end
+ def force_default_encoding?
+ TkCore::INTERP.force_default_encoding?
+ end
- def inspect
- Kernel.format "#<TkVariable: %s>", @id
- end
+ def default_encoding=(name)
+ TkCore::INTERP.default_encoding = name
+ end
- def coerce(other)
- case other
- when TkVariable
- [other.value, self.value]
- when String
- [other, self.to_s]
- when Symbol
- [other, self.to_sym]
- when Integer
- [other, self.to_i]
- when Float
- [other, self.to_f]
- when Array
- [other, self.to_a]
- else
- [other, self.value]
- end
- end
+ alias _encoding encoding
+ alias _encoding= encoding=
+ def encoding=(name)
+ name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING
+ TkCore::INTERP.encoding = name
+ end
- def &(other)
- if other.kind_of?(Array)
- self.to_a & other.to_a
- else
- self.to_i & other.to_i
- end
- end
- def |(other)
- if other.kind_of?(Array)
- self.to_a | other.to_a
- else
- self.to_i | other.to_i
- end
- end
- def +(other)
- case other
- when Array
- self.to_a + other
- when String
- self.value + other
- else
- begin
- number(self.value) + other
- rescue
- self.value + other.to_s
+ def encoding_name
+ TkCore::INTERP.encoding
end
- end
- end
- def -(other)
- if other.kind_of?(Array)
- self.to_a - other
- else
- number(self.value) - other
- end
- end
- def *(other)
- begin
- number(self.value) * other
- rescue
- self.value * other
- end
- end
- def /(other)
- number(self.value) / other
- end
- def %(other)
- begin
- number(self.value) % other
- rescue
- self.value % other
- end
- end
- def **(other)
- number(self.value) ** other
- end
- def =~(other)
- self.value =~ other
- end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
- def ==(other)
- case other
- when TkVariable
- self.equal?(other)
- when String
- self.to_s == other
- when Symbol
- self.to_sym == other
- when Integer
- self.to_i == other
- when Float
- self.to_f == other
- when Array
- self.to_a == other
- when Hash
- self.value == other
- else
- false
+ def encoding_obj
+ if Tk::WITH_ENCODING
+ Tk::Encoding.tcl2rb_encoding(TkCore::INTERP.encoding)
+ else
+ TkCore::INTERP.encoding
+ end
+ end
end
end
- def zero?
- numeric.zero?
- end
- def nonzero?
- !(numeric.zero?)
- end
-
- def <=>(other)
- if other.kind_of?(TkVariable)
+ # estimate encoding
+ unless TkCore::WITH_ENCODING
+ case $KCODE
+ when /^e/i # EUC
+ Tk.encoding = 'euc-jp'
+ Tk.encoding_system = 'euc-jp'
+ when /^s/i # SJIS
begin
- val = other.numeric
- other = val
- rescue
- other = other.value
+ if Tk.encoding_system == 'cp932'
+ Tk.encoding = 'cp932'
+ else
+ Tk.encoding = 'shiftjis'
+ Tk.encoding_system = 'shiftjis'
+ end
+ rescue StandardError, NameError
+ Tk.encoding = 'shiftjis'
+ Tk.encoding_system = 'shiftjis'
+ end
+ when /^u/i # UTF8
+ Tk.encoding = 'utf-8'
+ Tk.encoding_system = 'utf-8'
+ else # NONE
+ if defined? DEFAULT_TK_ENCODING
+ Tk.encoding_system = DEFAULT_TK_ENCODING
end
- end
- if other.kind_of?(Numeric)
begin
- return self.numeric <=> other
- rescue
- return self.value <=> other.to_s
+ Tk.encoding = Tk.encoding_system
+ rescue StandardError, NameError
+ Tk.encoding = 'utf-8'
+ Tk.encoding_system = 'utf-8'
end
- else
- return self.value <=> other
end
- end
- def to_eval
- @id
- end
+ else ### Ruby 1.9 !!!!!!!!!!!!
+ loc_enc_obj = ::Encoding.find(::Encoding.locale_charmap)
+ ext_enc_obj = ::Encoding.default_external
+ tksys_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding_system)
+ # p [Tk.encoding, Tk.encoding_system, loc_enc_obj, ext_enc_obj]
- def unset(elem=nil)
- if elem
- INTERP._eval(Kernel.format('global %s; unset %s(%s)',
- @id, @id, tk_tcl2ruby(elem)))
+=begin
+ if ext_enc_obj == Tk::Encoding::UNKNOWN
+ if defind? DEFAULT_TK_ENCODING
+ if DEFAULT_TK_ENCODING.kind_of?(::Encoding)
+ tk_enc_name = DEFAULT_TK_ENCODING.name
+ tksys_enc_name = DEFAULT_TK_ENCODING.name
+ else
+ tk_enc_name = DEFAULT_TK_ENCODING
+ tksys_enc_name = DEFAULT_TK_ENCODING
+ end
+ else
+ tk_enc_name = loc_enc_obj.name
+ tksys_enc_name = loc_enc_obj.name
+ end
else
- INTERP._eval(Kernel.format('global %s; unset %s', @id, @id))
+ tk_enc_name = ext_enc_obj.name
+ tksys_enc_name = ext_enc_obj.name
end
- end
- alias remove unset
- def trace_callback(elem, op)
- if @trace_var.kind_of? Array
- @trace_var.each{|m,e| e.call(self,elem,op) if m.index(op)}
- end
- if elem.kind_of? String
- if @trace_elem[elem].kind_of? Array
- @trace_elem[elem].each{|m,e| e.call(self,elem,op) if m.index(op)}
- end
- end
- end
+ # Tk.encoding = tk_enc_name
+ Tk.default_encoding = tk_enc_name
+ Tk.encoding_system = tksys_enc_name
+=end
- def trace(opts, cmd)
- @trace_var = [] if @trace_var == nil
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- @trace_var.unshift([opts,cmd])
- if @trace_opts == nil
- TkVar_CB_TBL[@id] = self
- @trace_opts = opts
- Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
- else
- newopts = @trace_opts.dup
- opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- if newopts != @trace_opts
- Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ if ext_enc_obj == Tk::Encoding::UNKNOWN
+ if loc_enc_obj == Tk::Encoding::UNKNOWN
+ # use Tk.encoding_system
+ else
+ # use locale_charmap
+ begin
+ loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj)
+ if loc_enc_name && loc_enc_name != tksys_enc_name
+ # use locale_charmap
+ Tk.encoding_system = loc_enc_name
+ else
+ # use Tk.encoding_system
+ end
+ rescue ArgumentError
+ # unsupported encoding on Tk -> use Tk.encoding_system
+ end
end
- end
- end
-
- def trace_element(elem, opts, cmd)
- @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('')
- @trace_elem[elem].unshift([opts,cmd])
- if @trace_opts == nil
- TkVar_CB_TBL[@id] = self
- @trace_opts = opts
- Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
else
- newopts = @trace_opts.dup
- opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- if newopts != @trace_opts
- Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ begin
+ ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj)
+ if ext_enc_name && ext_enc_name != tksys_enc_name
+ # use default_external
+ Tk.encoding_system = ext_enc_name
+ else
+ # use Tk.encoding_system
+ end
+ rescue ArgumentError
+ # unsupported encoding on Tk -> use Tk.encoding_system
end
end
- end
- def trace_vinfo
- return [] unless @trace_var
- @trace_var.dup
- end
- def trace_vinfo_for_element(elem)
- return [] unless @trace_elem
- return [] unless @trace_elem[elem]
- @trace_elem[elem].dup
- end
+ # setup Tk.encoding
+ enc_name = nil
- def trace_vdelete(opts,cmd)
- return unless @trace_var.kind_of? Array
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- idx = -1
- newopts = ''
- @trace_var.each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
+ begin
+ default_def = DEFAULT_TK_ENCODING
+ if ::Encoding.find(default_def.to_s) != Tk::Encoding::UNKNOWN
+ enc_name = Tk::Encoding::ENCODING_TABLE.get_name(default_def)
+ end
+ rescue NameError
+ # ignore
+ enc_name = nil
+ rescue ArgumentError
+ enc_name = nil
+ fail ArgumentError,
+ "DEFAULT_TK_ENCODING has an unknown encoding #{default_def}"
+ end
+
+ unless enc_name
+ if ext_enc_obj == Tk::Encoding::UNKNOWN
+ if loc_enc_obj == Tk::Encoding::UNKNOWN
+ # use Tk.encoding_system
+ enc_name = tksys_enc_name
+ else
+ # use locale_charmap
+ begin
+ loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj)
+ if loc_enc_name && loc_enc_name != tksys_enc_name
+ # use locale_charmap
+ enc_name = loc_enc_name
+ else
+ # use Tk.encoding_system
+ enc_name = tksys_enc_name
+ end
+ rescue ArgumentError
+ # unsupported encoding on Tk -> use Tk.encoding_system
+ enc_name = tksys_enc_name
+ end
+ end
+ else
+ begin
+ ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj)
+ if ext_enc_name && ext_enc_name != tksys_enc_name
+ # use default_external
+ enc_name = ext_enc_name
+ else
+ # use Tk.encoding_system
+ enc_name = tksys_enc_name
+ end
+ rescue ArgumentError
+ # unsupported encoding on Tk -> use Tk.encoding_system
+ enc_name = tksys_enc_name
+ end
end
- e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- }
- if idx >= 0
- @trace_var.delete_at(idx)
- else
- return
end
- @trace_elem.each{|elem|
- @trace_elem[elem].each{|e|
- e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- }
- }
+ Tk.default_encoding = (enc_name)? enc_name: tksys_enc_name
+ end
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+else
+ # dummy methods
+ module Tk
+ module Encoding
+ extend Encoding
+
+ def force_default_encoding=(mode)
+ nil
end
- end
- end
- def trace_vdelete_for_element(elem,opts,cmd)
- return unless @trace_elem.kind_of? Hash
- return unless @trace_elem[elem].kind_of? Array
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- idx = -1
- @trace_elem[elem].each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
+ def force_default_encoding?
+ nil
end
- }
- if idx >= 0
- @trace_elem[elem].delete_at(idx)
- else
- return
- end
- newopts = ''
- @trace_var.each{|e|
- e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- }
- @trace_elem.each{|elem|
- @trace_elem[elem].each{|e|
- e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- }
- }
+ def default_encoding=(enc)
+ nil
+ end
+ def default_encoding
+ nil
+ end
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ def encoding=(name)
+ nil
+ end
+ def encoding
+ nil
+ end
+ def encoding_names
+ nil
+ end
+ def encoding_system
+ nil
+ end
+ def encoding_system=(enc)
+ nil
end
- end
- end
-end
-class TkVarAccess<TkVariable
- def self.new(name, *args)
- return TkVar_ID_TBL[name] if TkVar_ID_TBL[name]
- super(name, *args)
- end
+ def encoding_convertfrom(str, enc=None)
+ str
+ end
+ alias encoding_convert_from encoding_convertfrom
- def initialize(varname, val=nil)
- @id = varname
- TkVar_ID_TBL[@id] = self
- if val
- s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"' #"
- INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
+ def encoding_convertto(str, enc=None)
+ str
+ end
+ alias encoding_convert_to encoding_convertto
+ def encoding_dirs
+ nil
+ end
+ def encoding_dirs=(dir_array)
+ nil
+ end
end
- end
-end
-module Tk
- begin
- auto_path = INTERP._invoke('set', 'auto_path')
- rescue
- begin
- auto_path = INTERP._invoke('set', 'env(TCLLIBPATH)')
- rescue
- auto_path = Tk::LIBRARY
- end
+ extend Encoding
end
- AUTO_PATH = TkVarAccess.new('auto_path', auto_path)
-
-=begin
- AUTO_OLDPATH = tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath'))
- AUTO_OLDPATH.each{|s| s.freeze}
- AUTO_OLDPATH.freeze
-=end
-
- TCL_PACKAGE_PATH = TkVarAccess.new('tcl_pkgPath')
- PACKAGE_PATH = TCL_PACKAGE_PATH
+ class TclTkIp
+ attr_accessor :encoding
- TCL_LIBRARY_PATH = TkVarAccess.new('tcl_libPath')
- LIBRARY_PATH = TCL_LIBRARY_PATH
+ alias __eval _eval
+ alias __invoke _invoke
- TCL_PRECISION = TkVarAccess.new('tcl_precision')
+ alias _eval_with_enc _eval
+ alias _invoke_with_enc _invoke
+ end
end
-module TkSelection
- include Tk
- extend Tk
- TkCommandNames = ['selection'.freeze].freeze
-
- def self.clear(sel=nil)
- if sel
- tk_call 'selection', 'clear', '-selection', sel
- else
- tk_call 'selection', 'clear'
- end
- end
- def self.clear_on_display(win, sel=nil)
- if sel
- tk_call 'selection', 'clear', '-displayof', win, '-selection', sel
+module TkBindCore
+ #def bind(context, cmd=Proc.new, *args)
+ # Tk.bind(self, context, cmd, *args)
+ #end
+ def bind(context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
else
- tk_call 'selection', 'clear', '-displayof', win
+ cmd = Proc.new
end
- end
- def clear(sel=nil)
- TkSelection.clear_on_display(self, sel)
- self
- end
-
- def self.get(keys=nil)
- tk_call 'selection', 'get', *hash_kv(keys)
- end
- def self.get_on_display(win, keys=nil)
- tk_call 'selection', 'get', '-displayof', win, *hash_kv(keys)
- end
- def get(keys=nil)
- TkSelection.get_on_display(self, sel)
- end
-
- def self.handle(win, func=Proc.new, keys=nil, &b)
- if func.kind_of?(Hash) && keys == nil
- keys = func
- func = Proc.new(&b)
- end
- args = ['selection', 'handle']
- args += hash_kv(keys)
- args += [win, func]
- tk_call(*args)
- end
- def handle(func=Proc.new, keys=nil, &b)
- TkSelection.handle(self, func, keys, &b)
+ Tk.bind(self, context, cmd, *args)
end
- def self.get_owner(sel=nil)
- if sel
- window(tk_call('selection', 'own', '-selection', sel))
+ #def bind_append(context, cmd=Proc.new, *args)
+ # Tk.bind_append(self, context, cmd, *args)
+ #end
+ def bind_append(context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
else
- window(tk_call('selection', 'own'))
+ cmd = Proc.new
end
- end
- def self.get_owner_on_display(win, sel=nil)
- if sel
- window(tk_call('selection', 'own', '-displayof', win, '-selection', sel))
- else
- window(tk_call('selection', 'own', '-displayof', win))
- end
- end
- def get_owner(sel=nil)
- TkSelection.get_owner_on_display(self, sel)
- self
+ Tk.bind_append(self, context, cmd, *args)
end
- def self.set_owner(win, keys=nil)
- tk_call('selection', 'own', *(hash_kv(keys) << win))
+ def bind_remove(context)
+ Tk.bind_remove(self, context)
end
- def set_owner(keys=nil)
- TkSelection.set_owner(self, keys)
- self
+
+ def bindinfo(context=nil)
+ Tk.bindinfo(self, context)
end
end
-module TkKinput
- include Tk
- extend Tk
-
- TkCommandNames = [
- 'kinput_start'.freeze,
- 'kinput_send_spot'.freeze,
- 'kanjiInput'.freeze
- ].freeze
- def TkKinput.start(window, style=None)
- tk_call 'kinput_start', window.path, style
- end
- def kinput_start(style=None)
- TkKinput.start(self, style)
+module TkTreatFont
+ def __font_optkeys
+ ['font']
end
+ private :__font_optkeys
- def TkKinput.send_spot(window)
- tk_call 'kinput_send_spot', window.path
- end
- def kinput_send_spot
- TkKinput.send_spot(self)
+ def __pathname
+ self.path
end
+ private :__pathname
- def TkKinput.input_start(window, keys=nil)
- tk_call 'kanjiInput', 'start', window.path, *hash_kv(keys)
- end
- def kanji_input_start(keys=nil)
- TkKinput.input_start(self, keys)
- end
+ ################################
- def TkKinput.attribute_config(window, slot, value=None)
- if slot.kind_of? Hash
- tk_call 'kanjiInput', 'attribute', window.path, *hash_kv(slot)
- else
- tk_call 'kanjiInput', 'attribute', window.path, "-#{slot}", value
+ 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
- end
- def kinput_attribute_config(slot, value=None)
- TkKinput.attribute_config(self, slot, value)
- end
- def TkKinput.attribute_info(window, slot=nil)
- if slot
- conf = tk_split_list(tk_call('kanjiInput', 'attribute',
- window.path, "-#{slot}"))
- conf[0] = conf[0][1..-1]
- conf
- else
- tk_split_list(tk_call('kanjiInput', 'attribute',
- window.path)).collect{|conf|
- conf[0] = conf[0][1..-1]
- conf
+ win, tag = __pathname.split(':')
+
+ if key
+ pathname = [win, tag, key].join(';')
+ TkFont.used_on(pathname) ||
+ TkFont.init_widget_font(pathname, *__confinfo_cmd)
+ elsif optkeys.size == 1
+ pathname = [win, tag, optkeys[0]].join(';')
+ TkFont.used_on(pathname) ||
+ TkFont.init_widget_font(pathname, *__confinfo_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, *__confinfo_cmd)
}
+ fonts
end
end
- def kinput_attribute_info(slot=nil)
- TkKinput.attribute_info(self, slot)
- end
-
- def TkKinput.input_end(window)
- tk_call 'kanjiInput', 'end', window.path
- end
- def kanji_input_end
- TkKinput.input_end(self)
- end
-end
-
-module TkXIM
- include Tk
- extend Tk
-
- TkCommandNames = ['imconfigure'.freeze].freeze
+ alias fontobj font_configinfo
- def TkXIM.useinputmethods(window=nil, value=nil)
- if window
- if value
- tk_call 'tk', 'useinputmethods', '-displayof', window.path, value
- else
- tk_call 'tk', 'useinputmethods', '-displayof', window.path
- end
- else
- if value
- tk_call 'tk', 'useinputmethods', value
- else
- tk_call 'tk', 'useinputmethods'
- end
- end
- end
+ def font_configure(slot)
+ pathname = __pathname
- def TkXIM.caret(window, keys=nil)
- if keys
- tk_call('tk', 'caret', window, *hash_kv(keys))
- self
- else
- lst = tk_split_list(tk_call('tk', 'caret', window))
- info = {}
- while key = lst.shift
- info[key[1..-1]] = lst.shift
- end
- info
- end
- end
+ slot = _symbolkey2str(slot)
- def TkXIM.configure(window, slot, value=None)
- begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
- if slot.kind_of? Hash
- tk_call 'imconfigure', window.path, *hash_kv(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
- tk_call 'imconfigure', window.path, "-#{slot}", value
+ 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
+ fnt = hash_kv(fnt) if fnt.kind_of?(Hash)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__config_cmd << "-#{optkey}" << fnt))
+ else
+ begin
+ tk_call(*(__config_cmd << "-#{optkey}" << fnt))
+ rescue
+ # ignore
+ end
+ end
+ end
+ end
+ next
end
end
- rescue
- end
- end
- def TkXIM.configinfo(window, slot=nil)
- begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
- if slot
- conf = tk_split_list(tk_call('imconfigure', window.path, "-#{slot}"))
- conf[0] = conf[0][1..-1]
- conf
- else
- tk_split_list(tk_call('imconfigure', window.path)).collect{|conf|
- conf[0] = conf[0][1..-1]
- conf
- }
- end
- else
- []
- end
- rescue
- []
- end
- end
+ lfnt = slot.delete(l_optkey)
+ lfnt = slot.delete(a_optkey) if slot.key?(a_optkey)
+ kfnt = slot.delete(k_optkey)
- def useinputmethods(value=nil)
- TkXIM.useinputmethods(self, value)
- end
-
- def caret(keys=nil)
- TkXIM.caret(self, keys=nil)
- end
+ 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
+ }
- def imconfigure(slot, value=None)
- TkXIM.configinfo(self, slot, value)
+ # configure other (without font) options
+ tk_call(*(__config_cmd.concat(hash_kv(slot)))) if slot != {}
+ self
end
- def imconfiginfo(slot=nil)
- TkXIM.configinfo(self, slot)
- end
-end
-
-module TkWinfo
- include Tk
- extend Tk
-
- TkCommandNames = ['winfo'.freeze].freeze
-
- def TkWinfo.atom(name, win=nil)
- if win
- number(tk_call('winfo', 'atom', '-displayof', win, name))
+ def latinfont_configure(ltn, keys=nil)
+ if ltn.kind_of?(Array)
+ key = ltn[1]
+ ltn = ltn[0]
else
- number(tk_call('winfo', 'atom', name))
+ key = nil
end
- end
- def winfo_atom(name)
- TkWinfo.atom(name, self)
- end
- def TkWinfo.atomname(id, win=nil)
- if win
- tk_call('winfo', 'atomname', '-displayof', win, id)
- else
- tk_call('winfo', 'atomname', id)
+ optkeys = __font_optkeys
+ if key && !optkeys.find{|opt| opt.to_s == key.to_s}
+ fail ArgumentError, "unknown font option name `#{key}'"
end
- end
- def winfo_atomname(id)
- TkWinfo.atomname(id, self)
- end
- def TkWinfo.cells(window)
- number(tk_call('winfo', 'cells', window.path))
- end
- def winfo_cells
- TkWinfo.cells self
- end
+ win, tag = __pathname.split(':')
- def TkWinfo.children(window)
- c = tk_call('winfo', 'children', window.path)
- list(c)
- end
- def winfo_children
- TkWinfo.children self
- end
+ optkeys = [key] if key
- def TkWinfo.classname(window)
- tk_call 'winfo', 'class', window.path
- end
- def winfo_classname
- TkWinfo.classname self
- end
- alias winfo_class winfo_classname
+ optkeys.each{|optkey|
+ optkey = optkey.to_s
- def TkWinfo.colormapfull(window)
- bool(tk_call('winfo', 'colormapfull', window.path))
- end
- def winfo_colormapfull
- TkWinfo.colormapfull self
+ 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
+ ltn = hash_kv(ltn) if ltn.kind_of?(Hash)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__config_cmd << "-#{optkey}" << ltn))
+ else
+ begin
+ tk_call(*(__config_cmd << "-#{optkey}" << ltn))
+ rescue => e
+ # ignore
+ end
+ end
+ 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 TkWinfo.containing(rootX, rootY, win=nil)
- if win
- window(tk_call('winfo', 'containing', '-displayof', win, rootX, rootY))
+ def kanjifont_configure(knj, keys=nil)
+ if knj.kind_of?(Array)
+ key = knj[1]
+ knj = knj[0]
else
- window(tk_call('winfo', 'containing', rootX, rootY))
+ key = nil
end
- end
- def winfo_containing(x, y)
- TkWinfo.containing(x, y, self)
- end
- def TkWinfo.depth(window)
- number(tk_call('winfo', 'depth', window.path))
- end
- def winfo_depth
- TkWinfo.depth self
- end
+ optkeys = __font_optkeys
+ if key && !optkeys.find{|opt| opt.to_s == key.to_s}
+ fail ArgumentError, "unknown font option name `#{key}'"
+ end
- def TkWinfo.exist?(window)
- bool(tk_call('winfo', 'exists', window.path))
- end
- def winfo_exist?
- TkWinfo.exist? self
- end
+ win, tag = __pathname.split(':')
- def TkWinfo.fpixels(window, dist)
- number(tk_call('winfo', 'fpixels', window.path, dist))
- end
- def winfo_fpixels(dist)
- TkWinfo.fpixels self, dist
- end
+ optkeys = [key] if key
- def TkWinfo.geometry(window)
- tk_call('winfo', 'geometry', window.path)
- end
- def winfo_geometry
- TkWinfo.geometry self
- end
+ optkeys.each{|optkey|
+ optkey = optkey.to_s
- def TkWinfo.height(window)
- number(tk_call('winfo', 'height', window.path))
- end
- def winfo_height
- TkWinfo.height self
- end
+ pathname = [win, tag, optkey].join(';')
- def TkWinfo.id(window)
- tk_call('winfo', 'id', window.path)
- end
- def winfo_id
- TkWinfo.id self
+ 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
+ knj = hash_kv(knj) if knj.kind_of?(Hash)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__config_cmd << "-#{optkey}" << knj))
+ else
+ begin
+ tk_call(*(__config_cmd << "-#{optkey}" << knj))
+ rescue => e
+ # ignore
+ end
+ end
+ 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 TkWinfo.interps(window=nil)
- if window
- tk_split_simplelist(tk_call('winfo', 'interps',
- '-displayof', window.path))
+ def font_copy(win, wintag=nil, winkey=nil, targetkey=nil)
+ if wintag
+ if winkey
+ fnt = win.tagfontobj(wintag, winkey).dup
+ else
+ fnt = win.tagfontobj(wintag).dup
+ end
else
- tk_split_simplelist(tk_call('winfo', 'interps'))
+ if winkey
+ fnt = win.fontobj(winkey).dup
+ else
+ fnt = win.fontobj.dup
+ end
end
- end
- def winfo_interps
- TkWinfo.interps self
- end
-
- def TkWinfo.mapped?(window)
- bool(tk_call('winfo', 'ismapped', window.path))
- end
- def winfo_mapped?
- TkWinfo.mapped? self
- end
- def TkWinfo.manager(window)
- tk_call('winfo', 'manager', window.path)
- end
- def winfo_manager
- TkWinfo.manager self
+ if targetkey
+ fnt.call_font_configure([__pathname, targetkey], *(__config_cmd << {}))
+ else
+ fnt.call_font_configure(__pathname, *(__config_cmd << {}))
+ end
+ self
end
- def TkWinfo.appname(window)
- tk_call('winfo', 'name', window.path)
- end
- def winfo_appname
- TkWinfo.appname self
- end
+ def latinfont_copy(win, 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
- def TkWinfo.parent(window)
- window(tk_call('winfo', 'parent', window.path))
- end
- def winfo_parent
- TkWinfo.parent self
+ if wintag
+ if winkey
+ fontobj.latin_replace(win.tagfontobj(wintag, winkey).latin_font_id)
+ else
+ fontobj.latin_replace(win.tagfontobj(wintag).latin_font_id)
+ end
+ else
+ if winkey
+ fontobj.latin_replace(win.fontobj(winkey).latin_font_id)
+ else
+ fontobj.latin_replace(win.fontobj.latin_font_id)
+ end
+ end
+ self
end
+ alias asciifont_copy latinfont_copy
- def TkWinfo.widget(id, win=nil)
- if win
- window(tk_call('winfo', 'pathname', '-displayof', win, id))
+ def kanjifont_copy(win, wintag=nil, winkey=nil, targetkey=nil)
+ if targetkey
+ fontobj(targetkey).dup.call_font_configure([__pathname, targetkey],
+ *(__config_cmd << {}))
else
- window(tk_call('winfo', 'pathname', id))
+ fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {}))
end
- end
- def winfo_widget(id)
- TkWinfo.widget id, self
- end
- def TkWinfo.pixels(window, dist)
- number(tk_call('winfo', 'pixels', window.path, dist))
- end
- def winfo_pixels(dist)
- TkWinfo.pixels self, dist
+ if wintag
+ if winkey
+ fontobj.kanji_replace(win.tagfontobj(wintag, winkey).kanji_font_id)
+ else
+ fontobj.kanji_replace(win.tagfontobj(wintag).kanji_font_id)
+ end
+ else
+ if winkey
+ fontobj.kanji_replace(win.fontobj(winkey).kanji_font_id)
+ else
+ fontobj.kanji_replace(win.fontobj.kanji_font_id)
+ end
+ end
+ self
end
+end
- def TkWinfo.reqheight(window)
- number(tk_call('winfo', 'reqheight', window.path))
- end
- def winfo_reqheight
- TkWinfo.reqheight self
- end
- def TkWinfo.reqwidth(window)
- number(tk_call('winfo', 'reqwidth', window.path))
- end
- def winfo_reqwidth
- TkWinfo.reqwidth self
- end
+module TkConfigMethod
+ include TkUtil
+ include TkTreatFont
- def TkWinfo.rgb(window, color)
- list(tk_call('winfo', 'rgb', window.path, color))
+ def TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ @mode || false
end
- def winfo_rgb(color)
- TkWinfo.rgb self, color
+ def TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode)
+ fail SecurityError, "can't change the mode" if $SAFE>=4
+ @mode = (mode)? true: false
end
- def TkWinfo.rootx(window)
- number(tk_call('winfo', 'rootx', window.path))
- end
- def winfo_rootx
- TkWinfo.rootx self
+ def __cget_cmd
+ [self.path, 'cget']
end
+ private :__cget_cmd
- def TkWinfo.rooty(window)
- number(tk_call('winfo', 'rooty', window.path))
- end
- def winfo_rooty
- TkWinfo.rooty self
+ def __config_cmd
+ [self.path, 'configure']
end
+ private :__config_cmd
- def TkWinfo.screen(window)
- tk_call 'winfo', 'screen', window.path
- end
- def winfo_screen
- TkWinfo.screen self
+ def __confinfo_cmd
+ __config_cmd
end
+ private :__confinfo_cmd
- def TkWinfo.screencells(window)
- number(tk_call('winfo', 'screencells', window.path))
- end
- def winfo_screencells
- TkWinfo.screencells self
+ def __configinfo_struct
+ {:key=>0, :alias=>1, :db_name=>1, :db_class=>2,
+ :default_value=>3, :current_value=>4}
end
+ private :__configinfo_struct
- def TkWinfo.screendepth(window)
- number(tk_call('winfo', 'screendepth', window.path))
- end
- def winfo_screendepth
- TkWinfo.screendepth self
+ def __optkey_aliases
+ {}
end
+ private :__optkey_aliases
- def TkWinfo.screenheight (window)
- number(tk_call('winfo', 'screenheight', window.path))
- end
- def winfo_screenheight
- TkWinfo.screenheight self
+ def __numval_optkeys
+ []
end
+ private :__numval_optkeys
- def TkWinfo.screenmmheight(window)
- number(tk_call('winfo', 'screenmmheight', window.path))
- end
- def winfo_screenmmheight
- TkWinfo.screenmmheight self
+ def __numstrval_optkeys
+ []
end
+ private :__numstrval_optkeys
- def TkWinfo.screenmmwidth(window)
- number(tk_call('winfo', 'screenmmwidth', window.path))
- end
- def winfo_screenmmwidth
- TkWinfo.screenmmwidth self
+ def __boolval_optkeys
+ ['exportselection', 'jump', 'setgrid', 'takefocus']
end
+ private :__boolval_optkeys
- def TkWinfo.screenvisual(window)
- tk_call('winfo', 'screenvisual', window.path)
- end
- def winfo_screenvisual
- TkWinfo.screenvisual self
+ def __strval_optkeys
+ [
+ 'text', 'label', 'show', 'data', 'file',
+ 'activebackground', 'activeforeground', 'background',
+ 'disabledforeground', 'disabledbackground', 'foreground',
+ 'highlightbackground', 'highlightcolor', 'insertbackground',
+ 'selectbackground', 'selectforeground', 'troughcolor'
+ ]
end
+ private :__strval_optkeys
- def TkWinfo.screenwidth(window)
- number(tk_call('winfo', 'screenwidth', window.path))
- end
- def winfo_screenwidth
- TkWinfo.screenwidth self
+ def __listval_optkeys
+ []
end
+ private :__listval_optkeys
- def TkWinfo.server(window)
- tk_call 'winfo', 'server', window.path
- end
- def winfo_server
- TkWinfo.server self
+ def __numlistval_optkeys
+ []
end
+ private :__numlistval_optkeys
- def TkWinfo.toplevel(window)
- window(tk_call('winfo', 'toplevel', window.path))
- end
- def winfo_toplevel
- TkWinfo.toplevel self
+ def __tkvariable_optkeys
+ ['variable', 'textvariable']
end
+ private :__tkvariable_optkeys
- def TkWinfo.visual(window)
- tk_call('winfo', 'visual', window.path)
- end
- def winfo_visual
- TkWinfo.visual self
+ def __val2ruby_optkeys # { key=>proc, ... }
+ # The method is used to convert a opt-value to a ruby's object.
+ # When get the value of the option "key", "proc.call(value)" is called.
+ {}
end
+ private :__val2ruby_optkeys
- def TkWinfo.visualid(window)
- tk_call('winfo', 'visualid', window.path)
- end
- def winfo_visualid
- TkWinfo.visualid self
+ def __ruby2val_optkeys # { key=>proc, ... }
+ # The method is used to convert a ruby's object to a opt-value.
+ # When set the value of the option "key", "proc.call(value)" is called.
+ # That is, "-#{key} #{proc.call(value)}".
+ {}
end
+ private :__ruby2val_optkeys
- def TkWinfo.visualsavailable(window, includeids=false)
- if includeids
- list(tk_call('winfo', 'visualsavailable', window.path, "includeids"))
- else
- list(tk_call('winfo', 'visualsavailable', window.path))
- end
- end
- def winfo_visualsavailable(includeids=false)
- TkWinfo.visualsavailable self, includeids
+ def __methodcall_optkeys # { key=>method, ... }
+ # The method is used to both of get and set.
+ # Usually, the 'key' will not be a widget option.
+ {}
end
+ private :__methodcall_optkeys
- def TkWinfo.vrootheight(window)
- number(tk_call('winfo', 'vrootheight', window.path))
- end
- def winfo_vrootheight
- TkWinfo.vrootheight self
+ def __keyonly_optkeys # { def_key=>undef_key or nil, ... }
+ {}
end
+ private :__keyonly_optkeys
- def TkWinfo.vrootwidth(window)
- number(tk_call('winfo', 'vrootwidth', window.path))
- end
- def winfo_vrootwidth
- TkWinfo.vrootwidth self
- end
-
- def TkWinfo.vrootx(window)
- number(tk_call('winfo', 'vrootx', window.path))
- end
- def winfo_vrootx
- TkWinfo.vrootx self
- end
-
- def TkWinfo.vrooty(window)
- number(tk_call('winfo', 'vrooty', window.path))
- end
- def winfo_vrooty
- TkWinfo.vrooty self
- end
-
- def TkWinfo.width(window)
- number(tk_call('winfo', 'width', window.path))
- end
- def winfo_width
- TkWinfo.width self
- end
-
- def TkWinfo.x(window)
- number(tk_call('winfo', 'x', window.path))
- end
- def winfo_x
- TkWinfo.x self
- end
-
- def TkWinfo.y(window)
- number(tk_call('winfo', 'y', window.path))
- end
- def winfo_y
- TkWinfo.y self
+ 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
+ private :__conv_keyonly_opts
- def TkWinfo.viewable(window)
- bool(tk_call('winfo', 'viewable', window.path))
- end
- def winfo_viewable
- TkWinfo.viewable self
+ def config_hash_kv(keys, enc_mode = nil, conf = nil)
+ hash_kv(__conv_keyonly_opts(keys), enc_mode, conf)
end
- def TkWinfo.pointerx(window)
- number(tk_call('winfo', 'pointerx', window.path))
- end
- def winfo_pointerx
- TkWinfo.pointerx self
- end
+ ################################
- def TkWinfo.pointery(window)
- number(tk_call('winfo', 'pointery', window.path))
- end
- def winfo_pointery
- TkWinfo.pointery self
+ def [](id)
+ cget(id)
end
- def TkWinfo.pointerxy(window)
- list(tk_call('winfo', 'pointerxy', window.path))
- end
- def winfo_pointerxy
- TkWinfo.pointerxy self
+ def []=(id, val)
+ configure(id, val)
+ val
end
-end
-module TkPack
- include Tk
- extend Tk
-
- TkCommandNames = ['pack'.freeze].freeze
-
- def configure(win, *args)
- if args[-1].kind_of?(Hash)
- keys = args.pop
- end
- wins = [win.epath]
- for i in args
- wins.push i.epath
+ def __cget_core(slot)
+ orig_slot = slot
+ slot = slot.to_s
+
+ if slot.length == 0
+ fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
end
- tk_call "pack", 'configure', *(wins+hash_kv(keys))
- end
- def forget(*args)
- tk_call 'pack', 'forget' *args
- end
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
- def info(slave)
- ilist = list(tk_call('pack', 'info', slave.epath))
- info = {}
- while key = ilist.shift
- info[key[1..-1]] = ilist.shift
+ if ( method = _symbolkey2str(__val2ruby_optkeys())[slot] )
+ optval = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
+ begin
+ return method.call(optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
+ return optval
+ end
end
- return info
- end
- def propagate(master, bool=None)
- if bool == None
- bool(tk_call('pack', 'propagate', master.epath))
- else
- tk_call('pack', 'propagate', master.epath, bool)
+ if ( method = _symbolkey2str(__methodcall_optkeys)[slot] )
+ return self.__send__(method)
end
- end
- def slaves(master)
- list(tk_call('pack', 'slaves', master.epath))
- end
+ case slot
+ when /^(#{__numval_optkeys.join('|')})$/
+ begin
+ number(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
+ rescue
+ nil
+ end
- module_function :configure, :forget, :info, :propagate, :slaves
-end
+ when /^(#{__numstrval_optkeys.join('|')})$/
+ num_or_str(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
-module TkGrid
- include Tk
- extend Tk
+ when /^(#{__boolval_optkeys.join('|')})$/
+ begin
+ bool(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
+ rescue
+ nil
+ end
- TkCommandNames = ['grid'.freeze].freeze
+ when /^(#{__listval_optkeys.join('|')})$/
+ simplelist(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
- def bbox(*args)
- list(tk_call('grid', 'bbox', *args))
- end
-
- def configure(widget, *args)
- if args[-1].kind_of?(Hash)
- keys = args.pop
- end
- wins = []
- args.unshift(widget)
- for i in args
- case i
- when '-', 'x', '^' # RELATIVE PLACEMENT
- wins.push(i)
+ when /^(#{__numlistval_optkeys.join('|')})$/
+ conf = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
+ if conf =~ /^[0-9+-]/
+ list(conf)
else
- wins.push(i.epath)
+ conf
end
- end
- tk_call "grid", 'configure', *(wins+hash_kv(keys))
- end
- def columnconfigure(master, index, args)
- tk_call "grid", 'columnconfigure', master, index, *hash_kv(args)
- end
+ when /^(#{__strval_optkeys.join('|')})$/
+ _fromUTF8(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
- def rowconfigure(master, index, args)
- tk_call "grid", 'rowconfigure', master, index, *hash_kv(args)
- end
-
- def columnconfiginfo(master, index, slot=nil)
- if slot
- tk_call('grid', 'columnconfigure', master, index, "-#{slot}").to_i
- else
- ilist = list(tk_call('grid', 'columnconfigure', master, index))
- info = {}
- while key = ilist.shift
- info[key[1..-1]] = ilist.shift
+ 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
- info
- end
- end
-
- def rowconfiginfo(master, index, slot=nil)
- if slot
- tk_call('grid', 'rowconfigure', master, index, "-#{slot}").to_i
- else
- ilist = list(tk_call('grid', 'rowconfigure', master, index))
- info = {}
- while key = ilist.shift
- info[key[1..-1]] = ilist.shift
+ if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
+ # obsolete; just for compatibility
+ fnt.kanji_font
+ else
+ fnt
end
- info
- end
- end
- def add(widget, *args)
- configure(widget, *args)
- end
+ when /^(#{__tkvariable_optkeys.join('|')})$/
+ v = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
+ (v.empty?)? nil: TkVarAccess.new(v)
- def forget(*args)
- tk_call 'grid', 'forget', *args
- end
-
- def info(slave)
- list(tk_call('grid', 'info', slave))
- end
-
- def location(master, x, y)
- list(tk_call('grid', 'location', master, x, y))
- end
-
- def propagate(master, bool=None)
- if bool == None
- bool(tk_call('grid', 'propagate', master.epath))
else
- tk_call('grid', 'propagate', master.epath, bool)
+ tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true)
end
end
+ private :__cget_core
- def remove(*args)
- tk_call 'grid', 'remove', *args
- end
-
- def size(master)
- tk_call 'grid', 'size', master
- end
-
- def slaves(master, args)
- list(tk_call('grid', 'slaves', master, *hash_kv(args)))
- end
-
- module_function :bbox, :forget, :propagate, :info
- module_function :remove, :size, :slaves, :location
- module_function :configure, :columnconfigure, :rowconfigure
- module_function :columnconfiginfo, :rowconfiginfo
-end
-
-module TkPlace
- include Tk
- extend Tk
-
- TkCommandNames = ['place'.freeze].freeze
-
- def configure(win, slot, value=None)
- if slot.kind_of? Hash
- tk_call 'place', 'configure', win.epath, *hash_kv(slot)
- else
- tk_call 'place', 'configure', win.epath, "-#{slot}", value
- end
- end
-
- def configinfo(win, slot = nil)
- # for >= Tk8.4a2 ?
- if slot
- conf = tk_split_list(tk_call('place', 'configure',
- win.epath, "-#{slot}") )
- conf[0] = conf[0][1..-1]
- conf
+ def cget(slot)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __cget_core(slot)
else
- tk_split_simplelist(tk_call('place', 'configure',
- win.epath)).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- conf
- }
+ begin
+ __cget_core(slot)
+ rescue => e
+ if current_configinfo.has_key?(slot.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ end
end
end
-
- def forget(win)
- tk_call 'place', 'forget', win
- end
-
- def info(win)
- ilist = list(tk_call('place', 'info', win.epath))
- info = {}
- while key = ilist.shift
- info[key[1..-1]] = ilist.shift
- end
- return info
+ def cget_strict(slot)
+ # never use TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __cget_core(slot)
end
- def slaves(master)
- list(tk_call('place', 'slaves', master.epath))
- end
-
- module_function :configure, :configinfo, :forget, :info, :slaves
-end
-
-module TkOptionDB
- include Tk
- extend Tk
-
- TkCommandNames = ['option'.freeze].freeze
-
- module Priority
- WidgetDefault = 20
- StartupFile = 40
- UserDefault = 60
- Interactive = 80
- end
-
- def add(pat, value, pri=None)
- if $SAFE >= 4
- fail SecurityError, "can't call 'TkOptionDB.add' at $SAFE >= 4"
- end
- tk_call 'option', 'add', pat, value, pri
- end
- def clear
- if $SAFE >= 4
- fail SecurityError, "can't call 'TkOptionDB.crear' at $SAFE >= 4"
- end
- tk_call 'option', 'clear'
- end
- def get(win, name, klass)
- tk_call('option', 'get', win ,name, klass)
- end
- def readfile(file, pri=None)
- tk_call 'option', 'readfile', file, pri
- end
- module_function :add, :clear, :get, :readfile
-
- def read_entries(file, f_enc=nil)
- if TkCore::INTERP.safe?
- fail SecurityError,
- "can't call 'TkOptionDB.read_entries' on a safe interpreter"
- end
-
- i_enc = Tk.encoding()
-
- unless f_enc
- f_enc = i_enc
- end
-
- ent = []
- cline = ''
- open(file, 'r') {|f|
- while line = f.gets
- cline += line.chomp!
- case cline
- when /\\$/ # continue
- cline.chop!
- next
- when /^!/ # coment
- cline = ''
- next
- when /^([^:]+):\s(.*)$/
- pat = $1
- val = $2
- p "ResourceDB: #{[pat, val].inspect}" if $DEBUG
- pat = TkCore::INTERP._toUTF8(pat, f_enc)
- pat = TkCore::INTERP._fromUTF8(pat, i_enc)
- val = TkCore::INTERP._toUTF8(val, f_enc)
- val = TkCore::INTERP._fromUTF8(val, i_enc)
- ent << [pat, val]
- cline = ''
- else # unknown --> ignore
- cline = ''
- next
- end
- end
- }
- ent
- end
- module_function :read_entries
-
- def read_with_encoding(file, f_enc=nil, pri=None)
- # try to read the file as an OptionDB file
- readfile(file, pri).each{|pat, val|
- add(pat, val, pri)
- }
+ def __configure_core(slot, value=None)
+ if slot.kind_of? Hash
+ slot = _symbolkey2str(slot)
-=begin
- i_enc = Tk.encoding()
-
- unless f_enc
- f_enc = i_enc
- end
-
- cline = ''
- open(file, 'r') {|f|
- while line = f.gets
- cline += line.chomp!
- case cline
- when /\\$/ # continue
- cline.chop!
- next
- when /^!/ # coment
- cline = ''
- next
- when /^([^:]+):\s(.*)$/
- pat = $1
- val = $2
- p "ResourceDB: #{[pat, val].inspect}" if $DEBUG
- pat = TkCore::INTERP._toUTF8(pat, f_enc)
- pat = TkCore::INTERP._fromUTF8(pat, i_enc)
- val = TkCore::INTERP._toUTF8(val, f_enc)
- val = TkCore::INTERP._fromUTF8(val, i_enc)
- add(pat, val, pri)
- cline = ''
- else # unknown --> ignore
- cline = ''
- next
- end
- end
- }
-=end
- end
- module_function :read_with_encoding
+ __optkey_aliases.each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if slot.has_key?(alias_name)
+ slot[real_name.to_s] = slot.delete(alias_name)
+ end
+ }
- # support procs on the resource database
- @@resource_proc_class = Class.new
- class << @@resource_proc_class
- private :new
-
- CARRIER = '.'.freeze
- METHOD_TBL = TkCore::INTERP.create_table
- ADD_METHOD = false
- SAFE_MODE = 4
-
- def __closed_block_check__(str)
- depth = 0
- str.scan(/[{}]/){|x|
- if x == "{"
- depth += 1
- elsif x == "}"
- depth -= 1
- end
- if depth <= 0 && !($' =~ /\A\s*\Z/)
- fail RuntimeError, "bad string for procedure : #{str.inspect}"
- end
+ __methodcall_optkeys.each{|key, method|
+ value = slot.delete(key.to_s)
+ self.__send__(method, value) if value
}
- str
- end
- def __check_proc_string__(str)
- # If you want to check the proc_string, do it in this method.
- # Please define this in the block given to 'new_proc_class' method.
- str
- end
+ __ruby2val_optkeys.each{|key, method|
+ key = key.to_s
+ slot[key] = method.call(slot[key]) if slot.has_key?(key)
+ }
- def method_missing(id, *args)
- res_proc = self::METHOD_TBL[id]
- unless res_proc.kind_of? Proc
- if id == :new || !(self::METHOD_TBL.has_key?(id) || self::ADD_METHOD)
- raise NoMethodError,
- "not support resource-proc '#{id.id2name}' for #{self.name}"
+ __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
- proc_str = TkOptionDB.get(self::CARRIER, id.id2name, '').strip
- proc_str = '{' + proc_str + '}' unless /\A\{.*\}\Z/ =~ proc_str
- proc_str = __closed_block_check__(proc_str)
- proc_str = __check_proc_string__(proc_str)
- res_proc = eval('Proc.new' + proc_str)
- self::METHOD_TBL[id] = res_proc
- end
- proc{
- $SAFE = self::SAFE_MODE
- res_proc.call(*args)
- }.call
- end
-
- private :__closed_block_check__, :__check_proc_string__, :method_missing
- end
- @@resource_proc_class.freeze
-
- def __create_new_class(klass, func, safe = 4, add = false, parent = nil)
- klass = klass.to_s if klass.kind_of? Symbol
- unless (?A..?Z) === klass[0]
- fail ArgumentError, "bad string '#{klass}' for class name"
- end
- unless func.kind_of? Array
- fail ArgumentError, "method-list must be Array"
- end
- func_str = func.join(' ')
- if parent == nil
- install_win(parent)
- elsif parent <= @@resource_proc_class
- install_win(parent::CARRIER)
- else
- fail ArgumentError, "parent must be Resource-Proc class"
- end
- carrier = Tk.tk_call('frame', @path, '-class', klass)
+ }
- body = <<-"EOD"
- class #{klass} < TkOptionDB.module_eval('@@resource_proc_class')
- CARRIER = '#{carrier}'.freeze
- METHOD_TBL = TkCore::INTERP.create_table
- ADD_METHOD = #{add}
- SAFE_MODE = #{safe}
- %w(#{func_str}).each{|f| METHOD_TBL[f.intern] = nil }
+ 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
- EOD
- if parent.kind_of?(Class) && parent <= @@resource_proc_class
- parent.class_eval(body)
- eval(parent.name + '::' + klass)
else
- eval(body)
- eval('TkOptionDB::' + klass)
- end
- end
- module_function :__create_new_class
- private_class_method :__create_new_class
-
- def __remove_methods_of_proc_class(klass)
- # for security, make these methods invalid
- class << klass
- attr_reader :class_eval, :name, :superclass,
- :ancestors, :const_defined?, :const_get, :const_set,
- :constants, :included_modules, :instance_methods,
- :method_defined?, :module_eval, :private_instance_methods,
- :protected_instance_methods, :public_instance_methods,
- :remove_const, :remove_method, :undef_method,
- :to_s, :inspect, :display, :method, :methods,
- :instance_eval, :instance_variables, :kind_of?, :is_a?,
- :private_methods, :protected_methods, :public_methods
- end
- end
- module_function :__remove_methods_of_proc_class
- private_class_method :__remove_methods_of_proc_class
-
- RAND_BASE_CNT = [0]
- RAND_BASE_HEAD = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
- RAND_BASE_CHAR = RAND_BASE_HEAD + 'abcdefghijklmnopqrstuvwxyz0123456789_'
- def __get_random_basename
- name = '%s%03d' % [RAND_BASE_HEAD[rand(RAND_BASE_HEAD.size),1],
- RAND_BASE_CNT[0]]
- len = RAND_BASE_CHAR.size
- (6+rand(10)).times{
- name << RAND_BASE_CHAR[rand(len),1]
- }
- RAND_BASE_CNT[0] = RAND_BASE_CNT[0] + 1
- name
- end
- module_function :__get_random_basename
- private_class_method :__get_random_basename
-
- # define new proc class :
- # If you want to modify the new class or create a new subclass,
- # you must do such operation in the block parameter.
- # Because the created class is flozen after evaluating the block.
- def new_proc_class(klass, func, safe = 4, add = false, parent = nil, &b)
- new_klass = __create_new_class(klass, func, safe, add, parent)
- new_klass.class_eval(&b) if block_given?
- __remove_methods_of_proc_class(new_klass)
- new_klass.freeze
- new_klass
- end
- module_function :new_proc_class
-
- def eval_under_random_base(parent = nil, &b)
- new_klass = __create_new_class(__get_random_basename(),
- [], 4, false, parent)
- ret = new_klass.class_eval(&b) if block_given?
- __remove_methods_of_proc_class(new_klass)
- new_klass.freeze
- ret
- end
- module_function :eval_under_random_base
-
- def new_proc_class_random(klass, func, safe = 4, add = false, &b)
- eval_under_random_base(){
- TkOption.new_proc_class(klass, func, safe, add, self, &b)
- }
- end
- module_function :new_proc_class_random
-end
-TkOption = TkOptionDB
-TkResourceDB = TkOptionDB
-
-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')
+ orig_slot = slot
+ slot = slot.to_s
+ if slot.length == 0
+ fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
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)
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
- if slot.key?('font')
- fnt = slot.delete('font')
- if fnt.kind_of? TkFont
- return fnt.call_font_configure(self.path, self.path,'configure',slot)
+ 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(__ruby2val_optkeys)[slot] )
+ tk_call(*(__config_cmd << "-#{slot}" << method.call(value)))
+ 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
- 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
+ tk_call(*(__config_cmd << "-#{slot}" << value))
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
+ private :__configure_core
- 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
+ def __check_available_configure_options(keys)
+ availables = self.current_configinfo.keys
- 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
+ # add non-standard keys
+ availables |= __font_optkeys.map{|k|
+ [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"]
+ }.flatten
+ availables |= __methodcall_optkeys.keys.map{|k| k.to_s}
+ availables |= __keyonly_optkeys.keys.map{|k| k.to_s}
- return fobj.call_font_configure(self.path, self.path, 'configure', {})
+ keys = _symbolkey2str(keys)
+ keys.delete_if{|k, v| !(availables.include?(k))}
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
+ def configure(slot, value=None)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __configure_core(slot, value)
+ else
+ if slot.kind_of?(Hash)
+ begin
+ __configure_core(slot)
+ rescue
+ slot = __check_available_configure_options(slot)
+ __configure_core(slot) unless slot.empty?
+ end
else
- fobj.kanji_replace(knj)
+ begin
+ __configure_core(slot, value)
+ rescue => e
+ if current_configinfo.has_key?(slot.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ end
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 TkTreatItemFont
- def __conf_cmd(idx)
- raise NotImplementedError, "need to define `__conf_cmd'"
- end
- def __item_pathname(tagOrId)
- raise NotImplementedError, "need to define `__item_pathname'"
- end
- private :__conf_cmd, :__item_pathname
-
- def tagfont_configinfo(tagOrId, name = nil)
- pathname = __item_pathname(tagOrId)
- ret = TkFont.used_on(pathname)
- if ret == nil
-=begin
- if name
- ret = name
+ def configure_cmd(slot, value)
+ configure(slot, install_cmd(value))
+ end
+
+ def __configinfo_core(slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (slot &&
+ slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
+ fontkey = $2
+ # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true)
+ conf[__configinfo_struct[:key]] =
+ conf[__configinfo_struct[:key]][1..-1]
+ if ( ! __configinfo_struct[:alias] \
+ || conf.size > __configinfo_struct[:alias] + 1 )
+ fnt = conf[__configinfo_struct[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt)
+ end
+ 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
- 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)
- end
- ret
- end
- alias tagfontobj tagfont_configinfo
-
- def tagfont_configure(tagOrId, slot)
- pathname = __item_pathname(tagOrId)
- slot = _symbolkey2str(slot)
+ if slot
+ slot = slot.to_s
+
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
+ case slot
+ when /^(#{__val2ruby_optkeys().keys.join('|')})$/
+ method = _symbolkey2str(__val2ruby_optkeys())[slot]
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd() << "-#{slot}")), false, true)
+ if ( __configinfo_struct[:default_value] \
+ && conf[__configinfo_struct[:default_value]] )
+ optval = conf[__configinfo_struct[:default_value]]
+ begin
+ val = method.call(optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__configinfo_struct[:default_value]] = val
+ end
+ if ( conf[__configinfo_struct[:current_value]] )
+ optval = conf[__configinfo_struct[:current_value]]
+ begin
+ val = method.call(optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__configinfo_struct[:current_value]] = val
+ end
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ when /^(#{__tkvariable_optkeys.join('|')})$/
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ if ( __configinfo_struct[:default_value] \
+ && conf[__configinfo_struct[:default_value]])
+ v = conf[__configinfo_struct[:default_value]]
+ if v.empty?
+ conf[__configinfo_struct[:default_value]] = nil
+ else
+ conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
+ end
+ end
+ if ( conf[__configinfo_struct[:current_value]] )
+ v = conf[__configinfo_struct[:current_value]]
+ if v.empty?
+ conf[__configinfo_struct[:current_value]] = nil
+ else
+ conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
+ end
+ end
+
+ else
+ # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true)
+ 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
- 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)
-
- 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
- end
-
- slot['font'] = fnt
- tk_call(self.path, __conf_cmd(0), __conf_cmd(1),
- tagOrId, *hash_kv(slot))
- end
- return self
- end
- end
+ conf
- lfnt = slot.delete('latinfont')
- lfnt = slot.delete('asciifont') if slot.key?('asciifont')
- kfnt = slot.delete('kanjifont')
+ else
+ # ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).collect{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ ret = tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).collect{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ conf[__configinfo_struct[:key]] =
+ conf[__configinfo_struct[:key]][1..-1]
+
+ optkey = conf[__configinfo_struct[:key]]
+ case optkey
+ when /^(#{__val2ruby_optkeys().keys.join('|')})$/
+ method = _symbolkey2str(__val2ruby_optkeys())[optkey]
+ if ( __configinfo_struct[:default_value] \
+ && conf[__configinfo_struct[:default_value]] )
+ optval = conf[__configinfo_struct[:default_value]]
+ begin
+ val = method.call(optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__configinfo_struct[:default_value]] = val
+ end
+ if ( conf[__configinfo_struct[:current_value]] )
+ optval = conf[__configinfo_struct[:current_value]]
+ begin
+ val = method.call(optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__configinfo_struct[:current_value]] = val
+ end
+
+ 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
+
+ when /^(#{__tkvariable_optkeys.join('|')})$/
+ if ( __configinfo_struct[:default_value] \
+ && conf[__configinfo_struct[:default_value]] )
+ v = conf[__configinfo_struct[:default_value]]
+ if v.empty?
+ conf[__configinfo_struct[:default_value]] = nil
+ else
+ conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
+ end
+ end
+ if ( conf[__configinfo_struct[:current_value]] )
+ v = conf[__configinfo_struct[:current_value]]
+ if v.empty?
+ conf[__configinfo_struct[:current_value]] = nil
+ else
+ conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
+ end
+ 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
- if lfnt && kfnt
- return TkFont.new(lfnt, kfnt).call_font_configure(pathname, self.path,
- __conf_cmd(0),
- __conf_cmd(1),
- tagOrId, slot)
- end
+ conf
+ }
- 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 != {}
- self
- end
+ __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}$/}
+ fnt = fontconf[__configinfo_struct[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__configinfo_struct[:default_value]] \
+ = TkNamedFont.new(fnt)
+ end
+ fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
+ ret.push(fontconf)
+ 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
- else
- tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', ltn)
- return self
- end
+ __methodcall_optkeys.each{|optkey, method|
+ ret << [optkey.to_s, '', '', '', self.__send__(method)]
+ }
- 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)
+ ret
+ end
end
- end
- return fobj.call_font_configure(pathname, self.path,
- __conf_cmd(0), __conf_cmd(1), tagOrId, {})
- end
- alias asciitagfont_configure latintagfont_configure
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (slot &&
+ slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
+ fontkey = $2
+ # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true)
+ conf[__configinfo_struct[:key]] =
+ conf[__configinfo_struct[:key]][1..-1]
+
+ if ( ! __configinfo_struct[:alias] \
+ || conf.size > __configinfo_struct[:alias] + 1 )
+ fnt = conf[__configinfo_struct[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt)
+ end
+ 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
+
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
+ case slot
+ when /^(#{__val2ruby_optkeys().keys.join('|')})$/
+ method = _symbolkey2str(__val2ruby_optkeys())[slot]
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+ if ( __configinfo_struct[:default_value] \
+ && conf[__configinfo_struct[:default_value]] )
+ optval = conf[__configinfo_struct[:default_value]]
+ begin
+ val = method.call(optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__configinfo_struct[:default_value]] = val
+ end
+ if ( conf[__configinfo_struct[:current_value]] )
+ optval = conf[__configinfo_struct[:current_value]]
+ begin
+ val = method.call(optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__configinfo_struct[:current_value]] = val
+ end
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ 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 /^(#{__tkvariable_optkeys.join('|')})$/
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+
+ if ( __configinfo_struct[:default_value] \
+ && conf[__configinfo_struct[:default_value]] )
+ v = conf[__configinfo_struct[:default_value]]
+ if v.empty?
+ conf[__configinfo_struct[:default_value]] = nil
+ else
+ conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
+ end
+ end
+ if ( conf[__configinfo_struct[:current_value]] )
+ v = conf[__configinfo_struct[:current_value]]
+ if v.empty?
+ conf[__configinfo_struct[:current_value]] = nil
+ else
+ conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
+ end
+ end
+
+ when /^(#{__strval_optkeys.join('|')})$/
+ # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
+ else
+ # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
+ conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true)
+ 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
- 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
- else
- tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', knj)
- return self
- end
+ else
+ ret = {}
+ # tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).each{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).each{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ conf[__configinfo_struct[:key]] =
+ conf[__configinfo_struct[:key]][1..-1]
+
+ optkey = conf[__configinfo_struct[:key]]
+ case optkey
+ when /^(#{__val2ruby_optkeys().keys.join('|')})$/
+ method = _symbolkey2str(__val2ruby_optkeys())[optkey]
+ if ( __configinfo_struct[:default_value] \
+ && conf[__configinfo_struct[:default_value]] )
+ optval = conf[__configinfo_struct[:default_value]]
+ begin
+ val = method.call(optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__configinfo_struct[:default_value]] = val
+ end
+ if ( conf[__configinfo_struct[:current_value]] )
+ optval = conf[__configinfo_struct[:current_value]]
+ begin
+ val = method.call(optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__configinfo_struct[:current_value]] = val
+ end
+
+ 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
+
+ when /^(#{__tkvariable_optkeys.join('|')})$/
+ if ( __configinfo_struct[:default_value] \
+ && conf[__configinfo_struct[:default_value]] )
+ v = conf[__configinfo_struct[:default_value]]
+ if v.empty?
+ conf[__configinfo_struct[:default_value]] = nil
+ else
+ conf[__configinfo_struct[:default_value]] = TkVarAccess.new
+ end
+ end
+ if ( conf[__configinfo_struct[:current_value]] )
+ v = conf[__configinfo_struct[:current_value]]
+ if v.empty?
+ conf[__configinfo_struct[:current_value]] = nil
+ else
+ conf[__configinfo_struct[:current_value]] = TkVarAccess.new
+ end
+ 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
+ }
- 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
+ __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)
+ fnt = fontconf[__configinfo_struct[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__configinfo_struct[:default_value]] \
+ = TkNamedFont.new(fnt)
+ end
+ fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
+ ret[optkey] = fontconf
+ end
+ }
- return fobj.call_font_configure(pathname, self.path,
- __conf_cmd(0), __conf_cmd(1), tagOrId, {})
- end
+ __methodcall_optkeys.each{|optkey, method|
+ ret[optkey.to_s] = ['', '', '', self.__send__(method)]
+ }
- def tagfont_copy(tagOrId, window, wintag=nil)
- pathname = __item_pathname(tagOrId)
- if wintag
- fnt = window.tagfontobj(wintag).dup
- else
- fnt = window.fontobj.dup
+ ret
+ end
+ end
end
- fnt.call_font_configure(pathname, self.path,
- __conf_cmd(0), __conf_cmd(1), tagOrId, {})
- return self
end
+ private :__configinfo_core
- 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 configinfo(slot = nil)
+ if slot && TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ begin
+ __configinfo_core(slot)
+ rescue
+ Array.new(__configinfo_struct.values.max).unshift(slot.to_s)
+ end
else
- tagfontobj(tagOrId).latin_replace(window.fontobj.latin_font_id)
+ __configinfo_core(slot)
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)
- else
- tagfontobj(tagOrId).kanji_replace(window.fontobj.kanji_font_id)
+ 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
- self
end
end
class TkObject<TkKernel
+ extend TkCore
include Tk
- include TkTreatFont
+ include TkConfigMethod
include TkBindCore
- def path
- return @path
- end
+### --> definition is moved to TkUtil module
+# def path
+# @path
+# end
def epath
- return @path
+ @path
end
def to_eval
@@ -3772,171 +4674,126 @@ class TkObject<TkKernel
end
def tk_send(cmd, *rest)
- tk_call path, cmd, *rest
+ tk_call(path, cmd, *rest)
+ end
+ def tk_send_without_enc(cmd, *rest)
+ tk_call_without_enc(path, cmd, *rest)
+ end
+ def tk_send_with_enc(cmd, *rest)
+ tk_call_with_enc(path, cmd, *rest)
+ end
+ # private :tk_send, :tk_send_without_enc, :tk_send_with_enc
+
+ def tk_send_to_list(cmd, *rest)
+ tk_call_to_list(path, cmd, *rest)
+ end
+ def tk_send_to_list_without_enc(cmd, *rest)
+ tk_call_to_list_without_enc(path, cmd, *rest)
+ end
+ def tk_send_to_list_with_enc(cmd, *rest)
+ tk_call_to_list_with_enc(path, cmd, *rest)
+ end
+ def tk_send_to_simplelist(cmd, *rest)
+ tk_call_to_simplelist(path, cmd, *rest)
+ end
+ def tk_send_to_simplelist_without_enc(cmd, *rest)
+ tk_call_to_simplelist_without_enc(path, cmd, *rest)
+ end
+ def tk_send_to_simplelist_with_enc(cmd, *rest)
+ tk_call_to_simplelist_with_enc(path, cmd, *rest)
end
- private :tk_send
def method_missing(id, *args)
name = id.id2name
case args.length
when 1
- configure name, args[0]
+ if name[-1] == ?=
+ configure name[0..-2], args[0]
+ args[0]
+ else
+ configure name, args[0]
+ self
+ end
when 0
begin
- cget name
+ cget(name)
rescue
- fail NameError,
- "undefined local variable or method `#{name}' for #{self.to_s}",
- error_at
+ if self.kind_of?(TkWindow)
+ fail NameError,
+ "unknown option '#{id}' for #{self.inspect} (deleted widget?)"
+ else
+ super(id, *args)
+ end
+# fail NameError,
+# "undefined local variable or method `#{name}' for #{self.to_s}",
+# error_at
end
else
- fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
+ super(id, *args)
+# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
end
end
+=begin
def [](id)
- cget id
+ cget(id)
end
def []=(id, val)
- configure id, val
- end
-
- def cget(slot)
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- tk_call path, 'cget', "-#{slot}"
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_call(path, 'cget', "-#{slot}"))
- fnt = tk_tcl2ruby(tk_call(path, 'cget', "-font"))
- unless fnt.kind_of?(TkFont)
- fnt = fontobj(fnt)
- end
- if slot == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby tk_call(path, 'cget', "-#{slot}")
- end
- end
-
- def configure(slot, value=None)
- if slot.kind_of? Hash
- if (slot['font'] || slot[:font] ||
- slot['kanjifont'] || slot[:kanjifont] ||
- slot['latinfont'] || slot[:latinfont] ||
- slot['asciifont'] || slot[:asciifont] )
- font_configure(slot)
- elsif slot.size > 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 slot == 'font' || slot == :font ||
- slot == 'kanjifont' || slot == :kanjifont
- conf = tk_split_simplelist(tk_send('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(tk_send('configure', "-#{slot}") )
- else
- conf = tk_split_list(tk_send('configure', "-#{slot}") )
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- ret = tk_split_simplelist(tk_send('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
- }
- 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
+ configure(id, val)
+ val
end
+=end
def event_generate(context, keys=nil)
- if keys
- tk_call('event', 'generate', path,
- "<#{tk_event_sequence(context)}>", *hash_kv(keys))
+ if context.kind_of?(TkEvent::Event)
+ context.generate(self, ((keys)? keys: {}))
+ elsif keys
+ #tk_call('event', 'generate', path,
+ # "<#{tk_event_sequence(context)}>", *hash_kv(keys))
+ tk_call_without_enc('event', 'generate', path,
+ "<#{tk_event_sequence(context)}>",
+ *hash_kv(keys, true))
else
- tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>")
+ #tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>")
+ tk_call_without_enc('event', 'generate', path,
+ "<#{tk_event_sequence(context)}>")
end
end
def tk_trace_variable(v)
- unless v.kind_of?(TkVariable)
- fail(ArgumentError,
- Kernel.format("type error (%s); must be TkVariable object",
- v.class))
- end
+ #unless v.kind_of?(TkVariable)
+ # fail(ArgumentError, "type error (#{v.class}); must be TkVariable object")
+ #end
v
end
private :tk_trace_variable
def destroy
- # tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id
+ #tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id
end
end
+
class TkWindow<TkObject
include TkWinfo
extend TkBindCore
+ include Tk::Wm_for_General
+
+ @@WIDGET_INSPECT_FULL = false
+ def TkWindow._widget_inspect_full_?
+ @@WIDGET_INSPECT_FULL
+ end
+ def TkWindow._widget_inspect_full_=(mode)
+ @@WIDGET_INSPECT_FULL = (mode && true) || false
+ end
+ TkCommandNames = [].freeze
+ ## ==> 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
@@ -3948,19 +4805,19 @@ class TkWindow<TkObject
widgetname = keys.delete('widgetname')
install_win(if parent then parent.path end, widgetname)
without_creating = keys.delete('without_creating')
- if without_creating && !widgetname
- fail ArgumentError,
- "if set 'without_creating' to true, need to define 'widgetname'"
- end
+ # if without_creating && !widgetname
+ # fail ArgumentError,
+ # "if set 'without_creating' to true, need to define 'widgetname'"
+ # end
elsif keys
keys = _symbolkey2str(keys)
widgetname = keys.delete('widgetname')
install_win(if parent then parent.path end, widgetname)
without_creating = keys.delete('without_creating')
- if without_creating && !widgetname
- fail ArgumentError,
- "if set 'without_creating' to true, need to define 'widgetname'"
- end
+ # if without_creating && !widgetname
+ # fail ArgumentError,
+ # "if set 'without_creating' to true, need to define 'widgetname'"
+ # end
else
install_win(if parent then parent.path end)
end
@@ -3974,25 +4831,110 @@ class TkWindow<TkObject
else
p 'create_self has args' if $DEBUG
fontkeys = {}
+ methodkeys = {}
if keys
- ['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
- fontkeys[key] = keys.delete(key) if keys.key?(key)
+ #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
+ # fontkeys[key] = keys.delete(key) if keys.key?(key)
+ #}
+ __font_optkeys.each{|key|
+ fkey = key.to_s
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+ fkey = "kanji#{key}"
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+ fkey = "latin#{key}"
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+ fkey = "ascii#{key}"
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+ }
+
+ __optkey_aliases.each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if keys.has_key?(alias_name)
+ keys[real_name.to_s] = keys.delete(alias_name)
+ end
+ }
+
+ __methodcall_optkeys.each{|key|
+ key = key.to_s
+ methodkeys[key] = keys.delete(key) if keys.key?(key)
+ }
+
+ __ruby2val_optkeys.each{|key, method|
+ key = key.to_s
+ keys[key] = method.call(keys[key]) if keys.has_key?(key)
}
end
if without_creating && keys
- configure(keys)
+ #configure(keys)
+ configure(__conv_keyonly_opts(keys))
else
- create_self(keys)
+ #create_self(keys)
+ create_self(__conv_keyonly_opts(keys))
end
font_configure(fontkeys) unless fontkeys.empty?
+ configure(methodkeys) unless methodkeys.empty?
end
end
- def create_self
- fail RuntimeError, "TkWindow is an abstract class"
+ def create_self(keys)
+ # may need to override
+ begin
+ cmd = self.class::TkCommandNames[0]
+ fail unless (cmd.kind_of?(String) && cmd.length > 0)
+ rescue
+ fail RuntimeError, "class #{self.class} may be an abstract class"
+ end
+
+ if keys and keys != None
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ rescue => e
+ tk_call_without_enc(cmd, @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ begin
+ # try to configure
+ configure(keys)
+ rescue
+ # fail => includes options adaptable when creattion only?
+ begin
+ tk_call_without_enc('destroy', @path)
+ rescue
+ # cannot rescue options error
+ fail e
+ else
+ # re-create widget
+ tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ end
+ end
+ end
+ end
+ end
+ else
+ tk_call_without_enc(cmd, @path)
+ end
end
private :create_self
+ def inspect
+ if @@WIDGET_INSPECT_FULL
+ super
+ else
+ str = super
+ str[0..(str.index(' '))] << '@path=' << @path.inspect << '>'
+ end
+ end
+
+ def exist?
+ TkWinfo.exist?(self)
+ end
+
def bind_class
@db_class || self.class()
end
@@ -4016,7 +4958,12 @@ class TkWindow<TkObject
end
def pack(keys = nil)
- tk_call 'pack', epath, *hash_kv(keys)
+ #tk_call_without_enc('pack', epath, *hash_kv(keys, true))
+ if keys
+ TkPack.configure(self, keys)
+ else
+ TkPack.configure(self)
+ end
self
end
@@ -4027,47 +4974,69 @@ class TkWindow<TkObject
else
keys = {'in'=>target}
end
- tk_call 'pack', epath, *hash_kv(keys)
+ #tk_call 'pack', epath, *hash_kv(keys)
+ TkPack.configure(self, keys)
self
end
- def unpack
- tk_call 'pack', 'forget', epath
+ def pack_forget
+ #tk_call_without_enc('pack', 'forget', epath)
+ TkPack.forget(self)
self
end
- alias pack_forget unpack
+ alias unpack pack_forget
def pack_config(slot, value=None)
+ #if slot.kind_of? Hash
+ # tk_call 'pack', 'configure', epath, *hash_kv(slot)
+ #else
+ # tk_call 'pack', 'configure', epath, "-#{slot}", value
+ #end
if slot.kind_of? Hash
- tk_call 'pack', 'configure', epath, *hash_kv(slot)
+ TkPack.configure(self, slot)
else
- tk_call 'pack', 'configure', epath, "-#{slot}", value
+ TkPack.configure(self, slot=>value)
end
end
+ alias pack_configure pack_config
def pack_info()
- ilist = list(tk_call('pack', 'info', epath))
- info = {}
- while key = ilist.shift
- info[key[1..-1]] = ilist.shift
- end
- return info
+ #ilist = list(tk_call('pack', 'info', epath))
+ #info = {}
+ #while key = ilist.shift
+ # info[key[1..-1]] = ilist.shift
+ #end
+ #return info
+ TkPack.info(self)
end
def pack_propagate(mode=None)
+ #if mode == None
+ # bool(tk_call('pack', 'propagate', epath))
+ #else
+ # tk_call('pack', 'propagate', epath, mode)
+ # self
+ #end
if mode == None
- tk_call('pack', 'propagate', epath, mode)
+ TkPack.propagate(self)
else
- bool(tk_call('pack', 'propagate', epath))
+ TkPack.propagate(self, mode)
+ self
end
end
def pack_slaves()
- list(tk_call('pack', 'slaves', epath))
+ #list(tk_call('pack', 'slaves', epath))
+ TkPack.slaves(self)
end
def grid(keys = nil)
- tk_call 'grid', epath, *hash_kv(keys)
+ #tk_call 'grid', epath, *hash_kv(keys)
+ if keys
+ TkGrid.configure(self, keys)
+ else
+ TkGrid.configure(self)
+ end
self
end
@@ -4078,92 +5047,132 @@ class TkWindow<TkObject
else
keys = {'in'=>target}
end
- tk_call 'grid', epath, *hash_kv(keys)
+ #tk_call 'grid', epath, *hash_kv(keys)
+ TkGrid.configure(self, keys)
self
end
- def ungrid
- tk_call 'grid', 'forget', epath
+ def grid_anchor(anchor=None)
+ if anchor == None
+ TkGrid.anchor(self)
+ else
+ TkGrid.anchor(self, anchor)
+ self
+ end
+ end
+
+ def grid_forget
+ #tk_call('grid', 'forget', epath)
+ TkGrid.forget(self)
self
end
- alias grid_forget ungrid
+ alias ungrid grid_forget
def grid_bbox(*args)
- list(tk_call('grid', 'bbox', epath, *args))
+ #list(tk_call('grid', 'bbox', epath, *args))
+ TkGrid.bbox(self, *args)
end
def grid_config(slot, value=None)
+ #if slot.kind_of? Hash
+ # tk_call 'grid', 'configure', epath, *hash_kv(slot)
+ #else
+ # tk_call 'grid', 'configure', epath, "-#{slot}", value
+ #end
if slot.kind_of? Hash
- tk_call 'grid', 'configure', epath, *hash_kv(slot)
+ TkGrid.configure(self, slot)
else
- tk_call 'grid', 'configure', epath, "-#{slot}", value
+ TkGrid.configure(self, slot=>value)
end
end
+ alias grid_configure grid_config
def grid_columnconfig(index, keys)
- tk_call('grid', 'columnconfigure', epath, index, *hash_kv(keys))
+ #tk_call('grid', 'columnconfigure', epath, index, *hash_kv(keys))
+ TkGrid.columnconfigure(self, index, keys)
end
+ alias grid_columnconfigure grid_columnconfig
+ alias grid_column grid_columnconfig
def grid_rowconfig(index, keys)
- tk_call('grid', 'rowconfigure', epath, index, *hash_kv(keys))
+ #tk_call('grid', 'rowconfigure', epath, index, *hash_kv(keys))
+ TkGrid.rowconfigure(self, index, keys)
end
+ alias grid_rowconfigure grid_rowconfig
+ alias grid_row grid_rowconfig
def grid_columnconfiginfo(index, slot=nil)
- if slot
- tk_call('grid', 'columnconfigure', epath, index, "-#{slot}").to_i
- else
- ilist = list(tk_call('grid', 'columnconfigure', epath, index))
- info = {}
- while key = ilist.shift
- info[key[1..-1]] = ilist.shift
- end
- info
- end
+ #if slot
+ # tk_call('grid', 'columnconfigure', epath, index, "-#{slot}").to_i
+ #else
+ # ilist = list(tk_call('grid', 'columnconfigure', epath, index))
+ # info = {}
+ # while key = ilist.shift
+ # info[key[1..-1]] = ilist.shift
+ # end
+ # info
+ #end
+ TkGrid.columnconfiginfo(self, index, slot)
end
def grid_rowconfiginfo(index, slot=nil)
- if slot
- tk_call('grid', 'rowconfigure', epath, index, "-#{slot}").to_i
- else
- ilist = list(tk_call('grid', 'rowconfigure', epath, index))
- info = {}
- while key = ilist.shift
- info[key[1..-1]] = ilist.shift
- end
- info
- end
+ #if slot
+ # tk_call('grid', 'rowconfigure', epath, index, "-#{slot}").to_i
+ #else
+ # ilist = list(tk_call('grid', 'rowconfigure', epath, index))
+ # info = {}
+ # while key = ilist.shift
+ # info[key[1..-1]] = ilist.shift
+ # end
+ # info
+ #end
+ TkGrid.rowconfiginfo(self, index, slot)
end
def grid_info()
- list(tk_call('grid', 'info', epath))
+ #list(tk_call('grid', 'info', epath))
+ TkGrid.info(self)
end
def grid_location(x, y)
- list(tk_call('grid', 'location', epath, x, y))
+ #list(tk_call('grid', 'location', epath, x, y))
+ TkGrid.location(self, x, y)
end
def grid_propagate(mode=None)
+ #if mode == None
+ # bool(tk_call('grid', 'propagate', epath))
+ #else
+ # tk_call('grid', 'propagate', epath, mode)
+ # self
+ #end
if mode == None
- tk_call('grid', 'propagate', epath, mode)
+ TkGrid.propagate(self)
else
- bool(tk_call('grid', 'propagate', epath))
+ TkGrid.propagate(self, mode)
+ self
end
end
def grid_remove()
- tk_call 'grid', 'remove', epath
+ #tk_call 'grid', 'remove', epath
+ TkGrid.remove(self)
+ self
end
def grid_size()
- tk_call 'grid', 'size', epath
+ #list(tk_call('grid', 'size', epath))
+ TkGrid.size(self)
end
def grid_slaves(args)
- list(tk_call('grid', 'slaves', epath, *hash_kv(args)))
+ #list(tk_call('grid', 'slaves', epath, *hash_kv(args)))
+ TkGrid.slaves(self, args)
end
- def place(keys = nil)
- tk_call 'place', epath, *hash_kv(keys)
+ def place(keys)
+ #tk_call 'place', epath, *hash_kv(keys)
+ TkPlace.configure(self, keys)
self
end
@@ -4174,122 +5183,144 @@ class TkWindow<TkObject
else
keys = {'in'=>target}
end
- tk_call 'place', epath, *hash_kv(keys)
+ #tk_call 'place', epath, *hash_kv(keys)
+ TkPlace.configure(self, keys)
self
end
- def unplace
- tk_call 'place', 'forget', epath
+ def place_forget
+ #tk_call 'place', 'forget', epath
+ TkPlace.forget(self)
self
end
- alias place_forget unplace
+ alias unplace place_forget
def place_config(slot, value=None)
- if slot.kind_of? Hash
- tk_call 'place', 'configure', epath, *hash_kv(slot)
- else
- tk_call 'place', 'configure', epath, "-#{slot}", value
- end
+ #if slot.kind_of? Hash
+ # tk_call 'place', 'configure', epath, *hash_kv(slot)
+ #else
+ # tk_call 'place', 'configure', epath, "-#{slot}", value
+ #end
+ TkPlace.configure(self, slot, value)
end
+ alias place_configure place_config
def place_configinfo(slot = nil)
# for >= Tk8.4a2 ?
- if slot
- conf = tk_split_list(tk_call('place', 'configure', epath, "-#{slot}") )
- conf[0] = conf[0][1..-1]
- conf
- else
- tk_split_simplelist(tk_call('place',
- 'configure', epath)).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- conf
- }
- end
+ #if slot
+ # conf = tk_split_list(tk_call('place', 'configure', epath, "-#{slot}") )
+ # conf[0] = conf[0][1..-1]
+ # conf
+ #else
+ # tk_split_simplelist(tk_call('place',
+ # 'configure', epath)).collect{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ # conf[0] = conf[0][1..-1]
+ # conf
+ # }
+ #end
+ TkPlace.configinfo(self, slot)
end
def place_info()
- ilist = list(tk_call('place', 'info', epath))
- info = {}
- while key = ilist.shift
- info[key[1..-1]] = ilist.shift
- end
- return info
+ #ilist = list(tk_call('place', 'info', epath))
+ #info = {}
+ #while key = ilist.shift
+ # info[key[1..-1]] = ilist.shift
+ #end
+ #return info
+ TkPlace.info(self)
end
def place_slaves()
- list(tk_call('place', 'slaves', epath))
+ #list(tk_call('place', 'slaves', epath))
+ TkPlace.slaves(self)
end
- def focus(force=false)
+ def set_focus(force=false)
if force
- tk_call 'focus', '-force', path
+ tk_call_without_enc('focus', '-force', path)
else
- tk_call 'focus', path
+ tk_call_without_enc('focus', path)
end
self
end
+ alias focus set_focus
- def grab(*args)
- if !args or args.length == 0
- tk_call 'grab', 'set', path
- self
- elsif args.length == 1
- case args[0]
- when 'global', :global
- #return(tk_call('grab', 'set', '-global', path))
- tk_call('grab', 'set', '-global', path)
- return self
- when 'release', :release
- #return tk_call('grab', 'release', path)
- tk_call('grab', 'release', path)
- return self
- else
- val = tk_call('grab', args[0], path)
- end
- case args[0]
- when 'current', :current
- return window(val)
- when 'status', :status
- return val
- end
- self
+ def grab(opt = nil)
+ unless opt
+ tk_call_without_enc('grab', 'set', path)
+ return self
+ end
+
+ case opt
+ when 'set', :set
+ tk_call_without_enc('grab', 'set', path)
+ return self
+ when 'global', :global
+ #return(tk_call('grab', 'set', '-global', path))
+ tk_call_without_enc('grab', 'set', '-global', path)
+ return self
+ when 'release', :release
+ #return tk_call('grab', 'release', path)
+ tk_call_without_enc('grab', 'release', path)
+ return self
+ when 'current', :current
+ return window(tk_call_without_enc('grab', 'current', path))
+ when 'status', :status
+ return tk_call_without_enc('grab', 'status', path)
else
- fail ArgumentError, 'wrong # of args'
+ return tk_call_without_enc('grab', opt, path)
end
end
def grab_current
grab('current')
end
+ alias current_grab grab_current
def grab_release
grab('release')
end
+ alias release_grab grab_release
def grab_set
grab('set')
end
+ alias set_grab grab_set
def grab_set_global
grab('global')
end
+ alias set_global_grab grab_set_global
def grab_status
grab('status')
end
def lower(below=None)
+ # below = below.epath if below.kind_of?(TkObject)
+ below = _epath(below)
tk_call 'lower', epath, below
self
end
+ alias lower_window lower
def raise(above=None)
+ #above = above.epath if above.kind_of?(TkObject)
+ above = _epath(above)
tk_call 'raise', epath, above
self
end
+ alias raise_window raise
- def command(cmd=Proc.new)
- configure_cmd 'command', cmd
+ def command(cmd=nil, &b)
+ if cmd
+ configure_cmd('command', cmd)
+ elsif b
+ configure_cmd('command', Proc.new(&b))
+ else
+ cget('command')
+ end
end
- def colormodel model=None
- tk_call 'tk', 'colormodel', path, model
+ def colormodel(model=None)
+ tk_call('tk', 'colormodel', path, model)
self
end
@@ -4306,21 +5337,23 @@ class TkWindow<TkObject
}
if defined?(@cmdtbl)
for id in @cmdtbl
- uninstall_cmd id
+ uninstall_cmd id
end
end
children.each{|path, obj|
- if defined?(@cmdtbl)
- for id in @cmdtbl
- uninstall_cmd id
- end
- end
+ obj.instance_eval{
+ if defined?(@cmdtbl)
+ for id in @cmdtbl
+ uninstall_cmd id
+ end
+ end
+ }
TkCore::INTERP.tk_windows.delete(path)
}
begin
- tk_call 'destroy', epath
+ tk_call_without_enc('destroy', epath)
rescue
end
uninstall_win
@@ -4330,6 +5363,7 @@ class TkWindow<TkObject
if $SAFE >= 4
fail SecurityError, "can't wait visibility at $SAFE >= 4"
end
+ on_thread &= (Thread.list.size != 1)
if on_thread
INTERP._thread_tkwait('visibility', path)
else
@@ -4355,21 +5389,31 @@ class TkWindow<TkObject
if $SAFE >= 4
fail SecurityError, "can't wait destroy at $SAFE >= 4"
end
+ on_thread &= (Thread.list.size != 1)
if on_thread
INTERP._thread_tkwait('window', epath)
else
INTERP._invoke('tkwait', 'window', epath)
end
end
+ alias wait_window wait_destroy
def eventloop_wait_destroy
wait_destroy(false)
end
+ alias eventloop_wait_window eventloop_wait_destroy
def thread_wait_destroy
wait_destroy(true)
end
+ alias thread_wait_window thread_wait_destroy
+
alias tkwait_destroy wait_destroy
+ alias tkwait_window wait_destroy
+
alias eventloop_tkwait_destroy eventloop_wait_destroy
+ alias eventloop_tkwait_window eventloop_wait_destroy
+
alias thread_tkwait_destroy thread_wait_destroy
+ alias thread_tkwait_window thread_wait_destroy
def bindtags(taglist=nil)
if taglist
@@ -4378,23 +5422,24 @@ class TkWindow<TkObject
taglist
else
list(tk_call('bindtags', path)).collect{|tag|
- if tag.kind_of?(String)
- if cls = WidgetClassNames[tag]
- cls
- elsif btag = TkBindTag.id2obj(tag)
- btag
- else
- tag
- end
- else
- tag
- end
+ if tag.kind_of?(String)
+ if cls = WidgetClassNames[tag]
+ cls
+ elsif btag = TkBindTag.id2obj(tag)
+ btag
+ else
+ tag
+ end
+ else
+ tag
+ end
}
end
end
def bindtags=(taglist)
bindtags(taglist)
+ taglist
end
def bindtags_shift
@@ -4408,1418 +5453,7 @@ class TkWindow<TkObject
bindtags(bindtags().unshift(tag))
end
end
-
-class TkRoot<TkWindow
- include Wm
-
-=begin
- ROOT = []
- def TkRoot.new(keys=nil)
- if ROOT[0]
- Tk_WINDOWS["."] = ROOT[0]
- return ROOT[0]
- end
- new = super(:without_creating=>true, :widgetname=>'.')
- if keys # wm commands
- keys.each{|k,v|
- if v.kind_of? Array
- new.send(k,*v)
- else
- new.send(k,v)
- end
- }
- end
- ROOT[0] = new
- Tk_WINDOWS["."] = new
- end
-=end
- def TkRoot.new(keys=nil, &b)
- unless TkCore::INTERP.tk_windows['.']
- TkCore::INTERP.tk_windows['.'] =
- super(:without_creating=>true, :widgetname=>'.')
- end
- root = TkCore::INTERP.tk_windows['.']
- if keys # wm commands
- keys.each{|k,v|
- if v.kind_of? Array
- root.send(k,*v)
- else
- root.send(k,v)
- end
- }
- end
- root.instance_eval(&b) if block_given?
- root
- end
-
- WidgetClassName = 'Tk'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def create_self
- @path = '.'
- end
- def path
- "."
- end
-
- def TkRoot.destroy
- TkCore::INTERP._invoke('destroy', '.')
- end
-end
-
-class TkToplevel<TkWindow
- include Wm
-
- TkCommandNames = ['toplevel'.freeze].freeze
- WidgetClassName = 'Toplevel'.freeze
- WidgetClassNames[WidgetClassName] = self
-
-################# old version
-# def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
-# if screen.kind_of? Hash
-# keys = screen.dup
-# else
-# @screen = screen
-# end
-# @classname = classname
-# if keys.kind_of? Hash
-# keys = keys.dup
-# @classname = keys.delete('classname') if keys.key?('classname')
-# @colormap = keys.delete('colormap') if keys.key?('colormap')
-# @container = keys.delete('container') if keys.key?('container')
-# @screen = keys.delete('screen') if keys.key?('screen')
-# @use = keys.delete('use') if keys.key?('use')
-# @visual = keys.delete('visual') if keys.key?('visual')
-# end
-# super(parent, keys)
-# end
-#
-# def create_self
-# s = []
-# s << "-class" << @classname if @classname
-# s << "-colormap" << @colormap if @colormap
-# s << "-container" << @container if @container
-# s << "-screen" << @screen if @screen
-# s << "-use" << @use if @use
-# s << "-visual" << @visual if @visual
-# tk_call 'toplevel', @path, *s
-# end
-#################
-
- def _wm_command_option_chk(keys)
- keys = {} unless keys
- new_keys = {}
- wm_cmds = {}
- keys.each{|k,v|
- if Wm.method_defined?(k)
- case k
- when 'screen','class','colormap','container','use','visual'
- new_keys[k] = v
- else
- case self.method(k).arity
- when -1,1
- wm_cmds[k] = v
- else
- new_keys[k] = v
- end
- end
- else
- new_keys[k] = v
- end
- }
- [new_keys, wm_cmds]
- end
- private :_wm_command_option_chk
-
- def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
- my_class_name = nil
- if self.class < WidgetClassNames[WidgetClassName]
- my_class_name = self.class.name
- my_class_name = nil if my_class_name == ''
- end
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- if keys.key?('classname')
- keys['class'] = keys.delete('classname')
- end
- @classname = keys['class']
- @colormap = keys['colormap']
- @container = keys['container']
- @screen = keys['screen']
- @use = keys['use']
- @visual = keys['visual']
- if !@classname && my_class_name
- keys['class'] = @classname = my_class_name
- end
- if @classname.kind_of? TkBindTag
- @db_class = @classname
- @classname = @classname.id
- elsif @classname
- @db_class = TkDatabaseClass.new(@classname)
- else
- @db_class = self.class
- @classname = @db_class::WidgetClassName
- end
- keys, cmds = _wm_command_option_chk(keys)
- super(keys)
- cmds.each{|k,v|
- if v.kind_of? Array
- self.send(k,*v)
- else
- self.send(k,v)
- end
- }
- return
- end
-
- if screen.kind_of? Hash
- keys = screen
- else
- @screen = screen
- if classname.kind_of? Hash
- keys = classname
- else
- @classname = classname
- end
- end
- if keys.kind_of? Hash
- keys = _symbolkey2str(keys)
- if keys.key?('classname')
- keys['class'] = keys.delete('classname')
- end
- @classname = keys['class'] unless @classname
- @colormap = keys['colormap']
- @container = keys['container']
- @screen = keys['screen'] unless @screen
- @use = keys['use']
- @visual = keys['visual']
- else
- keys = {}
- end
- if !@classname && my_class_name
- keys['class'] = @classname = my_class_name
- end
- if @classname.kind_of? TkBindTag
- @db_class = @classname
- @classname = @classname.id
- elsif @classname
- @db_class = TkDatabaseClass.new(@classname)
- else
- @db_class = self.class
- @classname = @db_class::WidgetClassName
- end
- keys, cmds = _wm_command_option_chk(keys)
- super(parent, keys)
- cmds.each{|k,v|
- if v.kind_of? Array
- self.send(k,*v)
- else
- self.send(k,v)
- end
- }
- end
-
- def create_self(keys)
- if keys and keys != None
- tk_call 'toplevel', @path, *hash_kv(keys)
- else
- tk_call 'toplevel', @path
- end
- end
-
- def specific_class
- @classname
- end
-
- def self.database_class
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- self
- else
- TkDatabaseClass.new(self.name)
- end
- end
- def self.database_classname
- self.database_class.name
- end
-
- def self.bind(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bind(*args)
- end
- end
- def self.bind_append(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bind_append(*args)
- end
- end
- def self.bind_remove(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bind_remove(*args)
- end
- end
- def self.bindinfo(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bindinfo(*args)
- end
- end
-end
-
-class TkFrame<TkWindow
- TkCommandNames = ['frame'.freeze].freeze
- WidgetClassName = 'Frame'.freeze
- WidgetClassNames[WidgetClassName] = self
-
-################# old version
-# def initialize(parent=nil, keys=nil)
-# if keys.kind_of? Hash
-# keys = keys.dup
-# @classname = keys.delete('classname') if keys.key?('classname')
-# @colormap = keys.delete('colormap') if keys.key?('colormap')
-# @container = keys.delete('container') if keys.key?('container')
-# @visual = keys.delete('visual') if keys.key?('visual')
-# end
-# super(parent, keys)
-# end
-#
-# def create_self
-# s = []
-# s << "-class" << @classname if @classname
-# s << "-colormap" << @colormap if @colormap
-# s << "-container" << @container if @container
-# s << "-visual" << @visual if @visual
-# tk_call 'frame', @path, *s
-# end
-#################
-
- def initialize(parent=nil, keys=nil)
- my_class_name = nil
- if self.class < WidgetClassNames[WidgetClassName]
- my_class_name = self.class.name
- my_class_name = nil if my_class_name == ''
- end
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- else
- if keys
- keys = _symbolkey2str(keys)
- keys['parent'] = parent
- else
- keys = {'parent'=>parent}
- end
- end
- if keys.key?('classname')
- keys['class'] = keys.delete('classname')
- end
- @classname = keys['class']
- @colormap = keys['colormap']
- @container = keys['container']
- @visual = keys['visual']
- if !@classname && my_class_name
- keys['class'] = @classname = my_class_name
- end
- if @classname.kind_of? TkBindTag
- @db_class = @classname
- @classname = @classname.id
- elsif @classname
- @db_class = TkDatabaseClass.new(@classname)
- else
- @db_class = self.class
- @classname = @db_class::WidgetClassName
- end
- super(keys)
- end
-
- def create_self(keys)
- if keys and keys != None
- tk_call 'frame', @path, *hash_kv(keys)
- else
- tk_call 'frame', @path
- end
- end
-
- def database_classname
- @classname
- end
-
- def self.database_class
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- self
- else
- TkDatabaseClass.new(self.name)
- end
- end
- def self.database_classname
- self.database_class.name
- end
-
- def self.bind(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bind(*args)
- end
- end
- def self.bind_append(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bind_append(*args)
- end
- end
- def self.bind_remove(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bind_remove(*args)
- end
- end
- def self.bindinfo(*args)
- if self == WidgetClassNames[WidgetClassName] || self.name == ''
- super(*args)
- else
- TkDatabaseClass.new(self.name).bindinfo(*args)
- end
- end
-end
-
-class TkLabelFrame<TkFrame
- TkCommandNames = ['labelframe'.freeze].freeze
- WidgetClassName = 'Labelframe'.freeze
- WidgetClassNames[WidgetClassName] = self
- def create_self(keys)
- if keys and keys != None
- tk_call 'labelframe', @path, *hash_kv(keys)
- else
- tk_call 'labelframe', @path
- end
- end
-end
-TkLabelframe = TkLabelFrame
-
-class TkPanedWindow<TkWindow
- TkCommandNames = ['panedwindow'.freeze].freeze
- WidgetClassName = 'Panedwindow'.freeze
- WidgetClassNames[WidgetClassName] = self
- def create_self(keys)
- if keys and keys != None
- tk_call 'panedwindow', @path, *hash_kv(keys)
- else
- tk_call 'panedwindow', @path
- end
- end
-
- def add(*args)
- keys = args.pop
- fail ArgumentError, "no window in arguments" unless keys
- if keys && keys.kind_of?(Hash)
- fail ArgumentError, "no window in arguments" if args == []
- args += hash_kv(keys)
- else
- args.push(keys) if keys
- end
- tk_send('add', *args)
- self
- end
-
- def forget(win, *wins)
- tk_send('forget', win, *wins)
- self
- end
- alias del forget
- alias delete forget
- alias remove forget
-
- def identify(x, y)
- list(tk_send('identify', x, y))
- end
-
- def proxy_coord
- list(tk_send('proxy', 'coord'))
- end
- def proxy_forget
- tk_send('proxy', 'forget')
- self
- end
- def proxy_place(x, y)
- tk_send('proxy', 'place', x, y)
- self
- end
-
- def sash_coord(index)
- list(tk_send('sash', 'coord', index))
- end
- def sash_dragto(index)
- tk_send('sash', 'dragto', index, x, y)
- self
- end
- def sash_mark(index, x, y)
- tk_send('sash', 'mark', index, x, y)
- self
- end
- def sash_place(index, x, y)
- tk_send('sash', 'place', index, x, y)
- self
- end
-
- def panecget(win, key)
- tk_tcl2ruby(tk_send('panecget', win, "-#{key}"))
- end
-
- def paneconfigure(win, key, value=nil)
- if key.kind_of? Hash
- tk_send('paneconfigure', win, *hash_kv(key))
- else
- tk_send('paneconfigure', win, "-#{key}", value)
- end
- self
- end
- alias pane_config paneconfigure
-
- def paneconfiginfo(win, key=nil)
- if key
- conf = tk_split_list(tk_send('paneconfigure', win, "-#{key}"))
- conf[0] = conf[0][1..-1]
- conf
- else
- tk_split_simplelist(tk_send('paneconfigure', win)).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- 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
- conf
- }
- end
- end
- alias pane_configinfo paneconfiginfo
-
- def panes
- list(tk_send('panes'))
- end
-end
-TkPanedwindow = TkPanedWindow
-
-class TkLabel<TkWindow
- TkCommandNames = ['label'.freeze].freeze
- WidgetClassName = 'Label'.freeze
- WidgetClassNames[WidgetClassName] = self
- def create_self(keys)
- if keys and keys != None
- tk_call 'label', @path, *hash_kv(keys)
- else
- tk_call 'label', @path
- end
- end
- def textvariable(v)
- configure 'textvariable', tk_trace_variable(v)
- end
-end
-
-class TkButton<TkLabel
- TkCommandNames = ['button'.freeze].freeze
- WidgetClassName = 'Button'.freeze
- WidgetClassNames[WidgetClassName] = self
- def create_self(keys)
- if keys and keys != None
- tk_call 'button', @path, *hash_kv(keys)
- else
- tk_call 'button', @path
- end
- end
- def invoke
- tk_send 'invoke'
- end
- def flash
- tk_send 'flash'
- self
- end
-end
-
-class TkRadioButton<TkButton
- TkCommandNames = ['radiobutton'.freeze].freeze
- WidgetClassName = 'Radiobutton'.freeze
- WidgetClassNames[WidgetClassName] = self
- def create_self(keys)
- if keys and keys != None
- tk_call 'radiobutton', @path, *hash_kv(keys)
- else
- tk_call 'radiobutton', @path
- end
- end
- def deselect
- tk_send 'deselect'
- self
- end
- def select
- tk_send 'select'
- self
- end
- def variable(v)
- configure 'variable', tk_trace_variable(v)
- end
-end
-TkRadiobutton = TkRadioButton
-
-class TkCheckButton<TkRadioButton
- TkCommandNames = ['checkbutton'.freeze].freeze
- WidgetClassName = 'Checkbutton'.freeze
- WidgetClassNames[WidgetClassName] = self
- def create_self(keys)
- if keys and keys != None
- tk_call 'checkbutton', @path, *hash_kv(keys)
- else
- tk_call 'checkbutton', @path
- end
- end
- def toggle
- tk_send 'toggle'
- self
- end
-end
-TkCheckbutton = TkCheckButton
-
-class TkMessage<TkLabel
- TkCommandNames = ['message'.freeze].freeze
- WidgetClassName = 'Message'.freeze
- WidgetClassNames[WidgetClassName] = self
- def create_self(keys)
- if keys and keys != None
- tk_call 'message', @path, *hash_kv(keys)
- else
- tk_call 'message', @path
- end
- end
-end
-
-class TkScale<TkWindow
- TkCommandNames = ['scale'.freeze].freeze
- WidgetClassName = 'Scale'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def create_self(keys)
- if keys and keys != None
- if keys.key?('command')
- cmd = keys.delete('command')
- keys['command'] = proc{|val| cmd.call(val.to_f)}
- end
- tk_call 'scale', @path, *hash_kv(keys)
- else
- tk_call 'scale', @path
- end
- end
-
- def _wrap_command_arg(cmd)
- proc{|val|
- if val.kind_of?(String)
- cmd.call(number(val))
- else
- cmd.call(val)
- end
- }
- end
- private :_wrap_command_arg
-
- def configure_cmd(slot, value)
- configure(slot=>value)
- end
-
- def configure(slot, value=None)
- if (slot == 'command' || slot == :command)
- configure('command'=>value)
- elsif slot.kind_of?(Hash) &&
- (slot.key?('command') || slot.key?(:command))
- slot = _symbolkey2str(slot)
- slot['command'] = _wrap_command_arg(slot.delete('command'))
- end
- super(slot, value)
- end
-
- def command(cmd=Proc.new)
- configure('command'=>cmd)
- end
-
- def get(x=None, y=None)
- number(tk_send('get', x, y))
- end
-
- def coords(val=None)
- tk_split_list(tk_send('coords', val))
- end
-
- def identify(x, y)
- tk_send('identify', x, y)
- end
-
- def set(val)
- tk_send("set", val)
- end
-
- def value
- get
- end
-
- def value= (val)
- set(val)
- end
-end
-
-class TkScrollbar<TkWindow
- TkCommandNames = ['scrollbar'.freeze].freeze
- WidgetClassName = 'Scrollbar'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def create_self(keys)
- if keys and keys != None
- tk_call 'scrollbar', @path, *hash_kv(keys)
- else
- tk_call 'scrollbar', @path
- end
- end
-
- def delta(deltax=None, deltay=None)
- number(tk_send('delta', deltax, deltay))
- end
-
- def fraction(x=None, y=None)
- number(tk_send('fraction', x, y))
- end
-
- def identify(x, y)
- tk_send('identify', x, y)
- end
-
- def get
- ary1 = tk_send('get').split
- ary2 = []
- for i in ary1
- ary2.push number(i)
- end
- ary2
- end
-
- def set(first, last)
- tk_send "set", first, last
- self
- end
-
- def activate(element=None)
- tk_send('activate', element)
- end
-end
-
-class TkTextWin<TkWindow
- def create_self
- fail RuntimeError, "TkTextWin is an abstract class"
- end
-
- def bbox(index)
- list(tk_send('bbox', index))
- end
- def delete(first, last=None)
- tk_send 'delete', first, last
- self
- end
- def get(*index)
- tk_send 'get', *index
- end
- def insert(index, *args)
- tk_send 'insert', index, *args
- self
- end
- def scan_mark(x, y)
- tk_send 'scan', 'mark', x, y
- self
- end
- def scan_dragto(x, y)
- tk_send 'scan', 'dragto', x, y
- self
- end
- def see(index)
- tk_send 'see', index
- self
- end
-end
-
-module TkTreatListItemFont
- include TkTreatItemFont
-
- ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze
- def __conf_cmd(idx)
- ItemCMD[idx]
- end
-
- def __item_pathname(tagOrId)
- self.path + ';' + tagOrId.to_s
- end
-end
-
-class TkListbox<TkTextWin
- include TkTreatListItemFont
- include Scrollable
-
- TkCommandNames = ['listbox'.freeze].freeze
- WidgetClassName = 'Listbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def create_self(keys)
- if keys and keys != None
- tk_call 'listbox', @path, *hash_kv(keys)
- else
- tk_call 'listbox', @path
- end
- end
-
- def activate(y)
- tk_send 'activate', y
- self
- end
- def curselection
- list(tk_send('curselection'))
- end
- def get(*index)
- v = tk_send('get', *index)
- if index.size == 1
- v
- else
- tk_split_simplelist(v)
- end
- end
- def nearest(y)
- tk_send('nearest', y).to_i
- end
- def size
- tk_send('size').to_i
- end
- def selection_anchor(index)
- tk_send 'selection', 'anchor', index
- self
- end
- def selection_clear(first, last=None)
- tk_send 'selection', 'clear', first, last
- self
- end
- def selection_includes(index)
- bool(tk_send('selection', 'includes', index))
- end
- def selection_set(first, last=None)
- tk_send 'selection', 'set', first, last
- self
- end
-
- def index(index)
- tk_send('index', index).to_i
- end
-
- def itemcget(index, key)
- case key.to_s
- when 'text', 'label', 'show'
- tk_send('itemcget', index, "-#{key}")
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('itemcget', index, "-#{key}"))
- fnt = tk_tcl2ruby(tk_send('itemcget', index, '-font'))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(index, fnt)
- end
- if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(tk_send('itemcget', index, "-#{key}"))
- end
- end
- def itemconfigure(index, key, val=None)
- if key.kind_of? Hash
- if (key['font'] || key[:font] ||
- key['kanjifont'] || key[:kanjifont] ||
- key['latinfont'] || key[:latinfont] ||
- key['asciifont'] || key[:asciifont] )
- tagfont_configure(index, _symbolkey2str(key))
- else
- tk_send 'itemconfigure', index, *hash_kv(key)
- end
-
- else
- if (key == 'font' || key == :font ||
- key == 'kanjifont' || key == :kanjifont ||
- key == 'latinfont' || key == :latinfont ||
- key == 'asciifont' || key == :asciifont )
- if val == None
- tagfontobj(index)
- else
- tagfont_configure(index, {key=>val})
- end
- else
- tk_call 'itemconfigure', index, "-#{key}", val
- end
- end
- self
- end
-
- def itemconfiginfo(index, key=nil)
- if key
- case key.to_s
- when 'text', 'label', 'show'
- conf = tk_split_simplelist(tk_send('itemconfigure',index,"-#{key}"))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(tk_send('itemconfigure',index,"-#{key}") )
- conf[4] = tagfont_configinfo(index, conf[4])
- else
- conf = tk_split_list(tk_send('itemconfigure',index,"-#{key}"))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- ret = tk_split_simplelist(tk_send('itemconfigure',
- index)).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show'
- 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
- }
- fontconf = ret.assoc('font')
- if fontconf
- ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
- fontconf[4] = tagfont_configinfo(index, fontconf[4])
- ret.push(fontconf)
- else
- ret
- end
- end
- end
-end
-
-module TkTreatMenuEntryFont
- include TkTreatItemFont
-
- ItemCMD = ['entryconfigure'.freeze, TkComm::None].freeze
- def __conf_cmd(idx)
- ItemCMD[idx]
- end
-
- def __item_pathname(tagOrId)
- self.path + ';' + tagOrId.to_s
- end
-end
-
-class TkMenu<TkWindow
- include TkTreatMenuEntryFont
-
- TkCommandNames = ['menu'.freeze].freeze
- WidgetClassName = 'Menu'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def create_self(keys)
- if keys and keys != None
- tk_call 'menu', @path, *hash_kv(keys)
- else
- tk_call 'menu', @path
- end
- end
- def activate(index)
- tk_send 'activate', index
- self
- end
- def add(type, keys=nil)
- tk_send 'add', type, *hash_kv(keys)
- self
- end
- def add_cascade(keys=nil)
- add('cascade', keys)
- end
- def add_checkbutton(keys=nil)
- add('checkbutton', keys)
- end
- def add_command(keys=nil)
- add('command', keys)
- end
- def add_radiobutton(keys=nil)
- add('radiobutton', keys)
- end
- def add_separator(keys=nil)
- add('separator', keys)
- end
- def index(index)
- ret = tk_send('index', index)
- (ret == 'none')? nil: number(ret)
- end
- def invoke(index)
- tk_send 'invoke', index
- end
- def insert(index, type, keys=nil)
- tk_send 'insert', index, type, *hash_kv(keys)
- self
- end
- def delete(index, last=None)
- tk_send 'delete', index, last
- self
- end
- def popup(x, y, index=None)
- tk_call('tk_popup', path, x, y, index)
- self
- end
- def post(x, y)
- tk_send 'post', x, y
- self
- end
- def postcascade(index)
- tk_send 'postcascade', index
- self
- end
- def postcommand(cmd=Proc.new)
- configure_cmd 'postcommand', cmd
- self
- end
- def set_focus
- tk_call('tk_menuSetFocus', path)
- end
- def tearoffcommand(cmd=Proc.new)
- configure_cmd 'tearoffcommand', cmd
- self
- end
- def menutype(index)
- tk_send 'type', index
- end
- def unpost
- tk_send 'unpost'
- end
- def yposition(index)
- number(tk_send('yposition', index))
- end
- def entrycget(index, key)
- case key.to_s
- when 'text', 'label', 'show'
- tk_send 'entrycget', index, "-#{key}"
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('entrycget', index, "-#{key}"))
- fnt = tk_tcl2ruby(tk_send('entrycget', index, '-font'))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(index, fnt)
- end
- if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(tk_send('entrycget', index, "-#{key}"))
- end
- end
- def entryconfigure(index, key, val=None)
- if key.kind_of? Hash
- if (key['font'] || key[:font] ||
- key['kanjifont'] || key[:kanjifont] ||
- key['latinfont'] || key[:latinfont] ||
- key['asciifont'] || key[:asciifont])
- tagfont_configure(index, _symbolkey2str(key))
- else
- tk_send 'entryconfigure', index, *hash_kv(key)
- end
-
- else
- if (key == 'font' || key == :font ||
- key == 'kanjifont' || key == :kanjifont ||
- key == 'latinfont' || key == :latinfont ||
- key == 'asciifont' || key == :asciifont )
- if val == None
- tagfontobj(index)
- else
- tagfont_configure(index, {key=>val})
- end
- else
- tk_call 'entryconfigure', index, "-#{key}", val
- end
- end
- self
- end
-
- def entryconfiginfo(index, key=nil)
- if key
- case key.to_s
- when 'text', 'label', 'show'
- conf = tk_split_simplelist(tk_send('entryconfigure',index,"-#{key}"))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(tk_send('entryconfigure',index,"-#{key}"))
- conf[4] = tagfont_configinfo(index, conf[4])
- else
- conf = tk_split_list(tk_send('entryconfigure',index,"-#{key}"))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- ret = tk_split_simplelist(tk_send('entryconfigure',
- index)).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show'
- 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
- }
- if fontconf
- ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
- fontconf[4] = tagfont_configinfo(index, fontconf[4])
- ret.push(fontconf)
- else
- ret
- end
- end
- end
-end
-
-class TkMenuClone<TkMenu
- def initialize(parent, type=None)
- widgetname = nil
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- parent = keys.delete('parent')
- widgetname = keys.delete('widgetname')
- type = keys.delete('type'); type = None unless type
- end
- unless parent.kind_of?(TkMenu)
- fail ArgumentError, "parent must be TkMenu"
- end
- @parent = parent
- install_win(@parent.path, widgetname)
- tk_call @parent.path, 'clone', @path, type
- end
-end
-
-module TkSystemMenu
- def initialize(parent, keys=nil)
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- parent = keys.delete('parent')
- end
- unless parent.kind_of? TkMenu
- fail ArgumentError, "parent must be a TkMenu object"
- end
- @path = Kernel.format("%s.%s", parent.path, self.class::SYSMENU_NAME)
- #TkComm::Tk_WINDOWS[@path] = self
- TkCore::INTERP.tk_windows[@path] = self
- if self.method(:create_self).arity == 0
- p 'create_self has no arg' if $DEBUG
- create_self
- configure(keys) if keys
- else
- p 'create_self has an arg' if $DEBUG
- create_self(keys)
- end
- end
-end
-
-class TkSysMenu_Help<TkMenu
- # for all platform
- include TkSystemMenu
- SYSMENU_NAME = 'help'
-end
-
-class TkSysMenu_System<TkMenu
- # for Windows
- include TkSystemMenu
- SYSMENU_NAME = 'system'
-end
-
-class TkSysMenu_Apple<TkMenu
- # for Machintosh
- include TkSystemMenu
- SYSMENU_NAME = 'apple'
-end
-
-class TkMenubutton<TkLabel
- TkCommandNames = ['menubutton'.freeze].freeze
- WidgetClassName = 'Menubutton'.freeze
- WidgetClassNames[WidgetClassName] = self
- def create_self(keys)
- if keys and keys != None
- tk_call 'menubutton', @path, *hash_kv(keys)
- else
- tk_call 'menubutton', @path
- end
- end
-end
-
-class TkOptionMenubutton<TkMenubutton
- TkCommandNames = ['tk_optionMenu'.freeze].freeze
-
- class OptionMenu<TkMenu
- def initialize(path) #==> return value of tk_optionMenu
- @path = path
- #TkComm::Tk_WINDOWS[@path] = self
- TkCore::INTERP.tk_windows[@path] = self
- end
- end
-
- def initialize(parent=nil, var=TkVariable.new, firstval=nil, *vals)
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- parent = keys['parent']
- var = keys['variable'] if keys['variable']
- firstval, *vals = keys['values']
- end
- fail 'variable option must be TkVariable' unless var.kind_of? TkVariable
- @variable = var
- firstval = @variable.value unless firstval
- @variable.value = firstval
- install_win(if parent then parent.path end)
- @menu = OptionMenu.new(tk_call('tk_optionMenu', @path, @variable.id,
- firstval, *vals))
- end
-
- def value
- @variable.value
- end
-
- def activate(index)
- @menu.activate(index)
- self
- end
- def add(value)
- @menu.add('radiobutton', 'variable'=>@variable,
- 'label'=>value, 'value'=>value)
- self
- end
- def index(index)
- @menu.index(index)
- end
- def invoke(index)
- @menu.invoke(index)
- end
- def insert(index, value)
- @menu.add(index, 'radiobutton', 'variable'=>@variable,
- 'label'=>value, 'value'=>value)
- self
- end
- def delete(index, last=None)
- @menu.delete(index, last)
- self
- end
- def yposition(index)
- @menu.yposition(index)
- end
- def menu
- @menu
- end
- def menucget(key)
- @menu.cget(key)
- end
- def menuconfigure(key, val=None)
- @menu.configure(key, val)
- self
- end
- def menuconfiginfo(key=nil)
- @menu.configinfo(key)
- end
- def entrycget(index, key)
- @menu.entrycget(index, key)
- end
- def entryconfigure(index, key, val=None)
- @menu.entryconfigure(index, key, val)
- self
- end
- def entryconfiginfo(index, key=nil)
- @menu.entryconfiginfo(index, key)
- end
-end
-
-module TkComposite
- include Tk
- extend Tk
-
- def initialize(parent=nil, *args)
- @delegates = {}
-
- if parent.kind_of? Hash
- keys = _symbolkey2str(parent)
- parent = keys.delete('parent')
- @frame = TkFrame.new(parent)
- @delegates['DEFAULT'] = @frame
- @path = @epath = @frame.path
- initialize_composite(keys)
- else
- @frame = TkFrame.new(parent)
- @delegates['DEFAULT'] = @frame
- @path = @epath = @frame.path
- initialize_composite(*args)
- end
- end
-
- def epath
- @epath
- end
-
- def initialize_composite(*args) end
- private :initialize_composite
-
- def delegate(option, *wins)
- if @delegates[option].kind_of?(Array)
- for i in wins
- @delegates[option].push(i)
- end
- else
- @delegates[option] = wins
- end
- end
-
- def configure(slot, value=None)
- if slot.kind_of? Hash
- slot.each{|slot,value| configure slot, value}
- else
- if @delegates and @delegates[slot]
- for i in @delegates[slot]
- if not i
- i = @delegates['DEFALUT']
- redo
- else
- last = i.configure(slot, value)
- end
- end
- last
- else
- super
- end
- end
- end
-end
-
-module TkClipboard
- include Tk
- extend Tk
-
- TkCommandNames = ['clipboard'.freeze].freeze
-
- def self.clear(win=nil)
- if win
- tk_call 'clipboard', 'clear', '-displayof', win
- else
- tk_call 'clipboard', 'clear'
- end
- end
- def self.clear_on_display(win)
- tk_call 'clipboard', 'clear', '-displayof', win
- end
-
- def self.get(type=nil)
- if type
- tk_call 'clipboard', 'get', '-type', type
- else
- tk_call 'clipboard', 'get'
- end
- end
- def self.get_on_display(win, type=nil)
- if type
- tk_call 'clipboard', 'get', '-displayof', win, '-type', type
- else
- tk_call 'clipboard', 'get', '-displayof', win
- end
- end
-
- def self.set(data, keys=nil)
- clear
- append(data, keys)
- end
- def self.set_on_display(win, data, keys=nil)
- clear(win)
- append_on_display(win, data, keys)
- end
-
- def self.append(data, keys=nil)
- args = ['clipboard', 'append']
- args += hash_kv(keys)
- args += ['--', data]
- tk_call(*args)
- end
- def self.append_on_display(win, data, keys=nil)
- args = ['clipboard', 'append', '-displayof', win]
- args += hash_kv(keys)
- args += ['--', data]
- tk_call(*args)
- end
-
- def clear
- TkClipboard.clear_on_display(self)
- self
- end
- def get(type=nil)
- TkClipboard.get_on_display(self, type)
- end
- def set(data, keys=nil)
- TkClipboard.set_on_display(self, data, keys)
- self
- end
- def append(data, keys=nil)
- TkClipboard.append_on_display(self, data, keys)
- self
- end
-end
-
-# widget_destroy_hook
-require 'tkvirtevent'
-TkBindTag::ALL.bind(TkVirtualEvent.new('Destroy'), proc{|xpath|
- path = xpath[1..-1]
- if (widget = TkCore::INTERP.tk_windows[path])
- if widget.respond_to?(:__destroy_hook__)
- begin
- widget.__destroy_hook__
- rescue Exception
- end
- end
- end
- }, 'x%W')
+TkWidget = TkWindow
# freeze core modules
#TclTkLib.freeze
@@ -5831,27 +5465,21 @@ TkBindTag::ALL.bind(TkVirtualEvent.new('Destroy'), proc{|xpath|
#TkCore.freeze
#Tk.freeze
-# autoload
-autoload :TkCanvas, 'tkcanvas'
-autoload :TkImage, 'tkcanvas'
-autoload :TkBitmapImage, 'tkcanvas'
-autoload :TkPhotoImage, 'tkcanvas'
-autoload :TkEntry, 'tkentry'
-autoload :TkSpinbox, 'tkentry'
-autoload :TkText, 'tktext'
-autoload :TkDialog, 'tkdialog'
-autoload :TkDialog2, 'tkdialog'
-autoload :TkWarning, 'tkdialog'
-autoload :TkWarning2, 'tkdialog'
-autoload :TkMenubar, 'tkmenubar'
-autoload :TkAfter, 'tkafter'
-autoload :TkTimer, 'tkafter'
-autoload :TkPalette, 'tkpalette'
-autoload :TkFont, 'tkfont'
-autoload :TkBgError, 'tkbgerror'
-autoload :TkManageFocus, 'tkmngfocus'
-autoload :TkPalette, 'tkpalette'
-autoload :TkWinDDE, 'tkwinpkg'
-autoload :TkWinRegistry, 'tkwinpkg'
-autoload :TkMacResource, 'tkmacpkg'
-autoload :TkConsole, 'tkconsole'
+module Tk
+ RELEASE_DATE = '2008-05-23'.freeze
+
+ autoload :AUTO_PATH, 'tk/variable'
+ autoload :TCL_PACKAGE_PATH, 'tk/variable'
+ autoload :PACKAGE_PATH, 'tk/variable'
+ autoload :TCL_LIBRARY_PATH, 'tk/variable'
+ autoload :LIBRARY_PATH, 'tk/variable'
+ autoload :TCL_PRECISION, 'tk/variable'
+end
+
+# call setup script for Tk extension libraries (base configuration)
+begin
+ require 'tkextlib/version.rb'
+ require 'tkextlib/setup.rb'
+rescue LoadError
+ # ignore
+end
diff --git a/ext/tk/lib/tk/after.rb b/ext/tk/lib/tk/after.rb
new file mode 100644
index 0000000000..8c58210331
--- /dev/null
+++ b/ext/tk/lib/tk/after.rb
@@ -0,0 +1,6 @@
+#
+# tk/after.rb : methods for Tcl/Tk after command
+#
+# $Id$
+#
+require 'tk/timer'
diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb
new file mode 100644
index 0000000000..0773f7708d
--- /dev/null
+++ b/ext/tk/lib/tk/autoload.rb
@@ -0,0 +1,414 @@
+#
+# autoload
+#
+############################################
+# geometry manager
+module Tk
+ autoload :Grid, 'tk/grid'
+ def Grid(*args); TkGrid.configure(*args); end
+
+ autoload :Pack, 'tk/pack'
+ def Pack(*args); TkPack.configure(*args); end
+
+ autoload :Place, 'tk/place'
+ def Place(*args); TkPlace.configure(*args); end
+end
+
+autoload :TkGrid, 'tk/grid'
+def TkGrid(*args); TkGrid.configure(*args); end
+
+autoload :TkPack, 'tk/pack'
+def TkPack(*args); TkPack.configure(*args); end
+
+autoload :TkPlace, 'tk/place'
+def TkPlace(*args); TkPlace.configure(*args); end
+
+
+############################################
+# classes on Tk module
+module Tk
+ autoload :Button, 'tk/button'
+
+ autoload :Canvas, 'tk/canvas'
+
+ autoload :CheckButton, 'tk/checkbutton'
+ autoload :Checkbutton, 'tk/checkbutton'
+
+ autoload :Entry, 'tk/entry'
+
+ autoload :Frame, 'tk/frame'
+
+ autoload :Label, 'tk/label'
+
+ autoload :LabelFrame, 'tk/labelframe'
+ autoload :Labelframe, 'tk/labelframe'
+
+ autoload :Listbox, 'tk/listbox'
+
+ autoload :Menu, 'tk/menu'
+ autoload :MenuClone, 'tk/menu'
+ autoload :CloneMenu, 'tk/menu'
+ autoload :SystemMenu, 'tk/menu'
+ autoload :SysMenu_Help, 'tk/menu'
+ autoload :SysMenu_System, 'tk/menu'
+ autoload :SysMenu_Apple, 'tk/menu'
+ autoload :Menubutton, 'tk/menu'
+ autoload :MenuButton, 'tk/menu'
+ autoload :OptionMenubutton, 'tk/menu'
+ autoload :OptionMenBbutton, 'tk/menu'
+
+ autoload :Message, 'tk/message'
+
+ autoload :PanedWindow, 'tk/panedwindow'
+ autoload :Panedwindow, 'tk/panedwindow'
+
+ autoload :RadioButton, 'tk/radiobutton'
+ autoload :Radiobutton, 'tk/radiobutton'
+
+ autoload :Root, 'tk/root'
+
+ autoload :Scale, 'tk/scale'
+
+ autoload :Scrollbar, 'tk/scrollbar'
+ autoload :XScrollbar, 'tk/scrollbar'
+ autoload :YScrollbar, 'tk/scrollbar'
+
+ autoload :Spinbox, 'tk/spinbox'
+
+ autoload :Text, 'tk/text'
+
+ autoload :Toplevel, 'tk/toplevel'
+end
+
+
+############################################
+# sub-module of Tk
+module Tk
+ autoload :Clock, 'tk/clock'
+
+ autoload :OptionObj, 'tk/optionobj'
+
+ autoload :X_Scrollable, 'tk/scrollable'
+ autoload :Y_Scrollable, 'tk/scrollable'
+ autoload :Scrollable, 'tk/scrollable'
+
+ autoload :Wm, 'tk/wm'
+ autoload :Wm_for_General, 'tk/wm'
+
+ autoload :MacResource, 'tk/macpkg'
+
+ autoload :WinDDE, 'tk/winpkg'
+ autoload :WinRegistry, 'tk/winpkg'
+
+ autoload :ValidateConfigure, 'tk/validation'
+ autoload :ItemValidateConfigure, 'tk/validation'
+
+ autoload :EncodedString, 'tk/encodedstr'
+ def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end
+
+ autoload :BinaryString, 'tk/encodedstr'
+ def Tk.BinaryString(str); Tk::BinaryString.new(str); end
+
+ autoload :UTF8_String, 'tk/encodedstr'
+ def Tk.UTF8_String(str); Tk::UTF8_String.new(str); end
+
+end
+
+
+############################################
+# toplevel classes/modules (fixed)
+autoload :TkBgError, 'tk/bgerror'
+
+autoload :TkBindTag, 'tk/bindtag'
+autoload :TkBindTagAll, 'tk/bindtag'
+autoload :TkDatabaseClass, 'tk/bindtag'
+
+autoload :TkConsole, 'tk/console'
+
+autoload :TkcItem, 'tk/canvas'
+autoload :TkcArc, 'tk/canvas'
+autoload :TkcBitmap, 'tk/canvas'
+autoload :TkcImage, 'tk/canvas'
+autoload :TkcLine, 'tk/canvas'
+autoload :TkcOval, 'tk/canvas'
+autoload :TkcPolygon, 'tk/canvas'
+autoload :TkcRectangle, 'tk/canvas'
+autoload :TkcText, 'tk/canvas'
+autoload :TkcWindow, 'tk/canvas'
+
+autoload :TkcTagAccess, 'tk/canvastag'
+autoload :TkcTag, 'tk/canvastag'
+autoload :TkcTagString, 'tk/canvastag'
+autoload :TkcNamedTag, 'tk/canvastag'
+autoload :TkcTagAll, 'tk/canvastag'
+autoload :TkcTagCurrent, 'tk/canvastag'
+autoload :TkcTagGroup, 'tk/canvastag'
+
+autoload :TkClipboard, 'tk/clipboard'
+
+autoload :TkComposite, 'tk/composite'
+
+autoload :TkConsole, 'tk/console'
+
+autoload :TkDialog, 'tk/dialog'
+autoload :TkDialog2, 'tk/dialog'
+autoload :TkDialogObj, 'tk/dialog'
+autoload :TkWarning, 'tk/dialog'
+autoload :TkWarning2, 'tk/dialog'
+autoload :TkWarningObj, 'tk/dialog'
+
+autoload :TkEvent, 'tk/event'
+
+autoload :TkFont, 'tk/font'
+autoload :TkNamedFont, 'tk/font'
+
+autoload :TkImage, 'tk/image'
+autoload :TkBitmapImage, 'tk/image'
+autoload :TkPhotoImage, 'tk/image'
+
+autoload :TkItemConfigMethod, 'tk/itemconfig'
+
+autoload :TkTreatItemFont, 'tk/itemfont'
+
+autoload :TkKinput, 'tk/kinput'
+
+autoload :TkSystemMenu, 'tk/menu'
+
+autoload :TkMenubar, 'tk/menubar'
+
+autoload :TkMenuSpec, 'tk/menuspec'
+
+autoload :TkManageFocus, 'tk/mngfocus'
+
+autoload :TkMsgCatalog, 'tk/msgcat'
+autoload :TkMsgCat, 'tk/msgcat'
+
+autoload :TkNamespace, 'tk/namespace'
+
+autoload :TkOptionDB, 'tk/optiondb'
+autoload :TkOption, 'tk/optiondb'
+autoload :TkResourceDB, 'tk/optiondb'
+
+autoload :TkPackage, 'tk/package'
+
+autoload :TkPalette, 'tk/palette'
+
+autoload :TkRoot, 'tk/root'
+
+autoload :TkScrollbox, 'tk/scrollbox'
+
+autoload :TkSelection, 'tk/selection'
+
+autoload :TkTreatTagFont, 'tk/tagfont'
+
+autoload :TkTextImage, 'tk/textimage'
+autoload :TktImage, 'tk/textimage'
+
+autoload :TkTextMark, 'tk/textmark'
+autoload :TkTextNamedMark, 'tk/textmark'
+autoload :TkTextMarkInsert, 'tk/textmark'
+autoload :TkTextMarkCurrent, 'tk/textmark'
+autoload :TkTextMarkAnchor, 'tk/textmark'
+autoload :TktMark, 'tk/textmark'
+autoload :TktNamedMark, 'tk/textmark'
+autoload :TktMarkInsert, 'tk/textmark'
+autoload :TktMarkCurrent, 'tk/textmark'
+autoload :TktMarkAnchor, 'tk/textmark'
+
+autoload :TkTextTag, 'tk/texttag'
+autoload :TkTextNamedTag, 'tk/texttag'
+autoload :TkTextTagSel, 'tk/texttag'
+autoload :TktTag, 'tk/texttag'
+autoload :TktNamedTag, 'tk/texttag'
+autoload :TktTagSel, 'tk/texttag'
+
+autoload :TkTextWindow, 'tk/textwindow'
+autoload :TktWindow, 'tk/textwindow'
+
+autoload :TkAfter, 'tk/timer'
+autoload :TkTimer, 'tk/timer'
+autoload :TkRTTimer, 'tk/timer'
+
+autoload :TkTextWin, 'tk/txtwin_abst'
+
+autoload :TkValidation, 'tk/validation'
+autoload :TkValidateCommand, 'tk/validation'
+
+autoload :TkVariable, 'tk/variable'
+autoload :TkVarAccess, 'tk/variable'
+
+autoload :TkVirtualEvent, 'tk/virtevent'
+autoload :TkNamedVirtualEvent,'tk/virtevent'
+
+autoload :TkWinfo, 'tk/winfo'
+
+autoload :TkXIM, 'tk/xim'
+
+
+############################################
+# toplevel classes/modules (switchable)
+module Tk
+ @TOPLEVEL_ALIAS_TABLE = {}
+ @TOPLEVEL_ALIAS_TABLE[:Tk] = {
+ :TkButton => 'tk/button',
+
+ :TkCanvas => 'tk/canvas',
+
+ :TkCheckButton => 'tk/checkbutton',
+ :TkCheckbutton => 'tk/checkbutton',
+
+ # :TkDialog => 'tk/dialog',
+ # :TkDialog2 => 'tk/dialog',
+ # :TkDialogObj => 'tk/dialog',
+ # :TkWarning => 'tk/dialog',
+ # :TkWarning2 => 'tk/dialog',
+ # :TkWarningObj => 'tk/dialog',
+
+ :TkEntry => 'tk/entry',
+
+ :TkFrame => 'tk/frame',
+
+ :TkLabel => 'tk/label',
+
+ :TkLabelFrame => 'tk/labelframe',
+ :TkLabelframe => 'tk/labelframe',
+
+ :TkListbox => 'tk/listbox',
+
+ :TkMacResource => 'tk/macpkg',
+
+ :TkMenu => 'tk/menu',
+ :TkMenuClone => 'tk/menu',
+ :TkCloneMenu => 'tk/menu',
+ # :TkSystemMenu => 'tk/menu',
+ :TkSysMenu_Help => 'tk/menu',
+ :TkSysMenu_System => 'tk/menu',
+ :TkSysMenu_Apple => 'tk/menu',
+ :TkMenubutton => 'tk/menu',
+ :TkMenuButton => 'tk/menu',
+ :TkOptionMenubutton => 'tk/menu',
+ :TkOptionMenuButton => 'tk/menu',
+
+ :TkMessage => 'tk/message',
+
+ :TkPanedWindow => 'tk/panedwindow',
+ :TkPanedwindow => 'tk/panedwindow',
+
+ :TkRadioButton => 'tk/radiobutton',
+ :TkRadiobutton => 'tk/radiobutton',
+
+ # :TkRoot => 'tk/root',
+
+ :TkScale => 'tk/scale',
+
+ :TkScrollbar => 'tk/scrollbar',
+ :TkXScrollbar => 'tk/scrollbar',
+ :TkYScrollbar => 'tk/scrollbar',
+
+ :TkSpinbox => 'tk/spinbox',
+
+ :TkText => 'tk/text',
+
+ :TkToplevel => 'tk/toplevel',
+
+ :TkWinDDE => 'tk/winpkg',
+ :TkWinRegistry => 'tk/winpkg',
+ }
+
+ @TOPLEVEL_ALIAS_OWNER = {}
+
+ @TOPLEVEL_ALIAS_SETUP_PROC = {}
+
+ @current_default_widget_set = nil
+end
+
+
+############################################
+# methods to control default widget set
+############################################
+
+class << Tk
+ def default_widget_set
+ @current_default_widget_set
+ end
+
+ def default_widget_set=(target)
+ target = target.to_sym
+ return target if target == @current_default_widget_set
+
+ if (cmd = @TOPLEVEL_ALIAS_SETUP_PROC[target])
+ cmd.call(target)
+ end
+
+ _replace_toplevel_aliases(target)
+ end
+
+ def __set_toplevel_aliases__(target, obj, *symbols)
+ @TOPLEVEL_ALIAS_TABLE[target = target.to_sym] ||= {}
+ symbols.each{|sym|
+ @TOPLEVEL_ALIAS_TABLE[target][sym = sym.to_sym] = obj
+ # if @current_default_widget_set == target
+ if @TOPLEVEL_ALIAS_OWNER[sym] == target
+ Object.class_eval{remove_const sym} if Object.const_defined?(sym)
+ Object.const_set(sym, obj)
+ end
+ }
+ end
+
+ ###################################
+ private
+ def _replace_toplevel_aliases(target)
+ # check already autoloaded
+ if (table = @TOPLEVEL_ALIAS_TABLE[current = @current_default_widget_set])
+ table.each{|sym, file|
+ if !Object.autoload?(sym) && Object.const_defined?(sym) &&
+ @TOPLEVEL_ALIAS_TABLE[current][sym].kind_of?(String)
+ # autoload -> class
+ @TOPLEVEL_ALIAS_TABLE[current][sym] = Object.const_get(sym)
+ end
+ }
+ end
+
+ # setup autoloads
+ @TOPLEVEL_ALIAS_TABLE[target].each{|sym, file|
+ Object.class_eval{remove_const sym} if Object.const_defined?(sym)
+ if file.kind_of?(String)
+ # file => autoload target file
+ Object.autoload(sym, file)
+ else
+ # file => loaded class object
+ Object.const_set(sym, file)
+ end
+ @TOPLEVEL_ALIAS_OWNER[sym] = target
+ }
+
+ # update current alias
+ @current_default_widget_set = target
+ end
+end
+
+############################################
+# setup default widget set => :Tk
+Tk.default_widget_set = :Tk
+
+
+############################################
+# depend on the version of Tcl/Tk
+# major, minor, type, type_name, patchlevel = TclTkLib.get_version
+
+############################################
+# Ttk (Tile) support
+=begin
+if major > 8 ||
+ (major == 8 && minor > 5) ||
+ (major == 8 && minor == 5 && type >= TclTkLib::RELEASE_TYPE::BETA)
+ # Tcl/Tk 8.5 beta or later
+ Object.autoload :Ttk, 'tkextlib/tile'
+ Tk.autoload :Tile, 'tkextlib/tile'
+
+ require 'tk/ttk_selector'
+end
+=end
+Object.autoload :Ttk, 'tkextlib/tile'
+Tk.autoload :Tile, 'tkextlib/tile'
+require 'tk/ttk_selector'
diff --git a/ext/tk/lib/tk/bgerror.rb b/ext/tk/lib/tk/bgerror.rb
new file mode 100644
index 0000000000..c82a8e046b
--- /dev/null
+++ b/ext/tk/lib/tk/bgerror.rb
@@ -0,0 +1,29 @@
+#
+# tkbgerror -- bgerror ( tkerror ) module
+# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+module TkBgError
+ extend Tk
+
+ TkCommandNames = ['bgerror'.freeze].freeze
+
+ def bgerror(message)
+ tk_call('bgerror', message)
+ end
+ alias tkerror bgerror
+ alias show bgerror
+ module_function :bgerror, :tkerror, :show
+
+ def set_handler(hdlr = Proc.new) #==> handler :: proc{|msg| ...body... }
+ tk_call('proc', 'bgerror', 'msg', install_cmd(hdlr) + ' $msg')
+ end
+ def set_default
+ begin
+ tk_call('rename', 'bgerror', '')
+ rescue RuntimeError
+ end
+ end
+ module_function :set_handler, :set_default
+end
diff --git a/ext/tk/lib/tk/bindtag.rb b/ext/tk/lib/tk/bindtag.rb
new file mode 100644
index 0000000000..88c8367a88
--- /dev/null
+++ b/ext/tk/lib/tk/bindtag.rb
@@ -0,0 +1,138 @@
+#
+# tk/bind.rb : control event binding
+#
+require 'tk'
+
+class TkBindTag
+ include TkBindCore
+
+ #BTagID_TBL = {}
+ BTagID_TBL = TkCore::INTERP.create_table
+
+ (Tk_BINDTAG_ID = ["btag".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ BTagID_TBL.mutex.synchronize{ BTagID_TBL.clear }
+ }
+
+ def TkBindTag.id2obj(id)
+ BTagID_TBL.mutex.synchronize{
+ (BTagID_TBL[id])? BTagID_TBL[id]: id
+ }
+ end
+
+=begin
+ def TkBindTag.new_by_name(name, *args, &b)
+ BTagID_TBL.mutex.synchronize{
+ return BTagID_TBL[name] if BTagID_TBL[name]
+ }
+
+ self.new.instance_eval{
+ BTagID_TBL.mutex.synchronize{
+ BTagID_TBL.delete @id
+ @id = name
+ BTagID_TBL[@id] = self
+ }
+ bind(*args, &b) if args != []
+ self
+ }
+ end
+=end
+ def TkBindTag.new_by_name(name, *args, &b)
+ obj = nil
+ BTagID_TBL.mutex.synchronize{
+ if BTagID_TBL[name]
+ obj = BTagID_TBL[name]
+ else
+ (obj = BTagID_TBL[name] = self.allocate).instance_eval{
+ @id = name
+ }
+ end
+ }
+ bind(*args, &b) if obj && args != []
+ obj
+ end
+
+ def initialize(*args, &b)
+ Tk_BINDTAG_ID.mutex.synchronize{
+ # @id = Tk_BINDTAG_ID.join('')
+ @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_)
+ Tk_BINDTAG_ID[1].succ!
+ }
+ BTagID_TBL.mutex.synchronize{
+ BTagID_TBL[@id] = self
+ }
+ bind(*args, &b) if args != []
+ end
+
+ ALL = self.new_by_name('all')
+
+ def name
+ @id
+ end
+
+ def to_eval
+ @id
+ end
+
+ def inspect
+ #Kernel.format "#<TkBindTag: %s>", @id
+ '#<TkBindTag: ' + @id + '>'
+ end
+end
+
+
+class TkBindTagAll<TkBindTag
+ def TkBindTagAll.new(*args, &b)
+ $stderr.puts "Warning: TkBindTagALL is obsolete. Use TkBindTag::ALL\n"
+
+ TkBindTag::ALL.bind(*args, &b) if args != []
+ TkBindTag::ALL
+ end
+end
+
+
+class TkDatabaseClass<TkBindTag
+=begin
+ def self.new(name, *args, &b)
+ BTagID_TBL.mutex.synchronize{
+ return BTagID_TBL[name] if BTagID_TBL[name]
+ }
+ super(name, *args, &b)
+ end
+
+ def initialize(name, *args, &b)
+ @id = name
+ BTagID_TBL.mutex.synchronize{
+ BTagID_TBL[@id] = self
+ }
+ bind(*args, &b) if args != []
+ end
+=end
+ def self.new(name, *args, &b)
+ BTagID_TBL.mutex.synchronize{
+ if BTagID_TBL[name]
+ BTagID_TBL[name]
+ else
+ BTagID_TBL[name] = self.allocate.instance_eval{
+ initialize(name, *args, &b)
+ self
+ }
+ end
+ }
+ end
+
+ def initialize(name, *args, &b)
+ @id = name
+ bind(*args, &b) if args != []
+ end
+
+ def inspect
+ #Kernel.format "#<TkDatabaseClass: %s>", @id
+ '#<TkDatabaseClass: ' + @id + '>'
+ end
+end
diff --git a/ext/tk/lib/tk/button.rb b/ext/tk/lib/tk/button.rb
new file mode 100644
index 0000000000..770a5785bb
--- /dev/null
+++ b/ext/tk/lib/tk/button.rb
@@ -0,0 +1,30 @@
+#
+# tk/button.rb : treat button widget
+#
+require 'tk'
+require 'tk/label'
+
+class Tk::Button<Tk::Label
+ TkCommandNames = ['button'.freeze].freeze
+ WidgetClassName = 'Button'.freeze
+ WidgetClassNames[WidgetClassName] = self
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('button', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('button', @path)
+ # end
+ #end
+ #private :create_self
+
+ def invoke
+ _fromUTF8(tk_send_without_enc('invoke'))
+ end
+ def flash
+ tk_send_without_enc('flash')
+ self
+ end
+end
+
+#TkButton = Tk::Button unless Object.const_defined? :TkButton
+Tk.__set_toplevel_aliases__(:Tk, Tk::Button, :TkButton)
diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb
new file mode 100644
index 0000000000..36ea008a17
--- /dev/null
+++ b/ext/tk/lib/tk/canvas.rb
@@ -0,0 +1,789 @@
+#
+# tk/canvas.rb - Tk canvas classes
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+#
+require 'tk'
+require 'tk/canvastag'
+require 'tk/itemconfig'
+require 'tk/scrollable'
+
+module TkCanvasItemConfig
+ include TkItemConfigMethod
+
+ def __item_strval_optkeys(id)
+ # maybe need to override
+ super(id) + [
+ 'fill', 'activefill', 'disabledfill',
+ 'outline', 'activeoutline', 'disabledoutline'
+ ]
+ end
+ private :__item_strval_optkeys
+
+ def __item_methodcall_optkeys(id)
+ {'coords'=>'coords'}
+ end
+ private :__item_methodcall_optkeys
+
+ def __item_val2ruby_optkeys(id) # { key=>proc, ... }
+ super(id).update('window'=>proc{|i, v| window(v)})
+ end
+ private :__item_val2ruby_optkeys
+
+ def __item_pathname(tagOrId)
+ if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag)
+ self.path + ';' + tagOrId.id.to_s
+ else
+ self.path + ';' + tagOrId.to_s
+ end
+ end
+ private :__item_pathname
+end
+
+class Tk::Canvas<TkWindow
+ include TkCanvasItemConfig
+ include Tk::Scrollable
+
+ TkCommandNames = ['canvas'.freeze].freeze
+ WidgetClassName = 'Canvas'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __destroy_hook__
+ TkcItem::CItemID_TBL.delete(@path)
+ end
+
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('canvas', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('canvas', @path)
+ # end
+ #end
+ #private :create_self
+
+ def __numval_optkeys
+ super() + ['closeenough']
+ end
+ private :__numval_optkeys
+
+ def __boolval_optkeys
+ super() + ['confine']
+ end
+ private :__boolval_optkeys
+
+ def tagid(tag)
+ if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag)
+ tag.id
+ else
+ tag # maybe an Array of configure paramters
+ end
+ end
+ private :tagid
+
+
+ # create a canvas item without creating a TkcItem object
+ def create(type, *args)
+ type.create(self, *args)
+ end
+
+
+ def addtag(tag, mode, *args)
+ mode = mode.to_s
+ if args[0] && mode =~ /^(above|below|with(tag)?)$/
+ args[0] = tagid(args[0])
+ end
+ tk_send_without_enc('addtag', tagid(tag), mode, *args)
+ self
+ end
+ def addtag_above(tagOrId, target)
+ addtag(tagOrId, 'above', tagid(target))
+ end
+ def addtag_all(tagOrId)
+ addtag(tagOrId, 'all')
+ end
+ def addtag_below(tagOrId, target)
+ addtag(tagOrId, 'below', tagid(target))
+ end
+ def addtag_closest(tagOrId, x, y, halo=None, start=None)
+ addtag(tagOrId, 'closest', x, y, halo, start)
+ end
+ def addtag_enclosed(tagOrId, x1, y1, x2, y2)
+ addtag(tagOrId, 'enclosed', x1, y1, x2, y2)
+ end
+ def addtag_overlapping(tagOrId, x1, y1, x2, y2)
+ addtag(tagOrId, 'overlapping', x1, y1, x2, y2)
+ end
+ def addtag_withtag(tagOrId, tag)
+ addtag(tagOrId, 'withtag', tagid(tag))
+ end
+
+ def bbox(tagOrId, *tags)
+ list(tk_send_without_enc('bbox', tagid(tagOrId),
+ *tags.collect{|t| tagid(t)}))
+ end
+
+ #def itembind(tag, context, cmd=Proc.new, *args)
+ # _bind([path, "bind", tagid(tag)], context, cmd, *args)
+ # self
+ #end
+ def itembind(tag, context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, "bind", tagid(tag)], context, cmd, *args)
+ self
+ end
+
+ #def itembind_append(tag, context, cmd=Proc.new, *args)
+ # _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
+ # self
+ #end
+ def itembind_append(tag, context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
+ self
+ end
+
+ def itembind_remove(tag, context)
+ _bind_remove([path, "bind", tagid(tag)], context)
+ self
+ end
+
+ def itembindinfo(tag, context=nil)
+ _bindinfo([path, "bind", tagid(tag)], context)
+ end
+
+ def canvasx(screen_x, *args)
+ #tk_tcl2ruby(tk_send_without_enc('canvasx', screen_x, *args))
+ number(tk_send_without_enc('canvasx', screen_x, *args))
+ end
+ def canvasy(screen_y, *args)
+ #tk_tcl2ruby(tk_send_without_enc('canvasy', screen_y, *args))
+ number(tk_send_without_enc('canvasy', screen_y, *args))
+ end
+ alias canvas_x canvasx
+ alias canvas_y canvasy
+
+ def coords(tag, *args)
+ if args == []
+ tk_split_list(tk_send_without_enc('coords', tagid(tag)))
+ else
+ tk_send_without_enc('coords', tagid(tag), *(args.flatten))
+ self
+ end
+ end
+
+ def dchars(tag, first, last=None)
+ tk_send_without_enc('dchars', tagid(tag),
+ _get_eval_enc_str(first), _get_eval_enc_str(last))
+ self
+ end
+
+ def delete(*args)
+ tbl = nil
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl = TkcItem::CItemID_TBL[self.path]
+ }
+ if tbl
+ args.each{|tag|
+ find('withtag', tag).each{|item|
+ if item.kind_of?(TkcItem)
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl.delete(item.id)
+ }
+ end
+ }
+ }
+ end
+ tk_send_without_enc('delete', *args.collect{|t| tagid(t)})
+ self
+ end
+ alias remove delete
+
+ def dtag(tag, tag_to_del=None)
+ tk_send_without_enc('dtag', tagid(tag), tagid(tag_to_del))
+ self
+ end
+ alias deltag dtag
+
+ def find(mode, *args)
+ list(tk_send_without_enc('find', mode, *args)).collect!{|id|
+ TkcItem.id2obj(self, id)
+ }
+ end
+ def find_above(target)
+ find('above', tagid(target))
+ end
+ def find_all
+ find('all')
+ end
+ def find_below(target)
+ find('below', tagid(target))
+ end
+ def find_closest(x, y, halo=None, start=None)
+ find('closest', x, y, halo, start)
+ end
+ def find_enclosed(x1, y1, x2, y2)
+ find('enclosed', x1, y1, x2, y2)
+ end
+ def find_overlapping(x1, y1, x2, y2)
+ find('overlapping', x1, y1, x2, y2)
+ end
+ def find_withtag(tag)
+ find('withtag', tag)
+ end
+
+ def itemfocus(tagOrId=nil)
+ if tagOrId
+ tk_send_without_enc('focus', tagid(tagOrId))
+ self
+ else
+ ret = tk_send_without_enc('focus')
+ if ret == ""
+ nil
+ else
+ TkcItem.id2obj(self, ret)
+ end
+ end
+ end
+
+ def gettags(tagOrId)
+ list(tk_send_without_enc('gettags', tagid(tagOrId))).collect{|tag|
+ TkcTag.id2obj(self, tag)
+ }
+ end
+
+ def icursor(tagOrId, index)
+ tk_send_without_enc('icursor', tagid(tagOrId), index)
+ self
+ end
+
+ def index(tagOrId, idx)
+ number(tk_send_without_enc('index', tagid(tagOrId), idx))
+ end
+
+ def insert(tagOrId, index, string)
+ tk_send_without_enc('insert', tagid(tagOrId), index,
+ _get_eval_enc_str(string))
+ self
+ end
+
+=begin
+ def itemcget(tagOrId, option)
+ case option.to_s
+ when 'dash', 'activedash', 'disableddash'
+ conf = tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}")
+ if conf =~ /^[0-9]/
+ list(conf)
+ else
+ conf
+ end
+ when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
+ _fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}"))
+ when 'font', 'kanjifont'
+ #fnt = tk_tcl2ruby(tk_send('itemcget', tagid(tagOrId), "-#{option}"))
+ fnt = tk_tcl2ruby(_fromUTF8(tk_send_with_enc('itemcget', tagid(tagOrId), '-font')))
+ unless fnt.kind_of?(TkFont)
+ fnt = tagfontobj(tagid(tagOrId), fnt)
+ end
+ if option.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
+ # obsolete; just for compatibility
+ fnt.kanji_font
+ else
+ fnt
+ end
+ else
+ tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId),
+ "-#{option}")))
+ end
+ end
+
+ def itemconfigure(tagOrId, key, value=None)
+ if key.kind_of? Hash
+ key = _symbolkey2str(key)
+ coords = key.delete('coords')
+ self.coords(tagOrId, coords) if coords
+
+ if ( key['font'] || key['kanjifont'] \
+ || key['latinfont'] || key['asciifont'] )
+ tagfont_configure(tagid(tagOrId), key.dup)
+ else
+ _fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),
+ *hash_kv(key, true)))
+ end
+
+ else
+ if ( key == 'coords' || key == :coords )
+ self.coords(tagOrId, value)
+ elsif ( key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont )
+ if value == None
+ tagfontobj(tagid(tagOrId))
+ else
+ tagfont_configure(tagid(tagOrId), {key=>value})
+ end
+ else
+ _fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),
+ "-#{key}", _get_eval_enc_str(value)))
+ end
+ end
+ self
+ end
+# def itemconfigure(tagOrId, key, value=None)
+# if key.kind_of? Hash
+# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key)
+# else
+# tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
+# end
+# end
+# def itemconfigure(tagOrId, keys)
+# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(keys)
+# end
+
+ def itemconfiginfo(tagOrId, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ case key.to_s
+ when 'coords'
+ return ['coords', '', '', '', self.coords(tagOrId)]
+ when 'dash', 'activedash', 'disableddash'
+ conf = tk_split_simplelist(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))
+ if conf[3] && conf[3] =~ /^[0-9]/
+ conf[3] = list(conf[3])
+ end
+ if conf[4] && conf[4] =~ /^[0-9]/
+ conf[4] = list(conf[4])
+ end
+ when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
+ when 'font', 'kanjifont'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}")))
+ conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4])
+ else
+ conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
+ end
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).collect{|conflist|
+ conf = tk_split_simplelist(conflist)
+ conf[0] = conf[0][1..-1]
+ case conf[0]
+ when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
+ when 'dash', 'activedash', 'disableddash'
+ if conf[3] && conf[3] =~ /^[0-9]/
+ conf[3] = list(conf[3])
+ end
+ if conf[4] && conf[4] =~ /^[0-9]/
+ conf[4] = list(conf[4])
+ end
+ 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] = tagfont_configinfo(tagid(tagOrId), fontconf[4])
+ ret.push(fontconf)
+ end
+
+ ret << ['coords', '', '', '', self.coords(tagOrId)]
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ case key.to_s
+ when 'coords'
+ {'coords' => ['', '', '', self.coords(tagOrId)]}
+ when 'dash', 'activedash', 'disableddash'
+ conf = tk_split_simplelist(tk_send_without_enc('itemconfigure',
+ tagid(tagOrId),
+ "-#{key}"))
+ if conf[3] && conf[3] =~ /^[0-9]/
+ conf[3] = list(conf[3])
+ end
+ if conf[4] && conf[4] =~ /^[0-9]/
+ conf[4] = list(conf[4])
+ end
+ when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
+ when 'font', 'kanjifont'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}")))
+ conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4])
+ else
+ conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
+ end
+ key = conf.shift[1..-1]
+ { key => conf }
+ else
+ ret = {}
+ tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).each{|conflist|
+ conf = tk_split_simplelist(conflist)
+ key = conf.shift[1..-1]
+ case key
+ when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
+ when 'dash', 'activedash', 'disableddash'
+ if conf[2] && conf[2] =~ /^[0-9]/
+ conf[2] = list(conf[2])
+ end
+ if conf[3] && conf[3] =~ /^[0-9]/
+ conf[3] = list(conf[3])
+ end
+ 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] = tagfont_configinfo(tagid(tagOrId), fontconf[3])
+ ret['font'] = fontconf
+ end
+
+ ret['coords'] = ['', '', '', self.coords(tagOrId)]
+
+ ret
+ end
+ end
+ end
+
+ def current_itemconfiginfo(tagOrId, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ conf = itemconfiginfo(tagOrId, key)
+ {conf[0] => conf[4]}
+ else
+ ret = {}
+ itemconfiginfo(tagOrId).each{|conf|
+ ret[conf[0]] = conf[4] if conf.size > 2
+ }
+ ret
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ itemconfiginfo(tagOrId, key).each{|k, conf|
+ ret[k] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+=end
+
+ def lower(tag, below=nil)
+ if below
+ tk_send_without_enc('lower', tagid(tag), tagid(below))
+ else
+ tk_send_without_enc('lower', tagid(tag))
+ end
+ self
+ end
+
+ def move(tag, x, y)
+ tk_send_without_enc('move', tagid(tag), x, y)
+ self
+ end
+
+ def postscript(keys)
+ tk_send("postscript", *hash_kv(keys))
+ end
+
+ def raise(tag, above=nil)
+ if above
+ tk_send_without_enc('raise', tagid(tag), tagid(above))
+ else
+ tk_send_without_enc('raise', tagid(tag))
+ end
+ self
+ end
+
+ def scale(tag, x, y, xs, ys)
+ tk_send_without_enc('scale', tagid(tag), x, y, xs, ys)
+ self
+ end
+
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y, gain=None)
+ tk_send_without_enc('scan', 'dragto', x, y, gain)
+ self
+ end
+
+ def select(mode, *args)
+ r = tk_send_without_enc('select', mode, *args)
+ (mode == 'item')? TkcItem.id2obj(self, r): self
+ end
+ def select_adjust(tagOrId, index)
+ select('adjust', tagid(tagOrId), index)
+ end
+ def select_clear
+ select('clear')
+ end
+ def select_from(tagOrId, index)
+ select('from', tagid(tagOrId), index)
+ end
+ def select_item
+ select('item')
+ end
+ def select_to(tagOrId, index)
+ select('to', tagid(tagOrId), index)
+ end
+
+ def itemtype(tag)
+ TkcItem.type2class(tk_send('type', tagid(tag)))
+ end
+end
+
+#TkCanvas = Tk::Canvas unless Object.const_defined? :TkCanvas
+Tk.__set_toplevel_aliases__(:Tk, Tk::Canvas, :TkCanvas)
+
+
+class TkcItem<TkObject
+ extend Tk
+ include TkcTagAccess
+ extend TkItemFontOptkeys
+ extend TkItemConfigOptkeys
+
+ CItemTypeName = nil
+ CItemTypeToClass = {}
+
+ CItemID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ CItemID_TBL.mutex.synchronize{ CItemID_TBL.clear }
+ }
+
+ def TkcItem.type2class(type)
+ CItemTypeToClass[type]
+ end
+
+ def TkcItem.id2obj(canvas, id)
+ cpath = canvas.path
+ CItemID_TBL.mutex.synchronize{
+ if CItemID_TBL[cpath]
+ CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ ########################################
+ def self._parse_create_args(args)
+ fontkeys = {}
+ methodkeys = {}
+ if args[-1].kind_of? Hash
+ keys = _symbolkey2str(args.pop)
+ if args.size == 0
+ args = keys.delete('coords')
+ unless args.kind_of?(Array)
+ fail "coords parameter must be given by an Array"
+ end
+ end
+
+ #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
+ # fontkeys[key] = keys.delete(key) if keys.key?(key)
+ #}
+ __item_font_optkeys(nil).each{|key|
+ fkey = key.to_s
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+ fkey = "kanji#{key}"
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+ fkey = "latin#{key}"
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+ fkey = "ascii#{key}"
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+ }
+
+ __item_optkey_aliases(nil).each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if keys.has_key?(alias_name)
+ keys[real_name.to_s] = keys.delete(alias_name)
+ end
+ }
+
+ __item_methodcall_optkeys(nil).each{|key|
+ key = key.to_s
+ methodkeys[key] = keys.delete(key) if keys.key?(key)
+ }
+
+ __item_ruby2val_optkeys(nil).each{|key, method|
+ key = key.to_s
+ keys[key] = method.call(keys[key]) if keys.has_key?(key)
+ }
+
+ #args = args.flatten.concat(hash_kv(keys))
+ args = args.flatten.concat(itemconfig_hash_kv(nil, keys))
+ else
+ args = args.flatten
+ end
+
+ [args, fontkeys]
+ end
+ private_class_method :_parse_create_args
+
+ def self.create(canvas, *args)
+ unless self::CItemTypeName
+ fail RuntimeError, "#{self} is an abstract class"
+ end
+ args, fontkeys = _parse_create_args(args)
+ idnum = tk_call_without_enc(canvas.path, 'create',
+ self::CItemTypeName, *args)
+ canvas.itemconfigure(idnum, fontkeys) unless fontkeys.empty?
+ idnum.to_i # 'canvas item id' is an integer number
+ end
+ ########################################
+
+ def initialize(parent, *args)
+ #unless parent.kind_of?(Tk::Canvas)
+ # fail ArgumentError, "expect Tk::Canvas for 1st argument"
+ #end
+ @parent = @c = parent
+ @path = parent.path
+
+ @id = create_self(*args) # an integer number as 'canvas item id'
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
+ CItemID_TBL[@path][@id] = self
+ }
+ end
+ def create_self(*args)
+ self.class.create(@c, *args) # return an integer number as 'canvas item id'
+ end
+ private :create_self
+
+ def id
+ @id
+ end
+
+ def exist?
+ if @c.find_withtag(@id)
+ true
+ else
+ false
+ end
+ end
+
+ def delete
+ @c.delete @id
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
+ self
+ end
+ alias remove delete
+ alias destroy delete
+end
+
+class TkcArc<TkcItem
+ CItemTypeName = 'arc'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+end
+
+class TkcBitmap<TkcItem
+ CItemTypeName = 'bitmap'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+end
+
+class TkcImage<TkcItem
+ CItemTypeName = 'image'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+end
+
+class TkcLine<TkcItem
+ CItemTypeName = 'line'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+end
+
+class TkcOval<TkcItem
+ CItemTypeName = 'oval'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+end
+
+class TkcPolygon<TkcItem
+ CItemTypeName = 'polygon'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+end
+
+class TkcRectangle<TkcItem
+ CItemTypeName = 'rectangle'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+end
+
+class TkcText<TkcItem
+ CItemTypeName = 'text'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+ def self.create(canvas, *args)
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ txt = keys['text']
+ keys['text'] = _get_eval_enc_str(txt) if txt
+ args.push(keys)
+ end
+ super(canvas, *args)
+ end
+end
+
+class TkcWindow<TkcItem
+ CItemTypeName = 'window'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+ def self.create(canvas, *args)
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ win = keys['window']
+ # keys['window'] = win.epath if win.kind_of?(TkWindow)
+ keys['window'] = _epath(win) if win
+ args.push(keys)
+ end
+ super(canvas, *args)
+ end
+end
diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb
new file mode 100644
index 0000000000..49796d80b2
--- /dev/null
+++ b/ext/tk/lib/tk/canvastag.rb
@@ -0,0 +1,434 @@
+#
+# tk/canvastag.rb - methods for treating canvas tags
+#
+require 'tk'
+require 'tk/tagfont'
+
+module TkcTagAccess
+ include TkComm
+ include TkTreatTagFont
+end
+
+require 'tk/canvas'
+
+module TkcTagAccess
+ def addtag(tag)
+ @c.addtag(tag, 'withtag', @id)
+ self
+ end
+
+ def bbox
+ @c.bbox(@id)
+ end
+
+ #def bind(seq, cmd=Proc.new, *args)
+ # @c.itembind(@id, seq, cmd, *args)
+ # self
+ #end
+ def bind(seq, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ @c.itembind(@id, seq, cmd, *args)
+ self
+ end
+
+ #def bind_append(seq, cmd=Proc.new, *args)
+ # @c.itembind_append(@id, seq, cmd, *args)
+ # self
+ #end
+ def bind_append(seq, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ @c.itembind_append(@id, seq, cmd, *args)
+ self
+ end
+
+ def bind_remove(seq)
+ @c.itembind_remove(@id, seq)
+ self
+ end
+
+ def bindinfo(seq=nil)
+ @c.itembindinfo(@id, seq)
+ end
+
+ def cget(option)
+ @c.itemcget(@id, option)
+ end
+ def cget_strict(option)
+ @c.itemcget_strict(@id, option)
+ end
+
+ def configure(key, value=None)
+ @c.itemconfigure(@id, key, value)
+ self
+ end
+# def configure(keys)
+# @c.itemconfigure @id, keys
+# end
+
+ def configinfo(key=nil)
+ @c.itemconfiginfo(@id, key)
+ end
+
+ def current_configinfo(key=nil)
+ @c.current_itemconfiginfo(@id, key)
+ end
+
+ def coords(*args)
+ @c.coords(@id, *args)
+ end
+
+ def dchars(first, last=None)
+ @c.dchars(@id, first, last)
+ self
+ end
+
+ def dtag(tag_to_del=None)
+ @c.dtag(@id, tag_to_del)
+ self
+ end
+ alias deltag dtag
+
+ def find
+ @c.find('withtag', @id)
+ end
+ alias list find
+
+ def focus
+ @c.itemfocus(@id)
+ end
+
+ def gettags
+ @c.gettags(@id)
+ end
+
+ def icursor(index)
+ @c.icursor(@id, index)
+ self
+ end
+
+ def index(idx)
+ @c.index(@id, idx)
+ end
+
+ def insert(beforethis, string)
+ @c.insert(@id, beforethis, string)
+ self
+ end
+
+ def lower(belowthis=None)
+ @c.lower(@id, belowthis)
+ self
+ end
+
+ def move(xamount, yamount)
+ @c.move(@id, xamount, yamount)
+ self
+ end
+
+ def raise(abovethis=None)
+ @c.raise(@id, abovethis)
+ self
+ end
+
+ def scale(xorigin, yorigin, xscale, yscale)
+ @c.scale(@id, xorigin, yorigin, xscale, yscale)
+ self
+ end
+
+ def select_adjust(index)
+ @c.select('adjust', @id, index)
+ self
+ end
+ def select_from(index)
+ @c.select('from', @id, index)
+ self
+ end
+ def select_to(index)
+ @c.select('to', @id, index)
+ self
+ end
+
+ def itemtype
+ @c.itemtype(@id)
+ end
+
+ # Following operators support logical expressions of canvas tags
+ # (for Tk8.3+).
+ # If tag1.path is 't1' and tag2.path is 't2', then
+ # ltag = tag1 & tag2; ltag.path => "(t1)&&(t2)"
+ # ltag = tag1 | tag2; ltag.path => "(t1)||(t2)"
+ # ltag = tag1 ^ tag2; ltag.path => "(t1)^(t2)"
+ # ltag = - tag1; ltag.path => "!(t1)"
+ def & (tag)
+ if tag.kind_of? TkObject
+ TkcTagString.new(@c, '(' + @id + ')&&(' + tag.path + ')')
+ else
+ TkcTagString.new(@c, '(' + @id + ')&&(' + tag.to_s + ')')
+ end
+ end
+
+ def | (tag)
+ if tag.kind_of? TkObject
+ TkcTagString.new(@c, '(' + @id + ')||(' + tag.path + ')')
+ else
+ TkcTagString.new(@c, '(' + @id + ')||(' + tag.to_s + ')')
+ end
+ end
+
+ def ^ (tag)
+ if tag.kind_of? TkObject
+ TkcTagString.new(@c, '(' + @id + ')^(' + tag.path + ')')
+ else
+ TkcTagString.new(@c, '(' + @id + ')^(' + tag.to_s + ')')
+ end
+ end
+
+ def -@
+ TkcTagString.new(@c, '!(' + @id + ')')
+ end
+end
+
+class TkcTag<TkObject
+ include TkcTagAccess
+
+ CTagID_TBL = TkCore::INTERP.create_table
+
+ (Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ CTagID_TBL.mutex.synchronize{ CTagID_TBL.clear }
+ }
+
+ def TkcTag.id2obj(canvas, id)
+ cpath = canvas.path
+ CTagID_TBL.mutex.synchronize{
+ if CTagID_TBL[cpath]
+ CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(parent, mode=nil, *args)
+ #unless parent.kind_of?(TkCanvas)
+ # fail ArgumentError, "expect TkCanvas for 1st argument"
+ #end
+ @c = parent
+ @cpath = parent.path
+ Tk_CanvasTag_ID.mutex.synchronize{
+ # @path = @id = Tk_CanvasTag_ID.join('')
+ @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_)
+ Tk_CanvasTag_ID[1].succ!
+ }
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
+ if mode
+ tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
+ end
+ end
+ def id
+ @id
+ end
+
+ def exist?
+ if @c.find_withtag(@id)
+ true
+ else
+ false
+ end
+ end
+
+ def delete
+ @c.delete @id
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
+ }
+ self
+ end
+ alias remove delete
+ alias destroy delete
+
+ def set_to_above(target)
+ @c.addtag_above(@id, target)
+ self
+ end
+ alias above set_to_above
+
+ def set_to_all
+ @c.addtag_all(@id)
+ self
+ end
+ alias all set_to_all
+
+ def set_to_below(target)
+ @c.addtag_below(@id, target)
+ self
+ end
+ alias below set_to_below
+
+ def set_to_closest(x, y, halo=None, start=None)
+ @c.addtag_closest(@id, x, y, halo, start)
+ self
+ end
+ alias closest set_to_closest
+
+ def set_to_enclosed(x1, y1, x2, y2)
+ @c.addtag_enclosed(@id, x1, y1, x2, y2)
+ self
+ end
+ alias enclosed set_to_enclosed
+
+ def set_to_overlapping(x1, y1, x2, y2)
+ @c.addtag_overlapping(@id, x1, y1, x2, y2)
+ self
+ end
+ alias overlapping set_to_overlapping
+
+ def set_to_withtag(target)
+ @c.addtag_withtag(@id, target)
+ self
+ end
+ alias withtag set_to_withtag
+end
+
+class TkcTagString<TkcTag
+ def self.new(parent, name, mode=nil, *args)
+ obj = nil
+ CTagID_TBL.mutex.synchronize{
+ if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name]
+ obj = CTagID_TBL[parent.path][name]
+ else
+ # super(parent, name, *args)
+ (obj = self.allocate).instance_eval{
+ @c = parent
+ @cpath = parent.path
+ @path = @id = name
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
+ end
+ }
+ if obj && mode
+ tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
+ end
+ obj
+ end
+
+ def initialize(parent, name, mode=nil, *args)
+ # dummy:: not called by 'new' method
+
+ #unless parent.kind_of?(TkCanvas)
+ # fail ArgumentError, "expect TkCanvas for 1st argument"
+ #end
+ @c = parent
+ @cpath = parent.path
+ @path = @id = name
+
+ if mode
+ tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
+ end
+ end
+end
+TkcNamedTag = TkcTagString
+
+class TkcTagAll<TkcTagString
+ def self.new(parent)
+ super(parent, 'all')
+ end
+=begin
+ def initialize(parent)
+ #unless parent.kind_of?(TkCanvas)
+ # fail ArgumentError, "expect TkCanvas for 1st argument"
+ #end
+ @c = parent
+ @cpath = parent.path
+ @path = @id = 'all'
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
+ end
+=end
+end
+
+class TkcTagCurrent<TkcTagString
+ def self.new(parent)
+ super(parent, 'current')
+ end
+=begin
+ def initialize(parent)
+ #unless parent.kind_of?(TkCanvas)
+ # fail ArgumentError, "expect TkCanvas for 1st argument"
+ #end
+ @c = parent
+ @cpath = parent.path
+ @path = @id = 'current'
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
+ end
+=end
+end
+
+class TkcGroup<TkcTag
+ (Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ #def create_self(parent, *args)
+ def initialize(parent, *args)
+ #unless parent.kind_of?(TkCanvas)
+ # fail ArgumentError, "expect TkCanvas for 1st argument"
+ #end
+ @c = parent
+ @cpath = parent.path
+ Tk_cGroup_ID.mutex.synchronize{
+ # @path = @id = Tk_cGroup_ID.join('')
+ @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_)
+ Tk_cGroup_ID[1].succ!
+ }
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
+ include(*args) if args != []
+ end
+ #private :create_self
+
+ def include(*tags)
+ for i in tags
+ #i.addtag(@id)
+ @c.addtag_withtag(@id, i)
+ end
+ self
+ end
+ alias add include
+
+ def exclude(*tags)
+ for i in tags
+ #i.dtag(@id)
+ @c.dtag(i, @id)
+ end
+ self
+ end
+end
diff --git a/ext/tk/lib/tk/checkbutton.rb b/ext/tk/lib/tk/checkbutton.rb
new file mode 100644
index 0000000000..b1186a87ed
--- /dev/null
+++ b/ext/tk/lib/tk/checkbutton.rb
@@ -0,0 +1,30 @@
+#
+# tk/checkbutton.rb : treat checkbutton widget
+#
+require 'tk'
+require 'tk/radiobutton'
+
+class Tk::CheckButton<Tk::RadioButton
+ TkCommandNames = ['checkbutton'.freeze].freeze
+ WidgetClassName = 'Checkbutton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('checkbutton', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('checkbutton', @path)
+ # end
+ #end
+ #private :create_self
+
+ def toggle
+ tk_send_without_enc('toggle')
+ self
+ end
+end
+
+Tk::Checkbutton = Tk::CheckButton
+#TkCheckButton = Tk::CheckButton unless Object.const_defined? :TkCheckButton
+#TkCheckbutton = Tk::Checkbutton unless Object.const_defined? :TkCheckbutton
+Tk.__set_toplevel_aliases__(:Tk, Tk::CheckButton,
+ :TkCheckButton, :TkCheckbutton)
diff --git a/ext/tk/lib/tk/clipboard.rb b/ext/tk/lib/tk/clipboard.rb
new file mode 100644
index 0000000000..d4205a5c28
--- /dev/null
+++ b/ext/tk/lib/tk/clipboard.rb
@@ -0,0 +1,75 @@
+#
+# tk/clipboard.rb : methods to treat clipboard
+#
+require 'tk'
+
+module TkClipboard
+ include Tk
+ extend Tk
+
+ TkCommandNames = ['clipboard'.freeze].freeze
+
+ def self.clear(win=nil)
+ if win
+ tk_call_without_enc('clipboard', 'clear', '-displayof', win)
+ else
+ tk_call_without_enc('clipboard', 'clear')
+ end
+ end
+ def self.clear_on_display(win)
+ tk_call_without_enc('clipboard', 'clear', '-displayof', win)
+ end
+
+ def self.get(type=nil)
+ if type
+ tk_call_without_enc('clipboard', 'get', '-type', type)
+ else
+ tk_call_without_enc('clipboard', 'get')
+ end
+ end
+ def self.get_on_display(win, type=nil)
+ if type
+ tk_call_without_enc('clipboard', 'get', '-displayof', win, '-type', type)
+ else
+ tk_call_without_enc('clipboard', 'get', '-displayof', win)
+ end
+ end
+
+ def self.set(data, keys=nil)
+ clear
+ append(data, keys)
+ end
+ def self.set_on_display(win, data, keys=nil)
+ clear(win)
+ append_on_display(win, data, keys)
+ end
+
+ def self.append(data, keys=nil)
+ args = ['clipboard', 'append']
+ args.concat(hash_kv(keys))
+ args.concat(['--', data])
+ tk_call(*args)
+ end
+ def self.append_on_display(win, data, keys=nil)
+ args = ['clipboard', 'append', '-displayof', win]
+ args.concat(hash_kv(keys))
+ args.concat(['--', data])
+ tk_call(*args)
+ end
+
+ def clear
+ TkClipboard.clear_on_display(self)
+ self
+ end
+ def get(type=nil)
+ TkClipboard.get_on_display(self, type)
+ end
+ def set(data, keys=nil)
+ TkClipboard.set_on_display(self, data, keys)
+ self
+ end
+ def append(data, keys=nil)
+ TkClipboard.append_on_display(self, data, keys)
+ self
+ end
+end
diff --git a/ext/tk/lib/tk/clock.rb b/ext/tk/lib/tk/clock.rb
new file mode 100644
index 0000000000..4e9438f5ab
--- /dev/null
+++ b/ext/tk/lib/tk/clock.rb
@@ -0,0 +1,71 @@
+#
+# tk/clock.rb : methods for clock command
+#
+require 'tk'
+
+module Tk
+ module Clock
+ include Tk
+ extend TkCore
+
+ def self.add(clk, *args)
+ tk_call_without_enc('clock','add', clk, *args).to_i
+ end
+
+ def self.clicks(ms=nil)
+ ms = ms.to_s if ms.kind_of?(Symbol)
+ case ms
+ when nil, ''
+ tk_call_without_enc('clock','clicks').to_i
+ when /^mic/
+ tk_call_without_enc('clock','clicks','-microseconds').to_i
+ when /^mil/
+ tk_call_without_enc('clock','clicks','-milliseconds').to_i
+ else
+ tk_call_without_enc('clock','clicks','-milliseconds').to_i
+ end
+ end
+
+ def self.format(clk, form=nil)
+ if form
+ tk_call('clock','format',clk,'-format',form)
+ else
+ tk_call('clock','format',clk)
+ end
+ end
+
+ def self.formatGMT(clk, form=nil)
+ if form
+ tk_call('clock','format',clk,'-format',form,'-gmt','1')
+ else
+ tk_call('clock','format',clk,'-gmt','1')
+ end
+ end
+
+ def self.scan(str, base=nil)
+ if base
+ tk_call('clock','scan',str,'-base',base).to_i
+ else
+ tk_call('clock','scan',str).to_i
+ end
+ end
+
+ def self.scanGMT(str, base=nil)
+ if base
+ tk_call('clock','scan',str,'-base',base,'-gmt','1').to_i
+ else
+ tk_call('clock','scan',str,'-gmt','1').to_i
+ end
+ end
+
+ def self.seconds
+ tk_call_without_enc('clock','seconds').to_i
+ end
+ def self.milliseconds
+ tk_call_without_enc('clock','milliseconds').to_i
+ end
+ def self.microseconds
+ tk_call_without_enc('clock','microseconds').to_i
+ end
+ end
+end
diff --git a/ext/tk/lib/tk/composite.rb b/ext/tk/lib/tk/composite.rb
new file mode 100644
index 0000000000..883d43c3ea
--- /dev/null
+++ b/ext/tk/lib/tk/composite.rb
@@ -0,0 +1,458 @@
+#
+# tk/composite.rb :
+#
+require 'tk'
+
+module TkComposite
+ include Tk
+ extend Tk
+
+=begin
+ def initialize(parent=nil, *args)
+ @delegates = {}
+ @option_methods = {}
+ @option_setting = {}
+
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ parent = keys.delete('parent')
+ @frame = TkFrame.new(parent)
+ @path = @epath = @frame.path
+ initialize_composite(keys)
+ else
+ @frame = TkFrame.new(parent)
+ @path = @epath = @frame.path
+ initialize_composite(*args)
+ end
+ end
+=end
+
+ def _choice_classname_of_baseframe
+ base_class_name = nil
+
+ klass = WidgetClassNames[self.class::WidgetClassName]
+
+ if klass
+ # WidgetClassName is a known class
+ #if klass <= TkFrame || klass < TkComposite
+ if klass <= TkFrame || klass < Tk::Frame || klass < TkComposite
+ # klass is valid for the base frame
+ if self.class <= klass
+ # use my classname
+ base_class_name = self.class.name
+ if base_class_name == ''
+ # anonymous class -> use ancestor's name
+ base_class_name = klass.name
+ end
+ else
+ # not subclass -> use WidgetClassName
+ base_class_name = klass.name
+ end
+
+ else
+ # klass is invalid for the base frame
+ #if self.class < TkFrame || self.class.superclass < TkComposite
+ if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite
+ # my class name is valid for the base frame -> use my classname
+ base_class_name = self.class.name
+ if base_class_name == ''
+ # anonymous class -> use TkFrame
+ base_class_name = nil
+ end
+ else
+ # no idea for the base frame -> use TkFrame
+ base_class_name = nil
+ end
+ end
+
+ elsif self.class::WidgetClassName && ! self.class::WidgetClassName.empty?
+ # unknown WidgetClassName is defined -> use it for the base frame
+ base_class_name = self.class::WidgetClassName
+
+ else
+ # no valid WidgetClassName
+ #if self.class < TkFrame || self.class.superclass < TkComposite
+ if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite
+ # my class name is valid for the base frame -> use my classname
+ base_class_name = self.class.name
+ if base_class_name == ''
+ # anonymous class -> use TkFrame
+ base_class_name = nil
+ end
+ else
+ # no idea for the base frame -> use TkFrame
+ base_class_name = nil
+ end
+ end
+
+ base_class_name
+ end
+ private :_choice_classname_of_baseframe
+
+ # def initialize(parent=nil, *args)
+ def initialize(*args)
+ @delegates = {}
+ @option_methods = {}
+ @option_setting = {}
+
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ else
+ keys = {}
+ end
+ parent = args.shift
+ parent = keys.delete('parent') if keys.has_key?('parent')
+
+ if keys.key?('classname')
+ keys['class'] = keys.delete('classname')
+ end
+ if (base_class_name = (keys.delete('class')).to_s).empty?
+ base_class_name = _choice_classname_of_baseframe
+ end
+
+ if base_class_name
+ # @frame = Tk::Frame.new(parent, :class=>base_class_name)
+ # --> use current TkFrame class
+ @frame = TkFrame.new(parent, :class=>base_class_name)
+ else
+ # @frame = Tk::Frame.new(parent)
+ # --> use current TkFrame class
+ @frame = TkFrame.new(parent)
+ end
+ @path = @epath = @frame.path
+
+ args.push(keys) unless keys.empty?
+ initialize_composite(*args)
+ end
+
+ def database_classname
+ @frame.database_classname
+ end
+
+ def database_class
+ @frame.database_class
+ end
+
+ def epath
+ @epath
+ end
+
+ def initialize_composite(*args) end
+ private :initialize_composite
+
+ def inspect
+ str = super
+ str.chop << ' @epath=' << @epath.inspect << '>'
+ end
+
+ def option_methods(*opts)
+ opts.each{|m_set, m_cget, m_info|
+ m_set = m_set.to_s
+ m_cget = m_set if !m_cget && self.method(m_set).arity == -1
+ m_cget = m_cget.to_s if m_cget
+ m_info = m_info.to_s if m_info
+ @option_methods[m_set] = {
+ :set => m_set, :cget => m_cget, :info => m_info
+ }
+ }
+ end
+
+ def delegate_alias(alias_opt, option, *wins)
+ if wins.length == 0
+ fail ArgumentError, "target widgets are not given"
+ end
+ if alias_opt != option && (alias_opt == 'DEFAULT' || option == 'DEFAULT')
+ fail ArgumentError, "cannot alias 'DEFAULT' option"
+ end
+ alias_opt = alias_opt.to_s
+ option = option.to_s
+ if @delegates[alias_opt].kind_of?(Array)
+ if (elem = @delegates[alias_opt].assoc(option))
+ wins.each{|w| elem[1].push(w)}
+ else
+ @delegates[alias_opt] << [option, wins]
+ end
+ else
+ @delegates[alias_opt] = [ [option, wins] ]
+ end
+ end
+
+ def delegate(option, *wins)
+ delegate_alias(option, option, *wins)
+ end
+
+ def __cget_delegates(slot)
+ slot = slot.to_s
+
+ if @option_methods.include?(slot)
+ if @option_methods[slot][:cget]
+ return self.__send__(@option_methods[slot][:cget])
+ else
+ if @option_setting[slot]
+ return @option_setting[slot]
+ else
+ return ''
+ end
+ end
+ end
+
+ tbl = @delegates[slot]
+ tbl = @delegates['DEFAULT'] unless tbl
+
+ begin
+ if tbl
+ opt, wins = tbl[-1]
+ opt = slot if opt == 'DEFAULT'
+ if wins && wins[-1]
+ # return wins[-1].cget(opt)
+ return wins[-1].cget_strict(opt)
+ end
+ end
+ rescue
+ end
+
+ return None
+ end
+ private :__cget_delegates
+
+ def cget(slot)
+ if (ret = __cget_delegates(slot)) == None
+ super(slot)
+ else
+ ret
+ end
+ end
+
+ def cget_strict(slot)
+ if (ret = __cget_delegates(slot)) == None
+ super(slot)
+ else
+ ret
+ end
+ end
+
+=begin
+ def cget(slot)
+ slot = slot.to_s
+
+ if @option_methods.include?(slot)
+ if @option_methods[slot][:cget]
+ return self.__send__(@option_methods[slot][:cget])
+ else
+ if @option_setting[slot]
+ return @option_setting[slot]
+ else
+ return ''
+ end
+ end
+ end
+
+ tbl = @delegates[slot]
+ tbl = @delegates['DEFAULT'] unless tbl
+
+ begin
+ if tbl
+ opt, wins = tbl[-1]
+ opt = slot if opt == 'DEFAULT'
+ if wins && wins[-1]
+ return wins[-1].cget(opt)
+ end
+ end
+ rescue
+ end
+
+ super(slot)
+ end
+=end
+
+ def configure(slot, value=None)
+ if slot.kind_of? Hash
+ slot.each{|slot,value| configure slot, value}
+ return self
+ end
+
+ slot = slot.to_s
+
+ if @option_methods.include?(slot)
+ unless @option_methods[slot][:cget]
+ if value.kind_of?(Symbol)
+ @option_setting[slot] = value.to_s
+ else
+ @option_setting[slot] = value
+ end
+ end
+ return self.__send__(@option_methods[slot][:set], value)
+ end
+
+ tbl = @delegates[slot]
+ tbl = @delegates['DEFAULT'] unless tbl
+
+ begin
+ if tbl
+ last = nil
+ tbl.each{|opt, wins|
+ opt = slot if opt == 'DEFAULT'
+ wins.each{|w| last = w.configure(opt, value)}
+ }
+ return last
+ end
+ rescue
+ end
+
+ super(slot, value)
+ end
+
+ def configinfo(slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ slot = slot.to_s
+ if @option_methods.include?(slot)
+ if @option_methods[slot][:info]
+ return self.__send__(@option_methods[slot][:info])
+ else
+ return [slot, '', '', '', self.cget(slot)]
+ end
+ end
+
+ tbl = @delegates[slot]
+ tbl = @delegates['DEFAULT'] unless tbl
+
+ begin
+ if tbl
+ if tbl.length == 1
+ opt, wins = tbl[0]
+ if slot == opt || opt == 'DEFAULT'
+ return wins[-1].configinfo(slot)
+ else
+ info = wins[-1].configinfo(opt)
+ info[0] = slot
+ return info
+ end
+ else
+ opt, wins = tbl[-1]
+ return [slot, '', '', '', wins[-1].cget(opt)]
+ end
+ end
+ rescue
+ end
+
+ super(slot)
+
+ else # slot == nil
+ info_list = super(slot)
+
+ tbl = @delegates['DEFAULT']
+ if tbl
+ wins = tbl[0][1]
+ if wins && wins[-1]
+ wins[-1].configinfo.each{|info|
+ slot = info[0]
+ info_list.delete_if{|i| i[0] == slot} << info
+ }
+ end
+ end
+
+ @delegates.each{|slot, tbl|
+ next if slot == 'DEFAULT'
+ if tbl.length == 1
+ opt, wins = tbl[0]
+ next unless wins && wins[-1]
+ if slot == opt
+ info_list.delete_if{|i| i[0] == slot} <<
+ wins[-1].configinfo(slot)
+ else
+ info = wins[-1].configinfo(opt)
+ info[0] = slot
+ info_list.delete_if{|i| i[0] == slot} << info
+ end
+ else
+ opt, wins = tbl[-1]
+ info_list.delete_if{|i| i[0] == slot} <<
+ [slot, '', '', '', wins[-1].cget(opt)]
+ end
+ }
+
+ @option_methods.each{|slot, m|
+ if m[:info]
+ info = self.__send__(m[:info])
+ else
+ info = [slot, '', '', '', self.cget(slot)]
+ end
+ info_list.delete_if{|i| i[0] == slot} << info
+ }
+
+ info_list
+ end
+
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ slot = slot.to_s
+ if @option_methods.include?(slot)
+ if @option_methods[slot][:info]
+ return self.__send__(@option_methods[slot][:info])
+ else
+ return {slot => ['', '', '', self.cget(slot)]}
+ end
+ end
+
+ tbl = @delegates[slot]
+ tbl = @delegates['DEFAULT'] unless tbl
+
+ begin
+ if tbl
+ if tbl.length == 1
+ opt, wins = tbl[0]
+ if slot == opt || opt == 'DEFAULT'
+ return wins[-1].configinfo(slot)
+ else
+ return {slot => wins[-1].configinfo(opt)[opt]}
+ end
+ else
+ opt, wins = tbl[-1]
+ return {slot => ['', '', '', wins[-1].cget(opt)]}
+ end
+ end
+ rescue
+ end
+
+ super(slot)
+
+ else # slot == nil
+ info_list = super(slot)
+
+ tbl = @delegates['DEFAULT']
+ if tbl
+ wins = tbl[0][1]
+ info_list.update(wins[-1].configinfo) if wins && wins[-1]
+ end
+
+ @delegates.each{|slot, tbl|
+ next if slot == 'DEFAULT'
+ if tbl.length == 1
+ opt, wins = tbl[0]
+ next unless wins && wins[-1]
+ if slot == opt
+ info_list.update(wins[-1].configinfo(slot))
+ else
+ info_list.update({slot => wins[-1].configinfo(opt)[opt]})
+ end
+ else
+ opt, wins = tbl[-1]
+ info_list.update({slot => ['', '', '', wins[-1].cget(opt)]})
+ end
+ }
+
+ @option_methods.each{|slot, m|
+ if m[:info]
+ info = self.__send__(m[:info])
+ else
+ info = {slot => ['', '', '', self.cget(slot)]}
+ end
+ info_list.update(info)
+ }
+
+ info_list
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tk/console.rb b/ext/tk/lib/tk/console.rb
new file mode 100644
index 0000000000..26ce262caa
--- /dev/null
+++ b/ext/tk/lib/tk/console.rb
@@ -0,0 +1,52 @@
+#
+# tk/console.rb : control the console on system without a real console
+#
+require 'tk'
+
+module TkConsole
+ include Tk
+ extend Tk
+
+ TkCommandNames = ['console'.freeze, 'consoleinterp'.freeze].freeze
+
+ def self.create
+ TkCore::INTERP._create_console
+ end
+ self.create # initialize console
+
+ def self.title(str=None)
+ tk_call 'console', str
+ end
+ def self.hide
+ tk_call_without_enc('console', 'hide')
+ end
+ def self.show
+ tk_call_without_enc('console', 'show')
+ end
+ def self.eval(tcl_script)
+ #
+ # supports a Tcl script only
+ # I have no idea to support a Ruby script seamlessly.
+ #
+ _fromUTF8(tk_call_without_enc('console', 'eval',
+ _get_eval_enc_str(tcl_script)))
+ end
+ def self.maininterp_eval(tcl_script)
+ #
+ # supports a Tcl script only
+ # I have no idea to support a Ruby script seamlessly.
+ #
+ _fromUTF8(tk_call_without_enc('consoleinterp', 'eval',
+ _get_eval_enc_str(tcl_script)))
+
+ end
+ def self.maininterp_record(tcl_script)
+ #
+ # supports a Tcl script only
+ # I have no idea to support a Ruby script seamlessly.
+ #
+ _fromUTF8(tk_call_without_enc('consoleinterp', 'record',
+ _get_eval_enc_str(tcl_script)))
+
+ end
+end
diff --git a/ext/tk/lib/tk/dialog.rb b/ext/tk/lib/tk/dialog.rb
new file mode 100644
index 0000000000..180da101e3
--- /dev/null
+++ b/ext/tk/lib/tk/dialog.rb
@@ -0,0 +1,326 @@
+#
+# tk/dialog.rb : create dialog boxes
+#
+require 'tk'
+require 'tk/variable.rb'
+
+class TkDialogObj < TkWindow
+ extend Tk
+
+ TkCommandNames = ['tk_dialog'.freeze].freeze
+
+ def self.show(*args)
+ dlog = self.new(*args)
+ dlog.show
+ dlog
+ end
+
+ def _set_button_config(configs)
+ set_config = proc{|c,i|
+ if $VERBOSE && (c.has_key?('command') || c.has_key?(:command))
+ STDERR.print("Warning: cannot give a command option " +
+ "to the dialog button#{i}. It was removed.\n")
+ end
+ c.delete('command'); c.delete(:command)
+ # @config << Kernel.format("%s.button%s configure %s; ",
+ # @path, i, hash_kv(c).join(' '))
+ # @config << @path+'.button'+i.to_s+' configure '+hash_kv(c).join(' ')+'; '
+ @config << @path+'.button'+i.to_s+' configure '+
+ array2tk_list(hash_kv(c))+'; '
+ }
+ case configs
+ when Proc
+ @buttons.each_index{|i|
+ if (c = configs.call(i)).kind_of?(Hash)
+ set_config.call(c,i)
+ end
+ }
+
+ when Array
+ @buttons.each_index{|i|
+ if (c = configs[i]).kind_of?(Hash)
+ set_config.call(c,i)
+ end
+ }
+
+ when Hash
+ @buttons.each_with_index{|s,i|
+ if (c = configs[s]).kind_of?(Hash)
+ set_config.call(c,i)
+ end
+ }
+ end
+ # @config = 'after idle {' + @config + '};' if @config != ""
+ @config = array2tk_list(['after', 'idle', @config]) << ';' if @config != ""
+ end
+ private :_set_button_config
+
+ # initialize tk_dialog
+ def create_self(keys)
+ # @var = TkVariable.new
+ @val = nil
+
+ @title = title
+
+ @message = message
+ @message_config = message_config
+ @msgframe_config = msgframe_config
+
+ @bitmap = bitmap
+ @bitmap_config = message_config
+
+ @default_button = default_button
+
+ @buttons = buttons
+ @button_configs = proc{|num| button_configs(num)}
+ @btnframe_config = btnframe_config
+
+ #@config = "puts [winfo children .w0000];"
+ @config = ""
+
+ @command = prev_command
+
+ if keys.kind_of?(Hash)
+ @title = keys['title'] if keys.key? 'title'
+ @message = keys['message'] if keys.key? 'message'
+ @bitmap = keys['bitmap'] if keys.key? 'bitmap'
+ # @bitmap = '{}' if @bitmap == nil || @bitmap == ""
+ @bitmap = '' unless @bitmap
+ @default_button = keys['default'] if keys.key? 'default'
+ @buttons = keys['buttons'] if keys.key? 'buttons'
+
+ @command = keys['prev_command'] if keys.key? 'prev_command'
+
+ @message_config = keys['message_config'] if keys.key? 'message_config'
+ @msgframe_config = keys['msgframe_config'] if keys.key? 'msgframe_config'
+ @bitmap_config = keys['bitmap_config'] if keys.key? 'bitmap_config'
+ @button_configs = keys['button_configs'] if keys.key? 'button_configs'
+ @btnframe_config = keys['btnframe_config'] if keys.key? 'btnframe_config'
+ end
+
+ #if @title.include? ?\s
+ # @title = '{' + @title + '}'
+ #end
+
+ if @buttons.kind_of?(Array)
+ _set_button_config(@buttons.collect{|cfg|
+ (cfg.kind_of? Array)? cfg[1]: nil})
+ @buttons = @buttons.collect{|cfg| (cfg.kind_of? Array)? cfg[0]: cfg}
+ end
+ if @buttons.kind_of?(Hash)
+ _set_button_config(@buttons)
+ @buttons = @buttons.keys
+ end
+ @buttons = tk_split_simplelist(@buttons) if @buttons.kind_of?(String)
+ @buttons = [] unless @buttons
+=begin
+ @buttons = @buttons.collect{|s|
+ if s.kind_of?(Array)
+ s = s.join(' ')
+ end
+ if s.include? ?\s
+ '{' + s + '}'
+ else
+ s
+ end
+ }
+=end
+
+ if @message_config.kind_of?(Hash)
+ # @config << Kernel.format("%s.msg configure %s;",
+ # @path, hash_kv(@message_config).join(' '))
+ # @config << @path+'.msg configure '+hash_kv(@message_config).join(' ')+';'
+ @config << @path+'.msg configure '+
+ array2tk_list(hash_kv(@message_config))+';'
+ end
+
+ if @msgframe_config.kind_of?(Hash)
+ # @config << Kernel.format("%s.top configure %s;",
+ # @path, hash_kv(@msgframe_config).join(' '))
+ # @config << @path+'.top configure '+hash_kv(@msgframe_config).join(' ')+';'
+ @config << @path+'.top configure '+
+ array2tk_list(hash_kv(@msgframe_config))+';'
+ end
+
+ if @btnframe_config.kind_of?(Hash)
+ # @config << Kernel.format("%s.bot configure %s;",
+ # @path, hash_kv(@btnframe_config).join(' '))
+ # @config << @path+'.bot configure '+hash_kv(@btnframe_config).join(' ')+';'
+ @config << @path+'.bot configure '+
+ array2tk_list(hash_kv(@btnframe_config))+';'
+ end
+
+ if @bitmap_config.kind_of?(Hash)
+ # @config << Kernel.format("%s.bitmap configure %s;",
+ # @path, hash_kv(@bitmap_config).join(' '))
+ # @config << @path+'.bitmap configure '+hash_kv(@bitmap_config).join(' ')+';'
+ @config << @path+'.bitmap configure '+
+ array2tk_list(hash_kv(@bitmap_config))+';'
+ end
+
+ _set_button_config(@button_configs) if @button_configs
+ end
+ private :create_self
+
+ def show
+ # if @command.kind_of?(Proc)
+ if TkComm._callback_entry?(@command)
+ @command.call(self)
+ end
+
+ if @default_button.kind_of?(String)
+ default_button = @buttons.index(@default_button)
+ else
+ default_button = @default_button
+ end
+ # default_button = '{}' if default_button == nil
+ default_button = '' if default_button == nil
+ #Tk.ip_eval('eval {global '+@var.id+';'+@config+
+ # 'set '+@var.id+' [tk_dialog '+
+ # @path+" "+@title+" {#{@message}} "+@bitmap+" "+
+ # String(default_button)+" "+@buttons.join(' ')+']}')
+ Tk.ip_eval(@config)
+ # @val = Tk.ip_eval('tk_dialog ' + @path + ' ' + @title +
+ # ' {' + @message + '} ' + @bitmap + ' ' +
+ # String(default_button) + ' ' + @buttons.join(' ')).to_i
+ # @val = Tk.ip_eval(self.class::TkCommandNames[0] + ' ' + @path + ' ' +
+ # @title + ' {' + @message + '} ' + @bitmap + ' ' +
+ # String(default_button) + ' ' + @buttons.join(' ')).to_i
+ @val = Tk.ip_eval(array2tk_list([
+ self.class::TkCommandNames[0],
+ @path, @title, @message, @bitmap,
+ String(default_button)
+ ].concat(@buttons))).to_i
+ end
+
+ def value
+ # @var.value.to_i
+ @val
+ end
+
+ def name
+ (@val)? @buttons[@val]: nil
+ end
+
+ ############################################################
+ # #
+ # following methods should be overridden for each dialog #
+ # #
+ ############################################################
+ private
+
+ def title
+ # returns a title string of the dialog window
+ return "DIALOG"
+ end
+ def message
+ # returns a message text to display on the dialog
+ return "MESSAGE"
+ end
+ def message_config
+ # returns a Hash {option=>value, ...} for the message text
+ return nil
+ end
+ def msgframe_config
+ # returns a Hash {option=>value, ...} for the message text frame
+ return nil
+ end
+ def bitmap
+ # returns a bitmap name or a bitmap file path
+ # (@ + path ; e.g. '@/usr/share/bitmap/sample.xbm')
+ return "info"
+ end
+ def bitmap_config
+ # returns nil or a Hash {option=>value, ...} for the bitmap
+ return nil
+ end
+ def default_button
+ # returns a default button's number or name
+ # if nil or null string, set no-default
+ return 0
+ end
+ def buttons
+ #return "BUTTON1 BUTTON2"
+ return ["BUTTON1", "BUTTON2"]
+ end
+ def button_configs(num)
+ # returns nil / Proc / Array or Hash (see _set_button_config)
+ return nil
+ end
+ def btnframe_config
+ # returns nil or a Hash {option=>value, ...} for the button frame
+ return nil
+ end
+ def prev_command
+ # returns nil or a Proc
+ return nil
+ end
+end
+TkDialog2 = TkDialogObj
+
+#
+# TkDialog : with showing at initialize
+#
+class TkDialog < TkDialogObj
+ def self.show(*args)
+ self.new(*args)
+ end
+
+ def initialize(*args)
+ super(*args)
+ show
+ end
+end
+
+
+#
+# dialog for warning
+#
+class TkWarningObj < TkDialogObj
+ def initialize(parent = nil, mes = nil)
+ if !mes
+ if parent.kind_of?(TkWindow)
+ mes = ""
+ else
+ mes = parent.to_s
+ parent = nil
+ end
+ end
+ super(parent, :message=>mes)
+ end
+
+ def show(mes = nil)
+ mes_bup = @message
+ @message = mes if mes
+ ret = super()
+ @message = mes_bup
+ ret
+ end
+
+ #######
+ private
+
+ def title
+ return "WARNING";
+ end
+ def bitmap
+ return "warning";
+ end
+ def default_button
+ return 0;
+ end
+ def buttons
+ return "OK";
+ end
+end
+TkWarning2 = TkWarningObj
+
+class TkWarning < TkWarningObj
+ def self.show(*args)
+ self.new(*args)
+ end
+ def initialize(*args)
+ super(*args)
+ show
+ end
+end
diff --git a/ext/tk/lib/tk/encodedstr.rb b/ext/tk/lib/tk/encodedstr.rb
new file mode 100644
index 0000000000..02de0b0d85
--- /dev/null
+++ b/ext/tk/lib/tk/encodedstr.rb
@@ -0,0 +1,187 @@
+#
+# tk/encodedstr.rb : Tk::EncodedString class
+#
+require 'tk'
+
+###########################################
+# string with Tcl's encoding
+###########################################
+module Tk
+ class EncodedString < String
+ Encoding = nil
+
+ def self.subst_utf_backslash(str)
+ # str.gsub(/\\u([0-9A-Fa-f]{1,4})/){[$1.hex].pack('U')}
+ TclTkLib._subst_UTF_backslash(str)
+ end
+ def self.utf_backslash(str)
+ self.subst_utf_backslash(str)
+ end
+
+ def self.subst_tk_backslash(str)
+ TclTkLib._subst_Tcl_backslash(str)
+ end
+
+ def self.utf_to_backslash_sequence(str)
+ str.unpack('U*').collect{|c|
+ if c <= 0xFF # ascii character
+ c.chr
+ else
+ format('\u%X', c)
+ end
+ }.join('')
+ end
+ def self.utf_to_backslash(str)
+ self.utf_to_backslash_sequence(str)
+ end
+
+ def self.to_backslash_sequence(str)
+ str.unpack('U*').collect{|c|
+ if c <= 0x1F # control character
+ case c
+ when 0x07; '\a'
+ when 0x08; '\b'
+ when 0x09; '\t'
+ when 0x0a; '\n'
+ when 0x0b; '\v'
+ when 0x0c; '\f'
+ when 0x0d; '\r'
+ else
+ format('\x%02X', c)
+ end
+ elsif c <= 0xFF # ascii character
+ c.chr
+ else
+ format('\u%X', c)
+ end
+ }.join('')
+ end
+
+ def self.new_with_utf_backslash(str, enc = nil)
+ self.new('', enc).replace(self.subst_utf_backslash(str))
+ end
+
+ def self.new_without_utf_backslash(str, enc = nil)
+ self.new('', enc).replace(str)
+ end
+
+ def initialize(str, enc = nil)
+ super(str)
+ # @encoding = ( enc ||
+ # ((self.class::Encoding)?
+ # self.class::Encoding : Tk.encoding_system) )
+ enc ||= (self.class::Encoding)?
+ self.class::Encoding :
+ ((Tk.encoding)? Tk.encoding : Tk.encoding_system)
+ if TkCore::WITH_ENCODING
+ unless encobj = Tk::Encoding::ENCODING_TABLE.get_obj(enc)
+ fail ArgumentError, "unsupported Tk encoding '#{enc}'"
+ end
+ self.force_encoding(encobj)
+ else
+ @encoding = enc
+ end
+ end
+
+ if TkCore::WITH_ENCODING
+ alias encoding_obj encoding
+ alias __encoding encoding
+ def encoding
+ Tk::Encoding::ENCODING_TABLE.get_name(super())
+ end
+ else
+ def encoding
+ @encoding
+ end
+ alias encoding_obj encoding
+ end
+
+ if TkCore::WITH_ENCODING
+ # wrapper methods for compatibility
+ alias __instance_variable_get instance_variable_get
+ alias __instance_variable_set instance_variable_set
+ alias __instance_eval instance_eval
+ alias __instance_variables instance_variables
+
+ def instance_variable_get(key)
+ if (key.to_s == '@encoding')
+ self.encoding
+ else
+ super(key)
+ end
+ end
+
+ def instance_variable_set(key, value)
+ if (key.to_s == '@encoding')
+ if value
+ self.force_encoding(value)
+ else
+ self.force_encoding(Tk::Encoding::UNKNOWN)
+ end
+ value
+ else
+ super(key, value)
+ end
+ end
+
+ def instance_eval(*args, &b)
+ old_enc = @encoding = self.encoding
+
+ ret = super(*args, &b)
+
+ if @encoding
+ if @encoding != old_enc
+ # modified by user
+ self.force_encoding(@encoding)
+ end
+ remove_instance_variable(:@encoding)
+ else
+ begin
+ remove_instance_variable(:@encoding)
+ # user sets to nil -> use current default
+ self.force_encoding(Tk.encoding)
+ rescue NameError
+ # removed by user -> ignore, because user don't use @encoding
+ end
+ end
+ ret
+ end
+ end
+
+ def instance_variables
+ ret = super()
+ ret << :@encoding # fake !!
+ ret
+ end
+ end
+ # def Tk.EncodedString(str, enc = nil)
+ # Tk::EncodedString.new(str, enc)
+ # end
+
+ ##################################
+
+ class BinaryString < EncodedString
+ Encoding = 'binary'.freeze
+ end
+ # def Tk.BinaryString(str)
+ # Tk::BinaryString.new(str)
+ # end
+
+ ##################################
+
+ class UTF8_String < EncodedString
+ Encoding = 'utf-8'.freeze
+ def self.new(str)
+ super(self.subst_utf_backslash(str))
+ end
+
+ def to_backslash_sequence
+ Tk::EncodedString.utf_to_backslash_sequence(self)
+ end
+ alias to_backslash to_backslash_sequence
+ end
+ # def Tk.UTF8_String(str)
+ # Tk::UTF8_String.new(str)
+ # end
+
+end
diff --git a/ext/tk/lib/tk/entry.rb b/ext/tk/lib/tk/entry.rb
new file mode 100644
index 0000000000..8ce8def1e7
--- /dev/null
+++ b/ext/tk/lib/tk/entry.rb
@@ -0,0 +1,119 @@
+#
+# tk/entry.rb - Tk entry classes
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require 'tk'
+require 'tk/label'
+require 'tk/scrollable'
+require 'tk/validation'
+
+class Tk::Entry<Tk::Label
+ include X_Scrollable
+ include TkValidation
+
+ TkCommandNames = ['entry'.freeze].freeze
+ WidgetClassName = 'Entry'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ #def create_self(keys)
+ # super(__conv_vcmd_on_hash_kv(keys))
+ #end
+ #private :create_self
+
+ def __strval_optkeys
+ super() + ['show', 'disabledbackground', 'readonlybackground']
+ end
+ private :__strval_optkeys
+
+ def bbox(index)
+ list(tk_send_without_enc('bbox', index))
+ end
+ def cursor
+ number(tk_send_without_enc('index', 'insert'))
+ end
+ alias icursor cursor
+ def cursor=(index)
+ tk_send_without_enc('icursor', index)
+ #self
+ index
+ end
+ alias icursor= cursor=
+ def index(idx)
+ number(tk_send_without_enc('index', idx))
+ end
+ def insert(pos,text)
+ tk_send_without_enc('insert', pos, _get_eval_enc_str(text))
+ self
+ end
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+ def mark(pos)
+ tk_send_without_enc('scan', 'mark', pos)
+ self
+ end
+ def dragto(pos)
+ tk_send_without_enc('scan', 'dragto', pos)
+ self
+ end
+ def selection_adjust(index)
+ tk_send_without_enc('selection', 'adjust', index)
+ self
+ end
+ def selection_clear
+ tk_send_without_enc('selection', 'clear')
+ self
+ end
+ def selection_from(index)
+ tk_send_without_enc('selection', 'from', index)
+ self
+ end
+ def selection_present()
+ bool(tk_send_without_enc('selection', 'present'))
+ end
+ def selection_range(s, e)
+ tk_send_without_enc('selection', 'range', s, e)
+ self
+ end
+ def selection_to(index)
+ tk_send_without_enc('selection', 'to', index)
+ self
+ end
+
+ def invoke_validate
+ bool(tk_send_without_enc('validate'))
+ end
+ def validate(mode = nil)
+ if mode
+ configure 'validate', mode
+ else
+ invoke_validate
+ end
+ end
+
+ def value
+ _fromUTF8(tk_send_without_enc('get'))
+ end
+ def value= (val)
+ tk_send_without_enc('delete', 0, 'end')
+ tk_send_without_enc('insert', 0, _get_eval_enc_str(val))
+ val
+ end
+ alias get value
+ alias set value=
+
+ def [](*args)
+ self.value[*args]
+ end
+ def []=(*args)
+ val = args.pop
+ str = self.value
+ str[*args] = val
+ self.value = str
+ val
+ end
+end
+
+#TkEntry = Tk::Entry unless Object.const_defined? :TkEntry
+Tk.__set_toplevel_aliases__(:Tk, Tk::Entry, :TkEntry)
diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb
new file mode 100644
index 0000000000..d8aad6248b
--- /dev/null
+++ b/ext/tk/lib/tk/event.rb
@@ -0,0 +1,542 @@
+#
+# tk/event.rb - module for event
+#
+
+module TkEvent
+end
+
+########################
+
+require 'tkutil'
+require 'tk'
+
+########################
+
+module TkEvent
+ class Event < TkUtil::CallbackSubst
+ module Grp
+ KEY = 0x1
+ BUTTON = 0x2
+ MOTION = 0x4
+ CROSSING = 0x8
+ FOCUS = 0x10
+ EXPOSE = 0x20
+ VISIBILITY = 0x40
+ CREATE = 0x80
+ DESTROY = 0x100
+ UNMAP = 0x200
+ MAP = 0x400
+ REPARENT = 0x800
+ CONFIG = 0x1000
+ GRAVITY = 0x2000
+ CIRC = 0x4000
+ PROP = 0x8000
+ COLORMAP = 0x10000
+ VIRTUAL = 0x20000
+ ACTIVATE = 0x40000
+ MAPREQ = 0x80000
+ CONFIGREQ = 0x100000
+ RESIZEREQ = 0x200000
+ CIRCREQ = 0x400000
+
+ MWHEEL = KEY
+
+ STRING_DATA = 0x80000000 # special flag for 'data' field
+
+ ALL = 0xFFFFFFFF
+
+ KEY_BUTTON_MOTION_VIRTUAL = (KEY|MWHEEL|BUTTON|MOTION|VIRTUAL)
+ KEY_BUTTON_MOTION_CROSSING = (KEY|MWHEEL|BUTTON|MOTION|CROSSING|VIRTUAL)
+ end
+
+ type_data = [
+ #-----+-------------------+------------------+-----------------------#
+ # ID | const | group_flag | context_name #
+ #-----+-------------------+------------------+-----------------------#
+ [ 2, :KeyPress, Grp::KEY, 'KeyPress', 'Key' ],
+ [ 3, :KeyRelease, Grp::KEY, 'KeyRelease' ],
+ [ 4, :ButtonPress, Grp::BUTTON, 'ButtonPress', 'Button' ],
+ [ 5, :ButtonRelease, Grp::BUTTON, 'ButtonRelease' ],
+ [ 6, :MotionNotify, Grp::MOTION, 'Motion' ],
+ [ 7, :EnterNotify, Grp::CROSSING, 'Enter' ],
+ [ 8, :LeaveNotify, Grp::CROSSING, 'Leave' ],
+ [ 9, :FocusIn, Grp::FOCUS, 'FocusIn' ],
+ [ 10, :FocusOut, Grp::FOCUS, 'FocusOut' ],
+ [ 11, :KeymapNotify, 0, ],
+ [ 12, :Expose, Grp::EXPOSE, 'Expose' ],
+ [ 13, :GraphicsExpose, Grp::EXPOSE, ],
+ [ 14, :NoExpose, 0, ],
+ [ 15, :VisibilityNotify, Grp::VISIBILITY, 'Visibility' ],
+ [ 16, :CreateNotify, Grp::CREATE, 'Create' ],
+ [ 17, :DestroyNotify, Grp::DESTROY, 'Destroy' ],
+ [ 18, :UnmapNotify, Grp::UNMAP, 'Unmap' ],
+ [ 19, :MapNotify, Grp::MAP, 'Map' ],
+ [ 20, :MapRequest, Grp::MAPREQ, 'MapRequest' ],
+ [ 21, :ReparentNotify, Grp::REPARENT, 'Reparent' ],
+ [ 22, :ConfigureNotify, Grp::CONFIG, 'Configure' ],
+ [ 23, :ConfigureRequest, Grp::CONFIGREQ, 'ConfigureRequest' ],
+ [ 24, :GravityNotify, Grp::GRAVITY, 'Gravity' ],
+ [ 25, :ResizeRequest, Grp::RESIZEREQ, 'ResizeRequest' ],
+ [ 26, :CirculateNotify, Grp::CIRC, 'Circulate' ],
+ [ 27, :CirculateRequest, 0, 'CirculateRequest' ],
+ [ 28, :PropertyNotify, Grp::PROP, 'Property' ],
+ [ 29, :SelectionClear, 0, ],
+ [ 30, :SelectionRequest, 0, ],
+ [ 31, :SelectionNotify, 0, ],
+ [ 32, :ColormapNotify, Grp::COLORMAP, 'Colormap' ],
+ [ 33, :ClientMessage, 0, ],
+ [ 34, :MappingNotify, 0, ],
+ [ 35, :VirtualEvent, Grp::VIRTUAL, ],
+ [ 36, :ActivateNotify, Grp::ACTIVATE, 'Activate' ],
+ [ 37, :DeactivateNotify, Grp::ACTIVATE, 'Deactivate' ],
+ [ 38, :MouseWheelEvent, Grp::MWHEEL, 'MouseWheel' ],
+ [ 39, :TK_LASTEVENT, 0, ]
+ ]
+
+ module TypeNum
+ end
+
+ TYPE_NAME_TBL = Hash.new
+ TYPE_ID_TBL = Hash.new
+ TYPE_GROUP_TBL = Hash.new
+
+ type_data.each{|id, c_name, g_flag, *t_names|
+ TypeNum.const_set(c_name, id)
+ t_names.each{|t_name| t_name.freeze; TYPE_NAME_TBL[t_name] = id }
+ TYPE_ID_TBL[id] = t_names
+ TYPE_GROUP_TBL[id] = g_flag
+ }
+
+ TYPE_NAME_TBL.freeze
+ TYPE_ID_TBL.freeze
+
+ def self.type_id(name)
+ TYPE_NAME_TBL[name.to_s]
+ end
+
+ def self.type_name(id)
+ TYPE_ID_TBL[id] && TYPE_ID_TBL[id][0]
+ end
+
+ def self.group_flag(id)
+ TYPE_GROUP_TBL[id] || 0
+ end
+
+ #############################################
+
+ module StateMask
+ ShiftMask = (1<<0)
+ LockMask = (1<<1)
+ ControlMask = (1<<2)
+ Mod1Mask = (1<<3)
+ Mod2Mask = (1<<4)
+ Mod3Mask = (1<<5)
+ Mod4Mask = (1<<6)
+ Mod5Mask = (1<<7)
+ Button1Mask = (1<<8)
+ Button2Mask = (1<<9)
+ Button3Mask = (1<<10)
+ Button4Mask = (1<<11)
+ Button5Mask = (1<<12)
+
+ AnyModifier = (1<<15)
+
+ META_MASK = (AnyModifier<<1)
+ ALT_MASK = (AnyModifier<<2)
+ EXTENDED_MASK = (AnyModifier<<3)
+
+ CommandMask = Mod1Mask
+ OptionMask = Mod2Mask
+ end
+
+ #############################################
+
+ FIELD_FLAG = {
+ # key => flag
+ 'above' => Grp::CONFIG,
+ 'borderwidth' => (Grp::CREATE|Grp::CONFIG),
+ 'button' => Grp::BUTTON,
+ 'count' => Grp::EXPOSE,
+ 'data' => (Grp::VIRTUAL|Grp::STRING_DATA),
+ 'delta' => Grp::MWHEEL,
+ 'detail' => (Grp::FOCUS|Grp::CROSSING),
+ 'focus' => Grp::CROSSING,
+ 'height' => (Grp::EXPOSE|Grp::CONFIG),
+ 'keycode' => Grp::KEY,
+ 'keysym' => Grp::KEY,
+ 'mode' => (Grp::CROSSING|Grp::FOCUS),
+ 'override' => (Grp::CREATE|Grp::MAP|Grp::REPARENT|Grp::CONFIG),
+ 'place' => Grp::CIRC,
+ 'root' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING),
+ 'rootx' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING),
+ 'rooty' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING),
+ 'sendevent' => Grp::ALL,
+ 'serial' => Grp::ALL,
+ 'state' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|
+ Grp::CROSSING|Grp::VISIBILITY),
+ 'subwindow' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING),
+ 'time' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING|
+ Grp::PROP),
+ 'warp' => Grp::KEY_BUTTON_MOTION_VIRTUAL,
+ 'width' => (Grp::EXPOSE|Grp::CREATE|Grp::CONFIG),
+ 'window' => (Grp::CREATE|Grp::UNMAP|Grp::MAP|Grp::REPARENT|
+ Grp::CONFIG|Grp::GRAVITY|Grp::CIRC),
+ 'when' => Grp::ALL,
+ 'x' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING|
+ Grp::EXPOSE|Grp::CREATE|Grp::CONFIG|Grp::GRAVITY|
+ Grp::REPARENT),
+ 'y' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING|
+ Grp::EXPOSE|Grp::CREATE|Grp::CONFIG|Grp::GRAVITY|
+ Grp::REPARENT),
+ }
+
+ FIELD_OPERATION = {
+ 'root' => proc{|val|
+ begin
+ Tk.tk_call_without_enc('winfo', 'pathname', val)
+ val
+ rescue
+ nil
+ end
+ },
+
+ 'subwindow' => proc{|val|
+ begin
+ Tk.tk_call_without_enc('winfo', 'pathname', val)
+ val
+ rescue
+ nil
+ end
+ },
+
+ 'window' => proc{|val| nil}
+ }
+
+ #-------------------------------------------
+
+ def valid_fields(group_flag=nil)
+ group_flag = self.class.group_flag(self.type) unless group_flag
+
+ fields = {}
+ FIELD_FLAG.each{|key, flag|
+ next if (flag & group_flag) == 0
+ begin
+ val = self.__send__(key)
+ rescue
+ next
+ end
+ # next if !val || val == '??'
+ next if !val || (val == '??' && (flag & Grp::STRING_DATA))
+ fields[key] = val
+ }
+
+ fields
+ end
+
+ def valid_for_generate(group_flag=nil)
+ fields = valid_fields(group_flag)
+
+ FIELD_OPERATION.each{|key, cmd|
+ next unless fields.has_key?(key)
+ val = FIELD_OPERATION[key].call(fields[key])
+ if val
+ fields[key] = val
+ else
+ fields.delete(key)
+ end
+ }
+
+ fields
+ end
+
+ def generate(win, modkeys={})
+ klass = self.class
+
+ if modkeys.has_key?(:type) || modkeys.has_key?('type')
+ modkeys = TkComm._symbolkey2str(modkeys)
+ type_id = modkeys.delete('type')
+ else
+ type_id = self.type
+ end
+
+ type_name = klass.type_name(type_id)
+ unless type_name
+ fail RuntimeError, "type_id #{type_id} is invalid"
+ end
+
+ group_flag = klass.group_flag(type_id)
+
+ opts = valid_for_generate(group_flag)
+
+ modkeys.each{|key, val|
+ if val
+ opts[key.to_s] = val
+ else
+ opts.delete(key.to_s)
+ end
+ }
+
+ if group_flag != Grp::KEY
+ Tk.event_generate(win, type_name, opts)
+ else
+ # If type is KEY event, focus should be set to target widget.
+ # If not set, original widget will get the same event.
+ # That will make infinite loop.
+ w = Tk.tk_call_without_enc('focus')
+ begin
+ Tk.tk_call_without_enc('focus', win)
+ Tk.event_generate(win, type_name, opts)
+ ensure
+ Tk.tk_call_without_enc('focus', w)
+ end
+ end
+ end
+
+ #############################################
+
+ # [ <'%' subst-key char>, <proc type char>, <instance var (accessor) name>]
+ KEY_TBL = [
+ [ ?#, ?n, :serial ],
+ [ ?a, ?s, :above ],
+ [ ?b, ?n, :num ],
+ [ ?c, ?n, :count ],
+ [ ?d, ?s, :detail ],
+ # ?e
+ [ ?f, ?b, :focus ],
+ # ?g
+ [ ?h, ?n, :height ],
+ [ ?i, ?s, :win_hex ],
+ # ?j
+ [ ?k, ?n, :keycode ],
+ # ?l
+ [ ?m, ?s, :mode ],
+ # ?n
+ [ ?o, ?b, :override ],
+ [ ?p, ?s, :place ],
+ # ?q
+ # ?r
+ [ ?s, ?x, :state ],
+ [ ?t, ?n, :time ],
+ # ?u
+ [ ?v, ?n, :value_mask ],
+ [ ?w, ?n, :width ],
+ [ ?x, ?n, :x ],
+ [ ?y, ?n, :y ],
+ # ?z
+ [ ?A, ?s, :char ],
+ [ ?B, ?n, :borderwidth ],
+ # ?C
+ [ ?D, ?n, :wheel_delta ],
+ [ ?E, ?b, :send_event ],
+ # ?F
+ # ?G
+ # ?H
+ # ?I
+ # ?J
+ [ ?K, ?s, :keysym ],
+ # ?L
+ # ?M
+ [ ?N, ?n, :keysym_num ],
+ # ?O
+ [ ?P, ?s, :property ],
+ # ?Q
+ [ ?R, ?s, :rootwin_id ],
+ [ ?S, ?s, :subwindow ],
+ [ ?T, ?n, :type ],
+ # ?U
+ # ?V
+ [ ?W, ?w, :widget ],
+ [ ?X, ?n, :x_root ],
+ [ ?Y, ?n, :y_root ],
+ # ?Z
+ nil
+ ]
+
+ # [ <'%' subst-key str>, <proc type char>, <instance var (accessor) name>]
+ # the subst-key string will be converted to a bytecode (128+idx).
+ LONGKEY_TBL = [
+ # for example, for %CTT and %CST subst-key on tkdnd-2.0
+ # ['CTT', ?l, :drop_target_type],
+ # ['CST', ?l, :drop_source_type],
+ ]
+
+ # [ <proc type char>, <proc/method to convert tcl-str to ruby-obj>]
+ PROC_TBL = [
+ [ ?n, TkComm.method(:num_or_str) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?b, TkComm.method(:bool) ],
+ [ ?w, TkComm.method(:window) ],
+
+ [ ?x, proc{|val|
+ begin
+ TkComm::number(val)
+ rescue ArgumentError
+ val
+ end
+ }
+ ],
+
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ # 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)
+ # _setup_subst_table(KEY_TBL, LONGKEY_TBL, PROC_TBL) # if use longname-keys
+
+ #
+ # NOTE: The order of parameters which passed to callback procedure is
+ # <extra_arg>, <extra_arg>, ... , <subst_arg>, <subst_arg>, ...
+ #
+
+ # If you need support extra arguments given by Tcl/Tk,
+ # please override _get_extra_args_tbl
+ #
+ #def self._get_extra_args_tbl
+ # # return an array of convert procs
+ # []
+ #end
+
+=begin
+ alias button num
+ alias delta wheel_delta
+ alias root rootwin_id
+ alias rootx x_root
+ alias root_x x_root
+ alias rooty y_root
+ alias root_y y_root
+ alias sendevent send_event
+=end
+ ALIAS_TBL = {
+ :button => :num,
+ :data => :detail,
+ :delta => :wheel_delta,
+ :root => :rootwin_id,
+ :rootx => :x_root,
+ :root_x => :x_root,
+ :rooty => :y_root,
+ :root_y => :y_root,
+ :sendevent => :send_event,
+ :window => :widget
+ }
+
+ _define_attribute_aliases(ALIAS_TBL)
+
+ end
+
+ ###############################################
+
+ def install_bind_for_event_class(klass, cmd, *args)
+ extra_args_tbl = klass._get_extra_args_tbl
+
+ if args.compact.size > 0
+ args.map!{|arg| klass._sym2subst(arg)}
+ args = args.join(' ')
+ 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|
+ ex_args = []
+ extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)}
+ begin
+ TkUtil.eval_cmd(cmd, *(ex_args.concat(klass.scan_args(keys, arg))))
+ rescue Exception=>e
+ if TkCore::INTERP.kind_of?(TclTkIp)
+ fail e
+ else
+ # MultiTkIp
+ fail Exception, "#{e.class}: #{e.message.dup}"
+ end
+ end
+ })
+ end
+ else
+ keys, args = klass._get_all_subst_keys
+
+ if cmd.kind_of?(String)
+ id = cmd
+ elsif cmd.kind_of?(TkCallbackEntry)
+ id = install_cmd(cmd)
+ else
+ id = install_cmd(proc{|*arg|
+ ex_args = []
+ extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)}
+ begin
+ TkUtil.eval_cmd(cmd, *(ex_args << klass.new(*klass.scan_args(keys, arg))))
+ rescue Exception=>e
+ if TkCore::INTERP.kind_of?(TclTkIp)
+ fail e
+ else
+ # MultiTkIp
+ fail Exception, "#{e.class}: #{e.message.dup}"
+ end
+ end
+ })
+ end
+ end
+
+ if TkCore::INTERP.kind_of?(TclTkIp)
+ id + ' ' + args
+ else
+ # MultiTkIp
+ "if {[set st [catch {#{id} #{args}} ret]] != 0} {
+ if {$st == 4} {
+ return -code continue $ret
+ } elseif {$st == 3} {
+ return -code break $ret
+ } elseif {$st == 2} {
+ return -code return $ret
+ } elseif {[regexp {^Exception: (TkCallbackContinue: .*)$} \
+ $ret m msg]} {
+ return -code continue $msg
+ } elseif {[regexp {^Exception: (TkCallbackBreak: .*)$} $ret m msg]} {
+ return -code break $msg
+ } elseif {[regexp {^Exception: (TkCallbackReturn: .*)$} $ret m msg]} {
+ return -code return $msg
+ } elseif {[regexp {^Exception: (\\S+: .*)$} $ret m msg]} {
+ return -code return $msg
+ } else {
+ return -code error $ret
+ }
+ } else {
+ set ret
+ }"
+ end
+ end
+
+ def install_bind(cmd, *args)
+ install_bind_for_event_class(TkEvent::Event, cmd, *args)
+ end
+end
diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb
new file mode 100644
index 0000000000..62d628c132
--- /dev/null
+++ b/ext/tk/lib/tk/font.rb
@@ -0,0 +1,2344 @@
+#
+# tk/font.rb - the class to treat fonts on Ruby/Tk
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+
+class TkFont
+ include Tk
+ extend TkCore
+
+ TkCommandNames = ['font'.freeze].freeze
+
+ (Tk_FontID = ["@font".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ Tk_FontNameTBL = TkCore::INTERP.create_table
+ Tk_FontUseTBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL.clear }
+ Tk_FontUseTBL.mutex.synchronize{ Tk_FontUseTBL.clear }
+ }
+
+ # option_type : default => string
+ OptionType = Hash.new(?s)
+ OptionType['size'] = ?n
+ OptionType['pointadjust'] = ?n
+ OptionType['underline'] = ?b
+ OptionType['overstrike'] = ?b
+
+ # metric_type : default => num_or_str
+ MetricType = Hash.new(?n)
+ MetricType['fixed'] = ?b
+
+ # system font names
+ SYSTEM_FONT_NAMES = []
+ def SYSTEM_FONT_NAMES.add(font_names)
+ (@mutex ||= Mutex.new).synchronize{
+ self.replace(self | font_names.map{|name| name.to_s})
+ }
+ end
+ def SYSTEM_FONT_NAMES.include?(name)
+ (@mutex ||= Mutex.new).synchronize{
+ super(name.to_s)
+ }
+ end
+
+ # set default font
+ case Tk::TK_VERSION
+ when /^4\..*/
+ DEFAULT_LATIN_FONT_NAME = 'a14'.freeze
+ DEFAULT_KANJI_FONT_NAME = 'k14'.freeze
+
+ when /^8\.[0-4]/
+ if JAPANIZED_TK
+ begin
+ fontnames = tk_call('font', 'names')
+ case fontnames
+ when /defaultgui/
+ # Tcl/Tk-JP for Windows
+ ltn = 'defaultgui'
+ knj = 'defaultgui'
+ when /Mincho:Helvetica-Bold-12/
+ # Tcl/Tk-JP for UNIX/X
+ ltn, knj = tk_split_simplelist(tk_call('font', 'configure',
+ 'Mincho:Helvetica-Bold-12',
+ '-compound'))
+ else
+ # unknown Tcl/Tk-JP
+ #platform = tk_call('set', 'tcl_platform(platform)')
+ platform = Tk::PLATFORM['platform']
+ case platform
+ 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
+ end
+ rescue
+ ltn = 'Helvetica'
+ knj = 'mincho'
+ end
+
+ else # not JAPANIZED_TK
+ begin
+ #platform = tk_call('set', 'tcl_platform(platform)')
+ platform = Tk::PLATFORM['platform']
+ case platform
+ when 'unix'
+ ltn = {'family'=>'Helvetica'.freeze,
+ 'size'=>-12, 'weight'=>'bold'.freeze}
+ when 'windows'
+ ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8}
+ when 'macintosh'
+ ltn = 'system'
+ else # unknown
+ ltn = 'Helvetica'
+ end
+ rescue
+ ltn = 'Helvetica'
+ end
+
+ knj = ltn.dup
+ end
+
+ DEFAULT_LATIN_FONT_NAME = ltn.freeze
+ DEFAULT_KANJI_FONT_NAME = knj.freeze
+
+ when /^8\.[5-9]/, /^9\..*/
+ if tk_call('font', 'names') =~ /\bTkDefaultFont\b/
+ DEFAULT_LATIN_FONT_NAME = 'TkDefaultFont'.freeze
+ DEFAULT_KANJI_FONT_NAME = 'TkDefaultFont'.freeze
+ else
+ DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze
+ DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze
+ end
+
+ else # unknown version
+ DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze
+ DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze
+
+ end
+
+ if $DEBUG
+ print "default latin font = "; p DEFAULT_LATIN_FONT_NAME
+ print "default kanji font = "; p DEFAULT_KANJI_FONT_NAME
+ end
+
+
+ ###################################
+ class DescendantFont
+ def initialize(compound, type)
+ unless compound.kind_of?(TkFont)
+ fail ArgumentError, "a TkFont object is expected for the 1st argument"
+ end
+
+ @compound = compound
+ case type
+ when 'kanji', 'latin', 'ascii'
+ @type = type
+ when :kanji, :latin, :ascii
+ @type = type.to_s
+ else
+ fail ArgumentError, "unknown type '#{type}'"
+ end
+ end
+
+ def dup
+ fail RuntimeError, "cannot dupulicate a descendant font"
+ end
+ def clone
+ fail RuntimeError, "cannot clone a descendant font"
+ end
+
+ def to_eval
+ @compound.__send__(@type + '_font_id')
+ end
+ def font
+ @compound.__send__(@type + '_font_id')
+ end
+ alias font_id font
+ alias name font
+ alias to_s font
+
+ def [](slot)
+ @compound.__send__(@type + '_configinfo', slot)
+ end
+ def []=(slot, value)
+ @compound.__send__(@type + '_configure', slot, value)
+ value
+ end
+
+ def method_missing(id, *args)
+ @compound.__send__(@type + '_' + id.id2name, *args)
+ end
+ end
+
+
+ ###################################
+ # class methods
+ ###################################
+ def TkFont.is_system_font?(fnt)
+ # true --> system font which is available on the current system
+ # false --> not system font (or unknown system font)
+ # nil --> system font name, but not available on the current system
+ fnt = fnt.to_s
+ SYSTEM_FONT_NAMES.include?(fnt) && self.names.index(fnt) && true
+ end
+
+ def TkFont.actual(fnt, option=nil)
+ fnt = '{}' if fnt == ''
+ if fnt.kind_of?(TkFont)
+ fnt.actual(option)
+ else
+ actual_core(fnt, nil, option)
+ end
+ end
+ def TkFont.actual_hash(fnt, option=nil)
+ Hash[TkFont.actual_hash(fnt, option)]
+ end
+
+ def TkFont.actual_displayof(fnt, win, option=nil)
+ fnt = '{}' if fnt == ''
+ if fnt.kind_of?(TkFont)
+ fnt.actual_displayof(win, option)
+ else
+ win = '.' unless win
+ actual_core(fnt, win, option)
+ end
+ end
+ def TkFont.actual_hash_displayof(fnt, option=nil)
+ Hash[TkFont.actual_hash_displayof(fnt, option)]
+ end
+
+ def TkFont.configure(fnt, slot, value=None)
+ if fnt.kind_of?(TkFont)
+ fnt.configure(fnt, slot, value)
+ else
+ configure_core(fnt, slot, value)
+ end
+ fnt
+ end
+
+ def TkFont.configinfo(fnt, slot=nil)
+ if fnt.kind_of?(TkFont)
+ fnt.configinfo(fnt, slot)
+ else
+ configinfo_core(fnt, slot)
+ end
+ end
+
+ def TkFont.current_configinfo(fnt, slot=nil)
+ if fnt.kind_of?(TkFont)
+ fnt.current_configinfo(fnt, slot)
+ else
+ current_configinfo_core(fnt, slot)
+ end
+ end
+
+ def TkFont.measure(fnt, text)
+ fnt = '{}' if fnt == ''
+ if fnt.kind_of?(TkFont)
+ fnt.measure(text)
+ else
+ measure_core(fnt, nil, text)
+ end
+ end
+
+ def TkFont.measure_displayof(fnt, win, text)
+ fnt = '{}' if fnt == ''
+ if fnt.kind_of?(TkFont)
+ fnt.measure_displayof(win, text)
+ else
+ win = '.' unless win
+ measure_core(fnt, win, text)
+ end
+ end
+
+ def TkFont.metrics(fnt, option=nil)
+ fnt = '{}' if fnt == ''
+ if fnt.kind_of?(TkFont)
+ fnt.metrics(option)
+ else
+ metrics_core(fnt, nil, option)
+ end
+ end
+ def TkFont.metrics_hash(fnt, option=nil)
+ if option
+ val = TkFont.metrics(fnt, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[TkFont.metrics(fnt)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
+
+ def TkFont.metrics_displayof(fnt, win, option=nil)
+ fnt = '{}' if fnt == ''
+ if fnt.kind_of?(TkFont)
+ font.metrics_displayof(win, option=nil)
+ else
+ win = '.' unless win
+ metrics_core(fnt, win, option)
+ end
+ end
+ def TkFont.metrics_hash_displayof(fnt, win, option=nil)
+ if option
+ val = TkFont.metrics_displayof(fnt, win, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[TkFont.metrics_displayof(fnt, win, option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
+
+ def TkFont.families(win=nil)
+ case (Tk::TK_VERSION)
+ when /^4\..*/
+ ['fixed']
+
+ when /^8\..*/
+ if win
+ tk_split_simplelist(tk_call('font', 'families', '-displayof', win))
+ else
+ tk_split_simplelist(tk_call('font', 'families'))
+ end
+ end
+ end
+
+ def TkFont.names
+ case (Tk::TK_VERSION)
+ when /^4\..*/
+ r = ['fixed']
+ r += ['a14', 'k14'] if JAPANIZED_TK
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL.each_value{|obj| r.push(obj)}
+ }
+ #r | []
+ r.uniq
+
+ when /^8\..*/
+ tk_split_simplelist(tk_call('font', 'names'))
+
+ end
+ end
+
+ def TkFont.create_copy(font)
+ fail 'source-font must be a TkFont object' unless font.kind_of? TkFont
+ if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ keys = {}
+ font.configinfo.each{|key,value| keys[key] = value }
+ TkFont.new(font.latin_font_id, font.kanji_font_id, keys)
+ else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ TkFont.new(font.latin_font_id, font.kanji_font_id, font.configinfo)
+ end
+ end
+
+ def TkFont.get_obj(name)
+ name = name.to_s
+ if name =~ /^(@font[0-9]+)(|c|l|k)$/
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[$1]
+ }
+ else
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[name]
+ }
+ end
+ end
+
+ def TkFont.init_widget_font(pathname, *args)
+ win, tag, key = pathname.split(';')
+ key = 'font' if key == nil || key == ''
+ path = [win, tag, key].join(';')
+
+ case (Tk::TK_VERSION)
+ when /^4\..*/
+ regexp = /^-(|kanji)#{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
+
+ 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\.[0-4]/
+ 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
+
+ args << {}
+
+ optkey = "-#{key}"
+
+ info = conf_list.find{|conf| conf[0] == optkey}
+ fnt = info[-1]
+ fnt = nil if fnt == [] || fnt == ""
+
+ unless fnt
+ # create dummy
+ # TkFont.new(nil, nil).call_font_configure([path, key], *args)
+ dummy_fnt = TkFont.allocate
+ dummy_fnt.instance_eval{ init_dummy_fontobj() }
+ dummy_fnt
+ else
+ begin
+ compound = tk_split_simplelist(
+ Hash[*tk_split_simplelist(tk_call('font', 'configure',
+ fnt))].collect{|k,v|
+ [k[1..-1], v]
+ }.assoc('compound')[1])
+ rescue
+ compound = []
+ end
+ if compound == []
+ if TkFont.is_system_font?(fnt)
+ TkNamedFont.new(fnt).call_font_configure([path, key], *args)
+ else
+ TkFont.new(fnt).call_font_configure([path, key], *args)
+ end
+ else
+ TkFont.new(compound[0],
+ compound[1]).call_font_configure([path, key], *args)
+ end
+ end
+
+ when /^8\.[5-9]/, /^9\..*/
+ 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
+
+ args << {}
+
+ optkey = "-#{key}"
+
+ info = conf_list.find{|conf| conf[0] == optkey}
+ fnt = info[-1]
+ fnt = nil if fnt == [] || fnt == ""
+
+ unless fnt
+ # create dummy
+ # TkFont.new(nil, nil).call_font_configure([path, key], *args)
+ dummy_fnt = TkFont.allocate
+ dummy_fnt.instance_eval{ init_dummy_fontobj() }
+ dummy_fnt
+ else
+ if TkFont.is_system_font?(fnt)
+ TkNamedFont.new(fnt).call_font_configure([path, key], *args)
+ else
+ TkFont.new(fnt).call_font_configure([path, key], *args)
+ end
+ end
+ end
+ end
+
+ def TkFont.used_on(path=nil)
+ Tk_FontUseTBL.mutex.synchronize{
+ if path
+ Tk_FontUseTBL[path]
+ else
+ # Tk_FontUseTBL.values | []
+ Tk_FontUseTBL.values.uniq
+ end
+ }
+ end
+
+ def TkFont.failsafe(font)
+ begin
+ if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK
+ tk_call('font', 'failsafe', font)
+ end
+ rescue
+ end
+ end
+
+ ###################################
+ # instance methods
+ ###################################
+ private
+ ###################################
+ def init_dummy_fontobj
+ Tk_FontID.mutex.synchronize{
+ @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
+ Tk_FontID[1].succ!
+ }
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[@id] = self
+ }
+
+ # @latin_desscendant = nil
+ # @kanji_desscendant = nil
+ @descendant = [nil, nil] # [latin, kanji]
+
+ case (Tk::TK_VERSION)
+ when /^4\..*/
+ @latinfont = ""
+ @kanjifont = ""
+ if JAPANIZED_TK
+ @compoundfont = [[@latinfont], [@kanjifont]]
+ @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont}
+ else
+ @compoundfont = @latinfont
+ @fontslot = {'font'=>@latinfont}
+ end
+ else
+ @latinfont = @id + 'l'
+ @kanjifont = @id + 'k'
+ @compoundfont = @id + 'c'
+
+ if JAPANIZED_TK
+ tk_call('font', 'create', @latinfont, '-charset', 'iso8859')
+ tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983')
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont])
+ else
+ tk_call('font', 'create', @latinfont)
+ tk_call('font', 'create', @kanjifont)
+ tk_call('font', 'create', @compoundfont)
+ end
+
+ @fontslot = {'font'=>@compoundfont}
+ end
+
+ self
+ end
+
+ def initialize(ltn=nil, knj=nil, keys=nil)
+ ltn = '{}' if ltn == ''
+ knj = '{}' if knj == ''
+
+ Tk_FontID.mutex.synchronize{
+ # @id = Tk_FontID.join('')
+ @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
+ Tk_FontID[1].succ!
+ }
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[@id] = self
+ }
+
+ # @latin_desscendant = nil
+ # @kanji_desscendant = nil
+ @descendant = [nil, nil] # [latin, kanji]
+
+ # @latinfont = @id + 'l'
+ # @kanjifont = @id + 'k'
+ # @compoundfont = @id + 'c'
+ # @fontslot = {}
+
+ if knj.kind_of?(Hash) && !keys
+ keys = knj
+ knj = nil
+ end
+
+ # compound font check
+ if Tk::TK_VERSION == '8.0' && JAPANIZED_TK
+ begin
+ compound = tk_split_simplelist(tk_call('font', 'configure',
+ ltn, '-compound'))
+ if knj == nil
+ if compound != []
+ ltn, knj = compound
+ end
+ else
+ if compound != []
+ ltn = compound[0]
+ end
+ compound = tk_split_simplelist(tk_call('font', 'configure',
+ knj, '-compound'))
+ if compound != []
+ knj = compound[1]
+ end
+ end
+ rescue
+ end
+ end
+
+ if ltn
+ if JAPANIZED_TK && !knj
+ if Tk::TK_VERSION =~ /^4..*/
+ knj = DEFAULT_KANJI_FONT_NAME
+ else
+ knj = ltn
+ end
+ end
+ else
+ ltn = DEFAULT_LATIN_FONT_NAME
+ knj = DEFAULT_KANJI_FONT_NAME if JAPANIZED_TK && !knj
+ end
+
+ create_compoundfont(ltn, knj, keys)
+ end
+
+ def initialize_copy(font)
+ unless font.kind_of?(TkFont)
+ fail TypeError, '"initialize_copy should take same class object'
+ end
+ if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ keys = {}
+ font.configinfo.each{|key,value| keys[key] = value }
+ initialize(font.latin_font_id, font.kanji_font_id, keys)
+ else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ initialize(font.latin_font_id, font.kanji_font_id, font.configinfo)
+ end
+ end
+
+ def _get_font_info_from_hash(font)
+ font = _symbolkey2str(font)
+ foundry = (info = font['foundry'] .to_s)? info: '*'
+ family = (info = font['family'] .to_s)? info: '*'
+ weight = (info = font['weight'] .to_s)? info: '*'
+ slant = (info = font['slant'] .to_s)? info: '*'
+ swidth = (info = font['swidth'] .to_s)? info: '*'
+ adstyle = (info = font['adstyle'] .to_s)? info: '*'
+ pixels = (info = font['pixels'] .to_s)? info: '*'
+ points = (info = font['points'] .to_s)? info: '*'
+ resx = (info = font['resx'] .to_s)? info: '*'
+ resy = (info = font['resy'] .to_s)? info: '*'
+ space = (info = font['space'] .to_s)? info: '*'
+ avgWidth = (info = font['avgWidth'].to_s)? info: '*'
+ charset = (info = font['charset'] .to_s)? info: '*'
+ encoding = (info = font['encoding'].to_s)? info: '*'
+
+ [foundry, family, weight, slant, swidth, adstyle,
+ pixels, points, resx, resy, space, avgWidth, charset, encoding]
+ end
+
+ def create_latinfont_tk4x(font)
+ if font.kind_of? Hash
+ @latinfont = '-' + _get_font_info_from_hash(font).join('-') + '-'
+
+ elsif font.kind_of? Array
+ finfo = {}
+ finfo['family'] = font[0].to_s
+ if font[1]
+ fsize = font[1].to_s
+ if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
+ if $1 == '-'
+ finfo['pixels'] = $2
+ else
+ finfo['points'] = $2
+ end
+ else
+ finfo['points'] = '13'
+ end
+ end
+ font[2..-1].each{|style|
+ case (style)
+ when 'normal'
+ finfo['weight'] = style
+ when 'bold'
+ finfo['weight'] = style
+ when 'roman'
+ finfo['slant'] = 'r'
+ when 'italic'
+ finfo['slant'] = 'i'
+ end
+ }
+
+ @latinfont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
+
+ elsif font.kind_of? TkFont
+ @latinfont = font.latin_font
+
+ else
+ if font
+ @latinfont = font
+ else
+ @latinfont = DEFAULT_LATIN_FONT_NAME
+ end
+
+ end
+ end
+
+ def create_kanjifont_tk4x(font)
+ unless JAPANIZED_TK
+ @kanjifont = ""
+ return
+ end
+
+ if font.kind_of? Hash
+ @kanjifont = '-' + _get_font_info_from_hash(font).join('-') + '-'
+
+ elsif font.kind_of? Array
+ finfo = {}
+ finfo['family'] = font[0].to_s
+ if font[1]
+ fsize = font[1].to_s
+ if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
+ if $1 == '-'
+ finfo['pixels'] = $2
+ else
+ finfo['points'] = $2
+ end
+ else
+ finfo['points'] = '13'
+ end
+ end
+ font[2..-1].each{|style|
+ case (style)
+ when 'normal'
+ finfo['weight'] = style
+ when 'bold'
+ finfo['weight'] = style
+ when 'roman'
+ finfo['slant'] = 'r'
+ when 'italic'
+ finfo['slant'] = 'i'
+ end
+ }
+
+ @kanjifont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
+ elsif font.kind_of? TkFont
+ @kanjifont = font.kanji_font_id
+ else
+ if font
+ @kanjifont = font
+ else
+ @kanjifont = DEFAULT_KANJI_FONT_NAME
+ end
+ end
+ end
+
+ def create_compoundfont_tk4x(ltn, knj, keys)
+ create_latinfont(ltn)
+ create_kanjifont(knj)
+
+ if JAPANIZED_TK
+ @compoundfont = [[@latinfont], [@kanjifont]]
+ @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont}
+ # @fontslot.clear
+ # @fontslot['font'] = @latinfont
+ # @fontslot['kanjifont'] = @kanjifont
+ else
+ @compoundfont = @latinfont
+ @fontslot = {'font'=>@latinfont}
+ # @fontslot.clear
+ # @fontslot['font'] = @latinfont
+ end
+ end
+
+ def create_latinfont_tk8x(font)
+ @latinfont = @id + 'l'
+
+ if JAPANIZED_TK
+ if font.kind_of? Hash
+ if font[:charset] || font['charset']
+ tk_call('font', 'create', @latinfont, *hash_kv(font))
+ else
+ tk_call('font', 'create', @latinfont,
+ '-charset', 'iso8859', *hash_kv(font))
+ end
+ elsif font.kind_of? Array
+ tk_call('font', 'create', @latinfont, '-copy', array2tk_list(font))
+ tk_call('font', 'configure', @latinfont, '-charset', 'iso8859')
+ elsif font.kind_of? TkFont
+ tk_call('font', 'create', @latinfont, '-copy', font.latin_font)
+ elsif font
+ tk_call('font', 'create', @latinfont, '-copy', font,
+ '-charset', 'iso8859')
+ else
+ tk_call('font', 'create', @latinfont, '-charset', 'iso8859')
+ end
+ else
+ if font.kind_of? Hash
+ tk_call('font', 'create', @latinfont, *hash_kv(font))
+ else
+ keys = {}
+ if font.kind_of? Array
+ actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
+ elsif font.kind_of? TkFont
+ actual_core(font.latin_font).each{|key,val| keys[key] = val}
+ elsif font
+ actual_core(font).each{|key,val| keys[key] = val}
+ end
+ tk_call('font', 'create', @latinfont, *hash_kv(keys))
+ end
+
+ if font && @compoundfont
+ keys = {}
+ actual_core(@latinfont).each{|key,val| keys[key] = val}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ end
+ end
+ end
+
+ def create_kanjifont_tk8x(font)
+ @kanjifont = @id + 'k'
+
+ if JAPANIZED_TK
+ if font.kind_of? Hash
+ if font[:charset] || font['charset']
+ tk_call('font', 'create', @kanjifont, *hash_kv(font))
+ else
+ tk_call('font', 'create', @kanjifont,
+ '-charset', 'jisx0208.1983', *hash_kv(font))
+ end
+ elsif font.kind_of? Array
+ tk_call('font', 'create', @kanjifont, '-copy', array2tk_list(font))
+ tk_call('font', 'configure', @kanjifont, '-charset', 'jisx0208.1983')
+ elsif font.kind_of? TkFont
+ tk_call('font', 'create', @kanjifont, '-copy', font.kanji_font_id)
+ elsif font
+ tk_call('font', 'create', @kanjifont, '-copy', font,
+ '-charset', 'jisx0208.1983')
+ else
+ tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983')
+ end
+ # end of JAPANIZED_TK
+
+ else
+ if font.kind_of? Hash
+ tk_call('font', 'create', @kanjifont, *hash_kv(font))
+ else
+ keys = {}
+ if font.kind_of? Array
+ actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
+ elsif font.kind_of? TkFont
+ actual_core(font.kanji_font_id).each{|key,val| keys[key] = val}
+ elsif font
+ actual_core(font).each{|key,val| keys[key] = val}
+ end
+ tk_call('font', 'create', @kanjifont, *hash_kv(keys))
+ end
+
+ if font && @compoundfont
+ keys = {}
+ actual_core(@kanjifont).each{|key,val| keys[key] = val}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ end
+ end
+ end
+
+ def create_compoundfont_tk8x(ltn, knj, keys)
+ if knj
+ create_latinfont(ltn)
+ create_kanjifont(knj)
+ else
+ cfnt = ltn
+ create_kanjifont(cfnt)
+ create_latinfont(cfnt)
+ end
+
+ @compoundfont = @id + 'c'
+
+ if JAPANIZED_TK
+ unless keys
+ keys = {}
+ else
+ keys = keys.dup
+ end
+ if (tk_call('font', 'configure', @latinfont, '-underline') == '1' &&
+ tk_call('font', 'configure', @kanjifont, '-underline') == '1' &&
+ !keys.key?('underline'))
+ keys['underline'] = true
+ end
+ if (tk_call('font', 'configure', @latinfont, '-overstrike') == '1' &&
+ tk_call('font', 'configure', @kanjifont, '-overstrike') == '1' &&
+ !keys.key?('overstrike'))
+ keys['overstrike'] = true
+ end
+
+ @fontslot = {'font'=>@compoundfont}
+ # @fontslot['font'] = @compoundfont
+ begin
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
+ rescue RuntimeError => e
+ if ltn == knj
+ if e.message =~ /kanji font .* specified/
+ tk_call('font', 'delete', @latinfont)
+ create_latinfont(DEFAULT_LATIN_FONT_NAME)
+ opts = []
+ Hash[*(tk_split_simplelist(tk_call('font', 'configure',
+ @kanjifont)))].each{|k,v|
+ case k
+ when '-size', '-weight', '-slant', '-underline', '-overstrike'
+ opts << k << v
+ end
+ }
+ tk_call('font', 'configure', @latinfont, *opts)
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
+
+ elsif e.message =~ /ascii font .* specified/
+ tk_call('font', 'delete', @kanjifont)
+ create_kanjifont(DEFAULT_KANJI_FONT_NAME)
+ opts = []
+ Hash[*(tk_split_simplelist(tk_call('font', 'configure',
+ @latinfont)))].each{|k,v|
+ case k
+ when '-size', '-weight', '-slant', '-underline', '-overstrike'
+ opts << k << v
+ end
+ }
+ tk_call('font', 'configure', @kanjifont, *opts)
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
+
+ else
+ raise e
+ end
+ else
+ raise e
+ end
+ end
+ else
+ tk_call('font', 'create', @compoundfont)
+
+ latinkeys = {}
+ begin
+ actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
+ rescue
+ latinkeys = {}
+ end
+ if latinkeys != {}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ end
+
+ if knj
+ compoundkeys = nil
+ kanjikeys = {}
+ begin
+ actual_core(@kanjifont).each{|key,val| kanjikeys[key] = val}
+ rescue
+ kanjikeys = {}
+ end
+ if kanjikeys != {}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(kanjikeys))
+ end
+ end
+
+ if cfnt
+ if cfnt.kind_of?(Hash)
+ compoundkeys = cfnt.dup
+ else
+ compoundkeys = {}
+ actual_core(cfnt).each{|key,val| compoundkeys[key] = val}
+ end
+ compoundkeys.update(_symbolkey2str(keys))
+ keys = compoundkeys
+ end
+
+ @fontslot = {'font'=>@compoundfont}
+ # @fontslot['font'] = @compoundfont
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ end
+ end
+
+ ###################################
+ public
+ ###################################
+ def inspect
+ sprintf("#<%s:%0x:%s>", self.class.inspect, self.__id__, @compoundfont)
+ end
+
+ def method_missing(id, *args)
+ name = id.id2name
+ case args.length
+ when 1
+ if name[-1] == ?=
+ configure name[0..-2], args[0]
+ args[0]
+ else
+ configure name, args[0]
+ self
+ end
+ when 0
+ begin
+ configinfo name
+ rescue
+ super(id, *args)
+# fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at
+ end
+ else
+ super(id, *args)
+# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
+ end
+ end
+
+ def call_font_configure(path, *args)
+ 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))
+ begin
+ tk_call(*args)
+ rescue => e
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ fail e
+ end
+ end
+ Tk_FontUseTBL.mutex.synchronize{
+ Tk_FontUseTBL[[win, tag, optkey].join(';')] = self
+ }
+ self
+ end
+
+ def used
+ ret = []
+ table = nil
+ Tk_FontUseTBL.mutex.synchronize{
+ table = Tk_FontUseTBL.clone # to avoid deadlock
+ }
+ table.each{|key,value|
+ next unless self == value
+ if key.include?(';')
+ win, tag, optkey = key.split(';')
+ winobj = tk_tcl2ruby(win)
+ #if winobj.kind_of? TkText
+ if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text)
+ if optkey
+ ret.push([winobj, winobj.tagid2obj(tag), optkey])
+ else
+ ret.push([winobj, winobj.tagid2obj(tag)])
+ end
+ #elsif winobj.kind_of? TkCanvas
+ elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas)
+ if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag
+ 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
+ elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu)
+ if optkey
+ ret.push([winobj, tag, optkey])
+ else
+ ret.push([winobj, tag])
+ end
+ else
+ if optkey
+ ret.push([win, tag, optkey])
+ else
+ ret.push([win, tag])
+ end
+ end
+ else
+ ret.push(tk_tcl2ruby(key))
+ end
+ }
+ ret
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ font
+ end
+
+ def font
+ @compoundfont
+ end
+ alias font_id font
+ alias name font
+ alias to_s font
+
+ def latin_font_id
+ @latinfont
+ end
+
+ def latin_font
+ # @latinfont
+ if @descendant[0] # [0] -> latin
+ @descendant[0]
+ else
+ @descendant[0] = DescendantFont.new(self, 'latin')
+ end
+=begin
+ if @latin_descendant
+ @latin_descendant
+ else
+ @latin_descendant = DescendantFont.new(self, 'latin')
+ end
+=end
+ end
+ alias latinfont latin_font
+
+ def kanji_font_id
+ @kanjifont
+ end
+
+ def kanji_font
+ # @kanjifont
+ if @descendant[1] # [1] -> kanji
+ @descendant[1]
+ else
+ @descendant[1] = DescendantFont.new(self, 'kanji')
+ end
+=begin
+ if @kanji_descendant
+ @kanji_descendant
+ else
+ @kanji_descendant = DescendantFont.new(self, 'kanji')
+ end
+=end
+ end
+ alias kanjifont kanji_font
+
+ def actual(option=nil)
+ actual_core(@compoundfont, nil, option)
+ end
+ def actual_hash(option=nil)
+ Hash[actual(option)]
+ end
+
+ def actual_displayof(win, option=nil)
+ win = '.' unless win
+ actual_core(@compoundfont, win, option)
+ end
+ def actual_hash_displayof(win, option=nil)
+ Hash[actual_displayof(win, option)]
+ end
+
+ def latin_actual(option=nil)
+ if @latinfont == nil
+ actual_core(@compoundfont, nil, option) # use @compoundfont
+ else
+ actual_core(@latinfont, nil, option)
+ end
+ end
+ def latin_actual_hash(option=nil)
+ Hash[latin_actual(option)]
+ end
+
+ def latin_actual_displayof(win, option=nil)
+ win = '.' unless win
+ if @latinfont == nil
+ actual_core(@compoundfont, win, option) # use @compoundfont
+ else
+ actual_core(@latinfont, win, option)
+ end
+ end
+ def latin_actual_hash_displayof(win, option=nil)
+ Hash[latin_actual_displayof(win, option)]
+ end
+
+ def kanji_actual(option=nil)
+ #if JAPANIZED_TK
+ if @kanjifont == nil
+ actual_core(@compoundfont, nil, option) # use @compoundfont
+ elsif @kanjifont != ""
+ actual_core(@kanjifont, nil, option)
+ else
+ actual_core_tk4x(nil, nil, option)
+ end
+ end
+ def kanji_actual_hash(option=nil)
+ Hash[kanji_actual(option)]
+ end
+
+ def kanji_actual_displayof(win, option=nil)
+ #if JAPANIZED_TK
+ if @kanjifont == nil
+ actual_core(@compoundfont, nil, option) # use @compoundfont
+ elsif @kanjifont != ""
+ win = '.' unless win
+ actual_core(@kanjifont, win, option)
+ else
+ actual_core_tk4x(nil, win, option)
+ end
+ end
+ def kanji_actual_hash_displayof(win, option=nil)
+ Hash[kanji_actual_displayof(win, option)]
+ end
+
+ def [](slot)
+ configinfo slot
+ end
+
+ def []=(slot, val)
+ configure slot, val
+ val
+ end
+
+ def configure(slot, value=None)
+ configure_core(@compoundfont, slot, value)
+ self
+ end
+
+ def configinfo(slot=nil)
+ configinfo_core(@compoundfont, slot)
+ end
+
+ def current_configinfo(slot=nil)
+ current_configinfo_core(@compoundfont, slot)
+ end
+
+ def delete
+ delete_core
+ end
+
+ def latin_configure(slot, value=None)
+ if JAPANIZED_TK
+ configure_core(@latinfont, slot, value)
+ else
+ configure(slot, value)
+ end
+ self
+ end
+
+ def latin_configinfo(slot=nil)
+ if JAPANIZED_TK
+ configinfo_core(@latinfont, slot)
+ else
+ configinfo(slot)
+ end
+ end
+ def latin_current_configinfo(slot=nil)
+ Hash[latin_configinfo(slot)]
+ end
+
+ def kanji_configure(slot, value=None)
+ #if JAPANIZED_TK
+ if @kanjifont == nil
+ configure_core(@compoundfont, slot, value) # use @compoundfont
+ elsif @kanjifont != ""
+ configure_core(@kanjifont, slot, value)
+ configure('size'=>configinfo('size')) # to reflect new configuration
+ else
+ #""
+ configure(slot, value)
+ end
+ self
+ end
+
+ def kanji_configinfo(slot=nil)
+ #if JAPANIZED_TK
+ if @kanjifont == nil
+ configure_core(@compoundfont, slot) # use @compoundfont
+ elsif @kanjifont != ""
+ configinfo_core(@kanjifont, slot)
+ else
+ #[]
+ configinfo(slot)
+ end
+ end
+ def kanji_current_configinfo(slot=nil)
+ Hash[kanji_configinfo(slot)]
+ end
+
+ def replace(ltn, knj=None)
+ knj = ltn if knj == None
+ latin_replace(ltn)
+ kanji_replace(knj)
+ self
+ end
+
+ def latin_replace(ltn)
+ if @latinfont
+ latin_replace_core(ltn)
+ reset_pointadjust
+ else
+ # not compound font -> copy properties of ltn
+ latinkeys = {}
+ begin
+ actual_core(ltn).each{|key,val| latinkeys[key] = val}
+ rescue
+ latinkeys = {}
+ end
+ begin
+ tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ rescue
+ # not exist? (deleted?) -> create font
+ tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys))
+ end
+ end
+
+ self
+ end
+
+ def kanji_replace(knj)
+ return self unless @kanjifont # ignore
+ kanji_replace_core(knj)
+ reset_pointadjust
+ self
+ end
+
+ def measure(text)
+ measure_core(@compoundfont, nil, text)
+ end
+
+ def measure_displayof(win, text)
+ win = '.' unless win
+ measure_core(@compoundfont, win, text)
+ end
+
+ def metrics(option=nil)
+ metrics_core(@compoundfont, nil, option)
+ end
+ def metrics_hash(option=nil)
+ if option
+ val = metrics(option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[metrics(option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
+
+ def metrics_displayof(win, option=nil)
+ win = '.' unless win
+ metrics_core(@compoundfont, win, option)
+ end
+ def metrics_hash_displayof(win, option=nil)
+ if option
+ val = metrics_displayof(win, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[metrics_displayof(win, option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
+
+ def latin_metrics(option=nil)
+ if @latinfont == nil
+ metrics_core(@compoundfont, nil, option) # use @compoundfont
+ else
+ metrics_core(@latinfont, nil, option)
+ end
+ end
+ def latin_metrics_hash(option=nil)
+ if option
+ val = latin_metrics(option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[latin_metrics(option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
+
+ def latin_metrics_displayof(win, option=nil)
+ win = '.' unless win
+ if @latinfont == nil
+ metrics_core(@compoundfont, win, option) # use @compoundfont
+ else
+ metrics_core(@latinfont, win, option)
+ end
+ end
+ def latin_metrics_hash_displayof(win, option=nil)
+ if option
+ val = latin_metrics_displayof(win, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[latin_metrics_displayof(win, option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
+
+ def kanji_metrics(option=nil)
+ if @latinfont == nil
+ metrics_core(@compoundfont, nil, option) # use @compoundfont
+ elsif JAPANIZED_TK
+ metrics_core(@kanjifont, nil, option)
+ else
+ metrics_core_tk4x(nil, nil, option)
+ end
+ end
+ def kanji_metrics_hash(option=nil)
+ if option
+ val = kanji_metrics(option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[kanji_metrics(option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
+
+ def kanji_metrics_displayof(win, option=nil)
+ win = '.' unless win
+ if @latinfont == nil
+ metrics_core(@compoundfont, win, option) # use @compoundfont
+ elsif JAPANIZED_TK
+ metrics_core(@kanjifont, win, option)
+ else
+ metrics_core_tk4x(nil, win, option)
+ end
+ end
+ def kanji_metrics_hash_displayof(win, option=nil)
+ if option
+ val = kanji_metrics_displayof(win, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[kanji_metrics_displayof(win, option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
+
+ def reset_pointadjust
+ begin
+ if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK
+ configure('pointadjust' => latin_actual.assoc('size')[1].to_f /
+ kanji_actual.assoc('size')[1].to_f )
+ end
+ rescue
+ end
+ self
+ end
+
+ ###################################
+ # private alias
+ ###################################
+ case (Tk::TK_VERSION)
+ when /^4\..*/
+ alias create_latinfont create_latinfont_tk4x
+ alias create_kanjifont create_kanjifont_tk4x
+ alias create_compoundfont create_compoundfont_tk4x
+
+ when /^8\.[0-5]/
+ alias create_latinfont create_latinfont_tk8x
+ alias create_kanjifont create_kanjifont_tk8x
+ alias create_compoundfont create_compoundfont_tk8x
+
+ else
+ alias create_latinfont create_latinfont_tk8x
+ alias create_kanjifont create_kanjifont_tk8x
+ alias create_compoundfont create_compoundfont_tk8x
+
+ end
+
+ ###################################
+ # public alias
+ ###################################
+ alias ascii_font latin_font
+ alias asciifont latinfont
+ alias create_asciifont create_latinfont
+ alias ascii_actual latin_actual
+ alias ascii_actual_displayof latin_actual_displayof
+ alias ascii_configure latin_configure
+ alias ascii_configinfo latin_configinfo
+ alias ascii_replace latin_replace
+ alias ascii_metrics latin_metrics
+
+ ###################################
+=begin
+ def dup
+ TkFont.new(self)
+ end
+ def clone
+ TkFont.new(self)
+ end
+=end
+end
+
+module TkFont::CoreMethods
+ include Tk
+ extend TkCore
+
+ private
+
+ def actual_core_tk4x(font, win=nil, option=nil)
+ # dummy
+ if option == 'pointadjust' || option == :pointadjust
+ 1.0
+ elsif option
+ case TkFont::OptionType[option.to_s]
+ when ?n
+ 0
+ when ?b
+ false
+ else
+ ''
+ end
+ else
+ [['family',''], ['size',0], ['weight',''], ['slant',''],
+ ['underline',false], ['overstrike',false], ['charset',''],
+ ['pointadjust',0]]
+ end
+ end
+
+ def actual_core_tk8x(font, win=nil, option=nil)
+ font = '{}' if font == ''
+
+ if option == 'compound' || option == :compound
+ ""
+ elsif option
+ if win
+ val = tk_call('font', 'actual', font,
+ "-displayof", win, "-#{option}")
+ else
+ val = tk_call('font', 'actual', font, "-#{option}")
+ end
+ case TkFont::OptionType[option.to_s]
+ when ?n
+ num_or_str(val)
+ when ?b
+ bool(val)
+ else
+ val
+ end
+ else
+ l = tk_split_simplelist(if win
+ tk_call('font', 'actual', font,
+ "-displayof", win)
+ else
+ tk_call('font', 'actual', font)
+ end)
+ r = []
+ while key=l.shift
+ if key == '-compound'
+ l.shift
+ else
+ key = key[1..-1]
+ val = l.shift
+ case TkFont::OptionType[key]
+ when ?n
+ r.push [key, num_or_str(val)]
+ when ?b
+ r.push [key, bool(val)]
+ else
+ r.push [key, val]
+ end
+ end
+ end
+ r
+ end
+ end
+
+ def configure_core_tk4x(font, slot, value=None)
+ #""
+ self
+ end
+
+ def configinfo_core_tk4x(font, option=nil)
+ # dummy
+ if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ if option == 'pointadjust' || option == :pointadjust
+ 1.0
+ elsif option
+ case TkFont::OptionType[option.to_s]
+ when ?n
+ 0
+ when ?b
+ false
+ else
+ ''
+ end
+ else
+ [['family',''], ['size',0], ['weight',''], ['slant',''],
+ ['underline',false], ['overstrike',false], ['charset',''],
+ ['pointadjust',1.0]]
+ end
+ else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ current_configinfo_core_tk4x(font, option)
+ end
+ end
+
+ def current_configinfo_core_tk4x(font, option=nil)
+ if option
+ case TkFont::OptionType[option.to_s]
+ when ?n
+ 0
+ when ?b
+ false
+ else
+ ''
+ end
+ else
+ {'family'=>'', 'size'=>0, 'weight'=>'', 'slant'=>'',
+ 'underline'=>false, 'overstrike'=>false,
+ 'charset'=>false, 'pointadjust'=>1.0}
+ end
+ end
+
+ def configure_core_tk8x(font, slot, value=None)
+ if JAPANIZED_TK
+ begin
+ padjust = tk_call('font', 'configure', font, '-pointadjust')
+ rescue
+ padjust = nil
+ end
+ else
+ padjust = nil
+ end
+ if slot.kind_of? Hash
+ if JAPANIZED_TK && (slot.key?('family') || slot.key?(:family))
+ slot = _symbolkey2str(slot)
+ configure_core_tk8x(font, 'family', slot.delete('family'))
+ end
+
+ if ((slot.key?('size') || slot.key?(:size)) &&
+ padjust && !slot.key?('pointadjust') && !slot.key?(:pointadjust))
+ tk_call('font', 'configure', font,
+ '-pointadjust', padjust, *hash_kv(slot))
+ else
+ tk_call('font', 'configure', font, *hash_kv(slot))
+ end
+ elsif (slot == 'size' || slot == :size) && padjust != nil
+ tk_call('font', 'configure', font,
+ "-#{slot}", value, '-pointadjust', padjust)
+ elsif JAPANIZED_TK && (slot == 'family' || slot == :family)
+ # coumpund font?
+ begin
+ compound = tk_split_simplelist(tk_call('font', 'configure',
+ font, '-compound'))
+ rescue
+ tk_call('font', 'configure', font, '-family', value)
+ return self
+ end
+ if compound == []
+ tk_call('font', 'configure', font, '-family', value)
+ return self
+ end
+ ltn, knj = compound
+
+ lfnt = tk_call('font', 'create', '-copy', ltn)
+ begin
+ tk_call('font', 'configure', lfnt, '-family', value)
+ latin_replace_core_tk8x(lfnt)
+ rescue RuntimeError => e
+ fail e if $DEBUG
+ ensure
+ tk_call('font', 'delete', lfnt) if lfnt != ''
+ end
+
+ kfnt = tk_call('font', 'create', '-copy', knj)
+ begin
+ tk_call('font', 'configure', kfnt, '-family', value)
+ kanji_replace_core_tk8x(lfnt)
+ rescue RuntimeError => e
+ fail e if $DEBUG
+ ensure
+ tk_call('font', 'delete', kfnt) if kfnt != ''
+ end
+
+ else
+ tk_call('font', 'configure', font, "-#{slot}", value)
+ end
+ self
+ end
+
+ def configinfo_core_tk8x(font, option=nil)
+ if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ if option == 'compound' || option == :compound
+ ""
+ elsif option
+ val = tk_call('font', 'configure', font, "-#{option}")
+ case TkFont::OptionType[option.to_s]
+ when ?n
+ num_or_str(val)
+ when ?b
+ bool(val)
+ else
+ val
+ end
+ else
+ l = tk_split_simplelist(tk_call('font', 'configure', font))
+ r = []
+ while key=l.shift
+ if key == '-compound'
+ l.shift
+ else
+ key = key[1..-1]
+ val = l.shift
+ case TkFont::OptionType[key]
+ when ?n
+ r.push [key, num_or_str(val)]
+ when ?b
+ r.push [key, bool(val)]
+ else
+ r.push [key, val]
+ end
+ end
+ end
+ r
+ end
+ else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ current_configinfo_core_tk8x(font, option)
+ end
+ end
+
+ def current_configinfo_core_tk8x(font, option=nil)
+ if option == 'compound'
+ ""
+ elsif option
+ val = tk_call('font', 'configure', font, "-#{option}")
+ case TkFont::OptionType[option.to_s]
+ when ?n
+ num_or_str(val)
+ when ?b
+ bool(val)
+ else
+ val
+ end
+ else
+ l = tk_split_simplelist(tk_call('font', 'configure', font))
+ h = {}
+ while key=l.shift
+ if key == '-compound'
+ l.shift
+ else
+ key = key[1..-1]
+ val = l.shift
+ case TkFont::OptionType[key]
+ when ?n
+ h[key] = num_or_str(val)
+ when ?b
+ h[key] = bool(val)
+ else
+ h[key] = val
+ end
+ end
+ end
+ h
+ end
+ end
+
+ def delete_core_tk4x
+ TkFont::Tk_FontNameTBL.mutex.synchronize{
+ TkFont::Tk_FontNameTBL.delete(@id)
+ }
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ }
+ end
+
+ def delete_core_tk8x
+ begin
+ tk_call('font', 'delete', @latinfont) if @latinfont
+ rescue
+ end
+ begin
+ tk_call('font', 'delete', @kanjifont) if @kanjifont
+ rescue
+ end
+ begin
+ tk_call('font', 'delete', @compoundfont) if @compoundfont
+ rescue
+ end
+ TkFont::Tk_FontNameTBL.mutex.synchronize{
+ TkFont::Tk_FontNameTBL.delete(@id)
+ }
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ }
+ end
+
+ def latin_replace_core_tk4x(ltn)
+ create_latinfont_tk4x(ltn)
+ @compoundfont[0] = [@latinfont] if JAPANIZED_TK
+ @fontslot['font'] = @latinfont
+ table = nil
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ table = TkFont::Tk_FontUseTBL.clone
+ }
+ table.each{|w, fobj|
+ if self == fobj
+ begin
+ if w.include?(';')
+ win, tag, optkey = w.split(';')
+ optkey = 'font' if optkey == nil || optkey == ''
+ winobj = tk_tcl2ruby(win)
+# winobj.tagfont_configure(tag, {'font'=>@latinfont})
+ #if winobj.kind_of? TkText
+ if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text)
+ tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @latinfont)
+ #elsif winobj.kind_of? TkCanvas
+ elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas)
+ tk_call(win, 'itemconfigure', tag, "-#{optkey}", @latinfont)
+ #elsif winobj.kind_of? TkMenu
+ elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu)
+ tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont)
+ else
+ raise RuntimeError, "unknown widget type"
+ end
+ else
+# tk_tcl2ruby(w).font_configure('font'=>@latinfont)
+ tk_call(w, 'configure', '-font', @latinfont)
+ end
+ rescue
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete(w)
+ }
+ end
+ end
+ }
+ self
+ end
+
+ def kanji_replace_core_tk4x(knj)
+ return self unless JAPANIZED_TK
+
+ create_kanjifont_tk4x(knj)
+ @compoundfont[1] = [@kanjifont]
+ @fontslot['kanjifont'] = @kanjifont
+ table = nil
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ table = TkFont::Tk_FontUseTBL.clone
+ }
+ table.dup.each{|w, fobj|
+ if self == fobj
+ begin
+ if w.include?(';')
+ win, tag, optkey = w.split(';')
+ optkey = 'kanjifont' unless optkey
+ winobj = tk_tcl2ruby(win)
+# winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont})
+ #if winobj.kind_of? TkText
+ if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text)
+ tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @kanjifont)
+ #elsif winobj.kind_of? TkCanvas
+ elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas)
+ tk_call(win, 'itemconfigure', tag, "-#{optkey}", @kanjifont)
+ #elsif winobj.kind_of? TkMenu
+ elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu)
+ tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont)
+ else
+ raise RuntimeError, "unknown widget type"
+ end
+ else
+# tk_tcl2ruby(w).font_configure('kanjifont'=>@kanjifont)
+ tk_call(w, 'configure', '-kanjifont', @kanjifont)
+ end
+ rescue
+ Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete(w)
+ }
+ end
+ end
+ }
+ self
+ end
+
+ def latin_replace_core_tk8x(ltn)
+ ltn = '{}' if ltn == ''
+
+ if JAPANIZED_TK
+ begin
+ tk_call('font', 'delete', '@font_tmp')
+ rescue
+ end
+ begin
+ fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @latinfont)
+ rescue
+ #fnt_bup = ''
+ fnt_bup = TkFont::DEFAULT_LATIN_FONT_NAME
+ end
+ end
+
+ begin
+ tk_call('font', 'delete', @latinfont)
+ rescue
+ end
+ create_latinfont(ltn)
+
+ if JAPANIZED_TK
+ keys = self.configinfo
+ tk_call('font', 'delete', @compoundfont)
+ begin
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
+=begin
+ latinkeys = {}
+ begin
+ actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
+ rescue
+ latinkeys = {}
+ end
+ if latinkeys != {}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ end
+=end
+ rescue RuntimeError => e
+ tk_call('font', 'delete', @latinfont)
+ if fnt_bup && fnt_bup != ''
+ tk_call('font', 'create', @latinfont, '-copy', fnt_bup)
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
+ tk_call('font', 'delete', fnt_bup)
+ else
+ fail e
+ end
+ end
+
+ else
+ latinkeys = {}
+ begin
+ actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
+ rescue
+ latinkeys = {}
+ end
+ begin
+ tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ rescue
+ # not exist? (deleted?) -> create font
+ tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys))
+ end
+ end
+ self
+ end
+
+ def kanji_replace_core_tk8x(knj)
+ knj = '{}' if knj == ''
+
+ if JAPANIZED_TK
+ begin
+ tk_call('font', 'delete', '@font_tmp')
+ rescue
+ end
+ begin
+ fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @kanjifont)
+ rescue
+ #fnt_bup = ''
+ fnt_bup = TkFont::DEFAULT_KANJI_FONT_NAME
+ end
+ end
+
+ begin
+ tk_call('font', 'delete', @kanjifont)
+ rescue
+ end
+ create_kanjifont(knj)
+
+ if JAPANIZED_TK
+ keys = self.configinfo
+ tk_call('font', 'delete', @compoundfont)
+ begin
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
+ rescue RuntimeError => e
+ tk_call('font', 'delete', @kanjifont)
+ if fnt_bup && fnt_bup != ''
+ tk_call('font', 'create', @kanjifont, '-copy', fnt_bup)
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
+ tk_call('font', 'delete', fnt_bup)
+ else
+ fail e
+ end
+ end
+ end
+ self
+ end
+
+ def measure_core_tk4x(font, win, text)
+ 0
+ end
+
+ def measure_core_tk8x(font, win, text)
+ font = '{}' if font == ''
+
+ if win
+ number(tk_call('font', 'measure', font,
+ '-displayof', win, text))
+ else
+ number(tk_call('font', 'measure', font, text))
+ end
+ end
+
+ def metrics_core_tk4x(font, win, option=nil)
+ # dummy
+ if option
+ ""
+ else
+ [['ascent',[]], ['descent',[]], ['linespace',[]], ['fixed',[]]]
+ end
+ end
+
+ def metrics_core_tk8x(font, win, option=nil)
+ font = '{}' if font == ''
+
+ if option
+ if win
+ number(tk_call('font', 'metrics', font,
+ "-displayof", win, "-#{option}"))
+ else
+ number(tk_call('font', 'metrics', font, "-#{option}"))
+ end
+ else
+ l = tk_split_list(if win
+ tk_call('font','metrics',font,"-displayof",win)
+ else
+ tk_call('font','metrics',font)
+ end)
+ r = []
+ while key=l.shift
+ r.push [key[1..-1], l.shift.to_i]
+=begin
+ if key == '-fixed' # boolean value
+ r.push [key[1..-1], bool(l.shift)]
+ else
+ r.push [key[1..-1], l.shift.to_i]
+ end
+=end
+ end
+ r
+ end
+ end
+
+ ###################################
+ # private alias
+ ###################################
+ case (Tk::TK_VERSION)
+ when /^4\..*/
+ alias actual_core actual_core_tk4x
+ alias configure_core configure_core_tk4x
+ alias configinfo_core configinfo_core_tk4x
+ alias current_configinfo_core current_configinfo_core_tk4x
+ alias delete_core delete_core_tk4x
+ alias latin_replace_core latin_replace_core_tk4x
+ alias kanji_replace_core kanji_replace_core_tk4x
+ alias measure_core measure_core_tk4x
+ alias metrics_core metrics_core_tk4x
+
+ when /^8\.[0-5]/
+ alias actual_core actual_core_tk8x
+ alias configure_core configure_core_tk8x
+ alias configinfo_core configinfo_core_tk8x
+ alias current_configinfo_core current_configinfo_core_tk8x
+ alias delete_core delete_core_tk8x
+ alias latin_replace_core latin_replace_core_tk8x
+ alias kanji_replace_core kanji_replace_core_tk8x
+ alias measure_core measure_core_tk8x
+ alias metrics_core metrics_core_tk8x
+
+ else
+ alias actual_core actual_core_tk8x
+ alias configure_core configure_core_tk8x
+ alias configinfo_core configinfo_core_tk8x
+ alias current_configinfo_core current_configinfo_core_tk8x
+ alias delete_core delete_core_tk8x
+ alias latin_replace_core latin_replace_core_tk8x
+ alias kanji_replace_core kanji_replace_core_tk8x
+ alias measure_core measure_core_tk8x
+ alias metrics_core metrics_core_tk8x
+
+ end
+end
+
+class TkFont
+ include TkFont::CoreMethods
+ extend TkFont::CoreMethods
+end
+
+class TkNamedFont < TkFont
+ # for built-in named fonts
+ def TkNamedFont.find(name)
+ name = name.to_s
+ unless (obj = Tk_FontNameTBL[name])
+ obj = self.new(name) if TkFont.is_system_font?(name)
+ end
+ obj
+ end
+
+ def TkNamedFont.new(name, keys=nil)
+ name = name.to_s
+ obj = nil
+ Tk_FontNameTBL.mutex.synchronize{
+ unless (obj = Tk_FontNameTBL[name])
+ (obj = self.allocate).instance_eval{
+ @id = @compoundfont = name.to_s
+ @latinfont = nil
+ @kanjifont = nil
+ @descendant = [self, self] # [latin, kanji] : dummy
+ Tk_FontNameTBL[@id] = self
+ }
+ end
+ }
+ obj.instance_eval{ initialize(name, keys) }
+ obj
+ end
+
+ ###########################
+ private
+ ###########################
+ def initialize(name, keys=nil)
+ @id = @compoundfont = name.to_s
+
+ # if not exist named font, create it.
+ begin
+ if keys
+ tk_call('font', 'configure', @compoundfont, keys)
+ else
+ tk_call('font', 'configure', @compoundfont)
+ end
+ rescue
+ # the named font doesn't exist -> create
+ if keys
+ tk_call('font', 'create', @compoundfont, keys)
+ else
+ tk_call('font', 'create', @compoundfont)
+ end
+ end
+ end
+
+ def create_latinfont(fnt)
+ # ignore
+ end
+ def create_kanjifont(fnt)
+ # ignore
+ end
+ def create_compoundfont(ltn, knj, keys)
+ # ignore
+ end
+
+ ###########################
+ public
+ ###########################
+ def latin_font_id
+ @compoundfont
+ end
+ def kanji_font_id
+ @compoundfont
+ end
+end
+
+#######################################
+# define system font names
+#######################################
+if Tk::TCL_MAJOR_VERSION > 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
+ # add standard fonts of Tcl/Tk 8.5+
+ TkFont::SYSTEM_FONT_NAMES.add [
+ 'TkDefaultFont', 'TkTextFont', 'TkFixedFont', 'TkMenuFont',
+ 'TkHeadingFont', 'TkCaptionFont', 'TkSmallCaptionFont',
+ 'TkIconFont', 'TkTooltipFont'
+ ]
+end
+
+# platform-specific fonts
+# -- windows
+TkFont::SYSTEM_FONT_NAMES.add [
+ 'ansifixed', 'ansi', 'device', 'oemfixed', 'systemfixed', 'system'
+]
+
+# -- macintosh, macosx
+TkFont::SYSTEM_FONT_NAMES.add ['system', 'application']
+
+if Tk::TCL_MAJOR_VERSION > 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
+ TkFont::SYSTEM_FONT_NAMES.add ['menu']
+end
+
+# -- macosx (Aqua theme)
+if Tk::TCL_MAJOR_VERSION > 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
+ TkFont::SYSTEM_FONT_NAMES.add [
+ 'systemSystemFont', 'systemEmphasizedSystemFont',
+ 'systemSmallSystemFont', 'systemSmallEmphasizedSystemFont',
+ 'systemApplicationFont', 'systemLabelFont', 'systemViewsFont',
+ 'systemMenuTitleFont', 'systemMenuItemFont', 'systemMenuItemMarkFont',
+ 'systemMenuItemCmdKeyFont', 'systemWindowTitleFont',
+ 'systemPushButtonFont', 'systemUtilityWindowTitleFont',
+ 'systemAlertHeaderFont', 'systemToolbarFont', 'systemMiniSystemFont',
+ 'systemDetailSystemFont', 'systemDetailEmphasizedSystemFont'
+ ]
+end
diff --git a/ext/tk/lib/tk/frame.rb b/ext/tk/lib/tk/frame.rb
new file mode 100644
index 0000000000..263b160f29
--- /dev/null
+++ b/ext/tk/lib/tk/frame.rb
@@ -0,0 +1,131 @@
+#
+# tk/frame.rb : treat frame widget
+#
+require 'tk'
+
+class Tk::Frame<TkWindow
+ TkCommandNames = ['frame'.freeze].freeze
+ WidgetClassName = 'Frame'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+################# old version
+# def initialize(parent=nil, keys=nil)
+# if keys.kind_of? Hash
+# keys = keys.dup
+# @classname = keys.delete('classname') if keys.key?('classname')
+# @colormap = keys.delete('colormap') if keys.key?('colormap')
+# @container = keys.delete('container') if keys.key?('container')
+# @visual = keys.delete('visual') if keys.key?('visual')
+# end
+# super(parent, keys)
+# end
+#
+# def create_self
+# s = []
+# s << "-class" << @classname if @classname
+# s << "-colormap" << @colormap if @colormap
+# s << "-container" << @container if @container
+# s << "-visual" << @visual if @visual
+# tk_call 'frame', @path, *s
+# end
+#################
+
+ def __boolval_optkeys
+ super() << 'container'
+ end
+ private :__boolval_optkeys
+
+ def initialize(parent=nil, keys=nil)
+ my_class_name = nil
+ if self.class < WidgetClassNames[self.class::WidgetClassName]
+ my_class_name = self.class.name
+ my_class_name = nil if my_class_name == ''
+ end
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ else
+ if keys
+ keys = _symbolkey2str(keys)
+ keys['parent'] = parent
+ else
+ keys = {'parent'=>parent}
+ end
+ end
+ if keys.key?('classname')
+ keys['class'] = keys.delete('classname')
+ end
+ @classname = keys['class']
+ @colormap = keys['colormap']
+ @container = keys['container']
+ @visual = keys['visual']
+ if !@classname && my_class_name
+ keys['class'] = @classname = my_class_name
+ end
+ if @classname.kind_of? TkBindTag
+ @db_class = @classname
+ @classname = @classname.id
+ elsif @classname
+ @db_class = TkDatabaseClass.new(@classname)
+ else
+ @db_class = self.class
+ @classname = @db_class::WidgetClassName
+ end
+ super(keys)
+ end
+
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('frame', @path, *hash_kv(keys))
+ # else
+ # tk_call_without_enc( 'frame', @path)
+ # end
+ #end
+ #private :create_self
+
+ def database_classname
+ @classname
+ end
+
+ def self.database_class
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ self
+ else
+ TkDatabaseClass.new(self.name)
+ end
+ end
+ def self.database_classname
+ self.database_class.name
+ end
+
+ def self.bind(*args, &b)
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ super(*args, &b)
+ else
+ TkDatabaseClass.new(self.name).bind(*args, &b)
+ end
+ end
+ def self.bind_append(*args, &b)
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ super(*args, &b)
+ else
+ TkDatabaseClass.new(self.name).bind_append(*args, &b)
+ end
+ end
+ def self.bind_remove(*args)
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ super(*args)
+ else
+ TkDatabaseClass.new(self.name).bind_remove(*args)
+ end
+ end
+ def self.bindinfo(*args)
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ super(*args)
+ else
+ TkDatabaseClass.new(self.name).bindinfo(*args)
+ end
+ end
+end
+
+#TkFrame = Tk::Frame unless Object.const_defined? :TkFrame
+Tk.__set_toplevel_aliases__(:Tk, Tk::Frame, :TkFrame)
diff --git a/ext/tk/lib/tk/grid.rb b/ext/tk/lib/tk/grid.rb
new file mode 100644
index 0000000000..0dfd7263a7
--- /dev/null
+++ b/ext/tk/lib/tk/grid.rb
@@ -0,0 +1,265 @@
+#
+# tk/grid.rb : control grid geometry manager
+#
+require 'tk'
+
+module TkGrid
+ include Tk
+ extend Tk
+
+ TkCommandNames = ['grid'.freeze].freeze
+
+ def anchor(master, anchor=None)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ tk_call_without_enc('grid', 'anchor', master, anchor)
+ end
+
+ def bbox(master, *args)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ args.unshift(master)
+ list(tk_call_without_enc('grid', 'bbox', *args))
+ end
+
+=begin
+ def configure(win, *args)
+ if args[-1].kind_of?(Hash)
+ opts = args.pop
+ else
+ opts = {}
+ end
+ params = []
+ params.push(_epath(win))
+ args.each{|win|
+ case win
+ when '-', 'x', '^' # RELATIVE PLACEMENT
+ params.push(win)
+ else
+ params.push(_epath(win))
+ end
+ }
+ opts.each{|k, v|
+ params.push("-#{k}")
+ params.push((v.kind_of?(TkObject))? v.epath: v)
+ }
+ if Tk::TCL_MAJOR_VERSION < 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION <= 3)
+ if params[0] == '-' || params[0] == 'x' || params[0] == '^'
+ tk_call_without_enc('grid', *params)
+ else
+ tk_call_without_enc('grid', 'configure', *params)
+ end
+ else
+ tk_call_without_enc('grid', 'configure', *params)
+ end
+ end
+=end
+ def configure(*args)
+ if args[-1].kind_of?(Hash)
+ opts = args.pop
+ else
+ opts = {}
+ end
+ fail ArgumentError, 'no widget is given' if args.empty?
+ params = []
+ args.flatten(1).each{|win|
+ case win
+ when '-', ?- # RELATIVE PLACEMENT (increase columnspan)
+ params.push('-')
+ when /^-+$/ # RELATIVE PLACEMENT (increase columnspan)
+ params.concat(win.to_s.split(//))
+ when '^', ?^ # RELATIVE PLACEMENT (increase rowspan)
+ params.push('^')
+ when /^\^+$/ # RELATIVE PLACEMENT (increase rowspan)
+ params.concat(win.to_s.split(//))
+ when 'x', :x, ?x, nil, '' # RELATIVE PLACEMENT (empty column)
+ params.push('x')
+ when /^x+$/ # RELATIVE PLACEMENT (empty column)
+ params.concat(win.to_s.split(//))
+ else
+ params.push(_epath(win))
+ end
+ }
+ opts.each{|k, v|
+ params.push("-#{k}")
+ params.push(_epath(v)) # have to use 'epath' (hash_kv() is unavailable)
+ }
+ if Tk::TCL_MAJOR_VERSION < 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION <= 3)
+ if params[0] == '-' || params[0] == 'x' || params[0] == '^'
+ tk_call_without_enc('grid', *params)
+ else
+ tk_call_without_enc('grid', 'configure', *params)
+ end
+ else
+ tk_call_without_enc('grid', 'configure', *params)
+ end
+ end
+ alias grid configure
+
+ def columnconfigure(master, index, args)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ tk_call_without_enc("grid", 'columnconfigure',
+ master, index, *hash_kv(args))
+ end
+ alias column columnconfigure
+
+ def rowconfigure(master, index, args)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ tk_call_without_enc("grid", 'rowconfigure', master, index, *hash_kv(args))
+ end
+ alias row rowconfigure
+
+ def columnconfiginfo(master, index, slot=nil)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ if slot
+ case slot
+ when 'uniform', :uniform
+ tk_call_without_enc('grid', 'columnconfigure',
+ master, index, "-#{slot}")
+ else
+ num_or_str(tk_call_without_enc('grid', 'columnconfigure',
+ master, index, "-#{slot}"))
+ end
+ else
+ #ilist = list(tk_call_without_enc('grid','columnconfigure',master,index))
+ ilist = simplelist(tk_call_without_enc('grid', 'columnconfigure',
+ master, index))
+ info = {}
+ while key = ilist.shift
+ case key
+ when 'uniform'
+ info[key[1..-1]] = ilist.shift
+ else
+ info[key[1..-1]] = tk_tcl2ruby(ilist.shift)
+ end
+ end
+ info
+ end
+ end
+
+ def rowconfiginfo(master, index, slot=nil)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ if slot
+ case slot
+ when 'uniform', :uniform
+ tk_call_without_enc('grid', 'rowconfigure',
+ master, index, "-#{slot}")
+ else
+ num_or_str(tk_call_without_enc('grid', 'rowconfigure',
+ master, index, "-#{slot}"))
+ end
+ else
+ #ilist = list(tk_call_without_enc('grid', 'rowconfigure', master, index))
+ ilist = simplelist(tk_call_without_enc('grid', 'rowconfigure',
+ master, index))
+ info = {}
+ while key = ilist.shift
+ case key
+ when 'uniform'
+ info[key[1..-1]] = ilist.shift
+ else
+ info[key[1..-1]] = tk_tcl2ruby(ilist.shift)
+ end
+ end
+ info
+ end
+ end
+
+ def add(widget, *args)
+ configure(widget, *args)
+ end
+
+ def forget(*args)
+ return '' if args.size == 0
+ wins = args.collect{|win|
+ # (win.kind_of?(TkObject))? win.epath: win
+ _epath(win)
+ }
+ tk_call_without_enc('grid', 'forget', *wins)
+ end
+
+ def info(slave)
+ # slave = slave.epath if slave.kind_of?(TkObject)
+ slave = _epath(slave)
+ #ilist = list(tk_call_without_enc('grid', 'info', slave))
+ ilist = simplelist(tk_call_without_enc('grid', 'info', slave))
+ info = {}
+ while key = ilist.shift
+ #info[key[1..-1]] = ilist.shift
+ info[key[1..-1]] = tk_tcl2ruby(ilist.shift)
+ end
+ return info
+ end
+
+ def location(master, x, y)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ list(tk_call_without_enc('grid', 'location', master, x, y))
+ end
+
+ def propagate(master, mode=None)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ if mode == None
+ bool(tk_call_without_enc('grid', 'propagate', master))
+ else
+ tk_call_without_enc('grid', 'propagate', master, mode)
+ end
+ end
+
+ def remove(*args)
+ return '' if args.size == 0
+ wins = args.collect{|win|
+ # (win.kind_of?(TkObject))? win.epath: win
+ _epath(win)
+ }
+ tk_call_without_enc('grid', 'remove', *wins)
+ end
+
+ def size(master)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ list(tk_call_without_enc('grid', 'size', master))
+ end
+
+ def slaves(master, args)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ list(tk_call_without_enc('grid', 'slaves', master, *hash_kv(args)))
+ end
+
+ module_function :anchor, :bbox, :add, :forget, :propagate, :info
+ module_function :remove, :size, :slaves, :location
+ module_function :grid, :configure, :columnconfigure, :rowconfigure
+ module_function :column, :row, :columnconfiginfo, :rowconfiginfo
+end
+=begin
+def TkGrid(win, *args)
+ if args[-1].kind_of?(Hash)
+ opts = args.pop
+ else
+ opts = {}
+ end
+ params = []
+ params.push((win.kind_of?(TkObject))? win.epath: win)
+ args.each{|win|
+ case win
+ when '-', 'x', '^' # RELATIVE PLACEMENT
+ params.push(win)
+ else
+ params.push((win.kind_of?(TkObject))? win.epath: win)
+ end
+ }
+ opts.each{|k, v|
+ params.push("-#{k}")
+ params.push((v.kind_of?(TkObject))? v.epath: v)
+ }
+ tk_call_without_enc("grid", *params)
+end
+=end
diff --git a/ext/tk/lib/tk/image.rb b/ext/tk/lib/tk/image.rb
new file mode 100644
index 0000000000..dffdc19644
--- /dev/null
+++ b/ext/tk/lib/tk/image.rb
@@ -0,0 +1,275 @@
+#
+# tk/image.rb : treat Tk image objects
+#
+
+require 'tk'
+
+class TkImage<TkObject
+ include Tk
+
+ TkCommandNames = ['image'.freeze].freeze
+
+ Tk_IMGTBL = TkCore::INTERP.create_table
+
+ (Tk_Image_ID = ['i'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk_IMGTBL.mutex.synchronize{ Tk_IMGTBL.clear }
+ }
+
+ def self.new(keys=nil)
+ if keys.kind_of?(Hash)
+ name = nil
+ if keys.key?(:imagename)
+ name = keys[:imagename]
+ elsif keys.key?('imagename')
+ name = keys['imagename']
+ end
+ if name
+ if name.kind_of?(TkImage)
+ obj = name
+ else
+ name = _get_eval_string(name)
+ obj = nil
+ Tk_IMGTBL.mutex.synchronize{
+ obj = Tk_IMGTBL[name]
+ }
+ end
+ if obj
+ if !(keys[:without_creating] || keys['without_creating'])
+ keys = _symbolkey2str(keys)
+ keys.delete('imagename')
+ keys.delete('without_creating')
+ obj.instance_eval{
+ tk_call_without_enc('image', 'create',
+ @type, @path, *hash_kv(keys, true))
+ }
+ end
+ return obj
+ end
+ end
+ end
+ (obj = self.allocate).instance_eval{
+ Tk_IMGTBL.mutex.synchronize{
+ initialize(keys)
+ Tk_IMGTBL[@path] = self
+ }
+ }
+ obj
+ end
+
+ def initialize(keys=nil)
+ @path = nil
+ without_creating = false
+ if keys.kind_of?(Hash)
+ keys = _symbolkey2str(keys)
+ @path = keys.delete('imagename')
+ without_creating = keys.delete('without_creating')
+ end
+ unless @path
+ Tk_Image_ID.mutex.synchronize{
+ # @path = Tk_Image_ID.join('')
+ @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Image_ID[1].succ!
+ }
+ end
+ unless without_creating
+ tk_call_without_enc('image', 'create',
+ @type, @path, *hash_kv(keys, true))
+ end
+ end
+
+ def delete
+ Tk_IMGTBL.mutex.synchronize{
+ Tk_IMGTBL.delete(@id) if @id
+ }
+ tk_call_without_enc('image', 'delete', @path)
+ self
+ end
+ def height
+ number(tk_call_without_enc('image', 'height', @path))
+ end
+ def inuse
+ bool(tk_call_without_enc('image', 'inuse', @path))
+ end
+ def itemtype
+ tk_call_without_enc('image', 'type', @path)
+ end
+ def width
+ number(tk_call_without_enc('image', 'width', @path))
+ end
+
+ def TkImage.names
+ Tk_IMGTBL.mutex.synchronize{
+ Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
+ (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ }
+ }
+ end
+
+ def TkImage.types
+ Tk.tk_call_without_enc('image', 'types').split
+ end
+end
+
+class TkBitmapImage<TkImage
+ def __strval_optkeys
+ super() + ['maskdata', 'maskfile']
+ end
+ private :__strval_optkeys
+
+ def initialize(*args)
+ @type = 'bitmap'
+ super(*args)
+ end
+end
+
+class TkPhotoImage<TkImage
+ NullArgOptionKeys = [ "shrink", "grayscale" ]
+
+ def _photo_hash_kv(keys)
+ keys = _symbolkey2str(keys)
+ NullArgOptionKeys.collect{|opt|
+ if keys[opt]
+ keys[opt] = None
+ else
+ keys.delete(opt)
+ end
+ }
+ keys.collect{|k,v|
+ ['-' << k, v]
+ }.flatten
+ end
+ private :_photo_hash_kv
+
+ def initialize(*args)
+ @type = 'photo'
+ super(*args)
+ end
+
+ def blank
+ tk_send_without_enc('blank')
+ self
+ end
+
+ def cget_strict(option)
+ case option.to_s
+ when 'data', 'file'
+ tk_send 'cget', '-' << option.to_s
+ else
+ tk_tcl2ruby(tk_send('cget', '-' << option.to_s))
+ end
+ end
+ def cget(option)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ cget_strict(option)
+ else
+ begin
+ cget_strict(option)
+ rescue => e
+ if current_configinfo.has_key?(option.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ end
+ end
+ end
+
+ def copy(src, *opts)
+ if opts.size == 0
+ tk_send('copy', src)
+ elsif opts.size == 1 && opts[0].kind_of?(Hash)
+ tk_send('copy', src, *_photo_hash_kv(opts[0]))
+ else
+ # for backward compatibility
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+ tk_send('copy', src, *args)
+ end
+ self
+ end
+
+ def data(keys={})
+ #tk_send('data', *_photo_hash_kv(keys))
+ tk_split_list(tk_send('data', *_photo_hash_kv(keys)))
+ end
+
+ def get(x, y)
+ tk_send('get', x, y).split.collect{|n| n.to_i}
+ end
+
+ def put(data, *opts)
+ if opts == []
+ tk_send('put', data)
+ elsif opts.size == 1 && opts[0].kind_of?(Hash)
+ tk_send('put', data, *_photo_hash_kv(opts[0]))
+ else
+ # for backward compatibility
+ tk_send('put', data, '-to', *opts)
+ end
+ self
+ end
+
+ def read(file, *opts)
+ if opts.size == 0
+ tk_send('read', file)
+ elsif opts.size == 1 && opts[0].kind_of?(Hash)
+ tk_send('read', file, *_photo_hash_kv(opts[0]))
+ else
+ # for backward compatibility
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+ tk_send('read', file, *args)
+ end
+ self
+ end
+
+ def redither
+ tk_send 'redither'
+ self
+ end
+
+ def get_transparency(x, y)
+ bool(tk_send('transparency', 'get', x, y))
+ end
+ def set_transparency(x, y, st)
+ tk_send('transparency', 'set', x, y, st)
+ self
+ end
+
+ def write(file, *opts)
+ if opts.size == 0
+ tk_send('write', file)
+ elsif opts.size == 1 && opts[0].kind_of?(Hash)
+ tk_send('write', file, *_photo_hash_kv(opts[0]))
+ else
+ # for backward compatibility
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+ tk_send('write', file, *args)
+ end
+ self
+ end
+end
diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb
new file mode 100644
index 0000000000..9c6a98d0f8
--- /dev/null
+++ b/ext/tk/lib/tk/itemconfig.rb
@@ -0,0 +1,1215 @@
+#
+# tk/itemconfig.rb : control item/tag configuration of widget
+#
+require 'tk'
+require 'tkutil'
+require 'tk/itemfont.rb'
+
+module TkItemConfigOptkeys
+ include TkUtil
+
+ def __item_optkey_aliases(id)
+ {}
+ end
+ private :__item_optkey_aliases
+
+ 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)
+ ['exportselection', 'jump', 'setgrid', 'takefocus']
+ end
+ private :__item_boolval_optkeys
+
+ def __item_strval_optkeys(id)
+ # maybe need to override
+ [
+ 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile',
+ 'activebackground', 'activeforeground', 'background',
+ 'disabledforeground', 'disabledbackground', 'foreground',
+ 'highlightbackground', 'highlightcolor', 'insertbackground',
+ 'selectbackground', 'selectforeground', 'troughcolor'
+ ]
+ 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_tkvariable_optkeys(id)
+ ['variable', 'textvariable']
+ end
+ private :__item_tkvariable_optkeys
+
+ def __item_val2ruby_optkeys(id) # { key=>method, ... }
+ # The method is used to convert a opt-value to a ruby's object.
+ # When get the value of the option "key", "method.call(id, val)" is called.
+ {}
+ end
+ private :__item_val2ruby_optkeys
+
+ def __item_ruby2val_optkeys(id) # { key=>method, ... }
+ # The method is used to convert a ruby's object to a opt-value.
+ # When set the value of the option "key", "method.call(id, val)" is called.
+ # That is, "-#{key} #{method.call(id, value)}".
+ {}
+ end
+ private :__item_ruby2val_optkeys
+
+ def __item_methodcall_optkeys(id) # { key=>method, ... }
+ # Use the method for both of get and set.
+ # Usually, the 'key' will not be a widget option.
+ #
+ # 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 TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ @mode || false
+ end
+ def TkItemConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode)
+ fail SecurityError, "can't change the mode" if $SAFE>=4
+ @mode = (mode)? true: false
+ end
+
+ 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_confinfo_cmd(id)
+ # maybe need to override
+ __item_config_cmd(id)
+ end
+ private :__item_confinfo_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 tagid(tagOrId)
+ # maybe need to override
+ tagOrId
+ end
+
+ ################################################
+
+ def __itemcget_core(tagOrId, option)
+ orig_opt = option
+ option = option.to_s
+
+ if option.length == 0
+ fail ArgumentError, "Invalid option `#{orig_opt.inspect}'"
+ end
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == option}
+ if real_name
+ option = real_name.to_s
+ end
+
+ if ( method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[option] )
+ optval = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))
+ begin
+ return method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ return optval
+ end
+ end
+
+ 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_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ v = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))
+ (v.empty?)? nil: TkVarAccess.new(v)
+
+ 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
+ private :__itemcget_core
+
+ def itemcget(tagOrId, option)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __itemcget_core(tagOrId, option)
+ else
+ begin
+ __itemcget_core(tagOrId, option)
+ rescue => e
+ begin
+ if __current_itemconfiginfo(tagOrId).has_key?(option.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+ def itemcget_strict(tagOrId, option)
+ # never use TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __itemcget_core(tagOrId, option)
+ end
+
+ def __itemconfigure_core(tagOrId, slot, value=None)
+ if slot.kind_of? Hash
+ slot = _symbolkey2str(slot)
+
+ __item_optkey_aliases(tagid(tagOrId)).each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if slot.has_key?(alias_name)
+ slot[real_name.to_s] = slot.delete(alias_name)
+ end
+ }
+
+ __item_methodcall_optkeys(tagid(tagOrId)).each{|key, method|
+ value = slot.delete(key.to_s)
+ self.__send__(method, tagOrId, value) if value
+ }
+
+ __item_ruby2val_optkeys(tagid(tagOrId)).each{|key, method|
+ key = key.to_s
+ slot[key] = method.call(tagOrId, slot[key]) if slot.has_key?(key)
+ }
+
+ __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
+ orig_slot = slot
+ slot = slot.to_s
+ if slot.length == 0
+ fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
+ end
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
+ 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_ruby2val_optkeys(tagid(tagOrId)))[slot] )
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}" << method.call(tagOrId, value)))
+ 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
+ private :__itemconfigure_core
+
+ def __check_available_itemconfigure_options(tagOrId, keys)
+ id = tagid(tagOrId)
+
+ availables = self.__current_itemconfiginfo(id).keys
+
+ # add non-standard keys
+ availables |= __font_optkeys.map{|k|
+ [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"]
+ }.flatten
+ availables |= __item_methodcall_optkeys(id).keys.map{|k| k.to_s}
+ availables |= __item_keyonly_optkeys(id).keys.map{|k| k.to_s}
+
+ keys = _symbolkey2str(keys)
+
+ keys.delete_if{|k, v| !(availables.include?(k))}
+ end
+
+ def itemconfigure(tagOrId, slot, value=None)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __itemconfigure_core(tagOrId, slot, value)
+ else
+ if slot.kind_of?(Hash)
+ begin
+ __itemconfigure_core(tagOrId, slot)
+ rescue
+ slot = __check_available_itemconfigure_options(tagOrId, slot)
+ __itemconfigure_core(tagOrId, slot) unless slot.empty?
+ end
+ else
+ begin
+ __itemconfigure_core(tagOrId, slot, value)
+ rescue => e
+ begin
+ if __current_itemconfiginfo(tagOrId).has_key?(slot.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+ self
+ end
+
+ def __itemconfiginfo_core(tagOrId, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
+ fontkey = $2
+ # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")), false, true)
+ 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 )
+ fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
+ 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
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
+ case slot
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+ if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
+ && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
+ optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val
+ end
+ if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
+ optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val
+ end
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
+ && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
+ v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if v.empty?
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
+ else
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v)
+ end
+ end
+ if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
+ v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
+ if v.empty?
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
+ else
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
+ end
+ end
+
+ else
+ # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_list(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), 0, false, true)
+ 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_confinfo_cmd(tagid(tagOrId)))))).collect{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ ret = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false).collect{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ conf[__item_configinfo_struct(tagid(tagOrId))[:key]] =
+ conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
+
+ optkey = conf[__item_configinfo_struct(tagid(tagOrId))[:key]]
+ case optkey
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey]
+ if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
+ && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
+ optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ begin
+ val = method(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val
+ end
+ if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
+ optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val
+ end
+
+ 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
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
+ && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
+ v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if v.empty?
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
+ else
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v)
+ end
+ end
+ if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
+ v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
+ if v.empty?
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
+ else
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
+ end
+ 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}$/}
+ fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
+ 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 && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
+ fontkey = $2
+ # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")), false, true)
+ 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 )
+ fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(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
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
+ case slot
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+ if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
+ && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
+ optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val
+ end
+ if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
+ optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val
+ end
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ 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_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true)
+
+ if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
+ && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
+ v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if v.empty?
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
+ else
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v)
+ end
+ end
+ if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
+ v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
+ if v.empty?
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
+ else
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
+ end
+ end
+
+ else
+ # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))))
+ conf = tk_split_list(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), 0, false, true)
+ 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_confinfo_cmd(tagid(tagOrId)))))).each{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false).each{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ conf[__item_configinfo_struct(tagid(tagOrId))[:key]] =
+ conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
+
+ optkey = conf[__item_configinfo_struct(tagid(tagOrId))[:key]]
+ case optkey
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey]
+ if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
+ && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
+ optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val
+ end
+ if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
+ optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val
+ end
+
+ 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
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \
+ && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] )
+ v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if v.empty?
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil
+ else
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v)
+ end
+ end
+ if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] )
+ v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]
+ if v.empty?
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
+ else
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
+ end
+ 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)
+ fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
+ 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
+ private :__itemconfiginfo_core
+
+ def itemconfiginfo(tagOrId, slot = nil)
+ if slot && TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ begin
+ __itemconfiginfo_core(tagOrId, slot)
+ rescue => e
+ begin
+ __itemconfiginfo_core(tagOrId)
+ # not tag error -> option is unknown
+ Array.new(__item_configinfo_struct.values.max).unshift(slot.to_s)
+ rescue
+ fail e # tag error
+ end
+ end
+ else
+ __itemconfiginfo_core(tagOrId, slot)
+ end
+ end
+
+ def __current_itemconfiginfo(tagOrId, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ org_slot = slot
+ begin
+ conf = __itemconfiginfo_core(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_core(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_core(tagOrId, slot).each{|key, conf|
+ ret[key] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+
+ def current_itemconfiginfo(tagOrId, slot = nil)
+ __current_itemconfiginfo(tagOrId, slot)
+ end
+end
diff --git a/ext/tk/lib/tk/itemfont.rb b/ext/tk/lib/tk/itemfont.rb
new file mode 100644
index 0000000000..4c5c917c57
--- /dev/null
+++ b/ext/tk/lib/tk/itemfont.rb
@@ -0,0 +1,327 @@
+#
+# tk/itemfont.rb : control font of widget items
+#
+require 'tk'
+
+module TkItemFontOptkeys
+ def __item_font_optkeys(id)
+ # maybe need to override
+ ['font']
+ end
+ private :__item_font_optkeys
+end
+
+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_confinfo_cmd(tagid(tagOrId))))
+ elsif optkeys.size == 1
+ pathname = [win, tag, optkeys[0]].join(';')
+ TkFont.used_on(pathname) ||
+ TkFont.init_widget_font(pathname,
+ *(__item_confinfo_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_confinfo_cmd(tagid(tagOrId))))
+ }
+ fonts
+ end
+ end
+ alias tagfontobj tagfont_configinfo
+
+ def tagfont_configure(tagOrId, slot)
+ pathname = __item_pathname(tagid(tagOrId))
+
+ slot = _symbolkey2str(slot)
+
+ __item_font_optkeys(tagid(tagOrId)).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],
+ *(__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
+ fnt = hash_kv(fnt) if fnt.kind_of?(Hash)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt))
+ else
+ begin
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt))
+ rescue => e
+ # ignore
+ end
+ end
+ 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],
+ *(__item_config_cmd(tagid(tagOrId)) << {}))
+ elsif lfnt
+ latintagfont_configure([lfnt, optkey])
+ elsif kfnt
+ kanjitagfont_configure([kfnt, optkey])
+ end
+ }
+
+ # 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)
+ if ltn.kind_of?(Array)
+ key = ltn[1]
+ ltn = ltn[0]
+ else
+ key = nil
+ 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
+ ltn = hash_kv(ltn) if ltn.kind_of?(Hash)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn))
+ else
+ begin
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn))
+ rescue => e
+ # ignore
+ end
+ end
+ 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], *(__item_config_cmd(tagid(tagOrId)) << {}))
+ }
+ self
+ end
+ alias asciitagfont_configure latintagfont_configure
+
+ def kanjitagfont_configure(tagOrId, knj, keys=nil)
+ if knj.kind_of?(Array)
+ key = knj[1]
+ knj = knj[0]
+ else
+ key = nil
+ 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
+ knj = hash_kv(knj) if knj.kind_of?(Hash)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj))
+ else
+ begin
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj))
+ rescue => e
+ # ignore
+ end
+ end
+ 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, win, wintag=nil, winkey=nil, targetkey=nil)
+ if wintag
+ if winkey
+ fnt = win.tagfontobj(wintag, winkey).dup
+ else
+ fnt = win.tagfontobj(wintag).dup
+ end
+ else
+ if winkey
+ fnt = win.fontobj(winkey).dup
+ else
+ fnt = win.fontobj.dup
+ end
+ end
+
+ if targetkey
+ fnt.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey],
+ *(__item_config_cmd(tagid(tagOrId)) << {}))
+ else
+ fnt.call_font_configure(__item_pathname(tagid(tagOrId)),
+ *(__item_config_cmd(tagid(tagOrId)) << {}))
+ end
+ self
+ end
+
+
+ def latintagfont_copy(tagOrId, win, 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
+ fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)),
+ *(__item_config_cmd(tagid(tagOrId)) << {}))
+ end
+
+ if wintag
+ if winkey
+ fontobj.latin_replace(win.tagfontobj(wintag, winkey).latin_font_id)
+ else
+ fontobj.latin_replace(win.tagfontobj(wintag).latin_font_id)
+ end
+ else
+ if winkey
+ fontobj.latin_replace(win.fontobj(winkey).latin_font_id)
+ else
+ fontobj.latin_replace(win.fontobj.latin_font_id)
+ end
+ end
+ self
+ end
+ alias asciitagfont_copy latintagfont_copy
+
+ def kanjifont_copy(tagOrId, win, 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
+ fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)),
+ *(__item_config_cmd(tagid(tagOrId)) << {}))
+ end
+
+ if wintag
+ if winkey
+ fontobj.kanji_replace(win.tagfontobj(wintag, winkey).kanji_font_id)
+ else
+ fontobj.kanji_replace(win.tagfontobj(wintag).kanji_font_id)
+ end
+ else
+ if winkey
+ fontobj.kanji_replace(win.fontobj(winkey).kanji_font_id)
+ else
+ fontobj.kanji_replace(win.fontobj.kanji_font_id)
+ end
+ end
+ self
+ end
+end
diff --git a/ext/tk/lib/tk/kinput.rb b/ext/tk/lib/tk/kinput.rb
new file mode 100644
index 0000000000..a29dbcdb72
--- /dev/null
+++ b/ext/tk/lib/tk/kinput.rb
@@ -0,0 +1,71 @@
+#
+# tk/kinput.rb : control kinput
+#
+require 'tk'
+
+module TkKinput
+ include Tk
+ extend Tk
+
+ TkCommandNames = [
+ 'kinput_start'.freeze,
+ 'kinput_send_spot'.freeze,
+ 'kanjiInput'.freeze
+ ].freeze
+
+ def TkKinput.start(win, style=None)
+ tk_call('kinput_start', win, style)
+ end
+ def kinput_start(style=None)
+ TkKinput.start(self, style)
+ end
+
+ def TkKinput.send_spot(win)
+ tk_call('kinput_send_spot', win)
+ end
+ def kinput_send_spot
+ TkKinput.send_spot(self)
+ end
+
+ def TkKinput.input_start(win, keys=nil)
+ tk_call('kanjiInput', 'start', win, *hash_kv(keys))
+ end
+ def kanji_input_start(keys=nil)
+ TkKinput.input_start(self, keys)
+ end
+
+ def TkKinput.attribute_config(win, slot, value=None)
+ if slot.kind_of? Hash
+ tk_call('kanjiInput', 'attribute', win, *hash_kv(slot))
+ else
+ tk_call('kanjiInput', 'attribute', win, "-#{slot}", value)
+ end
+ end
+ def kinput_attribute_config(slot, value=None)
+ TkKinput.attribute_config(self, slot, value)
+ end
+
+ def TkKinput.attribute_info(win, slot=nil)
+ if slot
+ conf = tk_split_list(tk_call('kanjiInput', 'attribute',
+ win, "-#{slot}"))
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_call('kanjiInput', 'attribute', win)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+ def kinput_attribute_info(slot=nil)
+ TkKinput.attribute_info(self, slot)
+ end
+
+ def TkKinput.input_end(win)
+ tk_call('kanjiInput', 'end', win)
+ end
+ def kanji_input_end
+ TkKinput.input_end(self)
+ end
+end
diff --git a/ext/tk/lib/tk/label.rb b/ext/tk/lib/tk/label.rb
new file mode 100644
index 0000000000..80b3d778f1
--- /dev/null
+++ b/ext/tk/lib/tk/label.rb
@@ -0,0 +1,21 @@
+#
+# tk/label.rb : treat label widget
+#
+require 'tk'
+
+class Tk::Label<TkWindow
+ TkCommandNames = ['label'.freeze].freeze
+ WidgetClassName = 'Label'.freeze
+ WidgetClassNames[WidgetClassName] = self
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('label', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('label', @path)
+ # end
+ #end
+ #private :create_self
+end
+
+#TkLabel = Tk::Label unless Object.const_defined? :TkLabel
+Tk.__set_toplevel_aliases__(:Tk, Tk::Label, :TkLabel)
diff --git a/ext/tk/lib/tk/labelframe.rb b/ext/tk/lib/tk/labelframe.rb
new file mode 100644
index 0000000000..995b5b7e72
--- /dev/null
+++ b/ext/tk/lib/tk/labelframe.rb
@@ -0,0 +1,29 @@
+#
+# tk/labelframe.rb : treat labelframe widget
+#
+require 'tk'
+require 'tk/frame'
+
+class Tk::LabelFrame<Tk::Frame
+ TkCommandNames = ['labelframe'.freeze].freeze
+ WidgetClassName = 'Labelframe'.freeze
+ WidgetClassNames[WidgetClassName] = self
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('labelframe', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('labelframe', @path)
+ # end
+ #end
+ #private :create_self
+
+ def __val2ruby_optkeys # { key=>proc, ... }
+ super().update('labelwidget'=>proc{|v| window(v)})
+ end
+ private :__val2ruby_optkeys
+end
+
+Tk::Labelframe = Tk::LabelFrame
+#TkLabelFrame = Tk::LabelFrame unless Object.const_defined? :TkLabelFrame
+#TkLabelframe = Tk::Labelframe unless Object.const_defined? :TkLabelframe
+Tk.__set_toplevel_aliases__(:Tk, Tk::LabelFrame, :TkLabelFrame, :TkLabelframe)
diff --git a/ext/tk/lib/tk/listbox.rb b/ext/tk/lib/tk/listbox.rb
new file mode 100644
index 0000000000..bb039ffb0e
--- /dev/null
+++ b/ext/tk/lib/tk/listbox.rb
@@ -0,0 +1,282 @@
+#
+# tk/listbox.rb : treat listbox widget
+#
+require 'tk'
+require 'tk/itemconfig'
+require 'tk/scrollable'
+require 'tk/txtwin_abst'
+
+module TkListItemConfig
+ include TkItemConfigMethod
+
+ def __item_listval_optkeys(id)
+ []
+ end
+ private :__item_listval_optkeys
+end
+
+class Tk::Listbox<TkTextWin
+ include TkListItemConfig
+ include Scrollable
+
+ TkCommandNames = ['listbox'.freeze].freeze
+ WidgetClassName = 'Listbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('listbox', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('listbox', @path)
+ # end
+ #end
+ #private :create_self
+
+ def __tkvariable_optkeys
+ super() << 'listvariable'
+ end
+ private :__tkvariable_optkeys
+
+ def tagid(id)
+ #id.to_s
+ _get_eval_string(id)
+ end
+
+ def activate(y)
+ tk_send_without_enc('activate', y)
+ self
+ end
+ def curselection
+ list(tk_send_without_enc('curselection'))
+ end
+ def get(first, last=nil)
+ if last
+ # tk_split_simplelist(_fromUTF8(tk_send_without_enc('get', first, last)))
+ tk_split_simplelist(tk_send_without_enc('get', first, last), false, true)
+ else
+ _fromUTF8(tk_send_without_enc('get', first))
+ end
+ end
+ def nearest(y)
+ tk_send_without_enc('nearest', y).to_i
+ end
+ def size
+ tk_send_without_enc('size').to_i
+ end
+ def selection_anchor(index)
+ tk_send_without_enc('selection', 'anchor', index)
+ self
+ end
+ def selection_clear(first, last=None)
+ tk_send_without_enc('selection', 'clear', first, last)
+ self
+ end
+ def selection_includes(index)
+ bool(tk_send_without_enc('selection', 'includes', index))
+ end
+ def selection_set(first, last=None)
+ tk_send_without_enc('selection', 'set', first, last)
+ self
+ end
+
+ def index(idx)
+ tk_send_without_enc('index', idx).to_i
+ end
+
+ def value
+ get('0', 'end')
+ end
+
+ def value= (vals)
+ unless vals.kind_of?(Array)
+ fail ArgumentError, 'an Array is expected'
+ end
+ tk_send_without_enc('delete', '0', 'end')
+ tk_send_without_enc('insert', '0',
+ *(vals.collect{|v| _get_eval_enc_str(v)}))
+ vals
+ end
+
+ def clear
+ tk_send_without_enc('delete', '0', 'end')
+ self
+ end
+ alias erase clear
+
+=begin
+ def itemcget(index, key)
+ case key.to_s
+ when 'text', 'label', 'show'
+ _fromUTF8(tk_send_without_enc('itemcget', index, "-#{key}"))
+ when 'font', 'kanjifont'
+ #fnt = tk_tcl2ruby(tk_send('itemcget', index, "-#{key}"))
+ fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', index,
+ '-font')))
+ unless fnt.kind_of?(TkFont)
+ fnt = tagfontobj(index, fnt)
+ end
+ if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
+ # obsolete; just for compatibility
+ fnt.kanji_font
+ else
+ fnt
+ end
+ else
+ tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', index, "-#{key}")))
+ end
+ end
+ def itemconfigure(index, key, val=None)
+ if key.kind_of? Hash
+ if (key['font'] || key[:font] ||
+ key['kanjifont'] || key[:kanjifont] ||
+ key['latinfont'] || key[:latinfont] ||
+ key['asciifont'] || key[:asciifont] )
+ tagfont_configure(index, _symbolkey2str(key))
+ else
+ tk_send_without_enc('itemconfigure', index, *hash_kv(key, true))
+ end
+
+ else
+ if (key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont )
+ if val == None
+ tagfontobj(index)
+ else
+ tagfont_configure(index, {key=>val})
+ end
+ else
+ tk_call('itemconfigure', index, "-#{key}", val)
+ end
+ end
+ self
+ end
+
+ def itemconfiginfo(index, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ case key.to_s
+ when 'text', 'label', 'show'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
+ when 'font', 'kanjifont'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
+ conf[4] = tagfont_configinfo(index, conf[4])
+ else
+ conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
+ end
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', index))).collect{|conflist|
+ conf = tk_split_simplelist(conflist)
+ conf[0] = conf[0][1..-1]
+ case conf[0]
+ when 'text', 'label', 'show'
+ 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] = tagfont_configinfo(index, fontconf[4])
+ ret.push(fontconf)
+ else
+ ret
+ end
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ case key.to_s
+ when 'text', 'label', 'show'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
+ when 'font', 'kanjifont'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
+ conf[4] = tagfont_configinfo(index, conf[4])
+ else
+ conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
+ end
+ key = conf.shift[1..-1]
+ { key => conf }
+ else
+ ret = {}
+ tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', index))).each{|conflist|
+ conf = tk_split_simplelist(conflist)
+ key = conf.shift[1..-1]
+ case key
+ when 'text', 'label', 'show'
+ 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] = tagfont_configinfo(index, fontconf[3])
+ ret['font'] = fontconf
+ end
+ ret
+ end
+ end
+ end
+
+ def current_itemconfiginfo(index, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ conf = itemconfiginfo(index, key)
+ {conf[0] => conf[4]}
+ else
+ ret = {}
+ itemconfiginfo(index).each{|conf|
+ ret[conf[0]] = conf[4] if conf.size > 2
+ }
+ ret
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ itemconfiginfo(index, key).each{|k, conf|
+ ret[k] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+=end
+end
+
+#TkListbox = Tk::Listbox unless Object.const_defined? :TkListbox
+Tk.__set_toplevel_aliases__(:Tk, Tk::Listbox, :TkListbox)
diff --git a/ext/tk/lib/tk/macpkg.rb b/ext/tk/lib/tk/macpkg.rb
new file mode 100644
index 0000000000..67b0a4bb60
--- /dev/null
+++ b/ext/tk/lib/tk/macpkg.rb
@@ -0,0 +1,78 @@
+#
+# tk/macpkg.rb : methods for Tcl/Tk packages for Macintosh
+# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+# ATTENTION !!
+# This is NOT TESTED. Because I have no test-environment.
+#
+#
+require 'tk'
+
+module Tk
+ def Tk.load_tclscript_rsrc(resource_name, file=None)
+ # Mac only
+ tk_call('source', '-rsrc', resource_name, file)
+ end
+
+ def Tk.load_tclscript_rsrcid(resource_id, file=None)
+ # Mac only
+ tk_call('source', '-rsrcid', resource_id, file)
+ end
+end
+
+module Tk::MacResource
+end
+#TkMacResource = Tk::MacResource
+Tk.__set_toplevel_aliases__(:Tk, Tk::MacResource, :TkMacResource)
+
+module Tk::MacResource
+ extend Tk
+ extend Tk::MacResource
+
+ TkCommandNames = ['resource'.freeze].freeze
+
+ PACKAGE_NAME = 'resource'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ tk_call_without_enc('package', 'require', 'resource')
+
+ def close(rsrcRef)
+ tk_call('resource', 'close', rsrcRef)
+ end
+
+ def delete(rsrcType, opts=nil)
+ tk_call('resource', 'delete', *(hash_kv(opts) << rsrcType))
+ end
+
+ def files(rsrcRef=nil)
+ if rsrcRef
+ tk_call('resource', 'files', rsrcRef)
+ else
+ tk_split_simplelist(tk_call('resource', 'files'))
+ end
+ end
+
+ def list(rsrcType, rsrcRef=nil)
+ tk_split_simplelist(tk_call('resource', 'list', rsrcType, rsrcRef))
+ end
+
+ def open(fname, access=nil)
+ tk_call('resource', 'open', fname, access)
+ end
+
+ def read(rsrcType, rsrcID, rsrcRef=nil)
+ tk_call('resource', 'read', rsrcType, rsrcID, rsrcRef)
+ end
+
+ def types(rsrcRef=nil)
+ tk_split_simplelist(tk_call('resource', 'types', rsrcRef))
+ end
+
+ def write(rsrcType, data, opts=nil)
+ tk_call('resource', 'write', *(hash_kv(opts) << rsrcType << data))
+ end
+
+ module_function :close, :delete, :files, :list, :open, :read, :types, :write
+end
diff --git a/ext/tk/lib/tk/menu.rb b/ext/tk/lib/tk/menu.rb
new file mode 100644
index 0000000000..3ae0548dd1
--- /dev/null
+++ b/ext/tk/lib/tk/menu.rb
@@ -0,0 +1,681 @@
+#
+# tk/menu.rb : treat menu and menubutton
+#
+require 'tk'
+require 'tk/itemconfig'
+require 'tk/menuspec'
+
+module TkMenuEntryConfig
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'entrycget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'entryconfigure', id]
+ end
+ private :__item_config_cmd
+
+ def __item_strval_optkeys(id)
+ super(id) << 'selectcolor'
+ end
+ private :__item_strval_optkeys
+
+ def __item_listval_optkeys(id)
+ []
+ end
+ private :__item_listval_optkeys
+
+ def __item_val2ruby_optkeys(id) # { key=>proc, ... }
+ super(id).update('menu'=>proc{|i, v| window(v)})
+ end
+ private :__item_val2ruby_optkeys
+
+ alias entrycget itemcget
+ alias entrycget_strict itemcget_strict
+ alias entryconfigure itemconfigure
+ alias entryconfiginfo itemconfiginfo
+ alias current_entryconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+end
+
+class Tk::Menu<TkWindow
+ include Wm
+ include TkMenuEntryConfig
+ extend TkMenuSpec
+
+ TkCommandNames = ['menu'.freeze].freeze
+ WidgetClassName = 'Menu'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('menu', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('menu', @path)
+ # end
+ #end
+ #private :create_self
+
+ def __strval_optkeys
+ super() << 'selectcolor' << 'title'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'tearoff'
+ end
+ private :__boolval_optkeys
+
+ def self.new_menuspec(menu_spec, parent = nil, tearoff = false, keys = nil)
+ if parent.kind_of?(Hash)
+ keys = _symbolkey2str(parent)
+ parent = keys.delete('parent')
+ tearoff = keys.delete('tearoff')
+ elsif tearoff.kind_of?(Hash)
+ keys = _symbolkey2str(tearoff)
+ tearoff = keys.delete('tearoff')
+ elsif keys
+ keys = _symbolkey2str(keys)
+ else
+ keys = {}
+ end
+
+ widgetname = keys.delete('widgetname')
+ _create_menu(parent, menu_spec, widgetname, tearoff, keys)
+ end
+
+ def tagid(id)
+ #id.to_s
+ _get_eval_string(id)
+ end
+
+ def activate(index)
+ tk_send_without_enc('activate', _get_eval_enc_str(index))
+ self
+ end
+ def add(type, keys=nil)
+ tk_send_without_enc('add', type, *hash_kv(keys, true))
+ self
+ end
+ def add_cascade(keys=nil)
+ add('cascade', keys)
+ end
+ def add_checkbutton(keys=nil)
+ add('checkbutton', keys)
+ end
+ def add_command(keys=nil)
+ add('command', keys)
+ end
+ def add_radiobutton(keys=nil)
+ add('radiobutton', keys)
+ end
+ def add_separator(keys=nil)
+ add('separator', keys)
+ end
+
+ def clone_menu(*args)
+ if args[0].kind_of?(TkWindow)
+ parent = args.shift
+ else
+ parent = self
+ end
+
+ if args[0].kind_of?(String) || args[0].kind_of?(Symbol) # menu type
+ type = args.shift
+ else
+ type = None # 'normal'
+ end
+
+ if args[0].kind_of?(Hash)
+ keys = _symbolkey2str(args.shift)
+ else
+ keys = {}
+ end
+
+ parent = keys.delete('parent') if keys.has_key?('parent')
+ type = keys.delete('type') if keys.has_key?('type')
+
+ if keys.empty?
+ Tk::MenuClone.new(self, parent, type)
+ else
+ Tk::MenuClone.new(self, parent, type, keys)
+ end
+ end
+
+ def index(idx)
+ ret = tk_send_without_enc('index', _get_eval_enc_str(idx))
+ (ret == 'none')? nil: number(ret)
+ end
+ def invoke(index)
+ _fromUTF8(tk_send_without_enc('invoke', _get_eval_enc_str(index)))
+ end
+ def insert(index, type, keys=nil)
+ tk_send_without_enc('insert', _get_eval_enc_str(index),
+ type, *hash_kv(keys, true))
+ self
+ end
+ def delete(first, last=nil)
+ if last
+ tk_send_without_enc('delete', _get_eval_enc_str(first),
+ _get_eval_enc_str(last))
+ else
+ tk_send_without_enc('delete', _get_eval_enc_str(first))
+ end
+ self
+ end
+ def popup(x, y, index=nil)
+ if index
+ tk_call_without_enc('tk_popup', path, x, y,
+ _get_eval_enc_str(index))
+ else
+ tk_call_without_enc('tk_popup', path, x, y)
+ end
+ self
+ end
+ def post(x, y)
+ _fromUTF8(tk_send_without_enc('post', x, y))
+ end
+ def postcascade(index)
+ tk_send_without_enc('postcascade', _get_eval_enc_str(index))
+ self
+ end
+ def postcommand(cmd=Proc.new)
+ configure_cmd 'postcommand', cmd
+ self
+ end
+ def set_focus
+ tk_call_without_enc('tk_menuSetFocus', path)
+ self
+ end
+ def tearoffcommand(cmd=Proc.new)
+ configure_cmd 'tearoffcommand', cmd
+ self
+ end
+ def menutype(index)
+ tk_send_without_enc('type', _get_eval_enc_str(index))
+ end
+ def unpost
+ tk_send_without_enc('unpost')
+ self
+ end
+ def xposition(index)
+ number(tk_send_without_enc('xposition', _get_eval_enc_str(index)))
+ end
+ def yposition(index)
+ number(tk_send_without_enc('yposition', _get_eval_enc_str(index)))
+ end
+
+=begin
+ def entrycget(index, key)
+ case key.to_s
+ when 'text', 'label', 'show'
+ _fromUTF8(tk_send_without_enc('entrycget',
+ _get_eval_enc_str(index), "-#{key}"))
+ when 'font', 'kanjifont'
+ #fnt = tk_tcl2ruby(tk_send('entrycget', index, "-#{key}"))
+ fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('entrycget', _get_eval_enc_str(index), '-font')))
+ unless fnt.kind_of?(TkFont)
+ fnt = tagfontobj(index, fnt)
+ end
+ if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
+ # obsolete; just for compatibility
+ fnt.kanji_font
+ else
+ fnt
+ end
+ else
+ tk_tcl2ruby(_fromUTF8(tk_send_without_enc('entrycget', _get_eval_enc_str(index), "-#{key}")))
+ end
+ end
+ def entryconfigure(index, key, val=None)
+ if key.kind_of? Hash
+ if (key['font'] || key[:font] ||
+ key['kanjifont'] || key[:kanjifont] ||
+ key['latinfont'] || key[:latinfont] ||
+ key['asciifont'] || key[:asciifont])
+ tagfont_configure(index, _symbolkey2str(key))
+ else
+ tk_send_without_enc('entryconfigure', _get_eval_enc_str(index),
+ *hash_kv(key, true))
+ end
+
+ else
+ if (key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont )
+ if val == None
+ tagfontobj(index)
+ else
+ tagfont_configure(index, {key=>val})
+ end
+ else
+ tk_call('entryconfigure', index, "-#{key}", val)
+ end
+ end
+ self
+ end
+
+ def entryconfiginfo(index, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ case key.to_s
+ when 'text', 'label', 'show'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
+ when 'font', 'kanjifont'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
+ conf[4] = tagfont_configinfo(index, conf[4])
+ else
+ conf = tk_split_list(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
+ end
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure', _get_eval_enc_str(index)))).collect{|conflist|
+ conf = tk_split_simplelist(conflist)
+ conf[0] = conf[0][1..-1]
+ case conf[0]
+ when 'text', 'label', 'show'
+ 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
+ }
+ if fontconf
+ ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
+ fontconf[4] = tagfont_configinfo(index, fontconf[4])
+ ret.push(fontconf)
+ else
+ ret
+ end
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ case key.to_s
+ when 'text', 'label', 'show'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
+ when 'font', 'kanjifont'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
+ conf[4] = tagfont_configinfo(index, conf[4])
+ else
+ conf = tk_split_list(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
+ end
+ key = conf.shift[1..-1]
+ { key => conf }
+ else
+ ret = {}
+ tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure', _get_eval_enc_str(index)))).each{|conflist|
+ conf = tk_split_simplelist(conflist)
+ key = conf.shift[1..-1]
+ case key
+ when 'text', 'label', 'show'
+ 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] = tagfont_configinfo(index, fontconf[3])
+ ret['font'] = fontconf
+ end
+ ret
+ end
+ end
+ end
+
+ def current_entryconfiginfo(index, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ conf = entryconfiginfo(index, key)
+ {conf[0] => conf[4]}
+ else
+ ret = {}
+ entryconfiginfo(index).each{|conf|
+ ret[conf[0]] = conf[4] if conf.size > 2
+ }
+ ret
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ entryconfiginfo(index, key).each{|k, conf|
+ ret[k] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+=end
+end
+
+#TkMenu = Tk::Menu unless Object.const_defined? :TkMenu
+Tk.__set_toplevel_aliases__(:Tk, Tk::Menu, :TkMenu)
+
+
+class Tk::MenuClone<Tk::Menu
+=begin
+ def initialize(parent, type=None)
+ widgetname = nil
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ parent = keys.delete('parent')
+ widgetname = keys.delete('widgetname')
+ type = keys.delete('type'); type = None unless type
+ end
+ #unless parent.kind_of?(TkMenu)
+ # fail ArgumentError, "parent must be TkMenu"
+ #end
+ @parent = parent
+ install_win(@parent.path, widgetname)
+ tk_call_without_enc(@parent.path, 'clone', @path, type)
+ end
+=end
+ def initialize(src_menu, *args)
+ widgetname = nil
+
+ if args[0].kind_of?(TkWindow) # parent window
+ parent = args.shift
+ else
+ parent = src_menu
+ end
+
+ if args[0].kind_of?(String) || args[0].kind_of?(Symbol) # menu type
+ type = args.shift
+ else
+ type = None # 'normal'
+ end
+
+ if args[0].kind_of?(Hash)
+ keys = _symbolkey2str(args.shift)
+ parent = keys.delete('parent') if keys.has_key?('parent')
+ widgetname = keys.delete('widgetname')
+ type = keys.delete('type') if keys.has_key?('type')
+ else
+ keys = nil
+ end
+
+ @src_menu = src_menu
+ @parent = parent
+ @type = type
+ install_win(@parent.path, widgetname)
+ tk_call_without_enc(@src_menu.path, 'clone', @path, @type)
+ configure(keys) if keys && !keys.empty?
+ end
+
+ def source_menu
+ @src_menu
+ end
+end
+Tk::CloneMenu = Tk::MenuClone
+#TkMenuClone = Tk::MenuClone unless Object.const_defined? :TkMenuClone
+#TkCloneMenu = Tk::CloneMenu unless Object.const_defined? :TkCloneMenu
+Tk.__set_toplevel_aliases__(:Tk, Tk::MenuClone, :TkMenuClone, :TkCloneMenu)
+
+module Tk::SystemMenu
+ def initialize(parent, keys=nil)
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ parent = keys.delete('parent')
+ end
+ #unless parent.kind_of? TkMenu
+ # fail ArgumentError, "parent must be a TkMenu object"
+ #end
+ # @path = Kernel.format("%s.%s", parent.path, self.class::SYSMENU_NAME)
+ @path = parent.path + '.' + self.class::SYSMENU_NAME
+ #TkComm::Tk_WINDOWS[@path] = self
+ TkCore::INTERP.tk_windows[@path] = self
+ if self.method(:create_self).arity == 0
+ p 'create_self has no arg' if $DEBUG
+ create_self
+ configure(keys) if keys
+ else
+ p 'create_self has an arg' if $DEBUG
+ create_self(keys)
+ end
+ end
+end
+TkSystemMenu = Tk::SystemMenu
+
+
+class Tk::SysMenu_Help<Tk::Menu
+ # for all platform
+ include Tk::SystemMenu
+ SYSMENU_NAME = 'help'
+end
+#TkSysMenu_Help = Tk::SysMenu_Help unless Object.const_defined? :TkSysMenu_Help
+Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Help, :TkSysMenu_Help)
+
+
+class Tk::SysMenu_System<Tk::Menu
+ # for Windows
+ include Tk::SystemMenu
+ SYSMENU_NAME = 'system'
+end
+#TkSysMenu_System = Tk::SysMenu_System unless Object.const_defined? :TkSysMenu_System
+Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_System, :TkSysMenu_System)
+
+
+class Tk::SysMenu_Apple<Tk::Menu
+ # for Machintosh
+ include Tk::SystemMenu
+ SYSMENU_NAME = 'apple'
+end
+#TkSysMenu_Apple = Tk::SysMenu_Apple unless Object.const_defined? :TkSysMenu_Apple
+Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Apple, :TkSysMenu_Apple)
+
+
+class Tk::Menubutton<Tk::Label
+ TkCommandNames = ['menubutton'.freeze].freeze
+ WidgetClassName = 'Menubutton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+ def create_self(keys)
+ if keys and keys != None
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true))
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ rescue
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ tk_call_without_enc('destroy', @path) rescue nil
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
+ end
+ end
+ else
+ # tk_call_without_enc('menubutton', @path)
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def __boolval_optkeys
+ super() << 'indicatoron'
+ end
+ private :__boolval_optkeys
+
+end
+Tk::MenuButton = Tk::Menubutton
+#TkMenubutton = Tk::Menubutton unless Object.const_defined? :TkMenubutton
+#TkMenuButton = Tk::MenuButton unless Object.const_defined? :TkMenuButton
+Tk.__set_toplevel_aliases__(:Tk, Tk::Menubutton, :TkMenubutton, :TkMenuButton)
+
+
+class Tk::OptionMenubutton<Tk::Menubutton
+ TkCommandNames = ['tk_optionMenu'.freeze].freeze
+
+ class OptionMenu<TkMenu
+ def initialize(path) #==> return value of tk_optionMenu
+ @path = path
+ #TkComm::Tk_WINDOWS[@path] = self
+ TkCore::INTERP.tk_windows[@path] = self
+ end
+ end
+
+ def initialize(*args)
+ # args :: [parent,] [var,] [value[, ...],] [keys]
+ # parent --> TkWindow or nil
+ # var --> TkVariable or nil
+ # keys --> Hash
+ # keys[:parent] or keys['parent'] --> parent
+ # keys[:variable] or keys['variable'] --> var
+ # keys[:values] or keys['values'] --> value, ...
+ # other Hash keys are menubutton options
+ keys = {}
+ keys = args.pop if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(keys)
+
+ parent = nil
+ if args[0].kind_of?(TkWindow) || args[0] == nil
+ keys.delete('parent') # ignore
+ parent = args.shift
+ else
+ parent = keys.delete('parent')
+ end
+
+ @variable = nil
+ if args[0].kind_of?(TkVariable) || args[0] == nil
+ keys.delete('variable') # ignore
+ @variable = args.shift
+ else
+ @variable = keys.delete('variable')
+ end
+ @variable = TkVariable.new unless @variable
+
+ (args = keys.delete('values') || []) if args.empty?
+ if args.empty?
+ args << @variable.value
+ else
+ @variable.value = args[0]
+ end
+
+ install_win(if parent then parent.path end)
+ @menu = OptionMenu.new(tk_call('tk_optionMenu',
+ @path, @variable.id, *args))
+
+ configure(keys) if keys
+ end
+
+ def value
+ @variable.value
+ end
+
+ def value=(val)
+ @variable.value = val
+ end
+
+ def activate(index)
+ @menu.activate(index)
+ self
+ end
+ def add(value)
+ @menu.add('radiobutton', 'variable'=>@variable,
+ 'label'=>value, 'value'=>value)
+ self
+ end
+ def index(index)
+ @menu.index(index)
+ end
+ def invoke(index)
+ @menu.invoke(index)
+ end
+ def insert(index, value)
+ @menu.insert(index, 'radiobutton', 'variable'=>@variable,
+ 'label'=>value, 'value'=>value)
+ self
+ end
+ def delete(index, last=None)
+ @menu.delete(index, last)
+ self
+ end
+ def xposition(index)
+ @menu.xposition(index)
+ end
+ def yposition(index)
+ @menu.yposition(index)
+ end
+ def menu
+ @menu
+ end
+ def menucget(key)
+ @menu.cget(key)
+ end
+ def menucget_strict(key)
+ @menu.cget_strict(key)
+ end
+ def menuconfigure(key, val=None)
+ @menu.configure(key, val)
+ self
+ end
+ def menuconfiginfo(key=nil)
+ @menu.configinfo(key)
+ end
+ def current_menuconfiginfo(key=nil)
+ @menu.current_configinfo(key)
+ end
+ def entrycget(index, key)
+ @menu.entrycget(index, key)
+ end
+ def entrycget_strict(index, key)
+ @menu.entrycget_strict(index, key)
+ end
+ def entryconfigure(index, key, val=None)
+ @menu.entryconfigure(index, key, val)
+ self
+ end
+ def entryconfiginfo(index, key=nil)
+ @menu.entryconfiginfo(index, key)
+ end
+ def current_entryconfiginfo(index, key=nil)
+ @menu.current_entryconfiginfo(index, key)
+ end
+end
+
+Tk::OptionMenuButton = Tk::OptionMenubutton
+#TkOptionMenubutton = Tk::OptionMenubutton unless Object.const_defined? :TkOptionMenubutton
+#TkOptionMenuButton = Tk::OptionMenuButton unless Object.const_defined? :TkOptionMenuButton
+Tk.__set_toplevel_aliases__(:Tk, Tk::OptionMenubutton,
+ :TkOptionMenubutton, :TkOptionMenuButton)
diff --git a/ext/tk/lib/tk/menubar.rb b/ext/tk/lib/tk/menubar.rb
new file mode 100644
index 0000000000..ef9da809b9
--- /dev/null
+++ b/ext/tk/lib/tk/menubar.rb
@@ -0,0 +1,131 @@
+#
+# tk/menubar.rb
+#
+# Original version:
+# Copyright (C) 1998 maeda shugo. All rights reserved.
+# This file can be distributed under the terms of the Ruby.
+
+# Usage:
+#
+# menu_spec = [
+# [['File', 0],
+# ['Open', proc{puts('Open clicked')}, 0],
+# '---',
+# ['Quit', proc{exit}, 0]],
+# [['Edit', 0],
+# ['Cut', proc{puts('Cut clicked')}, 2],
+# ['Copy', proc{puts('Copy clicked')}, 0],
+# ['Paste', proc{puts('Paste clicked')}, 0]]
+# ]
+# menubar = TkMenubar.new(nil, menu_spec,
+# 'tearoff'=>false,
+# 'foreground'=>'grey40',
+# 'activeforeground'=>'red',
+# 'font'=>'-adobe-helvetica-bold-r-*--12-*-iso8859-1')
+# menubar.pack('side'=>'top', 'fill'=>'x')
+#
+#
+# OR
+#
+#
+# menubar = TkMenubar.new
+# menubar.add_menu([['File', 0],
+# ['Open', proc{puts('Open clicked')}, 0],
+# '---',
+# ['Quit', proc{exit}, 0]])
+# menubar.add_menu([['Edit', 0],
+# ['Cut', proc{puts('Cut clicked')}, 2],
+# ['Copy', proc{puts('Copy clicked')}, 0],
+# ['Paste', proc{puts('Paste clicked')}, 0]])
+# menubar.configure('tearoff', false)
+# menubar.configure('foreground', 'grey40')
+# menubar.configure('activeforeground', 'red')
+# menubar.configure('font', '-adobe-helvetica-bold-r-*--12-*-iso8859-1')
+# menubar.pack('side'=>'top', 'fill'=>'x')
+#
+#
+# OR
+#
+# radio_var = TkVariable.new('y')
+# menu_spec = [
+# [['File', 0],
+# {:label=>'Open', :command=>proc{puts('Open clicked')}, :underline=>0},
+# '---',
+# ['Check_A', TkVariable.new(true), 6],
+# {:type=>'checkbutton', :label=>'Check_B',
+# :variable=>TkVariable.new, :underline=>6},
+# '---',
+# ['Radio_X', [radio_var, 'x'], 6],
+# ['Radio_Y', [radio_var, 'y'], 6],
+# ['Radio_Z', [radio_var, 'z'], 6],
+# '---',
+# ['cascade', [
+# ['sss', proc{p 'sss'}, 0],
+# ['ttt', proc{p 'ttt'}, 0],
+# ['uuu', proc{p 'uuu'}, 0],
+# ['vvv', proc{p 'vvv'}, 0],
+# ], 0],
+# '---',
+# ['Quit', proc{exit}, 0]],
+# [['Edit', 0],
+# ['Cut', proc{puts('Cut clicked')}, 2],
+# ['Copy', proc{puts('Copy clicked')}, 0],
+# ['Paste', proc{puts('Paste clicked')}, 0]]
+# ]
+# menubar = TkMenubar.new(nil, menu_spec,
+# 'tearoff'=>false,
+# 'foreground'=>'grey40',
+# 'activeforeground'=>'red',
+# 'font'=>'Helvetia 12 bold')
+# menubar.pack('side'=>'top', 'fill'=>'x')
+
+# See tk/menuspce.rb about the format of the menu_spec
+
+# To use add_menu, configuration must be done by calling configure after
+# adding all menus by add_menu, not by the constructor arguments.
+
+require 'tk'
+require 'tk/frame'
+require 'tk/composite'
+require 'tk/menuspec'
+
+class TkMenubar<Tk::Frame
+ include TkComposite
+ include TkMenuSpec
+
+ def initialize(parent = nil, spec = nil, options = nil)
+ if parent.kind_of? Hash
+ options = _symbolkey2str(parent)
+ spec = options.delete('spec')
+ super(options)
+ else
+ super(parent, options)
+ end
+
+ @menus = []
+
+ spec.each{|info| add_menu(info)} if spec
+
+ options.each{|key, value| configure(key, value)} if options
+ end
+
+ def add_menu(menu_info)
+ mbtn, menu = _create_menubutton(@frame, menu_info)
+
+ submenus = _get_cascade_menus(menu).flatten
+
+ @menus.push([mbtn, menu])
+ delegate('tearoff', menu, *submenus)
+ delegate('foreground', mbtn, menu, *submenus)
+ delegate('background', mbtn, menu, *submenus)
+ delegate('disabledforeground', mbtn, menu, *submenus)
+ delegate('activeforeground', mbtn, menu, *submenus)
+ delegate('activebackground', mbtn, menu, *submenus)
+ delegate('font', mbtn, menu, *submenus)
+ delegate('kanjifont', mbtn, menu, *submenus)
+ end
+
+ def [](index)
+ return @menus[index]
+ end
+end
diff --git a/ext/tk/lib/tk/menuspec.rb b/ext/tk/lib/tk/menuspec.rb
new file mode 100644
index 0000000000..2a2eb9ba3c
--- /dev/null
+++ b/ext/tk/lib/tk/menuspec.rb
@@ -0,0 +1,275 @@
+#
+# tk/menuspec.rb
+# Hidethoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# based on tkmenubar.rb :
+# Copyright (C) 1998 maeda shugo. All rights reserved.
+# This file can be distributed under the terms of the Ruby.
+#
+# The format of the menu_spec is:
+# [ menu_info, menu_info, ... ]
+#
+# And the format of the menu_info is:
+# [
+# [text, underline, configs], # menu button/entry (*1)
+# [label, command, underline, accelerator, configs], # command entry
+# [label, TkVar_obj, underline, accelerator, configs], # checkbutton entry
+# [label, [TkVar_obj, value],
+# underline, accelerator, configs], # radiobutton entry
+# [label, [[...menu_info...], [...menu_info...], ...],
+# underline, accelerator, configs], # cascade entry (*2)
+# '---', # separator
+# ...
+# ]
+#
+# underline, accelerator, and configs are optional pearameters.
+# Hashes are OK instead of Arrays. Then the entry type ('command',
+# 'checkbutton', 'radiobutton' or 'cascade') is given by 'type' key
+# (e.g. :type=>'cascade'). When type is 'cascade', an array of menu_info
+# is acceptable for 'menu' key (then, create sub-menu).
+#
+# NOTE: (*1)
+# If you want to make special menus (*.help for UNIX, *.system for Win,
+# and *.apple for Mac), append 'menu_name'=>name (name is 'help' for UNIX,
+# 'system' for Win, and 'apple' for Mac) option to the configs hash of
+# menu button/entry information.
+#
+# NOTE: (*2)
+# If you want to configure a cascade menu, add :menu_config=>{...configs..}
+# to the configs of the cascade entry.
+
+module TkMenuSpec
+ def _create_menu(parent, menu_info, menu_name = nil,
+ tearoff = false, default_opts = nil)
+ if tearoff.kind_of?(Hash)
+ default_opts = tearoff
+ tearoff = false
+ end
+
+ if menu_name.kind_of?(Hash)
+ default_opts = menu_name
+ menu_name = nil
+ tearoff = false
+ end
+
+ if default_opts.kind_of?(Hash)
+ orig_opts = _symbolkey2str(default_opts)
+ else
+ orig_opts = {}
+ end
+
+ tearoff = orig_opts.delete('tearoff') if orig_opts.key?('tearoff')
+
+ if menu_name
+ #menu = Tk::Menu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff)
+ # --> use current TkMenu class
+ menu = TkMenu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff)
+ else
+ #menu = Tk::Menu.new(parent, :tearoff=>tearoff)
+ # --> use current TkMenu class
+ menu = TkMenu.new(parent, :tearoff=>tearoff)
+ end
+
+ for item_info in menu_info
+ if item_info.kind_of?(Hash)
+ options = orig_opts.dup
+ options.update(_symbolkey2str(item_info))
+ item_type = (options.delete('type') || 'command').to_s
+ menu_name = options.delete('menu_name')
+ menu_opts = orig_opts.dup
+ menu_opts.update(_symbolkey2str(options.delete('menu_config') || {}))
+ if item_type == 'cascade' && options['menu'].kind_of?(Array)
+ # create cascade menu
+ submenu = _create_menu(menu, options['menu'], menu_name,
+ tearoff, menu_opts)
+ options['menu'] = submenu
+ end
+ menu.add(item_type, options)
+
+ elsif item_info.kind_of?(Array)
+ options = orig_opts.dup
+
+ options['label'] = item_info[0] if item_info[0]
+
+ case item_info[1]
+ when TkVariable
+ # checkbutton
+ item_type = 'checkbutton'
+ options['variable'] = item_info[1]
+ options['onvalue'] = true
+ options['offvalue'] = false
+
+ when Array
+ # radiobutton or cascade
+ if item_info[1][0].kind_of?(TkVariable)
+ # radiobutton
+ item_type = 'radiobutton'
+ options['variable'] = item_info[1][0]
+ options['value'] = item_info[1][1] if item_info[1][1]
+
+ else
+ # cascade
+ item_type = 'cascade'
+ menu_opts = orig_opts.dup
+ if item_info[4] && item_info[4].kind_of?(Hash)
+ opts = _symbolkey2str(item_info[4])
+ menu_name = opts.delete('menu_name')
+ menu_config = opts.delete('menu_config') || {}
+ menu_opts.update(_symbolkey2str(menu_config))
+ end
+ submenu = _create_menu(menu, item_info[1], menu_name,
+ tearoff, menu_opts)
+ options['menu'] = submenu
+ end
+
+ else
+ # command
+ item_type = 'command'
+ options['command'] = item_info[1] if item_info[1]
+ end
+
+ options['underline'] = item_info[2] if item_info[2]
+ options['accelerator'] = item_info[3] if item_info[3]
+ if item_info[4] && item_info[4].kind_of?(Hash)
+ opts = _symbolkey2str(item_info[4])
+ if item_type == 'cascade'
+ opts.delete('menu_name')
+ opts.delete('menu_config')
+ end
+ options.update(opts)
+ end
+ menu.add(item_type, options)
+
+ elsif /^-+$/ =~ item_info
+ menu.add('separator')
+
+ else
+ menu.add('command', 'label' => item_info)
+ end
+ end
+
+ menu
+ end
+ private :_create_menu
+
+ def _use_menubar?(parent)
+ use_menubar = false
+ if parent.kind_of?(Tk::Root) || parent.kind_of?(Tk::Toplevel)
+ true
+ elsif parent.current_configinfo.has_key?('menu')
+ true
+ else
+ false
+ end
+ end
+ private :_use_menubar?
+
+ def _create_menu_for_menubar(parent)
+ #unless (mbar = parent.menu).kind_of?(TkMenu)
+ # --> use current TkMenu class
+ mbar = parent.menu
+ unless mbar.kind_of?(Tk::Menu) || mbar.kind_of?(TkMenu)
+ #mbar = Tk::Menu.new(parent, :tearoff=>false)
+ mbar = TkMenu.new(parent, :tearoff=>false)
+ parent.menu(mbar)
+ end
+ mbar
+ end
+ private :_create_menu_for_menubar
+
+ def _create_menubutton(parent, menu_info, tearoff=false, default_opts = nil)
+ btn_info = menu_info[0]
+
+ if tearoff.kind_of?(Hash)
+ default_opts = tearoff
+ tearoff = false
+ end
+
+ if default_opts.kind_of?(Hash)
+ keys = _symbolkey2str(default_opts)
+ else
+ keys = {}
+ end
+
+ tearoff = keys.delete('tearoff') if keys.key?('tearoff')
+
+ if _use_menubar?(parent)
+ # menubar by menu entries
+ mbar = _create_menu_for_menubar(parent)
+
+ menu_name = nil
+
+ if btn_info.kind_of?(Hash)
+ keys.update(_symbolkey2str(btn_info))
+ menu_name = keys.delete('menu_name')
+ keys['label'] = keys.delete('text') if keys.key?('text')
+ elsif btn_info.kind_of?(Array)
+ keys['label'] = btn_info[0] if btn_info[0]
+ keys['underline'] = btn_info[1] if btn_info[1]
+ if btn_info[2]&&btn_info[2].kind_of?(Hash)
+ keys.update(_symbolkey2str(btn_info[2]))
+ menu_name = keys.delete('menu_name')
+ end
+ else
+ keys = {:label=>btn_info}
+ end
+
+ menu = _create_menu(mbar, menu_info[1..-1], menu_name,
+ tearoff, default_opts)
+ menu.tearoff(tearoff)
+
+ keys['menu'] = menu
+ mbar.add('cascade', keys)
+
+ [mbar, menu]
+
+ else
+ # menubar by menubuttons
+ #mbtn = Tk::Menubutton.new(parent)
+ # --> use current TkMenubutton class
+ mbtn = TkMenubutton.new(parent)
+
+ menu_name = nil
+
+ if btn_info.kind_of?(Hash)
+ keys.update(_symbolkey2str(btn_info))
+ menu_name = keys.delete('menu_name')
+ keys['text'] = keys.delete('label') if keys.key?('label')
+ mbtn.configure(keys)
+ elsif btn_info.kind_of?(Array)
+ mbtn.configure('text', btn_info[0]) if btn_info[0]
+ mbtn.configure('underline', btn_info[1]) if btn_info[1]
+ # mbtn.configure('accelerator', btn_info[2]) if btn_info[2]
+ if btn_info[2]&&btn_info[2].kind_of?(Hash)
+ keys.update(_symbolkey2str(btn_info[2]))
+ menu_name = keys.delete('menu_name')
+ mbtn.configure(keys)
+ end
+ else
+ mbtn.configure('text', btn_info)
+ end
+
+ mbtn.pack('side' => 'left')
+
+ menu = _create_menu(mbtn, menu_info[1..-1], menu_name,
+ tearoff, default_opts)
+
+ mbtn.menu(menu)
+
+ [mbtn, menu]
+ end
+ end
+ private :_create_menubutton
+
+ def _get_cascade_menus(menu)
+ menus = []
+ (0..(menu.index('last'))).each{|idx|
+ if menu.menutype(idx) == 'cascade'
+ submenu = menu.entrycget(idx, 'menu')
+ menus << [submenu, _get_cascade_menus(submenu)]
+ end
+ }
+ menus
+ end
+ private :_get_cascade_menus
+end
diff --git a/ext/tk/lib/tk/message.rb b/ext/tk/lib/tk/message.rb
new file mode 100644
index 0000000000..946b68c704
--- /dev/null
+++ b/ext/tk/lib/tk/message.rb
@@ -0,0 +1,22 @@
+#
+# tk/message.rb : treat message widget
+#
+require 'tk'
+require 'tk/label'
+
+class Tk::Message<Tk::Label
+ TkCommandNames = ['message'.freeze].freeze
+ WidgetClassName = 'Message'.freeze
+ WidgetClassNames[WidgetClassName] = self
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('message', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('message', @path)
+ # end
+ #end
+ private :create_self
+end
+
+#TkMessage = Tk::Message unless Object.const_defined? :TkMessage
+Tk.__set_toplevel_aliases__(:Tk, Tk::Message, :TkMessage)
diff --git a/ext/tk/lib/tk/mngfocus.rb b/ext/tk/lib/tk/mngfocus.rb
new file mode 100644
index 0000000000..1a2049c8a8
--- /dev/null
+++ b/ext/tk/lib/tk/mngfocus.rb
@@ -0,0 +1,33 @@
+#
+# tk/mngfocus.rb : methods for Tcl/Tk standard library 'focus.tcl'
+# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+module TkManageFocus
+ extend Tk
+
+ TkCommandNames = [
+ 'tk_focusFollowMouse'.freeze,
+ 'tk_focusNext'.freeze,
+ 'tk_focusPrev'.freeze
+ ].freeze
+
+ def TkManageFocus.followsMouse
+ tk_call_without_enc('tk_focusFollowsMouse')
+ end
+
+ def TkManageFocus.next(win)
+ tk_tcl2ruby(tk_call('tk_focusNext', win))
+ end
+ def focusNext
+ TkManageFocus.next(self)
+ end
+
+ def TkManageFocus.prev(win)
+ tk_tcl2ruby(tk_call('tk_focusPrev', win))
+ end
+ def focusPrev
+ TkManageFocus.prev(self)
+ end
+end
diff --git a/ext/tk/lib/tk/msgcat.rb b/ext/tk/lib/tk/msgcat.rb
new file mode 100644
index 0000000000..162953f425
--- /dev/null
+++ b/ext/tk/lib/tk/msgcat.rb
@@ -0,0 +1,296 @@
+#
+# tk/msgcat.rb : methods for Tcl message catalog
+# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+#class TkMsgCatalog
+class TkMsgCatalog < TkObject
+ include TkCore
+ extend Tk
+ #extend TkMsgCatalog
+
+ TkCommandNames = [
+ '::msgcat::mc'.freeze,
+ '::msgcat::mcmax'.freeze,
+ '::msgcat::mclocale'.freeze,
+ '::msgcat::mcpreferences'.freeze,
+ '::msgcat::mcload'.freeze,
+ '::msgcat::mcset'.freeze,
+ '::msgcat::mcmset'.freeze,
+ '::msgcat::mcunknown'.freeze
+ ].freeze
+
+ tk_call_without_enc('package', 'require', 'Tcl', '8.2')
+
+ PACKAGE_NAME = 'msgcat'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ if self.const_defined? :FORCE_VERSION
+ tk_call_without_enc('package', 'require', 'msgcat', FORCE_VERSION)
+ else
+ tk_call_without_enc('package', 'require', 'msgcat')
+ end
+
+ MSGCAT_EXT = '.msg'
+
+ UNKNOWN_CBTBL = Hash.new{|hash,key| hash[key] = {}}.taint
+
+ TkCore::INTERP.add_tk_procs('::msgcat::mcunknown', 'args', <<-'EOL')
+ if {[set st [catch {eval {ruby_cmd TkMsgCatalog callback} [namespace current] $args} ret]] != 0} {
+ #return -code $st $ret
+ set idx [string first "\n\n" $ret]
+ if {$idx > 0} {
+ return -code $st \
+ -errorinfo [string range $ret [expr $idx + 2] \
+ [string length $ret]] \
+ [string range $ret 0 [expr $idx - 1]]
+ } else {
+ return -code $st $ret
+ }
+ } else {
+ return $ret
+ }
+ EOL
+
+ def self.callback(namespace, locale, src_str, *args)
+ src_str = sprintf(src_str, *args) unless args.empty?
+ cmd_tbl = TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip]
+ cmd = cmd_tbl[namespace]
+ cmd = cmd_tbl['::'] unless cmd # use global scope as interp default
+ return src_str unless cmd # no cmd -> return src-str (default action)
+ begin
+ cmd.call(locale, src_str)
+ rescue SystemExit
+ exit(0)
+ rescue Interrupt
+ exit!(1)
+ rescue Exception => e
+ begin
+ msg = _toUTF8(e.class.inspect) + ': ' +
+ _toUTF8(e.message) + "\n" +
+ "\n---< backtrace of Ruby side >-----\n" +
+ _toUTF8(e.backtrace.join("\n")) +
+ "\n---< backtrace of Tk side >-------"
+ if TkCore::WITH_ENCODING
+ msg.force_encoding('utf-8')
+ else
+ msg.instance_variable_set(:@encoding, 'utf-8')
+ end
+ rescue Exception
+ msg = e.class.inspect + ': ' + e.message + "\n" +
+ "\n---< backtrace of Ruby side >-----\n" +
+ e.backtrace.join("\n") +
+ "\n---< backtrace of Tk side >-------"
+ end
+ fail(e, msg)
+ end
+ end
+
+ def initialize(namespace = nil)
+ if namespace.kind_of?(TkNamespace)
+ @namespace = namespace
+ elsif namespace == nil
+ @namespace = TkNamespace.new('::') # global namespace
+ else
+ @namespace = TkNamespace.new(namespace)
+ end
+ @path = @namespace.path
+
+ @msgcat_ext = '.msg'
+ end
+ attr_accessor :msgcat_ext
+
+ def method_missing(id, *args)
+ # locale(src, trans) ==> set_translation(locale, src, trans)
+ loc = id.id2name
+ case args.length
+ when 0 # set locale
+ self.locale=(loc)
+
+ when 1 # src only, or trans_list
+ if args[0].kind_of?(Array)
+ # trans_list
+ #list = args[0].collect{|src, trans|
+ # [ Tk::UTF8_String.new(src), Tk::UTF8_String.new(trans) ]
+ #}
+ self.set_translation_list(loc, args[0])
+ else
+ # src
+ #self.set_translation(loc, Tk::UTF8_String.new(args[0]))
+ self.set_translation(loc, args[0])
+ end
+
+ when 2 # src and trans, or, trans_list and enc
+ if args[0].kind_of?(Array)
+ else
+ #self.set_translation(loc, args[0], Tk::UTF8_String.new(args[1]))
+ self.set_translation(loc, *args)
+ end
+
+ when 3 # src and trans and enc
+ self.set_translation(loc, *args)
+
+ else
+ super(id, *args)
+# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
+
+ end
+ end
+
+ # *args ::= form, arg, arg, ...
+ def self.translate(*args)
+ dst = args.collect{|src|
+ tk_call_without_enc('::msgcat::mc', _get_eval_string(src, true))
+ }
+ Tk.UTF8_String(sprintf(*dst))
+ end
+ class << self
+ alias mc translate
+ alias [] translate
+ end
+ def translate(*args)
+ dst = args.collect{|src|
+ @namespace.eval{tk_call_without_enc('::msgcat::mc',
+ _get_eval_string(src, true))}
+ }
+ Tk.UTF8_String(sprintf(*dst))
+ end
+ alias mc translate
+ alias [] translate
+
+ def self.maxlen(*src_strings)
+ tk_call('::msgcat::mcmax', *src_strings).to_i
+ end
+ def maxlen(*src_strings)
+ @namespace.eval{tk_call('::msgcat::mcmax', *src_strings).to_i}
+ end
+
+ def self.locale
+ tk_call('::msgcat::mclocale')
+ end
+ def locale
+ @namespace.eval{tk_call('::msgcat::mclocale')}
+ end
+
+ def self.locale=(locale)
+ tk_call('::msgcat::mclocale', locale)
+ end
+ def locale=(locale)
+ @namespace.eval{tk_call('::msgcat::mclocale', locale)}
+ end
+
+ def self.preferences
+ tk_split_simplelist(tk_call('::msgcat::mcpreferences'))
+ end
+ def preferences
+ tk_split_simplelist(@namespace.eval{tk_call('::msgcat::mcpreferences')})
+ end
+
+ def self.load_tk(dir)
+ number(tk_call('::msgcat::mcload', dir))
+ end
+
+ def self.load_rb(dir)
+ count = 0
+ preferences().each{|loc|
+ file = File.join(dir, loc + self::MSGCAT_EXT)
+ if File.readable?(file)
+ count += 1
+ eval(open(file){|f| f.read})
+ end
+ }
+ count
+ end
+
+ def load_tk(dir)
+ number(@namespace.eval{tk_call('::msgcat::mcload', dir)})
+ end
+
+ def load_rb(dir)
+ count = 0
+ preferences().each{|loc|
+ file = File.join(dir, loc + @msgcat_ext)
+ if File.readable?(file)
+ count += 1
+ @namespace.eval(open(file){|f| f.read})
+ end
+ }
+ count
+ end
+
+ def self.load(dir)
+ self.load_rb(dir)
+ end
+ alias load load_rb
+
+ def self.set_translation(locale, src_str, trans_str=None, enc='utf-8')
+ if trans_str && trans_str != None
+ trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc))
+ Tk.UTF8_String(tk_call_without_enc('::msgcat::mcset',
+ locale,
+ _get_eval_string(src_str, true),
+ trans_str))
+ else
+ Tk.UTF8_String(tk_call_without_enc('::msgcat::mcset',
+ locale,
+ _get_eval_string(src_str, true)))
+ end
+ end
+ def set_translation(locale, src_str, trans_str=None, enc='utf-8')
+ if trans_str && trans_str != None
+ trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc))
+ Tk.UTF8_String(@namespace.eval{
+ tk_call_without_enc('::msgcat::mcset',
+ locale,
+ _get_eval_string(src_str, true),
+ trans_str)
+ })
+ else
+ Tk.UTF8_String(@namespace.eval{
+ tk_call_without_enc('::msgcat::mcset',
+ locale,
+ _get_eval_string(src_str, true))})
+ end
+ end
+
+ def self.set_translation_list(locale, trans_list, enc='utf-8')
+ # trans_list ::= [ [src, trans], [src, trans], ... ]
+ list = []
+ trans_list.each{|src, trans|
+ if trans && trans != None
+ list << _get_eval_string(src, true)
+ list << Tk.UTF8_Stirng(_toUTF8(trans, enc))
+ else
+ list << _get_eval_string(src, true) << ''
+ end
+ }
+ number(tk_call_without_enc('::msgcat::mcmset', locale, list))
+ end
+ def set_translation_list(locale, trans_list, enc='utf-8')
+ # trans_list ::= [ [src, trans], [src, trans], ... ]
+ list = []
+ trans_list.each{|src, trans|
+ if trans && trans != None
+ list << _get_eval_string(src, true)
+ list << Tk.UTF8_String(_toUTF8(trans, enc))
+ else
+ list << _get_eval_string(src, true) << ''
+ end
+ }
+ number(@namespace.eval{
+ tk_call_without_enc('::msgcat::mcmset', locale, list)
+ })
+ end
+
+ def self.def_unknown_proc(cmd=Proc.new)
+ TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip]['::'] = cmd
+ end
+ def def_unknown_proc(cmd=Proc.new)
+ TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip][@namespace.path] = cmd
+ end
+end
+
+TkMsgCat = TkMsgCatalog
diff --git a/ext/tk/lib/tk/namespace.rb b/ext/tk/lib/tk/namespace.rb
new file mode 100644
index 0000000000..20a8d65215
--- /dev/null
+++ b/ext/tk/lib/tk/namespace.rb
@@ -0,0 +1,551 @@
+#
+# tk/namespace.rb : methods to manipulate Tcl/Tk namespace
+# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+class TkNamespace < TkObject
+ extend Tk
+
+ TkCommandNames = [
+ 'namespace'.freeze,
+ ].freeze
+
+ Tk_Namespace_ID_TBL = TkCore::INTERP.create_table
+
+ (Tk_Namespace_ID = ["ns".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ Tk_NsCode_RetObjID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ Tk_Namespace_ID_TBL.mutex.synchronize{ Tk_Namespace_ID_TBL.clear }
+ Tk_NsCode_RetObjID_TBL.mutex.synchronize{ Tk_NsCode_RetObjID_TBL.clear }
+ }
+
+ def TkNamespace.id2obj(id)
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
+ }
+ end
+
+ #####################################
+
+ class Ensemble < TkObject
+ def __cget_cmd
+ ['namespace', 'ensemble', 'configure', self.path]
+ end
+ private :__cget_cmd
+
+ def __config_cmd
+ ['namespace', 'ensemble', 'configure', self.path]
+ end
+ private :__config_cmd
+
+ def __configinfo_struct
+ {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil,
+ :default_value=>nil, :current_value=>2}
+ end
+ private :__configinfo_struct
+
+ def __boolval_optkeys
+ ['prefixes']
+ end
+ private :__boolval_optkeys
+
+ def __listval_optkeys
+ ['map', 'subcommands', 'unknown']
+ end
+ private :__listval_optkeys
+
+ def self.exist?(ensemble)
+ bool(tk_call('namespace', 'ensemble', 'exists', ensemble))
+ end
+
+ def initialize(keys = {})
+ @ensemble = @path = tk_call('namespace', 'ensemble', 'create', keys)
+ end
+
+ def cget(slot)
+ if slot == :namespace || slot == 'namespace'
+ ns = super(slot)
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
+ TkNamespace::Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
+ else
+ super(slot)
+ end
+ end
+ def cget_strict(slot)
+ if slot == :namespace || slot == 'namespace'
+ ns = super(slot)
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
+ TkNamespace::Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
+ else
+ super(slot)
+ end
+ end
+
+ def configinfo(slot = nil)
+ if slot
+ if slot == :namespace || slot == 'namespace'
+ val = super(slot)
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
+ val = TkNamespace::Tk_Namespace_ID_TBL[val]
+ end
+ }
+ else
+ val = super(slot)
+ end
+
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ [slot.to_s, val]
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ {slot.to_s => val}
+ end
+
+ else
+ info = super()
+
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ info.map!{|inf|
+ if inf[0] == 'namespace' &&
+ TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1])
+ [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]]
+ else
+ inf
+ end
+ }
+ }
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ val = info['namespace']
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
+ info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val]
+ end
+ }
+ end
+
+ info
+ end
+ end
+
+ def exists?
+ bool(tk_call('namespace', 'ensemble', 'exists', @path))
+ end
+ end
+
+ #####################################
+
+ class ScopeArgs < Array
+ include Tk
+
+ # alias __tk_call tk_call
+ # alias __tk_call_without_enc tk_call_without_enc
+ # alias __tk_call_with_enc tk_call_with_enc
+ def tk_call(*args)
+ #super('namespace', 'eval', @namespace, *args)
+ args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
+ super('namespace', 'eval', @namespace,
+ TkCore::INTERP._merge_tklist(*args))
+ end
+ def tk_call_without_enc(*args)
+ #super('namespace', 'eval', @namespace, *args)
+ args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
+ super('namespace', 'eval', @namespace,
+ TkCore::INTERP._merge_tklist(*args))
+ end
+ def tk_call_with_enc(*args)
+ #super('namespace', 'eval', @namespace, *args)
+ args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
+ super('namespace', 'eval', @namespace,
+ TkCore::INTERP._merge_tklist(*args))
+ end
+
+ def initialize(namespace, *args)
+ @namespace = namespace
+ super(args.size)
+ self.replace(args)
+ end
+ end
+
+ #####################################
+
+ class NsCode < TkObject
+ def initialize(scope, use_obj_id = false)
+ @scope = scope + ' '
+ @use_obj_id = use_obj_id
+ end
+ def path
+ @scope
+ end
+ def to_eval
+ @scope
+ end
+ def call(*args)
+ ret = TkCore::INTERP._eval_without_enc(@scope + array2tk_list(args))
+ if @use_obj_id
+ ret = TkNamespace::Tk_NsCode_RetObjID_TBL.delete(ret.to_i)
+ end
+ ret
+ end
+ end
+
+ #####################################
+
+ def install_cmd(cmd)
+ lst = tk_split_simplelist(super(cmd), false, false)
+ if lst[1] =~ /^::/
+ lst[1] = @fullname
+ else
+ lst.insert(1, @fullname)
+ end
+ TkCore::INTERP._merge_tklist(*lst)
+ end
+
+ alias __tk_call tk_call
+ alias __tk_call_without_enc tk_call_without_enc
+ alias __tk_call_with_enc tk_call_with_enc
+ def tk_call(*args)
+ #super('namespace', 'eval', @fullname, *args)
+ args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
+ super('namespace', 'eval', @fullname,
+ TkCore::INTERP._merge_tklist(*args))
+ end
+ def tk_call_without_enc(*args)
+ #super('namespace', 'eval', @fullname, *args)
+ args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
+ super('namespace', 'eval', @fullname,
+ TkCore::INTERP._merge_tklist(*args))
+ end
+ def tk_call_with_enc(*args)
+ #super('namespace', 'eval', @fullname, *args)
+ args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
+ super('namespace', 'eval', @fullname,
+ TkCore::INTERP._merge_tklist(*args))
+ end
+ alias ns_tk_call tk_call
+ alias ns_tk_call_without_enc tk_call_without_enc
+ alias ns_tk_call_with_enc tk_call_with_enc
+
+ def initialize(name = nil, parent = nil)
+ unless name
+ Tk_Namespace_ID.mutex.synchronize{
+ # name = Tk_Namespace_ID.join('')
+ name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Namespace_ID[1].succ!
+ }
+ end
+ name = __tk_call('namespace', 'current') if name == ''
+ if parent
+ if parent =~ /^::/
+ if name =~ /^::/
+ @fullname = parent + name
+ else
+ @fullname = parent +'::'+ name
+ end
+ else
+ ancestor = __tk_call('namespace', 'current')
+ ancestor = '' if ancestor == '::'
+ if name =~ /^::/
+ @fullname = ancestor + '::' + parent + name
+ else
+ @fullname = ancestor + '::'+ parent +'::'+ name
+ end
+ end
+ else # parent == nil
+ ancestor = __tk_call('namespace', 'current')
+ ancestor = '' if ancestor == '::'
+ if name =~ /^::/
+ @fullname = name
+ else
+ @fullname = ancestor + '::' + name
+ end
+ end
+ @path = @fullname
+ @parent = __tk_call('namespace', 'qualifiers', @fullname)
+ @name = __tk_call('namespace', 'tail', @fullname)
+
+ # create namespace
+ __tk_call('namespace', 'eval', @fullname, '')
+
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ Tk_Namespace_ID_TBL[@fullname] = self
+ }
+ end
+
+ def self.children(*args)
+ # args ::= [<namespace>] [<pattern>]
+ # <pattern> must be glob-style pattern
+ tk_split_simplelist(tk_call('namespace', 'children', *args)).collect{|ns|
+ # ns is fullname
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if Tk_Namespace_ID_TBL.key?(ns)
+ Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
+ }
+ end
+ def children(pattern=None)
+ TkNamespace.children(@fullname, pattern)
+ end
+
+ def self.code(script = Proc.new)
+ TkNamespace.new('').code(script)
+ end
+=begin
+ def code(script = Proc.new)
+ if script.kind_of?(String)
+ cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(script)}
+ elsif script.kind_of?(Proc)
+ cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(&script)}
+ else
+ fail ArgumentError, "String or Proc is expected"
+ end
+ TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code',
+ _get_eval_string(cmd, false)))
+ end
+=end
+ def code(script = Proc.new)
+ if script.kind_of?(String)
+ cmd = proc{|*args|
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ obj = ScopeArgs.new(@fullname,*args)
+ ret = obj.instance_exec(obj, script)
+ else
+ ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
+ end
+ id = ret.object_id
+ TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
+ id
+ }
+ elsif script.kind_of?(Proc)
+ cmd = proc{|*args|
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ obj = ScopeArgs.new(@fullname,*args)
+ ret = obj.instance_exec(obj, &script)
+ else
+ ret = ScopeArgs.new(@fullname,*args).instance_eval(&script)
+ end
+ id = ret.object_id
+ TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
+ id
+ }
+ else
+ fail ArgumentError, "String or Proc is expected"
+ end
+ TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code',
+ _get_eval_string(cmd, false)),
+ true)
+ end
+
+ def self.current_path
+ tk_call('namespace', 'current')
+ end
+ def current_path
+ @fullname
+ end
+
+ def self.current
+ ns = self.current_path
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if Tk_Namespace_ID_TBL.key?(ns)
+ Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
+ end
+ def current_namespace
+ # ns_tk_call('namespace', 'current')
+ # @fullname
+ self
+ end
+ alias current current_namespace
+
+ def self.delete(*ns_list)
+ tk_call('namespace', 'delete', *ns_list)
+ ns_list.each{|ns|
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if ns.kind_of?(TkNamespace)
+ Tk_Namespace_ID_TBL.delete(ns.path)
+ else
+ Tk_Namespace_ID_TBL.delete(ns.to_s)
+ end
+ }
+ }
+ end
+ def delete
+ TkNamespece.delete(@fullname)
+ end
+
+ def self.ensemble_create(*keys)
+ tk_call('namespace', 'ensemble', 'create', *hash_kv(keys))
+ end
+ def self.ensemble_configure(cmd, slot, value=None)
+ if slot.kind_of?(Hash)
+ tk_call('namespace', 'ensemble', 'configure', cmd, *hash_kv(slot))
+ else
+ tk_call('namespace', 'ensemble', 'configure', cmd, '-'+slot.to_s, value)
+ end
+ end
+ def self.ensemble_configinfo(cmd, slot = nil)
+ if slot
+ tk_call('namespace', 'ensemble', 'configure', cmd, '-' + slot.to_s)
+ else
+ inf = {}
+ Hash(*tk_split_simplelist(tk_call('namespace', 'ensemble', 'configure', cmd))).each{|k, v| inf[k[1..-1]] = v}
+ inf
+ end
+ end
+ def self.ensemble_exist?(cmd)
+ bool(tk_call('namespace', 'ensemble', 'exists', cmd))
+ end
+
+ def self.eval(namespace, cmd = Proc.new, *args)
+ #tk_call('namespace', 'eval', namespace, cmd, *args)
+ TkNamespace.new(namespace).eval(cmd, *args)
+ end
+=begin
+ def eval(cmd = Proc.new, *args)
+ #TkNamespace.eval(@fullname, cmd, *args)
+ #ns_tk_call(cmd, *args)
+ code_obj = code(cmd)
+ ret = code_obj.call(*args)
+ # uninstall_cmd(TkCore::INTERP._split_tklist(code_obj.path)[-1])
+ uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1]))
+ tk_tcl2ruby(ret)
+ end
+=end
+ def eval(cmd = Proc.new, *args)
+ code_obj = code(cmd)
+ ret = code_obj.call(*args)
+ uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1]))
+ ret
+ end
+
+ def self.exist?(ns)
+ bool(tk_call('namespace', 'exists', ns))
+ end
+ def exist?
+ TkNamespece.exist?(@fullname)
+ end
+
+ def self.export(*patterns)
+ tk_call('namespace', 'export', *patterns)
+ end
+ def self.export_with_clear(*patterns)
+ tk_call('namespace', 'export', '-clear', *patterns)
+ end
+ def export
+ TkNamespace.export(@fullname)
+ end
+ def export_with_clear
+ TkNamespace.export_with_clear(@fullname)
+ end
+
+ def self.forget(*patterns)
+ tk_call('namespace', 'forget', *patterns)
+ end
+ def forget
+ TkNamespace.forget(@fullname)
+ end
+
+ def self.import(*patterns)
+ tk_call('namespace', 'import', *patterns)
+ end
+ def self.force_import(*patterns)
+ tk_call('namespace', 'import', '-force', *patterns)
+ end
+ def import
+ TkNamespace.import(@fullname)
+ end
+ def force_import
+ TkNamespace.force_import(@fullname)
+ end
+
+ def self.inscope(namespace, script, *args)
+ tk_call('namespace', 'inscope', namespace, script, *args)
+ end
+ def inscope(script, *args)
+ TkNamespace.inscope(@fullname, script, *args)
+ end
+
+ def self.origin(cmd)
+ tk_call('namespace', 'origin', cmd)
+ end
+
+ def self.parent(namespace=None)
+ ns = tk_call('namespace', 'parent', namespace)
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if Tk_Namespace_ID_TBL.key?(ns)
+ Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
+ end
+ def parent
+ tk_call('namespace', 'parent', @fullname)
+ end
+
+ def self.get_path
+ tk_call('namespace', 'path')
+ end
+ def self.set_path(*namespace_list)
+ tk_call('namespace', 'path', array2tk_list(namespace_list))
+ end
+ def set_path
+ tk_call('namespace', 'path', @fullname)
+ end
+
+ def self.qualifiers(str)
+ tk_call('namespace', 'qualifiers', str)
+ end
+
+ def self.tail(str)
+ tk_call('namespace', 'tail', str)
+ end
+
+ def self.upvar(namespace, *var_pairs)
+ tk_call('namespace', 'upvar', namespace, *(var_pairs.flatten))
+ end
+ def upvar(*var_pairs)
+ TkNamespace.inscope(@fullname, *(var_pairs.flatten))
+ end
+
+ def self.get_unknown_handler
+ tk_tcl2ruby(tk_call('namespace', 'unknown'))
+ end
+ def self.set_unknown_handler(cmd = Proc.new)
+ tk_call('namespace', 'unknown', cmd)
+ end
+
+ def self.which(name)
+ tk_call('namespace', 'which', name)
+ end
+ def self.which_command(name)
+ tk_call('namespace', 'which', '-command', name)
+ end
+ def self.which_variable(name)
+ tk_call('namespace', 'which', '-variable', name)
+ end
+end
+
+TkNamespace::Global = TkNamespace.new('::')
diff --git a/ext/tk/lib/tk/optiondb.rb b/ext/tk/lib/tk/optiondb.rb
new file mode 100644
index 0000000000..186811d37d
--- /dev/null
+++ b/ext/tk/lib/tk/optiondb.rb
@@ -0,0 +1,377 @@
+#
+# tk/optiondb.rb : treat option database
+#
+require 'tk'
+
+module TkOptionDB
+ include Tk
+ extend Tk
+
+ TkCommandNames = ['option'.freeze].freeze
+ (CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ module Priority
+ WidgetDefault = 20
+ StartupFile = 40
+ UserDefault = 60
+ Interactive = 80
+ end
+
+ def add(pat, value, pri=None)
+ # if $SAFE >= 4
+ # fail SecurityError, "can't call 'TkOptionDB.add' at $SAFE >= 4"
+ # end
+ tk_call('option', 'add', pat, value, pri)
+ end
+ def clear
+ # if $SAFE >= 4
+ # fail SecurityError, "can't call 'TkOptionDB.crear' at $SAFE >= 4"
+ # end
+ tk_call_without_enc('option', 'clear')
+ end
+ def get(win, name, klass)
+ tk_call('option', 'get', win ,name, klass)
+ end
+ def readfile(file, pri=None)
+ tk_call('option', 'readfile', file, pri)
+ end
+ alias read_file readfile
+ module_function :add, :clear, :get, :readfile, :read_file
+
+ def read_entries(file, f_enc=nil)
+ if TkCore::INTERP.safe?
+ fail SecurityError,
+ "can't call 'TkOptionDB.read_entries' on a safe interpreter"
+ end
+
+ i_enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system)
+
+ unless f_enc
+ f_enc = i_enc
+ end
+
+ ent = []
+ cline = ''
+ open(file, 'r') {|f|
+ while line = f.gets
+ #cline += line.chomp!
+ cline.concat(line.chomp!)
+ case cline
+ when /\\$/ # continue
+ cline.chop!
+ next
+ when /^\s*(!|#)/ # coment
+ cline = ''
+ next
+ when /^([^:]+):(.*)$/
+ pat = $1.strip
+ val = $2.lstrip
+ p "ResourceDB: #{[pat, val].inspect}" if $DEBUG
+ pat = TkCore::INTERP._toUTF8(pat, f_enc)
+ pat = TkCore::INTERP._fromUTF8(pat, i_enc)
+ val = TkCore::INTERP._toUTF8(val, f_enc)
+ val = TkCore::INTERP._fromUTF8(val, i_enc)
+ ent << [pat, val]
+ cline = ''
+ else # unknown --> ignore
+ cline = ''
+ next
+ end
+ end
+ }
+ ent
+ end
+ module_function :read_entries
+
+ def read_with_encoding(file, f_enc=nil, pri=None)
+ # try to read the file as an OptionDB file
+ read_entries(file, f_enc).each{|pat, val|
+ add(pat, val, pri)
+ }
+
+=begin
+ i_enc = Tk.encoding()
+
+ unless f_enc
+ f_enc = i_enc
+ end
+
+ cline = ''
+ open(file, 'r') {|f|
+ while line = f.gets
+ cline += line.chomp!
+ case cline
+ when /\\$/ # continue
+ cline.chop!
+ next
+ when /^\s*!/ # coment
+ cline = ''
+ next
+ when /^([^:]+):\s(.*)$/
+ pat = $1
+ val = $2
+ p "ResourceDB: #{[pat, val].inspect}" if $DEBUG
+ pat = TkCore::INTERP._toUTF8(pat, f_enc)
+ pat = TkCore::INTERP._fromUTF8(pat, i_enc)
+ val = TkCore::INTERP._toUTF8(val, f_enc)
+ val = TkCore::INTERP._fromUTF8(val, i_enc)
+ add(pat, val, pri)
+ cline = ''
+ else # unknown --> ignore
+ cline = ''
+ next
+ end
+ end
+ }
+=end
+ end
+ module_function :read_with_encoding
+
+ # support procs on the resource database
+ @@resource_proc_class = Class.new
+
+ @@resource_proc_class.const_set(:CARRIER, '.'.freeze)
+
+ @@resource_proc_class.instance_variable_set('@method_tbl',
+ TkCore::INTERP.create_table)
+ @@resource_proc_class.instance_variable_set('@add_method', false)
+ @@resource_proc_class.instance_variable_set('@safe_mode', 4)
+
+ class << @@resource_proc_class
+ private :new
+
+=begin
+ CARRIER = '.'.freeze
+ METHOD_TBL = TkCore::INTERP.create_table
+ ADD_METHOD = false
+ SAFE_MODE = 4
+=end
+
+=begin
+ def __closed_block_check__(str)
+ depth = 0
+ str.scan(/[{}]/){|x|
+ if x == "{"
+ depth += 1
+ elsif x == "}"
+ depth -= 1
+ end
+ if depth <= 0 && !($' =~ /\A\s*\Z/)
+ fail RuntimeError, "bad string for procedure : #{str.inspect}"
+ end
+ }
+ str
+ end
+ private :__closed_block_check__
+=end
+
+ def __check_proc_string__(str)
+ # If you want to check the proc_string, do it in this method.
+ # Please define this in the block given to 'new_proc_class' method.
+ str
+ end
+
+ def method_missing(id, *args)
+ #res_proc, proc_str = self::METHOD_TBL[id]
+ res_proc, proc_str = @method_tbl[id]
+
+ proc_source = TkOptionDB.get(self::CARRIER, id.id2name, '').strip
+ res_proc = nil if proc_str != proc_source # resource is changed
+
+ # unless res_proc.kind_of?(Proc)
+ unless TkComm._callback_entry?(res_proc)
+ #if id == :new || !(self::METHOD_TBL.has_key?(id) || self::ADD_METHOD)
+ if id == :new || !(@method_tbl.has_key?(id) || @add_method)
+ raise NoMethodError,
+ "not support resource-proc '#{id.id2name}' for #{self.name}"
+ end
+ proc_str = proc_source
+ proc_str = '{' + proc_str + '}' unless /\A\{.*\}\Z/ =~ proc_str
+ #proc_str = __closed_block_check__(proc_str)
+ proc_str = __check_proc_string__(proc_str)
+ res_proc = proc{
+ begin
+ #eval("$SAFE = #{self::SAFE_MODE};\nProc.new" + proc_str)
+ eval("$SAFE = #{@safe_mode};\nProc.new" + proc_str)
+ rescue SyntaxError=>err
+ raise SyntaxError,
+ TkCore::INTERP._toUTF8(err.message.gsub(/\(eval\):\d:/,
+ "(#{id.id2name}):"))
+ end
+ }.call
+ #self::METHOD_TBL[id] = [res_proc, proc_source]
+ @method_tbl[id] = [res_proc, proc_source]
+ end
+ res_proc.call(*args)
+ end
+
+ private :__check_proc_string__, :method_missing
+ end
+ @@resource_proc_class.freeze
+
+=begin
+ def __create_new_class(klass, func, safe = 4, add = false, parent = nil)
+ klass = klass.to_s if klass.kind_of? Symbol
+ unless (?A..?Z) === klass[0]
+ fail ArgumentError, "bad string '#{klass}' for class name"
+ end
+ unless func.kind_of? Array
+ fail ArgumentError, "method-list must be Array"
+ end
+ func_str = func.join(' ')
+ if parent == nil
+ install_win(parent)
+ elsif parent <= @@resource_proc_class
+ install_win(parent::CARRIER)
+ else
+ fail ArgumentError, "parent must be Resource-Proc class"
+ end
+ carrier = Tk.tk_call_without_enc('frame', @path, '-class', klass)
+
+ body = <<-"EOD"
+ class #{klass} < TkOptionDB.module_eval('@@resource_proc_class')
+ CARRIER = '#{carrier}'.freeze
+ METHOD_TBL = TkCore::INTERP.create_table
+ ADD_METHOD = #{add}
+ SAFE_MODE = #{safe}
+ %w(#{func_str}).each{|f| METHOD_TBL[f.intern] = nil }
+ end
+ EOD
+
+ if parent.kind_of?(Class) && parent <= @@resource_proc_class
+ parent.class_eval(body)
+ eval(parent.name + '::' + klass)
+ else
+ eval(body)
+ eval('TkOptionDB::' + klass)
+ end
+ end
+=end
+ def __create_new_class(klass, func, safe = 4, add = false, parent = nil)
+ if klass.kind_of?(TkWindow)
+ carrier = klass.path
+ CmdClassID.mutex.synchronize{
+ klass = CmdClassID.join(TkCore::INTERP._ip_id_)
+ CmdClassID[1].succ!
+ }
+ parent = nil # ignore parent
+ else
+ klass = klass.to_s if klass.kind_of?(Symbol)
+ unless (?A..?Z) === klass[0]
+ fail ArgumentError, "bad string '#{klass}' for class name"
+ end
+ if parent == nil
+ install_win(nil)
+ elsif parent.kind_of?(TkWindow)
+ install_win(parent.path)
+ elsif parent <= @@resource_proc_class
+ install_win(parent::CARRIER)
+ else
+ fail ArgumentError, "parent must be Resource-Proc class"
+ end
+ carrier = Tk.tk_call_without_enc('frame', @path, '-class', klass)
+ end
+
+ unless func.kind_of?(Array)
+ fail ArgumentError, "method-list must be Array"
+ end
+ func_str = func.join(' ')
+
+ if parent.kind_of?(Class) && parent <= @@resource_proc_class
+ cmd_klass = Class.new(parent)
+ else
+ cmd_klass = Class.new(TkOptionDB.module_eval('@@resource_proc_class'))
+ end
+ cmd_klass.const_set(:CARRIER, carrier.dup.freeze)
+
+ cmd_klass.instance_variable_set('@method_tbl', TkCore::INTERP.create_table)
+ cmd_klass.instance_variable_set('@add_method', add)
+ cmd_klass.instance_variable_set('@safe_mode', safe)
+ func.each{|f|
+ cmd_klass.instance_variable_get('@method_tbl')[f.to_s.intern] = nil
+ }
+=begin
+ cmd_klass.const_set(:METHOD_TBL, TkCore::INTERP.create_table)
+ cmd_klass.const_set(:ADD_METHOD, add)
+ cmd_klass.const_set(:SAFE_MODE, safe)
+ func.each{|f| cmd_klass::METHOD_TBL[f.to_s.intern] = nil }
+=end
+
+ cmd_klass
+ end
+ module_function :__create_new_class
+ private_class_method :__create_new_class
+
+ def __remove_methods_of_proc_class(klass)
+ # for security, make these methods invalid
+ class << klass
+ def __null_method(*args); nil; end
+ [ :class_eval, :name, :superclass, :clone, :dup, :autoload, :autoload?,
+ :ancestors, :const_defined?, :const_get, :const_set, :const_missing,
+ :class_variables, :constants, :included_modules, :instance_methods,
+ :method_defined?, :module_eval, :private_instance_methods,
+ :protected_instance_methods, :public_instance_methods,
+ :singleton_methods, :remove_const, :remove_method, :undef_method,
+ :to_s, :inspect, :display, :method, :methods, :respond_to?,
+ :instance_variable_get, :instance_variable_set, :instance_method,
+ :instance_eval, :instance_exec, :instance_variables, :kind_of?, :is_a?,
+ :private_methods, :protected_methods, :public_methods ].each{|m|
+ alias_method(m, :__null_method)
+ }
+ end
+ end
+ module_function :__remove_methods_of_proc_class
+ private_class_method :__remove_methods_of_proc_class
+
+ RAND_BASE_CNT = [0]
+ RAND_BASE_HEAD = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ RAND_BASE_CHAR = RAND_BASE_HEAD + 'abcdefghijklmnopqrstuvwxyz0123456789_'
+ def __get_random_basename
+ name = '%s%03d' % [RAND_BASE_HEAD[rand(RAND_BASE_HEAD.size),1],
+ RAND_BASE_CNT[0]]
+ len = RAND_BASE_CHAR.size
+ (6+rand(10)).times{
+ name << RAND_BASE_CHAR[rand(len),1]
+ }
+ RAND_BASE_CNT[0] = RAND_BASE_CNT[0] + 1
+ name
+ end
+ module_function :__get_random_basename
+ private_class_method :__get_random_basename
+
+ # define new proc class :
+ # If you want to modify the new class or create a new subclass,
+ # you must do such operation in the block parameter.
+ # Because the created class is flozen after evaluating the block.
+ def new_proc_class(klass, func, safe = 4, add = false, parent = nil, &b)
+ new_klass = __create_new_class(klass, func, safe, add, parent)
+ new_klass.class_eval(&b) if block_given?
+ __remove_methods_of_proc_class(new_klass)
+ new_klass.freeze
+ new_klass
+ end
+ module_function :new_proc_class
+
+ def eval_under_random_base(parent = nil, &b)
+ new_klass = __create_new_class(__get_random_basename(),
+ [], 4, false, parent)
+ ret = new_klass.class_eval(&b) if block_given?
+ __remove_methods_of_proc_class(new_klass)
+ new_klass.freeze
+ ret
+ end
+ module_function :eval_under_random_base
+
+ def new_proc_class_random(klass, func, safe = 4, add = false, &b)
+ eval_under_random_base(){
+ TkOptionDB.new_proc_class(klass, func, safe, add, self, &b)
+ }
+ end
+ module_function :new_proc_class_random
+end
+TkOption = TkOptionDB
+TkResourceDB = TkOptionDB
diff --git a/ext/tk/lib/tk/optionobj.rb b/ext/tk/lib/tk/optionobj.rb
new file mode 100644
index 0000000000..8fe7e0ee5a
--- /dev/null
+++ b/ext/tk/lib/tk/optionobj.rb
@@ -0,0 +1,212 @@
+#
+# tk/optionobj.rb : control options for a group of widgets
+#
+# NOTE: If you want to use key-only option (no value),
+# use Tk::None for the value of the key-only option.
+#
+# e.g. hash_kv({'aaa'=>1, '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/pack.rb b/ext/tk/lib/tk/pack.rb
new file mode 100644
index 0000000000..220a38e524
--- /dev/null
+++ b/ext/tk/lib/tk/pack.rb
@@ -0,0 +1,107 @@
+#
+# tk/pack.rb : control pack geometry manager
+#
+require 'tk'
+
+module TkPack
+ include Tk
+ extend Tk
+
+ TkCommandNames = ['pack'.freeze].freeze
+
+=begin
+ def configure(win, *args)
+ if args[-1].kind_of?(Hash)
+ opts = args.pop
+ else
+ opts = {}
+ end
+ params = []
+ # params.push((win.kind_of?(TkObject))? win.epath: win)
+ params.push(_epath(win))
+ args.each{|win|
+ # params.push((win.kind_of?(TkObject))? win.epath: win)
+ params.push(_epath(win))
+ }
+ opts.each{|k, v|
+ params.push("-#{k}")
+ # params.push((v.kind_of?(TkObject))? v.epath: v)
+ params.push(_epath(v))
+ }
+ tk_call_without_enc("pack", 'configure', *params)
+ end
+=end
+ def configure(*args)
+ if args[-1].kind_of?(Hash)
+ opts = args.pop
+ else
+ opts = {}
+ end
+ fail ArgumentError, 'no widget is given' if args.empty?
+ params = []
+ args.flatten(1).each{|win| params.push(_epath(win))}
+ opts.each{|k, v|
+ params.push("-#{k}")
+ params.push(_epath(v)) # have to use 'epath' (hash_kv() is unavailable)
+ }
+ tk_call_without_enc("pack", 'configure', *params)
+ end
+ alias pack configure
+
+ def forget(*args)
+ return '' if args.size == 0
+ wins = args.collect{|win|
+ # (win.kind_of?(TkObject))? win.epath: win
+ _epath(win)
+ }
+ tk_call_without_enc('pack', 'forget', *wins)
+ end
+
+ def info(slave)
+ # slave = slave.epath if slave.kind_of?(TkObject)
+ slave = _epath(slave)
+ ilist = list(tk_call_without_enc('pack', 'info', slave))
+ info = {}
+ while key = ilist.shift
+ info[key[1..-1]] = ilist.shift
+ end
+ return info
+ end
+
+ def propagate(master, mode=None)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ if mode == None
+ bool(tk_call_without_enc('pack', 'propagate', master))
+ else
+ tk_call_without_enc('pack', 'propagate', master, mode)
+ end
+ end
+
+ def slaves(master)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ list(tk_call_without_enc('pack', 'slaves', master))
+ end
+
+ module_function :pack, :configure, :forget, :info, :propagate, :slaves
+end
+=begin
+def TkPack(win, *args)
+ if args[-1].kind_of?(Hash)
+ opts = args.pop
+ else
+ opts = {}
+ end
+ params = []
+ params.push((win.kind_of?(TkObject))? win.epath: win)
+ args.each{|win|
+ params.push((win.kind_of?(TkObject))? win.epath: win)
+ }
+ opts.each{|k, v|
+ params.push("-#{k}")
+ params.push((v.kind_of?(TkObject))? v.epath: v)
+ }
+ tk_call_without_enc("pack", *params)
+end
+=end
diff --git a/ext/tk/lib/tk/package.rb b/ext/tk/lib/tk/package.rb
new file mode 100644
index 0000000000..0c329732f5
--- /dev/null
+++ b/ext/tk/lib/tk/package.rb
@@ -0,0 +1,143 @@
+#
+# tk/package.rb : package command
+#
+require 'tk'
+
+module TkPackage
+ include TkCore
+ extend TkPackage
+
+ TkCommandNames = ['package'.freeze].freeze
+
+ def add_path(path)
+ Tk::AUTO_PATH.value = Tk::AUTO_PATH.to_a << path
+ end
+
+ def forget(package)
+ tk_call('package', 'forget', package)
+ 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
+
+ def provide(package, version=nil)
+ if version
+ tk_call('package', 'provide', package, version)
+ end
+ if (ret = tk_call('package', 'provide', package)) == ''
+ nil
+ else
+ ret
+ end
+ end
+
+ def present(package, version=None)
+ begin
+ tk_call('package', 'present', package, version)
+ rescue => e
+ fail e.class, 'TkPackage ' << e.message
+ end
+ end
+
+ def 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)
+ begin
+ tk_call('package', 'require', package, version)
+ rescue => e
+ fail e.class, 'TkPackage ' << e.message
+ end
+ end
+
+ def 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)
+ tk_split_simplelist(tk_call('package', 'versions', package))
+ end
+
+ def vcompare(version1, version2)
+ number(tk_call('package', 'vcompare', version1, version2))
+ end
+
+ def vsatisfies(version1, version2)
+ bool(tk_call('package', 'vsatisfies', version1, version2))
+ end
+
+ def prefer(setting = None)
+ tk_call('package', 'prefer', setting)
+ end
+end
diff --git a/ext/tk/lib/tk/palette.rb b/ext/tk/lib/tk/palette.rb
new file mode 100644
index 0000000000..2d08d50f6a
--- /dev/null
+++ b/ext/tk/lib/tk/palette.rb
@@ -0,0 +1,55 @@
+#
+# tk/palette.rb : methods for Tcl/Tk standard library 'palette.tcl'
+# 1998/06/21 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+module TkPalette
+ include Tk
+ extend Tk
+
+ TkCommandNames = [
+ 'tk_setPalette'.freeze,
+ 'tk_bisque'.freeze,
+ 'tkDarken'.freeze
+ ].freeze
+
+ def TkPalette.set(*args)
+ args = args[0].to_a.flatten if args[0].kind_of? Hash
+ tk_call('tk_setPalette', *args)
+ end
+ def TkPalette.setPalette(*args)
+ TkPalette.set(*args)
+ end
+
+ def TkPalette.bisque
+ tk_call('tk_bisque')
+ end
+
+ def TkPalette.darken(color, percent)
+ tk_call('tkDarken', color, percent)
+ end
+
+ def TkPalette.recolorTree(win, colors)
+ if not colors.kind_of?(Hash)
+ fail "2nd arg need to be Hash"
+ end
+
+ tk_call('global', "tkPalette")
+ colors.each{|key, value|
+ begin
+ if win.cget(key) == tk_call('set', "tkPalette(#{key})")
+ win[key] = colors[key]
+ end
+ rescue
+ # ignore
+ end
+ }
+
+ TkWinfo.children(win).each{|w| TkPalette.recolorTree(w, colors)}
+ end
+
+ def recolorTree(colors)
+ TkPalette.recolorTree(self, colors)
+ end
+end
diff --git a/ext/tk/lib/tk/panedwindow.rb b/ext/tk/lib/tk/panedwindow.rb
new file mode 100644
index 0000000000..030144e677
--- /dev/null
+++ b/ext/tk/lib/tk/panedwindow.rb
@@ -0,0 +1,258 @@
+#
+# tk/panedwindow.rb : treat panedwindow
+#
+require 'tk'
+
+class Tk::PanedWindow<TkWindow
+ TkCommandNames = ['panedwindow'.freeze].freeze
+ WidgetClassName = 'Panedwindow'.freeze
+ WidgetClassNames[WidgetClassName] = self
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('panedwindow', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('panedwindow', @path)
+ # end
+ #end
+ #private :create_self
+
+ def add(*args)
+ keys = args.pop
+ fail ArgumentError, "no window in arguments" unless keys
+ if keys && keys.kind_of?(Hash)
+ fail ArgumentError, "no window in arguments" if args == []
+ # args = args.collect{|w| (w.kind_of?(TkObject))? w.epath: w }
+ args = args.collect{|w| _epath(w) }
+ #args.push(hash_kv(keys))
+ args.concat(hash_kv(keys))
+ else
+ args.push(keys) if keys
+ # args = args.collect{|w| (w.kind_of?(TkObject))? w.epath: w }
+ args = args.collect{|w| _epath(w) }
+ end
+ tk_send_without_enc('add', *args)
+ self
+ end
+
+ def forget(win, *wins)
+ wins.unshift(win)
+ # tk_send_without_enc('forget', *((w.kind_of?(TkObject))? w.epath: w))
+ tk_send_without_enc('forget', *(wins.collect{|w| _epath(w)}))
+ self
+ end
+ alias del forget
+ alias delete forget
+ alias remove forget
+
+ def identify(x, y)
+ list(tk_send_without_enc('identify', x, y))
+ end
+
+ def proxy_coord
+ list(tk_send_without_enc('proxy', 'coord'))
+ end
+ def proxy_forget
+ tk_send_without_enc('proxy', 'forget')
+ self
+ end
+ def proxy_place(x, y)
+ tk_send_without_enc('proxy', 'place', x, y)
+ self
+ end
+
+ def sash_coord(index)
+ list(tk_send('sash', 'coord', index))
+ end
+ def sash_dragto(index, x, y)
+ tk_send('sash', 'dragto', index, x, y)
+ self
+ end
+ def sash_mark(index, x, y)
+ tk_send('sash', 'mark', index, x, y)
+ self
+ end
+ def sash_place(index, x, y)
+ tk_send('sash', 'place', index, x, y)
+ self
+ end
+
+ def panecget_strict(win, key)
+ # win = win.epath if win.kind_of?(TkObject)
+ win = _epath(win)
+ tk_tcl2ruby(tk_send_without_enc('panecget', win, "-#{key}"))
+ end
+ def panecget(win, key)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ panecget_strict(win, key)
+ else
+ begin
+ panecget_strict(win, key)
+ rescue => e
+ begin
+ if current_paneconfiginfo(win).has_key?(option.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+
+ def paneconfigure(win, key, value=nil)
+ # win = win.epath if win.kind_of?(TkObject)
+ win = _epath(win)
+ if key.kind_of? Hash
+ params = []
+ key.each{|k, v|
+ params.push("-#{k}")
+ # params.push((v.kind_of?(TkObject))? v.epath: v)
+ params.push(_epath(v))
+ }
+ tk_send_without_enc('paneconfigure', win, *params)
+ else
+ # value = value.epath if value.kind_of?(TkObject)
+ value = _epath(value)
+ tk_send_without_enc('paneconfigure', win, "-#{key}", value)
+ end
+ self
+ end
+ alias pane_config paneconfigure
+
+ def paneconfiginfo(win, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ # win = win.epath if win.kind_of?(TkObject)
+ win = _epath(win)
+ if key
+ #conf = tk_split_list(tk_send_without_enc('paneconfigure',
+ # win, "-#{key}"))
+ conf = tk_split_list(tk_send_without_enc('paneconfigure',
+ win, "-#{key}"),
+ false, true)
+ conf[0] = conf[0][1..-1]
+ if conf[0] == 'hide'
+ conf[3] = bool(conf[3]) unless conf[3].empty?
+ conf[4] = bool(conf[4]) unless conf[4].empty?
+ end
+ conf
+ else
+ #tk_split_simplelist(tk_send_without_enc('paneconfigure',
+ # win)).collect{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ tk_split_simplelist(tk_send_without_enc('paneconfigure', win),
+ false, false).collect{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ conf[0] = conf[0][1..-1]
+ if conf[3]
+ if conf[0] == 'hide'
+ conf[3] = bool(conf[3]) unless conf[3].empty?
+ elsif conf[3].index('{')
+ conf[3] = tk_split_list(conf[3])
+ else
+ conf[3] = tk_tcl2ruby(conf[3])
+ end
+ end
+ if conf[4]
+ if conf[0] == 'hide'
+ conf[4] = bool(conf[4]) unless conf[4].empty?
+ elsif conf[4].index('{')
+ conf[4] = tk_split_list(conf[4])
+ else
+ conf[4] = tk_tcl2ruby(conf[4])
+ end
+ end
+ conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
+ conf
+ }
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ # win = win.epath if win.kind_of?(TkObject)
+ win = _epath(win)
+ if key
+ #conf = tk_split_list(tk_send_without_enc('paneconfigure',
+ # win, "-#{key}"))
+ conf = tk_split_list(tk_send_without_enc('paneconfigure',
+ win, "-#{key}"),
+ false, true)
+ key = conf.shift[1..-1]
+ if key == 'hide'
+ conf[2] = bool(conf[2]) unless conf[2].empty?
+ conf[3] = bool(conf[3]) unless conf[3].empty?
+ end
+ { key => conf }
+ else
+ ret = {}
+ #tk_split_simplelist(tk_send_without_enc('paneconfigure',
+ # win)).each{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ tk_split_simplelist(tk_send_without_enc('paneconfigure', win),
+ false, false).each{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ key = conf.shift[1..-1]
+ if key
+ if key == 'hide'
+ conf[2] = bool(conf[2]) unless conf[2].empty?
+ elsif conf[2].index('{')
+ conf[2] = tk_split_list(conf[2])
+ else
+ conf[2] = tk_tcl2ruby(conf[2])
+ end
+ end
+ if conf[3]
+ if key == 'hide'
+ conf[3] = bool(conf[3]) unless conf[3].empty?
+ elsif conf[3].index('{')
+ conf[3] = tk_split_list(conf[3])
+ else
+ conf[3] = tk_tcl2ruby(conf[3])
+ end
+ end
+ if conf.size == 1
+ ret[key] = conf[0][1..-1] # alias info
+ else
+ ret[key] = conf
+ end
+ }
+ ret
+ end
+ end
+ end
+ alias pane_configinfo paneconfiginfo
+
+ def current_paneconfiginfo(win, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ conf = paneconfiginfo(win, key)
+ {conf[0] => conf[4]}
+ else
+ ret = {}
+ paneconfiginfo(win).each{|conf|
+ ret[conf[0]] = conf[4] if conf.size > 2
+ }
+ ret
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ paneconfiginfo(win, key).each{|k, conf|
+ ret[k] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+
+ alias current_pane_configinfo current_paneconfiginfo
+
+ def panes
+ list(tk_send_without_enc('panes'))
+ end
+end
+
+Tk::Panedwindow = Tk::PanedWindow
+#TkPanedWindow = Tk::PanedWindow unless Object.const_defined? :TkPanedWindow
+#TkPanedwindow = Tk::Panedwindow unless Object.const_defined? :TkPanedwindow
+Tk.__set_toplevel_aliases__(:Tk, Tk::PanedWindow,
+ :TkPanedWindow, :TkPanedwindow)
diff --git a/ext/tk/lib/tk/place.rb b/ext/tk/lib/tk/place.rb
new file mode 100644
index 0000000000..f7ebdfcbd6
--- /dev/null
+++ b/ext/tk/lib/tk/place.rb
@@ -0,0 +1,128 @@
+#
+# tk/place.rb : control place geometry manager
+#
+require 'tk'
+
+module TkPlace
+ include Tk
+ extend Tk
+
+ TkCommandNames = ['place'.freeze].freeze
+
+ def configure(win, slot, value=None)
+ # for >= Tk8.4a2 ?
+ # win = win.epath if win.kind_of?(TkObject)
+ win = _epath(win)
+ if slot.kind_of? Hash
+ params = []
+ slot.each{|k, v|
+ params.push("-#{k}")
+ # params.push((v.kind_of?(TkObject))? v.epath: v)
+ params.push(_epath(v))
+ }
+ tk_call_without_enc('place', 'configure', win, *params)
+ else
+ # value = value.epath if value.kind_of?(TkObject)
+ value = _epath(value)
+ tk_call_without_enc('place', 'configure', win, "-#{slot}", value)
+ end
+ end
+ alias place configure
+
+ def configinfo(win, slot = nil)
+ # for >= Tk8.4a2 ?
+ if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ # win = win.epath if win.kind_of?(TkObject)
+ win = _epath(win)
+ if slot
+ #conf = tk_split_list(tk_call_without_enc('place', 'configure',
+ # win, "-#{slot}") )
+ conf = tk_split_simplelist(tk_call_without_enc('place', 'configure',
+ win, "-#{slot}") )
+ conf[0] = conf[0][1..-1]
+ conf[1] = tk_tcl2ruby(conf[1])
+ conf[2] = tk_tcl2ruby(conf[1])
+ conf[3] = tk_tcl2ruby(conf[1])
+ conf[4] = tk_tcl2ruby(conf[1])
+ conf
+ else
+ tk_split_simplelist(tk_call_without_enc('place', 'configure',
+ win)).collect{|conflist|
+ #conf = list(conflist)
+ conf = simplelist(conflist).collect!{|inf| tk_tcl2ruby(inf)}
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ current_configinfo(win, slot)
+ end
+ end
+
+ def current_configinfo(win, slot = nil)
+ # win = win.epath if win.kind_of?(TkObject)
+ win = _epath(win)
+ if slot
+ #conf = tk_split_list(tk_call_without_enc('place', 'configure',
+ # win, "-#{slot}") )
+ conf = tk_split_simplelist(tk_call_without_enc('place', 'configure',
+ win, "-#{slot}") )
+ # { conf[0][1..-1] => conf[1] }
+ { conf[0][1..-1] => tk_tcl2ruby(conf[4]) }
+ else
+ ret = {}
+ #tk_split_list(tk_call_without_enc('place','configure',win)).each{|conf|
+ tk_split_simplelist(tk_call_without_enc('place', 'configure',
+ win)).each{|conf_list|
+ #ret[conf[0][1..-1]] = conf[1]
+ conf = simplelist(conf_list)
+ ret[conf[0][1..-1]] = tk_tcl2ruby(conf[4])
+ }
+ ret
+ end
+ end
+
+ def forget(win)
+ # win = win.epath if win.kind_of?(TkObject)
+ win = _epath(win)
+ tk_call_without_enc('place', 'forget', win)
+ end
+
+ def info(win)
+ # win = win.epath if win.kind_of?(TkObject)
+ win = _epath(win)
+ #ilist = list(tk_call_without_enc('place', 'info', win))
+ ilist = simplelist(tk_call_without_enc('place', 'info', win))
+ info = {}
+ while key = ilist.shift
+ #info[key[1..-1]] = ilist.shift
+ info[key[1..-1]] = tk_tcl2ruby(ilist.shift)
+ end
+ return info
+ end
+
+ def slaves(master)
+ # master = master.epath if master.kind_of?(TkObject)
+ master = _epath(master)
+ list(tk_call('place', 'slaves', master))
+ end
+
+ module_function :place, :configure, :configinfo, :current_configinfo
+ module_function :forget, :info, :slaves
+end
+=begin
+def TkPlace(win, slot, value=None)
+ win = win.epath if win.kind_of?(TkObject)
+ if slot.kind_of? Hash
+ params = []
+ slot.each{|k, v|
+ params.push("-#{k}")
+ params.push((v.kind_of?(TkObject))? v.epath: v)
+ }
+ tk_call_without_enc('place', win, *params)
+ else
+ value = value.epath if value.kind_of?(TkObject)
+ tk_call_without_enc('place', win, "-#{slot}", value)
+ end
+end
+=end
diff --git a/ext/tk/lib/tk/radiobutton.rb b/ext/tk/lib/tk/radiobutton.rb
new file mode 100644
index 0000000000..1f864ec06b
--- /dev/null
+++ b/ext/tk/lib/tk/radiobutton.rb
@@ -0,0 +1,71 @@
+#
+# tk/radiobutton.rb : treat radiobutton widget
+#
+require 'tk'
+require 'tk/button'
+
+class Tk::RadioButton<Tk::Button
+ TkCommandNames = ['radiobutton'.freeze].freeze
+ WidgetClassName = 'Radiobutton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('radiobutton', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('radiobutton', @path)
+ # end
+ #end
+ #private :create_self
+
+ def __boolval_optkeys
+ super() << 'indicatoron'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'selectcolor'
+ end
+ private :__strval_optkeys
+
+ def __ruby2val_optkeys # { key=>proc, ... }
+ {
+ 'variable'=>proc{|v| tk_trace_variable(v)} # for backward compatibility
+ }
+ end
+ private :__ruby2val_optkeys
+
+
+ def deselect
+ tk_send_without_enc('deselect')
+ self
+ end
+ def select
+ tk_send_without_enc('select')
+ self
+ end
+
+ def get_value
+ var = tk_send_without_enc('cget', '-variable')
+ if TkVariable::USE_TCLs_SET_VARIABLE_FUNCTIONS
+ _fromUTF8(INTERP._get_global_var(var))
+ else
+ INTERP._eval(Kernel.format('global %s; set %s', var, var))
+ end
+ end
+
+ def set_value(val)
+ var = tk_send_without_enc('cget', '-variable')
+ if TkVariable::USE_TCLs_SET_VARIABLE_FUNCTIONS
+ _fromUTF8(INTERP._set_global_var(var, _get_eval_string(val, true)))
+ else
+ s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
+ INTERP._eval(Kernel.format('global %s; set %s %s', var, var, s))
+ end
+ end
+end
+
+Tk::Radiobutton = Tk::RadioButton
+#TkRadioButton = Tk::RadioButton unless Object.const_defined? :TkRadioButton
+#TkRadiobutton = Tk::Radiobutton unless Object.const_defined? :TkRadiobutton
+Tk.__set_toplevel_aliases__(:Tk, Tk::RadioButton,
+ :TkRadioButton, :TkRadiobutton)
diff --git a/ext/tk/lib/tk/root.rb b/ext/tk/lib/tk/root.rb
new file mode 100644
index 0000000000..7237b4c614
--- /dev/null
+++ b/ext/tk/lib/tk/root.rb
@@ -0,0 +1,95 @@
+#
+# tk/root.rb : treat root widget
+#
+require 'tk'
+require 'tk/wm'
+require 'tk/menuspec'
+
+class Tk::Root<TkWindow
+ include Wm
+ include TkMenuSpec
+
+ def __methodcall_optkeys # { key=>method, ... }
+ TOPLEVEL_METHODCALL_OPTKEYS
+ end
+ private :__methodcall_optkeys
+
+ def Root.new(keys=nil, &b)
+ unless TkCore::INTERP.tk_windows['.']
+ TkCore::INTERP.tk_windows['.'] =
+ super(:without_creating=>true, :widgetname=>'.'){}
+ end
+ root = TkCore::INTERP.tk_windows['.']
+
+ keys = _symbolkey2str(keys)
+
+ # wm commands
+ root.instance_eval{
+ __methodcall_optkeys.each{|key, method|
+ value = keys.delete(key.to_s)
+ self.__send__(method, value) if value
+ }
+ }
+
+ if keys # wm commands ( for backward comaptibility )
+ keys.each{|k,v|
+ if v.kind_of? Array
+ root.__send__(k,*v)
+ else
+ root.__send__(k,v)
+ end
+ }
+ end
+
+ if block_given?
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ root.instance_exec(root, &b)
+ else
+ root.instance_eval(&b)
+ end
+ end
+ root
+ end
+
+ WidgetClassName = 'Tk'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.to_eval
+ # self::WidgetClassName
+ '.'
+ end
+
+ def create_self
+ @path = '.'
+ end
+ private :create_self
+
+ def path
+ "."
+ end
+
+ def add_menu(menu_info, tearoff=false, opts=nil)
+ # See tk/menuspec.rb for menu_info.
+ # opts is a hash of default configs for all of cascade menus.
+ # Configs of menu_info can override it.
+ if tearoff.kind_of?(Hash)
+ opts = tearoff
+ tearoff = false
+ end
+ _create_menubutton(self, menu_info, tearoff, opts)
+ end
+
+ def add_menubar(menu_spec, tearoff=false, opts=nil)
+ # See tk/menuspec.rb for menu_spec.
+ # opts is a hash of default configs for all of cascade menus.
+ # Configs of menu_spec can override it.
+ menu_spec.each{|info| add_menu(info, tearoff, opts)}
+ self.menu
+ end
+
+ def Root.destroy
+ TkCore::INTERP._invoke('destroy', '.')
+ end
+end
+
+TkRoot = Tk::Root unless Object.const_defined? :TkRoot
diff --git a/ext/tk/lib/tk/scale.rb b/ext/tk/lib/tk/scale.rb
new file mode 100644
index 0000000000..7e758d92f4
--- /dev/null
+++ b/ext/tk/lib/tk/scale.rb
@@ -0,0 +1,111 @@
+#
+# tk/scale.rb : treat scale widget
+#
+require 'tk'
+
+class Tk::Scale<TkWindow
+ TkCommandNames = ['scale'.freeze].freeze
+ WidgetClassName = 'Scale'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def create_self(keys)
+ if keys and keys != None
+ if keys.key?('command') && ! keys['command'].kind_of?(String)
+ cmd = keys.delete('command')
+ keys['command'] = proc{|val| cmd.call(val.to_f)}
+ end
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ #tk_call_without_enc('scale', @path, *hash_kv(keys, true))
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ rescue
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ begin
+ tk_call_without_enc('destroy', @path)
+ rescue
+ # cannot destroy
+ configure(keys)
+ else
+ # re-create widget
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
+ end
+ end
+ end
+ else
+ #tk_call_without_enc('scale', @path)
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def __strval_optkeys
+ super() << 'label'
+ end
+ private :__strval_optkeys
+
+ def _wrap_command_arg(cmd)
+ proc{|val|
+ if val.kind_of?(String)
+ cmd.call(number(val))
+ else
+ cmd.call(val)
+ end
+ }
+ end
+ private :_wrap_command_arg
+
+ def configure_cmd(slot, value)
+ configure(slot=>value)
+ end
+
+ def configure(slot, value=None)
+ if (slot == 'command' || slot == :command)
+ configure('command'=>value)
+ elsif slot.kind_of?(Hash) &&
+ (slot.key?('command') || slot.key?(:command))
+ slot = _symbolkey2str(slot)
+ slot['command'] = _wrap_command_arg(slot.delete('command'))
+ end
+ super(slot, value)
+ end
+
+ def command(cmd=Proc.new)
+ configure('command'=>cmd)
+ end
+
+ def get(x=None, y=None)
+ number(tk_send_without_enc('get', x, y))
+ end
+
+ def coords(val=None)
+ tk_split_list(tk_send_without_enc('coords', val))
+ end
+
+ def identify(x, y)
+ tk_send_without_enc('identify', x, y)
+ end
+
+ def set(val)
+ tk_send_without_enc('set', val)
+ end
+
+ def value
+ get
+ end
+
+ def value= (val)
+ set(val)
+ val
+ end
+end
+
+#TkScale = Tk::Scale unless Object.const_defined? :TkScale
+Tk.__set_toplevel_aliases__(:Tk, Tk::Scale, :TkScale)
diff --git a/ext/tk/lib/tk/scrollable.rb b/ext/tk/lib/tk/scrollable.rb
new file mode 100644
index 0000000000..96959b7a4b
--- /dev/null
+++ b/ext/tk/lib/tk/scrollable.rb
@@ -0,0 +1,82 @@
+#
+# tk/scrollable.rb : module for scrollable widget
+#
+require 'tk'
+
+module Tk
+ module XScrollable
+ def xscrollcommand(cmd=Proc.new)
+ configure_cmd 'xscrollcommand', cmd
+ # Tk.update # avoid scrollbar trouble
+ self
+ end
+
+ def xview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('xview'))
+ else
+ tk_send_without_enc('xview', *index)
+ self
+ end
+ end
+ def xview_moveto(*index)
+ xview('moveto', *index)
+ end
+ def xview_scroll(*index)
+ xview('scroll', *index)
+ end
+
+ def xscrollbar(bar=nil)
+ if bar
+ @xscrollbar = bar
+ @xscrollbar.orient 'horizontal'
+ self.xscrollcommand {|*arg| @xscrollbar.set(*arg)}
+ @xscrollbar.command {|*arg| self.xview(*arg)}
+ Tk.update # avoid scrollbar trouble
+ end
+ @xscrollbar
+ end
+ end
+
+ module YScrollable
+ def yscrollcommand(cmd=Proc.new)
+ configure_cmd 'yscrollcommand', cmd
+ # Tk.update # avoid scrollbar trouble
+ self
+ end
+
+ def yview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('yview'))
+ else
+ tk_send_without_enc('yview', *index)
+ self
+ end
+ end
+ def yview_moveto(*index)
+ yview('moveto', *index)
+ end
+ def yview_scroll(*index)
+ yview('scroll', *index)
+ end
+
+ def yscrollbar(bar=nil)
+ if bar
+ @yscrollbar = bar
+ @yscrollbar.orient 'vertical'
+ self.yscrollcommand {|*arg| @yscrollbar.set(*arg)}
+ @yscrollbar.command {|*arg| self.yview(*arg)}
+ Tk.update # avoid scrollbar trouble
+ end
+ @yscrollbar
+ end
+ end
+
+ X_Scrollable = XScrollable
+ Y_Scrollable = YScrollable
+
+ module Scrollable
+ include XScrollable
+ include YScrollable
+ end
+end
diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb
new file mode 100644
index 0000000000..87db46a9f9
--- /dev/null
+++ b/ext/tk/lib/tk/scrollbar.rb
@@ -0,0 +1,177 @@
+#
+# tk/scrollbar.rb : treat scrollbar widget
+#
+require 'tk'
+
+class Tk::Scrollbar<TkWindow
+ TkCommandNames = ['scrollbar'.freeze].freeze
+ WidgetClassName = 'Scrollbar'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def create_self(keys)
+ @assigned = []
+ @scroll_proc = proc{|*args|
+ if self.orient == 'horizontal'
+ @assigned.each{|w| w.xview(*args)}
+ else # 'vertical'
+ @assigned.each{|w| w.yview(*args)}
+ end
+ }
+
+ if keys and keys != None
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true))
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ rescue
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ begin
+ tk_call_without_enc('destroy', @path)
+ rescue
+ # cannot destroy
+ configure(keys)
+ else
+ # re-create widget
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
+ end
+ end
+ end
+ else
+ #tk_call_without_enc('scrollbar', @path)
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def propagate_set(src_win, first, last)
+ self.set(first, last)
+ if self.orient == 'horizontal'
+ @assigned.each{|w| w.xview('moveto', first) if w != src_win}
+ else # 'vertical'
+ @assigned.each{|w| w.yview('moveto', first) if w != src_win}
+ end
+ end
+
+ def assign(*wins)
+ begin
+ self.command(@scroll_proc) if self.cget('command').cmd != @scroll_proc
+ rescue Exception
+ self.command(@scroll_proc)
+ end
+ orient = self.orient
+ wins.each{|w|
+ @assigned << w unless @assigned.index(w)
+ if orient == 'horizontal'
+ w.xscrollcommand proc{|first, last| self.propagate_set(w, first, last)}
+ else # 'vertical'
+ w.yscrollcommand proc{|first, last| self.propagate_set(w, first, last)}
+ end
+ }
+ Tk.update # avoid scrollbar trouble
+ self
+ end
+
+ def assigned_list
+ begin
+ return @assigned.dup if self.cget('command').cmd == @scroll_proc
+ rescue Exception
+ end
+ fail RuntimeError, "not depend on the assigned_list"
+ end
+
+ def configure(*args)
+ ret = super(*args)
+ # Tk.update # avoid scrollbar trouble
+ ret
+ end
+
+ #def delta(deltax=None, deltay=None)
+ def delta(deltax, deltay)
+ number(tk_send_without_enc('delta', deltax, deltay))
+ end
+
+ #def fraction(x=None, y=None)
+ def fraction(x, y)
+ number(tk_send_without_enc('fraction', x, y))
+ end
+
+ def identify(x, y)
+ tk_send_without_enc('identify', x, y)
+ end
+
+ def get
+ #ary1 = tk_send('get').split
+ #ary2 = []
+ #for i in ary1
+ # ary2.push number(i)
+ #end
+ #ary2
+ list(tk_send_without_enc('get'))
+ end
+
+ def set(first, last)
+ tk_send_without_enc('set', first, last)
+ self
+ end
+
+ def activate(element=None)
+ tk_send_without_enc('activate', element)
+ end
+
+ def moveto(fraction)
+ tk_send_without_enc('moveto', fraction)
+ self
+ end
+
+ def scroll(*args)
+ tk_send_without_enc('scroll', *args)
+ self
+ end
+
+ def scroll_units(num)
+ scroll(num, 'units')
+ self
+ end
+
+ def scroll_pages(num)
+ scroll(num, 'pages')
+ self
+ end
+end
+
+#TkScrollbar = Tk::Scrollbar unless Object.const_defined? :TkScrollbar
+Tk.__set_toplevel_aliases__(:Tk, Tk::Scrollbar, :TkScrollbar)
+
+
+class Tk::XScrollbar<Tk::Scrollbar
+ def create_self(keys)
+ keys = {} unless keys
+ keys['orient'] = 'horizontal'
+ super(keys)
+ end
+ private :create_self
+end
+
+#TkXScrollbar = Tk::XScrollbar unless Object.const_defined? :TkXScrollbar
+Tk.__set_toplevel_aliases__(:Tk, Tk::XScrollbar, :TkXScrollbar)
+
+
+class Tk::YScrollbar<Tk::Scrollbar
+ def create_self(keys)
+ keys = {} unless keys
+ keys['orient'] = 'vertical'
+ super(keys)
+ end
+ private :create_self
+end
+
+#TkYScrollbar = Tk::YScrollbar unless Object.const_defined? :TkYScrollbar
+Tk.__set_toplevel_aliases__(:Tk, Tk::YScrollbar, :TkYScrollbar)
diff --git a/ext/tk/lib/tk/scrollbox.rb b/ext/tk/lib/tk/scrollbox.rb
new file mode 100644
index 0000000000..d20742a666
--- /dev/null
+++ b/ext/tk/lib/tk/scrollbox.rb
@@ -0,0 +1,39 @@
+#
+# tk/scrollbox.rb - Tk Listbox with Scrollbar
+# as an example of Composite Widget
+# by Yukihiro Matsumoto <matz@netlab.co.jp>
+#
+require 'tk'
+require 'tk/listbox'
+
+class TkScrollbox<Tk::Listbox
+ include TkComposite
+ def initialize_composite(keys=nil)
+ #list = Tk::Listbox.new(@frame)
+ # -> use current TkListbox class
+ list = TkListbox.new(@frame)
+ #scroll = Tk::Scrollbar.new(@frame)
+ # -> use current TkScrollbar class
+ scroll = TkScrollbar.new(@frame)
+ @path = list.path
+
+=begin
+ list.configure 'yscroll', scroll.path+" set"
+ list.pack 'side'=>'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)
+ delegate('background', list, scroll)
+ delegate('borderwidth', @frame)
+ delegate('relief', @frame)
+
+ configure keys if keys
+ end
+ private :initialize_composite
+end
diff --git a/ext/tk/lib/tk/selection.rb b/ext/tk/lib/tk/selection.rb
new file mode 100644
index 0000000000..5caa6ef8ef
--- /dev/null
+++ b/ext/tk/lib/tk/selection.rb
@@ -0,0 +1,86 @@
+#
+# tk/selection.rb : control selection
+#
+require 'tk'
+
+module TkSelection
+ include Tk
+ extend Tk
+
+ TkCommandNames = ['selection'.freeze].freeze
+
+ def self.clear(sel=nil)
+ if sel
+ tk_call_without_enc('selection', 'clear', '-selection', sel)
+ else
+ tk_call_without_enc('selection', 'clear')
+ end
+ end
+ def self.clear_on_display(win, sel=nil)
+ if sel
+ tk_call_without_enc('selection', 'clear',
+ '-displayof', win, '-selection', sel)
+ else
+ tk_call_without_enc('selection', 'clear', '-displayof', win)
+ end
+ end
+ def clear(sel=nil)
+ TkSelection.clear_on_display(self, sel)
+ self
+ end
+
+ def self.get(keys=nil)
+ #tk_call('selection', 'get', *hash_kv(keys))
+ _fromUTF8(tk_call_without_enc('selection', 'get', *hash_kv(keys)))
+ end
+ def self.get_on_display(win, keys=nil)
+ #tk_call('selection', 'get', '-displayof', win, *hash_kv(keys))
+ _fromUTF8(tk_call_without_enc('selection', 'get', '-displayof',
+ win, *hash_kv(keys)))
+ end
+ def get(keys=nil)
+ TkSelection.get_on_display(self, sel)
+ end
+
+ def self.handle(win, func=Proc.new, keys=nil, &b)
+ if func.kind_of?(Hash) && keys == nil
+ keys = func
+ func = Proc.new(&b)
+ end
+ args = ['selection', 'handle']
+ args.concat(hash_kv(keys))
+ args.concat([win, func])
+ tk_call_without_enc(*args)
+ end
+ def handle(func=Proc.new, keys=nil, &b)
+ TkSelection.handle(self, func, keys, &b)
+ end
+
+ def self.get_owner(sel=nil)
+ if sel
+ window(tk_call_without_enc('selection', 'own', '-selection', sel))
+ else
+ window(tk_call_without_enc('selection', 'own'))
+ end
+ end
+ def self.get_owner_on_display(win, sel=nil)
+ if sel
+ window(tk_call_without_enc('selection', 'own',
+ '-displayof', win, '-selection', sel))
+ else
+ window(tk_call_without_enc('selection', 'own', '-displayof', win))
+ end
+ end
+ def get_owner(sel=nil)
+ TkSelection.get_owner_on_display(self, sel)
+ self
+ end
+
+ def self.set_owner(win, keys=nil)
+ tk_call_without_enc('selection', 'own', *(hash_kv(keys) << win))
+ end
+ def set_owner(keys=nil)
+ TkSelection.set_owner(self, keys)
+ self
+ end
+end
diff --git a/ext/tk/lib/tk/spinbox.rb b/ext/tk/lib/tk/spinbox.rb
new file mode 100644
index 0000000000..34dc1904f7
--- /dev/null
+++ b/ext/tk/lib/tk/spinbox.rb
@@ -0,0 +1,119 @@
+#
+# tk/spinbox.rb - Tk spinbox classes
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+#
+require 'tk'
+require 'tk/entry'
+
+class Tk::Spinbox<Tk::Entry
+ TkCommandNames = ['spinbox'.freeze].freeze
+ WidgetClassName = 'Spinbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ class SpinCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?d, ?s, :direction ],
+ [ ?s, ?e, :current ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+
+ [ ?e, proc{|val|
+ #enc = Tk.encoding
+ enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system)
+ if enc
+ Tk.fromUTF8(TkComm::string(val), enc)
+ else
+ TkComm::string(val)
+ end
+ }
+ ],
+
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ (val)? '1': '0'
+ end
+ end
+
+ def self._config_keys
+ ['command']
+ end
+ end
+
+ def __validation_class_list
+ super() << SpinCommand
+ end
+
+ Tk::ValidateConfigure.__def_validcmd(binding, SpinCommand)
+
+ #def create_self(keys)
+ # tk_call_without_enc('spinbox', @path)
+ # if keys and keys != None
+ # configure(keys)
+ # end
+ #end
+ #private :create_self
+
+ def __boolval_optkeys
+ super() << 'wrap'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'buttonbackground' << 'format'
+ end
+ private :__strval_optkeys
+
+ def __listval_optkeys
+ super() << 'values'
+ end
+ private :__listval_optkeys
+
+ def identify(x, y)
+ tk_send_without_enc('identify', x, y)
+ end
+
+ def spinup
+ tk_send_without_enc('invoke', 'spinup')
+ self
+ end
+
+ def spindown
+ tk_send_without_enc('invoke', 'spindown')
+ self
+ end
+
+ def set(str)
+ _fromUTF8(tk_send_without_enc('set', _get_eval_enc_str(str)))
+ end
+end
+
+#TkSpinbox = Tk::Spinbox unless Object.const_defined? :TkSpinbox
+Tk.__set_toplevel_aliases__(:Tk, Tk::Spinbox, :TkSpinbox)
diff --git a/ext/tk/lib/tk/tagfont.rb b/ext/tk/lib/tk/tagfont.rb
new file mode 100644
index 0000000000..a1807395d2
--- /dev/null
+++ b/ext/tk/lib/tk/tagfont.rb
@@ -0,0 +1,43 @@
+#
+# tk/tagfont.rb : control font of tags
+#
+require 'tk'
+
+module TkTreatTagFont
+ def font_configinfo
+ @parent.tagfont_configinfo(@id)
+ end
+# alias font font_configinfo
+
+ def font_configure(slot)
+ @parent.tagfont_configure(@id, slot)
+ self
+ end
+
+ def latinfont_configure(ltn, keys=nil)
+ @parent.latintagfont_configure(@id, ltn, keys)
+ self
+ end
+ alias asciifont_configure latinfont_configure
+
+ def kanjifont_configure(knj, keys=nil)
+ @parent.kanjitagfont_configure(@id, ltn, keys)
+ self
+ end
+
+ def font_copy(win, wintag=nil)
+ @parent.tagfont_copy(@id, win, wintag)
+ self
+ end
+
+ def latinfont_copy(win, wintag=nil)
+ @parent.latintagfont_copy(@id, win, wintag)
+ self
+ end
+ alias asciifont_copy latinfont_copy
+
+ def kanjifont_copy(win, wintag=nil)
+ @parent.kanjitagfont_copy(@id, win, wintag)
+ self
+ end
+end
diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb
new file mode 100644
index 0000000000..4ec82bed1d
--- /dev/null
+++ b/ext/tk/lib/tk/text.rb
@@ -0,0 +1,1596 @@
+#
+# tk/text.rb - Tk text classes
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+require 'tk'
+require 'tk/itemfont'
+require 'tk/itemconfig'
+require 'tk/scrollable'
+require 'tk/txtwin_abst'
+
+module TkTextTagConfig
+ include TkTreatItemFont
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id) # id := [ type, tagOrId ]
+ [self.path, id[0], 'cget', id[1]]
+ end
+ private :__item_cget_cmd
+
+ 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_cget_strict(tagOrId, option)
+ itemcget_strict(['tag', tagOrId], option)
+ end
+ def tag_configure(tagOrId, slot, value=None)
+ itemconfigure(['tag', tagOrId], slot, value)
+ end
+ def tag_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['tag', tagOrId], slot)
+ end
+ def current_tag_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['tag', tagOrId], slot)
+ end
+
+ def window_cget(tagOrId, option)
+ itemcget(['window', tagOrId], option)
+ end
+ def window_cget_strict(tagOrId, option)
+ itemcget_strict(['window', tagOrId], option)
+ end
+ def window_configure(tagOrId, slot, value=None)
+ itemconfigure(['window', tagOrId], slot, value)
+ end
+ def window_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['window', tagOrId], slot)
+ end
+ def current_window_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['window', tagOrId], slot)
+ end
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+end
+
+class Tk::Text<TkTextWin
+ ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze
+ #include TkTreatTextTagFont
+ include TkTextTagConfig
+ include Scrollable
+
+ #######################################
+
+ module IndexModMethods
+ def +(mod)
+ return chars(mod) if mod.kind_of?(Numeric)
+
+ mod = mod.to_s
+ if mod =~ /^\s*[+-]?\d/
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod)
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod)
+ end
+ end
+
+ def -(mod)
+ return chars(-mod) if mod.kind_of?(Numeric)
+
+ mod = mod.to_s
+ if mod =~ /^\s*[+-]?\d/
+ Tk::Text::IndexString.new(String.new(id) << ' - ' << mod)
+ elsif mod =~ /^\s*[-]\s+(\d.*)$/
+ Tk::Text::IndexString.new(String.new(id) << ' - -' << $1)
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod)
+ end
+ end
+
+ def chars(mod)
+ fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
+ if mod < 0
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars')
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars')
+ end
+ end
+ alias char chars
+
+ def display_chars(mod)
+ # Tk8.5 feature
+ fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
+ if mod < 0
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars')
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars')
+ end
+ end
+ alias display_char display_chars
+
+ def any_chars(mod)
+ # Tk8.5 feature
+ fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
+ if mod < 0
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars')
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars')
+ end
+ end
+ alias any_char any_chars
+
+ def indices(mod)
+ # Tk8.5 feature
+ fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
+ if mod < 0
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices')
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices')
+ end
+ end
+
+ def display_indices(mod)
+ # Tk8.5 feature
+ fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
+ if mod < 0
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices')
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices')
+ end
+ end
+
+ def any_indices(mod)
+ # Tk8.5 feature
+ fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
+ if mod < 0
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices')
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices')
+ end
+ end
+
+ def lines(mod)
+ fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
+ if mod < 0
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines')
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines')
+ end
+ end
+ alias line lines
+
+ def display_lines(mod)
+ # Tk8.5 feature
+ fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
+ if mod < 0
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines')
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines')
+ end
+ end
+ alias display_line display_lines
+
+ def any_lines(mod)
+ # Tk8.5 feature
+ fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
+ if mod < 0
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines')
+ else
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines')
+ end
+ end
+ alias any_line any_lines
+
+ def linestart
+ Tk::Text::IndexString.new(String.new(id) << ' linestart')
+ end
+ def lineend
+ Tk::Text::IndexString.new(String.new(id) << ' lineend')
+ end
+
+ def display_linestart
+ # Tk8.5 feature
+ Tk::Text::IndexString.new(String.new(id) << ' display linestart')
+ end
+ def display_lineend
+ # Tk8.5 feature
+ Tk::Text::IndexString.new(String.new(id) << ' display lineend')
+ end
+
+ def wordstart
+ Tk::Text::IndexString.new(String.new(id) << ' wordstart')
+ end
+ def wordend
+ Tk::Text::IndexString.new(String.new(id) << ' wordend')
+ end
+
+ def display_wordstart
+ # Tk8.5 feature
+ Tk::Text::IndexString.new(String.new(id) << ' display wordstart')
+ end
+ def display_wordend
+ # Tk8.5 feature
+ Tk::Text::IndexString.new(String.new(id) << ' display wordend')
+ end
+ end
+
+ class IndexString < String
+ include IndexModMethods
+
+ def self.at(x,y)
+ self.new("@#{x},#{y}")
+ end
+
+ def self.new(str)
+ if str.kind_of?(String)
+ super(str)
+ elsif str.kind_of?(Symbol)
+ super(str.to_s)
+ else
+ str
+ end
+ end
+
+ def id
+ self
+ end
+ end
+
+ #######################################
+
+ TkCommandNames = ['text'.freeze].freeze
+ WidgetClassName = 'Text'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.new(*args, &block)
+ obj = super(*args){}
+ obj.init_instance_variable
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ obj.instance_exec(obj, &block) if defined? yield
+ else
+ obj.instance_eval(&block) if defined? yield
+ end
+ obj
+ end
+
+ def init_instance_variable
+ @cmdtbl = []
+ @tags = {}
+ end
+
+ def __destroy_hook__
+ TkTextTag::TTagID_TBL.mutex.synchronize{
+ TkTextTag::TTagID_TBL.delete(@path)
+ }
+ TkTextTag::TMarkID_TBL.mutex.synchronize{
+ TkTextMark::TMarkID_TBL.delete(@path)
+ }
+ end
+
+ def create_self(keys)
+ #if keys and keys != None
+ # #tk_call_without_enc('text', @path, *hash_kv(keys, true))
+ # tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ # *hash_kv(keys, true))
+ #else
+ # #tk_call_without_enc('text', @path)
+ # tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ #end
+ super(keys)
+ init_instance_variable
+ end
+ private :create_self
+
+ def __strval_optkeys
+ super() << 'inactiveseletcionbackground'
+ end
+ private :__strval_optkeys
+
+ def self.at(x, y)
+ Tk::Text::IndexString.at(x, y)
+ end
+
+ def at(x, y)
+ Tk::Text::IndexString.at(x, y)
+ end
+
+ def index(idx)
+ Tk::Text::IndexString.new(tk_send_without_enc('index',
+ _get_eval_enc_str(idx)))
+ end
+
+ def get_displaychars(*index)
+ # Tk8.5 feature
+ get('-displaychars', *index)
+ end
+
+ def value
+ _fromUTF8(tk_send_without_enc('get', "1.0", "end - 1 char"))
+ end
+
+ def value= (val)
+ tk_send_without_enc('delete', "1.0", 'end')
+ tk_send_without_enc('insert', "1.0", _get_eval_enc_str(val))
+ val
+ end
+
+ def clear
+ tk_send_without_enc('delete', "1.0", 'end')
+ self
+ end
+ alias erase clear
+
+ def _addcmd(cmd)
+ @cmdtbl.push cmd
+ end
+
+ def _addtag(name, obj)
+ @tags[name] = obj
+ end
+
+ def tagid(tag)
+ if tag.kind_of?(TkTextTag) \
+ || tag.kind_of?(TkTextMark) \
+ || tag.kind_of?(TkTextImage) \
+ || tag.kind_of?(TkTextWindow)
+ tag.id
+ else
+ tag # maybe an Array of configure paramters
+ end
+ end
+ private :tagid
+
+ def tagid2obj(tagid)
+ if @tags[tagid]
+ @tags[tagid]
+ else
+ tagid
+ end
+ end
+
+ def tag_names(index=None)
+ #tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)))).collect{|elt|
+ tk_split_simplelist(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)), false, true).collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+
+ def mark_names
+ #tk_split_simplelist(_fromUTF8(tk_send_without_enc('mark', 'names'))).collect{|elt|
+ tk_split_simplelist(tk_send_without_enc('mark', 'names'), false, true).collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+
+ def mark_gravity(mark, direction=nil)
+ if direction
+ tk_send_without_enc('mark', 'gravity',
+ _get_eval_enc_str(mark), direction)
+ self
+ else
+ tk_send_without_enc('mark', 'gravity', _get_eval_enc_str(mark))
+ end
+ end
+
+ def mark_set(mark, index)
+ tk_send_without_enc('mark', 'set', _get_eval_enc_str(mark),
+ _get_eval_enc_str(index))
+ self
+ end
+ alias set_mark mark_set
+
+ def mark_unset(*marks)
+ tk_send_without_enc('mark', 'unset',
+ *(marks.collect{|mark| _get_eval_enc_str(mark)}))
+ self
+ end
+ alias unset_mark mark_unset
+
+ def mark_next(index)
+ tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'next',
+ _get_eval_enc_str(index))))
+ end
+ alias next_mark mark_next
+
+ def mark_previous(index)
+ tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'previous',
+ _get_eval_enc_str(index))))
+ end
+ alias previous_mark mark_previous
+
+ def image_cget_strict(index, slot)
+ case slot.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ _fromUTF8(tk_send_without_enc('image', 'cget',
+ _get_eval_enc_str(index), "-#{slot}"))
+ else
+ tk_tcl2ruby(_fromUTF8(tk_send_without_enc('image', 'cget',
+ _get_eval_enc_str(index),
+ "-#{slot}")))
+ end
+ end
+
+ def image_cget(index, slot)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ image_cget_strict(index, slot)
+ else
+ begin
+ image_cget_strict(index, slot)
+ rescue => e
+ begin
+ if current_image_configinfo(index).has_key?(slot.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+
+ def image_configure(index, slot, value=None)
+ if slot.kind_of?(Hash)
+ _fromUTF8(tk_send_without_enc('image', 'configure',
+ _get_eval_enc_str(index),
+ *hash_kv(slot, true)))
+ else
+ _fromUTF8(tk_send_without_enc('image', 'configure',
+ _get_eval_enc_str(index),
+ "-#{slot}",
+ _get_eval_enc_str(value)))
+ end
+ self
+ end
+
+ def image_configinfo(index, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ case slot.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
+ conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
+ else
+ #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
+ conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
+ end
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ # tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).collect{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).collect{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ 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
+ }
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ case slot.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
+ conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
+ else
+ #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
+ conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
+ end
+ key = conf.shift[1..-1]
+ { key => conf }
+ else
+ ret = {}
+ #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).each{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).each{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ 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
+ }
+ ret
+ end
+ end
+ end
+
+ def current_image_configinfo(index, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ conf = image_configinfo(index, slot)
+ {conf[0] => conf[4]}
+ else
+ ret = {}
+ image_configinfo(index).each{|conf|
+ ret[conf[0]] = conf[4] if conf.size > 2
+ }
+ ret
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ image_configinfo(index, slot).each{|k, conf|
+ ret[k] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+
+ def image_names
+ #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'names'))).collect{|elt|
+ tk_split_simplelist(tk_send_without_enc('image', 'names'), false, true).collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+
+ def set_insert(index)
+ tk_send_without_enc('mark','set','insert', _get_eval_enc_str(index))
+ self
+ end
+
+ def set_current(index)
+ tk_send_without_enc('mark','set','current', _get_eval_enc_str(index))
+ self
+ end
+
+ def insert(index, chars, *tags)
+ if tags[0].kind_of?(Array)
+ # multiple chars-taglist argument :: str, [tag,...], str, [tag,...], ...
+ args = [chars]
+ while tags.size > 0
+ args << tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist
+ args << tags.shift if tags.size > 0 # chars
+ end
+ super(index, *args)
+ else
+ # single chars-taglist argument :: str, tag, tag, ...
+ if tags.size == 0
+ super(index, chars)
+ else
+ super(index, chars, tags.collect{|x|_get_eval_string(x)}.join(' '))
+ end
+ end
+ end
+
+ def destroy
+ @tags = {} unless @tags
+ @tags.each_value do |t|
+ t.destroy
+ end
+ super()
+ end
+
+ def backspace
+ self.delete 'insert'
+ end
+
+ def bbox(index)
+ list(tk_send_without_enc('bbox', _get_eval_enc_str(index)))
+ end
+
+ def compare(idx1, op, idx2)
+ bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1),
+ op, _get_eval_enc_str(idx2)))
+ end
+
+ def count(idx1, idx2, *opts)
+ # opts are Tk8.5 feature
+ cnt = 0
+ args = opts.collect{|opt|
+ str = opt.to_s
+ cnt += 1 if str != 'update'
+ '-' + str
+ }
+ args << _get_eval_enc_str(idx1) << _get_eval_enc_str(idx2)
+ if cnt <= 1
+ number(tk_send_without_enc('count', *opts))
+ else
+ list(tk_send_without_enc('count', *opts))
+ end
+ end
+
+ def count_info(idx1, idx2, update=true)
+ # Tk8.5 feature
+ opts = [
+ :chars, :displaychars, :displayindices, :displaylines,
+ :indices, :lines, :xpixels, :ypixels
+ ]
+ if update
+ lst = count(idx1, idx2, :update, *opts)
+ else
+ lst = count(idx1, idx2, *opts)
+ end
+ info = {}
+ opts.each_with_index{|key, idx| info[key] = lst[idx]}
+ info
+ end
+
+ def peer_names()
+ # Tk8.5 feature
+ list(tk_send_without_enc('peer', 'names'))
+ end
+
+ def replace(idx1, idx2, *opts)
+ tk_send('replace', idx1, idx2, *opts)
+ self
+ end
+
+ def debug
+ bool(tk_send_without_enc('debug'))
+ end
+ def debug=(boolean)
+ tk_send_without_enc('debug', boolean)
+ #self
+ boolean
+ end
+
+ def dlineinfo(index)
+ list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index)))
+ end
+
+ def modified?
+ bool(tk_send_without_enc('edit', 'modified'))
+ end
+ def modified(mode)
+ tk_send_without_enc('edit', 'modified', mode)
+ self
+ end
+ def modified=(mode)
+ modified(mode)
+ mode
+ end
+
+ def edit_redo
+ tk_send_without_enc('edit', 'redo')
+ self
+ end
+ def edit_reset
+ tk_send_without_enc('edit', 'reset')
+ self
+ end
+ def edit_separator
+ tk_send_without_enc('edit', 'separator')
+ self
+ end
+ def edit_undo
+ tk_send_without_enc('edit', 'undo')
+ self
+ end
+
+ def xview_pickplace(index)
+ tk_send_without_enc('xview', '-pickplace', _get_eval_enc_str(index))
+ self
+ end
+
+ def yview_pickplace(index)
+ tk_send_without_enc('yview', '-pickplace', _get_eval_enc_str(index))
+ self
+ end
+
+ def text_copy
+ # Tk8.4 feature
+ tk_call_without_enc('tk_textCopy', @path)
+ self
+ end
+
+ def text_cut
+ # Tk8.4 feature
+ tk_call_without_enc('tk_textCut', @path)
+ self
+ end
+
+ def text_paste
+ # Tk8.4 feature
+ tk_call_without_enc('tk_textPaste', @path)
+ self
+ end
+
+ def tag_add(tag, index1, index2=None)
+ tk_send_without_enc('tag', 'add', _get_eval_enc_str(tag),
+ _get_eval_enc_str(index1),
+ _get_eval_enc_str(index2))
+ self
+ end
+ alias addtag tag_add
+ alias add_tag tag_add
+
+ def tag_delete(*tags)
+ tk_send_without_enc('tag', 'delete',
+ *(tags.collect{|tag| _get_eval_enc_str(tag)}))
+ TkTextTag::TTagID_TBL.mutex.synchronize{
+ if TkTextTag::TTagID_TBL[@path]
+ tags.each{|tag|
+ if tag.kind_of?(TkTextTag)
+ TkTextTag::TTagID_TBL[@path].delete(tag.id)
+ else
+ TkTextTag::TTagID_TBL[@path].delete(tag)
+ end
+ }
+ end
+ }
+ self
+ end
+ alias deltag tag_delete
+ alias delete_tag tag_delete
+
+ #def tag_bind(tag, seq, cmd=Proc.new, *args)
+ # _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
+ # self
+ #end
+ def tag_bind(tag, seq, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
+ self
+ end
+
+ #def tag_bind_append(tag, seq, cmd=Proc.new, *args)
+ # _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
+ # self
+ #end
+ def tag_bind_append(tag, seq, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
+ self
+ end
+
+ def tag_bind_remove(tag, seq)
+ _bind_remove([@path, 'tag', 'bind', tag], seq)
+ self
+ end
+
+ def tag_bindinfo(tag, context=nil)
+ _bindinfo([@path, 'tag', 'bind', tag], context)
+ end
+
+=begin
+ def tag_cget(tag, key)
+ case key.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ tk_call_without_enc(@path, 'tag', 'cget',
+ _get_eval_enc_str(tag), "-#{key}")
+ when 'font', 'kanjifont'
+ #fnt = tk_tcl2ruby(tk_send('tag', 'cget', tag, "-#{key}"))
+ fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('tag','cget',_get_eval_enc_str(tag),'-font')))
+ unless fnt.kind_of?(TkFont)
+ fnt = tagfontobj(tag, fnt)
+ end
+ if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
+ # obsolete; just for compatibility
+ fnt.kanji_font
+ else
+ fnt
+ end
+ else
+ tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@path,'tag','cget',_get_eval_enc_str(tag),"-#{key}")))
+ end
+ end
+
+ def tag_configure(tag, key, val=None)
+ if key.kind_of?(Hash)
+ key = _symbolkey2str(key)
+ if ( key['font'] || key['kanjifont'] \
+ || key['latinfont'] || key['asciifont'] )
+ tagfont_configure(tag, key)
+ else
+ tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag),
+ *hash_kv(key, true))
+ end
+
+ else
+ if key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont
+ if val == None
+ tagfontobj(tag)
+ else
+ tagfont_configure(tag, {key=>val})
+ end
+ else
+ tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag),
+ "-#{key}", _get_eval_enc_str(val))
+ end
+ end
+ self
+ end
+
+ def tag_configinfo(tag, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ case key.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
+ when 'font', 'kanjifont'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
+ conf[4] = tagfont_configinfo(tag, conf[4])
+ else
+ conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
+ end
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ ret = tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).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] = tagfont_configinfo(tag, fontconf[4])
+ ret.push(fontconf)
+ else
+ ret
+ end
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ case key.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
+ when 'font', 'kanjifont'
+ conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
+ conf[4] = tagfont_configinfo(tag, conf[4])
+ else
+ conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
+ end
+ key = conf.shift[1..-1]
+ { key => conf }
+ else
+ ret = {}
+ tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).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] = tagfont_configinfo(tag, fontconf[3])
+ ret['font'] = fontconf
+ end
+ ret
+ end
+ end
+ end
+
+ def current_tag_configinfo(tag, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ conf = tag_configinfo(tag, key)
+ {conf[0] => conf[4]}
+ else
+ ret = {}
+ tag_configinfo(tag).each{|conf|
+ ret[conf[0]] = conf[4] if conf.size > 2
+ }
+ ret
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ tag_configinfo(tag, key).each{|k, conf|
+ ret[k] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+=end
+
+ def tag_raise(tag, above=None)
+ tk_send_without_enc('tag', 'raise', _get_eval_enc_str(tag),
+ _get_eval_enc_str(above))
+ self
+ end
+
+ def tag_lower(tag, below=None)
+ tk_send_without_enc('tag', 'lower', _get_eval_enc_str(tag),
+ _get_eval_enc_str(below))
+ self
+ end
+
+ def tag_remove(tag, *indices)
+ tk_send_without_enc('tag', 'remove', _get_eval_enc_str(tag),
+ *(indices.collect{|idx| _get_eval_enc_str(idx)}))
+ self
+ end
+
+ def tag_ranges(tag)
+ #l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges',
+ # _get_eval_enc_str(tag)))
+ l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges',
+ _get_eval_enc_str(tag)),
+ false, true)
+ r = []
+ while key=l.shift
+ r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)]
+ end
+ r
+ end
+
+ def tag_nextrange(tag, first, last=None)
+ simplelist(tk_send_without_enc('tag', 'nextrange',
+ _get_eval_enc_str(tag),
+ _get_eval_enc_str(first),
+ _get_eval_enc_str(last))).collect{|idx|
+ Tk::Text::IndexString.new(idx)
+ }
+ end
+
+ def tag_prevrange(tag, first, last=None)
+ simplelist(tk_send_without_enc('tag', 'prevrange',
+ _get_eval_enc_str(tag),
+ _get_eval_enc_str(first),
+ _get_eval_enc_str(last))).collect{|idx|
+ Tk::Text::IndexString.new(idx)
+ }
+ end
+
+=begin
+ def window_cget(index, slot)
+ case slot.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ _fromUTF8(tk_send_without_enc('window', 'cget',
+ _get_eval_enc_str(index), "-#{slot}"))
+ when 'font', 'kanjifont'
+ #fnt = tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}"))
+ fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('window', 'cget', _get_eval_enc_str(index), '-font')))
+ unless fnt.kind_of?(TkFont)
+ fnt = tagfontobj(index, fnt)
+ end
+ if slot.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
+ # obsolete; just for compatibility
+ fnt.kanji_font
+ else
+ fnt
+ end
+ else
+ tk_tcl2ruby(_fromUTF8(tk_send_without_enc('window', 'cget', _get_eval_enc_str(index), "-#{slot}")))
+ end
+ end
+
+ def window_configure(index, slot, value=None)
+ if index.kind_of?(TkTextWindow)
+ index.configure(slot, value)
+ else
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ win = slot['window']
+ # slot['window'] = win.epath if win.kind_of?(TkWindow)
+ slot['window'] = _epath(win) if win
+ if slot['create']
+ p_create = slot['create']
+ if p_create.kind_of?(Proc)
+#=begin
+ slot['create'] = install_cmd(proc{
+ id = p_create.call
+ if id.kind_of?(TkWindow)
+ id.epath
+ else
+ id
+ end
+ })
+#=end
+ slot['create'] = install_cmd(proc{_epath(p_create.call)})
+ end
+ end
+ tk_send_without_enc('window', 'configure',
+ _get_eval_enc_str(index),
+ *hash_kv(slot, true))
+ else
+ if slot == 'window' || slot == :window
+ # id = value
+ # value = id.epath if id.kind_of?(TkWindow)
+ value = _epath(value)
+ end
+ if slot == 'create' || slot == :create
+ p_create = value
+ if p_create.kind_of?(Proc)
+#=begin
+ value = install_cmd(proc{
+ id = p_create.call
+ if id.kind_of?(TkWindow)
+ id.epath
+ else
+ id
+ end
+ })
+#=end
+ value = install_cmd(proc{_epath(p_create.call)})
+ end
+ end
+ tk_send_without_enc('window', 'configure',
+ _get_eval_enc_str(index),
+ "-#{slot}", _get_eval_enc_str(value))
+ end
+ end
+ self
+ end
+
+ def window_configinfo(win, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ case slot.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
+ else
+ conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
+ end
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).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
+ }
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ case slot.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
+ else
+ conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
+ end
+ key = conf.shift[1..-1]
+ { key => conf }
+ else
+ ret = {}
+ tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).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
+ }
+ ret
+ end
+ end
+ end
+
+ def current_window_configinfo(win, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ conf = window_configinfo(win, slot)
+ {conf[0] => conf[4]}
+ else
+ ret = {}
+ window_configinfo(win).each{|conf|
+ ret[conf[0]] = conf[4] if conf.size > 2
+ }
+ ret
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ window_configinfo(win, slot).each{|k, conf|
+ ret[k] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+=end
+
+ def window_names
+ # tk_split_simplelist(_fromUTF8(tk_send_without_enc('window', 'names'))).collect{|elt|
+ tk_split_simplelist(tk_send_without_enc('window', 'names'), false, true).collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+
+ def _ktext_length(txt)
+ if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!!
+ return txt.length
+ end
+ ###########################
+
+ if $KCODE !~ /n/i
+ return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
+ end
+
+ # $KCODE == 'NONE'
+ if JAPANIZED_TK
+ tk_call_without_enc('kstring', 'length',
+ _get_eval_enc_str(txt)).to_i
+ else
+ begin
+ tk_call_without_enc('encoding', 'convertto', 'ascii',
+ _get_eval_enc_str(txt)).length
+ rescue StandardError, NameError
+ # sorry, I have no plan
+ txt.length
+ end
+ end
+ end
+ private :_ktext_length
+
+ def tksearch(*args)
+ # call 'search' subcommand of text widget
+ # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>]
+ # If <pattern> is regexp, then it must be a regular expression of Tcl
+ nocase = false
+ if args[0].kind_of?(Array)
+ opts = args.shift.collect{|opt|
+ s_opt = opt.to_s
+ nocase = true if s_opt == 'nocase'
+ '-' + s_opt
+ }
+ else
+ opts = []
+ end
+
+ if args[0].kind_of?(Regexp)
+ regexp = args.shift
+ if !nocase && (regexp.options & Regexp::IGNORECASE) != 0
+ opts << '-nocase'
+ end
+ args.unshift(regexp.source)
+ end
+
+ opts << '--'
+
+ ret = tk_send('search', *(opts + args))
+ if ret == ""
+ nil
+ else
+ Tk::Text::IndexString.new(ret)
+ end
+ end
+
+ def tksearch_with_count(*args)
+ # call 'search' subcommand of text widget
+ # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>]
+ # If <pattern> is regexp, then it must be a regular expression of Tcl
+ nocase = false
+ if args[0].kind_of?(Array)
+ opts = args.shift.collect{|opt|
+ s_opt = opt.to_s
+ nocase = true if s_opt == 'nocase'
+ '-' + s_opt
+ }
+ else
+ opts = []
+ end
+
+ opts << '-count' << args.shift
+
+ if args[0].kind_of?(Regexp)
+ regexp = args.shift
+ if !nocase && (regexp.options & Regexp::IGNORECASE) != 0
+ opts << '-nocase'
+ end
+ args.unshift(regexp.source)
+ end
+
+ opts << '--'
+
+ ret = tk_send('search', *(opts + args))
+ if ret == ""
+ nil
+ else
+ Tk::Text::IndexString.new(ret)
+ end
+ end
+
+ def search_with_length(pat,start,stop=None)
+ pat = pat.chr if pat.kind_of?(Integer)
+ if stop != None
+ return ["", 0] if compare(start,'>=',stop)
+ txt = get(start,stop)
+ if (pos = txt.index(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of?(String)
+ #return [index(start + " + #{pos} chars"), pat.split('').length]
+ return [index(start + " + #{pos} chars"),
+ _ktext_length(pat), pat.dup]
+ else
+ #return [index(start + " + #{pos} chars"), $&.split('').length]
+ return [index(start + " + #{pos} chars"),
+ _ktext_length(match), match]
+ end
+ else
+ return ["", 0]
+ end
+ else
+ txt = get(start,'end - 1 char')
+ if (pos = txt.index(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of?(String)
+ #return [index(start + " + #{pos} chars"), pat.split('').length]
+ return [index(start + " + #{pos} chars"),
+ _ktext_length(pat), pat.dup]
+ else
+ #return [index(start + " + #{pos} chars"), $&.split('').length]
+ return [index(start + " + #{pos} chars"),
+ _ktext_length(match), match]
+ end
+ else
+ txt = get('1.0','end - 1 char')
+ if (pos = txt.index(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of?(String)
+ #return [index("1.0 + #{pos} chars"), pat.split('').length]
+ return [index("1.0 + #{pos} chars"),
+ _ktext_length(pat), pat.dup]
+ else
+ #return [index("1.0 + #{pos} chars"), $&.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
+ end
+ else
+ return ["", 0]
+ end
+ end
+ end
+ end
+
+ def search(pat,start,stop=None)
+ search_with_length(pat,start,stop)[0]
+ end
+
+ def rsearch_with_length(pat,start,stop=None)
+ pat = pat.chr if pat.kind_of?(Integer)
+ if stop != None
+ return ["", 0] if compare(start,'<=',stop)
+ txt = get(stop,start)
+ if (pos = txt.rindex(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of?(String)
+ #return [index(stop + " + #{pos} chars"), pat.split('').length]
+ return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup]
+ else
+ #return [index(stop + " + #{pos} chars"), $&.split('').length]
+ return [index(stop + " + #{pos} chars"), _ktext_length(match), match]
+ end
+ else
+ return ["", 0]
+ end
+ else
+ txt = get('1.0',start)
+ if (pos = txt.rindex(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of?(String)
+ #return [index("1.0 + #{pos} chars"), pat.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
+ else
+ #return [index("1.0 + #{pos} chars"), $&.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
+ end
+ else
+ txt = get('1.0','end - 1 char')
+ if (pos = txt.rindex(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of?(String)
+ #return [index("1.0 + #{pos} chars"), pat.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
+ else
+ #return [index("1.0 + #{pos} chars"), $&.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
+ end
+ else
+ return ["", 0]
+ end
+ end
+ end
+ end
+
+ def rsearch(pat,start,stop=None)
+ rsearch_with_length(pat,start,stop)[0]
+ end
+
+ def dump(type_info, *index, &block)
+ if type_info.kind_of?(Symbol)
+ type_info = [ type_info.to_s ]
+ elsif type_info.kind_of?(String)
+ type_info = [ type_info ]
+ end
+ args = type_info.collect{|inf| '-' + inf}
+ args << '-command' << block if block
+ str = tk_send('dump', *(args + index))
+ result = []
+ sel = nil
+ i = 0
+ while i < str.size
+ # retrieve key
+ idx = str.index(/ /, i)
+ result.push str[i..(idx-1)]
+ i = idx + 1
+
+ # retrieve value
+ case result[-1]
+ when 'text'
+ if str[i] == ?{
+ # text formed as {...}
+ val, i = _retrieve_braced_text(str, i)
+ result.push val
+ else
+ # text which may contain backslahes
+ val, i = _retrieve_backslashed_text(str, i)
+ result.push val
+ end
+ else
+ idx = str.index(/ /, i)
+ val = str[i..(idx-1)]
+ case result[-1]
+ when 'mark'
+ case val
+ when 'insert'
+ result.push TkTextMarkInsert.new(self)
+ when 'current'
+ result.push TkTextMarkCurrent.new(self)
+ when 'anchor'
+ result.push TkTextMarkAnchor.new(self)
+ else
+ result.push tk_tcl2ruby(val)
+ end
+ when 'tagon'
+ if val == 'sel'
+ if sel
+ result.push sel
+ else
+ result.push TkTextTagSel.new(self)
+ end
+ else
+ result.push tk_tcl2ruby(val)
+ end
+ when 'tagoff'
+ result.push tk_tcl2ruby(val)
+ when 'window'
+ result.push tk_tcl2ruby(val)
+ when 'image'
+ result.push tk_tcl2ruby(val)
+ end
+ i = idx + 1
+ end
+
+ # retrieve index
+ idx = str.index(/ /, i)
+ if idx
+ result.push(Tk::Text::IndexString.new(str[i..(idx-1)]))
+ i = idx + 1
+ else
+ result.push(Tk::Text::IndexString.new(str[i..-1]))
+ break
+ end
+ end
+
+ kvis = []
+ until result.empty?
+ kvis.push [result.shift, result.shift, result.shift]
+ end
+ kvis # result is [[key1, value1, index1], [key2, value2, index2], ...]
+ end
+
+ def _retrieve_braced_text(str, i)
+ cnt = 0
+ idx = i
+ while idx < str.size
+ case str[idx]
+ when ?{
+ cnt += 1
+ when ?}
+ cnt -= 1
+ if cnt == 0
+ break
+ end
+ end
+ idx += 1
+ end
+ return str[i+1..idx-1], idx + 2
+ end
+ private :_retrieve_braced_text
+
+ def _retrieve_backslashed_text(str, i)
+ j = i
+ idx = nil
+ loop {
+ idx = str.index(/ /, j)
+ if str[idx-1] == ?\\
+ j += 1
+ else
+ break
+ end
+ }
+ val = str[i..(idx-1)]
+ val.gsub!(/\\( |\{|\})/, '\1')
+ return val, idx + 1
+ end
+ private :_retrieve_backslashed_text
+
+ def dump_all(*index, &block)
+ dump(['all'], *index, &block)
+ end
+ def dump_mark(*index, &block)
+ dump(['mark'], *index, &block)
+ end
+ def dump_tag(*index, &block)
+ dump(['tag'], *index, &block)
+ end
+ def dump_text(*index, &block)
+ dump(['text'], *index, &block)
+ end
+ def dump_window(*index, &block)
+ dump(['window'], *index, &block)
+ end
+ def dump_image(*index, &block)
+ dump(['image'], *index, &block)
+ end
+end
+
+#TkText = Tk::Text unless Object.const_defined? :TkText
+Tk.__set_toplevel_aliases__(:Tk, Tk::Text, :TkText)
+
+
+#######################################
+
+class Tk::Text::Peer < Tk::Text
+ # Tk8.5 feature
+ def initialize(text, parent=nil, keys={})
+ unless text.kind_of?(Tk::Text)
+ fail ArgumentError, "Tk::Text is expected for 1st argument"
+ end
+ @src_text = text
+ super(parent, keys)
+ end
+
+ def create_self(keys)
+ if keys and keys != None
+ tk_call_without_enc(@src_text.path, 'peer', 'create', @path)
+ else
+ tk_call_without_enc(@src_text.path, 'peer', 'create', @path)
+ end
+ end
+ private :create_self
+end
diff --git a/ext/tk/lib/tk/textimage.rb b/ext/tk/lib/tk/textimage.rb
new file mode 100644
index 0000000000..fb306a9c17
--- /dev/null
+++ b/ext/tk/lib/tk/textimage.rb
@@ -0,0 +1,88 @@
+#
+# tk/textimage.rb - treat Tk text image object
+#
+require 'tk'
+require 'tk/text'
+
+class TkTextImage<TkObject
+ include Tk::Text::IndexModMethods
+
+ def initialize(parent, index, keys)
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
+ #end
+ @t = parent
+ if index == 'end' || index == :end
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
+ elsif index.kind_of? TkTextMark
+ if tk_call_without_enc(@t.path,'index',index.path) == tk_call_without_enc(@t.path,'index','end')
+ @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
+ 'end - 1 chars'))
+ else
+ @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
+ index.path))
+ end
+ else
+ @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
+ _get_eval_enc_str(index)))
+ end
+ @path.gravity = 'left'
+ @index = @path.path
+ @id = tk_call_without_enc(@t.path, 'image', 'create', @index,
+ *hash_kv(keys, true)).freeze
+ @path.gravity = 'right'
+ end
+
+ def id
+ Tk::Text::IndexString.new(@id)
+ end
+ def mark
+ @path
+ end
+
+ def [](slot)
+ cget(slot)
+ end
+ def []=(slot, value)
+ configure(slot, value)
+ value
+ end
+
+ def cget(slot)
+ @t.image_cget(@index, slot)
+ end
+
+ def cget_strict(slot)
+ @t.image_cget_strict(@index, slot)
+ end
+
+ def configure(slot, value=None)
+ @t.image_configure(@index, slot, value)
+ self
+ end
+# def configure(slot, value)
+# tk_call @t.path, 'image', 'configure', @index, "-#{slot}", value
+# end
+
+ def configinfo(slot = nil)
+ @t.image_configinfo(@index, slot)
+ end
+
+ def current_configinfo(slot = nil)
+ @t.current_image_configinfo(@index, slot)
+ end
+
+ def image
+ img = tk_call_without_enc(@t.path, 'image', 'cget', @index, '-image')
+ TkImage::Tk_IMGTBL[img]? TkImage::Tk_IMGTBL[img] : img
+ end
+
+ def image=(value)
+ tk_call_without_enc(@t.path, 'image', 'configure', @index, '-image',
+ _get_eval_enc_str(value))
+ #self
+ value
+ end
+end
+
+TktImage = TkTextImage
diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb
new file mode 100644
index 0000000000..72c1ce1ab4
--- /dev/null
+++ b/ext/tk/lib/tk/textmark.rb
@@ -0,0 +1,204 @@
+#
+# tk/textmark.rb - methods for treating text marks
+#
+require 'tk'
+require 'tk/text'
+
+class TkTextMark<TkObject
+ include Tk::Text::IndexModMethods
+
+ TMarkID_TBL = TkCore::INTERP.create_table
+
+ (Tk_TextMark_ID = ['mark'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TMarkID_TBL.mutex.synchronize{ TMarkID_TBL.clear }
+ }
+
+ def TkTextMark.id2obj(text, id)
+ tpath = text.path
+ TMarkID_TBL.mutex.synchronize{
+ if TMarkID_TBL[tpath]
+ TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(parent, index)
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
+ #end
+ @parent = @t = parent
+ @tpath = parent.path
+ Tk_TextMark_ID.mutex.synchronize{
+ # @path = @id = Tk_TextMark_ID.join('')
+ @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze
+ Tk_TextMark_ID[1].succ!
+ }
+ TMarkID_TBL.mutex.synchronize{
+ TMarkID_TBL[@id] = self
+ TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
+ TMarkID_TBL[@tpath][@id] = self
+ }
+ tk_call_without_enc(@t.path, 'mark', 'set', @id,
+ _get_eval_enc_str(index))
+ @t._addtag id, self
+ end
+
+ def id
+ Tk::Text::IndexString.new(@id)
+ end
+
+ def exist?
+ #if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'names'))).find{|id| id == @id } )
+ if ( tk_split_simplelist(tk_call_without_enc(@t.path, 'mark', 'names'), false, true).find{|id| id == @id } )
+ true
+ else
+ false
+ end
+ end
+
+=begin
+ # move to Tk::Text::IndexModMethods module
+ def +(mod)
+ return chars(mod) if mod.kind_of?(Numeric)
+
+ mod = mod.to_s
+ if mod =~ /^\s*[+-]?\d/
+ Tk::Text::IndexString.new(@id + ' + ' + mod)
+ else
+ Tk::Text::IndexString.new(@id + ' ' + mod)
+ end
+ end
+
+ def -(mod)
+ return chars(-mod) if mod.kind_of?(Numeric)
+
+ mod = mod.to_s
+ if mod =~ /^\s*[+-]?\d/
+ Tk::Text::IndexString.new(@id + ' - ' + mod)
+ elsif mod =~ /^\s*[-]\s+(\d.*)$/
+ Tk::Text::IndexString.new(@id + ' - -' + $1)
+ else
+ Tk::Text::IndexString.new(@id + ' ' + mod)
+ end
+ end
+=end
+
+ def pos
+ @t.index(@id)
+ end
+
+ def pos=(where)
+ set(where)
+ end
+
+ def set(where)
+ tk_call_without_enc(@t.path, 'mark', 'set', @id,
+ _get_eval_enc_str(where))
+ self
+ end
+
+ def unset
+ tk_call_without_enc(@t.path, 'mark', 'unset', @id)
+ self
+ end
+ alias destroy unset
+
+ def gravity
+ tk_call_without_enc(@t.path, 'mark', 'gravity', @id)
+ end
+
+ def gravity=(direction)
+ tk_call_without_enc(@t.path, 'mark', 'gravity', @id, direction)
+ #self
+ direction
+ end
+
+ def next(index = nil)
+ if index
+ @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'next', _get_eval_enc_str(index))))
+ else
+ @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'next', @id)))
+ end
+ end
+
+ def previous(index = nil)
+ if index
+ @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'previous', _get_eval_enc_str(index))))
+ else
+ @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'previous', @id)))
+ end
+ end
+end
+TktMark = TkTextMark
+
+class TkTextNamedMark<TkTextMark
+ def self.new(parent, name, index=nil)
+ TMarkID_TBL.mutex.synchronize{
+ if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
+ obj = TMarkID_TBL[parent.path][name]
+ else
+ # super(parent, name, *args)
+ (obj = self.allocate).instance_eval{
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ TMarkID_TBL[@id] = self
+ TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
+ TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
+ @t._addtag @id, self
+ }
+ obj
+ end
+
+ if obj && index
+ tk_call_without_enc(parent.path, 'mark', 'set', name,
+ _get_eval_enc_str(index))
+ end
+ obj
+ }
+ end
+
+ def initialize(parent, name, index=nil)
+ # dummy:: not called by 'new' method
+
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
+ #end
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ tk_call_without_enc(@t.path, 'mark', 'set', @id,
+ _get_eval_enc_str(index)) if index
+ @t._addtag @id, self
+ end
+end
+TktNamedMark = TkTextNamedMark
+
+class TkTextMarkInsert<TkTextNamedMark
+ def self.new(parent,*args)
+ super(parent, 'insert', *args)
+ end
+end
+TktMarkInsert = TkTextMarkInsert
+
+class TkTextMarkCurrent<TkTextNamedMark
+ def self.new(parent,*args)
+ super(parent, 'current', *args)
+ end
+end
+TktMarkCurrent = TkTextMarkCurrent
+
+class TkTextMarkAnchor<TkTextNamedMark
+ def self.new(parent,*args)
+ super(parent, 'anchor', *args)
+ end
+end
+TktMarkAnchor = TkTextMarkAnchor
diff --git a/ext/tk/lib/tk/texttag.rb b/ext/tk/lib/tk/texttag.rb
new file mode 100644
index 0000000000..b08d923ea1
--- /dev/null
+++ b/ext/tk/lib/tk/texttag.rb
@@ -0,0 +1,318 @@
+#
+# tk/texttag.rb - methods for treating text tags
+#
+require 'tk'
+require 'tk/text'
+require 'tk/tagfont'
+
+class TkTextTag<TkObject
+ include TkTreatTagFont
+ include Tk::Text::IndexModMethods
+
+ TTagID_TBL = TkCore::INTERP.create_table
+
+ (Tk_TextTag_ID = ['tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TTagID_TBL.mutex.synchronize{ TTagID_TBL.clear }
+ }
+
+ def TkTextTag.id2obj(text, id)
+ tpath = text.path
+ TTagID_TBL.mutex.synchronize{
+ if TTagID_TBL[tpath]
+ TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(parent, *args)
+ #unless parent.kind_of?(TkText)
+ # fail ArgumentError, "expect TkText for 1st argument"
+ #end
+ @parent = @t = parent
+ @tpath = parent.path
+ Tk_TextTag_ID.mutex.synchronize{
+ # @path = @id = Tk_TextTag_ID.join('')
+ @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze
+ Tk_TextTag_ID[1].succ!
+ }
+ TTagID_TBL.mutex.synchronize{
+ TTagID_TBL[@id] = self
+ TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
+ TTagID_TBL[@tpath][@id] = self
+ }
+ #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
+ if args != []
+ keys = args.pop
+ if keys.kind_of?(Hash)
+ add(*args) if args != []
+ configure(keys)
+ else
+ args.push keys
+ add(*args)
+ end
+ end
+ @t._addtag id, self
+ end
+
+ def id
+ Tk::Text::IndexString.new(@id)
+ end
+
+ def exist?
+ #if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'names'))).find{|id| id == @id } )
+ if ( tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'names'), false, true).find{|id| id == @id } )
+ true
+ else
+ false
+ end
+ end
+
+ def first
+ Tk::Text::IndexString.new(@id + '.first')
+ end
+
+ def last
+ Tk::Text::IndexString.new(@id + '.last')
+ end
+
+ def add(*indices)
+ tk_call_without_enc(@t.path, 'tag', 'add', @id,
+ *(indices.collect{|idx| _get_eval_enc_str(idx)}))
+ self
+ end
+
+ def remove(*indices)
+ tk_call_without_enc(@t.path, 'tag', 'remove', @id,
+ *(indices.collect{|idx| _get_eval_enc_str(idx)}))
+ self
+ end
+
+ def ranges
+ l = tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'ranges', @id))
+ r = []
+ while key=l.shift
+ r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)]
+ end
+ r
+ end
+
+ def nextrange(first, last=None)
+ simplelist(tk_call_without_enc(@t.path, 'tag', 'nextrange', @id,
+ _get_eval_enc_str(first),
+ _get_eval_enc_str(last))).collect{|idx|
+ Tk::Text::IndexString.new(idx)
+ }
+ end
+
+ def prevrange(first, last=None)
+ simplelist(tk_call_without_enc(@t.path, 'tag', 'prevrange', @id,
+ _get_eval_enc_str(first),
+ _get_eval_enc_str(last))).collect{|idx|
+ Tk::Text::IndexString.new(idx)
+ }
+ end
+
+ def [](key)
+ cget key
+ end
+
+ def []=(key,val)
+ configure key, val
+ val
+ end
+
+ def cget(key)
+ @t.tag_cget @id, key
+ end
+ def cget_strict(key)
+ @t.tag_cget_strict @id, key
+ end
+=begin
+ def cget(key)
+ case key.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ _fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget', @id, "-#{key}"))
+ when 'font', 'kanjifont'
+ #fnt = tk_tcl2ruby(tk_call(@t.path, 'tag', 'cget', @id, "-#{key}"))
+ fnt = tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget',
+ @id, '-font')))
+ unless fnt.kind_of?(TkFont)
+ fnt = tagfontobj(@id, fnt)
+ end
+ if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
+ # obsolete; just for compatibility
+ fnt.kanji_font
+ else
+ fnt
+ end
+ else
+ tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget',
+ @id, "-#{key}")))
+ end
+ end
+=end
+
+ def configure(key, val=None)
+ @t.tag_configure @id, key, val
+ end
+# def configure(key, val=None)
+# if key.kind_of?(Hash)
+# tk_call @t.path, 'tag', 'configure', @id, *hash_kv(key)
+# else
+# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", val
+# end
+# end
+# def configure(key, value)
+# if value == FALSE
+# value = "0"
+# elsif value.kind_of?(Proc)
+# value = install_cmd(value)
+# end
+# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", value
+# end
+
+ def configinfo(key=nil)
+ @t.tag_configinfo @id, key
+ end
+
+ def current_configinfo(key=nil)
+ @t.current_tag_configinfo @id, key
+ end
+
+ #def bind(seq, cmd=Proc.new, *args)
+ # _bind([@t.path, 'tag', 'bind', @id], seq, cmd, *args)
+ # self
+ #end
+ def bind(seq, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([@t.path, 'tag', 'bind', @id], seq, cmd, *args)
+ self
+ end
+
+ #def bind_append(seq, cmd=Proc.new, *args)
+ # _bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, *args)
+ # self
+ #end
+ def bind_append(seq, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, *args)
+ self
+ end
+
+ def bind_remove(seq)
+ _bind_remove([@t.path, 'tag', 'bind', @id], seq)
+ self
+ end
+
+ def bindinfo(context=nil)
+ _bindinfo([@t.path, 'tag', 'bind', @id], context)
+ end
+
+ def raise(above=None)
+ tk_call_without_enc(@t.path, 'tag', 'raise', @id,
+ _get_eval_enc_str(above))
+ self
+ end
+
+ def lower(below=None)
+ tk_call_without_enc(@t.path, 'tag', 'lower', @id,
+ _get_eval_enc_str(below))
+ self
+ end
+
+ def destroy
+ tk_call_without_enc(@t.path, 'tag', 'delete', @id)
+ TTagID_TBL.mutex.synchronize{
+ TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
+ }
+ self
+ end
+end
+TktTag = TkTextTag
+
+class TkTextNamedTag<TkTextTag
+ def self.new(parent, name, *args)
+ tagobj = nil
+ TTagID_TBL.mutex.synchronize{
+ if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
+ tagobj = TTagID_TBL[parent.path][name]
+ else
+ # super(parent, name, *args)
+ (tagobj = self.allocate).instance_eval{
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ TTagID_TBL[@id] = self
+ TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
+ TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id]
+ @t._addtag @id, self
+ }
+ end
+ }
+
+ if args != []
+ keys = args.pop
+ if keys.kind_of?(Hash)
+ tagobj.add(*args) if args != []
+ tagobj.configure(keys)
+ else
+ args.push keys
+ tagobj.add(*args)
+ end
+ end
+
+ tagobj
+ end
+
+ def initialize(parent, name, *args)
+ # dummy:: not called by 'new' method
+
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
+ #end
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+
+ #if mode
+ # tk_call @t.path, "addtag", @id, *args
+ #end
+ if args != []
+ keys = args.pop
+ if keys.kind_of?(Hash)
+ add(*args) if args != []
+ configure(keys)
+ else
+ args.push keys
+ add(*args)
+ end
+ end
+ @t._addtag @id, self
+ end
+end
+TktNamedTag = TkTextNamedTag
+
+class TkTextTagSel<TkTextNamedTag
+ def self.new(parent, *args)
+ super(parent, 'sel', *args)
+ end
+end
+TktTagSel = TkTextTagSel
diff --git a/ext/tk/lib/tk/textwindow.rb b/ext/tk/lib/tk/textwindow.rb
new file mode 100644
index 0000000000..004422e4f3
--- /dev/null
+++ b/ext/tk/lib/tk/textwindow.rb
@@ -0,0 +1,154 @@
+#
+# tk/textwindow.rb - treat Tk text window object
+#
+require 'tk'
+require 'tk/text'
+
+class TkTextWindow<TkObject
+ include Tk::Text::IndexModMethods
+
+ def initialize(parent, index, keys = {})
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
+ #end
+ @t = parent
+ if index == 'end' || index == :end
+ @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
+ 'end - 1 chars'))
+ elsif index.kind_of?(TkTextMark)
+ if tk_call_without_enc(@t.path,'index',index.path) == tk_call_without_enc(@t.path,'index','end')
+ @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
+ 'end - 1 chars'))
+ else
+ @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
+ index.path))
+ end
+ else
+ @path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index', _get_eval_enc_str(index)))
+ end
+ @path.gravity = 'left'
+ @index = @path.path
+ keys = _symbolkey2str(keys)
+ @id = keys['window']
+ # keys['window'] = @id.epath if @id.kind_of?(TkWindow)
+ keys['window'] = _epath(@id) if @id
+ if keys['create']
+ @p_create = keys['create']
+ # if @p_create.kind_of?(Proc)
+ if TkComm._callback_entry?(@p_create)
+=begin
+ keys['create'] = install_cmd(proc{
+ @id = @p_create.call
+ if @id.kind_of?(TkWindow)
+ @id.epath
+ else
+ @id
+ end
+ })
+=end
+ keys['create'] = install_cmd(proc{@id = @p_create.call; _epath(@id)})
+ end
+ end
+ tk_call_without_enc(@t.path, 'window', 'create', @index,
+ *hash_kv(keys, true))
+ @path.gravity = 'right'
+ end
+
+ def id
+ Tk::Text::IndexString.new(_epath(@id))
+ end
+ def mark
+ @path
+ end
+
+ def [](slot)
+ cget(slot)
+ end
+ def []=(slot, value)
+ configure(slot, value)
+ value
+ end
+
+ def cget(slot)
+ @t.window_cget(@index, slot)
+ end
+ def cget_strict(slot)
+ @t.window_cget_strict(@index, slot)
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ if slot['window']
+ @id = slot['window']
+ # slot['window'] = @id.epath if @id.kind_of?(TkWindow)
+ slot['window'] = _epath(@id) if @id
+ end
+ if slot['create']
+ self.create=slot.delete('create')
+ end
+ if slot.size > 0
+ tk_call_without_enc(@t.path, 'window', 'configure', @index,
+ *hash_kv(slot, true))
+ end
+ else
+ if slot == 'window' || slot == :window
+ @id = value
+ # value = @id.epath if @id.kind_of?(TkWindow)
+ value = _epath(@id) if @id
+ end
+ if slot == 'create' || slot == :create
+ self.create=value
+ else
+ tk_call_without_enc(@t.path, 'window', 'configure', @index,
+ "-#{slot}", _get_eval_enc_str(value))
+ end
+ end
+ self
+ end
+
+ def configinfo(slot = nil)
+ @t.window_configinfo(@index, slot)
+ end
+
+ def current_configinfo(slot = nil)
+ @t.current_window_configinfo(@index, slot)
+ end
+
+ def window
+ @id
+ end
+
+ def window=(value)
+ @id = value
+ # value = @id.epath if @id.kind_of?(TkWindow)
+ value = _epath(@id) if @id
+ tk_call_without_enc(@t.path, 'window', 'configure', @index,
+ '-window', _get_eval_enc_str(value))
+ value
+ end
+
+ def create
+ @p_create
+ end
+
+ def create=(value)
+ @p_create = value
+ # if @p_create.kind_of?(Proc)
+ if TkComm._callback_entry?(@p_create)
+ value = install_cmd(proc{
+ @id = @p_create.call
+ if @id.kind_of?(TkWindow)
+ @id.epath
+ else
+ @id
+ end
+ })
+ end
+ tk_call_without_enc(@t.path, 'window', 'configure', @index,
+ '-create', _get_eval_enc_str(value))
+ value
+ end
+end
+
+TktWindow = TkTextWindow
diff --git a/ext/tk/lib/tk/timer.rb b/ext/tk/lib/tk/timer.rb
new file mode 100644
index 0000000000..91840d0575
--- /dev/null
+++ b/ext/tk/lib/tk/timer.rb
@@ -0,0 +1,669 @@
+#
+# tk/timer.rb : methods for Tcl/Tk after command
+#
+# $Id$
+#
+require 'tk'
+
+class TkTimer
+ include TkCore
+ extend TkCore
+
+ TkCommandNames = ['after'.freeze].freeze
+
+ (Tk_CBID = ['a'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ Tk_CBTBL = {}.taint
+
+ TkCore::INTERP.add_tk_procs('rb_after', 'id', <<-'EOL')
+ if {[set st [catch {eval {ruby_cmd TkTimer callback} $id} ret]] != 0} {
+ return -code $st $ret
+ } {
+ return $ret
+ }
+ EOL
+
+ DEFAULT_IGNORE_EXCEPTIONS = [ NameError, RuntimeError ].freeze
+
+ ###############################
+ # class methods
+ ###############################
+ def self.start(*args, &b)
+ self.new(*args, &b).start
+ end
+
+ def self.callback(obj_id)
+ ex_obj = Tk_CBTBL[obj_id]
+ return "" if ex_obj == nil; # canceled
+ ex_obj.cb_call
+ end
+
+ def self.info(obj = nil)
+ if obj
+ if obj.kind_of?(TkTimer)
+ if obj.after_id
+ inf = tk_split_list(tk_call_without_enc('after','info',obj.after_id))
+ [Tk_CBTBL[inf[0][1]], inf[1]]
+ else
+ nil
+ end
+ else
+ fail ArgumentError, "TkTimer object is expected"
+ end
+ else
+ tk_call_without_enc('after', 'info').split(' ').collect!{|id|
+ ret = Tk_CBTBL.find{|key,val| val.after_id == id}
+ (ret == nil)? id: ret[1]
+ }
+ end
+ end
+
+
+ ###############################
+ # instance methods
+ ###############################
+ def do_callback
+ @in_callback = true
+ @after_id = nil
+ begin
+ @return_value = @current_proc.call(self)
+ rescue SystemExit
+ exit(0)
+ rescue Interrupt
+ exit!(1)
+ rescue Exception => e
+ if @cancel_on_exception &&
+ @cancel_on_exception.find{|exc| e.kind_of?(exc)}
+ cancel
+ @return_value = e
+ @in_callback = false
+ return e
+ else
+ fail e
+ end
+ end
+ if @set_next
+ set_next_callback(@current_args)
+ else
+ @set_next = true
+ end
+ @in_callback = false
+ @return_value
+ end
+
+ def set_callback(sleep, args=nil)
+ if TkCore::INTERP.deleted?
+ self.cancel
+ return self
+ end
+ @after_script = "rb_after #{@id}"
+ @current_args = args
+ @current_script = [sleep, @after_script]
+ @after_id = tk_call_without_enc('after', sleep, @after_script)
+ self
+ end
+
+ def set_next_callback(args)
+ if @running == false || @proc_max == 0 || @do_loop == 0
+ Tk_CBTBL.delete(@id) ;# for GC
+ @running = false
+ # @wait_var.value = 0
+ __at_end__
+ return
+ end
+ if @current_pos >= @proc_max
+ if @do_loop < 0 || (@do_loop -= 1) > 0
+ @current_pos = 0
+ else
+ Tk_CBTBL.delete(@id) ;# for GC
+ @running = false
+ # @wait_var.value = 0
+ __at_end__
+ return
+ end
+ end
+
+ @current_args = args
+
+ # if @sleep_time.kind_of?(Proc)
+ if TkComm._callback_entry?(@sleep_time)
+ sleep = @sleep_time.call(self)
+ else
+ sleep = @sleep_time
+ end
+ @current_sleep = sleep
+
+ cmd, *cmd_args = @loop_proc[@current_pos]
+ @current_pos += 1
+ @current_proc = cmd
+
+ set_callback(sleep, cmd_args)
+ end
+
+ def initialize(*args, &b)
+ Tk_CBID.mutex.synchronize{
+ # @id = Tk_CBID.join('')
+ @id = Tk_CBID.join(TkCore::INTERP._ip_id_)
+ Tk_CBID[1].succ!
+ }
+
+ @wait_var = TkVariable.new(0)
+
+ @at_end_proc = nil
+
+ @cb_cmd = TkCore::INTERP.get_cb_entry(self.method(:do_callback))
+
+ @set_next = true
+
+ @init_sleep = 0
+ @init_proc = nil
+ @init_args = []
+
+ @current_script = []
+ @current_proc = nil
+ @current_args = nil
+ @return_value = nil
+
+ @sleep_time = 0
+ @current_sleep = 0
+ @loop_exec = 0
+ @do_loop = 0
+ @loop_proc = []
+ @proc_max = 0
+ @current_pos = 0
+
+ @after_id = nil
+ @after_script = nil
+
+ @cancel_on_exception = DEFAULT_IGNORE_EXCEPTIONS
+ # Unless @cancel_on_exception, Ruby/Tk shows an error dialog box when
+ # an excepsion is raised on TkTimer callback procedure.
+ # If @cancel_on_exception is an array of exception classes and the raised
+ # exception is included in the array, Ruby/Tk cancels executing TkTimer
+ # callback procedures silently (TkTimer#cancel is called and no dialog is
+ # shown).
+
+ if b
+ case args.size
+ when 0
+ add_procs(b)
+ when 1
+ args << -1 << b
+ else
+ args << b
+ end
+ end
+
+ set_procs(*args) if args != []
+
+ @running = false
+ @in_callback = false
+ end
+
+ attr :after_id
+ attr :after_script
+ attr :current_proc
+ attr :current_args
+ attr :current_sleep
+ alias :current_interval :current_sleep
+ attr :return_value
+
+ attr_accessor :loop_exec
+
+ def __at_end__
+ @at_end_proc.call(self) if @at_end_proc
+ @wait_var.value = 0 # for wait
+ end
+ private :__at_end__
+
+ def cb_call
+ @cb_cmd.call
+ end
+
+ def get_procs
+ [@init_sleep, @init_proc, @init_args, @sleep_time, @loop_exec, @loop_proc]
+ end
+
+ def current_status
+ [@running, @current_sleep, @current_proc, @current_args,
+ @do_loop, @cancel_on_exception]
+ end
+
+ def cancel_on_exception?
+ @cancel_on_exception
+ end
+
+ def cancel_on_exception=(mode)
+ if mode.kind_of?(Array)
+ @cancel_on_exception = mode
+ elsif mode
+ @cancel_on_exception = DEFAULT_IGNORE_EXCEPTIONS
+ else
+ @cancel_on_exception = false
+ end
+ #self
+ end
+
+ def running?
+ @running
+ end
+
+ def loop_rest
+ @do_loop
+ end
+
+ def loop_rest=(rest)
+ @do_loop = rest
+ #self
+ end
+
+ def set_interval(interval)
+ #if interval != 'idle' && interval != :idle \
+ # && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
+ if interval != 'idle' && interval != :idle \
+ && !interval.kind_of?(Integer) && !TkComm._callback_entry?(interval)
+ fail ArgumentError, "expect Integer or Proc"
+ end
+ @sleep_time = interval
+ end
+
+ def set_procs(interval, loop_exec, *procs)
+ #if interval != 'idle' && interval != :idle \
+ # && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
+ if interval != 'idle' && interval != :idle \
+ && !interval.kind_of?(Integer) && !TkComm._callback_entry?(interval)
+ fail ArgumentError, "expect Integer or Proc for 1st argument"
+ end
+ @sleep_time = interval
+
+ @loop_proc = []
+ procs.each{|e|
+ # if e.kind_of?(Proc)
+ if TkComm._callback_entry?(e)
+ @loop_proc.push([e])
+ else
+ @loop_proc.push(e)
+ end
+ }
+ @proc_max = @loop_proc.size
+ @current_pos = 0
+
+ if loop_exec.kind_of?(Integer) && loop_exec < 0
+ @loop_exec = -1
+ elsif loop_exec == true
+ @loop_exec = -1
+ elsif loop_exec == nil || loop_exec == false || loop_exec == 0
+ @loop_exec = 0
+ else
+ if not loop_exec.kind_of?(Integer)
+ fail ArgumentError, "expect Integer for 2nd argument"
+ end
+ @loop_exec = loop_exec
+ end
+ @do_loop = @loop_exec
+
+ self
+ end
+
+ def add_procs(*procs)
+ procs.each{|e|
+ # if e.kind_of?(Proc)
+ if TkComm._callback_entry?(e)
+ @loop_proc.push([e])
+ else
+ @loop_proc.push(e)
+ end
+ }
+ @proc_max = @loop_proc.size
+
+ self
+ end
+
+ def delete_procs(*procs)
+ procs.each{|e|
+ # if e.kind_of?(Proc)
+ if TkComm._callback_entry?(e)
+ @loop_proc.delete([e])
+ else
+ @loop_proc.delete(e)
+ end
+ }
+ @proc_max = @loop_proc.size
+
+ cancel if @proc_max == 0
+
+ self
+ end
+
+ def delete_at(n)
+ @loop_proc.delete_at(n)
+ @proc_max = @loop_proc.size
+ cancel if @proc_max == 0
+ self
+ end
+
+ def set_start_proc(sleep=nil, init_proc=nil, *init_args, &b)
+ # set parameters for 'restart'
+ sleep = @init_sleep unless sleep
+
+ if sleep != 'idle' && sleep != :idle && !sleep.kind_of?(Integer)
+ fail ArgumentError, "expect Integer or 'idle' for 1st argument"
+ end
+
+ @init_sleep = sleep
+ @init_proc = init_proc
+ @init_args = init_args
+
+ @init_proc = b if !@init_proc && b
+ @init_proc = proc{|*args| } if @init_sleep > 0 && !@init_proc
+
+ self
+ end
+
+ def start(*init_args, &b)
+ return nil if @running
+
+ Tk_CBTBL[@id] = self
+ @do_loop = @loop_exec
+ @current_pos = 0
+ @return_value = nil
+ @after_id = nil
+
+ @init_sleep = 0
+ @init_proc = nil
+ @init_args = nil
+
+ argc = init_args.size
+ if argc > 0
+ sleep = init_args.shift
+ if sleep != 'idle' && sleep != :idle && !sleep.kind_of?(Integer)
+ fail ArgumentError, "expect Integer or 'idle' for 1st argument"
+ end
+ @init_sleep = sleep
+ end
+ @init_proc = init_args.shift if argc > 1
+ @init_args = init_args if argc > 2
+
+ @init_proc = b if !@init_proc && b
+ @init_proc = proc{|*args| } if @init_sleep > 0 && !@init_proc
+
+ @current_sleep = @init_sleep
+ @running = true
+ if @init_proc
+ # if not @init_proc.kind_of?(Proc)
+ if !TkComm._callback_entry?(@init_proc)
+ fail ArgumentError, "Argument '#{@init_proc}' need to be Proc"
+ end
+ @current_proc = @init_proc
+ set_callback(@init_sleep, @init_args)
+ @set_next = false if @in_callback
+ else
+ set_next_callback(@init_args)
+ end
+
+ self
+ end
+
+ def reset(*reset_args)
+ restart() if @running
+
+ if @init_proc
+ @return_value = @init_proc.call(self)
+ else
+ @return_value = nil
+ end
+
+ @current_pos = 0
+ @current_args = @init_args
+ @current_script = []
+
+ @set_next = false if @in_callback
+
+ self
+ end
+
+ def restart(*restart_args, &b)
+ cancel if @running
+ if restart_args == [] && !b
+ start(@init_sleep, @init_proc, *@init_args)
+ else
+ start(*restart_args, &b)
+ end
+ end
+
+ def cancel
+ @running = false
+ # @wait_var.value = 0
+ __at_end__
+ tk_call 'after', 'cancel', @after_id if @after_id
+ @after_id = nil
+
+ Tk_CBTBL.delete(@id) ;# for GC
+ self
+ end
+ alias stop cancel
+
+ def continue(wait=nil)
+ fail RuntimeError, "is already running" if @running
+ return restart() if @current_script.empty?
+ sleep, cmd = @current_script
+ fail RuntimeError, "no procedure to continue" unless cmd
+ if wait
+ unless wait.kind_of?(Integer)
+ fail ArgumentError, "expect Integer for 1st argument"
+ end
+ sleep = wait
+ end
+ Tk_CBTBL[@id] = self
+ @running = true
+ @after_id = tk_call_without_enc('after', sleep, cmd)
+ self
+ end
+
+ def skip
+ fail RuntimeError, "is not running now" unless @running
+ cancel
+ Tk_CBTBL[@id] = self
+ @running = true
+ set_next_callback(@current_args)
+ self
+ end
+
+ def info
+ if @after_id
+ inf = tk_split_list(tk_call_without_enc('after', 'info', @after_id))
+ [Tk_CBTBL[inf[0][1]], inf[1]]
+ else
+ nil
+ end
+ end
+
+ def at_end(*arg, &b)
+ if arg.empty?
+ if b
+ @at_end_proc = b
+ else
+ # no proc
+ return @at_end_proc
+ end
+ else
+ fail ArgumentError, "wrong number of arguments" if arg.length != 1 || b
+ @at_end_proc = arg[0]
+ end
+ self
+ end
+
+ def wait(on_thread = true, check_root = false)
+ if $SAFE >= 4
+ fail SecurityError, "can't wait timer at $SAFE >= 4"
+ end
+
+ unless @running
+ if @return_value.kind_of?(Exception)
+ fail @return_value
+ else
+ return @return_value
+ end
+ end
+
+ @wait_var.wait(on_thread, check_root)
+ if @return_value.kind_of?(Exception)
+ fail @return_value
+ else
+ @return_value
+ end
+ end
+ def eventloop_wait(check_root = false)
+ wait(false, check_root)
+ end
+ def thread_wait(check_root = false)
+ wait(true, check_root)
+ end
+ def tkwait(on_thread = true)
+ wait(on_thread, true)
+ end
+ def eventloop_tkwait
+ wait(false, true)
+ end
+ def thread_tkwait
+ wait(true, true)
+ end
+end
+
+TkAfter = TkTimer
+
+
+class TkRTTimer < TkTimer
+ DEFAULT_OFFSET_LIST_SIZE = 5
+
+ def initialize(*args, &b)
+ super(*args, &b)
+
+ @offset_list = Array.new(DEFAULT_OFFSET_LIST_SIZE){ [0, 0] }
+ @offset_s = 0
+ @offset_u = 0
+ @est_time = nil
+ end
+
+ def start(*args, &b)
+ return nil if @running
+ @est_time = nil
+ @cb_start_time = Time.now
+ super(*args, &b)
+ end
+
+ def cancel
+ super()
+ @est_time = nil
+ @cb_start_time = Time.now
+ self
+ end
+ alias stop cancel
+
+ def continue(wait=nil)
+ fail RuntimeError, "is already running" if @running
+ @cb_start_time = Time.now
+ super(wait)
+ end
+
+ def set_interval(interval)
+ super(interval)
+ @est_time = nil
+ end
+
+ def _offset_ave
+ size = 0
+ d_sec = 0; d_usec = 0
+ @offset_list.each_with_index{|offset, idx|
+ # weight = 1
+ weight = idx + 1
+ size += weight
+ d_sec += offset[0] * weight
+ d_usec += offset[1] * weight
+ }
+ offset_s, mod = d_sec.divmod(size)
+ offset_u = ((mod * 1000000 + d_usec) / size.to_f).round
+ [offset_s, offset_u]
+ end
+ private :_offset_ave
+
+ def set_next_callback(args)
+ if @running == false || @proc_max == 0 || @do_loop == 0
+ Tk_CBTBL.delete(@id) ;# for GC
+ @running = false
+ # @wait_var.value = 0
+ __at_end__
+ return
+ end
+ if @current_pos >= @proc_max
+ if @do_loop < 0 || (@do_loop -= 1) > 0
+ @current_pos = 0
+ else
+ Tk_CBTBL.delete(@id) ;# for GC
+ @running = false
+ # @wait_var.value = 0
+ __at_end__
+ return
+ end
+ end
+
+ @current_args = args
+
+ cmd, *cmd_args = @loop_proc[@current_pos]
+ @current_pos += 1
+ @current_proc = cmd
+
+ @offset_s, @offset_u = _offset_ave
+
+ if TkComm._callback_entry?(@sleep_time)
+ sleep = @sleep_time.call(self)
+ else
+ sleep = @sleep_time
+ end
+
+ if @est_time
+ @est_time = Time.at(@est_time.to_i, @est_time.usec + sleep*1000)
+ else
+ @est_time = Time.at(@cb_start_time.to_i,
+ @cb_start_time.usec + sleep*1000)
+ end
+
+ now = Time.now
+ real_sleep = ((@est_time.to_i - now.to_i + @offset_s)*1000.0 +
+ (@est_time.usec - now.usec + @offset_u)/1000.0).round
+ if real_sleep <= 0
+ real_sleep = 0
+ @offset_s = now.to_i
+ @offset_u = now.usec
+ end
+ @current_sleep = real_sleep
+
+ set_callback(real_sleep, cmd_args)
+ end
+
+ def cb_call
+ if @est_time
+ @offset_list.shift
+
+ @cb_start_time = Time.now
+
+ if @current_sleep == 0
+ @offset_list.push([
+ @offset_s - @cb_start_time.to_i,
+ @offset_u - @cb_start_time.usec
+ ])
+ else
+ @offset_list.push([
+ @offset_s + (@est_time.to_i - @cb_start_time.to_i),
+ @offset_u + (@est_time.usec - @cb_start_time.usec)
+ ])
+ end
+ end
+
+ @cb_cmd.call
+ end
+end
diff --git a/ext/tk/lib/tk/toplevel.rb b/ext/tk/lib/tk/toplevel.rb
new file mode 100644
index 0000000000..bd6e8307f5
--- /dev/null
+++ b/ext/tk/lib/tk/toplevel.rb
@@ -0,0 +1,262 @@
+#
+# tk/toplevel.rb : treat toplevel widget
+#
+require 'tk'
+require 'tk/wm'
+require 'tk/menuspec'
+
+class Tk::Toplevel<TkWindow
+ include Wm
+ include TkMenuSpec
+
+ TkCommandNames = ['toplevel'.freeze].freeze
+ WidgetClassName = 'Toplevel'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+################# old version
+# def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
+# if screen.kind_of? Hash
+# keys = screen.dup
+# else
+# @screen = screen
+# end
+# @classname = classname
+# if keys.kind_of? Hash
+# keys = keys.dup
+# @classname = keys.delete('classname') if keys.key?('classname')
+# @colormap = keys.delete('colormap') if keys.key?('colormap')
+# @container = keys.delete('container') if keys.key?('container')
+# @screen = keys.delete('screen') if keys.key?('screen')
+# @use = keys.delete('use') if keys.key?('use')
+# @visual = keys.delete('visual') if keys.key?('visual')
+# end
+# super(parent, keys)
+# end
+#
+# def create_self
+# s = []
+# s << "-class" << @classname if @classname
+# s << "-colormap" << @colormap if @colormap
+# s << "-container" << @container if @container
+# s << "-screen" << @screen if @screen
+# s << "-use" << @use if @use
+# s << "-visual" << @visual if @visual
+# tk_call 'toplevel', @path, *s
+# end
+#################
+
+ def __boolval_optkeys
+ super() << 'container'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'screen'
+ end
+ private :__strval_optkeys
+
+ def __val2ruby_optkeys # { key=>proc, ... }
+ super().update('menu'=>proc{|v| window(v)})
+ end
+ private :__val2ruby_optkeys
+
+ def __methodcall_optkeys # { key=>method, ... }
+ TOPLEVEL_METHODCALL_OPTKEYS
+ end
+ private :__methodcall_optkeys
+
+ def _wm_command_option_chk(keys)
+ keys = {} unless keys
+ new_keys = {}
+ wm_cmds = {}
+
+ conf_methods = _symbolkey2str(__methodcall_optkeys())
+
+ keys.each{|k,v| # k is a String
+ if conf_methods.key?(k)
+ wm_cmds[conf_methods[k]] = v
+ elsif Wm.method_defined?(k)
+ case k
+ when 'screen','class','colormap','container','use','visual'
+ new_keys[k] = v
+ else
+ case self.method(k).arity
+ when -1,1
+ wm_cmds[k] = v
+ else
+ new_keys[k] = v
+ end
+ end
+ else
+ new_keys[k] = v
+ end
+ }
+ [new_keys, wm_cmds]
+ end
+ private :_wm_command_option_chk
+
+ def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
+ my_class_name = nil
+ if self.class < WidgetClassNames[WidgetClassName]
+ my_class_name = self.class.name
+ my_class_name = nil if my_class_name == ''
+ end
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ if keys.key?('classname')
+ keys['class'] = keys.delete('classname')
+ end
+ @classname = keys['class']
+ @colormap = keys['colormap']
+ @container = keys['container']
+ @screen = keys['screen']
+ @use = keys['use']
+ @visual = keys['visual']
+ if !@classname && my_class_name
+ keys['class'] = @classname = my_class_name
+ end
+ if @classname.kind_of? TkBindTag
+ @db_class = @classname
+ keys['class'] = @classname = @classname.id
+ elsif @classname
+ @db_class = TkDatabaseClass.new(@classname)
+ keys['class'] = @classname
+ else
+ @db_class = self.class
+ @classname = @db_class::WidgetClassName
+ end
+ keys, cmds = _wm_command_option_chk(keys)
+ super(keys)
+ cmds.each{|k,v|
+ if v.kind_of? Array
+ self.__send__(k,*v)
+ else
+ self.__send__(k,v)
+ end
+ }
+ return
+ end
+
+ if screen.kind_of? Hash
+ keys = screen
+ else
+ @screen = screen
+ if classname.kind_of? Hash
+ keys = classname
+ else
+ @classname = classname
+ end
+ end
+ if keys.kind_of? Hash
+ keys = _symbolkey2str(keys)
+ if keys.key?('classname')
+ keys['class'] = keys.delete('classname')
+ end
+ @classname = keys['class'] unless @classname
+ @colormap = keys['colormap']
+ @container = keys['container']
+ @screen = keys['screen'] unless @screen
+ @use = keys['use']
+ @visual = keys['visual']
+ else
+ keys = {}
+ end
+ if !@classname && my_class_name
+ keys['class'] = @classname = my_class_name
+ end
+ if @classname.kind_of? TkBindTag
+ @db_class = @classname
+ keys['class'] = @classname = @classname.id
+ elsif @classname
+ @db_class = TkDatabaseClass.new(@classname)
+ keys['class'] = @classname
+ else
+ @db_class = self.class
+ @classname = @db_class::WidgetClassName
+ end
+ keys, cmds = _wm_command_option_chk(keys)
+ super(parent, keys)
+ cmds.each{|k,v|
+ if v.kind_of? Array
+ self.send(k,*v)
+ else
+ self.send(k,v)
+ end
+ }
+ end
+
+ #def create_self(keys)
+ # if keys and keys != None
+ # tk_call_without_enc('toplevel', @path, *hash_kv(keys, true))
+ # else
+ # tk_call_without_enc('toplevel', @path)
+ # end
+ #end
+ #private :create_self
+
+ def specific_class
+ @classname
+ end
+
+ def add_menu(menu_info, tearoff=false, opts=nil)
+ # See tk/menuspec.rb for menu_info.
+ # opts is a hash of default configs for all of cascade menus.
+ # Configs of menu_info can override it.
+ if tearoff.kind_of?(Hash)
+ opts = tearoff
+ tearoff = false
+ end
+ _create_menubutton(self, menu_info, tearoff, opts)
+ end
+
+ def add_menubar(menu_spec, tearoff=false, opts=nil)
+ # See tk/menuspec.rb for menu_spec.
+ # opts is a hash of default configs for all of cascade menus.
+ # Configs of menu_spec can override it.
+ menu_spec.each{|info| add_menu(info, tearoff, opts)}
+ self.menu
+ end
+
+ def self.database_class
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ self
+ else
+ TkDatabaseClass.new(self.name)
+ end
+ end
+ def self.database_classname
+ self.database_class.name
+ end
+
+ def self.bind(*args, &b)
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ super(*args, &b)
+ else
+ TkDatabaseClass.new(self.name).bind(*args, &b)
+ end
+ end
+ def self.bind_append(*args, &b)
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ super(*args, &b)
+ else
+ TkDatabaseClass.new(self.name).bind_append(*args, &b)
+ end
+ end
+ def self.bind_remove(*args)
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ super(*args)
+ else
+ TkDatabaseClass.new(self.name).bind_remove(*args)
+ end
+ end
+ def self.bindinfo(*args)
+ if self == WidgetClassNames[WidgetClassName] || self.name == ''
+ super(*args)
+ else
+ TkDatabaseClass.new(self.name).bindinfo(*args)
+ end
+ end
+end
+
+#TkToplevel = Tk::Toplevel unless Object.const_defined? :TkToplevel
+Tk.__set_toplevel_aliases__(:Tk, Tk::Toplevel, :TkToplevel)
diff --git a/ext/tk/lib/tk/ttk_selector.rb b/ext/tk/lib/tk/ttk_selector.rb
new file mode 100644
index 0000000000..72ed637a38
--- /dev/null
+++ b/ext/tk/lib/tk/ttk_selector.rb
@@ -0,0 +1,76 @@
+#
+# ttk_selector
+#
+######################################
+# toplevel classes/modules
+module Tk
+ @TOPLEVEL_ALIAS_TABLE[:Ttk] = {
+ :TkButton => 'tkextlib/tile/tbutton',
+
+ :TkCheckbutton => 'tkextlib/tile/tcheckbutton',
+ :TkCheckButton => 'tkextlib/tile/tcheckbutton',
+
+ # :TkDialog => 'tkextlib/tile/dialog',
+
+ :TkEntry => 'tkextlib/tile/tentry',
+
+ :TkCombobox => 'tkextlib/tile/tcombobox',
+
+ :TkFrame => 'tkextlib/tile/tframe',
+
+ :TkLabel => 'tkextlib/tile/tlabel',
+
+ :TkLabelframe => 'tkextlib/tile/tlabelframe',
+ :TkLabelFrame => 'tkextlib/tile/tlabelframe',
+
+ :TkMenubutton => 'tkextlib/tile/tmenubutton',
+ :TkMenuButton => 'tkextlib/tile/tmenubutton',
+
+ :TkNotebook => 'tkextlib/tile/tnotebook',
+
+ # :TkPaned => 'tkextlib/tile/tpaned',
+ :TkPanedwindow => 'tkextlib/tile/tpaned',
+ :TkPanedWindow => 'tkextlib/tile/tpaned',
+
+ :TkProgressbar => 'tkextlib/tile/tprogressbar',
+
+ :TkRadiobutton => 'tkextlib/tile/tradiobutton',
+ :TkRadioButton => 'tkextlib/tile/tradiobutton',
+
+ :TkScale => 'tkextlib/tile/tscale',
+ # :TkProgress => 'tkextlib/tile/tscale',
+
+ :TkScrollbar => 'tkextlib/tile/tscrollbar',
+ :TkXScrollbar => 'tkextlib/tile/tscrollbar',
+ :TkYScrollbar => 'tkextlib/tile/tscrollbar',
+
+ :TkSeparator => 'tkextlib/tile/tseparator',
+
+ :TkSizeGrip => 'tkextlib/tile/sizegrip',
+ :TkSizegrip => 'tkextlib/tile/sizegrip',
+
+ # :TkSquare => 'tkextlib/tile/tsquare',
+
+ :TkTreeview => 'tkextlib/tile/treeview',
+ }
+ @TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk]
+
+ ################################################
+ # register some Ttk widgets as default
+ # (Ttk is a standard library on Tcl/Tk8.5+)
+ @TOPLEVEL_ALIAS_TABLE[:Ttk].each{|sym, file|
+ unless Object.autoload?(sym) || Object.const_defined?(sym)
+ Object.autoload(sym, file)
+ end
+ }
+
+ ################################################
+
+ @TOPLEVEL_ALIAS_SETUP_PROC[:Tile] =
+ @TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod|
+ unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile)
+ Object.autoload :Ttk, 'tkextlib/tile'
+ Tk.autoload :Tile, 'tkextlib/tile'
+ end
+ }
+end
diff --git a/ext/tk/lib/tk/txtwin_abst.rb b/ext/tk/lib/tk/txtwin_abst.rb
new file mode 100644
index 0000000000..540f806d17
--- /dev/null
+++ b/ext/tk/lib/tk/txtwin_abst.rb
@@ -0,0 +1,39 @@
+#
+# tk/txtwin_abst.rb : TkTextWin abstruct class
+#
+require 'tk'
+
+class TkTextWin<TkWindow
+ TkCommandNames = [].freeze
+ #def create_self
+ # fail RuntimeError, "TkTextWin is an abstract class"
+ #end
+ #private :create_self
+
+ def bbox(index)
+ list(tk_send_without_enc('bbox', index))
+ end
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+ def get(*index)
+ _fromUTF8(tk_send_without_enc('get', *index))
+ end
+ def insert(index, *args)
+ tk_send('insert', index, *args)
+ self
+ end
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send_without_enc('scan', 'dragto', x, y)
+ self
+ end
+ def see(index)
+ tk_send_without_enc('see', index)
+ self
+ end
+end
diff --git a/ext/tk/lib/tk/validation.rb b/ext/tk/lib/tk/validation.rb
new file mode 100644
index 0000000000..60bd433cdc
--- /dev/null
+++ b/ext/tk/lib/tk/validation.rb
@@ -0,0 +1,397 @@
+#
+# tk/validation.rb - validation support module for entry, spinbox, and so on
+#
+require 'tk'
+
+module Tk
+ module ValidateConfigure
+ def self.__def_validcmd(scope, klass, keys=nil)
+ keys = klass._config_keys unless keys
+ keys.each{|key|
+ eval("def #{key}(*args, &b)
+ __validcmd_call(#{klass.name}, '#{key}', *args, &b)
+ end", scope)
+ }
+ end
+
+ def __validcmd_call(klass, key, *args, &b)
+ return cget(key) if args.empty? && !b
+
+ cmd = (b)? proc(&b) : args.shift
+
+ if cmd.kind_of?(klass)
+ configure(key, cmd)
+ elsif !args.empty?
+ configure(key, [cmd, args])
+ else
+ configure(key, cmd)
+ end
+ end
+
+ def __validation_class_list
+ # maybe need to override
+ []
+ end
+
+ def __get_validate_key2class
+ k2c = {}
+ __validation_class_list.each{|klass|
+ klass._config_keys.each{|key|
+ k2c[key.to_s] = klass
+ }
+ }
+ k2c
+ end
+
+ def __conv_vcmd_on_hash_kv(keys)
+ key2class = __get_validate_key2class
+
+ keys = _symbolkey2str(keys)
+ key2class.each{|key, klass|
+ if keys[key].kind_of?(Array)
+ cmd, *args = keys[key]
+ #keys[key] = klass.new(cmd, args.join(' '))
+ keys[key] = klass.new(cmd, *args)
+ # elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method)
+ elsif TkComm._callback_entry?(keys[key])
+ keys[key] = klass.new(keys[key])
+ end
+ }
+ keys
+ end
+
+ def create_self(keys)
+ super(__conv_vcmd_on_hash_kv(keys))
+ end
+ private :create_self
+
+ def configure(slot, value=TkComm::None)
+ if slot.kind_of?(Hash)
+ super(__conv_vcmd_on_hash_kv(slot))
+ else
+ super(__conv_vcmd_on_hash_kv(slot=>value))
+ end
+ self
+ end
+=begin
+ def configure(slot, value=TkComm::None)
+ key2class = __get_validate_key2class
+
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ key2class.each{|key, klass|
+ if slot[key].kind_of?(Array)
+ cmd, *args = slot[key]
+ slot[key] = klass.new(cmd, args.join(' '))
+ elsif slot[key].kind_of?(Proc) || slot[key].kind_of?(Method)
+ slot[key] = klass.new(slot[key])
+ end
+ }
+ super(slot)
+
+ else
+ slot = slot.to_s
+ if (klass = key2class[slot])
+ if value.kind_of?(Array)
+ cmd, *args = value
+ value = klass.new(cmd, args.join(' '))
+ elsif value.kind_of?(Proc) || value.kind_of?(Method)
+ value = klass.new(value)
+ end
+ end
+ super(slot, value)
+ end
+
+ self
+ end
+=end
+ end
+
+ module ItemValidateConfigure
+ def self.__def_validcmd(scope, klass, keys=nil)
+ keys = klass._config_keys unless keys
+ keys.each{|key|
+ eval("def item_#{key}(id, *args, &b)
+ __item_validcmd_call(#{klass.name}, '#{key}', id, *args, &b)
+ end", scope)
+ }
+ end
+
+ def __item_validcmd_call(tagOrId, klass, key, *args, &b)
+ return itemcget(tagid(tagOrId), key) if args.empty? && !b
+
+ cmd = (b)? proc(&b) : args.shift
+
+ if cmd.kind_of?(klass)
+ itemconfigure(tagid(tagOrId), key, cmd)
+ elsif !args.empty?
+ itemconfigure(tagid(tagOrId), key, [cmd, args])
+ else
+ itemconfigure(tagid(tagOrId), key, cmd)
+ end
+ end
+
+ def __item_validation_class_list(id)
+ # maybe need to override
+ []
+ end
+
+ def __get_item_validate_key2class(id)
+ k2c = {}
+ __item_validation_class_list(id).each{|klass|
+ klass._config_keys.each{|key|
+ k2c[key.to_s] = klass
+ }
+ }
+ end
+
+ def __conv_item_vcmd_on_hash_kv(keys)
+ key2class = __get_item_validate_key2class(tagid(tagOrId))
+
+ keys = _symbolkey2str(keys)
+ key2class.each{|key, klass|
+ if keys[key].kind_of?(Array)
+ cmd, *args = keys[key]
+ #keys[key] = klass.new(cmd, args.join(' '))
+ keys[key] = klass.new(cmd, *args)
+ # elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method)
+ elsif TkComm._callback_entry?(keys[key])
+ keys[key] = klass.new(keys[key])
+ end
+ }
+ keys
+ end
+
+ def itemconfigure(tagOrId, slot, value=TkComm::None)
+ if slot.kind_of?(Hash)
+ super(__conv_item_vcmd_on_hash_kv(slot))
+ else
+ super(__conv_item_vcmd_on_hash_kv(slot=>value))
+ end
+ self
+ end
+=begin
+ def itemconfigure(tagOrId, slot, value=TkComm::None)
+ key2class = __get_item_validate_key2class(tagid(tagOrId))
+
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ key2class.each{|key, klass|
+ if slot[key].kind_of?(Array)
+ cmd, *args = slot[key]
+ slot[key] = klass.new(cmd, args.join(' '))
+ elsif slot[key].kind_of?(Proc) || slot[key].kind_of?(Method)
+ slot[key] = klass.new(slot[key])
+ end
+ }
+ super(slot)
+
+ else
+ slot = slot.to_s
+ if (klass = key2class[slot])
+ if value.kind_of?(Array)
+ cmd, *args = value
+ value = klass.new(cmd, args.join(' '))
+ elsif value.kind_of?(Proc) || value.kind_of?(Method)
+ value = klass.new(value)
+ end
+ end
+ super(slot, value)
+ end
+
+ self
+ end
+=end
+ end
+end
+
+class TkValidateCommand
+ include TkComm
+ extend TkComm
+
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?d, ?n, :action ],
+ [ ?i, ?x, :index ],
+ [ ?s, ?e, :current ],
+ [ ?v, ?s, :type ],
+ [ ?P, ?e, :value ],
+ [ ?S, ?e, :string ],
+ [ ?V, ?s, :triggered ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?n, TkComm.method(:number) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+
+ [ ?e, proc{|val|
+ #enc = Tk.encoding
+ enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system)
+ if enc
+ Tk.fromUTF8(TkComm::string(val), enc)
+ else
+ TkComm::string(val)
+ end
+ }
+ ],
+
+ [ ?x, proc{|val|
+ idx = TkComm::number(val)
+ if idx < 0
+ nil
+ else
+ idx
+ end
+ }
+ ],
+
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ #
+ # NOTE: The order of parameters which passed to callback procedure is
+ # <extra_arg>, <extra_arg>, ... , <subst_arg>, <subst_arg>, ...
+ #
+
+ #def self._get_extra_args_tbl
+ # # return an array of convert procs
+ # []
+ #end
+
+ def self.ret_val(val)
+ (val)? '1': '0'
+ end
+ end
+
+ ###############################################
+
+ def self._config_keys
+ # array of config-option key (string or symbol)
+ ['vcmd', 'validatecommand', 'invcmd', 'invalidcommand']
+ end
+
+ def _initialize_for_cb_class(klass, cmd = Proc.new, *args)
+ extra_args_tbl = klass._get_extra_args_tbl
+
+ if args.compact.size > 0
+ args.map!{|arg| klass._sym2subst(arg)}
+ args = args.join(' ')
+ 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|
+ ex_args = []
+ extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)}
+ klass.ret_val(cmd.call(
+ *(ex_args.concat(klass.scan_args(keys, arg)))
+ ))
+ }) + ' ' + args
+ end
+ else
+ keys, args = klass._get_all_subst_keys
+ if cmd.kind_of?(String)
+ id = cmd
+ elsif cmd.kind_of?(TkCallbackEntry)
+ @id = install_cmd(cmd)
+ else
+ @id = install_cmd(proc{|*arg|
+ ex_args = []
+ extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)}
+ klass.ret_val(cmd.call(
+ *(ex_args << klass.new(*klass.scan_args(keys, arg)))
+ ))
+ }) + ' ' + args
+ end
+ end
+ end
+
+ def initialize(cmd = Proc.new, *args)
+ _initialize_for_cb_class(self.class::ValidateArgs, cmd, *args)
+ end
+
+ def to_eval
+ @id
+ end
+end
+
+module TkValidation
+ include Tk::ValidateConfigure
+
+ class ValidateCmd < TkValidateCommand
+ module Action
+ Insert = 1
+ Delete = 0
+ Others = -1
+ Focus = -1
+ Forced = -1
+ Textvariable = -1
+ TextVariable = -1
+ end
+ end
+
+ #####################################
+
+ def __validation_class_list
+ super() << ValidateCmd
+ end
+
+ Tk::ValidateConfigure.__def_validcmd(binding, ValidateCmd)
+
+=begin
+ def validatecommand(cmd = Proc.new, args = nil)
+ if cmd.kind_of?(ValidateCmd)
+ configure('validatecommand', cmd)
+ elsif args
+ configure('validatecommand', [cmd, args])
+ else
+ configure('validatecommand', cmd)
+ end
+ end
+=end
+# def validatecommand(*args, &b)
+# __validcmd_call(ValidateCmd, 'validatecommand', *args, &b)
+# end
+# alias vcmd validatecommand
+
+=begin
+ def invalidcommand(cmd = Proc.new, args = nil)
+ if cmd.kind_of?(ValidateCmd)
+ configure('invalidcommand', cmd)
+ elsif args
+ configure('invalidcommand', [cmd, args])
+ else
+ configure('invalidcommand', cmd)
+ end
+ end
+=end
+# def invalidcommand(*args, &b)
+# __validcmd_call(ValidateCmd, 'invalidcommand', *args, &b)
+# end
+# alias invcmd invalidcommand
+end
diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb
new file mode 100644
index 0000000000..f738a96ee7
--- /dev/null
+++ b/ext/tk/lib/tk/variable.rb
@@ -0,0 +1,1765 @@
+#
+# tk/variable.rb : treat Tk variable object
+#
+require 'tk'
+
+class TkVariable
+ include Tk
+ extend TkCore
+
+ include Comparable
+
+ #TkCommandNames = ['tkwait'.freeze].freeze
+ TkCommandNames = ['vwait'.freeze].freeze
+
+ #TkVar_CB_TBL = {}
+ #TkVar_ID_TBL = {}
+ TkVar_CB_TBL = TkCore::INTERP.create_table
+ TkVar_ID_TBL = TkCore::INTERP.create_table
+ (Tk_VARIABLE_ID = ["v".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+ TkCore::INTERP.init_ip_env{
+ TkVar_CB_TBL.mutex.synchronize{ TkVar_CB_TBL.clear }
+ TkVar_ID_TBL.mutex.synchronize{ TkVar_ID_TBL.clear }
+ }
+
+ major, minor, type, type_name, patchlevel = TclTkLib.get_version
+ USE_OLD_TRACE_OPTION_STYLE = (major < 8) || (major == 8 && minor < 4)
+
+ #TkCore::INTERP.add_tk_procs('rb_var', 'args',
+ # "ruby [format \"TkVariable.callback %%Q!%s!\" $args]")
+ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
+ if {[set st [catch {eval {ruby_cmd TkVariable callback} $args} ret]] != 0} {
+ set idx [string first "\n\n" $ret]
+ if {$idx > 0} {
+ global errorInfo
+ set tcl_backtrace $errorInfo
+ set errorInfo [string range $ret [expr $idx + 2] \
+ [string length $ret]]
+ append errorInfo "\n" $tcl_backtrace
+ bgerror [string range $ret 0 [expr $idx - 1]]
+ } else {
+ bgerror $ret
+ }
+ return ""
+ #return -code $st $ret
+ } else {
+ return $ret
+ }
+ EOL
+
+ #def TkVariable.callback(args)
+ def TkVariable.callback(id, name1, name2, op)
+ #name1,name2,op = tk_split_list(args)
+ #name1,name2,op = tk_split_simplelist(args)
+ if cb_obj = TkVar_CB_TBL[id]
+ #_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
+ begin
+ _get_eval_string(cb_obj.trace_callback(name2, op))
+ rescue SystemExit
+ exit(0)
+ rescue Interrupt
+ exit!(1)
+ rescue Exception => e
+ begin
+ msg = _toUTF8(e.class.inspect) + ': ' +
+ _toUTF8(e.message) + "\n" +
+ "\n---< backtrace of Ruby side >-----\n" +
+ _toUTF8(e.backtrace.join("\n")) +
+ "\n---< backtrace of Tk side >-------"
+ if TkCore::WITH_ENCODING
+ msg.force_encoding('utf-8')
+ else
+ msg.instance_variable_set(:@encoding, 'utf-8')
+ end
+ rescue Exception
+ msg = e.class.inspect + ': ' + e.message + "\n" +
+ "\n---< backtrace of Ruby side >-----\n" +
+ e.backtrace.join("\n") +
+ "\n---< backtrace of Tk side >-------"
+ end
+ fail(e, msg)
+ end
+=begin
+ begin
+ raise 'check backtrace'
+ rescue
+ # ignore backtrace before 'callback'
+ pos = -($!.backtrace.size)
+ end
+ begin
+ _get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
+ rescue
+ trace = $!.backtrace
+ raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" +
+ "\tfrom #{trace[1..pos].join("\n\tfrom ")}"
+ end
+=end
+ else
+ ''
+ end
+ end
+
+ def self.new_hash(val = {})
+ if val.kind_of?(Hash)
+ self.new(val)
+ else
+ fail ArgumentError, 'Hash is expected'
+ end
+ end
+
+ #
+ # default_value is available only when the variable is an assoc array.
+ #
+ def default_value(val=nil, &b)
+ if b
+ @def_default = :proc
+ @default_val = proc(&b)
+ else
+ @def_default = :val
+ @default_val = val
+ end
+ self
+ end
+ def set_default_value(val)
+ @def_default = :val
+ @default_val = val
+ self
+ end
+ alias default_value= set_default_value
+ def default_proc(cmd = Proc.new)
+ @def_default = :proc
+ @default_val = cmd
+ self
+ end
+
+ def undef_default
+ @default_val = nil
+ @def_default = false
+ self
+ end
+
+ def default_value_type
+ @type
+ end
+ def default_element_value_type(idxs)
+ if idxs.kind_of?(Array)
+ index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
+ else
+ index = _get_eval_string(idxs, true)
+ end
+ @element_type[index]
+ end
+
+ def _set_default_value_type_core(type, idxs)
+ if type.kind_of?(Class)
+ if type == NilClass
+ type = nil
+ elsif type == Numeric
+ type = :numeric
+ elsif type == TrueClass || type == FalseClass
+ type = :bool
+ elsif type == String
+ type = :string
+ elsif type == Symbol
+ type = :symbol
+ elsif type == Array
+ type = :list
+ elsif type <= TkVariable
+ type = :variable
+ elsif type <= TkWindow
+ type = :window
+ elsif TkComm._callback_entry_class?(type)
+ type = :procedure
+ else
+ type = nil
+ end
+ else
+ case(type)
+ when nil
+ type = nil
+ when :numeric, 'numeric'
+ type = :numeric
+ when true, false, :bool, 'bool'
+ type = :bool
+ when :string, 'string'
+ type = :string
+ when :symbol, 'symbol'
+ type = :symbol
+ when :list, 'list'
+ type = :list
+ when :numlist, 'numlist'
+ type = :numlist
+ when :variable, 'variable'
+ type = :variable
+ when :window, 'window'
+ type = :window
+ when :procedure, 'procedure'
+ type = :procedure
+ else
+ return _set_default_value_type_core(type.class, idxs)
+ end
+ end
+ if idxs
+ if idxs.kind_of?(Array)
+ index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
+ else
+ index = _get_eval_string(idxs, true)
+ end
+ @element_type[index] = type
+ else
+ @type = type
+ end
+ type
+ end
+ private :_set_default_value_type_core
+
+ def set_default_value_type(type)
+ _set_default_value_type_core(type, nil)
+ self
+ end
+ alias default_value_type= set_default_value_type
+
+ def set_default_element_value_type(idxs, type)
+ _set_default_value_type_core(type, idxs)
+ self
+ end
+
+ def _to_default_type(val, idxs = nil)
+ if idxs
+ if idxs.kind_of?(Array)
+ index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
+ else
+ index = _get_eval_string(idxs, true)
+ end
+ type = @element_type[index]
+ else
+ type = @type
+ end
+ return val unless type
+ if val.kind_of?(Hash)
+ val.keys.each{|k| val[k] = _to_default_type(val[k], idxs) }
+ val
+ else
+ begin
+ case(type)
+ when :numeric
+ number(val)
+ when :bool
+ TkComm.bool(val)
+ when :string
+ val
+ when :symbol
+ val.intern
+ when :list
+ tk_split_simplelist(val)
+ when :numlist
+ tk_split_simplelist(val).collect!{|v| number(v)}
+ when :variable
+ TkVarAccess.new(val)
+ when :window
+ TkComm.window(val)
+ when :procedure
+ TkComm.procedure(val)
+ else
+ val
+ end
+ rescue
+ val
+ end
+ end
+ end
+ private :_to_default_type
+
+ def _to_default_element_type(idxs, val)
+ _to_default_type(val, idxs)
+ end
+ private :_to_default_element_type
+
+ def initialize(val="", type=nil)
+ # @id = Tk_VARIABLE_ID.join('')
+ begin
+ Tk_VARIABLE_ID.mutex.synchronize{
+ @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_)
+ Tk_VARIABLE_ID[1].succ!
+ }
+ end until INTERP._invoke_without_enc('info', 'globals', @id).empty?
+
+ TkVar_ID_TBL.mutex.synchronize{
+ TkVar_ID_TBL[@id] = self
+ }
+
+ @var = @id
+ @elem = nil
+
+ @def_default = false
+ @default_val = nil
+
+ @trace_var = nil
+ @trace_elem = nil
+ @trace_opts = nil
+
+ @type = nil
+ var = self
+ @element_type = Hash.new{|k,v| var.default_value_type }
+
+ self.default_value_type = type
+
+ # teach Tk-ip that @id is global var
+ 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
+ if val == []
+ # INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)',
+ # @id, @id, @id))
+ elsif val.kind_of?(Array)
+ a = []
+ # val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
+ # s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"'
+ val.each_with_index{|e,i| a.push(i); a.push(e)}
+ #s = '"' + array2tk_list(a).gsub(/[\[\]$"]/, '\\\\\&') + '"'
+ s = '"' + array2tk_list(a).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
+ elsif val.kind_of?(Hash)
+ #s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
+ # .gsub(/[\[\]$"]/, '\\\\\&') + '"'
+ s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
+ .gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
+ else
+ #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
+ s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; set %s %s', @id, @id, s))
+ end
+=end
+=begin
+ if val.kind_of?(Hash)
+ #s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
+ # .gsub(/[\[\]$"]/, '\\\\\&') + '"'
+ s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
+ .gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
+ INTERP._eval(Kernel.format('global %s; array set %s %s', @id, @id, s))
+ else
+ #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
+ s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
+ INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
+ end
+=end
+ end
+
+ def wait(on_thread = false, check_root = false)
+ if $SAFE >= 4
+ fail SecurityError, "can't wait variable at $SAFE >= 4"
+ end
+ on_thread &= (Thread.list.size != 1)
+ if on_thread
+ if check_root
+ INTERP._thread_tkwait('variable', @id)
+ else
+ INTERP._thread_vwait(@id)
+ end
+ else
+ if check_root
+ INTERP._invoke_without_enc('tkwait', 'variable', @id)
+ else
+ INTERP._invoke_without_enc('vwait', @id)
+ end
+ end
+ end
+ def eventloop_wait(check_root = false)
+ wait(false, check_root)
+ end
+ def thread_wait(check_root = false)
+ wait(true, check_root)
+ end
+ def tkwait(on_thread = true)
+ wait(on_thread, true)
+ end
+ def eventloop_tkwait
+ wait(false, true)
+ end
+ def thread_tkwait
+ wait(true, true)
+ end
+
+ def id
+ @id
+ end
+
+ def ref(*idxs)
+ # "#{@id}(#{idxs.collect{|idx| _get_eval_string(idx)}.join(',')})"
+ TkVarAccess.new("#{@id}(#{idxs.collect{|idx| _get_eval_string(idx)}.join(',')})")
+ end
+
+ def is_hash?
+ #ITNERP._eval("global #{@id}; array exist #{@id}") == '1'
+ INTERP._invoke_without_enc('global', @id)
+ # INTERP._invoke_without_enc('array', 'exist', @id) == '1'
+ TkComm.bool(INTERP._invoke_without_enc('array', 'exist', @id))
+ end
+
+ def is_scalar?
+ ! is_hash?
+ end
+
+ def exist?(*elems)
+ INTERP._invoke_without_enc('global', @id)
+ if elems.empty?
+ TkComm.bool(tk_call('info', 'exist', @id))
+ else
+ # array
+ index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',')
+ TkComm.bool(tk_call('info', 'exist', "#{@id}")) &&
+ TkComm.bool(tk_call('info', 'exist', "#{@id}(#{index})"))
+ end
+ end
+
+ def keys
+ if (is_scalar?)
+ fail RuntimeError, 'cannot get keys from a scalar variable'
+ end
+ #tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}"))
+ INTERP._invoke_without_enc('global', @id)
+ #tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'names', @id)))
+ tk_split_simplelist(INTERP._invoke_without_enc('array', 'names', @id),
+ false, true)
+ end
+
+ def size
+ INTERP._invoke_without_enc('global', @id)
+ TkComm.number(INTERP._invoke_without_enc('array', 'size', @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
+
+unless const_defined?(:USE_TCLs_SET_VARIABLE_FUNCTIONS)
+ USE_TCLs_SET_VARIABLE_FUNCTIONS = true
+end
+
+if USE_TCLs_SET_VARIABLE_FUNCTIONS
+ ###########################################################################
+ # use Tcl function version of set tkvariable
+ ###########################################################################
+
+ def _value
+ #if INTERP._eval("global #{@id}; array exist #{@id}") == '1'
+ INTERP._invoke_without_enc('global', @id)
+ # if INTERP._invoke('array', 'exist', @id) == '1'
+ if TkComm.bool(INTERP._invoke('array', 'exist', @id))
+ #Hash[*tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}"))]
+ Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', @id))]
+ else
+ _fromUTF8(INTERP._get_global_var(@id))
+ end
+ end
+
+ def value=(val)
+ val = val._value if !@type && @type != :variable && val.kind_of?(TkVariable)
+ 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),
+ _get_eval_string(v, true))
+ }
+ self.value
+# elsif val.kind_of?(Array)
+=begin
+ INTERP._set_global_var(@id, '')
+ val.each{|v|
+ #INTERP._set_variable(@id, _toUTF8(_get_eval_string(v)),
+ INTERP._set_variable(@id, _get_eval_string(v, true),
+ TclTkLib::VarAccessFlag::GLOBAL_ONLY |
+ TclTkLib::VarAccessFlag::LEAVE_ERR_MSG |
+ TclTkLib::VarAccessFlag::APPEND_VALUE |
+ TclTkLib::VarAccessFlag::LIST_ELEMENT)
+ }
+ self.value
+=end
+# _fromUTF8(INTERP._set_global_var(@id, array2tk_list(val, true)))
+ else
+ #_fromUTF8(INTERP._set_global_var(@id, _toUTF8(_get_eval_string(val))))
+ _fromUTF8(INTERP._set_global_var(@id, _get_eval_string(val, true)))
+ end
+ end
+
+ def _element_value(*idxs)
+ index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
+ begin
+ _fromUTF8(INTERP._get_global_var2(@id, index))
+ rescue => e
+ case @def_default
+ when :proc
+ @default_val.call(self, *idxs)
+ when :val
+ @default_val
+ else
+ fail e
+ end
+ end
+ #_fromUTF8(INTERP._get_global_var2(@id, index))
+ #_fromUTF8(INTERP._get_global_var2(@id, _toUTF8(_get_eval_string(index))))
+ #_fromUTF8(INTERP._get_global_var2(@id, _get_eval_string(index, true)))
+ end
+
+ def []=(*args)
+ val = args.pop
+ type = default_element_value_type(args)
+ val = val._value if !type && type != :variable && val.kind_of?(TkVariable)
+ index = args.collect{|idx| _get_eval_string(idx, true)}.join(',')
+ _fromUTF8(INTERP._set_global_var2(@id, index, _get_eval_string(val, true)))
+ #_fromUTF8(INTERP._set_global_var2(@id, _toUTF8(_get_eval_string(index)),
+ # _toUTF8(_get_eval_string(val))))
+ #_fromUTF8(INTERP._set_global_var2(@id, _get_eval_string(index, true),
+ # _get_eval_string(val, true)))
+ end
+
+ def unset(*elems)
+ if elems.empty?
+ INTERP._unset_global_var(@id)
+ else
+ index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',')
+ INTERP._unset_global_var2(@id, index)
+ end
+ end
+ alias remove unset
+
+else
+ ###########################################################################
+ # use Ruby script version of set tkvariable (traditional methods)
+ ###########################################################################
+
+ def _value
+ begin
+ INTERP._eval(Kernel.format('global %s; set %s', @id, @id))
+ #INTERP._eval(Kernel.format('set %s', @id))
+ #INTERP._invoke_without_enc('set', @id)
+ rescue
+ if INTERP._eval(Kernel.format('global %s; array exists %s',
+ @id, @id)) != "1"
+ #if INTERP._eval(Kernel.format('array exists %s', @id)) != "1"
+ #if INTERP._invoke_without_enc('array', 'exists', @id) != "1"
+ fail
+ else
+ Hash[*tk_split_simplelist(INTERP._eval(Kernel.format('global %s; array get %s', @id, @id)))]
+ #Hash[*tk_split_simplelist(_fromUTF8(INTERP._invoke_without_enc('array', 'get', @id)))]
+ end
+ end
+ end
+
+ def value=(val)
+ val = val._value if !@type && @type != :variable && val.kind_of?(TkVariable)
+ begin
+ #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
+ s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
+ INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
+ #INTERP._eval(Kernel.format('set %s %s', @id, s))
+ #_fromUTF8(INTERP._invoke_without_enc('set', @id, _toUTF8(s)))
+ rescue
+ if INTERP._eval(Kernel.format('global %s; array exists %s',
+ @id, @id)) != "1"
+ #if INTERP._eval(Kernel.format('array exists %s', @id)) != "1"
+ #if INTERP._invoke_without_enc('array', 'exists', @id) != "1"
+ fail
+ else
+ if val == []
+ INTERP._eval(Kernel.format('global %s; unset %s; set %s(0) 0; unset %s(0)', @id, @id, @id, @id))
+ #INTERP._eval(Kernel.format('unset %s; set %s(0) 0; unset %s(0)',
+ # @id, @id, @id))
+ #INTERP._invoke_without_enc('unset', @id)
+ #INTERP._invoke_without_enc('set', @id+'(0)', 0)
+ #INTERP._invoke_without_enc('unset', @id+'(0)')
+ elsif val.kind_of?(Array)
+ a = []
+ val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e, true))}
+ #s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"'
+ s = '"' + a.join(" ").gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
+ INTERP._eval(Kernel.format('global %s; unset %s; array set %s %s',
+ @id, @id, @id, s))
+ #INTERP._eval(Kernel.format('unset %s; array set %s %s',
+ # @id, @id, s))
+ #INTERP._invoke_without_enc('unset', @id)
+ #_fromUTF8(INTERP._invoke_without_enc('array','set', @id, _toUTF8(s)))
+ elsif val.kind_of?(Hash)
+ #s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
+ # .gsub(/[\[\]$"]/, '\\\\\&') + '"'
+ s = '"' + val.to_a.collect{|e| array2tk_list(e, true)}.join(" ")\
+ .gsub(/[\[\]$\\"]/, '\\\\\&') + '"'
+ INTERP._eval(Kernel.format('global %s; unset %s; array set %s %s',
+ @id, @id, @id, s))
+ #INTERP._eval(Kernel.format('unset %s; array set %s %s',
+ # @id, @id, s))
+ #INTERP._invoke_without_enc('unset', @id)
+ #_fromUTF8(INTERP._invoke_without_enc('array','set', @id, _toUTF8(s)))
+ else
+ fail
+ end
+ end
+ end
+ end
+
+ def _element_value(*idxs)
+ index = idxs.collect{|idx| _get_eval_string(idx)}.join(',')
+ begin
+ INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index))
+ rescue => e
+ case @def_default
+ when :proc
+ @default_val.call(self, *idxs)
+ when :val
+ @default_val
+ else
+ fail e
+ end
+ end
+ #INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index))
+ #INTERP._eval(Kernel.format('global %s; set %s(%s)',
+ # @id, @id, _get_eval_string(index)))
+ #INTERP._eval(Kernel.format('set %s(%s)', @id, _get_eval_string(index)))
+ #INTERP._eval('set ' + @id + '(' + _get_eval_string(index) + ')')
+ end
+
+ def []=(*args)
+ val = args.pop
+ type = default_element_value_type(args)
+ val = val._value if !type && type != :variable && val.kind_of?(TkVariable)
+ index = args.collect{|idx| _get_eval_string(idx)}.join(',')
+ INTERP._eval(Kernel.format('global %s; set %s(%s) %s', @id, @id,
+ index, _get_eval_string(val)))
+ #INTERP._eval(Kernel.format('global %s; set %s(%s) %s', @id, @id,
+ # _get_eval_string(index), _get_eval_string(val)))
+ #INTERP._eval(Kernel.format('set %s(%s) %s', @id,
+ # _get_eval_string(index), _get_eval_string(val)))
+ #INTERP._eval('set ' + @id + '(' + _get_eval_string(index) + ') ' +
+ # _get_eval_string(val))
+ end
+
+ def unset(*elems)
+ if elems.empty?
+ INTERP._eval(Kernel.format('global %s; unset %s', @id, @id))
+ #INTERP._eval(Kernel.format('unset %s', @id))
+ #INTERP._eval('unset ' + @id)
+ else
+ index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',')
+ INTERP._eval(Kernel.format('global %s; unset %s(%s)', @id, @id, index))
+ #INTERP._eval(Kernel.format('global %s; unset %s(%s)',
+ # @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) + ')')
+ end
+ end
+ alias remove unset
+
+end
+
+ protected :_value, :_element_value
+
+ def value
+ _to_default_type(_value)
+ end
+
+ def [](*idxs)
+ _to_default_element_type(idxs, _element_value(*idxs))
+ end
+
+ def set_value(val)
+ self.value = val
+ self
+ end
+
+ def set_element_value(idxs, val)
+ if idxs.kind_of?(Array)
+ self[*idxs]=val
+ else
+ self[idxs]=val
+ end
+ self
+ end
+
+ def set_value_type(val)
+ self.default_value_type = val.class
+ self.value = val
+ self
+ end
+
+ alias value_type= set_value_type
+
+ def set_element_value_type(idxs, val)
+ self.set_default_element_value_type(idxs, val.class)
+ if idxs.kind_of?(Array)
+ self[*idxs]=val
+ else
+ self[idxs]=val
+ end
+ self
+ end
+
+ def numeric
+ number(_value)
+ end
+ def numeric_element(*idxs)
+ number(_element_value(*idxs))
+ end
+ def set_numeric(val)
+ case val
+ when Numeric
+ self.value=(val)
+ when TkVariable
+ self.value=(val.numeric)
+ else
+ raise ArgumentError, "Numeric is expected"
+ end
+ self
+ end
+ alias numeric= set_numeric
+ def set_numeric_element(idxs, val)
+ case val
+ when Numeric
+ val
+ when TkVariable
+ val = val.numeric
+ else
+ raise ArgumentError, "Numeric is expected"
+ end
+ if idxs.kind_of?(Array)
+ self[*idxs]=val
+ else
+ self[idxs]=val
+ end
+ self
+ end
+ def set_numeric_type(val)
+ @type = :numeric
+ self.numeric=(val)
+ self
+ end
+ alias numeric_type= set_numeric_type
+ def set_numeric_element_type(idxs, val)
+ self.set_default_element_value_type(idxs, :numeric)
+ self.set_numeric_element(idxs, val)
+ end
+
+ def bool
+ TkComm.bool(_value)
+=begin
+ # see Tcl_GetBoolean man-page
+ case _value.downcase
+ when '0', 'false', 'no', 'off'
+ false
+ else
+ true
+ end
+=end
+ end
+ def bool_element(*idxs)
+ TkComm.bool(_element_value(*idxs))
+ end
+ def set_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
+ self
+ end
+ alias bool= set_bool
+ def set_bool_element(idxs, val)
+ if ! val
+ val = '0'
+ else
+ case val.to_s.downcase
+ when 'false', '0', 'no', 'off'
+ val = '0'
+ else
+ val = '1'
+ end
+ end
+ if idxs.kind_of?(Array)
+ self[*idxs]=val
+ else
+ self[idxs]=val
+ end
+ self
+ end
+ def set_bool_type(val)
+ @type = :bool
+ self.bool=(val)
+ self
+ end
+ alias bool_type= set_bool_type
+ def set_bool_element_type(idxs, val)
+ self.set_default_element_value_type(idxs, :bool)
+ self.set_bool_element(idxs, val)
+ end
+
+ def variable
+ # keeps a Tcl's variable name
+ TkVarAccess.new(self._value)
+ end
+ def variable_element(*idxs)
+ TkVarAccess.new(_element_value(*idxs))
+ end
+ def set_variable(var)
+ var = var.id if var.kind_of?(TkVariable)
+ self.value = var
+ self
+ end
+ alias variable= set_variable
+ def set_variable_element(idxs, var)
+ var = var.id if var.kind_of?(TkVariable)
+ if idxs.kind_of?(Array)
+ self[*idxs]=var
+ else
+ self[idxs]=var
+ end
+ self
+ end
+ def set_variable_type(var)
+ @type = :variable
+ var = var.id if var.kind_of?(TkVariable)
+ self.value = var
+ self
+ end
+ alias variable_type= set_variable_type
+ def set_variable_element_type(idxs, var)
+ self.set_default_element_value_type(idxs, :variable)
+ self.set_variable_element(idxs, var)
+ end
+
+ def window
+ TkComm.window(self._value)
+ end
+ def window_element(*idxs)
+ TkComm.window(_element_value(*idxs))
+ end
+ def set_window(win)
+ win = win._value if win.kind_of?(TkVariable)
+ self.value = win
+ self
+ end
+ alias window= set_window
+ def set_window_element(idxs, win)
+ win = win._value if win.kind_of?(TkVariable)
+ if idxs.kind_of?(Array)
+ self[*idxs]=win
+ else
+ self[idxs]=win
+ end
+ self
+ end
+ def set_window_type(win)
+ @type = :window
+ self.window=(win)
+ self
+ end
+ alias window_type= set_window_type
+ def set_window_element_type(idxs, win)
+ self.set_default_element_value_type(idxs, :window)
+ self.set_window_element(idxs, win)
+ end
+
+ def procedure
+ TkComm.procedure(self._value)
+ end
+ def procedure_element(*idxs)
+ TkComm.procedure(_element_value(*idxs))
+ end
+ def set_procedure(cmd)
+ self.value = cmd
+ self
+ end
+ alias procedure= set_procedure
+ def set_procedure_element(idxs, cmd)
+ cmd = cmd._value if cmd.kind_of?(TkVariable)
+ if idxs.kind_of?(Array)
+ self[*idxs]=cmd
+ else
+ self[idxs]=cmd
+ end
+ self
+ end
+ def set_procedure_type(cmd)
+ @type = :procedure
+ self.procedure=(cmd)
+ self
+ end
+ alias procedure_type= set_procedure_type
+ def set_procedure_element_type(idxs, cmd)
+ self.set_default_element_value_type(idxs, :procedure)
+ self.set_proceure_element(idxs, cmd)
+ end
+
+ def to_i
+ number(_value).to_i
+ end
+ def element_to_i(*idxs)
+ number(_element_value(*idxs)).to_i
+ end
+
+ def to_f
+ number(_value).to_f
+ end
+ def element_to_f(*idxs)
+ number(_element_value(*idxs)).to_f
+ end
+
+ def to_s
+ #string(value).to_s
+ _value
+ end
+ alias string to_s
+ def element_to_s(*idxs)
+ _element_value(*idxs)
+ end
+ def string_element(*idxs)
+ _element_value(*idxs)
+ end
+ def set_string(val)
+ val = val._value if val.kind_of?(TkVariable)
+ self.value=val
+ self
+ end
+ alias string= set_string
+ def set_string_element(idxs, val)
+ val = val._value if val.kind_of?(TkVariable)
+ if idxs.kind_of?(Array)
+ self[*idxs]=val
+ else
+ self[idxs]=val
+ end
+ self
+ end
+ def set_string_type(val)
+ @type = :string
+ self.string=(val)
+ self
+ end
+ alias string_type= set_string_type
+ def set_string_element_type(idxs, val)
+ self.set_default_element_value_type(idxs, :string)
+ self.set_string_element(idxs, val)
+ end
+
+ def to_sym
+ _value.intern
+ end
+ alias symbol to_sym
+ def element_to_sym(*idxs)
+ _element_value(*idxs).intern
+ end
+ alias symbol_element element_to_sym
+ def set_symbol(val)
+ val = val._value if val.kind_of?(TkVariable)
+ self.value=val
+ self
+ end
+ alias symbol= set_symbol
+ def set_symbol_element(idxs, val)
+ val = val._value if val.kind_of?(TkVariable)
+ if idxs.kind_of?(Array)
+ self[*idxs]=val
+ else
+ self[idxs]=val
+ end
+ self
+ end
+ def set_symbol_type(val)
+ @type = :symbol
+ self.value=(val)
+ self
+ end
+ alias symbol_type= set_symbol_type
+ def set_symbol_element_type(idxs, val)
+ self.set_default_element_value_type(idxs, :symbol)
+ self.set_symbol_element(idxs, val)
+ end
+
+ def list
+ #tk_split_list(value)
+ tk_split_simplelist(_value)
+ end
+ alias to_a list
+ def list_element(*idxs)
+ tk_split_simplelist(_element_value(*idxs))
+ end
+ alias element_to_a list_element
+
+ def numlist
+ list.collect!{|val| number(val)}
+ end
+ def numlist_element(*idxs)
+ list_element(*idxs).collect!{|val| number(val)}
+ end
+
+ def set_list(val)
+ case val
+ when Array
+ self.value=(val)
+ when TkVariable
+ self.value=(val.list)
+ else
+ raise ArgumentError, "Array is expected"
+ end
+ self
+ end
+ alias list= set_list
+
+ alias set_numlist set_list
+ alias numlist= set_numlist
+
+ def set_list_element(idxs, val)
+ case val
+ when Array
+ val
+ when TkVariable
+ val = val.list
+ else
+ raise ArgumentError, "Array is expected"
+ end
+ if idxs.kind_of?(Array)
+ self[*idxs]=val
+ else
+ self[idxs]=val
+ end
+ self
+ end
+ alias set_numlist_element set_list_element
+
+ def set_list_type(val)
+ @type = :list
+ self.list=(val)
+ self
+ end
+ alias list_type= set_list_type
+ def set_list_element_type(idxs, val)
+ self.set_default_element_value_type(idxs, :list)
+ self.set_list_element(idxs, val)
+ end
+ def set_numlist_type(val)
+ @type = :numlist
+ self.numlist=(val)
+ self
+ end
+ alias numlist_type= set_numlist_type
+ def set_numlist_element_type(idxs, val)
+ self.set_default_element_value_type(idxs, :numlist)
+ self.set_numlist_element(idxs, val)
+ end
+
+ def lappend(*elems)
+ tk_call('lappend', @id, *elems)
+ self
+ end
+ def element_lappend(idxs, *elems)
+ if idxs.kind_of?(Array)
+ idxs = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
+ end
+ tk_call('lappend', "#{@id}(#{idxs})", *elems)
+ self
+ end
+
+ def lindex(idx)
+ tk_call('lindex', self._value, idx)
+ end
+ alias lget lindex
+ def element_lindex(elem_idxs, idx)
+ if elem_idxs.kind_of?(Array)
+ val = _element_value(*elem_idxs)
+ else
+ val = _element_value(elem_idxs)
+ end
+ tk_call('lindex', val, idx)
+ end
+ alias element_lget element_lindex
+
+ def lget_i(idx)
+ number(lget(idx)).to_i
+ end
+ def element_lget_i(elem_idxs, idx)
+ number(element_lget(elem_idxs, idx)).to_i
+ end
+
+ def lget_f(idx)
+ number(lget(idx)).to_f
+ end
+ def element_lget_f(elem_idxs, idx)
+ number(element_lget(elem_idxs, idx)).to_f
+ end
+
+ def lset(idx, val)
+ tk_call('lset', @id, idx, val)
+ self
+ end
+ def element_lset(elem_idxs, idx, val)
+ if elem_idxs.kind_of?(Array)
+ idxs = elem_idxs.collect{|i| _get_eval_string(i, true)}.join(',')
+ end
+ tk_call('lset', "#{@id}(#{idxs})", idx, val)
+ self
+ end
+
+ def inspect
+ #Kernel.format "#<TkVariable: %s>", @id
+ '#<TkVariable: ' + @id + '>'
+ end
+
+ def coerce(other)
+ case other
+ when TkVariable
+ [other._value, self._value]
+ when String
+ [other, self.to_s]
+ when Symbol
+ [other, self.to_sym]
+ when Integer
+ [other, self.to_i]
+ when Float
+ [other, self.to_f]
+ when Array
+ [other, self.to_a]
+ else
+ [other, self._value]
+ end
+ end
+
+ def &(other)
+ if other.kind_of?(Array)
+ self.to_a & other.to_a
+ else
+ self.to_i & other.to_i
+ end
+ end
+ def |(other)
+ if other.kind_of?(Array)
+ self.to_a | other.to_a
+ else
+ self.to_i | other.to_i
+ end
+ end
+ def +(other)
+ case other
+ when Array
+ self.to_a + other
+ when String
+ self._value + other
+ else
+ begin
+ number(self._value) + other
+ rescue
+ self._value + other.to_s
+ end
+ end
+ end
+ def -(other)
+ if other.kind_of?(Array)
+ self.to_a - other
+ else
+ number(self._value) - other
+ end
+ end
+ def *(other)
+ num_or_str(self._value) * other.to_i
+ #begin
+ # number(self._value) * other
+ #rescue
+ # self._value * other
+ #end
+ end
+ def /(other)
+ number(self._value) / other
+ end
+ def %(other)
+ num_or_str(self._value) % other.to_i
+ #begin
+ # number(self._value) % other
+ #rescue
+ # self._value % other
+ #end
+ end
+ def **(other)
+ number(self._value) ** other
+ end
+ def =~(other)
+ self._value =~ other
+ end
+
+ def ==(other)
+ case other
+ when TkVariable
+ #self.equal?(other)
+ self._value == other._value
+ when String
+ self.to_s == other
+ when Symbol
+ self.to_sym == other
+ when Integer
+ self.to_i == other
+ when Float
+ self.to_f == other
+ when Array
+ self.to_a == other
+ when Hash
+ # false if self is not an assoc array
+ self._value == other
+ else
+ # false
+ self._value == _get_eval_string(other)
+ end
+ end
+
+ def zero?
+ numeric.zero?
+ end
+ def nonzero?
+ !(numeric.zero?)
+ end
+
+ def <=>(other)
+ if other.kind_of?(TkVariable)
+ begin
+ val = other.numeric
+ other = val
+ rescue
+ other = other._value
+ end
+ elsif other.kind_of?(Numeric)
+ begin
+ return self.numeric <=> other
+ rescue
+ return self._value <=> other.to_s
+ end
+ elsif other.kind_of?(Array)
+ return self.list <=> other
+ else
+ return self._value <=> other
+ end
+ end
+
+ def to_eval
+ @id
+ end
+
+ def trace_callback(elem, op)
+ if @trace_var.kind_of? Array
+ @trace_var.each{|m,e| e.call(self,elem,op) if m.index(op)}
+ end
+ if elem.kind_of?(String) && elem != ''
+ if @trace_elem.kind_of?(Hash) && @trace_elem[elem].kind_of?(Array)
+ @trace_elem[elem].each{|m,e| e.call(self,elem,op) if m.index(op)}
+ end
+ end
+ end
+
+ def _check_trace_opt(opts)
+ if opts.kind_of?(Array)
+ opt_str = opts.map{|s| s.to_s}.join(' ')
+ else
+ opt_str = opts.to_s
+ end
+
+ fail ArgumentError, 'null trace option' if opt_str.empty?
+
+ if opt_str =~ /[^arwu\s]/
+ # new format (Tcl/Tk8.4+?)
+ if opts.kind_of?(Array)
+ opt_ary = opts.map{|opt| opt.to_s.strip}
+ else
+ opt_ary = opt_str.split(/\s+|\|/)
+ opt_ary.delete('')
+ end
+ if USE_OLD_TRACE_OPTION_STYLE
+ opt_ary.uniq.map{|opt|
+ case opt
+ when 'array'
+ 'a'
+ when 'read'
+ 'r'
+ when 'write'
+ 'w'
+ when 'unset'
+ 'u'
+ else
+ fail ArgumentError, "unsupported trace option '#{opt}' on Tcl/Tk#{Tk::TCL_PATCHLEVEL}"
+ end
+ }.join
+ else
+ opt_ary
+ end
+ else
+ # old format
+ opt_ary = opt_str.delete('^arwu').split(//).uniq
+ if USE_OLD_TRACE_OPTION_STYLE
+ opt_ary.join
+ else
+ opt_ary.map{|c|
+ case c
+ when 'a'
+ 'array'
+ when 'r'
+ 'read'
+ when 'w'
+ 'write'
+ when 'u'
+ 'unset'
+ end
+ }
+ end
+ end
+ end
+ private :_check_trace_opt
+
+ def trace(opts, cmd = Proc.new)
+ opts = _check_trace_opt(opts)
+ (@trace_var ||= []).unshift([opts,cmd])
+
+ if @trace_opts == nil
+ TkVar_CB_TBL[@id] = self
+ @trace_opts = opts
+ if USE_OLD_TRACE_OPTION_STYLE
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ else
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ else
+ newopts = @trace_opts.dup
+ if USE_OLD_TRACE_OPTION_STYLE
+ opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ if newopts != @trace_opts
+ Tk.tk_call_without_enc('trace', 'vdelete',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ else
+ newopts |= opts
+ unless (newopts - @trace_opts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ end
+ end
+
+ self
+ end
+
+ def trace_element(elem, opts, cmd = Proc.new)
+ if @elem
+ fail(RuntimeError,
+ "invalid for a TkVariable which denotes an element of Tcl's array")
+ end
+
+ opts = _check_trace_opt(opts)
+
+ ((@trace_elem ||= {})[elem] ||= []).unshift([opts,cmd])
+
+ if @trace_opts == nil
+ TkVar_CB_TBL[@id] = self
+ @trace_opts = opts
+ if USE_OLD_TRACE_OPTION_STYLE
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ else
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ else
+ newopts = @trace_opts.dup
+ if USE_OLD_TRACE_OPTION_STYLE
+ opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ if newopts != @trace_opts
+ Tk.tk_call_without_enc('trace', 'vdelete',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ else
+ newopts |= opts
+ unless (newopts - @trace_opts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ end
+ end
+
+ self
+ end
+
+ def trace_info
+ return [] unless @trace_var
+ @trace_var.dup
+ end
+ alias trace_vinfo trace_info
+
+ def trace_info_for_element(elem)
+ if @elem
+ fail(RuntimeError,
+ "invalid for a TkVariable which denotes an element of Tcl's array")
+ end
+ return [] unless @trace_elem
+ return [] unless @trace_elem[elem]
+ @trace_elem[elem].dup
+ end
+ alias trace_vinfo_for_element trace_info_for_element
+
+ def trace_remove(opts,cmd)
+ return self unless @trace_var.kind_of? Array
+
+ opts = _check_trace_opt(opts)
+
+ idx = -1
+ if USE_OLD_TRACE_OPTION_STYLE
+ newopts = ''
+ @trace_var.each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd
+ diff = false
+ ['a', 'r', 'w', 'u'].each{|c|
+ break if (diff = e[0].index(c) ^ opts.index(c))
+ }
+ unless diff
+ #find
+ idx = i
+ next
+ end
+ end
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ else
+ newopts = []
+ @trace_var.each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd &&
+ e[0].size == opts.size && (e[0] - opts).empty?
+ # find
+ idx = i
+ next
+ end
+ newopts |= e[0]
+ }
+ end
+
+ if idx >= 0
+ @trace_var.delete_at(idx)
+ else
+ return self
+ end
+
+ (@trace_elem ||= {}).each{|elem|
+ @trace_elem[elem].each{|e|
+ if USE_OLD_TRACE_OPTION_STYLE
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ else
+ newopts |= e[0]
+ end
+ }
+ }
+
+ if USE_OLD_TRACE_OPTION_STYLE
+ diff = false
+ @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))}
+ if diff
+ Tk.tk_call_without_enc('trace', 'vdelete',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ end
+ else
+ unless (@trace_opts - newopts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ end
+ end
+
+ self
+ end
+ alias trace_delete trace_remove
+ alias trace_vdelete trace_remove
+
+ def trace_remove_for_element(elem,opts,cmd)
+ if @elem
+ fail(RuntimeError,
+ "invalid for a TkVariable which denotes an element of Tcl's array")
+ end
+ return self unless @trace_elem.kind_of? Hash
+ return self unless @trace_elem[elem].kind_of? Array
+
+ opts = _check_trace_opt(opts)
+
+ idx = -1
+ if USE_OLD_TRACE_OPTION_STYLE
+ @trace_elem[elem].each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd
+ diff = false
+ ['a', 'r', 'w', 'u'].each{|c|
+ break if (diff = e[0].index(c) ^ opts.index(c))
+ }
+ unless diff
+ #find
+ idx = i
+ next
+ end
+ end
+ }
+ else
+ @trace_elem[elem].each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd &&
+ e[0].size == opts.size && (e[0] - opts).empty?
+ # find
+ idx = i
+ next
+ end
+ }
+ end
+
+ if idx >= 0
+ @trace_elem[elem].delete_at(idx)
+ else
+ return self
+ end
+
+ if USE_OLD_TRACE_OPTION_STYLE
+ newopts = ''
+ @trace_var.each{|e|
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ }
+ else
+ newopts = []
+ @trace_var.each{|e|
+ newopts |= e[0]
+ }
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ }
+ end
+
+ if USE_OLD_TRACE_OPTION_STYLE
+ diff = false
+ @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))}
+ if diff
+ Tk.tk_call_without_enc('trace', 'vdelete',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ end
+ else
+ unless (@trace_opts - newopts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ end
+ end
+
+ self
+ end
+ alias trace_delete_for_element trace_remove_for_element
+ alias trace_vdelete_for_element trace_remove_for_element
+end
+
+class TkVarAccess<TkVariable
+ def self.new(name, *args)
+ if name.kind_of?(TkVariable)
+ name.value = args[0] unless args.empty?
+ return name
+ end
+
+ name = name.to_s
+ v = nil
+ TkVar_ID_TBL.mutex.synchronize{
+ if v = TkVar_ID_TBL[name]
+ v.value = args[0] unless args.empty?
+ return v
+ else
+ (v = self.allocate).instance_eval{
+ @id = name
+ TkVar_ID_TBL[@id] = self
+ @var = @id
+ }
+ end
+ }
+
+ v.instance_eval{ initialize(name, *args) }
+ v
+ end
+
+ def self.new_hash(name, *args)
+ if name.kind_of?(TkVariable)
+ unless name.is_hash?
+ fail ArgumentError, "already exist as a scalar variable"
+ end
+ name.value = args[0] unless args.empty?
+ return name
+ end
+
+ name = name.to_s
+ v = nil
+ TkVar_ID_TBL.mutex.synchronize{
+ if v = TkVar_ID_TBL[name]
+ unless v.is_hash?
+ fail ArgumentError, "already exist as a scalar variable"
+ end
+ v.value = args[0] unless args.empty?
+ return v
+ else
+ (v = self.allocate).instance_eval{
+ @id = name
+ TkVar_ID_TBL[@id] = self
+ @var = @id
+ }
+ end
+ }
+
+ INTERP._invoke_without_enc('global', name)
+ if args.empty? && INTERP._invoke_without_enc('array', 'exist', name) == '0'
+ v.instance_eval{ initialize(name, {}) } # force creating
+ else
+ v.instance_eval{ initialize(name, *args) }
+ end
+ v
+ end
+
+ def initialize(varname, val=nil)
+ # @id = varname
+ # TkVar_ID_TBL[@id] = self
+
+ # @var = @id
+ @elem = nil
+
+ @def_default = false
+ @default_val = nil
+
+ @trace_var = nil
+ @trace_elem = nil
+ @trace_opts = nil
+
+ @type = nil
+ var = self
+ @element_type = Hash.new{|k,v| var.default_value_type }
+
+ # is an element?
+ if @id =~ /^([^(]+)\((.+)\)$/
+ # is an element --> var == $1, elem == $2
+ @var = $1
+ @elem = $2
+ end
+
+ # teach Tk-ip that @id is global var
+ INTERP._invoke_without_enc('global', @var)
+=begin
+ begin
+ INTERP._invoke_without_enc('global', @id)
+ rescue => e
+ if @id =~ /^(.+)\([^()]+\)$/
+ # is an element --> varname == $1
+ INTERP._invoke_without_enc('global', $1)
+ else
+ fail e
+ end
+ end
+=end
+
+ if val
+ if val.kind_of?(Hash)
+ # assoc-array variable
+ self[''] = 0
+ self.clear
+ end
+ #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"' #"
+ #s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"' #"
+ #INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
+ #INTERP._set_global_var(@id, _toUTF8(_get_eval_string(val)))
+ self.value = val
+ end
+ end
+end
+
+module Tk
+ begin
+ INTERP._invoke_without_enc('global', 'auto_path')
+ auto_path = INTERP._invoke('set', 'auto_path')
+ rescue => e
+ begin
+ INTERP._invoke_without_enc('global', 'env')
+ auto_path = INTERP._invoke('set', 'env(TCLLIBPATH)')
+ rescue => e
+ auto_path = Tk::LIBRARY
+ end
+ end
+
+ AUTO_PATH = TkVarAccess.new('auto_path', auto_path)
+
+=begin
+ AUTO_OLDPATH = tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath'))
+ AUTO_OLDPATH.each{|s| s.freeze}
+ AUTO_OLDPATH.freeze
+=end
+
+ TCL_PACKAGE_PATH = TkVarAccess.new('tcl_pkgPath')
+ PACKAGE_PATH = TCL_PACKAGE_PATH
+
+ TCL_LIBRARY_PATH = TkVarAccess.new('tcl_libPath')
+ LIBRARY_PATH = TCL_LIBRARY_PATH
+
+ TCL_PRECISION = TkVarAccess.new('tcl_precision')
+end
diff --git a/ext/tk/lib/tk/virtevent.rb b/ext/tk/lib/tk/virtevent.rb
new file mode 100644
index 0000000000..ae31ac1f8f
--- /dev/null
+++ b/ext/tk/lib/tk/virtevent.rb
@@ -0,0 +1,139 @@
+#
+# tk/virtevent.rb : treats virtual events
+# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+class TkVirtualEvent<TkObject
+ extend Tk
+
+ TkCommandNames = ['event'.freeze].freeze
+
+ (TkVirtualEventID = ["VirtEvent".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkVirtualEventTBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ TkVirtualEventTBL.mutex.synchronize{ TkVirtualEventTBL.clear }
+ }
+
+ class PreDefVirtEvent<self
+ def self.new(event, *sequences)
+ if event =~ /^<(<.*>)>$/
+ event = $1
+ elsif event !~ /^<.*>$/
+ event = '<' + event + '>'
+ end
+ TkVirtualEvent::TkVirtualEventTBL.mutex.synchronize{
+ if TkVirtualEvent::TkVirtualEventTBL.has_key?(event)
+ TkVirtualEvent::TkVirtualEventTBL[event]
+ else
+ # super(event, *sequences)
+ (obj = self.allocate).instance_eval{
+ initialize(event, *sequences)
+ TkVirtualEvent::TkVirtualEventTBL[@id] = self
+ }
+ end
+ }
+ end
+
+ def initialize(event, *sequences)
+ @path = @id = event
+ _add_sequences(sequences)
+ end
+ end
+
+ def TkVirtualEvent.getobj(event)
+ obj = nil
+ TkVirtualEventTBL.mutex.synchronize{
+ obj = TkVirtualEventTBL[event]
+ }
+ if obj
+ obj
+ else
+ if tk_call_without_enc('event', 'info').index("<#{event}>")
+ PreDefVirtEvent.new(event)
+ else
+ fail ArgumentError, "undefined virtual event '<#{event}>'"
+ end
+ end
+ end
+
+ def TkVirtualEvent.info
+ tk_call_without_enc('event', 'info').split(/\s+/).collect!{|seq|
+ TkVirtualEvent.getobj(seq[1..-2])
+ }
+ end
+
+ def initialize(*sequences)
+ TkVirtualEventID.mutex.synchronize{
+ # @path = @id = '<' + TkVirtualEventID.join('') + '>'
+ @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>'
+ TkVirtualEventID[1].succ!
+ }
+ _add_sequences(sequences)
+ end
+
+ def _add_sequences(seq_ary)
+ unless seq_ary.empty?
+ tk_call_without_enc('event', 'add', "<#{@id}>",
+ *(seq_ary.collect{|seq|
+ "<#{tk_event_sequence(seq)}>"
+ }) )
+ end
+ self
+ end
+ private :_add_sequences
+
+ def add(*sequences)
+ if sequences != []
+ _add_sequences(sequences)
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL[@id] = self
+ }
+ end
+ self
+ end
+
+ def delete(*sequences)
+ if sequences == []
+ tk_call_without_enc('event', 'delete', "<#{@id}>")
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL.delete(@id)
+ }
+ else
+ tk_call_without_enc('event', 'delete', "<#{@id}>",
+ *(sequences.collect{|seq|
+ "<#{tk_event_sequence(seq)}>"
+ }) )
+ if tk_call_without_enc('event','info',"<#{@id}>").empty?
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL.delete(@id)
+ }
+ end
+ end
+ self
+ end
+
+ def info
+ tk_call_without_enc('event','info',"<#{@id}>").split(/\s+/).collect!{|seq|
+ lst = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
+ case (subseq)
+ when /^<<[^<>]+>>$/
+ TkVirtualEvent.getobj(subseq[1..-2])
+ when /^<[^<>]+>$/
+ subseq[1..-2]
+ else
+ subseq.split('')
+ end
+ }.flatten
+ (lst.size == 1) ? lst[0] : lst
+ }
+ end
+end
+
+TkNamedVirtualEvent = TkVirtualEvent::PreDefVirtEvent
diff --git a/ext/tk/lib/tk/winfo.rb b/ext/tk/lib/tk/winfo.rb
new file mode 100644
index 0000000000..c649b4a0c9
--- /dev/null
+++ b/ext/tk/lib/tk/winfo.rb
@@ -0,0 +1,392 @@
+#
+# tk/winfo.rb : methods for winfo command
+#
+module TkWinfo
+end
+
+require 'tk'
+
+module TkWinfo
+ include Tk
+ extend Tk
+
+ TkCommandNames = ['winfo'.freeze].freeze
+
+ def TkWinfo.atom(name, win=nil)
+ if win
+ number(tk_call_without_enc('winfo', 'atom', '-displayof', win,
+ _get_eval_enc_str(name)))
+ else
+ number(tk_call_without_enc('winfo', 'atom', _get_eval_enc_str(name)))
+ end
+ end
+ def winfo_atom(name)
+ TkWinfo.atom(name, self)
+ end
+
+ def TkWinfo.atomname(id, win=nil)
+ if win
+ _fromUTF8(tk_call_without_enc('winfo', 'atomname',
+ '-displayof', win, id))
+ else
+ _fromUTF8(tk_call_without_enc('winfo', 'atomname', id))
+ end
+ end
+ def winfo_atomname(id)
+ TkWinfo.atomname(id, self)
+ end
+
+ def TkWinfo.cells(win)
+ number(tk_call_without_enc('winfo', 'cells', win))
+ end
+ def winfo_cells
+ TkWinfo.cells self
+ end
+
+ def TkWinfo.children(win)
+ list(tk_call_without_enc('winfo', 'children', win))
+ end
+ def winfo_children
+ TkWinfo.children self
+ end
+
+ def TkWinfo.classname(win)
+ tk_call_without_enc('winfo', 'class', win)
+ end
+ def winfo_classname
+ TkWinfo.classname self
+ end
+ alias winfo_class winfo_classname
+
+ def TkWinfo.colormapfull(win)
+ bool(tk_call_without_enc('winfo', 'colormapfull', win))
+ end
+ def winfo_colormapfull
+ TkWinfo.colormapfull self
+ end
+
+ def TkWinfo.containing(rootX, rootY, win=nil)
+ if win
+ window(tk_call_without_enc('winfo', 'containing',
+ '-displayof', win, rootX, rootY))
+ else
+ window(tk_call_without_enc('winfo', 'containing', rootX, rootY))
+ end
+ end
+ def winfo_containing(x, y)
+ TkWinfo.containing(x, y, self)
+ end
+
+ def TkWinfo.depth(win)
+ number(tk_call_without_enc('winfo', 'depth', win))
+ end
+ def winfo_depth
+ TkWinfo.depth self
+ end
+
+ def TkWinfo.exist?(win)
+ bool(tk_call_without_enc('winfo', 'exists', win))
+ end
+ def winfo_exist?
+ TkWinfo.exist? self
+ end
+
+ def TkWinfo.fpixels(win, dist)
+ number(tk_call_without_enc('winfo', 'fpixels', win, dist))
+ end
+ def winfo_fpixels(dist)
+ TkWinfo.fpixels self, dist
+ end
+
+ def TkWinfo.geometry(win)
+ tk_call_without_enc('winfo', 'geometry', win)
+ end
+ def winfo_geometry
+ TkWinfo.geometry self
+ end
+
+ def TkWinfo.height(win)
+ number(tk_call_without_enc('winfo', 'height', win))
+ end
+ def winfo_height
+ TkWinfo.height self
+ end
+
+ def TkWinfo.id(win)
+ tk_call_without_enc('winfo', 'id', win)
+ end
+ def winfo_id
+ TkWinfo.id self
+ end
+
+ def TkWinfo.interps(win=nil)
+ if win
+ #tk_split_simplelist(tk_call_without_enc('winfo', 'interps',
+ # '-displayof', win))
+ tk_split_simplelist(tk_call_without_enc('winfo', 'interps',
+ '-displayof', win),
+ false, true)
+ else
+ #tk_split_simplelist(tk_call_without_enc('winfo', 'interps'))
+ tk_split_simplelist(tk_call_without_enc('winfo', 'interps'),
+ false, true)
+ end
+ end
+ def winfo_interps
+ TkWinfo.interps self
+ end
+
+ def TkWinfo.mapped?(win)
+ bool(tk_call_without_enc('winfo', 'ismapped', win))
+ end
+ def winfo_mapped?
+ TkWinfo.mapped? self
+ end
+
+ def TkWinfo.manager(win)
+ tk_call_without_enc('winfo', 'manager', win)
+ end
+ def winfo_manager
+ TkWinfo.manager self
+ end
+
+ def TkWinfo.appname(win)
+ tk_call('winfo', 'name', win)
+ end
+ def winfo_appname
+ TkWinfo.appname self
+ end
+
+ def TkWinfo.parent(win)
+ window(tk_call_without_enc('winfo', 'parent', win))
+ end
+ def winfo_parent
+ TkWinfo.parent self
+ end
+
+ def TkWinfo.widget(id, win=nil)
+ if win
+ window(tk_call_without_enc('winfo', 'pathname', '-displayof', win, id))
+ else
+ window(tk_call_without_enc('winfo', 'pathname', id))
+ end
+ end
+ def winfo_widget(id)
+ TkWinfo.widget id, self
+ end
+
+ def TkWinfo.pixels(win, dist)
+ number(tk_call_without_enc('winfo', 'pixels', win, dist))
+ end
+ def winfo_pixels(dist)
+ TkWinfo.pixels self, dist
+ end
+
+ def TkWinfo.reqheight(win)
+ number(tk_call_without_enc('winfo', 'reqheight', win))
+ end
+ def winfo_reqheight
+ TkWinfo.reqheight self
+ end
+
+ def TkWinfo.reqwidth(win)
+ number(tk_call_without_enc('winfo', 'reqwidth', win))
+ end
+ def winfo_reqwidth
+ TkWinfo.reqwidth self
+ end
+
+ def TkWinfo.rgb(win, color)
+ list(tk_call_without_enc('winfo', 'rgb', win, color))
+ end
+ def winfo_rgb(color)
+ TkWinfo.rgb self, color
+ end
+
+ def TkWinfo.rootx(win)
+ number(tk_call_without_enc('winfo', 'rootx', win))
+ end
+ def winfo_rootx
+ TkWinfo.rootx self
+ end
+
+ def TkWinfo.rooty(win)
+ number(tk_call_without_enc('winfo', 'rooty', win))
+ end
+ def winfo_rooty
+ TkWinfo.rooty self
+ end
+
+ def TkWinfo.screen(win)
+ tk_call('winfo', 'screen', win)
+ end
+ def winfo_screen
+ TkWinfo.screen self
+ end
+
+ def TkWinfo.screencells(win)
+ number(tk_call_without_enc('winfo', 'screencells', win))
+ end
+ def winfo_screencells
+ TkWinfo.screencells self
+ end
+
+ def TkWinfo.screendepth(win)
+ number(tk_call_without_enc('winfo', 'screendepth', win))
+ end
+ def winfo_screendepth
+ TkWinfo.screendepth self
+ end
+
+ def TkWinfo.screenheight (win)
+ number(tk_call_without_enc('winfo', 'screenheight', win))
+ end
+ def winfo_screenheight
+ TkWinfo.screenheight self
+ end
+
+ def TkWinfo.screenmmheight(win)
+ number(tk_call_without_enc('winfo', 'screenmmheight', win))
+ end
+ def winfo_screenmmheight
+ TkWinfo.screenmmheight self
+ end
+
+ def TkWinfo.screenmmwidth(win)
+ number(tk_call_without_enc('winfo', 'screenmmwidth', win))
+ end
+ def winfo_screenmmwidth
+ TkWinfo.screenmmwidth self
+ end
+
+ def TkWinfo.screenvisual(win)
+ tk_call_without_enc('winfo', 'screenvisual', win)
+ end
+ def winfo_screenvisual
+ TkWinfo.screenvisual self
+ end
+
+ def TkWinfo.screenwidth(win)
+ number(tk_call_without_enc('winfo', 'screenwidth', win))
+ end
+ def winfo_screenwidth
+ TkWinfo.screenwidth self
+ end
+
+ def TkWinfo.server(win)
+ tk_call('winfo', 'server', win)
+ end
+ def winfo_server
+ TkWinfo.server self
+ end
+
+ def TkWinfo.toplevel(win)
+ window(tk_call_without_enc('winfo', 'toplevel', win))
+ end
+ def winfo_toplevel
+ TkWinfo.toplevel self
+ end
+
+ def TkWinfo.visual(win)
+ tk_call_without_enc('winfo', 'visual', win)
+ end
+ def winfo_visual
+ TkWinfo.visual self
+ end
+
+ def TkWinfo.visualid(win)
+ tk_call_without_enc('winfo', 'visualid', win)
+ end
+ def winfo_visualid
+ TkWinfo.visualid self
+ end
+
+ def TkWinfo.visualsavailable(win, includeids=false)
+ if includeids
+ list(tk_call_without_enc('winfo', 'visualsavailable',
+ win, "includeids"))
+ else
+ list(tk_call_without_enc('winfo', 'visualsavailable', win))
+ end
+ end
+ def winfo_visualsavailable(includeids=false)
+ TkWinfo.visualsavailable self, includeids
+ end
+
+ def TkWinfo.vrootheight(win)
+ number(tk_call_without_enc('winfo', 'vrootheight', win))
+ end
+ def winfo_vrootheight
+ TkWinfo.vrootheight self
+ end
+
+ def TkWinfo.vrootwidth(win)
+ number(tk_call_without_enc('winfo', 'vrootwidth', win))
+ end
+ def winfo_vrootwidth
+ TkWinfo.vrootwidth self
+ end
+
+ def TkWinfo.vrootx(win)
+ number(tk_call_without_enc('winfo', 'vrootx', win))
+ end
+ def winfo_vrootx
+ TkWinfo.vrootx self
+ end
+
+ def TkWinfo.vrooty(win)
+ number(tk_call_without_enc('winfo', 'vrooty', win))
+ end
+ def winfo_vrooty
+ TkWinfo.vrooty self
+ end
+
+ def TkWinfo.width(win)
+ number(tk_call_without_enc('winfo', 'width', win))
+ end
+ def winfo_width
+ TkWinfo.width self
+ end
+
+ def TkWinfo.x(win)
+ number(tk_call_without_enc('winfo', 'x', win))
+ end
+ def winfo_x
+ TkWinfo.x self
+ end
+
+ def TkWinfo.y(win)
+ number(tk_call_without_enc('winfo', 'y', win))
+ end
+ def winfo_y
+ TkWinfo.y self
+ end
+
+ def TkWinfo.viewable(win)
+ bool(tk_call_without_enc('winfo', 'viewable', win))
+ end
+ def winfo_viewable
+ TkWinfo.viewable self
+ end
+
+ def TkWinfo.pointerx(win)
+ number(tk_call_without_enc('winfo', 'pointerx', win))
+ end
+ def winfo_pointerx
+ TkWinfo.pointerx self
+ end
+
+ def TkWinfo.pointery(win)
+ number(tk_call_without_enc('winfo', 'pointery', win))
+ end
+ def winfo_pointery
+ TkWinfo.pointery self
+ end
+
+ def TkWinfo.pointerxy(win)
+ list(tk_call_without_enc('winfo', 'pointerxy', win))
+ end
+ def winfo_pointerxy
+ TkWinfo.pointerxy self
+ end
+end
diff --git a/ext/tk/lib/tk/winpkg.rb b/ext/tk/lib/tk/winpkg.rb
new file mode 100644
index 0000000000..89fb391c77
--- /dev/null
+++ b/ext/tk/lib/tk/winpkg.rb
@@ -0,0 +1,153 @@
+#
+# tk/winpkg.rb : methods for Tcl/Tk packages for Microsoft Windows
+# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+# ATTENTION !!
+# This is NOT TESTED. Because I have no test-environment.
+#
+require 'tk'
+
+module Tk::WinDDE
+end
+#TkWinDDE = Tk::WinDDE
+Tk.__set_toplevel_aliases__(:Tk, Tk::WinDDE, :TkWinDDE)
+
+module Tk::WinDDE
+ extend Tk
+ extend Tk::WinDDE
+
+ TkCommandNames = ['dde'.freeze].freeze
+
+ PACKAGE_NAME = 'dde'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ if self.const_defined? :FORCE_VERSION
+ tk_call_without_enc('package', 'require', 'dde', FORCE_VERSION)
+ else
+ tk_call_without_enc('package', 'require', 'dde')
+ end
+
+ #def servername(topic=None)
+ # tk_call('dde', 'servername', topic)
+ #end
+ def servername(*args)
+ if args.size == 0
+ tk_call('dde', 'servername')
+ else
+ if args[-1].kind_of?(Hash) # dde 1.2 +
+ keys = _symbolkey2str(args.pop)
+ force = (keys.delete('force'))? '-force': None
+ exact = (keys.delete('exact'))? '-exact': None
+ if keys.size == 0
+ tk_call('dde', 'servername', force, exact)
+ elsif args.size == 0
+ tk_call('dde', 'servername', force, exact, *hash_kv(keys))
+ else
+ tk_call('dde', 'servername', force, exact,
+ *((hash_kv(keys) << '--') + args))
+ end
+ else
+ tk_call('dde', 'servername', *args)
+ end
+ end
+ end
+
+ def execute(service, topic, data)
+ tk_call('dde', 'execute', service, topic, data)
+ end
+
+ def async_execute(service, topic, data)
+ tk_call('dde', '-async', 'execute', service, topic, data)
+ end
+
+ def poke(service, topic, item, data)
+ tk_call('dde', 'poke', service, topic, item, data)
+ end
+
+ def request(service, topic, item)
+ tk_call('dde', 'request', service, topic, item)
+ end
+
+ def binary_request(service, topic, item)
+ tk_call('dde', 'request', '-binary', service, topic, item)
+ end
+
+ def services(service, topic)
+ tk_call('dde', 'services', service, topic)
+ end
+
+ def eval(topic, cmd, *args)
+ tk_call('dde', 'eval', topic, cmd, *args)
+ end
+
+ def async_eval(topic, cmd, *args)
+ tk_call('dde', 'eval', -async, topic, cmd, *args)
+ end
+
+ module_function :servername, :execute, :async_execute,
+ :poke, :request, :services, :eval
+end
+
+module Tk::WinRegistry
+end
+#TkWinRegistry = Tk::WinRegistry
+Tk.__set_toplevel_aliases__(:Tk, Tk::WinRegistry, :TkWinRegistry)
+
+module Tk::WinRegistry
+ extend Tk
+ extend Tk::WinRegistry
+
+ TkCommandNames = ['registry'.freeze].freeze
+
+ if self.const_defined? :FORCE_VERSION
+ tk_call('package', 'require', 'registry', FORCE_VERSION)
+ else
+ tk_call('package', 'require', 'registry')
+ end
+
+ def broadcast(keynam, timeout=nil)
+ if timeout
+ tk_call('registry', 'broadcast', keynam, '-timeout', timeout)
+ else
+ tk_call('registry', 'broadcast', keynam)
+ end
+ end
+
+ def delete(keynam, valnam=None)
+ tk_call('registry', 'delete', keynam, valnam)
+ end
+
+ def get(keynam, valnam)
+ tk_call('registry', 'get', keynam, valnam)
+ end
+
+ def keys(keynam, pattern=nil)
+ lst = tk_split_simplelist(tk_call('registry', 'keys', keynam))
+ if pattern
+ lst.find_all{|key| key =~ pattern}
+ else
+ lst
+ end
+ end
+
+ def set(keynam, valnam=None, data=None, dattype=None)
+ tk_call('registry', 'set', keynam, valnam, data, dattype)
+ end
+
+ def type(keynam, valnam)
+ tk_call('registry', 'type', keynam, valnam)
+ end
+
+ def values(keynam, pattern=nil)
+ lst = tk_split_simplelist(tk_call('registry', 'values', keynam))
+ if pattern
+ lst.find_all{|val| val =~ pattern}
+ else
+ lst
+ end
+ end
+
+ module_function :delete, :get, :keys, :set, :type, :values
+end
diff --git a/ext/tk/lib/tk/wm.rb b/ext/tk/lib/tk/wm.rb
new file mode 100644
index 0000000000..0394296189
--- /dev/null
+++ b/ext/tk/lib/tk/wm.rb
@@ -0,0 +1,552 @@
+#
+# tk/wm.rb : methods for wm command
+#
+require 'tk'
+
+module Tk
+ module Wm
+ #include TkComm
+ extend TkCore
+
+ TkCommandNames = ['wm'.freeze].freeze
+
+ TOPLEVEL_METHODCALL_OPTKEYS = {}
+
+ def Wm.aspect(win, *args)
+ if args.length == 0
+ list(tk_call_without_enc('wm', 'aspect', win.epath))
+ else
+ args = args[0] if args.length == 1 && args[0].kind_of?(Array)
+ tk_call('wm', 'aspect', win.epath, *args)
+ win
+ end
+ end
+ def aspect(*args)
+ Wm.aspect(self, *args)
+ end
+ alias wm_aspect aspect
+ TOPLEVEL_METHODCALL_OPTKEYS['aspect'] = 'aspect'
+
+ def Wm.attributes(win, slot=nil,value=TkComm::None)
+ if slot == nil
+ lst = tk_split_list(tk_call('wm', 'attributes', win.epath))
+ info = {}
+ while key = lst.shift
+ info[key[1..-1]] = lst.shift
+ end
+ info
+ elsif slot.kind_of? Hash
+ tk_call('wm', 'attributes', win.epath, *hash_kv(slot))
+ win
+ elsif value == TkComm::None
+ tk_call('wm', 'attributes', win.epath, "-#{slot}")
+ else
+ tk_call('wm', 'attributes', win.epath, "-#{slot}", value)
+ win
+ end
+ end
+ def attributes(slot=nil,value=TkComm::None)
+ Wm.attributes(self, slot, value)
+ end
+ alias wm_attributes attributes
+ TOPLEVEL_METHODCALL_OPTKEYS['attributes'] = 'attributes'
+
+ def Wm.client(win, name=TkComm::None)
+ if name == TkComm::None
+ tk_call('wm', 'client', win.epath)
+ else
+ name = '' if name == nil
+ tk_call('wm', 'client', win.epath, name)
+ win
+ end
+ end
+ def client(name=TkComm::None)
+ Wm.client(self, name)
+ end
+ alias wm_client client
+ TOPLEVEL_METHODCALL_OPTKEYS['client'] = 'client'
+
+ def Wm.colormapwindows(win, *args)
+ if args.size == 0
+ list(tk_call_without_enc('wm', 'colormapwindows', win.epath))
+ else
+ args = args[0] if args.length == 1 && args[0].kind_of?(Array)
+ tk_call_without_enc('wm', 'colormapwindows', win.epath, *args)
+ win
+ end
+ end
+ def colormapwindows(*args)
+ Wm.colormapwindows(self, *args)
+ end
+ alias wm_colormapwindows colormapwindows
+ TOPLEVEL_METHODCALL_OPTKEYS['colormapwindows'] = 'colormapwindows'
+
+ def Wm.command(win, value=nil)
+ if value
+ tk_call('wm', 'command', epath, value)
+ win
+ else
+ #procedure(tk_call('wm', 'command', epath))
+ tk_call('wm', 'command', epath)
+ end
+ end
+ def wm_command(value=nil)
+ Wm.command(self, value)
+ end
+ TOPLEVEL_METHODCALL_OPTKEYS['wm_command'] = 'wm_command'
+
+ def Wm.deiconify(win, ex = true)
+ if ex
+ tk_call_without_enc('wm', 'deiconify', win.epath)
+ else
+ Wm.iconify(win)
+ end
+ win
+ end
+ def deiconify(ex = true)
+ Wm.deiconify(self, ex)
+ end
+ alias wm_deiconify deiconify
+
+ def Wm.focusmodel(win, mode = nil)
+ if mode
+ tk_call_without_enc('wm', 'focusmodel', win.epath, mode)
+ win
+ else
+ tk_call_without_enc('wm', 'focusmodel', win.epath)
+ end
+ end
+ def focusmodel(mode = nil)
+ Wm.focusmodel(self, mode)
+ end
+ alias wm_focusmodel focusmodel
+ TOPLEVEL_METHODCALL_OPTKEYS['focusmodel'] = 'focusmodel'
+
+ def Wm.forget(win)
+ # Tcl/Tk 8.5+
+ # work with dockable frames
+ tk_call_without_enc('wm', 'forget', win.epath)
+ win
+ end
+ def wm_forget
+ Wm.forget(self)
+ end
+
+ def Wm.frame(win)
+ tk_call_without_enc('wm', 'frame', win.epath)
+ end
+ def frame
+ Wm.frame(self)
+ end
+ alias wm_frame frame
+
+ def Wm.geometry(win, geom=nil)
+ if geom
+ tk_call_without_enc('wm', 'geometry', win.epath, geom)
+ win
+ else
+ tk_call_without_enc('wm', 'geometry', win.epath)
+ end
+ end
+ def geometry(geom=nil)
+ Wm.geometry(self, geom)
+ end
+ alias wm_geometry geometry
+ TOPLEVEL_METHODCALL_OPTKEYS['geometry'] = 'geometry'
+
+ def Wm.grid(win, *args)
+ if args.size == 0
+ list(tk_call_without_enc('wm', 'grid', win.epath))
+ else
+ args = args[0] if args.length == 1 && args[0].kind_of?(Array)
+ tk_call_without_enc('wm', 'grid', win.epath, *args)
+ win
+ end
+ end
+ def wm_grid(*args)
+ Wm.grid(self, *args)
+ end
+ TOPLEVEL_METHODCALL_OPTKEYS['wm_grid'] = 'wm_grid'
+
+ def Wm.group(win, leader = nil)
+ if leader
+ tk_call('wm', 'group', win.epath, leader)
+ win
+ else
+ window(tk_call('wm', 'group', win.epath))
+ end
+ end
+ def group(leader = nil)
+ Wm.group(self, leader)
+ end
+ alias wm_group group
+ TOPLEVEL_METHODCALL_OPTKEYS['group'] = 'group'
+
+ def Wm.iconbitmap(win, bmp=nil)
+ if bmp
+ tk_call_without_enc('wm', 'iconbitmap', win.epath, bmp)
+ win
+ else
+ image_obj(tk_call_without_enc('wm', 'iconbitmap', win.epath))
+ end
+ end
+ def iconbitmap(bmp=nil)
+ Wm.iconbitmap(self, bmp)
+ end
+ alias wm_iconbitmap iconbitmap
+ TOPLEVEL_METHODCALL_OPTKEYS['iconbitmap'] = 'iconbitmap'
+
+ def Wm.iconphoto(win, *imgs)
+ if imgs.empty?
+ win.instance_eval{
+ @wm_iconphoto = nil unless defined? @wm_iconphoto
+ return @wm_iconphoto
+ }
+ end
+
+ imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array)
+ tk_call_without_enc('wm', 'iconphoto', win.epath, *imgs)
+ win.instance_eval{ @wm_iconphoto = imgs }
+ win
+ end
+ def iconphoto(*imgs)
+ Wm.iconphoto(self, *imgs)
+ end
+ alias wm_iconphoto iconphoto
+ TOPLEVEL_METHODCALL_OPTKEYS['iconphoto'] = 'iconphoto'
+
+ def Wm.iconphoto_default(win, *imgs)
+ imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array)
+ tk_call_without_enc('wm', 'iconphoto', win.epath, '-default', *imgs)
+ win
+ end
+ def iconphoto_default(*imgs)
+ Wm.iconphoto_default(self, *imgs)
+ end
+ alias wm_iconphoto_default iconphoto_default
+
+ def Wm.iconify(win, ex = true)
+ if ex
+ tk_call_without_enc('wm', 'iconify', win.epath)
+ else
+ Wm.deiconify(win)
+ end
+ win
+ end
+ def iconify(ex = true)
+ Wm.iconify(self, ex)
+ end
+ alias wm_iconify iconify
+
+ def Wm.iconmask(win, bmp=nil)
+ if bmp
+ tk_call_without_enc('wm', 'iconmask', win.epath, bmp)
+ win
+ else
+ image_obj(tk_call_without_enc('wm', 'iconmask', win.epath))
+ end
+ end
+ def iconmask(bmp=nil)
+ Wm.iconmask(self, bmp)
+ end
+ alias wm_iconmask iconmask
+ TOPLEVEL_METHODCALL_OPTKEYS['iconmask'] = 'iconmask'
+
+ def Wm.iconname(win, name=nil)
+ if name
+ tk_call('wm', 'iconname', win.epath, name)
+ win
+ else
+ tk_call('wm', 'iconname', win.epath)
+ end
+ end
+ def iconname(name=nil)
+ Wm.iconname(self, name)
+ end
+ alias wm_iconname iconname
+ TOPLEVEL_METHODCALL_OPTKEYS['iconname'] = 'iconname'
+
+ def Wm.iconposition(win, *args)
+ if args.size == 0
+ list(tk_call_without_enc('wm', 'iconposition', win.epath))
+ else
+ args = args[0] if args.length == 1 && args[0].kind_of?(Array)
+ tk_call_without_enc('wm', 'iconposition', win.epath, *args)
+ win
+ end
+ end
+ def iconposition(*args)
+ Wm.iconposition(self, *args)
+ end
+ alias wm_iconposition iconposition
+ TOPLEVEL_METHODCALL_OPTKEYS['iconposition'] = 'iconposition'
+
+ def Wm.iconwindow(win, iconwin = nil)
+ if iconwin
+ tk_call_without_enc('wm', 'iconwindow', win.epath, iconwin)
+ win
+ else
+ w = tk_call_without_enc('wm', 'iconwindow', win.epath)
+ (w == '')? nil: window(w)
+ end
+ end
+ def iconwindow(iconwin = nil)
+ Wm.iconwindow(self, iconwin)
+ end
+ alias wm_iconwindow iconwindow
+ TOPLEVEL_METHODCALL_OPTKEYS['iconwindow'] = 'iconwindow'
+
+ def Wm.manage(win)
+ # Tcl/Tk 8.5+ feature
+ tk_call_without_enc('wm', 'manage', win.epath)
+ win
+ end
+ def wm_manage
+ Wm.manage(self)
+ end
+=begin
+ def Wm.manage(win, use_id = nil)
+ # Tcl/Tk 8.5+ feature
+ # --------------------------------------------------------------
+ # In the future release, I want to support to embed the 'win'
+ # into the container which has window-id 'use-id'.
+ # It may give users frexibility on controlling their GUI.
+ # However, it may be difficult for current Tcl/Tk (Tcl/Tk8.5.1),
+ # because it seems to require to modify Tcl/Tk's source code.
+ # --------------------------------------------------------------
+ if use_id
+ tk_call_without_enc('wm', 'manage', win.epath, '-use', use_id)
+ else
+ tk_call_without_enc('wm', 'manage', win.epath)
+ end
+ win
+ end
+=end
+
+ def Wm.maxsize(win, *args)
+ if args.size == 0
+ list(tk_call_without_enc('wm', 'maxsize', win.epath))
+ else
+ args = args[0] if args.length == 1 && args[0].kind_of?(Array)
+ tk_call_without_enc('wm', 'maxsize', win.epath, *args)
+ win
+ end
+ end
+ def maxsize(*args)
+ Wm.maxsize(self, *args)
+ end
+ alias wm_maxsize maxsize
+ TOPLEVEL_METHODCALL_OPTKEYS['maxsize'] = 'maxsize'
+
+ def Wm.minsize(win, *args)
+ if args.size == 0
+ list(tk_call_without_enc('wm', 'minsize', win.epath))
+ else
+ args = args[0] if args.length == 1 && args[0].kind_of?(Array)
+ tk_call_without_enc('wm', 'minsize', win.path, *args)
+ win
+ end
+ end
+ def minsize(*args)
+ Wm.minsize(self, *args)
+ end
+ alias wm_minsize minsize
+ TOPLEVEL_METHODCALL_OPTKEYS['minsize'] = 'minsize'
+
+ def Wm.overrideredirect(win, mode=TkComm::None)
+ if mode == TkComm::None
+ bool(tk_call_without_enc('wm', 'overrideredirect', win.epath))
+ else
+ tk_call_without_enc('wm', 'overrideredirect', win.epath, mode)
+ win
+ end
+ end
+ def overrideredirect(mode=TkComm::None)
+ Wm.overrideredirect(self, mode)
+ end
+ alias wm_overrideredirect overrideredirect
+ TOPLEVEL_METHODCALL_OPTKEYS['overrideredirect'] = 'overrideredirect'
+
+ def Wm.positionfrom(win, who=TkComm::None)
+ if who == TkComm::None
+ r = tk_call_without_enc('wm', 'positionfrom', win.epath)
+ (r == "")? nil: r
+ else
+ tk_call_without_enc('wm', 'positionfrom', win.epath, who)
+ win
+ end
+ end
+ def positionfrom(who=TkComm::None)
+ Wm.positionfrom(self, who)
+ end
+ alias wm_positionfrom positionfrom
+ TOPLEVEL_METHODCALL_OPTKEYS['positionfrom'] = 'positionfrom'
+
+ def Wm.protocol(win, name=nil, cmd=nil, &b)
+ if cmd
+ tk_call_without_enc('wm', 'protocol', win.epath, name, cmd)
+ win
+ elsif b
+ tk_call_without_enc('wm', 'protocol', win.epath, name, proc(&b))
+ win
+ elsif name
+ result = tk_call_without_enc('wm', 'protocol', win.epath, name)
+ (result == "")? nil : tk_tcl2ruby(result)
+ else
+ tk_split_simplelist(tk_call_without_enc('wm', 'protocol', win.epath))
+ end
+ end
+ def protocol(name=nil, cmd=nil, &b)
+ Wm.protocol(self, name, cmd, &b)
+ end
+ alias wm_protocol protocol
+
+ def Wm.protocols(win, kv=nil)
+ unless kv
+ ret = {}
+ Wm.protocol(win).each{|name|
+ ret[name] = Wm.protocol(win, name)
+ }
+ return ret
+ end
+
+ unless kv.kind_of?(Hash)
+ fail ArgumentError, 'expect a hash of protocol=>command'
+ end
+ kv.each{|k, v| Wm.protocol(win, k, v)}
+ win
+ end
+ def protocols(kv=nil)
+ Wm.protocols(self, kv)
+ end
+ alias wm_protocols protocols
+ TOPLEVEL_METHODCALL_OPTKEYS['protocols'] = 'protocols'
+
+ def Wm.resizable(win, *args)
+ if args.length == 0
+ list(tk_call_without_enc('wm', 'resizable', win.epath)).map!{|e| bool(e)}
+ else
+ args = args[0] if args.length == 1 && args[0].kind_of?(Array)
+ tk_call_without_enc('wm', 'resizable', win.epath, *args)
+ win
+ end
+ end
+ def resizable(*args)
+ Wm.resizable(self, *args)
+ end
+ alias wm_resizable resizable
+ TOPLEVEL_METHODCALL_OPTKEYS['resizable'] = 'resizable'
+
+ def Wm.sizefrom(win, who=TkComm::None)
+ if who == TkComm::None
+ r = tk_call_without_enc('wm', 'sizefrom', win.epath)
+ (r == "")? nil: r
+ else
+ tk_call_without_enc('wm', 'sizefrom', win.epath, who)
+ win
+ end
+ end
+ def sizefrom(who=TkComm::None)
+ Wm.sizefrom(self, who)
+ end
+ alias wm_sizefrom sizefrom
+ TOPLEVEL_METHODCALL_OPTKEYS['sizefrom'] = 'sizefrom'
+
+ def Wm.stackorder(win)
+ list(tk_call('wm', 'stackorder', win.epath))
+ end
+ def stackorder
+ Wm.stackorder(self)
+ end
+ alias wm_stackorder stackorder
+
+ def Wm.stackorder_isabove(win, target)
+ bool(tk_call('wm', 'stackorder', win.epath, 'isabove', target))
+ end
+ def Wm.stackorder_is_above(win, target)
+ Wm.stackorder_isabove(win, target)
+ end
+ def stackorder_isabove(target)
+ Wm.stackorder_isabove(self, target)
+ end
+ alias stackorder_is_above stackorder_isabove
+ alias wm_stackorder_isabove stackorder_isabove
+ alias wm_stackorder_is_above stackorder_isabove
+
+ def Wm.stackorder_isbelow(win, target)
+ bool(tk_call('wm', 'stackorder', win.epath, 'isbelow', target))
+ end
+ def Wm.stackorder_is_below(win, target)
+ Wm.stackorder_isbelow(win, target)
+ end
+ def stackorder_isbelow(target)
+ Wm.stackorder_isbelow(self, target)
+ end
+ alias stackorder_is_below stackorder_isbelow
+ alias wm_stackorder_isbelow stackorder_isbelow
+ alias wm_stackorder_is_below stackorder_isbelow
+
+ def Wm.state(win, st=nil)
+ if st
+ tk_call_without_enc('wm', 'state', win.epath, st)
+ win
+ else
+ tk_call_without_enc('wm', 'state', win.epath)
+ end
+ end
+ def state(st=nil)
+ Wm.state(self, st)
+ end
+ alias wm_state state
+ TOPLEVEL_METHODCALL_OPTKEYS['state'] = 'state'
+
+ def Wm.title(win, str=nil)
+ if str
+ tk_call('wm', 'title', win.epath, str)
+ win
+ else
+ tk_call('wm', 'title', win.epath)
+ end
+ end
+ def title(str=nil)
+ Wm.title(self, str)
+ end
+ alias wm_title title
+ TOPLEVEL_METHODCALL_OPTKEYS['title'] = 'title'
+
+ def Wm.transient(win, master=nil)
+ if master
+ tk_call_without_enc('wm', 'transient', win.epath, master)
+ win
+ else
+ window(tk_call_without_enc('wm', 'transient', win.epath))
+ end
+ end
+ def transient(master=nil)
+ Wm.transient(self, master)
+ end
+ alias wm_transient transient
+ TOPLEVEL_METHODCALL_OPTKEYS['transient'] = 'transient'
+
+ def Wm.withdraw(win, ex = true)
+ if ex
+ tk_call_without_enc('wm', 'withdraw', win.epath)
+ else
+ Wm.deiconify(win)
+ end
+ win
+ end
+ def withdraw(ex = true)
+ Wm.withdraw(self, ex)
+ end
+ alias wm_withdraw withdraw
+ end
+
+ module Wm_for_General
+ Wm.instance_methods.each{|m|
+ if (m = m.to_s) =~ /^wm_(.*)$/
+ eval "def #{m}(*args, &b); Tk::Wm.#{$1}(self, *args, &b); end"
+ end
+ }
+ end
+end
diff --git a/ext/tk/lib/tk/xim.rb b/ext/tk/lib/tk/xim.rb
new file mode 100644
index 0000000000..0ac8559bb9
--- /dev/null
+++ b/ext/tk/lib/tk/xim.rb
@@ -0,0 +1,122 @@
+#
+# tk/xim.rb : control imput_method
+#
+require 'tk'
+
+module TkXIM
+ include Tk
+ extend Tk
+
+ TkCommandNames = ['imconfigure'.freeze].freeze
+
+ def TkXIM.useinputmethods(value = None, win = nil)
+ if value == None
+ if win
+ bool(tk_call_without_enc('tk', 'useinputmethods',
+ '-displayof', win))
+ else
+ bool(tk_call_without_enc('tk', 'useinputmethods'))
+ end
+ else
+ if win
+ bool(tk_call_without_enc('tk', 'useinputmethods',
+ '-displayof', win, value))
+ else
+ bool(tk_call_without_enc('tk', 'useinputmethods', value))
+ end
+ end
+ end
+
+ def TkXIM.useinputmethods_displayof(win, value = None)
+ TkXIM.useinputmethods(value, win)
+ end
+
+ def TkXIM.caret(win, keys=nil)
+ if keys
+ tk_call_without_enc('tk', 'caret', win, *hash_kv(keys))
+ self
+ else
+ lst = tk_split_list(tk_call_without_enc('tk', 'caret', win))
+ info = {}
+ while key = lst.shift
+ info[key[1..-1]] = lst.shift
+ end
+ info
+ end
+ end
+
+ def TkXIM.configure(win, slot, value=None)
+ begin
+ if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
+ if slot.kind_of? Hash
+ tk_call('imconfigure', win, *hash_kv(slot))
+ else
+ tk_call('imconfigure', win, "-#{slot}", value)
+ end
+ end
+ rescue
+ end
+ end
+
+ def TkXIM.configinfo(win, slot=nil)
+ if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ begin
+ if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
+ if slot
+ conf = tk_split_list(tk_call('imconfigure', win, "-#{slot}"))
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_call('imconfigure', win)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ else
+ []
+ end
+ rescue
+ []
+ end
+ else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
+ TkXIM.current_configinfo(win, slot)
+ end
+ end
+
+ def TkXIM.current_configinfo(win, slot=nil)
+ begin
+ if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
+ if slot
+ conf = tk_split_list(tk_call('imconfigure', win, "-#{slot}"))
+ { conf[0][1..-1] => conf[1] }
+ else
+ ret = {}
+ tk_split_list(tk_call('imconfigure', win)).each{|conf|
+ ret[conf[0][1..-1]] = conf[1]
+ }
+ ret
+ end
+ else
+ {}
+ end
+ rescue
+ {}
+ end
+ end
+
+ def useinputmethods(value=None)
+ TkXIM.useinputmethods(value, self)
+ end
+
+ def caret(keys=nil)
+ TkXIM.caret(self, keys=nil)
+ end
+
+ def imconfigure(slot, value=None)
+ TkXIM.configure(self, slot, value)
+ end
+
+ def imconfiginfo(slot=nil)
+ TkXIM.configinfo(self, slot)
+ end
+end
diff --git a/ext/tk/lib/tkafter.rb b/ext/tk/lib/tkafter.rb
index 53e78b8808..f65945884c 100644
--- a/ext/tk/lib/tkafter.rb
+++ b/ext/tk/lib/tkafter.rb
@@ -1,414 +1,4 @@
#
-# tkafter.rb : methods for Tcl/Tk after command
+# tkafter.rb - load tk/after.rb
#
-# $Id$
-#
-require 'tk'
-
-class TkTimer
- include TkCore
- extend TkCore
-
- TkCommandNames = ['after'.freeze].freeze
-
- Tk_CBID = ['a'.freeze, '00000'.taint].freeze
- Tk_CBTBL = {}.taint
-
- TkCore::INTERP.add_tk_procs('rb_after', 'id', <<-'EOL')
- if {[set st [catch {ruby [format "TkTimer.callback %%Q!%s!" $id]} ret]] != 0} {
- return -code $st $ret
- } {
- return $ret
- }
- EOL
-
-
- ###############################
- # class methods
- ###############################
- def self.callback(obj_id)
- @after_id = nil
- ex_obj = Tk_CBTBL[obj_id]
- return "" if ex_obj == nil; # canceled
- ex_obj.cb_call
- end
-
- def self.info
- tk_call('after', 'info').split(' ').collect!{|id|
- ret = Tk_CBTBL.find{|key,val| val.after_id == id}
- (ret == nil)? id: ret[1]
- }
- end
-
- ###############################
- # instance methods
- ###############################
- def do_callback
- @in_callback = true
- begin
- @return_value = @current_proc.call(self)
- rescue Exception => e
- if @cancel_on_exception
- cancel
- @return_value = e
- return e
- else
- fail e
- end
- end
- if @set_next
- set_next_callback(@current_args)
- else
- @set_next = true
- end
- @in_callback = false
- @return_value
- end
-
- def set_callback(sleep, args=nil)
- @after_script = "rb_after #{@id}"
- @after_id = tk_call('after', sleep, @after_script)
- @current_args = args
- @current_script = [sleep, @after_script]
- self
- end
-
- def set_next_callback(args)
- if @running == false || @proc_max == 0 || @do_loop == 0
- Tk_CBTBL.delete(@id) ;# for GC
- @running = false
- @wait_var.value = 0
- return
- end
- if @current_pos >= @proc_max
- if @do_loop < 0 || (@do_loop -= 1) > 0
- @current_pos = 0
- else
- Tk_CBTBL.delete(@id) ;# for GC
- @running = false
- @wait_var.value = 0
- return
- end
- end
-
- @current_args = args
-
- if @sleep_time.kind_of? Proc
- sleep = @sleep_time.call(self)
- else
- sleep = @sleep_time
- end
- @current_sleep = sleep
-
- cmd, *cmd_args = @loop_proc[@current_pos]
- @current_pos += 1
- @current_proc = cmd
-
- set_callback(sleep, cmd_args)
- end
-
- def initialize(*args)
- @id = Tk_CBID.join
- Tk_CBID[1].succ!
-
- @wait_var = TkVariable.new(0)
-
- @cb_cmd = TkCore::INTERP.get_cb_entry(self.method(:do_callback))
-
- @set_next = true
-
- @init_sleep = 0
- @init_proc = nil
- @init_args = []
-
- @current_script = []
- @current_proc = nil
- @current_args = nil
- @return_value = nil
-
- @sleep_time = 0
- @current_sleep = 0
- @loop_exec = 0
- @do_loop = 0
- @loop_proc = []
- @proc_max = 0
- @current_pos = 0
-
- @after_id = nil
- @after_script = nil
-
- @cancel_on_exception = true
-
- set_procs(*args) if args != []
-
- @running = false
- @in_callback = false
- end
-
- attr :after_id
- attr :after_script
- attr :current_proc
- attr :current_args
- attr :current_sleep
- alias :current_interval :current_sleep
- attr :return_value
-
- attr_accessor :loop_exec
-
- def cb_call
- @cb_cmd.call
- end
-
- def get_procs
- [@init_sleep, @init_proc, @init_args, @sleep_time, @loop_exec, @loop_proc]
- end
-
- def current_status
- [@running, @current_sleep, @current_proc, @current_args,
- @do_loop, @cancel_on_exception]
- end
-
- def cancel_on_exception?
- @cancel_on_exception
- end
-
- def cancel_on_exception=(mode)
- @cancel_on_exception = mode
- self
- end
-
- def running?
- @running
- end
-
- def loop_rest
- @do_loop
- end
-
- def loop_rest=(rest)
- @do_loop = rest
- self
- end
-
- def set_procs(interval, loop_exec, *procs)
- if !interval == 'idle' \
- && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
- fail Kernel.format("%s need to be Integer or Proc", interval.inspect)
- end
- @sleep_time = interval
-
- @loop_proc = []
- procs.each{|e|
- if e.kind_of? Proc
- @loop_proc.push([e])
- else
- @loop_proc.push(e)
- end
- }
- @proc_max = @loop_proc.size
- @current_pos = 0
-
- @do_loop = 0
- if loop_exec
- if loop_exec.kind_of?(Integer) && loop_exec < 0
- @loop_exec = -1
- elsif loop_exec == nil || loop_exec == false || loop_exec == 0
- @loop_exec = 1
- else
- if not loop_exec.kind_of?(Integer)
- fail Kernel.format("%s need to be Integer", loop_exec.inspect)
- end
- @loop_exec = loop_exec
- end
- @do_loop = @loop_exec
- end
-
- self
- end
-
- def add_procs(*procs)
- procs.each{|e|
- if e.kind_of? Proc
- @loop_proc.push([e])
- else
- @loop_proc.push(e)
- end
- }
- @proc_max = @loop_proc.size
-
- self
- end
-
- def delete_procs(*procs)
- procs.each{|e|
- if e.kind_of? Proc
- @loop_proc.delete([e])
- else
- @loop_proc.delete(e)
- end
- }
- @proc_max = @loop_proc.size
-
- cancel if @proc_max == 0
-
- self
- end
-
- def delete_at(n)
- @loop_proc.delete_at(n)
- @proc_max = @loop_proc.size
- cancel if @proc_max == 0
- self
- end
-
- def set_start_proc(sleep, init_proc, *init_args)
- if !sleep == 'idle' && !sleep.kind_of?(Integer)
- fail Kernel.format("%s need to be Integer", sleep.inspect)
- end
- @init_sleep = sleep
- @init_proc = init_proc
- @init_args = init_args
- self
- end
-
- def start(*init_args)
- return nil if @running
-
- Tk_CBTBL[@id] = self
- @do_loop = @loop_exec
- @current_pos = 0
-
- argc = init_args.size
- if argc > 0
- sleep = init_args.shift
- if !sleep == 'idle' && !sleep.kind_of?(Integer)
- fail Kernel.format("%s need to be Integer", sleep.inspect)
- end
- @init_sleep = sleep
- end
- @init_proc = init_args.shift if argc > 1
- @init_args = init_args if argc > 0
-
- @current_sleep = @init_sleep
- @running = true
- if @init_proc
- if not @init_proc.kind_of? Proc
- fail Kernel.format("%s need to be Proc", @init_proc.inspect)
- end
- @current_proc = @init_proc
- set_callback(@init_sleep, @init_args)
- @set_next = false if @in_callback
- else
- set_next_callback(@init_args)
- end
-
- self
- end
-
- def reset(*reset_args)
- restart() if @running
-
- if @init_proc
- @return_value = @init_proc.call(self)
- else
- @return_value = nil
- end
-
- @current_pos = 0
- @current_args = @init_args
- @set_next = false if @in_callback
-
- self
- end
-
- def restart(*restart_args)
- cancel if @running
- if restart_args == []
- start(@init_sleep, @init_proc, *@init_args)
- else
- start(*restart_args)
- end
- end
-
- def cancel
- @running = false
- @wait_var.value = 0
- tk_call 'after', 'cancel', @after_id if @after_id
- @after_id = nil
- Tk_CBTBL.delete(@id) ;# for GC
- self
- end
- alias stop cancel
-
- def continue(wait=nil)
- fail RuntimeError, "is already running" if @running
- sleep, cmd = @current_script
- fail RuntimeError, "no procedure to continue" unless cmd
- if wait
- if not wait.kind_of? Integer
- fail RuntimeError, Kernel.format("%s need to be Integer", wait.inspect)
- end
- sleep = wait
- end
- Tk_CBTBL[@id] = self
- @running = true
- @after_id = tk_call('after', sleep, cmd)
- self
- end
-
- def skip
- fail RuntimeError, "is not running now" unless @running
- cancel
- Tk_CBTBL[@id] = self
- @running = true
- set_next_callback(@current_args)
- self
- end
-
- def info
- if @after_id
- inf = tk_split_list(tk_call('after', 'info', @after_id))
- [Tk_CBTBL[inf[0][1]], inf[1]]
- else
- nil
- end
- end
-
- def wait(on_thread = true, check_root = false)
- if $SAFE >= 4
- fail SecurityError, "can't wait timer at $SAFE >= 4"
- end
-
- unless @running
- if @return_value.kind_of?(Exception)
- fail @return_value
- else
- return @return_value
- end
- end
-
- @wait_var.wait(on_thread, check_root)
- if @return_value.kind_of?(Exception)
- fail @return_value
- else
- @return_value
- end
- end
- def eventloop_wait(check_root = false)
- wait(false, check_root)
- end
- def thread_wait(check_root = false)
- wait(true, check_root)
- end
- def tkwait(on_thread = true)
- wait(on_thread, true)
- end
- def eventloop_tkwait
- wait(false, true)
- end
- def thread_tkwait
- wait(true, true)
- end
-end
-
-TkAfter = TkTimer
+require 'tk/timer'
diff --git a/ext/tk/lib/tkbgerror.rb b/ext/tk/lib/tkbgerror.rb
index 760a3901b3..deba7a57fa 100644
--- a/ext/tk/lib/tkbgerror.rb
+++ b/ext/tk/lib/tkbgerror.rb
@@ -1,29 +1,4 @@
#
-# tkbgerror -- bgerror ( tkerror ) module
-# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+# tkbgerror.rb - load tk/bgerror.rb
#
-require 'tk'
-
-module TkBgError
- extend Tk
-
- TkCommandNames = ['bgerror'.freeze].freeze
-
- def bgerror(message)
- tk_call 'bgerror', message
- end
- alias tkerror bgerror
- alias show bgerror
- module_function :bgerror, :tkerror, :show
-
- def set_handler(hdlr = Proc.new) #==> handler :: proc{|msg| ...body... }
- tk_call('proc', 'bgerror', 'msg', install_cmd(hdlr) + ' $msg')
- end
- def set_default
- begin
- tk_call('rename', 'bgerror', '')
- rescue RuntimeError
- end
- end
- module_function :set_handler, :set_default
-end
+require 'tk/bgerror'
diff --git a/ext/tk/lib/tkcanvas.rb b/ext/tk/lib/tkcanvas.rb
index 58177584af..9524614291 100644
--- a/ext/tk/lib/tkcanvas.rb
+++ b/ext/tk/lib/tkcanvas.rb
@@ -1,992 +1,4 @@
#
-# tkcanvas.rb - Tk canvas classes
-# $Date$
-# by Yukihiro Matsumoto <matz@caelum.co.jp>
-# $Date$
-# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
-
-require "tk"
-require 'tkfont'
-
-module TkTreatCItemFont
- include TkTreatItemFont
-
- ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze
- def __conf_cmd(idx)
- ItemCMD[idx]
- end
-
- def __item_pathname(tagOrId)
- if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag)
- self.path + ';' + tagOrId.id.to_s
- else
- self.path + ';' + tagOrId.to_s
- end
- end
-end
-
-class TkCanvas<TkWindow
- include TkTreatCItemFont
- include Scrollable
-
- TkCommandNames = ['canvas'.freeze].freeze
- WidgetClassName = 'Canvas'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def __destroy_hook__
- TkcItem::CItemID_TBL.delete(@path)
- end
-
- def create_self(keys)
- if keys and keys != None
- tk_call 'canvas', @path, *hash_kv(keys)
- else
- tk_call 'canvas', @path
- end
- end
-
- def tagid(tag)
- if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag)
- tag.id
- else
- tag
- end
- end
- private :tagid
-
- def addtag(tag, mode, *args)
- tk_send 'addtag', tagid(tag), mode, *args
- self
- end
- def addtag_above(tagOrId, target)
- addtag(tagOrId, 'above', tagid(target))
- end
- def addtag_all(tagOrId)
- addtag(tagOrId, 'all')
- end
- def addtag_below(tagOrId, target)
- addtag(tagOrId, 'below', tagid(target))
- end
- def addtag_closest(tagOrId, x, y, halo=None, start=None)
- addtag(tagOrId, 'closest', x, y, halo, start)
- end
- def addtag_enclosed(tagOrId, x1, y1, x2, y2)
- addtag(tagOrId, 'enclosed', x1, y1, x2, y2)
- end
- def addtag_overlapping(tagOrId, x1, y1, x2, y2)
- addtag(tagOrId, 'overlapping', x1, y1, x2, y2)
- end
- def addtag_withtag(tagOrId, tag)
- addtag(tagOrId, 'withtag', tagid(tag))
- end
-
- def bbox(tagOrId, *tags)
- list(tk_send('bbox', tagid(tagOrId), *tags.collect{|t| tagid(t)}))
- end
-
- def itembind(tag, context, cmd=Proc.new, args=nil)
- _bind([path, "bind", tagid(tag)], context, cmd, args)
- self
- end
-
- def itembind_append(tag, context, cmd=Proc.new, args=nil)
- _bind_append([path, "bind", tagid(tag)], context, cmd, args)
- self
- end
-
- def itembind_remove(tag, context)
- _bind_remove([path, "bind", tagid(tag)], context)
- self
- end
-
- def itembindinfo(tag, context=nil)
- _bindinfo([path, "bind", tagid(tag)], context)
- end
-
- def canvasx(x, *args)
- tk_tcl2ruby(tk_send('canvasx', x, *args))
- end
- def canvasy(y, *args)
- tk_tcl2ruby(tk_send('canvasy', y, *args))
- end
-
- def coords(tag, *args)
- if args == []
- tk_split_list(tk_send('coords', tagid(tag)))
- else
- tk_send('coords', tagid(tag), *(args.flatten))
- end
- end
-
- def dchars(tag, first, last=None)
- tk_send 'dchars', tagid(tag), first, last
- self
- end
-
- def delete(*args)
- if TkcItem::CItemID_TBL[self.path]
- find('withtag', *args).each{|item|
- TkcItem::CItemID_TBL[self.path].delete(item.id)
- }
- end
- tk_send 'delete', *args.collect{|t| tagid(t)}
- self
- end
- alias remove delete
-
- def dtag(tag, tag_to_del=None)
- tk_send 'dtag', tagid(tag), tag_to_del
- self
- end
-
- def find(mode, *args)
- list(tk_send('find', mode, *args)).collect!{|id|
- TkcItem.id2obj(self, id)
- }
- end
- def find_above(target)
- find('above', tagid(target))
- end
- def find_all
- find('all')
- end
- def find_below(target)
- find('below', tagid(target))
- end
- def find_closest(x, y, halo=None, start=None)
- find('closest', x, y, halo, start)
- end
- def find_enclosed(x1, y1, x2, y2)
- find('enclosed', x1, y1, x2, y2)
- end
- def find_overlapping(x1, y1, x2, y2)
- find('overlapping', x1, y1, x2, y2)
- end
- def find_withtag(tag)
- find('withtag', tag)
- end
-
- def itemfocus(tagOrId=nil)
- if tagOrId
- tk_send 'focus', tagid(tagOrId)
- self
- else
- ret = tk_send('focus')
- if ret == ""
- nil
- else
- TkcItem.id2obj(self, ret)
- end
- end
- end
-
- def gettags(tagOrId)
- list(tk_send('gettags', tagid(tagOrId))).collect{|tag|
- TkcTag.id2obj(self, tag)
- }
- end
-
- def icursor(tagOrId, index)
- tk_send 'icursor', tagid(tagOrId), index
- self
- end
-
- def index(tagOrId, index)
- number(tk_send('index', tagid(tagOrId), index))
- end
-
- def insert(tagOrId, index, string)
- tk_send 'insert', tagid(tagOrId), index, string
- self
- end
-
- def itemcget(tagOrId, option)
- case option.to_s
- when 'dash', 'activedash', 'disableddash'
- conf = tk_send('itemcget', tagid(tagOrId), "-#{option}")
- if conf =~ /^[0-9]/
- list(conf)
- else
- conf
- end
- when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
- tk_send 'itemcget', tagid(tagOrId), "-#{option}"
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('itemcget', tagid(tagOrId), "-#{option}"))
- fnt = tk_tcl2ruby(tk_send('itemcget', tagid(tagOrId), '-font'))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(tagid(tagOrId), fnt)
- end
- if option.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby tk_send('itemcget', tagid(tagOrId), "-#{option}")
- end
- end
-
- def itemconfigure(tagOrId, key, value=None)
- if key.kind_of? Hash
- key = _symbolkey2str(key)
- if ( key['font'] || key['kanjifont'] \
- || key['latinfont'] || key['asciifont'] )
- tagfont_configure(tagid(tagOrId), key.dup)
- else
- tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key)
- end
-
- else
- if ( key == 'font' || key == :font ||
- key == 'kanjifont' || key == :kanjifont ||
- key == 'latinfont' || key == :latinfont ||
- key == 'asciifont' || key == :asciifont )
- if value == None
- tagfontobj(tagid(tagOrId))
- else
- tagfont_configure(tagid(tagOrId), {key=>value})
- end
- else
- tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
- end
- end
- self
- end
-# def itemconfigure(tagOrId, key, value=None)
-# if key.kind_of? Hash
-# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key)
-# else
-# tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
-# end
-# end
-# def itemconfigure(tagOrId, keys)
-# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(keys)
-# end
-
- def itemconfiginfo(tagOrId, key=nil)
- if key
- case key.to_s
- when 'dash', 'activedash', 'disableddash'
- conf = tk_split_simplelist(tk_send('itemconfigure',
- tagid(tagOrId), "-#{key}"))
- if conf[3] && conf[3] =~ /^[0-9]/
- conf[3] = list(conf[3])
- end
- if conf[4] && conf[4] =~ /^[0-9]/
- conf[4] = list(conf[4])
- end
- when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
- conf = tk_split_simplelist(tk_send('itemconfigure',
- tagid(tagOrId), "-#{key}"))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(tk_send('itemconfigure',
- tagid(tagOrId),"-#{key}") )
- conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4])
- else
- conf = tk_split_list(tk_send('itemconfigure',
- tagid(tagOrId), "-#{key}"))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- ret = tk_split_simplelist(tk_send('itemconfigure',
- tagid(tagOrId))).collect{|conflist|
- conf = tk_split_simplelist(conflist)
- conf[0] = conf[0][1..-1]
- case conf[0]
- when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
- when 'dash', 'activedash', 'disableddash'
- if conf[3] && conf[3] =~ /^[0-9]/
- conf[3] = list(conf[3])
- end
- if conf[4] && conf[4] =~ /^[0-9]/
- conf[4] = list(conf[4])
- end
- 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
- }
- fontconf = ret.assoc('font')
- if fontconf
- ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
- fontconf[4] = tagfont_configinfo(tagid(tagOrId), fontconf[4])
- ret.push(fontconf)
- else
- ret
- end
- end
- end
-
- def lower(tag, below=None)
- tk_send 'lower', tagid(tag), tagid(below)
- self
- end
-
- def move(tag, x, y)
- tk_send 'move', tagid(tag), x, y
- self
- end
-
- def postscript(keys)
- tk_send "postscript", *hash_kv(keys)
- end
-
- def raise(tag, above=None)
- tk_send 'raise', tagid(tag), tagid(above)
- self
- end
-
- def scale(tag, x, y, xs, ys)
- tk_send 'scale', tagid(tag), x, y, xs, ys
- self
- end
-
- def scan_mark(x, y)
- tk_send 'scan', 'mark', x, y
- self
- end
- def scan_dragto(x, y)
- tk_send 'scan', 'dragto', x, y
- self
- end
-
- def select(mode, *args)
- r = tk_send('select', mode, *args)
- (mode == 'item')? TkcItem.id2obj(self, r): self
- end
- def select_adjust(tagOrId, index)
- select('adjust', tagid(tagOrId), index)
- end
- def select_clear
- select('clear')
- end
- def select_from(tagOrId, index)
- select('from', tagid(tagOrId), index)
- end
- def select_item
- select('item')
- end
- def select_to(tagOrId, index)
- select('to', tagid(tagOrId), index)
- end
-
- def itemtype(tag)
- TkcItem.type2class(tk_send('type', tagid(tag)))
- end
-end
-
-module TkcTagAccess
- include TkComm
- include TkTreatTagFont
-
- def addtag(tag)
- @c.addtag(tag, 'with', @id)
- self
- end
-
- def bbox
- @c.bbox(@id)
- end
-
- def bind(seq, cmd=Proc.new, args=nil)
- @c.itembind @id, seq, cmd, args
- self
- end
-
- def bind_append(seq, cmd=Proc.new, args=nil)
- @c.itembind_append @id, seq, cmd, args
- self
- end
-
- def bind_remove(seq)
- @c.itembind_remove @id, seq
- self
- end
-
- def bindinfo(seq=nil)
- @c.itembindinfo @id, seq
- end
-
- def cget(option)
- @c.itemcget @id, option
- end
-
- def configure(key, value=None)
- @c.itemconfigure @id, key, value
- self
- end
-# def configure(keys)
-# @c.itemconfigure @id, keys
-# end
-
- def configinfo(key=nil)
- @c.itemconfiginfo @id, key
- end
-
- def coords(*args)
- @c.coords @id, *args
- end
-
- def dchars(first, last=None)
- @c.dchars @id, first, last
- self
- end
-
- def dtag(tag_to_del=None)
- @c.dtag @id, tag_to_del
- self
- end
-
- def find
- @c.find 'withtag', @id
- end
- alias list find
-
- def focus
- @c.itemfocus @id
- end
-
- def gettags
- @c.gettags @id
- end
-
- def icursor(index)
- @c.icursor @id, index
- self
- end
-
- def index(index)
- @c.index @id, index
- end
-
- def insert(beforethis, string)
- @c.insert @id, beforethis, string
- self
- end
-
- def lower(belowthis=None)
- @c.lower @id, belowthis
- self
- end
-
- def move(xamount, yamount)
- @c.move @id, xamount, yamount
- self
- end
-
- def raise(abovethis=None)
- @c.raise @id, abovethis
- self
- end
-
- def scale(xorigin, yorigin, xscale, yscale)
- @c.scale @id, xorigin, yorigin, xscale, yscale
- self
- end
-
- def select_adjust(index)
- @c.select('adjust', @id, index)
- self
- end
- def select_from(index)
- @c.select('from', @id, index)
- self
- end
- def select_to(index)
- @c.select('to', @id, index)
- self
- end
-
- def itemtype
- @c.itemtype @id
- end
-
- # Following operators support logical expressions of canvas tags
- # (for Tk8.3+).
- # If tag1.path is 't1' and tag2.path is 't2', then
- # ltag = tag1 & tag2; ltag.path => "(t1)&&(t2)"
- # ltag = tag1 | tag2; ltag.path => "(t1)||(t2)"
- # ltag = tag1 ^ tag2; ltag.path => "(t1)^(t2)"
- # ltag = - tag1; ltag.path => "!(t1)"
- def & (tag)
- if tag.kind_of? TkObject
- TkcTagString.new(@c, '(' + @id + ')&&(' + tag.path + ')')
- else
- TkcTagString.new(@c, '(' + @id + ')&&(' + tag.to_s + ')')
- end
- end
-
- def | (tag)
- if tag.kind_of? TkObject
- TkcTagString.new(@c, '(' + @id + ')||(' + tag.path + ')')
- else
- TkcTagString.new(@c, '(' + @id + ')||(' + tag.to_s + ')')
- end
- end
-
- def ^ (tag)
- if tag.kind_of? TkObject
- TkcTagString.new(@c, '(' + @id + ')^(' + tag.path + ')')
- else
- TkcTagString.new(@c, '(' + @id + ')^(' + tag.to_s + ')')
- end
- end
-
- def -@
- TkcTagString.new(@c, '!(' + @id + ')')
- end
-end
-
-class TkcTag<TkObject
- include TkcTagAccess
-
- CTagID_TBL = TkCore::INTERP.create_table
- Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ CTagID_TBL.clear }
-
- def TkcTag.id2obj(canvas, id)
- cpath = canvas.path
- return id unless CTagID_TBL[cpath]
- CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
- end
-
- def initialize(parent, mode=nil, *args)
- if not parent.kind_of?(TkCanvas)
- fail Kernel.format("%s need to be TkCanvas", parent.inspect)
- end
- @c = parent
- @cpath = parent.path
- @path = @id = Tk_CanvasTag_ID.join
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_CanvasTag_ID[1].succ!
- if mode
- tk_call @c.path, "addtag", @id, mode, *args
- end
- end
- def id
- @id
- end
-
- def delete
- @c.delete @id
- CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
- self
- end
- alias remove delete
- alias destroy delete
-
- def set_to_above(target)
- @c.addtag_above(@id, target)
- self
- end
- alias above set_to_above
-
- def set_to_all
- @c.addtag_all(@id)
- self
- end
- alias all set_to_all
-
- def set_to_below(target)
- @c.addtag_below(@id, target)
- self
- end
- alias below set_to_below
-
- def set_to_closest(x, y, halo=None, start=None)
- @c.addtag_closest(@id, x, y, halo, start)
- self
- end
- alias closest set_to_closest
-
- def set_to_enclosed(x1, y1, x2, y2)
- @c.addtag_enclosed(@id, x1, y1, x2, y2)
- self
- end
- alias enclosed set_to_enclosed
-
- def set_to_overlapping(x1, y1, x2, y2)
- @c.addtag_overlapping(@id, x1, y1, x2, y2)
- self
- end
- alias overlapping set_to_overlapping
-
- def set_to_withtag(target)
- @c.addtag_withtag(@id, target)
- self
- end
- alias withtag set_to_withtag
-end
-
-class TkcTagString<TkcTag
- def self.new(parent, name, *args)
- if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name]
- return CTagID_TBL[parent.path][name]
- else
- super(parent, name, *args)
- end
- end
-
- def initialize(parent, name, mode=nil, *args)
- if not parent.kind_of?(TkCanvas)
- fail Kernel.format("%s need to be TkCanvas", parent.inspect)
- end
- @c = parent
- @cpath = parent.path
- @path = @id = name
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- if mode
- tk_call @c.path, "addtag", @id, mode, *args
- end
- end
-end
-TkcNamedTag = TkcTagString
-
-class TkcTagAll<TkcTag
- def initialize(parent)
- if not parent.kind_of?(TkCanvas)
- fail Kernel.format("%s need to be TkCanvas", parent.inspect)
- end
- @c = parent
- @cpath = parent.path
- @path = @id = 'all'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- end
-end
-
-class TkcTagCurrent<TkcTag
- def initialize(parent)
- if not parent.kind_of?(TkCanvas)
- fail Kernel.format("%s need to be TkCanvas", parent.inspect)
- end
- @c = parent
- @cpath = parent.path
- @path = @id = 'current'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- end
-end
-
-class TkcGroup<TkcTag
- Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint].freeze
- def create_self(parent, *args)
- if not parent.kind_of?(TkCanvas)
- fail Kernel.format("%s need to be TkCanvas", parent.inspect)
- end
- @c = parent
- @cpath = parent.path
- @path = @id = Tk_cGroup_ID.join
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_cGroup_ID[1].succ!
- add(*args) if args != []
- end
-
- def include(*tags)
- for i in tags
- i.addtag @id
- end
- self
- end
-
- def exclude(*tags)
- for i in tags
- i.delete @id
- end
- self
- end
-end
-
-class TkcItem<TkObject
- include TkcTagAccess
-
- CItemTypeToClass = {}
- CItemID_TBL = TkCore::INTERP.create_table
-
- TkCore::INTERP.init_ip_env{ CItemID_TBL.clear }
-
- def TkcItem.type2class(type)
- CItemTypeToClass[type]
- end
-
- def TkcItem.id2obj(canvas, id)
- cpath = canvas.path
- return id unless CItemID_TBL[cpath]
- CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
- end
-
- def initialize(parent, *args)
- if not parent.kind_of?(TkCanvas)
- fail Kernel.format("%s need to be TkCanvas", parent.inspect)
- end
- @parent = @c = parent
- @path = parent.path
- fontkeys = {}
- if args.size == 1 && args[0].kind_of?(Hash)
- args[0] = _symbolkey2str(args[0])
- coords = args[0].delete('coords')
- if not coords.kind_of?(Array)
- fail "coords parameter must be given by an Array"
- end
- args[0,0] = coords.flatten
- end
- if args[-1].kind_of? Hash
- keys = _symbolkey2str(args.pop)
- ['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
- fontkeys[key] = keys.delete(key) if keys.key?(key)
- }
- args += hash_kv(keys)
- end
- @id = create_self(*args).to_i ;# 'canvas item id' is integer number
- CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
- CItemID_TBL[@path][@id] = self
- configure(fontkeys) unless fontkeys.empty?
-
-######## old version
-# if args[-1].kind_of? Hash
-# keys = args.pop
-# end
-# @id = create_self(*args).to_i ;# 'canvas item id' is integer number
-# CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
-# CItemID_TBL[@path][@id] = self
-# if keys
-# # tk_call @path, 'itemconfigure', @id, *hash_kv(keys)
-# configure(keys) if keys
-# end
-########
- end
- def create_self(*args); end
- private :create_self
- def id
- @id
- end
-
- def delete
- @c.delete @id
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
- self
- end
- alias remove delete
- alias destroy delete
-end
-
-class TkcArc<TkcItem
- CItemTypeToClass['arc'] = self
- def create_self(*args)
- tk_call(@path, 'create', 'arc', *args)
- end
-end
-class TkcBitmap<TkcItem
- CItemTypeToClass['bitmap'] = self
- def create_self(*args)
- tk_call(@path, 'create', 'bitmap', *args)
- end
-end
-class TkcImage<TkcItem
- CItemTypeToClass['image'] = self
- def create_self(*args)
- tk_call(@path, 'create', 'image', *args)
- end
-end
-class TkcLine<TkcItem
- CItemTypeToClass['line'] = self
- def create_self(*args)
- tk_call(@path, 'create', 'line', *args)
- end
-end
-class TkcOval<TkcItem
- CItemTypeToClass['oval'] = self
- def create_self(*args)
- tk_call(@path, 'create', 'oval', *args)
- end
-end
-class TkcPolygon<TkcItem
- CItemTypeToClass['polygon'] = self
- def create_self(*args)
- tk_call(@path, 'create', 'polygon', *args)
- end
-end
-class TkcRectangle<TkcItem
- CItemTypeToClass['rectangle'] = self
- def create_self(*args)
- tk_call(@path, 'create', 'rectangle', *args)
- end
-end
-class TkcText<TkcItem
- CItemTypeToClass['text'] = self
- def create_self(*args)
- tk_call(@path, 'create', 'text', *args)
- end
-end
-class TkcWindow<TkcItem
- CItemTypeToClass['window'] = self
- def create_self(*args)
- tk_call(@path, 'create', 'window', *args)
- end
-end
-
-class TkImage<TkObject
- include Tk
-
- TkCommandNames = ['image'.freeze].freeze
-
- Tk_IMGTBL = TkCore::INTERP.create_table
- Tk_Image_ID = ['i'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ Tk_IMGTBL.clear }
-
- def initialize(keys=nil)
- @path = Tk_Image_ID.join
- Tk_Image_ID[1].succ!
- tk_call 'image', 'create', @type, @path, *hash_kv(keys)
- Tk_IMGTBL[@path] = self
- end
-
- def delete
- Tk_IMGTBL.delete(@id) if @id
- tk_call('image', 'delete', @path)
- self
- end
- def height
- number(tk_call('image', 'height', @path))
- end
- def inuse
- bool(tk_call('image', 'inuse', @path))
- end
- def itemtype
- tk_call('image', 'type', @path)
- end
- def width
- number(tk_call('image', 'width', @path))
- end
-
- def TkImage.names
- Tk.tk_call('image', 'names').split.collect!{|id|
- (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
- }
- end
-
- def TkImage.types
- Tk.tk_call('image', 'types').split
- end
-end
-
-class TkBitmapImage<TkImage
- def initialize(*args)
- @type = 'bitmap'
- super
- end
-end
-
-class TkPhotoImage<TkImage
- def initialize(*args)
- @type = 'photo'
- super
- end
-
- def blank
- tk_send 'blank'
- self
- end
-
- def cget(option)
- case option.to_s
- when 'data', 'file'
- tk_send 'cget', option
- else
- tk_tcl2ruby tk_send('cget', option)
- end
- end
-
- def copy(source, *opts)
- args = opts.collect{|term|
- if term.kind_of?(String) && term.include?(?\s)
- term.split
- else
- term
- end
- }.flatten
-
- tk_send 'copy', source, *args
-
- self
- end
-
- def data(keys=nil)
- tk_send('data', *hash_kv(keys))
- end
-
- def get(x, y)
- tk_send('get', x, y).split.collect{|n| n.to_i}
- end
-
- def put(data, *to)
- if to == []
- tk_send 'put', data
- else
- tk_send 'put', data, '-to', *to
- end
- self
- end
-
- def read(file, *opts)
- args = opts.collect{|term|
- if term.kind_of?(String) && term.include?(?\s)
- term.split
- else
- term
- end
- }.flatten
-
- tk_send 'read', file, *args
-
- self
- end
-
- def redither
- tk_send 'redither'
- self
- end
-
- def get_transparency(x, y)
- bool(tk_send('transparency', 'get', x, y))
- end
- def set_transparency(x, y, st)
- tk_send('transparency', 'set', x, y, st)
- self
- end
-
- def write(file, *opts)
- args = opts.collect{|term|
- if term.kind_of?(String) && term.include?(?\s)
- term.split
- else
- term
- end
- }.flatten
-
- tk_send 'write', file, *args
-
- self
- end
-end
+# tkcanvas.rb - load tk/canvas.rb
+#
+require 'tk/canvas'
diff --git a/ext/tk/lib/tkclass.rb b/ext/tk/lib/tkclass.rb
index 9ea275e560..87f5acc453 100644
--- a/ext/tk/lib/tkclass.rb
+++ b/ext/tk/lib/tkclass.rb
@@ -1,9 +1,9 @@
#
-# tkclass.rb - Tk classes
-# Date: 2000/11/27 09:23:36
-# by Yukihiro Matsumoto <matz@caelum.co.jp>
+# tkclass.rb - Tk classes
+# Date: 2000/11/27 09:23:36
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
#
-# $Id$
+# $Id$
require "tk"
diff --git a/ext/tk/lib/tkconsole.rb b/ext/tk/lib/tkconsole.rb
index d97df159fc..9960ddb8ac 100644
--- a/ext/tk/lib/tkconsole.rb
+++ b/ext/tk/lib/tkconsole.rb
@@ -1,28 +1,4 @@
#
-# tkconsole.rb : control the console on system without a real console
+# tkconsole.rb - load tk/console.rb
#
-require 'tk'
-
-module TkConsole
- include Tk
- extend Tk
-
- TkCommandNames = ['console'.freeze].freeze
-
- def self.title(str=None)
- tk_call 'console', str
- end
- def self.hide
- tk_call 'console', 'hide'
- end
- def self.show
- tk_call 'console', 'show'
- end
- def self.eval(tcl_script)
- #
- # supports a Tcl script only
- # I have no idea to support a Ruby script seamlessly.
- #
- tk_call 'console', 'eval', tcl_script
- end
-end
+require 'tk/console'
diff --git a/ext/tk/lib/tkdialog.rb b/ext/tk/lib/tkdialog.rb
index d5c13dca1a..bec5e5d29a 100644
--- a/ext/tk/lib/tkdialog.rb
+++ b/ext/tk/lib/tkdialog.rb
@@ -1,275 +1,4 @@
-require "tk"
-
-class TkDialog2 < TkWindow
- extend Tk
-
- TkCommandNames = ['tk_dialog'.freeze].freeze
-
- def self.show(*args)
- dlog = self.new(*args)
- dlog.show
- dlog
- end
-
- def _set_button_config(configs)
- set_config = proc{|c,i|
- if $VERBOSE && (c.has_key?('command') || c.has_key?(:command))
- STDERR.print("Warning: cannot give a command option " +
- "to the dialog button#{i}. It was removed.\n")
- end
- c.delete('command'); c.delete(:command)
- @config << Kernel.format("%s.button%s configure %s; ",
- @path, i, hash_kv(c).join(' '))
- }
- case configs
- when Proc
- @buttons.each_index{|i|
- if (c = configs.call(i)).kind_of? Hash
- set_config.call(c,i)
- end
- }
-
- when Array
- @buttons.each_index{|i|
- if (c = configs[i]).kind_of? Hash
- set_config.call(c,i)
- end
- }
-
- when Hash
- @buttons.each_with_index{|s,i|
- if (c = configs[s]).kind_of? Hash
- set_config.call(c,i)
- end
- }
- end
- @config = 'after idle {' + @config + '};' if @config != ""
- end
- private :_set_button_config
-
- # initialize tk_dialog
- def create_self(keys)
- @var = TkVariable.new
-
- @title = title
-
- @message = message
- @message_config = message_config
- @msgframe_config = msgframe_config
-
- @bitmap = bitmap
- @bitmap_config = message_config
-
- @default_button = default_button
-
- @buttons = buttons
- @button_configs = proc{|num| button_configs(num)}
- @btnframe_config = btnframe_config
-
- #@config = "puts [winfo children .w0000];"
- @config = ""
-
- @command = nil
-
- if keys.kind_of? Hash
- @title = keys['title'] if keys.key? 'title'
- @message = keys['message'] if keys.key? 'message'
- @bitmap = keys['bitmap'] if keys.key? 'bitmap'
- @bitmap = '{}' if @bitmap == nil || @bitmap == ""
- @default_button = keys['default'] if keys.key? 'default'
- @buttons = keys['buttons'] if keys.key? 'buttons'
-
- @command = keys['prev_command']
-
- @message_config = keys['message_config'] if keys.key? 'message_config'
- @msgframe_config = keys['msgframe_config'] if keys.key? 'msgframe_config'
- @bitmap_config = keys['bitmap_config'] if keys.key? 'bitmap_config'
- @button_configs = keys['button_configs'] if keys.key? 'button_configs'
- @btnframe_config = keys['btnframe_config'] if keys.key? 'btnframe_config'
- end
-
- if @title.include? ?\s
- @title = '{' + @title + '}'
- end
-
- if @buttons.kind_of? Array
- _set_button_config(@buttons.collect{|cfg|
- (cfg.kind_of? Array)? cfg[1]: nil})
- @buttons = @buttons.collect{|cfg| (cfg.kind_of? Array)? cfg[0]: cfg}
- end
- if @buttons.kind_of? Hash
- _set_button_config(@buttons)
- @buttons = @buttons.keys
- end
- @buttons = tk_split_simplelist(@buttons) if @buttons.kind_of? String
- @buttons = @buttons.collect{|s|
- if s.kind_of? Array
- s = s.join(' ')
- end
- if s.include? ?\s
- '{' + s + '}'
- else
- s
- end
- }
-
- if @message_config.kind_of? Hash
- @config << Kernel.format("%s.msg configure %s;",
- @path, hash_kv(@message_config).join(' '))
- end
-
- if @msgframe_config.kind_of? Hash
- @config << Kernel.format("%s.top configure %s;",
- @path, hash_kv(@msgframe_config).join(' '))
- end
-
- if @btnframe_config.kind_of? Hash
- @config << Kernel.format("%s.bot configure %s;",
- @path, hash_kv(@btnframe_config).join(' '))
- end
-
- if @bitmap_config.kind_of? Hash
- @config << Kernel.format("%s.bitmap configure %s;",
- @path, hash_kv(@bitmap_config).join(' '))
- end
-
- _set_button_config(@button_configs) if @button_configs
-
- if @command.kind_of? Proc
- @command.call(self)
- end
- end
-
- def show
- if @default_button.kind_of? String
- default_button = @buttons.index(@default_button)
- else
- default_button = @default_button
- end
- default_button = '{}' if default_button == nil
- Tk.ip_eval('eval {global '+@var.id+';'+@config+
- 'set '+@var.id+' [tk_dialog '+
- @path+" "+@title+" {#{@message}} "+@bitmap+" "+
- String(default_button)+" "+@buttons.join(' ')+']}')
- end
-
- def value
- return @var.value.to_i
- end
- ######################################################
- # #
- # these methods must be overridden for each dialog #
- # #
- ######################################################
- private
-
- def title
- # returns a title string of the dialog window
- return "DIALOG"
- end
- def message
- # returns a message text to display on the dialog
- return "MESSAGE"
- end
- def message_config
- # returns a Hash {option=>value, ...} for the message text
- return nil
- end
- def msgframe_config
- # returns a Hash {option=>value, ...} for the message text frame
- return nil
- end
- def bitmap
- # returns a bitmap name or a bitmap file path
- # (@ + path ; e.g. '@/usr/share/bitmap/sample.xbm')
- return "info"
- end
- def bitmap_config
- # returns nil or a Hash {option=>value, ...} for the bitmap
- return nil
- end
- def default_button
- # returns a default button's number or name
- # if nil or null string, set no-default
- return 0
- end
- def buttons
- #return "BUTTON1 BUTTON2"
- return ["BUTTON1", "BUTTON2"]
- end
- def button_configs(num)
- # returns nil / Proc / Array or Hash (see _set_button_config)
- return nil
- end
- def btnframe_config
- # returns nil or a Hash {option=>value, ...} for the button frame
- return nil
- end
-end
-
-
#
-# TkDialog : with showing at initialize
+# tkdialog.rb - load tk/dialog.rb
#
-class TkDialog < TkDialog2
- def self.show(*args)
- self.new(*args)
- end
-
- def initialize(*args)
- super(*args)
- show
- end
-end
-
-
-#
-# dialog for warning
-#
-class TkWarning2 < TkDialog2
- def initialize(parent = nil, mes = nil)
- if !mes
- if parent.kind_of? TkWindow
- mes = ""
- else
- mes = parent.to_s
- parent = nil
- end
- end
- super(parent, :message=>mes)
- end
-
- def show(mes = nil)
- mes_bup = @message
- @message = mes if mes
- ret = super()
- @message = mes_bup
- ret
- end
-
- #######
- private
-
- def title
- return "WARNING";
- end
- def bitmap
- return "warning";
- end
- def default_button
- return 0;
- end
- def buttons
- return "OK";
- end
-end
-
-class TkWarning < TkWarning2
- def self.show(*args)
- self.new(*args)
- end
- def initialize(*args)
- super(*args)
- show
- end
-end
+require 'tk/dialog'
diff --git a/ext/tk/lib/tkentry.rb b/ext/tk/lib/tkentry.rb
index e0589802d2..2dcfcab5da 100644
--- a/ext/tk/lib/tkentry.rb
+++ b/ext/tk/lib/tkentry.rb
@@ -1,290 +1,4 @@
#
-# tkentry.rb - Tk entry classes
-# $Date$
-# by Yukihiro Matsumoto <matz@caelum.co.jp>
-
-require 'tk.rb'
-
-class TkEntry<TkLabel
- include Scrollable
-
- TkCommandNames = ['entry'.freeze].freeze
- WidgetClassName = 'Entry'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- class ValidateCmd
- include TkComm
-
- module Action
- Insert = 1
- Delete = 0
- Others = -1
- Focus = -1
- Forced = -1
- Textvariable = -1
- TextVariable = -1
- end
-
- class ValidateArgs
- VARG_KEY = 'disvPSVW'
- VARG_TYPE = 'nxeseesw'
-
- def self.scan_args(arg_str, arg_val)
- enc = Tk.encoding
- arg_cnv = []
- arg_str.strip.split(/\s+/).each_with_index{|kwd,idx|
- if kwd =~ /^%(.)$/
- if num = VARG_KEY.index($1)
- case VARG_TYPE[num]
- when ?n
- arg_cnv << TkComm::number(arg_val[idx])
- when ?s
- arg_cnv << TkComm::string(arg_val[idx])
- when ?e
- if enc
- arg_cnv << Tk.fromUTF8(TkComm::string(arg_val[idx]), enc)
- else
- arg_cnv << TkComm::string(arg_val[idx])
- end
- when ?w
- arg_cnv << TkComm::window(arg_val[idx])
- when ?x
- idx = TkComm::number(arg_val[idx])
- if idx < 0
- arg_cnv << nil
- else
- arg_cnv << idx
- end
- else
- arg_cnv << arg_val[idx]
- end
- else
- arg_cnv << arg_val[idx]
- end
- else
- arg_cnv << arg_val[idx]
- end
- }
- arg_cnv
- end
-
- def initialize(d,i,s,v,pp,ss,vv,ww)
- @action = d
- @index = i
- @current = s
- @type = v
- @value = pp
- @string = ss
- @triggered = vv
- @widget = ww
- end
- attr :action
- attr :index
- attr :current
- attr :type
- attr :value
- attr :string
- attr :triggered
- attr :widget
- end
-
- def initialize(cmd = Proc.new, args=nil)
- if args
- @id =
- install_cmd(proc{|*arg|
- TkUtil.eval_cmd(proc{|*v| (cmd.call(*v))? '1': '0'},
- *ValidateArgs.scan_args(args, arg))
- }) + " " + args
- else
- args = ' %d %i %s %v %P %S %V %W'
- @id =
- install_cmd(proc{|*arg|
- TkUtil.eval_cmd(proc{|*v| (cmd.call(*v))? '1': '0'},
- ValidateArgs.new(*ValidateArgs \
- .scan_args(args,arg)))
- }) + args
- end
- end
-
- def to_eval
- @id
- end
- end
-
- def create_self(keys)
- tk_call 'entry', @path
- if keys and keys != None
- configure(keys)
- end
- end
-
- def configure(slot, value=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
- end
-
- def bbox(index)
- list(tk_send('bbox', index))
- end
- def cursor
- number(tk_send('index', 'insert'))
- end
- def cursor=(index)
- tk_send 'icursor', index
- self
- end
- def index(index)
- number(tk_send('index', index))
- end
- def insert(pos,text)
- tk_send 'insert', pos, text
- self
- end
- def delete(first, last=None)
- tk_send 'delete', first, last
- self
- end
- def mark(pos)
- tk_send 'scan', 'mark', pos
- self
- end
- def dragto(pos)
- tk_send 'scan', 'dragto', pos
- self
- end
- def selection_adjust(index)
- tk_send 'selection', 'adjust', index
- self
- end
- def selection_clear
- tk_send 'selection', 'clear'
- self
- end
- def selection_from(index)
- tk_send 'selection', 'from', index
- self
- end
- def selection_present()
- bool(tk_send('selection', 'present'))
- end
- def selection_range(s, e)
- tk_send 'selection', 'range', s, e
- self
- end
- def selection_to(index)
- tk_send 'selection', 'to', index
- self
- end
-
- def invoke_validate
- bool(tk_send('validate'))
- end
- def validate(mode = nil)
- if mode
- configure 'validate', mode
- else
- invoke_validate
- end
- end
-
- def validatecommand(cmd = Proc.new, args = nil)
- if cmd.kind_of?(ValidateCmd)
- configure('validatecommand', cmd)
- elsif args
- configure('validatecommand', [cmd, args])
- else
- configure('validatecommand', cmd)
- end
- end
- alias vcmd validatecommand
-
- def invalidcommand(cmd = Proc.new, args = nil)
- if cmd.kind_of?(ValidateCmd)
- configure('invalidcommand', cmd)
- elsif args
- configure('invalidcommand', [cmd, args])
- else
- configure('invalidcommand', cmd)
- end
- end
- alias invcmd invalidcommand
-
- def value
- tk_send 'get'
- end
- def value= (val)
- tk_send 'delete', 0, 'end'
- tk_send 'insert', 0, val
- end
-end
-
-class TkSpinbox<TkEntry
- TkCommandNames = ['spinbox'.freeze].freeze
- WidgetClassName = 'Spinbox'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def create_self(keys)
- tk_call 'spinbox', @path
- if keys and keys != None
- configure(keys)
- end
- end
-
- def identify(x, y)
- tk_send 'identify', x, y
- end
-
- def spinup
- tk_send 'invoke', 'spinup'
- self
- end
-
- def spindown
- tk_send 'invoke', 'spindown'
- self
- end
-
- def set(str)
- tk_send 'set', str
- end
-end
+# tkentry.rb - load tk/entry.rb
+#
+require 'tk/entry'
diff --git a/ext/tk/lib/tkextlib/ICONS.rb b/ext/tk/lib/tkextlib/ICONS.rb
new file mode 100644
index 0000000000..18d84c05e9
--- /dev/null
+++ b/ext/tk/lib/tkextlib/ICONS.rb
@@ -0,0 +1,13 @@
+#
+# ICONS support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# call setup script
+require 'tkextlib/ICONS/setup.rb'
+
+# load library
+require 'tkextlib/ICONS/icons'
diff --git a/ext/tk/lib/tkextlib/ICONS/icons.rb b/ext/tk/lib/tkextlib/ICONS/icons.rb
new file mode 100644
index 0000000000..b430bae55d
--- /dev/null
+++ b/ext/tk/lib/tkextlib/ICONS/icons.rb
@@ -0,0 +1,129 @@
+#
+# tkextlib/ICONS/icons.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 'tkextlib/ICONS/setup.rb'
+
+# TkPackage.require('icons', '1.0')
+TkPackage.require('icons')
+
+module Tk
+ class ICONS < TkImage
+ extend Tk
+
+ PACKAGE_NAME = 'icons'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('icons')
+ rescue
+ ''
+ end
+ end
+
+ def self.create(*args) # icon, icon, ..., ?option=>value, ...?
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ icons = simplelist(tk_call('::icons::icons', 'create',
+ *(hash_kv(keys) << (args.flatten))))
+ else
+ icons = simplelist(tk_call('::icons::icons', 'create',
+ args.flatten))
+ end
+
+ icons.collect{|icon| self.new(icon, :without_creating=>true)}
+ end
+
+ def self.delete(*icons) # icon, icon, ...
+ icons = icons.flatten
+ return if icons.empty?
+ icons.map!{|icon|
+ if icon.kind_of?(Tk::ICONS)
+ Tk_IMGTBL.delete(icon.path)
+ icon.name
+ elsif icon.to_s =~ /^::icon::(.*)/
+ name = $1
+ Tk_IMGTBL.delete(icon)
+ name
+ else
+ Tk_IMGTBL.delete("::icon::#{icon}")
+ icon
+ end
+ }
+ tk_call('::icons::icons', 'delete', icons)
+ end
+
+ def self.query(*args) # icon, icon, ..., ?option=>value, ...?
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ simplelist(tk_call('::icons::icons', 'query',
+ *(hash_kv(keys) << (args.flatten))))
+ else
+ simplelist(tk_call('::icons::icons', 'query', args.flatten))
+ end . map{|inf| list(inf) }
+ end
+
+ ##########################################
+
+ class << self
+ alias _new new
+
+ def new(name, keys=nil)
+ if obj = Tk_IMGTBL["::icon::#{name}"]
+ if keys
+ keys = _symbolkey2str(keys)
+ unless keys.delete('without_creating')
+ tk_call('::icons::icons', 'create', *(hash_kv(keys) << obj.name))
+ end
+ end
+ else
+ obj = _new(name, keys)
+ end
+ obj
+ end
+ 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..cfbe274c86
--- /dev/null
+++ b/ext/tk/lib/tkextlib/SUPPORT_STATUS
@@ -0,0 +1,196 @@
+
+ [ current support status of Tcl/Tk extensions ]
+
+ *** RELEASE_DATE of the libraries => see 'tkextlib/version.rb' ***
+
+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.
+
+ The version number of each extension means the latest version
+ which is checked its feature. That is, it does NOT means only
+ version of working. Library files maybe include some features
+ which is included in the former version but removed from the
+ latest, and maybe able to support the later version then the
+ shown version.
+
+ 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 "<ruby archive>/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(<libname>)).
+
+ *******************************************************************
+
+
+===< support with some examples (may be beta quality) >=======================
+
+Tcllib 1.8
+Tklib 0.4.1 http://sourceforge.net/projects/tcllib ==> tcllib
+
+IWidgets 4.0.2 http://sourceforge.net/projects/incrtcl ==> iwidgets
+
+BWidgets 1.7 http://sourceforge.net/projects/tcllib ==> bwidget
+
+TkTable 2.9 http://sourceforge.net/projects/tktable ==> tktable
+ * see also <http://www.korus.hu/~fery/ruby/tktable.rb>
+ written by Ferenc Engard (ferenc@engard.hu)
+
+vu 2.3.0 http://sourceforge.net/projects/tktable ==> vu
+
+TkHTML 2.0 http://www.hwaci.com/sw/tkhtml/ ==> tkHTML
+
+ICONS 1.0 http://www.satisoft.com/tcltk/icons/ ==> ICONS
+
+TkImg 1.3 http://sourceforge.net/projects/tkimg ==> tkimg
+
+
+BLT 2.4z http://sourceforge.net/projects/blt
+ * see also tcltk-ext library on RAA
+ (http://raa.ruby-lang.org/)
+ ==> blt
+
+TkTreeCtrl CVS/Hd(2005-12-02)
+ http://sourceforge.net/projects/tktreectrl ==> treectrl
+
+Tile 0.8.0/8.5.1
+ http://sourceforge.net/projects/tktable ==> tile
+
+
+
+===< support (may be alpha or beta quality) >=================================
+
+IncrTcl CVS/Hd(2005-02-14)
+ http://sourceforge.net/projects/incrtcl ==> itcl, itk
+
+TclX CVS/Hd(2005-02-07)
+ http://sourceforge.net/projects/tclx
+ ==> tclx (partial support; infox command and
+ XPG/3 message catalogs only)
+
+Trofs 0.4.3 http://math.nist.gov/~DPorter/tcltk/trofs/
+
+
+
+===< possibly available (not tested; alpha quality) >=========================
+
+winico 0.6
+ http://sourceforge.net/projects/tktable
+ ==> winico (win32 only)
+
+TkTrans latest(2004-10-11)
+ http://www2.cmp.uea.ac.uk/~fuzz/tktrans/default.html
+ ==> tktrans (win32 only)
+
+TkDND 1.0a2 http://sourceforge.net/projects/tkdnd ==> tkDND
+
+
+
+===< plan to support (alpha quality libraries may be included) >==============
+
+GraphViz *** http://www.graphviz.org/
+
+Tkgeomap *** http://tkgeomap.sourceforge.net/index.html
+
+
+
+===< not determined to supprt or not >========================================
+
+Tix *** http://tixlibrary.sourceforge.net/
+ * see also tcltk-ext library on RAA
+ (http://raa.ruby-lang.org/)
+
+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/
+
+ANIGIF *** http://cardtable.sourceforge.net/tcltk/
+
+IMG_ROTATE *** http://cardtable.sourceforge.net/tcltk/
+
+TclVfs *** http://sourceforge.net/projects/tclvfs/
+
+vfwtcl *** http://sourceforge.net/projects/avicaptcl
+ * Win32 only
+
+multicast *** http://sourceforge.net/projects/avicaptcl
+ * Win32 only
+
+XBit *** http://www.geocities.com/~chengye/
+ * current implementation is for Windows only
+
+QuickTimeTcl *** http://hem.fyristorg.com/matben/qt/
+ * works under Mac OS (8,9,X) or Windows
+
+
+
+===< may not support (already exist, out of Ruby/Tk scope, and so on) >=======
+
+TkCon *** http://sourceforge.net/projects/tkcon
+
+Expect *** http://sourceforge.net/projects/expect
+
+TclXML *** http://sourceforge.net/projects/tclxml
+
+TclXSLT *** http://sourceforge.net/projects/tclxml
+
+TclDOM *** http://sourceforge.net/projects/tclxml
+
+TclSOAP *** http://sourceforge.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://sourceforge.net/projects/memchan
+
+XOTcl *** http://www.xotcl.org/
+
+
+===< tool (may not supprt) >==================================================
+
+tbcload/tclcompiler
+ *** http://www.tcl.tk/software/tclpro/
+
+
+(End of List)
diff --git a/ext/tk/lib/tkextlib/blt.rb b/ext/tk/lib/tkextlib/blt.rb
new file mode 100644
index 0000000000..8d58c1f1bc
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt.rb
@@ -0,0 +1,187 @@
+#
+# BLT support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/variable'
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# call setup script
+require 'tkextlib/blt/setup.rb'
+
+# load all image format handlers
+#TkPackage.require('BLT', '2.4')
+TkPackage.require('BLT')
+
+module Tk
+ module BLT
+ TkComm::TkExtlibAutoloadModule.unshift(self)
+
+ extend TkCore
+
+ VERSION = tk_call('set', 'blt_version')
+ PATCH_LEVEL = tk_call('set', 'blt_patchLevel')
+
+ begin
+ lib = TkCore::INTERP._invoke('set', 'blt_library')
+ rescue
+ lib = ''
+ end
+ LIBRARY = TkVarAccess.new('blt_library', lib)
+
+ begin
+ lib = TkCore::INTERP._invoke('set', 'blt_libPath')
+ rescue
+ lib = ''
+ end
+ LIB_PATH = TkVarAccess.new('blt_libPath', lib)
+
+ PACKAGE_NAME = 'BLT'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('BLT')
+ rescue
+ ''
+ end
+ end
+
+ ####################################################
+
+ def self.beep(percent = 50)
+ tk_call('::blt::beep', percent)
+ end
+
+ def self.bgexec(*args)
+ if args[0].kind_of?(TkVariable)
+ var = args.shift
+ else
+ var = TkVariable.new
+ end
+ params = [var]
+
+ params.concat(hash_kv(args.shift, true)) if args[0].kind_of?(Hash)
+
+ params << '--' if args[0] =~ /^\s*-[^-]/
+ params.concat(args)
+
+ tk_call('::blt::bgexec', *params)
+ var
+ end
+
+ def self.detach_bgexec(*args)
+ if args[0].kind_of?(TkVariable)
+ var = args.shift
+ else
+ var = TkVariable.new
+ end
+ params = [var]
+
+ params.concat(hash_kv(args.shift, true)) if args[0].kind_of?(Hash)
+
+ params << '--' if args[0] =~ /^\s*-[^-]/
+ params.concat(args)
+ params << '&'
+
+ [var, tk_split_list(tk_call('::blt::bgexec', *params))]
+ end
+
+ def self.bltdebug(lvl = nil)
+ if lvl
+ tk_call('::blt::bltdebug', lvl)
+ else
+ number(tk_call('::blt::bltdebug'))
+ end
+ end
+
+ def self.crc32_file(name)
+ tk_call_without_enc('::blt::crc32', name)
+ end
+ def self.crc32_data(dat)
+ tk_call_without_enc('::blt::crc32', '-data', dat)
+ end
+
+ ####################################################
+
+ def self.active_legend(graph)
+ tk_call_without_enc('Blt_ActiveLegend', graph)
+ end
+ def self.crosshairs(graph)
+ tk_call_without_enc('Blt_Crosshairs', graph)
+ end
+ def self.zoom_stack(graph)
+ tk_call_without_enc('Blt_ZoomStack', graph)
+ end
+ def self.print_key(graph)
+ tk_call_without_enc('Blt_PrintKey', graph)
+ end
+ def self.closest_point(graph)
+ tk_call_without_enc('Blt_ClosestPoint', graph)
+ end
+
+ module GraphCommand
+ def active_legend
+ tk_call_without_enc('Blt_ActiveLegend', @path)
+ self
+ end
+ def crosshairs
+ tk_call_without_enc('Blt_Crosshairs', @path)
+ self
+ end
+ def zoom_stack
+ tk_call_without_enc('Blt_ZoomStack', @path)
+ self
+ end
+ def print_key
+ tk_call_without_enc('Blt_PrintKey', @path)
+ self
+ end
+ def closest_point
+ tk_call_without_enc('Blt_ClosestPoint', @path)
+ self
+ end
+ end
+
+ ####################################################
+
+ autoload :PlotComponent,'tkextlib/blt/component.rb'
+
+ autoload :Barchart, 'tkextlib/blt/barchart.rb'
+ autoload :Bitmap, 'tkextlib/blt/bitmap.rb'
+ autoload :Busy, 'tkextlib/blt/busy.rb'
+ autoload :Container, 'tkextlib/blt/container.rb'
+ autoload :CutBuffer, 'tkextlib/blt/cutbuffer.rb'
+ autoload :DragDrop, 'tkextlib/blt/dragdrop.rb'
+ autoload :EPS, 'tkextlib/blt/eps.rb'
+ autoload :Htext, 'tkextlib/blt/htext.rb'
+ autoload :Graph, 'tkextlib/blt/graph.rb'
+ autoload :Spline, 'tkextlib/blt/spline.rb'
+ autoload :Stripchart, 'tkextlib/blt/stripchart.rb'
+ autoload :Table, 'tkextlib/blt/table.rb'
+ autoload :Tabnotebook, 'tkextlib/blt/tabnotebook.rb'
+ autoload :Tabset, 'tkextlib/blt/tabset.rb'
+ autoload :Ted, 'tkextlib/blt/ted.rb'
+ autoload :Tile, 'tkextlib/blt/tile.rb'
+ autoload :Tree, 'tkextlib/blt/tree.rb'
+ autoload :TreeView, 'tkextlib/blt/treeview.rb'
+ autoload :Hiertable, 'tkextlib/blt/treeview.rb'
+ # Hierbox is obsolete
+ autoload :Vector, 'tkextlib/blt/vector.rb'
+ autoload :VectorAccess, 'tkextlib/blt/vector.rb'
+ autoload :Watch, 'tkextlib/blt/watch.rb'
+ autoload :Winop, 'tkextlib/blt/winop.rb'
+ autoload :WinOp, 'tkextlib/blt/winop.rb'
+
+ # Unix only
+ autoload :DnD, 'tkextlib/blt/unix_dnd.rb'
+
+ # Windows only
+ autoload :Printer, 'tkextlib/blt/win_printer.rb'
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/barchart.rb b/ext/tk/lib/tkextlib/blt/barchart.rb
new file mode 100644
index 0000000000..cb481c5889
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/barchart.rb
@@ -0,0 +1,79 @@
+#
+# tkextlib/blt/barchart.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+require 'tkextlib/blt/component.rb'
+
+module Tk::BLT
+ class Barchart < TkWindow
+ TkCommandNames = ['::blt::barchart'.freeze].freeze
+ WidgetClassName = 'Barchart'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ include PlotComponent
+ include GraphCommand
+
+ def __boolval_optkeys
+ ['bufferelements', 'buffergraph', 'invertxy']
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ ['text', 'label', 'title', 'file',
+ 'background', 'plotbackground']
+ end
+ private :__strval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'colormap' << 'fontmap'
+ end
+ private :__tkvariable_optkeys
+
+=begin
+ BarElement_ID = ['blt_barchart_bar'.freeze, '00000'.taint].freeze
+
+ def bar(elem=nil, keys={})
+ if elem.kind_of?(Hash)
+ keys = elem
+ elem = nil
+ end
+ unless elem
+ elem = BarElement_ID.join(TkCore::INTERP._ip_id_).freeze
+ BarElement_ID[1].succ!
+ end
+ tk_send('bar', elem, keys)
+ Element.new(self, elem, :without_creating=>true)
+ end
+=end
+
+ def extents(item)
+ num_or_str(tk_send_without_enc('extents', item))
+ end
+
+ def invtransform(x, y)
+ list(tk_send_without_enc('invtransform', x, y))
+ end
+
+ def inside(x, y)
+ bool(tk_send_without_enc('inside', x, y))
+ end
+
+ def metafile(file=None)
+ # Windows only
+ tk_send('metafile', file)
+ self
+ end
+
+ def snap(output, keys={})
+ tk_send_without_enc('snap', *(hash_kv(keys, false) + output))
+ self
+ end
+
+ def transform(x, y)
+ list(tk_send_without_enc('transform', x, y))
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/bitmap.rb b/ext/tk/lib/tkextlib/blt/bitmap.rb
new file mode 100644
index 0000000000..23c6d2d064
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/bitmap.rb
@@ -0,0 +1,112 @@
+#
+# tkextlib/blt/bitmap.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ class Bitmap < TkObject
+ extend TkCore
+
+ TkCommandNames = ['::blt::bitmap'.freeze].freeze
+
+ BITMAP_ID_TBL = TkCore::INTERP.create_table
+
+ (BITMAP_ID = ['blt_bitmap_id'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ BITMAP_ID_TBL.mutex.synchronize{ BITMAP_ID_TBL.clear }
+ }
+
+ def self.data(name)
+ dat = tk_simple_list(tk_call('::blt::bitmap', 'data', name))
+ [ tk_split_list(dat[0]), tk_simple_list(dat[1]) ]
+ end
+
+ def self.exist?(name)
+ bool(tk_call('::blt::bitmap', 'exists', name))
+ end
+
+ def self.height(name)
+ number(tk_call('::blt::bitmap', 'height', name))
+ end
+
+ def self.width(name)
+ number(tk_call('::blt::bitmap', 'width', name))
+ end
+
+ def self.source(name)
+ tk_simple_list(tk_call('::blt::bitmap', 'source', name))
+ end
+
+ #################################
+
+ class << self
+ alias _new new
+
+ def new(data, keys={})
+ _new(:data, nil, data, keys)
+ end
+ alias define new
+
+ def new_with_name(name, data, keys={})
+ _new(:data, name, data, keys)
+ end
+ alias define_with_name new_with_name
+
+ def compose(text, keys={})
+ _new(:text, nil, text, keys)
+ end
+
+ def compose_with_name(name, text, keys={})
+ _new(:text, name, text, keys)
+ end
+ end
+
+ def initialize(type, name, data, keys = {})
+ if name
+ @id = name
+ else
+ BITMAP_ID.mutex.synchronize{
+ @id = BITMAP_ID.join(TkCore::INTERP._ip_id_)
+ BITMAP_ID[1].succ!
+ }
+ BITMAP_ID_TBL.mutex.synchronize{
+ BITMAP_ID_TBL[@id] = self
+ }
+ end
+
+ @path = @id
+
+ unless bool(tk_call('::blt::bitmap', 'exists', @id))
+ if type == :text
+ tk_call('::blt::bitmap', 'compose', @id, data, *hash_kv(keys))
+ else # :data
+ tk_call('::blt::bitmap', 'define', @id, data, *hash_kv(keys))
+ end
+ end
+ end
+
+ def exist?
+ bool(tk_call('::blt::bitmap', 'exists', @id))
+ end
+
+ def height
+ number(tk_call('::blt::bitmap', 'height', @id))
+ end
+
+ def width
+ number(tk_call('::blt::bitmap', 'width', @id))
+ end
+
+ def source
+ tk_simple_list(tk_call('::blt::bitmap', 'source', @id))
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/busy.rb b/ext/tk/lib/tkextlib/blt/busy.rb
new file mode 100644
index 0000000000..2f807fcd9c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/busy.rb
@@ -0,0 +1,82 @@
+#
+# tkextlib/blt/busy.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/itemconfig.rb'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module Busy
+ extend TkCore
+ extend TkItemConfigMethod
+
+ TkCommandNames = ['::blt::busy'.freeze].freeze
+
+ ###########################
+
+ class Shield < TkWindow
+ def self.shield_path(win)
+ win = window(win) unless win.kind_of?(TkWindow)
+ if win.kind_of?(Tk::Toplevel)
+ win.path + '._Busy'
+ else
+ win.path + '_Busy'
+ end
+ end
+
+ def initialize(win)
+ @path = self.class.shield_path(win)
+ end
+ end
+
+ def self.shield_path(win)
+ Tk::BLT::Busy::Shield.shield_path(win)
+ end
+ end
+end
+
+class << Tk::BLT::Busy
+ def __item_config_cmd(win)
+ ['::blt::busy', 'configure', win]
+ end
+ private :__item_config_cmd
+
+ undef itemcget
+ alias configure itemconfigure
+ alias configinfo itemconfiginfo
+ alias current_configinfo current_itemconfiginfo
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ##################################
+
+ def hold(win, keys={})
+ tk_call('::blt::busy', 'hold', win, *hash_kv(keys))
+ end
+
+ def release(*wins)
+ tk_call('::blt::busy', 'release', *wins)
+ end
+
+ def forget(*wins)
+ tk_call('::blt::busy', 'forget', *wins)
+ end
+
+ def is_busy(pat=None)
+ tk_split_list(tk_call('::blt::busy', 'isbusy', pat))
+ end
+
+ def names(pat=None)
+ tk_split_list(tk_call('::blt::busy', 'names', pat))
+ end
+ alias windows names
+
+ def check(win)
+ bool(tk_call('::blt::busy', 'check', win))
+ end
+
+ def status(win)
+ bool(tk_call('::blt::busy', 'status', win))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/component.rb b/ext/tk/lib/tkextlib/blt/component.rb
new file mode 100644
index 0000000000..b2005b2f2b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/component.rb
@@ -0,0 +1,2145 @@
+#
+# tkextlib/blt/component.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module PlotComponent
+ include TkItemConfigMethod
+
+ module OptKeys
+ def __item_font_optkeys(id)
+ ['font', 'tickfont', 'titlefont']
+ end
+ private :__item_font_optkeys
+
+ def __item_numstrval_optkeys(id)
+ ['xoffset', 'yoffset']
+ end
+ private :__item_numstrval_optkeys
+
+ def __item_boolval_optkeys(id)
+ ['hide', 'under', 'descending', 'logscale', 'loose', 'showticks',
+ 'titlealternate', 'scalesymbols', 'minor', 'raised',
+ 'center', 'decoration', 'landscape', 'maxpect']
+ end
+ private :__item_boolval_optkeys
+
+ def __item_strval_optkeys(id)
+ ['text', 'label', 'limits', 'title',
+ 'show', 'file', 'maskdata', 'maskfile',
+ 'color', 'titlecolor', 'fill', 'outline', 'offdash']
+ end
+ private :__item_strval_optkeys
+
+ def __item_listval_optkeys(id)
+ ['bindtags']
+ end
+ private :__item_listval_optkeys
+
+ def __item_numlistval_optkeys(id)
+ ['dashes', 'majorticks', 'minorticks']
+ end
+ private :__item_numlistval_optkeys
+
+ def __item_tkvariable_optkeys(id)
+ ['variable', 'textvariable', 'colormap', 'fontmap']
+ end
+ private :__item_tkvariable_optkeys
+ end
+
+ include OptKeys
+
+ def __item_cget_cmd(id)
+ if id.kind_of?(Array)
+ # id := [ type, name ]
+ [self.path, id[0], 'cget', id[1]]
+ else
+ [self.path, id, 'cget']
+ end
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ if id.kind_of?(Array)
+ # id := [ type, name, ... ]
+ type, *names = id
+ [self.path, type, 'configure'].concat(names)
+ else
+ [self.path, id, 'configure']
+ end
+ 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 axis_cget(id, option)
+ ret = itemcget(['axis', tagid(id)], option)
+ end
+ def axis_cget_strict(id, option)
+ ret = itemcget_strict(['axis', tagid(id)], option)
+ end
+ def axis_configure(*args)
+ slot = args.pop
+ if slot.kind_of?(Hash)
+ value = None
+ slot = _symbolkey2str(slot)
+ if cmd = slot.delete('command')
+ slot['command'] = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ else
+ value = slot
+ slot = args.pop
+ if slot == :command || slot == 'command'
+ cmd = value
+ value = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ end
+ id_list = args.flatten.collect!{|id| tagid(id)}.unshift('axis')
+ itemconfigure(id_list, slot, value)
+ end
+ def axis_configinfo(id, slot=nil)
+ itemconfiginfo(['axis', tagid(id)], slot)
+ end
+ def current_axis_configinfo(id, slot=nil)
+ current_itemconfiginfo(['axis', tagid(id)], slot)
+ end
+
+ def crosshairs_cget(option)
+ itemcget('crosshairs', option)
+ end
+ def crosshairs_cget_strict(option)
+ itemcget_strict('crosshairs', option)
+ end
+ def crosshairs_configure(slot, value=None)
+ itemconfigure('crosshairs', slot, value)
+ end
+ def crosshairs_configinfo(slot=nil)
+ itemconfiginfo('crosshairs', slot)
+ end
+ def current_crosshairs_configinfo(slot=nil)
+ current_itemconfiginfo('crosshairs', slot)
+ end
+
+ def element_cget(id, option)
+ itemcget(['element', tagid(id)], option)
+ end
+ def element_cget_strict(id, option)
+ itemcget_strict(['element', tagid(id)], option)
+ end
+ def element_configure(*args)
+ slot = args.pop
+ if slot.kind_of?(Hash)
+ value = None
+ else
+ value = slot
+ slot = args.pop
+ end
+ id_list = args.flatten.collect!{|id| tagid(id)}.unshift('element')
+ itemconfigure(id_list, slot, value)
+ end
+ def element_configinfo(id, slot=nil)
+ itemconfiginfo(['element', tagid(id)], slot)
+ end
+ def current_element_configinfo(id, slot=nil)
+ current_itemconfiginfo(['element', tagid(id)], slot)
+ end
+
+ def bar_cget(id, option)
+ itemcget(['bar', tagid(id)], option)
+ end
+ def bar_cget_strict(id, option)
+ itemcget_strict(['bar', tagid(id)], option)
+ end
+ def bar_configure(*args)
+ slot = args.pop
+ if slot.kind_of?(Hash)
+ value = None
+ else
+ value = slot
+ slot = args.pop
+ end
+ id_list = args.flatten.collect!{|id| tagid(id)}.unshift('bar')
+ itemconfigure(id_list, slot, value)
+ end
+ def bar_configinfo(id, slot=nil)
+ itemconfiginfo(['bar', tagid(id)], slot)
+ end
+ def current_bar_configinfo(id, slot=nil)
+ current_itemconfiginfo(['bar', tagid(id)], slot)
+ end
+
+ def line_cget(id, option)
+ itemcget(['line', tagid(id)], option)
+ end
+ def line_cget_strict(id, option)
+ itemcget_strict(['line', tagid(id)], option)
+ end
+ def line_configure(*args)
+ slot = args.pop
+ if slot.kind_of?(Hash)
+ value = None
+ else
+ value = slot
+ slot = args.pop
+ end
+ id_list = args.flatten.collect!{|id| tagid(id)}.unshift('line')
+ itemconfigure(id_list, slot, value)
+ end
+ def line_configinfo(id, slot=nil)
+ itemconfiginfo(['line', tagid(id)], slot)
+ end
+ def current_line_configinfo(id, slot=nil)
+ current_itemconfiginfo(['line', tagid(id)], slot)
+ end
+
+ def gridline_cget(option)
+ itemcget('grid', option)
+ end
+ def gridline_cget_strict(option)
+ itemcget_strict('grid', option)
+ end
+ def gridline_configure(slot, value=None)
+ itemconfigure('grid', slot, value)
+ end
+ def gridline_configinfo(slot=nil)
+ itemconfiginfo('grid', slot)
+ end
+ def current_gridline_configinfo(slot=nil)
+ current_itemconfiginfo('grid', slot)
+ end
+
+ def legend_cget(option)
+ itemcget('legend', option)
+ end
+ def legend_cget_strict(option)
+ itemcget_strict('legend', option)
+ end
+ def legend_configure(slot, value=None)
+ itemconfigure('legend', slot, value)
+ end
+ def legend_configinfo(slot=nil)
+ itemconfiginfo('legend', slot)
+ end
+ def current_legend_configinfo(slot=nil)
+ current_itemconfiginfo('legend', slot)
+ end
+
+ def pen_cget(id, option)
+ itemcget(['pen', tagid(id)], option)
+ end
+ def pen_cget_strict(id, option)
+ itemcget_strict(['pen', tagid(id)], option)
+ end
+ def pen_configure(*args)
+ slot = args.pop
+ if slot.kind_of?(Hash)
+ value = None
+ else
+ value = slot
+ slot = args.pop
+ end
+ id_list = args.flatten.collect!{|id| tagid(id)}.unshift('pen')
+ itemconfigure(id_list, slot, value)
+ end
+ def pen_configinfo(id, slot=nil)
+ itemconfiginfo(['pen', tagid(id)], slot)
+ end
+ def current_pen_configinfo(id, slot=nil)
+ current_itemconfiginfo(['pen', tagid(id)], slot)
+ end
+
+ def postscript_cget(option)
+ itemcget('postscript', option)
+ end
+ def postscript_cget_strict(option)
+ itemcget_strict('postscript', option)
+ end
+ def postscript_configure(slot, value=None)
+ itemconfigure('postscript', slot, value)
+ end
+ def postscript_configinfo(slot=nil)
+ itemconfiginfo('postscript', slot)
+ end
+ def current_postscript_configinfo(slot=nil)
+ current_itemconfiginfo('postscript', slot)
+ end
+
+ def marker_cget(id, option)
+ itemcget(['marker', tagid(id)], option)
+ end
+ def marker_cget_strict(id, option)
+ itemcget_strict(['marker', tagid(id)], option)
+ end
+ def marker_configure(*args)
+ slot = args.pop
+ if slot.kind_of?(Hash)
+ value = None
+ else
+ value = slot
+ slot = args.pop
+ end
+ id_list = args.flatten.collect!{|id| tagid(id)}.unshift('marker')
+ itemconfigure(id_list, slot, value)
+ end
+ def marker_configinfo(id, slot=nil)
+ itemconfiginfo(['marker', tagid(id)], slot)
+ end
+ def current_marker_configinfo(id, slot=nil)
+ current_itemconfiginfo(['marker', tagid(id)], slot)
+ end
+
+ alias __itemcget itemcget
+ alias __itemcget_strict itemcget_strict
+ alias __itemconfiginfo itemconfiginfo
+ alias __current_itemconfiginfo current_itemconfiginfo
+ private :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo
+
+ def itemcget_strict(tagOrId, option)
+ ret = __itemcget(tagid(tagOrId), option)
+ if option == 'bindtags' || option == :bindtags
+ ret.collect{|tag| TkBindTag.id2obj(tag)}
+ else
+ ret
+ end
+ end
+ def itemcget(tagOrId, option)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ itemcget_strict(tagOrId, option)
+ else
+ begin
+ itemcget_strict(tagOrId, option)
+ rescue => e
+ begin
+ if current_itemconfiginfo(tagOrId).has_key?(option.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+ def itemconfiginfo(tagOrId, slot = nil)
+ ret = __itemconfiginfo(tagid(tagOrId), slot)
+
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ if slot == 'bindtags' || slot == :bindtags
+ ret[-2] = ret[-2].collect{|tag| TkBindTag.id2obj(tag)}
+ ret[-1] = ret[-1].collect{|tag| TkBindTag.id2obj(tag)}
+ end
+ else
+ if (inf = ret.assoc('bindtags'))
+ inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
+ inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
+ end
+ end
+
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (inf = ret['bindtags'])
+ inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
+ inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
+ ret['bindtags'] = inf
+ end
+ end
+
+ ret
+ end
+ def current_itemconfiginfo(tagOrId, slot = nil)
+ ret = __current_itemconfiginfo(tagid(tagOrId), slot)
+
+ if (val = ret['bindtags'])
+ ret['bindtags'] = val.collect{|tag| TkBindTag.id2obj(tag)}
+ end
+
+ ret
+ end
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ #################
+
+ class Axis < TkObject
+ (OBJ_ID = ['blt_chart_axis'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ AxisID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ AxisID_TBL.mutex.synchronize{ AxisID_TBL.clear }
+ }
+
+ def self.id2obj(chart, id)
+ cpath = chart.path
+ AxisID_TBL.mutex.synchronize{
+ return id unless AxisID_TBL[cpath]
+ AxisID_TBL[cpath][id]? AxisID_TBL[cpath][id]: id
+ }
+ end
+
+ def self.new(chart, axis=nil, keys={})
+ if axis.kind_of?(Hash)
+ keys = axis
+ axis = nil
+ end
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
+ end
+
+ obj = nil
+ AxisID_TBL.mutex.synchronize{
+ chart_path = chart.path
+ AxisID_TBL[chart_path] ||= {}
+ if axis && AxisID_TBL[chart_path][axis]
+ obj = AxisID_TBL[chart_path][axis]
+ else
+ (obj = self.allocate).instance_eval{
+ if axis
+ @axis = @id = axis.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ Axis::AxisID_TBL[@cpath][@axis] = self
+ unless not_create
+ tk_call(@chart, 'axis', 'create', @axis, keys)
+ return obj
+ end
+ }
+ end
+ }
+
+ obj.configure(keys) if obj && ! keys.empty?
+ obj
+ end
+
+ def initialize(chart, axis=nil, keys={})
+ # dummy:: not called by 'new' method
+
+ if axis.kind_of?(Hash)
+ keys = axis
+ axis = nil
+ end
+ if axis
+ @axis = @id = axis.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ # Axis::AxisID_TBL[@cpath][@axis] = self
+ keys = _symbolkey2str(keys)
+ unless keys.delete('without_creating')
+ # @chart.axis_create(@axis, keys)
+ tk_call(@chart, 'axis', 'create', @axis, keys)
+ end
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ @id
+ end
+
+ def cget(option)
+ @chart.axis_cget(@id, option)
+ end
+ def cget_strict(option)
+ @chart.axis_cget_strict(@id, option)
+ end
+ def configure(key, value=None)
+ @chart.axis_configure(@id, key, value)
+ self
+ end
+ def configinfo(key=nil)
+ @chart.axis_configinfo(@id, key)
+ end
+ def current_configinfo(key=nil)
+ @chart.current_axis_configinfo(@id, key)
+ end
+
+ def command(cmd=nil, &b)
+ if cmd
+ configure('command', cmd)
+ elsif b
+ configure('command', Proc.new(&b))
+ else
+ cget('command')
+ end
+ end
+
+ def delete
+ @chart.axis_delete(@id)
+ self
+ end
+
+ def invtransform(val)
+ @chart.axis_invtransform(@id, val)
+ end
+
+ def limits
+ @chart.axis_limits(@id)
+ end
+
+ def name
+ @axis
+ end
+
+ def transform(val)
+ @chart.axis_transform(@id, val)
+ end
+
+ def view
+ @chart.axis_view(@id)
+ self
+ end
+
+ def use(name=None) # if @id == xaxis | x2axis | yaxis | y2axis
+ @chart.axis_use(@id, name)
+ end
+
+ def use_as(axis) # axis := xaxis | x2axis | yaxis | y2axis
+ @chart.axis_use(axis, @id)
+ end
+ end
+
+ #################
+
+ class Crosshairs < TkObject
+ CrosshairsID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ CrosshairsID_TBL.mutex.synchronize{ CrosshairsID_TBL.clear }
+ }
+
+ def self.new(chart, keys={})
+ obj = nil
+ CrosshairsID_TBL.mutex.synchronize{
+ unless (obj = CrosshairsID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'crosshairs'
+ Crosshairs::CrosshairsID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.crosshair_configure(keys) if obj && ! keys.empty?
+ obj
+ end
+
+ def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
+ @parent = @chart = chart
+ @cpath = @chart.path
+ # Crosshairs::CrosshairsID_TBL[@cpath] = self
+ @chart.crosshair_configure(keys) unless keys.empty?
+ @path = @id = 'crosshairs'
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ @id
+ end
+
+ def cget(option)
+ @chart.crosshair_cget(option)
+ end
+ def cget_strict(option)
+ @chart.crosshair_cget_strict(option)
+ end
+ def configure(key, value=None)
+ @chart.crosshair_configure(key, value)
+ self
+ end
+ def configinfo(key=nil)
+ @chart.crosshair_configinfo(key)
+ end
+ def current_configinfo(key=nil)
+ @chart.current_crosshair_configinfo(key)
+ end
+
+ def off
+ @chart.crosshair_off
+ self
+ end
+ def on
+ @chart.crosshair_on
+ self
+ end
+ def toggle
+ @chart.crosshair_toggle
+ self
+ end
+ end
+
+ #################
+
+ class Element < TkObject
+ extend Tk
+ extend TkItemFontOptkeys
+ extend TkItemConfigOptkeys
+
+ extend Tk::BLT::PlotComponent::OptKeys
+
+ ElementTypeName = 'element'
+ ElementTypeToClass = { ElementTypeName=>self }
+
+ ElementID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ ElementID_TBL.mutex.synchronize{ ElementID_TBL.clear }
+ }
+
+ (OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ def Element.type2class(type)
+ ElementTypeToClass[type]
+ end
+
+ def Element.id2obj(chart, id)
+ cpath = chart.path
+ ElementID_TBL.mutex.synchronize{
+ return id unless ElementID_TBL[cpath]
+ ElementID_TBL[cpath][id]? ElementID_TBL[cpath][id]: id
+ }
+ end
+
+ def self.new(chart, element=nil, keys={})
+ if element.kind_of?(Hash)
+ keys = element
+ element = nil
+ end
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
+ end
+
+ obj = nil
+ ElementID_TBL.mutex.synchronize{
+ chart_path = chart.path
+ ElementID_TBL[chart_path] ||= {}
+ if element && ElementID_TBL[chart_path][element]
+ obj = ElementID_TBL[chart_path][element]
+ else
+ (obj = self.allocate).instance_eval{
+ if element
+ @element = @id = element.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @typename = self.class::ElementTypeName
+ Element::ElementID_TBL[@cpath][@element] = self
+ unless not_create
+ tk_call(@chart, @typename, 'create', @element, keys)
+ return obj
+ end
+ }
+ end
+ }
+
+ obj.configure(keys) if obj && ! keys.empty?
+ obj
+ end
+
+ def initialize(chart, element=nil, keys={})
+ # dummy:: not called by 'new' method
+
+ if element.kind_of?(Hash)
+ keys = element
+ element = nil
+ end
+ if element
+ @element = @id = element.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @typename = self.class::ElementTypeName
+ # Element::ElementID_TBL[@cpath][@element] = self
+ keys = _symbolkey2str(keys)
+ unless keys.delete('without_creating')
+ # @chart.element_create(@element, keys)
+ tk_call(@chart, @typename, 'create', @element, keys)
+ end
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ @id
+ end
+
+ def cget(option)
+ # @chart.element_cget(@id, option)
+ @chart.__send__(@typename + '_cget', @id, option)
+ end
+ def cget_strict(option)
+ @chart.__send__(@typename + '_cget_strict', @id, option)
+ end
+ def configure(key, value=None)
+ # @chart.element_configure(@id, key, value)
+ @chart.__send__(@typename + '_configure', @id, key, value)
+ self
+ end
+ def configinfo(key=nil)
+ # @chart.element_configinfo(@id, key)
+ @chart.__send__(@typename + '_configinfo', @id, key)
+ end
+ def current_configinfo(key=nil)
+ # @chart.current_element_configinfo(@id, key)
+ @chart.__send__('current_' << @typename << '_configinfo', @id, key)
+ end
+
+ def activate(*args)
+ @chart.element_activate(@id, *args)
+ end
+
+ def closest(x, y, var, keys={})
+ # @chart.element_closest(x, y, var, @id, keys)
+ @chart.__send__(@typename + '_closest', x, y, var, @id, keys)
+ end
+
+ def deactivate
+ @chart.element_deactivate(@id)
+ self
+ end
+
+ def delete
+ @chart.element_delete(@id)
+ self
+ end
+
+ def exist?
+ @chart.element_exist?(@id)
+ end
+
+ def name
+ @element
+ end
+
+ def type
+ @chart.element_type(@id)
+ end
+ end
+
+ class Bar < Element
+ ElementTypeName = 'bar'.freeze
+ ElementTypeToClass[ElementTypeName] = self
+ end
+ class Line < Element
+ ElementTypeName = 'line'.freeze
+ ElementTypeToClass[ElementTypeName] = self
+ end
+
+ #################
+
+ class GridLine < TkObject
+ GridLineID_TBL = TkCore::INTERP.create_table
+ TkCore::INTERP.init_ip_env{
+ GridLineID_TBL.mutex.synchronize{ GridLineID_TBL.clear }
+ }
+
+ def self.new(chart, keys={})
+ obj = nil
+ GridLineID_TBL.mutex.synchronize{
+ unless (obj = GridLineID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'grid'
+ GridLine::GridLineID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.gridline_configure(keys) if obj && ! keys.empty?
+ obj
+ end
+
+ def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
+ @parent = @chart = chart
+ @cpath = @chart.path
+ # GridLine::GridLineID_TBL[@cpath] = self
+ @chart.gridline_configure(keys) unless keys.empty?
+ @path = @id = 'grid'
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ @id
+ end
+
+ def cget(option)
+ @chart.gridline_cget(option)
+ end
+ def cget_strict(option)
+ @chart.gridline_cget_strict(option)
+ end
+ def configure(key, value=None)
+ @chart.gridline_configure(key, value)
+ self
+ end
+ def configinfo(key=nil)
+ @chart.gridline_configinfo(key)
+ end
+ def current_configinfo(key=nil)
+ @chart.current_gridline_configinfo(key)
+ end
+
+ def off
+ @chart.gridline_off
+ self
+ end
+ def on
+ @chart.gridline_on
+ self
+ end
+ def toggle
+ @chart.gridline_toggle
+ self
+ end
+ end
+
+ #################
+
+ class Legend < TkObject
+ LegendID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ LegendID_TBL.mutex.synchronize{ LegendID_TBL.clear }
+ }
+
+ def self.new(chart, keys={})
+ obj = nil
+ LegenedID_TBL.mutex.synchronize{
+ unless (obj = LegenedID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'crosshairs'
+ Legend::LegenedID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.legend_configure(keys) if obj && ! keys.empty?
+ obj
+ end
+
+ def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
+ @parent = @chart = chart
+ @cpath = @chart.path
+ # Legend::LegendID_TBL[@cpath] = self
+ @chart.legend_configure(keys) unless keys.empty?
+ @path = @id = 'legend'
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ @id
+ end
+
+ def cget(option)
+ @chart.legend_cget(option)
+ end
+ def cget_strict(option)
+ @chart.legend_cget_strict(option)
+ end
+ def configure(key, value=None)
+ @chart.legend_configure(key, value)
+ self
+ end
+ def configinfo(key=nil)
+ @chart.legend_configinfo(key)
+ end
+ def current_configinfo(key=nil)
+ @chart.current_legend_configinfo(key)
+ end
+
+ def activate(*args)
+ @chart.legend_activate(*args)
+ end
+
+ def deactivate(*args)
+ @chart.legend_deactivate(*args)
+ end
+
+ def get(pos, y=nil)
+ @chart.legend_get(pos, y)
+ end
+ end
+
+ #################
+
+ class Pen < TkObject
+ (OBJ_ID = ['blt_chart_pen'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ PenID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ PenID_TBL.mutex.synchronize{ PenID_TBL.clear }
+ }
+
+ def self.id2obj(chart, id)
+ cpath = chart.path
+ PenID_TBL.mutex.synchronize{
+ return id unless PenID_TBL[cpath]
+ PenID_TBL[cpath][id]? PenID_TBL[cpath][id]: id
+ }
+ end
+
+ def self.new(chart, pen=nil, keys={})
+ if pen.kind_of?(Hash)
+ keys = pen
+ pen = nil
+ end
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
+ end
+
+ obj = nil
+ PenID_TBL.mutex.synchronize{
+ chart_path = chart.path
+ PenID_TBL[chart_path] ||= {}
+ if pen && PenID_TBL[chart_path][pen]
+ obj = PenID_TBL[chart_path][pen]
+ else
+ (obj = self.allocate).instance_eval{
+ if pen
+ @pen = @id = pen.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ Pen::PenID_TBL[@cpath][@pen] = self
+ unless not_create
+ tk_call(@chart, 'pen', 'create', @pen, keys)
+ return obj
+ end
+ }
+ end
+ }
+
+ obj.configure(keys) if obj && ! keys.empty?
+ obj
+ end
+
+ def initialize(chart, pen=nil, keys={})
+ if pen.kind_of?(Hash)
+ keys = pen
+ pen = nil
+ end
+ if pen
+ @pen = @id = pen.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ Pen::PenID_TBL[@cpath][@pen] = self
+ keys = _symbolkey2str(keys)
+ unless keys.delete('without_creating')
+ # @chart.pen_create(@pen, keys)
+ tk_call(@chart, 'pen', 'create', @pen, keys)
+ end
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ @id
+ end
+
+ def cget(option)
+ @chart.pen_cget(@id, option)
+ end
+ def cget_strict(option)
+ @chart.pen_cget_strict(@id, option)
+ end
+ def configure(key, value=None)
+ @chart.pen_configure(@id, key, value)
+ self
+ end
+ def configinfo(key=nil)
+ @chart.pen_configinfo(@id, key)
+ end
+ def current_configinfo(key=nil)
+ @chart.current_pen_configinfo(@id, key)
+ end
+
+ def delete
+ @chart.pen_delete(@id)
+ self
+ end
+
+ def name
+ @pen
+ end
+ end
+
+ #################
+
+ class Postscript < TkObject
+ PostscriptID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ PostscriptID_TBL.mutex.synchronize{ PostscriptID_TBL.clear }
+ }
+
+ def self.new(chart, keys={})
+ obj = nil
+ PostscriptID_TBL.mutex.synchronize{
+ unless (obj = PostscriptID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'postscript'
+ Postscript::PostscriptID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.postscript_configure(keys) if obj && ! keys.empty?
+ obj
+ end
+
+ def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
+ @parent = @chart = chart
+ @cpath = @chart.path
+ # Postscript::PostscriptID_TBL[@cpath] = self
+ @chart.postscript_configure(keys) unless keys.empty?
+ @path = @id = 'postscript'
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ @id
+ end
+
+ def cget(option)
+ @chart.postscript_cget(option)
+ end
+ def cget_strict(option)
+ @chart.postscript_cget_strict(option)
+ end
+ def configure(key, value=None)
+ @chart.postscript_configure(key, value)
+ self
+ end
+ def configinfo(key=nil)
+ @chart.postscript_configinfo(key)
+ end
+ def current_configinfo(key=nil)
+ @chart.current_postscript_configinfo(key)
+ end
+
+ def output(file=nil, keys={})
+ if file.kind_of?(Hash)
+ keys = file
+ file = nil
+ end
+
+ ret = @chart.postscript_output(file, keys)
+
+ if file
+ self
+ else
+ ret
+ end
+ end
+ end
+
+ #################
+ class Marker < TkObject
+ extend Tk
+ extend TkItemFontOptkeys
+ extend TkItemConfigOptkeys
+
+ extend Tk::BLT::PlotComponent::OptKeys
+
+ MarkerTypeName = nil
+ MarkerTypeToClass = {}
+ MarkerID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ MarkerID_TBL.mutex.synchronize{ MarkerID_TBL.clear }
+ }
+
+ def Marker.type2class(type)
+ MarkerTypeToClass[type]
+ end
+
+ def Marker.id2obj(chart, id)
+ cpath = chart.path
+ MarkerID_TBL.mutex.synchronize{
+ if MarkerID_TBL[cpath]
+ MarkerID_TBL[cpath][id]? MarkerID_TBL[cpath][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def self._parse_create_args(keys)
+ fontkeys = {}
+ methodkeys = {}
+ if keys.kind_of? Hash
+ keys = _symbolkey2str(keys)
+
+ __item_font_optkeys(nil).each{|key|
+ fkey = key.to_s
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+ fkey = "kanji#{key}"
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+ fkey = "latin#{key}"
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+ fkey = "ascii#{key}"
+ fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+ }
+
+ __item_optkey_aliases(nil).each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if keys.has_key?(alias_name)
+ keys[real_name.to_s] = keys.delete(alias_name)
+ end
+ }
+
+ __item_methodcall_optkeys(nil).each{|key|
+ key = key.to_s
+ methodkeys[key] = keys.delete(key) if keys.key?(key)
+ }
+
+ __item_ruby2val_optkeys(nil).each{|key, method|
+ key = key.to_s
+ keys[key] = method.call(keys[key]) if keys.has_key?(key)
+ }
+
+ args = itemconfig_hash_kv(nil, keys)
+ else
+ args = []
+ end
+
+ [args, fontkeys]
+ end
+ private_class_method :_parse_create_args
+
+ def self.create(chart, keys={})
+ unless self::MarkerTypeName
+ fail RuntimeError, "#{self} is an abstract class"
+ end
+ args, fontkeys = _parse_create_args(keys)
+ idnum = tk_call_without_enc(chart.path, 'marker', 'create',
+ self::MarkerTypeName, *args)
+ chart.marker_configure(idnum, fontkeys) unless fontkeys.empty?
+ idnum.to_i # 'item id' is an integer number
+ end
+
+ def self.create_type(chart, type, keys={})
+ args, fontkeys = _parse_create_args(keys)
+ idnum = tk_call_without_enc(chart.path, 'marker', 'create',
+ type, *args)
+ chart.marker_configure(idnum, fontkeys) unless fontkeys.empty?
+ id = idnum.to_i # 'item id' is an integer number
+ obj = self.allocate
+ obj.instance_eval{
+ @parent = @chart = chart
+ @cpath = chart.path
+ @id = id
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {}
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ }
+ }
+ obj
+ end
+
+ def initialize(parent, *args)
+ @parent = @chart = parent
+ @cpath = parent.path
+
+ @path = @id = create_self(*args) # an integer number as 'item id'
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {}
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ }
+ end
+ def create_self(*args)
+ self.class.create(@chart, *args) # return an integer as 'item id'
+ end
+ private :create_self
+
+ def id
+ @id
+ end
+
+ def to_eval
+ @id
+ end
+
+ def cget(option)
+ @chart.marker_cget(@id, option)
+ end
+ def cget_strict(option)
+ @chart.marker_cget_strict(@id, option)
+ end
+ def configure(key, value=None)
+ @chart.marker_configure(@id, key, value)
+ self
+ end
+ def configinfo(key=nil)
+ @chart.marker_configinfo(@id, key)
+ end
+ def current_configinfo(key=nil)
+ @chart.current_marker_configinfo(@id, key)
+ end
+
+ def after(target=None)
+ @chart.marker_after(@id, target)
+ end
+
+ def before(target=None)
+ @chart.marker_before(@id, target)
+ end
+
+ def delete
+ @chart.marker_delete(@id)
+ end
+
+ def exist?
+ @chart.marker_exist(@id)
+ end
+
+ def type
+ @chart.marker_type(@id)
+ end
+ end
+
+ class TextMarker < Marker
+ MarkerTypeName = 'text'.freeze
+ MarkerTypeToClass[MarkerTypeName] = self
+ end
+ class LineMarker < Marker
+ MarkerTypeName = 'line'.freeze
+ MarkerTypeToClass[MarkerTypeName] = self
+ end
+ class BitmapMarker < Marker
+ MarkerTypeName = 'bitmap'.freeze
+ MarkerTypeToClass[MarkerTypeName] = self
+ end
+ class ImageMarker < Marker
+ MarkerTypeName = 'image'.freeze
+ MarkerTypeToClass[MarkerTypeName] = self
+ end
+ class PolygonMarker < Marker
+ MarkerTypeName = 'polygon'.freeze
+ MarkerTypeToClass[MarkerTypeName] = self
+ end
+ class WindowMarker < Marker
+ MarkerTypeName = 'window'.freeze
+ MarkerTypeToClass[MarkerTypeName] = self
+ end
+
+ #################
+
+ def __destroy_hook__
+ Axis::AxisID_TBL.delete(@path)
+ Crosshairs::CrosshairsID_TBL.delete(@path)
+ Element::ElementID_TBL.delete(@path)
+ GridLine::GridLineID_TBL.delete(@path)
+ Legend::LegendID_TBL.delete(@path)
+ Pen::PenID_TBL.delete(@path)
+ Postscript::PostscriptID_TBL.delete(@path)
+ Marker::MarkerID_TBL.delete(@path)
+ super()
+ end
+
+ #################
+
+ def tagid(tag)
+ if tag.kind_of?(Axis) ||
+ tag.kind_of?(Crosshairs) ||
+ tag.kind_of?(Element) ||
+ tag.kind_of?(GridLine) ||
+ tag.kind_of?(Legend) ||
+ tag.kind_of?(Pen) ||
+ tag.kind_of?(Postscript) ||
+ tag.kind_of?(Marker)
+ tag.id
+ else
+ tag # maybe an Array of configure paramters
+ end
+ end
+
+ def _component_bind(target, tag, context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, target, 'bind', tagid(tag)], context, cmd, *args)
+ self
+ end
+ def _component_bind_append(target, tag, context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, target, 'bind', tagid(tag)], context, cmd, *args)
+ self
+ end
+ def _component_bind_remove(target, tag, context)
+ _bind_remove([path, target, 'bind', tagid(tag)], context)
+ self
+ end
+ def _component_bindinfo(target, tag, context=nil)
+ _bindinfo([path, target, 'bind', tagid(tag)], context)
+ end
+ private :_component_bind, :_component_bind_append
+ private :_component_bind_remove, :_component_bindinfo
+
+ def axis_bind(tag, context, *args)
+ _component_bind('axis', tag, context, *args)
+ end
+ def axis_bind_append(tag, context, *args)
+ _component_bind_append('axis', tag, context, *args)
+ end
+ def axis_bind_remove(tag, context)
+ _component_bind_remove('axis', tag, context)
+ end
+ def axis_bindinfo(tag, context=nil)
+ _component_bindinfo('axis', tag, context)
+ end
+
+ def element_bind(tag, context, *args)
+ _component_bind('element', tag, context, *args)
+ end
+ def element_bind_append(tag, context, *args)
+ _component_bind_append('element', tag, context, *args)
+ end
+ def element_bind_remove(tag, context)
+ _component_bind_remove('element', tag, context)
+ end
+ def element_bindinfo(tag, context=nil)
+ _component_bindinfo('element', tag, context)
+ end
+
+ def bar_bind(tag, context, *args)
+ _component_bind('bar', tag, context, *args)
+ end
+ def bar_bind_append(tag, context, *args)
+ _component_bind_append('bar', tag, context, *args)
+ end
+ def bar_bind_remove(tag, context)
+ _component_bind_remove('bar', tag, context)
+ end
+ def bar_bindinfo(tag, context=nil)
+ _component_bindinfo('bar', tag, context)
+ end
+
+ def line_bind(tag, context, *args)
+ _component_bind('line', tag, context, *args)
+ end
+ def line_bind_append(tag, context, *args)
+ _component_bind_append('line', tag, context, *args)
+ end
+ def line_bind_remove(tag, context)
+ _component_bind_remove('line', tag, context)
+ end
+ def line_bindinfo(tag, context=nil)
+ _component_bindinfo('line', tag, context)
+ end
+
+ def legend_bind(tag, context, *args)
+ _component_bind('legend', tag, context, *args)
+ end
+ def legend_bind_append(tag, context, *args)
+ _component_bind_append('legend', tag, context, *args)
+ end
+ def legend_bind_remove(tag, context)
+ _component_bind_remove('legend', tag, context)
+ end
+ def legend_bindinfo(tag, context=nil)
+ _component_bindinfo('legend', tag, context)
+ end
+
+ def marker_bind(tag, context, *args)
+ _component_bind('marker', tag, context, *args)
+ end
+ def marker_bind_append(tag, context, *args)
+ _component_bind_append('marker', tag, context, *args)
+ end
+ def marker_bind_remove(tag, context)
+ _component_bind_remove('marker', tag, context)
+ end
+ def marker_bindinfo(tag, context=nil)
+ _component_bindinfo('marker', tag, context)
+ end
+
+ ###################
+
+ def axis_create(id=nil, keys={})
+ # tk_send('axis', 'create', tagid(id), keys)
+ Tk::BLT::PlotComponent::Axis.new(self, tagid(id), keys)
+ end
+ def axis_delete(*ids)
+ tk_send('axis', 'delete', *(ids.collect{|id| tagid(id)}))
+ self
+ end
+ def axis_invtransform(id, val)
+ list(tk_send('axis', 'invtransform', tagid(id), val))
+ end
+ def axis_limits(id)
+ list(tk_send('axis', 'limits', tagid(id)))
+ end
+ def axis_names(*pats)
+ simplelist(tk_send('axis', 'names',
+ *(pats.collect{|pat| tagid(pat)}))).collect{|axis|
+ Tk::BLT::PlotComponent::Axis.id2obj(self, axis)
+ }
+ end
+ def axis_transform(id, val)
+ list(tk_send('axis', 'transform', tagid(id), val))
+ end
+ def axis_view(id)
+ tk_send('axis', 'view', tagid(id))
+ self
+ end
+ def axis_use(id, target=nil)
+ if target
+ Tk::BLT::PlotComponent::Axis.id2obj(self,
+ tk_send('axis', 'use',
+ tagid(id), tagid(target)))
+ else
+ Tk::BLT::PlotComponent::Axis.id2obj(self,
+ tk_send('axis', 'use', tagid(id)))
+ end
+ end
+
+ ###################
+
+ def crosshairs_off
+ tk_send_without_enc('crosshairs', 'off')
+ self
+ end
+ def crosshairs_on
+ tk_send_without_enc('crosshairs', 'on')
+ self
+ end
+ def crosshairs_toggle
+ tk_send_without_enc('crosshairs', 'toggle')
+ self
+ end
+
+ ###################
+
+ def element_create(id=nil, keys={})
+ # tk_send('element', 'create', tagid(id), keys)
+ Tk::BLT::PlotComponent::Element.new(self, tagid(id), keys)
+ end
+ def element_activate(*args)
+ if args.empty?
+ list(tk_send('element', 'activate')).collect{|elem|
+ Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+ }
+ else
+ # id, *indices
+ id = args.shift
+ tk_send('element', 'activate', tagid(id), *args)
+ end
+ end
+ def element_closest(x, y, var, *args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ bool(tk_send('element', 'closest', x, y, var,
+ *(hash_kv(keys).concat(args.collect{|id| tagid(id)}))))
+ else
+ bool(tk_send('element', 'closest', x, y, var,
+ *(args.collect{|id| tagid(id)})))
+ end
+ end
+ def element_deactivate(*ids)
+ tk_send('element', 'deactivate', *(ids.collect{|id| tagid(id)}))
+ self
+ end
+ def element_delete(*ids)
+ tk_send('element', 'delete', *(ids.collect{|id| tagid(id)}))
+ self
+ end
+ def element_exist?(id)
+ bool(tk_send('element', 'exists', tagid(id)))
+ end
+ def element_names(*pats)
+ simplelist(tk_send('element', 'names',
+ *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+ Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+ }
+ end
+ def element_show(*names)
+ if names.empty?
+ simplelist(tk_send('element', 'show'))
+ else
+ tk_send('element', 'show', *(names.collect{|n| tagid(n)}))
+ self
+ end
+ end
+ def element_type(id)
+ tk_send('element', 'type', tagid(id))
+ end
+
+ ###################
+
+ def bar_create(id=nil, keys={})
+ # tk_send('bar', 'create', tagid(id), keys)
+ Tk::BLT::PlotComponent::Bar.new(self, tagid(id), keys)
+ end
+ alias bar bar_create
+ def bar_activate(*args)
+ if args.empty?
+ list(tk_send('bar', 'activate')).collect{|elem|
+ Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+ }
+ else
+ # id, *indices
+ id = args.shift
+ tk_send('bar', 'activate', tagid(id), *args)
+ end
+ end
+ def bar_closest(x, y, var, *args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ bool(tk_send('bar', 'closest', x, y, var,
+ *(hash_kv(keys).concat(args.collect{|id| tagid(id)}))))
+ else
+ bool(tk_send('bar', 'closest', x, y, var,
+ *(args.collect{|id| tagid(id)})))
+ end
+ end
+ def bar_deactivate(*ids)
+ tk_send('bar', 'deactivate', *(ids.collect{|id| tagid(id)}))
+ self
+ end
+ def bar_delete(*ids)
+ tk_send('bar', 'delete', *(ids.collect{|id| tagid(id)}))
+ self
+ end
+ def bar_exist?(id)
+ bool(tk_send('bar', 'exists', tagid(id)))
+ end
+ def bar_names(*pats)
+ simplelist(tk_send('bar', 'names',
+ *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+ Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+ }
+ end
+ def bar_show(*names)
+ if names.empty?
+ simplelist(tk_send('bar', 'show'))
+ else
+ tk_send('bar', 'show', *(names.collect{|n| tagid(n)}))
+ self
+ end
+ end
+ def bar_type(id)
+ tk_send('bar', 'type', tagid(id))
+ end
+
+ ###################
+
+ def line_create(id=nil, keys={})
+ # tk_send('line', 'create', tagid(id), keys)
+ Tk::BLT::PlotComponent::Line.new(self, tagid(id), keys)
+ end
+ alias bar line_create
+ def line_activate(*args)
+ if args.empty?
+ list(tk_send('line', 'activate')).collect{|elem|
+ Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+ }
+ else
+ # id, *indices
+ id = args.shift
+ tk_send('line', 'activate', tagid(id), *args)
+ end
+ end
+ def line_closest(x, y, var, *args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ bool(tk_send('line', 'closest', x, y, var,
+ *(hash_kv(keys).concat(args.collect{|id| tagid(id)}))))
+ else
+ bool(tk_send('line', 'closest', x, y, var,
+ *(args.collect{|id| tagid(id)})))
+ end
+ end
+ def line_deactivate(*ids)
+ tk_send('line', 'deactivate', *(ids.collect{|id| tagid(id)}))
+ self
+ end
+ def line_delete(*ids)
+ tk_send('line', 'delete', *(ids.collect{|id| tagid(id)}))
+ self
+ end
+ def line_exist?(id)
+ bool(tk_send('line', 'exists', tagid(id)))
+ end
+ def line_names(*pats)
+ simplelist(tk_send('line', 'names',
+ *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+ Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+ }
+ end
+ def line_show(*names)
+ if names.empty?
+ simplelist(tk_send('line', 'show'))
+ else
+ tk_send('line', 'show', *(names.collect{|n| tagid(n)}))
+ self
+ end
+ end
+ def line_type(id)
+ tk_send('line', 'type', tagid(id))
+ end
+
+ ###################
+
+ def gridline_off
+ tk_send_without_enc('grid', 'off')
+ self
+ end
+ def gridline_on
+ tk_send_without_enc('grid', 'on')
+ self
+ end
+ def gridline_toggle
+ tk_send_without_enc('grid', 'toggle')
+ self
+ end
+
+ ###################
+
+ def legend_window_create(parent=nil, keys=nil)
+ if parent.kind_of?(Hash)
+ keys = _symbolkey2str(parent)
+ parent = keys.delete('parent')
+ widgetname = keys.delete('widgetname')
+ keys.delete('without_creating')
+ elsif keys
+ keys = _symbolkey2str(keys)
+ widgetname = keys.delete('widgetname')
+ keys.delete('without_creating')
+ end
+
+ legend = self.class.new(parent, :without_creating=>true,
+ :widgetname=>widgetname)
+ class << legend
+ def __destroy_hook__
+ TkCore::INTERP.tk_windows.delete(@path)
+ end
+ end
+
+ if keys
+ self.legend_configure(keys.update('position'=>legend))
+ else
+ self.legend_configure('position'=>legend)
+ end
+ legend
+ end
+
+ def legend_activate(*pats)
+ list(tk_send('legend', 'activate',
+ *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+ Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+ }
+ end
+ def legend_deactivate(*pats)
+ list(tk_send('legend', 'deactivate',
+ *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+ Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+ }
+ end
+ def legend_get(pos, y=nil)
+ if y
+ Tk::BLT::PlotComponent::Element.id2obj(self,
+ tk_send('legend', 'get',
+ _at(pos, y)))
+ else
+ Tk::BLT::PlotComponent::Element.id2obj(self,
+ tk_send('legend', 'get', pos))
+ end
+ end
+
+ ###################
+
+ def pen_create(id=nil, keys={})
+ # tk_send('pen', 'create', tagid(id), keys)
+ Tk::BLT::PlotComponent::Pen.new(self, tagid(id), keys)
+ end
+ def pen_delete(*ids)
+ tk_send('pen', 'delete', *(ids.collect{|id| tagid(id)}))
+ self
+ end
+ def pen_names(*pats)
+ simplelist(tk_send('pen', 'names',
+ *(pats.collect{|pat| tagid(pat)}))).collect{|pen|
+ Tk::BLT::PlotComponent::Pen.id2obj(self, pen)
+ }
+ end
+
+ ###################
+
+ def postscript_output(file=nil, keys={})
+ if file.kind_of?(Hash)
+ keys = file
+ file = nil
+ end
+
+ if file
+ tk_send('postscript', 'output', file, keys)
+ self
+ else
+ tk_send('postscript', 'output', keys)
+ end
+ end
+
+ ###################
+
+ def marker_create(type, keys={})
+ case type
+ when :text, 'text'
+ Tk::BLT::PlotComponent::TextMarker.new(self, keys)
+ when :line, 'line'
+ Tk::BLT::PlotComponent::LineMarker.new(self, keys)
+ when :bitmap, 'bitmap'
+ Tk::BLT::PlotComponent::BitmapMarker.new(self, keys)
+ when :image, 'image'
+ Tk::BLT::PlotComponent::ImageMarker.new(self, keys)
+ when :polygon, 'polygon'
+ Tk::BLT::PlotComponent::PolygonMarker.new(self, keys)
+ when :window, 'window'
+ Tk::BLT::PlotComponent::WindowMarker.new(self, keys)
+ else
+ if type.kind_of?(Tk::BLT::PlotComponent::Marker)
+ type.new(self, keys)
+ else
+ Tk::BLT::PlotComponent::Marker.create_type(self, type, keys)
+ end
+ end
+ end
+ def marker_after(id, target=nil)
+ if target
+ tk_send_without_enc('marker', 'after', tagid(id), tagid(target))
+ else
+ tk_send_without_enc('marker', 'after', tagid(id))
+ end
+ self
+ end
+ def marker_before(id, target=None)
+ if target
+ tk_send_without_enc('marker', 'before', tagid(id), tagid(target))
+ else
+ tk_send_without_enc('marker', 'before', tagid(id))
+ end
+ self
+ end
+ def marker_delete(*ids)
+ tk_send('marker', 'delete', *(ids.collect{|id| tagid(id)}))
+ self
+ end
+ def marker_exist?(id)
+ bool(tk_send('marker', 'exists', tagid(id)))
+ end
+ def marker_names(*pats)
+ simplelist(tk_send('marker', 'names',
+ *(pats.collect{|pat| tagid(pat)}))).collect{|id|
+ Tk::BLT::PlotComponent::Marker.id2obj(self, id)
+ }
+ end
+ def marker_type(id)
+ tk_send('marker', 'type', tagid(id))
+ end
+
+ ###################
+
+ def xaxis_cget(option)
+ itemcget('xaxis', option)
+ end
+ def xaxis_cget_strict(option)
+ itemcget_strict('xaxis', option)
+ end
+ def xaxis_configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ if cmd = slot.delete('command')
+ slot['command'] = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ elsif slot == :command || slot == 'command'
+ cmd = value
+ value = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ itemconfigure('xaxis', slot, value)
+ end
+ def xaxis_configinfo(slot=nil)
+ itemconfiginfo('xaxis', slot)
+ end
+ def current_xaxis_configinfo(slot=nil)
+ current_itemconfiginfo('xaxis', slot)
+ end
+ def xaxis_bind(context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, 'xaxis', 'bind'], context, cmd, *args)
+ self
+ end
+ def xaxis_bind_append(context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, 'xaxis', 'bind'], context, cmd, *args)
+ self
+ end
+ def xaxis_bind_remove(context)
+ _bind_remove([path, 'xaxis', 'bind'], context)
+ self
+ end
+ def xaxis_bindinfo(context=nil)
+ _bindinfo([path, 'xaxis', 'bind'], context)
+ end
+ def xaxis_invtransform(val)
+ list(tk_send('xaxis', 'invtransform', val))
+ end
+ def xaxis_limits
+ list(tk_send('xaxis', 'limits'))
+ end
+ def xaxis_transform(val)
+ list(tk_send('xaxis', 'transform', val))
+ end
+ def xaxis_use(target=nil)
+ if target
+ Tk::BLT::PlotComponent::Axis.id2obj(self,
+ tk_send('xaxis', 'use',
+ tagid(target)))
+ else
+ Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('xaxis', 'use'))
+ end
+ end
+
+ def x2axis_cget(option)
+ itemcget('x2axis', option)
+ end
+ def x2axis_cget_strict(option)
+ itemcget_strict('x2axis', option)
+ end
+ def x2axis_configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ if cmd = slot.delete('command')
+ slot['command'] = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ elsif slot == :command || slot == 'command'
+ cmd = value
+ value = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ itemconfigure('x2axis', slot, value)
+ end
+ def x2axis_configinfo(slot=nil)
+ itemconfiginfo('x2axis', slot)
+ end
+ def current_x2axis_configinfo(slot=nil)
+ current_itemconfiginfo('x2axis', slot)
+ end
+ def x2axis_bind(context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, 'x2axis', 'bind'], context, cmd, *args)
+ self
+ end
+ def x2axis_bind_append(context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, 'x2axis', 'bind'], context, cmd, *args)
+ self
+ end
+ def x2axis_bind_remove(context)
+ _bind_remove([path, 'x2axis', 'bind'], context)
+ self
+ end
+ def x2axis_bindinfo(context=nil)
+ _bindinfo([path, 'x2axis', 'bind'], context)
+ end
+ def x2axis_invtransform(val)
+ list(tk_send('x2axis', 'invtransform', val))
+ end
+ def x2axis_limits
+ list(tk_send('x2axis', 'limits'))
+ end
+ def x2axis_transform(val)
+ list(tk_send('x2axis', 'transform', val))
+ end
+ def x2axis_use(target=nil)
+ if target
+ Tk::BLT::PlotComponent::Axis.id2obj(self,
+ tk_send('x2axis', 'use',
+ tagid(target)))
+ else
+ Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('x2axis', 'use'))
+ end
+ end
+
+ def yaxis_cget(option)
+ itemcget('yaxis', option)
+ end
+ def yaxis_cget_strict(option)
+ itemcget_strict('yaxis', option)
+ end
+ def yaxis_configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ if cmd = slot.delete('command')
+ slot['command'] = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ elsif slot == :command || slot == 'command'
+ cmd = value
+ value = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ itemconfigure('yaxis', slot, value)
+ end
+ def yaxis_configinfo(slot=nil)
+ itemconfiginfo('yaxis', slot)
+ end
+ def current_yaxis_configinfo(slot=nil)
+ current_itemconfiginfo('yaxis', slot)
+ end
+ def yaxis_bind(context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, 'yaxis', 'bind'], context, cmd, *args)
+ self
+ end
+ def yaxis_bind_append(context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, 'yaxis', 'bind'], context, cmd, *args)
+ self
+ end
+ def yaxis_bind_remove(context)
+ _bind_remove([path, 'yaxis', 'bind'], context)
+ self
+ end
+ def yaxis_bindinfo(context=nil)
+ _bindinfo([path, 'yaxis', 'bind'], context)
+ end
+ def yaxis_invtransform(val)
+ list(tk_send('yaxis', 'invtransform', val))
+ end
+ def yaxis_limits
+ list(tk_send('yaxis', 'limits'))
+ end
+ def yaxis_transform(val)
+ list(tk_send('yaxis', 'transform', val))
+ end
+ def yaxis_use(target=nil)
+ if target
+ Tk::BLT::PlotComponent::Axis.id2obj(self,
+ tk_send('yaxis', 'use',
+ tagid(target)))
+ else
+ Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('yaxis', 'use'))
+ end
+ end
+
+ def y2axis_cget(option)
+ itemcget('y2axis', option)
+ end
+ def y2axis_cget_strict(option)
+ itemcget_strict('y2axis', option)
+ end
+ def y2axis_configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ if cmd = slot.delete('command')
+ slot['command'] = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ elsif slot == :command || slot == 'command'
+ cmd = value
+ value = proc{|w, tick|
+ cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+ }
+ end
+ itemconfigure('y2axis', slot, value)
+ end
+ def y2axis_configinfo(slot=nil)
+ axis_configinfo('y2axis', slot)
+ end
+ def current_y2axis_configinfo(slot=nil)
+ current_itemconfiginfo('y2axis', slot)
+ end
+ def y2axis_bind(context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, 'y2axis', 'bind'], context, cmd, *args)
+ self
+ end
+ def y2axis_bind_append(context, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, 'y2axis', 'bind'], context, cmd, *args)
+ self
+ end
+ def y2axis_bind_remove(context)
+ _bind_remove([path, 'y2axis', 'bind'], context)
+ self
+ end
+ def y2axis_bindinfo(context=nil)
+ _bindinfo([path, 'y2axis', 'bind'], context)
+ end
+ def y2axis_invtransform(val)
+ list(tk_send('y2axis', 'invtransform', val))
+ end
+ def y2axis_limits
+ list(tk_send('y2axis', 'limits'))
+ end
+ def y2axis_transform(val)
+ list(tk_send('y2axis', 'transform', val))
+ end
+ def y2axis_use(target=nil)
+ if target
+ Tk::BLT::PlotComponent::Axis.id2obj(self,
+ tk_send('y2axis', 'use',
+ tagid(target)))
+ else
+ Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('y2axis', 'use'))
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/container.rb b/ext/tk/lib/tkextlib/blt/container.rb
new file mode 100644
index 0000000000..cdbec21f25
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/container.rb
@@ -0,0 +1,28 @@
+#
+# tkextlib/blt/container.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ class Container < TkWindow
+ TkCommandNames = ['::blt::container'.freeze].freeze
+ WidgetClassName = 'Container'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'name'
+ end
+ private :__strval_optkeys
+
+ def find_command(pat)
+ Hash[*simplelist(tk_send_without_enc('find', '-command', pat))]
+ end
+
+ def find_name(pat)
+ Hash[*simplelist(tk_send_without_enc('find', '-name', pat))]
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/cutbuffer.rb b/ext/tk/lib/tkextlib/blt/cutbuffer.rb
new file mode 100644
index 0000000000..1cc39dfb94
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/cutbuffer.rb
@@ -0,0 +1,23 @@
+#
+# tkextlib/blt/cutbuffer.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module CutBuffer
+ TkCommandNames = ['::blt::cutbuffer'.freeze].freeze
+
+ def self.get(num = 0)
+ Tk.tk_call('::blt::cutbuffer', 'get', num)
+ end
+ def self.rotate(count = 1)
+ Tk.tk_call('::blt::cutbuffer', 'rotate', count)
+ end
+ def self.set(val, num = 0)
+ Tk.tk_call('::blt::cutbuffer', 'set', val, num)
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/dragdrop.rb b/ext/tk/lib/tkextlib/blt/dragdrop.rb
new file mode 100644
index 0000000000..201548504a
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/dragdrop.rb
@@ -0,0 +1,268 @@
+#
+# tkextlib/blt/dragdrop.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/itemconfig'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module DragDrop
+ extend TkCore
+
+ TkCommandNames = ['::blt::drag&drop'.freeze].freeze
+
+ class Token < TkWindow
+ WidgetClassName = 'DragDropToken'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def initialize(arg)
+ if arg.kind_of?(Hash) # arg is a hash includes the widgetpath of token
+ arg = _symbolkey2str(arg)
+ install_win(nil, arg['widgetname'])
+ else # arg is a drag&drop source
+ tk_call('::blt::drag&drop', 'source', arg)
+ install_win(nil, tk_call('::blt::drag&drop', 'token', arg))
+ end
+ end
+ end
+
+ ###################################
+
+ extend TkItemConfigMethod
+ extend Tk::ValidateConfigure
+
+ class << self
+ def __item_config_cmd(id) # id := ['source'|'target', win]
+ ['::blt::drag&drop', id[0], id[1]]
+ end
+ private :__item_config_cmd
+
+ def __item_boolval_optkeys(id)
+ super(id) << 'selftarget'
+ end
+ private :__item_boolval_optkeys
+
+ def __item_listval_optkeys(id)
+ super(id) << 'send'
+ end
+ private :__item_listval_optkeys
+
+ def __item_strval_optkeys(id)
+ super(id) << 'rejectbg' << 'rejectfg' << 'tokenbg'
+ end
+ private :__item_strval_optkeys
+
+ undef itemcget
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ def source_configure(win, slot, value=None)
+ itemconfigure(['source', win], slot, value)
+ end
+ def source_configinfo(win, slot=nil)
+ itemconfiginfo(['source', win], slot)
+ end
+ def current_source_configinfo(win, slot=nil)
+ current_itemconfiginfo(['source', win], slot)
+ end
+ end
+
+ class PackageCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?t, ?w, :token ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?w, TkComm.method(:window) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL)
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ ['packagecmd']
+ end
+ end
+
+ class SiteCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?s, ?b, :compatible ],
+ [ ?t, ?w, :token ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?b, TkComm.method(:bool) ],
+ [ ?w, TkComm.method(:window) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL)
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ ['sitecmd']
+ end
+ end
+
+ def self.__validation_class_list
+ super() << PackageCommand << SiteCommand
+ end
+
+ class << self
+ Tk::ValidateConfigure.__def_validcmd(binding, PackageCommand)
+ Tk::ValidateConfigure.__def_validcmd(binding, SiteCommand)
+ end
+
+ ###################################
+
+ class DnD_Handle < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?i, ?s, :ip_name ],
+ [ ?v, ?v, :value ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?i, TkComm.method(:string) ],
+ [ ?v, TkComm.method(:tk_tcl2ruby) ],
+ [ ?w, TkComm.method(:window) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL)
+ end
+
+ def self.source_handler(win, datatype, cmd=Proc.new, *args)
+ _bind_for_event_class(DnD_Handle,
+ ['::blt::drag&drop', 'source', win, 'handler'],
+ cmd, *args)
+ end
+
+ def self.target_handler(win, datatype, cmd=Proc.new, *args)
+ _bind_for_event_class(DnD_Handle,
+ ['::blt::drag&drop', 'target', win, 'handler'],
+ cmd, *args)
+ end
+
+ ###################################
+
+ def self.init_source(win)
+ tk_call('::blt::drag&drop', 'source', win)
+ end
+
+ def self.source()
+ list(tk_call('::blt::drag&drop', 'source'))
+ end
+
+ def self.source_handler_list(win)
+ simplelist(tk_call('::blt::drag&drop', 'source', win, 'handler'))
+ end
+ def self.source_handler_info(win, type)
+ tk_tcl2ruby(tk_call('::blt::drag&drop', 'source', win, 'handler', type))
+ end
+
+ def self.target
+ list(tk_call('::blt::drag&drop', 'target'))
+ end
+ def self.target_handler_list(win)
+ simplelist(tk_call('::blt::drag&drop', 'target', win, 'handler'))
+ end
+
+ def self.handle_target(win, type, val=None)
+ tk_call('::blt::drag&drop', 'target', win, 'handle', type, val)
+ end
+
+ def self.token(win)
+ window(tk_call('::blt::drag&drop', 'token', win))
+ end
+
+ def self.drag(win, x, y)
+ tk_call('::blt::drag&drop', 'drag', win, x, y)
+ end
+ def self.drop(win, x, y)
+ tk_call('::blt::drag&drop', 'drop', win, x, y)
+ end
+
+ def self.errors(cmd=Proc.new)
+ tk_call('::blt::drag&drop', 'errors', cmd)
+ end
+
+ def self.active
+ bool(tk_call('::blt::drag&drop', 'active'))
+ end
+
+ def self.location(x=None, y=None)
+ list(tk_call('::blt::drag&drop', 'location', x, y))
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/eps.rb b/ext/tk/lib/tkextlib/blt/eps.rb
new file mode 100644
index 0000000000..0dba87a7cc
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/eps.rb
@@ -0,0 +1,32 @@
+#
+# tkextlib/blt/eps.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/canvas'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ class EPS < TkcItem
+ CItemTypeName = 'eps'.freeze
+ CItemTypeToClass[CItemTypeName] = self
+ end
+end
+
+class Tk::Canvas
+ alias __BLT_EPS_item_strval_optkeys __item_strval_optkeys
+ def __item_strval_optkeys(id)
+ __BLT_EPS_item_strval_optkeys(id) + [
+ 'shadowcolor', 'title', 'titlecolor'
+ ]
+ end
+ private :__item_strval_optkeys
+
+ alias __BLT_EPS_item_boolval_optkeys __item_boolval_optkeys
+ def __item_boolval_optkeys(id)
+ __BLT_EPS_item_boolval_optkeys(id) + ['showimage']
+ end
+ private :__item_boolval_optkeys
+end
+
diff --git a/ext/tk/lib/tkextlib/blt/graph.rb b/ext/tk/lib/tkextlib/blt/graph.rb
new file mode 100644
index 0000000000..9ae99bff5c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/graph.rb
@@ -0,0 +1,67 @@
+#
+# tkextlib/blt/graph.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+require 'tkextlib/blt/component.rb'
+
+module Tk::BLT
+ class Graph < TkWindow
+ TkCommandNames = ['::blt::graph'.freeze].freeze
+ WidgetClassName = 'Graph'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ include PlotComponent
+ include GraphCommand
+
+ def __boolval_optkeys
+ ['bufferelements', 'invertxy']
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ ['text', 'label', 'title', 'file', 'plotbackground']
+ end
+ private :__strval_optkeys
+
+=begin
+ BarElement_ID = ['blt_graph_bar'.freeze, '00000'.taint].freeze
+
+ def bar(elem=nil, keys={})
+ if elem.kind_of?(Hash)
+ keys = elem
+ elem = nil
+ end
+ unless elem
+ elem = BarElement_ID.join(TkCore::INTERP._ip_id_).freeze
+ BarElement_ID[1].succ!
+ end
+ tk_send('bar', elem, keys)
+ Element.new(self, elem, :without_creating=>true)
+ end
+=end
+
+ def extents(item)
+ num_or_str(tk_send_without_enc('extents', item))
+ end
+
+ def invtransform(x, y)
+ list(tk_send_without_enc('invtransform', x, y))
+ end
+
+ def inside(x, y)
+ bool(tk_send_without_enc('inside', x, y))
+ end
+
+ def snap(output, keys={})
+ tk_send_without_enc('snap', *(hash_kv(keys, false) + output))
+ self
+ end
+
+ def transform(x, y)
+ list(tk_send_without_enc('transform', x, y))
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/htext.rb b/ext/tk/lib/tkextlib/blt/htext.rb
new file mode 100644
index 0000000000..0d9cb30185
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/htext.rb
@@ -0,0 +1,111 @@
+#
+# tkextlib/blt/htext.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/itemconfig.rb'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ class Htext<TkWindow
+ Htext_Var = TkVarAccess.new_hash('htext')
+ Htext_Widget = TkVarAccess.new('htext(widget)', :window)
+ Htext_File = TkVarAccess.new('htext(file)')
+ Htext_Line = TkVarAccess.new('htext(line)')
+
+ include TkItemConfigMethod
+ include Scrollable
+
+ TkCommandNames = ['::blt::htext'.freeze].freeze
+ WidgetClassName = 'Htext'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ alias window_cget itemcget
+ alias window_cget_strict itemcget_strict
+ alias window_configure itemconfigure
+ alias window_configuinfo itemconfiginfo
+ alias current_window_configuinfo current_itemconfiginfo
+
+ def __strval_optkeys
+ super() << 'filename'
+ end
+ private :__strval_optkeys
+
+ def append(win, keys={})
+ tk_send('append', _epath(win), keys)
+ self
+ end
+
+ def goto_line(idx)
+ tk_send_without_enc('gotoline', idx)
+ self
+ end
+ def current_line
+ number(tk_send_without_enc('gotoline'))
+ end
+
+ def index(str)
+ number(tk_send('index', str))
+ end
+
+ def line_pos(str)
+ tk_send('linepos', str)
+ end
+
+ def range(from=None, to=None)
+ tk_send_without_enc('range', from, to)
+ end
+
+ def scan_mark(pos)
+ tk_send_without_enc('scan', 'mark', pos)
+ self
+ end
+
+ def scan_dragto(pos)
+ tk_send_without_enc('scan', 'dragto', pos)
+ self
+ end
+
+ def search(pat, from=None, to=None)
+ num = number(tk_send('search', pat, from, to))
+ (num < 0)? nil: num
+ end
+
+ def selection_adjust(index)
+ tk_send_without_enc('selection', 'adjust', index)
+ self
+ end
+ def selection_clear()
+ tk_send_without_enc('selection', 'clear')
+ self
+ end
+ def selection_from(index)
+ tk_send_without_enc('selection', 'from', index)
+ self
+ end
+ def selection_line(index)
+ tk_send_without_enc('selection', 'line', index)
+ self
+ end
+ def selection_present()
+ bool(tk_send_without_enc('selection', 'present'))
+ end
+ def selection_range(first, last)
+ tk_send_without_enc('selection', 'range', first, last)
+ self
+ end
+ def selection_to(index)
+ tk_send_without_enc('selection', 'to', index)
+ self
+ end
+ def selection_word(index)
+ tk_send_without_enc('selection', 'word', index)
+ self
+ end
+
+ def windows(pat=None)
+ list(tk_send('windows', pat))
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/setup.rb b/ext/tk/lib/tkextlib/blt/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/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/blt/spline.rb b/ext/tk/lib/tkextlib/blt/spline.rb
new file mode 100644
index 0000000000..9f75a0b217
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/spline.rb
@@ -0,0 +1,23 @@
+#
+# tkextlib/blt/spline.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module Spline
+ extend TkCore
+
+ TkCommandNames = ['::blt::spline'.freeze].freeze
+
+ def self.natural(x, y, sx, sy)
+ tk_call('::blt::spline', 'natural', x, y, sx, sy)
+ end
+
+ def self.quadratic(x, y, sx, sy)
+ tk_call('::blt::spline', 'quadratic', x, y, sx, sy)
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/stripchart.rb b/ext/tk/lib/tkextlib/blt/stripchart.rb
new file mode 100644
index 0000000000..fe5afbb095
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/stripchart.rb
@@ -0,0 +1,74 @@
+#
+# tkextlib/blt/stripchart.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+require 'tkextlib/blt/component.rb'
+
+module Tk::BLT
+ class Stripchart < TkWindow
+ TkCommandNames = ['::blt::stripchart'.freeze].freeze
+ WidgetClassName = 'Stripchart'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ include PlotComponent
+ include GraphCommand
+
+ def __boolval_optkeys
+ ['bufferelements', 'buffergraph', 'invertxy']
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ ['text', 'label', 'title', 'file',
+ 'background', 'plotbackground']
+ end
+ private :__strval_optkeys
+
+=begin
+ BarElement_ID = ['blt_stripchart_bar'.freeze, '00000'.taint].freeze
+
+ def bar(elem=nil, keys={})
+ if elem.kind_of?(Hash)
+ keys = elem
+ elem = nil
+ end
+ unless elem
+ elem = BarElement_ID.join(TkCore::INTERP._ip_id_).freeze
+ BarElement_ID[1].succ!
+ end
+ tk_send('bar', elem, keys)
+ Element.new(self, elem, :without_creating=>true)
+ end
+=end
+
+ def extents(item)
+ num_or_str(tk_send_without_enc('extents', item))
+ end
+
+ def invtransform(x, y)
+ list(tk_send_without_enc('invtransform', x, y))
+ end
+
+ def inside(x, y)
+ bool(tk_send_without_enc('inside', x, y))
+ end
+
+ def metafile(file=None)
+ # Windows only
+ tk_send('metafile', file)
+ self
+ end
+
+ def snap(output, keys={})
+ tk_send_without_enc('snap', *(hash_kv(keys, false) + output))
+ self
+ end
+
+ def transform(x, y)
+ list(tk_send_without_enc('transform', x, y))
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/table.rb b/ext/tk/lib/tkextlib/blt/table.rb
new file mode 100644
index 0000000000..dfa10269ed
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/table.rb
@@ -0,0 +1,399 @@
+#
+# tkextlib/blt/table.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/itemconfig.rb'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module Table
+ include Tk
+ extend Tk
+ extend TkItemConfigMethod
+
+ TkCommandNames = ['::blt::table'.freeze].freeze
+
+ module TableContainer
+ def blt_table_add(*args)
+ Tk::BLT::Table.add(self, *args)
+ self
+ end
+
+ def blt_table_arrange()
+ Tk::BLT::Table.arrange(self)
+ self
+ end
+
+ def blt_table_cget(*args)
+ Tk::BLT::Table.cget(self, *args)
+ end
+ def blt_table_cget_strict(*args)
+ Tk::BLT::Table.cget_strict(self, *args)
+ end
+
+ def blt_table_configure(*args)
+ Tk::BLT::Table.configure(self, *args)
+ self
+ end
+
+ def blt_table_configinfo(*args)
+ Tk::BLT::Table.configinfo(self, *args)
+ end
+
+ def blt_table_current_configinfo(*args)
+ Tk::BLT::Table.current_configinfo(self, *args)
+ end
+
+ def blt_table_locate(x, y)
+ Tk::BLT::Table.locate(self, x, y)
+ end
+
+ def blt_table_delete(*args)
+ Tk::BLT::Table.delete(self, *args)
+ self
+ end
+
+ def blt_table_extents(item)
+ Tk::BLT::Table.extents(self, item)
+ end
+
+ def blt_table_insert(*args)
+ Tk::BLT::Table.insert(self, *args)
+ self
+ end
+
+ def blt_table_insert_before(*args)
+ Tk::BLT::Table.insert_before(self, *args)
+ self
+ end
+
+ def blt_table_insert_after(*args)
+ Tk::BLT::Table.insert_after(self, *args)
+ self
+ end
+
+ def blt_table_join(first, last)
+ Tk::BLT::Table.join(self, first, last)
+ self
+ end
+
+ def blt_table_save()
+ Tk::BLT::Table.save(self)
+ end
+
+ def blt_table_search(*args)
+ Tk::BLT::Table.search(self, *args)
+ end
+
+ def blt_table_split(*args)
+ Tk::BLT::Table.split(self, *args)
+ self
+ end
+
+ def blt_table_itemcget(*args)
+ Tk::BLT::Table.itemcget(self, *args)
+ end
+ def blt_table_itemcget_strict(*args)
+ Tk::BLT::Table.itemcget_strict(self, *args)
+ end
+
+ def blt_table_itemconfigure(*args)
+ Tk::BLT::Table.itemconfigure(self, *args)
+ self
+ end
+
+ def blt_table_itemconfiginfo(*args)
+ Tk::BLT::Table.itemconfiginfo(self, *args)
+ end
+
+ def blt_table_current_itemconfiginfo(*args)
+ Tk::BLT::Table.current_itemconfiginfo(self, *args)
+ end
+
+ def blt_table_iteminfo(item)
+ Tk::BLT::Table.iteminfo(self, item)
+ end
+ end
+ end
+end
+
+
+############################################
+class << Tk::BLT::Table
+ def __item_cget_cmd(id) # id := [ container, item ]
+ win = (id[0].kind_of?(TkWindow))? id[0].path: id[0].to_s
+ ['::blt::table', 'cget', win, id[1]]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id) # id := [ container, item, ... ]
+ container, *items = id
+ win = (container.kind_of?(TkWindow))? container.path: container.to_s
+ ['::blt::table', 'configure', win, *items]
+ end
+ private :__item_config_cmd
+
+ def __item_pathname(id)
+ win = (id[0].kind_of?(TkWindow))? id[0].path: id[0].to_s
+ win + ';'
+ end
+ private :__item_pathname
+
+ alias __itemcget itemcget
+ alias __itemcget_strict itemcget_strict
+ alias __itemconfigure itemconfigure
+ alias __itemconfiginfo itemconfiginfo
+ alias __current_itemconfiginfo current_itemconfiginfo
+
+ private :__itemcget, :__itemcget_strict
+ private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo
+
+ def __boolval_optkeys
+ super() << 'propagate'
+ end
+ private :__boolval_optkeys
+
+ def tagid(tag)
+ if tag.kind_of?(Array)
+ case tag[0]
+ when Integer
+ # [row, col]
+ tag.join(',')
+ when :c, :C, 'c', 'C', :r, :R, 'r', 'R'
+ # c0 or r1 or C*, and so on
+ tag.collect{|elem| elem.to_s}.join('')
+ else
+ tag
+ end
+ elsif tag.kind_of?(TkWindow)
+ _epath(tag)
+ else
+ tag
+ end
+ end
+
+ def tagid2obj(tagid)
+ tagid
+ end
+
+ ############################################
+
+ def cget(container, option)
+ __itemcget([container], option)
+ end
+ def cget_strict(container, option)
+ __itemcget_strict([container], option)
+ end
+
+ def configure(container, *args)
+ __itemconfigure([container], *args)
+ end
+
+ def configinfo(container, *args)
+ __itemconfiginfo([container], *args)
+ end
+
+ def current_configinfo(container, *args)
+ __current_itemconfiginfo([container], *args)
+ end
+
+ def itemcget(container, item, option)
+ __itemcget([container, tagid(item)], option)
+ end
+ def itemcget_strict(container, item, option)
+ __itemcget_strict([container, tagid(item)], option)
+ end
+
+ def itemconfigure(container, *args)
+ if args[-1].kind_of?(Hash)
+ # container, item, item, ... , hash_optkeys
+ keys = args.pop
+ fail ArgumentError, 'no item is given' if args.empty?
+ id = [container]
+ args.each{|item| id << tagid(item)}
+ __itemconfigure(id, keys)
+ else
+ # container, item, item, ... , option, value
+ val = args.pop
+ opt = args.pop
+ fail ArgumentError, 'no item is given' if args.empty?
+ id = [container]
+ args.each{|item| id << tagid(item)}
+ __itemconfigure(id, opt, val)
+ end
+ container
+ end
+
+ def itemconfiginfo(container, *args)
+ slot = args[-1]
+ if slot.kind_of?(String) || slot.kind_of?(Symbol)
+ slot = slot.to_s
+ if slot[0] == ?. || slot =~ /^\d+,\d+$/ || slot =~ /^(c|C|r|R)(\*|\d+)/
+ # widget || row,col || Ci or Ri
+ slot = nil
+ else
+ # option
+ slot = args.pop
+ end
+ else
+ slot = nil
+ end
+
+ fail ArgumentError, 'no item is given' if args.empty?
+
+ id = [container]
+ args.each{|item| id << tagid(item)}
+ __itemconfiginfo(id, slot)
+ end
+
+ def current_itemconfiginfo(container, *args)
+ slot = args[-1]
+ if slot.kind_of?(String) || slot.kind_of?(Symbol)
+ slot = slot.to_s
+ if slot[0] == ?. || slot =~ /^\d+,\d+$/ || slot =~ /^(c|C|r|R)(\*|\d+)/
+ # widget || row,col || Ci or Ri
+ slot = nil
+ else
+ # option
+ slot = args.pop
+ end
+ else
+ slot = nil
+ end
+
+ fail ArgumentError, 'no item is given' if args.empty?
+
+ id = [container]
+ args.each{|item| id << tagid(item)}
+ __current_itemconfiginfo(id, slot)
+ end
+
+ def info(container)
+ ret = {}
+ inf = list(tk_call('::blt::table', 'info', container))
+ until inf.empty?
+ opt = inf.slice!(0..1)
+ ret[opt[1..-1]] = opt[1]
+ end
+ ret
+ end
+
+ def iteminfo(container, item)
+ inf = list(tk_call('::blt::table', 'info', container, tagid(item)).chomp)
+
+ ret = []
+ until inf.empty? || (inf[0].kind_of?(String) && inf[0] =~ /^-/)
+ ret << inf.shift
+ end
+
+ if inf.length > 1
+ keys = {}
+ while inf.length > 1
+ opt = inf.slice!(0..1)
+ keys[opt[0][1..-1]] = opt[1]
+ end
+ ret << keys
+ end
+
+ ret
+ end
+
+ ############################################
+
+ def create_container(container)
+ tk_call('::blt::table', container)
+ begin
+ class << container
+ include Tk::BLT::Table::TableContainer
+ end
+ rescue
+ warn('fail to include TableContainer methods (frozen object?)')
+ end
+ container
+ end
+
+ def add(container, *args)
+ if args.empty?
+ tk_call('::blt::table', container)
+ else
+ args = args.collect{|arg|
+ if arg.kind_of?(TkWindow)
+ _epath(arg)
+ elsif arg.kind_of?(Array) # index
+ arg.join(',')
+ else
+ arg
+ end
+ }
+ tk_call('::blt::table', container, *args)
+ end
+ container
+ end
+
+ def arrange(container)
+ tk_call('::blt::table', 'arrange', container)
+ container
+ end
+
+ def delete(container, *args)
+ tk_call('::blt::table', 'delete', container, *args)
+ end
+
+ def extents(container, item)
+ ret = []
+ inf = list(tk_call('::blt::table', 'extents', container, item))
+ ret << inf.slice!(0..4) until inf.empty?
+ ret
+ end
+
+ def forget(*wins)
+ wins = wins.collect{|win| _epath(win)}
+ tk_call('::blt::table', 'forget', *wins)
+ end
+
+ def insert(container, *args)
+ tk_call('::blt::table', 'insert', container, *args)
+ end
+
+ def insert_before(container, *args)
+ tk_call('::blt::table', 'insert', container, '-before', *args)
+ end
+
+ def insert_after(container, *args)
+ tk_call('::blt::table', 'insert', container, '-after', *args)
+ end
+
+ def join(container, first, last)
+ tk_call('::blt::table', 'join', container, first, last)
+ end
+
+ def locate(container, x, y)
+ tk_call('::blt::table', 'locate', container, x, y)
+ end
+
+ def containers(arg={})
+ list(tk_call('::blt::table', 'containers', *hash_kv(arg)))
+ end
+
+ def containers_pattern(pat)
+ list(tk_call('::blt::table', 'containers', '-pattern', pat))
+ end
+
+ def containers_slave(win)
+ list(tk_call('::blt::table', 'containers', '-slave', win))
+ end
+
+ def save(container)
+ tk_call('::blt::table', 'save', container)
+ end
+
+ def search(container, keys={})
+ list(tk_call('::blt::table', 'containers', *hash_kv(keys)))
+ end
+
+ def split(container, *args)
+ tk_call('::blt::table', 'split', container, *args)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tabnotebook.rb b/ext/tk/lib/tkextlib/blt/tabnotebook.rb
new file mode 100644
index 0000000000..508fa2b82f
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tabnotebook.rb
@@ -0,0 +1,21 @@
+#
+# tkextlib/blt/tabnotebook.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+require 'tkextlib/blt/tabset.rb'
+
+module Tk::BLT
+ class Tabnotebook < Tabset
+ TkCommandNames = ['::blt::tabnotebook'.freeze].freeze
+ WidgetClassName = 'Tabnotebook'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def get_tab(index)
+ Tk::BLT::Tabset::Tab.id2obj(tk_send_without_enc('id', tagindex(index)))
+ end
+ alias get_id get_tab
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tabset.rb b/ext/tk/lib/tkextlib/blt/tabset.rb
new file mode 100644
index 0000000000..ca81ad8f95
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tabset.rb
@@ -0,0 +1,430 @@
+#
+# tkextlib/blt/tabset.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ class Tabset < TkWindow
+ class Tab < TkObject
+ include TkTreatItemFont
+
+ TabID_TBL = TkCore::INTERP.create_table
+
+ (TabsetTab_ID = ['blt_tabset_tab'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TabID_TBL.mutex.synchronize{ TabID_TBL.clear }
+ }
+
+ def self.id2obj(tabset, id)
+ tpath = tabset.path
+ TabID_TBL.mutex.synchronize{
+ if TabID_TBL[tpath]
+ TabID_TBL[tpath][id]? TabID_TBL[tpath]: id
+ else
+ id
+ end
+ }
+ end
+
+ def self.new(parent, pos=nil, name=nil, keys={})
+ if pos.kind_of?(Hash)
+ keys = pos
+ name = nil
+ pos = nil
+ end
+ if name.kind_of?(Hash)
+ keys = name
+ name = nil
+ end
+ obj = nil
+ TabID_TBL.mutex.synchronize{
+ if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name]
+ obj = TabID_TBL[parent.path][name]
+ obj.configure if keys && ! keys.empty?
+ else
+ (obj = self.allocate).instance_eval{
+ initialize(parent, pos, name, keys)
+ TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
+ TabID_TBL[@tpath][@id] = self
+ }
+ end
+ }
+ obj
+ end
+
+ def initialize(parent, pos, name, keys)
+ @t = parent
+ @tpath = parent.path
+ if name
+ @path = @id = name
+ unless (list(tk_call(@tpath, 'tab', 'names', @id)).empty?)
+ if pos
+ idx = tk_call(@tpath, 'index', '-name', @id)
+ if pos.to_s == 'end'
+ tk_call(@tpath, idx, 'moveto', 'after', 'end')
+ else
+ tk_call(@tpath, idx, 'moveto', 'before', pos)
+ end
+ end
+ tk_call(@tpath, 'tab', 'configure', @id, keys)
+ else
+ pos = 'end' unless pos
+ tk_call(@tpath, 'insert', pos, @id, keys)
+ end
+ else
+ TabsetTab_ID.mutex.synchronize{
+ @path = @id = TabsetTab_ID.join(TkCore::INTERP._ip_id_)
+ TabsetTab_ID[1].succ!
+ }
+ pos = 'end' unless pos
+ tk_call(@tpath, 'insert', pos, @id, keys)
+ end
+ end
+
+ #def bind(context, cmd=Proc.new, *args)
+ # @t.tab_bind(@id, context, cmd, *args)
+ # self
+ #end
+ def bind(context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ @t.tab_bind(@id, context, cmd, *args)
+ self
+ end
+ #def bind_append(context, cmd=Proc.new, *args)
+ # @t.tab_bind_append(@id, context, cmd, *args)
+ # self
+ #end
+ def bind_append(context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ @t.tab_bind_append(@id, context, cmd, *args)
+ self
+ end
+ def bind_remove(context)
+ @t.tab_bind_remove(@id, context)
+ self
+ end
+ def bindinfo(context=nil)
+ @t.tab_bindinfo(@id, context)
+ end
+
+ def cget(*args)
+ @t.tab_cget(@id, *args)
+ end
+ def cget_strict(*args)
+ @t.tab_cget_strict(@id, *args)
+ end
+ def configure(*args)
+ @t.tab_configure(@id, *args)
+ end
+ def configinfo(*args)
+ @t.tab_configinfo(@id, *args)
+ end
+ def current_configinfo(*args)
+ @t.current_tab_configinfo(@id, *args)
+ end
+
+ def delete()
+ @t.delete(@id)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@tpath].delete(@id)
+ }
+ self
+ end
+
+ def get_name()
+ @id.dup
+ end
+
+ def focus()
+ @t.focus(self.index)
+ end
+
+ def index()
+ @t.index_name(@id)
+ end
+
+ def invoke()
+ @t.invoke(self.index)
+ end
+
+ def move_before(idx)
+ @t.move_before(self.index, idx)
+ end
+ def move_after(idx)
+ @t.move_after(self.index, idx)
+ end
+
+ def perforation_highlight(mode)
+ @t.perforation.highlight(self.index, mode)
+ end
+ def perforation_invoke()
+ @t.perforation.invoke(self.index)
+ end
+
+ def see()
+ @t.see(self.index)
+ end
+
+ def tearoff(name=None)
+ @t.tab_tearoff(self.index, *args)
+ end
+ end
+
+ ########################################
+
+ class NamedTab < Tab
+ def self.new(parent, name)
+ super(parent, nil, name, {})
+ end
+ end
+
+ ########################################
+
+ include X_Scrollable
+ include TkItemConfigMethod
+
+ TkCommandNames = ['::blt::tabset'.freeze].freeze
+ WidgetClassName = 'Tabset'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __destroy_hook__
+ Tk::BLT::Tabset::Tab::TabID_TBL.mutex.synchronize{
+ Tk::BLT::Tabset::Tab::TabID_TBL.delete(@path)
+ }
+ end
+
+ ########################################
+
+ def __boolval_optkeys
+ super() << 'samewidth' << 'tearoff'
+ end
+ private :__strval_optkeys
+
+ def __strval_optkeys
+ super() << 'tabbackground' << 'tabforeground'
+ end
+ private :__strval_optkeys
+
+ def __item_cget_cmd(id)
+ [self.path, 'tab', 'cget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'tab', 'configure', id]
+ end
+ private :__item_config_cmd
+
+ def __item_pathname(tagOrId)
+ if tagOrId.kind_of?(Tk::BLT::Tabset::Tab)
+ self.path + ';' + tagOrId.id.to_s
+ else
+ self.path + ';' + tagOrId.to_s
+ end
+ end
+ private :__item_pathname
+
+ alias tab_cget itemcget
+ alias tab_cget_strict itemcget_strict
+ alias tab_configure itemconfigure
+ alias tab_configinfo itemconfiginfo
+ alias current_tab_configinfo current_itemconfiginfo
+
+ def __item_strval_optkeys(id)
+ super(id) << 'shadow'
+ end
+ private :__item_strval_optkeys
+
+ def tagid(tab)
+ if tab.kind_of?(Tk::BLT::Tabset::Tab)
+ tab.id
+ else
+ tab
+ end
+ end
+
+ def tagindex(tab)
+ if tab.kind_of?(Tk::BLT::Tabset::Tab)
+ tab.index
+ else
+ tab
+ end
+ end
+
+ ########################################
+
+ def activate(index)
+ tk_send('activate', tagindex(index))
+ self
+ end
+ alias highlight activate
+
+ #def tabbind(tag, context, cmd=Proc.new, *args)
+ # _bind([path, "bind", tagid(tag)], context, cmd, *args)
+ # self
+ #end
+ def tabbind(tag, context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, "bind", tagid(tag)], context, cmd, *args)
+ self
+ end
+ #def tabbind_append(tag, context, cmd=Proc.new, *args)
+ # _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
+ # self
+ #end
+ def tabbind_append(tag, context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
+ self
+ end
+ def tabbind_remove(tag, context)
+ _bind_remove([path, "bind", tagid(tag)], context)
+ self
+ end
+ def tabbindinfo(tag, context=nil)
+ _bindinfo([path, "bind", tagid(tag)], context)
+ end
+
+ def delete(first, last=None)
+ tk_send('delete', tagindex(first), tagindex(last))
+ if first.kind_of?(Tk::BLT::Tabset::Tab)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@path].delete(first.id)
+ }
+ end
+ # middle tabs of the range are unknown
+ if last.kind_of?(Tk::BLT::Tabset::Tab)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@path].delete(last.id)
+ }
+ end
+ self
+ end
+
+ def focus(index)
+ tk_send('focus', tagindex(index))
+ self
+ end
+
+ def get_tab(index)
+ Tk::BLT::Tabset::Tab.id2obj(tk_send_without_enc('get', tagindex(index)))
+ end
+
+ def index(str)
+ num_or_str(tk_send('index', str))
+ end
+ def index_name(tab)
+ num_or_str(tk_send('index', '-mame', tagid(tab)))
+ end
+
+ def insert(pos, tab, keys={})
+ Tk::BLT::Tabset::Tab.new(self, tagindex(pos), tagid(tab), keys)
+ end
+
+ def invoke(index)
+ tk_send('invoke', tagindex(index))
+ end
+
+ def move_before(index, base_idx)
+ tk_send('move', tagindex(index), 'before', tagindex(base_idx))
+ self
+ end
+ def move_after(index, base_idx)
+ tk_send('move', tagindex(index), 'after', tagindex(base_idx))
+ self
+ end
+
+ def nearest(x, y)
+ Tk::BLT::Tabset::Tab.id2obj(num_or_str(tk_send_without_enc('nearest', x, y)))
+ end
+
+ def perforation_highlight(index, mode)
+ tk_send('perforation', 'highlight', tagindex(index), mode)
+ self
+ end
+ def perforation_invoke(index)
+ tk_send('perforation', 'invoke', tagindex(index))
+ end
+
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send_without_enc('scan', 'dragto', x, y)
+ self
+ end
+
+ def see(index)
+ tk_send('see', tagindex(index))
+ self
+ end
+
+ def size()
+ number(tk_send_without_enc('size'))
+ end
+
+ def select(index)
+ tk_send('select', tagindex(index))
+ self
+ end
+
+ def tab_names(pat=None)
+ simplelist(tk_send('tab', 'names', pat)).collect{|name|
+ Tk::BLT::Tabset::Tab.id2obj(name)
+ }
+ end
+
+ def tab_tearoff(index, name=None)
+ window(tk_send('tab', 'tearoff', tagindex(index), name))
+ end
+
+ def xscrollcommand(cmd=Proc.new)
+ configure_cmd 'scrollcommand', cmd
+ self
+ end
+ alias scrollcommand xscrollcommand
+
+ def xview(*index)
+ if index.empty?
+ list(tk_send_without_enc('view'))
+ else
+ tk_send_without_enc('view', *index)
+ self
+ end
+ end
+ alias view xview
+ alias view_moveto xview_moveto
+ alias view_scroll xview_scroll
+
+ alias scrollbar xscrollbar
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/ted.rb b/ext/tk/lib/tkextlib/blt/ted.rb
new file mode 100644
index 0000000000..670265fc78
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/ted.rb
@@ -0,0 +1,65 @@
+#
+# tkextlib/blt/ted.rb
+#
+# *** This is alpha version, because there is no document on BLT. ***
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module Ted
+ extend TkCore
+
+ TkCommandNames = ['::blt::ted'.freeze].freeze
+
+ ##############################
+
+ extend TkItemConfigMethod
+
+ class << self
+ def __item_cget_cmd(id)
+ ['::blt::ted', 'cget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ ['::blt::ted', 'configure', id]
+ end
+ private :__item_config_cmd
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ def cget(master, option)
+ itemcget(master, option)
+ end
+ def cget_strict(master, option)
+ itemcget_strict(master, option)
+ end
+ def configure(master, slot, value=None)
+ itemconfigure(master, slot, value)
+ end
+ def configinfo(master, slot=nil)
+ itemconfiginfo(master, slot)
+ end
+ def current_configinfo(master, slot=nil)
+ current_itemconfiginfo(master, slot)
+ end
+ end
+
+ ##############################
+
+ def self.edit(master, *args)
+ tk_call('::blt::ted', 'edit', master, *args)
+ end
+ def self.rep(master, *args)
+ tk_call('::blt::ted', 'rep', master, *args)
+ end
+ def self.select(master, *args)
+ tk_call('::blt::ted', 'select', master, *args)
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tile.rb b/ext/tk/lib/tkextlib/blt/tile.rb
new file mode 100644
index 0000000000..5f5242f299
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tile.rb
@@ -0,0 +1,21 @@
+#
+# tkextlib/blt/tile.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module Tile
+ autoload :Button, 'tkextlib/blt/tile/button.rb'
+ autoload :CheckButton, 'tkextlib/blt/tile/checkbutton.rb'
+ autoload :Checkbutton, 'tkextlib/blt/tile/checkbutton.rb'
+ autoload :Radiobutton, 'tkextlib/blt/tile/radiobutton.rb'
+ autoload :RadioButton, 'tkextlib/blt/tile/radiobutton.rb'
+ autoload :Frame, 'tkextlib/blt/tile/frame.rb'
+ autoload :Label, 'tkextlib/blt/tile/label.rb'
+ autoload :Scrollbar, 'tkextlib/blt/tile/scrollbar.rb'
+ autoload :Toplevel, 'tkextlib/blt/tile/toplevel.rb'
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tile/button.rb b/ext/tk/lib/tkextlib/blt/tile/button.rb
new file mode 100644
index 0000000000..2e0863cfbe
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tile/button.rb
@@ -0,0 +1,16 @@
+#
+# tkextlib/blt/tile/button.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/button'
+require 'tkextlib/blt/tile.rb'
+
+module Tk::BLT
+ module Tile
+ class Button < Tk::Button
+ TkCommandNames = ['::blt::tile::button'.freeze].freeze
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb b/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
new file mode 100644
index 0000000000..da230b5925
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
@@ -0,0 +1,17 @@
+#
+# tkextlib/blt/tile/checkbutton.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/checkbutton'
+require 'tkextlib/blt/tile.rb'
+
+module Tk::BLT
+ module Tile
+ class CheckButton < Tk::CheckButton
+ TkCommandNames = ['::blt::tile::checkbutton'.freeze].freeze
+ end
+ Checkbutton = CheckButton
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tile/frame.rb b/ext/tk/lib/tkextlib/blt/tile/frame.rb
new file mode 100644
index 0000000000..5434af4b72
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tile/frame.rb
@@ -0,0 +1,16 @@
+#
+# tkextlib/blt/tile/frame.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/blt/tile.rb'
+
+module Tk::BLT
+ module Tile
+ class Frame < Tk::Frame
+ TkCommandNames = ['::blt::tile::frame'.freeze].freeze
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tile/label.rb b/ext/tk/lib/tkextlib/blt/tile/label.rb
new file mode 100644
index 0000000000..f370c1403b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tile/label.rb
@@ -0,0 +1,16 @@
+#
+# tkextlib/blt/tile/label.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/label'
+require 'tkextlib/blt/tile.rb'
+
+module Tk::BLT
+ module Tile
+ class Label < Tk::Label
+ TkCommandNames = ['::blt::tile::label'.freeze].freeze
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb b/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
new file mode 100644
index 0000000000..814f9a5cc4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
@@ -0,0 +1,17 @@
+#
+# tkextlib/blt/tile/radiobutton.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/radiobutton'
+require 'tkextlib/blt/tile.rb'
+
+module Tk::BLT
+ module Tile
+ class RadioButton < Tk::RadioButton
+ TkCommandNames = ['::blt::tile::radiobutton'.freeze].freeze
+ end
+ Radiobutton = RadioButton
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb b/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
new file mode 100644
index 0000000000..2ae871d518
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
@@ -0,0 +1,16 @@
+#
+# tkextlib/blt/tile/scrollbar.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/scrollbar'
+require 'tkextlib/blt/tile.rb'
+
+module Tk::BLT
+ module Tile
+ class Scrollbar < Tk::Scrollbar
+ TkCommandNames = ['::blt::tile::scrollbar'.freeze].freeze
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tile/toplevel.rb b/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
new file mode 100644
index 0000000000..76d5f86b1b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
@@ -0,0 +1,16 @@
+#
+# tkextlib/blt/tile/toplevel.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/toplevel'
+require 'tkextlib/blt/tile.rb'
+
+module Tk::BLT
+ module Tile
+ class Toplevel < Tk::Toplevel
+ TkCommandNames = ['::blt::tile::toplevel'.freeze].freeze
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/tree.rb b/ext/tk/lib/tkextlib/blt/tree.rb
new file mode 100644
index 0000000000..77b85f1717
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/tree.rb
@@ -0,0 +1,1058 @@
+#
+# tkextlib/blt/tree.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ class Tree < TkObject
+ TkCommandNames = ['::blt::tree'.freeze].freeze
+
+ ###################################
+
+ class Node < TkObject
+ TreeNodeID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ TreeNodeID_TBL.mutex.synchronize{
+ if TreeNodeID_TBL[tpath]
+ if TreeNodeID_TBL[tpath][id]
+ TreeNodeID_TBL[tpath][id]
+ else
+ begin
+ # self.new(tree, nil, 'node'=>Integer(id))
+ id = Integer(id)
+ if bool(tk_call(@tpath, 'exists', id))
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = tpath
+ @path = @id = id
+ TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
+ TreeNodeID_TBL[@tpath][@id] = self
+ }
+ obj
+ else
+ id
+ end
+ rescue
+ id
+ end
+ end
+ else
+ id
+ end
+ }
+ end
+
+ def self.new(tree, parent, keys={})
+ keys = _symbolkey2str(keys)
+ tpath = tree.path
+
+ TreeNodeID_TBL.mutex.synchronize{
+ TreeNodeID_TBL[tpath] ||= {}
+ if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
+ keys.delete('node')
+ tk_call(tree.path, 'move', id, parent, keys) if parent
+ return obj
+ end
+
+ (obj = self.allocate).instance_eval{
+ initialize(tree, parent, keys)
+ TreeNodeID_TBL[tpath][@id] = self
+ }
+ obj
+ }
+ end
+
+ def initialize(tree, parent, keys={})
+ @parent = @tree = tree
+ @tpath = @parent.path
+
+ if (id = keys['node']) && bool(tk_call(@tpath, 'exists', id))
+ @path = @id = id
+ keys.delete('node')
+ tk_call(@tpath, 'move', @id, parent, keys) if parent
+ else
+ parent = tk_call(@tpath, 'root') unless parent
+ @path = @id = tk_call(@tpath, 'insert', parent, keys)
+ end
+ end
+
+ def id
+ @id
+ end
+
+ def apply(keys={})
+ @tree.apply(@id, keys)
+ self
+ end
+
+ def children()
+ @tree.children(@id)
+ end
+
+ def copy(parent, keys={})
+ @tree.copy(@id, parent, keys)
+ end
+ def copy_to(dest_tree, parent, keys={})
+ @tree.copy_to(@id, dest_tree, parent, keys)
+ end
+
+ def degree()
+ @tree.degree(@id)
+ end
+
+ def delete()
+ @tree.delete(@id)
+ self
+ end
+
+ def depth()
+ @tree.depth(@id)
+ end
+
+ def dump()
+ @tree.dump(@id)
+ end
+
+ def dump_to_file(file)
+ @tree.dump_to_file(@id, file)
+ self
+ end
+
+ def exist?(keys={})
+ @tree.exist?(@id, keys)
+ end
+
+ def find(keys={})
+ @tree.find(@id, keys)
+ end
+
+ def find_child(label)
+ @tree.find_child(@id, label)
+ end
+
+ def first_child()
+ @tree.first_child(@id)
+ end
+
+ def get()
+ @tree.get(@id)
+ end
+ def get_value(key, default_val=None)
+ @tree.get_value(@id, key, default_val)
+ end
+
+ def index()
+ @tree.index(@id)
+ end
+
+ def leaf?()
+ @tree.leaf?(@id)
+ end
+ def link?()
+ @tree.link?(@id)
+ end
+ def root?()
+ @tree.root?(@id)
+ end
+
+ def keys()
+ @tree.keys(@id)
+ end
+
+ def label(text = nil)
+ @tree.label(@id, nil)
+ end
+ def label=(text)
+ @tree.label(@id, text)
+ end
+
+ def last_child()
+ @tree.last_child(@id)
+ end
+
+ def move(dest, keys={})
+ @tree.keys(@id, dest, keys)
+ self
+ end
+
+ def next()
+ @tree.next(@id)
+ end
+
+ def next_sibling()
+ @tree.next_sibling(@id)
+ end
+
+ def parent()
+ @tree.parent(@id)
+ end
+
+ def fullpath()
+ @tree.fullpath(@id)
+ end
+
+ def position()
+ @tree.position(@id)
+ end
+
+ def previous()
+ @tree.previous(@id)
+ end
+
+ def prev_sibling()
+ @tree.prev_sibling(@id)
+ end
+
+ def restore(str, keys={})
+ @tree.restore(@id, str, keys)
+ self
+ end
+ def restore_overwrite(str, keys={})
+ @tree.restore_overwrite(@id, str, keys)
+ self
+ end
+
+ def restore_from_file(file, keys={})
+ @tree.restore_from_file(@id, file, keys)
+ self
+ end
+ def restore_overwrite_from_file(file, keys={})
+ @tree.restore_overwrite_from_file(@id, file, keys)
+ self
+ end
+
+ def root()
+ @tree.root(@id)
+ self
+ end
+
+ def set(data)
+ @tree.set(@id, data)
+ self
+ end
+
+ def size()
+ @tree.size(@id)
+ end
+
+ def sort(keys={})
+ @tree.sort(@id, keys)
+ self
+ end
+
+ def type(key)
+ @tree.type(@id, key)
+ end
+
+ def unset(*keys)
+ @tree.unset(@id, *keys)
+ self
+ end
+
+ def values(key=None)
+ @tree.values(@id, key)
+ end
+ end
+
+ ###################################
+
+ class Tag < TkObject
+ TreeTagID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear }
+ }
+
+ (TreeTag_ID = ['blt_tree_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ TreeTagID_TBL.mutex.synchronize{
+ if TreeTagID_TBL[tpath]
+ if TreeTagID_TBL[tpath][id]
+ TreeTagID_TBL[tpath][id]
+ else
+ begin
+ # self.new(tree, id)
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = id.dup.freeze if id
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ obj
+ rescue
+ id
+ end
+ end
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(tree, tag_str = nil)
+ @parent = @tree = tree
+ @tpath = @parent.path
+
+ if tag_str
+ @path = @id = tag_str.dup.freeze
+ else
+ TreeTag_ID.mutex.synchronize{
+ @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_)
+ TreeTag_ID[1].succ!
+ }
+ end
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ end
+
+ def id
+ @id
+ end
+
+ def add(*nodes)
+ tk_call(@tpath, 'tag', 'add', @id, *nodes)
+ self
+ end
+
+ def delete(*nodes)
+ tk_call(@tpath, 'tag', 'delete', @id, *nodes)
+ self
+ end
+
+ def forget()
+ tk_call(@tpath, 'tag', 'forget', @id)
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@tpath].delete(@id)
+ }
+ self
+ end
+
+ def nodes()
+ simplelist(tk_call(@tpath, 'tag', 'nodes', @id)).collect{|node|
+ Tk::BLT::Tree::Node.id2obj(@path, node)
+ }
+ end
+
+ def set(node)
+ tk_call(@tpath, 'tag', 'set', node, @id)
+ self
+ end
+
+ def unset(node)
+ tk_call(@tpath, 'tag', 'unset', node, @id)
+ self
+ end
+ end
+
+ ###################################
+
+ class Notify < TkObject
+ NotifyID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ NotifyID_TBL.mutex.synchronize{ NotifyID_TBL.clear }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ NotifyID_TBL.mutex.synchronize{
+ if NotifyID_TBL[tpath]
+ if NotifyID_TBL[tpath][id]
+ NotifyID_TBL[tpath][id]
+ else
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = id
+ NotifyID_TBL[@tpath] ||= {}
+ NotifyID_TBL[@tpath][@id] = self
+ }
+ obj
+ end
+ else
+ return id
+ end
+ }
+ end
+
+ def self.new(tree, *args, &b)
+ NotifyID_TBL.mutex.synchronize{
+ if tree.kind_of?(Array)
+ # not create
+ tpath = tree[0].path
+ NotifyID_TBL[tpath] ||= {}
+ unless (obj = NotifyID_TBL[tpath][tree[1]])
+ (NotifyID_TBL[tpath][tree[1]] =
+ obj = self.allocate).instance_eval{
+ @parent = @tree = tree[0]
+ @tpath = @parent.path
+ @path = @id = tree[1]
+ }
+ end
+ return obj
+ end
+
+ (obj = self.allocate).instance_eval{
+ initialize(tree, *args, &b)
+ NotifyID_TBL[@tpath] ||= {}
+ NotifyID_TBL[@tpath][@id] = self
+ }
+ return obj
+ }
+ end
+
+ def initialize(tree, *args, &b)
+ @parent = @tree = tree
+ @tpath = @parent.path
+
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0])
+ cmd = args.shift
+ # elsif args[-1].kind_of?(Proc) || args[-1].kind_of?(Method)
+ elsif TkComm._callback_entry?(args[-1])
+ cmd = args.pop
+ elsif b
+ cmd = Proc.new(&b)
+ else
+ fail ArgumentError, "lack of 'command' argument"
+ end
+
+ args = args.collect{|arg| '-' << arg.to_s}
+
+ args << proc{|id, type|
+ cmd.call(Tk::BLT::Tree::Node.id2obj(@tree, id),
+ ((type[0] == ?-)? type[1..-1]: type))
+ }
+
+ @path = @id = tk_call(@tpath, 'notify', 'create', *args)
+ end
+
+ def id
+ @id
+ end
+
+ def delete()
+ tk_call(@tpath, 'notify', 'delete', @id)
+ NotifyID_TBL.mutex.synchronize{
+ NotifyID_TBL[@tpath].delete(@id)
+ }
+ self
+ end
+
+ def info()
+ lst = simplelist(tk_call(@tpath, 'notify', 'info', id))
+ lst[0] = Tk::BLT::Tree::Notify.id2obj(@tree, lst[0])
+ lst[1] = simplelist(lst[1]).collect{|flag| flag[1..-1]}
+ lst[2] = tk_tcl2ruby(lst[2])
+ lst
+ end
+ end
+
+ ###################################
+
+ class Trace < TkObject
+ TraceID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ TraceID_TBL.mutex.synchronize{ TraceID_TBL.clear }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ TraceID_TBL.mutex.synchronize{
+ if TraceID_TBL[tpath]
+ if TraceID_TBL[tpath][id]
+ TraceID_TBL[tpath][id]
+ else
+ begin
+ # self.new([tree, id])
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = node # == traceID
+ TraceID_TBL[@tpath] ||= {}
+ TraceID_TBL[@tpath][@id] = self
+ }
+ obj
+ rescue
+ id
+ end
+ end
+ else
+ id
+ end
+ }
+ end
+
+ def self.new(tree, *args, &b)
+ TraceID_TBL.mutex.synchronize{
+ if tree.kind_of?(Array)
+ # not create
+ tpath = tree[0].path
+ TraceID_TBL[tpath] ||= {}
+ unless (obj = TraceID_TBL[tpath][tree[1]])
+ (TraceID_TBL[tpath][tree[1]] =
+ obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = tree[1] # == traceID
+ }
+ end
+ return obj
+ end
+
+ # super(true, tree, *args, &b)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, *args, &b)
+ TraceID_TBL[@tpath] ||= {}
+ TraceID_TBL[@tpath][@id] = self
+ }
+ return obj
+ }
+ end
+
+ def initialize(tree, node, key, opts, cmd=nil, &b)
+ @parent = @tree = tree
+ @tpath = @parent.path
+
+ if !cmd
+ if b
+ cmd = Proc.new(&b)
+ else
+ fail ArgumentError, "lack of 'command' argument"
+ end
+ end
+
+ @path = @id = tk_call(@tpath, 'trace', 'create', node, key, opts,
+ proc{|t, id, k, ops|
+ tobj = Tk::BLT::Tree.id2obj(t)
+ if tobj.kind_of?(Tk::BLT::Tree)
+ nobj = Tk::BLT::Tree::Node.id2obj(tobj, id)
+ else
+ nobj = id
+ end
+ cmd.call(tobj, nobj, k, ops)
+ })
+ end
+
+ def id
+ @id
+ end
+
+ def delete()
+ tk_call(@tpath, 'trace', 'delete', @id)
+ TraceID_TBL.mutex.synchronize{
+ TraceID_TBL[tpath].delete(@id)
+ }
+ self
+ end
+
+ def info()
+ lst = simplelist(tk_call(@tpath, 'trace', 'info', id))
+ lst[0] = Tk::BLT::Tree::Trace.id2obj(@tree, lst[0])
+ lst[2] = simplelist(lst[2])
+ lst[3] = tk_tcl2ruby(lst[3])
+ lst
+ end
+ end
+
+ ###################################
+
+ TreeID_TBL = TkCore::INTERP.create_table
+
+ (Tree_ID = ['blt_tree'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ def __keyonly_optkeys
+ {
+ # apply / find command
+ 'invert'=>nil, 'leafonly'=>nil, 'nocase'=>nil,
+
+ # apply / find / sort command
+ 'path'=>nil,
+
+ # copy / restore / restorefile command
+ 'overwrite'=>nil,
+
+ # copy command
+ 'recurse'=>nil, 'tags'=>nil,
+
+ # sort command
+ 'ascii'=>nil, 'decreasing'=>nil, 'disctionary'=>nil,
+ 'integer'=>nil, 'real'=>nil, 'recurse'=>nil, 'reorder'=>nil,
+ }
+ end
+
+ def self.id2obj(id)
+ TreeID_TBL.mutex.synchronize{
+ TreeID_TBL[id]? TreeID_TBL[id]: id
+ }
+ end
+
+ def self.names(pat = None)
+ simplelist(tk_call('::blt::tree', 'names', pat)).collect{|name|
+ id2obj(name)
+ }
+ end
+
+ def self.destroy(*names)
+ tk_call('::blt::tree', 'destroy',
+ *(names.collect{|n| (n.kind_of?(Tk::BLT::Tree))? n.id: n }) )
+ end
+
+ def self.new(name = nil)
+ TreeID_TBL.mutex.synchronize{
+ if name && TreeID_TBL[name]
+ TreeID_TBL[name]
+ else
+ (obj = self.allocate).instance_eval{
+ initialize(name)
+ TreeID_TBL[@id] = self
+ }
+ obj
+ end
+ }
+ end
+
+ def initialzie(name = nil)
+ if name
+ @path = @id = name
+ else
+ Tree_ID.mutex.synchronize{
+ @path = @id = Tree_ID.join(TkCore::INTERP._ip_id_)
+ Tree_ID[1].succ!
+ }
+ end
+
+ tk_call('::blt::tree', 'create', @id)
+ end
+
+ def __destroy_hook__
+ Tk::BLT::Tree::Node::TreeNodeID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Node::TreeNodeID_TBL.delete(@path)
+ }
+ Tk::BLT::Tree::Tag::TreeTagID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Tag::TreeTagID_TBL.delete(@path)
+ }
+ Tk::BLT::Tree::Notify::NotifyID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Notify::NotifyID_TBL.delete(@path)
+ }
+ Tk::BLT::Tree::Trace::TraceID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Trace::TraceID_TBL.delete(@path)
+ }
+ end
+
+ def tagid(tag)
+ if tag.kind_of?(Tk::BLT::Tree::Node) ||
+ tag.kind_of?(Tk::BLT::Tree::Tag) ||
+ tag.kind_of?(Tk::BLT::Tree::Notify) ||
+ tag.kind_of?(Tk::BLT::Tree::Trace)
+ tag.id
+ else
+ tag # maybe an Array of configure paramters
+ end
+ end
+
+ def destroy()
+ tk_call('::blt::tree', 'destroy', @id)
+ self
+ end
+
+ def ancestor(node1, node2)
+ Tk::BLT::Tree::Node.id2obj(self, tk_call('::blt::tree', 'ancestor',
+ tagid(node1), tagid(node2)))
+ end
+
+ def apply(node, keys={})
+ tk_call('::blt::tree', 'apply', tagid(node), __conv_keyonly_opts(keys))
+ self
+ end
+
+ def attach(tree_obj)
+ tk_call('::blt::tree', 'attach', tree_obj)
+ self
+ end
+
+ def children(node)
+ simplelist(tk_call('::blt::tree', 'children', tagid(node))).collect{|n|
+ Tk::BLT::Tree::Node.id2obj(self, n)
+ }
+ end
+
+ def copy(src, parent, keys={})
+ id = tk_call('::blt::tree', 'copy', tagid(src), tagid(parent),
+ __conv_keyonly_opts(keys))
+ Tk::BLT::Tree::Node.new(self, nil, 'node'=>id)
+ end
+ def copy_to(src, dest_tree, parent, keys={})
+ return copy(src, parent, keys={}) unless dest_tree
+
+ id = tk_call('::blt::tree', 'copy', tagid(src), dest_tree,
+ tagid(parent), __conv_keyonly_opts(keys))
+ Tk::BLT::Tree::Node.new(dest_tree, nil, 'node'=>id)
+ end
+
+ def degree(node)
+ number(tk_call('::blt::tree', 'degree', tagid(node)))
+ end
+
+ def delete(*nodes)
+ tk_call('::blt::tree', 'delete', *(nodes.collect{|node| tagid(node)}))
+ Tk::BLT::Tree::Node::TreeNodeID_TBL.mutex.synchronize{
+ nodes.each{|node|
+ if node.kind_of?(Tk::BLT::Tree::Node)
+ Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.id)
+ else
+ Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.to_s)
+ end
+ }
+ }
+ self
+ end
+
+ def depth(node)
+ number(tk_call('::blt::tree', 'depth', tagid(node)))
+ end
+
+ def dump(node)
+ simplelist(tk_call('::blt::tree', 'dump', tagid(node))).collect{|n|
+ simplelist(n)
+ }
+ end
+
+ def dump_to_file(node, file)
+ tk_call('::blt::tree', 'dumpfile', tagid(node), file)
+ self
+ end
+
+ def exist?(node, key=None)
+ bool(tk_call('::blt::tree', 'exists', tagid(node), key))
+ end
+
+ def find(node, keys={})
+ simplelist(tk_call('::blt::tree', 'find', tagid(node),
+ __conv_keyonly_opts(keys))).collect{|n|
+ Tk::BLT::Tree::Node.id2obj(self, n)
+ }
+ end
+
+ def find_child(node, label)
+ ret = tk_call('::blt::tree', 'findchild', tagid(node), label)
+ (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
+ end
+
+ def first_child(node)
+ ret = tk_call('::blt::tree', 'firstchild', tagid(node))
+ (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
+ end
+
+ def get(node)
+ Hash[*simplelist(tk_call('::blt::tree', 'get', tagid(node)))]
+ end
+ def get_value(node, key, default_val=None)
+ tk_call('::blt::tree', 'get', tagid(node), key, default_val)
+ end
+
+ def index(node)
+ Tk::BLT::Tree::Node.id2obj(self,
+ tk_call('::blt::tree', 'index', tagid(node)))
+ end
+
+ def insert(parent, keys={})
+ id = tk_call('::blt::tree', 'insert', tagid(parent), keys)
+ Tk::BLT::Tree::Node.new(self, nil, 'node'=>id)
+ end
+
+ def ancestor?(node1, node2)
+ bool(tk_call('::blt::tree', 'is', 'ancestor',
+ tagid(node1), tagid(node2)))
+ end
+ def before?(node1, node2)
+ bool(tk_call('::blt::tree', 'is', 'before',
+ tagid(node1), tagid(node2)))
+ end
+ def leaf?(node)
+ bool(tk_call('::blt::tree', 'is', 'leaf', tagid(node)))
+ end
+ def link?(node)
+ bool(tk_call('::blt::tree', 'is', 'link', tagid(node)))
+ end
+ def root?(node)
+ bool(tk_call('::blt::tree', 'is', 'root', tagid(node)))
+ end
+
+ def keys(node, *nodes)
+ if nodes.empty?
+ simplelist(tk_call('blt::tree', 'keys', tagid(node)))
+ else
+ simplelist(tk_call('blt::tree', 'keys', tagid(node),
+ *(nodes.collect{|n| tagid(n)}))).collect{|lst|
+ simplelist(lst)
+ }
+ end
+ end
+
+ def label(node, text=nil)
+ if text
+ tk_call('::blt::tree', 'label', tagid(node), text)
+ text
+ else
+ tk_call('::blt::tree', 'label', tagid(node))
+ end
+ end
+
+ def last_child(node)
+ ret = tk_call('::blt::tree', 'lastchild', tagid(node))
+ (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
+ end
+
+ def link(parent, node, keys={})
+ ret = tk_call('::blt::tree', 'link', tagid(parent), tagid(node),
+ __conv_keyonly_opts(keys))
+ (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
+ end
+
+ def move(node, dest, keys={})
+ tk_call('::blt::tree', 'move', tagid(node), tagid(dest), keys)
+ self
+ end
+
+ def next(node)
+ ret = tk_call('::blt::tree', 'next', tagid(node))
+ (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
+ end
+
+ def next_sibling(node)
+ ret = tk_call('::blt::tree', 'nextsibling', tagid(node))
+ (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
+ end
+
+ def notify_create(*args, &b)
+ Tk::BLT::Tree::Notify.new(self, *args, &b)
+ end
+
+ def notify_delete(id)
+ if id.kind_of?(Tk::BLT::Tree::Notify)
+ id.delete
+ else
+ tk_call(@path, 'notify', 'delete', id)
+ Tk::BLT::Tree::Notify::NotifyID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Notify::NotifyID_TBL[@path].delete(id.to_s)
+ }
+ end
+ self
+ end
+
+ def notify_info(id)
+ lst = simplelist(tk_call(@path, 'notify', 'info', tagid(id)))
+ lst[0] = Tk::BLT::Tree::Notify.id2obj(self, lst[0])
+ lst[1] = simplelist(lst[1]).collect{|flag| flag[1..-1]}
+ lst[2] = tk_tcl2ruby(lst[2])
+ lst
+ end
+
+ def notify_names()
+ tk_call(@path, 'notify', 'names').collect{|id|
+ Tk::BLT::Tree::Notify.id2obj(self, id)
+ }
+ end
+
+ def parent(node)
+ ret = tk_call('::blt::tree', 'parent', tagid(node))
+ (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
+ end
+
+ def fullpath(node)
+ tk_call('::blt::tree', 'path', tagid(node))
+ end
+
+ def position(node)
+ number(tk_call('::blt::tree', 'position', tagid(node)))
+ end
+
+ def previous(node)
+ ret = tk_call('::blt::tree', 'previous', tagid(node))
+ (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
+ end
+
+ def prev_sibling(node)
+ ret = tk_call('::blt::tree', 'prevsibling', tagid(node))
+ (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret)
+ end
+
+ def restore(node, str, keys={})
+ tk_call('::blt::tree', 'restore', tagid(node), str,
+ __conv_keyonly_opts(keys))
+ self
+ end
+ def restore_overwrite(node, str, keys={})
+ keys = __conv_keyonly_opts(keys)
+ keys.delete('overwrite')
+ keys.delete(:overwrite)
+ tk_call('::blt::tree', 'restore', tagid(node), str, '-overwrite', keys)
+ self
+ end
+
+ def restore_from_file(node, file, keys={})
+ tk_call('::blt::tree', 'restorefile', tagid(node), file,
+ __conv_keyonly_opts(keys))
+ self
+ end
+ def restore_overwrite_from_file(node, file, keys={})
+ keys = __conv_keyonly_opts(keys)
+ keys.delete('overwrite')
+ keys.delete(:overwrite)
+ tk_call('::blt::tree', 'restorefile', tagid(node), file,
+ '-overwrite', keys)
+ self
+ end
+
+ def root(node=None)
+ Tk::BLT::Tree::Node.id2obj(self, tk_call('::blt::tree', 'root',
+ tagid(node)))
+ end
+
+ def set(node, data)
+ unless data.kind_of?(Hash)
+ fail ArgumentError, 'Hash is expected for data'
+ end
+ args = []
+ data.each{|k, v| args << k << v}
+ tk_call('::blt::tree', 'set', tagid(node), *args)
+ self
+ end
+
+ def size(node)
+ number(tk_call('::blt::tree', 'size', tagid(node)))
+ end
+
+ def sort(node, keys={})
+ tk_call('::blt::tree', 'sort', tagid(node), __conv_keyonly_opts(keys))
+ self
+ end
+
+ def tag_add(tag, *nodes)
+ tk_call(@path, 'tag', 'add', tagid(tag), *(nodes.collect{|n| tagid(n)}))
+ self
+ end
+
+ def tag_delete(tag, *nodes)
+ tk_call(@path, 'tag', 'delete', tagid(tag),
+ *(nodes.collect{|n| tagid(n)}))
+ self
+ end
+
+ def tag_forget(tag)
+ tag = tag.id if tag.kind_of?(Tk::BLT::Tree::Tag)
+ tk_call(@path, 'tag', 'forget', tag)
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@path].delete(tag)
+ }
+ self
+ end
+
+ def tag_get(node, *patterns)
+ simplelist(tk_call(@tpath, 'tag', 'get', tagid(node),
+ *(patterns.collect{|pat| tagid(pat)}))).collect{|str|
+ Tk::BLT::Tree::Tag.id2obj(self, str)
+ }
+ end
+
+ def tag_names(node = None)
+ simplelist(tk_call(@tpath, 'tag', 'names', tagid(node))).collect{|str|
+ Tk::BLT::Tree::Tag.id2obj(self, str)
+ }
+ end
+
+ def tag_nodes(tag)
+ simplelist(tk_call(@tpath, 'tag', 'nodes', tagid(tag))).collect{|node|
+ Tk::BLT::Tree::Node.id2obj(self, node)
+ }
+ end
+
+ def tag_set(node, *tags)
+ tk_call(@path, 'tag', 'set', tagid(node), *(tags.collect{|t| tagid(t)}))
+ self
+ end
+
+ def tag_unset(node, *tags)
+ tk_call(@path, 'tag', 'unset', tagid(node),
+ *(tags.collect{|t| tagid(t)}))
+ self
+ end
+
+ def trace_create(*args, &b)
+ Tk::BLT::Tree::Trace.new(self, *args, &b)
+ end
+
+=begin
+ def trace_delete(*args)
+ args.each{|id|
+ if id.kind_of?(Tk::BLT::Tree::Trace)
+ id.delete
+ else
+ tk_call(@path, 'trace', 'delete', id)
+ Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)
+ end
+ self
+ }
+ end
+=end
+ def trace_delete(*args)
+ args = args.collect{|id| tagid(id)}
+ tk_call(@path, 'trace', 'delete', *args)
+ Tk::BLT::Tree::Trace::TraceID_TBL.mutex.synchronize{
+ args.each{|id| Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)}
+ }
+ self
+ end
+
+ def trace_info(id)
+ lst = simplelist(tk_call(@path, 'trace', 'info', tagid(id)))
+ lst[0] = Tk::BLT::Tree::Trace.id2obj(self, lst[0])
+ lst[2] = simplelist(lst[2])
+ lst[3] = tk_tcl2ruby(lst[3])
+ lst
+ end
+
+ def trace_names()
+ tk_call(@path, 'trace', 'names').collect{|id|
+ Tk::BLT::Tree::Trace.id2obj(self, id)
+ }
+ end
+
+ def type(node, key)
+ tk_call('::blt::tree', 'type', tagid(node), key)
+ end
+
+ def unset(node, *keys)
+ tk_call('::blt::tree', 'unset', tagid(node), *keys)
+ self
+ end
+
+ def values(node, key=None)
+ simplelist(tk_call('::blt::tree', 'values', tagid(node), key))
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/treeview.rb b/ext/tk/lib/tkextlib/blt/treeview.rb
new file mode 100644
index 0000000000..c5a5697186
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/treeview.rb
@@ -0,0 +1,1272 @@
+#
+# tkextlib/blt/treeview.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+require 'tk/validation.rb'
+
+module Tk::BLT
+ class Treeview < TkWindow
+ module ConfigMethod
+ end
+
+ module TagOrID_Methods
+ end
+
+ class Node < TkObject
+ end
+
+ class Tag < TkObject
+ end
+ end
+
+ class Hiertable < Treeview
+ end
+end
+
+######################################
+
+module Tk::BLT::Treeview::ConfigMethod
+ include TkItemConfigMethod
+
+ def __item_boolval_optkeys(id)
+ case id
+ when Array
+ # id := [ 'column', name ]
+ ['edit', 'hide']
+ when 'sort'
+ ['decreasing']
+ else
+ []
+ end
+ end
+ private :__item_boolval_optkeys
+
+ def __item_strval_optkeys(id)
+ case id
+ when Array
+ # id := [ 'column', name ]
+ super() << 'titleforeground' << 'titleshadow'
+ when 'sort'
+ ['decreasing']
+ else
+ []
+ end
+ end
+ private :__item_strval_optkeys
+
+ def __item_listval_optkeys(id)
+ case id
+ when 'entry'
+ ['bindtags']
+ else
+ []
+ end
+ end
+ private :__item_listval_optkeys
+
+ def __item_cget_cmd(id)
+ if id.kind_of?(Array)
+ # id := [ type, name ]
+ [self.path, id[0], 'cget', id[1]]
+ else
+ [self.path, id, 'cget']
+ end
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ if id.kind_of?(Array)
+ # id := [ type, name ]
+ [self.path, id[0], 'configure', id[1]]
+ else
+ [self.path, id, 'configure']
+ end
+ 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 column_cget(name, option)
+ itemcget(['column', name], option)
+ end
+ def column_cget_strict(name, option)
+ itemcget_strict(['column', name], option)
+ end
+ def column_configure(name, slot, value=None)
+ itemconfigure(['column', name], slot, value)
+ end
+ def column_configinfo(name, slot=nil)
+ itemconfiginfo(['column', name], slot)
+ end
+ def current_column_configinfo(name, slot=nil)
+ current_itemconfiginfo(['column', name], slot)
+ end
+
+ def button_cget(option)
+ itemcget('button', option)
+ end
+ def button_cget_strict(option)
+ itemcget_strict('button', option)
+ end
+ def button_configure(slot, value=None)
+ itemconfigure('button', slot, value)
+ end
+ def button_configinfo(slot=nil)
+ itemconfiginfo('button', slot)
+ end
+ def current_button_configinfo(slot=nil)
+ current_itemconfiginfo('button', slot)
+ end
+
+ def entry_cget(option)
+ ret = itemcget('entry', option)
+ if option == 'bindtags' || option == :bindtags
+ ret.collect{|tag| TkBindTag.id2obj(tag)}
+ else
+ ret
+ end
+ end
+ def entry_cget_strict(option)
+ ret = itemcget_strict('entry', option)
+ if option == 'bindtags' || option == :bindtags
+ ret.collect{|tag| TkBindTag.id2obj(tag)}
+ else
+ ret
+ end
+ end
+ def entry_configure(slot, value=None)
+ itemconfigure('entry', slot, value)
+ end
+ def entry_configinfo(slot=nil)
+ ret = itemconfiginfo('entry', slot)
+
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ if slot == 'bindtags' || slot == :bindtags
+ ret[-2] = ret[-2].collect{|tag| TkBindTag.id2obj(tag)}
+ ret[-1] = ret[-1].collect{|tag| TkBindTag.id2obj(tag)}
+ end
+ else
+ inf = ret.assoc('bindtags')
+ inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
+ inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
+ end
+
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (inf = ret['bindtags'])
+ inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
+ inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
+ ret['bindtags'] = inf
+ end
+ end
+
+ ret
+ end
+ def current_entry_configinfo(slot=nil)
+ ret = current_itemconfiginfo('entry', slot)
+
+ if (val = ret['bindtags'])
+ ret['bindtags'] = val.collect{|tag| TkBindTag.id2obj(tag)}
+ end
+
+ ret
+ end
+
+ def sort_cget(option)
+ itemcget('sort', option)
+ end
+ def sort_cget_strict(option)
+ itemcget_strict('sort', option)
+ end
+ def sort_configure(slot, value=None)
+ itemconfigure('sort', slot, value)
+ end
+ def sort_configinfo(slot=nil)
+ itemconfiginfo('sort', slot)
+ end
+ def current_sort_configinfo(slot=nil)
+ current_itemconfiginfo('sort', slot)
+ end
+
+ def text_cget(option)
+ itemcget('text', option)
+ end
+ def text_cget_strict(option)
+ itemcget_strict('text', option)
+ end
+ def text_configure(slot, value=None)
+ itemconfigure('text', slot, value)
+ end
+ def text_configinfo(slot=nil)
+ itemconfiginfo('text', slot)
+ end
+ def current_text_configinfo(slot=nil)
+ current_itemconfiginfo('text', slot)
+ end
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+end
+
+class Tk::BLT::Treeview
+ TkCommandNames = ['::blt::treeview'.freeze].freeze
+ WidgetClassName = 'TreeView'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ include Scrollable
+ include ValidateConfigure
+ include ItemValidateConfigure
+ include Tk::BLT::Treeview::ConfigMethod
+
+ ########################
+
+ def __boolval_optkeys
+ ['autocreate', 'allowduplicates', 'exportselection', 'flat', 'hideroot',
+ 'newtags', 'showtitles', 'sortselection']
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() + ['focusforeground', 'linecolor', 'separator', 'trim']
+ end
+ private :__strval_optkeys
+
+ ########################
+
+ class OpenCloseCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?W, ?w, :widget ],
+ [ ?p, ?s, :name ],
+ [ ?P, ?s, :fullpath ],
+ [ ?#, ?x, :node_id ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?x, TkComm.method(:num_or_str) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ ['opencommand', 'closecomand']
+ end
+ end
+
+ def __validation_class_list
+ super() << OpenCloseCommand
+ end
+
+ Tk::ValidateConfigure.__def_validcmd(binding, OpenCloseCommand)
+
+ ########################
+
+ def __item_validation_class_list(id)
+ case id
+ when 'entry'
+ super(id) << OpenCloseCommand
+ else
+ super(id)
+ end
+ end
+
+ Tk::ItemValidateConfigure.__def_validcmd(binding, OpenCloseCommand)
+
+ ########################
+
+ def __destroy_hook__
+ Tk::BLT::Treeview::Node::TreeNodeID_TBL.mutex.synchronize{
+ Tk::BLT::Treeview::Node::TreeNodeID_TBL.delete(@path)
+ }
+ Tk::BLT::Treeview::Tag::TreeTagID_TBL.mutex.synchronize{
+ Tk::BLT::Treeview::Tag::TreeTagID_TBL.delete(@path)
+ }
+ end
+
+ def tagid(tag)
+ if tag.kind_of?(Tk::BLT::Treeview::Node) \
+ || tag.kind_of?(Tk::BLT::Treeview::Tag)
+ tag.id
+ else
+ tag # maybe an Array of configure paramters
+ end
+ end
+ private :tagid
+
+ def tagid2obj(tagid)
+ if tagid.kind_of?(Integer)
+ Tk::BLT::Treeview::Node.id2obj(self, tagid.to_s)
+ elsif tagid.kind_of?(String)
+ if tagid =~ /^\d+$/
+ Tk::BLT::Treeview::Node.id2obj(self, tagid)
+ else
+ Tk::BLT::Treeview::Tag.id2obj(self, tagid)
+ end
+ else
+ tagid
+ end
+ end
+
+ def bbox(*tags)
+ list(tk_send('bbox', *(tags.collect{|tag| tagid(tag)})))
+ end
+
+ def screen_bbox(*tags)
+ list(tk_send('bbox', '-screen', *(tags.collect{|tag| tagid(tag)})))
+ end
+
+ def tag_bind(tag, seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([@path, 'bind', tagid(tag)], seq, cmd, *args)
+ self
+ end
+ def tag_bind_append(tag, seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([@path, 'bind', tagid(tag)], seq, cmd, *args)
+ self
+ end
+ def tag_bind_remove(tag, seq)
+ _bind_remove([@path, 'bind', tagid(tag)], seq)
+ self
+ end
+ def tag_bindinfo(tag, seq=nil)
+ _bindinfo([@path, 'bind', tagid(tag)], seq)
+ end
+
+ def button_activate(tag)
+ tk_send('button', 'activate', tagid(tag))
+ self
+ end
+
+ def button_bind(tag, seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([@path, 'button', 'bind', tagid(tag)], seq, cmd, *args)
+ self
+ end
+ def button_bind_append(tag, seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([@path, 'button', 'bind', tagid(tag)], seq, cmd, *args)
+ self
+ end
+ def button_bind_remove(tag, seq)
+ _bind_remove([@path, 'button', 'bind', tagid(tag)], seq)
+ self
+ end
+ def button_bindinfo(tag, seq=nil)
+ _bindinfo([@path, 'button', 'bind', tagid(tag)], seq)
+ end
+
+ def close(*tags)
+ tk_send('close', *(tags.collect{|tag| tagid(tag)}))
+ self
+ end
+ def close_recurse(*tags)
+ tk_send('close', '-recurse', *(tags.collect{|tag| tagid(tag)}))
+ self
+ end
+
+ def column_activate(column=None)
+ if column == None
+ tk_send('column', 'activate')
+ else
+ tk_send('column', 'activate', column)
+ self
+ end
+ end
+
+ def column_delete(*fields)
+ tk_send('column', 'delete', *fields)
+ self
+ end
+ def column_insert(pos, field, *opts)
+ tk_send('column', 'insert', pos, field, *opts)
+ self
+ end
+ def column_invoke(field)
+ tk_send('column', 'invoke', field)
+ self
+ end
+ def column_move(name, dest)
+ tk_send('column', 'move', name, dest)
+ self
+ end
+ def column_names()
+ simplelist(tk_send('column', 'names'))
+ end
+ def column_nearest(x, y=None)
+ tk_send('column', 'nearest', x, y)
+ end
+
+ def curselection
+ simplelist(tk_send('curselection')).collect{|id| tagid2obj(id)}
+ end
+
+ def delete(*tags)
+ tk_send('delete', *(tags.collect{|tag| tagid(tag)}))
+ self
+ end
+
+ def entry_activate(tag)
+ tk_send('entry', 'activate', tagid(tag))
+ self
+ end
+ def entry_children(tag, first=None, last=None)
+ simplelist(tk_send('entry', 'children', tagid(tag),
+ first, last)).collect{|id| tagid2obj(id)}
+ end
+ def entry_delete(tag, first=None, last=None)
+ tk_send('entry', 'delete', tagid(tag), first, last)
+ end
+ def entry_before?(tag1, tag2)
+ bool(tk_send('entry', 'isbefore', tagid(tag1), tagid(tag2)))
+ end
+ def entry_hidden?(tag)
+ bool(tk_send('entry', 'ishidden', tagid(tag)))
+ end
+ def entry_open?(tag)
+ bool(tk_send('entry', 'isopen', tagid(tag)))
+ end
+
+ def entry_size(tag)
+ number(tk_send('entry', 'size', tagid(tag)))
+ end
+ def entry_size_recurse(tag)
+ number(tk_send('entry', 'size', '-recurse', tagid(tag)))
+ end
+
+ def _search_flags(keys)
+ keys = _symbolkey2str(keys)
+ keys['exact'] = None if keys.delete('exact')
+ keys['glob'] = None if keys.delete('glob')
+ keys['regexp'] = None if keys.delete('regexp')
+ keys['nonmatching'] = None if keys.delete('nonmatching')
+ end
+ private :_search_flags
+
+ ################################
+
+ class FindExecFlagValue < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?W, ?w, :widget ],
+ [ ?p, ?s, :name ],
+ [ ?P, ?s, :fullpath ],
+ [ ?#, ?x, :node_id ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?x, TkComm.method(:num_or_str) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ []
+ end
+ end
+
+ def _find_exec_flag_value(val)
+ if val.kind_of?(Array)
+ cmd, *args = val
+ #FindExecFlagValue.new(cmd, args.join(' '))
+ FindExecFlagValue.new(cmd, *args)
+ elsif TkComm._callback_entry?(val)
+ FindExecFlagValue.new(val)
+ else
+ val
+ end
+ end
+
+ ################################
+
+ def find(first, last, keys={})
+ keys = _search_flags(keys)
+ keys['exec'] = _find_exec_flag_value(keys['exec']) if keys.key?('exec')
+ args = hash_kv(keys) << '--' << tagid(first) << tagid(last)
+ simplelist(tk_send('find', *args)).collect{|id| tagid2obj(id)}
+ end
+
+ def tag_focus(tag)
+ tk_send('focus', tagid(tag))
+ self
+ end
+ def get(*tags)
+ simplelist(tk_send('get', *(tags.collect{|tag| tagid(tag)})))
+ end
+ def get_full(*tags)
+ simplelist(tk_send('get', '-full', *(tags.collect{|tag| tagid(tag)})))
+ end
+
+ def hide(*tags)
+ if tags[-1].kind_of?(Hash)
+ keys = tags.pop
+ else
+ keys = {}
+ end
+ keys = _search_flags(keys)
+ args = hash_kv(keys) << '--'
+ args.concat(tags.collect{|t| tagid(t)})
+ tk_send('hide', *args)
+ self
+ end
+
+ def index(str)
+ tagid2obj(tk_send('index', str))
+ end
+ def index_at(tag, str)
+ tagid2obj(tk_send('index', '-at', tagid(tag), str))
+ end
+ def index_at_path(tag, str)
+ tagid2obj(tk_send('index', '-at', tagid(tag), '-path', str))
+ end
+
+ def insert(pos, parent=nil, keys={})
+ Tk::BLT::Treeview::Node.new(pos, parent, keys)
+ end
+ def insert_at(tag, pos, parent=nil, keys={})
+ if parent.kind_of?(Hash)
+ keys = parent
+ parent = nil
+ end
+
+ keys = _symbolkey2str(keys)
+ keys['at'] = tagid(tag)
+
+ Tk::BLT::Treeview::Node.new(pos, parent, keys)
+ end
+
+ def move_before(tag, dest)
+ tk_send('move', tagid(tag), 'before', tagid(dest))
+ self
+ end
+ def move_after(tag, dest)
+ tk_send('move', tagid(tag), 'after', tagid(dest))
+ self
+ end
+ def move_into(tag, dest)
+ tk_send('move', tagid(tag), 'into', tagid(dest))
+ self
+ end
+
+ def nearest(x, y, var=None)
+ tagid2obj(tk_send('nearest', x, y, var))
+ end
+
+ def open(*tags)
+ tk_send('open', *(tags.collect{|tag| tagid(tag)}))
+ self
+ end
+ def open_recurse(*tags)
+ tk_send('open', '-recurse', *(tags.collect{|tag| tagid(tag)}))
+ self
+ end
+
+ def range(first, last)
+ simplelist(tk_send('range', tagid(first), tagid(last))).collect{|id|
+ tagid2obj(id)
+ }
+ end
+ def range_open(first, last)
+ simplelist(tk_send('range', '-open',
+ tagid(first), tagid(last))).collect{|id|
+ tagid2obj(id)
+ }
+ end
+
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send_without_enc('scan', 'dragto', x, y)
+ self
+ end
+
+ def see(tag)
+ tk_send_without_enc('see', tagid(tag))
+ self
+ end
+ def see_anchor(anchor, tag)
+ tk_send_without_enc('see', '-anchor', anchor, tagid(tag))
+ self
+ end
+
+ def selection_anchor(tag)
+ tk_send_without_enc('selection', 'anchor', tagid(tag))
+ self
+ end
+ def selection_cancel()
+ tk_send_without_enc('selection', 'cancel')
+ self
+ end
+ def selection_clear(first, last=None)
+ tk_send_without_enc('selection', 'clear', tagid(first), tagid(last))
+ self
+ end
+ def selection_clear_all()
+ tk_send_without_enc('selection', 'clearall')
+ self
+ end
+ def selection_mark(tag)
+ tk_send_without_enc('selection', 'mark', tagid(tag))
+ self
+ end
+ def selection_include?(tag)
+ bool(tk_send('selection', 'include', tagid(tag)))
+ end
+ def selection_present?()
+ bool(tk_send('selection', 'present'))
+ end
+ def selection_set(first, last=None)
+ tk_send_without_enc('selection', 'set', tagid(first), tagid(last))
+ self
+ end
+ def selection_toggle(first, last=None)
+ tk_send_without_enc('selection', 'toggle', tagid(first), tagid(last))
+ self
+ end
+
+ def show(*tags)
+ if tags[-1].kind_of?(Hash)
+ keys = tags.pop
+ else
+ keys = {}
+ end
+ keys = _search_flags(keys)
+ args = hash_kv(keys) << '--'
+ args.concat(tags.collect{|t| tagid(t)})
+ tk_send('show', *args)
+ self
+ end
+
+ def sort_auto(mode)
+ tk_send('sort', 'auto', mode)
+ self
+ end
+ def sort_auto=(mode)
+ tk_send('sort', 'auto', mode)
+ mode
+ end
+ def sort_auto?
+ bool(tk_send('sort', 'auto'))
+ end
+ def sort_once(*tags)
+ tk_send('sort', 'once', *(tags.collect{|tag| tagid(tag)}))
+ self
+ end
+ def sort_once_recurse(*tags)
+ tk_send('sort', 'once', '-recurse', *(tags.collect{|tag| tagid(tag)}))
+ self
+ end
+
+ def tag_add(tag, *ids)
+ tk_send('tag', 'add', tagid(tag), *ids)
+ self
+ end
+ def tag_delete(tag, *ids)
+ tk_send('tag', 'delete', tagid(tag), *ids)
+ self
+ end
+ def tag_forget(tag)
+ tk_send('tag', 'forget', tagid(tag))
+ self
+ end
+ def tag_names(id=nil)
+ id = (id)? tagid(id): None
+
+ simplelist(tk_send('tag', 'nodes', id)).collect{|tag|
+ Tk::BLT::Treeview::Tag.id2obj(self, tag)
+ }
+ end
+ def tag_nodes(tag)
+ simplelist(tk_send('tag', 'nodes', tagid(tag))).collect{|id|
+ Tk::BLT::Treeview::Node.id2obj(self, id)
+ }
+ end
+
+ def text_apply
+ tk_send('text', 'apply')
+ self
+ end
+ def text_cancel
+ tk_send('text', 'cancel')
+ self
+ end
+
+ def text_delete(first, last)
+ tk_send('text', 'delete', first, last)
+ self
+ end
+ def text_get(x, y)
+ tk_send('text', 'get', x, y)
+ end
+ def text_get_root(x, y)
+ tk_send('text', 'get', '-root', x, y)
+ end
+ def text_icursor(idx)
+ tk_send('text', 'icursor', idx)
+ self
+ end
+ def text_index(idx)
+ num_or_str(tk_send('text', 'index', idx))
+ end
+ def text_insert(idx, str)
+ tk_send('text', 'insert', idx, str)
+ self
+ end
+
+ def text_selection_adjust(idx)
+ tk_send('text', 'selection', 'adjust', idx)
+ self
+ end
+ def text_selection_clear
+ tk_send('text', 'selection', 'clear')
+ self
+ end
+ def text_selection_from(idx)
+ tk_send('text', 'selection', 'from', idx)
+ self
+ end
+ def text_selection_present
+ num_or_str(tk_send('text', 'selection', 'present'))
+ end
+ def text_selection_range(start, last)
+ tk_send('text', 'selection', 'range', start, last)
+ self
+ end
+ def text_selection_to(idx)
+ tk_send('text', 'selection', 'to', idx)
+ self
+ end
+
+ def toggle(tag)
+ tk_send('toggle', tagid(tag))
+ self
+ end
+end
+
+######################################
+
+module Tk::BLT::Treeview::TagOrID_Methods
+ def bbox
+ @tree.bbox(self)
+ end
+ def screen_bbox
+ @tree.screen_bbox(self)
+ end
+
+ def bind(seq, *args)
+ @tree.tag_bind(self, seq, *args)
+ self
+ end
+ def bind_append(seq, *args)
+ @tree.tag_bind_append(self, seq, *args)
+ self
+ end
+ def bind_remove(seq)
+ @tree.tag_bind_remove(self, seq)
+ self
+ end
+ def bindinfo(seq=nil)
+ @tree.tag_bindinfo(self, seq)
+ end
+
+ def button_activate
+ @tree.button_activate(self)
+ self
+ end
+
+ def button_bind(seq, *args)
+ @tree.button_bind(self, seq, *args)
+ self
+ end
+ def button_bind_append(seq, *args)
+ @tree.button_bind_append(self, seq, *args)
+ self
+ end
+ def button_bind_remove(seq)
+ @tree.button_bind_remove(self, seq)
+ self
+ end
+ def button_bindinfo(seq=nil)
+ @tree.button_bindinfo(self, seq)
+ end
+
+ def close
+ @tree.close(self)
+ self
+ end
+ def close_recurse
+ @tree.close_recurse(self)
+ self
+ end
+
+ def delete
+ @tree.delete(self)
+ self
+ end
+
+ def entry_activate
+ @tree.entry_activate(self)
+ self
+ end
+ def entry_children(first=None, last=None)
+ @tree.entry_children(self, first, last)
+ end
+ def entry_delete(first=None, last=None)
+ @tree.entry_delete(self, first, last)
+ end
+ def entry_before?(tag)
+ @tree.entry_before?(self, tag)
+ end
+ def entry_hidden?
+ @tree.entry_before?(self)
+ end
+ def entry_open?
+ @tree.entry_open?(self)
+ end
+
+ def entry_size
+ @tree.entry_size(self)
+ end
+ def entry_size_recurse
+ @tree.entry_size_recurse(self)
+ end
+
+ def focus
+ @tree.tag_focus(self)
+ self
+ end
+
+ def get
+ @tree.get(self)
+ end
+ def get_full
+ @tree.get_full(self)
+ end
+
+ def hide
+ @tree.hide(self)
+ self
+ end
+
+ def index(str)
+ @tree.index_at(self, str)
+ end
+ def index_path(str)
+ @tree.index_at_path(self, str)
+ end
+
+ def insert(pos, parent=nil, keys={})
+ @tree.insert_at(self, pos, parent, keys)
+ end
+
+ def move_before(dest)
+ @tree.move_before(self, dest)
+ self
+ end
+ def move_after(dest)
+ @tree.move_after(self, dest)
+ self
+ end
+ def move_into(dest)
+ @tree.move_into(self, dest)
+ self
+ end
+
+ def open
+ @tree.open(self)
+ self
+ end
+ def open_recurse
+ @tree.open_recurse(self)
+ self
+ end
+
+ def range_to(tag)
+ @tree.range(self, tag)
+ end
+ def range_open_to(tag)
+ @tree.range(self, tag)
+ end
+
+ def see
+ @tree.see(self)
+ self
+ end
+ def see_anchor(anchor)
+ @tree.see_anchor(anchor, self)
+ self
+ end
+
+ def selection_anchor
+ @tree.selection_anchor(self)
+ self
+ end
+ def selection_clear
+ @tree.selection_clear(self)
+ self
+ end
+ def selection_mark
+ @tree.selection_mark(self)
+ self
+ end
+ def selection_include?
+ @tree.selection_include?(self)
+ end
+ def selection_set
+ @tree.selection_set(self)
+ self
+ end
+ def selection_toggle
+ @tree.selection_toggle(self)
+ self
+ end
+
+ def show
+ @tree.show(self)
+ self
+ end
+
+ def sort_once
+ @tree.sort_once(self)
+ self
+ end
+ def sort_once_recurse
+ @tree.sort_once_recurse(self)
+ self
+ end
+
+ def toggle
+ @tree.toggle(self)
+ self
+ end
+end
+
+######################################
+
+class Tk::BLT::Treeview::Node < TkObject
+ include Tk::BLT::Treeview::TagOrID_Methods
+
+ TreeNodeID_TBL = TkCore::INTERP.create_table
+
+ (TreeNode_ID = ['blt_treeview_node'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ TreeNodeID_TBL.mutex.synchronize{
+ if TreeNodeID_TBL[tpath]
+ if TreeNodeID_TBL[tpath][id]
+ TreeNodeID_TBL[tpath][id]
+ else
+ begin
+ # self.new(tree, nil, nil, 'node'=>Integer(id))
+ unless (tk_call(@tpath, 'get', id)).empty?
+ id = Integer(id)
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = id
+ TreeNodeID_TBL[@tpath] ||= {}
+ TreeNodeID_TBL[@tpath][@id] = self
+ }
+ obj
+ else
+ id
+ end
+ rescue
+ id
+ end
+ end
+ else
+ id
+ end
+ }
+ end
+
+ def self.new(tree, pos, parent=nil, keys={})
+ if parent.kind_of?(Hash)
+ keys = parent
+ parent = nil
+ end
+
+ keys = _symbolkey2str(keys)
+ tpath = tree.path
+
+ TreeNodeID_TBL.mutex.synchronize{
+ TreeNodeID_TBL[tpath] ||= {}
+ if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
+ keys.delete('node')
+ tk_call(tree.path, 'move', id, pos, parent) if parent
+ return obj
+ end
+
+ #super(tree, pos, parent, keys)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, pos, parent, keys)
+ TreeNodeID_TBL[tpath][@id] = self
+ }
+ obj
+ }
+ end
+
+ def initialize(tree, pos, parent, keys)
+ @parent = @tree = tree
+ @tpath = @parent.path
+
+ if (id = keys['node'])
+ # if tk_call(@tpath, 'get', id).empty?
+ # fail RuntimeError, "not exist the node '#{id}'"
+ # end
+ @path = @id = id
+ tk_call(@tpath, 'move', @id, pos, tagid(parent)) if parent
+ configure(keys) if keys && ! keys.empty?
+ else
+ name = nil
+ TreeNode_ID.mutex.synchronize{
+ name = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze
+ TreeNode_ID[1].succ!
+ }
+
+ at = keys.delete['at']
+
+ if parent
+ if parent.kind_of?(Tk::BLT::Treeview::Node) ||
+ parent.kind_of?(Tk::BLT::Treeview::Tag)
+ path = [get_full(parent.id)[0], name]
+ at = nil # ignore 'at' option
+ else
+ path = [parent.to_s, name]
+ end
+ else
+ path = name
+ end
+
+ if at
+ @id = tk_call(@tpath, 'insert', '-at', tagid(at), pos, path, keys)
+ else
+ @id = tk_call(@tpath, 'insert', pos, path, keys)
+ end
+ @path = @id
+ end
+ end
+
+ def id
+ @id
+ end
+end
+
+######################################
+
+class Tk::BLT::Treeview::Tag < TkObject
+ include Tk::BLT::Treeview::TagOrID_Methods
+
+ TreeTagID_TBL = TkCore::INTERP.create_table
+
+ (TreeTag_ID = ['blt_treeview_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear }
+ }
+
+ def self.id2obj(tree, name)
+ tpath = tree.path
+ TreeTagID_TBL.mutex.synchronize{
+ if TreeTagID_TBL[tpath]
+ if TreeTagID_TBL[tpath][name]
+ TreeTagID_TBL[tpath][name]
+ else
+ #self.new(tree, name)
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = name
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ obj
+ end
+ else
+ id
+ end
+ }
+ end
+
+ def self.new_by_name(tree, name, *ids)
+ TreeTagID_TBL.mutex.synchronize{
+ unless (obj = TreeTagID_TBL[tree.path][name])
+ (obj = self.allocate).instance_eval{
+ initialize(tree, name, ids)
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ end
+ obj
+ }
+ end
+
+ def self.new(tree, *ids)
+ TreeTagID_TBL.mutex.synchronize{
+ (obj = self.allocate).instance_eval{
+ if tree.kind_of?(Array)
+ initialize(tree[0], tree[1], ids)
+ else
+ initialize(tree, nil, ids)
+ end
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ obj
+ }
+ end
+
+ def initialize(tree, name, ids)
+ @parent = @tree = tree
+ @tpath = @parent.path
+
+ if name
+ @path = @id = name
+ else
+ TreeTag_ID.mutex.synchronize{
+ @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze
+ TreeTag_ID[1].succ!
+ }
+ end
+
+ unless ids.empty?
+ tk_call(@tpath, 'tag', 'add', @id, *(ids.collect{|id| tagid(id)}))
+ end
+ end
+
+ def tagid(tag)
+ if tag.kind_of?(Tk::BLT::Treeview::Node) \
+ || tag.kind_of?(Tk::BLT::Treeview::Tag)
+ tag.id
+ else
+ tag
+ end
+ end
+ private :tagid
+
+ def id
+ @id
+ end
+
+ def add(*ids)
+ tk_call(@tpath, 'tag', 'add', @id, *(ids{|id| tagid(id)}))
+ self
+ end
+
+ def remove(*ids)
+ tk_call(@tpath, 'tag', 'delete', @id, *(ids{|id| tagid(id)}))
+ self
+ end
+
+ def forget
+ tk_call(@tpath, 'tag', 'forget', @id)
+ self
+ end
+
+ def nodes
+ simplelist(tk_call(@tpath, 'tag', 'nodes', @id)).collect{|id|
+ Tk::BLT::Treeview::Node.id2obj(@tree, id)
+ }
+ end
+end
+
+class Tk::BLT::Hiertable
+ TkCommandNames = ['::blt::hiertable'.freeze].freeze
+ WidgetClassName = 'Hiertable'.freeze
+ WidgetClassNames[WidgetClassName] = self
+end
diff --git a/ext/tk/lib/tkextlib/blt/unix_dnd.rb b/ext/tk/lib/tkextlib/blt/unix_dnd.rb
new file mode 100644
index 0000000000..445002d7a5
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/unix_dnd.rb
@@ -0,0 +1,135 @@
+#
+# tkextlib/blt/unix_dnd.rb
+#
+# *** This is alpha version, because there is no document on BLT. ***
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module DnD
+ extend TkCore
+
+ TkCommandNames = ['::blt::dnd'.freeze].freeze
+
+ ##############################
+
+ extend TkItemConfigMethod
+
+ class << self
+ def __item_cget_cmd(id)
+ ['::blt::dnd', *id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ ['::blt::dnd', *id]
+ end
+ private :__item_config_cmd
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ def cget(win, option)
+ itemcget(['cget', win], option)
+ end
+ def cget_strict(win, option)
+ itemcget_strict(['cget', win], option)
+ end
+ def configure(win, slot, value=None)
+ itemconfigure(['configure', win], slot, value)
+ end
+ def configinfo(win, slot=nil)
+ itemconfiginfo(['configure', win], slot)
+ end
+ def current_configinfo(win, slot=nil)
+ current_itemconfiginfo(['configure', win], slot)
+ end
+
+ def token_cget(win, option)
+ itemcget(['token', 'cget', win], option)
+ end
+ def token_cget_strict(win, option)
+ itemcget_strict(['token', 'cget', win], option)
+ end
+ def token_configure(win, slot, value=None)
+ itemconfigure(['token', 'configure', win], slot, value)
+ end
+ def token_configinfo(win, slot=nil)
+ itemconfiginfo(['token', 'configure', win], slot)
+ end
+ def current_token_configinfo(win, slot=nil)
+ current_itemconfiginfo(['token', 'configure', win], slot)
+ end
+
+ def token_windowconfigure(win, slot, value=None)
+ itemconfigure(['token', 'window', win], slot, value)
+ end
+ def token_windowconfiginfo(win, slot=nil)
+ itemconfiginfo(['token', 'window', win], slot)
+ end
+ def current_token_windowconfiginfo(win, slot=nil)
+ current_itemconfiginfo(['token', 'window', win], slot)
+ end
+ end
+
+ ##############################
+
+ def self.cancel(win)
+ tk_call('::blt::dnd', 'cancel', *wins)
+ end
+ def self.delete(*wins)
+ tk_call('::blt::dnd', 'delete', *wins)
+ end
+ def self.delete_source(*wins)
+ tk_call('::blt::dnd', 'delete', '-source', *wins)
+ end
+ def self.delete_target(*wins)
+ tk_call('::blt::dnd', 'delete', '-target', *wins)
+ end
+ def self.drag(win, x, y, token=None)
+ tk_call('::blt::dnd', 'drag', win, x, y, token)
+ end
+ def self.drop(win, x, y, token=None)
+ tk_call('::blt::dnd', 'drop', win, x, y, token)
+ end
+ def self.get_data(win, fmt=nil, cmd=nil)
+ if fmt
+ tk_call('::blt::dnd', 'getdata', win, fmt, cmd)
+ else
+ list(tk_call('::blt::dnd', 'getdata', win))
+ end
+ end
+ def self.names(pat=None)
+ list(tk_call('::blt::dnd', 'names', pat))
+ end
+ def self.source_names(pat=None)
+ list(tk_call('::blt::dnd', 'names', '-source', pat))
+ end
+ def self.target_names(pat=None)
+ list(tk_call('::blt::dnd', 'names', '-target', pat))
+ end
+ def self.pull(win, fmt)
+ tk_call('::blt::dnd', 'pull', win, fmt)
+ end
+ def self.register(win, keys={})
+ tk_call('::blt::dnd', 'register', win, keys)
+ end
+ def self.select(win, x, y, timestamp)
+ tk_call('::blt::dnd', 'select', win, x, y, timestamp)
+ end
+ def self.set_data(win, fmt=nil, cmd=nil)
+ if fmt
+ tk_call('::blt::dnd', 'setdata', win, fmt, cmd)
+ else
+ list(tk_call('::blt::dnd', 'setdata', win))
+ end
+ end
+ def self.token(*args)
+ tk_call('::blt::dnd', 'token', *args)
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/vector.rb b/ext/tk/lib/tkextlib/blt/vector.rb
new file mode 100644
index 0000000000..97fb1b96ff
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/vector.rb
@@ -0,0 +1,256 @@
+#
+# tkextlib/blt/vector.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ class Vector < TkVariable
+ TkCommandNames = ['::blt::vector'.freeze].freeze
+
+ def self.create(*args)
+ tk_call('::blt::vector', 'create', *args)
+ end
+
+ def self.destroy(*args)
+ tk_call('::blt::vector', 'destroy', *args)
+ end
+
+ def self.expr(expression)
+ tk_call('::blt::vector', 'expr', expression)
+ end
+
+ def self.names(pat=None)
+ list = simplelist(tk_call('::blt::vector', 'names', pat))
+ TkVar_ID_TBL.mutex.synchronize{
+ list.collect{|name|
+ if TkVar_ID_TBL[name]
+ TkVar_ID_TBL[name]
+ elsif name[0..1] == '::' && TkVar_ID_TBL[name[2..-1]]
+ TkVar_ID_TBL[name[2..-1]]
+ else
+ name
+ end
+ }
+ }
+ end
+
+ ####################################
+
+ def initialize(size=nil, keys={})
+ if size.kind_of?(Hash)
+ keys = size
+ size = nil
+ end
+ if size.kind_of?(Array)
+ # [first, last]
+ size = size.join(':')
+ end
+ if size
+ @id = TkCore::INTERP._invoke('::blt::vector', 'create',
+ "#auto(#{size})", *hash_kv(keys))
+ else
+ @id = TkCore::INTERP._invoke('::blt::vector', 'create',
+ "#auto", *hash_kv(keys))
+ end
+
+ TkVar_ID_TBL.mutex.synchronize{
+ TkVar_ID_TBL[@id] = self
+ }
+
+ @def_default = false
+ @default_val = nil
+
+ @trace_var = nil
+ @trace_elem = nil
+ @trace_opts = nil
+
+ # teach Tk-ip that @id is global var
+ TkCore::INTERP._invoke_without_enc('global', @id)
+ end
+
+ def destroy
+ tk_call('::blt::vector', 'destroy', @id)
+ end
+
+ def inspect
+ '#<Tk::BLT::Vector: ' + @id + '>'
+ end
+
+ def to_s
+ @id
+ end
+
+ def *(item)
+ list(tk_call(@id, '*', item))
+ end
+
+ def +(item)
+ list(tk_call(@id, '+', item))
+ end
+
+ def -(item)
+ list(tk_call(@id, '-', item))
+ end
+
+ def /(item)
+ list(tk_call(@id, '/', item))
+ end
+
+ def append(*vectors)
+ tk_call(@id, 'append', *vectors)
+ end
+
+ def binread(channel, len=None, keys={})
+ if len.kind_of?(Hash)
+ keys = len
+ len = None
+ end
+ keys = _symbolkey2str(keys)
+ keys['swap'] = None if keys.delete('swap')
+ tk_call(@id, 'binread', channel, len, keys)
+ end
+
+ def clear()
+ tk_call(@id, 'clear')
+ self
+ end
+
+ def delete(*indices)
+ tk_call(@id, 'delete', *indices)
+ self
+ end
+
+ def dup_vector(vec)
+ tk_call(@id, 'dup', vec)
+ self
+ end
+
+ def expr(expression)
+ tk_call(@id, 'expr', expression)
+ self
+ end
+
+ def index(idx, val=None)
+ number(tk_call(@id, 'index', idx, val))
+ end
+
+ def [](idx)
+ index(idx)
+ end
+
+ def []=(idx, val)
+ index(idx, val)
+ end
+
+ def length()
+ number(tk_call(@id, 'length'))
+ end
+
+ def length=(size)
+ number(tk_call(@id, 'length', size))
+ end
+
+ def merge(*vectors)
+ tk_call(@id, 'merge', *vectors)
+ self
+ end
+
+ def normalize(vec=None)
+ tk_call(@id, 'normalize', vec)
+ self
+ end
+
+ def notify(keyword)
+ tk_call(@id, 'notify', keyword)
+ self
+ end
+
+ def offset()
+ number(tk_call(@id, 'offset'))
+ end
+
+ def offset=(val)
+ number(tk_call(@id, 'offset', val))
+ end
+
+ def random()
+ tk_call(@id, 'random')
+ end
+
+ def populate(vector, density=None)
+ tk_call(@id, 'populate', vector, density)
+ self
+ end
+
+ def range(first, last=None)
+ list(tk_call(@id, 'range', first, last))
+ end
+
+ def search(val1, val2=None)
+ list(tk_call(@id, 'search', val1, val2))
+ end
+
+ def set(item)
+ tk_call(@id, 'set', item)
+ self
+ end
+
+ def seq(start, finish=None, step=None)
+ tk_call(@id, 'seq', start, finish, step)
+ self
+ end
+
+ def sort(*vectors)
+ tk_call(@id, 'sort', *vectors)
+ self
+ end
+
+ def sort_reverse(*vectors)
+ tk_call(@id, 'sort', '-reverse', *vectors)
+ self
+ end
+
+ def split(*vectors)
+ tk_call(@id, 'split', *vectors)
+ self
+ end
+
+ def variable(var)
+ tk_call(@id, 'variable', var)
+ self
+ end
+ end
+
+ class VectorAccess < Vector
+ def self.new(name)
+ TkVar_ID_TBL.mutex.synchronize{
+ if TkVar_ID_TBL[name]
+ TkVar_ID_TBL[name]
+ else
+ (obj = self.allocate).instance_eval{
+ initialize(name)
+ TkVar_ID_TBL[@id] = self
+ }
+ obj
+ end
+ }
+ end
+
+ def initialize(vec_name)
+ @id = vec_name
+
+ @def_default = false
+ @default_val = nil
+
+ @trace_var = nil
+ @trace_elem = nil
+ @trace_opts = nil
+
+ # teach Tk-ip that @id is global var
+ TkCore::INTERP._invoke_without_enc('global', @id)
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/watch.rb b/ext/tk/lib/tkextlib/blt/watch.rb
new file mode 100644
index 0000000000..219ff78e97
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/watch.rb
@@ -0,0 +1,175 @@
+#
+# tkextlib/blt/watch.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ class Watch < TkObject
+ extend TkCore
+
+ TkCommandNames = ['::blt::watch'.freeze].freeze
+
+ WATCH_ID_TBL = TkCore::INTERP.create_table
+
+ (BLT_WATCH_ID = ['blt_watch_id'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ WATCH_ID_TBL.mutex.synchronize{ WATCH_ID_TBL.clear }
+ }
+
+ def self.names(state = None)
+ lst = tk_split_list(tk_call('::blt::watch', 'names', state))
+ WATCH_ID_TBL.mutex.synchronize{
+ lst.collect{|name|
+ WATCH_ID_TBL[name] || name
+ }
+ }
+ end
+
+ def __numval_optkeys
+ ['maxlevel']
+ end
+ private :__numval_optkeys
+
+ def __boolval_optkeys
+ ['active']
+ end
+ private :__boolval_optkeys
+
+ def __config_cmd
+ ['::blt::watch', 'configure', self.path]
+ end
+ private :__config_cmd
+
+ def initialize(name = nil, keys = {})
+ if name.kind_of?(Hash)
+ keys = name
+ name = nil
+ end
+
+ if name
+ @id = name.to_s
+ else
+ BLT_WATCH_ID.mutex.synchronize{
+ @id = BLT_WATCH_ID.join(TkCore::INTERP._ip_id_)
+ BLT_WATCH_ID[1].succ!
+ }
+ end
+
+ @path = @id
+
+ WATCH_ID_TBL.mutex.synchronize{
+ WATCH_ID_TBL[@id] = self
+ }
+ tk_call('::blt::watch', 'create', @id, *hash_kv(keys))
+ end
+
+ def activate
+ tk_call('::blt::watch', 'activate', @id)
+ self
+ end
+ def deactivate
+ tk_call('::blt::watch', 'deactivate', @id)
+ self
+ end
+ def delete
+ tk_call('::blt::watch', 'delete', @id)
+ self
+ end
+ def info
+ ret = []
+ lst = tk_split_simplelist(tk_call('::blt::watch', 'info', @id))
+ until lst.empty?
+ k, v, *lst = lst
+ k = k[1..-1]
+ case k
+ when /^(#{__strval_optkeys.join('|')})$/
+ # do nothing
+
+ when /^(#{__numval_optkeys.join('|')})$/
+ begin
+ v = number(v)
+ rescue
+ v = nil
+ end
+
+ when /^(#{__numstrval_optkeys.join('|')})$/
+ v = num_or_str(v)
+
+ when /^(#{__boolval_optkeys.join('|')})$/
+ begin
+ v = bool(v)
+ rescue
+ v = nil
+ end
+
+ when /^(#{__listval_optkeys.join('|')})$/
+ v = simplelist(v)
+
+ when /^(#{__numlistval_optkeys.join('|')})$/
+ v = list(v)
+
+ else
+ if v.index('{')
+ v = tk_split_list(v)
+ else
+ v = tk_tcl2ruby(v)
+ end
+ end
+
+ ret << [k, v]
+ end
+
+ ret
+ end
+ def configinfo(slot = nil)
+ if slot
+ slot = slot.to_s
+ v = cget(slot)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ [slot, v]
+ else
+ {slot=>v}
+ end
+ else
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ info
+ else
+ Hash[*(info.flatten)]
+ end
+ end
+ end
+ def cget_strict(key)
+ key = key.to_s
+ begin
+ info.assoc(key)[1]
+ rescue
+ fail ArgumentError, "unknown option '#{key}'"
+ end
+ end
+ def cget(key)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ cget_strict(key)
+ else
+ begin
+ cget_strict(key)
+ rescue => e
+ if current_configinfo.has_key?(key.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/win_printer.rb b/ext/tk/lib/tkextlib/blt/win_printer.rb
new file mode 100644
index 0000000000..7ac6a0dcfc
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/win_printer.rb
@@ -0,0 +1,61 @@
+#
+# tkextlib/blt/win_printer.rb
+#
+# *** Windows only ***
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ class Printer < TkObject
+ extend TkCore
+
+ TkCommandNames = ['::blt::printer'.freeze].freeze
+
+ def self.enum(attribute)
+ simplelist(tk_call('::blt::printer', 'enum', attribute))
+ end
+
+ def self.names(pat=None)
+ simplelist(tk_call('::blt::printer', 'names', pat))
+ end
+
+ def self.open(printer)
+ self.new(printer)
+ end
+
+ #################################
+
+ def initialize(printer)
+ @printer_id = tk_call('::blt::printer', 'open', printer)
+ end
+
+ def close
+ tk_call('::blt::print', 'close', @printer_id)
+ self
+ end
+ def get_attrs(var)
+ tk_call('::blt::print', 'getattrs', @printer_id, var)
+ var
+ end
+ def set_attrs(var)
+ tk_call('::blt::print', 'setattrs', @printer_id, var)
+ self
+ end
+ def snap(win)
+ tk_call('::blt::print', 'snap', @printer_id, win)
+ self
+ end
+ def write(str)
+ tk_call('::blt::print', 'write', @printer_id, str)
+ self
+ end
+ def write_with_title(title, str)
+ tk_call('::blt::print', 'write', @printer_id, title, str)
+ self
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/blt/winop.rb b/ext/tk/lib/tkextlib/blt/winop.rb
new file mode 100644
index 0000000000..e371d28ab7
--- /dev/null
+++ b/ext/tk/lib/tkextlib/blt/winop.rb
@@ -0,0 +1,107 @@
+#
+# tkextlib/blt/winop.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+ module Winop
+ extend TkCore
+
+ TkCommandNames = ['::blt::winop'.freeze].freeze
+ end
+ WinOp = Winop
+end
+
+class << Tk::BLT::Winop
+ def changes(win)
+ tk_call('::blt::winop', 'changes', win)
+ end
+
+ def colormap(win)
+ Hash[*list(tk_call('::blt::winop', 'colormap', win))]
+ end
+
+ def convolve(src, dest, filter)
+ tk_call('::blt::winop', 'convolve', src, dest, filter)
+ end
+
+ def image_convolve(src, dest, filter)
+ tk_call('::blt::winop', 'image', 'convolve', src, dest, filter)
+ end
+ def image_gradient(photo, left, right, type)
+ tk_call('::blt::winop', 'image', 'gradient', photo, left, right, type)
+ end
+ def image_read_jpeg(file, photo)
+ tk_call('::blt::winop', 'image', 'readjpeg', file, photo)
+ end
+ def image_resample(src, dest, horiz_filter=None, vert_filter=None)
+ tk_call('::blt::winop', 'image', 'resample',
+ src, dest, horiz_filter, vert_filter)
+ end
+ def image_rotate(src, dest, angle)
+ tk_call('::blt::winop', 'image', 'rotate', src, dest, angle)
+ end
+ def image_snap(win, photo, width=None, height=None)
+ tk_call('::blt::winop', 'image', 'snap', win, photo, width, height)
+ end
+ def image_subsample(src, dest, x, y, width, height,
+ horiz_filter=None, vert_filter=None)
+ tk_call('::blt::winop', 'image', 'subsample',
+ src, dest, x, y, width, height, horiz_filter, vert_filter)
+ end
+
+ def quantize(src, dest, colors)
+ tk_call('::blt::winop', 'quantize', src, dest, colors)
+ end
+
+ def query()
+ tk_call('::blt::winop', 'query')
+ end
+
+ def read_jpeg(file, photo)
+ tk_call('::blt::winop', 'readjpeg', file, photo)
+ end
+
+ def resample(src, dest, horiz_filter=None, vert_filter=None)
+ tk_call('::blt::winop', 'resample',
+ src, dest, horiz_filter, vert_filter)
+ end
+
+ def subsample(src, dest, x, y, width, height,
+ horiz_filter=None, vert_filter=None)
+ tk_call('::blt::winop', 'subsample',
+ src, dest, x, y, width, height, horiz_filter, vert_filter)
+ end
+
+ def raise(*wins)
+ tk_call('::blt::winop', 'raise', *wins)
+ end
+
+ def lower(*wins)
+ tk_call('::blt::winop', 'lower', *wins)
+ end
+
+ def map(*wins)
+ tk_call('::blt::winop', 'map', *wins)
+ end
+
+ def unmap(*wins)
+ tk_call('::blt::winop', 'unmap', *wins)
+ end
+
+ def move(win, x, y)
+ tk_call('::blt::winop', 'move', win, x, y)
+ end
+
+ def snap(win, photo)
+ tk_call('::blt::winop', 'snap', win, photo)
+ end
+
+ def warpto(win = None)
+ tk_call('::blt::winop', 'warpto', win)
+ end
+ alias warp_to warpto
+end
diff --git a/ext/tk/lib/tkextlib/bwidget.rb b/ext/tk/lib/tkextlib/bwidget.rb
new file mode 100644
index 0000000000..62631d8b54
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget.rb
@@ -0,0 +1,151 @@
+#
+# BWidget extension support
+# 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 'tkextlib/bwidget/setup.rb'
+
+# load all image format handlers
+#TkPackage.require('BWidget', '1.7')
+TkPackage.require('BWidget')
+
+module Tk
+ module BWidget
+ TkComm::TkExtlibAutoloadModule.unshift(self)
+
+ extend TkCore
+
+ LIBRARY = tk_call('set', '::BWIDGET::LIBRARY')
+
+ PACKAGE_NAME = 'BWidget'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('BWidget')
+ rescue
+ ''
+ end
+ end
+
+ def self.XLFDfont(cmd, *args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ args.concat(hash_kv(keys))
+ end
+ tk_call('BWidget::XLFDfont', cmd, *args)
+ end
+
+ def self.assert(exp, msg=None)
+ tk_call('BWidget::assert', exp, msg)
+ end
+
+ def self.badOptionString(type, value, list)
+ tk_call('BWidget::badOptionString', type, value, list)
+ end
+
+ def self.bindMouseWheel(widget)
+ tk_call('BWidget::bindMouseWheel', widget)
+ end
+
+ def self.classes(klass)
+ list(tk_call('BWidget::classes', klass))
+ end
+
+ def self.clonename(menu)
+ tk_call('BWidget::clonename', menu)
+ end
+
+ def self.focus(opt, path)
+ tk_call('BWidget::focus', opt, path)
+ end
+
+ def self.get3dcolor(path, bgcolor)
+ tk_call('BWidget::get3dcolor', path, bgcolor)
+ end
+
+ def self.getname(name)
+ tk_call('BWidget::getname', name)
+ end
+
+ def self.grab(opt, path)
+ tk_call('BWidget::grab', opt, path)
+ end
+
+ def self.inuse(klass)
+ bool(tk_call('BWidget::inuse', klass))
+ end
+
+ def self.library(klass, *klasses)
+ tk_call('BWidget::library', klass, *klasses)
+ end
+
+ def self.lreorder(list, neworder)
+ tk_call('BWidget::lreorder', list, neworder)
+ end
+
+ def self.parsetext(text)
+ tk_call('BWidget::parsetext', text)
+ end
+
+ def self.place(path, w, h, *args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ args.concat(hash_kv(keys))
+ end
+ tk_call('BWidget::place', path, w, h, *(args.flatten))
+ end
+
+ def self.write(file, mode=None)
+ tk_call('BWidget::write', file, mode)
+ end
+
+ def self.wrongNumArgsString(str)
+ tk_call('BWidget::wrongNumArgsString', str)
+ end
+
+ ####################################################
+
+ autoload :ArrowButton, 'tkextlib/bwidget/arrowbutton'
+ autoload :Bitmap, 'tkextlib/bwidget/bitmap'
+ autoload :Button, 'tkextlib/bwidget/button'
+ autoload :ButtonBox, 'tkextlib/bwidget/buttonbox'
+ autoload :ComboBox, 'tkextlib/bwidget/combobox'
+ autoload :Dialog, 'tkextlib/bwidget/dialog'
+ autoload :DragSite, 'tkextlib/bwidget/dragsite'
+ autoload :DropSite, 'tkextlib/bwidget/dropsite'
+ autoload :DynamicHelp, 'tkextlib/bwidget/dynamichelp'
+ autoload :Entry, 'tkextlib/bwidget/entry'
+ autoload :Label, 'tkextlib/bwidget/label'
+ autoload :LabelEntry, 'tkextlib/bwidget/labelentry'
+ autoload :LabelFrame, 'tkextlib/bwidget/labelframe'
+ autoload :ListBox, 'tkextlib/bwidget/listbox'
+ autoload :MainFrame, 'tkextlib/bwidget/mainframe'
+ autoload :MessageDlg, 'tkextlib/bwidget/messagedlg'
+ autoload :NoteBook, 'tkextlib/bwidget/notebook'
+ autoload :PagesManager, 'tkextlib/bwidget/pagesmanager'
+ autoload :PanedWindow, 'tkextlib/bwidget/panedwindow'
+ autoload :PasswdDlg, 'tkextlib/bwidget/passwddlg'
+ autoload :ProgressBar, 'tkextlib/bwidget/progressbar'
+ autoload :ProgressDlg, 'tkextlib/bwidget/progressdlg'
+ autoload :ScrollableFrame, 'tkextlib/bwidget/scrollableframe'
+ autoload :ScrolledWindow, 'tkextlib/bwidget/scrolledwindow'
+ autoload :ScrollView, 'tkextlib/bwidget/scrollview'
+ autoload :SelectColor, 'tkextlib/bwidget/selectcolor'
+ autoload :SelectFont, 'tkextlib/bwidget/selectfont'
+ autoload :Separator, 'tkextlib/bwidget/separator'
+ autoload :SpinBox, 'tkextlib/bwidget/spinbox'
+ autoload :TitleFrame, 'tkextlib/bwidget/titleframe'
+ autoload :Tree, 'tkextlib/bwidget/tree'
+ autoload :Widget, 'tkextlib/bwidget/widget'
+
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb b/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb
new file mode 100644
index 0000000000..770e5e9ef1
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb
@@ -0,0 +1,21 @@
+#
+# tkextlib/bwidget/arrowbutton.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/button'
+
+module Tk
+ module BWidget
+ class ArrowButton < Tk::BWidget::Button
+ end
+ end
+end
+
+class Tk::BWidget::ArrowButton
+ TkCommandNames = ['ArrowButton'.freeze].freeze
+ WidgetClassName = 'ArrowButton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/bitmap.rb b/ext/tk/lib/tkextlib/bwidget/bitmap.rb
new file mode 100644
index 0000000000..6cfde203e8
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/bitmap.rb
@@ -0,0 +1,21 @@
+#
+# tkextlib/bwidget/bitmap.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tk/image'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class Bitmap < TkPhotoImage
+ end
+ end
+end
+
+class Tk::BWidget::Bitmap
+ def initialize(name)
+ @path = tk_call_without_enc('Bitmap::get', name)
+ Tk_IMGTBL[@path] = self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/button.rb b/ext/tk/lib/tkextlib/bwidget/button.rb
new file mode 100644
index 0000000000..8f3087d098
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/button.rb
@@ -0,0 +1,31 @@
+#
+# tkextlib/bwidget/button.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/button'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class Button < Tk::Button
+ end
+ end
+end
+
+class Tk::BWidget::Button
+ TkCommandNames = ['Button'.freeze].freeze
+ WidgetClassName = 'Button'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'helptext'
+ end
+ private :__strval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'helpvar'
+ end
+ private :__tkvariable_optkeys
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
new file mode 100644
index 0000000000..8d6d212189
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
@@ -0,0 +1,90 @@
+#
+# tkextlib/bwidget/buttonbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/button'
+
+module Tk
+ module BWidget
+ class ButtonBox < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::ButtonBox
+ TkCommandNames = ['ButtonBox'.freeze].freeze
+ WidgetClassName = 'ButtonBox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ include TkItemConfigMethod
+
+ def __boolval_optkeys
+ super() << 'homogeneous'
+ end
+ private :__boolval_optkeys
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::BWidget::Button)
+ name = tagOrId[:name]
+ return index(name) unless name.empty?
+ end
+ if tagOrId.kind_of?(Tk::Button)
+ return index(tagOrId[:text])
+ end
+ # index(tagOrId.to_s)
+ index(_get_eval_string(tagOrId))
+ end
+
+ def add(keys={}, &b)
+ win = window(tk_send('add', *hash_kv(keys)))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def delete(idx)
+ tk_send('delete', tagid(idx))
+ self
+ end
+
+ def index(idx)
+ if idx.kind_of?(Tk::BWidget::Button)
+ name = idx[:name]
+ idx = name unless name.empty?
+ end
+ if idx.kind_of?(Tk::Button)
+ idx = idx[:text]
+ end
+ number(tk_send('index', idx.to_s))
+ end
+
+ def insert(idx, keys={}, &b)
+ win = window(tk_send('insert', tagid(idx), *hash_kv(keys)))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def invoke(idx)
+ tk_send('invoke', tagid(idx))
+ self
+ end
+
+ def set_focus(idx)
+ tk_send('setfocus', tagid(idx))
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/combobox.rb b/ext/tk/lib/tkextlib/bwidget/combobox.rb
new file mode 100644
index 0000000000..1c58a4ccb0
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/combobox.rb
@@ -0,0 +1,51 @@
+#
+# tkextlib/bwidget/combobox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/entry'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/listbox'
+require 'tkextlib/bwidget/spinbox'
+
+module Tk
+ module BWidget
+ class ComboBox < Tk::BWidget::SpinBox
+ end
+ end
+end
+
+class Tk::BWidget::ComboBox
+ include Scrollable
+
+ TkCommandNames = ['ComboBox'.freeze].freeze
+ WidgetClassName = 'ComboBox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def get_listbox(&b)
+ win = window(tk_send_without_enc('getlistbox'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def icursor(idx)
+ tk_send_without_enc('icursor', idx)
+ end
+
+ def post
+ tk_send_without_enc('post')
+ self
+ end
+
+ def unpost
+ tk_send_without_enc('unpost')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/dialog.rb b/ext/tk/lib/tkextlib/bwidget/dialog.rb
new file mode 100644
index 0000000000..291ca4a962
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/dialog.rb
@@ -0,0 +1,182 @@
+#
+# tkextlib/bwidget/dialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/buttonbox'
+
+module Tk
+ module BWidget
+ class Dialog < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::Dialog
+ TkCommandNames = ['Dialog'.freeze].freeze
+ WidgetClassName = 'Dialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ include TkItemConfigMethod
+
+ def __strval_optkeys
+ super() << 'title'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'transient' << 'homogeneous'
+ end
+ private :__boolval_optkeys
+
+ def initialize(parent=nil, keys=nil)
+ @relative = ''
+ if parent.kind_of?(Hash)
+ keys = _symbolkey2str(parent)
+ @relative = keys['parent'] if keys.key?('parent')
+ @relative = keys.delete('relative') if keys.key?('relative')
+ super(keys)
+ elsif keys
+ keys = _symbolkey2str(keys)
+ @relative = keys.delete('parent') if keys.key?('parent')
+ @relative = keys.delete('relative') if keys.key?('relative')
+ super(parent, keys)
+ else
+ super(parent)
+ end
+ end
+
+ def create_self(keys)
+ cmd = self.class::TkCommandNames[0]
+ if keys and keys != None
+ tk_call_without_enc(cmd, @path, '-parent', @relative,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(cmd, @path, '-parent', @relative)
+ end
+ end
+
+ def cget_strict(slot)
+ if slot.to_s == 'relative'
+ super('parent')
+ else
+ super(slot)
+ end
+ end
+ def cget(slot)
+ if slot.to_s == 'relative'
+ super('parent')
+ else
+ super(slot)
+ end
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ slot['parent'] = slot.delete('relative') if slot.key?('relative')
+ super(slot)
+ else
+ if slot.to_s == 'relative'
+ super('parent', value)
+ else
+ super(slot, value)
+ end
+ end
+ end
+
+ def configinfo(slot=nil)
+ if slot
+ if slot.to_s == 'relative'
+ super('parent')
+ else
+ super(slot)
+ end
+ else
+ ret = super()
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret << ['relative', 'parent']
+ else
+ ret['relative'] = 'parent'
+ end
+ end
+ end
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::BWidget::Button)
+ name = tagOrId[:name]
+ return index(name) unless name.empty?
+ end
+ if tagOrId.kind_of?(Tk::Button)
+ return index(tagOrId[:text])
+ end
+ # index(tagOrId.to_s)
+ index(_get_eval_string(tagOrId))
+ end
+
+ def add(keys={}, &b)
+ win = window(tk_send('add', *hash_kv(keys)))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def get_frame(&b)
+ win = window(tk_send('getframe'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def get_buttonbox(&b)
+ win = window(@path + '.bbox')
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def draw(focus_win=None)
+ tk_send('draw', focus_win)
+ end
+
+ def enddialog(ret)
+ tk_send('enddialog', ret)
+ end
+
+ def index(idx)
+ get_buttonbox.index(idx)
+ end
+
+ def invoke(idx)
+ tk_send('invoke', tagid(idx))
+ self
+ end
+
+ def set_focus(idx)
+ tk_send('setfocus', tagid(idx))
+ self
+ end
+
+ def withdraw
+ tk_send('withdraw')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/dragsite.rb b/ext/tk/lib/tkextlib/bwidget/dragsite.rb
new file mode 100644
index 0000000000..4d4de1780c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/dragsite.rb
@@ -0,0 +1,31 @@
+#
+# tkextlib/bwidget/dragsite.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ module DragSite
+ end
+ end
+end
+
+module Tk::BWidget::DragSite
+ include Tk
+ extend Tk
+
+ def self.include(klass, type, event)
+ tk_call('DragSite::include', klass, type, event)
+ end
+
+ def self.register(path, keys={})
+ tk_call('DragSite::register', path, *hash_kv(keys))
+ end
+
+ def self.set_drag(path, subpath, initcmd, endcmd, force=None)
+ tk_call('DragSite::setdrag', path, subpath, initcmd, endcmd, force)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/dropsite.rb b/ext/tk/lib/tkextlib/bwidget/dropsite.rb
new file mode 100644
index 0000000000..e5e98fbc51
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/dropsite.rb
@@ -0,0 +1,39 @@
+#
+# tkextlib/bwidget/dropsite.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ module DropSite
+ end
+ end
+end
+
+module Tk::BWidget::DropSite
+ include Tk
+ extend Tk
+
+ def self.include(klass, type)
+ tk_call('DropSite::include', klass, type)
+ end
+
+ def self.register(path, keys={})
+ tk_call('DropSite::register', path, *hash_kv(keys))
+ end
+
+ def self.set_cursor(cursor)
+ tk_call('DropSite::setcursor', cursor)
+ end
+
+ def self.set_drop(path, subpath, dropover, drop, force=None)
+ tk_call('DropSite::setdrop', path, subpath, dropover, drop, force)
+ end
+
+ def self.set_operation(op)
+ tk_call('DropSite::setoperation', op)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb b/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
new file mode 100644
index 0000000000..846e58062d
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
@@ -0,0 +1,63 @@
+#
+# tkextlib/bwidget/dynamichelp.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ module DynamicHelp
+ end
+ end
+end
+
+module Tk::BWidget::DynamicHelp
+ include Tk
+ extend Tk
+
+ def self.__pathname
+ 'DynamicHelp::configure'
+ end
+
+ def __strval_optkeys
+ super() << 'topbackground'
+ end
+ private :__strval_optkeys
+
+ def self.__cget_cmd
+ ['DynamicHelp::configure']
+ end
+
+ def self.__config_cmd
+ ['DynamicHelp::configure']
+ end
+
+ def self.cget_strict(slot)
+ slot = slot.to_s
+ info = {}
+ self.current_configinfo.each{|k,v| info[k.to_s] = v if k.to_s == slot}
+ fail RuntimeError, "unknown option \"-#{slot}\"" if info.empty?
+ info.values[0]
+ end
+ def self.cget(slot)
+ self.current_configinfo(slot).values[0]
+ end
+
+ def self.add(widget, keys={})
+ tk_call('DynamicHelp::add', widget, *hash_kv(keys))
+ end
+
+ def self.delete(widget)
+ tk_call('DynamicHelp::delete', widget)
+ end
+
+ def self.include(klass, type)
+ tk_call('DynamicHelp::include', klass, type)
+ end
+
+ def self.sethelp(path, subpath, force=None)
+ tk_call('DynamicHelp::sethelp', path, subpath, force)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/entry.rb b/ext/tk/lib/tkextlib/bwidget/entry.rb
new file mode 100644
index 0000000000..a56890f4e3
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/entry.rb
@@ -0,0 +1,43 @@
+#
+# tkextlib/bwidget/entry.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/entry'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class Entry < Tk::Entry
+ end
+ end
+end
+
+class Tk::BWidget::Entry
+ include Scrollable
+
+ TkCommandNames = ['Entry'.freeze].freeze
+ WidgetClassName = 'Entry'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'helptext' << 'insertbackground'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'dragenabled' << 'dropenabled' << 'editable'
+ end
+ private :__boolval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'helpvar'
+ end
+ private :__tkvariable_optkeys
+
+ def invoke
+ tk_send_without_enc('invoke')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/label.rb b/ext/tk/lib/tkextlib/bwidget/label.rb
new file mode 100644
index 0000000000..88a504aa50
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/label.rb
@@ -0,0 +1,41 @@
+#
+# tkextlib/bwidget/label.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/label'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class Label < Tk::Label
+ end
+ end
+end
+
+class Tk::BWidget::Label
+ TkCommandNames = ['Label'.freeze].freeze
+ WidgetClassName = 'Label'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'helptext'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'dragenabled' << 'dropenabled'
+ end
+ private :__boolval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'helpvar'
+ end
+ private :__tkvariable_optkeys
+
+ def set_focus
+ tk_send_without_enc('setfocus')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/labelentry.rb b/ext/tk/lib/tkextlib/bwidget/labelentry.rb
new file mode 100644
index 0000000000..95b40946a6
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/labelentry.rb
@@ -0,0 +1,80 @@
+#
+# tkextlib/bwidget/labelentry.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/entry'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/labelframe'
+require 'tkextlib/bwidget/entry'
+
+module Tk
+ module BWidget
+ class LabelEntry < Tk::Entry
+ end
+ end
+end
+
+class Tk::BWidget::LabelEntry
+ include Scrollable
+
+ TkCommandNames = ['LabelEntry'.freeze].freeze
+ WidgetClassName = 'LabelEntry'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'helptext' << 'insertbackground' << 'entryfg' << 'entrybg'
+ end
+ private :__strval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'helpvar'
+ end
+ private :__tkvariable_optkeys
+
+ def __font_optkeys
+ super() << 'labelfont'
+ end
+ private :__font_optkeys
+
+ #def entrybind(*args)
+ # _bind([path, 'bind'], *args)
+ # self
+ #end
+ def entrybind(context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, 'bind'], context, cmd, *args)
+ self
+ end
+
+ #def entrybind_append(*args)
+ # _bind_append([path, 'bind'], *args)
+ # self
+ #end
+ def entrybind_append(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, 'bind'], context, cmd, *args)
+ self
+ end
+
+ def entrybind_remove(*args)
+ _bind_remove([path, 'bind'], *args)
+ self
+ end
+
+ def entrybindinfo(*args)
+ _bindinfo([path, 'bind'], *args)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/labelframe.rb b/ext/tk/lib/tkextlib/bwidget/labelframe.rb
new file mode 100644
index 0000000000..dc221806e4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/labelframe.rb
@@ -0,0 +1,52 @@
+#
+# tkextlib/bwidget/labelframe.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/label'
+
+module Tk
+ module BWidget
+ class LabelFrame < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::LabelFrame
+ TkCommandNames = ['LabelFrame'.freeze].freeze
+ WidgetClassName = 'LabelFrame'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'helptext'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'dragenabled' << 'dropenabled'
+ end
+ private :__boolval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'helpvar'
+ end
+ private :__tkvariable_optkeys
+
+ def self.align(*args)
+ tk_call('LabelFrame::align', *args)
+ end
+ def get_frame(&b)
+ win = window(tk_send_without_enc('getframe'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/listbox.rb b/ext/tk/lib/tkextlib/bwidget/listbox.rb
new file mode 100644
index 0000000000..093fcb6fb3
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/listbox.rb
@@ -0,0 +1,358 @@
+#
+# tkextlib/bwidget/listbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/canvas'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class ListBox < TkWindow
+ # is NOT a subclass of a listbox widget class.
+ # because it constructed on a canvas widget.
+
+ class Item < TkObject
+ end
+ end
+ end
+end
+
+class Tk::BWidget::ListBox
+ include TkItemConfigMethod
+ include Scrollable
+
+ TkCommandNames = ['ListBox'.freeze].freeze
+ WidgetClassName = 'ListBox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ class Event_for_Items < TkEvent::Event
+ def self._get_extra_args_tbl
+ [
+ TkComm.method(:string) # item idenfier
+ ]
+ end
+ end
+
+ def __boolval_optkeys
+ super() << 'autofocus' << 'dragenabled' << 'dropenabled' << 'selectfill'
+ end
+ private :__boolval_optkeys
+
+ def tagid(tag)
+ if tag.kind_of?(Tk::BWidget::ListBox::Item)
+ tag.id
+ else
+ # tag
+ _get_eval_string(tag)
+ end
+ end
+
+ #def imagebind(*args)
+ # _bind_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
+ # self
+ #end
+ def imagebind(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_for_event_class(Event_for_Items, [path, 'bindImage'],
+ context, cmd, *args)
+ self
+ end
+
+ #def imagebind_append(*args)
+ # _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
+ # self
+ #end
+ def imagebind_append(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'],
+ context, cmd, *args)
+ self
+ end
+
+ def imagebind_remove(*args)
+ _bind_remove_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
+ self
+ end
+
+ def imagebindinfo(*args)
+ _bindinfo_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
+ end
+
+ #def textbind(*args)
+ # _bind_for_event_class(Event_for_Items, [path, 'bindText'], *args)
+ # self
+ #end
+ def textbind(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_for_event_class(Event_for_Items, [path, 'bindText'],
+ context, cmd, *args)
+ self
+ end
+
+ #def textbind_append(*args)
+ # _bind_append_for_event_class(Event_for_Items, [path, 'bindText'], *args)
+ # self
+ #end
+ def textbind_append(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append_for_event_class(Event_for_Items, [path, 'bindText'],
+ context, cmd, *args)
+ self
+ end
+
+ def textbind_remove(*args)
+ _bind_remove_for_event_class(Event_for_Items, [path, 'bindText'], *args)
+ self
+ end
+
+ def textbindinfo(*args)
+ _bindinfo_for_event_class(Event_for_Items, [path, 'bindText'], *args)
+ end
+
+ def delete(*args)
+ tk_send('delete', *args)
+ self
+ end
+
+ def edit(item, text, *args)
+ tk_send('edit', tagid(item), text, *args)
+ self
+ end
+
+ def exist?(item)
+ bool(tk_send('exists', tagid(item)))
+ end
+
+ def index(item)
+ num_or_str(tk_send('index', tagid(item)))
+ end
+
+ def insert(idx, item, keys={})
+ tk_send('insert', idx, tagid(item), *hash_kv(keys))
+ self
+ end
+
+ def get_item(idx)
+ tk_send('items', idx)
+ end
+
+ def items(first=None, last=None)
+ list(tk_send('items', first, last))
+ end
+
+ def move(item, idx)
+ tk_send('move', tagid(item), idx)
+ self
+ end
+
+ def reorder(neworder)
+ tk_send('reorder', neworder)
+ self
+ end
+
+ def see(item)
+ tk_send('see', tagid(item))
+ self
+ end
+
+ def selection_clear
+ tk_send_without_enc('selection', 'clear')
+ self
+ end
+
+ def selection_set(*args)
+ tk_send_without_enc('selection', 'set',
+ *(args.collect{|item| tagid(item)}))
+ self
+ end
+
+ def selection_add(*args)
+ tk_send_without_enc('selection', 'add',
+ *(args.collect{|item| tagid(item)}))
+ self
+ end
+
+ def selection_remove(*args)
+ tk_send_without_enc('selection', 'remove',
+ *(args.collect{|item| tagid(item)}))
+ self
+ end
+
+ def selection_get(*args)
+ simplelist(tk_send_without_enc('selection', 'get')).collect{|item|
+ Tk::BWidget::ListBox::Item.id2obj(self, item)
+ }
+ end
+end
+
+class Tk::BWidget::ListBox::Item
+ include TkTreatTagFont
+
+ ListItem_TBL = TkCore::INTERP.create_table
+
+ (ListItem_ID = ['bw:item'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ ListItem_TBL.mutex.synchronize{ ListItem_TBL.clear }
+ }
+
+ def self.id2obj(lbox, id)
+ lpath = lbox.path
+ ListItem_TBL.mutex.synchronize{
+ if ListItem_TBL[lpath]
+ ListItem_TBL[lpath][id]? ListItem_TBL[lpath][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(lbox, *args)
+ if lbox.kind_of?(Tk::BWidget::ListBox)
+ @listbox = lbox
+ else
+ fail RuntimeError,
+ "expect Tk::BWidget::ListBox or Tk::BWidget::ListBox::Item for 1st argument"
+ end
+
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ else
+ keys = {}
+ end
+
+ index = keys.delete('index')
+ unless args.empty?
+ index = args.shift
+ end
+ index = 'end' unless index
+
+ unless args.empty?
+ fail RuntimeError, 'too much arguments'
+ end
+
+ @lpath = @listbox.path
+
+ if keys.key?('itemname')
+ @path = @id = keys.delete('itemname')
+ else
+ ListItem_ID.mutex.synchronize{
+ @path = @id = ListItem_ID.join(TkCore::INTERP._ip_id_)
+ ListItem_ID[1].succ!
+ }
+ end
+
+ ListItem_TBL.mutex.synchronize{
+ ListItem_TBL[@id] = self
+ ListItem_TBL[@lpath] = {} unless ListItem_TBL[@lpath]
+ ListItem_TBL[@lpath][@id] = self
+ }
+
+ @listbox.insert(index, @id, keys)
+ end
+
+ def listbox
+ @listbox
+ end
+
+ def id
+ @id
+ end
+
+ def [](key)
+ cget(key)
+ end
+
+ def []=(key, val)
+ configure(key, val)
+ val
+ end
+
+ def cget(key)
+ @listbox.itemcget(@id, key)
+ end
+ def cget_strict(key)
+ @listbox.itemcget_strict(@id, key)
+ end
+
+ def configure(key, val=None)
+ @listbox.itemconfigure(@id, key, val)
+ end
+
+ def configinfo(key=nil)
+ @listbox.itemconfiginfo(@id, key)
+ end
+
+ def current_configinfo(key=nil)
+ @listbox.current_itemconfiginfo(@id, key)
+ end
+
+ def delete
+ @listbox.delete(@id)
+ self
+ end
+
+ def edit(*args)
+ @listbox.edit(@id, *args)
+ self
+ end
+
+ def exist?
+ @listbox.exist?(@id)
+ end
+
+ def index
+ @listbox.index(@id)
+ end
+
+ def move(index)
+ @listbox.move(@id, index)
+ end
+
+ def see
+ @listbox.see(@id)
+ end
+
+ def selection_add
+ @listbox.selection_add(@id)
+ end
+
+ def selection_remove
+ @listbox.selection_remove(@id)
+ end
+
+ def selection_set
+ @listbox.selection_set(@id)
+ end
+
+ def selection_toggle
+ @listbox.selection_toggle(@id)
+ end
+end
+
diff --git a/ext/tk/lib/tkextlib/bwidget/mainframe.rb b/ext/tk/lib/tkextlib/bwidget/mainframe.rb
new file mode 100644
index 0000000000..de66eaf81e
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/mainframe.rb
@@ -0,0 +1,128 @@
+#
+# tkextlib/bwidget/mainframe.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/progressbar'
+
+module Tk
+ module BWidget
+ class MainFrame < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::MainFrame
+ TkCommandNames = ['MainFrame'.freeze].freeze
+ WidgetClassName = 'MainFrame'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'progressfg'
+ end
+ private :__strval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'progressvar'
+ end
+ private :__tkvariable_optkeys
+
+ def __val2ruby_optkeys # { key=>proc, ... }
+ # The method is used to convert a opt-value to a ruby's object.
+ # When get the value of the option "key", "proc.call(value)" is called.
+ {
+ 'menu'=>proc{|v| simplelist(v).collect!{|elem| simplelist(v)}}
+ }
+ end
+ private :__val2ruby_optkeys
+
+ def add_indicator(keys={}, &b)
+ win = window(tk_send('addindicator', *hash_kv(keys)))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def add_toolbar(&b)
+ win = window(tk_send('addtoolbar'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def get_frame(&b)
+ win = window(tk_send('getframe'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def get_indicator(idx, &b)
+ win = window(tk_send('getindicator', idx))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def get_menu(menu_id, &b)
+ win = window(tk_send('getmenu', menu_id))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def get_toolbar(idx, &b)
+ win = window(tk_send('gettoolbar', idx))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def set_menustate(tag, state)
+ tk_send('setmenustate', tag, state)
+ self
+ end
+
+ def show_statusbar(name)
+ tk_send('showstatusbar', name)
+ self
+ end
+
+ def show_toolbar(idx, mode)
+ tk_send('showtoolbar', idx, mode)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
new file mode 100644
index 0000000000..b88461baf7
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
@@ -0,0 +1,192 @@
+#
+# tkextlib/bwidget/messagedlg.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/dialog.rb'
+
+module Tk
+ module BWidget
+ class MessageDlg < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::MessageDlg
+ TkCommandNames = ['MessageDlg'.freeze].freeze
+ WidgetClassName = 'MessageDlg'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def initialize(parent=nil, keys=nil)
+ @relative = ''
+ if parent.kind_of?(Hash)
+ keys = _symbolkey2str(parent)
+ @relative = keys['parent'] if keys.key?('parent')
+ @relative = keys.delete('relative') if keys.key?('relative')
+ super(keys)
+ elsif keys
+ keys = _symbolkey2str(keys)
+ @relative = keys.delete('parent') if keys.key?('parent')
+ @relative = keys.delete('relative') if keys.key?('relative')
+ super(parent, keys)
+ else
+ super(parent)
+ end
+ end
+
+ def create_self(keys)
+ # NOT create widget.
+ # Because the widget no longer exist when returning from creation.
+ @keys = _symbolkey2str(keys).update('parent'=>@relative)
+ @info = nil
+ end
+ private :create_self
+
+ def __strval_optkeys
+ super() << 'message' << 'title'
+ end
+ private :__strval_optkeys
+
+ def __listval_optkeys
+ super() << 'buttons'
+ end
+ private :__listval_optkeys
+
+ def cget(slot)
+ slot = slot.to_s
+ if slot == 'relative'
+ slot = 'parent'
+ end
+ if winfo_exist?
+ val = super(slot)
+ @keys[slot] = val
+ end
+ @keys[slot]
+ end
+ def cget_strict(slot)
+ slot = slot.to_s
+ if slot == 'relative'
+ slot = 'parent'
+ end
+ if winfo_exist?
+ val = super(slot)
+ @keys[slot] = val
+ end
+ @keys[slot]
+ end
+
+ def configure(slot, value=None)
+ if winfo_exist?
+ super(slot, value)
+ end
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ slot['parent'] = slot.delete('relative') if slot.key?('relative')
+ @keys.update(slot)
+
+ if @info
+ # update @info
+ slot.each{|k, v|
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (inf = @info.assoc(k))
+ inf[-1] = v
+ else
+ @info << [k, '', '', '', v]
+ end
+ else
+ if (inf = @info[k])
+ inf[-1] = v
+ else
+ @info[k] = ['', '', '', v]
+ end
+ end
+ }
+ end
+
+ else # ! Hash
+ slot = slot.to_s
+ slot = 'parent' if slot == 'relative'
+ @keys[slot] = value
+
+ if @info
+ # update @info
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (inf = @info.assoc(slot))
+ inf[-1] = value
+ else
+ @info << [slot, '', '', '', value]
+ end
+ else
+ if (inf = @info[slot])
+ inf[-1] = value
+ else
+ @info[slot] = ['', '', '', value]
+ end
+ end
+ end
+ end
+
+ self
+ end
+
+ def configinfo(slot=nil)
+ if winfo_exist?
+ @info = super()
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ @info << ['relative', 'parent']
+ else
+ @info['relative'] = 'parent'
+ end
+ end
+
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if @info
+ if winfo_exist?
+ # update @keys
+ @info.each{|inf| @keys[inf[0]] = inf[-1] if inf.size > 2 }
+ end
+ else
+ @info = []
+ @keys.each{|k, v|
+ @info << [k, '', '', '', v]
+ }
+ @info << ['relative', 'parent']
+ end
+
+ if slot
+ @info.asoc(slot.to_s).dup
+ else
+ @info.dup
+ end
+
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if @info
+ if winfo_exist?
+ # update @keys
+ @info.each{|k, inf| @keys[k] = inf[-1] if inf.size > 2 }
+ end
+ else
+ @info = {}
+ @keys.each{|k, v|
+ @info[k] = ['', '', '', v]
+ }
+ @info['relative'] = 'parent'
+ end
+
+ if slot
+ @info[slot.to_s].dup
+ else
+ @info.dup
+ end
+ end
+ end
+
+ def create
+ # return the index of the pressed button, or nil if it is destroyed
+ ret = num_or_str(tk_call(self.class::TkCommandNames[0],
+ @path, *hash_kv(@keys)))
+ (ret < 0)? nil: ret
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/notebook.rb b/ext/tk/lib/tkextlib/bwidget/notebook.rb
new file mode 100644
index 0000000000..423943619c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/notebook.rb
@@ -0,0 +1,166 @@
+#
+# tkextlib/bwidget/notebook.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class NoteBook < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::NoteBook
+ include TkItemConfigMethod
+
+ TkCommandNames = ['NoteBook'.freeze].freeze
+ WidgetClassName = 'NoteBook'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ class Event_for_Tabs < TkEvent::Event
+ def self._get_extra_args_tbl
+ [
+ TkComm.method(:string) # page idenfier
+ ]
+ end
+ end
+
+ def __boolval_optkeys
+ super() << 'homogeneous'
+ end
+ private :__boolval_optkeys
+
+ def tagid(id)
+ if id.kind_of?(TkWindow)
+ #id.path
+ id.epath
+ elsif id.kind_of?(TkObject)
+ id.to_eval
+ else
+ # id.to_s
+ _get_eval_string(id)
+ end
+ end
+
+ #def tabbind(*args)
+ # _bind_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args)
+ # self
+ #end
+ def tabbind(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_for_event_class(Event_for_Tabs, [path, 'bindtabs'],
+ context, cmd, *args)
+ self
+ end
+
+ #def tabbind_append(*args)
+ # _bind_append_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args)
+ # self
+ #end
+ def tabbind_append(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append_for_event_class(Event_for_Tabs, [path, 'bindtabs'],
+ context, cmd, *args)
+ self
+ end
+
+ def tabbind_remove(*args)
+ _bind_remove_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args)
+ self
+ end
+
+ def tabbindinfo(*args)
+ _bindinfo_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args)
+ end
+
+ def add(page, &b)
+ win = window(tk_send('add', tagid(page)))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def compute_size
+ tk_send('compute_size')
+ self
+ end
+
+ def delete(page, destroyframe=None)
+ tk_send('delete', tagid(page), destroyframe)
+ self
+ end
+
+ def get_frame(page, &b)
+ win = window(tk_send('getframe', tagid(page)))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def index(page)
+ num_or_str(tk_send('index', tagid(page)))
+ end
+
+ def insert(index, page, keys={}, &b)
+ win = window(tk_send('insert', index, tagid(page), *hash_kv(keys)))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def move(page, index)
+ tk_send('move', tagid(page), index)
+ self
+ end
+
+ def get_page(page)
+ tk_send('pages', page)
+ end
+
+ def pages(first=None, last=None)
+ list(tk_send('pages', first, last))
+ end
+
+ def raise(page=nil)
+ if page
+ tk_send('raise', page)
+ self
+ else
+ tk_send('raise')
+ end
+ end
+
+ def see(page)
+ tk_send('see', page)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
new file mode 100644
index 0000000000..fbc2c11255
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
@@ -0,0 +1,73 @@
+#
+# tkextlib/bwidget/pagesmanager.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class PagesManager < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::PagesManager
+ TkCommandNames = ['PagesManager'.freeze].freeze
+ WidgetClassName = 'PagesManager'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def tagid(id)
+ # id.to_s
+ _get_eval_string(id)
+ end
+
+ def add(page, &b)
+ win = window(tk_send('add', tagid(page)))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def compute_size
+ tk_send('compute_size')
+ self
+ end
+
+ def delete(page)
+ tk_send('delete', tagid(page))
+ self
+ end
+
+ def get_frame(page, &b)
+ win = window(tk_send('getframe', tagid(page)))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def get_page(page)
+ tk_send('pages', page)
+ end
+
+ def pages(first=None, last=None)
+ list(tk_send('pages', first, last))
+ end
+
+ def raise(page=None)
+ tk_send('raise', page)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
new file mode 100644
index 0000000000..4d979fd523
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
@@ -0,0 +1,37 @@
+#
+# tkextlib/bwidget/panedwindow.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class PanedWindow < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::PanedWindow
+ TkCommandNames = ['PanedWindow'.freeze].freeze
+ WidgetClassName = 'PanedWindow'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def add(keys={})
+ window(tk_send('add', *hash_kv(keys)))
+ end
+
+ def get_frame(idx, &b)
+ win = window(tk_send_without_enc('getframe', idx))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/panelframe.rb b/ext/tk/lib/tkextlib/bwidget/panelframe.rb
new file mode 100644
index 0000000000..84bae0768b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/panelframe.rb
@@ -0,0 +1,57 @@
+#
+# tkextlib/bwidget/panelframe.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class PanelFrame < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::PanelFrame
+ TkCommandNames = ['PanelFrame'.freeze].freeze
+ WidgetClassName = 'PanelFrame'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() + ['panelforeground', 'panelbackground']
+ end
+ private :__strval_optkeys
+
+ def add(win, keys={})
+ tk_send('add', win, keys)
+ self
+ end
+
+ def delete(*wins)
+ tk_send('delete', *wins)
+ self
+ end
+
+ def get_frame(&b)
+ win = window(tk_send_without_enc('getframe'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def items
+ list(tk_send('items'))
+ end
+
+ def remove(*wins)
+ tk_send('remove', *wins)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/passwddlg.rb b/ext/tk/lib/tkextlib/bwidget/passwddlg.rb
new file mode 100644
index 0000000000..0b635d97bb
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/passwddlg.rb
@@ -0,0 +1,44 @@
+#
+# tkextlib/bwidget/passwddlg.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/messagedlg'
+
+module Tk
+ module BWidget
+ class PasswdDlg < Tk::BWidget::MessageDlg
+ end
+ end
+end
+
+class Tk::BWidget::PasswdDlg
+ TkCommandNames = ['PasswdDlg'.freeze].freeze
+ WidgetClassName = 'PasswdDlg'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'loginhelptext' << 'loginlabel' << 'logintext' <<
+ 'passwdlabel' << 'passwdtext'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'passwdeditable' << 'homogeneous'
+ end
+ private :__boolval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'loginhelpvar' << 'logintextvariable' <<
+ 'passwdhelpvar' << 'passwdtextvariable'
+ end
+ private :__tkvariable_optkeys
+
+ def create
+ login, passwd = simplelist(tk_call(self.class::TkCommandNames[0],
+ @path, *hash_kv(@keys)))
+ [login, passwd]
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/progressbar.rb b/ext/tk/lib/tkextlib/bwidget/progressbar.rb
new file mode 100644
index 0000000000..0253ce2ada
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/progressbar.rb
@@ -0,0 +1,20 @@
+#
+# tkextlib/bwidget/progressbar.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class ProgressBar < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::ProgressBar
+ TkCommandNames = ['ProgressBar'.freeze].freeze
+ WidgetClassName = 'ProgressBar'.freeze
+ WidgetClassNames[WidgetClassName] = self
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
new file mode 100644
index 0000000000..32600255d5
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
@@ -0,0 +1,58 @@
+#
+# tkextlib/bwidget/progressdlg.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/variable'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/progressbar'
+require 'tkextlib/bwidget/messagedlg'
+
+module Tk
+ module BWidget
+ class ProgressDlg < Tk::BWidget::MessageDlg
+ end
+ end
+end
+
+class Tk::BWidget::ProgressDlg
+ TkCommandNames = ['ProgressDlg'.freeze].freeze
+ WidgetClassName = 'ProgressDlg'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def create_self(keys)
+ # NOT create widget for reusing the object
+ super(keys)
+ @keys['textvariable'] = TkVariable.new unless @keys.key?('textvariable')
+ @keys['variable'] = TkVariable.new unless @keys.key?('variable')
+ end
+
+ def textvariable
+ @keys['textvariable']
+ end
+
+ def text
+ @keys['textvariable'].value
+ end
+
+ def text= (txt)
+ @keys['textvariable'].value = txt
+ end
+
+ def variable
+ @keys['variable']
+ end
+
+ def value
+ @keys['variable'].value
+ end
+
+ def value= (val)
+ @keys['variable'].value = val
+ end
+
+ def create
+ window(tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys)))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
new file mode 100644
index 0000000000..010c960ec5
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
@@ -0,0 +1,40 @@
+#
+# tkextlib/bwidget/scrollableframe.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class ScrollableFrame < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::ScrollableFrame
+ include Scrollable
+
+ TkCommandNames = ['ScrollableFrame'.freeze].freeze
+ WidgetClassName = 'ScrollableFrame'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def get_frame(&b)
+ win = window(tk_send_without_enc('getframe'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def see(win, vert=None, horiz=None)
+ tk_send_without_enc('see', win, vert, horiz)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
new file mode 100644
index 0000000000..3599fd8459
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
@@ -0,0 +1,38 @@
+#
+# tkextlib/bwidget/scrolledwindow.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class ScrolledWindow < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::ScrolledWindow
+ TkCommandNames = ['ScrolledWindow'.freeze].freeze
+ WidgetClassName = 'ScrolledWindow'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def get_frame(&b)
+ win = window(tk_send_without_enc('getframe'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def set_widget(win)
+ tk_send_without_enc('setwidget', win)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrollview.rb b/ext/tk/lib/tkextlib/bwidget/scrollview.rb
new file mode 100644
index 0000000000..0546af2c43
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/scrollview.rb
@@ -0,0 +1,25 @@
+#
+# tkextlib/bwidget/scrollview.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class ScrollView < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::ScrollView
+ TkCommandNames = ['ScrollView'.freeze].freeze
+ WidgetClassName = 'ScrollView'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'fill'
+ end
+ private :__strval_optkeys
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
new file mode 100644
index 0000000000..0f9014f8de
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
@@ -0,0 +1,73 @@
+#
+# tkextlib/bwidget/selectcolor.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/messagedlg'
+
+module Tk
+ module BWidget
+ class SelectColor < Tk::BWidget::MessageDlg
+ class Dialog < Tk::BWidget::SelectColor
+ end
+ class Menubutton < Tk::Menubutton
+ end
+ MenuButton = Menubutton
+ end
+ end
+end
+
+class Tk::BWidget::SelectColor
+ extend Tk
+
+ TkCommandNames = ['SelectColor'.freeze].freeze
+ WidgetClassName = 'SelectColor'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def dialog(keys={})
+ newkeys = @keys.dup
+ newkeys.update(_symbolkey2str(keys))
+ tk_call('SelectColor::dialog', @path, *hash_kv(newkeys))
+ end
+
+ def menu(*args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ else
+ keys = {}
+ end
+ place = args.flatten
+ newkeys = @keys.dup
+ newkeys.update(_symbolkey2str(keys))
+ tk_call('SelectColor::menu', @path, place, *hash_kv(newkeys))
+ end
+
+ def self.set_color(idx, color)
+ tk_call('SelectColor::setcolor', idx, color)
+ end
+end
+
+class Tk::BWidget::SelectColor::Dialog
+ def create_self(keys)
+ super(keys)
+ @keys['type'] = 'dialog'
+ end
+
+ def create
+ @keys['type'] = 'dialog' # 'dialog' type returns color
+ tk_call(Tk::BWidget::SelectColor::TkCommandNames[0],
+ @path, *hash_kv(@keys))
+ end
+end
+
+class Tk::BWidget::SelectColor::Menubutton
+ def create_self(keys)
+ keys = {} unless keys
+ keys = _symbolkey2str(keys)
+ keys['type'] = 'menubutton' # 'toolbar' type returns widget path
+ window(tk_call(Tk::BWidget::SelectColor::TkCommandNames[0],
+ @path, *hash_kv(keys)))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/selectfont.rb b/ext/tk/lib/tkextlib/bwidget/selectfont.rb
new file mode 100644
index 0000000000..e53eb3b5bc
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/selectfont.rb
@@ -0,0 +1,86 @@
+#
+# tkextlib/bwidget/selectfont.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/messagedlg'
+
+module Tk
+ module BWidget
+ class SelectFont < Tk::BWidget::MessageDlg
+ class Dialog < Tk::BWidget::SelectFont
+ end
+ class Toolbar < TkWindow
+ end
+ end
+ end
+end
+
+class Tk::BWidget::SelectFont
+ extend Tk
+
+ TkCommandNames = ['SelectFont'.freeze].freeze
+ WidgetClassName = 'SelectFont'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'sampletext' << 'title'
+ end
+ private :__strval_optkeys
+
+ def __font_optkeys
+ [] # without fontobj operation
+ end
+ private :__font_optkeys
+
+ def create
+ tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys))
+ end
+
+ def self.load_font
+ tk_call('SelectFont::loadfont')
+ end
+end
+
+class Tk::BWidget::SelectFont::Dialog
+ def __font_optkeys
+ [] # without fontobj operation
+ end
+
+ def create_self(keys)
+ super(keys)
+ @keys['type'] = 'dialog'
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot.delete['type']
+ slot.delete[:type]
+ return self if slot.empty?
+ else
+ return self if slot == 'type' || slot == :type
+ end
+ super(slot, value)
+ end
+
+ def create
+ @keys['type'] = 'dialog' # 'dialog' type returns font name
+ tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(@keys))
+ end
+end
+
+class Tk::BWidget::SelectFont::Toolbar
+ def __font_optkeys
+ [] # without fontobj operation
+ end
+
+ def create_self(keys)
+ keys = {} unless keys
+ keys = _symbolkey2str(keys)
+ keys['type'] = 'toolbar' # 'toolbar' type returns widget path
+ window(tk_call(Tk::BWidget::SelectFont::TkCommandNames[0],
+ @path, *hash_kv(keys)))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/separator.rb b/ext/tk/lib/tkextlib/bwidget/separator.rb
new file mode 100644
index 0000000000..d9c3458e51
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/separator.rb
@@ -0,0 +1,20 @@
+#
+# tkextlib/bwidget/separator.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class Separator < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::Separator
+ TkCommandNames = ['Separator'.freeze].freeze
+ WidgetClassName = 'Separator'.freeze
+ WidgetClassNames[WidgetClassName] = self
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/setup.rb b/ext/tk/lib/tkextlib/bwidget/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/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/bwidget/spinbox.rb b/ext/tk/lib/tkextlib/bwidget/spinbox.rb
new file mode 100644
index 0000000000..48358baa5c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/spinbox.rb
@@ -0,0 +1,98 @@
+#
+# tkextlib/bwidget/entry.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+require 'tkextlib/bwidget/arrowbutton'
+require 'tkextlib/bwidget/entry'
+
+module Tk
+ module BWidget
+ class SpinBox < Tk::Entry
+ end
+ end
+end
+
+class Tk::BWidget::SpinBox
+ include Scrollable
+
+ TkCommandNames = ['SpinBox'.freeze].freeze
+ WidgetClassName = 'SpinBox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'helptext' << 'insertbackground' << 'entryfg' << 'entrybg'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'dragenabled' << 'dropenabled' << 'editable'
+ end
+ private :__boolval_optkeys
+
+ def __listval_optkeys
+ super() << 'values'
+ end
+ private :__listval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'helpvar'
+ end
+ private :__tkvariable_optkeys
+
+ #def entrybind(*args)
+ # _bind([path, 'bind'], *args)
+ # self
+ #end
+ def entrybind(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, 'bind'], context, cmd, *args)
+ self
+ end
+
+ #def entrybind_append(*args)
+ # _bind_append([path, 'bind'], *args)
+ # self
+ #end
+ def entrybind_append(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, 'bind'], context, cmd, *args)
+ self
+ end
+
+ def entrybind_remove(*args)
+ _bind_remove([path, 'bind'], *args)
+ self
+ end
+
+ def entrybindinfo(*args)
+ _bindinfo([path, 'bind'], *args)
+ self
+ end
+
+ def get_index_of_value
+ number(tk_send_without_enc('getvalue'))
+ end
+ alias get_value get_index_of_value
+ alias get_value_index get_index_of_value
+
+ def set_value_by_index(idx)
+ idx = "@#{idx}" if idx.kind_of?(Integer)
+ tk_send_without_enc('setvalue', idx)
+ self
+ end
+ alias set_value set_value_by_index
+ alias set_index_value set_value_by_index
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/statusbar.rb b/ext/tk/lib/tkextlib/bwidget/statusbar.rb
new file mode 100644
index 0000000000..39c678d37e
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/statusbar.rb
@@ -0,0 +1,52 @@
+#
+# tkextlib/bwidget/statusbar.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class StatusBar < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::StatusBar
+ TkCommandNames = ['StatusBar'.freeze].freeze
+ WidgetClassName = 'StatusBar'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'showresize'
+ end
+ private :__boolval_optkeys
+
+ def add(win, keys={})
+ tk_send('add', win, keys)
+ self
+ end
+
+ def delete(*wins)
+ tk_send('delete', *wins)
+ self
+ end
+
+ def get_frame(&b)
+ win = window(tk_send_without_enc('getframe'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def items
+ list(tk_send('items'))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/titleframe.rb b/ext/tk/lib/tkextlib/bwidget/titleframe.rb
new file mode 100644
index 0000000000..68534e66e9
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/titleframe.rb
@@ -0,0 +1,33 @@
+#
+# tkextlib/bwidget/titleframe.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/frame'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class TitleFrame < TkWindow
+ end
+ end
+end
+
+class Tk::BWidget::TitleFrame
+ TkCommandNames = ['TitleFrame'.freeze].freeze
+ WidgetClassName = 'TitleFrame'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def get_frame(&b)
+ win = window(tk_send_without_enc('getframe'))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/tree.rb b/ext/tk/lib/tkextlib/bwidget/tree.rb
new file mode 100644
index 0000000000..aed4512a73
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/tree.rb
@@ -0,0 +1,453 @@
+#
+# tkextlib/bwidget/tree.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/canvas'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ class Tree < TkWindow
+ class Node < TkObject
+ end
+ end
+ end
+end
+
+class Tk::BWidget::Tree
+ include TkItemConfigMethod
+ include Scrollable
+
+ TkCommandNames = ['Tree'.freeze].freeze
+ WidgetClassName = 'Tree'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ class Event_for_Items < TkEvent::Event
+ def self._get_extra_args_tbl
+ [
+ TkComm.method(:string) # item idenfier
+ ]
+ end
+ end
+
+ def __strval_optkeys
+ super() << 'crossfill' << 'linesfill'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'dragenabled' << 'dropenabled' <<
+ 'redraw' << 'selectfill' << 'showlines'
+ end
+ private :__boolval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'helpvar'
+ end
+ private :__tkvariable_optkeys
+
+ def tagid(tag)
+ if tag.kind_of?(Tk::BWidget::Tree::Node)
+ tag.id
+ else
+ # tag
+ _get_eval_string(tag)
+ end
+ end
+
+ #def imagebind(*args)
+ # _bind_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
+ # self
+ #end
+ def imagebind(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_for_event_class(Event_for_Items, [path, 'bindImage'],
+ context, cmd, *args)
+ self
+ end
+
+ #def imagebind_append(*args)
+ # _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
+ # self
+ #end
+ def imagebind_append(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'],
+ context, cmd, *args)
+ self
+ end
+
+ def imagebind_remove(*args)
+ _bind_remove_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
+ self
+ end
+
+ def imagebindinfo(*args)
+ _bindinfo_for_event_class(Event_for_Items, [path, 'bindImage'], *args)
+ end
+
+ #def textbind(*args)
+ # _bind_for_event_class(Event_for_Items, [path, 'bindText'], *args)
+ # self
+ #end
+ def textbind(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_for_event_class(Event_for_Items, [path, 'bindText'],
+ context, cmd, *args)
+ self
+ end
+
+ #def textbind_append(*args)
+ # _bind_append_for_event_class(Event_for_Items, [path, 'bindText'], *args)
+ # self
+ #end
+ def textbind_append(context, *args)
+ #if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append_for_event_class(Event_for_Items, [path, 'bindText'],
+ context, cmd, *args)
+ self
+ end
+
+ def textbind_remove(*args)
+ _bind_remove_for_event_class(Event_for_Items, [path, 'bindText'], *args)
+ self
+ end
+
+ def textbindinfo(*args)
+ _bindinfo_for_event_class(Event_for_Items, [path, 'bindText'], *args)
+ end
+
+ def close_tree(node, recurse=None)
+ tk_send('closetree', tagid(node), recurse)
+ self
+ end
+
+ def delete(*args)
+ tk_send('delete', *(args.collect{|node| tagid(node)}))
+ self
+ end
+
+ def edit(node, text, *args)
+ tk_send('edit', tagid(node), text, *args)
+ self
+ end
+
+ def exist?(node)
+ bool(tk_send('exists', tagid(node)))
+ end
+
+ def index(node)
+ num_or_str(tk_send('index', tagid(node)))
+ end
+
+ def insert(idx, parent, node, keys={})
+ tk_send('insert', idx, tagid(parent), tagid(node), *hash_kv(keys))
+ self
+ end
+
+ def move(parent, node, idx)
+ tk_send('move', tagid(parent), tagid(node), idx)
+ self
+ end
+
+ def get_node(node, idx)
+ Tk::BWidget::Tree::Node.id2obj(self, tk_send('nodes', tagid(node), idx))
+ end
+
+ def nodes(node, first=None, last=None)
+ simplelist(tk_send('nodes', tagid(node), first, last)).collect{|node|
+ Tk::BWidget::Tree::Node.id2obj(self, node)
+ }
+ end
+
+ def open?(node)
+ bool(@tree.itemcget(tagid(node), 'open'))
+ end
+
+ def open_tree(node, recurse=None)
+ tk_send('opentree', tagid(node), recurse)
+ self
+ end
+
+ def parent(node)
+ Tk::BWidget::Tree::Node.id2obj(self, tk_send('parent', tagid(node)))
+ end
+
+ def reorder(node, neworder)
+ tk_send('reorder', tagid(node), neworder)
+ self
+ end
+
+ def see(node)
+ tk_send('see', tagid(node))
+ self
+ end
+
+ def selection_add(*args)
+ tk_send_without_enc('selection', 'add',
+ *(args.collect{|node| tagid(node)}))
+ self
+ end
+
+ def selection_clear
+ tk_send_without_enc('selection', 'clear')
+ self
+ end
+
+ def selection_get
+ list(tk_send_without_enc('selection', 'get'))
+ end
+
+ def selection_include?(*args)
+ bool(tk_send_without_enc('selection', 'get',
+ *(args.collect{|node| tagid(node)})))
+ end
+
+ def selection_range(*args)
+ tk_send_without_enc('selection', 'range',
+ *(args.collect{|node| tagid(node)}))
+ self
+ end
+
+ def selection_remove(*args)
+ tk_send_without_enc('selection', 'remove',
+ *(args.collect{|node| tagid(node)}))
+ self
+ end
+
+ def selection_set(*args)
+ tk_send_without_enc('selection', 'set',
+ *(args.collect{|node| tagid(node)}))
+ self
+ end
+
+ def selection_toggle(*args)
+ tk_send_without_enc('selection', 'toggle',
+ *(args.collect{|node| tagid(node)}))
+ self
+ end
+
+ def toggle(node)
+ tk_send_without_enc('toggle', tagid(node))
+ self
+ end
+
+ def visible(node)
+ bool(tk_send_without_enc('visible', tagid(node)))
+ end
+end
+
+class Tk::BWidget::Tree::Node
+ include TkTreatTagFont
+
+ TreeNode_TBL = TkCore::INTERP.create_table
+
+ (TreeNode_ID = ['bw:node'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TreeNode_TBL.mutex.synchronize{ TreeNode_TBL.clear }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ TreeNode_TBL.mutex.synchronize{
+ if TreeNode_TBL[tpath]
+ TreeNode_TBL[tpath][id]? TreeNode_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(tree, *args)
+ if tree.kind_of?(Tk::BWidget::Tree)
+ @tree = tree
+ parent = args.shift
+ if parent.kind_of?(Tk::BWidget::Tree::Node)
+ if parent.tree.path != @tree.path
+ fail RuntimeError, 'tree of parent node is not match'
+ end
+ end
+ elsif tree.kind_of?(Tk::BWidget::Tree::Node)
+ @tree = tree.tree
+ parent = tree.parent
+ else
+ fail RuntimeError,
+ "expect Tk::BWidget::Tree or Tk::BWidget::Tree::Node for 1st argument"
+ end
+
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ else
+ keys = {}
+ end
+
+ index = keys.delete('index')
+ unless args.empty?
+ index = args.shift
+ end
+ index = 'end' unless index
+
+ unless args.empty?
+ fail RuntimeError, 'too much arguments'
+ end
+
+ @tpath = @tree.path
+
+ if keys.key?('nodename')
+ @path = @id = keys.delete('nodename')
+ else
+ TreeNode_ID.mutex.synchronize{
+ @path = @id = TreeNode_ID.join(TkCore::INTERP._ip_id_)
+ TreeNode_ID[1].succ!
+ }
+ end
+
+ TreeNode_TBL.mutex.synchronize{
+ TreeNode_TBL[@id] = self
+ TreeNode_TBL[@tpath] = {} unless TreeNode_TBL[@tpath]
+ TreeNode_TBL[@tpath][@id] = self
+ }
+
+ @tree.insert(index, parent, @id, keys)
+ end
+
+ def tree
+ @tree
+ end
+
+ def id
+ @id
+ end
+
+ def [](key)
+ cget(key)
+ end
+
+ def []=(key, val)
+ configure(key, val)
+ val
+ end
+
+ def cget(key)
+ @tree.itemcget(@id, key)
+ end
+ def cget_strict(key)
+ @tree.itemcget_strict(@id, key)
+ end
+
+ def configure(key, val=None)
+ @tree.itemconfigure(@id, key, val)
+ end
+
+ def configinfo(key=nil)
+ @tree.itemconfiginfo(@id, key)
+ end
+
+ def current_configinfo(key=nil)
+ @tree.current_itemconfiginfo(@id, key)
+ end
+
+ def close_tree(recurse=None)
+ @tree.close_tree(@id, recurse)
+ self
+ end
+
+ def delete
+ @tree.delete(@id)
+ self
+ end
+
+ def edit(*args)
+ @tree.edit(@id, *args)
+ self
+ end
+
+ def exist?
+ @tree.exist?(@id)
+ end
+
+ def index
+ @tree.index(@id)
+ end
+
+ def move(index, parent=nil)
+ if parent
+ @tree.move(parent, @id, index)
+ else
+ @tree.move(self.parent, @id, index)
+ end
+ end
+
+ def open_tree(recurse=None)
+ @tree.open_tree(@id, recurse)
+ self
+ end
+
+ def open?
+ bool(@tree.itemcget(@id, 'open'))
+ end
+
+ def parent
+ @tree.parent(@id)
+ end
+
+ def reorder(neworder)
+ @tree.reorder(@id, neworder)
+ end
+
+ def see
+ @tree.see(@id)
+ end
+
+ def selection_add
+ @tree.selection_add(@id)
+ end
+
+ def selection_remove
+ @tree.selection_remove(@id)
+ end
+
+ def selection_set
+ @tree.selection_set(@id)
+ end
+
+ def selection_toggle
+ @tree.selection_toggle(@id)
+ end
+
+ def toggle
+ @tree.toggle(@id)
+ end
+
+ def visible
+ @tree.visible(@id)
+ end
+end
+
diff --git a/ext/tk/lib/tkextlib/bwidget/widget.rb b/ext/tk/lib/tkextlib/bwidget/widget.rb
new file mode 100644
index 0000000000..a93364b567
--- /dev/null
+++ b/ext/tk/lib/tkextlib/bwidget/widget.rb
@@ -0,0 +1,129 @@
+#
+# tkextlib/bwidget/widget.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/bwidget.rb'
+
+module Tk
+ module BWidget
+ module Widget
+ end
+ end
+end
+
+module Tk::BWidget::Widget
+ include Tk
+ extend Tk
+
+ def self.__pathname
+ 'Widget::configure'
+ end
+
+ def self.__cget_cmd
+ ['Widget::cget']
+ end
+
+ def self.__config_cmd
+ ['Widget::configure']
+ end
+
+ def self.cget_strict(slot)
+ slot = slot.to_s
+ info = {}
+ self.current_configinfo.each{|k,v| info[k.to_s] = v if k.to_s == slot}
+ fail RuntimeError, "unknown option \"-#{slot}\"" if info.empty?
+ info.values[0]
+ end
+ def self.cget(slot)
+ self.current_configinfo(slot).values[0]
+ end
+
+ def self.add_map(klass, subclass, subpath, opts)
+ tk_call('Widget::addmap', klass, subclass, subpath, opts)
+ end
+
+ def self.bwinclude(klass, subclass, subpath, *args)
+ tk_call('Widget::bwinclude', klass, subclass, subpath, *args)
+ end
+
+ def self.create(klass, path, rename=None, &b)
+ win = window(tk_call('Widget::create', klass, path, rename))
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
+ win
+ end
+
+ def self.declare(klass, optlist)
+ tk_call('Widget::declare', klass, optlist)
+ end
+
+ def self.define(klass, filename, *args)
+ tk_call('Widget::define', klass, filename, *args)
+ end
+
+ def self.destroy(win)
+ tk_call('Widget::destroy', _epath(win))
+ end
+
+ def self.focus_next(win)
+ tk_call('Widget::focusNext', win)
+ end
+
+ def self.focus_ok(win)
+ tk_call('Widget::focusOk', win)
+ end
+
+ def self.focus_prev(win)
+ tk_call('Widget::focusPrev', win)
+ end
+
+ def self.generate_doc(dir, widgetlist)
+ tk_call('Widget::generate-doc', dir, widgetlist)
+ end
+
+ def self.generate_widget_doc(klass, iscmd, file)
+ tk_call('Widget::generate-widget-doc', klass, iscmd, file)
+ end
+
+ def self.get_option(win, option)
+ tk_call('Widget::getoption', win, option)
+ end
+
+ def self.get_variable(win, varname, my_varname=None)
+ tk_call('Widget::getVariable', win, varname, my_varname)
+ end
+
+ def self.has_changed(win, option, pvalue)
+ tk_call('Widget::hasChanged', win, option, pvalue)
+ end
+
+ def self.init(klass, win, options)
+ tk_call('Widget::init', klass, win, options)
+ end
+
+ def self.set_option(win, option, value)
+ tk_call('Widget::setoption', win, option, value)
+ end
+
+ def self.sub_cget_strict(win, subwidget)
+ tk_call('Widget::subcget', win, subwidget)
+ end
+ def self.sub_cget(win, subwidget)
+ self.sub_cget_strict(win, subwidget)
+ end
+
+ def self.sync_options(klass, subclass, subpath, options)
+ tk_call('Widget::syncoptions', klass, subclass, subpath, options)
+ end
+
+ def self.tkinclude(klass, tkwidget, subpath, *args)
+ tk_call('Widget::tkinclude', klass, tkwidget, subpath, *args)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/itcl.rb b/ext/tk/lib/tkextlib/itcl.rb
new file mode 100644
index 0000000000..1d6ecf04f2
--- /dev/null
+++ b/ext/tk/lib/tkextlib/itcl.rb
@@ -0,0 +1,13 @@
+#
+# [incr Tcl] support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# call setup script
+require 'tkextlib/itcl/setup.rb'
+
+# load library
+require 'tkextlib/itcl/incr_tcl.rb'
diff --git a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
new file mode 100644
index 0000000000..2b75d62eb9
--- /dev/null
+++ b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
@@ -0,0 +1,178 @@
+#
+# tkextlib/itk/incr_tcl.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+
+# call setup script
+require 'tkextlib/itcl.rb'
+
+# TkPackage.require('Itcl', '3.2')
+TkPackage.require('Itcl')
+
+module Tk
+ module Itcl
+ include Tk
+ extend Tk
+
+ LIBRARY = TkVarAccess.new('::itcl::library')
+ PURIST = TkVarAccess.new('::itcl::purist')
+
+ VERSION = TkCore::INTERP._invoke("set", "::itcl::version").freeze
+ PATCHLEVEL = TkCore::INTERP._invoke("set", "::itcl::patchLevel").freeze
+
+ PACKAGE_NAME = 'Itcl'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('Itcl')
+ rescue
+ ''
+ end
+ end
+
+ ##############################################
+
+ class ItclObject < TkObject
+ ITCL_CLASSNAME = ''.freeze
+
+ (ITCL_OBJ_ID = ['itclobj'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+ ITCL_OBJ_TBL = {}.taint
+
+ def initialize(*args)
+ if (@klass = self.class::ITCL_CLASSNAME).empty?
+ fail RuntimeError, 'unknown itcl class (abstract class?)'
+ end
+ Tk::Itcl::ItclObject::ITCL_OBJ_ID.mutex.synchronize{
+ @id = Tk::Itcl::ItclObject::TCL_OBJ_ID.join(TkCore::INTERP._ip_id_)
+ Tk::Itcl::ItclObject::ITCL_OBJ_ID[1].succ!
+ }
+ @path = @id
+ end
+
+ def self.call_proc(name, *args)
+ tk_call("#{ITCL_CLASSNAME}::#{cmd}", *args)
+ end
+
+ def call_method(name, *args)
+ tk_call(@path, name, *args)
+ end
+
+ def isa(klass)
+ bool(tk_call(@path, 'isa', klass))
+ end
+ alias itcl_kind_of? isa
+
+ def info_class
+ tk_call(@path, 'info', 'class')
+ end
+
+ def info_inherit
+ simplelist(tk_call(@path, 'info', 'inherit'))
+ end
+
+ def info_heritage
+ list(tk_call(@path, 'info', 'heritage'))
+ end
+
+ def info_function(*args)
+ if args[-1].kind_of?(Array)
+ params = args.pop
+ params.each{|param|
+ param = param.to_s
+ args << ( (param[0] == ?-)? param: "-#{param}" )
+ }
+ end
+ list(tk_call(@path, 'info', 'function', *args))
+ end
+
+ def info_variable(*args)
+ if args[-1].kind_of?(Array)
+ params = args.pop
+ params.each{|param|
+ param = param.to_s
+ args << ( (param[0] == ?-)? param: "-#{param}" )
+ }
+ end
+ list(tk_call(@path, 'info', 'variable', *args))
+ end
+ end
+
+ ##############################################
+
+ def self.body(klass, func, args, body)
+ tk_call('::itcl::body', "#{klass}::#{func}", args, body)
+ end
+
+ def self.code(cmd, *args)
+ tk_call('::itcl::code', cmd, *args)
+ end
+
+ def self.code_in_namespace(namespace, cmd, *args)
+ tk_call('::itcl::code', '-namespace', namespace, cmd, *args)
+ end
+
+ def self.configbody(klass, var, body)
+ tk_call('::itcl::configbody', "#{klass}::#{var}", body)
+ end
+
+ def self.create_itcl_class(name, body)
+ TkCore::INTERP._invoke('::itcl::class', name, body)
+ klass = Class.new(Tk::Itcl::ItclObject)
+ klass.const_set('ITCL_CLASSNAME', name.dup.freeze)
+ klass
+ end
+
+ def self.delete_itcl_class(*names)
+ tk_call('::itcl::delete', 'class', *names)
+ end
+
+ def self.delete_itcl_object(*names)
+ tk_call('::itcl::delete', 'object', *names)
+ end
+
+ def self.delete_namespace(*names)
+ tk_call('::itcl::delete', 'namespace', *names)
+ end
+
+ def self.ensemble(name, *args)
+ tk_call('::itcl::ensemble', name, *args)
+ end
+
+ def self.find_classes(pat=None)
+ simplelist(tk_call('::itcl::find', 'classes', pat))
+ end
+
+ def self.find_objects(*args)
+ simplelist(tk_call('::itcl::find', 'objects', *args))
+ end
+
+ def self.is_itcl_class(target)
+ bool(tk_call('::itcl::is', 'class', target))
+ end
+
+ def self.is_itcl_object(target)
+ bool(tk_call('::itcl::is', 'object', target))
+ end
+
+ def self.create_local_obj(klass, name, *args)
+ tk_call('::itcl::local', klass, name, *args)
+ end
+
+ def self.is_itcl_instance(klass, target)
+ bool(tk_call('::itcl::is', 'object', '-class', klass, target))
+ end
+
+ def self.scope(var)
+ tk_call('::itcl::scope', var)
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/itcl/setup.rb b/ext/tk/lib/tkextlib/itcl/setup.rb
new file mode 100644
index 0000000000..5be0588703
--- /dev/null
+++ b/ext/tk/lib/tkextlib/itcl/setup.rb
@@ -0,0 +1,13 @@
+#
+# 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.
+#
+
+
+# set [incr Tcl] library directory
+
+# ENV['ITCL_LIBRARY'] = '/usr/local/ActiveTcl/lib/itcl3.2/'
diff --git a/ext/tk/lib/tkextlib/itk.rb b/ext/tk/lib/tkextlib/itk.rb
new file mode 100644
index 0000000000..7492bd3eb4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/itk.rb
@@ -0,0 +1,13 @@
+#
+# [incr Tk] support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# call setup script
+require 'tkextlib/itk/setup.rb'
+
+# load library
+require 'tkextlib/itk/incr_tk.rb'
diff --git a/ext/tk/lib/tkextlib/itk/incr_tk.rb b/ext/tk/lib/tkextlib/itk/incr_tk.rb
new file mode 100644
index 0000000000..e06deb552c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/itk/incr_tk.rb
@@ -0,0 +1,446 @@
+#
+# tkextlib/itk/incr_tk.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/menuspec'
+require 'tkextlib/itcl.rb'
+
+# call setup script
+require 'tkextlib/itk.rb'
+
+#TkPackage.require('Itk', '3.2')
+TkPackage.require('Itk')
+
+module Tk
+ module Itk
+ include Tk
+ extend Tk
+
+ LIBRARY = TkVarAccess.new('::itk::library')
+
+ PACKAGE_NAME = 'Itk'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('Itk')
+ rescue
+ ''
+ end
+ end
+
+ def self.usual(arg, *args)
+ tk_call('::itk::usual', arg, *args)
+ end
+
+ def self.usual_names
+ list(tk_call('::itk::usual'))
+ end
+
+ ############################
+
+ class Archetype < TkWindow
+ TkCommandNames = [].freeze
+ # WidgetClassName = 'Archetype'.freeze
+ # WidgetClassNames[WidgetClassName] = self
+
+ def self.to_eval
+ '::itk::' << self::WidgetClassName
+ end
+
+ def __destroy_hook__
+ Tk::Itk::Component::ComponentID_TBL.delete(self.path)
+ end
+
+ #### [incr Tk] public methods
+ def component
+ simplelist(tk_send('component'))
+ end
+
+ def component_path(name)
+ window(tk_send('component', name))
+ end
+ alias component_widget component_path
+
+ def component_invoke(name, cmd, *args)
+ window(tk_send('component', name, cmd, *args))
+ end
+
+ def component_obj(*names)
+ names = component if names.empty?
+ names.collect{|name| Tk::Itk::Component.new(self.path, name) }
+ end
+
+ #### [incr Tk] protected methods
+=begin
+ def itk_component_add(visibility, name, create_cmds, option_cmds=None)
+ args = []
+ visibility.each{|v| v = v.to_s; args << ( (v[0] == ?-)? v: "-#{v}" )}
+ args << '--' << name << create_cmd << option_cmds
+ tk_call('itk_component', 'add', *args)
+ end
+
+ def itk_component_delete(*names)
+ tk_call('itk_component', 'delete', *names)
+ end
+
+ def itk_initialize(keys={})
+ tk_call('itk_initialize', keys)
+ end
+
+ def itk_option_add(*args)
+ tk_call('itk_option', 'add', *args)
+ end
+
+ def itk_option_define(name, resource, klass, init, config=None)
+ tk_call('itk_option', 'define', name, resource, klass, init, config)
+ end
+
+ def itk_option_remove(*args)
+ tk_call('itk_option', 'remove', *args)
+ end
+=end
+ end
+
+ ############################
+
+ class Toplevel < Archetype
+ TkCommandNames = ['::itk::Toplevel'].freeze
+ WidgetClassName = 'Toplevel'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ include Wm
+ include TkMenuSpec
+
+ def __strval_optkeys
+ super() << 'title'
+ end
+ private :__strval_optkeys
+ end
+
+ ############################
+
+ class Widget < Archetype
+ TkCommandNames = ['::itk::Widget'].freeze
+ WidgetClassName = 'Widget'.freeze
+ WidgetClassNames[WidgetClassName] = self
+ end
+
+
+ ############################
+
+ class Component < TkObject
+ def __cget_cmd
+ [self.master, 'component', self.name, 'cget']
+ end
+ private :__cget_cmd
+
+ def __config_cmd
+ [self.master, 'component', self.name, 'configure']
+ end
+ private :__config_cmd
+
+ ComponentID_TBL = TkCore::INTERP.create_table
+
+ (Itk_Component_ID = ['itk:component'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ ComponentID_TBL.mutex.synchronize{ ComponentID_TBL.clear }
+ }
+
+ def self.id2obj(master, id)
+ if master.kind_of?(TkObject)
+ master = master.path
+ else
+ master = master.to_s
+ end
+ ComponentID_TBL.mutex.synchronize{
+ if ComponentID_TBL.key?(master)
+ (ComponentID_TBL[master].key?(id))? ComponentID_TBL[master][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def self.new(master, component=nil)
+ if master.kind_of?(TkObject)
+ master = master.path
+ else
+ master = master.to_s
+ end
+
+ if component.kind_of?(Tk::Itk::Component)
+ component = component.name
+ elsif component
+ component = component.to_s
+ else
+ Itk_Component_ID.mutex.synchronize{
+ component = Itk_Component_ID.join(TkCore::INTERP._ip_id_)
+ Itk_Component_ID[1].succ!
+ }
+ end
+
+ ComponentID_TBL.mutex.synchronize{
+ if ComponentID_TBL.key?(master)
+ if ComponentID_TBL[master].key?(component)
+ return ComponentID_TBL[master][component]
+ end
+ else
+ ComponentID_TBL[master] = {}
+ end
+ }
+
+ super(master, component)
+ end
+
+ def initialize(master, component)
+ @master = master
+ @component = component
+
+ ComponentID_TBL.mutex.synchronize{
+ ComponentID_TBL[@master][@component] = self
+ }
+
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ @widget = nil
+ @path = nil
+ end
+ end
+
+ def path
+ unless @path
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ fail RuntimeError, 'component is not assigned to a widget'
+ end
+ end
+ @path
+ end
+
+ def epath
+ path()
+ end
+
+ def to_eval
+ path()
+ end
+
+ def master
+ @master
+ end
+
+ def name
+ @component
+ end
+
+ def widget
+ unless @widget
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ fail RuntimeError, 'component is not assigned to a widget'
+ end
+ end
+ @widget
+ end
+
+ def widget_class
+ unless @widget
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ @widget.classname
+ rescue
+ nil
+ end
+ end
+ end
+
+ def method_missing(id, *args)
+ name = id.id2name
+
+ # try 1 : component command
+ begin
+ return tk_call(@master, 'component', @component, name, *args)
+ rescue
+ end
+
+ # try 2 : component configure
+ len = args.length
+ begin
+ case len
+ when 1
+ if name[-1] == ?=
+ return configure(name[0..-2], args[0])
+ else
+ return configure(name, args[0])
+ end
+ when 0
+ return cget(name)
+ end
+ rescue
+ end
+
+ # try 3 : widget method or widget configure
+ begin
+ unless @widget
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ end
+ @widget.__send__(id, *args)
+ rescue
+ end
+
+ # unknown method
+ super(id, *args)
+ # fail RuntimeError, "unknown method '#{name}' for #{self.inspect}"
+ end
+
+ def tk_send(cmd, *rest)
+ begin
+ tk_call(@master, 'component', @component, cmd, *rest)
+ rescue
+ unless @path
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ fail RuntimeError, 'component is not assigned to a widget'
+ end
+ end
+ tk_call(@path, cmd, *rest)
+ end
+ end
+
+ def tk_send_without_enc(cmd, *rest)
+ begin
+ tk_call_without_enc(@master, 'component', @component, cmd, *rest)
+ rescue
+ unless @path
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ fail RuntimeError, 'component is not assigned to a widget'
+ end
+ end
+ tk_call_without_enc(@path, cmd, *rest)
+ end
+ end
+
+ def tk_send_with_enc(cmd, *rest)
+ begin
+ tk_call_with_enc(@master, 'component', @component, cmd, *rest)
+ rescue
+ unless @path
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ fail RuntimeError, 'component is not assigned to a widget'
+ end
+ end
+ tk_call_with_enc(@path, cmd, *rest)
+ end
+ end
+
+ #def bind(*args)
+ # unless @widget
+ # begin
+ # @widget = window(tk_call(@master, 'component', @component))
+ # @path = @widget.path
+ # rescue
+ # fail RuntimeError, 'component is not assigned to a widget'
+ # end
+ # end
+ # @widget.bind(*args)
+ #end
+ def bind(context, *args)
+ unless @widget
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ fail RuntimeError, 'component is not assigned to a widget'
+ end
+ end
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ @widget.bind(context, cmd, *args)
+ end
+
+ #def bind_append(*args)
+ # unless @widget
+ # begin
+ # @widget = window(tk_call(@master, 'component', @component))
+ # @path = @widget.path
+ # rescue
+ # fail RuntimeError, 'component is not assigned to a widget'
+ # end
+ # end
+ # @widget.bind_append(*args)
+ #end
+ def bind_append(context, *args)
+ unless @widget
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ fail RuntimeError, 'component is not assigned to a widget'
+ end
+ end
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ @widget.bind_append(context, cmd, *args)
+ end
+
+ def bind_remove(*args)
+ unless @widget
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ fail RuntimeError, 'component is not assigned to a widget'
+ end
+ end
+ @widget.bind_remove(*args)
+ end
+
+ def bindinfo(*args)
+ unless @widget
+ begin
+ @widget = window(tk_call(@master, 'component', @component))
+ @path = @widget.path
+ rescue
+ fail RuntimeError, 'component is not assigned to a widget'
+ end
+ end
+ @widget.bindinfo(*args)
+ end
+
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/itk/setup.rb b/ext/tk/lib/tkextlib/itk/setup.rb
new file mode 100644
index 0000000000..e47b64adae
--- /dev/null
+++ b/ext/tk/lib/tkextlib/itk/setup.rb
@@ -0,0 +1,13 @@
+#
+# 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.
+#
+
+
+# set [incr Tk] library directory
+
+# ENV['ITK_LIBRARY'] = '/usr/local/ActiveTcl/lib/itk3.2/'
diff --git a/ext/tk/lib/tkextlib/iwidgets.rb b/ext/tk/lib/tkextlib/iwidgets.rb
new file mode 100644
index 0000000000..ebd4cf7507
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets.rb
@@ -0,0 +1,94 @@
+#
+# [incr Widgets] support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/itcl'
+require 'tkextlib/itk'
+
+# call setup script for general 'tkextlib' libraries
+#require 'tkextlib/setup.rb'
+
+# call setup script
+#require 'tkextlib/iwidgets/setup.rb'
+
+# load all image format handlers
+#TkPackage.require('Iwidgets', '4.0')
+TkPackage.require('Iwidgets')
+
+module Tk
+ module Iwidgets
+ TkComm::TkExtlibAutoloadModule.unshift(self)
+
+ extend TkCore
+
+ PACKAGE_NAME = 'Iwidgets'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('Iwidgets')
+ rescue
+ ''
+ end
+ end
+
+ ####################################################
+
+ autoload :Buttonbox, 'tkextlib/iwidgets/buttonbox'
+ autoload :Calendar, 'tkextlib/iwidgets/calendar'
+ autoload :Canvasprintbox, 'tkextlib/iwidgets/canvasprintbox'
+ autoload :Canvasprintdialog, 'tkextlib/iwidgets/canvasprintdialog'
+ autoload :Checkbox, 'tkextlib/iwidgets/checkbox'
+ autoload :Combobox, 'tkextlib/iwidgets/combobox'
+ autoload :Dateentry, 'tkextlib/iwidgets/dateentry'
+ autoload :Datefield, 'tkextlib/iwidgets/datefield'
+ autoload :Dialog, 'tkextlib/iwidgets/dialog'
+ autoload :Dialogshell, 'tkextlib/iwidgets/dialogshell'
+ autoload :Disjointlistbox, 'tkextlib/iwidgets/disjointlistbox'
+ autoload :Entryfield, 'tkextlib/iwidgets/entryfield'
+ autoload :Extbutton, 'tkextlib/iwidgets/extbutton'
+ autoload :Extfileselectionbox, 'tkextlib/iwidgets/extfileselectionbox'
+ autoload :Extfileselectiondialog,'tkextlib/iwidgets/extfileselectiondialog'
+ autoload :Feedback, 'tkextlib/iwidgets/feedback'
+ autoload :Fileselectionbox, 'tkextlib/iwidgets/fileselectionbox'
+ autoload :Fileselectiondialog, 'tkextlib/iwidgets/fileselectiondialog'
+ autoload :Finddialog, 'tkextlib/iwidgets/finddialog'
+ autoload :Hierarchy, 'tkextlib/iwidgets/hierarchy'
+ autoload :Hyperhelp, 'tkextlib/iwidgets/hyperhelp'
+ autoload :Labeledframe, 'tkextlib/iwidgets/labeledframe'
+ autoload :Labeledwidget, 'tkextlib/iwidgets/labeledwidget'
+ autoload :Mainwindow, 'tkextlib/iwidgets/mainwindow'
+ autoload :Menubar, 'tkextlib/iwidgets/menubar'
+ autoload :Messagebox, 'tkextlib/iwidgets/messagebox'
+ autoload :Messagedialog, 'tkextlib/iwidgets/messagedialog'
+ autoload :Notebook, 'tkextlib/iwidgets/notebook'
+ autoload :Optionmenu, 'tkextlib/iwidgets/optionmenu'
+ autoload :Panedwindow, 'tkextlib/iwidgets/panedwindow'
+ autoload :Pushbutton, 'tkextlib/iwidgets/pushbutton'
+ autoload :Promptdialog, 'tkextlib/iwidgets/promptdialog'
+ autoload :Radiobox, 'tkextlib/iwidgets/radiobox'
+ autoload :Scrolledcanvas, 'tkextlib/iwidgets/scrolledcanvas'
+ autoload :Scrolledframe, 'tkextlib/iwidgets/scrolledframe'
+ autoload :Scrolledhtml, 'tkextlib/iwidgets/scrolledhtml'
+ autoload :Scrolledlistbox, 'tkextlib/iwidgets/scrolledlistbox'
+ autoload :Scrolledtext, 'tkextlib/iwidgets/scrolledtext'
+ autoload :Scrolledwidget, 'tkextlib/iwidgets/scrolledwidget'
+ autoload :Selectionbox, 'tkextlib/iwidgets/selectionbox'
+ autoload :Selectiondialog, 'tkextlib/iwidgets/selectiondialog'
+ autoload :Shell, 'tkextlib/iwidgets/shell'
+ autoload :Spindate, 'tkextlib/iwidgets/spindate'
+ autoload :Spinint, 'tkextlib/iwidgets/spinint'
+ autoload :Spinner, 'tkextlib/iwidgets/spinner'
+ autoload :Spintime, 'tkextlib/iwidgets/spintime'
+ autoload :Tabnotebook, 'tkextlib/iwidgets/tabnotebook'
+ autoload :Tabset, 'tkextlib/iwidgets/tabset'
+ autoload :Timeentry, 'tkextlib/iwidgets/timeentry'
+ autoload :Timefield, 'tkextlib/iwidgets/timefield'
+ autoload :Toolbar, 'tkextlib/iwidgets/toolbar'
+ autoload :Watch, 'tkextlib/iwidgets/watch'
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb b/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
new file mode 100644
index 0000000000..05d58c386f
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
@@ -0,0 +1,120 @@
+#
+# tkextlib/iwidgets/buttonbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Buttonbox < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Buttonbox
+ TkCommandNames = ['::iwidgets::buttonbox'.freeze].freeze
+ WidgetClassName = 'Buttonbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'buttoncget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'buttonconfigure', id]
+ end
+ private :__item_config_cmd
+
+ def __item_boolval_optkeys(id)
+ super(id) << 'defaultring'
+ end
+ private :__item_boolval_optkeys
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
+ alias buttonconfigure itemconfigure
+ alias buttonconfiginfo itemconfiginfo
+ alias current_buttonconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def add(tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ tk_call(@path, 'add', tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def default(idx)
+ tk_call(@path, 'default', index(idx))
+ self
+ end
+
+ def delete(idx)
+ tk_call(@path, 'delete', index(idx))
+ self
+ end
+
+ def hide(idx)
+ tk_call(@path, 'hide', index(idx))
+ self
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', tagid(idx)))
+ end
+
+ def insert(idx, tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def invoke(idx=nil)
+ if idx
+ tk_call(@path, 'invoke', index(idx))
+ else
+ tk_call(@path, 'invoke')
+ end
+ self
+ end
+
+ def show(idx)
+ tk_call(@path, 'show', index(idx))
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/calendar.rb b/ext/tk/lib/tkextlib/iwidgets/calendar.rb
new file mode 100644
index 0000000000..8495f0e29b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/calendar.rb
@@ -0,0 +1,125 @@
+#
+# tkextlib/iwidgets/calendar.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Calendar < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Calendar
+ TkCommandNames = ['::iwidgets::calendar'.freeze].freeze
+ WidgetClassName = 'Calendar'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() + [
+ 'buttonforeground', 'outline', 'selectcolor',
+ 'weekdaybackground', 'weekendbackground'
+ ]
+ end
+ private :__strval_optkeys
+
+ def __listval_optkeys
+ super() << 'days'
+ end
+ private :__listval_optkeys
+
+ def __font_optkeys
+ super() + ['currentdatefont', 'datefont', 'dayfont', 'titlefont']
+ end
+ private :__font_optkeys
+
+ ####################################
+
+ include Tk::ValidateConfigure
+
+ class CalendarCommand < TkValidateCommand
+ #class CalCmdArgs < TkUtil::CallbackSubst
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [ [?d, ?s, :date], nil ]
+ PROC_TBL = [ [?s, TkComm.method(:string) ], nil ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ # array of config-option key (string or symbol)
+ ['command']
+ end
+
+ #def initialize(cmd = Proc.new, *args)
+ # _initialize_for_cb_class(CalCmdArgs, cmd, *args)
+ #end
+ end
+
+ def __validation_class_list
+ super() << CalendarCommand
+ end
+
+ Tk::ValidateConfigure.__def_validcmd(binding, CalendarCommand)
+=begin
+ def command(cmd = Proc.new, args = nil)
+ if cmd.kind_of?(CalendarCommand)
+ configure('command', cmd)
+ elsif args
+ configure('command', [cmd, args])
+ else
+ configure('command', cmd)
+ end
+ end
+=end
+
+ ####################################
+
+ def get_string
+ tk_call(@path, 'get', '-string')
+ end
+ alias get get_string
+
+ def get_clicks
+ number(tk_call(@path, 'get', '-clicks'))
+ end
+
+ def select(date)
+ tk_call(@path, 'select', date)
+ self
+ end
+
+ def show(date)
+ tk_call(@path, 'show', date)
+ self
+ end
+ def show_now
+ tk_call(@path, 'show', 'now')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb b/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb
new file mode 100644
index 0000000000..fa5e90ad05
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb
@@ -0,0 +1,53 @@
+#
+# tkextlib/iwidgets/canvasprintbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Canvasprintbox < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Canvasprintbox
+ TkCommandNames = ['::iwidgets::canvasprintbox'.freeze].freeze
+ WidgetClassName = 'Canvasprintbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'filename'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'stretch'
+ end
+ private :__boolval_optkeys
+
+ def get_output
+ tk_call(@path, 'getoutput')
+ end
+
+ def print
+ bool(tk_call(@path, 'print'))
+ end
+
+ def refresh
+ tk_call(@path, 'refresh')
+ self
+ end
+
+ def set_canvas(win)
+ tk_call(@path, 'setcanvas', win)
+ self
+ end
+
+ def stop
+ tk_call(@path, 'stop')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb b/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb
new file mode 100644
index 0000000000..bbf507677c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb
@@ -0,0 +1,38 @@
+#
+# tkextlib/iwidgets/canvasprintdialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Canvasprintdialog < Tk::Iwidgets::Dialog
+ end
+ end
+end
+
+class Tk::Iwidgets::Canvasprintdialog
+ TkCommandNames = ['::iwidgets::canvasprintdialog'.freeze].freeze
+ WidgetClassName = 'Canvasprintdialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def get_output
+ tk_call(@path, 'getoutput')
+ end
+
+ def print
+ bool(tk_call(@path, 'print'))
+ end
+
+ def refresh
+ tk_call(@path, 'refresh')
+ self
+ end
+
+ def set_canvas(win)
+ tk_call(@path, 'setcanvas', win)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/checkbox.rb b/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
new file mode 100644
index 0000000000..c85d356c55
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
@@ -0,0 +1,129 @@
+#
+# tkextlib/iwidgets/checkbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Checkbox < Tk::Iwidgets::Labeledframe
+ end
+ end
+end
+
+class Tk::Iwidgets::Checkbox
+ TkCommandNames = ['::iwidgets::checkbox'.freeze].freeze
+ WidgetClassName = 'Checkbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'buttoncget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'buttonconfigure', id]
+ end
+ private :__item_config_cmd
+
+ def __item_boolval_optkeys(id)
+ super(id) << 'defaultring'
+ end
+ private :__item_boolval_optkeys
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
+ alias buttonconfigure itemconfigure
+ alias buttonconfiginfo itemconfiginfo
+ alias current_buttonconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def add(tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ tk_call(@path, 'add', tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def delete(idx)
+ tk_call(@path, 'delete', index(idx))
+ self
+ end
+
+ def deselect(idx)
+ tk_call(@path, 'deselect', index(idx))
+ self
+ end
+
+ def flash(idx)
+ tk_call(@path, 'flash', index(idx))
+ self
+ end
+
+ def get_tags
+ simplelist(tk_call_without_enc(@path, 'get'))
+ end
+
+ def get_objs
+ simplelist(tk_call_without_enc(@path, 'get')).collect{|id|
+ Tk::Itk::Component.id2obj(self, id)
+ }
+ end
+
+ def get(idx=nil)
+ if idx
+ bool(tk_call_without_enc(@path, 'get', index(idx)))
+ else
+ get_tags
+ end
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', tagid(idx)))
+ end
+
+ def insert(idx, tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def select(idx)
+ tk_call(@path, 'select', index(idx))
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/combobox.rb b/ext/tk/lib/tkextlib/iwidgets/combobox.rb
new file mode 100644
index 0000000000..a6d54d78fa
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/combobox.rb
@@ -0,0 +1,104 @@
+#
+# tkextlib/iwidgets/combobox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Combobox < Tk::Iwidgets::Entryfield
+ end
+ end
+end
+
+class Tk::Iwidgets::Combobox
+ TkCommandNames = ['::iwidgets::combobox'.freeze].freeze
+ WidgetClassName = 'Combobox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'completion' << 'dropdown' << 'editable' << 'unique'
+ end
+ private :__boolval_optkeys
+
+ def clear(component=None)
+ tk_call(@path, 'clear', component)
+ self
+ end
+
+ def delete_list(first, last=None)
+ tk_call(@path, 'delete', 'list', first, last)
+ self
+ end
+
+ def delete_entry(first, last=None)
+ tk_call(@path, 'delete', 'entry', first, last)
+ self
+ end
+
+ def get_list_contents(index)
+ tk_call(@path, 'get', index)
+ end
+
+ def insert_list(idx, *elems)
+ tk_call(@path, 'insert', 'list', idx, *elems)
+ self
+ end
+
+ def insert_entry(idx, *elems)
+ tk_call(@path, 'insert', 'entry', idx, *elems)
+ self
+ end
+
+ # listbox methods
+ def size
+ tk_send_without_enc('size').to_i
+ end
+ def see(index)
+ tk_send_without_enc('see', index)
+ self
+ end
+ def selection_anchor(index)
+ tk_send_without_enc('selection', 'anchor', index)
+ self
+ end
+ def selection_clear(first, last=None)
+ tk_send_without_enc('selection', 'clear', first, last)
+ self
+ end
+ def selection_includes(index)
+ bool(tk_send_without_enc('selection', 'includes', index))
+ end
+ def selection_set(first, last=None)
+ tk_send_without_enc('selection', 'set', first, last)
+ self
+ end
+
+ # scrolledlistbox methods
+ def get_curselection
+ tk_call(@path, 'getcurselection')
+ end
+ def justify(dir)
+ tk_call(@path, 'justify', dir)
+ self
+ end
+ def sort(*params, &b)
+ # see 'lsort' man page about params
+ if b
+ tk_call(@path, 'sort', '-command', proc(&b), *params)
+ else
+ tk_call(@path, 'sort', *params)
+ end
+ self
+ end
+ def sort_ascending
+ tk_call(@path, 'sort', 'ascending')
+ self
+ end
+ def sort_descending
+ tk_call(@path, 'sort', 'descending')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/dateentry.rb b/ext/tk/lib/tkextlib/iwidgets/dateentry.rb
new file mode 100644
index 0000000000..0a8897f50d
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/dateentry.rb
@@ -0,0 +1,20 @@
+#
+# tkextlib/iwidgets/dateentry.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Dateentry < Tk::Iwidgets::Datefield
+ end
+ end
+end
+
+class Tk::Iwidgets::Dateentry
+ TkCommandNames = ['::iwidgets::dateentry'.freeze].freeze
+ WidgetClassName = 'Dateentry'.freeze
+ WidgetClassNames[WidgetClassName] = self
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/datefield.rb b/ext/tk/lib/tkextlib/iwidgets/datefield.rb
new file mode 100644
index 0000000000..632f3334dc
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/datefield.rb
@@ -0,0 +1,58 @@
+#
+# tkextlib/iwidgets/datefield.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Datefield < Tk::Iwidgets::Labeledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Datefield
+ TkCommandNames = ['::iwidgets::datefield'.freeze].freeze
+ WidgetClassName = 'Datefield'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'gmt'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'textbackground'
+ end
+ private :__strval_optkeys
+
+ def __font_optkeys
+ super() << 'textfont'
+ end
+ private :__font_optkeys
+
+ def get_string
+ tk_call(@path, 'get', '-string')
+ end
+ alias get get_string
+
+ def get_clicks
+ number(tk_call(@path, 'get', '-clicks'))
+ end
+
+ def valid?
+ bool(tk_call(@path, 'isvalid'))
+ end
+ alias isvalid? valid?
+
+ def show(date=None)
+ tk_call(@path, 'show', date)
+ self
+ end
+ def show_now
+ tk_call(@path, 'show', 'now')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/dialog.rb b/ext/tk/lib/tkextlib/iwidgets/dialog.rb
new file mode 100644
index 0000000000..8540eae1b5
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/dialog.rb
@@ -0,0 +1,20 @@
+#
+# tkextlib/iwidgets/dialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Dialog < Tk::Iwidgets::Dialogshell
+ end
+ end
+end
+
+class Tk::Iwidgets::Dialog
+ TkCommandNames = ['::iwidgets::dialog'.freeze].freeze
+ WidgetClassName = 'Dialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb b/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
new file mode 100644
index 0000000000..8d43cc07ab
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
@@ -0,0 +1,120 @@
+#
+# tkextlib/iwidgets/dialogshell.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Dialogshell < Tk::Iwidgets::Shell
+ end
+ end
+end
+
+class Tk::Iwidgets::Dialogshell
+ TkCommandNames = ['::iwidgets::dialogshell'.freeze].freeze
+ WidgetClassName = 'Dialogshell'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'buttoncget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'buttonconfigure', id]
+ end
+ private :__item_config_cmd
+
+ def __item_boolval_optkeys(id)
+ super(id) << 'defaultring'
+ end
+ private :__item_boolval_optkeys
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
+ alias buttonconfigure itemconfigure
+ alias buttonconfiginfo itemconfiginfo
+ alias current_buttonconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def add(tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ tk_call(@path, 'add', tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def default(idx)
+ tk_call(@path, 'default', index(idx))
+ self
+ end
+
+ def delete(idx)
+ tk_call(@path, 'delete', index(idx))
+ self
+ end
+
+ def hide(idx)
+ tk_call(@path, 'hide', index(idx))
+ self
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', tagid(idx)))
+ end
+
+ def insert(idx, tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def invoke(idx=nil)
+ if idx
+ tk_call(@path, 'invoke', index(idx))
+ else
+ tk_call(@path, 'invoke')
+ end
+ self
+ end
+
+ def show(idx)
+ tk_call(@path, 'show', index(idx))
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb b/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb
new file mode 100644
index 0000000000..9bc063ba69
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb
@@ -0,0 +1,50 @@
+#
+# tkextlib/iwidgets/disjointlistbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Disjointlistbox < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Disjointlistbox
+ TkCommandNames = ['::iwidgets::disjointlistbox'.freeze].freeze
+ WidgetClassName = 'Disjointlistbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'lhslabeltext' << 'rhslabeltext' << 'lhsbuttonlabel' << 'rhsbuttonlabel'
+ end
+ private :__strval_optkeys
+
+ def set_lhs(*items)
+ tk_call(@path, 'setlhs', items)
+ self
+ end
+ def set_rhs(*items)
+ tk_call(@path, 'setrhs', items)
+ self
+ end
+
+ def get_lhs
+ simplelist(tk_call(@path, 'getlhs'))
+ end
+ def get_rhs
+ simplelist(tk_call(@path, 'getrhs'))
+ end
+
+ def insert_lhs(*items)
+ tk_call(@path, 'insertlhs', items)
+ self
+ end
+ def insert_rhs(*items)
+ tk_call(@path, 'insertrhs', items)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
new file mode 100644
index 0000000000..d53df216bf
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
@@ -0,0 +1,185 @@
+#
+# tkextlib/iwidgets/entryfield.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Entryfield < Tk::Iwidgets::Labeledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Entryfield
+ TkCommandNames = ['::iwidgets::entryfield'.freeze].freeze
+ WidgetClassName = 'Entryfield'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __font_optkeys
+ super() << 'textfont'
+ end
+ private :__font_optkeys
+
+ ####################################
+
+ include Tk::ValidateConfigure
+
+ class EntryfieldValidate < TkValidateCommand
+ #class CalCmdArgs < TkUtil::CallbackSubst
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?c, ?s, :char ],
+ [ ?P, ?s, :post ],
+ [ ?S, ?s, :current ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+ PROC_TBL = [
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+ end
+
+ def self._config_keys
+ ['validate', 'invalid']
+ end
+ end
+
+ def __validation_class_list
+ super() << EntryfieldValidate
+ end
+
+ Tk::ValidateConfigure.__def_validcmd(binding, EntryfieldValidate)
+=begin
+ def validate(cmd = Proc.new, args = nil)
+ if cmd.kind_of?(ValidateCmd)
+ configure('validate', cmd)
+ elsif args
+ configure('validate', [cmd, args])
+ else
+ configure('validate', cmd)
+ end
+ end
+
+ def invalid(cmd = Proc.new, args = nil)
+ if cmd.kind_of?(ValidateCmd)
+ configure('invalid', cmd)
+ elsif args
+ configure('invalid', [cmd, args])
+ else
+ configure('invalid', cmd)
+ end
+ end
+=end
+
+ ####################################
+
+ def clear
+ tk_call(@path, 'clear')
+ self
+ end
+
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+
+ def value
+ _fromUTF8(tk_send_without_enc('get'))
+ end
+ def value= (val)
+ tk_send_without_enc('delete', 0, 'end')
+ tk_send_without_enc('insert', 0, _get_eval_enc_str(val))
+ val
+ end
+ alias get value
+ alias set value=
+
+ def cursor=(index)
+ tk_send_without_enc('icursor', index)
+ #self
+ index
+ end
+ alias icursor cursor=
+
+ def index(index)
+ number(tk_send_without_enc('index', index))
+ end
+
+ def insert(pos,text)
+ tk_send_without_enc('insert', pos, _get_eval_enc_str(text))
+ self
+ end
+
+ def mark(pos)
+ tk_send_without_enc('scan', 'mark', pos)
+ self
+ end
+ def dragto(pos)
+ tk_send_without_enc('scan', 'dragto', pos)
+ self
+ end
+ def selection_adjust(index)
+ tk_send_without_enc('selection', 'adjust', index)
+ self
+ end
+ def selection_clear
+ tk_send_without_enc('selection', 'clear')
+ self
+ end
+ def selection_from(index)
+ tk_send_without_enc('selection', 'from', index)
+ self
+ end
+ def selection_present()
+ bool(tk_send_without_enc('selection', 'present'))
+ end
+ def selection_range(s, e)
+ tk_send_without_enc('selection', 'range', s, e)
+ self
+ end
+ def selection_to(index)
+ tk_send_without_enc('selection', 'to', index)
+ self
+ end
+
+ # based on tk/scrollable.rb
+ def xview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('xview'))
+ else
+ tk_send_without_enc('xview', *index)
+ self
+ end
+ end
+ def xview_moveto(*index)
+ xview('moveto', *index)
+ end
+ def xview_scroll(*index)
+ xview('scroll', *index)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/extbutton.rb b/ext/tk/lib/tkextlib/iwidgets/extbutton.rb
new file mode 100644
index 0000000000..158d9d474a
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/extbutton.rb
@@ -0,0 +1,40 @@
+#
+# tkextlib/iwidgets/extbutton.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Extbutton < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Extbutton
+ TkCommandNames = ['::iwidgets::extbutton'.freeze].freeze
+ WidgetClassName = 'Extbutton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'bitmapforeground' << 'ringbackground'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'defaultring'
+ end
+ private :__boolval_optkeys
+
+ def invoke
+ tk_call(@path, 'invoke')
+ self
+ end
+
+ def flash
+ tk_call(@path, 'flash')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb
new file mode 100644
index 0000000000..501f4c90a0
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb
@@ -0,0 +1,46 @@
+#
+# tkextlib/iwidgets/extfileselectionbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Extfileselectionbox < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Extfileselectionbox
+ TkCommandNames = ['::iwidgets::extfileselectionbox'.freeze].freeze
+ WidgetClassName = 'Extfileselectionbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() + [
+ 'dirslabel', 'fileslabel', 'filterlabel', 'mask', 'nomatchstring',
+ 'selectionlabel'
+ ]
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() + ['dirson', 'fileson', 'filteron', 'selectionon']
+ end
+ private :__boolval_optkeys
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def filter
+ tk_call(@path, 'filter')
+ self
+ end
+
+ def get
+ tk_call(@path, 'get')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb
new file mode 100644
index 0000000000..14388be7c4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb
@@ -0,0 +1,33 @@
+#
+# tkextlib/iwidgets/extfileselectiondialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Extfileselectiondialog < Tk::Iwidgets::Dialog
+ end
+ end
+end
+
+class Tk::Iwidgets::Extfileselectiondialog
+ TkCommandNames = ['::iwidgets::extfileselectiondialog'.freeze].freeze
+ WidgetClassName = 'Extfileselectiondialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def filter
+ tk_call(@path, 'filter')
+ self
+ end
+
+ def get
+ tk_call(@path, 'get')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/feedback.rb b/ext/tk/lib/tkextlib/iwidgets/feedback.rb
new file mode 100644
index 0000000000..0a25237a24
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/feedback.rb
@@ -0,0 +1,35 @@
+#
+# tkextlib/iwidgets/feedback.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Feedback < Tk::Iwidgets::Labeledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Feedback
+ TkCommandNames = ['::iwidgets::feedback'.freeze].freeze
+ WidgetClassName = 'Feedback'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'barcolor'
+ end
+ private :__strval_optkeys
+
+ def reset
+ tk_call(@path, 'reset')
+ self
+ end
+
+ def step(inc=1)
+ tk_call(@path, 'step', inc)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb
new file mode 100644
index 0000000000..7b331d0b40
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb
@@ -0,0 +1,46 @@
+#
+# tkextlib/iwidgets/fileselectionbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Fileselectionbox < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Fileselectionbox
+ TkCommandNames = ['::iwidgets::fileselectionbox'.freeze].freeze
+ WidgetClassName = 'Fileselectionbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() + [
+ 'directory', 'dirslabel', 'fileslabel', 'filterlabel', 'mask',
+ 'nomatchstring', 'selectionlabel'
+ ]
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() + ['dirson', 'fileson', 'filteron', 'selectionon']
+ end
+ private :__boolval_optkeys
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def filter
+ tk_call(@path, 'filter')
+ self
+ end
+
+ def get
+ tk_call(@path, 'get')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb
new file mode 100644
index 0000000000..50f459e56d
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb
@@ -0,0 +1,33 @@
+#
+# tkextlib/iwidgets/fileselectiondialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Fileselectiondialog < Tk::Iwidgets::Dialog
+ end
+ end
+end
+
+class Tk::Iwidgets::Fileselectiondialog
+ TkCommandNames = ['::iwidgets::fileselectiondialog'.freeze].freeze
+ WidgetClassName = 'Fileselectiondialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def filter
+ tk_call(@path, 'filter')
+ self
+ end
+
+ def get
+ tk_call(@path, 'get')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/finddialog.rb b/ext/tk/lib/tkextlib/iwidgets/finddialog.rb
new file mode 100644
index 0000000000..75e219c37e
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/finddialog.rb
@@ -0,0 +1,42 @@
+#
+# tkextlib/iwidgets/finddialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Finddialog < Tk::Iwidgets::Dialogshell
+ end
+ end
+end
+
+class Tk::Iwidgets::Finddialog
+ TkCommandNames = ['::iwidgets::finddialog'.freeze].freeze
+ WidgetClassName = 'Finddialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() + [
+ 'patternbackground', 'patternforeground',
+ 'searchbackground', 'searchforeground'
+ ]
+ end
+ private :__strval_optkeys
+
+ def __val2ruby_optkeys # { key=>proc, ... }
+ super().update('textwidget'=>proc{|v| window(v)})
+ end
+ private :__val2ruby_optkeys
+
+ def clear
+ tk_call(@path, 'clear')
+ self
+ end
+
+ def find
+ tk_call(@path, 'find')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
new file mode 100644
index 0000000000..d9220fecbf
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
@@ -0,0 +1,365 @@
+#
+# tkextlib/iwidgets/hierarchy.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/text'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Hierarchy < Tk::Iwidgets::Scrolledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Hierarchy
+ ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze
+ include TkTextTagConfig
+
+ TkCommandNames = ['::iwidgets::hierarchy'.freeze].freeze
+ WidgetClassName = 'Hierarchy'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include Tk::ValidateConfigure
+
+ class QueryCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [ [?n, ?s, :node], nil ]
+ PROC_TBL = [ [?s, TkComm.method(:string) ], nil ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ # array of config-option key (string or symbol)
+ ['querycommand']
+ end
+ end
+
+ class IndicatorCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?n, ?s, :node ],
+ [ ?s, ?b, :status ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?s, TkComm.method(:string) ],
+ [ ?b, TkComm.method(:bool) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ # array of config-option key (string or symbol)
+ ['iconcommand', 'icondblcommand', 'imagedblcommand']
+ end
+ end
+
+ class IconCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?n, ?s, :node ],
+ [ ?i, ?s, :icon ],
+ nil
+ ]
+ PROC_TBL = [ [ ?s, TkComm.method(:string) ], nil ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ # array of config-option key (string or symbol)
+ ['dblclickcommand', 'imagecommand', 'selectcommand']
+ end
+ end
+
+ def __validation_class_list
+ super() << QueryCommand << IndicatorCommand << IconCommand
+ end
+
+ Tk::ValidateConfigure.__def_validcmd(binding, QueryCommand)
+ Tk::ValidateConfigure.__def_validcmd(binding, IndicatorCommand)
+ Tk::ValidateConfigure.__def_validcmd(binding, IconCommand)
+
+ ####################################
+
+ def __boolval_optkeys
+ super() << 'alwaysquery' << 'expanded' << 'filter'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'markbackground' << 'markforeground' << 'textbackground'
+ end
+ private :__strval_optkeys
+
+ def __font_optkeys
+ super() << 'textfont'
+ end
+ private :__font_optkeys
+
+ def clear
+ tk_call(@path, 'clear')
+ self
+ end
+
+ def collapse(node)
+ tk_call(@path, 'collapse')
+ self
+ end
+
+ def current
+ tk_call(@path, 'current')
+ end
+
+ def draw(mode=None)
+ case mode
+ when None
+ # do nothing
+ when 'now', :now
+ mode = '-now'
+ when 'eventually', :eventually
+ mode = '-eventually'
+ when String, Symbol
+ mode = mode.to_s
+ mode = '-' << mode if mode[0] != ?-
+ end
+ tk_call(@path, 'draw', mode)
+ end
+
+ def expand(node)
+ tk_call(@path, 'expand', node)
+ self
+ end
+
+ def expanded?(node)
+ bool(tk_call(@path, 'expanded', node))
+ end
+
+ def exp_state
+ list(tk_call(@path, 'expState'))
+ end
+ alias expand_state exp_state
+ alias expanded_list exp_state
+
+ def mark_clear
+ tk_call(@path, 'mark', 'clear')
+ self
+ end
+ def mark_add(*nodes)
+ tk_call(@path, 'mark', 'add', *nodes)
+ self
+ end
+ def mark_remove(*nodes)
+ tk_call(@path, 'mark', 'remove', *nodes)
+ self
+ end
+ def mark_get
+ list(tk_call(@path, 'mark', 'get'))
+ end
+
+ def refresh(node)
+ tk_call(@path, 'refresh', node)
+ self
+ end
+
+ def prune(node)
+ tk_call(@path, 'prune', node)
+ self
+ end
+
+ def selection_clear
+ tk_call(@path, 'selection', 'clear')
+ self
+ end
+ def selection_add(*nodes)
+ tk_call(@path, 'selection', 'add', *nodes)
+ self
+ end
+ def selection_remove(*nodes)
+ tk_call(@path, 'selection', 'remove', *nodes)
+ self
+ end
+ def selection_get
+ list(tk_call(@path, 'selection', 'get'))
+ end
+
+ def toggle(node)
+ tk_call(@path, 'toggle', node)
+ self
+ end
+
+ # based on Tk::Text widget
+
+ def bbox(index)
+ list(tk_send_without_enc('bbox', _get_eval_enc_str(index)))
+ end
+
+ def compare(idx1, op, idx2)
+ bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1),
+ op, _get_eval_enc_str(idx2)))
+ end
+
+ def debug
+ bool(tk_send_without_enc('debug'))
+ end
+ def debug=(boolean)
+ tk_send_without_enc('debug', boolean)
+ #self
+ boolean
+ end
+
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+
+ def dlineinfo(index)
+ list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index)))
+ end
+
+ def get(*index)
+ _fromUTF8(tk_send_without_enc('get', *index))
+ end
+
+ def index(index)
+ tk_send_without_enc('index', _get_eval_enc_str(index))
+ end
+
+ def insert(index, chars, *tags)
+ if tags[0].kind_of? Array
+ # multiple chars-taglist argument :: str, [tag,...], str, [tag,...], ...
+ args = [chars]
+ while tags.size > 0
+ args << tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist
+ args << tags.shift if tags.size > 0 # chars
+ end
+ super(index, *args)
+ else
+ # single chars-taglist argument :: str, tag, tag, ...
+ if tags.size == 0
+ super(index, chars)
+ else
+ super(index, chars, tags.collect{|x|_get_eval_string(x)}.join(' '))
+ end
+ end
+ end
+
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send_without_enc('scan', 'dragto', x, y)
+ self
+ end
+ def see(index)
+ tk_send_without_enc('see', index)
+ self
+ end
+
+ # based on tk/scrollable.rb
+ def xview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('xview'))
+ else
+ tk_send_without_enc('xview', *index)
+ 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'))
+ else
+ tk_send_without_enc('yview', *index)
+ self
+ end
+ end
+ def yview_moveto(*index)
+ yview('moveto', *index)
+ end
+ def yview_scroll(*index)
+ yview('scroll', *index)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb b/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb
new file mode 100644
index 0000000000..77b0e090cd
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb
@@ -0,0 +1,50 @@
+#
+# tkextlib/iwidgets/hyperhelp.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Hyperhelp < Tk::Iwidgets::Shell
+ end
+ end
+end
+
+class Tk::Iwidgets::Hyperhelp
+ TkCommandNames = ['::iwidgets::hyperhelp'.freeze].freeze
+ WidgetClassName = 'Hyperhelp'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'helpdir'
+ end
+ private :__strval_optkeys
+
+ def __listval_optkeys
+ super() << 'topics'
+ end
+ private :__listval_optkeys
+
+ def show_topic(topic)
+ tk_call(@path, 'showtopic', topic)
+ self
+ end
+
+ def follow_link(href)
+ tk_call(@path, 'followlink', href)
+ self
+ end
+
+ def forward
+ tk_call(@path, 'forward')
+ self
+ end
+
+ def back
+ tk_call(@path, 'back')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb b/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb
new file mode 100644
index 0000000000..e77e85045d
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb
@@ -0,0 +1,39 @@
+#
+# tkextlib/iwidgets/labeledframe.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Labeledframe < Tk::Itk::Archetype
+ end
+ end
+end
+
+class Tk::Iwidgets::Labeledframe
+ TkCommandNames = ['::iwidgets::labeledframe'.freeze].freeze
+ WidgetClassName = 'Labeledframe'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'labeltext'
+ end
+ private :__strval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'labelvariable'
+ end
+ private :__tkvariable_optkeys
+
+ def __font_optkeys
+ super() << 'labelfont'
+ end
+ private :__font_optkeys
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb b/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb
new file mode 100644
index 0000000000..99387710cb
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb
@@ -0,0 +1,45 @@
+#
+# tkextlib/iwidgets/labeledwidget.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Labeledwidget < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Labeledwidget
+ extend TkCore
+
+ TkCommandNames = ['::iwidgets::labeledwidget'.freeze].freeze
+ WidgetClassName = 'Labeledwidget'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'labeltext'
+ end
+ private :__strval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'labelvariable'
+ end
+ private :__tkvariable_optkeys
+
+ def __font_optkeys
+ super() << 'labelfont'
+ end
+ private :__font_optkeys
+
+ def self.alignlabels(*wins)
+ tk_call('::iwidgets::Labeledwidget::alignlabels', *wins)
+ end
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb b/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb
new file mode 100644
index 0000000000..4b2541b997
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb
@@ -0,0 +1,67 @@
+#
+# tkextlib/iwidgets/mainwindow.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Mainwindow < Tk::Iwidgets::Shell
+ end
+ end
+end
+
+class Tk::Iwidgets::Mainwindow
+ TkCommandNames = ['::iwidgets::mainwindow'.freeze].freeze
+ WidgetClassName = 'Mainwindow'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'helpline' << 'statusline'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'menubarbackground' << 'menubarforeground' << 'toolbarforeground'
+ end
+ private :__strval_optkeys
+
+ def __font_optkeys
+ super() << 'menubarfont' << 'toolbarfont'
+ end
+ private :__font_optkeys
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def menubar(*args)
+ unless args.empty?
+ tk_call(@path, 'menubar', *args)
+ end
+ window(tk_call(@path, 'menubar'))
+ end
+
+ def mousebar(*args)
+ unless args.empty?
+ tk_call(@path, 'mousebar', *args)
+ end
+ window(tk_call(@path, 'mousebar'))
+ end
+
+ def msgd(*args)
+ unless args.empty?
+ tk_call(@path, 'msgd', *args)
+ end
+ window(tk_call(@path, 'msgd'))
+ end
+
+ def toolbar(*args)
+ unless args.empty?
+ tk_call(@path, 'toolbar', *args)
+ end
+ window(tk_call(@path, 'toolbar'))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/menubar.rb b/ext/tk/lib/tkextlib/iwidgets/menubar.rb
new file mode 100644
index 0000000000..5aaefbe50d
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/menubar.rb
@@ -0,0 +1,211 @@
+#
+# tkextlib/iwidgets/menubar.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Menubar < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Menubar
+ TkCommandNames = ['::iwidgets::menubar'.freeze].freeze
+ WidgetClassName = 'Menubar'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'menubuttons'
+ end
+ private :__strval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'helpvariable'
+ end
+ private :__tkvariable_optkeys
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'menucget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'menuconfigure', id]
+ end
+ private :__item_config_cmd
+
+ def __item_strval_optkeys(id)
+ super(id) << 'selectcolor'
+ end
+ private :__item_strval_optkeys
+
+ def __item_tkvariable_optkeys(id)
+ super(id) << 'helpstr'
+ end
+ private :__item_tkvariable_optkeys
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ alias menucget itemcget
+ alias menucget_strict itemcget_strict
+ alias menuconfigure itemconfigure
+ alias menuconfiginfo itemconfiginfo
+ alias current_menuconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def __methodcall_optkeys
+ {'menubuttons'=>'menubuttons'}
+ end
+
+ def menubuttons(val = nil)
+ unless val
+ return tk_call(@path, 'cget', '-menubuttons')
+ end
+
+ tk_call(@path, 'configure', '-menubuttons', _parse_menu_spec(val))
+ self
+ end
+
+ def _parse_menu_spec(menu_spec)
+ ret = ''
+ menu_spec.each{|spec|
+ next unless spec
+
+ if spec.kind_of?(Hash)
+ args = [spec]
+ type = 'options'
+ else
+ type, *args = spec
+ end
+
+ type = type.to_s
+ case type
+ when 'options'
+ keys = args[0]
+ ary = [type]
+ ary.concat(hash_kv(keys))
+ ret << array2tk_list(ary) << "\n"
+
+ when 'menubutton', 'cascade'
+ name, keys = args
+ if keys
+ ary = [type, name]
+ keys = _symbolkey2str(keys)
+ keys['menu'] = _parse_menu_spec(keys['menu']) if keys.key?('menu')
+ ary.concat(hash_kv(keys))
+ ret << array2tk_list(ary) << "\n"
+ else
+ ret << array2tk_list([type, name]) << "\n"
+ end
+
+ else
+ name, keys = args
+ if keys
+ ary = [type, name]
+ ary.concat(hash_kv(keys))
+ ret << array2tk_list(ary) << "\n"
+ else
+ ret << array2tk_list([type, name]) << "\n"
+ end
+ end
+ }
+ ret
+ end
+
+ ####################################
+
+ def add(type, tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ keys = _symbolkey2str(keys)
+ keys['menu'] = _parse_menu_spec(keys['menu']) if keys.key?('menu')
+ tk_call(@path, 'add', type, tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def delete(path1, path2=nil)
+ if path2
+ else
+ tk_call(@path, 'delete', index(idx))
+ end
+ self
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', tagid(idx)))
+ end
+
+ def insert(idx, type, tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ keys = _symbolkey2str(keys)
+ keys['menu'] = _parse_menu_spec(keys['menu']) if keys.key?('menu')
+ tk_call(@path, 'insert', index(idx), type, tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def invoke(idx)
+ tk_call(@path, 'invoke', index(idx))
+ self
+ end
+
+ def menupath(pat)
+ if (win = tk_call(@path, 'path', pat)) == '-1'
+ return nil
+ end
+ window(win)
+ end
+ def menupath_glob(pat)
+ if (win = tk_call(@path, 'path', '-glob', pat)) == '-1'
+ return nil
+ end
+ window(win)
+ end
+ def menupath_tclregexp(pat)
+ if (win = tk_call(@path, 'path', '-regexp', pat)) == '-1'
+ return nil
+ end
+ window(win)
+ end
+
+ def type(path)
+ tk_call(@path, 'type', path)
+ end
+
+ def yposition(path)
+ number(tk_call(@path, 'yposition', path))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/messagebox.rb b/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
new file mode 100644
index 0000000000..98ac32900c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
@@ -0,0 +1,92 @@
+#
+# tkextlib/iwidgets/messagebox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Messagebox < Tk::Iwidgets::Scrolledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Messagebox
+ TkCommandNames = ['::iwidgets::messagebox'.freeze].freeze
+ WidgetClassName = 'Messagebox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'type', 'cget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'type', 'configure', id]
+ end
+ private :__item_config_cmd
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ def __item_boolval_optkeys(id)
+ super(id) << 'bell' << 'show'
+ end
+ private :__item_boolval_optkeys
+
+ alias typecget itemcget
+ alias typecget_strict itemcget_strict
+ alias typeconfigure itemconfigure
+ alias typeconfiginfo itemconfiginfo
+ alias current_typeconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def __strval_optkeys
+ super() << 'filename' << 'savedir'
+ end
+ private :__strval_optkeys
+
+ def type_add(tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ unless tag
+ tag = Tk::Itk::Component.new(self)
+ end
+ tk_call(@path, 'type', 'add', tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def clear
+ tk_call(@path, 'clear')
+ self
+ end
+
+ def export(file)
+ tk_call(@path, 'export', file)
+ self
+ end
+
+ def issue(string, type=None, *args)
+ tk_call(@path, 'issue', string, tagid(type), *args)
+ self
+ end
+
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb b/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb
new file mode 100644
index 0000000000..c19b83e517
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb
@@ -0,0 +1,20 @@
+#
+# tkextlib/iwidgets/messagedialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Messagedialog < Tk::Iwidgets::Dialog
+ end
+ end
+end
+
+class Tk::Iwidgets::Messagedialog
+ TkCommandNames = ['::iwidgets::messagedialog'.freeze].freeze
+ WidgetClassName = 'Messagedialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/notebook.rb b/ext/tk/lib/tkextlib/iwidgets/notebook.rb
new file mode 100644
index 0000000000..03b50633df
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/notebook.rb
@@ -0,0 +1,174 @@
+#
+# tkextlib/iwidgets/notebook.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Notebook < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Notebook
+ TkCommandNames = ['::iwidgets::notebook'.freeze].freeze
+ WidgetClassName = 'Notebook'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'pagecget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'pageconfigure', id]
+ end
+ private :__item_config_cmd
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ alias pagecget itemcget
+ alias pagecget_strict itemcget_strict
+ alias pageconfigure itemconfigure
+ alias pageconfiginfo itemconfiginfo
+ alias current_pageconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def __boolval_optkeys
+ super() << 'auto'
+ end
+ private :__boolval_optkeys
+
+ def add(keys={})
+ window(tk_call(@path, 'add', *hash_kv(keys)))
+ end
+
+ def child_site_list
+ list(tk_call(@path, 'childsite'))
+ end
+
+ def child_site(idx)
+ if (new_idx = self.index(idx)) < 0
+ new_idx = tagid(idx)
+ end
+ window(tk_call(@path, 'childsite', new_idx))
+ end
+
+ def delete(idx1, idx2=nil)
+ if (new_idx1 = self.index(idx1)) < 0
+ new_idx1 = tagid(idx1)
+ end
+ if idx2
+ if (new_idx2 = self.index(idx2)) < 0
+ new_idx2 = tagid(idx2)
+ end
+ tk_call(@path, 'delete', new_idx1, new_idx2)
+ else
+ tk_call(@path, 'delete', new_idx1)
+ end
+ self
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', tagid(idx)))
+ end
+
+ def insert(idx, keys={})
+ if (new_idx = self.index(idx)) < 0
+ new_idx = tagid(idx)
+ end
+ window(tk_call(@path, 'insert', new_idx, *hash_kv(keys)))
+ end
+
+ def next
+ tk_call(@path, 'next')
+ self
+ end
+
+ def prev
+ tk_call(@path, 'prev')
+ self
+ end
+
+ def select(idx)
+ if (new_idx = self.index(idx)) < 0
+ new_idx = tagid(idx)
+ end
+ tk_call(@path, 'select', new_idx)
+ self
+ end
+
+ def scrollcommand(cmd=Proc.new)
+ configure_cmd 'scrollcommand', cmd
+ self
+ end
+ alias xscrollcommand scrollcommand
+ alias yscrollcommand scrollcommand
+
+ def xscrollbar(bar=nil)
+ if bar
+ @scrollbar = bar
+ @scrollbar.orient 'horizontal'
+ self.scrollcommand {|*arg| @scrollbar.set(*arg)}
+ @scrollbar.command {|*arg| self.xview(*arg)}
+ Tk.update # avoid scrollbar trouble
+ end
+ @scrollbar
+ end
+ def yscrollbar(bar=nil)
+ if bar
+ @scrollbar = bar
+ @scrollbar.orient 'vertical'
+ self.scrollcommand {|*arg| @scrollbar.set(*arg)}
+ @scrollbar.command {|*arg| self.yview(*arg)}
+ Tk.update # avoid scrollbar trouble
+ end
+ @scrollbar
+ end
+ alias scrollbar yscrollbar
+
+ def view(*idxs)
+ if idxs.size == 0
+ idx = num_or_str(tk_send_without_enc('view'))
+ if idx.kind_of?(Fixnum) && idx < 0
+ nil
+ else
+ idx
+ end
+ else
+ tk_send_without_enc('view', *idxs)
+ self
+ end
+ end
+ alias xview view
+ alias yview view
+
+ def view_moveto(*idxs)
+ view('moveto', *idxs)
+ end
+ alias xview_moveto view_moveto
+ alias yview_moveto view_moveto
+ def view_scroll(index, what='pages')
+ view('scroll', index, what)
+ end
+ alias xview_scroll view_scroll
+ alias yview_scroll view_scroll
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb b/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb
new file mode 100644
index 0000000000..0c74440be7
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb
@@ -0,0 +1,92 @@
+#
+# tkextlib/iwidgets/optionmenu.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Optionmenu < Tk::Iwidgets::Labeledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Optionmenu
+ TkCommandNames = ['::iwidgets::optionmenu'.freeze].freeze
+ WidgetClassName = 'Optionmenu'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'cyclicon'
+ end
+ private :__boolval_optkeys
+
+ def delete(first, last=nil)
+ if last
+ tk_call(@path, 'delete', first, last)
+ else
+ tk_call(@path, 'delete', first)
+ end
+ self
+ end
+
+ def disable(idx)
+ tk_call(@path, 'disable', idx)
+ self
+ end
+
+ def enable(idx)
+ tk_call(@path, 'enable', idx)
+ self
+ end
+
+ def get(first=nil, last=nil)
+ if last
+ simplelist(tk_call(@path, 'get', first, last))
+ elsif first
+ tk_call(@path, 'get', first)
+ else
+ tk_call(@path, 'get')
+ end
+ end
+ def get_range(first, last)
+ get(first, last)
+ end
+ def get_selected
+ get()
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', idx))
+ end
+
+ def insert(idx, *args)
+ tk_call(@path, 'insert', idx, *args)
+ self
+ end
+
+ def select(idx)
+ tk_call(@path, 'select', idx)
+ self
+ end
+
+ def sort(*params, &b)
+ # see 'lsort' man page about params
+ if b
+ tk_call(@path, 'sort', '-command', proc(&b), *params)
+ else
+ tk_call(@path, 'sort', *params)
+ end
+ self
+ end
+ def sort_ascending
+ tk_call(@path, 'sort', 'ascending')
+ self
+ end
+ def sort_descending
+ tk_call(@path, 'sort', 'descending')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb b/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
new file mode 100644
index 0000000000..3bf73d69fe
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
@@ -0,0 +1,133 @@
+#
+# tkextlib/iwidgets/panedwindow.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Panedwindow < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Panedwindow
+ TkCommandNames = ['::iwidgets::panedwindow'.freeze].freeze
+ WidgetClassName = 'Panedwindow'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'panecget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'paneconfigure', id]
+ end
+ private :__item_config_cmd
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ alias panecget itemcget
+ alias panecget_strict itemcget_strict
+ alias paneconfigure itemconfigure
+ alias paneconfiginfo itemconfiginfo
+ alias current_paneconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def __boolval_optkeys
+ super() << 'showhandle'
+ end
+ private :__boolval_optkeys
+
+ def add(tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ window(tk_call(@path, 'add', tagid(tag), *hash_kv(keys)))
+ tag
+ end
+
+ def child_site_list
+ list(tk_call(@path, 'childsite'))
+ end
+
+ def child_site(idx)
+ window(tk_call(@path, 'childsite', index(idx)))
+ end
+
+ def delete(idx)
+ tk_call(@path, 'delete', index(idx))
+ self
+ end
+
+ def fraction(*percentages)
+ tk_call(@path, 'fraction', *percentages)
+ self
+ end
+
+ def hide(idx)
+ tk_call(@path, 'hide', index(idx))
+ self
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', tagid(idx)))
+ end
+
+ def insert(idx, tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ window(tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys)))
+ tag
+ end
+
+ def invoke(idx=nil)
+ if idx
+ tk_call(@path, 'invoke', index(idx))
+ else
+ tk_call(@path, 'invoke')
+ end
+ self
+ end
+
+ def reset
+ tk_call(@path, 'reset')
+ self
+ end
+
+ def show(idx)
+ tk_call(@path, 'show', index(idx))
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb b/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb
new file mode 100644
index 0000000000..620b14b5d5
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb
@@ -0,0 +1,131 @@
+#
+# tkextlib/iwidgets/promptdialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Promptdialog < Tk::Iwidgets::Dialog
+ end
+ end
+end
+
+class Tk::Iwidgets::Promptdialog
+ TkCommandNames = ['::iwidgets::promptdialog'.freeze].freeze
+ WidgetClassName = 'Promptdialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ # index method is not available, because it shows index of the entry field
+ def default(name)
+ tk_call(@path, 'default', tagid(name))
+ self
+ end
+
+ def hide(name)
+ tk_call(@path, 'hide', tagid(name))
+ self
+ end
+
+ def invoke(name=nil)
+ if name
+ tk_call(@path, 'invoke', tagid(name))
+ else
+ tk_call(@path, 'invoke')
+ end
+ self
+ end
+
+ def show(name)
+ tk_call(@path, 'show', tagid(name))
+ self
+ end
+
+
+ # based on Tk::Iwidgets::Entryfield
+ def clear
+ tk_call(@path, 'clear')
+ self
+ end
+
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+
+ def value
+ _fromUTF8(tk_send_without_enc('get'))
+ end
+ def value= (val)
+ tk_send_without_enc('delete', 0, 'end')
+ tk_send_without_enc('insert', 0, _get_eval_enc_str(val))
+ val
+ end
+ alias get value
+ alias set value=
+
+ def cursor=(index)
+ tk_send_without_enc('icursor', index)
+ #self
+ index
+ end
+ alias icursor cursor=
+
+ def index(idx)
+ number(tk_send_without_enc('index', idx))
+ end
+
+ def insert(pos,text)
+ tk_send_without_enc('insert', pos, _get_eval_enc_str(text))
+ self
+ end
+
+ def mark(pos)
+ tk_send_without_enc('scan', 'mark', pos)
+ self
+ end
+ def dragto(pos)
+ tk_send_without_enc('scan', 'dragto', pos)
+ self
+ end
+ def selection_adjust(index)
+ tk_send_without_enc('selection', 'adjust', index)
+ self
+ end
+ def selection_clear
+ tk_send_without_enc('selection', 'clear')
+ self
+ end
+ def selection_from(index)
+ tk_send_without_enc('selection', 'from', index)
+ self
+ end
+ def selection_present()
+ bool(tk_send_without_enc('selection', 'present'))
+ end
+ def selection_range(s, e)
+ tk_send_without_enc('selection', 'range', s, e)
+ self
+ end
+ def selection_to(index)
+ tk_send_without_enc('selection', 'to', index)
+ self
+ end
+
+ def xview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('xview'))
+ else
+ tk_send_without_enc('xview', *index)
+ self
+ end
+ end
+ def xview_moveto(*index)
+ xview('moveto', *index)
+ end
+ def xview_scroll(*index)
+ xview('scroll', *index)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb b/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb
new file mode 100644
index 0000000000..c21007ca6c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb
@@ -0,0 +1,35 @@
+#
+# tkextlib/iwidgets/pushbutton.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Pushbutton < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Pushbutton
+ TkCommandNames = ['::iwidgets::pushbutton'.freeze].freeze
+ WidgetClassName = 'Pushbutton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'defaultring'
+ end
+ private :__boolval_optkeys
+
+ def invoke
+ tk_call_without_enc(@path, 'invoke')
+ self
+ end
+
+ def flash
+ tk_call_without_enc(@path, 'flash')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/radiobox.rb b/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
new file mode 100644
index 0000000000..e9d9521252
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
@@ -0,0 +1,120 @@
+#
+# tkextlib/iwidgets/radiobox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Radiobox < Tk::Iwidgets::Labeledframe
+ end
+ end
+end
+
+class Tk::Iwidgets::Radiobox
+ TkCommandNames = ['::iwidgets::radiobox'.freeze].freeze
+ WidgetClassName = 'Radiobox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'buttoncget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'buttonconfigure', id]
+ end
+ private :__item_config_cmd
+
+ def __item_boolval_optkeys(id)
+ super(id) << 'defaultring'
+ end
+ private :__item_boolval_optkeys
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
+ alias buttonconfigure itemconfigure
+ alias buttonconfiginfo itemconfiginfo
+ alias current_buttonconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def add(tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ tk_call(@path, 'add', tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def delete(idx)
+ tk_call(@path, 'delete', index(idx))
+ self
+ end
+
+ def deselect(idx)
+ tk_call(@path, 'deselect', index(idx))
+ self
+ end
+
+ def flash(idx)
+ tk_call(@path, 'flash', index(idx))
+ self
+ end
+
+ def get_tag
+ ((tag = tk_call_without_enc(@path, 'get')).empty?)? nil: tag
+ end
+ alias get get_tag
+
+ def get_obj
+ (tag = get_tag)? Tk::Itk::Component.id2obj(self, tag): nil
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', tagid(idx)))
+ end
+
+ def insert(idx, tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys))
+ tag
+ end
+
+ def select(idx)
+ tk_call(@path, 'select', index(idx))
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb b/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb
new file mode 100644
index 0000000000..bddef50841
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb
@@ -0,0 +1,24 @@
+#
+# tkextlib/iwidgets/buttonbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Scopedobject < TkObject
+ end
+ end
+end
+
+class Tk::Iwidgets::Scopedobject
+ TkCommandNames = ['::iwidgets::scopedobject'.freeze].freeze
+ WidgetClassName = 'Scopedobject'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def initialize(obj_name, keys={})
+ @path = tk_call(self.class::TkCommandNames[0], obj_name, *hash_kv(keys))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
new file mode 100644
index 0000000000..67ad67d07e
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
@@ -0,0 +1,353 @@
+#
+# tkextlib/iwidgets/scrolledcanvas.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/canvas'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Scrolledcanvas < Tk::Iwidgets::Scrolledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Scrolledcanvas
+ TkCommandNames = ['::iwidgets::scrolledcanvas'.freeze].freeze
+ WidgetClassName = 'Scrolledcanvas'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ################################
+
+ def __boolval_optkeys
+ super() << 'autoresize'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'textbackground'
+ end
+ private :__strval_optkeys
+
+ def initialize(*args)
+ super(*args)
+ @canvas = component_widget('canvas')
+ end
+
+ def method_missing(id, *args)
+ if @canvas.respond_to?(id)
+ @canvas.__send__(id, *args)
+ else
+ super(id, *args)
+ end
+ end
+
+ ################################
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def justify(dir)
+ tk_call(@path, 'justify', dir)
+ self
+ end
+
+ ##########################
+ include TkCanvasItemConfig
+
+ def tagid(tag)
+ if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag)
+ tag.id
+ elsif tag.kind_of?(Tk::Itk::Component)
+ tag.name
+ else
+ tag # maybe an Array of configure paramters
+ end
+ end
+ private :tagid
+
+ # create a canvas item without creating a TkcItem object
+ def create(type, *args)
+ type.create(self, *args)
+ end
+
+ #######################
+
+ def addtag(tag, mode, *args)
+ tk_send_without_enc('addtag', tagid(tag), mode, *args)
+ self
+ end
+ def addtag_above(tagOrId, target)
+ addtag(tagOrId, 'above', tagid(target))
+ end
+ def addtag_all(tagOrId)
+ addtag(tagOrId, 'all')
+ end
+ def addtag_below(tagOrId, target)
+ addtag(tagOrId, 'below', tagid(target))
+ end
+ def addtag_closest(tagOrId, x, y, halo=None, start=None)
+ addtag(tagOrId, 'closest', x, y, halo, start)
+ end
+ def addtag_enclosed(tagOrId, x1, y1, x2, y2)
+ addtag(tagOrId, 'enclosed', x1, y1, x2, y2)
+ end
+ def addtag_overlapping(tagOrId, x1, y1, x2, y2)
+ addtag(tagOrId, 'overlapping', x1, y1, x2, y2)
+ end
+ def addtag_withtag(tagOrId, tag)
+ addtag(tagOrId, 'withtag', tagid(tag))
+ end
+
+ def bbox(tagOrId, *tags)
+ list(tk_send_without_enc('bbox', tagid(tagOrId),
+ *tags.collect{|t| tagid(t)}))
+ end
+
+ #def itembind(tag, context, cmd=Proc.new, *args)
+ # _bind([path, "bind", tagid(tag)], context, cmd, *args)
+ # self
+ #end
+ def itembind(tag, context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([path, "bind", tagid(tag)], context, cmd, *args)
+ self
+ end
+
+ #def itembind_append(tag, context, cmd=Proc.new, *args)
+ # _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
+ # self
+ #end
+ def itembind_append(tag, context, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([path, "bind", tagid(tag)], context, cmd, *args)
+ self
+ end
+
+ def itembind_remove(tag, context)
+ _bind_remove([path, "bind", tagid(tag)], context)
+ self
+ end
+
+ def itembindinfo(tag, context=nil)
+ _bindinfo([path, "bind", tagid(tag)], context)
+ end
+
+ def canvasx(screen_x, *args)
+ #tk_tcl2ruby(tk_send_without_enc('canvasx', screen_x, *args))
+ number(tk_send_without_enc('canvasx', screen_x, *args))
+ end
+ def canvasy(screen_y, *args)
+ #tk_tcl2ruby(tk_send_without_enc('canvasy', screen_y, *args))
+ number(tk_send_without_enc('canvasy', screen_y, *args))
+ end
+
+ def coords(tag, *args)
+ if args == []
+ tk_split_list(tk_send_without_enc('coords', tagid(tag)))
+ else
+ tk_send_without_enc('coords', tagid(tag), *(args.flatten))
+ self
+ end
+ end
+
+ def dchars(tag, first, last=None)
+ tk_send_without_enc('dchars', tagid(tag),
+ _get_eval_enc_str(first), _get_eval_enc_str(last))
+ self
+ end
+
+ def delete(*args)
+ tbl = nil
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl = TkcItem::CItemID_TBL[self.path]
+ }
+ if tbl
+ find('withtag', *args).each{|item|
+ if item.kind_of?(TkcItem)
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl.delete(item.id)
+ }
+ end
+ }
+ end
+ tk_send_without_enc('delete', *args.collect{|t| tagid(t)})
+ self
+ end
+ alias remove delete
+
+ def dtag(tag, tag_to_del=None)
+ tk_send_without_enc('dtag', tagid(tag), tag_to_del)
+ self
+ end
+
+ def find(mode, *args)
+ list(tk_send_without_enc('find', mode, *args)).collect!{|id|
+ TkcItem.id2obj(self, id)
+ }
+ end
+ def find_above(target)
+ find('above', tagid(target))
+ end
+ def find_all
+ find('all')
+ end
+ def find_below(target)
+ find('below', tagid(target))
+ end
+ def find_closest(x, y, halo=None, start=None)
+ find('closest', x, y, halo, start)
+ end
+ def find_enclosed(x1, y1, x2, y2)
+ find('enclosed', x1, y1, x2, y2)
+ end
+ def find_overlapping(x1, y1, x2, y2)
+ find('overlapping', x1, y1, x2, y2)
+ end
+ def find_withtag(tag)
+ find('withtag', tag)
+ end
+
+ def itemfocus(tagOrId=nil)
+ if tagOrId
+ tk_send_without_enc('focus', tagid(tagOrId))
+ self
+ else
+ ret = tk_send_without_enc('focus')
+ if ret == ""
+ nil
+ else
+ TkcItem.id2obj(self, ret)
+ end
+ end
+ end
+
+ def gettags(tagOrId)
+ list(tk_send_without_enc('gettags', tagid(tagOrId))).collect{|tag|
+ TkcTag.id2obj(self, tag)
+ }
+ end
+
+ def icursor(tagOrId, index)
+ tk_send_without_enc('icursor', tagid(tagOrId), index)
+ self
+ end
+
+ def index(tagOrId, idx)
+ number(tk_send_without_enc('index', tagid(tagOrId), idx))
+ end
+
+ def insert(tagOrId, index, string)
+ tk_send_without_enc('insert', tagid(tagOrId), index,
+ _get_eval_enc_str(string))
+ self
+ end
+
+ def lower(tag, below=nil)
+ if below
+ tk_send_without_enc('lower', tagid(tag), tagid(below))
+ else
+ tk_send_without_enc('lower', tagid(tag))
+ end
+ self
+ end
+
+ def move(tag, x, y)
+ tk_send_without_enc('move', tagid(tag), x, y)
+ self
+ end
+
+ def postscript(keys)
+ tk_send("postscript", *hash_kv(keys))
+ end
+
+ def raise(tag, above=nil)
+ if above
+ tk_send_without_enc('raise', tagid(tag), tagid(above))
+ else
+ tk_send_without_enc('raise', tagid(tag))
+ end
+ self
+ end
+
+ def scale(tag, x, y, xs, ys)
+ tk_send_without_enc('scale', tagid(tag), x, y, xs, ys)
+ self
+ end
+
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send_without_enc('scan', 'dragto', x, y)
+ self
+ end
+
+ def select(mode, *args)
+ r = tk_send_without_enc('select', mode, *args)
+ (mode == 'item')? TkcItem.id2obj(self, r): self
+ end
+ def select_adjust(tagOrId, index)
+ select('adjust', tagid(tagOrId), index)
+ end
+ def select_clear
+ select('clear')
+ end
+ def select_from(tagOrId, index)
+ select('from', tagid(tagOrId), index)
+ end
+ def select_item
+ select('item')
+ end
+ def select_to(tagOrId, index)
+ select('to', tagid(tagOrId), index)
+ end
+
+ def itemtype(tag)
+ TkcItem.type2class(tk_send('type', tagid(tag)))
+ end
+
+ def xview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('xview'))
+ else
+ tk_send_without_enc('xview', *index)
+ 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'))
+ else
+ tk_send_without_enc('yview', *index)
+ self
+ end
+ end
+ def yview_moveto(*index)
+ yview('moveto', *index)
+ end
+ def yview_scroll(*index)
+ yview('scroll', *index)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb
new file mode 100644
index 0000000000..8b47460357
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb
@@ -0,0 +1,59 @@
+#
+# tkextlib/iwidgets/scrolledframe.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Scrolledframe < Tk::Iwidgets::Scrolledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Scrolledframe
+ TkCommandNames = ['::iwidgets::scrolledframe'.freeze].freeze
+ WidgetClassName = 'Scrolledframe'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def justify(dir)
+ tk_call(@path, 'justify', dir)
+ self
+ end
+
+ def xview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('xview'))
+ else
+ tk_send_without_enc('xview', *index)
+ 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'))
+ else
+ tk_send_without_enc('yview', *index)
+ self
+ end
+ end
+ def yview_moveto(*index)
+ yview('moveto', *index)
+ end
+ def yview_scroll(*index)
+ yview('scroll', *index)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb
new file mode 100644
index 0000000000..9b69ef07fe
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb
@@ -0,0 +1,58 @@
+#
+# tkextlib/iwidgets/scrolledhtml.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Scrolledhtml < Tk::Iwidgets::Scrolledtext
+ end
+ end
+end
+
+class Tk::Iwidgets::Scrolledhtml
+ TkCommandNames = ['::iwidgets::scrolledhtml'.freeze].freeze
+ WidgetClassName = 'Scrolledhtml'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'update'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'fontname' << 'link' << 'alink' << 'textbackground'
+ end
+ private :__strval_optkeys
+
+ def __font_optkeys
+ super() << 'fixedfont'
+ end
+ private :__font_optkeys
+
+ def import(href)
+ tk_call(@path, 'import', href)
+ self
+ end
+
+ def import_link(href)
+ tk_call(@path, 'import', '-link', href)
+ self
+ end
+
+ def pwd
+ tk_call(@path, 'pwd')
+ end
+
+ def render(htmltext, workdir=None)
+ tk_call(@path, 'render', htmltext, workdir)
+ self
+ end
+
+ def title
+ tk_call(@path, 'title')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
new file mode 100644
index 0000000000..7543d557e3
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
@@ -0,0 +1,207 @@
+#
+# tkextlib/iwidgets/scrolledlistbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/listbox'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Scrolledlistbox < Tk::Iwidgets::Scrolledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Scrolledlistbox
+ TkCommandNames = ['::iwidgets::scrolledlistbox'.freeze].freeze
+ WidgetClassName = 'Scrolledlistbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'textbackground'
+ end
+ private :__strval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'listvariable'
+ end
+ private :__tkvariable_optkeys
+
+ def __font_optkeys
+ super() << 'textfont'
+ end
+ private :__font_optkeys
+
+ ################################
+
+ def initialize(*args)
+ super(*args)
+ @listbox = component_widget('listbox')
+ end
+
+ def method_missing(id, *args)
+ if @listbox.respond_to?(id)
+ @listbox.__send__(id, *args)
+ else
+ super(id, *args)
+ end
+ end
+
+ ################################
+
+ def clear
+ tk_call(@path, 'clear')
+ self
+ end
+
+ def get_curselection
+ tk_call(@path, 'getcurselection')
+ end
+
+ def justify(dir)
+ tk_call(@path, 'justify', dir)
+ self
+ end
+
+ def selected_item_count
+ number(tk_call(@path, 'selecteditemcount'))
+ end
+
+ def sort(*params, &b)
+ # see 'lsort' man page about params
+ if b
+ tk_call(@path, 'sort', '-command', proc(&b), *params)
+ else
+ tk_call(@path, 'sort', *params)
+ end
+ self
+ end
+ def sort_ascending
+ tk_call(@path, 'sort', 'ascending')
+ self
+ end
+ def sort_descending
+ tk_call(@path, 'sort', 'descending')
+ self
+ end
+
+ #####################################
+
+ def bbox(index)
+ list(tk_send_without_enc('bbox', index))
+ end
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+ def get(*index)
+ _fromUTF8(tk_send_without_enc('get', *index))
+ end
+ def insert(index, *args)
+ tk_send('insert', index, *args)
+ self
+ end
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send_without_enc('scan', 'dragto', x, y)
+ self
+ end
+ def see(index)
+ tk_send_without_enc('see', index)
+ self
+ end
+
+ #####################################
+
+ include TkListItemConfig
+
+ def tagid(tag)
+ if tag.kind_of?(Tk::Itk::Component)
+ tag.name
+ else
+ super(tag)
+ end
+ end
+ private :tagid
+
+ #####################################
+
+ def activate(y)
+ tk_send_without_enc('activate', y)
+ self
+ end
+ def curselection
+ list(tk_send_without_enc('curselection'))
+ end
+ def get(first, last=nil)
+ if last
+ # tk_split_simplelist(_fromUTF8(tk_send_without_enc('get', first, last)))
+ tk_split_simplelist(tk_send_without_enc('get', first, last),
+ false, true)
+ else
+ _fromUTF8(tk_send_without_enc('get', first))
+ end
+ end
+ def nearest(y)
+ tk_send_without_enc('nearest', y).to_i
+ end
+ def size
+ tk_send_without_enc('size').to_i
+ end
+ def selection_anchor(index)
+ tk_send_without_enc('selection', 'anchor', index)
+ self
+ end
+ def selection_clear(first, last=None)
+ tk_send_without_enc('selection', 'clear', first, last)
+ self
+ end
+ def selection_includes(index)
+ bool(tk_send_without_enc('selection', 'includes', index))
+ end
+ def selection_set(first, last=None)
+ tk_send_without_enc('selection', 'set', first, last)
+ self
+ end
+
+ def index(idx)
+ tk_send_without_enc('index', idx).to_i
+ end
+
+ #####################################
+
+ def xview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('xview'))
+ else
+ tk_send_without_enc('xview', *index)
+ 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'))
+ else
+ tk_send_without_enc('yview', *index)
+ self
+ end
+ end
+ def yview_moveto(*index)
+ yview('moveto', *index)
+ end
+ def yview_scroll(*index)
+ yview('scroll', *index)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
new file mode 100644
index 0000000000..d6436d202a
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
@@ -0,0 +1,564 @@
+#
+# tkextlib/iwidgets/scrolledtext.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/text'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Scrolledtext < Tk::Iwidgets::Scrolledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Scrolledtext
+ TkCommandNames = ['::iwidgets::scrolledtext'.freeze].freeze
+ WidgetClassName = 'Scrolledtext'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'textbackground'
+ end
+ private :__strval_optkeys
+
+ def __font_optkeys
+ super() << 'textfont'
+ end
+ private :__font_optkeys
+
+ ################################
+
+ def initialize(*args)
+ super(*args)
+ @text = component_widget('text')
+ end
+
+ def method_missing(id, *args)
+ if @text.respond_to?(id)
+ @text.__send__(id, *args)
+ else
+ super(id, *args)
+ end
+ end
+
+ ################################
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def clear
+ tk_call(@path, 'clear')
+ self
+ end
+
+ def import(file, idx=nil)
+ if idx
+ tk_call(@path, 'import', file, index(idx))
+ else
+ tk_call(@path, 'import', file)
+ end
+ self
+ end
+
+ def export(file)
+ tk_call(@path, 'export', file)
+ self
+ end
+
+ #####################################
+
+ include TkTextTagConfig
+
+ def tagid(tag)
+ if tag.kind_of?(Tk::Itk::Component)
+ tag.name
+ else
+ super(tag)
+ end
+ end
+ private :tagid
+
+ def bbox(index)
+ list(tk_send('bbox', index))
+ end
+ def compare(idx1, op, idx2)
+ bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1),
+ op, _get_eval_enc_str(idx2)))
+ end
+
+ def debug
+ bool(tk_send_without_enc('debug'))
+ end
+ def debug=(boolean)
+ tk_send_without_enc('debug', boolean)
+ #self
+ boolean
+ end
+
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+
+ def dlineinfo(index)
+ list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index)))
+ end
+
+ def get(*index)
+ _fromUTF8(tk_send_without_enc('get', *index))
+ end
+ def get_displaychars(*index)
+ # Tk8.5 feature
+ get('-displaychars', *index)
+ end
+
+ def image_cget_strict(index, slot)
+ case slot.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ _fromUTF8(tk_send_without_enc('image', 'cget',
+ _get_eval_enc_str(index), "-#{slot}"))
+ else
+ tk_tcl2ruby(_fromUTF8(tk_send_without_enc('image', 'cget',
+ _get_eval_enc_str(index),
+ "-#{slot}")))
+ end
+ end
+ def image_cget(index, slot)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ image_cget_strict(index, slot)
+ else
+ begin
+ image_cget_strict(index, slot)
+ rescue => e
+ begin
+ if current_image_configinfo.has_key?(slot.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+
+ def image_configure(index, slot, value=None)
+ if slot.kind_of? Hash
+ _fromUTF8(tk_send_without_enc('image', 'configure',
+ _get_eval_enc_str(index),
+ *hash_kv(slot, true)))
+ else
+ _fromUTF8(tk_send_without_enc('image', 'configure',
+ _get_eval_enc_str(index),
+ "-#{slot}",
+ _get_eval_enc_str(value)))
+ end
+ self
+ end
+
+ def image_configinfo(index, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ case slot.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
+ conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
+ else
+ #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
+ conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
+ end
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).collect{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).collect{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ 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
+ }
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ case slot.to_s
+ when 'text', 'label', 'show', 'data', 'file'
+ #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
+ conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
+ else
+ #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
+ conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
+ end
+ key = conf.shift[1..-1]
+ { key => conf }
+ else
+ ret = {}
+ #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).each{|conflist|
+ # conf = tk_split_simplelist(conflist)
+ tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).each{|conflist|
+ conf = tk_split_simplelist(conflist, false, true)
+ 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
+ }
+ ret
+ end
+ end
+ end
+
+ def current_image_configinfo(index, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ conf = image_configinfo(index, slot)
+ {conf[0] => conf[4]}
+ else
+ ret = {}
+ image_configinfo(index).each{|conf|
+ ret[conf[0]] = conf[4] if conf.size > 2
+ }
+ ret
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ image_configinfo(index, slot).each{|k, conf|
+ ret[k] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+
+ def image_names
+ #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'names'))).collect{|elt|
+ tk_split_simplelist(tk_send_without_enc('image', 'names'), false, true).collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+
+ def index(idx)
+ tk_send_without_enc('index', _get_eval_enc_str(idx))
+ end
+
+ def insert(index, *args)
+ tk_send('insert', index, *args)
+ self
+ end
+
+ def mark_names
+ #tk_split_simplelist(_fromUTF8(tk_send_without_enc('mark', 'names'))).collect{|elt|
+ tk_split_simplelist(tk_send_without_enc('mark', 'names'), false, true).collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+
+ def mark_gravity(mark, direction=nil)
+ if direction
+ tk_send_without_enc('mark', 'gravity',
+ _get_eval_enc_str(mark), direction)
+ self
+ else
+ tk_send_without_enc('mark', 'gravity', _get_eval_enc_str(mark))
+ end
+ end
+
+ def mark_set(mark, index)
+ tk_send_without_enc('mark', 'set', _get_eval_enc_str(mark),
+ _get_eval_enc_str(index))
+ self
+ end
+ alias set_mark mark_set
+
+ def mark_unset(*marks)
+ tk_send_without_enc('mark', 'unset',
+ *(marks.collect{|mark| _get_eval_enc_str(mark)}))
+ self
+ end
+ alias unset_mark mark_unset
+
+ def mark_next(index)
+ tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'next',
+ _get_eval_enc_str(index))))
+ end
+ alias next_mark mark_next
+
+ def mark_previous(index)
+ tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'previous',
+ _get_eval_enc_str(index))))
+ end
+ alias previous_mark mark_previous
+
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send_without_enc('scan', 'dragto', x, y)
+ self
+ end
+
+
+ def _ktext_length(txt)
+ if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!!
+ return txt.length
+ end
+ ###########################
+
+ if $KCODE !~ /n/i
+ return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
+ end
+
+ # $KCODE == 'NONE'
+ if JAPANIZED_TK
+ tk_call_without_enc('kstring', 'length',
+ _get_eval_enc_str(txt)).to_i
+ else
+ begin
+ tk_call_without_enc('encoding', 'convertto', 'ascii',
+ _get_eval_enc_str(txt)).length
+ rescue StandardError, NameError
+ # sorry, I have no plan
+ txt.length
+ end
+ end
+ end
+ private :_ktext_length
+
+ def tksearch(*args)
+ # call 'search' subcommand of text widget
+ # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>]
+ # If <pattern> is regexp, then it must be a regular expression of Tcl
+ if args[0].kind_of?(Array)
+ opts = args.shift.collect{|opt| '-' + opt.to_s }
+ else
+ opts = []
+ end
+
+ opts << '--'
+
+ ret = tk_send('search', *(opts + args))
+ if ret == ""
+ nil
+ else
+ ret
+ end
+ end
+
+ def tksearch_with_count(*args)
+ # call 'search' subcommand of text widget
+ # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>]
+ # If <pattern> is regexp, then it must be a regular expression of Tcl
+ if args[0].kind_of?(Array)
+ opts = args.shift.collect{|opt| '-' + opt.to_s }
+ else
+ opts = []
+ end
+
+ opts << '-count' << args.shift << '--'
+
+ ret = tk_send('search', *(opts + args))
+ if ret == ""
+ nil
+ else
+ ret
+ end
+ end
+
+ def search_with_length(pat,start,stop=None)
+ pat = pat.chr if pat.kind_of? Integer
+ if stop != None
+ return ["", 0] if compare(start,'>=',stop)
+ txt = get(start,stop)
+ if (pos = txt.index(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of? String
+ #return [index(start + " + #{pos} chars"), pat.split('').length]
+ return [index(start + " + #{pos} chars"),
+ _ktext_length(pat), pat.dup]
+ else
+ #return [index(start + " + #{pos} chars"), $&.split('').length]
+ return [index(start + " + #{pos} chars"),
+ _ktext_length(match), match]
+ end
+ else
+ return ["", 0]
+ end
+ else
+ txt = get(start,'end - 1 char')
+ if (pos = txt.index(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of? String
+ #return [index(start + " + #{pos} chars"), pat.split('').length]
+ return [index(start + " + #{pos} chars"),
+ _ktext_length(pat), pat.dup]
+ else
+ #return [index(start + " + #{pos} chars"), $&.split('').length]
+ return [index(start + " + #{pos} chars"),
+ _ktext_length(match), match]
+ end
+ else
+ txt = get('1.0','end - 1 char')
+ if (pos = txt.index(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of? String
+ #return [index("1.0 + #{pos} chars"), pat.split('').length]
+ return [index("1.0 + #{pos} chars"),
+ _ktext_length(pat), pat.dup]
+ else
+ #return [index("1.0 + #{pos} chars"), $&.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
+ end
+ else
+ return ["", 0]
+ end
+ end
+ end
+ end
+
+ def search(pat,start,stop=None)
+ search_with_length(pat,start,stop)[0]
+ end
+
+ def rsearch_with_length(pat,start,stop=None)
+ pat = pat.chr if pat.kind_of? Integer
+ if stop != None
+ return ["", 0] if compare(start,'<=',stop)
+ txt = get(stop,start)
+ if (pos = txt.rindex(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of? String
+ #return [index(stop + " + #{pos} chars"), pat.split('').length]
+ return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup]
+ else
+ #return [index(stop + " + #{pos} chars"), $&.split('').length]
+ return [index(stop + " + #{pos} chars"), _ktext_length(match), match]
+ end
+ else
+ return ["", 0]
+ end
+ else
+ txt = get('1.0',start)
+ if (pos = txt.rindex(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of? String
+ #return [index("1.0 + #{pos} chars"), pat.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
+ else
+ #return [index("1.0 + #{pos} chars"), $&.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
+ end
+ else
+ txt = get('1.0','end - 1 char')
+ if (pos = txt.rindex(pat))
+ match = $&
+ #pos = txt[0..(pos-1)].split('').length if pos > 0
+ pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
+ if pat.kind_of? String
+ #return [index("1.0 + #{pos} chars"), pat.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
+ else
+ #return [index("1.0 + #{pos} chars"), $&.split('').length]
+ return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
+ end
+ else
+ return ["", 0]
+ end
+ end
+ end
+ end
+
+ def rsearch(pat,start,stop=None)
+ rsearch_with_length(pat,start,stop)[0]
+ end
+
+ def see(index)
+ tk_send_without_enc('see', index)
+ self
+ end
+
+ ###############################
+
+ def xview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('xview'))
+ else
+ tk_send_without_enc('xview', *index)
+ 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'))
+ else
+ tk_send_without_enc('yview', *index)
+ self
+ end
+ end
+ def yview_moveto(*index)
+ yview('moveto', *index)
+ end
+ def yview_scroll(*index)
+ yview('scroll', *index)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb
new file mode 100644
index 0000000000..eef093d314
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb
@@ -0,0 +1,20 @@
+#
+# tkextlib/iwidgets/scrolledwidget.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Scrolledwidget < Tk::Iwidgets::Labeledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Scrolledwidget
+ TkCommandNames = ['::iwidgets::scrolledwidget'.freeze].freeze
+ WidgetClassName = 'Scrolledwidget'.freeze
+ WidgetClassNames[WidgetClassName] = self
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb
new file mode 100644
index 0000000000..bf9b5ec30a
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb
@@ -0,0 +1,102 @@
+#
+# tkextlib/iwidgets/selectionbox.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Selectionbox < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Selectionbox
+ TkCommandNames = ['::iwidgets::selectionbox'.freeze].freeze
+ WidgetClassName = 'Selectionbox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'itemson' << 'selectionon'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'itemslabel' << 'selectionlabel'
+ end
+ private :__strval_optkeys
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def clear_items
+ tk_call(@path, 'clear', 'items')
+ self
+ end
+
+ def clear_selection
+ tk_call(@path, 'clear', 'selection')
+ self
+ end
+
+ def get
+ tk_call(@path, 'get')
+ end
+
+ def insert_items(idx, *args)
+ tk_call(@path, 'insert', 'items', idx, *args)
+ end
+
+ def insert_selection(pos, text)
+ tk_call(@path, 'insert', 'selection', pos, text)
+ end
+
+ def select_item
+ tk_call(@path, 'selectitem')
+ self
+ end
+
+ # based on Tk::Listbox ( and TkTextWin )
+ def curselection
+ list(tk_send_without_enc('curselection'))
+ end
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+ def index(idx)
+ tk_send_without_enc('index', idx).to_i
+ end
+ def nearest(y)
+ tk_send_without_enc('nearest', y).to_i
+ end
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send_without_enc('scan', 'dragto', x, y)
+ self
+ end
+ def selection_anchor(index)
+ tk_send_without_enc('selection', 'anchor', index)
+ self
+ end
+ def selection_clear(first, last=None)
+ tk_send_without_enc('selection', 'clear', first, last)
+ self
+ end
+ def selection_includes(index)
+ bool(tk_send_without_enc('selection', 'includes', index))
+ end
+ def selection_set(first, last=None)
+ tk_send_without_enc('selection', 'set', first, last)
+ self
+ end
+ def size
+ tk_send_without_enc('size').to_i
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb
new file mode 100644
index 0000000000..f772ecf8c2
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb
@@ -0,0 +1,92 @@
+#
+# tkextlib/iwidgets/selectiondialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Selectiondialog < Tk::Iwidgets::Dialog
+ end
+ end
+end
+
+class Tk::Iwidgets::Selectiondialog
+ TkCommandNames = ['::iwidgets::selectiondialog'.freeze].freeze
+ WidgetClassName = 'Selectiondialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def clear_items
+ tk_call(@path, 'clear', 'items')
+ self
+ end
+
+ def clear_selection
+ tk_call(@path, 'clear', 'selection')
+ self
+ end
+
+ def get
+ tk_call(@path, 'get')
+ end
+
+ def insert_items(idx, *args)
+ tk_call(@path, 'insert', 'items', idx, *args)
+ end
+
+ def insert_selection(pos, text)
+ tk_call(@path, 'insert', 'selection', pos, text)
+ end
+
+ def select_item
+ tk_call(@path, 'selectitem')
+ self
+ end
+
+ # based on Tk::Listbox ( and TkTextWin )
+ def curselection
+ list(tk_send_without_enc('curselection'))
+ end
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+ def index(idx)
+ tk_send_without_enc('index', idx).to_i
+ end
+ def nearest(y)
+ tk_send_without_enc('nearest', y).to_i
+ end
+ def scan_mark(x, y)
+ tk_send_without_enc('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send_without_enc('scan', 'dragto', x, y)
+ self
+ end
+ def selection_anchor(index)
+ tk_send_without_enc('selection', 'anchor', index)
+ self
+ end
+ def selection_clear(first, last=None)
+ tk_send_without_enc('selection', 'clear', first, last)
+ self
+ end
+ def selection_includes(index)
+ bool(tk_send_without_enc('selection', 'includes', index))
+ end
+ def selection_set(first, last=None)
+ tk_send_without_enc('selection', 'set', first, last)
+ self
+ end
+ def size
+ tk_send_without_enc('size').to_i
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/setup.rb b/ext/tk/lib/tkextlib/iwidgets/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/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/iwidgets/shell.rb b/ext/tk/lib/tkextlib/iwidgets/shell.rb
new file mode 100644
index 0000000000..dabf2e6f25
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/shell.rb
@@ -0,0 +1,38 @@
+#
+# tkextlib/iwidgets/shell.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Shell < Tk::Itk::Toplevel
+ end
+ end
+end
+
+class Tk::Iwidgets::Shell
+ TkCommandNames = ['::iwidgets::shell'.freeze].freeze
+ WidgetClassName = 'Shell'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def activate
+ tk_call(@path, 'activate') # may return val of deactibate method
+ end
+
+ def center(win=None)
+ tk_call(@path, 'center', win)
+ self
+ end
+
+ def child_site
+ window(tk_call(@path, 'childsite'))
+ end
+
+ def deactivate(val=None)
+ tk_call(@path, 'deactivate', val)
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/spindate.rb b/ext/tk/lib/tkextlib/iwidgets/spindate.rb
new file mode 100644
index 0000000000..2c98eb4629
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/spindate.rb
@@ -0,0 +1,48 @@
+#
+# tkextlib/iwidgets/spindate.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Spindate < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Spindate
+ TkCommandNames = ['::iwidgets::spindate'.freeze].freeze
+ WidgetClassName = 'Spindate'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'dayon' << 'monthon' << 'yearon'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'daylabel' << 'monthformat' << 'monthlabel' << 'yearlabel'
+ end
+ private :__strval_optkeys
+
+ def get_string
+ tk_call(@path, 'get', '-string')
+ end
+ alias get get_string
+
+ def get_clicks
+ number(tk_call(@path, 'get', '-clicks'))
+ end
+
+ def show(date=None)
+ tk_call(@path, 'show', date)
+ self
+ end
+ def show_now
+ tk_call(@path, 'show', 'now')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/spinint.rb b/ext/tk/lib/tkextlib/iwidgets/spinint.rb
new file mode 100644
index 0000000000..5eb944d081
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/spinint.rb
@@ -0,0 +1,30 @@
+#
+# tkextlib/iwidgets/spinint.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Spinint < Tk::Iwidgets::Spinner
+ end
+ end
+end
+
+class Tk::Iwidgets::Spinint
+ TkCommandNames = ['::iwidgets::spinint'.freeze].freeze
+ WidgetClassName = 'Spinint'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'wrap'
+ end
+ private :__boolval_optkeys
+
+ def __numlistval_optkeys
+ super() << 'range'
+ end
+ private :__numlistval_optkeys
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/spinner.rb b/ext/tk/lib/tkextlib/iwidgets/spinner.rb
new file mode 100644
index 0000000000..aeee5c9038
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/spinner.rb
@@ -0,0 +1,169 @@
+#
+# tkextlib/iwidgets/spinner.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Spinner < Tk::Iwidgets::Labeledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Spinner
+ TkCommandNames = ['::iwidgets::spinner'.freeze].freeze
+ WidgetClassName = 'Spinner'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include Tk::ValidateConfigure
+
+ class EntryfieldValidate < TkValidateCommand
+ #class CalCmdArgs < TkUtil::CallbackSubst
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?c, ?s, :char ],
+ [ ?P, ?s, :post ],
+ [ ?S, ?s, :current ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+ PROC_TBL = [
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+ end
+
+ def self._config_keys
+ ['validate', 'invalid']
+ end
+ end
+
+ def __validation_class_list
+ super() << EntryfieldValidate
+ end
+
+ Tk::ValidateConfigure.__def_validcmd(binding, EntryfieldValidate)
+
+ ####################################
+
+ def up
+ tk_call_without_enc(@path, 'up')
+ self
+ end
+
+ def down
+ tk_call_without_enc(@path, 'down')
+ self
+ end
+
+ def clear
+ tk_call_without_enc(@path, 'clear')
+ self
+ end
+
+ def delete(first, last=None)
+ tk_send_without_enc('delete', first, last)
+ self
+ end
+
+ def value
+ _fromUTF8(tk_send_without_enc('get'))
+ end
+ def value= (val)
+ tk_send_without_enc('delete', 0, 'end')
+ tk_send_without_enc('insert', 0, _get_eval_enc_str(val))
+ val
+ end
+ alias get value
+ alias set value=
+
+ def cursor=(index)
+ tk_send_without_enc('icursor', index)
+ #self
+ index
+ end
+ alias icursor cursor=
+
+ def index(idx)
+ number(tk_send_without_enc('index', idx))
+ end
+
+ def insert(pos,text)
+ tk_send_without_enc('insert', pos, _get_eval_enc_str(text))
+ self
+ end
+
+ def mark(pos)
+ tk_send_without_enc('scan', 'mark', pos)
+ self
+ end
+ def dragto(pos)
+ tk_send_without_enc('scan', 'dragto', pos)
+ self
+ end
+ def selection_adjust(index)
+ tk_send_without_enc('selection', 'adjust', index)
+ self
+ end
+ def selection_clear
+ tk_send_without_enc('selection', 'clear')
+ self
+ end
+ def selection_from(index)
+ tk_send_without_enc('selection', 'from', index)
+ self
+ end
+ def selection_present()
+ bool(tk_send_without_enc('selection', 'present'))
+ end
+ def selection_range(s, e)
+ tk_send_without_enc('selection', 'range', s, e)
+ self
+ end
+ def selection_to(index)
+ tk_send_without_enc('selection', 'to', index)
+ self
+ end
+
+ # based on tk/scrollable.rb
+ def xview(*index)
+ if index.size == 0
+ list(tk_send_without_enc('xview'))
+ else
+ tk_send_without_enc('xview', *index)
+ self
+ end
+ end
+ def xview_moveto(*index)
+ xview('moveto', *index)
+ end
+ def xview_scroll(*index)
+ xview('scroll', *index)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/spintime.rb b/ext/tk/lib/tkextlib/iwidgets/spintime.rb
new file mode 100644
index 0000000000..0ff683ab56
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/spintime.rb
@@ -0,0 +1,48 @@
+#
+# tkextlib/iwidgets/spintime.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Spintime < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Spintime
+ TkCommandNames = ['::iwidgets::spintime'.freeze].freeze
+ WidgetClassName = 'Spintime'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'houron' << 'militaryon' << 'minutelabel' << 'secondlabel'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'hourlabel' << 'minuteon' << 'secondon'
+ end
+ private :__strval_optkeys
+
+ def get_string
+ tk_call(@path, 'get', '-string')
+ end
+ alias get get_string
+
+ def get_clicks
+ number(tk_call(@path, 'get', '-clicks'))
+ end
+
+ def show(date=None)
+ tk_call(@path, 'show', date)
+ self
+ end
+ def show_now
+ tk_call(@path, 'show', 'now')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb b/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb
new file mode 100644
index 0000000000..dbb90e5102
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb
@@ -0,0 +1,180 @@
+#
+# tkextlib/iwidgets/tabnotebook.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Tabnotebook < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Tabnotebook
+ TkCommandNames = ['::iwidgets::tabnotebook'.freeze].freeze
+ WidgetClassName = 'Tabnotebook'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'pagecget', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'pageconfigure', id]
+ end
+ private :__item_config_cmd
+
+ def __item_strval_optkeys(id)
+ super(id) << 'tabbackground' << 'tabforeground'
+ end
+ private :__item_strval_optkeys
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ alias pagecget itemcget
+ alias pagecget_strict itemcget_strict
+ alias pageconfigure itemconfigure
+ alias pageconfiginfo itemconfiginfo
+ alias current_pageconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def __boolval_optkeys
+ super() << 'auto' << 'equaltabs' << 'raiseselect' << 'tabborders'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'backdrop' << 'tabbackground' << 'tabforeground'
+ end
+ private :__strval_optkeys
+
+ def initialize(*args)
+ super(*args)
+ @tabset = self.component_widget('tabset')
+ end
+
+ def add(keys={})
+ window(tk_call(@path, 'add', *hash_kv(keys)))
+ end
+
+ def child_site_list
+ list(tk_call(@path, 'childsite'))
+ end
+
+ def child_site(idx)
+ window(tk_call(@path, 'childsite', index(idx)))
+ end
+
+ def delete(idx1, idx2=nil)
+ if idx2
+ tk_call(@path, 'delete', index(idx1), index(idx2))
+ else
+ tk_call(@path, 'delete', index(idx1))
+ end
+ self
+ end
+
+ def index(idx)
+ #number(tk_call(@path, 'index', tagid(idx)))
+ @tabset.index(tagid(idx))
+ end
+
+ def insert(idx, keys={})
+ window(tk_call(@path, 'insert', index(idx), *hash_kv(keys)))
+ end
+
+ def next
+ tk_call(@path, 'next')
+ self
+ end
+
+ def prev
+ tk_call(@path, 'prev')
+ self
+ end
+
+ def select(idx)
+ tk_call(@path, 'select', index(idx))
+ self
+ end
+
+ def show_tab(idx)
+ @tabset.show_tab(idx)
+ self
+ end
+
+ def scrollcommand(cmd=Proc.new)
+ configure_cmd 'scrollcommand', cmd
+ self
+ end
+ alias xscrollcommand scrollcommand
+ alias yscrollcommand scrollcommand
+
+ def xscrollbar(bar=nil)
+ if bar
+ @scrollbar = bar
+ @scrollbar.orient 'horizontal'
+ self.scrollcommand {|*arg| @scrollbar.set(*arg)}
+ @scrollbar.command {|*arg| self.xview(*arg)}
+ Tk.update # avoid scrollbar trouble
+ end
+ @scrollbar
+ end
+ def yscrollbar(bar=nil)
+ if bar
+ @scrollbar = bar
+ @scrollbar.orient 'vertical'
+ self.scrollcommand {|*arg| @scrollbar.set(*arg)}
+ @scrollbar.command {|*arg| self.yview(*arg)}
+ Tk.update # avoid scrollbar trouble
+ end
+ @scrollbar
+ end
+ alias scrollbar yscrollbar
+
+ def view(*index)
+ if index.size == 0
+ idx = num_or_str(tk_send_without_enc('view'))
+ if idx.kind_of?(Fixnum) && idx < 0
+ nil
+ else
+ idx
+ end
+ else
+ tk_send_without_enc('view', *index)
+ self
+ end
+ end
+ alias xview view
+ alias yview view
+
+ def view_moveto(*index)
+ view('moveto', *index)
+ end
+ alias xview_moveto view_moveto
+ alias yview_moveto view_moveto
+ def view_scroll(index, what='pages')
+ view('scroll', index, what)
+ end
+ alias xview_scroll view_scroll
+ alias yview_scroll view_scroll
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/tabset.rb b/ext/tk/lib/tkextlib/iwidgets/tabset.rb
new file mode 100644
index 0000000000..300ba9dee0
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/tabset.rb
@@ -0,0 +1,144 @@
+#
+# tkextlib/iwidgets/tabset.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Tabset < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Tabset
+ TkCommandNames = ['::iwidgets::tabset'.freeze].freeze
+ WidgetClassName = 'Tabset'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ ####################################
+
+ 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 tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ alias tabcget itemcget
+ alias tabcget_strict itemcget_strict
+ alias tabconfigure itemconfigure
+ alias tabconfiginfo itemconfiginfo
+ alias current_tabconfiginfo current_itemconfiginfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+ ####################################
+
+ def __boolval_optkeys
+ super() << 'equaltabs' << 'raiseselect' << 'tabborders'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'backdrop'
+ end
+ private :__strval_optkeys
+
+ def add(keys={})
+ window(tk_call(@path, 'add', *hash_kv(keys)))
+ end
+
+ def delete(idx1, idx2=nil)
+ if idx2
+ tk_call(@path, 'delete', index(idx1), index(idx2))
+ else
+ tk_call(@path, 'delete', index(idx1))
+ end
+ self
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', tagid(idx)))
+ end
+
+ def insert(idx, keys={})
+ window(tk_call(@path, 'insert', index(idx), *hash_kv(keys)))
+ end
+
+ def next
+ tk_call(@path, 'next')
+ self
+ end
+
+ def prev
+ tk_call(@path, 'prev')
+ self
+ end
+
+ def select(idx)
+ tk_call(@path, 'select', index(idx))
+ self
+ end
+
+ def show_tab(idx)
+ if index(idx) == 0
+ self.start = 0
+ return
+ end
+
+ reutrn unless @canvas ||= self.winfo_children[0]
+
+ delta = 1 if (delta = cget(:gap)) == 'overlap' ||
+ (delta = self.winfo_pixels(delta) + 1) <= 0
+
+ case cget(:tabpos)
+ when 's', 'n'
+ if (head = tabcget(idx, :left)) < 0
+ self.start -= head
+ return
+ end
+ tabs_size = @canvas.winfo_width
+ tab_start, tab_end = @canvas .
+ find_overlapping(head, 0, head + delta, @canvas.winfo_height) .
+ find_all{|id| @canvas.itemtype(id) == TkcPolygon} .
+ map!{|id| bbox = @canvas.bbox(id); [bbox[0], bbox[2]]} . max
+
+ when 'e', 'w'
+ if (head = tabcget(idx, :top)) < 0
+ self.start -= head
+ return
+ end
+ tabs_size = @canvas.winfo_height
+ tab_start, tab_end = @canvas .
+ find_overlapping(0, head, @canvas.winfo_width, head + delta) .
+ find_all{|id| @canvas.itemtype(id) == TkcPolygon} .
+ map!{|id| bbox = @canvas.bbox(id); [bbox[1], bbox[3]]} . max
+ end
+
+ if (size = tab_end - tab_start + 1) > tabs_size
+ self.start -= tab_start
+ elsif head + size > tabs_size
+ self.start -= head + size - tabs_size
+ end
+
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/timeentry.rb b/ext/tk/lib/tkextlib/iwidgets/timeentry.rb
new file mode 100644
index 0000000000..588da77dc8
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/timeentry.rb
@@ -0,0 +1,25 @@
+#
+# tkextlib/iwidgets/timeentry.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Timeentry < Tk::Iwidgets::Timefield
+ end
+ end
+end
+
+class Tk::Iwidgets::Timeentry
+ TkCommandNames = ['::iwidgets::timeentry'.freeze].freeze
+ WidgetClassName = 'Timeentry'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __strval_optkeys
+ super() << 'closetext'
+ end
+ private :__strval_optkeys
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/timefield.rb b/ext/tk/lib/tkextlib/iwidgets/timefield.rb
new file mode 100644
index 0000000000..28e1504797
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/timefield.rb
@@ -0,0 +1,58 @@
+#
+# tkextlib/iwidgets/timefield.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Timefield < Tk::Iwidgets::Labeledwidget
+ end
+ end
+end
+
+class Tk::Iwidgets::Timefield
+ TkCommandNames = ['::iwidgets::timefield'.freeze].freeze
+ WidgetClassName = 'Timefield'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'gmt'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'textbackground'
+ end
+ private :__strval_optkeys
+
+ def __font_optkeys
+ super() << 'textfont'
+ end
+ private :__font_optkeys
+
+ def get_string
+ tk_call(@path, 'get', '-string')
+ end
+ alias get get_string
+
+ def get_clicks
+ number(tk_call(@path, 'get', '-clicks'))
+ end
+
+ def valid?
+ bool(tk_call(@path, 'isvalid'))
+ end
+ alias isvalid? valid?
+
+ def show(time=None)
+ tk_call(@path, 'show', time)
+ self
+ end
+ def show_now
+ tk_call(@path, 'show', 'now')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/toolbar.rb b/ext/tk/lib/tkextlib/iwidgets/toolbar.rb
new file mode 100644
index 0000000000..17cfa62156
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/toolbar.rb
@@ -0,0 +1,112 @@
+#
+# tkextlib/iwidgets/toolbar.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Toolbar < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Toolbar
+ TkCommandNames = ['::iwidgets::toolbar'.freeze].freeze
+ WidgetClassName = 'Toolbar'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __tkvariable_optkeys
+ super() << 'helpvariable'
+ end
+ private :__tkvariable_optkeys
+
+ ####################################
+
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'itemcget', self.index(id)]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'itemconfigure', self.index(id)]
+ end
+ private :__item_config_cmd
+
+ def __item_strval_optkeys(id)
+ super(id) << 'helpstr' << 'balloonstr'
+ end
+ private :__item_strval_optkeys
+
+ def tagid(tagOrId)
+ if tagOrId.kind_of?(Tk::Itk::Component)
+ tagOrId.name
+ else
+ #_get_eval_string(tagOrId)
+ tagOrId
+ end
+ end
+
+ ####################################
+
+ def __strval_optkeys
+ super() << 'balloonbackground' << 'balloonforeground'
+ end
+ private :__strval_optkeys
+
+ def __tkvariable_optkeys
+ super() << 'helpvariable'
+ end
+ private :__tkvariable_optkeys
+
+ def __font_optkeys
+ super() << 'balloonfont'
+ end
+ private :__font_optkeys
+
+ def add(type, tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ window(tk_call(@path, 'add', type, tagid(tag), *hash_kv(keys)))
+ tag
+ end
+
+ def delete(idx1, idx2=nil)
+ if idx2
+ tk_call(@path, 'delete', index(idx1), index(idx2))
+ else
+ tk_call(@path, 'delete', index(idx1))
+ end
+ self
+ end
+
+ def index(idx)
+ number(tk_call(@path, 'index', tagid(idx)))
+ end
+
+ def insert(idx, type, tag=nil, keys={})
+ if tag.kind_of?(Hash)
+ keys = tag
+ tag = nil
+ end
+ if tag
+ tag = Tk::Itk::Component.new(self, tagid(tag))
+ else
+ tag = Tk::Itk::Component.new(self)
+ end
+ window(tk_call(@path, 'insert', index(idx), type,
+ tagid(tag), *hash_kv(keys)))
+ tag
+ end
+end
diff --git a/ext/tk/lib/tkextlib/iwidgets/watch.rb b/ext/tk/lib/tkextlib/iwidgets/watch.rb
new file mode 100644
index 0000000000..ab2b687cf9
--- /dev/null
+++ b/ext/tk/lib/tkextlib/iwidgets/watch.rb
@@ -0,0 +1,56 @@
+#
+# tkextlib/iwidgets/watch.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/iwidgets.rb'
+
+module Tk
+ module Iwidgets
+ class Watch < Tk::Itk::Widget
+ end
+ end
+end
+
+class Tk::Iwidgets::Watch
+ TkCommandNames = ['::iwidgets::watch'.freeze].freeze
+ WidgetClassName = 'Watch'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'showampm'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'clockcolor' << 'hourcolor' << 'minutecolor' <<
+ 'pivotcolor' << 'secondcolor' << 'tickcolor'
+ end
+ private :__strval_optkeys
+
+ def get_string
+ tk_call(@path, 'get', '-string')
+ end
+ alias get get_string
+
+ def get_clicks
+ number(tk_call(@path, 'get', '-clicks'))
+ end
+
+ def show(time=None)
+ tk_call(@path, 'show', time)
+ self
+ end
+ def show_now
+ tk_call(@path, 'show', 'now')
+ self
+ end
+
+ def watch(*args)
+ unless args.empty?
+ tk_call(@path, 'watch', *args)
+ end
+ component_path('canvas')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/pkg_checker.rb b/ext/tk/lib/tkextlib/pkg_checker.rb
new file mode 100755
index 0000000000..5002ed7ff8
--- /dev/null
+++ b/ext/tk/lib/tkextlib/pkg_checker.rb
@@ -0,0 +1,184 @@
+#!/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__)
+
+add_path = false
+verbose = false
+
+def help_msg
+ print "Usage: #{$0} [-l] [-v] [-h] [--] [dir]\n"
+ print "\tIf dir is omitted, check the directry that this command exists.\n"
+ print "\tAvailable options are \n"
+ print "\t -l : Add dir to $LOAD_PATH\n"
+ print "\t (If dir == '<parent>/tkextlib', add <parent> also.)\n"
+ print "\t -v : Verbose mode (show reason of fail)\n"
+ print "\t -h : Show this message\n"
+ print "\t -- : End of options\n"
+end
+
+while(ARGV[0] && ARGV[0][0] == ?-)
+ case ARGV[0]
+ when '--'
+ ARGV.shift
+ break;
+ when '-l'
+ ARGV.shift
+ add_path = true
+ when '-v'
+ ARGV.shift
+ verbose = true
+ when '-h'
+ help_msg
+ exit(0)
+ else
+ print "Argument Error!! : unknown option '#{ARGV[0]}'\n"
+ help_msg
+ exit(1)
+ end
+end
+
+if ARGV[0]
+ dir = File.expand_path(ARGV[0])
+else
+ dir = File.dirname(File.expand_path(__FILE__))
+end
+
+if add_path
+ $LOAD_PATH.unshift(dir)
+ if File.basename(dir) == 'tkextlib'
+ $LOAD_PATH.unshift(File.dirname(dir))
+ end
+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}"
+print "\n $LOAD_PATH :: #{$LOAD_PATH.inspect}\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
+ if l =~ /^(?:[^#]+\s|\s*)(?:|;\s*)require\s*\(?\s*(["'])((\w|\/|:)+)\1/
+ pkg = [$2, :require_ruby_lib]
+ pkg_list << pkg unless pkg_list.member?(pkg)
+ end
+ }
+
+ pkg_list
+end
+
+def check_pkg(file, verbose=false)
+ 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}
+
+ when :require_ruby_lib
+ require name
+
+ end
+ rescue => e
+ if verbose
+ error_list << [name, type, e.message]
+ else
+ error_list << [name, type]
+ end
+ 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, verbose=false)
+ 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, verbose)
+ 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
+ begin
+ # read 'setup.rb' as if the library has standard structure
+ require File.join(subdir, 'setup.rb')
+ rescue LoadError
+ # ignore error
+ end
+=end
+ print "\n"
+
+ suc, err = check_pkg(f, verbose)
+ 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, verbose) 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..c6138f4275
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib.rb
@@ -0,0 +1,90 @@
+#
+# tcllib extension support
+# 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 'tkextlib/tcllib/setup.rb'
+
+err = ''
+
+# package:: autoscroll
+target = 'tkextlib/tcllib/autoscroll'
+begin
+ require target
+rescue => e
+ err << "\n ['" << target << "'] " << e.class.name << ' : ' << e.message
+end
+
+# package:: cursor
+target = 'tkextlib/tcllib/cursor'
+begin
+ require target
+rescue => e
+ err << "\n ['" << target << "'] " << e.class.name << ' : ' << e.message
+end
+
+# package:: style
+target = 'tkextlib/tcllib/style'
+begin
+ require target
+rescue => e
+ err << "\n ['" << target << "'] " << e.class.name << ' : ' << e.message
+end
+
+# autoload
+module Tk
+ module Tcllib
+ TkComm::TkExtlibAutoloadModule.unshift(self)
+
+ # package:: ctext
+ autoload :CText, 'tkextlib/tcllib/ctext'
+
+ # package:: getstring
+ autoload :GetString_Dialog, 'tkextlib/tcllib/getstring'
+
+ # package:: history
+ autoload :History, 'tkextlib/tcllib/history'
+
+ # package:: datefield
+ autoload :Datefield, 'tkextlib/tcllib/datefield'
+ autoload :DateField, 'tkextlib/tcllib/datefield'
+
+ # package:: ico
+ autoload :ICO, 'tkextlib/tcllib/ico'
+
+ # package:: ipentry
+ autoload :IP_Entry, 'tkextlib/tcllib/ip_entry'
+ autoload :IPEntry, 'tkextlib/tcllib/ip_entry'
+
+ # package:: swaplist
+ autoload :Swaplist_Dialog, 'tkextlib/tcllib/swaplist'
+
+ # package:: Plotchart
+ autoload :Plotchart, 'tkextlib/tcllib/plotchart'
+
+ # package:: tablelist
+ autoload :Tablelist, 'tkextlib/tcllib/tablelist'
+ autoload :TableList, 'tkextlib/tcllib/tablelist'
+ autoload :Tablelist_Tile, 'tkextlib/tcllib/tablelist_tile'
+ autoload :TableList_Tile, 'tkextlib/tcllib/tablelist_tile'
+
+ # package:: tkpiechart
+ autoload :Tkpiechart, 'tkextlib/tcllib/tkpiechart'
+
+ # package:: tooltip
+ autoload :Tooltip, 'tkextlib/tcllib/tooltip'
+
+ # package:: widget
+ autoload :Wdiget, 'tkextlib/tcllib/widget'
+ end
+end
+
+if $VERBOSE && !err.empty?
+ warn("Warning: some sub-packages are failed to require : " + err)
+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.
+
+-----<from "What is tcllib?">----------------------------
+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..7db3c2e2b7
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/autoscroll.rb
@@ -0,0 +1,158 @@
+#
+# 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'
+require 'tkextlib/tcllib.rb'
+
+module Tk
+ module Tcllib
+ module Autoscroll
+ PACKAGE_NAME = 'autoscroll'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('autoscroll')
+ rescue
+ ''
+ end
+ end
+
+ def self.not_available
+ fail RuntimeError, "'tkextlib/tcllib/autoscroll' extension is not available on your current environment."
+ end
+
+ def self.autoscroll(win)
+ Tk::Tcllib::Autoscroll.not_available
+ end
+
+ def self.unautoscroll(win)
+ Tk::Tcllib::Autoscroll.not_available
+ end
+ end
+ end
+end
+
+module Tk
+ module Scrollable
+ def autoscroll(mode = nil)
+ case mode
+ when :x, 'x'
+ if @xscrollbar
+ Tk::Tcllib::Autoscroll.autoscroll(@xscrollbar)
+ end
+ when :y, 'y'
+ if @yscrollbar
+ Tk::Tcllib::Autoscroll.autoscroll(@yscrollbar)
+ end
+ when nil, :both, 'both'
+ if @xscrollbar
+ Tk::Tcllib::Autoscroll.autoscroll(@xscrollbar)
+ end
+ if @yscrollbar
+ Tk::Tcllib::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::Tcllib::Autoscroll.unautoscroll(@xscrollbar)
+ end
+ when :y, 'y'
+ if @yscrollbar
+ Tk::Tcllib::Autoscroll.unautoscroll(@yscrollbar)
+ end
+ when nil, :both, 'both'
+ if @xscrollbar
+ Tk::Tcllib::Autoscroll.unautoscroll(@xscrollbar)
+ end
+ if @yscrollbar
+ Tk::Tcllib::Autoscroll.unautoscroll(@yscrollbar)
+ end
+ else
+ fail ArgumentError, "'x', 'y' or 'both' (String or Symbol) is expected"
+ end
+ self
+ end
+ end
+end
+
+class Tk::Scrollbar
+ def autoscroll
+ # Arranges for the already existing scrollbar to be mapped
+ # and unmapped as needed.
+ #tk_call_without_enc('::autoscroll::autoscroll', @path)
+ Tk::Tcllib::Autoscroll.autoscroll(self)
+ self
+ end
+ def unautoscroll
+ # Returns the scrollbar to its original static state.
+ #tk_call_without_enc('::autoscroll::unautoscroll', @path)
+ Tk::Tcllib::Autoscroll.unautoscroll(self)
+ self
+ end
+end
+
+# TkPackage.require('autoscroll', '1.0')
+# TkPackage.require('autoscroll', '1.1')
+TkPackage.require('autoscroll')
+
+module Tk
+ module Tcllib
+ class << Autoscroll
+ undef not_available
+ end
+
+ module Autoscroll
+ extend TkCore
+ def self.autoscroll(win)
+ tk_call_without_enc('::autoscroll::autoscroll', win.path)
+ end
+
+ def self.unautoscroll(win)
+ tk_call_without_enc('::autoscroll::unautoscroll', win.path)
+ end
+
+ def self.wrap
+ # v1.1
+ tk_call_without_enc('::autoscroll::wrap')
+ end
+
+ def self.unwrap
+ # v1.1
+ tk_call_without_enc('::autoscroll::unwrap')
+ end
+ end
+ 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..9014037f3d
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/ctext.rb
@@ -0,0 +1,160 @@
+#
+# 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'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('ctext', '3.1')
+TkPackage.require('ctext')
+
+module Tk
+ module Tcllib
+ class CText < Tk::Text
+ PACKAGE_NAME = 'ctext'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('ctext')
+ rescue
+ ''
+ end
+ end
+ 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(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def __strval_optkeys
+ super() << 'linemapfg' << 'linemapbg' <<
+ 'linemap_select_fg' << 'linemap_select_bg'
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() << 'highlight' << 'linemap_markable'
+ end
+ private :__boolval_optkeys
+
+ 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..9bb828e8dd
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/cursor.rb
@@ -0,0 +1,97 @@
+#
+# tkextlib/tcllib/cursor.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * Procedures to handle CURSOR data
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+module Tk
+ module Tcllib
+ module Cursor
+ PACKAGE_NAME = 'cursor'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('cursor')
+ rescue
+ ''
+ end
+ end
+
+ def self.not_available
+ fail RuntimeError, "'tkextlib/tcllib/cursor' extension is not available on your current environment."
+ end
+
+ def self.cursor_display(win=None)
+ Tk::Tcllib::Cursor.not_available
+ end
+
+ def self.cursor_propagate(win, cursor)
+ Tk::Tcllib::Cursor.not_available
+ end
+
+ def self.cursor_restore(win, cursor = None)
+ Tk::Tcllib::Cursor.not_available
+ end
+ end
+ end
+
+ 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)
+ Tk::Tcllib::Cursor.cursor_display(parent)
+ end
+end
+
+class TkWindow
+ def cursor_propagate(cursor)
+ # Sets the cursor for self and all its descendants to cursor.
+ #tk_call_without_enc('::cursor::propagate', @path, cursor)
+ Tk::Tcllib::Cursor.cursor_propagate(self, 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_call_without_enc('::cursor::restore', @path, cursor)
+ Tk::Tcllib::Cursor.cursor_restore(self, cursor)
+ end
+end
+
+# TkPackage.require('cursor', '0.1')
+TkPackage.require('cursor')
+
+module Tk
+ module Tcllib
+ class << Cursor
+ undef not_available
+ end
+
+ module Cursor
+ extend TkCore
+ def self.cursor_display(win=None)
+ tk_call_without_enc('::cursor::display', _epath(win))
+ end
+
+ def self.cursor_propagate(win, cursor)
+ #tk_call_without_enc('::cursor::propagate', win.path, cursor)
+ tk_call_without_enc('::cursor::propagate', _epath(win), cursor)
+ end
+
+ def self.cursor_restore(win, cursor = None)
+ #tk_call_without_enc('::cursor::restore', win.path, cursor)
+ tk_call_without_enc('::cursor::restore', _epath(win), cursor)
+ end
+ end
+ 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..2244dd7a9a
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/datefield.rb
@@ -0,0 +1,57 @@
+#
+# 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'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('datefield', '0.1')
+TkPackage.require('datefield')
+
+module Tk
+ module Tcllib
+ class Datefield < Tk::Entry
+ PACKAGE_NAME = 'datefield'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('datefield')
+ rescue
+ ''
+ end
+ end
+ 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(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/dialog.rb b/ext/tk/lib/tkextlib/tcllib/dialog.rb
new file mode 100644
index 0000000000..825621b5a1
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/dialog.rb
@@ -0,0 +1,84 @@
+#
+# tkextlib/tcllib/dialog.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * Generic dialog widget (themed)
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('widget::dialog', '1.2')
+TkPackage.require('widget::dialog')
+
+module Tk::Tcllib
+ module Widget
+ class Dialog < TkWindow
+ PACKAGE_NAME = 'widget::dialog'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('widget::dialog')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
+
+class Tk::Tcllib::Widget::Dialog
+ TkCommandNames = ['::widget::dialog'.freeze].freeze
+
+ def __boolval_optkeys
+ ['separator', 'synchronous', 'transient']
+ end
+ private :__boolval_optkeys
+
+ def create_self(keys)
+ if keys and keys != None
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def add(what, *args)
+ window(tk_send('add', *args))
+ end
+
+ def get_frame
+ window(tk_send('getframe'))
+ end
+
+ def set_widget(widget)
+ tk_send('setwidget', widget)
+ self
+ end
+
+ def display
+ tk_send('display')
+ self
+ end
+ alias show display
+
+ def cancel
+ tk_send('cancel')
+ self
+ end
+
+ def close(reason = None)
+ tk_send('close', reason)
+ end
+
+ def withdraw
+ tk_send('withdraw')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/getstring.rb b/ext/tk/lib/tkextlib/tcllib/getstring.rb
new file mode 100644
index 0000000000..fc5d8b26d9
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/getstring.rb
@@ -0,0 +1,134 @@
+#
+# tkextlib/tcllib/getstring.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * A dialog which consists of an Entry, OK, and Cancel buttons.
+#
+
+require 'tk'
+require 'tk/entry'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('getstring', '0.1')
+TkPackage.require('getstring')
+
+module Tk::Tcllib
+ class GetString_Dialog < TkWindow
+ PACKAGE_NAME = 'getstring'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('getstring')
+ rescue
+ ''
+ end
+ end
+ end
+end
+
+
+class Tk::Tcllib::GetString_Dialog
+ TkCommandNames = ['::getstring::tk_getString'.freeze].freeze
+ WidgetClassName = 'TkSDialog'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.show(*args)
+ dialog = self.new(*args)
+ dialog.show
+ [dialog.status, dialog.value]
+ end
+ def self.display(*args)
+ self.show(*args)
+ end
+
+ def initialize(*args) # args = (parent=nil, text='', keys=nil)
+ keys = args.pop
+ if keys.kind_of?(Hash)
+ text = args.pop
+ @keys = _symbolkey2str(keys)
+ args.push(keys)
+ else
+ text = keys
+ @keys = {}
+ end
+ if text
+ @text = text.dup
+ else
+ @text = ''
+ end
+
+ @variable = TkVariable.new
+ @status = nil
+
+ super(*args)
+ end
+
+ def create_self(keys)
+ # dummy
+ end
+ private :create_self
+
+ def show
+ @variable.value = ''
+ @status = bool(tk_call(self.class::TkCommandNames[0],
+ @path, @variable, @text, *hash_kv(@keys)))
+ end
+ alias display show
+
+ def status
+ @status
+ end
+
+ def value
+ @variable.value
+ end
+
+ def cget_strict(slot)
+ slot = slot.to_s
+ if slot == 'text'
+ @text
+ else
+ @keys[slot]
+ end
+ end
+ def cget(slot)
+ cget_strict(slot)
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot.each{|k, v| configure(k, v)}
+ else
+ slot = slot.to_s
+ value = _symbolkey2str(value) if value.kind_of?(Hash)
+ if value && value != None
+ if slot == 'text'
+ @text = value.to_s
+ else
+ @keys[slot] = value
+ end
+ else
+ if slot == 'text'
+ @text = ''
+ else
+ @keys.delete(slot)
+ end
+ end
+ end
+ self
+ end
+
+ def configinfo(slot = nil)
+ if slot
+ slot = slot.to_s
+ [ slot, nil, nil, nil, ( (slot == 'text')? @text: @keys[slot] ) ]
+ else
+ @keys.collect{|k, v| [ k, nil, nil, nil, v ] } \
+ << [ 'text', nil, nil, nil, @text ]
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/history.rb b/ext/tk/lib/tkextlib/tcllib/history.rb
new file mode 100644
index 0000000000..a01a4ebfcc
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/history.rb
@@ -0,0 +1,73 @@
+#
+# tkextlib/tcllib/history.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * Provides a history for Entry widgets
+#
+
+require 'tk'
+require 'tk/entry'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('history', '0.1')
+TkPackage.require('history')
+
+module Tk::Tcllib
+ module History
+ PACKAGE_NAME = 'history'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('history')
+ rescue
+ ''
+ end
+ end
+ end
+end
+
+module Tk::Tcllib::History
+ extend TkCore
+
+ def self.init(entry, length=None)
+ tk_call_without_enc('::history::init', entry.path, length)
+ entry.extend(self) # add methods to treat history to the entry widget
+ end
+
+ def self.remove(entry)
+ tk_call_without_enc('::history::remove', entry.path)
+ entry
+ end
+
+ def history_remove
+ tk_call_without_enc('::history::remove', @path)
+ self
+ end
+
+ def history_add(text)
+ tk_call('::history::add', @path, text)
+ self
+ end
+
+ def history_get
+ simplelist(tk_call_without_enc('::history::get', @path))
+ end
+
+ def history_clear
+ tk_call_without_enc('::history::clear', @path)
+ self
+ end
+
+ def history_configure(opt, value)
+ tk_call('::history::configure', @path, opt, value)
+ self
+ end
+
+ def history_configinfo(opt)
+ tk_call('::history::configure', @path, opt)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/ico.rb b/ext/tk/lib/tkextlib/tcllib/ico.rb
new file mode 100644
index 0000000000..8c92926a4c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/ico.rb
@@ -0,0 +1,116 @@
+#
+# tkextlib/tcllib/ico.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * Reading and writing windows icons
+#
+
+require 'tk'
+require 'tk/image'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('ico', '0.3')
+TkPackage.require('ico')
+
+module Tk
+ module Tcllib
+ class ICO < TkImage
+ PACKAGE_NAME = 'ico'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('ico')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
+
+class Tk::Tcllib::ICO
+ def self.list(file, keys=nil)
+ tk_split_list(tk_call_without_enc('::ico::getIconList', file,
+ *hash_kv(keys, true)))
+ end
+
+ def self.get(file, index, keys=nil)
+ tk_call_without_enc('::ico::getIcon', file, index, *hash_kv(keys, true))
+ end
+
+ def self.get_image(file, index, keys={})
+ keys = _symbolkey2str(keys)
+ keys.delete('format')
+ self.new(file, index, keys)
+ end
+
+ def self.get_data(file, index, keys={})
+ keys['format'] = 'data'
+ tk_split_list(tk_call_without_enc('::ico::getIcon', file, index,
+ *hash_kv(keys, true)))
+ end
+
+ def self.write(file, index, depth, data, keys=nil)
+ tk_call_without_enc('::ico::writeIcon', file, index, depth, data,
+ *hash_kv(keys, true))
+ end
+
+ def self.copy(from_file, from_index, to_file, to_index, keys=nil)
+ tk_call_without_enc('::ico::copyIcon',
+ from_file, from_index, to_file, to_index,
+ *hash_kv(keys, true))
+ end
+
+ def self.exe_to_ico(exe_file, ico_file, keys=nil)
+ tk_call_without_enc('::ico::copyIcon', exe_file, ico_file,
+ *hash_kv(keys, true))
+ end
+
+ def self.clear_cache(file=None)
+ tk_call_without_enc('::ico::clearCache', file)
+ end
+
+ def self.transparent_color(image, color)
+ if image.kind_of?(Array)
+ tk_split_list(tk_call_without_enc('::ico::transparentColor',
+ image, color))
+ else
+ tk_call_without_enc('::ico::transparentColor', image, color)
+ end
+ end
+
+ def self.show(file, keys=nil)
+ tk_call_without_enc('::ico::Show', file, *hash_kv(keys, true))
+ end
+
+ ###########################
+
+ def initialize(file, index, keys=nil)
+ keys = _symbolkey2str(keys)
+ if keys.key?('name')
+ @path = keys['name'].to_s
+ else
+ Tk_Image_ID.mutex.synchronize{
+ @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Image_ID[1].succ!
+ }
+ end
+ tk_call_without_enc('::ico::getIcon', file, index, '-name', @path,
+ '-format', 'image', *hash_kv(keys, true))
+ Tk_IMGTBL[@path] = self
+ end
+
+ def write(file, index, depth, keys=nil)
+ Tk::Tcllib::ICO.write(file, index, depth, @path, keys=nil)
+ self
+ end
+
+ def transparent_color(color)
+ tk_call_without_enc('::ico::transparentColor', @path, color)
+ self
+ end
+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..c4b8240c04
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb
@@ -0,0 +1,66 @@
+#
+# 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 'tkextlib/tcllib.rb'
+
+# TkPackage.require('ipentry', '0.1')
+TkPackage.require('ipentry')
+
+module Tk
+ module Tcllib
+ class IP_Entry < Tk::Entry
+ PACKAGE_NAME = 'ipentry'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('ipentry')
+ rescue
+ ''
+ end
+ end
+ end
+ IPEntry = IP_Entry
+ 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(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def __strval_optkeys
+ super() << 'fg' << 'bg' << 'insertbackground'
+ end
+ private :__strval_optkeys
+
+ 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/panelframe.rb b/ext/tk/lib/tkextlib/tcllib/panelframe.rb
new file mode 100644
index 0000000000..2a4562e779
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/panelframe.rb
@@ -0,0 +1,72 @@
+#
+# tkextlib/tcllib/panelframe.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * Create PanelFrame widgets.
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('widget::panelframe', '1.0')
+TkPackage.require('widget::panelframe')
+
+module Tk::Tcllib
+ module Widget
+ class PanelFrame < TkWindow
+ PACKAGE_NAME = 'widget::panelframe'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('widget::panelframe')
+ rescue
+ ''
+ end
+ end
+ end
+ Panelframe = PanelFrame
+ end
+end
+
+class Tk::Tcllib::Widget::PanelFrame
+ TkCommandNames = ['::widget::panelframe'.freeze].freeze
+
+ def create_self(keys)
+ if keys and keys != None
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def add(what, *args)
+ window(tk_send('add', *args))
+ end
+
+ #def get_frame
+ # window(tk_send('getframe'))
+ #end
+
+ def set_widget(widget)
+ tk_send('setwidget', widget)
+ self
+ end
+
+ def remove(*wins)
+ tk_send('remove', *wins)
+ end
+ def remove_destroy(*wins)
+ tk_send('remove', '-destroy', *wins)
+ end
+ alias delete remove_destroy
+
+ def items
+ simplelist(tk_send('items')).collect!{|w| window(w)}
+ 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..06ab20f3e6
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/plotchart.rb
@@ -0,0 +1,886 @@
+#
+# 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'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('Plotchart', '0.9')
+# TkPackage.require('Plotchart', '1.1')
+TkPackage.require('Plotchart')
+
+module Tk
+ module Tcllib
+ module Plotchart
+ PACKAGE_NAME = 'Plotchart'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('Plotchart')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
+
+module Tk::Tcllib::Plotchart
+ extend TkCore
+ ############################
+ 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 TkCore
+
+ 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 < Tk::Canvas
+ include ChartMethod
+
+ TkCommandNames = [
+ 'canvas'.freeze,
+ '::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?(Tk::Canvas)
+ @path = parent.path
+ else
+ super(parent, *args) # create canvas widget
+ end
+ end
+
+ @chart = _create_chart
+ end
+
+ def _create_chart
+ p self.class::TkCommandNames[1] if $DEBUG
+ tk_call_without_enc(self.class::TkCommandNames[1], @path,
+ array2tk_list(@xaxis), array2tk_list(@yaxis))
+ end
+ private :_create_chart
+
+ def __destroy_hook__
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
+ end
+
+ def plot(series, x, y)
+ tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(series), x, y)
+ self
+ end
+
+ def contourlines(xcrd, ycrd, vals, clss=None)
+ xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array)
+ ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array)
+ vals = array2tk_list(vals) if vals.kind_of?(Array)
+ clss = array2tk_list(clss) if clss.kind_of?(Array)
+
+ tk_call_without_enc(@chart, 'contourlines', xcrd, ycrd, vals, clss)
+ self
+ end
+
+ def contourfill(xcrd, ycrd, vals, klasses=None)
+ xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array)
+ ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array)
+ vals = array2tk_list(vals) if vals.kind_of?(Array)
+ clss = array2tk_list(clss) if clss.kind_of?(Array)
+
+ tk_call_without_enc(@chart, 'contourfill', xcrd, ycrd, vals, clss)
+ self
+ end
+
+ def contourbox(xcrd, ycrd, vals, klasses=None)
+ xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array)
+ ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array)
+ vals = array2tk_list(vals) if vals.kind_of?(Array)
+ clss = array2tk_list(clss) if clss.kind_of?(Array)
+
+ tk_call_without_enc(@chart, 'contourbox', xcrd, ycrd, vals, clss)
+ self
+ end
+
+ def color_map(colors)
+ colors = array2tk_list(colors) if colors.kind_of?(Array)
+
+ tk_call_without_enc(@chart, 'colorMap', colors)
+ self
+ end
+
+ def grid_cells(xcrd, ycrd)
+ xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array)
+ ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array)
+
+ tk_call_without_enc(@chart, 'grid', xcrd, ycrd)
+ 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 = [
+ 'canvas'.freeze,
+ '::Plotchart::createStripchart'.freeze
+ ].freeze
+ end
+
+ ############################
+ class PolarPlot < Tk::Canvas
+ include ChartMethod
+
+ TkCommandNames = [
+ 'canvas'.freeze,
+ '::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?(Tk::Canvas)
+ @path = parent.path
+ else
+ super(parent, *args) # create canvas widget
+ end
+ end
+
+ @chart = _create_chart
+ end
+
+ def _create_chart
+ p self.class::TkCommandNames[1] if $DEBUG
+ tk_call_without_enc(self.class::TkCommandNames[1], @path,
+ array2tk_list(@radius_data))
+ end
+ private :_create_chart
+
+ def __destroy_hook__
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
+ end
+
+ 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 < Tk::Canvas
+ include ChartMethod
+
+ TkCommandNames = [
+ 'canvas'.freeze,
+ '::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?(Tk::Canvas)
+ @path = parent.path
+ else
+ super(parent, *args) # create canvas widget
+ end
+ end
+
+ @chart = _create_chart
+ end
+
+ def _create_chart
+ p self.class::TkCommandNames[1] if $DEBUG
+ tk_call_without_enc(self.class::TkCommandNames[1], @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 < Tk::Canvas
+ include ChartMethod
+
+ TkCommandNames = [
+ 'canvas'.freeze,
+ '::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?(Tk::Canvas)
+ @path = parent.path
+ else
+ super(parent, *args) # create canvas widget
+ end
+ end
+
+ @chart = _create_chart
+ end
+
+ def _create_chart
+ p self.class::TkCommandNames[1] if $DEBUG
+ tk_call_without_enc(self.class::TkCommandNames[1], @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 plot_funcont(conts, cmd=Proc.new)
+ conts = array2tk_list(conts) if conts.kind_of?(Array)
+ Tk.ip_eval("proc #{@path}_#{@chart} {x y} {#{install_cmd(cmd)} $x $y}")
+ tk_call_without_enc(@chart, 'plotfuncont', "#{@path}_#{@chart}", conts)
+ 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 < Tk::Canvas
+ include ChartMethod
+
+ TkCommandNames = [
+ 'canvas'.freeze,
+ '::Plotchart::createPiechart'.freeze
+ ].freeze
+
+ def initialize(*args) # args := ([parent] [, keys])
+ if args[0].kind_of?(Tk::Canvas)
+ parent = args.shift
+ @path = parent.path
+ else
+ super(*args) # create canvas widget
+ end
+ @chart = _create_chart
+ end
+
+ def _create_chart
+ p self.class::TkCommandNames[1] if $DEBUG
+ tk_call_without_enc(self.class::TkCommandNames[1], @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 < Tk::Canvas
+ include ChartMethod
+
+ TkCommandNames = [
+ 'canvas'.freeze,
+ '::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?(Tk::Canvas)
+ @path = parent.path
+ else
+ super(parent, *args) # create canvas widget
+ end
+ end
+
+ @chart = _create_chart
+ end
+
+ def _create_chart
+ p self.class::TkCommandNames[1] if $DEBUG
+ tk_call_without_enc(self.class::TkCommandNames[1], @path,
+ array2tk_list(@xlabels), array2tk_list(@ylabels),
+ @series_size)
+ end
+ private :_create_chart
+
+ def __destroy_hook__
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
+ end
+
+ 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 = [
+ 'canvas'.freeze,
+ '::Plotchart::createHorizontalBarchart'.freeze
+ ].freeze
+ end
+
+ ############################
+ class Timechart < Tk::Canvas
+ include ChartMethod
+
+ TkCommandNames = [
+ 'canvas'.freeze,
+ '::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?(String)
+ @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?(Tk::Canvas)
+ @path = parent.path
+ else
+ super(parent, *args) # create canvas widget
+ end
+ end
+
+ @chart = _create_chart
+ end
+
+ def _create_chart
+ p self.class::TkCommandNames[1] if $DEBUG
+ tk_call_without_enc(self.class::TkCommandNames[1], @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 Gnattchart < Tk::Canvas
+ include ChartMethod
+
+ TkCommandNames = [
+ 'canvas'.freeze,
+ '::Plotchart::createGnattchart'.freeze
+ ].freeze
+
+ def initialize(*args)
+ # args := ([parent,] time_begin, time_end, items [, text_width] [, 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?(String)
+ @time_begin = args.shift
+ @time_end = args.shift
+ @items = args.shift
+
+ if args[0].kind_of?(Fixnum)
+ @text_width = args.shift
+ else
+ @text_width = None
+ end
+
+ super(*args) # create canvas widget
+ else
+ parent = args.shift
+
+ @time_begin = args.shift
+ @time_end = args.shift
+ @items = args.shift
+
+ if args[0].kind_of?(Fixnum)
+ @text_width = args.shift
+ else
+ @text_width = None
+ end
+
+ if parent.kind_of?(Tk::Canvas)
+ @path = parent.path
+ else
+ super(parent, *args) # create canvas widget
+ end
+ end
+
+ @chart = _create_chart
+ end
+
+ def _create_chart
+ p self.class::TkCommandNames[1] if $DEBUG
+ tk_call_without_enc(self.class::TkCommandNames[1], @path,
+ @time_begin, @time_end, @items, @text_width)
+ end
+ private :_create_chart
+
+ def task(txt, time_begin, time_end, completed=0.0)
+ list(tk_call_without_enc(@chart, 'task', txt, time_begin, time_end,
+ completed)).collect!{|id|
+ TkcItem.id2obj(self, id)
+ }
+ 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
+
+ def connect(from_task, to_task)
+ from_task = array2tk_list(from_task) if from_task.kind_of?(Array)
+ to_task = array2tk_list(to_task) if to_task.kind_of?(Array)
+
+ tk_call_without_enc(@chart, 'connect', from_task, to_task)
+ self
+ end
+
+ def summary(txt, tasks)
+ tasks = array2tk_list(tasks) if tasks.kind_of?(Array)
+ tk_call_without_enc(@chart, 'summary', tasks)
+ self
+ end
+
+ def color_of_part(keyword, newcolor)
+ tk_call_without_enc(@chart, 'color', keyword, newcolor)
+ self
+ end
+
+ def font_of_part(keyword, newfont)
+ tk_call_without_enc(@chart, 'font', keyword, newfont)
+ self
+ end
+ end
+
+ ############################
+ class PlotSeries < TkObject
+ SeriesID_TBL = TkCore::INTERP.create_table
+
+ (Series_ID = ['series'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+ TkCore::INTERP.init_ip_env{
+ SeriesID_TBL.mutex.synchronize{ SeriesID_TBL.clear }
+ }
+
+ def self.id2obj(chart, id)
+ path = chart.path
+ SeriesID_TBL.mutex.synchronize{
+ if SeriesID_TBL[path]
+ SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(chart, keys=nil)
+ @parent = @chart_obj = chart
+ @ppath = @chart_obj.path
+ Series_ID.mutex.synchronize{
+ @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_)
+ Series_ID[1].succ!
+ }
+ SeriesID_TBL.mutex.synchronize{
+ SeriesID_TBL[@ppath] ||= {}
+ SeriesID_TBL[@ppath][@id] = self
+ }
+ 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/ruler.rb b/ext/tk/lib/tkextlib/tcllib/ruler.rb
new file mode 100644
index 0000000000..88ffb2c912
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/ruler.rb
@@ -0,0 +1,65 @@
+#
+# tkextlib/tcllib/ruler.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * ruler widget
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('widget::ruler', '1.0')
+TkPackage.require('widget::ruler')
+
+module Tk::Tcllib
+ module Widget
+ class Ruler < TkWindow
+ PACKAGE_NAME = 'widget::ruler'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('widget::ruler')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
+
+class Tk::Tcllib::Widget::Ruler
+ TkCommandNames = ['::widget::ruler'.freeze].freeze
+
+ def __boolval_optkeys
+ ['showvalues', 'outline', 'grid']
+ end
+ private :__boolval_optkeys
+
+ def __numlistval_optkeys
+ ['interval', 'sizes']
+ end
+ private :__numlistval_optkeys
+
+ def create_self(keys)
+ if keys and keys != None
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def redraw
+ tk_send('redraw')
+ self
+ end
+
+ def shade(org, dest, frac)
+ tk_send('shade', org, dest, frac)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/screenruler.rb b/ext/tk/lib/tkextlib/tcllib/screenruler.rb
new file mode 100644
index 0000000000..1b4067e2f0
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/screenruler.rb
@@ -0,0 +1,68 @@
+#
+# tkextlib/tcllib/screenruler.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * screenruler dialog
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('widget::screenruler', '1.1')
+TkPackage.require('widget::screenruler')
+
+module Tk::Tcllib
+ module Widget
+ class ScreenRuler < TkWindow
+ PACKAGE_NAME = 'widget::ruler'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('widget::screenruler')
+ rescue
+ ''
+ end
+ end
+ end
+ Screenruler = ScreenRuler
+ end
+end
+
+class Tk::Tcllib::Widget::ScreenRuler
+ TkCommandNames = ['::widget::screenruler'.freeze].freeze
+
+ def __boolval_optkeys
+ ['topmost', 'reflect']
+ end
+ private :__boolval_optkeys
+
+ def __numlistval_optkeys
+ ['alpha']
+ end
+ private :__numlistval_optkeys
+
+ def create_self(keys)
+ if keys and keys != None
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def display
+ tk_send('display')
+ self
+ end
+ alias show display
+
+ def hide
+ tk_send('hide')
+ self
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/scrollwin.rb b/ext/tk/lib/tkextlib/tcllib/scrollwin.rb
new file mode 100644
index 0000000000..717728e34a
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/scrollwin.rb
@@ -0,0 +1,61 @@
+#
+# tkextlib/tcllib/scrollwin.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * Scrolled widget
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('widget::scrolledwindow', '1.0')
+TkPackage.require('widget::scrolledwindow')
+
+module Tk::Tcllib
+ module Widget
+ class ScrolledWindow < TkWindow
+ PACKAGE_NAME = 'widget::scrolledwindow'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('widget::scrolledwindow')
+ rescue
+ ''
+ end
+ end
+ end
+ Scrolledwindow = ScrolledWindow
+ end
+end
+
+class Tk::Tcllib::Widget::ScrolledWindow
+ TkCommandNames = ['::widget::scrolledwindow'.freeze].freeze
+
+ def __numlistval_optkeys
+ ['ipad']
+ end
+ private :__numlistval_optkeys
+
+ def create_self(keys)
+ if keys and keys != None
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def get_frame
+ window(tk_send('getframe'))
+ end
+
+ def set_widget(widget)
+ tk_send('setwidget', widget)
+ self
+ 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..dac6916e46
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/style.rb
@@ -0,0 +1,61 @@
+#
+# 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'
+require 'tkextlib/tcllib.rb'
+
+module Tk::Tcllib
+ module Style
+ PACKAGE_NAME = 'style'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('style')
+ rescue
+ ''
+ end
+ end
+
+ def self.not_available
+ fail RuntimeError, "'tkextlib/tcllib/style' extension is not available on your current environment."
+ end
+
+ def self.names
+ Tk::Tcllib::Style.not_available
+ end
+
+ def self.use(style)
+ Tk::Tcllib::Style.not_available
+ end
+ end
+end
+
+# TkPackage.require('style', '0.1')
+# TkPackage.require('style', '0.3')
+TkPackage.require('style')
+
+module Tk::Tcllib
+ class << Style
+ undef not_available
+ end
+
+ module Style
+ extend TkCore
+
+ 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/superframe.rb b/ext/tk/lib/tkextlib/tcllib/superframe.rb
new file mode 100644
index 0000000000..35da37efbf
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/superframe.rb
@@ -0,0 +1,51 @@
+#
+# tkextlib/tcllib/superframe.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * Superframe widget - enhanced labelframe widget
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('widget::superframe', '1.0')
+TkPackage.require('widget::superframe')
+
+module Tk::Tcllib
+ module Widget
+ class SuperFrame < TkWindow
+ PACKAGE_NAME = 'widget::superframe'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('widget::superframe')
+ rescue
+ ''
+ end
+ end
+ end
+ Superframe = SuperlFrame
+ end
+end
+
+class Tk::Tcllib::Widget::SuperFrame
+ TkCommandNames = ['::widget::superframe'.freeze].freeze
+
+ def create_self(keys)
+ if keys and keys != None
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def labelwidget
+ window(tk_send('labelwidget'))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/swaplist.rb b/ext/tk/lib/tkextlib/tcllib/swaplist.rb
new file mode 100644
index 0000000000..1c813e36da
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/swaplist.rb
@@ -0,0 +1,150 @@
+#
+# tkextlib/tcllib/swaplist.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * A dialog which allows a user to move options between two lists
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('swaplist', '0.1')
+TkPackage.require('swaplist')
+
+module Tk::Tcllib
+ class Swaplist_Dialog < TkWindow
+ PACKAGE_NAME = 'swaplist'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('swaplist')
+ rescue
+ ''
+ end
+ end
+ end
+end
+
+
+class Tk::Tcllib::Swaplist_Dialog
+ TkCommandNames = ['::swaplist::swaplist'.freeze].freeze
+ WidgetClassName = 'Swaplist'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.show(*args)
+ dialog = self.new(*args)
+ dialog.show
+ [dialog.status, dialog.value]
+ end
+ def self.display(*args)
+ self.show(*args)
+ end
+
+ def initialize(*args)
+ # args = (parent=nil, complete_list=[], selected_list=[], keys=nil)
+ keys = args.pop
+ if keys.kind_of?(Hash)
+ @selected_list = args.pop
+ @complete_list = args.pop
+ @keys = _symbolkey2str(keys)
+ args.push(keys)
+ else
+ @selected_list = keys
+ @complete_list = args.pop
+ @keys = {}
+ end
+
+ @selected_list = [] unless @selected_list
+ @complete_list = [] unless @complete_list
+
+ @variable = TkVariable.new
+ @status = nil
+
+ super(*args)
+ end
+
+ def create_self(keys)
+ # dummy
+ end
+ private :create_self
+
+ def show
+ @variable.value = ''
+ @status = bool(tk_call(self.class::TkCommandNames[0],
+ @path, @variable,
+ @complete_list, @selected_list,
+ *hash_kv(@keys)))
+ end
+ alias display show
+
+ def status
+ @status
+ end
+
+ def value
+ @variable.list
+ end
+ alias selected value
+
+ def cget_strict(slot)
+ slot = slot.to_s
+ if slot == 'complete_list'
+ @complete_list
+ elsif slot == 'selected_list'
+ @selected_list
+ else
+ @keys[slot]
+ end
+ end
+ def cget(slot)
+ cget_strict(slot)
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot.each{|k, v| configure(k, v)}
+ else
+ slot = slot.to_s
+ value = _symbolkey2str(value) if value.kind_of?(Hash)
+ if value && value != None
+ if slot == 'complete_list'
+ @complete_list = value
+ elsif slot == 'selected_list'
+ @selected_list = value
+ else
+ @keys[slot] = value
+ end
+ else
+ if slot == 'complete_list'
+ @complete_list = []
+ elsif slot == 'selected_list'
+ @selected_list = []
+ else
+ @keys.delete(slot)
+ end
+ end
+ end
+ self
+ end
+
+ def configinfo(slot = nil)
+ if slot
+ slot = slot.to_s
+ if slot == 'complete_list'
+ [ slot, nil, nil, nil, @complete_list ]
+ elsif slot == 'selected_list'
+ [ slot, nil, nil, nil, @selected_list ]
+ else
+ [ slot, nil, nil, nil, @keys[slot] ]
+ end
+ else
+ @keys.collect{|k, v| [ k, nil, nil, nil, v ] } \
+ << [ 'complete_list', nil, nil, nil, @complete_list ] \
+ << [ 'selected_list', nil, nil, nil, @selected_list ]
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/tablelist.rb b/ext/tk/lib/tkextlib/tcllib/tablelist.rb
new file mode 100644
index 0000000000..efeb8fbbac
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/tablelist.rb
@@ -0,0 +1,27 @@
+#
+# tkextlib/tcllib/tablelist.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * A multi-column listbox
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# check Tile extension :: If already loaded, use tablelist_tile.
+unless defined? Tk::Tcllib::Tablelist_usingTile
+ Tk::Tcllib::Tablelist_usingTile = TkPackage.provide('tile')
+end
+
+if Tk::Tcllib::Tablelist_usingTile
+ # with Tile
+ require 'tkextlib/tcllib/tablelist_tile'
+
+else
+ # without Tile
+
+ # TkPackage.require('Tablelist', '4.2')
+ TkPackage.require('Tablelist')
+
+ require 'tkextlib/tcllib/tablelist_core'
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb b/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb
new file mode 100644
index 0000000000..d7a6c97210
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb
@@ -0,0 +1,782 @@
+#
+# tkextlib/tcllib/tablelist_core.rb
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * This file is required by 'tkextlib/tcllib/tablelist.rb' or
+# 'tkextlib/tcllib/tablelist_tile.rb'.
+#
+
+module Tk
+ module Tcllib
+ class Tablelist < TkWindow
+ if Tk::Tcllib::Tablelist_usingTile
+ PACKAGE_NAME = 'Tablelist_tile'.freeze
+ else
+ PACKAGE_NAME = 'Tablelist'.freeze
+ end
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require(self.package_name)
+ rescue
+ ''
+ end
+ end
+
+ def self.use_Tile?
+ (Tk::Tcllib::Tablelist_usingTile)? true: false
+ end
+ end
+ TableList = Tablelist
+ end
+end
+
+module Tk::Tcllib::TablelistItemConfig
+ include TkItemConfigMethod
+
+ def _to_idx(idx)
+ if idx.kind_of?(Array)
+ idx.collect{|elem| _get_eval_string(elem)}.join(',')
+ else
+ idx
+ end
+ end
+ def _from_idx(idx)
+ return idx unless idx.kind_of?(String)
+
+ if idx[0] == ?@ # '@x,y'
+ idx
+ elsif idx =~ /([^,]+),([^,]+)/
+ row = $1, column = $2
+ [num_or_str(row), num_or_str(column)]
+ else
+ num_or_str(idx)
+ end
+ end
+ private :_to_idx, :_from_idx
+
+ def __item_cget_cmd(mixed_id)
+ [self.path, mixed_id[0] + 'cget', _to_idx(mixed_id[1])]
+ end
+ def __item_config_cmd(mixed_id)
+ [self.path, mixed_id[0] + 'configure', _to_idx(mixed_id[1])]
+ end
+
+ def cell_cget(tagOrId, option)
+ itemcget(['cell', tagOrId], option)
+ end
+ def cell_cget_strict(tagOrId, option)
+ itemcget_strict(['cell', tagOrId], option)
+ end
+ def cell_configure(tagOrId, slot, value=None)
+ itemconfigure(['cell', tagOrId], slot, value)
+ end
+ def cell_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['cell', tagOrId], slot)
+ end
+ def current_cell_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['cell', tagOrId], slot)
+ end
+ alias cellcget cell_cget
+ alias cellcget_strict cell_cget_strict
+ alias cellconfigure cell_configure
+ alias cellconfiginfo cell_configinfo
+ alias current_cellconfiginfo current_cell_configinfo
+
+ def column_cget(tagOrId, option)
+ itemcget(['column', tagOrId], option)
+ end
+ def column_cget_strict(tagOrId, option)
+ itemcget_strict(['column', tagOrId], option)
+ end
+ def column_configure(tagOrId, slot, value=None)
+ itemconfigure(['column', tagOrId], slot, value)
+ end
+ def column_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['column', tagOrId], slot)
+ end
+ def current_column_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['column', tagOrId], slot)
+ end
+ alias columncget column_cget
+ alias columncget_strict column_cget_strict
+ alias columnconfigure column_configure
+ alias columnconfiginfo column_configinfo
+ alias current_columnconfiginfo current_column_configinfo
+
+ def row_cget(tagOrId, option)
+ itemcget(['row', tagOrId], option)
+ end
+ def row_cget_strict(tagOrId, option)
+ itemcget_strict(['row', tagOrId], option)
+ end
+ def row_configure(tagOrId, slot, value=None)
+ itemconfigure(['row', tagOrId], slot, value)
+ end
+ def row_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['row', tagOrId], slot)
+ end
+ def current_row_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['row', tagOrId], slot)
+ end
+ alias rowcget row_cget
+ alias rowcget_strict row_cget_strict
+ alias rowconfigure row_configure
+ alias rowconfiginfo row_configinfo
+ alias current_rowconfiginfo current_row_configinfo
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+end
+
+class Tk::Tcllib::Tablelist
+ include Tk::Tcllib::TablelistItemConfig
+ include Scrollable
+
+ TkCommandNames = ['::tablelist::tablelist'.freeze].freeze
+ WidgetClassName = 'Tablelist'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def create_self(keys)
+ if keys and keys != None
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ ##########################
+
+ def __numval_optkeys
+ super() + ['titlecolumns']
+ end
+ private :__numval_optkeys
+
+ def __strval_optkeys
+ super() + ['snipstring']
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ super() + [
+ 'forceeditendcommand', 'movablecolumns', 'movablerows',
+ 'protecttitlecolumns', 'resizablecolumns',
+ 'showarrow', 'showlabels', 'showseparators'
+ ]
+ end
+ private :__boolval_optkeys
+
+ def __listval_optkeys
+ super() + ['columns']
+ end
+ private :__listval_optkeys
+
+ def __tkvariable_optkeys
+ super() + ['listvariable']
+ end
+ private :__tkvariable_optkeys
+
+ def __val2ruby_optkeys # { key=>proc, ... }
+ # The method is used to convert a opt-value to a ruby's object.
+ # When get the value of the option "key", "proc.call(value)" is called.
+ super().update('stretch'=>proc{|v| (v == 'all')? v: simplelist(v)})
+ end
+ private :__val2ruby_optkeys
+
+ def __ruby2val_optkeys # { key=>proc, ... }
+ # The method is used to convert a ruby's object to a opt-value.
+ # When set the value of the option "key", "proc.call(value)" is called.
+ # That is, "-#{key} #{proc.call(value)}".
+ super().update('stretch'=>proc{|v|
+ (v.kind_of?(Array))? v.collect{|e| _to_idx(e)}: v
+ })
+ end
+ private :__ruby2val_optkeys
+
+ def __font_optkeys
+ super() + ['labelfont']
+ end
+ private :__font_optkeys
+
+ ##########################
+
+ def __item_strval_optkeys(id)
+ if id[0] == 'cell'
+ super(id) + ['title']
+ else
+ super(id) - ['text'] + ['title']
+ end
+ end
+ private :__item_strval_optkeys
+
+ def __item_boolval_optkeys(id)
+ super(id) + [
+ 'editable', 'hide', 'resizable', 'showarrow', 'stretchable',
+ ]
+ end
+ private :__item_boolval_optkeys
+
+ def __item_listval_optkeys(id)
+ if id[0] == 'cell'
+ super(id)
+ else
+ super(id) + ['text']
+ end
+ end
+ private :__item_listval_optkeys
+
+ def __item_font_optkeys(id)
+ # maybe need to override
+ super(id) + ['labelfont']
+ end
+ private :__item_font_optkeys
+
+ ##########################
+
+ def activate(index)
+ tk_send('activate', _to_idx(index))
+ self
+ end
+
+ def activate_cell(index)
+ tk_send('activatecell', _to_idx(index))
+ self
+ end
+ alias activatecell activate_cell
+
+ def get_attrib(name=nil)
+ if name && name != None
+ tk_send('attrib', name)
+ else
+ ret = []
+ lst = simplelist(tk_send('attrib'))
+ until lst.empty?
+ ret << ( [lst.shift] << lst.shift )
+ end
+ ret
+ end
+ end
+ def set_attrib(*args)
+ tk_send('attrib', *(args.flatten))
+ self
+ end
+
+ def bbox(index)
+ list(tk_send('bbox', _to_idx(index)))
+ end
+
+ def bodypath
+ window(tk_send('bodypath'))
+ end
+
+ def bodytag
+ TkBindTag.new_by_name(tk_send('bodytag'))
+ end
+
+ def cancel_editing
+ tk_send('cancelediting')
+ self
+ end
+ alias cancelediting cancel_editing
+
+ def cellindex(idx)
+ _from_idx(tk_send('cellindex', _to_idx(idx)))
+ end
+
+ def cellselection_anchor(idx)
+ tk_send('cellselection', 'anchor', _to_idx(idx))
+ self
+ end
+
+ def cellselection_clear(first, last=nil)
+ if first.kind_of?(Array)
+ tk_send('cellselection', 'clear', first.collect{|idx| _to_idx(idx)})
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ tk_send('cellselection', 'clear', first, last)
+ end
+ self
+ end
+
+ def cellselection_includes(idx)
+ bool(tk_send('cellselection', 'includes', _to_idx(idx)))
+ end
+
+ def cellselection_set(first, last=nil)
+ if first.kind_of?(Array)
+ tk_send('cellselection', 'set', first.collect{|idx| _to_idx(idx)})
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ tk_send('cellselection', 'set', first, last)
+ end
+ self
+ end
+
+ def columncount
+ number(tk_send('columncount'))
+ end
+
+ def columnindex(idx)
+ number(tk_send('columnindex', _to_idx(idx)))
+ end
+
+ def containing(y)
+ idx = num_or_str(tk_send('containing', y))
+ (idx.kind_of?(Fixnum) && idx < 0)? nil: idx
+ end
+
+ def containing_cell(x, y)
+ idx = _from_idx(tk_send('containingcell', x, y))
+ if idx.kind_of?(Array)
+ [
+ ((idx[0].kind_of?(Fixnum) && idx[0] < 0)? nil: idx[0]),
+ ((idx[1].kind_of?(Fixnum) && idx[1] < 0)? nil: idx[1])
+ ]
+ else
+ idx
+ end
+ end
+ alias containingcell containing_cell
+
+ def containing_column(x)
+ idx = num_or_str(tk_send('containingcolumn', x))
+ (idx.kind_of?(Fixnum) && idx < 0)? nil: idx
+ end
+ alias containingcolumn containing_column
+
+ def curcellselection
+ simplelist(tk_send('curcellselection')).collect!{|idx| _from_idx(idx)}
+ end
+
+ def curselection
+ list(tk_send('curselection'))
+ end
+
+ def delete_items(first, last=nil)
+ if first.kind_of?(Array)
+ tk_send('delete', first.collect{|idx| _to_idx(idx)})
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ tk_send('delete', first, last)
+ end
+ self
+ end
+ alias delete delete_items
+ alias deleteitems delete_items
+
+ def delete_columns(first, last=nil)
+ if first.kind_of?(Array)
+ tk_send('deletecolumns', first.collect{|idx| _to_idx(idx)})
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ tk_send('deletecolumns', first, last)
+ end
+ self
+ end
+ alias deletecolumns delete_columns
+
+ def edit_cell(idx)
+ tk_send('editcell', _to_idx(idx))
+ self
+ end
+ alias editcell edit_cell
+
+ def editwinpath
+ window(tk_send('editwinpath'))
+ end
+
+ def entrypath
+ window(tk_send('entrypath'))
+ end
+
+ def fill_column(idx, txt)
+ tk_send('fillcolumn', _to_idx(idx), txt)
+ self
+ end
+ alias fillcolumn fill_column
+
+ def finish_editing
+ tk_send('finishediting')
+ self
+ end
+ alias finishediting finish_editing
+
+ def get(first, last=nil)
+ if first.kind_of?(Array)
+ simplelist(tk_send('get', first.collect{|idx| _to_idx(idx)})).collect!{|elem| simplelist(elem) }
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ simplelist(tk_send('get', first, last))
+ end
+ end
+
+ def get_cells(first, last=nil)
+ if first.kind_of?(Array)
+ simplelist(tk_send('getcells', first.collect{|idx| _to_idx(idx)})).collect!{|elem| simplelist(elem) }
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ simplelist(tk_send('getcells', first, last))
+ end
+ end
+ alias getcells get_cells
+
+ def get_columns(first, last=nil)
+ if first.kind_of?(Array)
+ simplelist(tk_send('getcolumns', first.collect{|idx| _to_idx(idx)})).collect!{|elem| simplelist(elem) }
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ simplelist(tk_send('getcolumns', first, last))
+ end
+ end
+ alias getcolumns get_columns
+
+ def get_keys(first, last=nil)
+ if first.kind_of?(Array)
+ simplelist(tk_send('getkeys', first.collect{|idx| _to_idx(idx)})).collect!{|elem| simplelist(elem) }
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ simplelist(tk_send('getkeys', first, last))
+ end
+ end
+ alias getkeys get_keys
+
+ def imagelabelpath(idx)
+ window(tk_send('imagelabelpath', _to_idx(idx)))
+ end
+
+ def index(idx)
+ number(tk_send('index', _to_idx(idx)))
+ end
+
+ def insert(idx, *items)
+ tk_send('insert', _to_idx(idx), *items)
+ self
+ end
+
+ def insert_columnlist(idx, columnlist)
+ tk_send('insertcolumnlist', _to_idx(idx), columnlist)
+ self
+ end
+ alias insertcolumnlist insert_columnlist
+
+ def insert_columns(idx, *args)
+ tk_send('insertcolums', _to_idx(idx), *args)
+ self
+ end
+ alias insertcolumns insert_columns
+
+ def insert_list(idx, list)
+ tk_send('insertlist', _to_idx(idx), list)
+ self
+ end
+ alias insertlist insert_list
+
+ def itemlistvar
+ TkVarAccess.new(tk_send('itemlistvar'))
+ end
+
+ def labelpath(idx)
+ window(tk_send('labelpath', _to_idx(idx)))
+ end
+
+ def labels
+ simplelist(tk_send('labels'))
+ end
+
+ def move(src, target)
+ tk_send('move', _to_idx(src), _to_idx(target))
+ self
+ end
+
+ def move_column(src, target)
+ tk_send('movecolumn', _to_idx(src), _to_idx(target))
+ self
+ end
+ alias movecolumn move_column
+
+ def nearest(y)
+ _from_idx(tk_send('nearest', y))
+ end
+
+ def nearest_cell(x, y)
+ _from_idx(tk_send('nearestcell', x, y))
+ end
+ alias nearestcell nearest_cell
+
+ def nearest_column(x)
+ _from_idx(tk_send('nearestcolumn', x))
+ end
+ alias nearestcolumn nearest_column
+
+ def reject_input
+ tk_send('rejectinput')
+ self
+ end
+ alias rejectinput reject_input
+
+ def reset_sortinfo
+ tk_send('resetsortinfo')
+ self
+ end
+ alias resetsortinfo reset_sortinfo
+
+ def scan_mark(x, y)
+ tk_send('scan', 'mark', x, y)
+ self
+ end
+
+ def scan_dragto(x, y)
+ tk_send('scan', 'dragto', x, y)
+ self
+ end
+
+ def see(idx)
+ tk_send('see', _to_idx(idx))
+ self
+ end
+
+ def see_cell(idx)
+ tk_send('seecell', _to_idx(idx))
+ self
+ end
+ alias seecell see_cell
+
+ def see_column(idx)
+ tk_send('seecolumn', _to_idx(idx))
+ self
+ end
+ alias seecolumn see_column
+
+ def selection_anchor(idx)
+ tk_send('selection', 'anchor', _to_idx(idx))
+ self
+ end
+
+ def selection_clear(first, last=nil)
+ if first.kind_of?(Array)
+ tk_send('selection', 'clear', first.collect{|idx| _to_idx(idx)})
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ tk_send('selection', 'clear', first, last)
+ end
+ self
+ end
+
+ def selection_includes(idx)
+ bool(tk_send('selection', 'includes', _to_idx(idx)))
+ end
+
+ def selection_set(first, last=nil)
+ if first.kind_of?(Array)
+ tk_send('selection', 'set', first.collect{|idx| _to_idx(idx)})
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ tk_send('selection', 'set', first, last)
+ end
+ self
+ end
+
+ def separatorpath(idx=nil)
+ if idx
+ window(tk_send('separatorpath', _to_idx(idx)))
+ else
+ window(tk_send('separatorpath'))
+ end
+ end
+
+ def separators
+ simplelist(tk_send('separators')).collect!{|w| window(w)}
+ end
+
+ def size
+ number(tk_send('size'))
+ end
+
+ def sort(order=nil)
+ if order
+ order = order.to_s
+ order = '-' << order if order[0] != ?-
+ if order.length < 2
+ order = nil
+ end
+ end
+ if order
+ tk_send('sort', order)
+ else
+ tk_send('sort')
+ end
+ self
+ end
+ def sort_increasing
+ tk_send('sort', '-increasing')
+ self
+ end
+ def sort_decreasing
+ tk_send('sort', '-decreasing')
+ self
+ end
+
+ DEFAULT_sortByColumn_cmd = '::tablelist::sortByColumn'
+
+ def sort_by_column(idx, order=nil)
+ if order
+ order = order.to_s
+ order = '-' << order if order[0] != ?-
+ if order.length < 2
+ order = nil
+ end
+ end
+ if order
+ tk_send('sortbycolumn', _to_idx(idx), order)
+ else
+ tk_send('sortbycolumn', _to_idx(idx))
+ end
+ self
+ end
+ def sort_by_column_increasing(idx)
+ tk_send('sortbycolumn', _to_idx(idx), '-increasing')
+ self
+ end
+ def sort_by_column_decreasing(idx)
+ tk_send('sortbycolumn', _to_idx(idx), '-decreasing')
+ self
+ end
+
+ def sortcolumn
+ idx = num_or_str(tk_send('sortcolum'))
+ (idx.kind_of?(Fixnum) && idx < 0)? nil: idx
+ end
+
+ def sortorder
+ tk_send('sortorder')
+ end
+
+ def toggle_visibility(first, last=nil)
+ if first.kind_of?(Array)
+ tk_send('togglevisibility', first.collect{|idx| _to_idx(idx)})
+ else
+ first = _to_idx(first)
+ last = (last)? _to_idx(last): first
+ tk_send('togglevisibility', first, last)
+ end
+ self
+ end
+ alias togglevisibility toggle_visibility
+
+ def windowpath(idx)
+ window(tk_send('windowpath', _to_idx(idx)))
+ end
+end
+
+class << Tk::Tcllib::Tablelist
+ ############################################################
+ # helper commands
+ def getTablelistPath(descendant)
+ window(Tk.tk_call('::tablelist::getTablelistPath', descendant))
+ end
+
+ def convEventFields(descendant, x, y)
+ window(Tk.tk_call('::tablelist::convEventFields', descendant, x, y))
+ end
+
+
+ ############################################################
+ # with the BWidget package
+ def addBWidgetEntry(name=None)
+ Tk.tk_call('::tablelist::addBWidgetEntry', name)
+ end
+
+ def addBWidgetSpinBox(name=None)
+ Tk.tk_call('::tablelist::addBWidgetSpinBox', name)
+ end
+
+ def addBWidgetComboBox(name=None)
+ Tk.tk_call('::tablelist::addBWidgetComboBox', name)
+ end
+
+
+ ############################################################
+ # with the Iwidgets ([incr Widgets]) package
+ def addIncrEntryfield(name=None)
+ Tk.tk_call('::tablelist::addIncrEntry', name)
+ end
+
+ def addIncrDateTimeWidget(type, seconds=false, name=None)
+ # type := 'datefield'|'dateentry'|timefield'|'timeentry'
+ if seconds && seconds != None
+ seconds = '-seconds'
+ else
+ seconds = None
+ end
+ Tk.tk_call('::tablelist::addDateTimeWidget', type, seconds, name)
+ end
+
+ def addIncrSpinner(name=None)
+ Tk.tk_call('::tablelist::addIncrSpinner', name)
+ end
+
+ def addIncrSpinint(name=None)
+ Tk.tk_call('::tablelist::addIncrSpinint', name)
+ end
+
+ def addIncrCombobox(name=None)
+ Tk.tk_call('::tablelist::addIncrCombobox', name)
+ end
+
+
+ ############################################################
+ # with Bryan Oakley's combobox package
+ def addOakleyCombobox(name=None)
+ Tk.tk_call('::tablelist::addOakleyCombobox', name)
+ end
+
+ ############################################################
+ # with the multi-entry package Mentry is a library extension
+ def addDateMentry(format, separator, gmt=false, name=None)
+ if gmt && gmt != None
+ gmt = '-gmt'
+ else
+ gmt = None
+ end
+ Tk.tk_call('::tablelist::addDateMentry', format, separator, gmt, name)
+ end
+
+ def addTimeMentry(format, separator, gmt=false, name=None)
+ if gmt && gmt != None
+ gmt = '-gmt'
+ else
+ gmt = None
+ end
+ Tk.tk_call('::tablelist::addTimeMentry', format, separator, gmt, name)
+ end
+
+ def addFixedPointMentry(count1, count2, comma=false, name=None)
+ if comma && comma != None
+ comma = '-comma'
+ else
+ comma = None
+ end
+ Tk.tk_call('::tablelist::addFixedPoingMentry', count1, count2, comma, name)
+ end
+
+ def addIPAddrMentry(name=None)
+ Tk.tk_call('::tablelist::addIPAddrMentry', name)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb b/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb
new file mode 100644
index 0000000000..0cb4eb735d
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb
@@ -0,0 +1,25 @@
+#
+# tkextlib/tcllib/tablelist_tlie.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * A multi-column listbox
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('tablelist_tile', '4.2')
+TkPackage.require('Tablelist_tile')
+
+unless defined? Tk::Tcllib::Tablelist_usingTile
+ Tk::Tcllib::Tablelist_usingTile = true
+end
+
+requrie 'tkextlib/tcllib/tablelist_core'
+
+module Tk
+ module Tcllib
+ Tablelist_Tile = Tablelist
+ TableList_Tile = Tablelist
+ 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..b366e0198b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
@@ -0,0 +1,314 @@
+#
+# 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'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('tkpiechart', '6.6')
+TkPackage.require('tkpiechart')
+
+module Tk
+ module Tcllib
+ module Tkpiechart
+ end
+ end
+end
+
+module Tk::Tcllib::Tkpiechart
+ PACKAGE_NAME = 'tkpiechart'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('tkpiechart')
+ rescue
+ ''
+ end
+ end
+
+ 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
+
+ def __boolval_optkeys
+ super() << 'select' << 'autoupdate' << 'selectable'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'bordercolor' << 'textbackground' <<
+ 'widestvaluetext' << 'title'
+ end
+ private :__strval_optkeys
+
+ def __listval_optkeys
+ super() << 'colors'
+ end
+ private :__listval_optkeys
+ 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.mutex.synchronize{
+ 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.mutex.synchronize{
+ 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.mutex.synchronize{
+ 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/tcllib/tooltip.rb b/ext/tk/lib/tkextlib/tcllib/tooltip.rb
new file mode 100644
index 0000000000..4301b39fd3
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/tooltip.rb
@@ -0,0 +1,95 @@
+#
+# tkextlib/tcllib/tooltip.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * Provides tooltips, a small text message that is displayed when the
+# mouse hovers over a widget.
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('tooltip', '1.1')
+TkPackage.require('tooltip')
+
+module Tk::Tcllib
+ module Tooltip
+ PACKAGE_NAME = 'tooltip'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('tooltip')
+ rescue
+ ''
+ end
+ end
+ end
+end
+
+module Tk::Tcllib::Tooltip
+ extend TkCore
+
+ WidgetClassName = 'Tooltip'.freeze
+ def self.database_classname
+ self::WidgetClassName
+ end
+ def self.database_class
+ WidgetClassNames[self::WidgetClassName]
+ end
+
+ def self.clear(glob_path_pat = None)
+ self.clear_glob(glob_path_pat)
+ end
+
+ def self.clear_glob(glob_path_pat)
+ tk_call_without_enc('::tooltip::tooltip', 'clear', glob_path_pat)
+ end
+
+ def self.clear_widgets(*args)
+ self.clear_glob("{#{args.collect{|w| _get_eval_string(w)}.join(',')}}")
+ end
+
+ def self.clear_children(*args)
+ self.clear_glob("{#{args.collect{|w| s = _get_eval_string(w); "#{s},#{s}.*"}.join(',')}}")
+ end
+
+ def self.delay(millisecs=None)
+ number(tk_call_without_enc('::tooltip::tooltip', 'delay', millisecs))
+ end
+ def self.delay=(millisecs)
+ self.delay(millisecs)
+ end
+
+ def self.disable
+ tk_call_without_enc('::tooltip::tooltip', 'disable')
+ false
+ end
+ def self.off
+ self.disable
+ end
+
+ def self.enable
+ tk_call_without_enc('::tooltip::tooltip', 'enable')
+ true
+ end
+ def self.on
+ self.enable
+ end
+
+ def self.register(widget, msg, keys=nil)
+ if keys.kind_of?(Hash)
+ args = hash_kv(keys) << msg
+ else
+ args = msg
+ end
+ tk_call_without_enc('::tooltip::tooltip', widget.path, *args)
+ end
+
+ def self.erase(widget)
+ tk_call_without_enc('::tooltip::tooltip', widget.path, '')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tcllib/widget.rb b/ext/tk/lib/tkextlib/tcllib/widget.rb
new file mode 100644
index 0000000000..ed69f67ce6
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tcllib/widget.rb
@@ -0,0 +1,48 @@
+#
+# tkextlib/tcllib/widget.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# * Part of tcllib extension
+# * megawidget package that uses snit as the object system (snidgets)
+#
+
+require 'tk'
+require 'tkextlib/tcllib.rb'
+
+# TkPackage.require('widget', '3.0')
+TkPackage.require('widget')
+
+module Tk::Tcllib
+ module Widget
+ PACKAGE_NAME = 'widget'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('widget')
+ rescue
+ ''
+ end
+ end
+ end
+end
+
+module Tk::Tcllib::Widget
+ autoload :Dialog, 'tkextlib/tcllib/dialog'
+
+ autoload :Panelframe, 'tkextlib/tcllib/panelframe'
+ autoload :PanelFrame, 'tkextlib/tcllib/panelframe'
+
+ autoload :Ruler, 'tkextlib/tcllib/ruler'
+
+ autoload :Screenruler, 'tkextlib/tcllib/screenruler'
+ autoload :ScreenRuler, 'tkextlib/tcllib/screenruler'
+
+ autoload :Scrolledwindow, 'tkextlib/tcllib/scrollwin'
+ autoload :ScrolledWindow, 'tkextlib/tcllib/scrollwin'
+
+ autoload :Superframe, 'tkextlib/tcllib/superframe'
+ autoload :SuperFrame, 'tkextlib/tcllib/superframe'
+end
diff --git a/ext/tk/lib/tkextlib/tclx.rb b/ext/tk/lib/tkextlib/tclx.rb
new file mode 100644
index 0000000000..3a4ff27644
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tclx.rb
@@ -0,0 +1,13 @@
+#
+# TclX support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# call setup script
+require 'tkextlib/tclx/setup.rb'
+
+# load library
+require 'tkextlib/tclx/tclx'
diff --git a/ext/tk/lib/tkextlib/tclx/setup.rb b/ext/tk/lib/tkextlib/tclx/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tclx/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/tclx/tclx.rb b/ext/tk/lib/tkextlib/tclx/tclx.rb
new file mode 100644
index 0000000000..5a908fcd0b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tclx/tclx.rb
@@ -0,0 +1,74 @@
+#
+# tclx/tclx.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 'tkextlib/tclx/setup.rb'
+
+# TkPackage.require('Tclx', '8.0')
+TkPackage.require('Tclx')
+
+module Tk
+ module TclX
+ PACKAGE_NAME = 'Tclx'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('Tclx')
+ rescue
+ ''
+ end
+ end
+
+ def self.infox(*args)
+ Tk.tk_call('infox', *args)
+ end
+
+ def self.signal(*args)
+ warn("Warning: Don't recommend to use TclX's 'signal' command. Please use Ruby's 'Signal.trap' method")
+ Tk.tk_call('signal', *args)
+ end
+
+ def self.signal_restart(*args)
+ warn("Warning: Don't recommend to use TclX's 'signal' command. Please use Ruby's 'Signal.trap' method")
+ Tk.tk_call('signal', '-restart', *args)
+ end
+
+ ##############################
+
+ class XPG3_MsgCat
+ class << self
+ alias open new
+ end
+
+ def initialize(catname, fail_mode=false)
+ if fail_mode
+ @msgcat_id = Tk.tk_call('catopen', '-fail', catname)
+ else
+ @msgcat_id = Tk.tk_call('catopen', '-nofail', catname)
+ end
+ end
+
+ def close(fail_mode=false)
+ if fail_mode
+ Tk.tk_call('catclose', '-fail', @msgcat_id)
+ else
+ Tk.tk_call('catclose', '-nofail', @msgcat_id)
+ end
+ self
+ end
+
+ def get(setnum, msgnum, defaultstr)
+ Tk.tk_call('catgets', @msgcat_id, setnum, msgnum, defaultstr)
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile.rb b/ext/tk/lib/tkextlib/tile.rb
new file mode 100644
index 0000000000..60ea012cc0
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile.rb
@@ -0,0 +1,419 @@
+#
+# Tile theme engin (tile widget set) support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/ttk_selector'
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# library directory
+require 'tkextlib/tile/setup.rb'
+
+# load package
+# TkPackage.require('tile', '0.4')
+# TkPackage.require('tile', '0.6')
+# TkPackage.require('tile', '0.7')
+if Tk::TK_MAJOR_VERSION > 8 ||
+ (Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION >= 5)
+ TkPackage.require('tile') # for compatibility (version check of 'tile')
+ verstr = TkPackage.require('Ttk')
+else
+ verstr = TkPackage.require('tile')
+end
+
+ver = verstr.split('.')
+if ver[0].to_i == 0
+ # Tile extension package
+ if ver[1].to_i <= 4
+ # version 0.4 or former
+ module Tk
+ module Tile
+ USE_TILE_NAMESPACE = true
+ USE_TTK_NAMESPACE = false
+ TILE_SPEC_VERSION_ID = 0
+ end
+ end
+ elsif ver[1].to_i <= 6
+ # version 0.5 -- version 0.6
+ module Tk
+ module Tile
+ USE_TILE_NAMESPACE = true
+ USE_TTK_NAMESPACE = true
+ TILE_SPEC_VERSION_ID = 5
+ end
+ end
+ elsif ver[1].to_i <= 7
+ module Tk
+ module Tile
+ USE_TILE_NAMESPACE = false
+ USE_TTK_NAMESPACE = true
+ TILE_SPEC_VERSION_ID = 7
+ end
+ end
+ else
+ # version 0.8 or later
+ module Tk
+ module Tile
+ USE_TILE_NAMESPACE = false
+ USE_TTK_NAMESPACE = true
+ TILE_SPEC_VERSION_ID = 8
+ end
+ end
+ end
+
+ module Tk::Tile
+ PACKAGE_NAME = 'tile'.freeze
+ end
+else
+ # Ttk package merged Tcl/Tk core (Tcl/Tk 8.5+)
+ module Tk
+ module Tile
+ USE_TILE_NAMESPACE = false
+ USE_TTK_NAMESPACE = true
+ TILE_SPEC_VERSION_ID = 8
+
+ PACKAGE_NAME = 'Ttk'.freeze
+ end
+ end
+end
+
+# autoload
+module Tk
+ module Tile
+ TkComm::TkExtlibAutoloadModule.unshift(self)
+
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require(PACKAGE_NAME)
+ rescue
+ ''
+ end
+ end
+
+ def self.__Import_Tile_Widgets__!
+ warn 'Warning: "Tk::Tile::__Import_Tile_Widgets__!" is obsolete.' <<
+ ' To control default widget set, use "Tk.default_widget_set = :Ttk"'
+ Tk.tk_call('namespace', 'import', '-force', 'ttk::*')
+ end
+
+ def self.__define_LoadImages_proc_for_compatibility__!
+ # Ttk 8.5 (Tile 0.8) lost 'LoadImages' utility procedure.
+ # So, some old scripts doen't work, because those scripts use the
+ # procedure to define local styles.
+ # Of course, rewriting such Tcl/Tk scripts isn't difficult for
+ # Tcl/Tk users. However, it may be troublesome for Ruby/Tk users
+ # who use such Tcl/Tk scripts as it is.
+ # This method may help Ruby/Tk users who don't want to modify old
+ # Tcl/Tk scripts for the latest version of Ttk (Tile) extension.
+ # This method defines a comaptible 'LoadImages' procedure on the
+ # Tcl/Tk interpreter working under Ruby/Tk.
+ # Please give attention to use this method. It may conflict with
+ # some definitions on Tcl/Tk scripts.
+ klass_name = self.name
+ proc_name = 'LoadImages'
+ if Tk::Tile::USE_TTK_NAMESPACE
+ ns_list = ['::tile']
+ if Tk.info(:commands, "::ttk::#{proc_name}").empty?
+ ns_list << '::ttk'
+ end
+ else # Tk::Tile::USE_TILE_NAMESPACE
+ ns_list = ['::ttk']
+ if Tk.info(:commands, "::tile::#{proc_name}").empty?
+ ns_list << '::tile'
+ end
+ end
+
+ ns_list.each{|ns|
+ cmd = "#{ns}::#{proc_name}"
+ unless Tk.info(:commands, cmd).empty?
+ #fail RuntimeError, "can't define '#{cmd}' command (already exist)"
+
+ # do nothing !!!
+ warn "Warning: can't define '#{cmd}' command (already exist)" if $DEBUG
+ next
+ end
+ TkNamespace.eval(ns){
+ TkCore::INTERP.add_tk_procs(proc_name, 'imgdir {patterns {*.gif}}',
+ <<-'EOS')
+ foreach pattern $patterns {
+ foreach file [glob -directory $imgdir $pattern] {
+ set img [file tail [file rootname $file]]
+ if {![info exists images($img)]} {
+ set images($img) [image create photo -file $file]
+ }
+ }
+ }
+ return [array get images]
+ EOS
+ }
+ }
+ end
+
+ def self.load_images(imgdir, pat=nil)
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ if Tk::Tile::USE_TTK_NAMESPACE
+ cmd = '::ttk::LoadImages'
+ else # Tk::Tile::USE_TILE_NAMESPACE
+ cmd = '::tile::LoadImages'
+ end
+ pat ||= TkComm::None
+ images = Hash[*TkComm.simplelist(Tk.tk_call(cmd, imgdir, pat))]
+ images.keys.each{|k|
+ images[k] = TkPhotoImage.new(:imagename=>images[k],
+ :without_creating=>true)
+ }
+ else ## TILE_SPEC_VERSION_ID >= 8
+ pat ||= '*.gif'
+ if pat.kind_of?(Array)
+ pat_list = pat
+ else
+ pat_list = [ pat ]
+ end
+ Dir.chdir(imgdir){
+ pat_list.each{|pat|
+ Dir.glob(pat).each{|f|
+ img = File.basename(f, '.*')
+ unless TkComm.bool(Tk.info('exists', "images(#{img})"))
+ Tk.tk_call('set', "images(#{img})",
+ Tk.tk_call('image', 'create', 'photo', '-file', f))
+ end
+ }
+ }
+ }
+ images = Hash[*TkComm.simplelist(Tk.tk_call('array', 'get', 'images'))]
+ images.keys.each{|k|
+ images[k] = TkPhotoImage.new(:imagename=>images[k],
+ :without_creating=>true)
+ }
+ end
+
+ images
+ end
+
+ def self.style(*args)
+ args.map!{|arg| TkComm._get_eval_string(arg)}.join('.')
+ end
+
+ def self.themes(glob_ptn = nil)
+ if TILE_SPEC_VERSION_ID < 8 && Tk.info(:commands, '::ttk::themes').empty?
+ fail RuntimeError, 'not support glob option' if glob_ptn
+ cmd = ['::tile::availableThemes']
+ else
+ glob_ptn = '*' unless glob_ptn
+ cmd = ['::ttk::themes', glob_ptn]
+ end
+
+ begin
+ TkComm.simplelist(Tk.tk_call_without_enc(*cmd))
+ rescue
+ TkComm.simplelist(Tk.tk_call('lsearch', '-all', '-inline',
+ Tk::Tile::Style.theme_names,
+ glob_ptn))
+ end
+ end
+
+ def self.set_theme(theme)
+ if TILE_SPEC_VERSION_ID < 8 && Tk.info(:commands, '::ttk::setTheme').empty?
+ cmd = '::tile::setTheme'
+ else
+ cmd = '::ttk::setTheme'
+ end
+
+ begin
+ Tk.tk_call_without_enc(cmd, theme)
+ rescue
+ Tk::Tile::Style.theme_use(theme)
+ end
+ end
+
+ module KeyNav
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ def self.enableMnemonics(w)
+ Tk.tk_call('::keynav::enableMnemonics', w)
+ end
+ def self.defaultButton(w)
+ Tk.tk_call('::keynav::defaultButton', w)
+ end
+ else # dummy
+ def self.enableMnemonics(w)
+ ""
+ end
+ def self.defaultButton(w)
+ ""
+ end
+ end
+ end
+
+ module Font
+ Default = 'TkDefaultFont'
+ Text = 'TkTextFont'
+ Heading = 'TkHeadingFont'
+ Caption = 'TkCaptionFont'
+ Tooltip = 'TkTooltipFont'
+
+ Fixed = 'TkFixedFont'
+ Menu = 'TkMenuFont'
+ SmallCaption = 'TkSmallCaptionFont'
+ Icon = 'TkIconFont'
+
+ TkFont::SYSTEM_FONT_NAMES.add [
+ 'TkDefaultFont', 'TkTextFont', 'TkHeadingFont',
+ 'TkCaptionFont', 'TkTooltipFont', 'TkFixedFont',
+ 'TkMenuFont', 'TkSmallCaptionFont', 'TkIconFont'
+ ]
+ end
+
+ module ParseStyleLayout
+ def _style_layout(lst)
+ ret = []
+ until lst.empty?
+ sub = [lst.shift]
+ keys = {}
+
+ until lst.empty?
+ if lst[0][0] == ?-
+ k = lst.shift[1..-1]
+ children = lst.shift
+ children = _style_layout(children) if children.kind_of?(Array)
+ keys[k] = children
+ else
+ break
+ end
+ end
+
+ sub << keys unless keys.empty?
+ ret << sub
+ end
+ ret
+ end
+ private :_style_layout
+ end
+
+ module TileWidget
+ include Tk::Tile::ParseStyleLayout
+
+ def __val2ruby_optkeys # { key=>proc, ... }
+ # The method is used to convert a opt-value to a ruby's object.
+ # When get the value of the option "key", "proc.call(value)" is called.
+ super().update('style'=>proc{|v| _style_layout(list(v))})
+ end
+ private :__val2ruby_optkeys
+
+ def ttk_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
+ alias tile_instate ttk_instate
+
+ def ttk_state(state=nil)
+ if state
+ tk_send('state', state)
+ else
+ list(tk_send('state'))
+ end
+ end
+ alias tile_state ttk_state
+
+ def ttk_identify(x, y)
+ ret = tk_send_without_enc('identify', x, y)
+ (ret.empty?)? nil: ret
+ end
+ alias tile_identify ttk_identify
+
+ # remove instate/state/identify method
+ # to avoid the conflict with widget options
+ if Tk.const_defined?(:USE_OBSOLETE_TILE_STATE_METHOD) && Tk::USE_OBSOLETE_TILE_STATE_METHOD
+ alias instate ttk_instate
+ alias state ttk_state
+ alias identify ttk_identify
+ end
+ end
+
+ ######################################
+
+ autoload :TButton, 'tkextlib/tile/tbutton'
+ autoload :Button, 'tkextlib/tile/tbutton'
+
+ autoload :TCheckButton, 'tkextlib/tile/tcheckbutton'
+ autoload :CheckButton, 'tkextlib/tile/tcheckbutton'
+ autoload :TCheckbutton, 'tkextlib/tile/tcheckbutton'
+ autoload :Checkbutton, 'tkextlib/tile/tcheckbutton'
+
+ autoload :Dialog, 'tkextlib/tile/dialog'
+
+ autoload :TEntry, 'tkextlib/tile/tentry'
+ autoload :Entry, 'tkextlib/tile/tentry'
+
+ autoload :TCombobox, 'tkextlib/tile/tcombobox'
+ autoload :Combobox, 'tkextlib/tile/tcombobox'
+
+ autoload :TFrame, 'tkextlib/tile/tframe'
+ autoload :Frame, 'tkextlib/tile/tframe'
+
+ autoload :TLabelframe, 'tkextlib/tile/tlabelframe'
+ autoload :Labelframe, 'tkextlib/tile/tlabelframe'
+ autoload :TLabelFrame, 'tkextlib/tile/tlabelframe'
+ autoload :LabelFrame, 'tkextlib/tile/tlabelframe'
+
+ autoload :TLabel, 'tkextlib/tile/tlabel'
+ autoload :Label, 'tkextlib/tile/tlabel'
+
+ autoload :TMenubutton, 'tkextlib/tile/tmenubutton'
+ autoload :Menubutton, 'tkextlib/tile/tmenubutton'
+ autoload :TMenuButton, 'tkextlib/tile/tmenubutton'
+ autoload :MenuButton, 'tkextlib/tile/tmenubutton'
+
+ autoload :TNotebook, 'tkextlib/tile/tnotebook'
+ autoload :Notebook, 'tkextlib/tile/tnotebook'
+
+ autoload :TPaned, 'tkextlib/tile/tpaned'
+ autoload :Paned, 'tkextlib/tile/tpaned'
+ autoload :PanedWindow, 'tkextlib/tile/tpaned'
+ autoload :Panedwindow, 'tkextlib/tile/tpaned'
+
+ autoload :TProgressbar, 'tkextlib/tile/tprogressbar'
+ autoload :Progressbar, 'tkextlib/tile/tprogressbar'
+
+ autoload :TRadioButton, 'tkextlib/tile/tradiobutton'
+ autoload :RadioButton, 'tkextlib/tile/tradiobutton'
+ autoload :TRadiobutton, 'tkextlib/tile/tradiobutton'
+ autoload :Radiobutton, 'tkextlib/tile/tradiobutton'
+
+ autoload :TScale, 'tkextlib/tile/tscale'
+ autoload :Scale, 'tkextlib/tile/tscale'
+ autoload :TProgress, 'tkextlib/tile/tscale'
+ autoload :Progress, 'tkextlib/tile/tscale'
+
+ autoload :TScrollbar, 'tkextlib/tile/tscrollbar'
+ autoload :Scrollbar, 'tkextlib/tile/tscrollbar'
+ autoload :XScrollbar, 'tkextlib/tile/tscrollbar'
+ autoload :YScrollbar, 'tkextlib/tile/tscrollbar'
+
+ autoload :TSeparator, 'tkextlib/tile/tseparator'
+ autoload :Separator, 'tkextlib/tile/tseparator'
+
+ autoload :TSquare, 'tkextlib/tile/tsquare'
+ autoload :Square, 'tkextlib/tile/tsquare'
+
+ autoload :SizeGrip, 'tkextlib/tile/sizegrip'
+ autoload :Sizegrip, 'tkextlib/tile/sizegrip'
+
+ autoload :Treeview, 'tkextlib/tile/treeview'
+
+ autoload :Style, 'tkextlib/tile/style'
+ end
+end
+
+Ttk = Tk::Tile
diff --git a/ext/tk/lib/tkextlib/tile/dialog.rb b/ext/tk/lib/tkextlib/tile/dialog.rb
new file mode 100644
index 0000000000..ef2d1fe577
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/dialog.rb
@@ -0,0 +1,96 @@
+#
+# ttk::dialog (tile-0.7+)
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class Dialog < TkWindow
+ end
+ end
+end
+
+class Tk::Tile::Dialog
+ TkCommandNames = ['::ttk::dialog'.freeze].freeze
+
+ def self.show(*args)
+ dialog = self.new(*args)
+ dialog.show
+ [dialog.status, dialog.value]
+ end
+ def self.display(*args)
+ self.show(*args)
+ end
+
+ def self.define_dialog_type(name, keys)
+ Tk.tk_call('::ttk::dialog::define', name, keys)
+ name
+ end
+
+ def self.style(*args)
+ ['Dialog', *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+
+ #########################
+
+ def initialize(keys={})
+ @keys = _symbolkey2str(keys)
+ super(*args)
+ end
+
+ def create_self(keys)
+ # dummy
+ end
+ private :create_self
+
+ def show
+ tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys))
+ end
+ alias display show
+
+ def client_frame
+ window(tk_call_without_enc('::ttk::dialog::clientframe', @path))
+ end
+
+ def cget_strict(slot)
+ @keys[slot.to_s]
+ end
+ def cget(slot)
+ @keys[slot.to_s]
+ end
+=begin
+ def cget(slot)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ cget_strict(slot)
+ else
+ cget_strict(slot) rescue nil
+ end
+ end
+=end
+
+ def configure(slot, value=None)
+ if slot.kind_of?(Hash)
+ slot.each{|k, v| configure(k, v)}
+ else
+ slot = slot.to_s
+ value = _symbolkey2str(value) if value.kind_of?(Hash)
+ if value && value != None
+ @keys[slot] = value
+ else
+ @keys.delete(slot)
+ end
+ end
+ self
+ end
+
+ def configinfo(slot = nil)
+ if slot
+ slot = slot.to_s
+ [ slot, nil, nil, nil, @keys[slot] ]
+ else
+ @keys.collect{|k, v| [ k, nil, nil, nil, v ] }
+ end
+ 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/sizegrip.rb b/ext/tk/lib/tkextlib/tile/sizegrip.rb
new file mode 100644
index 0000000000..c5068919a4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/sizegrip.rb
@@ -0,0 +1,29 @@
+#
+# ttk::sizegrip widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class SizeGrip < TkWindow
+ end
+ Sizegrip = SizeGrip
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Sizegrip, :TkSizegrip, :TkSizeGrip)
+
+
+class Tk::Tile::SizeGrip < TkWindow
+ include Tk::Tile::TileWidget
+
+ TkCommandNames = ['::ttk::sizegrip'.freeze].freeze
+ WidgetClassName = 'TSizegrip'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/style.rb b/ext/tk/lib/tkextlib/tile/style.rb
new file mode 100644
index 0000000000..ca7ee99c32
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/style.rb
@@ -0,0 +1,316 @@
+#
+# style commands
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ module Style
+ end
+ end
+end
+
+module Tk::Tile::Style
+ extend TkCore
+end
+
+class << Tk::Tile::Style
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ TkCommandNames = ['style'.freeze].freeze
+
+ # --- Tk::Tile::Style.__define_wrapper_proc_for_compatibility__! ---
+ # On Ttk (Tile) extension, 'style' command has imcompatible changes
+ # depend on the version of the extention. It requires modifying the
+ # Tcl/Tk scripts to define local styles. The rule for modification
+ # is a simple one. But, if users want to keep compatibility between
+ # versions of the extension, they will have to contrive to do that.
+ # It may be troublesome, especially for Ruby/Tk users.
+ # This method may help such work. This method make some definitions
+ # on the Tcl/Tk interpreter to work with different version of style
+ # command format. Please give attention to use this method. It may
+ # conflict with some definitions on Tcl/Tk scripts.
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 7
+ def __define_wrapper_proc_for_compatibility__!
+ __define_themes_and_setTheme_proc__!
+
+ unless Tk.info(:commands, '::ttk::style').empty?
+ # fail RuntimeError,
+ # "can't define '::ttk::style' command (already exist)"
+
+ # do nothing !!!
+ warn "Warning: can't define '::ttk::style' command (already exist)" if $DEBUG
+ return
+ end
+ TkCore::INTERP.add_tk_procs('::ttk::style', 'args', <<-'EOS')
+ if [string equal [lrange $args 0 1] {element create}] {
+ if [string equal [lindex $args 3] image] {
+ set spec [lindex $args 4]
+ set map [lrange $spec 1 end]
+ if [llength $map] {
+ # return [eval [concat [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]]
+ return [uplevel 1 [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]
+ }
+ }
+ }
+ # return [eval "::style $args"]
+ return [uplevel 1 ::style $args]
+ EOS
+ #########################
+ end
+ else ### TILE_SPEC_VERSION_ID == 7
+ def __define_wrapper_proc_for_compatibility__!
+ __define_themes_and_setTheme_proc__!
+
+ unless Tk.info(:commands, '::ttk::style').empty?
+ # fail RuntimeError,
+ # "can't define '::ttk::style' command (already exist)"
+
+ # do nothing !!!
+ warn "Warning: can't define '::ttk::style' command (already exist)" if $DEBUG
+ return
+ end
+ TkCore::INTERP.add_tk_procs('::ttk::style', 'args', <<-'EOS')
+ if [string equal [lrange $args 0 1] {element create}] {
+ if [string equal [lindex $args 3] image] {
+ set spec [lindex $args 4]
+ set map [lrange $spec 1 end]
+ if [llength $map] {
+ # return [eval [concat [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]]
+ return [uplevel 1 [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]]
+ }
+ }
+ } elseif [string equal [lindex $args 0] default] {
+ # return [eval "::style [lreplace $args 0 0 configure]"]
+ return [uplevel 1 ::style [lreplace $args 0 0 configure]]
+ }
+ # return [eval "::style $args"]
+ return [uplevel 1 ::style $args]
+ EOS
+ #########################
+ end
+ end
+ else ### TILE_SPEC_VERSION_ID >= 8
+ TkCommandNames = ['::ttk::style'.freeze].freeze
+
+ def __define_wrapper_proc_for_compatibility__!
+ __define_themes_and_setTheme_proc__!
+
+ unless Tk.info(:commands, '::style').empty?
+ # fail RuntimeError, "can't define '::style' command (already exist)"
+
+ # do nothing !!!
+ warn "Warning: can't define '::style' command (already exist)" if $DEBUG
+ return
+ end
+ TkCore::INTERP.add_tk_procs('::style', 'args', <<-'EOS')
+ if [string equal [lrange $args 0 1] {element create}] {
+ if [string equal [lindex $args 3] image] {
+ set name [lindex $args 4]
+ set opts [lrange $args 5 end]
+ set idx [lsearch $opts -map]
+ if {$idx >= 0 && [expr $idx % 2 == 0]} {
+ # return [eval [concat [list ::ttk::style element create [lindex $args 2] image [concat $name [lindex $opts [expr $idx + 1]]]] [lreplace $opts $idx [expr $idx + 1]]]]
+ return [uplevel 1 [list ::ttk::style element create [lindex $args 2] image [concat $name [lindex $opts [expr $idx + 1]]]] [lreplace $opts $idx [expr $idx + 1]]]
+ }
+ }
+ } elseif [string equal [lindex $args 0] default] {
+ # return [eval "::ttk::style [lreplace $args 0 0 configure]"]
+ return [uplevel 1 ::ttk::style [lreplace $args 0 0 configure]]
+ }
+ # return [eval "::ttk::style $args"]
+ return [uplevel 1 ::ttk::style $args]
+ EOS
+ #########################
+ end
+ end
+
+ def __define_themes_and_setTheme_proc__!
+ TkCore::INTERP.add_tk_procs('::ttk::themes', '{ptn *}', <<-'EOS')
+ #set themes [list]
+ set themes [::ttk::style theme names]
+ foreach pkg [lsearch -inline -all -glob [package names] ttk::theme::$ptn] {
+ set theme [namespace tail $pkg]
+ if {[lsearch -exact $themes $theme] < 0} {
+ lappend themes $theme
+ }
+ }
+ foreach pkg [lsearch -inline -all -glob [package names] tile::theme::$ptn] {
+ set theme [namespace tail $pkg]
+ if {[lsearch -exact $themes $theme] < 0} {
+ lappend themes $theme
+ }
+ }
+ return $themes
+ EOS
+ #########################
+ TkCore::INTERP.add_tk_procs('::ttk::setTheme', 'theme', <<-'EOS')
+ variable currentTheme
+ if {[lsearch -exact [::ttk::style theme names] $theme] < 0} {
+ package require [lsearch -inline -regexp [package names] (ttk|tile)::theme::$theme]
+ }
+ ::ttk::style theme use $theme
+ set currentTheme $theme
+ EOS
+ end
+ private :__define_themes_and_setTheme_proc__!
+
+ def configure(style=nil, keys=nil)
+ if style.kind_of?(Hash)
+ keys = style
+ style = nil
+ end
+ style = '.' unless style
+
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 7
+ sub_cmd = 'default'
+ else
+ sub_cmd = 'configure'
+ end
+
+ if keys && keys != None
+ tk_call(TkCommandNames[0], sub_cmd, style, *hash_kv(keys))
+ else
+ tk_call(TkCommandNames[0], sub_cmd, style)
+ end
+ end
+ alias default configure
+
+ def map(style=nil, keys=nil)
+ if style.kind_of?(Hash)
+ keys = style
+ style = nil
+ end
+ style = '.' unless style
+
+ if keys && keys != None
+ if keys.kind_of?(Hash)
+ tk_call(TkCommandNames[0], 'map', style, *hash_kv(keys))
+ else
+ simplelist(tk_call(TkCommandNames[0], 'map', style, '-' << keys.to_s))
+ end
+ else
+ ret = {}
+ Hash[*(simplelist(tk_call(TkCommandNames[0], 'map', style)))].each{|k, v|
+ ret[k[1..-1]] = list(v)
+ }
+ ret
+ end
+ end
+ alias map_configure map
+
+ def map_configinfo(style=nil, key=None)
+ style = '.' unless style
+ map(style, key)
+ end
+
+ def map_default_configinfo(key=None)
+ map('.', key)
+ end
+
+ def lookup(style, opt, state=None, fallback_value=None)
+ tk_call(TkCommandNames[0], 'lookup', style,
+ '-' << opt.to_s, state, fallback_value)
+ end
+
+ include Tk::Tile::ParseStyleLayout
+
+ def layout(style=nil, spec=nil)
+ if style.kind_of?(Hash)
+ spec = style
+ style = nil
+ end
+ style = '.' unless style
+
+ if spec
+ tk_call(TkCommandNames[0], 'layout', style, spec)
+ else
+ _style_layout(list(tk_call(TkCommandNames[0], 'layout', style)))
+ end
+ end
+
+ def element_create(name, type, *args)
+ if type == 'image' || type == :image
+ element_create_image(name, *args)
+ else
+ tk_call(TkCommandNames[0], 'element', 'create', name, type, *args)
+ end
+ end
+
+ def element_create_image(name, *args)
+ fail ArgumentError, 'Must supply a base image' unless (spec = args.shift)
+ if (opts = args.shift)
+ if opts.kind_of?(Hash)
+ opts = _symbolkey2str(opts)
+ else
+ fail ArgumentError, 'bad option'
+ end
+ end
+ fail ArgumentError, 'too many arguments' unless args.empty?
+
+ if spec.kind_of?(Array)
+ # probably, command format is tile 0.8+ (Tcl/Tk8.5+) style
+ if Tk::Tile::TILE_SPEC_VERSION_ID >= 8
+ if opts
+ tk_call(TkCommandNames[0],
+ 'element', 'create', name, 'image', spec, opts)
+ else
+ tk_call(TkCommandNames[0], 'element', 'create', name, 'image', spec)
+ end
+ else
+ fail ArgumentError, 'illegal arguments' if opts.key?('map')
+ base = spec.shift
+ opts['map'] = spec
+ tk_call(TkCommandNames[0],
+ 'element', 'create', name, 'image', base, opts)
+ end
+ else
+ # probably, command format is tile 0.7.8 or older style
+ if Tk::Tile::TILE_SPEC_VERSION_ID >= 8
+ spec = [spec, *(opts.delete('map'))] if opts.key?('map')
+ end
+ if opts
+ tk_call(TkCommandNames[0],
+ 'element', 'create', name, 'image', spec, opts)
+ else
+ tk_call(TkCommandNames[0], 'element', 'create', name, 'image', spec)
+ end
+ end
+ end
+
+ def element_names()
+ list(tk_call(TkCommandNames[0], 'element', 'names'))
+ end
+
+ def element_options(elem)
+ simplelist(tk_call(TkCommandNames[0], 'element', 'options', elem))
+ end
+
+ def theme_create(name, keys=nil)
+ name = name.to_s
+ if keys && keys != None
+ tk_call(TkCommandNames[0], 'theme', 'create', name, *hash_kv(keys))
+ else
+ tk_call(TkCommandNames[0], 'theme', 'create', name)
+ end
+ name
+ end
+
+ def theme_settings(name, cmd=nil, &b)
+ name = name.to_s
+ cmd = Proc.new(&b) if !cmd && b
+ tk_call(TkCommandNames[0], 'theme', 'settings', name, cmd)
+ name
+ end
+
+ def theme_names()
+ list(tk_call(TkCommandNames[0], 'theme', 'names'))
+ end
+
+ def theme_use(name)
+ name = name.to_s
+ tk_call(TkCommandNames[0], 'theme', 'use', name)
+ 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..5d7db10fe9
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tbutton.rb
@@ -0,0 +1,33 @@
+#
+# tbutton widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TButton < Tk::Button
+ end
+ Button = TButton
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Button, :TkButton)
+
+
+class Tk::Tile::TButton < Tk::Button
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::button'.freeze].freeze
+ else
+ TkCommandNames = ['::tbutton'.freeze].freeze
+ end
+ WidgetClassName = 'TButton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+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..172225fcec
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb
@@ -0,0 +1,36 @@
+#
+# tcheckbutton widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TCheckButton < Tk::CheckButton
+ end
+ TCheckbutton = TCheckButton
+ CheckButton = TCheckButton
+ Checkbutton = TCheckButton
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Checkbutton,
+ :TkCheckbutton, :TkCheckButton)
+
+
+class Tk::Tile::TCheckButton < Tk::CheckButton
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::checkbutton'.freeze].freeze
+ else
+ TkCommandNames = ['::tcheckbutton'.freeze].freeze
+ end
+ WidgetClassName = 'TCheckbutton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/tcombobox.rb b/ext/tk/lib/tkextlib/tile/tcombobox.rb
new file mode 100644
index 0000000000..b64372f1c9
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tcombobox.rb
@@ -0,0 +1,54 @@
+#
+# tcombobox widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TCombobox < Tk::Tile::TEntry
+ end
+ Combobox = TCombobox
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Combobox, :TkCombobox)
+
+
+class Tk::Tile::TCombobox < Tk::Tile::TEntry
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::combobox'.freeze].freeze
+ else
+ TkCommandNames = ['::tcombobox'.freeze].freeze
+ end
+ WidgetClassName = 'TCombobox'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __boolval_optkeys
+ super() << 'exportselection'
+ end
+ private :__boolval_optkeys
+
+ def __listval_optkeys
+ super() << 'values'
+ end
+ private :__listval_optkeys
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+
+ def current
+ number(tk_send_without_enc('current'))
+ end
+ def current=(idx)
+ tk_send_without_enc('current', idx)
+ end
+
+ def set(val)
+ tk_send('set', val)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/tentry.rb b/ext/tk/lib/tkextlib/tile/tentry.rb
new file mode 100644
index 0000000000..0bea98dcd9
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tentry.rb
@@ -0,0 +1,48 @@
+#
+# tentry widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TEntry < Tk::Entry
+ end
+ Entry = TEntry
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Entry, :TkEntry)
+
+
+class Tk::Tile::TEntry < Tk::Entry
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::entry'.freeze].freeze
+ else
+ TkCommandNames = ['::tentry'.freeze].freeze
+ end
+ WidgetClassName = 'TEntry'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __optkey_aliases
+ {:vcmd=>:validatecommand, :invcmd=>:invalidcommand}
+ end
+ private :__optkey_aliases
+
+ def __boolval_optkeys
+ super() << 'exportselection'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'show'
+ end
+ private :__strval_optkeys
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/tframe.rb b/ext/tk/lib/tkextlib/tile/tframe.rb
new file mode 100644
index 0000000000..3b5f98bb6e
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tframe.rb
@@ -0,0 +1,33 @@
+#
+# tframe widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TFrame < Tk::Frame
+ end
+ Frame = TFrame
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Frame, :TkFrame)
+
+
+class Tk::Tile::TFrame < Tk::Frame
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::frame'.freeze].freeze
+ else
+ TkCommandNames = ['::tframe'.freeze].freeze
+ end
+ WidgetClassName = 'TFrame'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ 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..7d074d3842
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tlabel.rb
@@ -0,0 +1,33 @@
+#
+# tlabel widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TLabel < Tk::Label
+ end
+ Label = TLabel
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Label, :TkLabel)
+
+
+class Tk::Tile::TLabel < Tk::Label
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::label'.freeze].freeze
+ else
+ TkCommandNames = ['::tlabel'.freeze].freeze
+ end
+ WidgetClassName = 'TLabel'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/tlabelframe.rb b/ext/tk/lib/tkextlib/tile/tlabelframe.rb
new file mode 100644
index 0000000000..cff66d8658
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tlabelframe.rb
@@ -0,0 +1,36 @@
+#
+# tlabelframe widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TLabelframe < Tk::Tile::TFrame
+ end
+ TLabelFrame = TLabelframe
+ Labelframe = TLabelframe
+ LabelFrame = TLabelframe
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Labelframe,
+ :TkLabelframe, :TkLabelFrame)
+
+
+class Tk::Tile::TLabelframe < Tk::Tile::TFrame
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::labelframe'.freeze].freeze
+ else
+ TkCommandNames = ['::tlabelframe'.freeze].freeze
+ end
+ WidgetClassName = 'TLabelframe'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+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..7c6ab28e52
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tmenubutton.rb
@@ -0,0 +1,36 @@
+#
+# tmenubutton widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TMenubutton < Tk::Menubutton
+ end
+ TMenuButton = TMenubutton
+ Menubutton = TMenubutton
+ MenuButton = TMenubutton
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Menubutton,
+ :TkMenubutton, :TkMenuButton)
+
+
+class Tk::Tile::TMenubutton < Tk::Menubutton
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::menubutton'.freeze].freeze
+ else
+ TkCommandNames = ['::tmenubutton'.freeze].freeze
+ end
+ WidgetClassName = 'TMenubutton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+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..4d65e363da
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tnotebook.rb
@@ -0,0 +1,139 @@
+#
+# tnotebook widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TNotebook < TkWindow
+ end
+ Notebook = TNotebook
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Notebook, :TkNotebook)
+
+
+class Tk::Tile::TNotebook < TkWindow
+ ################################
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id)
+ [self.path, 'tab', id]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, 'tab', id]
+ end
+ private :__item_config_cmd
+
+ def __item_listval_optkeys(id)
+ []
+ end
+ private :__item_listval_optkeys
+
+ def __item_methodcall_optkeys(id) # { key=>method, ... }
+ {}
+ end
+ private :__item_methodcall_optkeys
+
+ #alias tabcget itemcget
+ #alias tabcget_strict itemcget_strict
+ alias tabconfigure itemconfigure
+ alias tabconfiginfo itemconfiginfo
+ alias current_tabconfiginfo current_itemconfiginfo
+
+ def tabcget_strict(tagOrId, option)
+ tabconfigure(tagOrId, option)[-1]
+ end
+ def tabcget(tagOrId, option)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tabcget_strict(tagOrId, option)
+ else
+ begin
+ tabcget_strict(tagOrId, option)
+ rescue => e
+ begin
+ if current_tabconfiginfo(tagOrId).has_key?(option.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+ ################################
+
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::notebook'.freeze].freeze
+ else
+ TkCommandNames = ['::tnotebook'.freeze].freeze
+ end
+ WidgetClassName = 'TNotebook'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+
+ def enable_traversal()
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 5
+ tk_call_without_enc('::tile::enableNotebookTraversal', @path)
+ elsif Tk::Tile::TILE_SPEC_VERSION_ID < 7
+ tk_call_without_enc('::tile::notebook::enableTraversal', @path)
+ else
+ tk_call_without_enc('::ttk::notebook::enableTraversal', @path)
+ end
+ self
+ end
+
+ def add(child, keys=nil)
+ if keys && keys != None
+ tk_send('add', _epath(child), *hash_kv(keys))
+ else
+ tk_send('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 insert(idx, subwin, keys=nil)
+ if keys && keys != None
+ tk_send('insert', idx, subwin, *hash_kv(keys))
+ else
+ tk_send('insert', idx, subwin)
+ end
+ self
+ end
+
+ def select(idx)
+ tk_send('select', idx)
+ self
+ end
+
+ def selected
+ window(tk_send_without_enc('select'))
+ end
+
+ def tabs
+ list(tk_send('tabs'))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/tpaned.rb b/ext/tk/lib/tkextlib/tile/tpaned.rb
new file mode 100644
index 0000000000..d96ff43973
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tpaned.rb
@@ -0,0 +1,231 @@
+#
+# tpaned widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TPaned < TkWindow
+ end
+ PanedWindow = Panedwindow = Paned = TPaned
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Panedwindow,
+ :TkPanedwindow, :TkPanedWindow)
+
+
+class Tk::Tile::TPaned < TkWindow
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ TkCommandNames = ['::ttk::paned'.freeze].freeze
+ else
+ TkCommandNames = ['::ttk::panedwindow'.freeze].freeze
+ end
+ else
+ TkCommandNames = ['::tpaned'.freeze].freeze
+ end
+ WidgetClassName = 'TPaned'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+
+ def add(*args)
+ keys = args.pop
+ fail ArgumentError, "no window in arguments" unless keys
+
+ if keys && keys.kind_of?(Hash)
+ fail ArgumentError, "no window in arguments" if args == []
+ opts = hash_kv(keys)
+ else
+ args.push(keys) if keys
+ opts = []
+ end
+
+ args.each{|win|
+ tk_send_without_enc('add', _epath(win), *opts)
+ }
+ self
+ end
+
+ def forget(pane)
+ pane = _epath(pane)
+ tk_send_without_enc('forget', pane)
+ self
+ end
+
+ def insert(pos, win, keys)
+ win = _epath(win)
+ tk_send_without_enc('insert', pos, win, *hash_kv(keys))
+ self
+ end
+
+ def panecget_strict(pane, slot)
+ pane = _epath(pane)
+ tk_tcl2ruby(tk_send_without_enc('pane', pane, "-#{slot}"))
+ end
+ alias pane_cget_strict panecget_strict
+
+ def panecget(pane, slot)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ panecget_strict(pane, slot)
+ else
+ begin
+ panecget_strict(pane, slot)
+ rescue => e
+ begin
+ if current_paneconfiginfo(pane).has_key?(slot.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+ alias pane_cget panecget
+
+ def paneconfigure(pane, key, value=nil)
+ pane = _epath(pane)
+ if key.kind_of? Hash
+ params = []
+ key.each{|k, v|
+ params.push("-#{k}")
+ # params.push((v.kind_of?(TkObject))? v.epath: v)
+ params.push(_epath(v))
+ }
+ tk_send_without_enc('pane', pane, *params)
+ else
+ # value = value.epath if value.kind_of?(TkObject)
+ value = _epath(value)
+ tk_send_without_enc('pane', pane, "-#{key}", value)
+ end
+ self
+ end
+ alias pane_config paneconfigure
+ alias pane_configure paneconfigure
+
+ def paneconfiginfo(win)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ win = _epath(win)
+ if key
+ conf = tk_split_list(tk_send_without_enc('pane', win, "-#{key}"))
+ conf[0] = conf[0][1..-1]
+ if conf[0] == 'hide'
+ conf[3] = bool(conf[3]) unless conf[3].empty?
+ conf[4] = bool(conf[4]) unless conf[4].empty?
+ end
+ conf
+ else
+ tk_split_simplelist(tk_send_without_enc('pane',
+ win)).collect{|conflist|
+ conf = tk_split_simplelist(conflist)
+ conf[0] = conf[0][1..-1]
+ if conf[3]
+ if conf[0] == 'hide'
+ conf[3] = bool(conf[3]) unless conf[3].empty?
+ elsif conf[3].index('{')
+ conf[3] = tk_split_list(conf[3])
+ else
+ conf[3] = tk_tcl2ruby(conf[3])
+ end
+ end
+ if conf[4]
+ if conf[0] == 'hide'
+ conf[4] = bool(conf[4]) unless conf[4].empty?
+ elsif conf[4].index('{')
+ conf[4] = tk_split_list(conf[4])
+ else
+ conf[4] = tk_tcl2ruby(conf[4])
+ end
+ end
+ conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
+ conf
+ }
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ win = _epath(win)
+ if key
+ conf = tk_split_list(tk_send_without_enc('pane', win, "-#{key}"))
+ key = conf.shift[1..-1]
+ if key == 'hide'
+ conf[2] = bool(conf[2]) unless conf[2].empty?
+ conf[3] = bool(conf[3]) unless conf[3].empty?
+ end
+ { key => conf }
+ else
+ ret = {}
+ tk_split_simplelist(tk_send_without_enc('pane',
+ win)).each{|conflist|
+ conf = tk_split_simplelist(conflist)
+ key = conf.shift[1..-1]
+ if key
+ if key == 'hide'
+ conf[2] = bool(conf[2]) unless conf[2].empty?
+ elsif conf[2].index('{')
+ conf[2] = tk_split_list(conf[2])
+ else
+ conf[2] = tk_tcl2ruby(conf[2])
+ end
+ end
+ if conf[3]
+ if key == 'hide'
+ conf[3] = bool(conf[3]) unless conf[3].empty?
+ elsif conf[3].index('{')
+ conf[3] = tk_split_list(conf[3])
+ else
+ conf[3] = tk_tcl2ruby(conf[3])
+ end
+ end
+ if conf.size == 1
+ ret[key] = conf[0][1..-1] # alias info
+ else
+ ret[key] = conf
+ end
+ }
+ ret
+ end
+ end
+ end
+ alias pane_configinfo paneconfiginfo
+
+ def current_paneconfiginfo(win, key=nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if key
+ conf = paneconfiginfo(win, key)
+ {conf[0] => conf[4]}
+ else
+ ret = {}
+ paneconfiginfo(win).each{|conf|
+ ret[conf[0]] = conf[4] if conf.size > 2
+ }
+ ret
+ end
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ paneconfiginfo(win, key).each{|k, conf|
+ ret[k] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+ alias current_pane_configinfo current_paneconfiginfo
+
+ def identify(x, y)
+ list(tk_send_without_enc('identify', x, y))
+ end
+
+ def sashpos(idx, newpos=None)
+ num_or_str(tk_send_without_enc('sashpos', idx, newpos))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/tprogressbar.rb b/ext/tk/lib/tkextlib/tile/tprogressbar.rb
new file mode 100644
index 0000000000..f786d370dd
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tprogressbar.rb
@@ -0,0 +1,56 @@
+#
+# tprogressbar widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TProgressbar < TkWindow
+ end
+ Progressbar = TProgressbar
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Progressbar, :TkProgressbar)
+
+
+class Tk::Tile::TProgressbar
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::progressbar'.freeze].freeze
+ else
+ TkCommandNames = ['::tprogressbar'.freeze].freeze
+ end
+ WidgetClassName = 'TProgressbar'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+
+ def step(amount=None)
+ tk_send_without_enc('step', amount).to_f
+ end
+ #def step=(amount)
+ # tk_send_without_enc('step', amount)
+ #end
+
+ def start(interval=None)
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 5
+ tk_call_without_enc('::tile::progressbar::start', @path, interval)
+ else
+ tk_send_without_enc('start', interval)
+ end
+ end
+
+ def stop(amount=None)
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 5
+ tk_call_without_enc('::tile::progressbar::stop', @path)
+ else
+ tk_send_without_enc('stop', amount)
+ end
+ 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..d653a6d256
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tradiobutton.rb
@@ -0,0 +1,36 @@
+#
+# tradiobutton widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TRadioButton < Tk::RadioButton
+ end
+ TRadiobutton = TRadioButton
+ RadioButton = TRadioButton
+ Radiobutton = TRadioButton
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Radiobutton,
+ :TkRadiobutton, :TkRadioButton)
+
+
+class Tk::Tile::TRadioButton < Tk::RadioButton
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::radiobutton'.freeze].freeze
+ else
+ TkCommandNames = ['::tradiobutton'.freeze].freeze
+ end
+ WidgetClassName = 'TRadiobutton'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/treeview.rb b/ext/tk/lib/tkextlib/tile/treeview.rb
new file mode 100644
index 0000000000..c978a1a07b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/treeview.rb
@@ -0,0 +1,1238 @@
+#
+# treeview widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class Treeview < TkWindow
+ end
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Treeview, :TkTreeview)
+
+
+module Tk::Tile::TreeviewConfig
+ include TkItemConfigMethod
+
+ def __item_configinfo_struct(id)
+ # maybe need to override
+ {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil,
+ :default_value=>nil, :current_value=>1}
+ end
+ private :__item_configinfo_struct
+
+ def __itemconfiginfo_core(tagOrId, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
+ fontkey = $2
+ return [slot.to_s, tagfontobj(tagid(tagOrId), fontkey)]
+ else
+ if slot
+ slot = slot.to_s
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
+ case slot
+ when /^(#{__tile_specific_item_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
+ val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << slot))
+ rescue
+ # Maybe, 'state' option has '-' in future.
+ val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ end
+ return [slot, val]
+
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
+ optval = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ return [slot, val]
+
+ 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('|')})$/
+ begin
+ val = number(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ rescue
+ val = nil
+ end
+ return [slot, val]
+
+ when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = num_or_str(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ return [slot, val]
+
+ when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ val = bool(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ rescue
+ val = nil
+ end
+ return [slot, val]
+
+ when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ return [slot, val]
+
+ when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val =~ /^[0-9]/
+ return [slot, list(val)]
+ else
+ return [slot, val]
+ end
+
+ when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ return [slot, val]
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val.empty?
+ return [slot, nil]
+ else
+ return [slot, TkVarAccess.new(val)]
+ end
+
+ else
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val.index('{')
+ return [slot, tk_split_list(val)]
+ else
+ return [slot, tk_tcl2ruby(val)]
+ end
+ end
+
+ else # ! slot
+ ret = Hash[*(tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false))].to_a.collect{|conf|
+ conf[0] = conf[0][1..-1] if conf[0][0] == ?-
+ case conf[0]
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[conf[0]]
+ optval = conf[1]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[1] = val
+
+ when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
+ # do nothing
+
+ when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ conf[1] = number(conf[1])
+ rescue
+ conf[1] = nil
+ end
+
+ when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
+ conf[1] = num_or_str(conf[1])
+
+ when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ conf[1] = bool(conf[1])
+ rescue
+ conf[1] = nil
+ end
+
+ when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
+ conf[1] = simplelist(conf[1])
+
+ when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
+ if conf[1] =~ /^[0-9]/
+ conf[1] = list(conf[1])
+ end
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ if conf[1].empty?
+ conf[1] = nil
+ else
+ conf[1] = TkVarAccess.new(conf[1])
+ end
+
+ else
+ if conf[1].index('{')
+ conf[1] = tk_split_list(conf[1])
+ else
+ conf[1] = tk_tcl2ruby(conf[1])
+ end
+ end
+
+ conf
+ }
+
+ __item_font_optkeys(tagid(tagOrId)).each{|optkey|
+ optkey = optkey.to_s
+ fontconf = ret.assoc(optkey)
+ if fontconf
+ ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
+ fontconf[1] = 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 && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
+ fontkey = $2
+ return {slot.to_s => tagfontobj(tagid(tagOrId), fontkey)}
+ else
+ if slot
+ slot = slot.to_s
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
+ case slot
+ when /^(#{__tile_specific_item_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ # On tile-0.7.{2-8}, 'state' option has no '-' at its head.
+ val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << slot))
+ rescue
+ # Maybe, 'state' option has '-' in future.
+ val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ end
+ return {slot => val}
+
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
+ optval = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ return {slot => val}
+
+ 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('|')})$/
+ begin
+ val = number(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ rescue
+ val = nil
+ end
+ return {slot => val}
+
+ when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = num_or_str(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ return {slot => val}
+
+ when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ val = bool(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ rescue
+ val = nil
+ end
+ return {slot => val}
+
+ when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ return {slot => val}
+
+ when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val =~ /^[0-9]/
+ return {slot => list(val)}
+ else
+ return {slot => val}
+ end
+
+ when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ return {slot => val}
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val.empty?
+ return {slot => nil}
+ else
+ return {slot => TkVarAccess.new(val)}
+ end
+
+ else
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val.index('{')
+ return {slot => tk_split_list(val)}
+ else
+ return {slot => tk_tcl2ruby(val)}
+ end
+ end
+
+ else # ! slot
+ ret = {}
+ ret = Hash[*(tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false))].to_a.collect{|conf|
+ conf[0] = conf[0][1..-1] if conf[0][0] == ?-
+
+ optkey = conf[0]
+ case optkey
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey]
+ optval = conf[1]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[1] = val
+
+ when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
+ # do nothing
+
+ when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ conf[1] = number(conf[1])
+ rescue
+ conf[1] = nil
+ end
+
+ when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
+ conf[1] = num_or_str(conf[1])
+
+ when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ conf[1] = bool(conf[1])
+ rescue
+ conf[1] = nil
+ end
+
+ when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
+ conf[1] = simplelist(conf[1])
+
+ when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
+ if conf[1] =~ /^[0-9]/
+ conf[1] = list(conf[1])
+ end
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ if conf[1].empty?
+ conf[1] = nil
+ else
+ conf[1] = TkVarAccess.new(conf[1])
+ end
+
+ else
+ if conf[1].index('{')
+ return [slot, tk_split_list(conf[1])]
+ else
+ return [slot, tk_tcl2ruby(conf[1])]
+ end
+ end
+
+ ret[conf[0]] = conf[1]
+ }
+
+ __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[1] = 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 __item_cget_cmd(id)
+ [self.path, id[0], id[1]]
+ end
+ private :__item_cget_cmd
+
+ def __item_config_cmd(id)
+ [self.path, id[0], id[1]]
+ end
+ private :__item_config_cmd
+
+ def __item_numstrval_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ ['width']
+ when :column, 'column'
+ super(id[1]) + ['minwidth']
+ when :tag, 'tag'
+ super(id[1])
+ when :heading, 'heading'
+ super(id[1])
+ else
+ super(id[1])
+ end
+ end
+ private :__item_numstrval_optkeys
+
+ def __item_strval_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ super(id) + ['id']
+ when :column, 'column'
+ super(id[1])
+ when :tag, 'tag'
+ super(id[1])
+ when :heading, 'heading'
+ super(id[1])
+ else
+ super(id[1])
+ end
+ end
+ private :__item_strval_optkeys
+
+ def __item_boolval_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ ['open']
+ when :column, 'column'
+ super(id[1]) + ['stretch']
+ when :tag, 'tag'
+ super(id[1])
+ when :heading, 'heading'
+ super(id[1])
+ end
+ end
+ private :__item_boolval_optkeys
+
+ def __item_listval_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ ['values']
+ when :column, 'column'
+ []
+ when :heading, 'heading'
+ []
+ else
+ []
+ end
+ end
+ private :__item_listval_optkeys
+
+ def __item_val2ruby_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ {
+ 'tags'=>proc{|arg_id, val|
+ simplelist(val).collect{|tag|
+ Tk::Tile::Treeview::Tag.id2obj(self, tag)
+ }
+ }
+ }
+ when :column, 'column'
+ {}
+ when :heading, 'heading'
+ {}
+ else
+ {}
+ end
+ end
+ private :__item_val2ruby_optkeys
+
+ def __tile_specific_item_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ []
+ when :column, 'column'
+ []
+ when :heading, 'heading'
+ ['state'] # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
+ else
+ []
+ end
+ end
+ private :__item_val2ruby_optkeys
+
+ def itemconfiginfo(tagOrId, slot = nil)
+ __itemconfiginfo_core(tagOrId, slot)
+ end
+
+ def current_itemconfiginfo(tagOrId, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ org_slot = slot
+ begin
+ conf = __itemconfiginfo_core(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_core(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_core(tagOrId, slot).each{|key, conf|
+ ret[key] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+
+ alias __itemcget itemcget
+ alias __itemcget_strict itemcget_strict
+ alias __itemconfigure itemconfigure
+ alias __itemconfiginfo itemconfiginfo
+ alias __current_itemconfiginfo current_itemconfiginfo
+
+ private :__itemcget, :__itemcget_strict
+ private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo
+
+ # Treeview Item
+ def itemcget(tagOrId, option)
+ __itemcget([:item, tagOrId], option)
+ end
+ def itemcget_strict(tagOrId, option)
+ __itemcget_strict([:item, tagOrId], option)
+ end
+ def itemconfigure(tagOrId, slot, value=None)
+ __itemconfigure([:item, tagOrId], slot, value)
+ end
+ def itemconfiginfo(tagOrId, slot=nil)
+ __itemconfiginfo([:item, tagOrId], slot)
+ end
+ def current_itemconfiginfo(tagOrId, slot=nil)
+ __current_itemconfiginfo([:item, tagOrId], slot)
+ end
+
+ # Treeview Column
+ def columncget(tagOrId, option)
+ __itemcget([:column, tagOrId], option)
+ end
+ def columncget_strict(tagOrId, option)
+ __itemcget_strict([:column, tagOrId], option)
+ end
+ def columnconfigure(tagOrId, slot, value=None)
+ __itemconfigure([:column, tagOrId], slot, value)
+ end
+ def columnconfiginfo(tagOrId, slot=nil)
+ __itemconfiginfo([:column, tagOrId], slot)
+ end
+ def current_columnconfiginfo(tagOrId, slot=nil)
+ __current_itemconfiginfo([:column, tagOrId], slot)
+ end
+ alias column_cget columncget
+ alias column_cget_strict columncget_strict
+ alias column_configure columnconfigure
+ alias column_configinfo columnconfiginfo
+ alias current_column_configinfo current_columnconfiginfo
+
+ # Treeview Heading
+ def headingcget_strict(tagOrId, option)
+ if __tile_specific_item_optkeys([:heading, tagOrId]).index(option.to_s)
+ begin
+ # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
+ tk_call(*(__item_cget_cmd([:heading, tagOrId]) << option.to_s))
+ rescue
+ # Maybe, 'state' option has '-' in future.
+ tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{option}"))
+ end
+ else
+ __itemcget_strict([:heading, tagOrId], option)
+ end
+ end
+ def headingcget(tagOrId, option)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ headingcget_strict(tagOrId, option)
+ else
+ begin
+ headingcget_strict(tagOrId, option)
+ rescue => e
+ begin
+ if current_headingconfiginfo(tagOrId).has_key?(option.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+ def headingconfigure(tagOrId, slot, value=None)
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ sp_kv = []
+ __tile_specific_item_optkeys([:heading, tagOrId]).each{|k|
+ sp_kv << k << _get_eval_string(slot.delete(k)) if slot.has_key?(k)
+ }
+ tk_call(*(__item_config_cmd([:heading, tagOrId]).concat(sp_kv)))
+ tk_call(*(__item_config_cmd([:heading, tagOrId]).concat(hash_kv(slot))))
+ elsif __tile_specific_item_optkeys([:heading, tagOrId]).index(slot.to_s)
+ begin
+ # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
+ tk_call(*(__item_cget_cmd([:heading, tagOrId]) << slot.to_s << value))
+ rescue
+ # Maybe, 'state' option has '-' in future.
+ tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{slot}" << value))
+ end
+ else
+ __itemconfigure([:heading, tagOrId], slot, value)
+ end
+ self
+ end
+ def headingconfiginfo(tagOrId, slot=nil)
+ __itemconfiginfo([:heading, tagOrId], slot)
+ end
+ def current_headingconfiginfo(tagOrId, slot=nil)
+ __current_itemconfiginfo([:heading, tagOrId], slot)
+ end
+ alias heading_cget headingcget
+ alias heading_cget_strict headingcget_strict
+ alias heading_configure headingconfigure
+ alias heading_configinfo headingconfiginfo
+ alias current_heading_configinfo current_headingconfiginfo
+
+ # Treeview Tag
+ def tagcget(tagOrId, option)
+ __itemcget([:tag, tagOrId], option)
+ end
+ def tagcget_strict(tagOrId, option)
+ __itemcget_strict([:tag, tagOrId], option)
+ end
+ def tagconfigure(tagOrId, slot, value=None)
+ __itemconfigure([:tag, tagOrId], slot, value)
+ end
+ def tagconfiginfo(tagOrId, slot=nil)
+ __itemconfiginfo([:tag, tagOrId], slot)
+ end
+ def current_tagconfiginfo(tagOrId, slot=nil)
+ __current_itemconfiginfo([:tag, tagOrId], slot)
+ end
+ alias tag_cget tagcget
+ alias tag_cget_strict tagcget_strict
+ alias tag_configure tagconfigure
+ alias tag_configinfo tagconfiginfo
+ alias current_tag_configinfo current_tagconfiginfo
+end
+
+########################
+
+class Tk::Tile::Treeview::Item < TkObject
+ ItemID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Item::ItemID_TBL.clear
+ }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Item::ItemID_TBL[tpath]
+ (Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id])? \
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def self.assign(tree, id)
+ tpath = tree.path
+ obj = nil
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
+ return Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
+ end
+
+ obj = self.allocate
+ obj.instance_eval{
+ @parent = @t = tree
+ @tpath = tpath
+ @path = @id = id
+ }
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath] ||= {}
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id] = obj
+ }
+ obj
+ end
+
+ def _insert_item(tree, parent_item, idx, keys={})
+ keys = _symbolkey2str(keys)
+ id = keys.delete('id')
+ if id
+ num_or_str(tk_call(tree, 'insert',
+ parent_item, idx, '-id', id, *hash_kv(keys)))
+ else
+ num_or_str(tk_call(tree, 'insert', parent_item, idx, *hash_kv(keys)))
+ end
+ end
+ private :_insert_item
+
+ def initialize(tree, parent_item = '', idx = 'end', keys = {})
+ if parent_item.kind_of?(Hash)
+ keys = parent_item
+ idx = 'end'
+ parent_item = ''
+ elsif idx.kind_of?(Hash)
+ keys = idx
+ idx = 'end'
+ end
+
+ @parent = @t = tree
+ @tpath = tree.path
+ @path = @id = _insert_item(@t, parent_item, idx, keys)
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ ItemID_TBL[@tpath] = {} unless ItemID_TBL[@tpath]
+ ItemID_TBL[@tpath][@id] = self
+ }
+ end
+ def id
+ @id
+ end
+
+ def cget(option)
+ @t.itemcget(@id, option)
+ end
+ def cget_strict(option)
+ @t.itemcget_strict(@id, option)
+ end
+
+ def configure(key, value=None)
+ @t.itemconfigure(@id, key, value)
+ self
+ end
+
+ def configinfo(key=nil)
+ @t.itemconfiginfo(@id, key)
+ end
+
+ def current_configinfo(key=nil)
+ @t.current_itemconfiginfo(@id, key)
+ end
+
+ def open?
+ cget('open')
+ end
+ def open
+ configure('open', true)
+ self
+ end
+ def close
+ configure('open', false)
+ self
+ end
+
+ def bbox(column=None)
+ @t.bbox(@id, column)
+ end
+
+ def children
+ @t.children(@id)
+ end
+ def set_children(*items)
+ @t.set_children(@id, *items)
+ self
+ end
+
+ def delete
+ @t.delete(@id)
+ self
+ end
+
+ def detach
+ @t.detach(@id)
+ self
+ end
+
+ def exist?
+ @t.exist?(@id)
+ end
+
+ def focus
+ @t.focus_item(@id)
+ end
+
+ def index
+ @t.index(@id)
+ end
+
+ def insert(idx='end', keys={})
+ @t.insert(@id, idx, keys)
+ end
+
+ def move(parent, idx)
+ @t.move(@id, parent, idx)
+ self
+ end
+
+ def next_item
+ @t.next_item(@id)
+ end
+
+ def parent_item
+ @t.parent_item(@id)
+ end
+
+ def prev_item
+ @t.prev_item(@id)
+ end
+
+ def see
+ @t.see(@id)
+ self
+ end
+
+ def selection_add
+ @t.selection_add(@id)
+ self
+ end
+
+ def selection_remove
+ @t.selection_remove(@id)
+ self
+ end
+
+ def selection_set
+ @t.selection_set(@id)
+ self
+ end
+
+ def selection_toggle
+ @t.selection_toggle(@id)
+ self
+ end
+
+ def get_directory
+ @t.get_directory(@id)
+ end
+ alias get_dictionary get_directory
+
+ def get(col)
+ @t.get(@id, col)
+ end
+
+ def set(col, value)
+ @t.set(@id, col, value)
+ end
+end
+
+########################
+
+class Tk::Tile::Treeview::Root < Tk::Tile::Treeview::Item
+ def self.new(tree, keys = {})
+ tpath = tree.path
+ obj = nil
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
+ obj = Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
+ else
+ #super(tree, keys)
+ (obj = self.allocate).instance_eval{
+ @parent = @t = tree
+ @tpath = tree.path
+ @path = @id = ''
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {}
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
+ }
+ end
+ }
+ obj.configure(keys) if keys && ! keys.empty?
+ obj
+ end
+
+ def initialize(tree, keys = {})
+ # dummy:: not called by 'new' method
+ @parent = @t = tree
+ @tpath = tree.path
+ @path = @id = ''
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {}
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
+ }
+ end
+end
+
+########################
+
+class Tk::Tile::Treeview::Tag < TkObject
+ include TkTreatTagFont
+
+ TagID_TBL = TkCore::INTERP.create_table
+
+ (Tag_ID = ['tile_treeview_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Tag::TagID_TBL.clear
+ }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Tag::TagID_TBL[tpath]
+ (Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id])? \
+ Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(tree, keys=nil)
+ @parent = @t = tree
+ @tpath = tree.path
+ Tag_ID.mutex.synchronize{
+ @path = @id = Tag_ID.join(TkCore::INTERP._ip_id_)
+ Tag_ID[1].succ!
+ }
+ TagID_TBL.mutex.synchronize{
+ TagID_TBL[@tpath] = {} unless TagID_TBL[@tpath]
+ TagID_TBL[@tpath][@id] = self
+ }
+ if keys && keys != None
+ tk_call_without_enc(@tpath, 'tag', 'configure', *hash_kv(keys, true))
+ end
+ end
+ def id
+ @id
+ end
+
+ def bind(seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ @t.tag_bind(@id, seq, cmd, *args)
+ self
+ end
+
+ def bind_append(seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ @t.tag_bind_append(@id, seq, cmd, *args)
+ self
+ end
+
+ def bind_remove(seq)
+ @t.tag_bind_remove(@id, seq)
+ self
+ end
+
+ def bindinfo(seq=nil)
+ @t.tag_bindinfo(@id, seq)
+ end
+
+ def cget(option)
+ @t.tagcget(@id, option)
+ end
+ def cget_strict(option)
+ @t.tagcget_strict(@id, option)
+ end
+
+ def configure(key, value=None)
+ @t.tagconfigure(@id, key, value)
+ self
+ end
+
+ def configinfo(key=nil)
+ @t.tagconfiginfo(@id, key)
+ end
+
+ def current_configinfo(key=nil)
+ @t.current_tagconfiginfo(@id, key)
+ end
+end
+
+########################
+
+class Tk::Tile::Treeview < TkWindow
+ include Tk::Tile::TileWidget
+ include Scrollable
+
+ include Tk::Tile::TreeviewConfig
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::treeview'.freeze].freeze
+ else
+ TkCommandNames = ['::treeview'.freeze].freeze
+ end
+ WidgetClassName = 'Treeview'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def __destroy_hook__
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Item::ItemID_TBL.delete(@path)
+ }
+ Tk::Tile::Treeview::Tag::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Tag::ItemID_TBL.delete(@path)
+ }
+ end
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+
+ def tagid(id)
+ if id.kind_of?(Tk::Tile::Treeview::Item) ||
+ id.kind_of?(Tk::Tile::Treeview::Tag)
+ id.id
+ elsif id.kind_of?(Array)
+ [id[0], _get_eval_string(id[1])]
+ else
+ _get_eval_string(id)
+ end
+ end
+
+ def root
+ Tk::Tile::Treeview::Root.new(self)
+ end
+
+ def bbox(item, column=None)
+ list(tk_send('item', 'bbox', item, column))
+ end
+
+ def children(item)
+ simplelist(tk_send_without_enc('children', item)).collect{|id|
+ Tk::Tile::Treeview::Item.id2obj(self, id)
+ }
+ end
+ def set_children(item, *items)
+ tk_send_without_enc('children', item,
+ array2tk_list(items.flatten, true))
+ self
+ end
+
+ def delete(*items)
+ tk_send_without_enc('delete', array2tk_list(items.flatten, true))
+ self
+ end
+
+ def detach(*items)
+ tk_send_without_enc('detach', array2tk_list(items.flatten, true))
+ self
+ end
+
+ def exist?(item)
+ bool(tk_send_without_enc('exists', _get_eval_enc_str(item)))
+ end
+
+ def focus_item(item = nil)
+ if item
+ tk_send('focus', item)
+ item
+ else
+ id = tk_send('focus')
+ (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
+ end
+ end
+
+ def identify(x, y)
+ # tile-0.7.2 or previous
+ ret = simplelist(tk_send('identify', x, y))
+ case ret[0]
+ when 'heading', 'separator'
+ ret[-1] = num_or_str(ret[-1])
+ when 'cell'
+ ret[1] = Tk::Tile::Treeview::Item.id2obj(self, ret[1])
+ ret[-1] = num_or_str(ret[-1])
+ when 'item', 'row'
+ ret[1] = Tk::Tile::Treeview::Item.id2obj(self, ret[1])
+ end
+ end
+
+ def row_identify(x, y)
+ id = tk_send('identify', 'row', x, y)
+ (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
+ end
+
+ def column_identify(x, y)
+ tk_send('identify', 'column', x, y)
+ end
+
+ def index(item)
+ number(tk_send('index', item))
+ end
+
+ # def insert(parent, idx='end', keys={})
+ # keys = _symbolkey2str(keys)
+ # id = keys.delete('id')
+ # if id
+ # num_or_str(tk_send('insert', parent, idx, '-id', id, *hash_kv(keys)))
+ # else
+ # num_or_str(tk_send('insert', parent, idx, *hash_kv(keys)))
+ # end
+ # end
+ def insert(parent, idx='end', keys={})
+ Tk::Tile::Treeview::Item.new(self, parent, idx, keys)
+ end
+
+ # def instate(spec, cmd=Proc.new)
+ # tk_send('instate', spec, cmd)
+ # end
+ # def state(spec=None)
+ # tk_send('state', spec)
+ # end
+
+ def move(item, parent, idx)
+ tk_send('move', item, parent, idx)
+ self
+ end
+
+ def next_item(item)
+ id = tk_send('next', item)
+ (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
+ end
+
+ def parent_item(item)
+ if (id = tk_send('parent', item)).empty?
+ Tk::Tile::Treeview::Root.new(self)
+ else
+ Tk::Tile::Treeview::Item.id2obj(self, id)
+ end
+ end
+
+ def prev_item(item)
+ id = tk_send('prev', item)
+ (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
+ end
+
+ def see(item)
+ tk_send('see', item)
+ self
+ end
+
+ def selection
+ simplelist(tk_send('selection')).collect{|id|
+ Tk::Tile::Treeview::Item.id2obj(self, id)
+ }
+ end
+ alias selection_get selection
+
+ def selection_add(*items)
+ tk_send('selection', 'add', array2tk_list(items.flatten, true))
+ self
+ end
+ def selection_remove(*items)
+ tk_send('selection', 'remove', array2tk_list(items.flatten, true))
+ self
+ end
+ def selection_set(*items)
+ tk_send('selection', 'set', array2tk_list(items.flatten, true))
+ self
+ end
+ def selection_toggle(*items)
+ tk_send('selection', 'toggle', array2tk_list(items.flatten, true))
+ self
+ end
+
+ def get_directory(item)
+ # tile-0.7+
+ ret = []
+ lst = simplelist(tk_send('set', item))
+ until lst.empty?
+ col = lst.shift
+ val = lst.shift
+ ret << [col, val]
+ end
+ ret
+ end
+ alias get_dictionary get_directory
+
+ def get(item, col)
+ tk_send('set', item, col)
+ end
+ def set(item, col, value)
+ tk_send('set', item, col, value)
+ self
+ end
+
+ def tag_bind(tag, seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
+ self
+ end
+ alias tagbind tag_bind
+
+ def tag_bind_append(tag, seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
+ self
+ end
+ alias tagbind_append tag_bind_append
+
+ def tag_bind_remove(tag, seq)
+ _bind_remove([@path, 'tag', 'bind', tag], seq)
+ self
+ end
+ alias tagbind_remove tag_bind_remove
+
+ def tag_bindinfo(tag, context=nil)
+ _bindinfo([@path, 'tag', 'bind', tag], context)
+ end
+ alias tagbindinfo tag_bindinfo
+end
diff --git a/ext/tk/lib/tkextlib/tile/tscale.rb b/ext/tk/lib/tkextlib/tile/tscale.rb
new file mode 100644
index 0000000000..2c46fd9bd4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tscale.rb
@@ -0,0 +1,53 @@
+#
+# tscale & tprogress widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TScale < Tk::Scale
+ end
+ Scale = TScale
+
+ class TProgress < TScale
+ end
+ Progress = TProgress
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scale, :TkScale)
+
+
+class Tk::Tile::TScale < Tk::Scale
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::scale'.freeze].freeze
+ else
+ TkCommandNames = ['::tscale'.freeze].freeze
+ end
+ WidgetClassName = 'TScale'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
+
+class Tk::Tile::TProgress < Tk::Tile::TScale
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::progress'.freeze].freeze
+ else
+ TkCommandNames = ['::tprogress'.freeze].freeze
+ end
+ WidgetClassName = 'TProgress'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/tscrollbar.rb b/ext/tk/lib/tkextlib/tile/tscrollbar.rb
new file mode 100644
index 0000000000..163b8f4713
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tscrollbar.rb
@@ -0,0 +1,54 @@
+#
+# tscrollbar widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TScrollbar < Tk::Scrollbar
+ end
+ Scrollbar = TScrollbar
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scrollbar, :TkScrollbar)
+
+
+class Tk::Tile::TScrollbar < Tk::Scrollbar
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::scrollbar'.freeze].freeze
+ else
+ TkCommandNames = ['::tscrollbar'.freeze].freeze
+ end
+ WidgetClassName = 'TScrollbar'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
+
+class Tk::Tile::XScrollbar < Tk::Tile::TScrollbar
+ def create_self(keys)
+ keys = {} unless keys
+ keys['orient'] = 'horizontal'
+ super(keys)
+ end
+ private :create_self
+end
+
+class Tk::Tile::YScrollbar < Tk::Tile::TScrollbar
+ def create_self(keys)
+ keys = {} unless keys
+ keys['orient'] = 'vertical'
+ super(keys)
+ end
+ private :create_self
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::XScrollbar, :TkXScrollbar)
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::YScrollbar, :TkYScrollbar)
diff --git a/ext/tk/lib/tkextlib/tile/tseparator.rb b/ext/tk/lib/tkextlib/tile/tseparator.rb
new file mode 100644
index 0000000000..30fae2c525
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tseparator.rb
@@ -0,0 +1,33 @@
+#
+# tseparator widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TSeparator < TkWindow
+ end
+ Separator = TSeparator
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Separator, :TkSeparator)
+
+
+class Tk::Tile::TSeparator < TkWindow
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::separator'.freeze].freeze
+ else
+ TkCommandNames = ['::tseparator'.freeze].freeze
+ end
+ WidgetClassName = 'TSeparator'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/tsquare.rb b/ext/tk/lib/tkextlib/tile/tsquare.rb
new file mode 100644
index 0000000000..600b55e4e7
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/tsquare.rb
@@ -0,0 +1,30 @@
+#
+# tsquare widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class TSquare < TkWindow
+ end
+ Square = TSquare
+ end
+end
+
+class Tk::Tile::TSquare < TkWindow
+ include Tk::Tile::TileWidget
+
+ if Tk::Tile::USE_TTK_NAMESPACE
+ TkCommandNames = ['::ttk::square'.freeze].freeze
+ else
+ TkCommandNames = ['::tsquare'.freeze].freeze
+ end
+ WidgetClassName = 'TSquare'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkDND.rb b/ext/tk/lib/tkextlib/tkDND.rb
new file mode 100644
index 0000000000..5d52e34418
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkDND.rb
@@ -0,0 +1,18 @@
+#
+# 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'
+
+# call setup script
+require 'tkextlib/tkDND/setup.rb'
+
+module Tk
+ module TkDND
+ autoload :DND, 'tkextlib/tkDND/tkdnd'
+ autoload :Shape, 'tkextlib/tkDND/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..d44068ed33
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkDND/shape.rb
@@ -0,0 +1,125 @@
+#
+# 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 'tkextlib/tkDND/setup.rb'
+
+# TkPackage.require('Shape', '0.3')
+TkPackage.require('Shape')
+
+module Tk
+ module TkDND
+ module Shape
+ extend TkCore
+
+ PACKAGE_NAME = 'Shape'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+=begin
+ def self.package_version
+ begin
+ TkPackage.require('Shape')
+ rescue
+ ''
+ end
+ end
+=end
+ class << self
+ def package_version
+ Tk.tk_call('set', 'shape_version')
+ end
+ alias shape_version package_version
+
+ def package_patchlevel
+ Tk.tk_call('set', 'shape_patchLevel')
+ end
+ alias shape_patchlevel package_patchlevel
+
+ def version
+ tk_call('shape', 'version')
+ end
+ alias xshape_version 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 <x> <y>? srckind ?arg ...?
+ tk_call('shape', 'set', @path, *(_parse_shapespec_param(args)))
+ self
+ end
+
+ def shape_update(op, *args) # ?kind? ?offset <x> <y>? 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..9a9b2dc42c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
@@ -0,0 +1,182 @@
+#
+# 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 'tkextlib/tkDND/setup.rb'
+
+TkPackage.require('tkdnd')
+
+module Tk
+ module TkDND
+ PACKAGE_NAME = 'tkdnd'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('tkdnd')
+ rescue
+ ''
+ end
+ end
+
+ 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
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ # setup tables
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+ end
+
+ module DND
+ def self.version
+ begin
+ TkPackage.require('tkdnd')
+ rescue
+ ''
+ end
+ end
+
+ 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_bindtarget(type, event, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+
+ prior = 50
+ prior = args.shift unless args.empty?
+
+ 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_bindsource(type, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+
+ args = [None] if args.empty
+
+ tk_call('dnd', 'bindsource', @path, type, cmd, *args)
+ 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..5fddde72ff
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkHTML.rb
@@ -0,0 +1,13 @@
+#
+# TkHtml support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# call setup script
+require 'tkextlib/tkHTML/setup.rb'
+
+# load library
+require 'tkextlib/tkHTML/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..d893a83cf2
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
@@ -0,0 +1,453 @@
+#
+# 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 'tkextlib/tkHTML/setup.rb'
+
+# TkPackage.require('Tkhtml', '2.0')
+TkPackage.require('Tkhtml')
+
+module Tk
+ class HTML_Widget < TkWindow
+ PACKAGE_NAME = 'Tkhtml'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('Tkhtml')
+ rescue
+ ''
+ end
+ end
+
+ class ClippingWindow < TkWindow
+ end
+ end
+end
+
+class Tk::HTML_Widget::ClippingWindow
+ WidgetClassName = 'HtmlClip'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ HtmlClip_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ HtmlClip_TBL.mutex.synchronize{ HtmlClip_TBL.clear }
+ }
+
+ def self.new(parent, keys={})
+ if parent.kind_of?(Hash)
+ keys = TkComm._symbolkey2str(parent)
+ parent = keys.delete('parent')
+ end
+
+ if parent.kind_of?(String)
+ ppath = parent.path
+ elsif parent
+ ppath = parent
+ else
+ ppath = ''
+ end
+ HtmlClip_TBL.mutex.synchronize{
+ return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath]
+ }
+
+ widgetname = keys.delete('widgetname')
+ if widgetname =~ /^(.*)\.[^.]+$/
+ ppath2 = $1
+ if ppath2[0] != ?.
+ ppath2 = ppath + '.' + ppath2
+ end
+ HtmlClip_TBL.mutex.synchronize{
+ 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.mutex.synchronize{
+ 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(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ end
+ end
+ private :create_self
+
+ def __strval_optkeys
+ super() << 'base' << 'selectioncolor' << 'unvisitedcolor' << 'visitedcolor'
+ end
+ private :__strval_optkeys
+
+ ###################################
+ # 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..c01359d3ef
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg.rb
@@ -0,0 +1,36 @@
+#
+# TkImg extension support
+# 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 'tkextlib/tkimg/setup.rb'
+
+# load all image format handlers
+#TkPackage.require('Img', '1.3')
+TkPackage.require('Img')
+
+module Tk
+ module Img
+ PACKAGE_NAME = 'Img'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('Img')
+ rescue
+ ''
+ end
+ end
+ end
+end
+
+# autoload
+autoload :TkPixmapImage, 'tkextlib/tkimg/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..ea90181aa3
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/bmp.rb
@@ -0,0 +1,33 @@
+#
+# 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 'tkextlib/tkimg/setup.rb'
+
+#TkPackage.require('img::bmp', '1.3')
+TkPackage.require('img::bmp')
+
+module Tk
+ module Img
+ module BMP
+ PACKAGE_NAME = 'img::bmp'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::bmp')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/gif.rb b/ext/tk/lib/tkextlib/tkimg/gif.rb
new file mode 100644
index 0000000000..d542d47561
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/gif.rb
@@ -0,0 +1,33 @@
+#
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::gif', '1.3')
+TkPackage.require('img::gif')
+
+module Tk
+ module Img
+ module GIF
+ PACKAGE_NAME = 'img::gif'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::gif')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/ico.rb b/ext/tk/lib/tkextlib/tkimg/ico.rb
new file mode 100644
index 0000000000..e79bdf45e9
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/ico.rb
@@ -0,0 +1,33 @@
+#
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::ico', '1.3')
+TkPackage.require('img::ico')
+
+module Tk
+ module Img
+ module ICO
+ PACKAGE_NAME = 'img::ico'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::ico')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/jpeg.rb b/ext/tk/lib/tkextlib/tkimg/jpeg.rb
new file mode 100644
index 0000000000..2126120161
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/jpeg.rb
@@ -0,0 +1,33 @@
+#
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::jpeg', '1.3')
+TkPackage.require('img::jpeg')
+
+module Tk
+ module Img
+ module JPEG
+ PACKAGE_NAME = 'img::jpeg'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::jpeg')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/pcx.rb b/ext/tk/lib/tkextlib/tkimg/pcx.rb
new file mode 100644
index 0000000000..6831f4d35b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/pcx.rb
@@ -0,0 +1,33 @@
+#
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::pcx', '1.3')
+TkPackage.require('img::pcx')
+
+module Tk
+ module Img
+ module PCX
+ PACKAGE_NAME = 'img::pcx'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::pcx')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/pixmap.rb b/ext/tk/lib/tkextlib/tkimg/pixmap.rb
new file mode 100644
index 0000000000..bd1b870af7
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/pixmap.rb
@@ -0,0 +1,44 @@
+#
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::pixmap', '1.3')
+TkPackage.require('img::pixmap')
+
+module Tk
+ module Img
+ module PIXMAP
+ PACKAGE_NAME = 'img::pixmap'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::pixmap')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
+
+class TkPixmapImage<TkImage
+ def self.version
+ Tk::Img::PIXMAP.version
+ end
+
+ def initialize(*args)
+ @type = 'pixmap'
+ super(*args)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/png.rb b/ext/tk/lib/tkextlib/tkimg/png.rb
new file mode 100644
index 0000000000..5c829f48d2
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/png.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'png'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::png', '1.3')
+TkPackage.require('img::png')
+
+module Tk
+ module Img
+ module PNG
+ PACKAGE_NAME = 'img::png'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::png')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/ppm.rb b/ext/tk/lib/tkextlib/tkimg/ppm.rb
new file mode 100644
index 0000000000..eacfae467d
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/ppm.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'ppm'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::ppm', '1.3')
+TkPackage.require('img::ppm')
+
+module Tk
+ module Img
+ module PPM
+ PACKAGE_NAME = 'img::ppm'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::ppm')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/ps.rb b/ext/tk/lib/tkextlib/tkimg/ps.rb
new file mode 100644
index 0000000000..68e9178ac0
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/ps.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'ps'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::ps', '1.3')
+TkPackage.require('img::ps')
+
+module Tk
+ module Img
+ module PS
+ PACKAGE_NAME = 'img::ps'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::ps')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/setup.rb b/ext/tk/lib/tkextlib/tkimg/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/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/sgi.rb b/ext/tk/lib/tkextlib/tkimg/sgi.rb
new file mode 100644
index 0000000000..ec7038bf0e
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/sgi.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'sgi'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::sgi', '1.3')
+TkPackage.require('img::sgi')
+
+module Tk
+ module Img
+ module SGI
+ PACKAGE_NAME = 'img::sgi'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::sgi')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/sun.rb b/ext/tk/lib/tkextlib/tkimg/sun.rb
new file mode 100644
index 0000000000..651f946497
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/sun.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'sun'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::sun', '1.3')
+TkPackage.require('img::sun')
+
+module Tk
+ module Img
+ module SUN
+ PACKAGE_NAME = 'img::sun'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::sun')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/tga.rb b/ext/tk/lib/tkextlib/tkimg/tga.rb
new file mode 100644
index 0000000000..1eae407c0a
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/tga.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'tga'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::tga', '1.3')
+TkPackage.require('img::tga')
+
+module Tk
+ module Img
+ module TGA
+ PACKAGE_NAME = 'img::tga'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::tga')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/tiff.rb b/ext/tk/lib/tkextlib/tkimg/tiff.rb
new file mode 100644
index 0000000000..ed271c2600
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/tiff.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'tiff'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::tiff', '1.3')
+TkPackage.require('img::tiff')
+
+module Tk
+ module Img
+ module TIFF
+ PACKAGE_NAME = 'img::tiff'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::tiff')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/window.rb b/ext/tk/lib/tkextlib/tkimg/window.rb
new file mode 100644
index 0000000000..3b5906fab6
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/window.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'window'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::window', '1.3')
+TkPackage.require('img::window')
+
+module Tk
+ module Img
+ module WINDOW
+ PACKAGE_NAME = 'img::window'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::window')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/xbm.rb b/ext/tk/lib/tkextlib/tkimg/xbm.rb
new file mode 100644
index 0000000000..f4bea030be
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/xbm.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'xbm'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::xbm', '1.3')
+TkPackage.require('img::xbm')
+
+module Tk
+ module Img
+ module XBM
+ PACKAGE_NAME = 'img::xbm'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::xbm')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tkimg/xpm.rb b/ext/tk/lib/tkextlib/tkimg/xpm.rb
new file mode 100644
index 0000000000..5119c8710b
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tkimg/xpm.rb
@@ -0,0 +1,33 @@
+#
+# TkImg - format 'xpm'
+# 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 'tkextlib/tkimg/setup.rb'
+
+# TkPackage.require('img::xpm', '1.3')
+TkPackage.require('img::xpm')
+
+module Tk
+ module Img
+ module XPM
+ PACKAGE_NAME = 'img::xpm'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('img::xpm')
+ rescue
+ ''
+ end
+ end
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tktable.rb b/ext/tk/lib/tkextlib/tktable.rb
new file mode 100644
index 0000000000..385eb13497
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tktable.rb
@@ -0,0 +1,14 @@
+#
+# TkTable support
+# 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 'tkextlib/tktable/setup.rb'
+
+# load library
+require 'tkextlib/tktable/tktable'
diff --git a/ext/tk/lib/tkextlib/tktable/setup.rb b/ext/tk/lib/tkextlib/tktable/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tktable/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/tktable/tktable.rb b/ext/tk/lib/tkextlib/tktable/tktable.rb
new file mode 100644
index 0000000000..f6cf24b40f
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tktable/tktable.rb
@@ -0,0 +1,957 @@
+#
+# tkextlib/tktable/tktable.rb
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tk/validation'
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# call setup script
+require 'tkextlib/tktable/setup.rb'
+
+# TkPackage.require('Tktable', '2.8')
+TkPackage.require('Tktable')
+
+module Tk
+ class TkTable < TkWindow
+ PACKAGE_NAME = 'Tktable'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('Tktable')
+ rescue
+ ''
+ end
+ end
+
+ class CellTag < TkObject
+ end
+
+ module ConfigMethod
+ end
+ end
+end
+
+module Tk::TkTable::ConfigMethod
+ include TkItemConfigMethod
+
+ def __item_cget_cmd(id) # id := [ type, tagOrId ]
+ [self.path, id[0], 'cget', id[1]]
+ end
+ private :__item_cget_cmd
+
+ 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 __item_boolval_optkeys(id)
+ super(id) << 'multiline' << 'showtext' << 'wrap'
+ end
+ private :__item_boolval_optkeys
+
+ def __item_strval_optkeys(id)
+ super(id) << 'ellipsis'
+ end
+ private :__item_strval_optkeys
+
+ def __item_val2ruby_optkeys(id) # { key=>method, ... }
+ super(id).update('window'=>proc{|v| window(v)})
+ end
+ private :__item_val2ruby_optkeys
+
+ def tag_cget(tagOrId, option)
+ itemcget(['tag', tagid(tagOrId)], option)
+ end
+ def tag_cget_strict(tagOrId, option)
+ itemcget_strict(['tag', tagid(tagOrId)], option)
+ end
+ def tag_configure(tagOrId, slot, value=None)
+ itemconfigure(['tag', tagid(tagOrId)], slot, value)
+ end
+ def tag_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['tag', tagid(tagOrId)], slot)
+ end
+ def current_tag_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['tag', tagid(tagOrId)], slot)
+ end
+
+ def window_cget(tagOrId, option)
+ itemcget(['window', tagid(tagOrId)], option)
+ end
+ def window_cget_strict(tagOrId, option)
+ itemcget_strict(['window', tagid(tagOrId)], option)
+ end
+ def window_configure(tagOrId, slot, value=None)
+ if slot == :window || slot == 'window'
+ value = _epath(value)
+ elsif slot.kind_of?(Hash)
+ if slot.key?(:window) || slot.key?('window')
+ slot = _symbolkey2str(slot)
+ slot['window'] = _epath(slot['window'])
+ end
+ end
+ itemconfigure(['window', tagid(tagOrId)], slot, value)
+ end
+ def window_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['window', tagid(tagOrId)], slot)
+ end
+ def current_window_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['window', tagid(tagOrId)], slot)
+ end
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+end
+
+#####################################################
+
+class Tk::TkTable::CellTag
+ include TkTreatTagFont
+
+ CellTagID_TBL = TkCore::INTERP.create_table
+
+ (CellTag_ID = ['tktbl:celltag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ CellTagID_TBL.mutex.synchronize{ CellTagID_TBL.clear }
+ }
+
+ def self.id2obj(table, id)
+ tpath = table.path
+ CellTagID_TBL.mutex.synchronize{
+ if CellTagID_TBL[tpath]
+ CellTagID_TBL[tpath][id]? CellTagID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(parent, keys=nil)
+ @parent = @t = parent
+ @tpath - parent.path
+ CellTag_ID.mutex.synchronize{
+ @path = @id = CellTag_ID.join(TkCore::INTERP._ip_id_)
+ CellTag_ID[1].succ!
+ }
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
+ configure(keys) if keys
+ end
+
+ def id
+ @id
+ end
+
+ def destroy
+ tk_call(@tpath, 'tag', 'delete', @id)
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath].delete(@id) if CellTagID_TBL[@tpath]
+ }
+ self
+ end
+ alias delete destroy
+
+ def exist?
+ @t.tag_exist?(@id)
+ end
+ def include?(idx)
+ @t.tag_include?(@id, idx)
+ end
+
+ def add_cell(*args)
+ @t.tag_cell(@id, *args)
+ end
+ def add_col(*args)
+ @t.tag_col(@id, *args)
+ end
+ def add_row(*args)
+ @t.tag_row(@id, *args)
+ end
+
+ def raise(target=None)
+ @t.tag_raise(@id, target)
+ end
+ def lower(target=None)
+ @t.tag_lower(@id, target)
+ end
+
+ def cget(key)
+ @t.tag_cget(@id, key)
+ end
+ def cget_strict(key)
+ @t.tag_cget_strict(@id, key)
+ end
+ def configure(key, val=None)
+ @t.tag_configure(@id, key, val)
+ end
+ def configinfo(key=nil)
+ @t.tag_configinfo(@id, key)
+ end
+ def current_configinfo(key=nil)
+ @t.current_tag_configinfo(@id, key)
+ end
+end
+
+class Tk::TkTable::NamedCellTag < Tk::TkTable::CellTag
+ def self.new(parent, name, keys=nil)
+ obj = nil
+ CellTagID_TBL.mutex.synchronize{
+ if CellTagID_TBL[parent.path] && CellTagID_TBL[parent.path][name]
+ obj = CellTagID_TBL[parent.path][name]
+ else
+ #super(parent, name, keys)
+ (obj = self.allocate).instance_eval{
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
+ end
+ }
+ obj.configure(keys) if keys && ! keys.empty?
+ obj
+ end
+
+ def initialize(parent, name, keys=nil)
+ # dummy:: not called by 'new' method
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
+ configure(keys) if keys && ! keys.empty?
+ end
+end
+
+#####################################################
+
+class Tk::TkTable
+ TkCommandNames = ['table'.freeze].freeze
+ WidgetClassName = 'Table'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ include Scrollable
+ include Tk::TkTable::ConfigMethod
+ include Tk::ValidateConfigure
+
+ def __destroy_hook__
+ Tk::TkTable::CelTag::CellTagID_TBL.mutex.synchronize{
+ Tk::TkTable::CelTag::CellTagID_TBL.delete(@path)
+ }
+ end
+
+ def __boolval_optkeys
+ super() << 'autoclear' << 'flashmode' << 'invertselected' <<
+ 'multiline' << 'selecttitle' << 'wrap'
+ end
+ private :__boolval_optkeys
+
+ def __strval_optkeys
+ super() << 'colseparator' << 'ellipsis' << 'rowseparator' << 'sparsearray'
+ end
+ private :__strval_optkeys
+
+
+ #################################
+
+ class BrowseCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?c, ?n, :column ],
+ [ ?C, ?s, :index ],
+ [ ?i, ?x, :cursor ],
+ [ ?r, ?n, :row ],
+ [ ?s, ?s, :last_index ],
+ [ ?S, ?s, :new_index ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?n, TkComm.method(:number) ],
+ [ ?x, TkComm.method(:num_or_str) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ ['browsecommand', 'browsecmd']
+ end
+ end
+ #--------------------------------
+ class CellCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?c, ?n, :column ],
+ [ ?C, ?s, :index ],
+ [ ?i, ?m, :rw_mode ],
+ [ ?r, ?n, :row ],
+ [ ?s, ?v, :value ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?n, TkComm.method(:number) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+ [ ?m, proc{|val| (val == '0')? (:r) : (:w)} ],
+ [ ?v, proc{|val| TkComm.tk_tcl2ruby(val, true, false)} ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ TkComm._get_eval_string(val)
+ end
+ end
+
+ def self._config_keys
+ ['command']
+ end
+ end
+ #--------------------------------
+ class SelectionCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?c, ?n, :sel_columns ],
+ [ ?C, ?s, :sel_area ],
+ [ ?i, ?n, :total ],
+ [ ?r, ?n, :sel_rows ],
+ [ ?s, ?s, :value ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?n, TkComm.method(:number) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ val.to_s
+ end
+ end
+
+ def self._config_keys
+ ['selectioncommand', 'selcmd']
+ end
+ end
+ #--------------------------------
+ class ValidateCommand < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?c, ?n, :column ],
+ [ ?C, ?s, :index ],
+ [ ?i, ?x, :cursor ],
+ [ ?r, ?n, :row ],
+ [ ?s, ?v, :current_value ],
+ [ ?S, ?v, :new_value ],
+ [ ?W, ?w, :widget ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?n, TkComm.method(:number) ],
+ [ ?x, TkComm.method(:num_or_str) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?w, TkComm.method(:window) ],
+ [ ?v, proc{|val| TkComm.tk_tcl2ruby(val, true, false)} ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+ end
+
+ def self._config_keys
+ ['vcmd', 'validatecommand']
+ end
+ end
+
+ #################################
+
+ def __validation_class_list
+ super() <<
+ BrowseCommand << CellCommand << SelectionCommand << ValidateCommand
+ end
+
+ Tk::ValidateConfigure.__def_validcmd(binding, BrowseCommand)
+ Tk::ValidateConfigure.__def_validcmd(binding, CellCommand)
+ Tk::ValidateConfigure.__def_validcmd(binding, SelectionCommand)
+ Tk::ValidateConfigure.__def_validcmd(binding, ValidateCommand)
+
+ #################################
+
+ def activate(idx)
+ tk_send('activate', tagid(idx))
+ end
+
+ def bbox(idx)
+ list(tk_send('bbox', tagid(idx)))
+ end
+
+ def border_mark(x, y)
+ simplelist(tk_send('border', 'mark', x, y))
+ end
+ def border_mark_row(x, y)
+ tk_send('border', 'mark', x, y, 'row')
+ end
+ def border_mark_col(x, y)
+ tk_send('border', 'mark', x, y, 'col')
+ end
+ def border_dragto(x, y)
+ tk_send('border', 'dragto', x, y)
+ end
+
+ def clear_cache(first=None, last=None)
+ tk_send('clear', 'cache', tagid(first), tagid(last))
+ self
+ end
+ def clear_sizes(first=None, last=None)
+ tk_send('clear', 'sizes', tagid(first), tagid(last))
+ self
+ end
+ def clear_tags(first=None, last=None)
+ tk_send('clear', 'tags', tagid(first), tagid(last))
+ self
+ end
+ def clear_all(first=None, last=None)
+ tk_send('clear', 'all', tagid(first), tagid(last))
+ self
+ end
+
+ def curselection
+ simplelist(tk_send('curselection'))
+ end
+ def curselection=(val)
+ tk_send('curselection', val)
+ val
+ end
+
+ def curvalue
+ tk_tcl2ruby(tk_send('curvalue'), true, false)
+ end
+ def curvalue=(val)
+ tk_send('curvalue', val)
+ val
+ end
+
+ def delete_active(idx1, idx2=None)
+ tk_send('delete', 'active', tagid(idx1), tagid(idx2))
+ self
+ end
+ def delete_cols(*args) # ?switches_array?, index, ?count?
+ params = []
+ if args[0].kind_of?(Array)
+ switches = args.shift
+ switches.each{|k| params << "-#{k}"}
+ end
+ params << '--'
+ params << tagid(args.shift)
+ params.concat(args)
+ tk_send('delete', 'cols', *params)
+ self
+ end
+ def delete_rows(*args) # ?switches_array?, index, ?count?
+ params = []
+ if args[0].kind_of?(Array)
+ switches = args.shift
+ switches.each{|k| params << "-#{k}"}
+ end
+ params << '--'
+ params << tagid(args.shift)
+ params.concat(args)
+ tk_send('delete', 'rows', *params)
+ self
+ end
+
+ def get(idx)
+ tk_tcl2ruby(tk_send('get', tagid(idx)), true, false)
+ end
+ def get_area(idx1, idx2)
+ simplelist(tk_send('get', tagid(idx1), tagid(idx2))).collect{|v|
+ tk_tcl2ruby(v, true, false)
+ }
+ end
+
+ def height_list
+ list(tk_send('height'))
+ end
+ def height(row)
+ number(tk_send('height', row))
+ end
+ def set_height(*pairs)
+ tk_send('height', *(pairs.flatten))
+ self
+ end
+
+ def hidden_list
+ simplelist(tk_send('hidden'))
+ end
+ def hidden?(idx, *args)
+ if args.empty?
+ if (ret = tk_send('hidden', tagid(idx))) == ''
+ false
+ else
+ ret
+ end
+ else
+ bool(tk_send('hidden', tagid(idx), *(args.collect{|i| tagid(i)})))
+ end
+ end
+
+ def icursor
+ number(tk_send('icursor'))
+ end
+ def icursor_set(idx)
+ number(tk_send('icursor', tagid(idx)))
+ end
+
+ def index(idx)
+ tk_send('index', tagid(idx))
+ end
+ def row_index(idx)
+ number(tk_send('index', tagid(idx), 'row'))
+ end
+ def col_index(idx)
+ number(tk_send('index', tagid(idx), 'col'))
+ end
+
+ def insert_active(idx, val)
+ tk_send('insert', 'active', tagid(idx), val)
+ self
+ end
+ def insert_cols(*args) # ?switches_array?, index, ?count?
+ params = []
+ if args[0].kind_of?(Array)
+ switches = args.shift
+ switches.each{|k| params << "-#{k}"}
+ end
+ params << '--'
+ params.concat(args)
+ params << tagid(args.shift)
+ tk_send('insert', 'cols', *params)
+ self
+ end
+ def insert_rows(*args) # ?switches_array?, index, ?count?
+ params = []
+ if args[0].kind_of?(Array)
+ switches = args.shift
+ switches.each{|k| params << "-#{k}"}
+ end
+ params << '--'
+ params << tagid(args.shift)
+ params.concat(args)
+ tk_send('insert', 'rows', *params)
+ self
+ end
+
+ # def postscript(*args)
+ # tk_send('postscript', *args)
+ # end
+
+ def reread
+ tk_send('reread')
+ self
+ end
+
+ def scan_mark(x, y)
+ tk_send('scan', 'mark', x, y)
+ self
+ end
+ def scan_dragto(x, y)
+ tk_send('scan', 'dragto', x, y)
+ self
+ end
+
+ def see(idx)
+ tk_send('see', tagid(idx))
+ self
+ end
+
+ def selection_anchor(idx)
+ tk_send('selection', 'anchor', tagid(idx))
+ self
+ end
+ def selection_clear(first, last=None)
+ tk_send('selection', 'clear', tagid(first), tagid(last))
+ self
+ end
+ def selection_clear_all
+ selection_clear('all')
+ end
+ def selection_include?(idx)
+ bool(tk_send('selection', 'includes', tagid(idx)))
+ end
+ def selection_present
+ bool(tk_send('selection', 'present'))
+ end
+ def selection_set(first, last=None)
+ tk_send('selection', 'set', tagid(first), tagid(last))
+ self
+ end
+
+ def set(*pairs) # idx, val, idx, val, ...
+ args = []
+ 0.step(pairs.size-1, 2){|i|
+ args << tagid(pairs[i])
+ args << pairs[i+1]
+ }
+ tk_send('set', *args)
+ self
+ end
+ def set_row(*pairs) # idx, val, idx, val, ...
+ args = []
+ 0.step(pairs.size-1, 2){|i|
+ args << tagid(pairs[i])
+ args << pairs[i+1]
+ }
+ tk_send('set', 'row', *args)
+ self
+ end
+ def set_col(*pairs) # idx, val, idx, val, ...
+ args = []
+ 0.step(pairs.size-1, 2){|i|
+ args << tagid(pairs[i])
+ args << pairs[i+1]
+ }
+ tk_send('set', 'col', *args)
+ self
+ end
+=begin
+ def set(*pairs) # idx, val, idx, val, ... OR [idx, val], [idx, val], ...
+ if pairs[0].kind_of?(Array)
+ # [idx, val], [idx, val], ...
+ args = []
+ pairs.each{|idx, val| args << tagid(idx) << val }
+ tk_send('set', *args)
+ else
+ # idx, val, idx, val, ...
+ args = []
+ 0.step(pairs.size-1, 2){|i|
+ args << tagid(pairs[i])
+ args << pairs[i+1]
+ }
+ tk_send('set', *args)
+ end
+ self
+ end
+ def set_row(*pairs)
+ if pairs[0].kind_of?(Array)
+ # [idx, val], [idx, val], ...
+ args = []
+ pairs.each{|idx, val| args << tagid(idx) << val }
+ tk_send('set', 'row', *args)
+ else
+ # idx, val, idx, val, ...
+ args = []
+ 0.step(pairs.size-1, 2){|i|
+ args << tagid(pairs[i])
+ args << pairs[i+1]
+ }
+ tk_send('set', 'row', *args)
+ end
+ self
+ end
+ def set_col(*pairs)
+ if pairs[0].kind_of?(Array)
+ # [idx, val], [idx, val], ...
+ args = []
+ pairs.each{|idx, val| args << idx << val }
+ tk_send('set', 'col', *args)
+ else
+ # idx, val, idx, val, ...
+ args = []
+ 0.step(pairs.size-1, 2){|i|
+ args << tagid(pairs[i])
+ args << pairs[i+1]
+ }
+ tk_send('set', 'col', *args)
+ end
+ self
+ end
+=end
+
+ def spans
+ simplelist(tk_send('spans')).collect{|inf|
+ lst = simplelist(inf)
+ idx = lst[0]
+ rows, cols = lst[1].split(',').map!{|n| Integer(n)}
+ [idx [rows, cols]]
+ }
+ end
+ alias span_list spans
+ def span(idx)
+ lst = simplelist(tk_send('spans', tagid(idx)))
+ idx = lst[0]
+ rows, cols = lst[1].split(',').map!{|n| Integer(n)}
+ [idx [rows, cols]]
+ end
+ def set_spans(*pairs)
+ # idx, val, idx, val, ...
+ args = []
+ 0.step(pairs.size-1, 2){|i|
+ args << tagid(pairs[i])
+ val = pairs[i+1]
+ if val.kind_of?(Array)
+ args << val.join(',')
+ else
+ args << val
+ end
+ }
+ tk_send('spans', *args)
+ self
+ end
+=begin
+ def set_spans(*pairs)
+ if pairs[0].kind_of?(Array)
+ # [idx, val], [idx, val], ...
+ args = []
+ pairs.each{|idx, val|
+ args << tagid(idx)
+ if val.kind_of?(Array)
+ args << val.join(',')
+ else
+ args << val
+ end
+ }
+ tk_send('spans', *args)
+ else
+ # idx, val, idx, val, ...
+ args = []
+ 0.step(pairs.size-1, 2){|i|
+ args << tagid(pairs[i])
+ val = pairs[i+1]
+ if val.kind_of?(Array)
+ args << val.join(',')
+ else
+ args << val
+ end
+ }
+ tk_send('spans', *args)
+ end
+ self
+ end
+=end
+
+ def tagid(tag)
+ if tag.kind_of?(Tk::TkTable::CellTag)
+ tag.id
+ elsif tag.kind_of?(Array)
+ if tag[0].kind_of?(Integer) && tag[1].kind_of?(Integer)
+ # [row, col]
+ tag.join(',')
+ else
+ tag
+ end
+ else
+ tag
+ end
+ end
+
+ def tagid2obj(tagid)
+ Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{
+ if Tk::TkTable::CellTag::CellTagID_TBL.key?(@path)
+ if Tk::TkTable::CellTag::CellTagID_TBL[@path].key?(tagid)
+ Tk::TkTable::CellTag::CellTagID_TBL[@path][tagid]
+ else
+ tagid
+ end
+ else
+ tagid
+ end
+ }
+ end
+
+ def tag_cell(tag, *cells)
+ tk_send('tag', 'cell', tagid(tag), *(cells.collect{|idx| tagid(idx)}))
+ self
+ end
+ def tag_reset(*cells)
+ tk_send('tag', 'cell', '', *(cells.collect{|idx| tagid(idx)}))
+ self
+ end
+ def tag_col(tag, *cols)
+ tk_send('tag', 'col', tagid(tag), *cols)
+ self
+ end
+ def tag_col_reset(*cols)
+ tk_send('tag', 'col', '', *cols)
+ self
+ end
+ def tag_delete(tag)
+ tk_send('tag', 'delete', tagid(tag))
+ Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{
+ if Tk::TkTable::CellTag::CellTagID_TBL[@path]
+ if tag.kind_of? Tk::TkTable::CellTag
+ Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag.id)
+ else
+ Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag)
+ end
+ end
+ }
+ self
+ end
+ def tag_exist?(tag)
+ bool(tk_send('tag', 'exists', tagid(tag)))
+ end
+ def tag_include?(tag, idx)
+ bool(tk_send('tag', 'includes', tagid(tag), tagid(idx)))
+ end
+ def tag_lower(tag, target=None)
+ tk_send('tag', 'lower', tagid(tag), tagid(target))
+ self
+ end
+ def tag_names(pat=None)
+ simplelist(tk_send('tag', 'names', pat)).collect{|tag| tagid2obj(tag)}
+ end
+ def tag_raise(tag, target=None)
+ tk_send('tag', 'raise', tagid(tag), tagid(target))
+ self
+ end
+ def tag_row(tag, *rows)
+ tk_send('tag', 'row', tagid(tag), *rows)
+ self
+ end
+ def tag_row_reset(*rows)
+ tk_send('tag', 'row', '', *rows)
+ self
+ end
+
+ def validate(idx)
+ bool(tk_send('validate', tagid(idx)))
+ end
+
+ def width_list
+ list(tk_send('width'))
+ end
+ def width(row)
+ number(tk_send('width', row))
+ end
+ def set_width(*pairs)
+ tk_send('width', *(pairs.flatten))
+ self
+ end
+
+ def window_delete(*args)
+ tk_send('window', 'delete', *(args.collect{|idx| tagid(idx)}))
+ self
+ end
+ def window_move(from_idx, to_idx)
+ tk_send('window', 'move', tagid(from_idx), tagid(to_idx))
+ self
+ end
+ def window_names(pat=None)
+ simplelist(tk_send('window', 'names', pat))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tktrans.rb b/ext/tk/lib/tkextlib/tktrans.rb
new file mode 100644
index 0000000000..c5de5be5e6
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tktrans.rb
@@ -0,0 +1,14 @@
+#
+# TkTrans support (win32 only)
+# 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 'tkextlib/tktrans/setup.rb'
+
+# load library
+require 'tkextlib/tktrans/tktrans'
diff --git a/ext/tk/lib/tkextlib/tktrans/setup.rb b/ext/tk/lib/tkextlib/tktrans/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tktrans/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/tktrans/tktrans.rb b/ext/tk/lib/tkextlib/tktrans/tktrans.rb
new file mode 100644
index 0000000000..e051c09211
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tktrans/tktrans.rb
@@ -0,0 +1,64 @@
+#
+# TkTrans support (win32 only)
+# 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 'tkextlib/tktrans/setup.rb'
+
+TkPackage.require('tktrans') rescue Tk.load_tcllibrary('tktrans')
+
+module Tk
+ module TkTrans
+ PACKAGE_NAME = 'tktrans'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('tktrans')
+ rescue
+ ''
+ end
+ end
+ end
+end
+
+class TkWindow
+ def tktrans_set_image(img)
+ tk_send('tktrans::setwidget', @path, img)
+ self
+ end
+ def tktrans_get_image()
+ tk_send('tktrans::setwidget', @path)
+ end
+end
+
+class Tk::Root
+ undef tktrans_set_image, tktrans_get_image
+
+ def tktrans_set_image(img)
+ tk_send('tktrans::settoplevel', @path, img)
+ self
+ end
+ def tktrans_get_image()
+ tk_send('tktrans::settoplevel', @path)
+ end
+end
+
+class Tk::Toplevel
+ undef tktrans_set_image, tktrans_get_image
+
+ def tktrans_set_image(img)
+ tk_send('tktrans::settoplevel', @path, img)
+ self
+ end
+ def tktrans_get_image()
+ tk_send('tktrans::settoplevel', @path)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/treectrl.rb b/ext/tk/lib/tkextlib/treectrl.rb
new file mode 100644
index 0000000000..1944fb83e3
--- /dev/null
+++ b/ext/tk/lib/tkextlib/treectrl.rb
@@ -0,0 +1,13 @@
+#
+# TkTreeCtrl support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# call setup script
+require 'tkextlib/treectrl/setup.rb'
+
+# load library
+require 'tkextlib/treectrl/tktreectrl'
diff --git a/ext/tk/lib/tkextlib/treectrl/setup.rb b/ext/tk/lib/tkextlib/treectrl/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/treectrl/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/treectrl/tktreectrl.rb b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
new file mode 100644
index 0000000000..e10e6e299e
--- /dev/null
+++ b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
@@ -0,0 +1,2461 @@
+#
+# tkextlib/treectrl/tktreectrl.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 'tkextlib/treectrl/setup.rb'
+
+# TkPackage.require('treectrl', '1.0')
+# TkPackage.require('treectrl', '1.1')
+TkPackage.require('treectrl')
+
+module Tk
+ class TreeCtrl < TkWindow
+ BindTag_FileList = TkBindTag.new_by_name('TreeCtrlFileList')
+
+ PACKAGE_NAME = 'treectrl'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('treectrl')
+ rescue
+ ''
+ end
+ end
+
+ HasColumnCreateCommand =
+ (TkPackage.vcompare(self.package_version, '1.1') >= 0)
+
+ # dummy ::
+ # pkgIndex.tcl of TreeCtrl-1.0 doesn't support auto_load for
+ # 'loupe' command (probably it is bug, I think).
+ # So, calling a 'treectrl' command for loading the dll with
+ # the auto_load facility.
+ begin
+ tk_call('treectrl')
+ rescue
+ end
+ def self.loupe(img, x, y, w, h, zoom)
+ # NOTE: platform == 'unix' only
+
+ # img => TkPhotoImage
+ # x, y => screen coords
+ # w, h => magnifier width and height
+ # zoom => zooming rate
+ Tk.tk_call_without_enc('loupe', img, x, y, w, h, zoom)
+ end
+
+ def self.text_layout(font, text, keys={})
+ TkComm.list(Tk.tk_call_without_enc('textlayout', font, text, keys))
+ end
+
+ def self.image_tint(img, color, alpha)
+ Tk.tk_call_without_enc('imagetint', img, color, alpha)
+ end
+
+ class NotifyEvent < TkUtil::CallbackSubst
+ end
+
+ module ConfigMethod
+ end
+ end
+ TreeCtrl_Widget = TreeCtrl
+end
+
+##############################################
+
+class Tk::TreeCtrl::NotifyEvent
+ # [ <'%' subst-key char>, <proc type char>, <instance var (accessor) name>]
+ KEY_TBL = [
+ [ ?c, ?n, :item_num ],
+ [ ?d, ?s, :detail ],
+ [ ?D, ?l, :items ],
+ [ ?e, ?e, :event ],
+ [ ?I, ?n, :id ],
+ [ ?l, ?n, :lower_bound ],
+ [ ?p, ?n, :active_id ],
+ [ ?P, ?e, :pattern ],
+ [ ?S, ?l, :sel_items ],
+ [ ?T, ?w, :widget ],
+ [ ?u, ?n, :upper_bound ],
+ [ ?W, ?o, :object ],
+ [ ??, ?x, :parm_info ],
+ nil
+ ]
+
+ # [ <proc type char>, <proc/method to convert tcl-str to ruby-obj>]
+ PROC_TBL = [
+ [ ?n, TkComm.method(:num_or_str) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?l, TkComm.method(:list) ],
+ [ ?w, TkComm.method(:window) ],
+
+ [ ?e, proc{|val|
+ case val
+ when /^<<[^<>]+>>$/
+ TkVirtualEvent.getobj(val[1..-2])
+ when /^<[^<>]+>$/
+ val[1..-2]
+ else
+ val
+ end
+ }
+ ],
+
+ [ ?o, proc{|val| TkComm.tk_tcl2ruby(val)} ],
+
+ [ ?x, proc{|val|
+ begin
+ inf = {}
+ Hash[*(TkComm.list(val))].each{|k, v|
+ if keyinfo = KEY_TBL.assoc(k[0])
+ if cmd = PROC_TBL.assoc(keyinfo[1])
+ begin
+ new_v = cmd.call(v)
+ v = new_v
+ rescue
+ end
+ end
+ end
+ inf[k] = v
+ }
+ inf
+ rescue
+ val
+ end
+ } ],
+
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ # 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::ConfigMethod
+ include TkItemConfigMethod
+
+ def treectrl_tagid(key, obj)
+ if key.kind_of?(Array)
+ key = key.join(' ')
+ else
+ key = key.to_s
+ end
+
+ if (obj.kind_of?(Tk::TreeCtrl::Column) ||
+ obj.kind_of?(Tk::TreeCtrl::Element) ||
+ obj.kind_of?(Tk::TreeCtrl::Item) ||
+ obj.kind_of?(Tk::TreeCtrl::Style))
+ obj = obj.id
+ end
+
+ case key
+ when 'column'
+ obj
+
+ when 'debug'
+ None
+
+ when 'dragimage'
+ None
+
+ when 'element'
+ obj
+
+ when 'item element'
+ obj
+
+ when 'marquee'
+ None
+
+ when 'notify'
+ obj
+
+ when 'style'
+ obj
+
+ else
+ obj
+ end
+ end
+
+ def tagid(mixed_id)
+ if mixed_id == 'debug'
+ ['debug', None]
+ elsif mixed_id == 'dragimage'
+ ['dragimage', None]
+ elsif mixed_id == 'marquee'
+ ['marquee', None]
+ elsif mixed_id.kind_of?(Array)
+ [mixed_id[0], treectrl_tagid(*mixed_id)]
+ else
+ tagid(mixed_id.split(':'))
+ end
+ end
+
+ def __item_cget_cmd(mixed_id)
+ if mixed_id[0] == 'column' && mixed_id[1] == 'drag'
+ return [self.path, 'column', 'dragcget']
+ end
+
+ 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[0] == 'column' && mixed_id[1] == 'drag'
+ return [self.path, 'column', 'dragconfigure']
+ end
+
+ 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_font_optkeys(id)
+ if id.kind_of?(Array) && (id[0] == 'element' ||
+ (id[0].kind_of?(Array) && id[0][1] == 'element'))
+ []
+ else
+ ['font']
+ end
+ end
+ private :__item_font_optkeys
+
+ def __item_numstrval_optkeys(id)
+ if id == 'debug'
+ ['displaydelay']
+ else
+ super(id)
+ end
+ end
+ private :__item_numstrval_optkeys
+
+ def __item_boolval_optkeys(id)
+ if id == 'debug'
+ ['data', 'display', 'enable']
+ elsif id == 'dragimage'
+ ['visible']
+ elsif id == 'marquee'
+ ['visible']
+ elsif id.kind_of?(Array)
+ case id[0]
+ when 'item'
+ ['button', 'visible']
+ when 'column'
+ if id[1] == 'drag'
+ ['enable']
+ else
+ ['button', 'expand', 'resize', 'squeeze', 'sunken',
+ 'visible', 'widthhack']
+ end
+ when 'element'
+ ['draw', 'filled', 'showfocus', 'destroy']
+ when 'notify'
+ ['active']
+ when 'style'
+ ['detach']
+ else
+ if id[0].kind_of?(Array) && id[0][1] == 'element'
+ ['filled', 'showfocus']
+ else
+ super(id)
+ end
+ end
+ else
+ super(id)
+ end
+ end
+ private :__item_boolval_optkeys
+
+ def __item_strval_optkeys(id)
+ if id == 'debug'
+ ['erasecolor']
+ elsif id.kind_of?(Array)
+ case id[0]
+ when 'column'
+ if id[1] == 'drag'
+ ['indicatorcolor']
+ else
+ super(id) << 'textcolor'
+ end
+ when 'element'
+ super(id) << 'fill' << 'outline' << 'format'
+ else
+ super(id)
+ end
+ else
+ super(id)
+ end
+ end
+ private :__item_strval_optkeys
+
+ def __item_listval_optkeys(id)
+ if id.kind_of?(Array)
+ case id[0]
+ when 'column'
+ ['itembackground']
+ when 'element'
+ ['relief']
+ when 'style'
+ ['union']
+ else
+ if id[0].kind_of?(Array) && id[0][1] == 'element'
+ ['relief']
+ else
+ []
+ end
+ end
+ else
+ []
+ end
+ 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_cget_strict(tagOrId, option)
+ itemcget_strict(['column', tagOrId], option)
+ end
+ def column_configure(tagOrId, slot, value=None)
+ itemconfigure(['column', tagOrId], slot, value)
+ end
+ def column_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['column', tagOrId], slot)
+ end
+ def current_column_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['column', tagOrId], slot)
+ end
+
+ def column_dragcget(option)
+ itemcget(['column', 'drag'], option)
+ end
+ def column_dragcget_strict(option)
+ itemcget_strict(['column', 'drag'], option)
+ end
+ def column_dragconfigure(slot, value=None)
+ itemconfigure(['column', 'drag'], slot, value)
+ end
+ def column_dragconfiginfo(slot=nil)
+ itemconfiginfo(['column', 'drag'], slot)
+ end
+ def current_column_dragconfiginfo(slot=nil)
+ current_itemconfiginfo(['column', 'drag'], slot)
+ end
+
+ def debug_cget(option)
+ itemcget('debug', option)
+ end
+ def debug_cget_strict(option)
+ itemcget_strict('debug', option)
+ end
+ def debug_configure(slot, value=None)
+ itemconfigure('debug', slot, value)
+ end
+ def debug_configinfo(slot=nil)
+ itemconfiginfo('debug', slot)
+ end
+ def current_debug_configinfo(slot=nil)
+ current_itemconfiginfo('debug', slot)
+ end
+
+ def dragimage_cget(option)
+ itemcget('dragimage', option)
+ end
+ def dragimage_cget_strict(option)
+ itemcget_strict('dragimage', option)
+ end
+ def dragimage_configure(slot, value=None)
+ itemconfigure('dragimage', slot, value)
+ end
+ def dragimage_configinfo(slot=nil)
+ itemconfiginfo('dragimage', slot)
+ end
+ def current_dragimage_configinfo(slot=nil)
+ current_itemconfiginfo('dragimage', slot)
+ end
+
+ def element_cget(tagOrId, option)
+ itemcget(['element', tagOrId], option)
+ end
+ def element_cget_strict(tagOrId, option)
+ itemcget_strict(['element', tagOrId], option)
+ end
+ def element_configure(tagOrId, slot, value=None)
+ itemconfigure(['element', tagOrId], slot, value)
+ end
+ def element_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['element', tagOrId], slot)
+ end
+ def current_element_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['element', tagOrId], slot)
+ end
+
+ def item_cget(tagOrId, option)
+ itemcget(['item', tagOrId], option)
+ end
+ def item_cget_strict(tagOrId, option)
+ itemcget_strict(['item', tagOrId], option)
+ end
+ def item_configure(tagOrId, slot, value=None)
+ itemconfigure(['item', tagOrId], slot, value)
+ end
+ def item_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['item', tagOrId], slot)
+ end
+ def current_item_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['item', tagOrId], slot)
+ end
+
+ def item_element_cget(item, column, elem, option)
+ itemcget([['item', 'element'], [item, column, elem]], option)
+ end
+ def item_element_cget_strict(item, column, elem, option)
+ itemcget_strict([['item', 'element'], [item, column, elem]], option)
+ end
+ def item_element_configure(item, column, elem, slot, value=None)
+ itemconfigure([['item', 'element'], [item, column, elem]], slot, value)
+ end
+ def item_element_configinfo(item, column, elem, slot=nil)
+ itemconfiginfo([['item', 'element'], [item, column, elem]], slot)
+ end
+ def current_item_element_configinfo(item, column, elem, slot=nil)
+ current_itemconfiginfo([['item', 'element'], [item, column, elem]], slot)
+ end
+
+ def marquee_cget(option)
+ itemcget('marquee', option)
+ end
+ def marquee_cget_strict(option)
+ itemcget_strict('marquee', option)
+ end
+ def marquee_configure(slot, value=None)
+ itemconfigure('marquee', slot, value)
+ end
+ def marquee_configinfo(slot=nil)
+ itemconfiginfo('marquee', slot)
+ end
+ def current_marquee_configinfo(slot=nil)
+ current_itemconfiginfo('marquee', slot)
+ end
+
+ def notify_cget(win, pattern, option)
+ pattern = "<#{pattern}>"
+ # "notify" doesn't have cget subcommand.
+ current_itemconfiginfo(['notify', [win, pattern]])[option.to_s]
+ end
+ def notify_cget_strict(win, pattern, option)
+ pattern = "<#{pattern}>"
+ # "notify" doesn't have cget subcommand.
+ info = current_itemconfiginfo(['notify', [win, pattern]])
+ option = option.to_s
+ unless info.has_key?(option)
+ fail RuntimeError, "unknown option \"#{option}\""
+ else
+ info[option]
+ end
+ end
+ def notify_configure(win, pattern, slot, value=None)
+ pattern = "<#{pattern}>"
+ itemconfigure(['notify', [win, pattern]], slot, value)
+ end
+ def notify_configinfo(win, pattern, slot=nil)
+ pattern = "<#{pattern}>"
+ itemconfiginfo(['notify', [win, pattern]], slot)
+ end
+ def current_notify_configinfo(tagOrId, slot=nil)
+ pattern = "<#{pattern}>"
+ current_itemconfiginfo(['notify', [win, pattern]], slot)
+ end
+
+ def style_cget(tagOrId, option)
+ itemcget(['style', tagOrId], option)
+ end
+ def style_cget_strict(tagOrId, option)
+ itemcget_strict(['style', tagOrId], option)
+ end
+ def style_configure(tagOrId, slot, value=None)
+ itemconfigure(['style', tagOrId], slot, value)
+ end
+ def style_configinfo(tagOrId, slot=nil)
+ itemconfiginfo(['style', tagOrId], slot)
+ end
+ def current_style_configinfo(tagOrId, slot=nil)
+ current_itemconfiginfo(['style', tagOrId], slot)
+ end
+
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+end
+
+##############################################
+
+class Tk::TreeCtrl
+ include Tk::TreeCtrl::ConfigMethod
+ include Scrollable
+
+ TkCommandNames = ['treectrl'.freeze].freeze
+ WidgetClassName = 'TreeCtrl'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ #########################
+
+ def __destroy_hook__
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.delete(@path)
+ }
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.delete(@path)
+ }
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.delete(@path)
+ }
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.delete(@path)
+ }
+ end
+
+ #########################
+
+ def __strval_optkeys
+ super() + [
+ 'buttoncolor', 'columnprefix', 'itemprefix', 'linecolor'
+ ]
+ end
+ private :__strval_optkeys
+
+ def __boolval_optkeys
+ [
+ 'itemwidthequal', 'usetheme',
+ 'showbuttons', 'showheader', 'showlines', 'showroot',
+ 'showrootbutton', 'showrootlines',
+ ]
+ end
+ private :__boolval_optkeys
+
+ def __listval_optkeys
+ [ 'defaultstyle' ]
+ end
+ private :__listval_optkeys
+
+ #########################
+
+ def install_bind(cmd, *args)
+ install_bind_for_event_class(Tk::TreeCtrl::NotifyEvent, cmd, *args)
+ end
+
+ #########################
+
+ def create_self(keys)
+ if keys and keys != None
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ tk_call_without_enc(self.class::TkCommandNames[0], @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_without_enc('collapse', *(dsc.map!{|d| _get_eval_string(d, true)}))
+ self
+ end
+
+ def collapse_recurse(*dsc)
+ tk_send_without_enc('collapse', '-recurse',
+ *(dsc.map!{|d| _get_eval_string(d, true)}))
+ self
+ end
+
+ def column_bbox(idx)
+ list(tk_send('column', 'bbox', idx))
+ end
+
+ def column_compare(column1, op, column2)
+ bool(tk_send('column', 'compare', column1, op, column2))
+ end
+
+ def column_count
+ num_or_str(tk_send('column', 'count'))
+ end
+
+ def column_create(keys=nil)
+ if keys && keys.kind_of?(Hash)
+ num_or_str(tk_send('column', 'create', *hash_kv(keys)))
+ else
+ num_or_str(tk_send('column', 'create'))
+ end
+ end
+
+ def column_delete(idx)
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path]
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path].delete(idx)
+ end
+ }
+ tk_send('column', 'delete', idx)
+ self
+ end
+
+ def column_index(idx)
+ num_or_str(tk_send('column', 'index', idx))
+ end
+
+ def column_id(idx)
+ tk_send('column', 'id', idx)
+ end
+
+ def column_list(visible=false)
+ if visible
+ simplelist(tk_send('column', 'list', '-visible'))
+ else
+ simplelist(tk_send('column', 'list'))
+ end
+ end
+ def column_visible_list
+ column_list(true)
+ end
+
+ def column_move(idx, before)
+ tk_send('column', 'move', idx, before)
+ self
+ end
+
+ def column_needed_width(idx)
+ num_or_str(tk_send('column', 'neededwidth', idx))
+ end
+ alias column_neededwidth column_needed_width
+
+ def column_order(column, visible=false)
+ if visible
+ num_or_str(tk_send('column', 'order', column, '-visible'))
+ else
+ num_or_str(tk_send('column', 'order', column))
+ end
+ end
+ def column_visible_order(column)
+ column_order(column, true)
+ end
+
+ def column_width(idx)
+ num_or_str(tk_send('column', 'width', idx))
+ end
+
+ def compare(item1, op, item2)
+ bool(tk_send('compare', item1, op, item2))
+ end
+
+ def contentbox()
+ list(tk_send('contentbox'))
+ end
+
+ def depth(item=None)
+ num_or_str(tk_send_without_enc('depth', _get_eval_string(item, true)))
+ 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 debug_dinfo
+ tk_send('debug', 'dinfo')
+ self
+ end
+
+ def debug_scroll
+ tk_send('debug', 'scroll')
+ 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::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path]
+ elems.each{|elem|
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path].delete(elem)
+ }
+ end
+ }
+ tk_send('element', 'delete', *elems)
+ self
+ end
+
+ def element_names()
+ list(tk_send('element', 'names')).collect!{|elem|
+ Tk::TreeCtrl::Element.id2obj(self, elem)
+ }
+ end
+
+ def _conv_element_perstate_val(opt, val)
+ case opt
+ when 'background', 'foreground', 'fill', 'outline', 'format'
+ val
+ when 'draw', 'filled', 'showfocus', 'destroy'
+ bool(val)
+ else
+ tk_tcl2ruby(val)
+ end
+ end
+ private :_conv_element_perstate_val
+
+ def element_perstate(elem, opt, st_list)
+ tk_send('element', 'perstate', elem, "-{opt}", st_list)
+ end
+
+ def element_type(elem)
+ tk_send('element', 'type', elem)
+ end
+
+ def element_class(elem)
+ Tk::TreeCtrl::Element.type2class(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)
+ lst = list(tk_send('identify', x, y))
+
+ if lst[0] == 'item'
+ lst[1] = Tk::TreeCtrl::Item.id2obj(self, lst[1])
+ size = lst.size
+ i = 2
+ while i < size
+ case lst[i]
+ when 'line'
+ i += 1
+ lst[i] = Tk::TreeCtrl::Item.id2obj(self, lst[i])
+ i += 1
+
+ when 'button'
+ i += 1
+
+ when 'column'
+ i += 2
+
+ when 'elem'
+ i += 1
+ lst[i] = Tk::TreeCtrl::Element.id2obj(self, lst[i])
+ i += 1
+
+ else
+ i += 1
+ end
+ end
+ end
+
+ lst
+ end
+
+ def index(idx)
+ num_or_str(tk_send('index', idx))
+ end
+
+ def item_ancestors(item)
+ list(tk_send('item', 'ancestors', item)).collect!{|id|
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ }
+ end
+
+ def item_bbox(item, *args)
+ list(tk_send('item', 'bbox', item, *args))
+ end
+
+ def item_children(item)
+ list(tk_send('item', 'children', item)).collect!{|id|
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ }
+ end
+
+ def item_collapse(item)
+ tk_send_without_enc('item', 'collapse', _get_eval_string(item, true))
+ self
+ end
+
+ def item_collapse_recurse(item)
+ tk_send_without_enc('item', 'collapse',
+ _get_eval_string(item, true), '-recurse')
+ self
+ end
+
+ def item_compare(item1, op, item2)
+ bool(tk_send('item', 'compare', item1, op, item2))
+ end
+
+ def item_complex(item, *args)
+ tk_send_without_enc('item', 'complex',
+ _get_eval_string(item, true),
+ *(args.map!{|arg| _get_eval_string(arg, true)}))
+ self
+ end
+
+ def item_count
+ num_or_str(tk_send('item', 'count'))
+ end
+
+ def item_create(keys={})
+ num_or_str(tk_send_without_enc('item', 'create', *hash_kv(keys, true)))
+ end
+
+ def _erase_children(item)
+ item_children(item).each{|i| _erase_children(i)}
+ # table is already locked
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path].delete(item)
+ end
+ private :_erase_children
+
+ def item_delete(first, last=None)
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path]
+ if first == 'all' || first == :all || last == 'all' || last == :all
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path].clear
+ elsif last == None
+ _erase_children(first)
+ else
+ self.range(first, last).each{|id|
+ _erase_children(id)
+ }
+ end
+ end
+ }
+ tk_send('item', 'delete', first, last)
+ self
+ end
+
+ def item_dump(item)
+ list(tk_send('item', 'dump', item))
+ end
+
+ def item_dump_hash(item)
+ Hash[*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_element_perstate(elem, opt, st_list)
+ tk_send('item', 'element', 'perstate', elem, "-{opt}", st_list)
+ end
+
+ def item_expand(item)
+ tk_send('item', 'expand', item)
+ self
+ end
+
+ def item_expand_recurse(item)
+ tk_send('item', 'expand', item, '-recurse')
+ self
+ end
+
+ def item_firstchild(parent, child=nil)
+ if child
+ tk_send_without_enc('item', 'firstchild',
+ _get_eval_string(parent, true),
+ _get_eval_string(child, true))
+ self
+ else
+ id = num_or_str(tk_send_without_enc('item', 'firstchild',
+ _get_eval_string(parent, true)))
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ end
+ end
+ alias item_first_child item_firstchild
+
+ def item_hasbutton(item, st=None)
+ if st == None
+ bool(tk_send_without_enc('item', 'hasbutton',
+ _get_eval_string(item, true)))
+ else
+ tk_send_without_enc('item', 'hasbutton',
+ _get_eval_string(item, true),
+ _get_eval_string(st))
+ self
+ end
+ end
+ alias item_has_button item_hasbutton
+
+ def item_hasbutton?(item)
+ item_hasbutton(item)
+ end
+ alias item_has_button? item_hasbutton?
+
+ def item_id(item)
+ tk_send('item', 'id', item)
+ end
+
+ def item_image(item, column=nil, *args)
+ if args.empty?
+ if column
+ img = tk_send('item', 'image', item, column)
+ TkImage::Tk_IMGTBL[img]? TkImage::Tk_IMGTBL[img] : img
+ else
+ simplelist(tk_send('item', 'image', item)).collect!{|img|
+ TkImage::Tk_IMGTBL[img]? TkImage::Tk_IMGTBL[img] : img
+ }
+ end
+ else
+ tk_send('item', 'image', item, column, *args)
+ self
+ end
+ end
+ def get_item_image(item, column=nil)
+ item_image(item, column)
+ end
+ def set_item_image(item, col, img, *args)
+ item_image(item, col, img, *args)
+ 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
+ alias item_isopened? item_isopen
+ alias item_is_opened? item_isopen
+
+ def item_lastchild(parent, child=nil)
+ if child
+ tk_send_without_enc('item', 'lastchild',
+ _get_eval_string(parent, true),
+ _get_eval_string(child, true))
+ self
+ else
+ id = num_or_str(tk_send_without_enc('item', 'lastchild',
+ _get_eval_string(parent, true)))
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ end
+ end
+ alias item_last_child item_lastchild
+
+ def item_nextsibling(sibling, nxt=nil)
+ if nxt
+ tk_send('item', 'nextsibling', sibling, nxt)
+ self
+ else
+ id = num_or_str(tk_send('item', 'nextsibling', sibling))
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ end
+ end
+ alias item_next_sibling item_nextsibling
+
+ def item_numchildren(item)
+ number(tk_send_without_enc('item', 'numchildren',
+ _get_eval_string(item, true)))
+ end
+ alias item_num_children item_numchildren
+ alias item_children_size item_numchildren
+
+ def item_order(item, visible=false)
+ if visible
+ ret = num_or_str(tk_send('item', 'order', item, '-visible'))
+ else
+ ret = num_or_str(tk_send('item', 'order', item))
+ end
+
+ (ret.kind_of?(Fixnum) && ret < 0)? nil: ret
+ end
+ def item_visible_order(item)
+ item_order(item, true)
+ end
+
+ def item_parent(item)
+ id = num_or_str(tk_send('item', 'parent', item))
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ end
+
+ def item_prevsibling(sibling, prev=nil)
+ if prev
+ tk_send('item', 'prevsibling', sibling, prev)
+ self
+ else
+ id = num_or_str(tk_send('item', 'prevsibling', sibling))
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ end
+ end
+ alias item_prev_sibling item_prevsibling
+
+ def item_range(first, last)
+ simplelist(tk_send('item', 'range', first, last))
+ end
+
+ def item_remove(item)
+ tk_send('item', 'remove', item)
+ self
+ end
+
+ def item_rnc(item)
+ list(tk_send('item', 'rnc', item))
+ end
+
+ def _item_sort_core(real_sort, item, *opts)
+ # opts ::= sort_param [, sort_param, ... ]
+ # sort_param ::= {key=>val, ...}
+ # [type, desc, {key=>val, ...}]
+ # param
+ opts = opts.collect{|param|
+ if param.kind_of?(Hash)
+ param = _symbolkey2str(param)
+ if param.key?('column')
+ key = '-column'
+ desc = param.delete('column')
+ elsif param.key?('element')
+ key = '-element'
+ desc = param.delete('element')
+ else
+ key = nil
+ end
+
+ if param.empty?
+ param = None
+ else
+ param = hash_kv(__conv_item_keyonly_opts(item, param))
+ end
+
+ if key
+ [key, desc].concat(param)
+ else
+ param
+ end
+
+ elsif param.kind_of?(Array)
+ if param[2].kind_of?(Hash)
+ param[2] = hash_kv(__conv_item_keyonly_opts(item, param[2]))
+ end
+ param
+
+ elsif param.kind_of?(String) && param =~ /\A[a-z]+\Z/
+ '-' << param
+
+ elsif param.kind_of?(Symbol)
+ '-' << param.to_s
+
+ else
+ param
+ end
+ }.flatten
+
+ if real_sort
+ tk_send('item', 'sort', item, *opts)
+ self
+ else
+ list(tk_send('item', 'sort', item, '-notreally', *opts))
+ end
+ end
+ private :_item_sort_core
+
+ def item_sort(item, *opts)
+ _item_sort_core(true, item, *opts)
+ end
+ def item_sort_not_really(item, *opts)
+ _item_sort_core(false, item, *opts)
+ end
+
+ def item_span(item, column=nil, *args)
+ if args.empty?
+ if column
+ list(tk_send('item', 'span', item, column))
+ else
+ simplelist(tk_send('item', 'span', item)).collect!{|elem| list(elem)}
+ end
+ else
+ tk_send('item', 'span', item, column, *args)
+ self
+ end
+ end
+ def get_item_span(item, column=nil)
+ item_span(item, column)
+ end
+ def set_item_span(item, col, num, *args)
+ item_span(item, col, num, *args)
+ end
+
+ def item_state_forcolumn(item, column, *args)
+ tk_send('item', 'state', 'forcolumn', item, column, *args)
+ end
+ alias item_state_for_column item_state_forcolumn
+
+ 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', item, *args)
+ end
+
+ def item_style_elements(item, column)
+ list(tk_send('item', 'style', 'elements', item, column)).collect!{|id|
+ Tk::TreeCtrl::Style.id2obj(self, id)
+ }
+ 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
+ id = tk_send_without_enc('item', 'style', 'set',
+ _get_eval_string(item, true),
+ _get_eval_string(column, true))
+ Tk::TreeCtrl::Style.id2obj(self, id)
+ else
+ list(tk_send_without_enc('item', 'style', 'set',
+ _get_eval_string(item, true))).collect!{|id|
+ Tk::TreeCtrl::Style.id2obj(self, id)
+ }
+ end
+ else
+ tk_send_without_enc('item', 'style', 'set',
+ _get_eval_string(item, true),
+ _get_eval_string(column, true),
+ *(args.flatten.map!{|arg|
+ _get_eval_string(arg, true)
+ }))
+ 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, column, txt, *args)
+ self
+ end
+ end
+
+ def item_toggle(item)
+ tk_send('item', 'toggle', item)
+ self
+ end
+
+ def item_toggle_recurse(item)
+ tk_send('item', 'toggle', item, '-recurse')
+ self
+ 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')).collect!{|id|
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ }
+ 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)
+ # _bind([@path, 'notify', 'bind', obj], event, cmd, *args)
+ # self
+ #end
+ def notify_bind(obj, event, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([@path, 'notify', 'bind', obj], event, cmd, *args)
+ self
+ end
+
+ #def notify_bind_append(obj, event, cmd=Proc.new, *args)
+ # _bind_append([@path, 'notify', 'bind', obj], event, cmd, *args)
+ # self
+ #end
+ def notify_bind_append(obj, event, *args)
+ # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([@path, 'notify', 'bind', obj], event, cmd, *args)
+ self
+ end
+
+ def notify_bind_remove(obj, event)
+ _bind_remove([@path, 'notify', 'bind', obj], event)
+ 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, percents_cmd=None)
+ pattern = "<#{pattern}>"
+ tk_send('notify', 'generate', pattern, char_map, percents_cmd)
+ self
+ end
+
+ def notify_install(pattern, percents_cmd=nil, &b)
+ pattern = "<#{pattern}>"
+ percents_cmd = Proc.new(&b) if !percents_cmd && b
+ if percents_cmd
+ procedure(tk_send('notify', 'install', pattern, percents_cmd))
+ else
+ procedure(tk_send('notify', 'install', pattern))
+ end
+ 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(pattern, detail=None)
+ if detail != None
+ tk_send('notify', 'linkage', pattern, detail)
+ else
+ begin
+ if pattern.to_s.index(?-)
+ # TreeCtrl 1.1 format?
+ begin
+ tk_send('notify', 'linkage', "<#{pattern}>")
+ rescue
+ # TreeCtrl 1.0?
+ tk_send('notify', 'linkage', pattern)
+ end
+ else
+ # TreeCtrl 1.0 format?
+ begin
+ tk_send('notify', 'linkage', pattern)
+ rescue
+ # TreeCtrl 1.1?
+ tk_send('notify', 'linkage', "<#{pattern}>")
+ end
+ end
+ end
+ end
+ end
+
+ def notify_unbind(pattern=nil)
+ if pattern
+ tk_send('notify', 'unbind', "<#{pattern}>")
+ else
+ tk_send('notify', 'unbind')
+ end
+ self
+ end
+
+ def notify_uninstall(pattern)
+ pattern = "<#{pattern}>"
+ tk_send('notify', 'uninstall', pattern)
+ self
+ 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
+ alias num_columns numcolumns
+ alias columns_size numcolumns
+
+ def numitems()
+ num_or_str(tk_send('numitems'))
+ end
+ alias num_items numitems
+ alias items_size numitems
+
+ def orphans()
+ list(tk_send('orphans')).collect!{|id|
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ }
+ end
+
+ def range(first, last)
+ list(tk_send('range', first, last)).collect!{|id|
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ }
+ 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)
+ id = num_or_str(tk_send('selection', 'anchor', item))
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ 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')).collect!{|id|
+ Tk::TreeCtrl::Item.id2obj(self, id)
+ }
+ 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::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path]
+ args.each{|sty|
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path].delete(sty)
+ }
+ end
+ }
+ tk_send('style', 'delete', *args)
+ self
+ end
+
+ def style_elements(style, *elems)
+ if elems.empty?
+ list(tk_send('style', 'elements', style)).collect!{|id|
+ Tk::TreeCtrl::Element.id2obj(self, id)
+ }
+ else
+ tk_send('style', 'elements', style, elems.flatten)
+ self
+ end
+ end
+
+ def _conv_style_layout_val(sty, val)
+ case sty.to_s
+ when 'padx', 'pady', 'ipadx', 'ipady'
+ lst = list(val)
+ (lst.size == 1)? lst[0]: lst
+ when 'detach', 'indent'
+ bool(val)
+ when 'union'
+ simplelist(val).collect!{|elem|
+ Tk::TreeCtrl::Element.id2obj(self, elem)
+ }
+ else
+ val
+ end
+ end
+ private :_conv_style_layout_val
+
+ 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
+ _conv_style_layout_val(keys,
+ tk_send('style', 'layout',
+ style, elem, "-#{keys}"))
+ end
+ else
+ ret = Hash.new
+ Hash[*simplelist(tk_send('style', 'layout', style, elem))].each{|k, v|
+ k = k[1..-1]
+ ret[k] = _conv_style_layout_val(k, v)
+ }
+ ret
+ end
+ end
+ def get_style_layout(style, elem, opt=None)
+ style_layout(style, elem, opt)
+ end
+ def set_style_layout(style, elem, slot, value=None)
+ if slot.kind_of?(Hash)
+ style_layout(style, elem, slot)
+ else
+ style_layout(style, elem, {slot=>value})
+ end
+ end
+
+ def style_names()
+ list(tk_send('style', 'names')).collect!{|id|
+ Tk::TreeCtrl::Style.id2obj(self, id)
+ }
+ end
+
+ def toggle(*items)
+ tk_send('toggle', *items)
+ self
+ end
+
+ def toggle_recurse()
+ tk_send('toggle', '-recurse', *items)
+ self
+ end
+end
+
+#####################
+
+class Tk::TreeCtrl::Column < TkObject
+ TreeCtrlColumnID_TBL = TkCore::INTERP.create_table
+
+ (TreeCtrlColumnID = ['treectrl_column'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.clear
+ }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath]
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id]? \
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(parent, keys={})
+ @tree = parent
+ @tpath = parent.path
+
+ keys = _symbolkey2str(keys)
+
+ Tk::TreeCtrl::Column::TreeCtrlColumnID.mutex.synchronize{
+ @path = @id =
+ keys.delete('tag') ||
+ Tk::TreeCtrl::Column::TreeCtrlColumnID.join(TkCore::INTERP._ip_id_)
+ Tk::TreeCtrl::Column::TreeCtrlColumnID[1].succ!
+ }
+
+ keys['tag'] = @id
+
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath] ||= {}
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath][@id] = self
+ }
+
+ @tree.column_create(keys)
+ end
+
+ def id
+ @id
+ end
+
+ def to_s
+ @id.to_s.dup
+ end
+
+ def cget(opt)
+ @tree.column_cget(@tree.column_index(@id), opt)
+ end
+ def cget_strict(opt)
+ @tree.column_cget_strict(@tree.column_index(@id), opt)
+ end
+
+ def configure(*args)
+ @tree.column_configure(@tree.column_index(@id), *args)
+ end
+
+ def configinfo(*args)
+ @tree.column_configinfo(@tree.column_index(@id), *args)
+ end
+
+ def current_configinfo(*args)
+ @tree.current_column_configinfo(@tree.column_index(@id), *args)
+ end
+
+ def delete
+ @tree.column_delete(@tree.column_index(@id))
+ self
+ end
+
+ def index
+ @tree.column_index(@id)
+ end
+
+ def move(before)
+ @tree.column_move(@tree.column_index(@id), before)
+ self
+ end
+
+ def needed_width
+ @tree.column_needed_width(@tree.column_index(@id))
+ end
+ alias neededwidth needed_width
+
+ def current_width
+ @tree.column_width(@tree.column_index(@id))
+ end
+end
+
+#####################
+
+class Tk::TreeCtrl::Element < TkObject
+ TreeCtrlElementID_TBL = TkCore::INTERP.create_table
+
+ (TreeCtrlElementID = ['treectrl_element'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+ TreeCtrlElemTypeToClass = {}
+
+ TkCore::INTERP.init_ip_env{
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.clear
+ }
+ }
+
+ def self.type2class(type)
+ TreeCtrlElemTypeToClass[type] || type
+ end
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath]
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath][id]? \
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(parent, type, keys=nil)
+ @tree = parent
+ @tpath = parent.path
+ @type = type.to_s
+ Tk::TreeCtrl::Element::TreeCtrlElementID.mutex.synchronize{
+ @path = @id =
+ Tk::TreeCtrl::Element::TreeCtrlElementID.join(TkCore::INTERP._ip_id_)
+ Tk::TreeCtrl::Element::TreeCtrlElementID[1].succ!
+ }
+
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath] ||= {}
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath][@id] = self
+ }
+
+ @tree.element_create(@id, @type, keys)
+ end
+
+ def id
+ @id
+ end
+
+ def to_s
+ @id.dup
+ end
+
+ def cget(opt)
+ @tree.element_cget(@id, opt)
+ end
+ def cget_strict(opt)
+ @tree.element_cget_strict(@id, opt)
+ end
+
+ def configure(*args)
+ @tree.element_configure(@id, *args)
+ end
+
+ def configinfo(*args)
+ @tree.element_configinfo(@id, *args)
+ end
+
+ def current_configinfo(*args)
+ @tree.current_element_configinfo(@id, *args)
+ end
+
+ def delete
+ @tree.element_delete(@id)
+ self
+ end
+
+ def element_type
+ @tree.element_type(@id)
+ end
+
+ def element_class
+ @tree.element_class(@id)
+ end
+end
+
+class Tk::TreeCtrl::BitmapElement < Tk::TreeCtrl::Element
+ TreeCtrlElemTypeToClass['bitmap'] = self
+
+ def initialize(parent, keys=nil)
+ super(parent, 'bitmap', keys)
+ end
+end
+
+class Tk::TreeCtrl::BorderElement < Tk::TreeCtrl::Element
+ TreeCtrlElemTypeToClass['border'] = self
+
+ def initialize(parent, keys=nil)
+ super(parent, 'border', keys)
+ end
+end
+
+class Tk::TreeCtrl::ImageElement < Tk::TreeCtrl::Element
+ TreeCtrlElemTypeToClass['image'] = self
+
+ def initialize(parent, keys=nil)
+ super(parent, 'image', keys)
+ end
+end
+
+class Tk::TreeCtrl::RectangleElement < Tk::TreeCtrl::Element
+ TreeCtrlElemTypeToClass['rect'] = self
+
+ def initialize(parent, keys=nil)
+ super(parent, 'rect', keys)
+ end
+end
+
+#####################
+
+class Tk::TreeCtrl::Item < TkObject
+ TreeCtrlItemID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.clear
+ }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath]
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id]? \
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(parent, keys={})
+ @tree = parent
+ @tpath = parent.path
+ @path = @id = @tree.item_create(keys)
+
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath] ||= {}
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath][@id] = self
+ }
+ end
+
+ def id
+ @id
+ end
+
+ def to_s
+ @id.to_s.dup
+ end
+
+ def ancestors
+ @tree.item_ancestors(@id)
+ end
+
+ def bbox(*args)
+ @tree.item_bbox(@id, *args)
+ end
+
+ def children
+ @tree.item_children(@id)
+ end
+
+ def collapse
+ @tree.item_collapse(@id)
+ self
+ end
+
+ def collapse_recurse
+ @tree.item_collapse_recurse(@id)
+ self
+ end
+
+ def complex(*args)
+ @tree.item_complex(@id, *args)
+ self
+ end
+
+ def cget(opt)
+ @tree.item_cget(@id, opt)
+ end
+ def cget_strict(opt)
+ @tree.item_cget_strict(@id, opt)
+ end
+
+ def configure(*args)
+ @tree.item_configure(@id, *args)
+ end
+
+ def configinfo(*args)
+ @tree.item_configinfo(@id, *args)
+ end
+
+ def current_configinfo(*args)
+ @tree.current_item_configinfo(@id, *args)
+ end
+
+ def delete
+ @tree.item_delete(@id)
+ self
+ end
+
+ def element_dump
+ @tree.item_dump(@id)
+ end
+
+ def element_dump_hash
+ @tree.item_dump_hash(@id)
+ end
+
+ def element_actual(column, elem, key)
+ @tree.item_element_actual(@id, column, elem, key)
+ end
+
+ def element_cget(opt)
+ @tree.item_element_cget(@id, opt)
+ end
+ def element_cget_strict(opt)
+ @tree.item_element_cget_strict(@id, opt)
+ end
+
+ def element_configure(*args)
+ @tree.item_element_configure(@id, *args)
+ end
+
+ def element_configinfo(*args)
+ @tree.item_element_configinfo(@id, *args)
+ end
+
+ def current_element_configinfo(*args)
+ @tree.current_item_element_configinfo(@id, *args)
+ end
+
+ def expand
+ @tree.item_expand(@id)
+ self
+ end
+
+ def expand_recurse
+ @tree.item_expand_recurse(@id)
+ self
+ end
+
+ def firstchild(child=nil)
+ if child
+ @tree.item_firstchild(@id, child)
+ self
+ else
+ @tree.item_firstchild(@id)
+ end
+ end
+ alias first_child firstchild
+
+ def hasbutton(st=None)
+ if st == None
+ @tree.item_hasbutton(@id)
+ else
+ @tree.item_hasbutton(@id, st)
+ self
+ end
+ end
+ alias has_button hasbutton
+
+ def hasbutton?
+ @tree.item_hasbutton(@id)
+ end
+ alias has_button? hasbutton?
+
+ def index
+ @tree.item_index(@id)
+ end
+
+ def isancestor(des)
+ @tree.item_isancestor(@id, des)
+ end
+ alias is_ancestor isancestor
+ alias isancestor? isancestor
+ alias is_ancestor? isancestor
+ alias ancestor? isancestor
+
+ def isopen
+ @tree.item_isopen(@id)
+ end
+ alias is_open isopen
+ alias isopen? isopen
+ alias is_open? isopen
+ alias isopened? isopen
+ alias is_opened? isopen
+ alias open? isopen
+
+ def lastchild(child=nil)
+ if child
+ @tree.item_lastchild(@id, child)
+ self
+ else
+ @tree.item_lastchild(@id)
+ end
+ end
+ alias last_child lastchild
+
+ def nextsibling(nxt=nil)
+ if nxt
+ @tree.item_nextsibling(@id, nxt)
+ self
+ else
+ @tree.item_nextsibling(@id)
+ end
+ end
+ alias next_sibling nextsibling
+
+ def numchildren
+ @tree.item_numchildren(@id)
+ end
+ alias num_children numchildren
+ alias children_size numchildren
+
+ def parent_index
+ @tree.item_parent(@id)
+ end
+
+ def prevsibling(nxt=nil)
+ if nxt
+ @tree.item_prevsibling(@id, nxt)
+ self
+ else
+ @tree.item_prevsibling(@id)
+ end
+ end
+ alias prev_sibling prevsibling
+
+ def remove
+ @tree.item_remove(@id)
+ end
+
+ def rnc
+ @tree.item_rnc(@id)
+ end
+
+ def sort(*opts)
+ @tree.item_sort(@id, *opts)
+ end
+ def sort_not_really(*opts)
+ @tree.item_sort_not_really(@id, *opts)
+ self
+ end
+
+ def state_forcolumn(column, *args)
+ @tree.item_state_forcolumn(@id, column, *args)
+ self
+ end
+ alias state_for_column state_forcolumn
+
+ def state_get(*args)
+ @tree.item_state_get(@id, *args)
+ end
+
+ def state_set(*args)
+ @tree.item_state_set(@id, *args)
+ self
+ end
+
+ def style_elements(column)
+ @tree.item_style_elements(@id, column)
+ end
+
+ def style_map(column, style, map)
+ @tree.item_style_map(@id, column, style, map)
+ self
+ end
+
+ def style_set(column=nil, *args)
+ if args.empty?
+ @tree.item_style_set(@id, column)
+ else
+ @tree.item_style_set(@id, column, *args)
+ self
+ end
+ end
+
+ def item_text(column, txt=nil, *args)
+ if args.empty?
+ if txt
+ @tree.item_text(@id, column, txt)
+ self
+ else
+ @tree.item_text(@id, column)
+ end
+ else
+ @tree.item_text(@id, column, txt, *args)
+ self
+ end
+ end
+
+ def toggle
+ @tree.item_toggle(@id)
+ self
+ end
+
+ def toggle_recurse
+ @tree.item_toggle_recurse(@id)
+ self
+ end
+
+ def visible(st=None)
+ if st == None
+ @tree.item_visible(@id)
+ else
+ @tree.item_visible(@id, st)
+ self
+ end
+ end
+end
+
+#####################
+
+class Tk::TreeCtrl::Style < TkObject
+ TreeCtrlStyleID_TBL = TkCore::INTERP.create_table
+
+ (TreeCtrlStyleID = ['treectrl_style'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.clear
+ }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath]
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id]? \
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(parent, keys=nil)
+ @tree = parent
+ @tpath = parent.path
+
+ Tk::TreeCtrl::Style::TreeCtrlStyleID.mutex.synchronize{
+ @path = @id =
+ Tk::TreeCtrl::Style::TreeCtrlStyleID.join(TkCore::INTERP._ip_id_)
+ Tk::TreeCtrl::Style::TreeCtrlStyleID[1].succ!
+ }
+
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath] ||= {}
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath][@id] = self
+ }
+
+ @tree.style_create(@id, keys)
+ end
+
+ def id
+ @id
+ end
+
+ def to_s
+ @id.dup
+ end
+
+ def cget(opt)
+ @tree.style_cget(@id, opt)
+ end
+ def cget_strict(opt)
+ @tree.style_cget_strict(@id, opt)
+ end
+
+ def configure(*args)
+ @tree.style_configure(@id, *args)
+ end
+
+ def configinfo(*args)
+ @tree.style_configinfo(@id, *args)
+ end
+
+ def current_configinfo(*args)
+ @tree.current_style_configinfo(@id, *args)
+ end
+
+ def delete
+ @tree.style_delete(@id)
+ self
+ end
+
+ def elements(*elems)
+ if elems.empty?
+ @tree.style_elements(@id)
+ else
+ @tree.style_elements(@id, *elems)
+ self
+ end
+ end
+
+ def layout(elem, keys=None)
+ if keys && keys != None && keys.kind_of?(Hash)
+ @tree.style_layout(@id, elem, keys)
+ self
+ else
+ @tree.style_layout(@id, elem, keys)
+ end
+ end
+end
+
+module Tk::TreeCtrl::BindCallback
+ include Tk
+ extend Tk
+end
+
+class << Tk::TreeCtrl::BindCallback
+ def percentsCmd(*args)
+ tk_call('::TreeCtrl::PercentsCmd', *args)
+ end
+ def cursorCheck(w, x, y)
+ tk_call('::TreeCtrl::CursorCheck', w, x, y)
+ end
+ def cursorCheckAux(w)
+ tk_call('::TreeCtrl::CursorCheckAux', w)
+ end
+ def cursorCancel(w)
+ tk_call('::TreeCtrl::CursorCancel', w)
+ end
+ def buttonPress1(w, x, y)
+ tk_call('::TreeCtrl::ButtonPress1', w, x, y)
+ end
+ def doubleButton1(w, x, y)
+ tk_call('::TreeCtrl::DoubleButton1', w, x, y)
+ end
+ def motion1(w, x, y)
+ tk_call('::TreeCtrl::Motion1', w, x, y)
+ end
+ def leave1(w, x, y)
+ tk_call('::TreeCtrl::Leave1', w, x, y)
+ end
+ def release1(w, x, y)
+ tk_call('::TreeCtrl::Release1', w, x, y)
+ end
+ def beginSelect(w, el)
+ tk_call('::TreeCtrl::BeginSelect', w, el)
+ end
+ def motion(w, le)
+ tk_call('::TreeCtrl::Motion', w, el)
+ end
+ def beginExtend(w, el)
+ tk_call('::TreeCtrl::BeginExtend', w, el)
+ end
+ def beginToggle(w, el)
+ tk_call('::TreeCtrl::BeginToggle', w, el)
+ end
+ def cancelRepeat
+ tk_call('::TreeCtrl::CancelRepeat')
+ end
+ def autoScanCheck(w, x, y)
+ tk_call('::TreeCtrl::AutoScanCheck', w, x, y)
+ end
+ def autoScanCheckAux(w)
+ tk_call('::TreeCtrl::AutoScanCheckAux', w)
+ end
+ def autoScanCancel(w)
+ tk_call('::TreeCtrl::AutoScanCancel', w)
+ end
+ def up_down(w, n)
+ tk_call('::TreeCtrl::UpDown', w, n)
+ end
+ def left_right(w, n)
+ tk_call('::TreeCtrl::LeftRight', w, n)
+ end
+ def setActiveItem(w, idx)
+ tk_call('::TreeCtrl::SetActiveItem', w, idx)
+ end
+ def extendUpDown(w, amount)
+ tk_call('::TreeCtrl::ExtendUpDown', w, amount)
+ end
+ def dataExtend(w, el)
+ tk_call('::TreeCtrl::DataExtend', w, el)
+ end
+ def cancel(w)
+ tk_call('::TreeCtrl::Cancel', w)
+ end
+ def selectAll(w)
+ tk_call('::TreeCtrl::selectAll', w)
+ end
+ def marqueeBegin(w, x, y)
+ tk_call('::TreeCtrl::MarqueeBegin', w, x, y)
+ end
+ def marqueeUpdate(w, x, y)
+ tk_call('::TreeCtrl::MarqueeUpdate', w, x, y)
+ end
+ def marqueeEnd(w, x, y)
+ tk_call('::TreeCtrl::MarqueeEnd', w, x, y)
+ end
+ def scanMark(w, x, y)
+ tk_call('::TreeCtrl::ScanMark', w, x, y)
+ end
+ def scanDrag(w, x, y)
+ tk_call('::TreeCtrl::ScanDrag', w, x, y)
+ end
+
+ # filelist-bindings
+ def fileList_button1(w, x, y)
+ tk_call('::TreeCtrl::FileListButton1', w, x, y)
+ end
+ def fileList_motion1(w, x, y)
+ tk_call('::TreeCtrl::FileListMotion1', w, x, y)
+ end
+ def fileList_motion(w, x, y)
+ tk_call('::TreeCtrl::FileListMotion', w, x, y)
+ end
+ def fileList_leave1(w, x, y)
+ tk_call('::TreeCtrl::FileListLeave1', w, x, y)
+ end
+ def fileList_release1(w, x, y)
+ tk_call('::TreeCtrl::FileListRelease1', w, x, y)
+ end
+ def fileList_edit(w, i, s, e)
+ tk_call('::TreeCtrl::FileListEdit', w, i, s, e)
+ end
+ def fileList_editCancel(w)
+ tk_call('::TreeCtrl::FileListEditCancel', w)
+ end
+ def fileList_autoScanCheck(w, x, y)
+ tk_call('::TreeCtrl::FileListAutoScanCheck', w, x, y)
+ end
+ def fileList_autoScanCheckAux(w)
+ tk_call('::TreeCtrl::FileListAutoScanCheckAux', w)
+ end
+
+ def entryOpen(w, item, col, elem)
+ tk_call('::TreeCtrl::EntryOpen', w, item, col, elem)
+ end
+ def entryExpanderOpen(w, item, col, elem)
+ tk_call('::TreeCtrl::EntryExpanderOpen', w, item, col, elem)
+ end
+ def entryClose(w, accept)
+ tk_call('::TreeCtrl::EntryClose', w, accept)
+ end
+ def entryExpanderKeypress(w)
+ tk_call('::TreeCtrl::EntryExpanderKeypress', w)
+ end
+ def textOpen(w, item, col, elem, width=0, height=0)
+ tk_call('::TreeCtrl::TextOpen', w, item, col, elem, width, height)
+ end
+ def textExpanderOpen(w, item, col, elem, width)
+ tk_call('::TreeCtrl::TextOpen', w, item, col, elem, width)
+ end
+ def textClose(w, accept)
+ tk_call('::TreeCtrl::TextClose', w, accept)
+ end
+ def textExpanderKeypress(w)
+ tk_call('::TreeCtrl::TextExpanderKeypress', w)
+ end
+end
diff --git a/ext/tk/lib/tkextlib/trofs.rb b/ext/tk/lib/tkextlib/trofs.rb
new file mode 100644
index 0000000000..5914e5165f
--- /dev/null
+++ b/ext/tk/lib/tkextlib/trofs.rb
@@ -0,0 +1,13 @@
+#
+# trofs support
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+# call setup script for general 'tkextlib' libraries
+require 'tkextlib/setup.rb'
+
+# call setup script
+require 'tkextlib/trofs/setup.rb'
+
+# load library
+require 'tkextlib/trofs/trofs.rb'
diff --git a/ext/tk/lib/tkextlib/trofs/setup.rb b/ext/tk/lib/tkextlib/trofs/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/trofs/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/trofs/trofs.rb b/ext/tk/lib/tkextlib/trofs/trofs.rb
new file mode 100644
index 0000000000..7a2606a275
--- /dev/null
+++ b/ext/tk/lib/tkextlib/trofs/trofs.rb
@@ -0,0 +1,51 @@
+#
+# tkextlib/trofs/trofs.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 'tkextlib/trofs/setup.rb'
+
+# TkPackage.require('trofs', '0.4')
+TkPackage.require('trofs')
+
+module Tk
+ module Trofs
+ extend TkCore
+
+ PACKAGE_NAME = 'trofs'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('trofs')
+ rescue
+ ''
+ end
+ end
+
+ ##############################################
+
+ def self.create_archive(dir, archive)
+ tk_call('::trofs::archive', dir, archive)
+ archive
+ end
+
+ def self.mount(archive, mountpoint=None)
+ # returns the normalized path to mountpoint
+ tk_call('::trofs::mount', archive, mountpoint)
+ end
+
+ def self.umount(mountpoint)
+ tk_call('::trofs::umount', mountpoint)
+ mountpoint
+ end
+ end
+end
diff --git a/ext/tk/lib/tkextlib/version.rb b/ext/tk/lib/tkextlib/version.rb
new file mode 100644
index 0000000000..434ed11a2e
--- /dev/null
+++ b/ext/tk/lib/tkextlib/version.rb
@@ -0,0 +1,6 @@
+#
+# release date of tkextlib
+#
+module Tk
+ Tkextlib_RELEASE_DATE = '2008-05-23'.freeze
+end
diff --git a/ext/tk/lib/tkextlib/vu.rb b/ext/tk/lib/tkextlib/vu.rb
new file mode 100644
index 0000000000..d2234eb2a8
--- /dev/null
+++ b/ext/tk/lib/tkextlib/vu.rb
@@ -0,0 +1,48 @@
+#
+# 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'
+
+# call setup script
+require 'tkextlib/vu/setup.rb'
+
+# load package
+# TkPackage.require('vu', '2.1')
+TkPackage.require('vu')
+
+# autoload
+module Tk
+ module Vu
+ TkComm::TkExtlibAutoloadModule.unshift(self)
+
+ PACKAGE_NAME = 'vu'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('vu')
+ rescue
+ ''
+ end
+ end
+
+ ##########################################
+
+ autoload :Dial, 'tkextlib/vu/dial'
+
+ autoload :Pie, 'tkextlib/vu/pie'
+ autoload :PieSlice, 'tkextlib/vu/pie'
+ autoload :NamedPieSlice, 'tkextlib/vu/pie'
+
+ autoload :Spinbox, 'tkextlib/vu/spinbox'
+
+ autoload :Bargraph, 'tkextlib/vu/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..27ff3c7cd0
--- /dev/null
+++ b/ext/tk/lib/tkextlib/vu/bargraph.rb
@@ -0,0 +1,61 @@
+#
+# ::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 -- <libdir>/tkextlib/vu.rb
+require 'tkextlib/vu.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 __strval_optkeys
+ super() + [
+ 'title',
+ 'barbackground', 'barcolor', 'barcolour',
+ 'tickcolor', 'tickcolour',
+ 'textcolor', 'textcolour',
+ ]
+ end
+ private :__strval_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..ee4298fa1c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/vu/charts.rb
@@ -0,0 +1,53 @@
+#
+# charts -- Create and manipulate canvas Add-On Items
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tk/canvas'
+
+# call setup script -- <libdir>/tkextlib/vu.rb
+require 'tkextlib/vu.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_strval_optkeys(id)
+ super(id) << 'bar' << 'color' << 'outline' <<
+ 'fill' << 'scaleline' << 'stripline'
+ end
+ private :__item_strval_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..e27a38ae42
--- /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 -- <libdir>/tkextlib/vu.rb
+require 'tkextlib/vu.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..c1fb6857bf
--- /dev/null
+++ b/ext/tk/lib/tkextlib/vu/pie.rb
@@ -0,0 +1,282 @@
+#
+# ::vu::pie widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+
+# 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 -- <libdir>/tkextlib/vu.rb
+require 'tkextlib/vu.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
+
+ def __destroy_hook__
+ Tk::Vu::PieSlice::SliceID_TBL.delete(@path)
+ end
+
+ ###############################
+
+ include Tk::Vu::PieSliceConfigMethod
+
+ def tagid(tag)
+ if tag.kind_of?(Tk::Vu::PieSlice)
+ tag.id
+ else
+ # tag
+ _get_eval_string(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]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ SliceID_TBL.mutex.synchronize{ SliceID_TBL.clear }
+ }
+
+ def self.id2obj(pie, id)
+ pie_path = pie.path
+ SliceID_TBL.mutex.synchronize{
+ if SliceID_TBL[pie_path]
+ SliceID_TBL[pie_path][id]? SliceID_TBL[pie_path][id]: id
+ else
+ id
+ end
+ }
+ end
+
+ def initialize(parent, *args)
+ unless parent.kind_of?(Tk::Vu::Pie)
+ fail ArgumentError, "expect a Tk::Vu::Pie instance for 1st argument"
+ end
+ @parent = @pie = parent
+ @ppath = parent.path
+ Pie_Slice_ID.mutex.synchronize{
+ @path = @id = Pie_Slice_ID.join(TkCore::INTERP._ip_id_)
+ Pie_Slice_ID[1].succ!
+ }
+ SliceID_TBL.mutex.synchronize{
+ 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
+
+ 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 cget_strict(slot)
+ @pie.itemcget_strict(@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)
+ obj = nil
+ SliceID_TBL.mutex.synchronize{
+ if SliceID_TBL[parent.path] && SliceID_TBL[parent.path][name]
+ obj = SliceID_TBL[parent.path][name]
+ else
+ #super(parent, name, *args)
+ unless parent.kind_of?(Tk::Vu::Pie)
+ fail ArgumentError, "expect a Tk::Vu::Pie instance for 1st argument"
+ end
+ obj = self.allocate
+ obj.instance_eval{
+ @parent = @pie = parent
+ @ppath = parent.path
+ @path = @id = name.to_s
+ SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath]
+ SliceID_TBL[@ppath][@id] = self
+ }
+ end
+ }
+ obj.instance_eval{
+ if args[-1].kind_of?(Hash)
+ keys = args.unshift
+ end
+ @pie.set(@id, *args)
+ configure(keys)
+ }
+
+ obj
+ end
+
+ def initialize(parent, name, *args)
+ # dummy:: not called by 'new' method
+ unless parent.kind_of?(Tk::Vu::Pie)
+ fail ArgumentError, "expect a Tk::Vu::Pie instance for 1st argument"
+ end
+ @parent = @pie = parent
+ @ppath = parent.path
+ @path = @id = name.to_s
+ SliceID_TBL.mutex.synchronize{
+ 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..a7e40ea319
--- /dev/null
+++ b/ext/tk/lib/tkextlib/vu/spinbox.rb
@@ -0,0 +1,22 @@
+#
+# ::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.
+#
+require 'tk'
+
+if (Tk::TK_MAJOR_VERSION < 8 ||
+ (Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION < 4))
+ # call setup script -- <libdir>/tkextlib/vu.rb
+ require 'tkextlib/vu.rb'
+
+ Tk.tk_call('namespace', 'import', '::vu::spinbox')
+end
+
+module Tk
+ module Vu
+ Spinbox = Tk::Spinbox
+ end
+end
diff --git a/ext/tk/lib/tkextlib/winico.rb b/ext/tk/lib/tkextlib/winico.rb
new file mode 100644
index 0000000000..ce7b8eac5c
--- /dev/null
+++ b/ext/tk/lib/tkextlib/winico.rb
@@ -0,0 +1,14 @@
+#
+# winico -- Windows Icon extension support
+# 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 'tkextlib/tktable/setup.rb'
+
+# load library
+require 'tkextlib/winico/winico'
diff --git a/ext/tk/lib/tkextlib/winico/setup.rb b/ext/tk/lib/tkextlib/winico/setup.rb
new file mode 100644
index 0000000000..ce0f0bd4d4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/winico/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/winico/winico.rb b/ext/tk/lib/tkextlib/winico/winico.rb
new file mode 100644
index 0000000000..00316fd441
--- /dev/null
+++ b/ext/tk/lib/tkextlib/winico/winico.rb
@@ -0,0 +1,224 @@
+#
+# tkextlib/winico/winico.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 'tkextlib/winico/setup.rb'
+
+# TkPackage.require('winico', '0.5')
+# TkPackage.require('winico', '0.6')
+TkPackage.require('winico')
+
+module Tk
+ class Winico < TkObject
+ PACKAGE_NAME = 'winico'.freeze
+ def self.package_name
+ PACKAGE_NAME
+ end
+
+ def self.package_version
+ begin
+ TkPackage.require('winico')
+ rescue
+ ''
+ end
+ end
+ end
+end
+
+class Tk::Winico
+ WinicoID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ WinicoID_TBL.mutex.synchronize{ WinicoID_TBL.clear }
+ }
+
+ def self.id2obj(id)
+ WinicoID_TBL.mutex.synchronize{
+ (WinicoID_TBL.key?(id))? WinicoID_TBL[id] : id
+ }
+ end
+
+ def self.info
+ simplelist(Tk.tk_call('winico', 'info')).collect{|id|
+ Tk::Winico.id2obj(id)
+ }
+ end
+
+ def self.icon_info(id)
+ simplelist(Tk.tk_call('winico', 'info', id)).collect{|inf|
+ h = Hash[*list(inf)]
+ h.keys.each{|k| h[k[1..-1]] = h.delete(k)}
+ }
+ end
+
+ #################################
+
+ def self.new_from_file(file_name)
+ self.new(file_name)
+ end
+
+ def self.new_from_resource(resource_name, file_name = nil)
+ self.new(file_name, resource_name)
+ end
+
+ def initialize(file_name, resource_name=nil, winico_id=nil)
+ if resource_name
+ # from resource
+ if file_name
+ @id = Tk.tk_call('winico', 'load', resource_name, file_name)
+ else
+ @id = Tk.tk_call('winico', 'load', resource_name)
+ end
+ elsif file_name
+ # from .ico file
+ @id = Tk.tk_call('winico', 'createfrom', file_name)
+ elsif winico_id
+ @id = winico_id
+ else
+ fail ArgumentError,
+ "must be given proper information from where loading icons"
+ end
+ @path = @id
+ WinicoID_TBL.mutex.synchronize{
+ WinicoID_TBL[@id] = self
+ }
+ end
+
+ def id
+ @id
+ end
+
+ def set_window(win_id, *opts) # opts := ?'big'|'small'?, ?pos?
+ # NOTE:: the window, which is denoted by win_id, MUST BE MAPPED.
+ # If not, then this may fail or crash.
+ tk_call('winico', 'setwindow', win_id, @id, *opts)
+ end
+
+ def delete
+ tk_call('winico', 'delete', @id)
+ WinicoID_TBL.mutex.synchronize{
+ WinicoID_TBL.delete(@id)
+ }
+ self
+ end
+ alias destroy delete
+
+ def info
+ Tk::Winico.icon_info(@id)
+ end
+
+ #################################
+
+ class Winico_callback < TkValidateCommand
+ class ValidateArgs < TkUtil::CallbackSubst
+ KEY_TBL = [
+ [ ?m, ?s, :message ],
+ [ ?i, ?x, :icon ],
+ [ ?x, ?n, :x ],
+ [ ?y, ?n, :y ],
+ [ ?X, ?n, :last_x ],
+ [ ?Y, ?n, :last_y ],
+ [ ?t, ?n, :tickcount ],
+ [ ?w, ?n, :icon_idnum ],
+ [ ?l, ?n, :msg_idnum ],
+ nil
+ ]
+
+ PROC_TBL = [
+ [ ?n, TkComm.method(:number) ],
+ [ ?s, TkComm.method(:string) ],
+ [ ?x, proc{|id|
+ Tk::Winico::WinicoID_TBL.mutex.synchronize{
+ if Tk::Winico::WinicoID_TBL.key?(id)
+ obj = Tk::Winico::WinicoID_TBL[id]
+ else
+ # Tk::Winico.new(nil, nil, id)
+ obj = Tk::Winico.allocate
+ obj.instance_eval{ @path = @id = id }
+ Tk::Winico::WinicoID_TBL[id] = obj
+ end
+ obj
+ }
+ } ],
+ nil
+ ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
+ _setup_subst_table(KEY_TBL, PROC_TBL);
+
+ def self.ret_val(val)
+ val
+ end
+ end
+
+ def self._config_keys
+ ['callback']
+ end
+ end
+
+ #################################
+
+ def add_to_taskbar(keys = {})
+ keys = _symbolkey2str(keys)
+ Winico_callback._config_keys.each{|k|
+ if keys[k].kind_of?(Array)
+ cmd, *args = keys[k]
+ #keys[k] = Winico_callback.new(cmd, args.join(' '))
+ keys[k] = Winico_callback.new(cmd, *args)
+ # elsif keys[k].kind_of?(Proc)
+ elsif TkComm._callback_entry?(keys[k])
+ keys[k] = Winico_callback.new(keys[k])
+ end
+ }
+ tk_call('winico', 'taskbar', 'add', @id, *(hash_kv(keys)))
+ self
+ end
+ alias taskbar_add add_to_taskbar
+
+ def modify_taskbar(keys = {})
+ keys = _symbolkey2str(keys)
+ Winico_callback._config_keys.each{|k|
+ if keys[k].kind_of?(Array)
+ cmd, *args = keys[k]
+ #keys[k] = Winico_callback.new(cmd, args.join(' '))
+ keys[k] = Winico_callback.new(cmd, *args)
+ # elsif keys[k].kind_of?(Proc)
+ elsif TkComm._callback_entry?(keys[k])
+ keys[k] = Winico_callback.new(keys[k])
+ end
+ }
+ tk_call('winico', 'taskbar', 'modify', @id, *(hash_kv(keys)))
+ self
+ end
+ alias taskbar_modify modify_taskbar
+
+ def delete_from_taskbar
+ tk_call('winico', 'taskbar', 'delete', @id)
+ self
+ end
+ alias taskbar_delete delete_from_taskbar
+end
diff --git a/ext/tk/lib/tkfont.rb b/ext/tk/lib/tkfont.rb
index ff7bbc74e4..38a96633de 100644
--- a/ext/tk/lib/tkfont.rb
+++ b/ext/tk/lib/tkfont.rb
@@ -1,1390 +1,4 @@
#
-# tkfont.rb - the class to treat fonts on Ruby/Tk
+# tkfont.rb - load tk/font.rb
#
-# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
-#
-require 'tk'
-
-class TkFont
- include Tk
- extend TkCore
-
- TkCommandNames = ['font'.freeze].freeze
-
- Tk_FontID = ["@font".freeze, "00000".taint].freeze
- Tk_FontNameTBL = TkCore::INTERP.create_table
- Tk_FontUseTBL = TkCore::INTERP.create_table
-
- TkCore::INTERP.init_ip_env{
- Tk_FontNameTBL.clear
- Tk_FontUseTBL.clear
- }
-
- # set default font
- case Tk::TK_VERSION
- when /^4\.*/
- DEFAULT_LATIN_FONT_NAME = 'a14'.freeze
- DEFAULT_KANJI_FONT_NAME = 'k14'.freeze
-
- when /^8\.*/
- if JAPANIZED_TK
- begin
- fontnames = tk_call('font', 'names')
- case fontnames
- when /defaultgui/
- # Tcl/Tk-JP for Windows
- ltn = 'defaultgui'
- knj = 'defaultgui'
- when /Mincho:Helvetica-Bold-12/
- # Tcl/Tk-JP for UNIX/X
- ltn, knj = tk_split_simplelist(tk_call('font', 'configure',
- 'Mincho:Helvetica-Bold-12',
- '-compound'))
- else
- # unknown Tcl/Tk-JP
- platform = tk_call('set', 'tcl_platform(platform)')
- case platform
- 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
- end
- rescue
- ltn = 'Helvetica'
- knj = 'mincho'
- end
-
- else # not JAPANIZED_TK
- begin
- platform = tk_call('set', 'tcl_platform(platform)')
- case platform
- 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
- end
-
- DEFAULT_LATIN_FONT_NAME = ltn.freeze
- DEFAULT_KANJI_FONT_NAME = knj.freeze
-
- else # unknown version
- DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze
- DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze
-
- end
-
- if $DEBUG
- print "default latin font = "; p DEFAULT_LATIN_FONT_NAME
- print "default kanji font = "; p DEFAULT_KANJI_FONT_NAME
- end
-
-
- ###################################
- class DescendantFont
- def initialize(compound, type)
- unless compound.kind_of?(TkFont)
- fail ArgumentError, "a TkFont object is expected for the 1st argument"
- end
- @compound = compound
- case type
- when 'kanji', 'latin', 'ascii'
- @type = type
- else
- fail ArgumentError, "unknown type '#{type}'"
- end
- end
-
- def dup
- fail RuntimeError, "cannot dupulicate a descendant font"
- end
- def clone
- fail RuntimeError, "cannot clone a descendant font"
- end
-
- def to_eval
- @compound.__send__(@type + '_font_id')
- end
- def font
- @compound.__send__(@type + '_font_id')
- end
-
- def [](slot)
- @compound.__send__(@type + '_configinfo', slot)
- end
- def []=(slot, value=None)
- @compound.__send__(@type + '_configure', slot, value)
- end
-
- def method_missing(id, *args)
- @compound.__send__(@type + '_' + id.id2name, *args)
- end
- end
-
-
- ###################################
- # class methods
- ###################################
- def TkFont.families(window=nil)
- case (Tk::TK_VERSION)
- when /^4\.*/
- ['fixed']
-
- when /^8\.*/
- if window
- tk_split_simplelist(tk_call('font', 'families', '-displayof', window))
- else
- tk_split_simplelist(tk_call('font', 'families'))
- end
- end
- end
-
- def TkFont.names
- case (Tk::TK_VERSION)
- when /^4\.*/
- r = ['fixed']
- r += ['a14', 'k14'] if JAPANIZED_TK
- Tk_FontNameTBL.each_value{|obj| r.push(obj)}
- r | []
-
- when /^8\.*/
- tk_split_simplelist(tk_call('font', 'names'))
-
- end
- end
-
- def TkFont.create_copy(font)
- fail 'source-font must be a TkFont object' unless font.kind_of? TkFont
- keys = {}
- font.configinfo.each{|key,value| keys[key] = value }
- TkFont.new(font.latin_font_id, font.kanji_font_id, keys)
- end
-
- def TkFont.get_obj(name)
- if name =~ /^(@font[0-9]+)(|c|l|k)$/
- Tk_FontNameTBL[$1]
- else
- nil
- end
- end
-
- def TkFont.init_widget_font(path, *args)
- case (Tk::TK_VERSION)
- when /^4\.*/
- conf = tk_split_simplelist(tk_call(*args)).
- find_all{|prop| prop[0..5]=='-font ' || prop[0..10]=='-kanjifont '}.
- 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'"
- 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 + [{}]))
-
- when /^8\.*/
- font_prop = tk_split_simplelist(tk_call(*args)).find{|prop|
- prop[0..5] == '-font '
- }
- unless font_prop
- raise RuntimeError, "unknown option '-font'"
- end
- fnt = tk_split_simplelist(font_prop)[4]
- if fnt == ""
- TkFont.new(nil, nil).call_font_configure(path, *(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])
- 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 + [{}]))
- else
- TkFont.new(compound[0], compound[1]) \
- .call_font_configure(path, *(args + [{}]))
- end
- end
- end
- end
-
- def TkFont.used_on(path=nil)
- if path
- Tk_FontUseTBL[path]
- else
- Tk_FontUseTBL.values | []
- end
- end
-
- def TkFont.failsafe(font)
- begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
- tk_call('font', 'failsafe', font)
- end
- rescue
- end
- end
-
- ###################################
- # instance methods
- ###################################
- private
- ###################################
- def initialize(ltn=nil, knj=nil, keys=nil)
- @id = Tk_FontID.join
- Tk_FontID[1].succ!
- Tk_FontNameTBL[@id] = self
-
- @latin_desscendant = nil
- @kanji_desscendant = nil
-
- if knj.kind_of?(Hash) && !keys
- keys = knj
- knj = nil
- end
-
- # compound font check
- if Tk::TK_VERSION == '8.0' && JAPANIZED_TK
- begin
- compound = tk_split_simplelist(tk_call('font', 'configure',
- ltn, '-compound'))
- if knj == nil
- if compound != []
- ltn, knj = compound
- end
- else
- if compound != []
- ltn = compound[0]
- end
- compound = tk_split_simplelist(tk_call('font', 'configure',
- knj, '-compound'))
- if compound != []
- knj = compound[1]
- end
- end
- rescue
- end
- end
-
- if ltn
- knj = ltn if JAPANIZED_TK && !knj
- else
- ltn = DEFAULT_LATIN_FONT_NAME
- knj = DEFAULT_KANJI_FONT_NAME if JAPANIZED_TK && !knj
- end
-
- create_compoundfont(ltn, knj, keys)
- end
-
- def _get_font_info_from_hash(font)
- font = _symbolkey2str(font)
- foundry = (info = font['foundry'] .to_s)? info: '*'
- family = (info = font['family'] .to_s)? info: '*'
- weight = (info = font['weight'] .to_s)? info: '*'
- slant = (info = font['slant'] .to_s)? info: '*'
- swidth = (info = font['swidth'] .to_s)? info: '*'
- adstyle = (info = font['adstyle'] .to_s)? info: '*'
- pixels = (info = font['pixels'] .to_s)? info: '*'
- points = (info = font['points'] .to_s)? info: '*'
- resx = (info = font['resx'] .to_s)? info: '*'
- resy = (info = font['resy'] .to_s)? info: '*'
- space = (info = font['space'] .to_s)? info: '*'
- avgWidth = (info = font['avgWidth'].to_s)? info: '*'
- charset = (info = font['charset'] .to_s)? info: '*'
- encoding = (info = font['encoding'].to_s)? info: '*'
-
- [foundry, family, weight, slant, swidth, adstyle,
- pixels, points, resx, resy, space, avgWidth, charset, encoding]
- end
-
- def create_latinfont_tk4x(font)
- if font.kind_of? Hash
- @latinfont = '-' + _get_font_info_from_hash(font).join('-') + '-'
-
- elsif font.kind_of? Array
- finfo = {}
- finfo['family'] = font[0].to_s
- if font[1]
- fsize = font[1].to_s
- if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
- if $1 == '-'
- finfo['pixels'] = $2
- else
- finfo['points'] = $2
- end
- else
- finfo['points'] = '13'
- end
- end
- font[2..-1].each{|style|
- case (style)
- when 'normal'
- finfo['weight'] = style
- when 'bold'
- finfo['weight'] = style
- when 'roman'
- finfo['slant'] = 'r'
- when 'italic'
- finfo['slant'] = 'i'
- end
- }
-
- @latinfont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
-
- elsif font.kind_of? TkFont
- @latinfont = font.latin_font
-
- else
- if font
- @latinfont = font
- else
- @latinfont = DEFAULT_LATIN_FONT_NAME
- end
-
- end
- end
-
- def create_kanjifont_tk4x(font)
- unless JAPANIZED_TK
- @kanjifont = ""
- return
- end
-
- if font.kind_of? Hash
- @kanjifont = '-' + _get_font_info_from_hash(font).join('-') + '-'
-
- elsif font.kind_of? Array
- finfo = {}
- finfo['family'] = font[0].to_s
- if font[1]
- fsize = font[1].to_s
- if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
- if $1 == '-'
- finfo['pixels'] = $2
- else
- finfo['points'] = $2
- end
- else
- finfo['points'] = '13'
- end
- end
- font[2..-1].each{|style|
- case (style)
- when 'normal'
- finfo['weight'] = style
- when 'bold'
- finfo['weight'] = style
- when 'roman'
- finfo['slant'] = 'r'
- when 'italic'
- finfo['slant'] = 'i'
- end
- }
-
- @kanjifont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
- elsif font.kind_of? TkFont
- @kanjifont = font.kanji_font_id
- else
- if font
- @kanjifont = font
- else
- @kanjifont = DEFAULT_KANJI_FONT_NAME
- end
- end
- end
-
- def create_compoundfont_tk4x(ltn, knj, keys)
- create_latinfont(ltn)
- create_kanjifont(knj)
-
- if JAPANIZED_TK
- @compoundfont = [[@latinfont], [@kanjifont]]
- @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont}
- else
- @compoundfont = @latinfont
- @fontslot = {'font'=>@latinfont}
- end
- end
-
- def create_latinfont_tk8x(font)
- @latinfont = @id + 'l'
-
- if JAPANIZED_TK
- if font.kind_of? Hash
- if font[:charset] || font['charset']
- tk_call('font', 'create', @latinfont, *hash_kv(font))
- else
- tk_call('font', 'create', @latinfont,
- '-charset', 'iso8859', *hash_kv(font))
- end
- elsif font.kind_of? Array
- tk_call('font', 'create', @latinfont, '-copy', array2tk_list(font))
- tk_call('font', 'configure', @latinfont, '-charset', 'iso8859')
- elsif font.kind_of? TkFont
- tk_call('font', 'create', @latinfont, '-copy', font.latin_font)
- elsif font
- tk_call('font', 'create', @latinfont, '-copy', font,
- '-charset', 'iso8859')
- else
- tk_call('font', 'create', @latinfont, '-charset', 'iso8859')
- end
- else
- if font.kind_of? Hash
- tk_call('font', 'create', @latinfont, *hash_kv(font))
- else
- keys = {}
- if font.kind_of? Array
- actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
- elsif font.kind_of? TkFont
- actual_core(font.latin_font).each{|key,val| keys[key] = val}
- elsif font
- actual_core(font).each{|key,val| keys[key] = val}
- end
- tk_call('font', 'create', @latinfont, *hash_kv(keys))
- end
-
- if font && @compoundfont
- keys = {}
- actual_core(@latinfont).each{|key,val| keys[key] = val}
- tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
- end
- end
- end
-
- def create_kanjifont_tk8x(font)
- @kanjifont = @id + 'k'
-
- if JAPANIZED_TK
- if font.kind_of? Hash
- if font[:charset] || font['charset']
- tk_call('font', 'create', @kanjifont, *hash_kv(font))
- else
- tk_call('font', 'create', @kanjifont,
- '-charset', 'jisx0208.1983', *hash_kv(font))
- end
- elsif font.kind_of? Array
- tk_call('font', 'create', @kanjifont, '-copy', array2tk_list(font))
- tk_call('font', 'configure', @kanjifont, '-charset', 'jisx0208.1983')
- elsif font.kind_of? TkFont
- tk_call('font', 'create', @kanjifont, '-copy', font.kanji_font_id)
- elsif font
- tk_call('font', 'create', @kanjifont, '-copy', font,
- '-charset', 'jisx0208.1983')
- else
- tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983')
- end
- # end of JAPANIZED_TK
-
- else
- if font.kind_of? Hash
- tk_call('font', 'create', @kanjifont, *hash_kv(font))
- else
- keys = {}
- if font.kind_of? Array
- actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
- elsif font.kind_of? TkFont
- actual_core(font.kanji_font_id).each{|key,val| keys[key] = val}
- elsif font
- actual_core(font).each{|key,val| keys[key] = val}
- end
- tk_call('font', 'create', @kanjifont, *hash_kv(keys))
- end
-
- if font && @compoundfont
- keys = {}
- actual_core(@kanjifont).each{|key,val| keys[key] = val}
- tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
- end
- end
- end
-
- def create_compoundfont_tk8x(ltn, knj, keys)
- create_latinfont(ltn)
- create_kanjifont(knj)
-
- @compoundfont = @id + 'c'
- if JAPANIZED_TK
- unless keys
- keys = {}
- else
- keys = keys.dup
- end
- if (tk_call('font', 'configure', @latinfont, '-underline') == '1' &&
- tk_call('font', 'configure', @kanjifont, '-underline') == '1' &&
- !keys.key?('underline'))
- keys['underline'] = true
- end
- if (tk_call('font', 'configure', @latinfont, '-overstrike') == '1' &&
- tk_call('font', 'configure', @kanjifont, '-overstrike') == '1' &&
- !keys.key?('overstrike'))
- keys['overstrike'] = true
- end
-
- @fontslot = {'font'=>@compoundfont}
- begin
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
- rescue RuntimeError => e
- if ltn == knj
- if e.message =~ /kanji font .* specified/
- tk_call('font', 'delete', @latinfont)
- create_latinfont(DEFAULT_LATIN_FONT_NAME)
- opts = []
- Hash[*(tk_split_simplelist(tk_call('font', 'configure',
- @kanjifont)))].each{|k,v|
- case k
- when '-size', '-weight', '-slant', '-underline', '-overstrike'
- opts << k << v
- end
- }
- tk_call('font', 'configure', @latinfont, *opts)
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
-
- elsif e.message =~ /ascii font .* specified/
- tk_call('font', 'delete', @kanjifont)
- create_kanjifont(DEFAULT_KANJI_FONT_NAME)
- opts = []
- Hash[*(tk_split_simplelist(tk_call('font', 'configure',
- @latinfont)))].each{|k,v|
- case k
- when '-size', '-weight', '-slant', '-underline', '-overstrike'
- opts << k << v
- end
- }
- tk_call('font', 'configure', @kanjifont, *opts)
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
-
- else
- raise e
- end
- else
- raise e
- end
- end
- else
- tk_call('font', 'create', @compoundfont)
-
- latinkeys = {}
- begin
- actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
- rescue
- latinkeys {}
- end
- if latinkeys != {}
- tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
- end
-
- if knj
- kanjikeys = {}
- begin
- actual_core(@kanjifont).each{|key,val| kanjikeys[key] = val}
- rescue
- kanjikeys {}
- end
- if kanjikeys != {}
- tk_call('font', 'configure', @compoundfont, *hash_kv(kanjikeys))
- end
- end
-
- @fontslot = {'font'=>@compoundfont}
- tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
- end
- end
-
- def actual_core_tk4x(font, window=nil, option=nil)
- # dummy
- if option
- ""
- else
- [['family',[]], ['size',[]], ['weight',[]], ['slant',[]],
- ['underline',[]], ['overstrike',[]], ['charset',[]],
- ['pointadjust',[]]]
- end
- end
-
- def actual_core_tk8x(font, window=nil, option=nil)
- if option == 'compound'
- ""
- elsif option
- if window
- tk_call('font', 'actual', font, "-displayof", window, "-#{option}")
- else
- tk_call('font', 'actual', font, "-#{option}")
- end
- else
- l = tk_split_simplelist(if window
- tk_call('font', 'actual', font,
- "-displayof", window)
- else
- tk_call('font', 'actual', font)
- end)
- r = []
- while key=l.shift
- if key == '-compound'
- l.shift
- else
- r.push [key[1..-1], l.shift]
- end
- end
- r
- end
- end
-
- def configure_core_tk4x(font, slot, value=None)
- #""
- self
- end
-
- def configinfo_core_tk4x(font, option=nil)
- # dummy
- if option
- ""
- else
- [['family',[]], ['size',[]], ['weight',[]], ['slant',[]],
- ['underline',[]], ['overstrike',[]], ['charset',[]],
- ['pointadjust',[]]]
- end
- end
-
- def configure_core_tk8x(font, slot, value=None)
- if JAPANIZED_TK
- begin
- padjust = tk_call('font', 'configure', font, '-pointadjust')
- rescue
- padjust = nil
- end
- else
- padjust = nil
- end
- if slot.kind_of? Hash
- if JAPANIZED_TK && (slot.key?('family') || slot.key?(:family))
- slot = _symbolkey2str(slot)
- configure_core_tk8x(font, 'family', slot.delete('family'))
- end
-
- if ((slot.key?('size') || slot.key?(:size)) &&
- padjust && !slot.key?('pointadjust') && !slot.key?(:pointadjust))
- tk_call('font', 'configure', font,
- '-pointadjust', padjust, *hash_kv(slot))
- else
- tk_call('font', 'configure', font, *hash_kv(slot))
- end
- elsif (slot == 'size' || slot == :size) && padjust != nil
- tk_call('font', 'configure', font,
- "-#{slot}", value, '-pointadjust', padjust)
- elsif JAPANIZED_TK && (slot == 'family' || slot == :family)
- # coumpund font?
- begin
- compound = tk_split_simplelist(tk_call('font', 'configure',
- font, '-compound'))
- rescue
- tk_call('font', 'configure', font, '-family', value)
- return self
- end
- if compound == []
- tk_call('font', 'configure', font, '-family', value)
- return self
- end
- ltn, knj = compound
-
- lfnt = tk_call('font', 'create', '-copy', ltn)
- begin
- tk_call('font', 'configure', lfnt, '-family', value)
- latin_replace_core_tk8x(lfnt)
- rescue RuntimeError => e
- fail e if $DEBUG
- ensure
- tk_call('font', 'delete', lfnt) if lfnt != ''
- end
-
- kfnt = tk_call('font', 'create', '-copy', knj)
- begin
- tk_call('font', 'configure', kfnt, '-family', value)
- kanji_replace_core_tk8x(lfnt)
- rescue RuntimeError => e
- fail e if $DEBUG
- ensure
- tk_call('font', 'delete', kfnt) if kfnt != ''
- end
-
- else
- tk_call('font', 'configure', font, "-#{slot}", value)
- end
- self
- end
-
- def configinfo_core_tk8x(font, option=nil)
- if option == 'compound'
- ""
- elsif option
- tk_call('font', 'configure', font, "-#{option}")
- else
- l = tk_split_simplelist(tk_call('font', 'configure', font))
- r = []
- while key=l.shift
- if key == '-compound'
- l.shift
- else
- r.push [key[1..-1], l.shift]
- end
- end
- r
- end
- end
-
- def delete_core_tk4x
- Tk_FontNameTBL.delete(@id)
- Tk_FontUseTBL.delete_if{|key,value| value == self}
- end
-
- def delete_core_tk8x
- begin
- tk_call('font', 'delete', @latinfont)
- rescue
- end
- begin
- tk_call('font', 'delete', @kanjifont)
- rescue
- end
- begin
- tk_call('font', 'delete', @compoundfont)
- rescue
- end
- Tk_FontNameTBL.delete(@id)
- Tk_FontUseTBL.delete_if{|key,value| value == self}
- end
-
- def latin_replace_core_tk4x(ltn)
- create_latinfont_tk4x(ltn)
- @compoundfont[0] = [@latinfont] if JAPANIZED_TK
- @fontslot['font'] = @latinfont
- Tk_FontUseTBL.dup.each{|w, fobj|
- if self == fobj
- begin
- if w.include?(';')
- win, tag = w.split(';')
- winobj = tk_tcl2ruby(win)
-# winobj.tagfont_configure(tag, {'font'=>@latinfont})
- if winobj.kind_of? TkText
- tk_call(win, 'tag', 'configure', tag, '-font', @latinfont)
- elsif winobj.kind_of? TkCanvas
- tk_call(win, 'itemconfigure', tag, '-font', @latinfont)
- elsif winobj.kind_of? TkMenu
- tk_call(win, 'entryconfigure', tag, '-font', @latinfont)
- else
- raise RuntimeError, "unknown widget type"
- end
- else
-# tk_tcl2ruby(w).font_configure('font'=>@latinfont)
- tk_call(w, 'configure', '-font', @latinfont)
- end
- rescue
- Tk_FontUseTBL.delete(w)
- end
- end
- }
- self
- end
-
- def kanji_replace_core_tk4x(knj)
- return self unless JAPANIZED_TK
-
- create_kanjifont_tk4x(knj)
- @compoundfont[1] = [@kanjifont]
- @fontslot['kanjifont'] = @kanjifont
- Tk_FontUseTBL.dup.each{|w, fobj|
- if self == fobj
- begin
- if w.include?(';')
- win, tag = w.split(';')
- winobj = tk_tcl2ruby(win)
-# winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont})
- if winobj.kind_of? TkText
- tk_call(win, 'tag', 'configure', tag, '-kanjifont', @kanjifont)
- elsif winobj.kind_of? TkCanvas
- tk_call(win, 'itemconfigure', tag, '-kanjifont', @kanjifont)
- elsif winobj.kind_of? TkMenu
- tk_call(win, 'entryconfigure', tag, '-kanjifont', @latinfont)
- else
- raise RuntimeError, "unknown widget type"
- end
- else
-# tk_tcl2ruby(w).font_configure('kanjifont'=>@kanjifont)
- tk_call(w, 'configure', '-kanjifont', @kanjifont)
- end
- rescue
- Tk_FontUseTBL.delete(w)
- end
- end
- }
- self
- end
-
- def latin_replace_core_tk8x(ltn)
- if JAPANIZED_TK
- begin
- tk_call('font', 'delete', '@font_tmp')
- rescue
- end
- begin
- fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @latinfont)
- rescue
- #fnt_bup = ''
- fnt_bup = DEFAULT_LATIN_FONT_NAME
- end
- end
-
- begin
- tk_call('font', 'delete', @latinfont)
- rescue
- end
- create_latinfont(ltn)
-
- if JAPANIZED_TK
- keys = self.configinfo
- tk_call('font', 'delete', @compoundfont)
- begin
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
-=begin
- latinkeys = {}
- begin
- actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
- rescue
- latinkeys {}
- end
- if latinkeys != {}
- tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
- end
-=end
- rescue RuntimeError => e
- tk_call('font', 'delete', @latinfont)
- if fnt_bup && fnt_bup != ''
- tk_call('font', 'create', @latinfont, '-copy', fnt_bup)
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
- tk_call('font', 'delete', fnt_bup)
- else
- fail e
- end
- end
-
- else
- latinkeys = {}
- begin
- actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
- rescue
- latinkeys {}
- end
- if latinkeys != {}
- tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
- end
- end
- self
- end
-
- def kanji_replace_core_tk8x(knj)
- if JAPANIZED_TK
- begin
- tk_call('font', 'delete', '@font_tmp')
- rescue
- end
- begin
- fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @kanjifont)
- rescue
- #fnt_bup = ''
- fnt_bup = DEFAULT_KANJI_FONT_NAME
- end
- end
-
- begin
- tk_call('font', 'delete', @kanjifont)
- rescue
- end
- create_kanjifont(knj)
-
- if JAPANIZED_TK
- keys = self.configinfo
- tk_call('font', 'delete', @compoundfont)
- begin
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
- rescue RuntimeError => e
- tk_call('font', 'delete', @kanjifont)
- if fnt_bup && fnt_bup != ''
- tk_call('font', 'create', @kanjifont, '-copy', fnt_bup)
- tk_call('font', 'create', @compoundfont,
- '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
- tk_call('font', 'delete', fnt_bup)
- else
- fail e
- end
- end
- end
- self
- end
-
- def measure_core_tk4x(window, text)
- 0
- end
-
- def measure_core_tk8x(window, text)
- if window
- number(tk_call('font', 'measure', @compoundfont,
- '-displayof', window, text))
- else
- number(tk_call('font', 'measure', @compoundfont, text))
- end
- end
-
- def metrics_core_tk4x(font, window, option=nil)
- # dummy
- if option
- ""
- else
- [['ascent',[]], ['descent',[]], ['linespace',[]], ['fixed',[]]]
- end
- end
-
- def metrics_core_tk8x(font, window, option=nil)
- if option
- if window
- number(tk_call('font', 'metrics', font,
- "-displayof", window, "-#{option}"))
- else
- number(tk_call('font', 'metrics', font, "-#{option}"))
- end
- else
- l = tk_split_list(if window
- tk_call('font','metrics',font,"-displayof",window)
- else
- tk_call('font','metrics',font)
- end)
- r = []
- while key=l.shift
- r.push [key[1..-1], l.shift.to_i]
- end
- r
- end
- end
-
- ###################################
- # private alias
- ###################################
- case (Tk::TK_VERSION)
- when /^4\.*/
- alias create_latinfont create_latinfont_tk4x
- alias create_kanjifont create_kanjifont_tk4x
- alias create_compoundfont create_compoundfont_tk4x
- alias actual_core actual_core_tk4x
- alias configure_core configure_core_tk4x
- alias configinfo_core configinfo_core_tk4x
- alias delete_core delete_core_tk4x
- alias latin_replace_core latin_replace_core_tk4x
- alias kanji_replace_core kanji_replace_core_tk4x
- alias measure_core measure_core_tk4x
- alias metrics_core metrics_core_tk4x
-
- when /^8\.[0-4]/
- alias create_latinfont create_latinfont_tk8x
- alias create_kanjifont create_kanjifont_tk8x
- alias create_compoundfont create_compoundfont_tk8x
- alias actual_core actual_core_tk8x
- alias configure_core configure_core_tk8x
- alias configinfo_core configinfo_core_tk8x
- alias delete_core delete_core_tk8x
- alias latin_replace_core latin_replace_core_tk8x
- alias kanji_replace_core kanji_replace_core_tk8x
- alias measure_core measure_core_tk8x
- alias metrics_core metrics_core_tk8x
-
- when /^8\.*/
- alias create_latinfont create_latinfont_tk8x
- alias create_kanjifont create_kanjifont_tk8x
- alias create_compoundfont create_compoundfont_tk8x
- alias actual_core actual_core_tk8x
- alias configure_core configure_core_tk8x
- alias configinfo_core configinfo_core_tk8x
- alias delete_core delete_core_tk8x
- alias latin_replace_core latin_replace_core_tk8x
- alias kanji_replace_core kanji_replace_core_tk8x
- alias measure_core measure_core_tk8x
- alias metrics_core metrics_core_tk8x
-
- end
-
- ###################################
- public
- ###################################
- def method_missing(id, *args)
- name = id.id2name
- case args.length
- when 1
- configure name, args[0]
- when 0
- begin
- configinfo name
- rescue
- fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at
- end
- else
- fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
- end
- end
-
- def call_font_configure(path, *args)
- args += hash_kv(args.pop.update(@fontslot))
- tk_call(*args)
- Tk_FontUseTBL[path] = self
- self
- end
-
- def used
- ret = []
- Tk_FontUseTBL.each{|key,value|
- if key.include?(';')
- win, tag = key.split(';')
- winobj = tk_tcl2ruby(win)
- if winobj.kind_of? TkText
- ret.push([winobj, winobj.tagid2obj(tag)])
- 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])
- else
- ret.push([winobj, tag])
- end
- elsif winobj.kind_of? TkMenu
- ret.push([winobj, tag])
- else
- ret.push([win, tag])
- end
- else
- ret.push(tk_tcl2ruby(key)) if value == self
- end
- }
- ret
- end
-
- def id
- @id
- end
-
- def to_eval
- font
- end
-
- def font
- @compoundfont
- end
- alias font_id font
-
- def latin_font_id
- @latinfont
- end
-
- def latin_font
- # @latinfont
- if @latin_descendant
- @latin_descendant
- else
- @latin_descendant = DescendantFont.new(self, 'latin')
- end
- end
- alias latinfont latin_font
-
- def kanji_font_id
- @kanjifont
- end
-
- def kanji_font
- # @kanjifont
- if @kanji_descendant
- @kanji_descendant
- else
- @kanji_descendant = DescendantFont.new(self, 'kanji')
- end
- end
- alias kanjifont kanji_font
-
- def actual(option=nil)
- actual_core(@compoundfont, nil, option)
- end
-
- def actual_displayof(window, option=nil)
- window = '.' unless window
- actual_core(@compoundfont, window, option)
- end
-
- def latin_actual(option=nil)
- actual_core(@latinfont, nil, option)
- end
-
- def latin_actual_displayof(window, option=nil)
- window = '.' unless window
- actual_core(@latinfont, window, option)
- end
-
- def kanji_actual(option=nil)
- #if JAPANIZED_TK
- if @kanjifont != ""
- actual_core(@kanjifont, nil, option)
- else
- actual_core_tk4x(nil, nil, option)
- end
- end
-
- def kanji_actual_displayof(window, option=nil)
- #if JAPANIZED_TK
- if @kanjifont != ""
- window = '.' unless window
- actual_core(@kanjifont, window, option)
- else
- actual_core_tk4x(nil, window, option)
- end
- end
-
- def [](slot)
- configinfo slot
- end
-
- def []=(slot, val)
- configure slot, val
- end
-
- def configure(slot, value=None)
- configure_core(@compoundfont, slot, value)
- self
- end
-
- def configinfo(slot=nil)
- configinfo_core(@compoundfont, slot)
- end
-
- def delete
- delete_core
- end
-
- def latin_configure(slot, value=None)
- if JAPANIZED_TK
- configure_core(@latinfont, slot, value)
- else
- configure(slot, value)
- end
- self
- end
-
- def latin_configinfo(slot=nil)
- if JAPANIZED_TK
- configinfo_core(@latinfont, slot)
- else
- configinfo(slot)
- end
- end
-
- def kanji_configure(slot, value=None)
- #if JAPANIZED_TK
- if @kanjifont != ""
- configure_core(@kanjifont, slot, value)
- configure('size'=>configinfo('size')) # to reflect new configuration
- else
- #""
- configure(slot, value)
- end
- self
- end
-
- def kanji_configinfo(slot=nil)
- #if JAPANIZED_TK
- if @kanjifont != ""
- configinfo_core(@kanjifont, slot)
- else
- #[]
- configinfo(slot)
- end
- end
-
- def replace(ltn, knj)
- latin_replace(ltn)
- kanji_replace(knj)
- self
- end
-
- def latin_replace(ltn)
- latin_replace_core(ltn)
- reset_pointadjust
- self
- end
-
- def kanji_replace(knj)
- kanji_replace_core(knj)
- reset_pointadjust
- self
- end
-
- def measure(text)
- measure_core(nil, text)
- end
-
- def measure_displayof(window, text)
- window = '.' unless window
- measure_core(window, text)
- end
-
- def metrics(option=nil)
- metrics_core(@compoundfont, nil, option)
- end
-
- def metrics_displayof(window, option=nil)
- window = '.' unless window
- metrics_core(@compoundfont, window, option)
- end
-
- def latin_metrics(option=nil)
- metrics_core(@latinfont, nil, option)
- end
-
- def latin_metrics_displayof(window, option=nil)
- window = '.' unless window
- metrics_core(@latinfont, window, option)
- end
-
- def kanji_metrics(option=nil)
- if JAPANIZED_TK
- metrics_core(@kanjifont, nil, option)
- else
- metrics_core_tk4x(nil, nil, option)
- end
- end
-
- def kanji_metrics_displayof(window, option=nil)
- if JAPANIZED_TK
- window = '.' unless window
- metrics_core(@kanjifont, window, option)
- else
- metrics_core_tk4x(nil, window, option)
- end
- end
-
- def reset_pointadjust
- begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
- configure('pointadjust' => latin_actual.assoc('size')[1].to_f /
- kanji_actual.assoc('size')[1].to_f )
- end
- rescue
- end
- self
- end
-
- ###################################
- # public alias
- ###################################
- alias ascii_font latin_font
- alias asciifont latinfont
- alias create_asciifont create_latinfont
- alias ascii_actual latin_actual
- alias ascii_actual_displayof latin_actual_displayof
- alias ascii_configure latin_configure
- alias ascii_configinfo latin_configinfo
- alias ascii_replace latin_replace
- alias ascii_metrics latin_metrics
-
- ###################################
- def dup
- src = self
- obj = super()
- obj.instance_eval{ initialize(src) }
- obj
- end
- def clone
- src = self
- obj = super()
- obj.instance_eval{ initialize(src) }
- obj
- end
-end
-
-module TkTreatTagFont
- def font_configinfo
- @parent.tagfont_configinfo(@id)
- end
-# alias font font_configinfo
-
- def font_configure(slot)
- @parent.tagfont_configure(@id, slot)
- self
- end
-
- def latinfont_configure(ltn, keys=nil)
- @parent.latintagfont_configure(@id, ltn, keys)
- self
- end
- alias asciifont_configure latinfont_configure
-
- def kanjifont_configure(knj, keys=nil)
- @parent.kanjitagfont_configure(@id, ltn, keys)
- self
- end
-
- def font_copy(window, wintag=nil)
- @parent.tagfont_copy(@id, window, wintag)
- self
- end
-
- def latinfont_copy(window, wintag=nil)
- @parent.latintagfont_copy(@id, window, wintag)
- self
- end
- alias asciifont_copy latinfont_copy
-
- def kanjifont_copy(window, wintag=nil)
- @parent.kanjitagfont_copy(@id, window, wintag)
- self
- end
-end
+require 'tk/font'
diff --git a/ext/tk/lib/tkmacpkg.rb b/ext/tk/lib/tkmacpkg.rb
index 3bac5e6c3e..35560e78ce 100644
--- a/ext/tk/lib/tkmacpkg.rb
+++ b/ext/tk/lib/tkmacpkg.rb
@@ -1,56 +1,4 @@
#
-# tkmacpkg.rb : methods for Tcl/Tk packages for Macintosh
-# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+# tkmacpkg.rb - load tk/macpkg.rb
#
-# ATTENTION !!
-# This is NOT TESTED. Because I have no test-environment.
-#
-#
-require 'tk'
-
-module TkMacResource
- extend Tk
- extend TkMacResource
-
- TkCommandNames = ['resource'.freeze].freeze
-
- tk_call('package', 'require', 'resource')
-
- def close(rsrcRef)
- tk_call('resource', 'close', rsrcRef)
- end
-
- def delete(rsrcType, opts=nil)
- tk_call('resource', 'delete', *(hash_kv(opts) + rsrcType))
- end
-
- def files(rsrcRef=nil)
- if rsrcRef
- tk_call('resource', 'files', rsrcRef)
- else
- tk_split_simplelist(tk_call('resource', 'files'))
- end
- end
-
- def list(rsrcType, rsrcRef=nil)
- tk_split_simplelist(tk_call('resource', 'list', rsrcType, rsrcRef))
- end
-
- def open(fname, access=nil)
- tk_call('resource', 'open', fname, access)
- end
-
- def read(rsrcType, rsrcID, rsrcRef=nil)
- tk_call('resource', 'read', rsrcType, rsrcID, rsrcRef)
- end
-
- def types(rsrcRef=nil)
- tk_split_simplelist(tk_call('resource', 'types', rsrcRef))
- end
-
- def write(rsrcType, data, opts=nil)
- tk_call('resource', 'write', *(hash_kv(opts) + rsrcType + data))
- end
-
- module_function :close, :delete, :files, :list, :open, :read, :types, :write
-end
+require 'tk/macpkg'
diff --git a/ext/tk/lib/tkmenubar.rb b/ext/tk/lib/tkmenubar.rb
index 0d29571eb7..70214fda1a 100644
--- a/ext/tk/lib/tkmenubar.rb
+++ b/ext/tk/lib/tkmenubar.rb
@@ -1,143 +1,4 @@
#
-# tkmenubar.rb
+# tkmenubar.rb - load tk/menubar.rb
#
-# Copyright (C) 1998 maeda shugo. All rights reserved.
-# This file can be distributed under the terms of the Ruby.
-
-# Usage:
-#
-# menu_spec = [
-# [['File', 0],
-# ['Open', proc{puts('Open clicked')}, 0],
-# '---',
-# ['Quit', proc{exit}, 0]],
-# [['Edit', 0],
-# ['Cut', proc{puts('Cut clicked')}, 2],
-# ['Copy', proc{puts('Copy clicked')}, 0],
-# ['Paste', proc{puts('Paste clicked')}, 0]]
-# ]
-# menubar = TkMenubar.new(nil, menu_spec,
-# 'tearoff'=>false,
-# 'foreground'=>'grey40',
-# 'activeforeground'=>'red',
-# 'font'=>'-adobe-helvetica-bold-r-*--12-*-iso8859-1')
-# menubar.pack('side'=>'top', 'fill'=>'x')
-#
-#
-# OR
-#
-#
-# menubar = TkMenubar.new
-# menubar.add_menu([['File', 0],
-# ['Open', proc{puts('Open clicked')}, 0],
-# '---',
-# ['Quit', proc{exit}, 0]])
-# menubar.add_menu([['Edit', 0],
-# ['Cut', proc{puts('Cut clicked')}, 2],
-# ['Copy', proc{puts('Copy clicked')}, 0],
-# ['Paste', proc{puts('Paste clicked')}, 0]])
-# menubar.configure('tearoff', false)
-# menubar.configure('foreground', 'grey40')
-# menubar.configure('activeforeground', 'red')
-# menubar.configure('font', '-adobe-helvetica-bold-r-*--12-*-iso8859-1')
-# menubar.pack('side'=>'top', 'fill'=>'x')
-
-# The format of the menu_spec is:
-# [
-# [
-# [button text, underline, accelerator],
-# [menu label, command, underline, accelerator],
-# '---', # separator
-# ...
-# ],
-# ...
-# ]
-
-# underline and accelerator are optional parameters.
-# Hashes are OK instead of Arrays.
-
-# To use add_menu, configuration must be done by calling configure after
-# adding all menus by add_menu, not by the constructor arguments.
-
-require "tk"
-
-class TkMenubar<TkFrame
-
- include TkComposite
-
- def initialize(parent = nil, spec = nil, options = nil)
- if parent.kind_of? Hash
- options = _symbolkey2str(parent)
- spec = options.delete('spec')
- super(options)
- else
- super(parent, options)
- end
-
- @menus = []
-
- if spec
- for menu_info in spec
- add_menu(menu_info)
- end
- end
-
- if options
- for key, value in options
- configure(key, value)
- end
- end
- end
-
- def add_menu(menu_info)
- btn_info = menu_info.shift
- mbtn = TkMenubutton.new(@frame)
-
- if btn_info.kind_of?(Hash)
- for key, value in btn_info
- mbtn.configure(key, value)
- end
- elsif btn_info.kind_of?(Array)
- mbtn.configure('text', btn_info[0]) if btn_info[0]
- mbtn.configure('underline', btn_info[1]) if btn_info[1]
- mbtn.configure('accelerator', btn_info[2]) if btn_info[2]
- else
- mbtn.configure('text', btn_info)
- end
-
- menu = TkMenu.new(mbtn)
-
- for item_info in menu_info
- if item_info.kind_of?(Hash)
- menu.add('command', item_info)
- elsif item_info.kind_of?(Array)
- options = {}
- options['label'] = item_info[0] if item_info[0]
- options['command'] = item_info[1] if item_info[1]
- options['underline'] = item_info[2] if item_info[2]
- options['accelerator'] = item_info[3] if item_info[3]
- menu.add('command', options)
- elsif /^-+$/ =~ item_info
- menu.add('sep')
- else
- menu.add('command', 'label' => item_info)
- end
- end
-
- mbtn.menu(menu)
- @menus.push([mbtn, menu])
- delegate('tearoff', menu)
- delegate('foreground', mbtn, menu)
- delegate('background', mbtn, menu)
- delegate('disabledforeground', mbtn, menu)
- delegate('activeforeground', mbtn, menu)
- delegate('activebackground', mbtn, menu)
- delegate('font', mbtn, menu)
- delegate('kanjifont', mbtn, menu)
- mbtn.pack('side' => 'left')
- end
-
- def [](index)
- return @menus[index]
- end
-end
+require 'tk/menubar'
diff --git a/ext/tk/lib/tkmngfocus.rb b/ext/tk/lib/tkmngfocus.rb
index 461525009f..fe70950e8e 100644
--- a/ext/tk/lib/tkmngfocus.rb
+++ b/ext/tk/lib/tkmngfocus.rb
@@ -1,33 +1,4 @@
#
-# tkmngfocus.rb : methods for Tcl/Tk standard library 'focus.tcl'
-# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+# tkmngfocus.rb - load tk/mngfocus.rb
#
-require 'tk'
-
-module TkManageFocus
- extend Tk
-
- TkCommandNames = [
- 'tk_focusFollowMouse'.freeze,
- 'tk_focusNext'.freeze,
- 'tk_focusPrev'.freeze
- ].freeze
-
- def TkManageFocus.followsMouse
- tk_call 'tk_focusFollowsMouse'
- end
-
- def TkManageFocus.next(window)
- tk_tcl2ruby(tk_call('tk_focusNext', window))
- end
- def focusNext
- TkManageFocus.next(self)
- end
-
- def TkManageFocus.prev(window)
- tk_tcl2ruby(tk_call('tk_focusPrev', window))
- end
- def focusPrev
- TkManageFocus.prev(self)
- end
-end
+require 'tk/mngfocus'
diff --git a/ext/tk/lib/tkpalette.rb b/ext/tk/lib/tkpalette.rb
index dc2fd47e5c..56b203bbb9 100644
--- a/ext/tk/lib/tkpalette.rb
+++ b/ext/tk/lib/tkpalette.rb
@@ -1,54 +1,4 @@
#
-# tkpalette.rb : methods for Tcl/Tk standard library 'palette.tcl'
-# 1998/06/21 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+# tkpalette.rb - load tk/palette.rb
#
-require 'tk'
-
-module TkPalette
- include Tk
- extend Tk
-
- TkCommandNames = [
- 'tk_setPalette'.freeze,
- 'tk_bisque'.freeze,
- 'tkDarken'.freeze
- ].freeze
-
- def TkPalette.set(*args)
- args = args.to_a.flatten if args.kind_of? Hash
- tk_call 'tk_setPalette', *args
- end
- def TkPalette.setPalette(*args)
- TkPalette.set(*args)
- end
-
- def TkPalette.bisque
- tk_call 'tk_bisque'
- end
-
- def TkPalette.darken(color, percent)
- tk_call 'tkDarken', color, percent
- end
-
- def TkPalette.recolorTree(window, colors)
- if not colors.kind_of?(Hash)
- fail "2nd arg need to be Hash"
- end
-
- colors.each{|key, value|
- begin
- if window.cget(key) == tk_call('set', "tkPalette(#{key})")
- window[key] = colors[key]
- end
- rescue
- # ignore
- end
- }
-
- TkWinfo.children(window).each{|w| TkPalette.recolorTree(w, colors)}
- end
-
- def recolorTree(colors)
- TkPalette.recolorTree(self, colors)
- end
-end
+require 'tk/palette'
diff --git a/ext/tk/lib/tkscrollbox.rb b/ext/tk/lib/tkscrollbox.rb
index 6236430491..6093b2e4e7 100644
--- a/ext/tk/lib/tkscrollbox.rb
+++ b/ext/tk/lib/tkscrollbox.rb
@@ -1,29 +1,4 @@
#
-# tkscrollbox.rb - Tk Listbox with Scrollbar
-# as an example of Composite Widget
-# $Date$
-# by Yukihiro Matsumoto <matz@netlab.co.jp>
-
-require 'tk.rb'
-
-class TkScrollbox<TkListbox
- include TkComposite
- def initialize_composite(keys=nil)
- list = TkListbox.new(@frame)
- scroll = TkScrollbar.new(@frame)
- @path = list.path
-
- list.configure 'yscroll', scroll.path+" set"
- list.pack 'side'=>'left','fill'=>'both','expand'=>'yes'
- scroll.configure 'command', list.path+" yview"
- scroll.pack 'side'=>'right','fill'=>'y'
-
- delegate('DEFAULT', list)
- delegate('foreground', list)
- delegate('background', list, scroll)
- delegate('borderwidth', @frame)
- delegate('relief', @frame)
-
- configure keys if keys
- end
-end
+# tkscrollbox.rb - load tk/scrollbox.rb
+#
+require 'tk/scrollbox'
diff --git a/ext/tk/lib/tktext.rb b/ext/tk/lib/tktext.rb
index d7cb055a40..97ad62a3ea 100644
--- a/ext/tk/lib/tktext.rb
+++ b/ext/tk/lib/tktext.rb
@@ -1,1299 +1,4 @@
#
-# tktext.rb - Tk text classes
-# $Date$
-# by Yukihiro Matsumoto <matz@caelum.co.jp>
-
-require 'tk.rb'
-require 'tkfont'
-
-module TkTreatTextTagFont
- include TkTreatItemFont
-
- ItemCMD = ['tag'.freeze, 'configure'.freeze].freeze
- def __conf_cmd(idx)
- ItemCMD[idx]
- end
-
- def __item_pathname(tagOrId)
- if tagOrId.kind_of?(TkTextTag)
- self.path + ';' + tagOrId.id
- else
- self.path + ';' + tagOrId
- end
- end
-end
-
-class TkText<TkTextWin
- ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze
- include TkTreatTextTagFont
- include Scrollable
-
- TkCommandNames = ['text'.freeze].freeze
- WidgetClassName = 'Text'.freeze
- WidgetClassNames[WidgetClassName] = self
-
- def self.new(*args, &block)
- obj = super(*args){}
- obj.init_instance_variable
- obj.instance_eval(&block) if defined? yield
- obj
- end
-
- def init_instance_variable
- @cmdtbl = []
- @tags = {}
- end
-
- def __destroy_hook__
- TTagID_TBL.delete(@path)
- TMarkID_TBL.delete(@path)
- end
-
- def create_self(keys)
- if keys and keys != None
- tk_call 'text', @path, *hash_kv(keys)
- else
- tk_call 'text', @path
- end
- init_instance_variable
- end
-
- def index(index)
- tk_send 'index', index
- end
-
- def value
- tk_send 'get', "1.0", "end - 1 char"
- end
-
- def value= (val)
- tk_send 'delete', "1.0", 'end'
- tk_send 'insert', "1.0", val
- end
-
- def _addcmd(cmd)
- @cmdtbl.push cmd
- end
-
- def _addtag(name, obj)
- @tags[name] = obj
- end
-
- def tagid2obj(tagid)
- if @tags[tagid]
- @tags[tagid]
- else
- tagid
- end
- end
-
- def tag_names(index=None)
- tk_split_simplelist(tk_send('tag', 'names', index)).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def mark_names
- tk_split_simplelist(tk_send('mark', 'names')).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def mark_gravity(mark, direction=nil)
- if direction
- tk_send 'mark', 'gravity', mark, direction
- self
- else
- tk_send 'mark', 'gravity', mark
- end
- end
-
- def mark_set(mark, index)
- tk_send 'mark', 'set', mark, index
- self
- end
- alias set_mark mark_set
-
- def mark_unset(*marks)
- tk_send 'mark', 'unset', *marks
- self
- end
- alias unset_mark mark_unset
-
- def mark_next(index)
- tagid2obj(tk_send('mark', 'next', index))
- end
- alias next_mark mark_next
-
- def mark_previous(index)
- tagid2obj(tk_send('mark', 'previous', index))
- end
- alias previous_mark mark_previous
-
- def image_cget(index, slot)
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- tk_send('image', 'cget', index, "-#{slot}")
- else
- tk_tcl2ruby(tk_send('image', 'cget', index, "-#{slot}"))
- end
- end
-
- def image_configure(index, slot, value=None)
- if slot.kind_of? Hash
- tk_send('image', 'configure', index, *hash_kv(slot))
- else
- tk_send('image', 'configure', index, "-#{slot}", value)
- end
- self
- end
-
- def image_configinfo(index, slot = nil)
- if slot
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- conf = tk_split_simplelist(tk_send('image', 'configure',
- index, "-#{slot}"))
- else
- conf = tk_split_list(tk_send('image', 'configure',
- index, "-#{slot}"))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- tk_split_simplelist(tk_send('image', 'configure',
- index)).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
- }
- end
- end
-
- def image_names
- tk_split_simplelist(tk_send('image', 'names')).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def set_insert(index)
- tk_send 'mark', 'set', 'insert', index
- self
- end
-
- def set_current(index)
- tk_send 'mark', 'set', 'current', index
- self
- end
-
- def insert(index, chars, *tags)
- if tags[0].kind_of? Array
- # multiple chars-taglist argument
- args = [chars]
- while tags.size > 0
- tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist
- args << tags.shift if tags.size > 0 # chars
- end
- super index, *args
- else
- # single chars-taglist argument
- super index, chars, tags.collect{|x|_get_eval_string(x)}.join(' ')
- end
- end
-
- def destroy
- @tags = {} unless @tags
- @tags.each_value do |t|
- t.destroy
- end
- super
- end
-
- def backspace
- self.delete 'insert'
- end
-
- def compare(idx1, op, idx2)
- bool(tk_send('compare', idx1, op, idx2))
- end
-
- def debug
- bool(tk_send('debug'))
- end
- def debug=(boolean)
- tk_send 'debug', boolean
- self
- end
- def bbox(index)
- list(tk_send('bbox', index))
- end
-
- def dlineinfo(index)
- list(tk_send('dlineinfo', index))
- end
-
- def modified?
- bool(tk_send('edit', 'modified'))
- end
- def modified(mode)
- tk_send('edit', 'modified', mode)
- self
- end
- def edit_redo
- tk_send('edit', 'redo')
- self
- end
- def edit_reset
- tk_send('edit', 'reset')
- self
- end
- def edit_separator
- tk_send('edit', 'separator')
- self
- end
- def edit_undo
- tk_send('edit', 'undo')
- self
- end
-
- def yview_pickplace(*what)
- tk_send 'yview', '-pickplace', *what
- self
- end
-
- def xview_pickplace(*what)
- tk_send 'xview', '-pickplace', *what
- self
- end
-
- def text_copy
- # Tk8.4 feature
- tk_call('tk_textCopy', @path)
- end
-
- def text_cut
- # Tk8.4 feature
- tk_call('tk_textCut', @path)
- end
-
- def text_paste
- # Tk8.4 feature
- tk_call('tk_textPaste', @path)
- end
-
- def tag_add(tag, index1, index2=None)
- tk_send 'tag', 'add', tag, index1, index2
- self
- end
- alias addtag tag_add
- alias add_tag tag_add
-
- def tag_delete(*tags)
- tk_send 'tag', 'delete', *tags
- if TkTextTag::TTagID_TBL[@path]
- tags.each{|tag|
- if tag.kind_of? TkTextTag
- TTagID_TBL[@path].delete(tag.id)
- else
- TTagID_TBL[@path].delete(tag)
- end
- }
- end
- self
- end
- alias deltag tag_delete
- alias delete_tag tag_delete
-
- def tag_bind(tag, seq, cmd=Proc.new, args=nil)
- _bind([@path, 'tag', 'bind', tag], seq, cmd, args)
- self
- end
-
- def tag_bind_append(tag, seq, cmd=Proc.new, args=nil)
- _bind_append([@path, 'tag', 'bind', tag], seq, cmd, args)
- self
- end
-
- def tag_bind_remove(tag, seq)
- _bind_remove([@path, 'tag', 'bind', tag], seq)
- self
- end
-
- def tag_bindinfo(tag, context=nil)
- _bindinfo([@path, 'tag', 'bind', tag], context)
- end
-
- def tag_cget(tag, key)
- case key.to_s
- when 'text', 'label', 'show', 'data', 'file'
- tk_call(@path, 'tag', 'cget', tag, "-#{key}")
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('tag', 'cget', tag, "-#{key}"))
- fnt = tk_tcl2ruby(tk_send('tag', 'cget', tag, '-font'))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(tag, fnt)
- end
- if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(tk_call(@path, 'tag', 'cget', tag, "-#{key}"))
- end
- end
-
- def tag_configure(tag, key, val=None)
- if key.kind_of? Hash
- key = _symbolkey2str(key)
- if ( key['font'] || key['kanjifont'] \
- || key['latinfont'] || key['asciifont'] )
- tagfont_configure(tag, key)
- else
- tk_send 'tag', 'configure', tag, *hash_kv(key)
- end
-
- else
- if key == 'font' || key == :font ||
- key == 'kanjifont' || key == :kanjifont ||
- key == 'latinfont' || key == :latinfont ||
- key == 'asciifont' || key == :asciifont
- if val == None
- tagfontobj(tag)
- else
- tagfont_configure(tag, {key=>val})
- end
- else
- tk_send 'tag', 'configure', tag, "-#{key}", val
- end
- end
- self
- end
-
- def tag_configinfo(tag, key=nil)
- if key
- case key.to_s
- when 'text', 'label', 'show', 'data', 'file'
- conf = tk_split_simplelist(tk_send('tag','configure',tag,"-#{key}"))
- when 'font', 'kanjifont'
- conf = tk_split_simplelist(tk_send('tag','configure',tag,"-#{key}") )
- conf[4] = tagfont_configinfo(tag, conf[4])
- else
- conf = tk_split_list(tk_send('tag','configure',tag,"-#{key}"))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- ret = tk_split_simplelist(tk_send('tag', 'configure',
- tag)).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
- }
- fontconf = ret.assoc('font')
- if fontconf
- ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
- fontconf[4] = tagfont_configinfo(tag, fontconf[4])
- ret.push(fontconf)
- else
- ret
- end
- end
- end
-
- def tag_raise(tag, above=None)
- tk_send 'tag', 'raise', tag, above
- self
- end
-
- def tag_lower(tag, below=None)
- tk_send 'tag', 'lower', tag, below
- self
- end
-
- def tag_remove(tag, *index)
- tk_send 'tag', 'remove', tag, *index
- self
- end
-
- def tag_ranges(tag)
- l = tk_split_simplelist(tk_send('tag', 'ranges', tag))
- r = []
- while key=l.shift
- r.push [key, l.shift]
- end
- r
- end
-
- def tag_nextrange(tag, first, last=None)
- tk_split_list(tk_send('tag', 'nextrange', tag, first, last))
- end
-
- def tag_prevrange(tag, first, last=None)
- tk_split_list(tk_send('tag', 'prevrange', tag, first, last))
- end
-
- def window_cget(index, slot)
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- tk_send('window', 'cget', index, "-#{slot}")
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}"))
- fnt = tk_tcl2ruby(tk_send('window', 'cget', index, '-font'))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(index, fnt)
- end
- if slot.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}"))
- end
- end
-
- def window_configure(index, slot, value=None)
- if index.kind_of? TkTextWindow
- index.configure(slot, value)
- else
- if slot.kind_of? Hash
- tk_send('window', 'configure', index, *hash_kv(slot))
- else
- tk_send('window', 'configure', index, "-#{slot}", value)
- end
- end
- self
- end
-
- def window_configinfo(win, slot = nil)
- if slot
- case slot.to_s
- when 'text', 'label', 'show', 'data', 'file'
- conf = tk_split_simplelist(tk_send('window', 'configure',
- win, "-#{slot}"))
- else
- conf = tk_split_list(tk_send('window', 'configure',
- win, "-#{slot}"))
- end
- conf[0] = conf[0][1..-1]
- conf
- else
- tk_split_simplelist(tk_send('window', 'configure',
- win)).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
- }
- end
- end
-
- def window_names
- tk_split_simplelist(tk_send('window', 'names')).collect{|elt|
- tagid2obj(elt)
- }
- end
-
- def _ktext_length(txt)
- if $KCODE !~ /n/i
- return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
- end
-
- # $KCODE == 'NONE'
- if JAPANIZED_TK
- tk_call('kstring', 'length', txt).to_i
- else
- begin
- tk_call('encoding', 'convertto', 'ascii', txt).length
- rescue StandardError, NameError
- # sorry, I have no plan
- txt.length
- end
- end
- end
- private :_ktext_length
-
- def search_with_length(pat,start,stop=None)
- pat = pat.chr if pat.kind_of? Integer
- if stop != None
- return ["", 0] if compare(start,'>=',stop)
- txt = get(start,stop)
- if (pos = txt.index(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index(start + " + #{pos} chars"), pat.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(pat), pat.dup]
- else
- #return [index(start + " + #{pos} chars"), $&.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- else
- txt = get(start,'end - 1 char')
- if (pos = txt.index(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index(start + " + #{pos} chars"), pat.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(pat), pat.dup]
- else
- #return [index(start + " + #{pos} chars"), $&.split('').length]
- return [index(start + " + #{pos} chars"),
- _ktext_length(match), match]
- end
- else
- txt = get('1.0','end - 1 char')
- if (pos = txt.index(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index("1.0 + #{pos} chars"), pat.split('').length]
- return [index("1.0 + #{pos} chars"),
- _ktext_length(pat), pat.dup]
- else
- #return [index("1.0 + #{pos} chars"), $&.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- end
- end
- end
-
- def search(pat,start,stop=None)
- search_with_length(pat,start,stop)[0]
- end
-
- def rsearch_with_length(pat,start,stop=None)
- pat = pat.chr if pat.kind_of? Integer
- if stop != None
- return ["", 0] if compare(start,'<=',stop)
- txt = get(stop,start)
- if (pos = txt.rindex(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index(stop + " + #{pos} chars"), pat.split('').length]
- return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup]
- else
- #return [index(stop + " + #{pos} chars"), $&.split('').length]
- return [index(stop + " + #{pos} chars"), _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- else
- txt = get('1.0',start)
- if (pos = txt.rindex(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index("1.0 + #{pos} chars"), pat.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
- else
- #return [index("1.0 + #{pos} chars"), $&.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
- end
- else
- txt = get('1.0','end - 1 char')
- if (pos = txt.rindex(pat))
- match = $&
- #pos = txt[0..(pos-1)].split('').length if pos > 0
- pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
- if pat.kind_of? String
- #return [index("1.0 + #{pos} chars"), pat.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
- else
- #return [index("1.0 + #{pos} chars"), $&.split('').length]
- return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
- end
- else
- return ["", 0]
- end
- end
- end
- end
-
- def rsearch(pat,start,stop=None)
- rsearch_with_length(pat,start,stop)[0]
- end
-
- def dump(type_info, *index, &block)
- args = type_info.collect{|inf| '-' + inf}
- args << '-command' << block if block
- str = tk_send('dump', *(args + index))
- result = []
- sel = nil
- i = 0
- while i < str.size
- # retrieve key
- idx = str.index(/ /, i)
- result.push str[i..(idx-1)]
- i = idx + 1
-
- # retrieve value
- case result[-1]
- when 'text'
- if str[i] == ?{
- # text formed as {...}
- val, i = _retrieve_braced_text(str, i)
- result.push val
- else
- # text which may contain backslahes
- val, i = _retrieve_backslashed_text(str, i)
- result.push val
- end
- else
- idx = str.index(/ /, i)
- val = str[i..(idx-1)]
- case result[-1]
- when 'mark'
- case val
- when 'insert'
- result.push TkTextMarkInsert.new(self)
- when 'current'
- result.push TkTextMarkCurrent.new(self)
- when 'anchor'
- result.push TkTextMarkAnchor.new(self)
- else
- result.push tk_tcl2ruby(val)
- end
- when 'tagon'
- if val == 'sel'
- if sel
- result.push sel
- else
- result.push TkTextTagSel.new(self)
- end
- else
- result.push tk_tcl2ruby(val)
- end
- when 'tagoff'
- result.push tk_tcl2ruby(val)
- when 'window'
- result.push tk_tcl2ruby(val)
- end
- i = idx + 1
- end
-
- # retrieve index
- idx = str.index(/ /, i)
- if idx
- result.push str[i..(idx-1)]
- i = idx + 1
- else
- result.push str[i..-1]
- break
- end
- end
-
- kvis = []
- until result.empty?
- kvis.push [result.shift, result.shift, result.shift]
- end
- kvis # result is [[key1, value1, index1], [key2, value2, index2], ...]
- end
-
- def _retrieve_braced_text(str, i)
- cnt = 0
- idx = i
- while idx < str.size
- case str[idx]
- when ?{
- cnt += 1
- when ?}
- cnt -= 1
- if cnt == 0
- break
- end
- end
- idx += 1
- end
- return str[i+1..idx-1], idx + 2
- end
- private :_retrieve_braced_text
-
- def _retrieve_backslashed_text(str, i)
- j = i
- idx = nil
- loop {
- idx = str.index(/ /, j)
- if str[idx-1] == ?\\
- j += 1
- else
- break
- end
- }
- val = str[i..(idx-1)]
- val.gsub!(/\\( |\{|\})/, '\1')
- return val, idx + 1
- end
- private :_retrieve_backslashed_text
-
- def dump_all(*index, &block)
- dump(['all'], *index, &block)
- end
- def dump_mark(*index, &block)
- dump(['mark'], *index, &block)
- end
- def dump_tag(*index, &block)
- dump(['tag'], *index, &block)
- end
- def dump_text(*index, &block)
- dump(['text'], *index, &block)
- end
- def dump_window(*index, &block)
- dump(['window'], *index, &block)
- end
- def dump_image(*index, &block)
- dump(['image'], *index, &block)
- end
-end
-
-class TkTextTag<TkObject
- include TkTreatTagFont
-
- TTagID_TBL = TkCore::INTERP.create_table
- Tk_TextTag_ID = ['tag'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ TTagID_TBL.clear }
-
- def TkTextTag.id2obj(text, id)
- tpath = text.path
- return id unless TTagID_TBL[tpath]
- TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
- end
-
- def initialize(parent, *args)
- if not parent.kind_of?(TkText)
- fail Kernel.format("%s need to be TkText", parent.inspect)
- end
- @parent = @t = parent
- @tpath = parent.path
- @path = @id = Tk_TextTag_ID.join
- TTagID_TBL[@id] = self
- TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
- TTagID_TBL[@tpath][@id] = self
- Tk_TextTag_ID[1].succ!
- #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
- if args != [] then
- keys = args.pop
- if keys.kind_of? Hash then
- add(*args) if args != []
- configure(keys)
- else
- args.push keys
- add(*args)
- end
- end
- @t._addtag id, self
- end
-
- def id
- @id
- end
-
- def first
- @id + '.first'
- end
-
- def last
- @id + '.last'
- end
-
- def add(*index)
- tk_call @t.path, 'tag', 'add', @id, *index
- self
- end
-
- def remove(*index)
- tk_call @t.path, 'tag', 'remove', @id, *index
- self
- end
-
- def ranges
- l = tk_split_simplelist(tk_call(@t.path, 'tag', 'ranges', @id))
- r = []
- while key=l.shift
- r.push [key, l.shift]
- end
- r
- end
-
- def nextrange(first, last=None)
- tk_split_list(tk_call(@t.path, 'tag', 'nextrange', @id, first, last))
- end
-
- def prevrange(first, last=None)
- tk_split_list(tk_call(@t.path, 'tag', 'prevrange', @id, first, last))
- end
-
- def [](key)
- cget key
- end
-
- def []=(key,val)
- configure key, val
- end
-
- def cget(key)
- case key.to_s
- when 'text', 'label', 'show', 'data', 'file'
- tk_call @t.path, 'tag', 'cget', @id, "-#{key}"
- when 'font', 'kanjifont'
- #fnt = tk_tcl2ruby(tk_call(@t.path, 'tag', 'cget', @id, "-#{key}"))
- fnt = tk_tcl2ruby(tk_call(@t.path, 'tag', 'cget', @id, '-font'))
- unless fnt.kind_of?(TkFont)
- fnt = tagfontobj(@id, fnt)
- end
- if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
- # obsolete; just for compatibility
- fnt.kanji_font
- else
- fnt
- end
- else
- tk_tcl2ruby(tk_call(@t.path, 'tag', 'cget', @id, "-#{key}"))
- end
- end
-
- def configure(key, val=None)
- @t.tag_configure @id, key, val
- end
-# def configure(key, val=None)
-# if key.kind_of? Hash
-# tk_call @t.path, 'tag', 'configure', @id, *hash_kv(key)
-# else
-# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", val
-# end
-# end
-# def configure(key, value)
-# if value == FALSE
-# value = "0"
-# elsif value.kind_of? Proc
-# value = install_cmd(value)
-# end
-# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", value
-# end
-
- def configinfo(key=nil)
- @t.tag_configinfo @id, key
- end
-
- def bind(seq, cmd=Proc.new, args=nil)
- _bind([@t.path, 'tag', 'bind', @id], seq, cmd, args)
- self
- end
-
- def bind_append(seq, cmd=Proc.new, args=nil)
- _bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, args)
- self
- end
-
- def bind_remove(seq)
- _bind_remove([@t.path, 'tag', 'bind', @id], seq)
- self
- end
-
- def bindinfo(context=nil)
- _bindinfo([@t.path, 'tag', 'bind', @id], context)
- end
-
- def raise(above=None)
- tk_call @t.path, 'tag', 'raise', @id, above
- self
- end
-
- def lower(below=None)
- tk_call @t.path, 'tag', 'lower', @id, below
- self
- end
-
- def destroy
- tk_call @t.path, 'tag', 'delete', @id
- TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
- self
- end
-end
-
-class TkTextNamedTag<TkTextTag
- def self.new(parent, name, *args)
- if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
- tagobj = TTagID_TBL[parent.path][name]
- if args != [] then
- keys = args.pop
- if keys.kind_of? Hash then
- tagobj.add(*args) if args != []
- tagobj.configure(keys)
- else
- args.push keys
- tagobj.add(*args)
- end
- end
- return tagobj
- else
- super(parent, name, *args)
- end
- end
-
- def initialize(parent, name, *args)
- if not parent.kind_of?(TkText)
- fail Kernel.format("%s need to be TkText", parent.inspect)
- end
- @parent = @t = parent
- @tpath = parent.path
- @path = @id = name
- TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
- TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id]
- #if mode
- # tk_call @t.path, "addtag", @id, *args
- #end
- if args != [] then
- keys = args.pop
- if keys.kind_of? Hash then
- add(*args) if args != []
- configure(keys)
- else
- args.push keys
- add(*args)
- end
- end
- @t._addtag id, self
- end
-end
-
-class TkTextTagSel<TkTextNamedTag
- def self.new(parent, *args)
- super(parent, 'sel', *args)
- end
-end
-
-class TkTextMark<TkObject
- TMarkID_TBL = TkCore::INTERP.create_table
- Tk_TextMark_ID = ['mark'.freeze, '00000'.taint].freeze
-
- TkCore::INTERP.init_ip_env{ TMarkID_TBL.clear }
-
- def TkTextMark.id2obj(text, id)
- tpath = text.path
- return id unless TMarkID_TBL[tpath]
- TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
- end
-
- def initialize(parent, index)
- if not parent.kind_of?(TkText)
- fail Kernel.format("%s need to be TkText", parent.inspect)
- end
- @parent = @t = parent
- @tpath = parent.path
- @path = @id = Tk_TextMark_ID.join
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self
- Tk_TextMark_ID[1].succ!
- tk_call @t.path, 'mark', 'set', @id, index
- @t._addtag id, self
- end
-
- def id
- @id
- end
-
- def +(mod)
- @id + ' + ' + mod
- end
- def -(mod)
- @id + ' - ' + mod
- end
-
- def set(where)
- tk_call @t.path, 'mark', 'set', @id, where
- self
- end
-
- def unset
- tk_call @t.path, 'mark', 'unset', @id
- self
- end
- alias destroy unset
-
- def gravity
- tk_call @t.path, 'mark', 'gravity', @id
- end
-
- def gravity=(direction)
- tk_call @t.path, 'mark', 'gravity', @id, direction
- self
- end
-
- def next(index = nil)
- if index
- @t.tagid2obj(tk_call(@t.path, 'mark', 'next', index))
- else
- @t.tagid2obj(tk_call(@t.path, 'mark', 'next', @id))
- end
- end
-
- def previous(index = nil)
- if index
- @t.tagid2obj(tk_call(@t.path, 'mark', 'previous', index))
- else
- @t.tagid2obj(tk_call(@t.path, 'mark', 'previous', @id))
- end
- end
-end
-
-class TkTextNamedMark<TkTextMark
- def self.new(parent, name, *args)
- if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
- return TMarkID_TBL[parent.path][name]
- else
- super(parent, name, *args)
- end
- end
-
- def initialize(parent, name, index=nil)
- if not parent.kind_of?(TkText)
- fail Kernel.format("%s need to be TkText", parent.inspect)
- end
- @parent = @t = parent
- @tpath = parent.path
- @path = @id = name
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
- tk_call @t.path, 'mark', 'set', @id, index if index
- @t._addtag id, self
- end
-end
-
-class TkTextMarkInsert<TkTextNamedMark
- def self.new(parent,*args)
- super(parent, 'insert', *args)
- end
-end
-
-class TkTextMarkCurrent<TkTextMark
- def self.new(parent,*args)
- super(parent, 'current', *args)
- end
-end
-
-class TkTextMarkAnchor<TkTextMark
- def self.new(parent,*args)
- super(parent, 'anchor', *args)
- end
-end
-
-class TkTextWindow<TkObject
- def initialize(parent, index, keys)
- if not parent.kind_of?(TkText)
- fail Kernel.format("%s need to be TkText", parent.inspect)
- end
- @t = parent
- if index == 'end'
- @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
- elsif index.kind_of? TkTextMark
- if tk_call(@t.path,'index',index.path) == tk_call(@t.path,'index','end')
- @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
- else
- @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index.path))
- end
- else
- @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index))
- end
- @path.gravity = 'left'
- @index = @path.path
- keys = _symbolkey2str(keys)
- @id = keys['window']
- if keys['create']
- @p_create = keys['create']
- if @p_create.kind_of? Proc
- keys['create'] = install_cmd(proc{@id = @p_create.call; @id.path})
- end
- end
- tk_call @t.path, 'window', 'create', @index, *hash_kv(keys)
- end
-
- def [](slot)
- cget(slot)
- end
- def []=(slot, value)
- configure(slot, value)
- end
-
- def cget(slot)
- @t.window_cget(@index, slot)
- end
-
- def configure(slot, value=None)
- if slot.kind_of? Hash
- slot = _symbolkey2str(slot)
- @id = slot['window'] if slot['window']
- if slot['create']
- self.create=value
- slot['create']=nil
- end
- if slot.size > 0
- tk_call(@t.path, 'window', 'configure', @index, *hash_kv(slot))
- end
- else
- @id = value if slot == 'window' || slot == :window
- if slot == 'create' || slot == :create
- self.create=value
- else
- tk_call(@t.path, 'window', 'configure', @index, "-#{slot}", value)
- end
- end
- self
- end
-
- def configinfo(slot = nil)
- @t.window_configinfo(@index, slot)
- end
-
- def window
- @id
- end
-
- def window=(value)
- tk_call @t.path, 'window', 'configure', @index, '-window', value
- @id = value
- end
-
- def create
- @p_create
- end
-
- def create=(value)
- @p_create = value
- if @p_create.kind_of? Proc
- value = install_cmd(proc{@id = @p_create.call})
- end
- tk_call @t.path, 'window', 'configure', @index, '-create', value
- end
-end
-
-class TkTextImage<TkObject
- def initialize(parent, index, keys)
- if not parent.kind_of?(TkText)
- fail Kernel.format("%s need to be TkText", parent.inspect)
- end
- @t = parent
- if index == 'end'
- @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
- elsif index.kind_of? TkTextMark
- if tk_call(@t.path,'index',index.path) == tk_call(@t.path,'index','end')
- @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
- else
- @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index.path))
- end
- else
- @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index))
- end
- @path.gravity = 'left'
- @index = @path.path
- @id = tk_call(@t.path, 'image', 'create', @index, *hash_kv(keys))
- end
-
- def [](slot)
- cget(slot)
- end
- def []=(slot, value)
- configure(slot, value)
- end
-
- def cget(slot)
- @t.image_cget(@index, slot)
- end
-
- def configure(slot, value=None)
- @t.image_configure(@index, slot, value)
- self
- end
-# def configure(slot, value)
-# tk_call @t.path, 'image', 'configure', @index, "-#{slot}", value
-# end
-
- def configinfo(slot = nil)
- @t.image_configinfo(@index, slot)
- end
-
- def image
- img = tk_call(@t.path, 'image', 'configure', @index, '-image')
- TkImage::Tk_IMGTBL[img]? TkImage::Tk_IMGTBL[img] : img
- end
-
- def image=(value)
- tk_call @t.path, 'image', 'configure', @index, '-image', value
- self
- end
-end
+# tktext.rb - load tk/text.rb
+#
+require 'tk/text'
diff --git a/ext/tk/lib/tkvirtevent.rb b/ext/tk/lib/tkvirtevent.rb
index ccd3448434..f4fae19a0a 100644
--- a/ext/tk/lib/tkvirtevent.rb
+++ b/ext/tk/lib/tkvirtevent.rb
@@ -1,85 +1,4 @@
#
-# tkvirtevent.rb : treats virtual events
-# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+# tkvirtevent.rb - load tk/virtevent.rb
#
-require 'tk'
-
-class TkVirtualEvent<TkObject
- extend Tk
-
- TkCommandNames = ['event'.freeze].freeze
-
- TkVirtualEventID = ["<VirtEvent".freeze, "00000".taint, ">".freeze].freeze
- TkVirtualEventTBL = TkCore::INTERP.create_table
-
- TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear }
-
- class PreDefVirtEvent<self
- def initialize(event)
- @path = @id = event
- TkVirtualEvent::TkVirtualEventTBL[@id] = self
- end
- end
-
- def TkVirtualEvent.getobj(event)
- obj = TkVirtualEventTBL[event]
- if obj
- obj
- else
- if tk_call('event', 'info').index("<#{event}>")
- PreDefVirtEvent.new(event)
- else
- fail ArgumentError, "undefined virtual event '<#{event}>'"
- end
- end
- end
-
- def TkVirtualEvent.info
- tk_call('event', 'info').split(/\s+/).collect!{|seq|
- TkVirtualEvent.getobj(seq[1..-2])
- }
- end
-
- def initialize(*sequences)
- @path = @id = TkVirtualEventID.join
- TkVirtualEventID[1].succ!
- add(*sequences)
- end
-
- def add(*sequences)
- if sequences != []
- tk_call('event', 'add', "<#{@id}>",
- *(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
- TkVirtualEventTBL[@id] = self
- end
- self
- end
-
- def delete(*sequences)
- if sequences == []
- tk_call('event', 'delete', "<#{@id}>")
- TkVirtualEventTBL.delete(@id)
- else
- tk_call('event', 'delete', "<#{@id}>",
- *(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
- TkVirtualEventTBL.delete(@id) if info == []
- end
- self
- end
-
- def info
- tk_call('event', 'info', "<#{@id}>").split(/\s+/).collect!{|seq|
- l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
- case (subseq)
- when /^<<[^<>]+>>$/
- TkVirtualEvent.getobj(subseq[1..-2])
- when /^<[^<>]+>$/
- subseq[1..-2]
- else
- subseq.split('')
- end
- }.flatten
- (l.size == 1) ? l[0] : l
- }
- end
-end
+require 'tk/virtevent'
diff --git a/ext/tk/lib/tkwinpkg.rb b/ext/tk/lib/tkwinpkg.rb
index 7762b3a596..83371c546d 100644
--- a/ext/tk/lib/tkwinpkg.rb
+++ b/ext/tk/lib/tkwinpkg.rb
@@ -1,84 +1,4 @@
#
-# tkwinpkg.rb : methods for Tcl/Tk packages for Microsoft Windows
-# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+# tkwinpkg.rb - load tk/winpkg.rb
#
-# ATTENTION !!
-# This is NOT TESTED. Because I have no test-environment.
-#
-#
-require 'tk'
-
-module TkWinDDE
- extend Tk
- extend TkWinDDE
-
- TkCommandNames = ['dde'.freeze].freeze
-
- tk_call('package', 'require', 'dde')
-
- def servername(topic=nil)
- tk_call('dde', 'servername', topic)
- end
-
- def execute(service, topic, data)
- tk_call('dde', 'execute', service, topic, data)
- end
-
- def async_execute(service, topic, data)
- tk_call('dde', '-async', 'execute', service, topic, data)
- end
-
- def poke(service, topic, item, data)
- tk_call('dde', 'poke', service, topic, item, data)
- end
-
- def request(service, topic, item)
- tk_call('dde', 'request', service, topic, item)
- end
-
- def services(service, topic)
- tk_call('dde', 'services', service, topic)
- end
-
- def eval(topic, cmd, *args)
- tk_call('dde', 'eval', topic, cmd, *args)
- end
-
- module_function :servername, :execute, :async_execute,
- :poke, :request, :services, :eval
-end
-
-module TkWinRegistry
- extend Tk
- extend TkWinRegistry
-
- TkCommandNames = ['registry'.freeze].freeze
-
- tk_call('package', 'require', 'registry')
-
- def delete(keynam, valnam=nil)
- tk_call('registry', 'delete', keynam, valnam)
- end
-
- def get(keynam, valnam)
- tk_call('registry', 'get', keynam, valnam)
- end
-
- def keys(keynam)
- tk_split_simplelist(tk_call('registry', 'keys', keynam))
- end
-
- def set(keynam, valnam=nil, data=nil, dattype=nil)
- tk_call('registry', 'set', keynam, valnam, data, dattype)
- end
-
- def type(keynam, valnam)
- tk_call('registry', 'type', keynam, valnam)
- end
-
- def values(keynam)
- tk_split_simplelist(tk_call('registry', 'values', keynam))
- end
-
- module_function :delete, :get, :keys, :set, :type, :values
-end
+require 'tk/winpkg'
diff --git a/ext/tcltklib/README.euc b/ext/tk/old-README.tcltklib.eucj
index fd75202c18..fd75202c18 100644
--- a/ext/tcltklib/README.euc
+++ b/ext/tk/old-README.tcltklib.eucj
diff --git a/ext/tk/sample/24hr_clock.rb b/ext/tk/sample/24hr_clock.rb
new file mode 100644
index 0000000000..60d8072c57
--- /dev/null
+++ b/ext/tk/sample/24hr_clock.rb
@@ -0,0 +1,286 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+
+class Clock
+ def initialize(clock24 = true)
+ @clock = (clock24)? 24: 12
+
+ @size = 200
+ @cdot_size = 5
+
+ @cdot_color = 'black'
+ @hour_hand_color = 'black'
+ @minute_hand_color = 'gray25'
+ @second_hand_color = 'gray50'
+
+ @mark_font = 'Helvetica -14'
+ @mark_width = 3
+ @mark_color = 'black'
+ @submark_color = 'gray50'
+
+ @c = TkCanvas.new(:width=>2*@size, :height=>2*@size,
+ :scrollregion=>[-@size, -@size, @size, @size]
+ ).pack(:fill=>:both, :expand=>true)
+
+ @tag = TkcTag.new(@c)
+ @hand_tag = TkcTag.new(@c)
+
+ @circle_coords = [[-0.9*@size, -0.9*@size], [0.9*@size, 0.9*@size]]
+ @oval = TkcOval.new(@c, @circle_coords, :fill=>'white', :tags=>[@tag])
+
+ f = TkFrame.new.pack
+ TkLabel.new(f, :text=>'CURRENT:').pack(:side=>:left)
+ @now = TkLabel.new(f, :text=>'00:00:00').pack(:side=>:left, :padx=>2)
+ TkLabel.new(f, :text=>' ').pack(:side=>:left)
+ TkLabel.new(f, :text=>' ').pack(:side=>:right)
+ @l = TkLabel.new(f, :text=>'00:00').pack(:side=>:right, :padx=>2)
+ TkLabel.new(f, :text=>'MOUSE-POINTER:').pack(:side=>:right)
+
+ cmd = proc{|x, y|
+ @l.text = '%02d:%02d' % coords_to_time(@c.canvasx(x), @c.canvasy(y))
+ }
+ @c.bind('Motion', cmd, '%x %y')
+ @tag.bind('Motion', cmd, '%x %y')
+
+ _create_hands
+ _create_marks
+
+ timer_proc = proc{
+ t = Time.now
+ @now.text = '%02d:%02d:%02d' % [t.hour, t.min, t.sec]
+ set_hands(t.hour, t.min, t.sec)
+ }
+
+ timer_proc.call
+ @timer = TkRTTimer.start(100, -1, timer_proc)
+ end
+
+ def _create_marks
+ @mark_tag = TkcTag.new(@c)
+
+ TkcLine.new(@c, 0, -0.90*@size, 0, -0.85*@size,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@mark_color)
+ TkcLine.new(@c, 0.90*@size, 0, 0.85*@size, 0,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@mark_color)
+ TkcLine.new(@c, 0, 0.90*@size, 0, 0.85*@size,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@mark_color)
+ TkcLine.new(@c, -0.90*@size, 0, -0.85*@size, 0,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@mark_color)
+
+ TkcText.new(@c, [0, -0.92*@size], :text=>0,
+ :anchor=>'s', :fill=>@mark_color)
+ TkcText.new(@c, [0.92*@size, 0], :text=>@clock.div(4),
+ :anchor=>'w', :fill=>@mark_color)
+ TkcText.new(@c, [0, 0.92*@size], :text=>@clock.div(2),
+ :anchor=>'n', :fill=>@mark_color)
+ TkcText.new(@c, [-0.92*@size, 0], :text=>@clock.div(4)*3,
+ :anchor=>'e', :fill=>@mark_color)
+
+ [30.0, 60.0].each{|angle|
+ rad = Math::PI * angle / 180.0
+ x_base = @size*Math::sin(rad)
+ y_base = @size*Math::cos(rad)
+
+ x1 = 0.90*x_base
+ y1 = 0.90*y_base
+
+ x2 = 0.85*x_base
+ y2 = 0.85*y_base
+
+ TkcLine.new(@c, x1, y1, x2, y2,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@mark_color)
+ TkcLine.new(@c, x1, -y1, x2, -y2,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@mark_color)
+ TkcLine.new(@c, -x1, y1, -x2, y2,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@mark_color)
+ TkcLine.new(@c, -x1, -y1, -x2, -y2,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@mark_color)
+
+ x3 = 0.92*x_base
+ y3 = 0.92*y_base
+
+ if @clock == 24
+ dh = angle.to_i/15
+ else # @clock == 12
+ dh = angle.to_i/30
+ end
+
+ TkcText.new(@c, x3, -y3, :text=>dh,
+ :anchor=>'sw', :fill=>@mark_color)
+ TkcText.new(@c, x3, y3, :text=>@clock.div(2)-dh,
+ :anchor=>'nw', :fill=>@mark_color)
+ TkcText.new(@c, -x3, y3, :text=>@clock.div(2)+dh,
+ :anchor=>'ne', :fill=>@mark_color)
+ TkcText.new(@c, -x3, -y3, :text=>@clock-dh,
+ :anchor=>'se', :fill=>@mark_color)
+ }
+
+ if @clock == 24
+ [15.0, 45.0, 75.0].each{|angle|
+ rad = Math::PI * angle / 180.0
+ x_base = @size*Math::sin(rad)
+ y_base = @size*Math::cos(rad)
+
+ x1 = 0.90*x_base
+ y1 = 0.90*y_base
+
+ x2 = 0.875*x_base
+ y2 = 0.875*y_base
+
+ TkcLine.new(@c, x1, y1, x2, y2,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@submark_color)
+ TkcLine.new(@c, x1, -y1, x2, -y2,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@submark_color)
+ TkcLine.new(@c, -x1, y1, -x2, y2,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@submark_color)
+ TkcLine.new(@c, -x1, -y1, -x2, -y2,
+ :tags=>[@tag, @mark_tag],
+ :width=>@mark_width, :fill=>@submark_color)
+ }
+ end
+ end
+
+ def _create_hands
+ hour_hand_len = 0.55*@size
+ minute_hand_len = 0.85*@size
+ second_hand_len = 0.88*@size
+
+ hour_hand_width = 1.8*@cdot_size
+ minute_hand_width = 1.0*@cdot_size
+ second_hand_width = 1 # 0.4*@cdot_size
+
+ @hour_hand_coords = [
+ [0, -0.5*@cdot_size],
+ [hour_hand_width, -0.5*@cdot_size-hour_hand_width],
+ [hour_hand_width, -hour_hand_len+hour_hand_width],
+ [0, -hour_hand_len],
+ [-hour_hand_width, -hour_hand_len+hour_hand_width],
+ [-hour_hand_width, -0.5*@cdot_size-hour_hand_width],
+ ]
+ @minute_hand_coords = [
+ [0, -0.5*@cdot_size],
+ [minute_hand_width, -0.5*@cdot_size - minute_hand_width],
+ [minute_hand_width, -minute_hand_len+minute_hand_width],
+ [0, -minute_hand_len],
+ [-minute_hand_width, -minute_hand_len+minute_hand_width],
+ [-minute_hand_width, -0.5*@cdot_size-minute_hand_width],
+ ]
+ @second_hand_coords = [
+ [0, -0.5*@cdot_size],
+ [second_hand_width, -0.5*@cdot_size - second_hand_width],
+ [second_hand_width, -second_hand_len+second_hand_width],
+ [0, -second_hand_len],
+ [-second_hand_width, -second_hand_len+second_hand_width],
+ [-second_hand_width, -0.5*@cdot_size-second_hand_width],
+ ]
+
+ @hour_hand = TkcPolygon.new(@c, @hour_hand_coords,
+ :tags=>[@tag, @hand_tag],
+ :outline=>@hour_hand_color,
+ :fill=>@hour_hand_color)
+
+ @minute_hand = TkcPolygon.new(@c, @minute_hand_coords,
+ :tags=>[@tag, @hand_tag],
+ :outline=>@minute_hand_color,
+ :fill=>@minute_hand_color)
+
+ @second_hand = TkcPolygon.new(@c, @second_hand_coords,
+ :tags=>[@tag, @hand_tag],
+ :outline=>@second_hand_color,
+ :fill=>@second_hand_color)
+
+ @center_dot = TkcOval.new(@c,
+ [-@cdot_size, -@cdot_size],
+ [@cdot_size, @cdot_size],
+ :outline=>@cdot_color, :fill=>@cdot_color)
+ end
+ private :_create_hands
+
+ def _raise_hands
+ @hour_hand.raise
+ @minute_hand.raise
+ @second_hand.raise
+ @center_dot.raise
+ end
+ private :_raise_hands
+
+ def _raise_marks
+ @mark_tag.raise
+ end
+ private :_raise_marks
+
+ def set_hands(hh, mm, ss)
+ ss_angle = Math::PI * ss / 30.0
+ mm_angle = Math::PI * (mm + ss/60.0) / 30.0
+ hh_angle = Math::PI * (hh + (mm + ss/60.0)/60.0) / (@clock.div(2))
+
+ @second_hand.coords = @second_hand_coords.collect{|x, y|
+ r = Math::hypot(y, x)
+ a = Math::atan2(y, x) + ss_angle
+ [Math::cos(a) * r, Math::sin(a) * r]
+ }
+
+ @minute_hand.coords = @minute_hand_coords.collect{|x, y|
+ r = Math::hypot(y, x)
+ a = Math::atan2(y, x) + mm_angle
+ [Math::cos(a) * r, Math::sin(a) * r]
+ }
+
+ @hour_hand.coords = @hour_hand_coords.collect{|x, y|
+ r = Math::hypot(y, x)
+ a = Math::atan2(y, x) + hh_angle
+ [Math::cos(a) * r, Math::sin(a) * r]
+ }
+
+ _raise_hands
+ _raise_marks
+ end
+
+ def coords_to_time(x, y)
+ return ((y < 0)? [0, 0]: [@clock.div(2), 0]) if x == 0
+ if @clock == 24
+ offset = (x<0&&y<0)? 1800.0: 360.0
+ m_half = 720.0
+ else # @clock == 12
+ offset = (x<0&&y<0)? 900.0: 180.0
+ m_half = 360.0
+ end
+ (offset + m_half*Math.atan2(y,x)/Math::PI).round.divmod(60)
+ end
+
+ def create_pie(hh, mm, span, color='red')
+ if @clock == 24
+ start = 90.0 - (hh*60 + mm)/4.0 # 360.0*(hh*60+mm)/(24*60)
+ extent = -span/4.0
+ else # @clock == 12
+ start = 90.0 - (hh*60 + mm)/2.0 # 360.0*(hh*60+mm)/(12*60)
+ extent = -span/2.0
+ end
+
+ pie = TkcArc.new(@c, @circle_coords, :tags=>[@tag],
+ :outline=>'black', 'fill'=>color,
+ :start=>start, :extent=>extent)
+ _raise_hands
+ _raise_marks
+ pie
+ end
+end
+
+sched = Clock.new
+sched.create_pie(0,0, 60) # 60 minutes from 00:00
+sched.create_pie(6,30, 280, 'green') # 280 minutes from 06:30
+sched.create_pie(15,20, 90, 'blue') # 90 minutes from 15:20
+
+Tk.mainloop
diff --git a/ext/tk/sample/binding_sample.rb b/ext/tk/sample/binding_sample.rb
new file mode 100644
index 0000000000..693cc7de2f
--- /dev/null
+++ b/ext/tk/sample/binding_sample.rb
@@ -0,0 +1,87 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+
+class Button_clone < TkLabel
+ def initialize(*args)
+ @command = nil
+
+ if args[-1].kind_of?(Hash)
+ keys = _symbolkey2str(args.pop)
+ @command = keys.delete('command')
+
+ keys['highlightthickness'] = 1 unless keys.key?('highlightthickness')
+ keys['padx'] = '3m' unless keys.key?('padx')
+ keys['pady'] = '1m' unless keys.key?('pady')
+ keys['relief'] = 'raised' unless keys.key?('relief')
+
+ args.push(keys)
+ end
+
+ super(*args)
+
+ @press = false
+
+ self.bind('Enter', proc{self.background(self.activebackground)})
+ self.bind('Leave', proc{
+ @press = false
+ self.background(self.highlightbackground)
+ self.relief('raised')
+ })
+
+ self.bind('ButtonPress-1', proc{@press = true; self.relief('sunken')})
+ self.bind('ButtonRelease-1', proc{
+ self.relief('raised')
+ @command.call if @press && @command
+ @press = false
+ })
+ end
+
+ def command(cmd = Proc.new)
+ @command = cmd
+ end
+
+ def invoke
+ if @command
+ @command.call
+ else
+ ''
+ end
+ end
+end
+
+TkLabel.new(:text=><<EOT).pack
+This is a sample of 'event binding'.
+The first button is a normal button widget.
+And the second one is a normal label widget
+but with some bindings like a button widget.
+EOT
+
+lbl = TkLabel.new(:foreground=>'red').pack(:pady=>3)
+
+v = TkVariable.new(0)
+
+TkFrame.new{|f|
+ TkLabel.new(f, :text=>'click count : ').pack(:side=>:left)
+ TkLabel.new(f, :textvariable=>v).pack(:side=>:left)
+}.pack
+
+TkButton.new(:text=>'normal Button widget',
+ :command=>proc{
+ puts 'button is clicked!!'
+ lbl.text 'button is clicked!!'
+ v.numeric += 1
+ }){
+ pack(:fill=>:x, :expand=>true)
+}
+
+Button_clone.new(:text=>'Label with Button binding',
+ :command=>proc{
+ puts 'label is clicked!!'
+ lbl.text 'label is clicked!!'
+ v.numeric += 1
+ }){
+ pack(:fill=>:x, :expand=>true)
+}
+
+Tk.mainloop
diff --git a/ext/tk/sample/bindtag_sample.rb b/ext/tk/sample/bindtag_sample.rb
new file mode 100644
index 0000000000..8c93b4a260
--- /dev/null
+++ b/ext/tk/sample/bindtag_sample.rb
@@ -0,0 +1,127 @@
+#!/usr/bin/env ruby
+require 'tk'
+
+TkLabel.new(:text=><<EOT, :justify=>:left).pack
+This is a sample of bindtags and usage of
+Tk.callback_break/Tk.callback_continue.
+Please check the work of following buttons
+(attend the difference between before/after
+ pressing the bottom button), and see the
+source code.
+EOT
+
+def set_class_bind
+ TkButton.bind('ButtonPress-1',
+ proc{puts 'bind "ButtonPress-1" of TkButton class'})
+ TkButton.bind('ButtonRelease-1',
+ proc{puts 'bind "ButtonRelease-1" of TkButton class'})
+end
+
+# set root binding
+r = TkRoot.new
+r.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of root widget'})
+r.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of root widget'})
+
+# set 'all' binding
+TkBindTag::ALL.bind('ButtonPress-1',
+ proc{puts 'bind "ButtonPress-1" of the tag "all"'})
+TkBindTag::ALL.bind('ButtonRelease-1',
+ proc{puts 'bind "ButtonRelease-1" of the tag "all"'})
+
+# create buttons
+b1 = TkButton.new(:text=>'button-1',
+ :command=>proc{puts "command of button-1"}).pack
+b2 = TkButton.new(:text=>'button-2',
+ :command=>proc{puts "command of button-2"}).pack
+b3 = TkButton.new(:text=>'button-3',
+ :command=>proc{puts "command of button-3"}).pack
+b4 = TkButton.new(:text=>'button-4',
+ :command=>proc{puts "command of button-4"}).pack
+b5 = TkButton.new(:text=>'button-5',
+ :command=>proc{puts "command of button-5"}).pack
+
+# set button binding
+b1.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-1'})
+b1.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-1'})
+
+b2.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-2'})
+b2.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-2'})
+
+b3.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-3'})
+b3.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-3'})
+
+b4.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-4'})
+b4.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-4'})
+
+b5.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-5'})
+b5.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-5'})
+
+# create bindtag and set binding
+tag1 = TkBindTag.new
+tag1.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of tag1'})
+tag1.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of tag1'})
+
+tag2 = TkBindTag.new
+tag2.bind('ButtonPress-1',
+ proc{
+ puts 'bind "ButtonPress-1" of tag2'
+ puts 'call Tk.callback_continue'
+ Tk.callback_continue
+ puts 'never see this message'
+ })
+tag2.bind('ButtonRelease-1',
+ proc{
+ puts 'bind "ButtonRelease-1" of tag2'
+ puts 'call Tk.callback_continue'
+ Tk.callback_continue
+ puts 'never see this message'
+ })
+
+tag3 = TkBindTag.new
+tag3.bind('ButtonPress-1',
+ proc{
+ puts 'bind "ButtonPress-1" of tag3'
+ puts 'call Tk.callback_break'
+ Tk.callback_break
+ puts 'never see this message'
+ })
+tag3.bind('ButtonRelease-1',
+ proc{
+ puts 'bind "ButtonRelease-1" of tag3'
+ puts 'call Tk.callback_break'
+ Tk.callback_break
+ puts 'never see this message'
+ })
+
+# set bindtags
+p b1.bindtags
+
+tags = b2.bindtags
+tags[2,0] = tag1
+tags[0,0] = tag1
+b2.bindtags(tags)
+p b2.bindtags
+
+tags = b3.bindtags
+tags[2,0] = tag2
+tags[0,0] = tag2
+b3.bindtags(tags)
+p b3.bindtags
+
+tags = b4.bindtags
+tags[2,0] = tag3
+tags[0,0] = tag3
+b4.bindtags(tags)
+p b4.bindtags
+
+b5.bindtags([tag1, TkButton, tag2, b5])
+
+# create button to set button class binding
+TkButton.new(:text=>'set binding to TkButton class',
+ :command=>proc{
+ puts 'call "set_class_bind"'
+ set_class_bind
+ }).pack(:pady=>7)
+
+# start event-loop
+Tk.mainloop
diff --git a/ext/tk/sample/binstr_usage.rb b/ext/tk/sample/binstr_usage.rb
new file mode 100644
index 0000000000..be8399ba51
--- /dev/null
+++ b/ext/tk/sample/binstr_usage.rb
@@ -0,0 +1,45 @@
+#!/usr/bin/env ruby
+
+require "tk"
+
+TkMessage.new(:width=>360, :text=><<EOM).pack
+This sample shows how to use a binary sequence between Ruby and Tk. \
+This reads the image data from the file as the binary sequence.
+
+To treat the difference of encodings between on Ruby and on Tk seamlessly, \
+Ruby/Tk converts the encoding of string arguments automatically. \
+I think it is comfortable for users on almost all situations. \
+However, when treats a binary sequence, the convert process makes troubles.
+
+Tk::BinaryString class (subclass of Tk::EncodedString class) is the class \
+to avoid such troubles. Please see the source code of this sample. \
+A Tk::BinaryString instance is used to create the image for the center button.
+EOM
+
+ImgFile=[File.dirname(__FILE__), 'images','tcllogo.gif'].join(File::Separator)
+
+ph1 = TkPhotoImage.new(:file=>ImgFile)
+p ph1.configinfo
+
+b_str = Tk::BinaryString(IO.read(ImgFile))
+p [b_str, b_str.encoding]
+
+ph2 = TkPhotoImage.new(:data=>b_str)
+p ph2.configinfo
+p ph2.data(:grayscale=>true)
+
+ph3 = TkPhotoImage.new(:palette=>256)
+ph3.put(ph2.data)
+
+ph4 = TkPhotoImage.new()
+ph4.put(ph2.data(:grayscale=>true))
+
+#p [b_str.encoding, b_str.rb_encoding]
+
+f = TkFrame.new.pack
+TkButton.new(:parent=>f, :image=>ph1, :command=>proc{exit}).pack(:side=>:left)
+TkButton.new(:parent=>f, :image=>ph2, :command=>proc{exit}).pack(:side=>:left)
+TkButton.new(:parent=>f, :image=>ph3, :command=>proc{exit}).pack(:side=>:left)
+TkButton.new(:parent=>f, :image=>ph4, :command=>proc{exit}).pack(:side=>:left)
+
+Tk.mainloop
diff --git a/ext/tk/sample/btn_with_frame.rb b/ext/tk/sample/btn_with_frame.rb
new file mode 100644
index 0000000000..d04c95a289
--- /dev/null
+++ b/ext/tk/sample/btn_with_frame.rb
@@ -0,0 +1,20 @@
+require 'tk'
+
+class Button_with_Frame < TkButton
+ def create_self(keys)
+ @frame = TkFrame.new('widgetname'=>@path, 'background'=>'yellow')
+ install_win(@path) # create new @path which is a daughter of old @path
+ super(keys)
+ TkPack(@path, :padx=>7, :pady=>7)
+ @epath = @frame.path
+ end
+ def epath
+ @epath
+ end
+end
+
+Button_with_Frame.new(:text=>'QUIT', :command=>proc{exit}) {
+ pack(:padx=>15, :pady=>5)
+}
+
+Tk.mainloop
diff --git a/ext/tk/sample/cd_timer.rb b/ext/tk/sample/cd_timer.rb
new file mode 100644
index 0000000000..9154e89bfe
--- /dev/null
+++ b/ext/tk/sample/cd_timer.rb
@@ -0,0 +1,81 @@
+#!/usr/bin/env ruby
+#
+# countdown timer
+# usage: cd_timer min [, min ... ]
+# ( e.g. cd_timer 0.5 1 3 5 10 )
+#
+require 'tk'
+
+if ARGV.empty?
+ $stderr.puts 'Error:: No time arguments for counting down'
+ exit(1)
+end
+
+width = 10
+
+TkButton.new(:text=>'exit',
+ :command=>proc{exit}).pack(:side=>:bottom, :fill=>:x)
+
+b = TkButton.new(:text=>'start').pack(:side=>:top, :fill=>:x)
+
+f = TkFrame.new(:relief=>:ridge, :borderwidth=>2).pack(:fill=>:x)
+TkLabel.new(f, :relief=>:flat, :pady=>3,
+ :background=>'black', :foreground=>'white',
+ :text=>' elapsed: ').pack(:fill=>:x, :side=>:left, :expand=>true)
+now = TkLabel.new(f, :width=>width, :relief=>:flat, :pady=>3, :anchor=>:w,
+ :background=>'black', :foreground=>'white',
+ :text=>'%4d:%02d.00' % [0, 0]).pack(:side=>:right)
+
+timers = [ TkRTTimer.new(10){|tm|
+ t = (tm.return_value || 0) + 1
+ s, u = t.divmod(100)
+ m, s = s.divmod(60)
+ now.text('%4d:%02d.%02d' % [m, s, u])
+ t
+ }.set_start_proc(0, proc{
+ now.text('%4d:%02d.00' % [0,0])
+ now.foreground('white')
+ 0
+ })
+]
+
+ARGV.collect{|arg| (Float(arg) * 60).to_i}.sort.each_with_index{|time, idx|
+ f = TkFrame.new(:relief=>:ridge, :borderwidth=>2).pack(:fill=>:x)
+ TkLabel.new(f, :relief=>:flat, :pady=>3,
+ :text=>' %4d:%02d --> ' % (time.divmod(60))).pack(:side=>:left)
+ l = TkLabel.new(f, :width=>width, :relief=>:flat, :pady=>3, :anchor=>:w,
+ :text=>'%4d:%02d' % (time.divmod(60))).pack(:side=>:right)
+ timers << TkRTTimer.new(1000){|tm|
+ t = (tm.return_value || time) - 1
+ if t < 0
+ l.text('%4d:%02d' % ((-t).divmod(60)))
+ else
+ l.text('%4d:%02d' % (t.divmod(60)))
+ end
+ if t.zero?
+ l.foreground('red')
+ idx.times{Tk.bell}
+ end
+ t
+ }.set_start_proc(0, proc{
+ l.text('%4d:%02d' % (time.divmod(60)))
+ l.foreground('black')
+ time
+ })
+}
+
+mode = :start
+b.command(proc{
+ if mode == :start
+ timers.each{|timer| timer.restart}
+ b.text('reset')
+ mode = :reset
+ else
+ timers.each{|timer| timer.stop.reset}
+ b.text('start')
+ mode = :start
+ end
+ })
+
+Tk.mainloop
+
diff --git a/ext/tk/sample/cmd_res_test.rb b/ext/tk/sample/cmd_res_test.rb
new file mode 100644
index 0000000000..6e954f26ee
--- /dev/null
+++ b/ext/tk/sample/cmd_res_test.rb
@@ -0,0 +1,17 @@
+require 'tk'
+TkOptionDB.readfile(File.expand_path('cmd_resource',
+ File.dirname(__FILE__)))
+f = TkFrame.new(:class=>'BtnFrame').pack
+b = TkButton.new(:parent=>f, :widgetname=>'hello').pack
+cmd1 = TkOptionDB.new_proc_class(b, [:show_msg, :bye_msg], 3)
+cmd2 = TkOptionDB.new_proc_class(:ZZZ, [:show_msg, :bye_msg], 3, false, cmd1)
+cmd3 = TkOptionDB.new_proc_class(:ZZZ, [:show_msg, :bye_msg], 3, false, b)
+cmd4 = TkOptionDB.new_proc_class(:BTN_CMD, [:show_msg, :bye_msg], 3){
+ def self.__check_proc_string__(str)
+ "{|arg| print [arg, $SAFE].inspect, ': '; Proc.new#{str}.call(arg)}"
+ end
+}
+cmd1.show_msg('cmd1')
+cmd2.show_msg('cmd2')
+cmd3.show_msg('cmd3')
+cmd4.show_msg('cmd4')
diff --git a/ext/tk/sample/cmd_resource b/ext/tk/sample/cmd_resource
new file mode 100644
index 0000000000..9cc4915546
--- /dev/null
+++ b/ext/tk/sample/cmd_resource
@@ -0,0 +1,5 @@
+*BtnFrame.hello.text: HELLO
+*BtnFrame.hello.command: ruby {puts "Hello World!!"}
+*BTN_CMD.show_msg: {|arg| print "Hello, #{arg}!!\n"}
+*hello.show_msg: {|arg| print "Hello, Hello, #{arg}!!\n"}
+*hello.ZZZ.show_msg: {|arg| print "Hello, Hello, ZZZ:#{arg}!!\n"}
diff --git a/ext/tk/sample/demos-en/README.1st b/ext/tk/sample/demos-en/README.1st
new file mode 100644
index 0000000000..e031f123d2
--- /dev/null
+++ b/ext/tk/sample/demos-en/README.1st
@@ -0,0 +1,18 @@
+There are Ruby/Tk demo scripts.
+
+Files with '.rb' extension are sub-scripts which are launched 'widget'
+script. Those files don't work independently. Please call them from
+'widget' script.
+
+If you want start some sub-scripts at same time when the launcher
+script tarts, please give the sub-script names as arguments.
+(e.g. /usr/local/bin/ruby widget button.rb entry1.rb text.rb )
+You can ommit '.rb' of the sub-scripts
+(e.g. /usr/local/bin/ruby widget button entry1 text )
+
+If you don't need launcher's main window, give -n option.
+(e.g. /usr/local/bin/ruby widget -n button.rb entry1.rb text.rb )
+
+Others (browse1, hello, and so on) are standalone scripts.
+
+ 2004/04/14 Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tk/sample/demos-en/README.tkencoding b/ext/tk/sample/demos-en/README.tkencoding
index 8fcb494c03..f576bc593e 100644
--- a/ext/tk/sample/demos-en/README.tkencoding
+++ b/ext/tk/sample/demos-en/README.tkencoding
@@ -1,3 +1,8 @@
+This is a original document of 'tkencoding.rb'.
+The library 'tkencoding.rb' is obsolete.
+Functions of tkencoding.rb is already included into Ruby/Tk.
+
+-------------------------------------------------
tkencoding.rb¤òÍѤ¤¤¿ÆüËܸì¤Îɽ¼¨¤Ë¤Ä¤¤¤Æ
Copyright (C) 1999/07, Takaaki Tateishi <ttate@jaist.ac.jp>
diff --git a/ext/tk/sample/demos-en/anilabel.rb b/ext/tk/sample/demos-en/anilabel.rb
new file mode 100644
index 0000000000..0b9bc7357e
--- /dev/null
+++ b/ext/tk/sample/demos-en/anilabel.rb
@@ -0,0 +1,174 @@
+#
+# animated label widget demo (called by 'widget')
+#
+# based on Tcl/Tk8.5a2 widget demos
+
+if defined?($anilabel_demo) && $anilabel_demo
+ $anilabel_demo.destroy
+ $anilabel_demo = nil
+end
+
+# demo toplevel widget
+$anilabel_demo = TkToplevel.new {|w|
+ title("Animated Label Demonstration")
+ iconname("anilabel")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($anilabel_demo).pack(:fill=>:both, :expand=>true)
+
+# label
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '4i'
+ justify 'left'
+ text "Four animated labels are displayed below; each of the labels on the left is animated by making the text message inside it appear to scroll, and the label on the right is animated by animating the image that it displays."
+}
+msg.pack('side'=>'top')
+
+# frame
+TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ text 'Dismiss'
+ command proc{
+ tmppath = $anilabel_demo
+ $anilabel_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text 'See Code'
+ command proc{showCode 'anilabel'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# create frame for label demo
+f_left = TkLabelFrame.new(base_frame, :text=>'Scrolling Texts')
+f_right = TkLabelFrame.new(base_frame, :text=>'GIF Image')
+Tk.pack(f_left, f_right, 'side'=>'left', 'expand'=>'yes', 'fill'=>'both',
+ 'padx'=>10, 'pady'=>10)
+
+# animated label
+class AnimatedTextLabel < TkLabel
+ def initialize(*args)
+ super(*args)
+ @timer = TkTimer.new{ _animation_callback }
+ @timer.loop_exec = -1
+ # bind('Destroy'){ @timer.stop }
+ @btag = TkBindTag.new('Destroy'){ @timer.stop }
+ self.bindtags_unshift(@btag)
+ end
+
+ def _animation_callback()
+ txt = self.text
+ self.text = (txt[1..-1] << txt[0])
+ end
+ private :_animation_callback
+
+ def start(interval)
+ @timer.set_interval(interval)
+ @timer.start
+ end
+
+ def stop
+ @timer.stop
+ end
+end
+
+# animated image
+class AnimatedImageLabel < AnimatedTextLabel
+ def initialize(*args)
+ super(*args)
+ @destroy_image = false
+ @btag.bind_append('Destroy'){
+ if @destroy_image
+ begin
+ self.image.delete
+ rescue
+ end
+ end
+ }
+ end
+ attr_accessor :destroy_image
+
+ def _animation_callback()
+ img = self.image
+
+ fmt = img.format
+ if fmt.kind_of?(Array)
+ if fmt[1].kind_of?(Hash)
+ # fmt == ['GIF', {'index'=>idx}]
+ idx = fmt[1]['index']
+ else
+ # fmt == ['GIF', '-index', idx] :: Ruby1.8.2 returns this.
+ idx = fmt[2]
+ end
+ elsif fmt.kind_of?(String) && fmt =~ /GIF -index (\d+)/
+ idx = $1.to_i
+ else
+ idx = -1
+ end
+
+ begin
+ img.format("GIF -index #{idx + 1}")
+ rescue => e
+ img.format("GIF -index 0")
+ end
+ end
+ private :_animation_callback
+end
+
+# create labels
+l1 = AnimatedTextLabel.new(f_left, :borderwidth=>4, :relief=>:ridge,
+ :font=>{:family=>'Courier', :size=>10})
+l2 = AnimatedTextLabel.new(f_left, :borderwidth=>4, :relief=>:groove,
+ :font=>{:family=>'Courier', :size=>10})
+l3 = AnimatedTextLabel.new(f_left, :borderwidth=>4, :relief=>:flat,
+ :font=>{:family=>'Courier', :size=>10}, :width=>18)
+Tk.pack(l1, l2, l3,
+ :side=>:top, :expand=>true, :anchor=>:w, :padx=>10, :pady=>10)
+
+limg = AnimatedImageLabel.new(f_right, :borderwidth=>0)
+limg.pack(:side=>:top, :expand=>true, :padx=>10, :pady=>10)
+
+# base64-encoded animated GIF file
+tclPowerdData = <<EOD
+ R0lGODlhKgBAAPQAAP//////zP//AP/MzP/Mmf/MAP+Zmf+ZZv+ZAMz//8zM
+ zMyZmcyZZsxmZsxmAMwzAJnMzJmZzJmZmZlmmZlmZplmM5kzM2aZzGZmzGZm
+ mWZmZmYzZmYzMzNmzDMzZgAzmSH+IE1hZGUgd2l0aCBHSU1QIGJ5IExARGVt
+ YWlsbHkuY29tACH5BAVkAAEALAAAAAAqAEAAAAX+YCCOZEkyTKM2jOm66yPP
+ dF03bx7YcuHIDkGBR7SZeIyhTID4FZ+4Es8nQyCe2EeUNJ0peY2s9mi7PhAM
+ ngEAMGRbUpvzSxskLh1J+Hkg134OdDIDEB+GHxtYMEQMTjMGEYeGFoomezaC
+ DZGSHFmLXTQKkh8eNQVpZ2afmDQGHaOYSoEyhhcklzVmMpuHnaZmDqiGJbg0
+ qFqvh6UNAwB7VA+OwydEjgujkgrPNhbTI8dFvNgEYcHcHx0lB1kX2IYeA2G6
+ NN0YfkXJ2BsAMuAzHB9cZMk3qoEbRzUACsRCUBK5JxsC3iMiKd8GN088SIyT
+ 0RAFSROyeEg38caDiB/+JEgqxsODrZJ1BkT0oHKSmI0ceQxo94HDpg0qsuDk
+ UmRAMgu8OgwQ+uIJgUMVeGXA+IQkzEeHGvD8cIGlDXsLiRjQ+EHroQhea7xY
+ 8IQBSgYYDi1IS+OFBCgaDMGVS3fGi5BPJpBaENdQ0EomKGD56IHwO39EXiSC
+ Ysgxor5+Xfgq0qByYUpiXmwuoredB2aYH4gWWda0B7SeNENpEJHC1ghi+pS4
+ AJpIAwWvKPBi+8YEht5EriEqpFfMlhEdkBNpx0HUhwypx5T4IB1MBg/Ws2sn
+ wV3MSQOkzI8fUd48Aw3dOZto71x85hHtHijYv18Gf/3GqCdDCXHNoICBobSo
+ IqBqJLyCoH8JPrLgdh88CKCFD0CGmAiGYPgffwceZh6FC2ohIIklnkhehTNY
+ 4CIHHGzgwYw01ujBBhvAqKOLLq5AAk9kuSPkkKO40NB+h1gnypJIIvkBf09a
+ N5QIRz5p5ZJXJpmlIVhOGQA2TmIJZZhKKmmll2BqyWSXWUrZpQtpatlmk1c2
+ KaWRHeTZEJF8SqLDn/hhsOeQgBbqAh6DGqronxeARUIIACH5BAUeAAAALAUA
+ LgAFAAUAAAUM4CeKz/OV5YmqaRkCACH5BAUeAAEALAUALgAKAAUAAAUUICCK
+ z/OdJVCaa7p+7aOWcDvTZwgAIfkEBR4AAQAsCwAuAAkABQAABRPgA4zP95zA
+ eZqoWqqpyqLkZ38hACH5BAUKAAEALAcALgANAA4AAAU7ICA+jwiUJEqeKau+
+ r+vGaTmac63v/GP9HM7GQyx+jsgkkoRUHJ3Qx0cK/VQVTKtWwbVKn9suNunc
+ WkMAIfkEBQoAAAAsBwA3AAcABQAABRGgIHzk842j+Yjlt5KuO8JmCAAh+QQF
+ CgAAACwLADcABwAFAAAFEeAnfN9TjqP5oOWziq05lmUIACH5BAUKAAAALA8A
+ NwAHAAUAAAUPoPCJTymS3yiQj4qOcPmEACH5BAUKAAAALBMANwAHAAUAAAUR
+ oCB+z/MJX2o+I2miKimiawgAIfkEBQoAAAAsFwA3AAcABQAABRGgIHzfY47j
+ Q4qk+aHl+pZmCAAh+QQFCgAAACwbADcABwAFAAAFEaAgfs/zCV9qPiNJouo7
+ ll8IACH5BAUKAAAALB8ANwADAAUAAAUIoCB8o0iWZggAOw==
+EOD
+
+l1.text('* Slow Animation *').start(300)
+l2.text('* Fast Animation *').start(80)
+l3.text('This is a longer scrolling text in a widget that will not show the whole message at once. ').start(150)
+
+limg.destroy_image = true
+limg.image(TkPhotoImage.new(:format=>'GIF', :data=>tclPowerdData)).start(100)
diff --git a/ext/tk/sample/demos-en/aniwave.rb b/ext/tk/sample/demos-en/aniwave.rb
new file mode 100644
index 0000000000..63a04a7b98
--- /dev/null
+++ b/ext/tk/sample/demos-en/aniwave.rb
@@ -0,0 +1,118 @@
+#
+# animated wave demo (called by 'widget')
+#
+# based on Tcl/Tk8.5a2 widget demos
+
+# destroy toplevel widget for this demo script
+if defined?($aniwave_demo) && $aniwave_demo
+ $aniwave_demo.destroy
+ $aniwave_demo = nil
+end
+
+# create toplevel widget
+$aniwave_demo = TkToplevel.new {|w|
+ title("Animated Wave Demonstration")
+ iconname("aniwave")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($aniwave_demo).pack(:fill=>:both, :expand=>true)
+
+# create label
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '4i'
+ justify 'left'
+ text 'This demonstration contains a canvas widget with a line item inside it. The animation routines work by adjusting the coordinates list of the line.'
+}
+msg.pack('side'=>'top')
+
+# create frame
+TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ text 'Dismiss'
+ command proc{
+ tmppath = $aniwave_demo
+ $aniwave_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text 'See Code'
+ command proc{showCode 'aniwave'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# animated wave
+class AnimatedWaveDemo
+ def initialize(frame, dir=:left)
+ @direction = dir
+
+ # create canvas widget
+ @c = TkCanvas.new(frame, :width=>300, :height=>200,
+ :background=>'black')
+ @c.pack(:padx=>10, :pady=>10, :expand=>true)
+
+ # Creates a coordinates list of a wave.
+ @waveCoords = []
+ @backupCoords = []
+ n = 0
+ (-10..300).step(5){|n| @waveCoords << [n, 100]; @backupCoords << [n, 100] }
+ n = 305
+ @waveCoords << [n, 0]; @backupCoords << [n, 0]
+ @waveCoords << [n+5, 200]; @backupCoords << [n+5, 200]
+ @coordsLen = @waveCoords.length
+
+ # Create a smoothed line and arrange for its coordinates to be the
+ # contents of the variable waveCoords.
+ @line = TkcLine.new(@c, @waveCoords,
+ :width=>1, :fill=>'green', :smooth=>true)
+
+ # Main animation "loop".
+ # Theoretically 100 frames-per-second (==10ms between frames)
+ @timer = TkTimer.new(10){ basicMotion; reverser }
+
+ # Arrange for the animation loop to stop when the canvas is deleted
+ @c.bindtags_unshift(TkBindTag.new('Destroy'){ @timer.stop })
+ end
+
+ # Basic motion handler. Given what direction the wave is travelling
+ # in, it advances the y coordinates in the coordinate-list one step in
+ # that direction.
+ def basicMotion
+ @backupCoords, @waveCoords = @waveCoords, @backupCoords
+ (0...@coordsLen).each{|idx|
+ if @direction == :left
+ @waveCoords[idx][1] = @backupCoords[(idx+1 == @coordsLen)? 0: idx+1][1]
+ else
+ @waveCoords[idx][1] = @backupCoords[(idx == 0)? -1: idx-1][1]
+ end
+ }
+ @line.coords(@waveCoords)
+ end
+
+ # Oscillation handler. This detects whether to reverse the direction
+ # of the wave by checking to see if the peak of the wave has moved off
+ # the screen (whose size we know already.)
+ def reverser
+ if @waveCoords[0][1] < 10
+ @direction = :right
+ elsif @waveCoords[-1][1] < 10
+ @direction = :left
+ end
+ end
+
+ # animation control
+ def move
+ @timer.start
+ end
+
+ def stop
+ @timer.stop
+ end
+end
+
+# Start the animation processing
+AnimatedWaveDemo.new(base_frame, :left).move
diff --git a/ext/tk/sample/demos-en/arrow.rb b/ext/tk/sample/demos-en/arrow.rb
index 8ee13254ea..055cd2af3c 100644
--- a/ext/tk/sample/demos-en/arrow.rb
+++ b/ext/tk/sample/demos-en/arrow.rb
@@ -13,7 +13,7 @@
# interactively.
#
# Arguments:
-# c - Name of the canvas widget.
+# c - Name of the canvas widget.
def arrowSetup(c)
v = $demo_arrowInfo
@@ -29,59 +29,67 @@ def arrowSetup(c)
# Create the arrow and outline.
c.delete('all')
TkcLine.new(c, v.x1, v.y, v.x2, v.y,
- { 'width'=>10 * v.width,
- 'arrowshape'=>[10*v.a, 10*v.b, 10*v.c],
- 'arrow'=>'last'
- }.update(v.bigLineStyle) )
+ { 'width'=>10 * v.width,
+ 'arrowshape'=>[10*v.a, 10*v.b, 10*v.c],
+ 'arrow'=>'last'
+ }.update(v.bigLineStyle) )
xtip = v.x2 - 10*v.b
deltaY = 10*v.c + 5*v.width
TkcLine.new(c, v.x2, v.y, xtip, v.y + deltaY,
- v.x2 - 10*v.a, v.y, xtip, v.y - deltaY, v.x2, v.y,
- 'width'=>2, 'capstyle'=>'round', 'joinstyle'=>'round')
+ v.x2 - 10*v.a, v.y, xtip, v.y - deltaY, v.x2, v.y,
+ 'width'=>2, 'capstyle'=>'round', 'joinstyle'=>'round')
# Create the boxes for reshaping the line and arrowhead.
TkcRectangle.new(c, v.x2-10*v.a-5, v.y-5, v.x2-10*v.a+5, v.y+5,
- {'tags'=>['box1', $arrowTag_box]}.update(v.boxStyle) )
+ {'tags'=>['box1', $arrowTag_box]}.update(v.boxStyle) )
TkcRectangle.new(c, xtip-5, v.y-deltaY-5, xtip+5, v.y-deltaY+5,
- {'tags'=>['box2', $arrowTag_box]}.update(v.boxStyle) )
+ {'tags'=>['box2', $arrowTag_box]}.update(v.boxStyle) )
TkcRectangle.new(c, v.x1-5, v.y-5*v.width-5, v.x1+5, v.y-5*v.width+5,
- {'tags'=>['box3', $arrowTag_box]}.update(v.boxStyle) )
+ {'tags'=>['box3', $arrowTag_box]}.update(v.boxStyle) )
c.itemconfigure cur, v.activeStyle if cur
# Create three arrows in actual size with the same parameters
TkcLine.new(c, v.x2+50, 0, v.x2+50, 1000, 'width'=>2)
tmp = v.x2+100
TkcLine.new(c, tmp, v.y-125, tmp, v.y-75, 'width'=>v.width,
- 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
+ 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
TkcLine.new(c, tmp-25, v.y, tmp+25, v.y, 'width'=>v.width,
- 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
+ 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
TkcLine.new(c, tmp-25, v.y+75, tmp+25, v.y+125, 'width'=>v.width,
- 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
+ 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
# Create a bunch of other arrows and text items showing the
# current dimensions.
tmp = v.x2+10
TkcLine.new(c, tmp, v.y-5*v.width, tmp, v.y-deltaY,
- 'arrow'=>'both', 'arrowshape'=>v.smallTips)
+ 'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x2+15, v.y-deltaY+5*v.c, 'text'=>v.c, 'anchor'=>'w')
tmp = v.x1-10
TkcLine.new(c, tmp, v.y-5*v.width, tmp, v.y+5*v.width,
- 'arrow'=>'both', 'arrowshape'=>v.smallTips)
+ 'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x1-15, v.y, 'text'=>v.width, 'anchor'=>'e')
tmp = v.y+5*v.width+10*v.c+10
TkcLine.new(c, v.x2-10*v.a, tmp, v.x2, tmp,
- 'arrow'=>'both', 'arrowshape'=>v.smallTips)
+ 'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x2-5*v.a, tmp+5, 'text'=>v.a, 'anchor'=>'n')
tmp = tmp+25
TkcLine.new(c, v.x2-10*v.b, tmp, v.x2, tmp,
- 'arrow'=>'both', 'arrowshape'=>v.smallTips)
+ 'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x2-5*v.b, tmp+5, 'text'=>v.b, 'anchor'=>'n')
- TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
- TkcText.new(c, v.x1, 330,
- 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]", 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ if $tk_version =~ /^4.*/
+ TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
+ 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ TkcText.new(c, v.x1, 330,
+ 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]",'anchor'=>'w',
+ 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ else
+ TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
+ 'font'=>'Helvetica 18')
+ TkcText.new(c, v.x1, 330,
+ 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]",
+ 'anchor'=>'w', 'font'=>'Helvetica 18')
+ end
v.count += 1
end
@@ -99,14 +107,16 @@ $arrow_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($arrow_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($arrow_demo, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
- 'text'=>"This widget allows you to experiment with different widths and arrowhead shapes for lines in canvases. To change the line width or the shape of the arrowhead, drag any of the three boxes attached to the oversized arrow. The arrows on the right give examples at normal scale. The text at the bottom shows the configuration options as you'd enter them for a canvas line item."){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
+ 'text'=>"This widget allows you to experiment with different widths and arrowhead shapes for lines in canvases. To change the line width or the shape of the arrowhead, drag any of the three boxes attached to the oversized arrow. The arrows on the right give examples at normal scale. The text at the bottom shows the configuration options as you'd enter them for a canvas line item."){
pack('side'=>'top')
}
# frame
-$arrow_buttons = TkFrame.new($arrow_demo) {|frame|
+$arrow_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -124,15 +134,15 @@ $arrow_buttons = TkFrame.new($arrow_demo) {|frame|
$arrow_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# canvas
-$arrow_canvas = TkCanvas.new($arrow_demo, 'width'=>500, 'height'=>350,
- 'relief'=>'sunken', 'borderwidth'=>2)
+$arrow_canvas = TkCanvas.new(base_frame, 'width'=>500, 'height'=>350,
+ 'relief'=>'sunken', 'borderwidth'=>2)
$arrow_canvas.pack('expand'=>'yes', 'fill'=>'both')
#
unless Struct.const_defined?("ArrowInfo")
$demo_arrowInfo = Struct.new("ArrowInfo", :a, :b, :c, :width, :motionProc,
- :x1, :x2, :y, :smallTips, :count,
- :bigLineStyle, :boxStyle, :activeStyle).new
+ :x1, :x2, :y, :smallTips, :count,
+ :bigLineStyle, :boxStyle, :activeStyle).new
end
$demo_arrowInfo.a = 8
$demo_arrowInfo.b = 10
@@ -150,7 +160,7 @@ if TkWinfo.depth($arrow_canvas) > 1
$demo_arrowInfo.activeStyle = {'fill'=>'red', 'outline'=>'black', 'width'=>1}
else
$demo_arrowInfo.bigLineStyle = {'fill'=>'black',
- 'stipple'=>'@'+[$demo_dir, 'images', 'grey.25'].join(File::Separator)}
+ 'stipple'=>'@'+[$demo_dir,'..','images','grey.25'].join(File::Separator)}
$demo_arrowInfo.boxStyle = {'fill'=>'', 'outline'=>'black', 'width'=>1}
$demo_arrowInfo.activeStyle = {'fill'=>'black','outline'=>'black','width'=>1}
end
@@ -161,16 +171,16 @@ $arrowTag_box.bind('Leave', proc{$arrow_canvas.itemconfigure('current', $demo_ar
$arrowTag_box.bind('B1-Enter', proc{})
$arrowTag_box.bind('B1-Leave', proc{})
$arrow_canvas.itembind('box1', '1',
- proc{$demo_arrowInfo.motionProc \
- = proc{|x,y| arrowMove1 $arrow_canvas, x, y}})
+ proc{$demo_arrowInfo.motionProc \
+ = proc{|x,y| arrowMove1 $arrow_canvas, x, y}})
$arrow_canvas.itembind('box2', '1',
- proc{$demo_arrowInfo.motionProc \
- = proc{|x,y| arrowMove2 $arrow_canvas, x, y}})
+ proc{$demo_arrowInfo.motionProc \
+ = proc{|x,y| arrowMove2 $arrow_canvas, x, y}})
$arrow_canvas.itembind('box3', '1',
- proc{$demo_arrowInfo.motionProc \
- = proc{|x,y| arrowMove3 $arrow_canvas, x, y}})
+ proc{$demo_arrowInfo.motionProc \
+ = proc{|x,y| arrowMove3 $arrow_canvas, x, y}})
$arrowTag_box.bind('B1-Motion',
- proc{|x,y| $demo_arrowInfo.motionProc.call(x,y)}, "%x %y")
+ proc{|x,y| $demo_arrowInfo.motionProc.call(x,y)}, "%x %y")
$arrow_canvas.bind('Any-ButtonRelease-1', proc{arrowSetup $arrow_canvas})
# arrowMove1 --
@@ -179,8 +189,8 @@ $arrow_canvas.bind('Any-ButtonRelease-1', proc{arrowSetup $arrow_canvas})
# for the line and arrowhead.
#
# Arguments:
-# c - The name of the canvas window.
-# x, y - The coordinates of the mouse.
+# c - The name of the canvas window.
+# x, y - The coordinates of the mouse.
def arrowMove1(c,x,y)
v = $demo_arrowInfo
@@ -199,8 +209,8 @@ end
# parameters for the line and arrowhead.
#
# Arguments:
-# c - The name of the canvas window.
-# x, y - The coordinates of the mouse.
+# c - The name of the canvas window.
+# x, y - The coordinates of the mouse.
def arrowMove2(c,x,y)
v = $demo_arrowInfo
@@ -223,8 +233,8 @@ end
# controlling parameters for the line and arrowhead.
#
# Arguments:
-# c - The name of the canvas window.
-# x, y - The coordinates of the mouse.
+# c - The name of the canvas window.
+# x, y - The coordinates of the mouse.
def arrowMove3(c,x,y)
v = $demo_arrowInfo
diff --git a/ext/tk/sample/demos-en/bind.rb b/ext/tk/sample/demos-en/bind.rb
index 5d30d228f0..665592a2bc 100644
--- a/ext/tk/sample/demos-en/bind.rb
+++ b/ext/tk/sample/demos-en/bind.rb
@@ -19,8 +19,10 @@ $bind_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($bind_demo).pack(:fill=>:both, :expand=>true)
+
# frame
-TkFrame.new($bind_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -43,14 +45,14 @@ def tag_binding_for_bind_demo(tag, enter_style, leave_style)
end
# text
-TkText.new($bind_demo){|t|
+txt = TkText.new(base_frame){|t|
#
setgrid 'true'
- width 60
- height 24
+ #width 60
+ #height 24
font $font
wrap 'word'
- TkScrollbar.new($bind_demo) {|s|
+ TkScrollbar.new(base_frame) {|s|
pack('side'=>'right', 'fill'=>'y')
command proc{|*args| t.yview(*args)}
t.yscrollcommand proc{|first,last| s.set first,last}
@@ -67,7 +69,7 @@ TkText.new($bind_demo){|t|
tagstyle_normal = {'foreground'=>'', 'background'=>''}
end
- # ¥Æ¥­¥¹¥ÈÁÞÆþ
+ # insert text
insert 'insert', "The same tag mechanism that controls display styles in text widgets can also be used to associate Tcl commands with regions of text, so that mouse or keyboard actions on the text cause particular Tcl commands to be invoked. For example, in the text below the descriptions of the canvas demonstrations have been tagged. When you move the mouse over a demo description the description lights up, and when you press button 1 over a description then that particular demonstration is invoked.
"
@@ -76,35 +78,50 @@ TkText.new($bind_demo){|t|
insert('end', '2. A simple two-dimensional plot that allows you to adjust the positions of the data points.', (d2 = TkTextTag.new(t)) )
insert('end', "\n\n")
insert('end', '3. Anchoring and justification modes for text items.',
- (d3 = TkTextTag.new(t)) )
+ (d3 = TkTextTag.new(t)) )
insert('end', "\n\n")
insert('end', '4. An editor for arrow-head shapes for line items.',
- (d4 = TkTextTag.new(t)) )
+ (d4 = TkTextTag.new(t)) )
insert('end', "\n\n")
insert('end', '5. A ruler with facilities for editing tab stops.',
- (d5 = TkTextTag.new(t)) )
+ (d5 = TkTextTag.new(t)) )
insert('end', "\n\n")
insert('end',
- '6. A grid that demonstrates how canvases can be scrolled.',
- (d6 = TkTextTag.new(t)) )
+ '6. A grid that demonstrates how canvases can be scrolled.',
+ (d6 = TkTextTag.new(t)) )
# binding
[d1, d2, d3, d4, d5, d6].each{|tag|
tag_binding_for_bind_demo(tag, tagstyle_bold, tagstyle_normal)
}
d1.bind('1',
- proc{eval `cat #{[$demo_dir,'items.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'items.rb'].join(File::Separator)}`, 'items.rb')
+ })
d2.bind('1',
- proc{eval `cat #{[$demo_dir,'plot.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'plot.rb'].join(File::Separator)}`, 'plot.rb')
+ })
d3.bind('1',
- proc{eval `cat #{[$demo_dir,'ctext.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'ctext.rb'].join(File::Separator)}`, 'ctext.rb')
+ })
d4.bind('1',
- proc{eval `cat #{[$demo_dir,'arrow.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'arrow.rb'].join(File::Separator)}`, 'arrow.rb')
+ })
d5.bind('1',
- proc{eval `cat #{[$demo_dir,'ruler.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'ruler.rb'].join(File::Separator)}`, 'ruler.rb')
+ })
d6.bind('1',
- proc{eval `cat #{[$demo_dir,'cscroll.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'cscroll.rb'].join(File::Separator)}`, 'cscroll.rb')
+ })
TkTextMarkInsert.new(t, '0.0')
configure('state','disabled')
}
+
+txt.width 60
+txt.height 24
diff --git a/ext/tk/sample/demos-en/bitmap.rb b/ext/tk/sample/demos-en/bitmap.rb
index c81e4ac595..133adb0543 100644
--- a/ext/tk/sample/demos-en/bitmap.rb
+++ b/ext/tk/sample/demos-en/bitmap.rb
@@ -9,19 +9,19 @@
# Create a row of bitmap items in a window.
#
# Arguments:
-# w - The parent window that is to contain the row.
-# args - The names of one or more bitmaps, which will be displayed
-# in a new row across the bottom of w along with their
-# names.
+# w - The parent window that is to contain the row.
+# args - The names of one or more bitmaps, which will be displayed
+# in a new row across the bottom of w along with their
+# names.
def bitmapRow(w,*args)
TkFrame.new(w){|row|
pack('side'=>'top', 'fill'=>'both')
for bitmap in args
TkFrame.new(row){|base|
- pack('side'=>'left', 'fill'=>'both', 'pady'=>'.25c', 'padx'=>'.25c')
- TkLabel.new(base, 'text'=>bitmap, 'width'=>9).pack('side'=>'bottom')
- TkLabel.new(base, 'bitmap'=>bitmap).pack('side'=>'bottom')
+ pack('side'=>'left', 'fill'=>'both', 'pady'=>'.25c', 'padx'=>'.25c')
+ TkLabel.new(base, 'text'=>bitmap, 'width'=>9).pack('side'=>'bottom')
+ Tk::Label.new(base, 'bitmap'=>bitmap).pack('side'=>'bottom')
}
end
}
@@ -40,14 +40,16 @@ $bitmap_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($bitmap_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($bitmap_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
- 'text'=>"This window displays all of Tk's built-in bitmaps, along with the names you can use for them in Tcl scripts."){
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
+ 'text'=>"This window displays all of Tk's built-in bitmaps, along with the names you can use for them in Tcl scripts."){
pack('side'=>'top')
}
# frame
-$bitmap_buttons = TkFrame.new($bitmap_demo) {|frame|
+$bitmap_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -65,7 +67,7 @@ $bitmap_buttons = TkFrame.new($bitmap_demo) {|frame|
$bitmap_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
-TkFrame.new($bitmap_demo){|f|
+TkFrame.new(base_frame){|f|
bitmapRow(f,'error','gray25','gray50','hourglass')
bitmapRow(f,'info','question','questhead','warning')
pack('side'=>'top', 'expand'=>'yes', 'fill'=>'both')
diff --git a/ext/tk/sample/demos-en/browse2 b/ext/tk/sample/demos-en/browse2
index 304a5f547e..edad04dbcb 100644
--- a/ext/tk/sample/demos-en/browse2
+++ b/ext/tk/sample/demos-en/browse2
@@ -39,11 +39,11 @@ class Browse
}
# Set up bindings for the browser.
- base.bind('Control-c',
- proc{
- base.destroy
+ base.bind('Destroy', proc{
Browse::BROWSE_WIN_COUNTER.value = \
- Browse::BROWSE_WIN_COUNTER.to_i - 1})
+ Browse::BROWSE_WIN_COUNTER.to_i - 1
+ })
+ base.bind('Control-c', proc{base.destroy})
list.bind('Double-Button-1',
proc{TkSelection.get.each{|f| self.browse dir, f}})
end
diff --git a/ext/tk/sample/demos-en/button.rb b/ext/tk/sample/demos-en/button.rb
index 6614d99c92..5c03bd499b 100644
--- a/ext/tk/sample/demos-en/button.rb
+++ b/ext/tk/sample/demos-en/button.rb
@@ -29,7 +29,7 @@ msg = TkLabel.new($button_demo) {
msg.pack('side'=>'top')
# frame
-$button_buttons = TkFrame.new($button_demo) {|frame|
+$button_buttons = Tk::Frame.new($button_demo) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
diff --git a/ext/tk/sample/demos-en/check.rb b/ext/tk/sample/demos-en/check.rb
index b5def6a89b..2951962a79 100644
--- a/ext/tk/sample/demos-en/check.rb
+++ b/ext/tk/sample/demos-en/check.rb
@@ -19,8 +19,10 @@ $check_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($check_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($check_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -34,7 +36,7 @@ brakes = TkVariable.new(0)
sober = TkVariable.new(0)
# frame
-TkFrame.new($check_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -54,8 +56,8 @@ TkFrame.new($check_demo) {|frame|
TkButton.new(frame) {
text 'See Variables'
command proc{
- showVars($check_demo,
- ['wipers', wipers], ['brakes', brakes], ['sober', sober])
+ showVars(base_frame,
+ ['wipers', wipers], ['brakes', brakes], ['sober', sober])
}
}.pack('side'=>'left', 'expand'=>'yes')
@@ -63,8 +65,8 @@ TkFrame.new($check_demo) {|frame|
# checkbutton
-[ TkCheckButton.new($check_demo, 'text'=>'Wipers OK', 'variable'=>wipers),
- TkCheckButton.new($check_demo, 'text'=>'Brakes OK', 'variable'=>brakes),
- TkCheckButton.new($check_demo, 'text'=>'Driver Sober', 'variable'=>sober)
+[ TkCheckButton.new(base_frame, 'text'=>'Wipers OK', 'variable'=>wipers),
+ TkCheckButton.new(base_frame, 'text'=>'Brakes OK', 'variable'=>brakes),
+ TkCheckButton.new(base_frame, 'text'=>'Driver Sober', 'variable'=>sober)
].each{|w| w.relief('flat'); w.pack('side'=>'top', 'pady'=>2, 'anchor'=>'w')}
diff --git a/ext/tk/sample/demos-en/check2.rb b/ext/tk/sample/demos-en/check2.rb
new file mode 100644
index 0000000000..faea748a87
--- /dev/null
+++ b/ext/tk/sample/demos-en/check2.rb
@@ -0,0 +1,109 @@
+#
+# checkbutton widget demo2 (called by 'widget')
+#
+
+# delete old toplevel widget
+if defined?($check2_demo) && $check2_demo
+ $check2_demo.destroy
+ $check2_demo = nil
+end
+
+# create demo toplevel widget
+$check2_demo = TkToplevel.new {|w|
+ title("Checkbutton Demonstration 2")
+ iconname("check2")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($check2_demo).pack(:fill=>:both, :expand=>true)
+
+# label
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '4i'
+ justify 'left'
+ text "Four checkbuttons are displayed below. If you click on a button, it will toggle the button's selection state and set a Tcl variable to a value indicating the state of the checkbutton. The first button also follows the state of the other three. If only some of the three are checked, the first button will display the tri-state mode. Click the \"See Variables\" button to see the current values of the variables."
+}
+msg.pack('side'=>'top')
+
+# variable
+safety = TkVariable.new(0)
+wipers = TkVariable.new(0)
+brakes = TkVariable.new(0)
+sober = TkVariable.new(0)
+
+# frame
+TkFrame.new(base_frame) {|frame|
+ TkGrid(TkFrame.new(frame, :height=>2, :relief=>:sunken, :bd=>2),
+ :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ TkButton.new(frame, :text=>'See Variables',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{
+ showVars($check2_demo,
+ ['safety', safety], ['wipers', wipers],
+ ['brakes', brakes], ['sober', sober])
+ }),
+ TkButton.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'check2'}),
+ TkButton.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ tmppath = $check2_demo
+ $check2_demo = nil
+ $showVarsWin[tmppath.path] = nil
+ tmppath.destroy
+ }),
+ :padx=>4, :pady=>4)
+ frame.grid_columnconfigure(0, :weight=>1)
+}.pack('side'=>'bottom', 'fill'=>'x')
+
+
+# checkbutton
+TkCheckButton.new(base_frame, :text=>'Safety Check', :variable=>safety,
+ :relief=>:flat, :onvalue=>'all', :offvalue=>'none',
+ :tristatevalue=>'partial'){
+ pack('side'=>'top', 'pady'=>2, 'anchor'=>'w')
+}
+
+[ TkCheckButton.new(base_frame, 'text'=>'Wipers OK', 'variable'=>wipers),
+ TkCheckButton.new(base_frame, 'text'=>'Brakes OK', 'variable'=>brakes),
+ TkCheckButton.new(base_frame, 'text'=>'Driver Sober', 'variable'=>sober)
+].each{|w|
+ w.relief('flat')
+ w.pack('side'=>'top', 'padx'=>15, 'pady'=>2, 'anchor'=>'w')
+}
+
+# tristate check
+in_check = false
+tristate_check = proc{|n1,n2,op|
+ unless in_check
+ in_check = true
+ begin
+ if n1 == safety
+ if safety == 'none'
+ wipers.value = 0
+ brakes.value = 0
+ sober.value = 0
+ elsif safety == 'all'
+ wipers.value = 1
+ brakes.value = 1
+ sober.value = 1
+ end
+ else
+ if wipers == 1 && brakes == 1 && sober == 1
+ safety.value = 'all'
+ elsif wipers == 1 || brakes == 1 || sober == 1
+ safety.value = 'partial'
+ else
+ safety.value = 'none'
+ end
+ end
+ ensure
+ in_check = false
+ end
+ end
+}
+
+[wipers, brakes, sober, safety].each{|v| v.trace('w', tristate_check)}
diff --git a/ext/tk/sample/demos-en/clrpick.rb b/ext/tk/sample/demos-en/clrpick.rb
index 72c52a4394..431439d55d 100644
--- a/ext/tk/sample/demos-en/clrpick.rb
+++ b/ext/tk/sample/demos-en/clrpick.rb
@@ -4,6 +4,8 @@
#
# widget demo prompts the user to select a color (called by 'widget')
#
+# Note: don't support ttk_wrapper. work with standard widgets only.
+#
# toplevel widget
if defined?($clrpick_demo) && $clrpick_demo
@@ -18,13 +20,18 @@ $clrpick_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($clrpick_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($clrpick_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
- 'text'=>"Press the buttons below to choose the foreground and background colors for the widgets in this window.").pack('side'=>'top')
+#TkLabel.new($clrpick_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
+Tk::Label.new($clrpick_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
+ 'text'=>"Press the buttons below to choose the foreground and background colors for the widgets in this window.").pack('side'=>'top')
# frame
-TkFrame.new($clrpick_demo) {|frame|
- TkButton.new(frame) {
+#TkFrame.new($clrpick_demo) {|frame|
+Tk::Frame.new($clrpick_demo) {|frame|
+ # TkButton.new(frame) {
+ Tk::Button.new(frame) {
text 'Dismiss'
command proc{
tmppath = $clrpick_demo
@@ -33,20 +40,23 @@ TkFrame.new($clrpick_demo) {|frame|
}
}.pack('side'=>'left', 'expand'=>'yes')
- TkButton.new(frame) {
+ # TkButton.new(frame) {
+ Tk::Button.new(frame) {
text 'Show Code'
command proc{showCode 'clrpick'}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# button
-TkButton.new($clrpick_demo, 'text'=>'Set background color ...') {|b|
+# TkButton.new($clrpick_demo, 'text'=>'Set background color ...') {|b|
+Tk::Button.new($clrpick_demo, 'text'=>'Set background color ...') {|b|
command(proc{setColor $clrpick_demo, b, 'background',
- ['background', 'highlightbackground']})
+ ['background', 'highlightbackground']})
pack('side'=>'top', 'anchor'=>'c', 'pady'=>'2m')
}
-TkButton.new($clrpick_demo, 'text'=>'Set foreground color ...') {|b|
+# TkButton.new($clrpick_demo, 'text'=>'Set foreground color ...') {|b|
+Tk::Button.new($clrpick_demo, 'text'=>'Set foreground color ...') {|b|
command(proc{setColor $clrpick_demo, b, 'foreground', ['foreground']})
pack('side'=>'top', 'anchor'=>'c', 'pady'=>'2m')
}
@@ -55,7 +65,7 @@ def setColor(w,button,name,options)
w.grab
initialColor = button[name]
color = Tk.chooseColor('title'=>"Choose a #{name} color", 'parent'=>w,
- 'initialcolor'=>initialColor)
+ 'initialcolor'=>initialColor)
if color != ""
setColor_helper(w,options,color)
end
diff --git a/ext/tk/sample/demos-en/colors.rb b/ext/tk/sample/demos-en/colors.rb
index 66fb0afa36..4300a660ae 100644
--- a/ext/tk/sample/demos-en/colors.rb
+++ b/ext/tk/sample/demos-en/colors.rb
@@ -20,8 +20,10 @@ $colors_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($colors_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($colors_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -30,7 +32,7 @@ msg = TkLabel.new($colors_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($colors_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -49,7 +51,7 @@ TkFrame.new($colors_demo) {|frame|
# frame
colors_lbox = nil
-TkFrame.new($colors_demo, 'borderwidth'=>10) {|w|
+TkFrame.new(base_frame, 'borderwidth'=>10) {|w|
s = TkScrollbar.new(w)
colors_lbox = TkListbox.new(w) {
setgrid 1
@@ -62,7 +64,15 @@ TkFrame.new($colors_demo, 'borderwidth'=>10) {|w|
colors_lbox.pack('side'=>'left', 'expand'=>1, 'fill'=>'both')
}.pack('side'=>'top', 'expand'=>'yes', 'fill'=>'y')
-colors_lbox.bind('Double-1', proc{TkPalette.setPalette TkSelection.get})
+#colors_lbox.bind('Double-1', proc{TkPalette.setPalette TkSelection.get})
+colors_lbox.bind('Double-1', proc{
+ begin
+ TkPalette.setPalette TkSelection.get
+ rescue => e
+ p e
+ Tk.tk_call_without_enc('destroy', '.___tk_set_palette')
+ end
+ })
ins_data = [
'gray60','gray70','gray80','gray85','gray90','gray95',
diff --git a/ext/tk/sample/demos-en/combo.rb b/ext/tk/sample/demos-en/combo.rb
new file mode 100644
index 0000000000..0907d9e8ec
--- /dev/null
+++ b/ext/tk/sample/demos-en/combo.rb
@@ -0,0 +1,96 @@
+# combo.rb --
+#
+# This demonstration script creates several combobox widgets.
+#
+# based on "Id: combo.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($combo_demo) && $combo_demo
+ $combo_demo.destroy
+ $combo_demo = nil
+end
+
+$combo_demo = TkToplevel.new {|w|
+ title("Combobox Demonstration")
+ iconname("combo")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($combo_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'5i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top, :fill=>:x)
+Three different combo-boxes are displayed below. \
+You can add characters to the first \
+one by pointing, clicking and typing, just as with an entry; pressing \
+Return will cause the current value to be added to the list that is \
+selectable from the drop-down list, and you can choose other values \
+by pressing the Down key, using the arrow keys to pick another one, \
+and pressing Return again. The second combo-box is fixed to a \
+particular value, and cannot be modified at all. The third one only \
+allows you to select values from its drop-down list of Australian \
+cities.
+EOL
+
+## variables
+firstValue = TkVariable.new
+secondValue = TkVariable.new
+ozCity = TkVariable.new
+
+## See Code / Dismiss buttons
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Variables',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{
+ showVars(base_frame,
+ ['firstVariable', firstValue],
+ ['secondVariable', secondValue],
+ ['ozCity', ozCity])
+ }),
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'combo'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $combo_demo.destroy
+ $combo_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+frame = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+
+australianCities = [
+ 'Canberra', 'Sydney', 'Melbourne', 'Perth', 'Adelaide', 'Brisbane',
+ 'Hobart', 'Darwin', 'Alice Springs'
+]
+
+
+secondValue.value = 'unchangable'
+ozCity.value = 'Sydney'
+
+Tk.pack(Ttk::Labelframe.new(frame, :text=>'Fully Editable'){|f|
+ Ttk::Combobox.new(f, :textvariable=>firstValue){|b|
+ b.bind('Return', '%W'){|w|
+ w.values <<= w.value unless w.values.include?(w.value)
+ }
+ }.pack(:pady=>5, :padx=>10)
+ },
+
+ Ttk::LabelFrame.new(frame, :text=>'Disabled'){|f|
+ Ttk::Combobox.new(f, :textvariable=>secondValue, :state=>:disabled) .
+ pack(:pady=>5, :padx=>10)
+ },
+
+ Ttk::LabelFrame.new(frame, :text=>'Defined List Only'){|f|
+ Ttk::Combobox.new(f, :textvariable=>ozCity, :state=>:readonly,
+ :values=>australianCities) .
+ pack(:pady=>5, :padx=>10)
+ },
+
+ :side=>:top, :pady=>5, :padx=>10)
diff --git a/ext/tk/sample/demos-en/cscroll.rb b/ext/tk/sample/demos-en/cscroll.rb
index 2f2be60da2..259ed3bd8c 100644
--- a/ext/tk/sample/demos-en/cscroll.rb
+++ b/ext/tk/sample/demos-en/cscroll.rb
@@ -19,14 +19,16 @@ $cscroll_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($cscroll_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($cscroll_demo, 'font'=>$font, 'wraplength'=>'4i',
- 'justify'=>'left', 'text'=>"This window displays a canvas widget that can be scrolled either using the scrollbars or by dragging with button 2 in the canvas. If you click button 1 on one of the rectangles, its indices will be printed on stdout."){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'4i',
+ 'justify'=>'left', 'text'=>"This window displays a canvas widget that can be scrolled either using the scrollbars or by dragging with button 2 in the canvas. If you click button 1 on one of the rectangles, its indices will be printed on stdout."){
pack('side'=>'top')
}
# frame
-$cscroll_buttons = TkFrame.new($cscroll_demo) {|frame|
+$cscroll_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -45,43 +47,43 @@ $cscroll_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
unless $tk_version =~ /^4\.[01]/
- $cscroll_grid = TkFrame.new($cscroll_demo) {
+ $cscroll_grid = TkFrame.new(base_frame) {
pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
}
TkGrid.rowconfigure($cscroll_grid, 0, 'weight'=>1, 'minsize'=>0)
TkGrid.columnconfigure($cscroll_grid, 0, 'weight'=>1, 'minsize'=>0)
end
-# canvas ÀßÄê
-$cscroll_canvas = TkCanvas.new($cscroll_demo,
- 'relief'=>'sunken', 'borderwidth'=>2,
- 'scrollregion'=>['-11c', '-11c', '50c', '20c']
- ) {|c|
+# canvas
+$cscroll_canvas = TkCanvas.new(base_frame,
+ 'relief'=>'sunken', 'borderwidth'=>2,
+ 'scrollregion'=>['-11c', '-11c', '50c', '20c']
+ ) {|c|
if $tk_version =~ /^4\.[01]/
pack('expand'=>'yes', 'fill'=>'both')
else
grid('in'=>$cscroll_grid, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
end
- TkScrollbar.new($cscroll_demo, 'command'=>proc{|*args| c.yview(*args)}) {|vs|
+ TkScrollbar.new(base_frame, 'command'=>proc{|*args| c.yview(*args)}) {|vs|
c.yscrollcommand(proc{|first,last| vs.set first,last})
if $tk_version =~ /^4\.[01]/
pack('side'=>'right', 'fill'=>'y')
else
grid('in'=>$cscroll_grid, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
end
}
- TkScrollbar.new($cscroll_demo, 'orient'=>'horiz',
- 'command'=>proc{|*args| c.xview(*args)}) {|hs|
+ TkScrollbar.new(base_frame, 'orient'=>'horiz',
+ 'command'=>proc{|*args| c.xview(*args)}) {|hs|
c.xscrollcommand(proc{|first,last| hs.set first,last})
if $tk_version =~ /^4\.[01]/
pack('side'=>'bottom', 'fill'=>'x')
else
grid('in'=>$cscroll_grid, 'padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
end
}
}
@@ -92,9 +94,9 @@ bg = $cscroll_canvas.configinfo('bg')[4]
y = -10
(0..9).each{|j|
TkcRectangle.new($cscroll_canvas, "#{x}c", "#{y}c", "#{x+2}c", "#{y+2}c",
- 'outline'=>'black', 'fill'=>bg, 'tags'=>'rect')
+ 'outline'=>'black', 'fill'=>bg, 'tags'=>'rect')
TkcText.new($cscroll_canvas, "#{x+1}c", "#{y+1}c",
- 'text'=>"#{i},#{j}", 'anchor'=>'center', 'tags'=>'text')
+ 'text'=>"#{i},#{j}", 'anchor'=>'center', 'tags'=>'text')
y += 3
}
}
@@ -105,7 +107,7 @@ $cscroll_canvas.itembind('all', '1', proc{scrollButton $cscroll_canvas})
$cscroll_canvas.itembind('all', 'Any-Enter', proc{scrollEnter $cscroll_canvas})
$cscroll_canvas.bind('2', proc{|x,y| $cscroll_canvas.scan_mark(x,y)}, '%x %y')
$cscroll_canvas.bind('B2-Motion',
- proc{|x,y| $cscroll_canvas.scan_dragto(x,y)}, '%x %y')
+ proc{|x,y| $cscroll_canvas.scan_dragto(x,y)}, '%x %y')
def scrollEnter(c)
id = c.find_withtag('current')[0].id
diff --git a/ext/tk/sample/demos-en/ctext.rb b/ext/tk/sample/demos-en/ctext.rb
index 13f8de7218..01374b0321 100644
--- a/ext/tk/sample/demos-en/ctext.rb
+++ b/ext/tk/sample/demos-en/ctext.rb
@@ -19,9 +19,11 @@ $ctext_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($ctext_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($ctext_demo, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
- 'text'=>"This window displays a string of text to demonstrate the text facilities of canvas widgets. You can click in the boxes to adjust the position of the text relative to its positioning point or change its justification. The text also supports the following simple bindings for editing:
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
+ 'text'=>"This window displays a string of text to demonstrate the text facilities of canvas widgets. You can click in the boxes to adjust the position of the text relative to its positioning point or change its justification. The text also supports the following simple bindings for editing:
1. You can point, click, and type.
2. You can also select with button 1.
3. You can copy the selection to the mouse position with button 2.
@@ -33,7 +35,7 @@ TkLabel.new($ctext_demo, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
}
# frame
-$ctext_buttons = TkFrame.new($ctext_demo) {|frame|
+$ctext_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -51,46 +53,55 @@ $ctext_buttons = TkFrame.new($ctext_demo) {|frame|
$ctext_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# canvas
-$ctext_canvas = TkCanvas.new($ctext_demo, 'relief'=>'flat',
- 'borderwidth'=>0, 'width'=>500, 'height'=>350)
+$ctext_canvas = TkCanvas.new(base_frame, 'relief'=>'flat',
+ 'borderwidth'=>0, 'width'=>500, 'height'=>350)
$ctext_canvas.pack('side'=>'top', 'expand'=>'yes', 'fill'=>'both')
# font
-textFont = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+if $tk_version =~ /^4.*/
+ textFont = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+else
+ textFont = 'Helvetica 24'
+end
# canvas
TkcRectangle.new($ctext_canvas, 245, 195, 255, 205,
- 'outline'=>'black', 'fill'=>'red')
+ 'outline'=>'black', 'fill'=>'red')
+
+ctag_text_param = {
+ 'text'=>"This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been been defined to support editing (see above).",
+ 'width'=>440, 'anchor'=>'n', 'justify'=>'left'
+}
+if $tk_version =~ /^4.*/
+ ctag_text_param['font'] = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+else
+ ctag_text_param['font'] = 'Helvetica 24'
+end
$ctag_text = TkcTag.new($ctext_canvas)
-$ctag_text.withtag(TkcText.new($ctext_canvas, 250, 200,
- 'text'=>"This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been been defined to support editing (see above).",
- 'width'=>440, 'anchor'=>'n',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*',
- 'kanjifont'=>'-*--24-*-jisx0208.1983-0',
- 'justify'=>'left') )
+$ctag_text.withtag(TkcText.new($ctext_canvas, 250, 200, ctag_text_param))
$ctag_text.bind('1', proc{|x,y| textB1Press $ctext_canvas,x,y}, "%x %y")
$ctag_text.bind('B1-Motion', proc{|x,y| textB1Move $ctext_canvas,x,y}, "%x %y")
$ctag_text.bind('Shift-1',
- proc{|x,y| $ctext_canvas.seleect_adjust 'current', "@#{x},#{y}"},
- "%x %y")
+ proc{|x,y| $ctext_canvas.seleect_adjust 'current', "@#{x},#{y}"},
+ "%x %y")
$ctag_text.bind('Shift-B1-Motion',
- proc{|x,y| textB1Move $ctext_canvas,x,y}, "%x %y")
+ proc{|x,y| textB1Move $ctext_canvas,x,y}, "%x %y")
$ctag_text.bind('KeyPress', proc{|a| textInsert $ctext_canvas,a}, "%A")
$ctag_text.bind('Return', proc{textInsert $ctext_canvas,"\n"})
$ctag_text.bind('Control-h', proc{textBs $ctext_canvas})
$ctag_text.bind('BackSpace', proc{textBs $ctext_canvas})
$ctag_text.bind('Delete', proc{textDel $ctext_canvas})
$ctag_text.bind('2', proc{|x,y| textPaste $ctext_canvas, "@#{x},#{y}"},
- "%x %y")
+ "%x %y")
# Next, create some items that allow the text's anchor position
# to be edited.
def mkTextConfig(w,x,y,option,value,color)
item = TkcRectangle.new(w, x, y, x+30, y+30,
- 'outline'=>'black', 'fill'=>color, 'width'=>1)
+ 'outline'=>'black', 'fill'=>color, 'width'=>1)
item.bind('1', proc{$ctag_text.configure option, value})
w.addtag_withtag('config', item)
end
@@ -108,11 +119,16 @@ mkTextConfig $ctext_canvas, x, y+60, 'anchor', 'ne', color
mkTextConfig $ctext_canvas, x+30, y+60, 'anchor', 'n', color
mkTextConfig $ctext_canvas, x+60, y+60, 'anchor', 'nw', color
item = TkcRectangle.new($ctext_canvas, x+40, y+40, x+50, y+50,
- 'outline'=>'black', 'fill'=>'red')
+ 'outline'=>'black', 'fill'=>'red')
item.bind('1', proc{$ctag_text.configure 'anchor', 'center'})
-TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position', 'anchor'=>'s',
- 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
- 'fill'=>'brown')
+if $tk_version =~ /^4.*/
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position',
+ 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
+ 'anchor'=>'s', 'fill'=>'brown')
+else
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position',
+ 'font'=>'Times 24', 'anchor'=>'s', 'fill'=>'brown')
+end
# Lastly, create some items that allow the text's justification to be
# changed.
@@ -123,15 +139,20 @@ color = 'SeaGreen2'
mkTextConfig $ctext_canvas, x, y, 'justify', 'left', color
mkTextConfig $ctext_canvas, x+30, y, 'justify', 'center', color
mkTextConfig $ctext_canvas, x+60, y, 'justify', 'right', color
-TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification', 'anchor'=>'s',
- 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
- 'fill'=>'brown')
+if $tk_version =~ /^4.*/
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification',
+ 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
+ 'anchor'=>'s', 'fill'=>'brown')
+else
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification',
+ 'font'=>'Times 24', 'anchor'=>'s', 'fill'=>'brown')
+end
$ctext_canvas.itembind('config', 'Enter', proc{textEnter $ctext_canvas})
$ctext_canvas.itembind('config', 'Leave',
- proc{$ctext_canvas\
- .itemconfigure('current',
- 'fill'=>$textConfigFill)})
+ proc{$ctext_canvas\
+ .itemconfigure('current',
+ 'fill'=>$textConfigFill)})
$textConfigFill = ''
diff --git a/ext/tk/sample/demos-en/dialog1.rb b/ext/tk/sample/demos-en/dialog1.rb
index d2b34e6b46..af476ecd05 100644
--- a/ext/tk/sample/demos-en/dialog1.rb
+++ b/ext/tk/sample/demos-en/dialog1.rb
@@ -2,6 +2,9 @@
# a dialog box with a local grab (called by 'widget')
#
class TkDialog_Demo1 < TkDialog
+ ###############
+ private
+ ###############
def title
"Dialog with local grab"
end
@@ -19,7 +22,7 @@ class TkDialog_Demo1 < TkDialog
end
def buttons
- ["Dismiss", "", "Show Code"]
+ # ["Dismiss", "", "Show Code"]
["OK", "Cancel", "Show Code"]
end
end
diff --git a/ext/tk/sample/demos-en/dialog2.rb b/ext/tk/sample/demos-en/dialog2.rb
index c441dda62f..efc4b714da 100644
--- a/ext/tk/sample/demos-en/dialog2.rb
+++ b/ext/tk/sample/demos-en/dialog2.rb
@@ -2,6 +2,9 @@
# a dialog box with a global grab (called by 'widget')
#
class TkDialog_Demo2 < TkDialog
+ ###############
+ private
+ ###############
def title
"Dialog with global grab"
end
@@ -24,9 +27,9 @@ class TkDialog_Demo2 < TkDialog
end
ret = TkDialog_Demo2.new('message_config'=>{'wraplength'=>'4i'},
- 'prev_command'=>proc{|dialog|
- Tk.after 100, proc{dialog.grab('global')}
- }).value
+ 'prev_command'=>proc{|dialog|
+ Tk.after 100, proc{dialog.grab('global')}
+ }).value
case ret
when 0
print "\You pressed OK\n"
diff --git a/ext/tk/sample/demos-en/entry1.rb b/ext/tk/sample/demos-en/entry1.rb
index 29bc693395..6f5b10fb71 100644
--- a/ext/tk/sample/demos-en/entry1.rb
+++ b/ext/tk/sample/demos-en/entry1.rb
@@ -15,8 +15,10 @@ $entry1_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($entry1_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($entry1_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -25,7 +27,7 @@ msg = TkLabel.new($entry1_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($entry1_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -42,9 +44,9 @@ TkFrame.new($entry1_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
#
-e1 = TkEntry.new($entry1_demo, 'relief'=>'sunken')
-e2 = TkEntry.new($entry1_demo, 'relief'=>'sunken')
-e3 = TkEntry.new($entry1_demo, 'relief'=>'sunken')
+e1 = TkEntry.new(base_frame, 'relief'=>'sunken')
+e2 = TkEntry.new(base_frame, 'relief'=>'sunken')
+e3 = TkEntry.new(base_frame, 'relief'=>'sunken')
[e1,e2,e3].each{|w| w.pack('side'=>'top', 'padx'=>10, 'pady'=>5, 'fill'=>'x')}
#
diff --git a/ext/tk/sample/demos-en/entry2.rb b/ext/tk/sample/demos-en/entry2.rb
index d4e58d7dd5..d67d04b56d 100644
--- a/ext/tk/sample/demos-en/entry2.rb
+++ b/ext/tk/sample/demos-en/entry2.rb
@@ -19,8 +19,10 @@ $entry2_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($entry2_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($entry2_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -29,7 +31,7 @@ msg = TkLabel.new($entry2_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($entry2_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -46,7 +48,7 @@ TkFrame.new($entry2_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
-TkFrame.new($entry2_demo, 'borderwidth'=>10) {|w|
+TkFrame.new(base_frame, 'borderwidth'=>10) {|w|
# entry 1
s1 = TkScrollbar.new(w, 'relief'=>'sunken', 'orient'=>'horiz')
e1 = TkEntry.new(w, 'relief'=>'sunken') {
diff --git a/ext/tk/sample/demos-en/entry3.rb b/ext/tk/sample/demos-en/entry3.rb
index 44f788225c..f7df3a5653 100644
--- a/ext/tk/sample/demos-en/entry3.rb
+++ b/ext/tk/sample/demos-en/entry3.rb
@@ -17,9 +17,11 @@ $entry3_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($entry3_demo,
- :font=>$font, :wraplength=>'5i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+base_frame = TkFrame.new($entry3_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'5i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
Four different entries are displayed below. You can add characters \
by pointing, clicking and typing, though each is constrained in what \
it will accept. The first only accepts integers or the empty string \
@@ -28,23 +30,23 @@ problem. The second only accepts strings with fewer than ten \
characters and sounds the bell when an attempt to go over the limit \
is made. The third accepts US phone numbers, mapping letters to \
their digit equivalent and sounding the bell on encountering an \
-illegal character or if trying to type over a character that is not \
+invalid character or if trying to type over a character that is not \
a digit. The fourth is a password field that accepts up to eight \
characters (silently ignoring further ones), and displaying them as \
asterisk characters.
EOL
-TkFrame.new($entry3_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
TkButton.new(f, :text=>'Dismiss', :width=>15, :command=>proc{
- $entry3_demo.destroy
- $entry3_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ $entry3_demo.destroy
+ $entry3_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'See Code', :width=>15, :command=>proc{
- showCode 'entry3'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'entry3'
+ }).pack(:side=>:left, :expand=>true)
}
# focusAndFlash --
@@ -54,32 +56,50 @@ TkFrame.new($entry3_demo){|f|
# 2.5Hz).
#
# Arguments:
-# widget - entry widget to flash
-# fg - Initial foreground colour
-# bg - Initial background colour
-# count - Counter to control the number of times flashed
+# widget - entry widget to flash
+# fg - Initial foreground colour
+# bg - Initial background colour
+# count - Counter to control the number of times flashed
def focusAndFlash(widget, fg, bg, count=5)
return if count <= 0
- TkTimer.new(200, count,
- proc{widget.configure(:foreground=>bg, :background=>fg)},
- proc{widget.configure(:foreground=>fg, :background=>bg)}
- ).start
+ if fg && !fg.empty? && bg && !bg.empty?
+ TkTimer.new(200, count,
+ proc{widget.configure(:foreground=>bg, :background=>fg)},
+ proc{widget.configure(:foreground=>fg, :background=>bg)}
+ ).start
+ else
+ # TkTimer.new(150, 3){Tk.bell}.start
+ Tk.bell
+ TkTimer.new(200, count,
+ proc{widget.configure(:foreground=>'white',
+ :background=>'black')},
+ proc{widget.configure(:foreground=>'black',
+ :background=>'white')}
+ ).at_end{begin
+ widget.configure(:foreground=>fg,
+ :background=>bg)
+ rescue
+ # ignore
+ end}.start
+ end
widget.focus(true)
end
-l1 = TkLabelFrame.new($entry3_demo, :text=>"Integer Entry")
+l1 = TkLabelFrame.new(base_frame, :text=>"Integer Entry")
TkEntry.new(l1, :validate=>:focus,
- :vcmd=>[
- proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
- ]) {|e|
- invalidcommand [proc{|w| focusAndFlash(w, e.fg, e.bg)}, '%W']
+ :vcmd=>[
+ proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
+ ]) {|e|
+ fg = e.foreground
+ bg = e.background
+ invalidcommand [proc{|w| focusAndFlash(w, fg, bg)}, '%W']
pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
}
-l2 = TkLabelFrame.new($entry3_demo, :text=>"Length-Constrained Entry")
+l2 = TkLabelFrame.new(base_frame, :text=>"Length-Constrained Entry")
TkEntry.new(l2, :validate=>:key, :invcmd=>proc{Tk.bell},
- :vcmd=>[proc{|s| s.length < 10}, '%P']
- ).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
+ :vcmd=>[proc{|s| s.length < 10}, '%P']
+ ).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
### PHONE NUMBER ENTRY ###
# Note that the source to this is quite a bit longer as the behaviour
@@ -101,7 +121,7 @@ Hash[*(%w(abc 2 def 3 ghi 4 jkl 5 mno 6 pqrs 7 tuv 8 wxyz 9))].each{|chars, n|
# Skip over fixed characters in a phone-number string when moving left.
#
# Arguments:
-# widget - The entry widget containing the phone-number.
+# widget - The entry widget containing the phone-number.
def phoneSkipLeft(widget)
idx = widget.index('insert')
if idx == 8
@@ -121,7 +141,7 @@ end
# Skip over fixed characters in a phone-number string when moving right.
#
# Arguments:
-# widget - The entry widget containing the phone-number.
+# widget - The entry widget containing the phone-number.
# add - Offset to add to index before calculation (used by validation.)
def phoneSkipRight(widget, add = 0)
idx = widget.index('insert')
@@ -145,51 +165,53 @@ end
#
# widget - entry widget to validate
# vmode - The widget's validation mode
-# idx - The index where replacement is to occur
+# idx - The index where replacement is to occur
# char - The character (or string, though that will always be
-# refused) to be overwritten at that point.
+# refused) to be overwritten at that point.
def validatePhoneChange(widget, vmode, idx, char)
return true if idx == nil
Tk.after_idle(proc{widget.configure(:validate=>vmode,
- :invcmd=>proc{Tk.bell})})
+ :invcmd=>proc{Tk.bell})})
if !(idx<3 || idx==6 || idx==7 || idx==11 || idx>15) && char =~ /[0-9A-Za-z]/
widget.delete(idx)
widget.insert(idx, $phoneNumberMap[char] || char)
Tk.after_idle(proc{phoneSkipRight(widget, -1)})
return true
+ # Tk.update(true) # <- Don't work 'update' inter validation callback.
+ # It depends on Tcl/Tk side (tested on Tcl/Tk8.5a1).
end
return false
end
-l3 = TkLabelFrame.new($entry3_demo, :text=>"US Phone-Number Entry")
+l3 = TkLabelFrame.new(base_frame, :text=>"US Phone-Number Entry")
TkEntry.new(l3, :validate=>:key, :invcmd=>proc{Tk.bell},
- :textvariable=>entry3content,
- :vcmd=>[
- proc{|w,v,i,s| validatePhoneChange(w,v,i,s)},
- "%W %v %i %S"
- ]){|e|
+ :textvariable=>entry3content,
+ :vcmd=>[
+ proc{|w,v,i,s| validatePhoneChange(w,v,i,s)},
+ "%W %v %i %S"
+ ]){|e|
# Click to focus goes to the first editable character...
bind('FocusIn', proc{|d,w|
- if d != "NotifyAncestor"
- w.cursor = 3
- Tk.after_idle(proc{w.selection_clear})
- end
+ if d != "NotifyAncestor"
+ w.cursor = 3
+ Tk.after_idle(proc{w.selection_clear})
+ end
}, '%d %W')
bind('Left', proc{|w| phoneSkipLeft(w)}, '%W')
bind('Right', proc{|w| phoneSkipRight(w)}, '%W')
pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
}
-l4 = TkLabelFrame.new($entry3_demo, :text=>"Password Entry")
+l4 = TkLabelFrame.new(base_frame, :text=>"Password Entry")
TkEntry.new(l4, :validate=>:key, :show=>'*',
- :vcmd=>[
- proc{|s| s.length <= 8},
- '%P'
- ]).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
+ :vcmd=>[
+ proc{|s| s.length <= 8},
+ '%P'
+ ]).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
-TkFrame.new($entry3_demo){|f|
+TkFrame.new(base_frame){|f|
lower
TkGrid.configure(l1, l2, :in=>f, :padx=>'3m', :pady=>'1m', :sticky=>:ew)
TkGrid.configure(l3, l4, :in=>f, :padx=>'3m', :pady=>'1m', :sticky=>:ew)
diff --git a/ext/tk/sample/demos-en/filebox.rb b/ext/tk/sample/demos-en/filebox.rb
index 7caaaf0ede..676c347409 100644
--- a/ext/tk/sample/demos-en/filebox.rb
+++ b/ext/tk/sample/demos-en/filebox.rb
@@ -17,12 +17,14 @@ $filebox_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($filebox_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($filebox_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
- 'text'=>"Enter a file name in the entry box or click on the \"Browse\" buttons to select a file name using the file selection dialog.").pack('side'=>'top')
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
+ 'text'=>"Enter a file name in the entry box or click on the \"Browse\" buttons to select a file name using the file selection dialog.").pack('side'=>'top')
# frame
-TkFrame.new($filebox_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -40,7 +42,7 @@ TkFrame.new($filebox_demo) {|frame|
# frame
['open', 'save'].each{|type|
- TkFrame.new($filebox_demo) {|f|
+ TkFrame.new(base_frame) {|f|
TkLabel.new(f, 'text'=>"Select a file to #{type}: ", 'anchor'=>'e')\
.pack('side'=>'left')
@@ -48,7 +50,7 @@ TkFrame.new($filebox_demo) {|frame|
pack('side'=>'left', 'expand'=>'yes', 'fill'=>'x')
TkButton.new(f, 'text'=>'Browse ...',
- 'command'=>proc{fileDialog $filebox_demo,e,type})\
+ 'command'=>proc{fileDialog base_frame,e,type})\
.pack('side'=>'left')
}
@@ -58,10 +60,10 @@ TkFrame.new($filebox_demo) {|frame|
$tk_strictMotif = TkVarAccess.new('tk_strictMotif')
if ($tk_platform['platform'] == 'unix')
- TkCheckButton.new($filebox_demo,
- 'text'=>'Use Motif Style Dialog',
- 'variable'=>$tk_strictMotif,
- 'onvalue'=>1, 'offvalue'=>0 ).pack('anchor'=>'c')
+ TkCheckButton.new(base_frame,
+ 'text'=>'Use Motif Style Dialog',
+ 'variable'=>$tk_strictMotif,
+ 'onvalue'=>1, 'offvalue'=>0 ).pack('anchor'=>'c')
end
def fileDialog(w,ent,operation)
@@ -85,13 +87,16 @@ def fileDialog(w,ent,operation)
file = Tk.getOpenFile('filetypes'=>types, 'parent'=>w)
else
file = Tk.getSaveFile('filetypes'=>types, 'parent'=>w,
- 'initialfile'=>'Untitled',
- 'defaultextension'=>'.txt')
+ 'initialfile'=>'Untitled',
+ 'defaultextension'=>'.txt')
end
if file != ""
ent.delete 0, 'end'
ent.insert 0, file
- ent.xview 'end'
+ # ent.xview 'end'
+ Tk.update_idletasks # need this for Tk::Tile::Entry
+ # (to find right position of 'xview').
+ ent.xview(ent.index('end'))
end
end
diff --git a/ext/tk/sample/demos-en/floor.rb b/ext/tk/sample/demos-en/floor.rb
index db4d59fe73..7023f2a72e 100644
--- a/ext/tk/sample/demos-en/floor.rb
+++ b/ext/tk/sample/demos-en/floor.rb
@@ -12,8 +12,8 @@
# visible.
#
# Arguments:
-# w - Name of the canvas window.
-# active - Number of active floor (1, 2, or 3).
+# w - Name of the canvas window.
+# active - Number of active floor (1, 2, or 3).
def floorDisplay(w,active)
return if $activeFloor == active
@@ -63,7 +63,7 @@ end
# highlighted.
#
# Arguments:
-# w - The name of the canvas window.
+# w - The name of the canvas window.
def newRoom(w)
id = w.find_withtag('current')[0]
@@ -76,8 +76,8 @@ end
# It highlights the current room and unhighlights any previous room.
#
# Arguments:
-# w - The canvas window displaying the floorplan.
-# args - Not used.
+# w - The canvas window displaying the floorplan.
+# args - Not used.
def roomChanged(w,*args)
w.delete('highlight')
@@ -94,24 +94,24 @@ end
# floor.
#
# Arguments:
-# w - The canvas window.
-# fill - Fill color to use for the floor's background.
-# outline - Color to use for the floor's outline.
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
def floor_bg1(w,fill,outline)
TkcPolygon.new(w,347,80,349,82,351,84,353,85,363,92,375,99,386,104,
- 386,129,398,129,398,162,484,162,484,129,559,129,559,133,725,
- 133,725,129,802,129,802,389,644,389,644,391,559,391,559,327,
- 508,327,508,311,484,311,484,278,395,278,395,288,400,288,404,
- 288,409,290,413,292,418,297,421,302,422,309,421,318,417,325,
- 411,330,405,332,397,333,344,333,340,334,336,336,335,338,332,
- 342,331,347,332,351,334,354,336,357,341,359,340,360,335,363,
- 331,365,326,366,304,366,304,355,258,355,258,387,60,387,60,391,
- 0,391,0,337,3,337,3,114,8,114,8,25,30,25,30,5,93,5,98,5,104,7,
- 110,10,116,16,119,20,122,28,123,32,123,68,220,68,220,34,221,
- 22,223,17,227,13,231,8,236,4,242,2,246,0,260,0,283,1,300,5,
- 321,14,335,22,348,25,365,29,363,39,358,48,352,56,337,70,
- 344,76,347,80, 'tags'=>['floor1','bg'], 'fill'=>fill)
+ 386,129,398,129,398,162,484,162,484,129,559,129,559,133,725,
+ 133,725,129,802,129,802,389,644,389,644,391,559,391,559,327,
+ 508,327,508,311,484,311,484,278,395,278,395,288,400,288,404,
+ 288,409,290,413,292,418,297,421,302,422,309,421,318,417,325,
+ 411,330,405,332,397,333,344,333,340,334,336,336,335,338,332,
+ 342,331,347,332,351,334,354,336,357,341,359,340,360,335,363,
+ 331,365,326,366,304,366,304,355,258,355,258,387,60,387,60,391,
+ 0,391,0,337,3,337,3,114,8,114,8,25,30,25,30,5,93,5,98,5,104,7,
+ 110,10,116,16,119,20,122,28,123,32,123,68,220,68,220,34,221,
+ 22,223,17,227,13,231,8,236,4,242,2,246,0,260,0,283,1,300,5,
+ 321,14,335,22,348,25,365,29,363,39,358,48,352,56,337,70,
+ 344,76,347,80, 'tags'=>['floor1','bg'], 'fill'=>fill)
TkcLine.new(w,386,129,398,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
TkcLine.new(w,258,355,258,387, 'fill'=>outline, 'tags'=>['floor1','bg'])
TkcLine.new(w,60,387,60,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
@@ -218,17 +218,17 @@ end
# floor.
#
# Arguments:
-# w - The canvas window.
-# fill - Fill color to use for the floor's background.
-# outline - Color to use for the floor's outline.
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
def floor_bg2(w,fill,outline)
TkcPolygon.new(w,559,129,484,129,484,162,398,162,398,129,315,129,
- 315,133,176,133,176,129,96,129,96,133,3,133,3,339,0,339,0,391,
- 60,391,60,387,258,387,258,329,350,329,350,311,395,311,395,280,
- 484,280,484,311,508,311,508,327,558,327,558,391,644,391,644,
- 367,802,367,802,129,725,129,725,133,559,133,559,129,
- 'tags'=>['floor2','bg'], 'fill'=>fill)
+ 315,133,176,133,176,129,96,129,96,133,3,133,3,339,0,339,0,391,
+ 60,391,60,387,258,387,258,329,350,329,350,311,395,311,395,280,
+ 484,280,484,311,508,311,508,327,558,327,558,391,644,391,644,
+ 367,802,367,802,129,725,129,725,133,559,133,559,129,
+ 'tags'=>['floor2','bg'], 'fill'=>fill)
TkcLine.new(w,350,311,350,329, 'fill'=>outline, 'tags'=>['floor2','bg'])
TkcLine.new(w,398,129,398,162, 'fill'=>outline, 'tags'=>['floor2','bg'])
TkcLine.new(w,802,367,802,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
@@ -273,17 +273,17 @@ end
# floor.
#
# Arguments:
-# w - The canvas window.
-# fill - Fill color to use for the floor's background.
-# outline - Color to use for the floor's outline.
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
def floor_bg3(w,fill,outline)
TkcPolygon.new(w,159,300,107,300,107,248,159,248,159,129,96,129,96,
- 133,21,133,21,331,0,331,0,391,60,391,60,370,159,370,159,300,
- 'tags'=>['floor3','bg'], 'fill'=>fill)
+ 133,21,133,21,331,0,331,0,391,60,391,60,370,159,370,159,300,
+ 'tags'=>['floor3','bg'], 'fill'=>fill)
TkcPolygon.new(w,258,370,258,329,350,329,350,311,399,311,399,129,
- 315,129,315,133,176,133,176,129,159,129,159,370,258,370,
- 'tags'=>['floor3','bg'], 'fill'=>fill)
+ 315,129,315,133,176,133,176,129,159,129,159,370,258,370,
+ 'tags'=>['floor3','bg'], 'fill'=>fill)
TkcLine.new(w,96,133,96,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
TkcLine.new(w,176,129,96,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
TkcLine.new(w,176,129,176,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
@@ -303,7 +303,7 @@ def floor_bg3(w,fill,outline)
TkcLine.new(w,21,331,21,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
TkcLine.new(w,96,133,21,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
TkcLine.new(w,107,300,159,300,159,248,107,248,107,300,
- 'fill'=>outline, 'tags'=>['floor3','bg'])
+ 'fill'=>outline, 'tags'=>['floor3','bg'])
end
# floor_fg1 --
@@ -312,321 +312,321 @@ end
# floor (office outlines and numbers).
#
# Arguments:
-# w - The canvas window.
-# color - Color to use for drawing foreground information.
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
def floor_fg1(w,color)
i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '101'
$floorItems['101'] = i
TkcText.new(w,358,209, 'text'=>'101', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Pub Lift1'
$floorItems['Pub Lift1'] = i
TkcText.new(w,323,223, 'text'=>'Pub Lift1', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Priv Lift1'
$floorItems['Priv Lift1'] = i
TkcText.new(w,323,188, 'text'=>'Priv Lift1', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,42,389,42,337,1,337,1,389,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '110'
$floorItems['110'] = i
TkcText.new(w,21.5,363, 'text'=>'110', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,59,389,59,385,90,385,90,337,44,337,44,389,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '109'
$floorItems['109'] = i
TkcText.new(w,67,363, 'text'=>'109', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,51,300,51,253,6,253,6,300,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '111'
$floorItems['111'] = i
TkcText.new(w,28.5,276.5, 'text'=>'111', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,98,248,98,309,79,309,79,248,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '117B'
$floorItems['117B'] = i
TkcText.new(w,88.5,278.5, 'text'=>'117B', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,51,251,51,204,6,204,6,251,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '112'
$floorItems['112'] = i
TkcText.new(w,28.5,227.5, 'text'=>'112', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,6,156,51,156,51,203,6,203,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '113'
$floorItems['113'] = i
TkcText.new(w,28.5,179.5, 'text'=>'113', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,85,169,79,169,79,192,85,192,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '117A'
$floorItems['117A'] = i
TkcText.new(w,82,180.5, 'text'=>'117A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,77,302,77,168,53,168,53,302,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '117'
$floorItems['117'] = i
TkcText.new(w,65,235, 'text'=>'117', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,51,155,51,115,6,115,6,155,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '114'
$floorItems['114'] = i
TkcText.new(w,28.5,135, 'text'=>'114', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,95,115,53,115,53,168,95,168,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '115'
$floorItems['115'] = i
TkcText.new(w,74,141.5, 'text'=>'115', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,87,113,87,27,10,27,10,113,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '116'
$floorItems['116'] = i
TkcText.new(w,48.5,70, 'text'=>'116', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,89,91,128,91,128,113,89,131,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '118'
$floorItems['118'] = i
TkcText.new(w,108.5,102, 'text'=>'118', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,178,128,178,132,216,132,216,91,
- 163,91,163,112,149,112,149,128,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 163,91,163,112,149,112,149,128,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '120'
$floorItems['120'] = i
TkcText.new(w,189.5,111.5, 'text'=>'120', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,79,193,87,193,87,169,136,169,136,192,
- 156,192,156,169,175,169,175,246,79,246,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 156,192,156,169,175,169,175,246,79,246,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '122'
$floorItems['122'] = i
TkcText.new(w,131,207.5, 'text'=>'122', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,138,169,154,169,154,191,138,191,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '121'
$floorItems['121'] = i
TkcText.new(w,146,180, 'text'=>'121', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,99,300,126,300,126,309,99,309,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '106A'
$floorItems['106A'] = i
TkcText.new(w,112.5,304.5, 'text'=>'106A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,128,299,128,309,150,309,150,248,99,248,99,299,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '105'
$floorItems['105'] = i
TkcText.new(w,124.5,278.5, 'text'=>'105', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,174,309,174,300,152,300,152,309,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '106B'
$floorItems['106B'] = i
TkcText.new(w,163,304.5, 'text'=>'106B', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,176,299,176,309,216,309,216,248,152,248,152,299,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '104'
$floorItems['104'] = i
TkcText.new(w,184,278.5, 'text'=>'104', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,138,385,138,337,91,337,91,385,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '108'
$floorItems['108'] = i
TkcText.new(w,114.5,361, 'text'=>'108', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,256,337,140,337,140,385,256,385,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '107'
$floorItems['107'] = i
TkcText.new(w,198,361, 'text'=>'107', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,300,353,300,329,260,329,260,353,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Smoking'
$floorItems['Smoking'] = i
TkcText.new(w,280,341, 'text'=>'Smoking', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,314,135,314,170,306,170,306,246,177,246,177,135,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '123'
$floorItems['123'] = i
TkcText.new(w,245.5,190.5, 'text'=>'123', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,217,248,301,248,301,326,257,326,257,310,217,310,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '103'
$floorItems['103'] = i
TkcText.new(w,259,287, 'text'=>'103', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,396,188,377,188,377,169,316,169,316,131,396,131,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '124'
$floorItems['124'] = i
TkcText.new(w,356,150, 'text'=>'124', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,397,226,407,226,407,189,377,189,377,246,397,246,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '125'
$floorItems['125'] = i
TkcText.new(w,392,217.5, 'text'=>'125', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,399,187,409,187,409,207,474,207,474,164,399,164,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '126'
$floorItems['126'] = i
TkcText.new(w,436.5,185.5, 'text'=>'126', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,409,209,409,229,399,229,399,253,
- 486,253,486,239,474,239,474,209,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 486,253,486,239,474,239,474,209,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '127'
$floorItems['127'] = i
TkcText.new(w,436.5,'231', 'text'=>'127', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,501,164,501,174,495,174,495,188,
- 490,188,490,204,476,204,476,164,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 490,188,490,204,476,204,476,164,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'MShower'
$floorItems['MShower'] = i
TkcText.new(w,488.5,'184', 'text'=>'MShower', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,497,176,513,176,513,204,492,204,492,190,497,190,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Closet'
$floorItems['Closet'] = i
TkcText.new(w,502.5,190, 'text'=>'Closet', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,476,237,476,206,513,206,513,254,488,254,488,237,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'WShower'
$floorItems['WShower'] = i
TkcText.new(w,494.5,230, 'text'=>'WShower', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,486,131,558,131,558,135,724,135,724,166,
- 697,166,697,275,553,275,531,254,515,254,
- 515,174,503,174,503,161,486,161,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 697,166,697,275,553,275,531,254,515,254,
+ 515,174,503,174,503,161,486,161,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '130'
$floorItems['130'] = i
TkcText.new(w,638.5,205, 'text'=>'130', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,308,242,339,242,339,248,342,248,
- 342,246,397,246,397,276,393,276,
- 393,309,300,309,300,248,308,248,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 342,246,397,246,397,276,393,276,
+ 393,309,300,309,300,248,308,248,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '102'
$floorItems['102'] = i
TkcText.new(w,367.5,278.5, 'text'=>'102', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,397,255,486,255,486,276,397,276,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '128'
$floorItems['128'] = i
TkcText.new(w,441.5,265.5, 'text'=>'128', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,510,309,486,309,486,255,530,255,
- 552,277,561,277,561,325,510,325,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 552,277,561,277,561,325,510,325,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '129'
$floorItems['129'] = i
TkcText.new(w,535.5,293, 'text'=>'129', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,696,281,740,281,740,387,642,387,
- 642,389,561,389,561,277,696,277,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 642,389,561,389,561,277,696,277,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '133'
$floorItems['133'] = i
TkcText.new(w,628.5,335, 'text'=>'133', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,742,387,742,281,800,281,800,387,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '132'
$floorItems['132'] = i
TkcText.new(w,771,334, 'text'=>'132', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,800,168,800,280,699,280,699,168,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '134'
$floorItems['134'] = i
TkcText.new(w,749.5,224, 'text'=>'134', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,726,131,726,166,800,166,800,131,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '135'
$floorItems['135'] = i
TkcText.new(w,763,148.5, 'text'=>'135', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,340,360,335,363,331,365,326,366,304,366,
- 304,312,396,312,396,288,400,288,404,288,
- 409,290,413,292,418,297,421,302,422,309,
- 421,318,417,325,411,330,405,332,397,333,
- 344,333,340,334,336,336,335,338,332,342,
- 331,347,332,351,334,354,336,357,341,359,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 304,312,396,312,396,288,400,288,404,288,
+ 409,290,413,292,418,297,421,302,422,309,
+ 421,318,417,325,411,330,405,332,397,333,
+ 344,333,340,334,336,336,335,338,332,342,
+ 331,347,332,351,334,354,336,357,341,359,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Ramona Stair'
$floorItems['Ramona Stair'] = i
TkcText.new(w,368,323, 'text'=>'Ramona Stair', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,30,23,30,5,93,5,98,5,104,7,110,10,116,16,119,20,
- 122,28,123,32,123,68,220,68,220,87,90,87,90,23,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 122,28,123,32,123,68,220,68,220,87,90,87,90,23,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'University Stair'
$floorItems['University Stair'] = i
TkcText.new(w,155,77.5, 'text'=>'University Stair', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,282,37,295,40,312,49,323,56,337,70,352,56,
- 358,48,363,39,365,29,348,25,335,22,321,14,
- 300,5,283,1,260,0,246,0,242,2,236,4,231,8,
- 227,13,223,17,221,22,220,34,260,34,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 358,48,363,39,365,29,348,25,335,22,321,14,
+ 300,5,283,1,260,0,246,0,242,2,236,4,231,8,
+ 227,13,223,17,221,22,220,34,260,34,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Plaza Stair'
$floorItems['Plaza Stair'] = i
TkcText.new(w,317.5,28.5, 'text'=>'Plaza Stair', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,220,34,260,34,282,37,295,40,312,49,
- 323,56,337,70,350,83,365,94,377,100,
- 386,104,386,128,220,128,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 323,56,337,70,350,83,365,94,377,100,
+ 386,104,386,128,220,128,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Plaza Deck'
$floorItems['Plaza Deck'] = i
TkcText.new(w,303,81, 'text'=>'Plaza Deck', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,257,336,77,336,6,336,6,301,77,301,77,310,257,310,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '106'
$floorItems['106'] = i
TkcText.new(w,131.5,318.5, 'text'=>'106', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,146,110,162,110,162,91,130,91,130,115,95,115,
- 95,128,114,128,114,151,157,151,157,153,112,153,
- 112,130,97,130,97,168,175,168,175,131,146,131,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 95,128,114,128,114,151,157,151,157,153,112,153,
+ 112,130,97,130,97,168,175,168,175,131,146,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '119'
$floorItems['119'] = i
TkcText.new(w,143.5,133, 'text'=>'119', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
TkcLine.new(w,155,191,155,189, 'fill'=>color, 'tags'=>['floor1','wall'])
TkcLine.new(w,155,177,155,169, 'fill'=>color, 'tags'=>['floor1','wall'])
TkcLine.new(w,96,129,96,169, 'fill'=>color, 'tags'=>['floor1','wall'])
@@ -793,327 +793,327 @@ end
# floor (office outlines and numbers).
#
# Arguments:
-# w - The canvas window.
-# color - Color to use for drawing foreground information.
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
def floor_fg2(w,color)
i = TkcPolygon.new(w,748,188,755,188,755,205,758,205,758,222,
- 800,222,800,168,748,168,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 800,222,800,168,748,168,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '238'
$floorItems['238'] = i
TkcText.new(w,774,195, 'text'=>'238', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,726,188,746,188,746,166,800,166,800,131,726,131,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '237'
$floorItems['237'] = i
TkcText.new(w,763,148.5, 'text'=>'237', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,497,187,497,204,559,204,559,324,641,324,
- 643,324,643,291,641,291,641,205,696,205,
- 696,291,694,291,694,314,715,314,715,291,
- 715,205,755,205,755,190,724,190,724,187,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 643,324,643,291,641,291,641,205,696,205,
+ 696,291,694,291,694,314,715,314,715,291,
+ 715,205,755,205,755,190,724,190,724,187,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '246'
$floorItems['246'] = i
TkcText.new(w,600,264, 'text'=>'246', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,694,279,643,279,643,314,694,314,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '247'
$floorItems['247'] = i
TkcText.new(w,668.5,296.5, 'text'=>'247', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,232,250,308,250,308,242,339,242,339,246,
- 397,246,397,255,476,255,476,250,482,250,559,250,
- 559,274,482,274,482,278,396,278,396,274,232,274,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 397,246,397,255,476,255,476,250,482,250,559,250,
+ 559,274,482,274,482,278,396,278,396,274,232,274,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '202'
$floorItems['202'] = i
TkcText.new(w,285.5,260, 'text'=>'202', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,53,228,53,338,176,338,233,338,233,196,
- 306,196,306,180,175,180,175,169,156,169,
- 156,196,176,196,176,228,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 306,196,306,180,175,180,175,169,156,169,
+ 156,196,176,196,176,228,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '206'
$floorItems['206'] = i
TkcText.new(w,143,267, 'text'=>'206', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,51,277,6,277,6,338,51,338,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '212'
$floorItems['212'] = i
TkcText.new(w,28.5,307.5, 'text'=>'212', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,557,276,486,276,486,309,510,309,510,325,557,325,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '245'
$floorItems['245'] = i
TkcText.new(w,521.5,300.5, 'text'=>'245', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,560,389,599,389,599,326,560,326,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '244'
$floorItems['244'] = i
TkcText.new(w,579.5,357.5, 'text'=>'244', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,601,389,601,326,643,326,643,389,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '243'
$floorItems['243'] = i
TkcText.new(w,622,357.5, 'text'=>'243', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,688,316,645,316,645,365,688,365,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '242'
$floorItems['242'] = i
TkcText.new(w,666.5,340.5, 'text'=>'242', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,802,367,759,367,759,226,802,226,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = 'Barbecue Deck'
$floorItems['Barbecue Deck'] = i
TkcText.new(w,780.5,296.5, 'text'=>'Barbecue Deck', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,755,262,755,314,717,314,717,262,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '240'
$floorItems['240'] = i
TkcText.new(w,736,288, 'text'=>'240', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,755,316,689,316,689,365,755,365,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '241'
$floorItems['241'] = i
TkcText.new(w,722,340.5, 'text'=>'241', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,755,206,717,206,717,261,755,261,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '239'
$floorItems['239'] = i
TkcText.new(w,736,233.5, 'text'=>'239', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,695,277,643,277,643,206,695,206,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '248'
$floorItems['248'] = i
TkcText.new(w,669,241.5, 'text'=>'248', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,676,135,676,185,724,185,724,135,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '236'
$floorItems['236'] = i
TkcText.new(w,700,160, 'text'=>'236', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,675,135,635,135,635,145,628,145,628,185,675,185,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '235'
$floorItems['235'] = i
TkcText.new(w,651.5,160, 'text'=>'235', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,626,143,633,143,633,135,572,135,
- 572,143,579,143,579,185,626,185,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 572,143,579,143,579,185,626,185,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '234'
$floorItems['234'] = i
TkcText.new(w,606,160, 'text'=>'234', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,557,135,571,135,571,145,578,145,
- 578,185,527,185,527,131,557,131,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 578,185,527,185,527,131,557,131,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '233'
$floorItems['233'] = i
TkcText.new(w,552.5,158, 'text'=>'233', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,476,249,557,249,557,205,476,205,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '230'
$floorItems['230'] = i
TkcText.new(w,516.5,227, 'text'=>'230', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,476,164,486,164,486,131,525,131,525,185,476,185,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '232'
$floorItems['232'] = i
TkcText.new(w,500.5,158, 'text'=>'232', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,476,186,495,186,495,204,476,204,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '229'
$floorItems['229'] = i
TkcText.new(w,485.5,195, 'text'=>'229', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,474,207,409,207,409,187,399,187,399,164,474,164,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '227'
$floorItems['227'] = i
TkcText.new(w,436.5,185.5, 'text'=>'227', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,399,228,399,253,474,253,474,209,409,209,409,228,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '228'
$floorItems['228'] = i
TkcText.new(w,436.5,231, 'text'=>'228', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,397,246,397,226,407,226,407,189,377,189,377,246,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '226'
$floorItems['226'] = i
TkcText.new(w,392,217.5, 'text'=>'226', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,377,169,316,169,316,131,397,131,397,188,377,188,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '225'
$floorItems['225'] = i
TkcText.new(w,356.5,150, 'text'=>'225', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,234,198,306,198,306,249,234,249,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '224'
$floorItems['224'] = i
TkcText.new(w,270,223.5, 'text'=>'224', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,270,179,306,179,306,170,314,170,314,135,270,135,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '223'
$floorItems['223'] = i
TkcText.new(w,292,157, 'text'=>'223', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,268,179,221,179,221,135,268,135,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '222'
$floorItems['222'] = i
TkcText.new(w,244.5,157, 'text'=>'222', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,177,179,219,179,219,135,177,135,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '221'
$floorItems['221'] = i
TkcText.new(w,198,157, 'text'=>'221', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,299,327,349,327,349,284,341,284,341,276,299,276,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '204'
$floorItems['204'] = i
TkcText.new(w,324,301.5, 'text'=>'204', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,234,276,297,276,297,327,257,327,257,338,234,338,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '205'
$floorItems['205'] = i
TkcText.new(w,265.5,307, 'text'=>'205', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,256,385,256,340,212,340,212,385,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '207'
$floorItems['207'] = i
TkcText.new(w,234,362.5, 'text'=>'207', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,210,340,164,340,164,385,210,385,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '208'
$floorItems['208'] = i
TkcText.new(w,187,362.5, 'text'=>'208', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,115,340,162,340,162,385,115,385,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '209'
$floorItems['209'] = i
TkcText.new(w,138.5,362.5, 'text'=>'209', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,89,228,89,156,53,156,53,228,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '217'
$floorItems['217'] = i
TkcText.new(w,71,192, 'text'=>'217', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,89,169,97,169,97,190,89,190,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '217A'
$floorItems['217A'] = i
TkcText.new(w,93,179.5, 'text'=>'217A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,89,156,89,168,95,168,95,135,53,135,53,156,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '216'
$floorItems['216'] = i
TkcText.new(w,71,145.5, 'text'=>'216', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,51,179,51,135,6,135,6,179,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '215'
$floorItems['215'] = i
TkcText.new(w,28.5,157, 'text'=>'215', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,51,227,6,227,6,180,51,180,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '214'
$floorItems['214'] = i
TkcText.new(w,28.5,203.5, 'text'=>'214', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,51,275,6,275,6,229,51,229,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '213'
$floorItems['213'] = i
TkcText.new(w,28.5,252, 'text'=>'213', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,114,340,67,340,67,385,114,385,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '210'
$floorItems['210'] = i
TkcText.new(w,90.5,362.5, 'text'=>'210', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,59,389,59,385,65,385,65,340,1,340,1,389,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '211'
$floorItems['211'] = i
TkcText.new(w,33,364.5, 'text'=>'211', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,393,309,350,309,350,282,342,282,342,276,393,276,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '203'
$floorItems['203'] = i
TkcText.new(w,367.5,292.5, 'text'=>'203', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,99,191,91,191,91,226,174,226,174,198,
- 154,198,154,192,109,192,109,169,99,169,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 154,198,154,192,109,192,109,169,99,169,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '220'
$floorItems['220'] = i
TkcText.new(w,132.5,208.5, 'text'=>'220', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = 'Priv Lift2'
$floorItems['Priv Lift2'] = i
TkcText.new(w,323,188, 'text'=>'Priv Lift2', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = 'Pub Lift 2'
$floorItems['Pub Lift 2'] = i
TkcText.new(w,323,223, 'text'=>'Pub Lift 2', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,175,168,97,168,97,131,175,131,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '218'
$floorItems['218'] = i
TkcText.new(w,136,149.5, 'text'=>'218', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,154,191,111,191,111,169,154,169,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '219'
$floorItems['219'] = i
TkcText.new(w,132.5,180, 'text'=>'219', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '201'
$floorItems['201'] = i
TkcText.new(w,358,209, 'text'=>'201', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
TkcLine.new(w,641,186,678,186, 'fill'=>color, 'tags'=>['floor2','wall'])
TkcLine.new(w,757,350,757,367, 'fill'=>color, 'tags'=>['floor2','wall'])
TkcLine.new(w,634,133,634,144, 'fill'=>color, 'tags'=>['floor2','wall'])
@@ -1275,215 +1275,215 @@ end
# floor (office outlines and numbers).
#
# Arguments:
-# w - The canvas window.
-# color - Color to use for drawing foreground information.
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
def floor_fg3(w,color)
i = TkcPolygon.new(w,89,228,89,180,70,180,70,228,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '316'
$floorItems['316'] = i
TkcText.new(w,79.5,204, 'text'=>'316', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,115,368,162,368,162,323,115,323,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '309'
$floorItems['309'] = i
TkcText.new(w,138.5,345.5, 'text'=>'309', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,164,323,164,368,211,368,211,323,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '308'
$floorItems['308'] = i
TkcText.new(w,187.5,345.5, 'text'=>'308', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,256,368,212,368,212,323,256,323,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '307'
$floorItems['307'] = i
TkcText.new(w,234,345.5, 'text'=>'307', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,244,276,297,276,297,327,260,327,260,321,244,321,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '305'
$floorItems['305'] = i
TkcText.new(w,270.5,301.5, 'text'=>'305', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,251,219,251,203,244,203,244,219,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '324B'
$floorItems['324B'] = i
TkcText.new(w,247.5,211, 'text'=>'324B', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,251,249,244,249,244,232,251,232,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '324A'
$floorItems['324A'] = i
TkcText.new(w,247.5,240.5, 'text'=>'324A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,223,135,223,179,177,179,177,135,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '320'
$floorItems['320'] = i
TkcText.new(w,200,157, 'text'=>'320', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,114,368,114,323,67,323,67,368,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '310'
$floorItems['310'] = i
TkcText.new(w,90.5,345.5, 'text'=>'310', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,23,277,23,321,68,321,68,277,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '312'
$floorItems['312'] = i
TkcText.new(w,45.5,299, 'text'=>'312', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,23,229,68,229,68,275,23,275,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '313'
$floorItems['313'] = i
TkcText.new(w,45.5,252, 'text'=>'313', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,68,227,23,227,23,180,68,180,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '314'
$floorItems['314'] = i
TkcText.new(w,40.5,203.5, 'text'=>'314', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,95,179,95,135,23,135,23,179,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '315'
$floorItems['315'] = i
TkcText.new(w,59,157, 'text'=>'315', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,99,226,99,204,91,204,91,226,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '316B'
$floorItems['316B'] = i
TkcText.new(w,95,215, 'text'=>'316B', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,91,202,99,202,99,180,91,180,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '316A'
$floorItems['316A'] = i
TkcText.new(w,95,191, 'text'=>'316A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,97,169,109,169,109,192,154,192,154,198,
- 174,198,174,226,101,226,101,179,97,179,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 174,198,174,226,101,226,101,179,97,179,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '319'
$floorItems['319'] = i
TkcText.new(w,141.5,209, 'text'=>'319', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,65,368,58,368,58,389,1,389,1,333,23,333,23,323,65,323,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '311'
$floorItems['311'] = i
TkcText.new(w,29.5,361, 'text'=>'311', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,154,191,111,191,111,169,154,169,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '318'
$floorItems['318'] = i
TkcText.new(w,132.5,180, 'text'=>'318', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,175,168,97,168,97,131,175,131,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '317'
$floorItems['317'] = i
TkcText.new(w,136,149.5, 'text'=>'317', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,274,194,274,221,306,221,306,194,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '323'
$floorItems['323'] = i
TkcText.new(w,290,207.5, 'text'=>'323', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,306,222,274,222,274,249,306,249,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '325'
$floorItems['325'] = i
TkcText.new(w,290,235.5, 'text'=>'325', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,263,179,224,179,224,135,263,135,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '321'
$floorItems['321'] = i
TkcText.new(w,243.5,157, 'text'=>'321', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,314,169,306,169,306,192,273,192,
- 264,181,264,135,314,135,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 264,181,264,135,314,135,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '322'
$floorItems['322'] = i
TkcText.new(w,293.5,163.5, 'text'=>'322', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = 'Pub Lift3'
$floorItems['Pub Lift3'] = i
TkcText.new(w,323,223, 'text'=>'Pub Lift3', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = 'Priv Lift3'
$floorItems['Priv Lift3'] = i
TkcText.new(w,323,188, 'text'=>'Priv Lift3', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,350,284,376,284,376,276,397,276,397,309,350,309,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '303'
$floorItems['303'] = i
TkcText.new(w,373.5,292.5, 'text'=>'303', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,272,203,272,249,252,249,252,230,
- 244,230,244,221,252,221,252,203,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 244,230,244,221,252,221,252,203,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '324'
$floorItems['324'] = i
TkcText.new(w,262,226, 'text'=>'324', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,299,276,299,327,349,327,349,284,341,284,341,276,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '304'
$floorItems['304'] = i
TkcText.new(w,324,301.5, 'text'=>'304', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '301'
$floorItems['301'] = i
TkcText.new(w,358,209, 'text'=>'301', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,397,246,377,246,377,185,397,185,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '327'
$floorItems['327'] = i
TkcText.new(w,387,215.5, 'text'=>'327', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,316,131,316,169,377,169,377,185,397,185,397,131,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '326'
$floorItems['326'] = i
TkcText.new(w,365.5,150, 'text'=>'326', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,308,251,242,251,242,274,342,274,342,282,375, 282,
- 375,274,397,274,397,248,339,248,339,242,308,242,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 375,274,397,274,397,248,339,248,339,242,308,242,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '302'
$floorItems['302'] = i
TkcText.new(w,319.5,261, 'text'=>'302', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,70,321,242,321,242,200,259,200,259,203,272,203,
- 272,193,263,180,242,180,175,180,175,169,156,169,
- 156,196,177,196,177,228,107,228,70,228,70,275,107,275,
- 107,248,160,248,160,301,107,301,107,275,70,275,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 272,193,263,180,242,180,175,180,175,169,156,169,
+ 156,196,177,196,177,228,107,228,70,228,70,275,107,275,
+ 107,248,160,248,160,301,107,301,107,275,70,275,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '306'
$floorItems['306'] = i
TkcText.new(w,200.5,284.5, 'text'=>'306', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
TkcLine.new(w,341,275,341,283, 'fill'=>color, 'tags'=>['floor3','wall'])
TkcLine.new(w,162,197,155,197, 'fill'=>color, 'tags'=>['floor3','wall'])
TkcLine.new(w,396,247,399,247, 'fill'=>color, 'tags'=>['floor3','wall'])
@@ -1590,14 +1590,16 @@ $floor_demo = TkToplevel.new {|w|
minsize(100,100)
}
+base_frame = TkFrame.new($floor_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($floor_demo, 'font'=>$font, 'wraplength'=>'8i', 'justify'=>'left',
- 'text'=>"This window contains a canvas widget showing the floorplan of Digital Equipment Corporation's Western Research Laboratory. It has three levels. At any given time one of the levels is active, meaning that you can see its room structure. To activate a level, click the left mouse button anywhere on it. As the mouse moves over the active level, the room under the mouse lights up and its room number appears in the \"Room:\" entry. You can also type a room number in the entry and the room will light up."){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'8i', 'justify'=>'left',
+ 'text'=>"This window contains a canvas widget showing the floorplan of Digital Equipment Corporation's Western Research Laboratory. It has three levels. At any given time one of the levels is active, meaning that you can see its room structure. To activate a level, click the left mouse button anywhere on it. As the mouse moves over the active level, the room under the mouse lights up and its room number appears in the \"Room:\" entry. You can also type a room number in the entry and the room will light up."){
pack('side'=>'top')
}
# frame
-$floor_buttons = TkFrame.new($floor_demo) {|frame|
+$floor_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -1620,17 +1622,17 @@ $floorItems = {}
# canvas
if $tk_version =~ /^4\.[01]/
- $floor_canvas_frame = TkFrame.new($floor_demo,'bd'=>2,'relief'=>'sunken',
- 'highlightthickness'=>2)
+ $floor_canvas_frame = TkFrame.new(base_frame,'bd'=>2,'relief'=>'sunken',
+ 'highlightthickness'=>2)
$floor_canvas = TkCanvas.new($floor_canvas_frame,
- 'width'=>900, 'height'=>500, 'borderwidth'=>0,
- 'highlightthickness'=>0) {|c|
- TkScrollbar.new($floor_demo, 'orient'=>'horiz',
- 'command'=>proc{|*args| c.xview(*args)}){|hs|
+ 'width'=>900, 'height'=>500, 'borderwidth'=>0,
+ 'highlightthickness'=>0) {|c|
+ TkScrollbar.new(base_frame, 'orient'=>'horiz',
+ 'command'=>proc{|*args| c.xview(*args)}){|hs|
c.xscrollcommand(proc{|first,last| hs.set first,last})
pack('side'=>'bottom', 'fill'=>'x')
}
- TkScrollbar.new($floor_demo, 'command'=>proc{|*args| c.yview(*args)}){|vs|
+ TkScrollbar.new(base_frame, 'command'=>proc{|*args| c.yview(*args)}){|vs|
c.yscrollcommand(proc{|first,last| vs.set first,last})
pack('side'=>'right', 'fill'=>'y')
}
@@ -1639,7 +1641,7 @@ if $tk_version =~ /^4\.[01]/
$floor_canvas.pack('expand'=>'yes', 'fill'=>'both')
else
- TkFrame.new($floor_demo) {|f|
+ TkFrame.new(base_frame) {|f|
pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes')
h = TkScrollbar.new(f, 'highlightthickness'=>0, 'orient'=>'horizontal')
@@ -1647,28 +1649,28 @@ else
TkFrame.new(f, 'bd'=>2, 'relief'=>'sunken') {|f1|
$floor_canvas = TkCanvas.new(f1, 'width'=>900, 'height'=>500,
- 'borderwidth'=>0,
- 'highlightthickness'=>0) {
- xscrollcommand(proc{|first,last| h.set first,last})
- yscrollcommand(proc{|first,last| v.set first,last})
- pack('expand'=>'yes', 'fill'=>'both')
+ 'borderwidth'=>0,
+ 'highlightthickness'=>0) {
+ xscrollcommand(proc{|first,last| h.set first,last})
+ yscrollcommand(proc{|first,last| v.set first,last})
+ pack('expand'=>'yes', 'fill'=>'both')
}
grid('padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
}
v.grid('padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
h.grid('padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
TkGrid.rowconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
TkGrid.columnconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
- v.command(proc{|*args| c.yview(*args)})
- h.command(proc{|*args| c.xview(*args)})
+ v.command(proc{|*args| $floor_canvas.yview(*args)})
+ h.command(proc{|*args| $floor_canvas.xview(*args)})
}
end
@@ -1677,7 +1679,7 @@ end
$currentRoom = TkVariable.new
$floor_entry = TkEntry.new($floor_canvas, 'width'=>10, 'relief'=>'sunken',
- 'bd'=>2, 'textvariable'=>$currentRoom)
+ 'bd'=>2, 'textvariable'=>$currentRoom)
# Choose colors, then fill in the floorplan.
@@ -1714,7 +1716,7 @@ $floor_canvas.itembind('room', 'Enter', proc{newRoom $floor_canvas})
$floor_canvas.itembind('room', 'Leave', proc{$currentRoom.value = ''})
$floor_canvas.bind('2', proc{|x,y| $floor_canvas.scan_mark x,y}, '%x %y')
$floor_canvas.bind('B2-Motion',
- proc{|x,y| $floor_canvas.scan_dragto x,y}, '%x %y')
+ proc{|x,y| $floor_canvas.scan_dragto x,y}, '%x %y')
$floor_canvas.bind('Destroy', proc{$currentRoom.unset})
$currentRoom.value = ''
$currentRoom.trace('w',proc{roomChanged $floor_canvas})
diff --git a/ext/tk/sample/demos-en/floor2.rb b/ext/tk/sample/demos-en/floor2.rb
new file mode 100644
index 0000000000..88b07aeee4
--- /dev/null
+++ b/ext/tk/sample/demos-en/floor2.rb
@@ -0,0 +1,1722 @@
+%# floor2.rb
+#
+# This demonstration script creates a canvas widet that displays the
+# floorplan for DEC's Western Research Laboratory.
+#
+# floorDisplay widget demo (called by 'widget')
+#
+
+# floorDisplay2 --
+# Recreate the floorplan display in the canvas given by "w". The
+# floor given by "active" is displayed on top with its office structure
+# visible.
+#
+# Arguments:
+# w - Name of the canvas window.
+# active - Number of active floor (1, 2, or 3).
+
+def floorDisplay2(w,active)
+ return if $activeFloor2 == active
+
+ w.delete('all')
+ $activeFloor2 = active
+
+ # First go through the three floors, displaying the backgrounds for
+ # each floor.
+
+ floor2_bg1(w,$floor2_colors['bg1'],$floor2_colors['outline1'])
+ floor2_bg2(w,$floor2_colors['bg2'],$floor2_colors['outline2'])
+ floor2_bg3(w,$floor2_colors['bg3'],$floor2_colors['outline3'])
+
+ # Raise the background for the active floor so that it's on top.
+
+ w.raise("floor#{active}")
+
+ # Create a dummy item just to mark this point in the display list,
+ # so we can insert highlights here.
+
+ w.create(TkcRectangle,0,100,1,101,'fill'=>'','outline'=>'','tags'=>'marker')
+
+ # Add the walls and labels for the active floor, along with
+ # transparent polygons that define the rooms on the floor.
+ # Make sure that the room polygons are on top.
+
+ $floorLabels2.clear
+ $floorItems2.clear
+ send("floor2_fg#{active}", w, $floor2_colors['offices'])
+ w.raise('room')
+
+ # Offset the floors diagonally from each other.
+
+ w.move('floor1', '2c', '2c')
+ w.move('floor2', '1c', '1c')
+
+ # Create items for the room entry and its label.
+ w.create(TkcWindow, 600, 100, 'anchor'=>'w', 'window'=>$floor2_entry)
+ w.create(TkcText, 600, 100, 'anchor'=>'e', 'text'=>"Room: ")
+ w['scrollregion'] = w.bbox('all')
+end
+
+# newRoom2 --
+# This method is invoked whenever the mouse enters a room
+# in the floorplan. It changes tags so that the current room is
+# highlighted.
+#
+# Arguments:
+# w - The name of the canvas window.
+
+def newRoom2(w)
+ id = w.find_withtag('current')[0]
+ $currentRoom2.value = $floorLabels2[id.id] if id != ""
+ Tk.update(true)
+end
+
+# roomChanged2 --
+# This method is invoked whenever the currentRoom variable changes.
+# It highlights the current room and unhighlights any previous room.
+#
+# Arguments:
+# w - The canvas window displaying the floorplan.
+# args - Not used.
+
+def roomChanged2(w,*args)
+ w.delete('highlight')
+ item = $floorItems2[$currentRoom2.value]
+ return if item == nil
+ new = TkcPolygon.new(w, *(w.coords(item)))
+ new.configure('fill'=>$floor2_colors['active'], 'tags'=>'highlight')
+ w.raise(new, 'marker')
+end
+
+# floor2_bg1 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the background information for the first
+# floor.
+#
+# Arguments:
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
+
+def floor2_bg1(w,fill,outline)
+ w.create(TkcPolygon,347,80,349,82,351,84,353,85,363,92,375,99,386,104,
+ 386,129,398,129,398,162,484,162,484,129,559,129,559,133,725,
+ 133,725,129,802,129,802,389,644,389,644,391,559,391,559,327,
+ 508,327,508,311,484,311,484,278,395,278,395,288,400,288,404,
+ 288,409,290,413,292,418,297,421,302,422,309,421,318,417,325,
+ 411,330,405,332,397,333,344,333,340,334,336,336,335,338,332,
+ 342,331,347,332,351,334,354,336,357,341,359,340,360,335,363,
+ 331,365,326,366,304,366,304,355,258,355,258,387,60,387,60,391,
+ 0,391,0,337,3,337,3,114,8,114,8,25,30,25,30,5,93,5,98,5,104,7,
+ 110,10,116,16,119,20,122,28,123,32,123,68,220,68,220,34,221,
+ 22,223,17,227,13,231,8,236,4,242,2,246,0,260,0,283,1,300,5,
+ 321,14,335,22,348,25,365,29,363,39,358,48,352,56,337,70,
+ 344,76,347,80, 'tags'=>['floor1','bg'], 'fill'=>fill)
+ w.create(TkcLine,386,129,398,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,258,355,258,387, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,60,387,60,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,0,337,0,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,3,114,3,337, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,258,387,60,387, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,162,398,162, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,398,162,398,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,278,484,311, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,311,508,311, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,508,327,508,311, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,559,327,508,327, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,644,391,559,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,644,389,644,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,559,129,484,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,162,484,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,725,133,559,133, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,559,129,559,133, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,725,129,802,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,802,389,802,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,3,337,0,337, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,559,391,559,327, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,802,389,644,389, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,725,133,725,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,8,25,8,114, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,8,114,3,114, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,30,25,8,25, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,278,395,278, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,30,25,30,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,93,5,30,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,98,5,93,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,104,7,98,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,110,10,104,7, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,116,16,110,10, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,119,20,116,16, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,122,28,119,20, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,123,32,122,28, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,123,68,123,32, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,220,68,123,68, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,386,129,386,104, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,386,104,375,99, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,375,99,363,92, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,353,85,363,92, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,220,68,220,34, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,337,70,352,56, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,352,56,358,48, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,358,48,363,39, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,363,39,365,29, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,365,29,348,25, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,348,25,335,22, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,335,22,321,14, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,321,14,300,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,300,5,283,1, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,283,1,260,0, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,260,0,246,0, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,246,0,242,2, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,242,2,236,4, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,236,4,231,8, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,231,8,227,13, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,223,17,227,13, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,221,22,223,17, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,220,34,221,22, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,340,360,335,363, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,335,363,331,365, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,331,365,326,366, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,326,366,304,366, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,304,355,304,366, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,395,288,400,288, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,404,288,400,288, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,409,290,404,288, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,413,292,409,290, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,418,297,413,292, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,421,302,418,297, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,422,309,421,302, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,421,318,422,309, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,421,318,417,325, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,417,325,411,330, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,411,330,405,332, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,405,332,397,333, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,397,333,344,333, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,344,333,340,334, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,340,334,336,336, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,336,336,335,338, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,335,338,332,342, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,331,347,332,342, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,332,351,331,347, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,334,354,332,351, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,336,357,334,354, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,341,359,336,357, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,341,359,340,360, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,395,288,395,278, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,304,355,258,355, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,347,80,344,76, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,344,76,337,70, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,349,82,347,80, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,351,84,349,82, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,353,85,351,84, 'fill'=>outline, 'tags'=>['floor1','bg'])
+end
+
+# floor2_bg2 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the background information for the first
+# floor.
+#
+# Arguments:
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
+
+def floor2_bg2(w,fill,outline)
+ w.create(TkcPolygon,559,129,484,129,484,162,398,162,398,129,315,129,
+ 315,133,176,133,176,129,96,129,96,133,3,133,3,339,0,339,0,391,
+ 60,391,60,387,258,387,258,329,350,329,350,311,395,311,395,280,
+ 484,280,484,311,508,311,508,327,558,327,558,391,644,391,644,
+ 367,802,367,802,129,725,129,725,133,559,133,559,129,
+ 'tags'=>['floor2','bg'], 'fill'=>fill)
+ w.create(TkcLine,350,311,350,329, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,398,129,398,162, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,802,367,802,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,802,129,725,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,725,133,725,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,559,129,559,133, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,559,133,725,133, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,484,162,484,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,559,129,484,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,802,367,644,367, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,644,367,644,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,644,391,558,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,558,327,558,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,558,327,508,327, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,508,327,508,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,484,311,508,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,484,280,484,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,398,162,484,162, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,484,280,395,280, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,395,280,395,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,258,387,60,387, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,3,133,3,339, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,3,339,0,339, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,0,339,0,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,60,387,60,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,258,329,258,387, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,350,329,258,329, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,395,311,350,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,398,129,315,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,176,133,315,133, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,176,129,96,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,3,133,96,133, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,315,133,315,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,176,133,176,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,96,133,96,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+end
+
+# floor2_bg3 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the background information for the first
+# floor.
+#
+# Arguments:
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
+
+def floor2_bg3(w,fill,outline)
+ w.create(TkcPolygon,159,300,107,300,107,248,159,248,159,129,96,129,96,
+ 133,21,133,21,331,0,331,0,391,60,391,60,370,159,370,159,300,
+ 'tags'=>['floor3','bg'], 'fill'=>fill)
+ w.create(TkcPolygon,258,370,258,329,350,329,350,311,399,311,399,129,
+ 315,129,315,133,176,133,176,129,159,129,159,370,258,370,
+ 'tags'=>['floor3','bg'], 'fill'=>fill)
+ w.create(TkcLine,96,133,96,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,176,129,96,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,176,129,176,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,315,133,176,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,315,133,315,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,399,129,315,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,399,311,399,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,399,311,350,311, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,350,329,350,311, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,350,329,258,329, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,258,370,258,329, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,60,370,258,370, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,60,370,60,391, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,0,391,0,331, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,21,331,0,331, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,21,331,21,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,96,133,21,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,107,300,159,300,159,248,107,248,107,300,
+ 'fill'=>outline, 'tags'=>['floor3','bg'])
+end
+
+# floor2_fg1 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the foreground information for the first
+# floor (office outlines and numbers).
+#
+# Arguments:
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
+
+def floor2_fg1(w,color)
+ i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '101'
+ $floorItems2['101'] = i
+ w.create(TkcText,358,209, 'text'=>'101', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Pub Lift1'
+ $floorItems2['Pub Lift1'] = i
+ w.create(TkcText,323,223, 'text'=>'Pub Lift1', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Priv Lift1'
+ $floorItems2['Priv Lift1'] = i
+ w.create(TkcText,323,188, 'text'=>'Priv Lift1', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,42,389,42,337,1,337,1,389,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '110'
+ $floorItems2['110'] = i
+ w.create(TkcText,21.5,363, 'text'=>'110', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,59,389,59,385,90,385,90,337,44,337,44,389,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '109'
+ $floorItems2['109'] = i
+ w.create(TkcText,67,363, 'text'=>'109', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,51,300,51,253,6,253,6,300,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '111'
+ $floorItems2['111'] = i
+ w.create(TkcText,28.5,276.5, 'text'=>'111', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,98,248,98,309,79,309,79,248,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '117B'
+ $floorItems2['117B'] = i
+ w.create(TkcText,88.5,278.5, 'text'=>'117B', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,51,251,51,204,6,204,6,251,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '112'
+ $floorItems2['112'] = i
+ w.create(TkcText,28.5,227.5, 'text'=>'112', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,6,156,51,156,51,203,6,203,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '113'
+ $floorItems2['113'] = i
+ w.create(TkcText,28.5,179.5, 'text'=>'113', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,85,169,79,169,79,192,85,192,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '117A'
+ $floorItems2['117A'] = i
+ w.create(TkcText,82,180.5, 'text'=>'117A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,77,302,77,168,53,168,53,302,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '117'
+ $floorItems2['117'] = i
+ w.create(TkcText,65,235, 'text'=>'117', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,51,155,51,115,6,115,6,155,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '114'
+ $floorItems2['114'] = i
+ w.create(TkcText,28.5,135, 'text'=>'114', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,95,115,53,115,53,168,95,168,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '115'
+ $floorItems2['115'] = i
+ w.create(TkcText,74,141.5, 'text'=>'115', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,87,113,87,27,10,27,10,113,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '116'
+ $floorItems2['116'] = i
+ w.create(TkcText,48.5,70, 'text'=>'116', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,89,91,128,91,128,113,89,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '118'
+ $floorItems2['118'] = i
+ w.create(TkcText,108.5,102, 'text'=>'118', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,178,128,178,132,216,132,216,91,
+ 163,91,163,112,149,112,149,128,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '120'
+ $floorItems2['120'] = i
+ w.create(TkcText,189.5,111.5, 'text'=>'120', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,79,193,87,193,87,169,136,169,136,192,
+ 156,192,156,169,175,169,175,246,79,246,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '122'
+ $floorItems2['122'] = i
+ w.create(TkcText,131,207.5, 'text'=>'122', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,138,169,154,169,154,191,138,191,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '121'
+ $floorItems2['121'] = i
+ w.create(TkcText,146,180, 'text'=>'121', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,99,300,126,300,126,309,99,309,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '106A'
+ $floorItems2['106A'] = i
+ w.create(TkcText,112.5,304.5, 'text'=>'106A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,128,299,128,309,150,309,150,248,99,248,99,299,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '105'
+ $floorItems2['105'] = i
+ w.create(TkcText,124.5,278.5, 'text'=>'105', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,174,309,174,300,152,300,152,309,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '106B'
+ $floorItems2['106B'] = i
+ w.create(TkcText,163,304.5, 'text'=>'106B', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,176,299,176,309,216,309,216,248,152,248,152,299,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '104'
+ $floorItems2['104'] = i
+ w.create(TkcText,184,278.5, 'text'=>'104', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,138,385,138,337,91,337,91,385,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '108'
+ $floorItems2['108'] = i
+ w.create(TkcText,114.5,361, 'text'=>'108', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,256,337,140,337,140,385,256,385,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '107'
+ $floorItems2['107'] = i
+ w.create(TkcText,198,361, 'text'=>'107', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,300,353,300,329,260,329,260,353,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Smoking'
+ $floorItems2['Smoking'] = i
+ w.create(TkcText,280,341, 'text'=>'Smoking', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,314,135,314,170,306,170,306,246,177,246,177,135,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '123'
+ $floorItems2['123'] = i
+ w.create(TkcText,245.5,190.5, 'text'=>'123', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,217,248,301,248,301,326,257,326,257,310,217,310,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '103'
+ $floorItems2['103'] = i
+ w.create(TkcText,259,287, 'text'=>'103', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,396,188,377,188,377,169,316,169,316,131,396,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '124'
+ $floorItems2['124'] = i
+ w.create(TkcText,356,150, 'text'=>'124', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,397,226,407,226,407,189,377,189,377,246,397,246,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '125'
+ $floorItems2['125'] = i
+ w.create(TkcText,392,217.5, 'text'=>'125', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,399,187,409,187,409,207,474,207,474,164,399,164,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '126'
+ $floorItems2['126'] = i
+ w.create(TkcText,436.5,185.5, 'text'=>'126', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,409,209,409,229,399,229,399,253,
+ 486,253,486,239,474,239,474,209,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '127'
+ $floorItems2['127'] = i
+ w.create(TkcText,436.5,'231', 'text'=>'127', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,501,164,501,174,495,174,495,188,
+ 490,188,490,204,476,204,476,164,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'MShower'
+ $floorItems2['MShower'] = i
+ w.create(TkcText,488.5,'184', 'text'=>'MShower', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,497,176,513,176,513,204,492,204,492,190,497,190,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Closet'
+ $floorItems2['Closet'] = i
+ w.create(TkcText,502.5,190, 'text'=>'Closet', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,476,237,476,206,513,206,513,254,488,254,488,237,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'WShower'
+ $floorItems2['WShower'] = i
+ w.create(TkcText,494.5,230, 'text'=>'WShower', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,486,131,558,131,558,135,724,135,724,166,
+ 697,166,697,275,553,275,531,254,515,254,
+ 515,174,503,174,503,161,486,161,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '130'
+ $floorItems2['130'] = i
+ w.create(TkcText,638.5,205, 'text'=>'130', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,308,242,339,242,339,248,342,248,
+ 342,246,397,246,397,276,393,276,
+ 393,309,300,309,300,248,308,248,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '102'
+ $floorItems2['102'] = i
+ w.create(TkcText,367.5,278.5, 'text'=>'102', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,397,255,486,255,486,276,397,276,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '128'
+ $floorItems2['128'] = i
+ w.create(TkcText,441.5,265.5, 'text'=>'128', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,510,309,486,309,486,255,530,255,
+ 552,277,561,277,561,325,510,325,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '129'
+ $floorItems2['129'] = i
+ w.create(TkcText,535.5,293, 'text'=>'129', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,696,281,740,281,740,387,642,387,
+ 642,389,561,389,561,277,696,277,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '133'
+ $floorItems2['133'] = i
+ w.create(TkcText,628.5,335, 'text'=>'133', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,742,387,742,281,800,281,800,387,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '132'
+ $floorItems2['132'] = i
+ w.create(TkcText,771,334, 'text'=>'132', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,800,168,800,280,699,280,699,168,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '134'
+ $floorItems2['134'] = i
+ w.create(TkcText,749.5,224, 'text'=>'134', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,726,131,726,166,800,166,800,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '135'
+ $floorItems2['135'] = i
+ w.create(TkcText,763,148.5, 'text'=>'135', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,340,360,335,363,331,365,326,366,304,366,
+ 304,312,396,312,396,288,400,288,404,288,
+ 409,290,413,292,418,297,421,302,422,309,
+ 421,318,417,325,411,330,405,332,397,333,
+ 344,333,340,334,336,336,335,338,332,342,
+ 331,347,332,351,334,354,336,357,341,359,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Ramona Stair'
+ $floorItems2['Ramona Stair'] = i
+ w.create(TkcText,368,323, 'text'=>'Ramona Stair', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,30,23,30,5,93,5,98,5,104,7,110,10,116,16,119,20,
+ 122,28,123,32,123,68,220,68,220,87,90,87,90,23,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'University Stair'
+ $floorItems2['University Stair'] = i
+ w.create(TkcText,155,77.5, 'text'=>'University Stair', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,282,37,295,40,312,49,323,56,337,70,352,56,
+ 358,48,363,39,365,29,348,25,335,22,321,14,
+ 300,5,283,1,260,0,246,0,242,2,236,4,231,8,
+ 227,13,223,17,221,22,220,34,260,34,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Plaza Stair'
+ $floorItems2['Plaza Stair'] = i
+ w.create(TkcText,317.5,28.5, 'text'=>'Plaza Stair', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,220,34,260,34,282,37,295,40,312,49,
+ 323,56,337,70,350,83,365,94,377,100,
+ 386,104,386,128,220,128,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Plaza Deck'
+ $floorItems2['Plaza Deck'] = i
+ w.create(TkcText,303,81, 'text'=>'Plaza Deck', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,257,336,77,336,6,336,6,301,77,301,77,310,257,310,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '106'
+ $floorItems2['106'] = i
+ w.create(TkcText,131.5,318.5, 'text'=>'106', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,146,110,162,110,162,91,130,91,130,115,95,115,
+ 95,128,114,128,114,151,157,151,157,153,112,153,
+ 112,130,97,130,97,168,175,168,175,131,146,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '119'
+ $floorItems2['119'] = i
+ w.create(TkcText,143.5,133, 'text'=>'119', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ w.create(TkcLine,155,191,155,189, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,155,177,155,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,96,129,96,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,169,176,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,176,247,176,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,206,307,206, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,187,340,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,210,340,201, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,247,340,224, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,241,307,241, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,376,246,376,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,307,247,307,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,376,170,307,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,315,129,315,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,147,129,176,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,202,133,176,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,398,129,315,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,352,258,387, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,60,387,60,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,0,337,0,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,3,114,3,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,387,60,387, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,237,52,273, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,189,52,225, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,140,52,177, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,395,306,395,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,531,254,398,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,475,178,475,238, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,502,162,398,162, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,398,129,398,188, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,383,188,376,188, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,188,408,194, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,398,227,398,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,227,398,227, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,222,408,227, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,206,408,210, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,208,475,208, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,484,278,484,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,484,311,508,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,508,327,508,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,559,327,508,327, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,644,391,559,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,644,389,644,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,514,205,475,205, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,496,189,496,187, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,559,129,484,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,484,162,484,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,725,133,559,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,559,129,559,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,725,149,725,167, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,725,129,802,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,802,389,802,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,739,167,802,167, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,396,188,408,188, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,0,337,9,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,58,337,21,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,43,391,43,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,105,337,75,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,91,387,91,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,154,337,117,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,139,387,139,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,227,337,166,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,337,251,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,328,302,328, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,302,355,302,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,395,311,302,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,484,278,395,278, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,395,294,395,278, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,473,278,473,275, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,473,256,473,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,533,257,531,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,553,276,551,274, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,698,276,553,276, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,559,391,559,327, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,802,389,644,389, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,741,314,741,389, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,698,280,698,167, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,707,280,698,280, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,802,280,731,280, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,741,280,741,302, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,698,167,727,167, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,725,137,725,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,514,254,514,175, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,496,175,514,175, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,502,175,502,162, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,475,166,475,162, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,496,176,496,175, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,491,189,496,189, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,491,205,491,189, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,487,238,475,238, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,487,240,487,238, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,487,252,487,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,315,133,304,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,256,133,280,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,247,270,247, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,307,247,294,247, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,214,133,232,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,217,247,217,266, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,217,309,217,291, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,217,309,172,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,154,309,148,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,175,300,175,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,151,300,175,300, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,151,247,151,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,237,78,265, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,286,78,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,106,309,78,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,130,309,125,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,99,309,99,247, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,127,299,99,299, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,127,309,127,299, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,155,191,137,191, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,137,169,137,191, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,171,78,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,190,78,218, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,86,192,86,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,86,192,78,192, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,301,3,301, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,286,52,301, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,252,3,252, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,203,3,203, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,3,156,52,156, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,8,25,8,114, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,63,114,3,114, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,75,114,97,114, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,108,114,129,114, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,129,114,129,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,114,52,128, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,132,89,88,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,88,25,88,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,88,114,88,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,218,89,144,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,147,111,147,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,162,111,147,111, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,162,109,162,111, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,162,96,162,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,218,89,218,94, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,218,89,218,119, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,8,25,88,25, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,337,258,328, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,113,129,96,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,302,355,258,355, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,386,104,386,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,377,100,386,104, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,365,94,377,100, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,350,83,365,94, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,337,70,350,83, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,337,70,323,56, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,312,49,323,56, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,295,40,312,49, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,282,37,295,40, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,260,34,282,37, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,253,34,260,34, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,386,128,386,104, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,113,152,156,152, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,113,152,156,152, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,113,152,113,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+end
+
+# floor2_fg2 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the foreground information for the second
+# floor (office outlines and numbers).
+#
+# Arguments:
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
+
+def floor2_fg2(w,color)
+ i = TkcPolygon.new(w,748,188,755,188,755,205,758,205,758,222,
+ 800,222,800,168,748,168,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '238'
+ $floorItems2['238'] = i
+ w.create(TkcText,774,195, 'text'=>'238', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,726,188,746,188,746,166,800,166,800,131,726,131,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '237'
+ $floorItems2['237'] = i
+ w.create(TkcText,763,148.5, 'text'=>'237', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,497,187,497,204,559,204,559,324,641,324,
+ 643,324,643,291,641,291,641,205,696,205,
+ 696,291,694,291,694,314,715,314,715,291,
+ 715,205,755,205,755,190,724,190,724,187,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '246'
+ $floorItems2['246'] = i
+ w.create(TkcText,600,264, 'text'=>'246', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,694,279,643,279,643,314,694,314,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '247'
+ $floorItems2['247'] = i
+ w.create(TkcText,668.5,296.5, 'text'=>'247', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,232,250,308,250,308,242,339,242,339,246,
+ 397,246,397,255,476,255,476,250,482,250,559,250,
+ 559,274,482,274,482,278,396,278,396,274,232,274,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '202'
+ $floorItems2['202'] = i
+ w.create(TkcText,285.5,260, 'text'=>'202', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,53,228,53,338,176,338,233,338,233,196,
+ 306,196,306,180,175,180,175,169,156,169,
+ 156,196,176,196,176,228,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '206'
+ $floorItems2['206'] = i
+ w.create(TkcText,143,267, 'text'=>'206', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,51,277,6,277,6,338,51,338,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '212'
+ $floorItems2['212'] = i
+ w.create(TkcText,28.5,307.5, 'text'=>'212', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,557,276,486,276,486,309,510,309,510,325,557,325,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '245'
+ $floorItems2['245'] = i
+ w.create(TkcText,521.5,300.5, 'text'=>'245', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,560,389,599,389,599,326,560,326,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '244'
+ $floorItems2['244'] = i
+ w.create(TkcText,579.5,357.5, 'text'=>'244', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,601,389,601,326,643,326,643,389,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '243'
+ $floorItems2['243'] = i
+ w.create(TkcText,622,357.5, 'text'=>'243', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,688,316,645,316,645,365,688,365,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '242'
+ $floorItems2['242'] = i
+ w.create(TkcText,666.5,340.5, 'text'=>'242', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,802,367,759,367,759,226,802,226,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = 'Barbecue Deck'
+ $floorItems2['Barbecue Deck'] = i
+ w.create(TkcText,780.5,296.5, 'text'=>'Barbecue Deck', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,755,262,755,314,717,314,717,262,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '240'
+ $floorItems2['240'] = i
+ w.create(TkcText,736,288, 'text'=>'240', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,755,316,689,316,689,365,755,365,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '241'
+ $floorItems2['241'] = i
+ w.create(TkcText,722,340.5, 'text'=>'241', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,755,206,717,206,717,261,755,261,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '239'
+ $floorItems2['239'] = i
+ w.create(TkcText,736,233.5, 'text'=>'239', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,695,277,643,277,643,206,695,206,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '248'
+ $floorItems2['248'] = i
+ w.create(TkcText,669,241.5, 'text'=>'248', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,676,135,676,185,724,185,724,135,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '236'
+ $floorItems2['236'] = i
+ w.create(TkcText,700,160, 'text'=>'236', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,675,135,635,135,635,145,628,145,628,185,675,185,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '235'
+ $floorItems2['235'] = i
+ w.create(TkcText,651.5,160, 'text'=>'235', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,626,143,633,143,633,135,572,135,
+ 572,143,579,143,579,185,626,185,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '234'
+ $floorItems2['234'] = i
+ w.create(TkcText,606,160, 'text'=>'234', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,557,135,571,135,571,145,578,145,
+ 578,185,527,185,527,131,557,131,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '233'
+ $floorItems2['233'] = i
+ w.create(TkcText,552.5,158, 'text'=>'233', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,476,249,557,249,557,205,476,205,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '230'
+ $floorItems2['230'] = i
+ w.create(TkcText,516.5,227, 'text'=>'230', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,476,164,486,164,486,131,525,131,525,185,476,185,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '232'
+ $floorItems2['232'] = i
+ w.create(TkcText,500.5,158, 'text'=>'232', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,476,186,495,186,495,204,476,204,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '229'
+ $floorItems2['229'] = i
+ w.create(TkcText,485.5,195, 'text'=>'229', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,474,207,409,207,409,187,399,187,399,164,474,164,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '227'
+ $floorItems2['227'] = i
+ w.create(TkcText,436.5,185.5, 'text'=>'227', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,399,228,399,253,474,253,474,209,409,209,409,228,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '228'
+ $floorItems2['228'] = i
+ w.create(TkcText,436.5,231, 'text'=>'228', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,397,246,397,226,407,226,407,189,377,189,377,246,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '226'
+ $floorItems2['226'] = i
+ w.create(TkcText,392,217.5, 'text'=>'226', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,377,169,316,169,316,131,397,131,397,188,377,188,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '225'
+ $floorItems2['225'] = i
+ w.create(TkcText,356.5,150, 'text'=>'225', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,234,198,306,198,306,249,234,249,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '224'
+ $floorItems2['224'] = i
+ w.create(TkcText,270,223.5, 'text'=>'224', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,270,179,306,179,306,170,314,170,314,135,270,135,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '223'
+ $floorItems2['223'] = i
+ w.create(TkcText,292,157, 'text'=>'223', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,268,179,221,179,221,135,268,135,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '222'
+ $floorItems2['222'] = i
+ w.create(TkcText,244.5,157, 'text'=>'222', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,177,179,219,179,219,135,177,135,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '221'
+ $floorItems2['221'] = i
+ w.create(TkcText,198,157, 'text'=>'221', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,299,327,349,327,349,284,341,284,341,276,299,276,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '204'
+ $floorItems2['204'] = i
+ w.create(TkcText,324,301.5, 'text'=>'204', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,234,276,297,276,297,327,257,327,257,338,234,338,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '205'
+ $floorItems2['205'] = i
+ w.create(TkcText,265.5,307, 'text'=>'205', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,256,385,256,340,212,340,212,385,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '207'
+ $floorItems2['207'] = i
+ w.create(TkcText,234,362.5, 'text'=>'207', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,210,340,164,340,164,385,210,385,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '208'
+ $floorItems2['208'] = i
+ w.create(TkcText,187,362.5, 'text'=>'208', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,115,340,162,340,162,385,115,385,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '209'
+ $floorItems2['209'] = i
+ w.create(TkcText,138.5,362.5, 'text'=>'209', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,89,228,89,156,53,156,53,228,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '217'
+ $floorItems2['217'] = i
+ w.create(TkcText,71,192, 'text'=>'217', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,89,169,97,169,97,190,89,190,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '217A'
+ $floorItems2['217A'] = i
+ w.create(TkcText,93,179.5, 'text'=>'217A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,89,156,89,168,95,168,95,135,53,135,53,156,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '216'
+ $floorItems2['216'] = i
+ w.create(TkcText,71,145.5, 'text'=>'216', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,51,179,51,135,6,135,6,179,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '215'
+ $floorItems2['215'] = i
+ w.create(TkcText,28.5,157, 'text'=>'215', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,51,227,6,227,6,180,51,180,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '214'
+ $floorItems2['214'] = i
+ w.create(TkcText,28.5,203.5, 'text'=>'214', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,51,275,6,275,6,229,51,229,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '213'
+ $floorItems2['213'] = i
+ w.create(TkcText,28.5,252, 'text'=>'213', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,114,340,67,340,67,385,114,385,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '210'
+ $floorItems2['210'] = i
+ w.create(TkcText,90.5,362.5, 'text'=>'210', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,59,389,59,385,65,385,65,340,1,340,1,389,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '211'
+ $floorItems2['211'] = i
+ w.create(TkcText,33,364.5, 'text'=>'211', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,393,309,350,309,350,282,342,282,342,276,393,276,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '203'
+ $floorItems2['203'] = i
+ w.create(TkcText,367.5,292.5, 'text'=>'203', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,99,191,91,191,91,226,174,226,174,198,
+ 154,198,154,192,109,192,109,169,99,169,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '220'
+ $floorItems2['220'] = i
+ w.create(TkcText,132.5,208.5, 'text'=>'220', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = 'Priv Lift2'
+ $floorItems2['Priv Lift2'] = i
+ w.create(TkcText,323,188, 'text'=>'Priv Lift2', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = 'Pub Lift 2'
+ $floorItems2['Pub Lift 2'] = i
+ w.create(TkcText,323,223, 'text'=>'Pub Lift 2', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,175,168,97,168,97,131,175,131,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '218'
+ $floorItems2['218'] = i
+ w.create(TkcText,136,149.5, 'text'=>'218', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,154,191,111,191,111,169,154,169,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '219'
+ $floorItems2['219'] = i
+ w.create(TkcText,132.5,180, 'text'=>'219', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '201'
+ $floorItems2['201'] = i
+ w.create(TkcText,358,209, 'text'=>'201', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ w.create(TkcLine,641,186,678,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,350,757,367, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,634,133,634,144, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,634,144,627,144, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,572,133,572,144, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,572,144,579,144, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,129,398,162, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,174,197,175,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,175,197,175,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,206,757,221, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,396,188,408,188, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,727,189,725,189, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,747,167,802,167, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,747,167,747,189, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,755,189,739,189, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,769,224,757,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,802,224,802,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,802,129,725,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,725,189,725,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,725,186,690,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,676,133,676,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,627,144,627,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,629,186,593,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,579,144,579,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,559,129,559,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,725,133,559,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,484,162,484,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,559,129,484,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,526,129,526,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,540,186,581,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,528,186,523,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,511,186,475,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,496,190,496,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,496,205,496,202, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,475,205,527,205, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,205,539,205, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,205,558,249, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,249,475,249, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,662,206,642,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,695,206,675,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,695,278,642,278, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,642,291,642,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,695,291,695,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,716,208,716,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,206,716,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,221,757,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,793,224,802,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,262,716,262, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,716,220,716,264, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,716,315,716,276, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,315,703,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,325,757,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,367,644,367, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,689,367,689,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,647,315,644,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,659,315,691,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,600,325,600,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,627,325,644,325, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,644,391,644,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,615,325,575,325, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,644,391,558,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,563,325,558,325, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,391,558,314, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,327,508,327, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,275,484,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,302,558,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,508,327,508,311, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,484,311,508,311, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,484,275,484,311, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,475,208,408,208, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,408,206,408,210, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,408,222,408,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,408,227,398,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,227,398,254, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,408,188,408,194, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,383,188,376,188, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,188,398,162, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,162,484,162, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,475,162,475,254, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,254,475,254, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,484,280,395,280, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,395,311,395,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,307,197,293,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,278,197,233,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,233,197,233,249, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,307,179,284,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,233,249,278,249, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,269,179,269,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,220,179,220,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,155,191,110,191, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,90,190,98,190, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,98,169,98,190, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,133,52,165, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,214,52,177, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,226,52,262, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,274,52,276, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,234,275,234,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,226,339,258,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,211,387,211,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,214,339,177,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,258,387,60,387, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,3,133,3,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,165,339,129,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,117,339,80,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,68,339,59,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,0,339,46,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,0,339,0,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,60,387,60,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,258,329,258,387, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,350,329,258,329, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,395,311,350,311, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,129,315,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,176,133,315,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,176,129,96,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,3,133,96,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,66,387,66,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,115,387,115,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,163,387,163,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,234,275,276,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,288,275,309,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,298,275,298,329, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,341,283,350,283, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,321,275,341,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,375,275,395,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,315,129,315,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,376,170,307,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,307,250,307,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,376,245,376,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,241,307,241, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,245,340,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,210,340,201, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,187,340,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,206,307,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,293,250,307,250, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,271,179,238,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,226,179,195,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,176,129,176,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,182,179,176,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,174,169,176,169, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,162,169,90,169, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,96,169,96,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,175,227,90,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,90,190,90,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,179,3,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,228,3,228, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,276,3,276, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,155,177,155,169, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,110,191,110,169, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,155,189,155,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,350,283,350,329, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,162,197,155,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,341,275,341,283, 'fill'=>color, 'tags'=>['floor2','wall'])
+end
+
+# floor2_fg3 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the foreground information for the third
+# floor (office outlines and numbers).
+#
+# Arguments:
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
+
+def floor2_fg3(w,color)
+ i = TkcPolygon.new(w,89,228,89,180,70,180,70,228,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '316'
+ $floorItems2['316'] = i
+ w.create(TkcText,79.5,204, 'text'=>'316', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,115,368,162,368,162,323,115,323,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '309'
+ $floorItems2['309'] = i
+ w.create(TkcText,138.5,345.5, 'text'=>'309', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,164,323,164,368,211,368,211,323,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '308'
+ $floorItems2['308'] = i
+ w.create(TkcText,187.5,345.5, 'text'=>'308', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,256,368,212,368,212,323,256,323,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '307'
+ $floorItems2['307'] = i
+ w.create(TkcText,234,345.5, 'text'=>'307', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,244,276,297,276,297,327,260,327,260,321,244,321,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '305'
+ $floorItems2['305'] = i
+ w.create(TkcText,270.5,301.5, 'text'=>'305', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,251,219,251,203,244,203,244,219,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '324B'
+ $floorItems2['324B'] = i
+ w.create(TkcText,247.5,211, 'text'=>'324B', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,251,249,244,249,244,232,251,232,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '324A'
+ $floorItems2['324A'] = i
+ w.create(TkcText,247.5,240.5, 'text'=>'324A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,223,135,223,179,177,179,177,135,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '320'
+ $floorItems2['320'] = i
+ w.create(TkcText,200,157, 'text'=>'320', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,114,368,114,323,67,323,67,368,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '310'
+ $floorItems2['310'] = i
+ w.create(TkcText,90.5,345.5, 'text'=>'310', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,23,277,23,321,68,321,68,277,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '312'
+ $floorItems2['312'] = i
+ w.create(TkcText,45.5,299, 'text'=>'312', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,23,229,68,229,68,275,23,275,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '313'
+ $floorItems2['313'] = i
+ w.create(TkcText,45.5,252, 'text'=>'313', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,68,227,23,227,23,180,68,180,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '314'
+ $floorItems2['314'] = i
+ w.create(TkcText,40.5,203.5, 'text'=>'314', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,95,179,95,135,23,135,23,179,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '315'
+ $floorItems2['315'] = i
+ w.create(TkcText,59,157, 'text'=>'315', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,99,226,99,204,91,204,91,226,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '316B'
+ $floorItems2['316B'] = i
+ w.create(TkcText,95,215, 'text'=>'316B', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,91,202,99,202,99,180,91,180,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '316A'
+ $floorItems2['316A'] = i
+ w.create(TkcText,95,191, 'text'=>'316A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,97,169,109,169,109,192,154,192,154,198,
+ 174,198,174,226,101,226,101,179,97,179,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '319'
+ $floorItems2['319'] = i
+ w.create(TkcText,141.5,209, 'text'=>'319', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,65,368,58,368,58,389,1,389,1,333,23,333,23,323,65,323,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '311'
+ $floorItems2['311'] = i
+ w.create(TkcText,29.5,361, 'text'=>'311', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,154,191,111,191,111,169,154,169,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '318'
+ $floorItems2['318'] = i
+ w.create(TkcText,132.5,180, 'text'=>'318', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,175,168,97,168,97,131,175,131,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '317'
+ $floorItems2['317'] = i
+ w.create(TkcText,136,149.5, 'text'=>'317', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,274,194,274,221,306,221,306,194,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '323'
+ $floorItems2['323'] = i
+ w.create(TkcText,290,207.5, 'text'=>'323', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,306,222,274,222,274,249,306,249,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '325'
+ $floorItems2['325'] = i
+ w.create(TkcText,290,235.5, 'text'=>'325', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,263,179,224,179,224,135,263,135,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '321'
+ $floorItems2['321'] = i
+ w.create(TkcText,243.5,157, 'text'=>'321', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,314,169,306,169,306,192,273,192,
+ 264,181,264,135,314,135,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '322'
+ $floorItems2['322'] = i
+ w.create(TkcText,293.5,163.5, 'text'=>'322', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = 'Pub Lift3'
+ $floorItems2['Pub Lift3'] = i
+ w.create(TkcText,323,223, 'text'=>'Pub Lift3', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = 'Priv Lift3'
+ $floorItems2['Priv Lift3'] = i
+ w.create(TkcText,323,188, 'text'=>'Priv Lift3', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,350,284,376,284,376,276,397,276,397,309,350,309,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '303'
+ $floorItems2['303'] = i
+ w.create(TkcText,373.5,292.5, 'text'=>'303', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,272,203,272,249,252,249,252,230,
+ 244,230,244,221,252,221,252,203,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '324'
+ $floorItems2['324'] = i
+ w.create(TkcText,262,226, 'text'=>'324', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,299,276,299,327,349,327,349,284,341,284,341,276,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '304'
+ $floorItems2['304'] = i
+ w.create(TkcText,324,301.5, 'text'=>'304', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '301'
+ $floorItems2['301'] = i
+ w.create(TkcText,358,209, 'text'=>'301', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,397,246,377,246,377,185,397,185,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '327'
+ $floorItems2['327'] = i
+ w.create(TkcText,387,215.5, 'text'=>'327', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,316,131,316,169,377,169,377,185,397,185,397,131,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '326'
+ $floorItems2['326'] = i
+ w.create(TkcText,365.5,150, 'text'=>'326', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,308,251,242,251,242,274,342,274,342,282,375, 282,
+ 375,274,397,274,397,248,339,248,339,242,308,242,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '302'
+ $floorItems2['302'] = i
+ w.create(TkcText,319.5,261, 'text'=>'302', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,70,321,242,321,242,200,259,200,259,203,272,203,
+ 272,193,263,180,242,180,175,180,175,169,156,169,
+ 156,196,177,196,177,228,107,228,70,228,70,275,107,275,
+ 107,248,160,248,160,301,107,301,107,275,70,275,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '306'
+ $floorItems2['306'] = i
+ w.create(TkcText,200.5,284.5, 'text'=>'306', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ w.create(TkcLine,341,275,341,283, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,162,197,155,197, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,396,247,399,247, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,399,129,399,311, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,258,202,243,202, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,350,283,350,329, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,251,231,243,231, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,243,220,251,220, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,243,250,243,202, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,155,197,155,190, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,110,192,110,169, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,155,192,110,192, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,155,177,155,169, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,176,197,176,227, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,69,280,69,274, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,276,69,276, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,69,262,69,226, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,228,69,228, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,179,75,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,69,179,69,214, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,220,90,227, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,204,90,202, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,203,100,203, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,187,90,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,227,176,227, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,100,179,100,227, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,100,179,87,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,96,179,96,129, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,162,169,96,169, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,173,169,176,169, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,182,179,176,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,176,129,176,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,195,179,226,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,224,133,224,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,264,179,264,133, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,238,179,264,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,207,273,193, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,235,273,250, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,224,273,219, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,193,307,193, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,222,307,222, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,250,307,250, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,384,247,376,247, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,206,307,206, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,187,340,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,210,340,201, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,247,340,224, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,241,307,241, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,376,247,376,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,307,250,307,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,376,170,307,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,315,129,315,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,376,283,366,283, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,376,283,376,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,399,275,376,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,341,275,320,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,341,283,350,283, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,298,275,298,329, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,308,275,298,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,243,322,243,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,243,275,284,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,258,322,226,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,212,370,212,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,214,322,177,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,163,370,163,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,165,322,129,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,84,322,117,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,71,322,64,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,115,322,115,370, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,66,322,66,370, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,52,322,21,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,331,0,331, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,331,21,133, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,96,133,21,133, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,176,129,96,129, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,315,133,176,133, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,315,129,399,129, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,399,311,350,311, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,350,329,258,329, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,258,322,258,370, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,60,370,258,370, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,60,370,60,391, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,0,391,0,331, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,307,250,307,242, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,250,307,250, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,258,250,243,250, 'fill'=>color, 'tags'=>['floor3','wall'])
+end
+
+# Below is the "main program" that creates the floorplan demonstration.
+
+# toplevel widget
+if defined?($floor2_demo) && $floor2_demo
+ $floor2_demo.destroy
+ $floor2_demo = nil
+end
+
+# demo toplevel widget
+$floor2_demo = TkToplevel.new {|w|
+ title("Floorplan Canvas Demonstration 2")
+ iconname("Floorplan2")
+ positionWindow(w)
+ geometry('+20+20')
+ minsize(100,100)
+}
+
+base_frame = TkFrame.new($floor2_demo).pack(:fill=>:both, :expand=>true)
+
+# label
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'8i', 'justify'=>'left',
+ 'text'=>"This window contains a canvas widget showing the floorplan of Digital Equipment Corporation's Western Research Laboratory. It has three levels. At any given time one of the levels is active, meaning that you can see its room structure. To activate a level, click the left mouse button anywhere on it. As the mouse moves over the active level, the room under the mouse lights up and its room number appears in the \"Room:\" entry. You can also type a room number in the entry and the room will light up."){
+ pack('side'=>'top')
+}
+
+# frame
+$floor2_buttons = TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ text 'Dismiss'
+ command proc{
+ tmppath = $floor2_demo
+ $floor2_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text 'Show Code'
+ command proc{showCode 'floor2'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+}
+$floor2_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+#
+$floorLabels2 = {}
+$floorItems2 = {}
+
+# canvas
+if $tk_version =~ /^4\.[01]/
+ $floor2_canvas_frame = TkFrame.new(base_frame,'bd'=>2,'relief'=>'sunken',
+ 'highlightthickness'=>2)
+ $floor2_canvas = TkCanvas.new($floor2_canvas_frame,
+ 'width'=>900, 'height'=>500, 'borderwidth'=>0,
+ 'highlightthickness'=>0) {|c|
+ TkScrollbar.new(base_frame, 'orient'=>'horiz',
+ 'command'=>proc{|*args| c.xview(*args)}){|hs|
+ c.xscrollcommand(proc{|first,last| hs.set first,last})
+ pack('side'=>'bottom', 'fill'=>'x')
+ }
+ TkScrollbar.new(base_frame, 'command'=>proc{|*args| c.yview(*args)}){|vs|
+ c.yscrollcommand(proc{|first,last| vs.set first,last})
+ pack('side'=>'right', 'fill'=>'y')
+ }
+ }
+ $floor2_canvas_frame.pack('side'=>'top','fill'=>'both', 'expand'=>'yes')
+ $floor2_canvas.pack('expand'=>'yes', 'fill'=>'both')
+
+else
+ TkFrame.new(base_frame) {|f|
+ pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes')
+
+ h = TkScrollbar.new(f, 'highlightthickness'=>0, 'orient'=>'horizontal')
+ v = TkScrollbar.new(f, 'highlightthickness'=>0, 'orient'=>'vertical')
+
+ TkFrame.new(f, 'bd'=>2, 'relief'=>'sunken') {|f1|
+ $floor2_canvas = TkCanvas.new(f1, 'width'=>900, 'height'=>500,
+ 'borderwidth'=>0,
+ 'highlightthickness'=>0) {
+ xscrollcommand(proc{|first,last| h.set first,last})
+ yscrollcommand(proc{|first,last| v.set first,last})
+ pack('expand'=>'yes', 'fill'=>'both')
+ }
+ grid('padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ }
+
+ v.grid('padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ h.grid('padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+
+ TkGrid.rowconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
+ TkGrid.columnconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
+
+ pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
+
+ v.command(proc{|*args| $floor2_canvas.yview(*args)})
+ h.command(proc{|*args| $floor2_canvas.xview(*args)})
+ }
+end
+
+
+# Create an entry for displaying and typing in current room.
+
+$currentRoom2 = TkVariable.new
+$floor2_entry = TkEntry.new($floor2_canvas, 'width'=>10, 'relief'=>'sunken',
+ 'bd'=>2, 'textvariable'=>$currentRoom2)
+
+# Choose colors, then fill in the floorplan.
+
+$floor2_colors = {}
+if TkWinfo.depth($floor2_canvas) > 1
+ $floor2_colors['bg1'] = '#a9c1da'
+ $floor2_colors['outline1'] = '#77889a'
+ $floor2_colors['bg2'] = '#9ab0c6'
+ $floor2_colors['outline2'] = '#687786'
+ $floor2_colors['bg3'] = '#8ba0b3'
+ $floor2_colors['outline3'] = '#596673'
+ $floor2_colors['offices'] = 'Black'
+ $floor2_colors['active'] = '#c4d1df'
+else
+ $floor2_colors['bg1'] = 'white'
+ $floor2_colors['outline1'] = 'black'
+ $floor2_colors['bg2'] = 'white'
+ $floor2_colors['outline2'] = 'black'
+ $floor2_colors['bg3'] = 'white'
+ $floor2_colors['outline3'] = 'black'
+ $floor2_colors['offices'] = 'Black'
+ $floor2_colors['active'] = 'black'
+end
+
+$activeFloor2 = ''
+floorDisplay2 $floor2_canvas,3
+
+# Set up event bindings for canvas:
+
+$floor2_canvas.itembind('floor1', '1', proc{floorDisplay2 $floor2_canvas,1})
+$floor2_canvas.itembind('floor2', '1', proc{floorDisplay2 $floor2_canvas,2})
+$floor2_canvas.itembind('floor3', '1', proc{floorDisplay2 $floor2_canvas,3})
+$floor2_canvas.itembind('room', 'Enter', proc{newRoom2 $floor2_canvas})
+$floor2_canvas.itembind('room', 'Leave', proc{$currentRoom2.value = ''})
+$floor2_canvas.bind('2', proc{|x,y| $floor2_canvas.scan_mark x,y}, '%x %y')
+$floor2_canvas.bind('B2-Motion',
+ proc{|x,y| $floor2_canvas.scan_dragto x,y}, '%x %y')
+$floor2_canvas.bind('Destroy', proc{$currentRoom2.unset})
+$currentRoom2.value = ''
+$currentRoom2.trace('w',proc{roomChanged2 $floor2_canvas})
diff --git a/ext/tk/sample/demos-en/form.rb b/ext/tk/sample/demos-en/form.rb
index dbb14302dc..3119752b1c 100644
--- a/ext/tk/sample/demos-en/form.rb
+++ b/ext/tk/sample/demos-en/form.rb
@@ -15,8 +15,10 @@ $form_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($form_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($form_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,7 +27,7 @@ msg = TkLabel.new($form_demo) {
msg.pack('side'=>'top', 'fill'=>'x')
# frame
-TkFrame.new($form_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -44,7 +46,7 @@ TkFrame.new($form_demo) {|frame|
# entry
form_data = []
(1..5).each{|i|
- f = TkFrame.new($form_demo, 'bd'=>2)
+ f = TkFrame.new(base_frame, 'bd'=>2)
e = TkEntry.new(f, 'relief'=>'sunken', 'width'=>40)
l = TkLabel.new(f)
e.pack('side'=>'right')
diff --git a/ext/tk/sample/demos-en/goldberg.rb b/ext/tk/sample/demos-en/goldberg.rb
new file mode 100644
index 0000000000..c6fa37c09c
--- /dev/null
+++ b/ext/tk/sample/demos-en/goldberg.rb
@@ -0,0 +1,2006 @@
+#
+# Ruby/Tk Goldverg demo (called by 'widget')
+#
+# Based on Tcl/Tk8.5a2 widget demos.
+# The following is the original comment of TkGoldberg.tcl.
+#
+#>>##+#################################################################
+#>>#
+#>># TkGoldberg.tcl
+#>># by Keith Vetter, March 13, 2003
+#>>#
+#>># "Man will always find a difficult means to perform a simple task"
+#>># Rube Goldberg
+#>>#
+#>># Reproduced here with permission.
+#>>#
+#>>##+#################################################################
+#>>#
+#>># Keith Vetter 2003-03-21: this started out as a simple little program
+#>># but was so much fun that it grew and grew. So I apologize about the
+#>># size but I just couldn't resist sharing it.
+#>>#
+#>># This is a whizzlet that does a Rube Goldberg type animation, the
+#>># design of which comes from an New Years e-card from IncrediMail.
+#>># That version had nice sound effects which I eschewed. On the other
+#>># hand, that version was in black and white (actually dark blue and
+#>># light blue) and this one is fully colorized.
+#>>#
+#>># One thing I learned from this project is that drawing filled complex
+#>># objects on a canvas is really hard. More often than not I had to
+#>># draw each item twice--once with the desired fill color but no
+#>># outline, and once with no fill but with the outline. Another trick
+#>># is erasing by drawing with the background color. Having a flood fill
+#>># command would have been extremely helpful.
+#>>#
+#>># Two wiki pages were extremely helpful: Drawing rounded rectangles
+#>># which I generalized into Drawing rounded polygons, and regular
+#>># polygons which allowed me to convert ovals and arcs into polygons
+#>># which could then be rotated (see Canvas Rotation). I also wrote
+#>># Named Colors to aid in the color selection.
+#>>#
+#>># I could comment on the code, but it's just 26 state machines with
+#>># lots of canvas create and move calls.
+
+if defined?($goldberg_demo) && $goldberg_demo
+ $goldberg_demo.destroy
+ $goldberg_demo = nil
+end
+
+# demo toplevel widget
+$goldberg_demo = TkToplevel.new {|w|
+ title("Tk Goldberg (demonstration)")
+ iconname("goldberg")
+# positionWindow(w)
+}
+
+base_frame = TkFrame.new($goldberg_demo).pack(:fill=>:both, :expand=>true)
+
+=begin
+# label
+msg = TkLabel.new($goldberg_demo) {
+ font 'Arial 10'
+ wraplength '4i'
+ justify 'left'
+ text "This is a demonstration of just how complex you can make your animations become. Click the ball to start things moving!\n\n\"Man will always find a difficult means to perform a simple task\"\n - Rube Goldberg"
+}
+msg.pack('side'=>'top')
+=end
+
+=begin
+# frame
+TkFrame.new($goldberg_demo) {|frame|
+ TkButton.new(frame) {
+ text 'Dismiss'
+ command proc{
+ tmppath = $goldberg_demo
+ $goldberg_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text 'See Code'
+ command proc{showCode 'goldberg'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+=end
+
+#########################################
+
+class TkGoldberg_Demo
+ def initialize(parent)
+ @parent = parent
+
+ @S = {}
+ @S['title'] = 'Tk Goldberg'
+ @S['speed'] = TkVariable.new(5)
+ @S['cnt'] = TkVariable.new(0)
+ @S['message'] = TkVariable.new("\\nWelcome\\nto\\nRuby/Tk")
+ @S['pause'] = TkVariable.new
+ @S['details'] = TkVariable.new(true)
+
+ @S['mode'] = TkVariable.new(:MSTART, :symbol)
+ # :MSTART, :MGO, :MPAUSE, :MSSTEP, :MBSTEP, :MDONE, :MDEBUG
+
+ # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+ @speed = [1, 10, 20, 50, 80, 100, 150, 200, 300, 400, 500]
+
+ # colors
+ @C = {}
+ @C['fg'] = 'black'
+ # @C['bg'] = 'gray75'
+ @C['bg'] = 'cornflowerblue'
+
+ @C['0'] = 'white'; @C['1a'] = 'darkgreen'; @C['1b'] = 'yellow'
+ @C['2'] = 'red'; @C['3a'] = 'green'; @C['3b'] = 'darkblue'
+ @C['4'] = @C['fg']; @C['5a'] = 'brown'; @C['5b'] = 'white'
+ @C['6'] = 'magenta'; @C['7'] = 'green'; @C['8'] = @C['fg']
+ @C['9'] = 'blue4'; @C['10a'] = 'white'; @C['10b'] = 'cyan'
+ @C['11a'] = 'yellow'; @C['11b'] = 'mediumblue'; @C['12'] = 'tan2'
+ @C['13a'] = 'yellow'; @C['13b'] = 'red'; @C['14'] = 'white'
+ @C['15a'] = 'green'; @C['15b'] = 'yellow'; @C['16'] = 'gray65'
+ @C['17'] = '#A65353'; @C['18'] = @C['fg']; @C['19'] = 'gray50'
+ @C['20'] = 'cyan'; @C['21'] = 'gray65'; @C['22'] = @C['20']
+ @C['23a'] = 'blue'; @C['23b'] = 'red'; @C['23c'] = 'yellow'
+ @C['24a'] = 'red'; @C['24b'] = 'white';
+
+ @STEP = TkVariable.new_hash
+ @STEP.default_value_type = :numeric
+
+ @XY = {}
+
+ @XY6 = {
+ '-1'=>[366, 207], '-2'=>[349, 204], '-3'=>[359, 193], '-4'=>[375, 192],
+ '-5'=>[340, 190], '-6'=>[349, 177], '-7'=>[366, 177], '-8'=>[380, 176],
+ '-9'=>[332, 172], '-10'=>[342, 161], '-11'=>[357, 164],
+ '-12'=>[372, 163], '-13'=>[381, 149], '-14'=>[364, 151],
+ '-15'=>[349, 146], '-16'=>[333, 148], '0'=>[357, 219],
+ '1'=>[359, 261], '2'=>[359, 291], '3'=>[359, 318], '4'=>[361, 324],
+ '5'=>[365, 329], '6'=>[367, 334], '7'=>[367, 340], '8'=>[366, 346],
+ '9'=>[364, 350], '10'=>[361, 355], '11'=>[359, 370], '12'=>[359, 391],
+ '13,0'=>[360, 456], '13,1'=>[376, 456], '13,2'=>[346, 456],
+ '13,3'=>[330, 456], '13,4'=>[353, 444], '13,5'=>[368, 443],
+ '13,6'=>[339, 442], '13,7'=>[359, 431], '13,8'=>[380, 437],
+ '13,9'=>[345, 428], '13,10'=>[328, 434], '13,11'=>[373, 424],
+ '13,12'=>[331, 420], '13,13'=>[360, 417], '13,14'=>[345, 412],
+ '13,15'=>[376, 410], '13,16'=>[360, 403]
+ }
+
+ @timer = TkTimer.new(@speed[@S['speed'].numeric]){|timer|
+ timer.set_interval(go)
+ }
+
+ do_display
+ reset
+
+ # Start everything going
+ @timer.start
+ end
+
+ def do_display()
+ @ctrl = TkFrame.new(@parent, :relief=>:ridge, :bd=>2, :padx=>5, :pady=>5)
+ @screen = TkFrame.new(@parent, :bd=>2,
+ :relief=>:raised).pack(:side=>:left, :fill=>:both,
+ :expand=>true)
+
+ @canvas = TkCanvas.new(@parent, :width=>850, :height=>700,
+ :bg=>@C['bg'], :highlightthickness=>0){
+ scrollregion([0, 0, 1000, 1000]) # Kludge to move everything up
+ yview_moveto(0.05)
+ }.pack(:in=>@screen, :side=>:top, :fill=>:both, :expand=>true)
+
+ @canvas.bind('3'){ @pause.invoke }
+ @canvas.bind('Destroy'){ @timer.stop }
+
+ do_ctrl_frame
+ do_detail_frame
+
+ # msg = TkLabel.new(@parent, :bg=>@C['bg'], :fg=>'white') {
+ msg = Tk::Label.new(@parent, :bg=>@C['bg'], :fg=>'white') {
+ font 'Arial 10'
+ wraplength 600
+ justify 'left'
+ text "This is a demonstration of just how complex you can make your animations become. Click the ball to start things moving!\n\"Man will always find a difficult means to perform a simple task\" - Rube Goldberg"
+ }
+ msg.place(:in=>@canvas, :relx=>0, :rely=>0, :anchor=>:nw)
+
+ frame = TkFrame.new(@parent, :bg=>@C['bg'])
+
+ # TkButton.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ Tk::Button.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ text 'Dismiss'
+ command proc{
+ tmppath = $goldberg_demo
+ $goldberg_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left')
+
+ # TkButton.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ Tk::Button.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ text 'See Code'
+ command proc{showCode 'goldberg'}
+ }.pack('side'=>'left', 'padx'=>5)
+
+ # @show = TkButton.new(frame, :text=>'>>', :command=>proc{show_ctrl},
+ @show = Tk::Button.new(frame, :text=>'>>', :command=>proc{show_ctrl},
+ :bg=>@C['bg'], :activebackground=>@C['bg'])
+ @show.pack('side'=>'left')
+ frame.place(:in=>@canvas, :relx=>1, :rely=>0, :anchor=>:ne)
+
+ Tk.update
+ end
+
+ def do_ctrl_frame
+ @start = Tk::Button.new(@parent, :text=>'Start', :bd=>6,
+ :command=>proc{do_button(0)})
+ if font = @start['font']
+ @start.font(font.weight('bold'))
+ end
+
+ @pause = TkCheckbutton.new(@parent, :text=>'Pause', :font=>font,
+ :command=>proc{do_button(1)}, :relief=>:raised,
+ :variable=>@S['pause'])
+
+ @step = TkButton.new(@parent, :text=>'Single Step', :font=>font,
+ :command=>proc{do_button(2)})
+ @bstep = TkButton.new(@parent, :text=>'Big Step', :font=>font,
+ :command=>proc{do_button(4)})
+ @reset = TkButton.new(@parent, :text=>'Reset', :font=>font,
+ :command=>proc{do_button(3)})
+
+ @details = TkFrame.new(@parent, :bd=>2, :relief=>:ridge)
+ @detail = TkCheckbutton.new(@parent, :text=>'Details', :font=>font,
+ :relief=>:raised, :variable=>@S['details'])
+
+ @msg_entry = TkEntry.new(@parent, :textvariable=>@S['message'],
+ :justify=>:center)
+ @speed_scale = TkScale.new(@parent, :orient=>:horizontal,
+ :from=>1, :to=>10, :font=>font,
+ :variable=>@S['speed'], :bd=>2,
+ :relief=>:ridge, :showvalue=>false)
+ @about = TkButton.new(@parent, :text=>'About',
+ :command=>proc{about}, :font=>font)
+
+ Tk.grid(@start, :in=>@ctrl, :row=>0, :sticky=>:ew)
+ @ctrl.grid_rowconfigure(1, :minsize=>10)
+ Tk.grid(@pause, :in=>@ctrl, :row=>2, :sticky=>:ew)
+ Tk.grid(@step, :in=>@ctrl, :sticky=>:ew)
+ Tk.grid(@bstep, :in=>@ctrl, :sticky=>:ew)
+ Tk.grid(@reset, :in=>@ctrl, :sticky=>:ew)
+ @ctrl.grid_rowconfigure(10, :minsize=>20)
+ Tk.grid(@details, :in=>@ctrl, :row=>11, :sticky=>:ew)
+ Tk.grid(@detail, :in=>@details, :row=>0, :sticky=>:ew)
+ @ctrl.grid_rowconfigure(50, :weight=>1)
+
+ @S['mode'].trace('w', proc{|*args| active_GUI(*args)})
+ @S['details'].trace('w', proc{|*args| active_GUI(*args)})
+ @S['speed'].trace('w', proc{|*args| active_GUI(*args)})
+
+ Tk.grid(@msg_entry, :in=>@ctrl, :row=>98, :sticky=>:ew, :pady=>5)
+ Tk.grid(@speed_scale, :in=>@ctrl, :row=>99, :sticky=>:ew)
+ Tk.grid(@about, :in=>@ctrl, :row=>100, :sticky=>:ew)
+
+ @reset.bind('3'){@S['mode'].value = -1} # Debugging
+ end
+
+ def do_detail_frame
+ @f_details = TkFrame.new(@details)
+
+ @label = TkLabel.new(@f_details, :textvariable=>@S['cnt'],
+ :bd=>1, :relief=>:solid, :bg=>'white')
+ Tk.grid(@label, '-', '-', '-', :sticky=>:ew, :row=>0)
+
+ idx = 1
+ loop {
+ break unless respond_to?("move#{idx}")
+ l = TkLabel.new(@f_details, :text=>idx, :anchor=>:e,
+ :width=>2, :bd=>1, :relief=>:solid, :bg=>'white')
+ @STEP[idx] = 0
+ ll = TkLabel.new(@f_details, :textvariable=>@STEP.ref(idx),
+ :width=>5, :bd=>1, :relief=>:solid, :bg=>'white')
+ row = (idx + 1)/2
+ col = ((idx + 1) & 1) * 2
+ Tk.grid(l, :sticky=>:ew, :row=>row, :column=>col)
+ Tk.grid(ll, :sticky=>:ew, :row=>row, :column=>(col + 1))
+ idx += 1
+ }
+ @f_details.grid_columnconfigure(1, :weight=>1)
+ end
+
+ def show_ctrl
+ if @ctrl.winfo_mapped?
+ @ctrl.pack_forget
+ @show.text('>>')
+ else
+ @ctrl.pack(:side=>:right, :fill=>:both, :ipady=>5)
+ @show.text('<<')
+ end
+ end
+
+ def draw_all
+ reset_step
+ @canvas.delete(:all)
+ idx = 0
+ loop{
+ m = "draw#{idx}"
+ break unless respond_to?(m)
+ send(m)
+ idx += 1
+ }
+ end
+
+ def active_GUI(var1, var2, op)
+ st = {false=>:disabled, true=>:normal}
+
+ m = @S['mode'].to_sym
+ @S['pause'].value = (m == :MPAUSE)
+ @start.state(st[m != :MGO])
+ @pause.state(st[m != :MSTART && m != :MDONE])
+ @step.state(st[m != :MGO && m != :MDONE])
+ @bstep.state(st[m != :MGO && m != :MDONE])
+ @reset.state(st[m != :MSTART])
+
+ if @S['details'].bool
+ Tk.grid(@f_details, :in=>@details, :row=>2, :sticky=>:ew)
+ else
+ Tk.grid_forget(@f_details)
+ end
+ @speed_scale.label("Speed: #{@S['speed'].value}")
+ end
+
+ def start
+ @S['mode'].value = :MGO
+ end
+
+ def do_button(what)
+ case what
+ when 0 # Start
+ reset if @S['mode'].to_sym == :MDONE
+ @S['mode'].value = :MGO
+
+ when 1 # Pause
+ @S['mode'].value = ((@S['pause'].bool)? :MPAUSE: :MGO)
+
+ when 2 # Step
+ @S['mode'].value = :MSSTEP
+
+ when 3 # Reset
+ reset
+
+ when 4 # Big step
+ @S['mode'].value = :MBSTEP
+ end
+ end
+
+ def go(who = nil)
+ now = Tk::Clock.clicks(:miliseconds)
+ if who # Start here for debugging
+ @S['active'] = [who]
+ @S['mode'].value = :MGO
+ end
+ return if @S['mode'].to_sym == :MDEBUG # Debugging
+ # If not paused, do the next move
+ n = next_step if @S['mode'].to_sym != :MPAUSE
+ @S['mode'].value = :MPAUSE if @S['mode'].to_sym == :MSSTEP # Single step
+ @S['mode'].value = :MSSTEP if @S['mode'].to_sym == :MBSTEP && n # big step
+ elapsed = Tk::Clock.clicks(:miliseconds) - now
+ delay = @speed[@S['speed'].to_i] - elapsed
+ delay = 1 if delay <= 0
+ return delay
+ end
+
+ def next_step
+ retval = false # Return value
+
+ if @S['mode'].to_sym != :MSTART && @S['mode'].to_sym != :MDONE
+ @S['cnt'].numeric += 1
+ end
+ alive = []
+ @S['active'].each{|who|
+ who = who.to_i
+ n = send("move#{who}")
+ if (n & 1).nonzero? # This guy still alive
+ alive << who
+ end
+ if (n & 2).nonzero? # Next guy is active
+ alive << (who + 1)
+ retval = true
+ end
+ if (n & 4).nonzero? # End of puzzle flag
+ @S['mode'].value = :MDONE # Done mode
+ @S['active'] = [] # No more animation
+ return true
+ end
+ }
+ @S['active'] = alive
+ return retval
+ end
+
+ def about
+ msg = "Ruby/Tk Version ::\nby Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)\n\n"
+ msg += "Original Version ::\n"
+ msg += "#{@S['title']}\nby Keith Vetter, March 2003\n(Reproduced by kind permission of the author)\n\n"
+ msg += "Man will always find a difficult means to perform a simple task"
+ msg += "\nRube Goldberg"
+ Tk.messageBox(:message=>msg, :title=>'About')
+ end
+
+ ################################################################
+ #
+ # All the drawing and moving routines
+ #
+
+ # START HERE! banner
+ def draw0
+ color = @C['0']
+ TkcText.new(@canvas, [579, 119], :text=>'START HERE!',
+ :fill=>color, :anchor=>:w,
+ :tag=>'I0', :font=>['Times Roman', 12, :italic, :bold])
+ TkcLine.new(@canvas, [719, 119, 763, 119], :tag=>'I0', :fill=>color,
+ :width=>5, :arrow=>:last, :arrowshape=>[18, 18, 5])
+ @canvas.itembind('I0', '1'){ start }
+ end
+
+ def move0(step = nil)
+ step = get_step(0, step)
+
+ if @S['mode'].to_sym != :MSTART # Start the ball rolling
+ move_abs('I0', [-100, -100]) # Hide the banner
+ return 2
+ end
+
+ pos = [
+ [673, 119], [678, 119], [683, 119], [688, 119],
+ [693, 119], [688, 119], [683, 119], [678, 119]
+ ]
+ step = step % pos.length
+ move_abs('I0', pos[step])
+ return 1
+ end
+
+ # Dropping ball
+ def draw1
+ color = @C['1a']
+ color2 = @C['1b']
+ TkcPolygon.new(@canvas,
+ [ 844, 133, 800, 133, 800, 346, 820, 346,
+ 820, 168, 844, 168, 844, 133 ],
+ :width=>3, :fill=>color, :outline=>'')
+ TkcPolygon.new(@canvas,
+ [ 771, 133, 685, 133, 685, 168, 751, 168,
+ 751, 346, 771, 346, 771, 133 ],
+ :width=>3, :fill=>color, :outline=>'')
+ TkcOval.new(@canvas, box(812, 122, 9),
+ :tag=>'I1', :fill=>color2, :outline=>'')
+
+ @canvas.itembind('I1', '1'){ start }
+ end
+
+ def move1(step = nil)
+ step = get_step(1, step)
+ pos = [
+ [807, 122], [802, 122], [797, 123], [793, 124], [789, 129], [785, 153],
+ [785, 203], [785, 278, :x], [785, 367], [810, 392], [816, 438],
+ [821, 503], [824, 585, :y], [838, 587], [848, 593], [857, 601],
+ [-100, -100]
+ ]
+ return 0 if step >= pos.length
+ where = pos[step]
+ move_abs('I1', where)
+ move15a if where[2] == :y
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Lighting the match
+ def draw2
+ color = @C['2']
+
+ # Fulcrum
+ TkcPolygon.new(@canvas, [750, 369, 740, 392, 760, 392],
+ :fill=>@C['fg'], :outline=>@C['fg'])
+
+ # Strike box
+ TkcRectangle.new(@canvas, [628, 335, 660, 383],
+ :fill=>'', :outline=>@C['fg'])
+ (0..2).each{|y|
+ yy = 335 + y*16
+ TkcBitmap.new(@canvas, [628, yy], :bitmap=>'gray25',
+ :anchor=>:nw, :foreground=>@C['fg'])
+ TkcBitmap.new(@canvas, [644, yy], :bitmap=>'gray25',
+ :anchor=>:nw, :foreground=>@C['fg'])
+ }
+
+ # Lever
+ TkcLine.new(@canvas, [702, 366, 798, 366],
+ :fill=>@C['fg'], :width=>6, :tag=>'I2_0')
+
+ # R strap
+ TkcLine.new(@canvas, [712, 363, 712, 355],
+ :fill=>@C['fg'], :width=>3, :tag=>'I2_1')
+
+ # L strap
+ TkcLine.new(@canvas, [705, 363, 705, 355],
+ :fill=>@C['fg'], :width=>3, :tag=>'I2_2')
+
+ # Match stick
+ TkcLine.new(@canvas, [679, 356, 679, 360, 717, 360, 717, 356, 679, 356],
+ :fill=>@C['fg'], :width=>3, :tag=>'I2_3')
+
+ # Match head
+ TkcPolygon.new(@canvas,
+ [ 671, 352, 677.4, 353.9, 680, 358.5, 677.4, 363.1,
+ 671, 365, 664.6, 363.1, 662, 358.5, 664.6, 353.9 ],
+ :fill=>color, :outline=>color, :tag=>'I2_4')
+ end
+
+ def move2(step = nil)
+ step = get_step(2, step)
+
+ stages = [0, 0, 1, 2, 0, 2, 1, 0, 1, 2, 0, 2, 1]
+ xy = []
+ xy[0] = [
+ 686, 333, 692, 323, 682, 316, 674, 309, 671, 295, 668, 307,
+ 662, 318, 662, 328, 671, 336
+ ]
+ xy[1] = [
+ 687, 331, 698, 322, 703, 295, 680, 320, 668, 297, 663, 311,
+ 661, 327, 671, 335
+ ]
+ xy[2] = [
+ 686, 331, 704, 322, 688, 300, 678, 283, 678, 283, 674, 298,
+ 666, 309, 660, 324, 672, 336
+ ]
+
+ if step >= stages.length
+ @canvas.delete('I2')
+ return 0
+ end
+
+ if step == 0 # Rotate the match
+ beta = 20
+
+ ox, oy = anchor('I2_0', :s) # Where to pivot
+
+ i = 0
+ until @canvas.find_withtag("I2_#{i}").empty?
+ rotate_item("I2_#{i}", ox, oy, beta)
+ i += 1
+ end
+
+ # For the flame
+ TkcPolygon.new(@canvas, [], :tag=>'I2', :smooth=>true, :fill=>@C['2'])
+
+ return 1
+ end
+ @canvas.coords('I2', xy[stages[step]])
+ return ((step == 7)? 3: 1)
+ end
+
+ # Weight and pulleys
+ def draw3
+ color = @C['3a']
+ color2 = @C['3b']
+
+ xy = [ [602, 296], [577, 174], [518, 174] ]
+ xy.each{|x, y| # 3 Pulleys
+ TkcOval.new(@canvas, box(x, y, 13),
+ :fill=>color, :outline=>@C['fg'], :width=>3)
+ TkcOval.new(@canvas, box(x, y, 2), :fill=>@C['fg'], :outline=>@C['fg'])
+ }
+
+ # Wall to flame
+ TkcLine.new(@canvas, [750, 309, 670, 309], :tag=>'I3_s',
+ :width=>3, :fill=>@C['fg'], :smooth=>true)
+
+ # Flame to pulley 1
+ TkcLine.new(@canvas, [670, 309, 650, 309], :tag=>'I3_0',
+ :width=>3, :fill=>@C['fg'], :smooth=>true)
+ TkcLine.new(@canvas, [650, 309, 600, 309], :tag=>'I3_1',
+ :width=>3, :fill=>@C['fg'], :smooth=>true)
+
+ # Pulley 1 half way to 2
+ TkcLine.new(@canvas, [589, 296, 589, 235], :tag=>'I3_2',
+ :width=>3, :fill=>@C['fg'])
+
+ # Pulley 1 other half to 2
+ TkcLine.new(@canvas, [589, 235, 589, 174], :width=>3, :fill=>@C['fg'])
+
+ # Across the top
+ TkcLine.new(@canvas, [577, 161, 518, 161], :width=>3, :fill=>@C['fg'])
+
+ # Down to weight
+ TkcLine.new(@canvas, [505, 174, 505, 205], :tag=>'I3_w',
+ :width=>3, :fill=>@C['fg'])
+
+ # Draw the weight as 2 circles, two rectangles and 1 rounded rectangle
+ x1, y1, x2, y2 = [515, 207, 495, 207]
+ TkcOval.new(@canvas, box(x1, y1, 6),
+ :tag=>'I3_', :fill=>color2, :outline=>color2)
+ TkcOval.new(@canvas, box(x2, y2, 6),
+ :tag=>'I3_', :fill=>color2, :outline=>color2)
+ TkcRectangle.new(@canvas, x1, y1 - 6, x2, y2 + 6,
+ :tag=>'I3_', :fill=>color2, :outline=>color2)
+
+ TkcPolygon.new(@canvas, round_rect([492, 220, 518, 263], 15),
+ :smooth=>true, :tag=>'I3_', :fill=>color2, :outline=>color2)
+
+ TkcLine.new(@canvas, [500, 217, 511, 217],
+ :tag=>'I3_', :fill=>color2, :width=>10)
+
+ # Bottom weight target
+ TkcLine.new(@canvas, [502, 393, 522, 393, 522, 465],
+ :tag=>'I3__', :fill=>@C['fg'], :joinstyle=>:miter, :width=>10)
+ end
+
+ def move3(step = nil)
+ step = get_step(3, step)
+
+ pos = [ [505, 247], [505, 297], [505, 386.5], [505, 386.5] ]
+ rope = []
+ rope[0] = [750, 309, 729, 301, 711, 324, 690, 300]
+ rope[1] = [750, 309, 737, 292, 736, 335, 717, 315, 712, 320]
+ rope[2] = [750, 309, 737, 309, 740, 343, 736, 351, 725, 340]
+ rope[3] = [750, 309, 738, 321, 746, 345, 742, 356]
+
+ return 0 if step >= pos.length
+
+ @canvas.delete("I3_#{step}") # Delete part of the rope
+ move_abs('I3_', pos[step]) # Move weight down
+ @canvas.coords('I3_s', rope[step]) # Flapping rope end
+ @canvas.coords('I3_w', [505, 174].concat(pos[step]))
+ if step == 2
+ @canvas.move('I3__', 0, 30)
+ return 2
+ end
+ return 1
+ end
+
+ # Cage and door
+ def draw4
+ color = @C['4']
+ x0, y0, x1, y1 = [527, 356, 611, 464]
+
+ # Horizontal bars
+ y0.step(y1, 12){|y|
+ TkcLine.new(@canvas, [x0, y, x1, y], :fill=>color, :width=>1)
+ }
+
+ # Vertical bars
+ x0.step(x1, 12){|x|
+ TkcLine.new(@canvas, [x, y0, x, y1], :fill=>color, :width=>1)
+ }
+
+ # Swing gate
+ TkcLine.new(@canvas, [518, 464, 518, 428],
+ :tag=>'I4', :fill=>color, :width=>1)
+ end
+
+ def move4(step = nil)
+ step = get_step(4, step)
+
+ angles = [-10, -20, -30, -30]
+ return 0 if step >= angles.length
+
+ rotate_item('I4', 518, 464, angles[step])
+ @canvas.raise('I4')
+
+ return((step == 3)? 3: 1)
+ end
+
+ # Mouse
+ def draw5
+ color = @C['5a']
+ color2 = @C['5b']
+
+ xy = [377, 248, 410, 248, 410, 465, 518, 465] # Mouse course
+ xy.concat [518, 428, 451, 428, 451, 212, 377, 212]
+
+ TkcPolygon.new(@canvas, xy, :fill=>color2, :outline=>@C['fg'], :width=>3)
+
+ xy = [
+ 534.5, 445.5, 541, 440, 552, 436, 560, 436, 569, 440, 574, 446,
+ 575, 452, 574, 454, 566, 456, 554, 456, 545, 456, 537, 454, 530, 452
+ ]
+ TkcPolygon.new(@canvas, xy, :tag=>['I5', 'I5_0'], :fill=>color)
+
+ TkcLine.new(@canvas, [573, 452, 592, 458, 601, 460, 613, 456], # Tail
+ :tag=>['I5', 'I5_1'], :fill=>color, :smooth=>true, :width=>3)
+
+ xy = box(540, 446, 2) # Eye
+ xy = [540, 444, 541, 445, 541, 447, 540, 448, 538, 447, 538, 445]
+ TkcPolygon.new(@canvas, xy, :tag=>['I5', 'I5_2'], :fill=>@C['bg'],
+ :outline=>'', :smooth=>true)
+
+ xy = [538, 454, 535, 461] # Front leg
+ TkcLine.new(@canvas, xy, :tag=>['I5', 'I5_3'], :fill=>color, :width=>2)
+
+ xy = [566, 455, 569, 462] # Back leg
+ TkcLine.new(@canvas, xy, :tag=>['I5', 'I5_4'], :fill=>color, :width=>2)
+
+ xy = [544, 455, 545, 460] # 2nd front leg
+ TkcLine.new(@canvas, xy, :tag=>['I5', 'I5_5'], :fill=>color, :width=>2)
+
+ xy = [560, 455, 558, 460] # 2nd back leg
+ TkcLine.new(@canvas, xy, :tag=>['I5', 'I5_6'], :fill=>color, :width=>2)
+ end
+
+ def move5(step = nil)
+ step = get_step(5, step)
+
+ pos = [
+ [553, 452], [533, 452], [513, 452], [493, 452], [473, 452],
+ [463, 442, 30], [445.5, 441.5, 30], [425.5, 434.5, 30], [422, 414],
+ [422, 394], [422, 374], [422, 354], [422, 334], [422, 314], [422, 294],
+ [422, 274, -30], [422, 260.5, -30, :x], [422.5, 248.5, -28], [425, 237]
+ ]
+
+ return 0 if step >= pos.length
+
+ x, y, beta, nxt = pos[step]
+ move_abs('I5', [x, y])
+ if beta
+ ox, oy = centroid('I5_0')
+ (0..6).each{|id| rotate_item("I5_#{id}", ox, oy, beta) }
+ end
+ return 3 if nxt == :x
+ return 1
+ end
+
+ # Dropping gumballs
+ def draw6
+ color = @C['6']
+ xy = [324, 130, 391, 204] # Ball holder
+ xy = round_rect(xy, 10)
+ TkcPolygon.new(@canvas, xy, :smooth=>true,
+ :outline=>@C['fg'], :width=>3, :fill=>color)
+ xy = [339, 204, 376, 253] # Below the ball holder
+ TkcRectangle.new(@canvas, xy, :outline=>@C['fg'], :width=>3,
+ :fill=>color, :tag=>'I6c')
+ xy = box(346, 339, 28)
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'') # Roter
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>2, :style=>:arc,
+ :start=>80, :extent=>205)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>2, :style=>:arc,
+ :start=>-41, :extent=>85)
+
+ xy = box(346, 339, 15) # Center of rotor
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>@C['fg'], :tag=>'I6m')
+ xy = [352, 312, 352, 254, 368, 254, 368, 322] # Top drop to rotor
+ TkcPolygon.new(@canvas, xy, :fill=>color, :outline=>'')
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2)
+
+ xy = [353, 240, 367, 300] # Poke bottom hole
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>'')
+ xy = [341, 190, 375, 210] # Poke another hole
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>'')
+
+ xy = [
+ 368, 356, 368, 403, 389, 403, 389, 464, 320, 464, 320, 403,
+ 352, 403, 352, 366
+ ]
+ TkcPolygon.new(@canvas, xy, :fill=>color, :outline=>'',
+ :width=>2) # Below rotor
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2)
+ xy = box(275, 342, 7) # On/off rotor
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>@C['fg'])
+ xy = [276, 334, 342, 325] # Fan belt top
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = [276, 349, 342, 353] # Fan belt bottom
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+
+ xy = [337, 212, 337, 247] # What the mouse pushes
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I6_')
+ xy = [392, 212, 392, 247]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I6_')
+ xy = [337, 230, 392, 230]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>7, :tag=>'I6_')
+
+ who = -1 # All the balls
+ colors = %w(red cyan orange green blue darkblue)
+ colors *= 3
+
+ (0..16).each{|i|
+ loc = -i
+ color = colors[i]
+ x, y = @XY6["#{loc}"]
+ TkcOval.new(@canvas, box(x, y, 5),
+ :fill=>color, :outline=>color, :tag=>"I6_b#{i}")
+ }
+ draw6a(12) # The wheel
+ end
+
+ def draw6a(beta)
+ @canvas.delete('I6_0')
+ ox, oy = [346, 339]
+ (0..3).each{|i|
+ b = beta + i * 45
+ x, y = rotate_c(28, 0, 0, 0, b)
+ xy = [ox + x, oy + y, ox - x, oy - y]
+ TkcLine.new(@canvas, xy, :tag=>'I6_0', :fill=>@C['fg'], :width=>2)
+ }
+ end
+
+ def move6(step = nil)
+ step = get_step(6, step)
+
+ return 0 if step > 62
+
+ if step < 2 # Open gate for balls to drop
+ @canvas.move('I6_', -7, 0)
+ if step == 1 # Poke a hole
+ xy = [348, 226, 365, 240]
+ TkcRectangle.new(@canvas, xy, :fill=>@canvas.itemcget('I6c', :fill),
+ :outline=>'')
+ end
+ return 1
+ end
+
+ s = step - 1 # Do the gumball drop dance
+ (0..(((s - 1)/3).to_i)).each{|i|
+ tag = "I6_b#{i}"
+ break if @canvas.find_withtag(tag).empty?
+ loc = s - 3*i
+
+ if @XY6["#{loc},#{i}"]
+ move_abs(tag, @XY6["#{loc},#{i}"])
+ elsif @XY6["#{loc}"]
+ move_abs(tag, @XY6["#{loc}"])
+ end
+ }
+ if s % 3 == 1
+ first = (s + 2)/3
+ i = first
+ loop {
+ tag = "I6_b#{i}"
+ break if @canvas.find_withtag(tag).empty?
+ loc = first - i
+ move_abs(tag, @XY6["#{loc}"])
+ i += 1
+ }
+ end
+ if s >= 3 # Rotate the motor
+ idx = s % 3
+ draw6a(12 + s * 15)
+ end
+ return((s == 3)? 3 : 1)
+ end
+
+ # On/off switch
+ def draw7
+ color = @C['7']
+ xy = [198, 306, 277, 374] # Box
+ TkcRectangle.new(@canvas, xy, :outline=>@C['fg'], :width=>2,
+ :fill=>color, :tag=>'I7z')
+ @canvas.lower('I7z')
+ xy = [275, 343, 230, 349]
+ TkcLine.new(@canvas, xy, :tag=>'I7', :fill=>@C['fg'], :arrow=>:last,
+ :arrowshape=>[23, 23, 8], :width=>6)
+ xy = [225, 324] # On button
+ x, y = xy
+ TkcOval.new(@canvas, box(x, y, 3), :fill=>@C['fg'], :outline=>@C['fg'])
+ xy = [218, 323] # On text
+ font = ['Times Roman', 8]
+ TkcText.new(@canvas, xy, :text=>'on', :anchor=>:e,
+ :fill=>@C['fg'], :font=>font)
+ xy = [225, 350] # Off button
+ x, y = xy
+ TkcOval.new(@canvas, box(x, y, 3), :fill=>@C['fg'], :outline=>@C['fg'])
+ xy = [218, 349] # Off text
+ TkcText.new(@canvas, xy, :text=>'off', :anchor=>:e,
+ :fill=>@C['fg'], :font=>font)
+ end
+
+ def move7(step = nil)
+ step = get_step(7, step)
+
+ numsteps = 30
+ return 0 if step > numsteps
+ beta = 30.0 / numsteps
+ rotate_item('I7', 275, 343, beta)
+
+ return((step == numsteps)? 3: 1)
+ end
+
+ # Electricity to the fan
+ def draw8
+ sine([271, 248, 271, 306], 5, 8, :tag=>'I8_s', :fill=>@C['8'], :width=>3)
+ end
+
+ def move8(step = nil)
+ step = get_step(8, step)
+
+ return 0 if step > 3
+ if step == 0
+ sparkle(anchor('I8_s', :s), 'I8')
+ return 1
+ elsif step == 1
+ move_abs('I8', anchor('I8_s', :c))
+ elsif step == 2
+ move_abs('I8', anchor('I8_s', :n))
+ else
+ @canvas.delete('I8')
+ end
+ return((step == 2)? 3: 1)
+ end
+
+ # Fan
+ def draw9
+ color = @C['9']
+ xy = [266, 194, 310, 220]
+ TkcOval.new(@canvas, xy, :outline=>color, :fill=>color)
+ xy = [280, 209, 296, 248]
+ TkcOval.new(@canvas, xy, :outline=>color, :fill=>color)
+ xy = [
+ 288, 249, 252, 249, 260, 240, 280, 234,
+ 296, 234, 316, 240, 324, 249, 288, 249
+ ]
+ TkcPolygon.new(@canvas, xy, :fill=>color, :smooth=>true)
+
+ xy = [248, 205, 265, 214, 264, 205, 265, 196] # Spinner
+ TkcPolygon.new(@canvas, xy, :fill=>color)
+
+ xy = [255, 206, 265, 234] # Fan blades
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'],
+ :width=>3, :tag=>'I9_0')
+ xy = [255, 176, 265, 204]
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'],
+ :width=>3, :tag=>'I9_0')
+ xy = [255, 206, 265, 220]
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'],
+ :width=>1, :tag=>'I9_1')
+ xy = [255, 190, 265, 204]
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'],
+ :width=>1, :tag=>'I9_1')
+ end
+
+ def move9(step = nil)
+ step = get_step(9, step)
+
+ if (step & 1).nonzero?
+ @canvas.itemconfigure('I9_0', :width=>4)
+ @canvas.itemconfigure('I9_1', :width=>1)
+ @canvas.lower('I9_1', 'I9_0')
+ else
+ @canvas.itemconfigure('I9_0', :width=>1)
+ @canvas.itemconfigure('I9_1', :width=>4)
+ @canvas.lower('I9_0', 'I9_1')
+ end
+ return 3 if step == 0
+ return 1
+ end
+
+ # Boat
+ def draw10
+ color = @C['10a']
+ color2 = @C['10b']
+ xy = [191, 230, 233, 230, 233, 178, 191, 178] # Sail
+ TkcPolygon.new(@canvas, xy, :fill=>color, :width=>3, :outline=>@C['fg'],
+ :tag=>'I10')
+ xy = box(209, 204, 31) # Front
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :style=>:pie,
+ :start=>120, :extent=>120, :tag=>'I10')
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>120, :extent=>120, :tag=>'I10')
+ xy = box(249, 204, 31) # Back
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>@C['bg'], :width=>3,
+ :style=>:pie, :start=>120, :extent=>120, :tag=>'I10')
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>120, :extent=>120, :tag=>'I10')
+
+ xy = [200, 171, 200, 249] # Mast
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I10')
+ xy = [159, 234, 182, 234] # Bow sprit
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I10')
+ xy = [180, 234, 180, 251, 220, 251] # Hull
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>6, :tag=>'I10')
+
+ xy = [92, 255, 221, 255] # Waves
+ sine(xy, 2, 25, :fill=>color2, :width=>1, :tag=>'I10w')
+
+ xy = @canvas.coords('I10w')[4..-5] # Water
+ xy.concat([222, 266, 222, 277, 99, 277])
+ TkcPolygon.new(@canvas, xy, :fill=>color2, :outline=>color2)
+ xy = [222, 266, 222, 277, 97, 277, 97, 266] # Water bottom
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+
+ xy = box(239, 262, 17)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>95, :extent=>103)
+ xy = box(76, 266, 21)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :extent=>190)
+ end
+
+ def move10(step = nil)
+ step = get_step(10, step)
+
+ pos = [
+ [195, 212], [193, 212], [190, 212], [186, 212], [181, 212], [176, 212],
+ [171, 212], [166, 212], [161, 212], [156, 212], [151, 212], [147, 212],
+ [142, 212], [137, 212], [132, 212, :x], [127, 212], [121, 212],
+ [116, 212], [111, 212]
+ ]
+
+ return 0 if step >= pos.length
+
+ where = pos[step]
+ move_abs('I10', where)
+
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # 2nd ball drop
+ def draw11
+ color = @C['11a']
+ color2 = @C['11b']
+ xy = [23, 264, 55, 591] # Color the down tube
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>'')
+ xy = box(71, 460, 48) # Color the outer loop
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'')
+
+ xy = [55, 264, 55, 458] # Top right side
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = [55, 504, 55, 591] # Bottom right side
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = box(71, 460, 48) # Outer loop
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>110, :extent=>-290, :tag=>'I11i')
+ xy = box(71, 460, 16) # Inner loop
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>'',
+ :width=>3, :tag=>'I11i')
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>@C['bg'], :width=>3)
+
+ xy = [23, 264, 23, 591] # Left side
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = box(1, 266, 23) # Top left curve
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3,
+ :style=>:arc, :extent=>90)
+
+ xy = box(75, 235, 9) # The ball
+ TkcOval.new(@canvas, xy, :fill=>color2, :outline=>'',
+ :width=>3, :tag=>'I11')
+ end
+
+ def move11(step = nil)
+ step = get_step(11, step)
+
+ pos = [
+ [75, 235], [70, 235], [65, 237], [56, 240], [46, 247], [38, 266],
+ [38, 296], [38, 333], [38, 399], [38, 475], [74, 496], [105, 472],
+ [100, 437], [65, 423], [-100, -100], [38, 505], [38, 527, :x], [38, 591]
+ ]
+
+ return 0 if step >= pos.length
+ where = pos[step]
+ move_abs('I11', where)
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Hand
+ def draw12
+ xy = [
+ 20, 637, 20, 617, 20, 610, 20, 590, 40, 590, 40, 590,
+ 60, 590, 60, 610, 60, 610
+ ]
+ xy.concat([60, 610, 65, 620, 60, 631]) # Thumb
+ xy.concat([60, 631, 60, 637, 60, 662, 60, 669, 52, 669,
+ 56, 669, 50, 669, 50, 662, 50, 637])
+
+ y0 = 637 # Bumps for fingers
+ y1 = 645
+ 50.step(21, -10){|x|
+ x1 = x - 5
+ x2 = x - 10
+ xy << x << y0 << x1 << y1 << x2 << y0
+ }
+ TkcPolygon.new(@canvas, xy, :fill=>@C['12'], :outline=>@C['fg'],
+ :smooth=>true, :tag=>'I12', :width=>3)
+ end
+
+ def move12(step = nil)
+ step = get_step(12, step)
+
+ pos = [[42.5, 641, :x]]
+ return 0 if step >= pos.length
+ where = pos[step]
+ move_abs('I12', where)
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Fax
+ def draw13
+ color = @C['13a']
+ xy = [86, 663, 149, 663, 149, 704, 50, 704, 50, 681, 64, 681, 86, 671]
+ xy2 = [
+ 784, 663, 721, 663, 721, 704, 820, 704, 820, 681, 806, 681, 784, 671
+ ]
+ radii = [2, 9, 9, 8, 5, 5, 2]
+
+ round_poly(@canvas, xy, radii, :width=>3,
+ :outline=>@C['fg'], :fill=>color)
+ round_poly(@canvas, xy2, radii, :width=>3,
+ :outline=>@C['fg'], :fill=>color)
+
+ xy = [56, 677]
+ x, y = xy
+ TkcRectangle.new(@canvas, box(x, y, 4), :fill=>'', :outline=>@C['fg'],
+ :width=>3, :tag=>'I13')
+ xy = [809, 677]
+ x, y = xy
+ TkcRectangle.new(@canvas, box(x, y, 4), :fill=>'', :outline=>@C['fg'],
+ :width=>3, :tag=>'I13R')
+
+ xy = [112, 687] # Label
+ TkcText.new(@canvas, xy, :text=>'FAX', :fill=>@C['fg'],
+ :font=>['Times Roman', 12, :bold])
+ xy = [762, 687]
+ TkcText.new(@canvas, xy, :text=>'FAX', :fill=>@C['fg'],
+ :font=>['Times Roman', 12, :bold])
+
+ xy = [138, 663, 148, 636, 178, 636] # Paper guide
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>@C['fg'], :width=>3)
+ xy = [732, 663, 722, 636, 692, 636]
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>@C['fg'], :width=>3)
+
+ sine([149, 688, 720, 688], 5, 15,
+ :tag=>'I13_s', :fill=>@C['fg'], :width=>3)
+ end
+
+ def move13(step = nil)
+ step = get_step(13, step)
+
+ numsteps = 7
+
+ if step == numsteps + 2
+ move_abs('I13_star', [-100, -100])
+ @canvas.itemconfigure('I13R', :fill=>@C['13b'], :width=>2)
+ return 2
+ end
+ if step == 0 # Button down
+ @canvas.delete('I13')
+ sparkle([-100, -100], 'I13_star') # Create off screen
+ return 1
+ end
+ x0, y0 = anchor('I13_s', :w)
+ x1, y1 = anchor('I13_s', :e)
+ x = x0 + (x1 - x0) * (step - 1) / numsteps.to_f
+ move_abs('I13_star', [x, y0])
+ return 1
+ end
+
+ # Paper in fax
+ def draw14
+ color = @C['14']
+ xy = [102, 661, 113, 632, 130, 618] # Left paper edge
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>color,
+ :width=>3, :tag=>'I14L_0')
+ xy = [148, 629, 125, 640, 124, 662] # Right paper edge
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>color,
+ :width=>3, :tag=>'I14L_1')
+ draw14a('L')
+
+ xy = [
+ 768.0, 662.5, 767.991316225, 662.433786215, 767.926187912, 662.396880171
+ ]
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>color,
+ :width=>3, :tag=>'I14R_0')
+ @canvas.lower('I14R_0')
+ # NB. these numbers are VERY sensitive, you must start with final size
+ # and shrink down to get the values
+ xy = [
+ 745.947897349, 662.428358855, 745.997829056, 662.452239237, 746.0, 662.5
+ ]
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>color,
+ :width=>3, :tag=>'I14R_1')
+ @canvas.lower('I14R_1')
+ end
+
+ def draw14a(side)
+ color = @C['14']
+ xy = @canvas.coords("I14#{side}_0")
+ xy2 = @canvas.coords("I14#{side}_1")
+ x0, y0, x1, y1, x2, y2 = xy
+ x3, y3, x4, y4, x5, y5 = xy2
+
+ zz = [
+ x0, y0, x0, y0, xy, x2, y2, x2, y2,
+ x3, y3, x3, y3, xy2, x5, y5, x5, y5
+ ].flatten
+ @canvas.delete("I14#{side}")
+ TkcPolygon.new(@canvas, zz, :tag=>"I14#{side}", :smooth=>true,
+ :fill=>color, :outline=>color, :width=>3)
+ @canvas.lower("I14#{side}")
+ end
+
+ def move14(step = nil)
+ step = get_step(14, step)
+
+ # Paper going down
+ sc = 0.9 - 0.05*step
+ if sc < 0.3
+ @canvas.delete('I14L')
+ return 0
+ end
+
+ ox, oy = @canvas.coords('I14L_0')
+ @canvas.scale('I14L_0', ox, oy, sc, sc)
+ ox, oy = @canvas.coords('I14L_1')[-2..-1]
+ @canvas.scale('I14L_1', ox, oy, sc, sc)
+ draw14a('L')
+
+ # Paper going up
+ sc = 0.35 + 0.05*step
+ sc = 1/sc
+
+ ox, oy = @canvas.coords('I14R_0')
+ @canvas.scale('I14R_0', ox, oy, sc, sc)
+ ox, oy = @canvas.coords('I14R_1')[-2..-1]
+ @canvas.scale('I14R_1', ox, oy, sc, sc)
+ draw14a('R')
+
+ return((step == 10)? 3: 1)
+ end
+
+ # Light beam
+ def draw15
+ color = @C['15a']
+ xy = [824, 599, 824, 585, 820, 585, 829, 585]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I15a')
+ xy = [789, 599, 836, 643]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>3)
+ xy = [778, 610, 788, 632]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>3)
+ xy = [766, 617, 776, 625]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>3)
+
+ xy = [633, 600, 681, 640]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>3)
+ xy = [635, 567, 657, 599]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>2)
+ xy = [765, 557, 784, 583]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>2)
+
+ sine([658, 580, 765, 580], 3, 15,
+ :tag=>'I15_s', :fill=>@C['fg'], :width=>3)
+ end
+
+ def move15a
+ color = @C['15b']
+ @canvas.scale('I15a', 824, 599, 1, 0.3) # Button down
+ xy = [765, 621, 681, 621]
+ TkcLine.new(@canvas, xy, :dash=>'-', :width=>3, :fill=>color, :tag=>'I15')
+ end
+
+ def move15(step = nil)
+ step = get_step(15, step)
+
+ numsteps = 6
+
+ if step == numsteps + 2
+ move_abs('I15_star', [-100, -100])
+ return 2
+ end
+ if step == 0 # Break the light beam
+ sparkle([-100, -100], 'I15_star')
+ xy = [765, 621, 745, 621]
+ @canvas.coords('I15', xy)
+ return 1
+ end
+ x0, y0 = anchor('I15_s', :w)
+ x1, y1 = anchor('I15_s', :e)
+ x = x0 + (x1 - x0) * (step - 1) / numsteps.to_f
+ move_abs('I15_star', [x, y0])
+ return 1
+ end
+
+ # Bell
+ def draw16
+ color = @C['16']
+ xy = [722, 485, 791, 556]
+ TkcRectangle.new(@canvas, xy, :fill=>'', :outline=>@C['fg'], :width=>3)
+ xy = box(752, 515, 25) # Bell
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'black',
+ :tag=>'I16b', :width=>2)
+ xy = box(752, 515, 5) # Bell button
+ TkcOval.new(@canvas, xy, :fill=>'black', :outline=>'black', :tag=>'I16b')
+
+ xy = [784, 523, 764, 549] # Clapper
+ TkcLine.new(@canvas, xy, :width=>3, :tag=>'I16c', :fill=>@C['fg'])
+ xy = box(784, 523, 4)
+ TkcOval.new(@canvas, xy, :fill=>@C['fg'], :outline=>@C['fg'], :tag=>'I16d')
+ end
+
+ def move16(step = nil)
+ step = get_step(16, step)
+
+ # Note: we never stop
+ ox, oy = [760, 553]
+ if (step & 1).nonzero?
+ beta = 12
+ @canvas.move('I16b', 3, 0)
+ else
+ beta = -12
+ @canvas.move('I16b', -3, 0)
+ end
+ rotate_item('I16c', ox, oy, beta)
+ rotate_item('I16d', ox, oy, beta)
+
+ return ((step == 1)? 3: 1)
+ end
+
+ # Cat
+ def draw17
+ color = @C['17']
+
+ xy = [584, 556, 722, 556]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = [584, 485, 722, 485]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+
+ xy = [664, 523, 717, 549] # Body
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :fill=>color, :width=>3,
+ :style=>:chord, :start=>128, :extent=>260, :tag=>'I17')
+
+ xy = [709, 554, 690, 543] # Paw
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>color,
+ :width=>3, :tag=>'I17')
+ xy = [657, 544, 676, 555]
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>color,
+ :width=>3, :tag=>'I17')
+
+ xy = box(660, 535, 15) # Lower face
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>150, :extent=>240, :tag=>'I17_')
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :width=>1,
+ :style=>:chord, :start=>150, :extent=>240, :tag=>'I17_')
+ xy = [674, 529, 670, 513, 662, 521, 658, 521, 650, 513, 647, 529] # Ears
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ TkcPolygon.new(@canvas, xy, :fill=>color, :outline=>'', :width=>1,
+ :tag=>['I17_', 'I17_c'])
+ xy = [652, 542, 628, 539] # Whiskers
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [652, 543, 632, 545]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [652, 546, 632, 552]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+
+ xy = [668, 543, 687, 538]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :tag=>['I17_', 'I17_w'])
+ xy = [668, 544, 688, 546]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :tag=>['I17_', 'I17_w'])
+ xy = [668, 547, 688, 553]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :tag=>['I17_', 'I17_w'])
+
+ xy = [649, 530, 654, 538, 659, 530] # Left eye
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2,
+ :smooth=>true, :tag=>'I17')
+ xy = [671, 530, 666, 538, 661, 530] # Right eye
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2,
+ :smooth=>true, :tag=>'I17')
+ xy = [655, 543, 660, 551, 665, 543] # Mouth
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2,
+ :smooth=>true, :tag=>'I17')
+ end
+
+ def move17(step = nil)
+ step = get_step(17, step)
+
+ if step == 0
+ @canvas.delete('I17') # Delete most of the cat
+ xy = [655, 543, 660, 535, 665, 543] # Mouth
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :smooth=>true, :tag=>'I17_')
+ xy = box(654, 530, 4) # Left eye
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :fill=>'',
+ :tag=>'I17_')
+ xy = box(666, 530, 4) # Right eye
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :fill=>'',
+ :tag=>'I17_')
+
+ @canvas.move('I17_', 0, -20) # Move face up
+ xy = [652, 528, 652, 554] # Front leg
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [670, 528, 670, 554] # 2nd front leg
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+
+ xy = [ # Body
+ 675, 506, 694, 489, 715, 513, 715, 513, 715, 513, 716, 525,
+ 716, 525, 716, 525, 706, 530, 695, 530, 679, 535, 668, 527,
+ 668, 527, 668, 527, 675, 522, 676, 517, 677, 512
+ ]
+ TkcPolygon.new(@canvas, xy, :fill=>@canvas.itemcget('I17_c', :fill),
+ :outline=>@C['fg'], :width=>3, :smooth=>true,
+ :tag=>'I17_')
+ xy = [716, 514, 716, 554] # Back leg
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [694, 532, 694, 554] # 2nd back leg
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [715, 514, 718, 506, 719, 495, 716, 488] # Tail
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :smooth=>true, :tag=>'I17_')
+
+ @canvas.raise('I17w') # Make whiskers visible
+ @canvas.move('I17_', -5, 0) # Move away from the wall a bit
+ return 2
+ end
+ return 0
+ end
+
+ # Sling shot
+ def draw18
+ color = @C['18']
+ xy = [721, 506, 627, 506] # Sling hold
+ TkcLine.new(@canvas, xy, :width=>4, :fill=>@C['fg'], :tag=>'I18')
+
+ xy = [607, 500, 628, 513] # Sling rock
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'', :tag=>'I18a')
+
+ xy = [526, 513, 606, 507, 494, 502] # Sling band
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>4, :tag=>'I18b')
+ xy = [485, 490, 510, 540, 510, 575, 510, 540, 535, 491] # Sling
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>6)
+ end
+
+ def move18(step = nil)
+ step = get_step(18, step)
+
+ pos = [
+ [587, 506], [537, 506], [466, 506], [376, 506], [266, 506, :x],
+ [136, 506], [16, 506], [-100, -100]
+ ]
+
+ b = []
+ b[0] = [490, 502, 719, 507, 524, 512] # Band collapsing
+ b[1] = [
+ 491, 503, 524, 557, 563, 505, 559, 496, 546, 506, 551, 525,
+ 553, 536, 538, 534, 532, 519, 529, 499
+ ]
+ b[2] = [
+ 491, 503, 508, 563, 542, 533, 551, 526, 561, 539, 549, 550, 530, 500
+ ]
+ b[3] = [
+ 491, 503, 508, 563, 530, 554, 541, 562, 525, 568, 519, 544, 530, 501
+ ]
+
+ return 0 if step >= pos.length
+
+ if step == 0
+ @canvas.delete('I18')
+ @canvas.itemconfigure('I18b', :smooth=>true)
+ end
+ if b[step]
+ @canvas.coords('I18b', b[step])
+ end
+
+ where = pos[step]
+ move_abs('I18a', where)
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Water pipe
+ def draw19
+ color = @C['19']
+ xx = [[249, 181], [155, 118], [86, 55], [22, 0]]
+ xx.each{|x1, x2|
+ TkcRectangle.new(@canvas, x1, 453, x2, 467,
+ :fill=>color, :outline=>'', :tag=>'I19')
+ TkcLine.new(@canvas, x1, 453, x2, 453,
+ :fill=>@C['fg'], :width=>1) # Pipe top
+ TkcLine.new(@canvas, x1, 467, x2, 467,
+ :fill=>@C['fg'], :width=>1) # Pipe bottom
+ }
+ @canvas.raise('I11i')
+
+ xy = box(168, 460, 16) # Bulge by the joint
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'')
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1, :style=>:arc,
+ :start=>21, :extent=>136)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1, :style=>:arc,
+ :start=>-21, :extent=>-130)
+
+ xy = [249, 447, 255, 473] # First joint 26x6
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+
+ xy = box(257, 433, 34) # Bend up
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :width=>1,
+ :style=>:pie, :start=>0, :extent=>-91)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>0, :extent=>-90)
+ xy = box(257, 433, 20)
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>@C['bg'], :width=>1,
+ :style=>:pie, :start=>0, :extent=>-92)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>0, :extent=>-90)
+ xy = box(257, 421, 34) # Bend left
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :width=>1,
+ :style=>:pie, :start=>0, :extent=>91)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>0, :extent=>90)
+ xy = box(257, 421, 20)
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>@C['bg'], :width=>1,
+ :style=>:pie, :start=>0, :extent=>90)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>0, :extent=>90)
+ xy = box(243, 421, 34) # Bend down
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :width=>1,
+ :style=>:pie, :start=>90, :extent=>90)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>90, :extent=>90)
+ xy = box(243, 421, 20)
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>@C['bg'], :width=>1,
+ :style=>:pie, :start=>90, :extent=>90)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>90, :extent=>90)
+
+ xy = [270, 427, 296, 433] # 2nd joint bottom
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+ xy = [270, 421, 296, 427] # 2nd joint top
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+ xy = [249, 382, 255, 408] # Third joint right
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+ xy = [243, 382, 249, 408] # Third joint left
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+ xy = [203, 420, 229, 426] # Last joint
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+
+ xy = box(168, 460, 6) # Handle joint
+ TkcOval.new(@canvas, xy, :fill=>@C['fg'], :outline=>'', :tag=>'I19a')
+ xy = [168, 460, 168, 512] # Handle bar
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>5, :tag=>'I19b')
+ end
+
+ def move19(step = nil)
+ step = get_step(19, step)
+
+ angles = [30, 30, 30]
+ return 2 if step == angles.length
+ ox, oy = centroid('I19a')
+ rotate_item('I19b', ox, oy, angles[step])
+
+ return 1
+ end
+
+ # Water pouring
+ def draw20
+ # do nothing
+ end
+
+ def move20(step = nil)
+ step = get_step(20, step)
+
+ pos = [451, 462, 473, 484, 496, 504, 513, 523, 532]
+ freq = [20, 40, 40, 40, 40, 40, 40, 40, 40]
+ pos = [
+ [451, 20], [462, 40], [473, 40], [484, 40], [496, 40],
+ [504, 40], [513, 40], [523, 40], [532, 40, :x]
+ ]
+ return 0 if step >= pos.length
+
+ @canvas.delete('I20')
+ where = pos[step]
+ y, f = where
+ h20(y, f)
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ def h20(y, f)
+ color = @C['20']
+ @canvas.delete('I20')
+
+ sine([208, 428, 208, y], 4, f, :tag=>['I20', 'I20s'],
+ :width=>3, :fill=>color, :smooth=>true)
+ TkcLine.new(@canvas, @canvas.coords('I20s'), :width=>3,
+ :fill=>color, :smooth=>1, :tag=>['I20', 'I20a'])
+ TkcLine.new(@canvas, @canvas.coords('I20s'), :width=>3,
+ :fill=>color, :smooth=>1, :tag=>['I20', 'I20b'])
+ @canvas.move('I20a', 8, 0)
+ @canvas.move('I20b', 16, 0)
+ end
+
+ # Bucket
+ def draw21
+ color = @C['21']
+ xy = [217, 451, 244, 490] # Right handle
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2, :tag=>'I21_a')
+ xy = [201, 467, 182, 490] # Left handle
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2, :tag=>'I21_a')
+
+ xy = [245, 490, 237, 535] # Right side
+ xy2 = [189, 535, 181, 490] # Left side
+ TkcPolygon.new(@canvas, xy + xy2, :fill=>color, :outline=>'',
+ :tag=>['I21', 'I21f'])
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2, :tag=>'I21')
+ TkcLine.new(@canvas, xy2, :fill=>@C['fg'], :width=>2, :tag=>'I21')
+
+ xy = [182, 486, 244, 498] # Top
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'', :width=>2,
+ :tag=>['I21', 'I21f'])
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'], :width=>2,
+ :tag=>['I21', 'I21t'])
+ xy = [189, 532, 237, 540] # Bottom
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>2,
+ :tag=>['I21', 'I21b'])
+ end
+
+ def move21(step = nil)
+ step = get_step(21, step)
+
+ numsteps = 30
+ return 0 if step >= numsteps
+
+ x1, y1, x2, y2 = @canvas.coords('I21b')
+ # lx1, ly1, lx2, ly2 = @canvas.coords('I21t')
+ lx1, ly1, lx2, ly2 = [183, 492, 243, 504]
+
+ f = step / numsteps.to_f
+ y2 = y2 - 3
+ xx1 = x1 + (lx1 - x1) * f
+ yy1 = y1 + (ly1 - y1) * f
+ xx2 = x2 + (lx2 - x2) * f
+ yy2 = y2 + (ly2 - y2) * f
+
+ @canvas.itemconfigure('I21b', :fill=>@C['20'])
+ @canvas.delete('I21w')
+ TkcPolygon.new(@canvas, x2, y2, x1, y1, xx1, yy1, xx2, yy1,
+ :tag=>['I21', 'I21w'], :outline=>'', :fill=>@C['20'])
+ @canvas.lower('I21w', 'I21')
+ @canvas.raise('I21b')
+ @canvas.lower('I21f')
+
+ return((step == numsteps - 1)? 3: 1)
+ end
+
+ # Bucket drop
+ def draw22
+ # do nothing
+ end
+
+ def move22(step = nil)
+ step = get_step(22, step)
+ pos = [[213, 513], [213, 523], [213, 543, :x], [213, 583], [213, 593]]
+
+ @canvas.itemconfigure('I21f', :fill=>@C['22']) if step == 0
+ return 0 if step >= pos.length
+ where = pos[step]
+ move_abs('I21', where)
+ h20(where[1], 40)
+ @canvas.delete('I21_a') # Delete handles
+
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Blow dart
+ def draw23
+ color = @C['23a']
+ color2 = @C['23b']
+ color3 = @C['23c']
+
+ xy = [185, 623, 253, 650] # Block
+ TkcRectangle.new(@canvas, xy, :fill=>'black', :outline=>@C['fg'],
+ :width=>2, :tag=>'I23a')
+ xy = [187, 592, 241, 623] # Balloon
+ TkcOval.new(@canvas, xy, :outline=>'', :fill=>color, :tag=>'I23b')
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :tag=>'I23b',
+ :style=>:arc, :start=>12, :extent=>336)
+ xy = [239, 604, 258, 589, 258, 625, 239, 610] # Balloon nozzle
+ TkcPolygon.new(@canvas, xy, :outline=>'', :fill=>color, :tag=>'I23b')
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I23b')
+
+ xy = [285, 611, 250, 603] # Dart body
+ TkcOval.new(@canvas, xy, :fill=>color2, :outline=>@C['fg'],
+ :width=>3, :tag=>'I23d')
+ xy = [249, 596, 249, 618, 264, 607, 249, 596] # Dart tail
+ TkcPolygon.new(@canvas, xy, :fill=>color3, :outline=>@C['fg'],
+ :width=>3, :tag=>'I23d')
+ xy = [249, 607, 268, 607] # Dart detail
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I23d')
+ xy = [285, 607, 305, 607] # Dart needle
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I23d')
+ end
+
+ def move23(step = nil)
+ step = get_step(23, step)
+
+ pos = [
+ [277, 607], [287, 607], [307, 607, :x], [347, 607], [407, 607],
+ [487, 607], [587, 607], [687, 607], [787, 607], [-100, -100]
+ ]
+
+ return 0 if step >= pos.length
+ if step <= 1
+ ox, oy = anchor('I23a', :n)
+ @canvas.scale('I23b', ox, oy, 0.9, 0.5)
+ end
+ where = pos[step]
+ move_abs('I23d', where)
+
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Balloon
+ def draw24
+ color = @C['24a']
+ xy = [366, 518, 462, 665] # Balloon
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>@C['fg'],
+ :width=>3, :tag=>'I24')
+ xy = [414, 666, 414, 729] # String
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I24')
+ xy = [410, 666, 404, 673, 422, 673, 418, 666] # Nozzle
+ TkcPolygon.new(@canvas, xy, :fill=>color, :outline=>@C['fg'],
+ :width=>3, :tag=>'I24')
+
+ xy = [387, 567, 390, 549, 404, 542] # Reflections
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :smooth=>true,
+ :width=>2, :tag=>'I24')
+ xy = [395, 568, 399, 554, 413, 547]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :smooth=>true,
+ :width=>2, :tag=>'I24')
+ xy = [403, 570, 396, 555, 381, 553]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :smooth=>true,
+ :width=>2, :tag=>'I24')
+ xy = [408, 564, 402, 547, 386, 545]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :smooth=>true,
+ :width=>2, :tag=>'I24')
+ end
+
+ def move24(step = nil)
+ step = get_step(24, step)
+
+ return 0 if step > 4
+ return 2 if step == 4
+
+ if step == 0
+ @canvas.delete('I24') # Exploding balloon
+ xy = [
+ 347, 465, 361, 557, 271, 503, 272, 503, 342, 574, 259, 594,
+ 259, 593, 362, 626, 320, 737, 320, 740, 398, 691, 436, 738,
+ 436, 739, 476, 679, 528, 701, 527, 702, 494, 627, 548, 613,
+ 548, 613, 480, 574, 577, 473, 577, 473, 474, 538, 445, 508,
+ 431, 441, 431, 440, 400, 502, 347, 465, 347, 465
+ ]
+ TkcPolygon.new(@canvas, xy, :tag=>'I24', :fill=>@C['24b'],
+ :outline=>@C['24a'], :width=>10, :smooth=>true)
+ msg = Tk.subst(@S['message'].value)
+ TkcText.new(@canvas, centroid('I24'), :text=>msg, :tag=>['I24', 'I24t'],
+ :justify=>:center, :font=>['Times Roman', 18, :bold])
+ return 1
+ end
+
+ @canvas.itemconfigure('I24t', :font=>['Times Roman', 18 + 6*step, :bold])
+ @canvas.move('I24', 0, -60)
+ ox, oy = centroid('I24')
+ @canvas.scale('I24', ox, oy, 1.25, 1.25)
+ return 1
+ end
+
+ # Displaying the message
+ def move25(step = nil)
+ step = get_step(25, step)
+
+ if step == 0
+ @XY['25'] = Tk::Clock.clicks(:miliseconds)
+ return 1
+ end
+ elapsed = Tk::Clock.clicks(:miliseconds) - @XY['25']
+ return 1 if elapsed < 5000
+ return 2
+ end
+
+ # Collapsing balloon
+ def move26(step = nil)
+ step = get_step(26, step)
+
+ if step >= 3
+ @canvas.delete('I24', 'I26')
+ TkcText.new(@canvas, 430, 740, :anchor=>:s, :tag=>'I26',
+ :text=>'click to continue',
+ :font=>['Times Roman', 24, :bold])
+ @canvas.bind('1', proc{reset})
+ return 4
+ end
+
+ ox, oy = centroid('I24')
+ @canvas.scale('I24', ox, oy, 0.8, 0.8)
+ @canvas.move('I24', 0, 60)
+ @canvas.itemconfigure('I24t', :font=>['Times Roman', 30 - 6*step, :bold])
+ return 1
+ end
+
+ ################################################################
+ #
+ # Helper functions
+ #
+ def box(x, y, r)
+ [x - r, y - r, x + r, y + r]
+ end
+
+ def move_abs(item, xy)
+ x, y = xy
+ ox, oy = centroid(item)
+ dx = x - ox
+ dy = y - oy
+ @canvas.move(item, dx, dy)
+ end
+
+ def rotate_item(item, ox, oy, beta)
+ xy = @canvas.coords(item)
+ xy2 = []
+ 0.step(xy.length - 1, 2){|idx|
+ x, y = xy[idx, 2]
+ xy2.concat(rotate_c(x, y, ox, oy, beta))
+ }
+ @canvas.coords(item, xy2)
+ end
+
+ def rotate_c(x, y, ox, oy, beta)
+ # rotates vector (ox,oy)->(x,y) by beta degrees clockwise
+
+ x -= ox # Shift to origin
+ y -= oy
+
+ beta = beta * Math.atan(1) * 4 / 180.0 # Radians
+ xx = x * Math.cos(beta) - y * Math.sin(beta) # Rotate
+ yy = x * Math.sin(beta) + y * Math.cos(beta)
+
+ xx += ox # Shift back
+ yy += oy
+
+ [xx, yy]
+ end
+
+ def reset
+ draw_all
+ @canvas.bind_remove('1')
+ @S['mode'].value = :MSTART
+ @S['active'] = [0]
+ end
+
+ # Each Move## keeps its state info in STEP, this retrieves and increments it
+ def get_step(who, step)
+ if step
+ @STEP[who] = step
+ else
+ if !@STEP.exist?(who) || @STEP[who] == ""
+ @STEP[who] = 0
+ else
+ @STEP[who] += 1
+ end
+ end
+ @STEP[who]
+ end
+
+ def reset_step
+ @S['cnt'].value = 0
+ @STEP.keys.each{|k| @STEP[k] = ''}
+ end
+
+ def sine(xy0, amp, freq, opts = {})
+ x0, y0, x1, y1 = xy0
+ step = 2
+ xy = []
+ if y0 == y1 # Horizontal
+ x0.step(x1, step){|x|
+ beta = (x - x0) * 2 * Math::PI / freq
+ y = y0 + amp * Math.sin(beta)
+ xy << x << y
+ }
+ else
+ y0.step(y1, step){|y|
+ beta = (y - y0) * 2 * Math::PI / freq
+ x = x0 + amp * Math.sin(beta)
+ xy << x << y
+ }
+ end
+ TkcLine.new(@canvas, xy, opts)
+ end
+
+ def round_rect(xy, radius, opts={})
+ x0, y0, x3, y3 = xy
+ r = @canvas.winfo_pixels(radius)
+ d = 2 * r
+
+ # Make sure that the radius of the curve is less than 3/8 size of the box!
+ maxr = 0.75
+ if d > maxr * (x3 - x0)
+ d = maxr * (x3 - x0)
+ end
+ if d > maxr * (y3 - y0)
+ d = maxr * (y3 - y0)
+ end
+
+ x1 = x0 + d
+ x2 = x3 - d
+ y1 = y0 + d
+ y2 = y3 - d
+
+ xy = [x0, y0, x1, y0, x2, y0, x3, y0, x3, y1, x3, y2]
+ xy.concat([x3, y3, x2, y3, x1, y3, x0, y3, x0, y2, x0, y1])
+ return xy
+ end
+
+ def round_poly(canv, xy, radii, opts)
+ lenXY = xy.length
+ lenR = radii.length
+ if lenXY != 2*lenR
+ raise "wrong number of vertices and radii"
+ end
+
+ knots = []
+ x0 = xy[-2]; y0 = xy[-1]
+ x1 = xy[0]; y1 = xy[1]
+ xy << xy[0] << xy[1]
+
+ 0.step(lenXY - 1, 2){|i|
+ radius = radii[i/2]
+ r = canv.winfo_pixels(radius)
+
+ x2 = xy[i+2]; y2 = xy[i+3]
+ z = _round_poly2(x0, y0, x1, y1, x2, y2, r)
+ knots.concat(z)
+
+ x0 = x1; y0 = y1
+ x1 = x2; y1 = y2
+ }
+ TkcPolygon.new(canv, knots, {:smooth=>true}.update(opts))
+ end
+
+ def _round_poly2(x0, y0, x1, y1, x2, y2, radius)
+ d = 2 * radius
+ maxr = 0.75
+
+ v1x = x0 - x1
+ v1y = y0 - y1
+ v2x = x2 - x1
+ v2y = y2 - y1
+
+ vlen1 = Math.sqrt(v1x*v1x + v1y*v1y)
+ vlen2 = Math.sqrt(v2x*v2x + v2y*v2y)
+
+ if d > maxr * vlen1
+ d = maxr * vlen1
+ end
+ if d > maxr * vlen2
+ d = maxr * vlen2
+ end
+
+ xy = []
+ xy << (x1 + d * v1x / vlen1) << (y1 + d * v1y / vlen1)
+ xy << x1 << y1
+ xy << (x1 + d * v2x / vlen2) << (y1 + d * v2y / vlen2)
+
+ return xy
+ end
+
+ def sparkle(oxy, tag)
+ xy = [
+ [299, 283], [298, 302], [295, 314], [271, 331],
+ [239, 310], [242, 292], [256, 274], [281, 273]
+ ]
+ xy.each{|x, y|
+ TkcLine.new(@canvas, 271, 304, x, y,
+ :fill=>'white', :width=>3, :tag=>tag)
+ }
+ move_abs(tag, oxy)
+ end
+
+ def centroid(item)
+ anchor(item, :c)
+ end
+
+ def anchor(item, where)
+ x1, y1, x2, y2 = @canvas.bbox(item)
+ case(where)
+ when :n
+ y = y1
+ when :s
+ y = y2
+ else
+ y = (y1 + y2) / 2.0
+ end
+ case(where)
+ when :w
+ x = x1
+ when :e
+ x = x2
+ else
+ x = (x1 + x2) / 2.0
+ end
+ return [x, y]
+ end
+end
+
+TkGoldberg_Demo.new(base_frame)
diff --git a/ext/tk/sample/demos-en/hello b/ext/tk/sample/demos-en/hello
index f06eabe518..5e86ad7e3e 100644
--- a/ext/tk/sample/demos-en/hello
+++ b/ext/tk/sample/demos-en/hello
@@ -1,9 +1,9 @@
#!/usr/bin/env ruby
require 'tk'
-unless /^8\.[1-9]/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK
- require 'tkencoding'
-end
+#unless /^8\.[1-9]/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK
+# require 'tkencoding'
+#end
TkButton.new(nil,
'text'=>"Hello Ruby world!",
diff --git a/ext/tk/sample/demos-en/hscale.rb b/ext/tk/sample/demos-en/hscale.rb
index 14e395b61a..e660216967 100644
--- a/ext/tk/sample/demos-en/hscale.rb
+++ b/ext/tk/sample/demos-en/hscale.rb
@@ -11,8 +11,9 @@ $hscale_demo = TkToplevel.new {|w|
}
positionWindow($hscale_demo)
+base_frame = TkFrame.new($hscale_demo).pack(:fill=>:both, :expand=>true)
-msg = TkLabel.new($hscale_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '3.5i'
justify 'left'
@@ -20,7 +21,7 @@ msg = TkLabel.new($hscale_demo) {
}
msg.pack('side'=>'top')
-TkFrame.new($hscale_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc {
@@ -36,7 +37,18 @@ TkFrame.new($hscale_demo) {|frame|
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
-TkFrame.new($hscale_demo) {|frame|
+
+def setWidth(w, width)
+ width = width + 21
+ x2 = width - 30
+ if x2 < 21
+ x2 = 21
+ end
+ w.coords 'poly',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
+ w.coords 'line',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
+end
+
+TkFrame.new(base_frame) {|frame|
canvas = TkCanvas.new(frame) {|c|
width 50
height 50
@@ -61,14 +73,3 @@ TkFrame.new($hscale_demo) {|frame|
}.pack('side'=>'bottom', 'expand'=>'yes', 'anchor'=>'n')
scale.set 75
}.pack('side'=>'top', 'fill'=>'x')
-
-
-def setWidth(w, width)
- width = width + 21
- x2 = width - 30
- if x2 < 21
- x2 = 21
- end
- w.coords 'poly',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
- w.coords 'line',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
-end
diff --git a/ext/tk/sample/demos-en/icon.rb b/ext/tk/sample/demos-en/icon.rb
index 7557257ef4..a3921d2333 100644
--- a/ext/tk/sample/demos-en/icon.rb
+++ b/ext/tk/sample/demos-en/icon.rb
@@ -19,8 +19,10 @@ $icon_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($icon_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($icon_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -29,7 +31,7 @@ msg = TkLabel.new($icon_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($icon_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -48,45 +50,53 @@ TkFrame.new($icon_demo) {|frame|
# image
flagup = \
-TkBitmapImage.new('file'=>[$demo_dir,
+TkBitmapImage.new('file'=>[$demo_dir,'..',
'images','flagup.xbm'].join(File::Separator),
- 'maskfile'=>\
- [$demo_dir,'images','flagup.xbm'].join(File::Separator))
+ 'maskfile'=>\
+ [$demo_dir,'..','images','flagup.xbm'].join(File::Separator))
flagdown = \
-TkBitmapImage.new('file'=>[$demo_dir,
+TkBitmapImage.new('file'=>[$demo_dir,'..',
'images','flagdown.xbm'].join(File::Separator),
- 'maskfile'=>\
- [$demo_dir,'images','flagdown.xbm'].join(File::Separator))
+ 'maskfile'=>\
+ [$demo_dir,'..',
+ 'images','flagdown.xbm'].join(File::Separator))
-# ÊÑ¿ôÀ¸À®
+# create variable
letters = TkVariable.new
# frame
-TkFrame.new($icon_demo, 'borderwidth'=>10){|w|
+TkFrame.new(base_frame, 'borderwidth'=>10){|w|
TkFrame.new(w) {|f|
- TkRadioButton.new(f){
- bitmap '@' + [$demo_dir,'images','letters.xbm'].join(File::Separator)
+ # TkRadioButton.new(f){
+ Tk::RadioButton.new(f){
+ bitmap '@' + [$demo_dir,'..',
+ 'images','letters.xbm'].join(File::Separator)
variable letters
value 'full'
}.pack('side'=>'top', 'expand'=>'yes')
- TkRadioButton.new(f){
- bitmap '@' + [$demo_dir,'images','noletter.xbm'].join(File::Separator)
+ # TkRadioButton.new(f){
+ Tk::RadioButton.new(f){
+ bitmap '@' + [$demo_dir,'..',
+ 'images','noletter.xbm'].join(File::Separator)
variable letters
value 'empty'
}.pack('side'=>'top', 'expand'=>'yes')
}.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'5m')
- TkCheckButton.new(w) {
+ # TkCheckButton.new(w) {
+ Tk::CheckButton.new(w) {
image flagdown
selectimage flagup
indicatoron 0
selectcolor self['background']
}.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'5m')
- TkCheckButton.new(w) {
- bitmap '@' + [$demo_dir,'images','letters.xbm'].join(File::Separator)
+ # TkCheckButton.new(w) {
+ Tk::CheckButton.new(w) {
+ bitmap '@' + [$demo_dir,'..',
+ 'images','letters.xbm'].join(File::Separator)
indicatoron 0
selectcolor 'SeaGreen1'
}.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'5m')
diff --git a/ext/tk/sample/demos-en/image1.rb b/ext/tk/sample/demos-en/image1.rb
index 8d39b20049..a9072bb308 100644
--- a/ext/tk/sample/demos-en/image1.rb
+++ b/ext/tk/sample/demos-en/image1.rb
@@ -18,8 +18,10 @@ $image1_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($image1_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($image1_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -28,7 +30,7 @@ msg = TkLabel.new($image1_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($image1_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -47,14 +49,17 @@ TkFrame.new($image1_demo) {|frame|
# image
image1a = \
-TkPhotoImage.new('file'=>[$demo_dir,
+TkPhotoImage.new('file'=>[$demo_dir,'..',
'images','earth.gif'].join(File::Separator))
image1b = \
-TkPhotoImage.new('file'=>[$demo_dir,
+TkPhotoImage.new('file'=>[$demo_dir,'..',
'images','earthris.gif'].join(File::Separator))
# label
-[ TkLabel.new($image1_demo, 'image'=>image1a, 'bd'=>1, 'relief'=>'sunken'),
- TkLabel.new($image1_demo, 'image'=>image1b, 'bd'=>1, 'relief'=>'sunken')
+#[ TkLabel.new(base_frame, 'image'=>image1a, 'bd'=>1, 'relief'=>'sunken'),
+# TkLabel.new(base_frame, 'image'=>image1b, 'bd'=>1, 'relief'=>'sunken')
+#].each{|w| w.pack('side'=>'top', 'padx'=>'.5m', 'pady'=>'.5m')}
+[ Tk::Label.new(base_frame, 'image'=>image1a, 'bd'=>1, 'relief'=>'sunken'),
+ Tk::Label.new(base_frame, 'image'=>image1b, 'bd'=>1, 'relief'=>'sunken')
].each{|w| w.pack('side'=>'top', 'padx'=>'.5m', 'pady'=>'.5m')}
diff --git a/ext/tk/sample/demos-en/image2.rb b/ext/tk/sample/demos-en/image2.rb
index 9924195675..1975dd6b02 100644
--- a/ext/tk/sample/demos-en/image2.rb
+++ b/ext/tk/sample/demos-en/image2.rb
@@ -19,8 +19,10 @@ $image2_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($image2_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($image2_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -29,7 +31,7 @@ msg = TkLabel.new($image2_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($image2_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -46,28 +48,28 @@ TkFrame.new($image2_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
-# ÊÑ¿ôÀ¸À®
-$dirName = TkVariable.new([$demo_dir,'images'].join(File::Separator))
+# create variable
+$dirName = TkVariable.new([$demo_dir,'..','images'].join(File::Separator))
# image
$image2a = TkPhotoImage.new
#
-TkLabel.new($image2_demo, 'text'=>'Directory:')\
+TkLabel.new(base_frame, 'text'=>'Directory:')\
.pack('side'=>'top', 'anchor'=>'w')
-image2_e = TkEntry.new($image2_demo) {
+image2_e = TkEntry.new(base_frame) {
width 30
textvariable $dirName
}.pack('side'=>'top', 'anchor'=>'w')
-TkFrame.new($image2_demo, 'height'=>'3m', 'width'=>20)\
+TkFrame.new(base_frame, 'height'=>'3m', 'width'=>20)\
.pack('side'=>'top', 'anchor'=>'w')
-TkLabel.new($image2_demo, 'text'=>'File:')\
+TkLabel.new(base_frame, 'text'=>'File:')\
.pack('side'=>'top', 'anchor'=>'w')
-TkFrame.new($image2_demo){|w|
+TkFrame.new(base_frame){|w|
s = TkScrollbar.new(w)
l = TkListbox.new(w) {
width 20
@@ -86,9 +88,9 @@ TkFrame.new($image2_demo){|w|
}.pack('side'=>'top', 'anchor'=>'w')
# image
-[ TkFrame.new($image2_demo, 'height'=>'3m', 'width'=>20),
- TkLabel.new($image2_demo, 'text'=>'Image:'),
- TkLabel.new($image2_demo, 'image'=>$image2a)
+[ TkFrame.new(base_frame, 'height'=>'3m', 'width'=>20),
+ TkLabel.new(base_frame, 'text'=>'Image:'),
+ TkLabel.new(base_frame, 'image'=>$image2a)
].each{|w| w.pack('side'=>'top', 'anchor'=>'w')}
#
diff --git a/ext/tk/sample/demos-en/image3.rb b/ext/tk/sample/demos-en/image3.rb
index d997ef7772..43afab7ecd 100644
--- a/ext/tk/sample/demos-en/image3.rb
+++ b/ext/tk/sample/demos-en/image3.rb
@@ -19,26 +19,29 @@ $image3_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($image3_demo).pack(:fill=>:both, :expand=>true)
+
#
-def loadDir(w)
+def loadDir3(w)
w.delete(0,'end')
Dir.glob([$dirName,'*'].join(File::Separator)).sort.each{|f|
w.insert('end',File.basename(f))
}
end
-# selectAndLoadDir --
+# selectAndLoadDir3 --
# This procedure pops up a dialog to ask for a directory to load into
# the listobx and (if the user presses OK) reloads the directory
# listbox from the directory named in the demo's entry.
#
# Arguments:
-# w - Name of the toplevel window of the demo.
-def selectAndLoadDir(w, lbox)
- dir = Tk.chooseDirectory(:initialdir=>$dirName, :parent=>w, :mustexist=>true)
+# w - Name of the toplevel window of the demo.
+def selectAndLoadDir3(w, lbox)
+ dir = Tk.chooseDirectory(:initialdir=>$dirName.value,
+ :parent=>w, :mustexist=>true)
if dir.length > 0
$dirName.value = dir
- loadDir(lbox)
+ loadDir3(lbox)
end
end
@@ -48,7 +51,7 @@ end
# label
-msg = TkLabel.new($image3_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -57,7 +60,7 @@ msg = TkLabel.new($image3_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($image3_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -75,7 +78,7 @@ TkFrame.new($image3_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# variable
-$dirName = TkVariable.new([$demo_dir,'images'].join(File::Separator))
+$dirName = TkVariable.new([$demo_dir,'..','images'].join(File::Separator))
# image
begin
@@ -85,37 +88,38 @@ end
$image3a = TkPhotoImage.new
#
-image3_f = TkFrame.new($image3_demo).pack(:fill=>:both, :expand=>true)
+image3_f = TkFrame.new(base_frame).pack(:fill=>:both, :expand=>true)
-image3_df = TkLabelFrame.new($image3_demo, :text=>'Directory:')
+image3_df = TkLabelFrame.new(base_frame, :text=>'Directory:')
-image3_ff = TkLabelFrame.new($image3_demo, :text=>'File:',
- :padx=>'2m', :pady=>'2m')
+image3_ff = TkLabelFrame.new(base_frame, :text=>'File:',
+ :padx=>'2m', :pady=>'2m')
image3_lbx = TkListbox.new(image3_ff, :width=>20, :height=>10) {
pack(:side=>:left, :fill=>:y, :expand=>true)
yscrollbar(TkScrollbar.new(image3_ff).pack(:side=>:left, :fill=>:y,
- :expand=>true))
+ :expand=>true))
insert(0, *(%w(earth.gif earthris.gif teapot.ppm)))
bind('Double-1', proc{|x,y| loadImage(self, x, y)}, '%x %y')
}
image3_ent = TkEntry.new(image3_df, :width=>30, :textvariable=>$dirName){
pack(:side=>:left, :fill=>:both, :padx=>'2m', :pady=>'2m', :expand=>true)
- bind('Return', proc{loadDir(image3_lbx)})
+ bind('Return', proc{loadDir3(image3_lbx)})
}
TkButton.new(image3_df, :pady=>0, :padx=>'2m', :text=>"Select Dir.",
- :command=>proc{selectAndLoadDir(image3_ent, image3_lbx)}) {
+ :command=>proc{selectAndLoadDir3(image3_ent, image3_lbx)}) {
pack(:side=>:left, :fill=>:y, :padx=>[0, '2m'], :pady=>'2m')
}
-image3_if = TkLabelFrame.new($image3_demo, :text=>'Image:') {|f|
- TkLabel.new(f, :image=>$image3a).pack(:padx=>'2m', :pady=>'2m')
+image3_if = TkLabelFrame.new(base_frame, :text=>'Image:') {|f|
+ # TkLabel.new(f, :image=>$image3a).pack(:padx=>'2m', :pady=>'2m')
+ Tk::Label.new(f, :image=>$image3a).pack(:padx=>'2m', :pady=>'2m')
}
Tk.grid(image3_df, '-',
- :sticky=>:ew, :padx=>'1m', :pady=>'1m', :in=>image3_f)
+ :sticky=>:ew, :padx=>'1m', :pady=>'1m', :in=>image3_f)
Tk.grid(image3_ff, image3_if,
- :sticky=>:nw, :padx=>'1m', :pady=>'1m', :in=>image3_f)
+ :sticky=>:nw, :padx=>'1m', :pady=>'1m', :in=>image3_f)
TkGrid.columnconfigure(image3_f, 1, :weight=>1)
diff --git a/ext/tk/sample/demos-en/images/earth.gif b/ext/tk/sample/demos-en/images/earth.gif
deleted file mode 100644
index 3ae4a9ce01..0000000000
--- a/ext/tk/sample/demos-en/images/earth.gif
+++ /dev/null
Binary files differ
diff --git a/ext/tk/sample/demos-en/images/earthris.gif b/ext/tk/sample/demos-en/images/earthris.gif
deleted file mode 100644
index 48f08c4421..0000000000
--- a/ext/tk/sample/demos-en/images/earthris.gif
+++ /dev/null
Binary files differ
diff --git a/ext/tk/sample/demos-en/images/tcllogo.gif b/ext/tk/sample/demos-en/images/tcllogo.gif
deleted file mode 100644
index 3fc7720b17..0000000000
--- a/ext/tk/sample/demos-en/images/tcllogo.gif
+++ /dev/null
Binary files differ
diff --git a/ext/tk/sample/demos-en/images/teapot.ppm b/ext/tk/sample/demos-en/images/teapot.ppm
deleted file mode 100644
index 78afefbf82..0000000000
--- a/ext/tk/sample/demos-en/images/teapot.ppm
+++ /dev/null
@@ -1,56 +0,0 @@
-P6
-256 256
-255
-\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[7 eOLjQLmSMoTMnSMlRMhPL_9 \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀnSMtVMzYN~[N~[N\N\O€\O€]O€]O€]O€]O€\O€\O}[NyYNtVM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-wXN}[N€]O„^O†_O†`O‡`Oˆ`Oˆ`OˆaO‰aO‰aO‰aO‰aO‰aO‰aOˆaOˆ`O†_Oƒ^O\N \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaMLyYN…_O‰aP‹bPcPŽcPŽdPŽdPdPdPdPdPdPdPdPeP‘eP’eP’eP‘ePdPcP…_OpUM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN…_OdP“fP•gQ–hQ˜hQ˜iQ™iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœjQœjQœjQ›jQœjQ™iQ“fP‡`O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJiQL‹bP—hQkQ¡mR¤nR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦pR¨pS©qSªqS«rS¬rS«rS©qS¤oRœjQ€]O\KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀfOLrUMcPŸlR©qS¯tS²uTµwT·xT¸xT¹yTºyT»zT»zU¼zU¼zU¼zU»zUºyT¸xT¶wT¯tS¡mR‰aOhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àa0 cNLqUM€\O”fQ¦pS²wVºzV¿|VÂ}VÄVÆVÇ€VÉ‚WÌ…[Õeæ w÷³‹êª…Ĉg§qT“fQ{ZNYIK9\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀO1{G#‘JkRMqUMtVN–iS¨v\·€d¹bµzZ±vU°uT®sSªqS¤nRœjQ’eP„^OrUMHh>!T4\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-V5wE"~I#†M%U+¥e7²l:°g2®b*­a(­`(©^(¥])¡^-›]1ŠS,qC$`9 R3G-\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@)J/i>!pA"tD"wF$yH&xH&tE$wE#yG%}M+ƒT4S5mE*Z7!K/B*;'\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‰aO¦oR½{UÇ€VÏ…X<(F-a: e<!h>!j@#k@$h>"d<!c=$hD-fF2[<)K0@);'5$Ë‚VÇ€V¿|U_LKYIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À…_O·xTÉ‚Wó«€ûµ‹Ö’k¼|X×>µf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&c<!b=%jH2_A/I0!<(8&5$”J¥Y’S%8&;'?)E,<:HA=HE?IJAISFJYIKXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À£nRÁ}UܘqÊŠe±vU²e,™V&¥V†C
-€@ |> y< u: r9 o7 l6
-j5
-h4
-g3
-5$D,K/b; h>"wM1tK.e="a<#cA,U8&E-<(9&.!a0 b1 c1    
-
-+3#@)46G<:HMCIXHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀU*´vT¿~X¸{YÃk+›W&‰N$|> u: p8 k5
-f3
-a0 _/ ]. [- I¡\*ª_(‘LkRMmSMmSMnSMnSMD,R3W5mA"|O0|P1j?"c<!a=%Y7"N1F,;'NCJNCJNDJODJODJODJh>!a: X/K%
-g3
-a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d<!yF#O+€N,rC#qB"pB#k?"a: Z7 6ODJPDJPEJQEJQEJREJREJREJRFJSFJSFJSFJSFJe<!X/
-^/ V+Q(L&I$r9  TlRMnSM46G47G47G46G46G46G46G46G36G36G25G25G15G04G/4F.3F
-ˆ`O~[NqUM[- ‰HUGJUGJVGJVGJVHJWHJWHJWHKWHKXHKXHKXHKXHKXHKXIKXIKXIKXIKXIKh>!Y0
-
-L&C!:4
-X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?<H@<HA=HC>HG@ILBIREJ[JKcNLjQL§pR±uTºzUÃ~VÈWË‚XÖŽcäsÒŽe¼{V²vT¨pSžkR•gQŒbP†_O‚^O]O€\O€\O€\O€\O€]O]O]O]O]O]O]O]O]O]O]O€\O€\O~\N}[N|ZNxXN•T%H$
-›W&rVMvWNyYNzYN|ZN}[N}[N><H?<H?<H?<H?<H?<H@<H@<H@<HA=HA=HB=HC>HE?IG@IIAIKBIODJSFJWHK—hQŸlR§pR°b(¾i*Én+Ù|7Û|6Ïr,Íq+Êp-Ãl+»g)±b(®sS§pS lRšiQ•gQePcPŠaPˆaO‡`O‡`O†_O†_O…_O…_O…_O…_O…_O…_O…_O„_O„^O„^Oƒ^Oƒ^O‚]O]O€\O~[N{ZN•T%
-
-
-
- 
-@%<-$G?@…pfdNLuWM\NdNL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJvWN‰aP./01„E}[N]O…_Oˆ`O‰aP‹bPŒbPcPcPŽcPdPdPdPeP‘eP’eP’eP“fP“fQ”fQ•gQ•gQ–gQ–hQ—hQ˜hQ™iQšiQ›jQœjQkQkRžlRŸlRžY&¤\'¨^'µ^½bÀcÃeÇi ÄgÀc½b¼a¹`µ^´]¯X¢[' Z'žY&¢mR¡mR¡mR lRŸlRŸlRžkRkQœkQœjQ›jQšjQšiQ™iQ™iQ˜iQ˜hQ—hQ—hQ—hQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘ePdPcP‰aP—O
- B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6
- 
-\À\À\À\À\À\À\À\À\À B B
-$5 ¬`(¶e)£nRœjQƒ^OJAI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXIK^KKdNLhPLuWM‚]OŒbP”fQeP
-m6
-†`OŽcP“fQ—hQ˜hQ™iQšiQšjQ›jQ›jQ›jQœjQœjQœjQœkQkQkQkRžkRžkRžkRžlRŸlRŸlRŸlR lR lR lR¡mR¡mR¡mR¡mRºg)³c(²c(±b(­V¿cÂeÅi!Åi!Àd¼bº`¹`·_·_¶^¢Q§]'ª_(­`(¹f)£nR£nR£nR£nR£nR£nR£nR¢nR¢nR¢nR¢nR¢nR¢nR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR¢mR¢mR£nR¢mR¢mR¡mR mRkR—hQˆGa0 ŠbP mRœjQ“fQ‰aP}[NrUMmSM…L$\À\À\À\À\À\À\À\À B B
-#C, 8&H.Z7 §pR›jQ{ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJ[JK`LKdNLhQLqUM{ZN…_OŽcP–gQ—hQ
-‹bP‘eP–hQšiQ›jQœjQkQkQkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlR lR lR lR mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢nR£nRÀj*ºg)·e)¶d)Âd°XÅgÅhÂe¿c½b½b¾bªU­`(®a(¯a(³c(¾i*¤oR¤oR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¥oR¥oR¤nR¡mR›jQŽQ%Z- œjQ£nRŸlR—hQŽdP…_OuWMpTMnSMkRLa: \À\À\À\À\À\À\À B B&D2
-@*S6#G@IPDJ˜hQmSM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ]KKbMLeOLiQLlRMvWN\OˆaO‘eP—hQœjQ•gQ
-\À\À\À\À\À B'D+E$(1 J/jH1NCJUGJYIKUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK]KKbNLfOLiQLkRMmSMoTMqUMxXN\N†_OŒbP’fP˜hQkQ¡mR¥oR§pS¦pR˜hQ¢mR¥oR¨pSªqS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rSªrSªrSªrS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬rS¬rS¬rS¬rS¬sS¬sS­sS­sS­sS­sS­sS­sS®sS®sS®sS®sS®tS¯tS°tS°uS±uS±uT±uT²uT²uT²uT´vTµwT´vT³vT²uT¯tS¢mR¯tS±uT±uS®tS«rS§pR¢mRkQ—hQ‘ePŠaPƒ^O\N{ZNvXNqUMpTMnSMlRMP%\À\À\À\À B#C*E$.E- .!G$Y:%d<"SFJYIKZIKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀPDJZIK_LKdNLgPLjQLlRMnSMpTMqUMuWMyYN€\O†`OcP’fP—hQœjQ¡mR¥oR¨qS«rS«rSªrS mR
-!C+E'0F.4F7%8%U/lG.SFJZIK]KKZIKB=H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀREJZJK`LKdNLgPLjQLlRMnSMpTMqUMtWMxXN{ZN~[N]O„^O†`O‰aO‹bPdP•gQ™iQœkQ lR¤nR§pSªrS­sS¯tT²uT´vT¶wT·xT¹yT¹yTºyTºyT¹yT¶xT´vT¬rS¢nR—hQ¿|U¿|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ}UÀ}UÁ}UÁ}UÁ}UÁ}UÂ}UÂ~UÃ~UÃ~VÃ~VÄVÅ€WÆX®a(ŸlRªrS´vT¸yT¼zU¾|UÁ~VÃXÆ‚[Ɇ_΋dÓ‘jÔ“mÔ“nБlÊŒhĆd½_¶{[°vWªsU¦pS¢nRžkRšiQ˜hQ•gQ“fQ‘ePdPŒbP‰aO†_Oƒ^O€\O|ZNxXNsVMpTMnTMmSMjQL€C B)D&/F-3F47G6%>" Y7 kA$YIK]KK^KKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\KKbMLeOLhPLkRLmSMnTMpTMrUMuWNyYN|ZN\N‚]O„_O‡`OŠaPŒbPŽcPeP“fP—hQ›jQžlR¢nR¥oS©qT¬sT¯uU²vU´wV¶xV¸yV¹yUºzU»zU¼{U½{U¾{U¾|U¿|U¿|U¿|U¿|U¾{U½{U¼{U¼zU»zTºyT¹yT¸xTµwT³vT´vT´vT´vT´wT´wTµwT·xT¹yTºzT¼zU½{U¾{U¿|UÀ|UÂ}UÄVÅ€WÇ‚YÉ„\͈_ÑŒdÙ”láuç£|쩂ſt명æ¦ÞŸ{Õ—sËŽl†d¹^³yZ­uW¨qU¤oSŸlRžkRœjQšiQ˜hQ–gQ”fQ‘ePdPcPŠaP‡`O„^O]O}[NyYNuWMpTMoTMmSMkRLgPL&D#.E,3F46G;'<(D"iB(VGJ]KK`LK[JKB>H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRMmSMoTMqUMsVMvXNzYN}[N€\O‚^O…_Oˆ`OŠaPŒcPdP‘eP“fQ•gQ—hQ™iQkR mS¤oT¨rU¬tW°wY´zZ¸}\»]¾€^À^Á‚^‚^Â\Á€ZÁYÁXÁ~WÁ~WÂ~VÂ~VÂ~VÃ~VÃ~UÃ~UÄ~UÄ~UÄUÄUÅVÅVÅVÅVÆVÆ€VÆ€VÇ€WÇWÈ‚XɃZË…[͇^ЊaÓdØ’iÜ—nâtè£zî©ó¯‡ø´û¸‘üº“û¹“÷¶ñ±Œé©…à¡~Ö˜vËmÇf»€`´z[®vX©rU¥pT£oS¢nS lRžkRœkRšjQ˜iQ–hQ”fQ’ePdPcP‹bPˆ`O…_O‚]O~[NzYNvWNpTMoTMnSMkRMhQLo7 ,2F36G99HC+@ ]8 nA"\JK`ML_LKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_OˆaO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRžlR mS£oU§rW¬vZ²{]¹€a¿…fÅŠjËnГqÓ•sÕ–sÕ–rÕ–qÕ”oÓ’mÑjÏgÍŠcˈaɆ^È„\Ç‚[ÆYÅ€XÅ€WÅWÅWÅVÅVÅWÅ€WÆ€WÇXÈ‚YɃ[Ê…\͇_ÏŠaÒeÕ‘hÙ•mÝ™qávä¡zç¤}꧀멃몄騃奀ߠ|Ù›wÓ•rÌmƉh¿„c¸~^²yZ®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRœkR›jQ™iQ—hQ•gQ“fPePŽcP‹bPˆaO…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQL~I#26G99G?<HA*E$ i@$ZIKaMLbML[JK;:H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ]KKbMLeOLhPLjRLlSMnTMpTMrUMuWMxXN{ZN~\N]O„^O†`O‰aO‹bPŽcPdP’eP”fQ–gQ˜hQšiQœkRžlS mT£oU¦rWªuZ¯y]´~aºƒfŠlË’sÔšzÜ¡€ã§†è«‰ë®‹í¯Œí®‹ë¬ˆè¨„ã£~ßžyÚ™tÖ•oÒjÎŒfˈbÈ…_ƃ\ÅZÄ€YÃXÂWÂ~WÂ~WÂ~WÃXÀXÄ€YÅZƃ\Ç…^Ɇ`ˈbÌŠdÍ‹fÎgÎŽiÎŽjÎŽjÍŽjËŒiljgÆd¿ƒaº^¸}]¶|\´{[²yZ°xY®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRkR›jQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aO†_Oƒ^O€\O|ZNxXNtVMpTMnSMmSMjQLgPL99G?<HG-E&b;!YIK`MLdOM`LKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlRºyTÄ~UÊ‚XʃYÄXº{W­tUšW'¢[(—hQ lRcP€\OhQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRLmSMoTMqUMrVMvWNyYN|ZN\N‚]O„_O‡`O‰aPŒbPŽcPdP’fP”gQ–hQ˜iQšjRœkRžlS¡nT¤pU§sW«vZ°z]µb»„gŠlÉ‘sИyØžÞ¤…㩊è­ì±ï³‘ﳑ뭊穅⣀ݞzؘtÒ“nÎiɉdÆ…`Â]Á€[¿~Y¾}X½|W½|V¼{V¼{V¼{V¼{V¼{V¼|W¼|W½}X½}Y½~Z½~Z¼~Z»}[º}[º}[º~\º~\º~]º~]¹~]¸~]·}]¶|\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS mRŸlRkR›jQšiQ˜hQ–gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O}[NyYNuWNpTMnTMmSMkRLhPL|H$D>IQ2P+XHK_LLfQOcNLXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À©qSºyTÃ~VΈ`遲ޜv¾€]ªqS–LŽG|> g3
-S)?*%.—hQ—hQ‘eP‡`OuWM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMoTMqUMsVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽdP‘eP“fP•gQ—hQ˜iQšjRœkRŸlS¡nT¤pV§sX«vZ°z^¶b¼…gËmÊ’sјzØŸ€Þ¤…㩊è­ê¯ë°ê¯Žè¬‹å¨‡à¤‚Ûž|Ö™wÑ“qÌŽlljgÃ…bÀ‚_½\»}Zº{X¹zW¸yV·yU·xU·xU·xT·xT·xU·xU·xU·yV·yV·yW¸zW¸{X¹{Y¹|Zº}[º}[º}\º~\¹~]¹~]¸}]·|\µ{\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS¡mRŸlRkRœjQšiQ˜hQ–gQ”fQ’ePdPcPŠbP‡`O…_O‚]O~[NzZNvWNrUMoTMmSMlRMiQLeOLJAIJ(h>!]KKfQOgQN_LKD>I\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À™iQ°tS¸yT¼{UÂYÎŒeï­ˆô´Õ—u¶|\ Z'™LˆD
-|>
-
-+,!.! "`E6†iYŒlZo\“q]•s^^J™va›wbycŸzd {e¤}foTMqUMsVMuWNwXNyYN{ZN|ZN~[N\O]O‚]Oƒ^O…_O†_O‡`Oˆ`O‰aOŠaP‹bPŒbPŒcPcPŽcPŽdPdPdPdPeP‘eP‘eP‘eP’eP’eP’eP’eP’fP’fP’fP“fP’fP’fP’fP’eP’eP’eP‘eP‘eP‘ePePdPdPdPŽdPŽcPcPŒcPŒbP‹bPŠaP‰aOˆ`O‡`O†_O…_Oƒ^O‚]O]O\O~[N|[N{ZNyYNwXN®ƒi¬ƒiª‚i¨i¦€hŒhR‰fQ†dQ‚bP•wfx]Oˆpdkbtd_m`]OEDG?A;:@.S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTx«Tx«Tx«Ty«/S†GlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ£Ö£Ö£Ö£Ö¤Ö¤Ö¤Ö¤Ö¤ÖEi›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×€¥×€¥×€¥×Bg™Bg™Bg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Af˜Af˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|
-+,YA5jPBpSD‹l[o]’q^–t`‚_Kšwbœycžze {f¡}g¤h¨i”lSrVMtWMvWNxXNyYN{ZN|[N~[N\O]O‚]Oƒ^O„_O…_O†`O‡`Oˆ`O‰aPŠaP‹bP‹bPŒbPcPcPŽcPŽcPdPdPdPdPdPdPdPdPePePePePePdPdPdPdPdPdPdPŽcPŽcPcPcPŒbP‹bP‹bPŠaP‰aOˆ`O‡`O†`O…_O„^Oƒ^O‚]O€]O\O~[N|[N{ZNyYNxXN°…j®„j¬„jªƒj¨‚j¦€jŒhSŠgS†eRƒcR|`QŒsf…oe}jcrd`k_]LCDC=@,,3(4F(4F.S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžChšChš¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|#5H71O;3V?4iOBoSDsVFo]{[I^Kƒ`L…bN‡dOŸ{f }g¢~h¥€j’kT•mU˜oVšqWrWwXNxXNzYN{ZN}[N~[N\O€]O‚]Oƒ^O„^O…_O…_O†`O‡`Oˆ`O‰aO‰aPŠaP‹bP‹bPŒbPŒbPŒcPcPcPcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPcPcPcPŒcPŒbP‹bP‹bP‹bPŠaP‰aP‰aOˆ`O‡`O†_O…_O„_O„^Oƒ^O]O€\O\N~[N|ZN{ZNyYN›oTšoT™oT—nT¬„lªƒl¨‚ljUŒiTŠhT†fT€cSvi‰rgnfyidqdah^^HBD?<@)+3OZkMYk(5F(5F(5F/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Ty«Uy«†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžDhšDhšDhšChš&K}&K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|A99N?;L:2T>4gNBlRD‡k\‹n^z[J~^LaN…cO‡dP‰fQŠgRŒhTjU’lV•nW˜pXšrXsY¶‹q¸qºŽr¼r½r¿s©z[©z[ªz[«{[¬{[¬{ZÅ“rÅ’qÅ’qÅ’pÅ’pÅ‘o­yV­xV¬xU¬wT¬wTŠaPŠbP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bPŠaPŠaPŠaP‰aP‰aOˆaOˆ`O‡`O‡`O†_O…_O„^Oƒ^O‚^O‚]O]O€\O~\N}[N|ZNzYNpTœpU›pUšpU˜oV—oV•nV“mV‘lVkVŒjVˆhVƒfU~cUuj†qh~mfugdkaad\^E@D98?$(2minffm^blV^lMYk(5F(5F/S…TxªTxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Uy«Uy«†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}ChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|Ae˜Ae˜;GY<68I=:I82Q=4XA6~fZ„j\‰m^p`|]L€`NƒcP†eQˆgS¡j£€l¦‚m©„n•oX˜qYšrZt[¶Œr¸sºs¼t½t¾‘t¨z]©{]ª{]«{\«{\¬{\¬{[Ä“sÄ“rÄ’rÄ’qÄ’pÄ‘p¬yWÄoÃnÃmÃlÂŽlÂŽkÁkˆaOˆaOˆaOˆaOˆaOˆaOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O…_O„_O„^Oƒ^O‚]O]O€]O\O~\N}[N|ZN¶‰l¶‰lµˆmœqV›qVšqV™pW˜pW–oW¬…nª…n§„n¤‚nŸ€n›~n€eW‘xlŠtk‚piykfodcf_`JDG@>C*,5$1MYktr~tstmolinadmX_lNZkMZkTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«ÝHlŸHlŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™&J}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Af˜Af˜Af˜Af˜;GY;GY;GY1'!D:9N?;N;3]I?zdY€h[†l^‹oasc“ue€bQ„dR‡fT l¢m¦ƒn©…o«‡p®ˆq±Šr³‹sžv] w]¹u»u¼‘u¾‘u¿’v¨{^©{^ª|^«|]«|]«{\¬{\¬{[¬{[¬zZ«zZ«yY«yX«xXÂoÂnÂnÁŽmÁŽm¨uT¨uS§tS§tS§tR¦sR¦sQ…_O…_O…_O„^O„^Oƒ^Oƒ^O‚^O‚]O]O€]O¢rS¡rS¡rS¸‰k·‰l·‰l¶‰m¶‰mµ‰m´‰n³‰n›qWšqX™qX®‡o­‡o«†p¨…p¤ƒp pœp—}o{cXv`Vp]U}nishfhaba\_DAF::B$)4
-., 7(8'A1&F4(L8*oXIw]Jpdasfcvhexkg{mi~oj€qll\Xn^Yp`Zpa[qa\rb]rc^sc^sd_ue`wf`xgayhayhayhbxy‘y‘y‘y‘yy~ywgbvfateasd`qd`pc`nb_la_€ut|ssxqrunpZUXVRWROUMMSHIRIC@967-/3'+0(*-ACF?AD;=@#%(
-.+>1(B3)B2&F4'E4)gTGlXJs^OzcTzaPqfethgvjhbVTcWUdXVeYWfZXg[Yh\Zi]Zi][j^\€us€ususts~tt~tt}tt|st{stut~tt|sszrsyqrwpquoqsmpqloXTXTQWPOULLSSJEA<:=99757335./2113)+.'),)+.8:="(
-"6*#5*">2)>0&A2'C3(I8-^OFbRHfUJjXMq^RwcVzfYfRDfQCdN@zdTqijrjksklrklrklrklqjmpjmpjmojmojmnimmimkhliflscYm`Xg\VbYT^VRE>;A<:>98:77645:873220/0,-/)+.*,/#%( &
-
-&3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!'
-
- %' %$#" ! !$
-
-
- 
-
-
-*  
-  ;?E7CU;HY=I[ 
diff --git a/ext/tk/sample/demos-en/items.rb b/ext/tk/sample/demos-en/items.rb
index 8447430694..3fd44fd4f4 100644
--- a/ext/tk/sample/demos-en/items.rb
+++ b/ext/tk/sample/demos-en/items.rb
@@ -19,8 +19,10 @@ $items_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($items_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($items_demo) {
+TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -28,7 +30,7 @@ TkLabel.new($items_demo) {
}.pack('side'=>'top')
# frame
-TkFrame.new($items_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -46,7 +48,7 @@ TkFrame.new($items_demo) {|frame|
# frame
cvs = nil
-TkFrame.new($items_demo) {|cf|
+TkFrame.new(base_frame) {|cf|
# canvas
cvs = TkCanvas.new(cf) {|c|
focus
@@ -74,11 +76,11 @@ TkFrame.new($items_demo) {|cf|
else
c.grid('in'=>cf, 'row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
vs.grid('row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
hs.grid('row'=>1, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
TkGrid.rowconfigure(cf, 0, 'weight'=>1, 'minsize'=>0)
TkGrid.columnconfigure(cf, 0, 'weight'=>1, 'minsize'=>0)
@@ -94,8 +96,13 @@ TkcLine.new(cvs, '0c', '16c', '30c', '16c', 'width'=>2)
TkcLine.new(cvs, '10c', '0c', '10c', '24c', 'width'=>2)
TkcLine.new(cvs, '20c', '0c', '20c', '24c', 'width'=>2)
-font1 = '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
-font2 = '-Adobe-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*'
+if $tk_version =~ /^4.*/
+ font1 = '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
+ font2 = '-Adobe-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*'
+else
+ font1 = 'Helvetica 12'
+ font2 = 'Helvetica 24 bold'
+end
if TkWinfo.depth($root).to_i > 1
blue = 'DeepSkyBlue3'
red = 'red'
@@ -114,129 +121,129 @@ $tag_item = TkcGroup.new(cvs)
# Set up demos within each of the areas of the grid.
TkcText.new(cvs, '5c', '.2c', 'text'=>'Lines', 'anchor'=>'n')
TkcLine.new(cvs, '1c', '1c', '3c', '1c', '1c', '4c', '3c', '4c',
- 'width'=>2, 'fill'=>blue, 'capstyle'=>'butt',
- 'join'=>'miter', 'tags'=>$tag_item )
+ 'width'=>2, 'fill'=>blue, 'capstyle'=>'butt',
+ 'join'=>'miter', 'tags'=>$tag_item )
TkcLine.new(cvs, '4.67c','1c','4.67c','4c', 'arrow'=>'last', 'tags'=>$tag_item)
TkcLine.new(cvs, '6.33c','1c','6.33c','4c', 'arrow'=>'both', 'tags'=>$tag_item)
TkcLine.new(cvs, '5c','6c','9c','6c','9c','1c','8c','1c','8c','4.8c','8.8c',
- '4.8c','8.8c','1.2c','8.2c','1.2c','8.2c','4.6c','8.6c','4.6c',
- '8.6c','1.4c','8.4c','1.4c','8.4c','4.4c',
- 'width'=>3, 'fill'=>red, 'tags'=>$tag_item )
+ '4.8c','8.8c','1.2c','8.2c','1.2c','8.2c','4.6c','8.6c','4.6c',
+ '8.6c','1.4c','8.4c','1.4c','8.4c','4.4c',
+ 'width'=>3, 'fill'=>red, 'tags'=>$tag_item )
TkcLine.new(cvs, '1c','5c','7c','5c','7c','7c','9c','7c', 'width'=>'.5c',
- 'stipple'=>'@'+[$demo_dir,
- 'images','gray25.xbm'].join(File::Separator),
- 'arrow'=>'both', 'arrowshape'=>'15 15 7', 'tags'=>$tag_item )
+ 'stipple'=>'@'+[$demo_dir,'..',
+ 'images','gray25.xbm'].join(File::Separator),
+ 'arrow'=>'both', 'arrowshape'=>'15 15 7', 'tags'=>$tag_item )
TkcLine.new(cvs, '1c','7c','1.75c','5.8c','2.5c','7c','3.25c','5.8c','4c','7c',
- 'width'=>'.5c', 'capstyle'=>'round', 'join'=>'round',
- 'tags'=>$tag_item )
+ 'width'=>'.5c', 'capstyle'=>'round', 'join'=>'round',
+ 'tags'=>$tag_item )
TkcText.new(cvs, '15c', '.2c',
- 'text'=>'Curves (smoothed lines)', 'anchor'=>'n')
+ 'text'=>'Curves (smoothed lines)', 'anchor'=>'n')
TkcLine.new(cvs, '11c','4c','11.5c','1c','13.5c','1c','14c','4c',
- 'smooth'=>'on', 'fill'=>blue, 'tags'=>$tag_item )
+ 'smooth'=>'on', 'fill'=>blue, 'tags'=>$tag_item )
TkcLine.new(cvs, '15.5c','1c','19.5c','1.5c','15.5c','4.5c','19.5c','4c',
- 'smooth'=>'on', 'arrow'=>'both', 'width'=>3, 'tags'=>$tag_item )
+ 'smooth'=>'on', 'arrow'=>'both', 'width'=>3, 'tags'=>$tag_item )
TkcLine.new(cvs, '12c','6c','13.5c','4.5c','16.5c','7.5c','18c','6c',
- '16.5c','4.5c','13.5c','7.5c','12c','6c',
- 'smooth'=>'on', 'width'=>'3m', 'capstyle'=>'round',
- 'stipple'=>'@'+[$demo_dir,
- 'images', 'gray25.xbm'].join(File::Separator),
- 'fill'=>red, 'tags'=>$tag_item )
+ '16.5c','4.5c','13.5c','7.5c','12c','6c',
+ 'smooth'=>'on', 'width'=>'3m', 'capstyle'=>'round',
+ 'stipple'=>'@'+[$demo_dir, '..',
+ 'images', 'gray25.xbm'].join(File::Separator),
+ 'fill'=>red, 'tags'=>$tag_item )
TkcText.new(cvs, '25c', '.2c', 'text'=>'Polygons', 'anchor'=>'n')
TkcPolygon.new(cvs, '21c','1.0c','22.5c','1.75c','24c','1.0c','23.25c','2.5c',
- '24c','4.0c','22.5c','3.25c','21c','4.0c','21.75c','2.5c',
- 'fill'=>'green', 'outline'=>'black', 'width'=>4,
- 'tags'=>$tag_item )
+ '24c','4.0c','22.5c','3.25c','21c','4.0c','21.75c','2.5c',
+ 'fill'=>'green', 'outline'=>'black', 'width'=>4,
+ 'tags'=>$tag_item )
TkcPolygon.new(cvs, '25c','4c','25c','4c','25c','1c','26c','1c','27c','4c',
- '28c','1c','29c','1c','29c','4c','29c','4c',
- 'fill'=>red, 'smooth'=>'on', 'tags'=> $tag_item)
+ '28c','1c','29c','1c','29c','4c','29c','4c',
+ 'fill'=>red, 'smooth'=>'on', 'tags'=> $tag_item)
TkcPolygon.new(cvs, '22c','4.5c','25c','4.5c','25c','6.75c','28c','6.75c',
- '28c','5.25c','24c','5.25c','24c','6.0c','26c','6c','26c',
- '7.5c','22c','7.5c',
- 'stipple'=>'@' + [$demo_dir,
+ '28c','5.25c','24c','5.25c','24c','6.0c','26c','6c','26c',
+ '7.5c','22c','7.5c',
+ 'stipple'=>'@' + [$demo_dir, '..',
'images', 'gray25.xbm'].join(File::Separator),
- 'outline'=>'black', 'tags'=>$tag_item )
+ 'outline'=>'black', 'tags'=>$tag_item )
TkcText.new(cvs, '5c', '8.2c', 'text'=>'Rectangles', 'anchor'=>'n')
TkcRectangle.new(cvs, '1c','9.5c','4c','12.5c',
- 'outline'=>red, 'width'=>'3m', 'tags'=>$tag_item)
+ 'outline'=>red, 'width'=>'3m', 'tags'=>$tag_item)
TkcRectangle.new(cvs, '0.5c','13.5c','4.5c','15.5c',
- 'fill'=>green, 'tags'=>$tag_item )
+ 'fill'=>green, 'tags'=>$tag_item )
TkcRectangle.new(cvs, '6c','10c','9c','15c', 'outline'=>'',
- 'stipple'=>'@'+[$demo_dir,
- 'images','gray25.xbm'].join(File::Separator),
- 'fill'=>blue, 'tags'=>$tag_item )
+ 'stipple'=>'@'+[$demo_dir,'..',
+ 'images','gray25.xbm'].join(File::Separator),
+ 'fill'=>blue, 'tags'=>$tag_item )
TkcText.new(cvs, '15c', '8.2c', 'text'=>'Ovals', 'anchor'=>'n')
TkcOval.new(cvs, '11c','9.5c','14c','12.5c',
- 'outline'=>red, 'width'=>'3m', 'tags'=>$tag_item)
+ 'outline'=>red, 'width'=>'3m', 'tags'=>$tag_item)
TkcOval.new(cvs, '10.5c','13.5c','14.5c','15.5c',
- 'fill'=>green, 'tags'=>$tag_item )
+ 'fill'=>green, 'tags'=>$tag_item )
TkcOval.new(cvs, '16c','10c','19c','15c', 'outline'=>'',
- 'stipple'=>'@'+[$demo_dir,
- 'images','gray25.xbm'].join(File::Separator),
- 'fill'=>blue, 'tags'=>$tag_item )
+ 'stipple'=>'@'+[$demo_dir,'..',
+ 'images','gray25.xbm'].join(File::Separator),
+ 'fill'=>blue, 'tags'=>$tag_item )
TkcText.new(cvs, '25c', '8.2c', 'text'=>'Text', 'anchor'=>'n')
TkcRectangle.new(cvs, '22.4c','8.9c','22.6c','9.1c')
TkcText.new(cvs, '22.5c', '9c', 'anchor'=>'n', 'font'=>font1, 'width'=>'4c',
- 'text'=>'A short string of text, word-wrapped, justified left, and anchored north (at the top). The rectangles show the anchor points for each piece of text.', 'tags'=>$tag_item )
+ 'text'=>'A short string of text, word-wrapped, justified left, and anchored north (at the top). The rectangles show the anchor points for each piece of text.', 'tags'=>$tag_item )
TkcRectangle.new(cvs, '25.4c','10.9c','25.6c','11.1c')
TkcText.new(cvs, '25.5c', '11c', 'anchor'=>'w', 'font'=>font1, 'fill'=>blue,
- 'text'=>'Several lines,\n each centered\nindividually,\nand all anchored\nat the left edge.', 'justify'=>'center', 'tags'=>$tag_item )
+ 'text'=>"Several lines,\n each centered\nindividually,\nand all anchored\nat the left edge.", 'justify'=>'center', 'tags'=>$tag_item )
TkcRectangle.new(cvs, '24.9c','13.9c','25.1c','14.1c')
if $tk_version =~ /^4\.[01]/
TkcText.new(cvs, '25c', '14c', 'anchor'=>'c', 'font'=>font2, 'fill'=>red,
- 'stipple'=>'@' + [$demo_dir,
+ 'stipple'=>'@' + [$demo_dir, '..',
'images', 'grey.5'].join(File::Separator),
- 'text'=>'Stippled characters', 'tags'=>$tag_item )
+ 'text'=>'Stippled characters', 'tags'=>$tag_item )
else
TkcText.new(cvs, '25c', '14c', 'anchor'=>'c', 'font'=>font2, 'fill'=>red,
- 'stipple'=>'gray50', 'text'=>'Stippled characters',
- 'tags'=>$tag_item )
+ 'stipple'=>'gray50', 'text'=>'Stippled characters',
+ 'tags'=>$tag_item )
end
TkcText.new(cvs, '5c', '16.2c', 'text'=>'Arcs', 'anchor'=>'n')
TkcArc.new(cvs, '0.5c','17c','7c','20c', 'fill'=>green, 'outline'=>'black',
- 'start'=>45, 'extent'=>270, 'style'=>'pieslice', 'tags'=>$tag_item)
+ 'start'=>45, 'extent'=>270, 'style'=>'pieslice', 'tags'=>$tag_item)
#TkcArc.new(cvs, '6.5c','17c','9.5c','20c', 'width'=>'4m', 'style'=>'arc',
-# 'outline'=>blue, 'start'=>135, 'extent'=>270,
-# 'outlinestipple'=>'@' + ['images', 'grey.25'].join(File::Separator),
-# 'tags'=>$tag_item)
+# 'outline'=>blue, 'start'=>135, 'extent'=>270,
+# 'outlinestipple'=>'@' + ['images', 'grey.25'].join(File::Separator),
+# 'tags'=>$tag_item)
TkcArc.new(cvs, '6.5c','17c','9.5c','20c', 'width'=>'4m', 'style'=>'arc',
- 'outline'=>blue, 'start'=>135, 'extent'=>270,
- 'outlinestipple'=>'@'+[$demo_dir,
+ 'outline'=>blue, 'start'=>135, 'extent'=>270,
+ 'outlinestipple'=>'@'+[$demo_dir, '..',
'images','gray25.xbm'].join(File::Separator),
- 'tags'=>$tag_item)
+ 'tags'=>$tag_item)
TkcArc.new(cvs, '0.5c','20c','9.5c','24c', 'width'=>'4m', 'style'=>'pieslice',
- 'fill'=>'', 'outline'=>red, 'start'=>225, 'extent'=>90,
- 'tags'=>$tag_item)
+ 'fill'=>'', 'outline'=>red, 'start'=>225, 'extent'=>90,
+ 'tags'=>$tag_item)
TkcArc.new(cvs, '5.5c','20.5c','9.5c','23.5c', 'width'=>'4m', 'style'=>'chord',
- 'fill'=>blue, 'outline'=>'', 'start'=>45, 'extent'=>270,
- 'tags'=>$tag_item)
+ 'fill'=>blue, 'outline'=>'', 'start'=>45, 'extent'=>270,
+ 'tags'=>$tag_item)
TkcText.new(cvs, '15c', '16.2c', 'text'=>'Bitmaps', 'anchor'=>'n')
#TkcBitmap.new(cvs, '13c','20c',
-# 'bitmap'=>'@' + ['images', 'face'].join(File::Separator),
-# 'tags'=>$tag_item)
+# 'bitmap'=>'@' + ['images', 'face'].join(File::Separator),
+# 'tags'=>$tag_item)
TkcBitmap.new(cvs, '13c','20c',
- 'bitmap'=>'@' + [$demo_dir,
+ 'bitmap'=>'@' + [$demo_dir, '..',
'images', 'face.xbm'].join(File::Separator),
- 'tags'=>$tag_item)
+ 'tags'=>$tag_item)
#TkcBitmap.new(cvs, '17c','18.5c',
-# 'bitmap'=>'@' + ['images', 'noletters'].join(File::Separator),
-# 'tags'=>$tag_item)
+# 'bitmap'=>'@' + ['images', 'noletters'].join(File::Separator),
+# 'tags'=>$tag_item)
TkcBitmap.new(cvs, '17c','18.5c',
- 'bitmap'=>'@' + [$demo_dir,
- 'images', 'noletter.xbm'].join(File::Separator),
- 'tags'=>$tag_item)
+ 'bitmap'=>'@' + [$demo_dir, '..',
+ 'images', 'noletter.xbm'].join(File::Separator),
+ 'tags'=>$tag_item)
#TkcBitmap.new(cvs, '17c','21.5c',
-# 'bitmap'=>'@' + ['images', 'letters'].join(File::Separator),
-# 'tags'=>$tag_item)
+# 'bitmap'=>'@' + ['images', 'letters'].join(File::Separator),
+# 'tags'=>$tag_item)
#
TkcBitmap.new(cvs, '17c','21.5c') {
- bitmap '@' + [$demo_dir, 'images', 'letters.xbm'].join(File::Separator)
+ bitmap '@' + [$demo_dir, '..', 'images', 'letters.xbm'].join(File::Separator)
tags $tag_item
}
#TkcBitmap.new(cvs, '17c','21.5c') {
@@ -249,17 +256,17 @@ TkButton.new(cvs) {|b|
text 'Press Me'
command proc{butPress cvs, red}
TkcWindow.new(cvs, '21c','18c',
- 'window'=>b, 'anchor'=>'nw', 'tags'=>$tag_item)
+ 'window'=>b, 'anchor'=>'nw', 'tags'=>$tag_item)
}
TkEntry.new(cvs, 'width'=>20, 'relief'=>'sunken') {|e|
insert 'end', 'Edit this text'
TkcWindow.new(cvs, '21c','21c',
- 'window'=>e, 'anchor'=>'nw', 'tags'=>$tag_item)
+ 'window'=>e, 'anchor'=>'nw', 'tags'=>$tag_item)
}
TkScale.new(cvs, 'from'=>0, 'to'=>100, 'length'=>'6c', 'sliderlength'=>'.4c',
- 'width'=>'.5c', 'tickinterval'=>0 ) {|scl|
+ 'width'=>'.5c', 'tickinterval'=>0 ) {|scl|
TkcWindow.new(cvs, '28.5c','17.5c',
- 'window'=>scl, 'anchor'=>'n', 'tags'=>$tag_item)
+ 'window'=>scl, 'anchor'=>'n', 'tags'=>$tag_item)
}
TkcText.new(cvs, '21c', '17.9c', 'text'=>'Button:', 'anchor'=>'sw')
TkcText.new(cvs, '21c', '20.9c', 'text'=>'Entry:', 'anchor'=>'sw')
@@ -324,7 +331,7 @@ def itemStroke(c,x,y)
if $areaX1 != x && $areaY1 != y
c.delete 'area'
c.addtag_withtag 'area', TkcRectangle.new(c, $areaX1, $areaY1, x, y,
- '-outline', 'black')
+ '-outline', 'black')
$areaX2 = x
$areaY2 = y
end
@@ -369,6 +376,6 @@ end
def butPress(w,color)
i = TkcText.new(w, '25c', '18.1c',
- 'text'=>'Ouch!!', 'fill'=>color, 'anchor'=>'n')
+ 'text'=>'Ouch!!', 'fill'=>color, 'anchor'=>'n')
Tk.after(500, proc{w.delete i})
end
diff --git a/ext/tk/sample/demos-en/knightstour.rb b/ext/tk/sample/demos-en/knightstour.rb
new file mode 100644
index 0000000000..618fce5f02
--- /dev/null
+++ b/ext/tk/sample/demos-en/knightstour.rb
@@ -0,0 +1,271 @@
+# Based on the widget demo of Tcl/Tk8.5.2
+# The following is the original copyright text.
+#----------------------------------------------------------------------------
+# Copyright (C) 2008 Pat Thoyts <patthoyts@users.sourceforge.net>
+#
+# Calculate a Knight's tour of a chessboard.
+#
+# This uses Warnsdorff's rule to calculate the next square each
+# time. This specifies that the next square should be the one that
+# has the least number of available moves.
+#
+# Using this rule it is possible to get to a position where
+# there are no squares available to move into. In this implementation
+# this occurs when the starting square is d6.
+#
+# To solve this fault an enhancement to the rule is that if we
+# have a choice of squares with an equal score, we should choose
+# the one nearest the edge of the board.
+#
+# If the call to the Edgemost function is commented out you can see
+# this occur.
+#
+# You can drag the knight to a specific square to start if you wish.
+# If you let it repeat then it will choose random start positions
+# for each new tour.
+#----------------------------------------------------------------------------
+require 'tk'
+
+class Knights_Tour
+ # Return a list of accessible squares from a given square
+ def valid_moves(square)
+ moves = []
+ [
+ [-1,-2], [-2,-1], [-2,1], [-1,2], [1,2], [2,1], [2,-1], [1,-2]
+ ].each{|col_delta, row_delta|
+ col = (square % 8) + col_delta
+ row = (square.div(8)) + row_delta
+ moves << (row * 8 + col) if row > -1 && row < 8 && col > -1 && col < 8
+ }
+ moves
+ end
+
+ # Return the number of available moves for this square
+ def check_square(square)
+ valid_moves(square).find_all{|pos| ! @visited.include?(pos)}.length
+ end
+
+ # Select the next square to move to. Returns -1 if there are no available
+ # squares remaining that we can move to.
+ def next_square(square)
+ minimum = 9
+ nxt = -1
+ valid_moves(square).each{|pos|
+ unless @visited.include?(pos)
+ cnt = check_square(pos)
+ if cnt < minimum
+ minimum = cnt
+ nxt = pos
+ elsif cnt == minimum
+ nxt = edgemost(nxt, pos)
+ end
+ end
+ }
+ nxt
+ end
+
+ # Select the square nearest the edge of the board
+ def edgemost(nxt, pos)
+ col_A = 3 - ((3.5 - nxt % 8).abs.to_i)
+ col_B = 3 - ((3.5 - pos % 8).abs.to_i)
+ row_A = 3 - ((3.5 - nxt.div(8)).abs.to_i)
+ row_B = 3 - ((3.5 - pos.div(8)).abs.to_i)
+ (col_A * row_A < col_B * row_B)? nxt : pos
+ end
+
+ # Display a square number as a standard chess square notation.
+ def _N(square)
+ '%c%d' % [(97 + square % 8), (square.div(8) + 1)]
+ end
+
+ # Perform a Knight's move and schedule the next move.
+ def move_piece(last, square)
+ @log.insert(:end, "#{@visited.length}. #{_N last} -> #{_N square}\n", '')
+ @log.see(:end)
+ @board.itemconfigure(1+last, :state=>:normal, :outline=>'black')
+ @board.itemconfigure(1+square, :state=>:normal, :outline=>'red')
+ @knight.coords(@board.coords(1+square)[0..1])
+ @visited << square
+ if (nxt = next_square(square)) != -1
+ @after_id = Tk.after(@delay.numeric){move_piece(square, nxt) rescue nil}
+ else
+ @start_btn.state :normal
+ if @visited.length == 64
+ if @initial == square
+ @log.insert :end, 'Closed tour!'
+ else
+ @log.insert :end, "Success\n", {}
+ Tk.after(@delay.numeric * 2){tour(rand(64))} if @continuous.bool
+ end
+ else
+ @log.insert :end, "FAILED!\n", {}
+ end
+ end
+ end
+
+ # Begin a new tour of the board given a random start position
+ def tour(square = nil)
+ @visited.clear
+ @log.clear
+ @start_btn.state :disabled
+ 1.upto(64){|n|
+ @board.itemconfigure(n, :state=>:disabled, :outline=>'black')
+ }
+ unless square
+ square = @board.find_closest(*(@knight.coords << 0 << 65))[0].to_i - 1
+ end
+ @initial = square
+ Tk.after_idle{ move_piece(@initial, @initial) rescue nil }
+ end
+
+ def _stop
+ Tk.after_cancel(@after_id) rescue nil
+ end
+
+ def _exit
+ _stop
+ $knightstour.destroy
+ end
+
+ def set_delay(new)
+ @delay.numeric = new.to_i
+ end
+
+ def drag_start(w, x, y)
+ w.dtag('selected')
+ w.addtag('selected', :withtag, 'current')
+ @dragging = [x, y]
+ end
+
+ def drag_motion(w, x, y)
+ return unless @dragging
+ w.move('selected', x - @dragging[0], y - @dragging[1])
+ @dragging = [x, y]
+ end
+
+ def drag_end(w, x, y)
+ square = w.find_closest(x, y, 0, 65)
+ w.coords('selected', w.coords(square)[0..1])
+ w.dtag('selected')
+ @dragging = nil
+ end
+
+ def make_SeeDismiss
+ ## See Code / Dismiss
+ frame = Ttk::Frame.new($knightstour)
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'knightstour'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $knightstour.destroy
+ $knightstour = nil
+ }),
+ :padx=>4, :pady=>4)
+ frame.grid_columnconfigure(0, :weight=>1)
+ frame
+ end
+
+ def create_gui(parent = nil)
+ $knightstour.destroy rescue nil
+ $knightstour = Tk::Toplevel.new(parent, :title=>"Knight's tour")
+ $knightstour.withdraw
+ base_f = Ttk::Frame.new($knightstour)
+ @board = Tk::Canvas.new(base_f, :width=>240, :height=>240)
+ @log = Tk::Text.new(base_f, :width=>12, :height=>1,
+ :font=>'Arial 8', :background=>'white')
+ scr = @log.yscrollbar(Ttk::Scrollbar.new(base_f))
+
+ @visited = []
+ @delay = TkVariable.new(600)
+ @continuous = TkVariable.new(false)
+
+ tool_f = Ttk::Frame.new($knightstour)
+ label = Ttk::Label.new(tool_f, :text=>'Speed')
+ scale = Ttk::Scale.new(tool_f, :from=>8, :to=>2000, :variable=>@delay,
+ :command=>proc{|n| set_delay(n)})
+ check = Ttk::Checkbutton.new(tool_f, :text=>'Repeat',
+ :variable=>@continuous)
+ @start_btn = Ttk::Button.new(tool_f, :text=>'Start',
+ :command=>proc{tour()})
+ @exit_btn = Ttk::Button.new(tool_f, :text=>'Exit',
+ :command=>proc{_exit()})
+
+ 7.downto(0){|row|
+ 0.upto(7){|col|
+ if ((col & 1) ^ (row & 1)).zero?
+ fill = 'bisque'
+ dfill = 'bisque3'
+ else
+ fill = 'tan3'
+ dfill = 'tan4'
+ end
+ coords = [col * 30 + 4, row * 30 + 4, col * 30 + 30, row * 30 + 30]
+ @board.create(TkcRectangle, coords,
+ :fill=>fill, :disabledfill=>dfill,
+ :width=>2, :state=>:disabled)
+ }
+ }
+
+ @knight_font = TkFont.new(:size=>-24)
+ @knight = TkcText.new(@board, 0, 0, :font=>@knight_font,
+ :text=>Tk::UTF8_String.new('\u265e'),
+ :anchor=>'nw', # :tags=>'knight',
+ :fill=>'black', :activefill=>'#600000')
+ @knight.coords(@board.coords(rand(64)+1)[0..1])
+ @knight.bind('ButtonPress-1', '%W %x %y'){|w,x,y| drag_start(w,x,y)}
+ @knight.bind('Motion', '%W %x %y'){|w,x,y| drag_motion(w,x,y)}
+ @knight.bind('ButtonRelease-1', '%W %x %y'){|w,x,y| drag_end(w,x,y)}
+
+ Tk.grid(@board, @log, scr, :sticky=>'news')
+ base_f.grid_rowconfigure(0, :weight=>1)
+ base_f.grid_columnconfigure(0, :weight=>1)
+
+ Tk.grid(base_f, '-', '-', '-', '-', '-', :sticky=>'news')
+ widgets = [label, scale, check, @start_btn]
+ sg = nil
+ unless $RubyTk_WidgetDemo
+ widgets << @exit_btn
+ if Tk.windowingsystem != 'aqua'
+ #widgets.unshift(Ttk::SizeGrip.new(tool_f))
+ Ttk::SizeGrip.new(tool_f).pack(:side=>:right, :anchor=>'se')
+ end
+ end
+ Tk.pack(widgets, :side=>:right)
+ if Tk.windowingsystem == 'aqua'
+ TkPack.configure(widgets, :padx=>[4, 4], :pady=>[12, 12])
+ TkPack.configure(widgets[0], :padx=>[4, 24])
+ TkPack.configure(widgets[-1], :padx=>[16, 4])
+ end
+
+ Tk.grid(tool_f, '-', '-', '-', '-', '-', :sticky=>'ew')
+
+ if $RubyTk_WidgetDemo
+ Tk.grid(make_SeeDismiss(), '-', '-', '-', '-', '-', :sticky=>'ew')
+ end
+
+ $knightstour.grid_rowconfigure(0, :weight=>1)
+ $knightstour.grid_columnconfigure(0, :weight=>1)
+
+ $knightstour.bind('Control-F2'){TkConsole.show}
+ $knightstour.bind('Return'){@start_btn.invoke}
+ $knightstour.bind('Escape'){@exit_btn.invoke}
+ $knightstour.bind('Destroy'){ _stop }
+ $knightstour.protocol('WM_DELETE_WINDOW'){ _exit }
+
+ $knightstour.deiconify
+ $knightstour.tkwait_destroy
+ end
+
+ def initialize(parent = nil)
+ create_gui(parent)
+ end
+end
+
+Tk.root.withdraw unless $RubyTk_WidgetDemo
+Thread.new{Tk.mainloop} if __FILE__ == $0
+Knights_Tour.new
diff --git a/ext/tk/sample/demos-en/label.rb b/ext/tk/sample/demos-en/label.rb
index ef1bfa6f8a..91e41e4a22 100644
--- a/ext/tk/sample/demos-en/label.rb
+++ b/ext/tk/sample/demos-en/label.rb
@@ -19,8 +19,10 @@ $label_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($label_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($label_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -29,7 +31,7 @@ msg = TkLabel.new($label_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($label_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -47,20 +49,21 @@ TkFrame.new($label_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# label demo
-f_left = TkFrame.new($label_demo)
-f_right = TkFrame.new($label_demo)
+f_left = TkFrame.new(base_frame)
+f_right = TkFrame.new(base_frame)
[f_left, f_right].each{|w| w.pack('side'=>'left', 'expand'=>'yes',
- 'padx'=>10, 'pady'=>10, 'fill'=>'both')}
+ 'padx'=>10, 'pady'=>10, 'fill'=>'both')}
# label
[ TkLabel.new(f_left, 'text'=>'First label'),
TkLabel.new(f_left, 'text'=>'Second label, raised',
- 'relief'=>'raised'),
+ 'relief'=>'raised'),
TkLabel.new(f_left, 'text'=>'Third label, sunken', 'relief'=>'sunken')
].each{|w| w.pack('side'=>'top', 'expand'=>'yes', 'pady'=>2, 'anchor'=>'w')}
-TkLabel.new(f_right) {
- bitmap('@' + [$demo_dir,'images','face.xbm'].join(File::Separator))
+# TkLabel.new(f_right) {
+Tk::Label.new(f_right) {
+ bitmap('@' + [$demo_dir,'..','images','face.xbm'].join(File::Separator))
borderwidth 2
relief 'sunken'
}.pack('side'=>'top')
diff --git a/ext/tk/sample/demos-en/labelframe.rb b/ext/tk/sample/demos-en/labelframe.rb
index 8636a4a9b9..c912ff4c52 100644
--- a/ext/tk/sample/demos-en/labelframe.rb
+++ b/ext/tk/sample/demos-en/labelframe.rb
@@ -17,10 +17,12 @@ $labelframe_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($labelframe_demo).pack(:fill=>:both, :expand=>true)
+
# Some information
-TkLabel.new($labelframe_demo,
- :font=>$font, :wraplength=>'4i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
Labelframes are used to group related widgets together. \
The label may be either plain text or another widget. \
If your Tk library linked to Ruby doesn't include a 'labelframe' widget, \
@@ -29,32 +31,32 @@ which supports a 'labelframe' widget.
EOL
# The bottom buttons
-TkFrame.new($labelframe_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
TkButton.new(f, :text=>'Dismiss', :width=>15, :command=>proc{
- $labelframe_demo.destroy
- $labelframe_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ $labelframe_demo.destroy
+ $labelframe_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'See Code', :width=>15, :command=>proc{
- showCode 'labelframe'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'labelframe'
+ }).pack(:side=>:left, :expand=>true)
}
# Demo area
-w = TkFrame.new($labelframe_demo).pack(:side=>:bottom, :fill=>:both,
- :expand=>true)
+w = TkFrame.new(base_frame).pack(:side=>:bottom, :fill=>:both,
+ :expand=>true)
# A group of radiobuttons in a labelframe
TkLabelFrame.new(w, :text=>'Value',
- :padx=>2, :pady=>2) {|f|
+ :padx=>2, :pady=>2) {|f|
grid(:row=>0, :column=>0, :pady=>'2m', :padx=>'2m')
v = TkVariable.new
(1..4).each{|i|
TkRadiobutton.new(f, :text=>"This is value #{i}",
- :variable=>v, :value=>i) {
+ :variable=>v, :value=>i) {
pack(:side=>:top, :fill=>:x, :pady=>2)
}
}
@@ -77,7 +79,7 @@ end
TkLabelFrame.new(w, :pady=>2, :padx=>2){|f|
TkCheckButton.new(f, :widgetname=>'cb', :variable=>$lfdummy,
- :text=>"Use this option.", :padx=>0) {|cb|
+ :text=>"Use this option.", :padx=>0) {|cb|
command proc{lfEnableButtons(f)}
f.labelwidget(cb)
}
diff --git a/ext/tk/sample/demos-en/mclist.rb b/ext/tk/sample/demos-en/mclist.rb
new file mode 100644
index 0000000000..a849eba515
--- /dev/null
+++ b/ext/tk/sample/demos-en/mclist.rb
@@ -0,0 +1,117 @@
+# mclist.rb --
+#
+# This demonstration script creates a toplevel window containing a Ttk
+# tree widget configured as a multi-column listbox.
+#
+# based on "Id: mclist.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($mclist_demo) && $mclist_demo
+ $mclist_demo.destroy
+ $mclist_demo = nil
+end
+
+$mclist_demo = TkToplevel.new {|w|
+ title("Multi-Column List")
+ iconname("mclist")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($mclist_demo).pack(:fill=>:both, :expand=>true)
+
+## Explanatory text
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i',
+ :justify=>:left, :anchor=>'n', :padding=>[10, 2, 10, 6],
+ :text=><<EOL).pack(:fill=>:x)
+Ttk is the new Tk themed widget set. \
+One of the widgets it includes is a tree widget, \
+which can be configured to display multiple columns of informational data \
+without displaying the tree itself. \
+This is a simple way to build a listbox that has multiple columns. \
+Clicking on the heading for a column will sort the data by that column. \
+You can also change the width of the columns \
+by dragging the boundary between them.
+EOL
+
+## See Code / Dismiss
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'mclist'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $mclist_demo.destroy
+ $mclist_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+container = Ttk::Frame.new(base_frame)
+tree = Ttk::Treeview.new(base_frame, :columns=>%w(country capital currency),
+ :show=>:headings)
+if Tk.windowingsystem != 'aqua'
+ vsb = tree.yscrollbar(Ttk::Scrollbar.new(base_frame))
+ hsb = tree.xscrollbar(Ttk::Scrollbar.new(base_frame))
+else
+ vsb = tree.yscrollbar(Tk::Scrollbar.new(base_frame))
+ hsb = tree.xscrollbar(Tk::Scrollbar.new(base_frame))
+end
+
+container.pack(:fill=>:both, :expand=>true)
+Tk.grid(tree, vsb, :in=>container, :sticky=>'nsew')
+Tk.grid(hsb, :in=>container, :sticky=>'nsew')
+container.grid_columnconfigure(0, :weight=>1)
+container.grid_rowconfigure(0, :weight=>1)
+
+## The data we're going to insert
+data = [
+ ['Argentina', 'Buenos Aires', 'ARS'],
+ ['Australia', 'Canberra', 'AUD'],
+ ['Brazil', 'Brazilia', 'BRL'],
+ ['Canada', 'Ottawa', 'CAD'],
+ ['China', 'Beijing', 'CNY'],
+ ['France', 'Paris', 'EUR'],
+ ['Germany', 'Berlin', 'EUR'],
+ ['India', 'New Delhi', 'INR'],
+ ['Italy', 'Rome', 'EUR'],
+ ['Japan', 'Tokyo', 'JPY'],
+ ['Mexico', 'Mexico City', 'MXN'],
+ ['Russia', 'Moscow', 'RUB'],
+ ['South Africa', 'Pretoria', 'ZAR'],
+ ['United Kingdom', 'London', 'GBP'],
+ ['United States', 'Washington, D.C.', 'USD'],
+]
+
+## Code to insert the data nicely
+font = Ttk::Style.lookup(tree[:style], :font)
+cols = %w(country capital currency)
+cols.zip(%w(Country Capital Currency)).each{|col, name|
+ tree.heading_configure(col, :text=>name,
+ :command=>proc{sort_by(tree, col, false)})
+ tree.column_configure(col, :width=>TkFont.measure(font, name))
+}
+
+data.each{|country, capital, currency|
+ #tree.insert('', :end, :values=>[country, capital, currency])
+ tree.insert(nil, :end, :values=>[country, capital, currency])
+ cols.zip([country, capital, currency]).each{|col, val|
+ len = TkFont.measure(font, "#{val} ")
+ if tree.column_cget(col, :width) < len
+ tree.column_configure(col, :width=>len)
+ end
+ }
+}
+
+## Code to do the sorting of the tree contents when clicked on
+def sort_by(tree, col, direction)
+ tree.children(nil).map!{|row| [tree.get(row, col), row.id]} .
+ sort(&((direction)? proc{|x, y| y <=> x}: proc{|x, y| x <=> y})) .
+ each_with_index{|info, idx| tree.move(info[1], nil, idx)}
+
+ tree.heading_configure(col, :command=>proc{sort_by(tree, col, ! direction)})
+end
diff --git a/ext/tk/sample/demos-en/menu.rb b/ext/tk/sample/demos-en/menu.rb
index 7ea3fd2ebb..bf6c22cb9d 100644
--- a/ext/tk/sample/demos-en/menu.rb
+++ b/ext/tk/sample/demos-en/menu.rb
@@ -15,13 +15,22 @@ $menu_demo = TkToplevel.new {|w|
positionWindow(w)
}
-# menu frame À¸À®
-$menu_frame = TkFrame.new($menu_demo, 'relief'=>'raised', 'bd'=>2)
+base_frame = TkFrame.new($menu_demo).pack(:fill=>:both, :expand=>true)
+
+# menu frame
+$menu_frame = TkFrame.new(base_frame, 'relief'=>'raised', 'bd'=>2)
$menu_frame.pack('side'=>'top', 'fill'=>'x')
+begin
+ windowingsystem = Tk.windowingsystem()
+rescue
+ windowingsystem = ""
+end
+
# label
-TkLabel.new($menu_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
- if $tk_platform['platform'] == 'macintosh'
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
+ if $tk_platform['platform'] == 'macintosh' ||
+ windowingsystem == "classic" || windowingsystem == "aqua"
text("This window contains a menubar with cascaded menus. You can invoke entries with an accelerator by typing Command+x, where \"x\" is the character next to the command key symbol. The rightmost menu can be torn off into a palette by dragging outside of its bounds and releasing the mouse.")
else
text("This window contains a menubar with cascaded menus. You can post a menu from the keyboard by typing Alt+x, where \"x\" is the character underlined on the menu. You can then traverse among the menus using the arrow keys. When a menu is posted, you can invoke the current entry by typing space, or you can invoke any entry by typing its underlined character. If a menu entry has an accelerator, you can invoke the entry without posting the menu just by typing the accelerator. The rightmost menu can be torn off into a palette by selecting the first item in the menu.")
@@ -29,7 +38,7 @@ TkLabel.new($menu_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
}.pack('side'=>'top')
# frame
-TkFrame.new($menu_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -62,7 +71,8 @@ TkMenubutton.new($menu_frame, 'text'=>'File', 'underline'=>0) {|m|
}
}
-if $tk_platform['platform'] == 'macintosh'
+if $tk_platform['platform'] == 'macintosh' ||
+ windowingsystem == "classic" || windowingsystem == "aqua"
modifier = 'Command'
elsif $tk_platform['platform'] == 'windows'
modifier = 'Control'
@@ -77,8 +87,8 @@ TkMenubutton.new($menu_frame, 'text'=>'Basic', 'underline'=>0) {|m|
add('command', 'label'=>'Long entry that does nothing')
['A','B','C','D','E','F','G'].each{|c|
add('command', 'label'=>"Print letter \"#{c}\"",
- 'underline'=>14, 'accelerator'=>"Meta+#{c}",
- 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
+ 'underline'=>14, 'accelerator'=>"Meta+#{c}",
+ 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
$menu_demo.bind("#{modifier}-#{c.downcase}", proc{print c,"\n"})
}
}
@@ -89,17 +99,17 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
TkMenu.new(m, 'tearoff'=>false) {|cascade_menu|
m.configure('menu'=>cascade_menu)
add('command', 'label'=>'Print hello',
- 'command'=>proc{print "Hello\n"},
- 'accelerator'=>"#{modifier}+H", 'underline'=>6)
+ 'command'=>proc{print "Hello\n"},
+ 'accelerator'=>"#{modifier}+H", 'underline'=>6)
$menu_demo.bind("#{modifier}-h", proc{print "Hello\n"})
add('command', 'label'=>'Print goodbye',
- 'command'=>proc{print "Goodbye\n"},
- 'accelerator'=>"#{modifier}+G", 'underline'=>6)
+ 'command'=>proc{print "Goodbye\n"},
+ 'accelerator'=>"#{modifier}+G", 'underline'=>6)
$menu_demo.bind("#{modifier}-g", proc{print "Goodbye\n"})
- TkMenu.new(m, 'tearoff'=>false) {|cascade_check|
+ TkMenu.new(cascade_menu, 'tearoff'=>false) {|cascade_check|
cascade_menu.add('cascade', 'label'=>'Check buttons',
- 'menu'=>cascade_check, 'underline'=>0)
+ 'menu'=>cascade_check, 'underline'=>0)
oil = TkVariable.new(0)
add('check', 'label'=>'Oil checked', 'variable'=>oil)
trans = TkVariable.new(0)
@@ -110,18 +120,18 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
add('check', 'label'=>'Lights checked', 'variable'=>lights)
add('separator')
add('command', 'label'=>'Show current values',
- 'command'=>proc{showVars($menu_demo,
- ['oil', oil],
- ['trans', trans],
- ['brakes', brakes],
- ['lights', lights])} )
+ 'command'=>proc{showVars($menu_demo,
+ ['oil', oil],
+ ['trans', trans],
+ ['brakes', brakes],
+ ['lights', lights])} )
invoke 1
invoke 3
}
- TkMenu.new(m, 'tearoff'=>false) {|cascade_radio|
+ TkMenu.new(cascade_menu, 'tearoff'=>false) {|cascade_radio|
cascade_menu.add('cascade', 'label'=>'Radio buttons',
- 'menu'=>cascade_radio, 'underline'=>0)
+ 'menu'=>cascade_radio, 'underline'=>0)
pointSize = TkVariable.new
add('radio', 'label'=>'10 point', 'variable'=>pointSize, 'value'=>10)
add('radio', 'label'=>'14 point', 'variable'=>pointSize, 'value'=>14)
@@ -135,9 +145,9 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
add('radio', 'label'=>'Italic', 'variable'=>style, 'value'=>'italic')
add('separator')
add('command', 'label'=>'Show current values',
- 'command'=>proc{showVars($menu_demo,
- ['pointSize', pointSize],
- ['style', style])} )
+ 'command'=>proc{showVars($menu_demo,
+ ['pointSize', pointSize],
+ ['style', style])} )
invoke 1
invoke 7
}
@@ -149,14 +159,15 @@ TkMenubutton.new($menu_frame, 'text'=>'Icons', 'underline'=>0) {|m|
TkMenu.new(m, 'tearoff'=>false) {|icon_menu|
m.configure('menu'=>icon_menu)
add('command',
- 'bitmap'=>'@'+[$demo_dir,'images','pattern.xbm'].join(File::Separator),
- 'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry',
- 'text'=>'The menu entry you invoked displays a bitmap rather than a text string. Other than this, it is just like any other menu entry.',
- 'bitmap'=>'', 'default'=>0,
- 'buttons'=>'Dismiss')} )
+ 'bitmap'=>'@'+[$demo_dir,'..',
+ 'images','pattern.xbm'].join(File::Separator),
+ 'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry',
+ 'text'=>'The menu entry you invoked displays a bitmap rather than a text string. Other than this, it is just like any other menu entry.',
+ 'bitmap'=>'', 'default'=>0,
+ 'buttons'=>'Dismiss')} )
['info', 'questhead', 'error'].each{|icon|
add('command', 'bitmap'=>icon,
- 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
+ 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
}
}
}
@@ -168,7 +179,7 @@ TkMenubutton.new($menu_frame, 'text'=>'More', 'underline'=>0) {|m|
[ 'An entry','Another entry','Does nothing','Does almost nothing',
'Make life meaningful' ].each{|i|
add('command', 'label'=>i,
- 'command'=>proc{print "You invoked \"#{i}\"\n"})
+ 'command'=>proc{print "You invoked \"#{i}\"\n"})
}
}
}
@@ -179,7 +190,7 @@ TkMenubutton.new($menu_frame, 'text'=>'Colors', 'underline'=>0) {|m|
m.configure('menu'=>colors_menu)
['red', 'orange', 'yellow', 'green', 'blue'].each{|c|
add('command', 'label'=>c, 'background'=>c,
- 'command'=>proc{print "You invoked \"#{c}\"\n"})
+ 'command'=>proc{print "You invoked \"#{c}\"\n"})
}
}
}
diff --git a/ext/tk/sample/demos-en/menu84.rb b/ext/tk/sample/demos-en/menu84.rb
index 82e29f6475..4029ce5541 100644
--- a/ext/tk/sample/demos-en/menu84.rb
+++ b/ext/tk/sample/demos-en/menu84.rb
@@ -15,6 +15,8 @@ $menu84_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($menu84_demo).pack(:fill=>:both, :expand=>true)
+
begin
windowingsystem = Tk.windowingsystem()
rescue
@@ -22,7 +24,7 @@ rescue
end
# label
-TkLabel.new($menu84_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
if $tk_platform['platform'] == 'macintosh' ||
windowingsystem == "classic" || windowingsystem == "aqua"
text("This window contains a menubar with cascaded menus. You can invoke entries with an accelerator by typing Command+x, where \"x\" is the character next to the command key symbol. The rightmost menu can be torn off into a palette by dragging outside of its bounds and releasing the mouse.")
@@ -33,17 +35,17 @@ TkLabel.new($menu84_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
menustatus = TkVariable.new(" ")
-TkFrame.new($menu84_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkLabel.new(frame, 'textvariable'=>menustatus, 'relief'=>'sunken',
- 'bd'=>1, 'font'=>['Helvetica', '10'],
- 'anchor'=>'w').pack('side'=>'left', 'padx'=>2,
- 'expand'=>true, 'fill'=>'both')
+ 'bd'=>1, 'font'=>['Helvetica', '10'],
+ 'anchor'=>'w').pack('side'=>'left', 'padx'=>2,
+ 'expand'=>true, 'fill'=>'both')
pack('side'=>'bottom', 'fill'=>'x', 'pady'=>2)
}
# frame
-TkFrame.new($menu84_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -91,8 +93,8 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
add('command', 'label'=>'Long entry that does nothing')
['A','B','C','D','E','F','G'].each{|c|
add('command', 'label'=>"Print letter \"#{c}\"",
- 'underline'=>14, 'accelerator'=>"Meta+#{c}",
- 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
+ 'underline'=>14, 'accelerator'=>"Meta+#{c}",
+ 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
$menu84_demo.bind("#{modifier}-#{c.downcase}", proc{print c,"\n"})
}
}
@@ -110,7 +112,7 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
TkMenu.new(m, 'tearoff'=>false) {|cascade_check|
m.add('cascade', 'label'=>'Check buttons',
- 'menu'=>cascade_check, 'underline'=>0)
+ 'menu'=>cascade_check, 'underline'=>0)
oil = TkVariable.new(0)
add('check', 'label'=>'Oil checked', 'variable'=>oil)
trans = TkVariable.new(0)
@@ -121,18 +123,18 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
add('check', 'label'=>'Lights checked', 'variable'=>lights)
add('separator')
add('command', 'label'=>'Show current values',
- 'command'=>proc{showVars($menu84_demo,
- ['oil', oil],
- ['trans', trans],
- ['brakes', brakes],
- ['lights', lights])} )
+ 'command'=>proc{showVars($menu84_demo,
+ ['oil', oil],
+ ['trans', trans],
+ ['brakes', brakes],
+ ['lights', lights])} )
invoke 1
invoke 3
}
TkMenu.new(m, 'tearoff'=>false) {|cascade_radio|
m.add('cascade', 'label'=>'Radio buttons',
- 'menu'=>cascade_radio, 'underline'=>0)
+ 'menu'=>cascade_radio, 'underline'=>0)
pointSize = TkVariable.new
add('radio', 'label'=>'10 point', 'variable'=>pointSize, 'value'=>10)
add('radio', 'label'=>'14 point', 'variable'=>pointSize, 'value'=>14)
@@ -146,9 +148,9 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
add('radio', 'label'=>'Italic', 'variable'=>style, 'value'=>'italic')
add('separator')
add('command', 'label'=>'Show current values',
- 'command'=>proc{showVars($menu84_demo,
- ['pointSize', pointSize],
- ['style', style])} )
+ 'command'=>proc{showVars($menu84_demo,
+ ['pointSize', pointSize],
+ ['style', style])} )
invoke 1
invoke 7
}
@@ -157,14 +159,15 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
$menu84_frame.add('cascade', 'label'=>'Icons', 'menu'=>m, 'underline'=>0)
add('command', 'hidemargin'=>1,
- 'bitmap'=>'@'+[$demo_dir,'images','pattern.xbm'].join(File::Separator),
+ 'bitmap'=>'@'+[$demo_dir,'..',
+ 'images','pattern.xbm'].join(File::Separator),
'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry',
- 'text'=>'The menu entry you invoked displays a bitmap rather than a text string. Other than this, it is just like any other menu entry.',
- 'bitmap'=>'', 'default'=>0,
- 'buttons'=>'Dismiss')} )
+ 'text'=>'The menu entry you invoked displays a bitmap rather than a text string. Other than this, it is just like any other menu entry.',
+ 'bitmap'=>'', 'default'=>0,
+ 'buttons'=>'Dismiss')} )
['info', 'questhead', 'error'].each{|icon|
add('command', 'bitmap'=>icon, 'hidemargin'=>1,
- 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
+ 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
}
entryconfigure(2, :columnbreak=>true)
@@ -175,38 +178,38 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
[ 'An entry','Another entry','Does nothing','Does almost nothing',
'Make life meaningful' ].each{|i|
add('command', 'label'=>i,
- 'command'=>proc{print "You invoked \"#{i}\"\n"})
+ 'command'=>proc{print "You invoked \"#{i}\"\n"})
}
m.entryconfigure('Does almost nothing',
- 'bitmap'=>'questhead', 'compound'=>'left',
- 'command'=>proc{
- TkDialog.new('title'=>'Compound Menu Entry',
- 'message'=>'The menu entry you invoked'+
- 'displays both a bitmap and '+
- 'a text string. Other than '+
- 'this, it isjust like any '+
- 'other menu entry.',
- 'buttons'=>['OK'], 'bitmap'=>'')
- })
+ 'bitmap'=>'questhead', 'compound'=>'left',
+ 'command'=>proc{
+ TkDialog.new('title'=>'Compound Menu Entry',
+ 'message'=>'The menu entry you invoked'+
+ 'displays both a bitmap and '+
+ 'a text string. Other than '+
+ 'this, it isjust like any '+
+ 'other menu entry.',
+ 'buttons'=>['OK'], 'bitmap'=>'')
+ })
}
TkMenu.new($menu84_frame) {|m|
$menu84_frame.add('cascade', 'label'=>'Colors', 'menu'=>m, 'underline'=>0)
['red', 'orange', 'yellow', 'green', 'blue'].each{|c|
add('command', 'label'=>c, 'background'=>c,
- 'command'=>proc{print "You invoked \"#{c}\"\n"})
+ 'command'=>proc{print "You invoked \"#{c}\"\n"})
}
}
$menu84_demo.menu($menu84_frame)
TkMenu.bind('<MenuSelect>', proc{|w|
- begin
- label = w.entrycget('active', 'label')
- rescue
- label = " "
- end
- menustatus.value = label
- Tk.update(true)
- }, '%W')
+ begin
+ label = w.entrycget('active', 'label')
+ rescue
+ label = " "
+ end
+ menustatus.value = label
+ Tk.update(true)
+ }, '%W')
diff --git a/ext/tk/sample/demos-en/menubu.rb b/ext/tk/sample/demos-en/menubu.rb
index 42a5931dd1..b37367e515 100644
--- a/ext/tk/sample/demos-en/menubu.rb
+++ b/ext/tk/sample/demos-en/menubu.rb
@@ -37,16 +37,18 @@ $menubu_demo = TkToplevel.new {|w|
positionWindow($menubu_demo)
+base_frame = TkFrame.new($menubu_demo).pack(:fill=>:both, :expand=>true)
+
# version check
if $tk_version.to_f < 8.0
# label
-TkLabel.new($menubu_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
text("This is a demonstration of menubuttons. The \"Below\" menubutton pops its menu below the button; the \"Right\" button pops to the right, etc. There are two option menus directly below this text; one is just a standard menu and the other is a 16-color palette.")
}.pack('side'=>'top')
# frame
-TkFrame.new($menubu_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -58,13 +60,13 @@ TkFrame.new($menubu_demo) {|frame|
TkButton.new(frame) {
text 'Show Code'
- command proc{showCode 'menu'}
+ command proc{showCode 'menubu'}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
else ; # Tk8.x
-body = TkFrame.new($menubu_demo)
+body = TkFrame.new(base_frame)
body.pack('expand'=>'yes', 'fill'=>'both')
below = TkMenubutton.new(body) {
@@ -159,7 +161,7 @@ center = TkFrame.new(body) {
grid('row'=>1, 'column'=>1, 'sticky'=>'news')
}
-TkFrame.new($menubu_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc {
@@ -187,7 +189,7 @@ TkFrame.new(center) {|f|
menubuttonoptions = TkVariable.new
mbutton = TkMenubutton.new(f)
options = optionMenu(mbutton, menubuttonoptions,
- 'one', 'two', 'three')
+ 'one', 'two', 'three')
mbutton.pack('side'=>'left', 'padx'=>25, 'pady'=>25)
paletteColor = TkVariable.new
colors = ['Black','red4','DarkGreen','NavyBlue', 'gray75',
diff --git a/ext/tk/sample/demos-en/msgbox.rb b/ext/tk/sample/demos-en/msgbox.rb
index 4152477e67..62b1f2b985 100644
--- a/ext/tk/sample/demos-en/msgbox.rb
+++ b/ext/tk/sample/demos-en/msgbox.rb
@@ -18,12 +18,14 @@ $msgbox_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($msgbox_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($msgbox_demo, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
- 'text'=>"Choose the icon and type option of the message box. Then press the \"Message Box\" button to see the message box.").pack('side'=>'top')
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
+ 'text'=>"Choose the icon and type option of the message box. Then press the \"Message Box\" button to see the message box.").pack('side'=>'top')
# frame
-TkFrame.new($msgbox_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -45,12 +47,12 @@ TkFrame.new($msgbox_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
-$msgbox_leftframe = TkFrame.new($msgbox_demo)
-$msgbox_rightframe = TkFrame.new($msgbox_demo)
+$msgbox_leftframe = TkFrame.new(base_frame)
+$msgbox_rightframe = TkFrame.new(base_frame)
$msgbox_leftframe .pack('side'=>'left', 'expand'=>'yes', 'fill'=>'y',
- 'pady'=>'.5c', 'padx'=>'.5c')
+ 'pady'=>'.5c', 'padx'=>'.5c')
$msgbox_rightframe.pack('side'=>'left', 'expand'=>'yes', 'fill'=>'y',
- 'pady'=>'.5c', 'padx'=>'.5c')
+ 'pady'=>'.5c', 'padx'=>'.5c')
TkLabel.new($msgbox_leftframe, 'text'=>'Icon').pack('side'=>'top')
TkFrame.new($msgbox_leftframe, 'relief'=>'ridge', 'bd'=>1, 'height'=>2)\
@@ -59,9 +61,9 @@ TkFrame.new($msgbox_leftframe, 'relief'=>'ridge', 'bd'=>1, 'height'=>2)\
$msgboxIcon = TkVariable.new('info')
['error', 'info', 'question', 'warning'].each {|icon|
TkRadioButton.new($msgbox_leftframe, 'text'=>icon, 'variable'=>$msgboxIcon,
- 'relief'=>'flat', 'value'=>icon, 'width'=>16,
- 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
- 'anchor'=>'w', 'fill'=>'x')
+ 'relief'=>'flat', 'value'=>icon, 'width'=>16,
+ 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
+ 'anchor'=>'w', 'fill'=>'x')
}
TkLabel.new($msgbox_rightframe, 'text'=>'Type').pack('side'=>'top')
@@ -72,17 +74,17 @@ $msgboxType = TkVariable.new('ok')
['abortretryignore', 'ok', 'okcancel',
'retrycancel', 'yesno', 'yesnocancel'].each {|type|
TkRadioButton.new($msgbox_rightframe, 'text'=>type, 'variable'=>$msgboxType,
- 'relief'=>'flat', 'value'=>type, 'width'=>16,
- 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
- 'anchor'=>'w', 'fill'=>'x')
+ 'relief'=>'flat', 'value'=>type, 'width'=>16,
+ 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
+ 'anchor'=>'w', 'fill'=>'x')
}
def showMessageBox(w)
button = Tk.messageBox('icon'=>$msgboxIcon.value, 'type'=>$msgboxType.value,
- 'title'=>'Message', 'parent'=>w,
- 'message'=>"This is a \"#{$msgboxType.value}\" type messagebox with the \"#{$msgboxIcon.value}\" icon")
+ 'title'=>'Message', 'parent'=>w,
+ 'message'=>"This is a \"#{$msgboxType.value}\" type messagebox with the \"#{$msgboxIcon.value}\" icon")
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'parent'=>w,
- 'message'=>"You have selected \"#{button}\"")
+ 'message'=>"You have selected \"#{button}\"")
end
diff --git a/ext/tk/sample/demos-en/msgbox2.rb b/ext/tk/sample/demos-en/msgbox2.rb
new file mode 100644
index 0000000000..6fe6c778b3
--- /dev/null
+++ b/ext/tk/sample/demos-en/msgbox2.rb
@@ -0,0 +1,91 @@
+# msgbox2.rb
+#
+# This demonstration script creates message boxes of various type
+#
+# message boxes widget demo (called by 'widget')
+#
+
+# toplevel widget
+if defined?($msgbox2_demo) && $msgbox2_demo
+ $msgbox2_demo.destroy
+ $msgbox2_demo = nil
+end
+
+# demo toplevel widget
+$msgbox2_demo = TkToplevel.new {|w|
+ title("Message Box Demonstration")
+ iconname("messagebox")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($msgbox2_demo).pack(:fill=>:both, :expand=>true)
+
+# label
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
+ 'text'=>"Choose the icon and type option of the message box. Then press the \"Message Box\" button to see the message box with both of a message and a detail.").pack('side'=>'top')
+
+# frame
+TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ text 'Dismiss'
+ command proc{
+ tmppath = $msgbox2_demo
+ $msgbox2_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text 'Show Code'
+ command proc{showCode 'msgbox2'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text 'Message Box'
+ command proc{showMessageBox $msgbox2_demo}
+ }.pack('side'=>'left', 'expand'=>'yes')
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# frame
+$msgbox_leftframe = TkFrame.new(base_frame)
+$msgbox_rightframe = TkFrame.new(base_frame)
+$msgbox_leftframe .pack('side'=>'left', 'expand'=>'yes', 'fill'=>'y',
+ 'pady'=>'.5c', 'padx'=>'.5c')
+$msgbox_rightframe.pack('side'=>'left', 'expand'=>'yes', 'fill'=>'y',
+ 'pady'=>'.5c', 'padx'=>'.5c')
+
+TkLabel.new($msgbox_leftframe, 'text'=>'Icon').pack('side'=>'top')
+TkFrame.new($msgbox_leftframe, 'relief'=>'ridge', 'bd'=>1, 'height'=>2)\
+.pack('side'=>'top', 'fill'=>'x', 'expand'=>'no')
+
+$msgboxIcon = TkVariable.new('info')
+['error', 'info', 'question', 'warning'].each {|icon|
+ TkRadioButton.new($msgbox_leftframe, 'text'=>icon, 'variable'=>$msgboxIcon,
+ 'relief'=>'flat', 'value'=>icon, 'width'=>16,
+ 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
+ 'anchor'=>'w', 'fill'=>'x')
+}
+
+TkLabel.new($msgbox_rightframe, 'text'=>'Type').pack('side'=>'top')
+TkFrame.new($msgbox_rightframe, 'relief'=>'ridge', 'bd'=>1, 'height'=>2)\
+.pack('side'=>'top', 'fill'=>'x', 'expand'=>'no')
+
+$msgboxType = TkVariable.new('ok')
+['abortretryignore', 'ok', 'okcancel',
+ 'retrycancel', 'yesno', 'yesnocancel'].each {|type|
+ TkRadioButton.new($msgbox_rightframe, 'text'=>type, 'variable'=>$msgboxType,
+ 'relief'=>'flat', 'value'=>type, 'width'=>16,
+ 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
+ 'anchor'=>'w', 'fill'=>'x')
+}
+
+def showMessageBox(w)
+ button = Tk.messageBox('icon'=>$msgboxIcon.value, 'type'=>$msgboxType.value,
+ 'title'=>'Message', 'parent'=>w,
+ 'message'=>"\"#{$msgboxType.value}\" Type MessageBox",
+ 'detail'=>"This is a \"#{$msgboxType.value}\" type messagebox with the \"#{$msgboxIcon.value}\" icon. Please click one of the following button.")
+
+ Tk.messageBox('icon'=>'info', 'type'=>'ok', 'parent'=>w,
+ 'message'=>"You have selected \"#{button}\"")
+end
+
diff --git a/ext/tk/sample/demos-en/paned1.rb b/ext/tk/sample/demos-en/paned1.rb
index 8c25de0ef3..26941b84a8 100644
--- a/ext/tk/sample/demos-en/paned1.rb
+++ b/ext/tk/sample/demos-en/paned1.rb
@@ -16,30 +16,32 @@ $paned1_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($paned1_demo,
- :font=>$font, :wraplength=>'4i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+base_frame = TkFrame.new($paned1_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
The sash between the two coloured windows below can be used to divide the area between them. Use the left mouse button to resize without redrawing by just moving the sash, and use the middle mouse button to resize opaquely (always redrawing the windows in each position.)
If your Tk library linked to Ruby doesn't include a 'panedwindow', this demo doesn't work. Please use later version of Tk which supports a 'panedwindow'.
EOL
# The bottom buttons
-TkFrame.new($paned1_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
TkButton.new(f, :text=>'Dismiss', :width=>15, :command=>proc{
- $paned1_demo.destroy
- $paned1_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ $paned1_demo.destroy
+ $paned1_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'See Code', :width=>15, :command=>proc{
- showCode 'paned1'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'paned1'
+ }).pack(:side=>:left, :expand=>true)
}
-TkPanedwindow.new($paned1_demo){|f|
- pack(:side=>:top, :expand=>true, :fill=>:both, :pady=>2, :padx=>'2m')
+TkPanedwindow.new(base_frame, :orient=>:horizontal){|f|
+ add(Tk::Label.new(f, :text=>"This is the\nleft side", :bg=>'yellow'),
+ Tk::Label.new(f, :text=>"This is the\nright side", :bg=>'cyan'))
- add(TkLabel.new(f, :text=>"This is the\nleft side", :bg=>'yellow'),
- TkLabel.new(f, :text=>"This is the\nright side", :bg=>'cyan'))
+ pack(:side=>:top, :expand=>true, :fill=>:both, :pady=>2, :padx=>'2m')
}
diff --git a/ext/tk/sample/demos-en/paned2.rb b/ext/tk/sample/demos-en/paned2.rb
index c8c5abb470..0e62013886 100644
--- a/ext/tk/sample/demos-en/paned2.rb
+++ b/ext/tk/sample/demos-en/paned2.rb
@@ -16,25 +16,27 @@ $paned2_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($paned2_demo,
- :font=>$font, :wraplength=>'4i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+base_frame = TkFrame.new($paned2_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
The sash between the two scrolled windows below can be used to divide the area between them. Use the left mouse button to resize without redrawing by just moving the sash, and use the middle mouse button to resize opaquely (always redrawing the windows in each position.)
If your Tk library linked to Ruby doesn't include a 'panedwindow', this demo doesn't work. Please use later version of Tk which supports a 'panedwindow'.
EOL
# The bottom buttons
-TkFrame.new($paned2_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
TkButton.new(f, :text=>'Dismiss', :width=>15, :command=>proc{
- $paned2_demo.destroy
- $paned2_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ $paned2_demo.destroy
+ $paned2_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'See Code', :width=>15, :command=>proc{
- showCode 'paned2'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'paned2'
+ }).pack(:side=>:left, :expand=>true)
}
paneList = TkVariable.new # define as normal variable (not array)
@@ -61,32 +63,32 @@ paneList.value = [ # ruby's array --> tcl's list
]
# Create the pane itself
-TkPanedwindow.new($paned2_demo, :orient=>:vertical){|f|
+TkPanedwindow.new(base_frame, :orient=>:vertical){|f|
pack(:side=>:top, :expand=>true, :fill=>:both, :pady=>2, :padx=>'2m')
add(TkFrame.new(f){|paned2_top|
- TkListbox.new(paned2_top, :listvariable=>paneList) {
- # Invert the first item to highlight it
- itemconfigure(0, :background=>self.cget(:foreground),
- :foreground=>self.cget(:background) )
- yscrollbar(TkScrollbar.new(paned2_top).pack(:side=>:right,
- :fill=>:y))
- pack(:fill=>:both, :expand=>true)
- }
+ TkListbox.new(paned2_top, :listvariable=>paneList) {
+ # Invert the first item to highlight it
+ itemconfigure(0, :background=>self.cget(:foreground),
+ :foreground=>self.cget(:background) )
+ yscrollbar(TkScrollbar.new(paned2_top).pack(:side=>:right,
+ :fill=>:y))
+ pack(:fill=>:both, :expand=>true)
+ }
},
- TkFrame.new(f) {|paned2_bottom|
- # The bottom window is a text widget with scrollbar
- paned2_xscr = TkScrollbar.new(paned2_bottom)
- paned2_yscr = TkScrollbar.new(paned2_bottom)
- paned2_text = TkText.new(paned2_bottom, :width=>30, :wrap=>:non) {
- insert('1.0', "This is just a normal text widget")
- xscrollbar(paned2_xscr)
- yscrollbar(paned2_yscr)
- }
- Tk.grid(paned2_text, paned2_yscr, :sticky=>'nsew')
- Tk.grid(paned2_xscr, :sticky=>'nsew')
- TkGrid.columnconfigure(paned2_bottom, 0, :weight=>1)
- TkGrid.rowconfigure(paned2_bottom, 0, :weight=>1)
+ 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)
+ paned2_text = TkText.new(paned2_bottom, :width=>30, :wrap=>:non) {
+ insert('1.0', "This is just a normal text widget")
+ xscrollbar(paned2_xscr)
+ yscrollbar(paned2_yscr)
+ }
+ Tk.grid(paned2_text, paned2_yscr, :sticky=>'nsew')
+ Tk.grid(paned2_xscr, :sticky=>'nsew')
+ TkGrid.columnconfigure(paned2_bottom, 0, :weight=>1)
+ TkGrid.rowconfigure(paned2_bottom, 0, :weight=>1)
} )
}
diff --git a/ext/tk/sample/demos-en/patch_1.1c1 b/ext/tk/sample/demos-en/patch_1.1c1
deleted file mode 100644
index d3952e71eb..0000000000
--- a/ext/tk/sample/demos-en/patch_1.1c1
+++ /dev/null
@@ -1,93 +0,0 @@
---- /usr/src/ruby-1.1c1/lib/tkcanvas.rb Tue Jul 21 18:18:02 1998
-+++ tkcanvas.rb Fri Jul 24 20:38:24 1998
-@@ -310,7 +310,7 @@
- || key == 'latinfont' || key == 'asciifont' )
- tagfont_configure(tagid(tagOrId), {key=>value})
- else
-- tk_call 'itemconfigure', tagid(tagOrId), "-#{key}", value
-+ tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
- end
- end
- end
---- /usr/src/ruby-1.1c1/lib/tkfont.rb Fri Jul 17 23:43:28 1998
-+++ tkfont.rb Fri Jul 24 17:46:22 1998
-@@ -42,7 +42,7 @@
- r | []
-
- when /^8\.*/
-- list(tk_call('font', 'names'))
-+ tk_split_simplelist(tk_call('font', 'names'))
-
- end
- end
-@@ -89,10 +89,14 @@
- if fnt == []
- TkFont.new(nil, nil).call_font_configure(path, *(args + [{}]))
- else
-- compound = Hash[*list(tk_call('font', 'configure',
-- fnt))].collect{|key,value|
-- [key[1..-1], value]
-- }.assoc('compound')[1]
-+ begin
-+ compound = Hash[*list(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 + [{}]))
-@@ -156,14 +160,19 @@
- elsif font.kind_of? Array
- finfo = {}
- finfo['family'] = font[0].to_s
-- if font[1] && font[1] != '0' && font[1] =~ /^(|\+|-)([0-9]+)$/
-- if $1 == '-'
-- finfo['pixels'] = font[1].to_s
-+ if font[1]
-+ fsize = font[1].to_s
-+ if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
-+ if $1 == '-'
-+ finfo['pixels'] = $2
-+ else
-+ finfo['points'] = $2
-+ end
- else
-- finfo['points'] = font[1].to_s
-+ finfo['points'] = '13'
- end
- end
-- finfo[2..-1].each{|style|
-+ font[2..-1].each{|style|
- case (style)
- when 'normal'
- finfo['weight'] = style
-@@ -199,16 +208,19 @@
- elsif font.kind_of? Array
- finfo = {}
- finfo['family'] = font[0].to_s
-- if font[1] && font[1] != '0' && font[1] =~ /^(|\+|-)([0-9]+)$/
-- if $1 == '-'
-- finfo['pixels'] = $2
-+ if font[1]
-+ fsize = font[1].to_s
-+ if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
-+ if $1 == '-'
-+ finfo['pixels'] = $2
-+ else
-+ finfo['points'] = $2
-+ end
- else
-- finfo['points'] = $2
-+ finfo['points'] = '13'
- end
-- else
-- finfo['points'] = '13'
- end
-- finfo[2..-1].each{|style|
-+ font[2..-1].each{|style|
- case (style)
- when 'normal'
- finfo['weight'] = style
diff --git a/ext/tk/sample/demos-en/pendulum.rb b/ext/tk/sample/demos-en/pendulum.rb
new file mode 100644
index 0000000000..5f7d361170
--- /dev/null
+++ b/ext/tk/sample/demos-en/pendulum.rb
@@ -0,0 +1,240 @@
+#
+# This demonstration illustrates how Tcl/Tk can be used to construct
+# simulations of physical systems.
+# (called by 'widget')
+#
+# based on Tcl/Tk8.5a2 widget demos
+
+# destroy toplevel widget for this demo script
+if defined?($pendulum_demo) && $pendulum_demo
+ $pendulum_demo.destroy
+ $pendulum_demo = nil
+end
+
+# create toplevel widget
+$pendulum_demo = TkToplevel.new {|w|
+ title("Pendulum Animation Demonstration")
+ iconname("pendulum")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($pendulum_demo).pack(:fill=>:both, :expand=>true)
+
+# create label
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '4i'
+ justify 'left'
+ text 'This demonstration shows how Ruby/Tk can be used to carry out animations that are linked to simulations of physical systems. In the left canvas is a graphical representation of the physical system itself, a simple pendulum, and in the right canvas is a graph of the phase space of the system, which is a plot of the angle (relative to the vertical) against the angular velocity. The pendulum bob may be repositioned by clicking and dragging anywhere on the left canvas.'
+}
+msg.pack('side'=>'top')
+
+# create frame
+TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ text 'Dismiss'
+ command proc{
+ tmppath = $pendulum_demo
+ $pendulum_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text 'See Code'
+ command proc{showCode 'pendulum'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# animated wave
+class PendulumAnimationDemo
+ def initialize(frame)
+ # Create some structural widgets
+ @pane = TkPanedWindow.new(frame, :orient=>:horizontal).pack(:fill=>:both, :expand=>true)
+# @pane.add(@lf1 = TkLabelFrame.new(@pane, :text=>'Pendulum Simulation'))
+# @pane.add(@lf2 = TkLabelFrame.new(@pane, :text=>'Phase Space'))
+ @lf1 = TkLabelFrame.new(@pane, :text=>'Pendulum Simulation')
+ @lf2 = TkLabelFrame.new(@pane, :text=>'Phase Space')
+
+ # Create the canvas containing the graphical representation of the
+ # simulated system.
+ @c = TkCanvas.new(@lf1, :width=>320, :height=>200, :background=>'white',
+ :borderwidth=>2, :relief=>:sunken)
+ TkcText.new(@c, 5, 5, :anchor=>:nw,
+ :text=>'Click to Adjust Bob Start Position')
+ # Coordinates of these items don't matter; they will be set properly below
+ @plate = TkcLine.new(@c, 0, 25, 320, 25, :width=>2, :fill=>'grey50')
+ @rod = TkcLine.new(@c, 1, 1, 1, 1, :width=>3, :fill=>'black')
+ @bob = TkcOval.new(@c, 1, 1, 2, 2,
+ :width=>3, :fill=>'yellow', :outline=>'black')
+ TkcOval.new(@c, 155, 20, 165, 30, :fill=>'grey50', :outline=>'')
+
+ # pack
+ @c.pack(:fill=>:both, :expand=>true)
+
+ # Create the canvas containing the phase space graph; this consists of
+ # a line that gets gradually paler as it ages, which is an extremely
+ # effective visual trick.
+ @k = TkCanvas.new(@lf2, :width=>320, :height=>200, :background=>'white',
+ :borderwidth=>2, :relief=>:sunken)
+ @y_axis = TkcLine.new(@k, 160, 200, 160, 0, :fill=>'grey75', :arrow=>:last)
+ @x_axis = TkcLine.new(@k, 0, 100, 320, 100, :fill=>'grey75', :arrow=>:last)
+
+ @graph = {}
+ 90.step(0, -10){|i|
+ # Coordinates of these items don't matter;
+ # they will be set properly below
+ @graph[i] = TkcLine.new(@k, 0, 0, 1, 1, :smooth=>true, :fill=>"grey#{i}")
+ }
+
+ # labels
+ @label_theta = TkcText.new(@k, 0, 0, :anchor=>:ne,
+ :text=>'q', :font=>'Symbol 8')
+ @label_dtheta = TkcText.new(@k, 0, 0, :anchor=>:ne,
+ :text=>'dq', :font=>'Symbol 8')
+
+ # pack
+ @k.pack(:fill=>:both, :expand=>true)
+
+ # Initialize some variables
+ @points = []
+ @theta = 45.0
+ @dTheta = 0.0
+ @length = 150
+
+ # animation loop
+ @timer = TkTimer.new(15){ repeat }
+
+ # binding
+ @c.bindtags_unshift(btag = TkBindTag.new)
+ btag.bind('Destroy'){ @timer.stop }
+ btag.bind('1', proc{|x, y| @timer.stop; showPendulum(x.to_i, y.to_i)},
+ '%x %y')
+ btag.bind('B1-Motion', proc{|x, y| showPendulum(x.to_i, y.to_i)}, '%x %y')
+ btag.bind('ButtonRelease-1',
+ proc{|x, y| showPendulum(x.to_i, y.to_i); @timer.start },
+ '%x %y')
+
+ btag.bind('Configure', proc{|w| @plate.coords(0, 25, w.to_i, 25)}, '%w')
+
+ @k.bind('Configure', proc{|h, w|
+ h = h.to_i
+ w = w.to_i
+ @psh = h/2;
+ @psw = w/2
+ @x_axis.coords(2, @psh, w-2, @psh)
+ @y_axis.coords(@psw, h-2, @psw, 2)
+ @label_theta.coords(@psw-4, 6)
+ @label_dtheta.coords(w-6, @psh+4)
+ }, '%h %w')
+
+ # add
+ Tk.update
+ @pane.add(@lf1)
+ @pane.add(@lf2)
+
+ # init display
+ showPendulum
+
+ # animation start
+ @timer.start(500)
+ end
+
+ # This procedure makes the pendulum appear at the correct place on the
+ # canvas. If the additional arguments x, y are passed instead of computing
+ # the position of the pendulum from the length of the pendulum rod and its
+ # angle, the length and angle are computed in reverse from the given
+ # location (which is taken to be the centre of the pendulum bob.)
+ def showPendulum(x=nil, y=nil)
+ if x && y && (x != 160 || y != 25)
+ @dTheta = 0.0
+ x2 = x - 160
+ y2 = y - 25
+ @length = Math.hypot(x2, y2)
+ @theta = Math.atan2(x2,y2)*180/Math::PI
+ else
+ angle = @theta*Math::PI/180
+ x = 160 + @length*Math.sin(angle)
+ y = 25 + @length*Math.cos(angle)
+ end
+
+ @rod.coords(160, 25, x, y)
+ @bob.coords(x-15, y-15, x+15, y+15)
+ end
+
+ # Update the phase-space graph according to the current angle and the
+ # rate at which the angle is changing (the first derivative with
+ # respect to time.)
+ def showPhase
+ unless @psw && @psh
+ @psw = @k.width/2
+ @psh = @k.height/2
+ end
+ @points << @theta + @psw << -20*@dTheta + @psh
+ if @points.length > 100
+ @points = @points[-100..-1]
+ end
+ (0...100).step(10){|i|
+ first = - i
+ last = 11 - i
+ last = -1 if last >= 0
+ next if first > last
+ lst = @points[first..last]
+ @graph[i].coords(lst) if lst && lst.length >= 4
+ }
+ end
+
+ # This procedure is the "business" part of the simulation that does
+ # simple numerical integration of the formula for a simple rotational
+ # pendulum.
+ def recomputeAngle
+ scaling = 3000.0/@length/@length
+
+ # To estimate the integration accurately, we really need to
+ # compute the end-point of our time-step. But to do *that*, we
+ # need to estimate the integration accurately! So we try this
+ # technique, which is inaccurate, but better than doing it in a
+ # single step. What we really want is bound up in the
+ # differential equation:
+ # .. - sin theta
+ # theta + theta = -----------
+ # length
+ # But my math skills are not good enough to solve this!
+
+ # first estimate
+ firstDDTheta = -Math.sin(@theta * Math::PI/180) * scaling
+ midDTheta = @dTheta + firstDDTheta
+ midTheta = @theta + (@dTheta + midDTheta)/2
+ # second estimate
+ midDDTheta = -Math.sin(midTheta * Math::PI/180) * scaling
+ midDTheta = @dTheta + (firstDDTheta + midDDTheta)/2
+ midTheta = @theta + (@dTheta + midDTheta)/2
+ # Now we do a double-estimate approach for getting the final value
+ # first estimate
+ midDDTheta = -Math.sin(midTheta * Math::PI/180) * scaling
+ lastDTheta = midDTheta + midDDTheta
+ lastTheta = midTheta + (midDTheta+ lastDTheta)/2
+ # second estimate
+ lastDDTheta = -Math.sin(lastTheta * Math::PI/180) * scaling
+ lastDTheta = midDTheta + (midDDTheta + lastDDTheta)/2
+ lastTheta = midTheta + (midDTheta + lastDTheta)/2
+ # Now put the values back in our globals
+ @dTheta = lastDTheta
+ @theta = lastTheta
+ end
+
+ # This method ties together the simulation engine and the graphical
+ # display code that visualizes it.
+ def repeat
+ # Simulate
+ recomputeAngle
+
+ # Update the display
+ showPendulum
+ showPhase
+ end
+end
+
+# Start the animation processing
+PendulumAnimationDemo.new(base_frame)
diff --git a/ext/tk/sample/demos-en/plot.rb b/ext/tk/sample/demos-en/plot.rb
index fb887011a7..628c9df584 100644
--- a/ext/tk/sample/demos-en/plot.rb
+++ b/ext/tk/sample/demos-en/plot.rb
@@ -19,14 +19,16 @@ $plot_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($plot_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($plot_demo, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
- 'text'=>"This window displays a canvas widget containing a simple 2-dimensional plot. You can doctor the data by dragging any of the points with mouse button 1."){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
+ 'text'=>"This window displays a canvas widget containing a simple 2-dimensional plot. You can doctor the data by dragging any of the points with mouse button 1."){
pack('side'=>'top')
}
# frame
-$plot_buttons = TkFrame.new($plot_demo) {|frame|
+$plot_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -47,46 +49,46 @@ $plot_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
plotFont = '-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
# canvas
-$plot_canvas = TkCanvas.new($plot_demo,'relief'=>'raised','width'=>450,'height'=>300)
+$plot_canvas = TkCanvas.new(base_frame,'relief'=>'raised','width'=>450,'height'=>300)
$plot_canvas.pack('side'=>'top', 'fill'=>'x')
# plot
TkcLine.new($plot_canvas, 100, 250, 400, 250, 'width'=>2)
TkcLine.new($plot_canvas, 100, 250, 100, 50, 'width'=>2)
TkcText.new($plot_canvas, 225, 20,
- 'text'=>"A Simple Plot", 'font'=>plotFont, 'fill'=>'brown')
+ 'text'=>"A Simple Plot", 'font'=>plotFont, 'fill'=>'brown')
(0..10).each {|i|
x = 100 + (i * 30)
TkcLine.new($plot_canvas, x, 250, x, 245, 'width'=>2)
TkcText.new($plot_canvas, x, 254,
- 'text'=>10*i, 'font'=>plotFont, 'anchor'=>'n')
+ 'text'=>10*i, 'font'=>plotFont, 'anchor'=>'n')
}
(0..5).each {|i|
y = 250 - (i * 40)
TkcLine.new($plot_canvas, 100, y, 105, y, 'width'=>2)
TkcText.new($plot_canvas, 96, y,
- 'text'=>"#{i*50}.0", 'font'=>plotFont, 'anchor'=>'e')
+ 'text'=>"#{i*50}.0", 'font'=>plotFont, 'anchor'=>'e')
}
for xx, yy in [[12,56],[20,94],[33,98],[32,120],[61,180],[75,160],[98,223]]
x = 100 + (3*xx)
y = 250 - (4*yy)/5
item = TkcOval.new($plot_canvas, x-6, y-6, x+6, y+6,
- 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
+ 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
item.addtag 'point'
end
$plot_canvas.itembind('point', 'Any-Enter',
- proc{$plot_canvas.itemconfigure 'current','fill','red'})
+ proc{$plot_canvas.itemconfigure 'current','fill','red'})
$plot_canvas.itembind('point', 'Any-Leave',
- proc{$plot_canvas.itemconfigure 'current','fill','SkyBlue2'})
+ proc{$plot_canvas.itemconfigure 'current','fill','SkyBlue2'})
$plot_canvas.itembind('point', '1',
- proc{|x,y| plotDown $plot_canvas,x,y}, "%x %y")
+ proc{|x,y| plotDown $plot_canvas,x,y}, "%x %y")
$plot_canvas.itembind('point', 'ButtonRelease-1',
- proc{$plot_canvas.dtag 'selected'})
+ proc{$plot_canvas.dtag 'selected'})
$plot_canvas.bind('B1-Motion',
- proc{|x,y| plotMove $plot_canvas,x,y}, "%x %y")
+ proc{|x,y| plotMove $plot_canvas,x,y}, "%x %y")
$plot = {'lastX'=>0, 'lastY'=>0}
@@ -95,8 +97,8 @@ $plot = {'lastX'=>0, 'lastY'=>0}
# data points. It sets up state to allow the point to be dragged.
#
# Arguments:
-# w - The canvas window.
-# x, y - The coordinates of the mouse press.
+# w - The canvas window.
+# x, y - The coordinates of the mouse press.
def plotDown (w, x, y)
w.dtag 'selected'
@@ -111,8 +113,8 @@ end
# current item.
#
# Arguments:
-# w - The canvas window.
-# x, y - The coordinates of the mouse.
+# w - The canvas window.
+# x, y - The coordinates of the mouse.
def plotMove (w, x, y)
w.move 'selected', x - $plot['lastX'], y - $plot['lastY']
diff --git a/ext/tk/sample/demos-en/puzzle.rb b/ext/tk/sample/demos-en/puzzle.rb
index d206efe34b..43c61f519f 100644
--- a/ext/tk/sample/demos-en/puzzle.rb
+++ b/ext/tk/sample/demos-en/puzzle.rb
@@ -19,8 +19,10 @@ $puzzle_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($puzzle_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($puzzle_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -29,7 +31,7 @@ msg = TkLabel.new($puzzle_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($puzzle_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -52,18 +54,27 @@ TkFrame.new($puzzle_demo) {|frame|
# scrollbar widget and using its trough color.
begin
if Tk.windowingsystem() == 'aqua'
- frameSize = 160
+ frameWidth = 168
+ frameHeight = 168
+ elsif Tk.default_widget_set == :Ttk
+ frameWidth = 148
+ frameHeight = 124
else
- frameSize = 120
+ frameWidth = 120
+ frameHeight = 120
end
rescue
- frameSize = 120
+ frameWidth = 120
+ frameHeight = 120
end
+
+# depend_on_button_width = true
+depend_on_button_width = false
-s = TkScrollbar.new($puzzle_demo)
-base = TkFrame.new($puzzle_demo) {
- width frameSize
- height frameSize
+s = TkScrollbar.new(base_frame)
+base = TkFrame.new(base_frame) {
+ width frameWidth
+ height frameHeight
borderwidth 2
relief 'sunken'
bg s['troughcolor']
@@ -87,8 +98,11 @@ order = [3,1,6,2,5,7,15,13,4,11,8,9,14,10,12]
text num
highlightthickness 0
command def_puzzleswitch_proc(w, num)
+ if depend_on_button_width && (w.winfo_reqwidth * 4 > base.width)
+ base.width = w.winfo_reqwidth * 4
+ end
}.place('relx'=>$xpos[num], 'rely'=>$ypos[num],
- 'relwidth'=>0.25, 'relheight'=>0.25)
+ 'relwidth'=>0.25, 'relheight'=>0.25)
}
$xpos['space'] = 0.75
$ypos['space'] = 0.75
@@ -105,9 +119,9 @@ def puzzleSwitch(w, num)
&& ($xpos[num] >= ($xpos['space'] - 0.26)) \
&& ($xpos[num] <= ($xpos['space'] + 0.26))) \
|| (($xpos[num] >= ($xpos['space'] - 0.01)) \
- && ($xpos[num] <= ($xpos['space'] + 0.01)) \
- && ($ypos[num] >= ($ypos['space'] - 0.26)) \
- && ($ypos[num] <= ($ypos['space'] + 0.26)))
+ && ($xpos[num] <= ($xpos['space'] + 0.01)) \
+ && ($ypos[num] >= ($ypos['space'] - 0.26)) \
+ && ($ypos[num] <= ($ypos['space'] + 0.26)))
tmp = $xpos['space']
$xpos['space'] = $xpos[num]
$xpos[num] = tmp
diff --git a/ext/tk/sample/demos-en/radio.rb b/ext/tk/sample/demos-en/radio.rb
index 96cdc4c54a..25cfac2134 100644
--- a/ext/tk/sample/demos-en/radio.rb
+++ b/ext/tk/sample/demos-en/radio.rb
@@ -19,8 +19,10 @@ $radio_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($radio_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($radio_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -33,7 +35,7 @@ size = TkVariable.new
color = TkVariable.new
# frame
-TkFrame.new($radio_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -52,14 +54,14 @@ TkFrame.new($radio_demo) {|frame|
TkButton.new(frame) {
text 'See Variables'
command proc{
- showVars($radio_demo, ['size', size], ['color', color])
+ showVars(base_frame, ['size', size], ['color', color])
}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
-f_left = TkFrame.new($radio_demo)
-f_right = TkFrame.new($radio_demo)
+f_left = TkFrame.new(base_frame)
+f_right = TkFrame.new(base_frame)
f_left.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
f_right.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
diff --git a/ext/tk/sample/demos-en/radio2.rb b/ext/tk/sample/demos-en/radio2.rb
index aefd81bdca..6c02aef0cf 100644
--- a/ext/tk/sample/demos-en/radio2.rb
+++ b/ext/tk/sample/demos-en/radio2.rb
@@ -1,4 +1,4 @@
-# radio.rb
+# radio2.rb
#
# This demonstration script creates a toplevel window containing
# several radiobutton widgets.
@@ -14,13 +14,15 @@ end
# demo toplevel widget
$radio2_demo = TkToplevel.new {|w|
- title("Radiobutton Demonstration")
- iconname("radio")
+ title("Radiobutton Demonstration 2")
+ iconname("radio2")
positionWindow(w)
}
+base_frame = TkFrame.new($radio2_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($radio2_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -34,7 +36,7 @@ color = TkVariable.new
align = TkVariable.new
# frame
-TkFrame.new($radio2_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -47,25 +49,25 @@ TkFrame.new($radio2_demo) {|frame|
TkButton.new(frame) {
text 'Show Code'
- command proc{showCode 'radio'}
+ command proc{showCode 'radio2'}
}.pack('side'=>'left', 'expand'=>'yes')
TkButton.new(frame) {
text 'See Variables'
command proc{
- showVars($radio2_demo,
- ['size', size], ['color', color], ['compound', align])
+ showVars(base_frame,
+ ['size', size], ['color', color], ['compound', align])
}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
-f_left = TkLabelFrame.new($radio2_demo, 'text'=>'Point Size',
- 'pady'=>2, 'padx'=>2)
-f_mid = TkLabelFrame.new($radio2_demo, 'text'=>'Color',
- 'pady'=>2, 'padx'=>2)
-f_right = TkLabelFrame.new($radio2_demo, 'text'=>'Alignment',
- 'pady'=>2, 'padx'=>2)
+f_left = TkLabelFrame.new(base_frame, 'text'=>'Point Size',
+ 'pady'=>2, 'padx'=>2)
+f_mid = TkLabelFrame.new(base_frame, 'text'=>'Color',
+ 'pady'=>2, 'padx'=>2)
+f_right = TkLabelFrame.new(base_frame, 'text'=>'Alignment',
+ 'pady'=>2, 'padx'=>2)
f_left.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
f_mid.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
f_right.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
@@ -90,15 +92,16 @@ f_right.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
}.pack('side'=>'top', 'pady'=>2, 'fill'=>'x')
}
-label = TkLabel.new(f_right, 'text'=>'Label', 'bitmap'=>'questhead',
- 'compound'=>'left')
+# label = TkLabel.new(f_right, 'text'=>'Label', 'bitmap'=>'questhead',
+label = Tk::Label.new(f_right, 'text'=>'Label', 'bitmap'=>'questhead',
+ 'compound'=>'left')
label.configure('width'=>TkWinfo.reqwidth(label), 'compound'=>'top')
label.height(TkWinfo.reqheight(label))
abtn = ['Top', 'Left', 'Right', 'Bottom'].collect{|a|
lower = a.downcase
TkRadioButton.new(f_right, 'text'=>a, 'variable'=>align, 'relief'=>'flat',
- 'value'=>lower, 'indicatoron'=>0, 'width'=>7,
- 'command'=>proc{label.compound(align.value)})
+ 'value'=>lower, 'indicatoron'=>0, 'width'=>7,
+ 'command'=>proc{label.compound(align.value)})
}
Tk.grid('x', abtn[0])
diff --git a/ext/tk/sample/demos-en/radio3.rb b/ext/tk/sample/demos-en/radio3.rb
new file mode 100644
index 0000000000..9c9d75ef4a
--- /dev/null
+++ b/ext/tk/sample/demos-en/radio3.rb
@@ -0,0 +1,117 @@
+# radio3.rb
+#
+# This demonstration script creates a toplevel window containing
+# several radiobutton widgets.
+#
+# radiobutton widget demo (called by 'widget')
+#
+
+# toplevel widget
+if defined?($radio3_demo) && $radio3_demo
+ $radio3_demo.destroy
+ $radio3_demo = nil
+end
+
+# demo toplevel widget
+$radio3_demo = TkToplevel.new {|w|
+ title("Radiobutton Demonstration 3")
+ iconname("radio3")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($radio3_demo).pack(:fill=>:both, :expand=>true)
+
+# label
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '5i'
+ justify 'left'
+ text "Three groups of radiobuttons are displayed below. If you click on a button then the button will become selected exclusively among all the buttons in its group. A Tcl variable is associated with each group to indicate which of the group's buttons is selected. When the 'Tristate' button is pressed, the radio buttons will display the tri-state mode. Selecting any radio button will return the buttons to their respective on/off state. Click the \"See Variables\" button to see the current values of the variables."
+}
+msg.grid(:row=>0, :column=>0, :columnspan=>3, :sticky=>'nsew')
+
+# variable
+size = TkVariable.new
+color = TkVariable.new
+align = TkVariable.new
+
+# frame
+TkFrame.new(base_frame) {|frame|
+ TkGrid(TkFrame.new(frame, :height=>2, :relief=>:sunken, :bd=>2),
+ :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ TkButton.new(frame, :text=>'See Variables',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{
+ showVars(base_frame, ['size', size],
+ ['color', color], ['compound', align])
+ }),
+ TkButton.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'radio3'}),
+ TkButton.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ tmppath = $radio3_demo
+ $radio3_demo = nil
+ $showVarsWin[tmppath.path] = nil
+ tmppath.destroy
+ }),
+ :padx=>4, :pady=>4)
+ frame.grid_columnconfigure(0, :weight=>1)
+ TkGrid(frame, :row=>3, :column=>0, :columnspan=>3, :sticky=>'nsew')
+}
+
+# frame
+f_left = TkLabelFrame.new(base_frame, 'text'=>'Point Size',
+ 'pady'=>2, 'padx'=>2)
+f_mid = TkLabelFrame.new(base_frame, 'text'=>'Color',
+ 'pady'=>2, 'padx'=>2)
+f_right = TkLabelFrame.new(base_frame, 'text'=>'Alignment',
+ 'pady'=>2, 'padx'=>2)
+f_left .grid('column'=>0, 'row'=>1, 'pady'=>'.5c', 'padx'=>'.5c', 'rowspan'=>2)
+f_mid .grid('column'=>1, 'row'=>1, 'pady'=>'.5c', 'padx'=>'.5c', 'rowspan'=>2)
+f_right.grid('column'=>2, 'row'=>1, 'pady'=>'.5c', 'padx'=>'.5c')
+
+TkButton.new(base_frame, 'text'=>'Tristate',
+ 'command'=>proc{size.value = 'multi'; color.value = 'multi'}){
+ grid('column'=>2, 'row'=>2, 'pady'=>'.5c', 'padx'=>'.5c')
+}
+
+# radiobutton
+[10, 12, 14, 18, 24].each {|sz|
+ TkRadioButton.new(f_left) {
+ text "Point Size #{sz}"
+ variable size
+ relief 'flat'
+ value sz
+ tristatevalue 'multi'
+ }.pack('side'=>'top', 'pady'=>2, 'anchor'=>'w', 'fill'=>'x')
+}
+
+['Red', 'Green', 'Blue', 'Yellow', 'Orange', 'Purple'].each {|col|
+ TkRadioButton.new(f_mid) {
+ text col
+ variable color
+ relief 'flat'
+ value col.downcase
+ anchor 'w'
+ tristatevalue 'multi'
+ command proc{f_mid.fg(color.value)}
+ }.pack('side'=>'top', 'pady'=>2, 'fill'=>'x')
+}
+
+# label = TkLabel.new(f_right, 'text'=>'Label', 'bitmap'=>'questhead',
+label = Tk::Label.new(f_right, 'text'=>'Label', 'bitmap'=>'questhead',
+ 'compound'=>'left')
+label.configure('width'=>TkWinfo.reqwidth(label), 'compound'=>'top')
+label.height(TkWinfo.reqheight(label))
+a_btn = ['Top', 'Left', 'Right', 'Bottom'].collect{|a|
+ TkRadioButton.new(f_right, 'text'=>a, 'variable'=>align, 'relief'=>'flat',
+ 'value'=>a.downcase, 'indicatoron'=>0, 'width'=>7,
+ 'command'=>proc{label.compound(align.value)})
+}
+
+Tk.grid('x', a_btn[0])
+Tk.grid(a_btn[1], label, a_btn[2])
+Tk.grid('x', a_btn[3])
diff --git a/ext/tk/sample/demos-en/rolodex-j b/ext/tk/sample/demos-en/rolodex-j
deleted file mode 100644
index 27e2bc9da0..0000000000
--- a/ext/tk/sample/demos-en/rolodex-j
+++ /dev/null
@@ -1,323 +0,0 @@
-#!/usr/bin/env ruby
-#
-# rolodex --
-# ¤³¤Î¥¹¥¯¥ê¥×¥È¤Ï Tom LaStrange ¤Î rolodex ¤Î°ìÉô¤Ç¤¹¡£
-#
-# Copyright (C) 1998 by Takaaki Tateishi <ttate@jaist.ac.jp>
-# Time-stamp: "03/08/02 14:02:04 nagai"
-#
-
-require "tk"
-
-Tk.encoding = "euc-jp"
-$font = TkFont.new('k14')
-
-def show_help(topic,x=0,y=0)
- if( topic.is_a?(TkWindow) )
- w = TkWinfo.containing(x,y)
- if( w.is_a?(TkWindow) )
- if( TkWinfo.exist?(w) )
- topic = w
- end
- end
- end
-
- if( $helpTopics.include?(topic) )
- msg = $helpTopics[topic]
- else
- msg = "¤³¤Î¥È¥Ô¥Ã¥¯¤Ë¤Ä¤¤¤Æ¤Î¥Ø¥ë¥×¤Ï¤Þ¤À»ÈÍѤǤ­¤Þ¤»¤ó"
- end
- TkDialog.new("title"=>"Rolodex Help",
- "message"=>"¡Ö#{topic}¡×\n\n#{msg}",
- "font"=>$font,
- "default_button"=>0,
- "buttons"=>["OK"])
-end
-
-def fillCard
- clearAction
- $root.frame.entry[1].insert(0, "ΩÀÐ ¹§¾´")
- $root.frame.entry[2].insert(0, "923-1292 ÀÐÀ")
- $root.frame.entry[3].insert(0, "ä¸ýÄ® °°Âæ 1-1")
- $root.frame.entry[4].insert(0, "ËÌΦÀèü²Ê³Øµ»½ÑÂç³Ø±¡Âç³Ø")
- $root.frame.entry[5].insert(0,"private")
- $root.frame.entry[6].insert(0,"***-***-****")
- $root.frame.entry[7].insert(0,"***-***-****")
-end
-
-def addAction
- for i in 1..7
- STDERR.print format("%-12s %s\n",
- RolodexFrame::LABEL[i],
- $root.frame.entry[i].value)
- end
-end
-
-def clearAction
- for i in 1..7
- $root.frame.entry[i].delete(0,"end")
- end
-end
-
-def fileAction
- TkDialog.new("title"=>"File Selection",
- "message"=>"¤³¤ì¤Ï¥Õ¥¡¥¤¥ëÁªÂò¥À¥¤¥¢¥í¥°¤Î¥À¥ß¡¼¤Ç¤¹¡£\n",
- "font"=>$font,
- "default_button"=>0,
- "buttons"=>["OK"])
- STDERR.print "dummy file name\n"
-end
-
-def deleteAction
- result = TkDialog.new("title"=>"Confirm Action",
- "message"=>"¤è¤í¤·¤¤¤Ç¤¹¤«¡©",
- "font"=>$font,
- "default_button"=>0,
- "buttons"=>["¥­¥ã¥ó¥»¥ë"])
- if( result.value == 0 )
- clearAction
- end
-end
-
-
-class RolodexFrame < TkFrame
- attr_reader :entry, :label
-
- LABEL = ["","̾Á°:","½»½ê","","","ÅÅÏÃ(¼«Âð):","ÅÅÏÃ(²ñ¼Ò):","Fax:"]
-
- def initialize(parent=nil,keys=nil)
- super(parent,keys)
- self["relief"] = "flat"
- @i = []
- @label = []
- @entry = []
- for i in 1..7
- @i[i] = TkFrame.new(self)
- @i[i].pack("side"=>"top",
- "pady"=>2,
- "anchor"=>"e")
- @label[i] = TkLabel.new(@i[i],
- "text"=>LABEL[i],
- "anchor"=>"e",
- "font" => $font)
- @entry[i] = TkEntry.new(@i[i],
- "width"=>30,
- "relief"=>"sunken",
- "font" => $font)
- @entry[i].pack("side"=>"right")
- @label[i].pack("side"=>"right")
- end
- end
-end
-
-class RolodexButtons < TkFrame
- attr_reader :clear, :add, :search, :delete
-
- def initialize(parent,keys=nil)
- super(parent,keys)
- @clear = TkButton.new(self,
- "text" => "¥¯¥ê¥¢¡¼",
- "font" => $font)
- @add = TkButton.new(self,
- "text" => "ÄɲÃ",
- "font" => $font)
- @search = TkButton.new(self,
- "text" => "¸¡º÷",
- "font" => $font)
- @delete = TkButton.new(self,
- "text" => "¾Ãµî",
- "font" => $font)
- for w in [@clear,@add,@search,@delete]
- w.pack("side"=>"left", "padx"=>2)
- end
- end
-end
-
-class RolodexMenuFrame < TkFrame
- attr_reader :file_menu, :help_menu, :file, :help
-
- def initialize(parent,keys=nil)
- super(parent,keys)
- configure("relief"=>"raised",
- "borderwidth"=>1)
-
- @file = TkMenubutton.new(self,
- "text"=> "¥Õ¥¡¥¤¥ë",
- "font"=> $font,
- "underline"=>0)
- @file_menu = TkMenu.new(@file)
- @file_menu.add("command",
- "label" => "ÆÉ¤ß¹þ¤ß ...",
- "font" => $font,
- "command" => proc{fileAction},
- "underline" => 0)
- @file_menu.add("command",
- "label" => "½ªÎ»",
- "font" => $font,
- "command" => proc{$root.destroy},
- "underline" => 0)
- @file.menu(@file_menu)
- @file.pack("side"=>"left")
-
- @help = TkMenubutton.new(self,
- "text"=> "¥Ø¥ë¥×",
- "font"=> $font,
- "underline"=>0)
- @help_menu = TkMenu.new(@help)
- @help_menu.add("command",
- "label"=> "¥³¥ó¥Æ¥­¥¹¥È¤Ë¤Ä¤¤¤Æ",
- "font" => $font,
- "command"=>proc{show_help("¥³¥ó¥Æ¥­¥¹¥È")},
- "underline"=>3)
- @help_menu.add("command",
- "label"=> "¥Ø¥ë¥×¤Ë¤Ä¤¤¤Æ",
- "font" => $font,
- "command"=>proc{show_help("¥Ø¥ë¥×")},
- "underline"=>3)
- @help_menu.add("command",
- "label"=> "¥¦¥£¥ó¥É¥¦¤Ë¤Ä¤¤¤Æ",
- "font" => $font,
- "command"=>proc{show_help("¥¦¥£¥ó¥É¥¦")},
- "underline"=>3)
- @help_menu.add("command",
- "label"=> "¥­¡¼Áàºî¤Ë¤Ä¤¤¤Æ",
- "font" => $font,
- "command"=>proc{show_help("¥­¡¼Áàºî")},
- "underline"=>3)
- @help_menu.add("command",
- "label"=> "¥Ð¡¼¥¸¥ç¥ó¾ðÊó",
- "font" => $font,
- "command"=>proc{show_help("¥Ð¡¼¥¸¥ç¥ó¾ðÊó")},
- "underline"=>3)
- @help.menu(@help_menu)
- @help.pack("side"=>"right")
- end
-end
-
-class Rolodex < TkRoot
- attr_reader :frame, :buttons, :menu
-
- def initialize(*args)
- super(*args)
- @frame = RolodexFrame.new(self)
- @frame.pack("side"=>"top",
- "fill"=>"y",
- "anchor"=>"center")
- @buttons = RolodexButtons.new(self)
- @buttons.pack("side"=>"bottom",
- "pady"=>2,
- "anchor"=>"center")
- @menu = RolodexMenuFrame.new(self)
- @menu.pack("before"=>@frame,
- "side"=>"top",
- "fill"=>"x")
- end
-end
-
-$root = Rolodex.new
-
-$root.buttons.delete.configure("command"=>proc{deleteAction})
-$root.buttons.add.configure("command"=>proc{addAction})
-$root.buttons.clear.configure("command"=>proc{clearAction})
-$root.buttons.search.configure("command"=>proc{addAction; fillCard})
-
-$root.buttons.clear.configure("text"=> "¥¯¥ê¥¢¡¼ Ctrl+C", "font" => $font)
-$root.bind("Control-c",proc{clearAction})
-
-$root.buttons.add.configure("text"=> "Äɲà Ctrl+A", "font" => $font)
-$root.bind("Control-a",proc{addAction})
-
-$root.buttons.search.configure("text"=> "¸¡º÷ Ctrl+S", "font" => $font)
-$root.bind("Control-s",proc{addAction; fillCard})
-
-$root.buttons.delete.configure("text"=> "¾Ãµî Ctrl+D", "font" => $font)
-$root.bind("Control-d",proc{deleteAction})
-
-$root.menu.file_menu.entryconfigure(1, "accel"=>"Ctrl+F")
-$root.bind("Control-f",proc{fileAction})
-
-$root.menu.file_menu.entryconfigure(2, "accel"=>"Ctrl+Q")
-$root.bind("Control-q",proc{$root.destroy})
-
-$root.frame.entry[1].focus
-
-$root.bind("Any-F1",
- proc{|event| show_help(event.widget, event.x_root, event.y_root)})
-$root.bind("Any-Help",
- proc{|event| show_help(event.widget, event.x_root, event.y_root)})
-
-
-$helpTopics = {}
-
-$helpTopics[$root.menu.file] = <<EOF
-¤³¤ì¤Ï¡Ö¥Õ¥¡¥¤¥ë¡×¥á¥Ë¥å¡¼¤Ç¤¹¡£¡ÖÆÉ¤ß¹þ¤ß¡×¤ä¡Ö½ªÎ»¡×¤Ê¤É¤ò
-¹Ô¤Ê¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£
-EOF
-
-$helpTopics[$root.menu.file_menu.index(0)] = <<EOF
-¥Õ¥¡¥¤¥ë¤ÎÆÉ¤ß¹þ¤ß¤ò¹Ô¤Ê¤¦¤È¤­¤Ë»È¤¤¤Þ¤¹¡£
-EOF
-
-$helpTopics[$root.menu.file_menu.index(1)] = <<EOF
-¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ò½ªÎ»¤¹¤ë¤È¤­¤Ë»È¤¤¤Þ¤¹¡£
-EOF
-
-$helpTopics[$root.frame.entry[1]] = <<EOF
-̾Á°¤òµ­Æþ¤¹¤ë¥¨¥ó¥È¥ê¤Ç¤¹¡£
-EOF
-
-$helpTopics[$root.frame.entry[2]] = <<EOF
-½»½ê¤òµ­Æþ¤¹¤ë¥¨¥ó¥È¥ê¤Ç¤¹¡£
-EOF
-
-$helpTopics[$root.frame.entry[3]] = <<EOF
-½»½ê¤òµ­Æþ¤¹¤ë¥¨¥ó¥È¥ê¤Ç¤¹¡£
-EOF
-
-$helpTopics[$root.frame.entry[4]] = <<EOF
-½»½ê¤òµ­Æþ¤¹¤ë¥¨¥ó¥È¥ê¤Ç¤¹¡£
-EOF
-
-$helpTopics[$root.frame.entry[5]] = <<EOF
-¼«Âð¤ÎÅÅÏÃÈÖ¹æ¤òµ­Æþ¤¹¤ë¥¨¥ó¥È¥ê¤Ç¤¹¡£¸ø³«\
-¤·¤¿¤¯¤Ê¤¤¤È¤­¤Ï private ¤Èµ­Æþ¤·¤Þ¤¹¡£
-EOF
-
-$helpTopics[$root.frame.entry[6]] = <<EOF
-²ñ¼Ò¤ÎÅÅÏÃÈÖ¹æ¤òµ­Æþ¤¹¤ë¥¨¥ó¥È¥ê¤Ç¤¹¡£
-EOF
-
-$helpTopics[$root.frame.entry[7]] = <<EOF
-FAXÈÖ¹æ¤òµ­Æþ¤¹¤ë¥¨¥ó¥È¥ê¤Ç¤¹¡£
-EOF
-
-$helpTopics["¥³¥ó¥Æ¥­¥¹¥È"] = <<EOF
-Ruby/Tk¤Ç¤Ïgrab¤Îµ¡¹½¤¬¤Ê¤¤¤¿¤á¤³¤Î¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Ç¤Ï\
-¥³¥ó¥Æ¥­¥¹¥È¥Ø¥ë¥×¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó¡£
-¤·¤«¤·Æ±¤¸¤è¤¦¤Ê¸ú²Ì¤òbind¤È¥Þ¥¦¥¹¤Î°ÌÃÖ¤ÎWedget¤òÃΤë\
-¤³¤È¤ÇÆÀ¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£
-EOF
-
-$helpTopics["¥Ø¥ë¥×"] = <<EOF
-¥Þ¥¦¥¹¤ò¥¦¥£¥ó¥É¥¦¤Ë¤¢¤ï¤»¤ÆF1¥­¡¼¤ò²¡¤¹¤³¤È¤Ë¤è¤Ã¤Æ\
-¤½¤Î¥Ø¥ë¥×¤ò¸«¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£
-EOF
-
-$helpTopics["¥¦¥£¥ó¥É¥¦"] = <<EOF
-¤³¤Î¥¦¥£¥ó¥É¥¦¤Ï¥À¥ß¡¼¤Ç¤¹¡£
-EOF
-
-$helpTopics["¥­¡¼Áàºî"] = <<EOF
-Ctrl+A: ÄɲÃ
-Ctrl+C: ¥¯¥ê¥¢¡¼
-Ctrl+D: ¾Ãµî
-Ctrl+F: ¥Õ¥¡¥¤¥ëÁªÂò
-Ctrl+Q: ½ªÎ»
-Ctrl+S: ¸¡º÷
-EOF
-
-$helpTopics["¥Ð¡¼¥¸¥ç¥ó¾ðÊó"] = <<EOF
-¥Ð¡¼¥¸¥ç¥ó¤Ï 1.0.1e ¤Ç¤¹¡£
-EOF
-
-Tk.mainloop
diff --git a/ext/tk/sample/demos-en/ruler.rb b/ext/tk/sample/demos-en/ruler.rb
index f5e7add516..26cd4f3b1c 100644
--- a/ext/tk/sample/demos-en/ruler.rb
+++ b/ext/tk/sample/demos-en/ruler.rb
@@ -11,8 +11,8 @@
# represent a tab stop.
#
# Arguments:
-# c - The canvas window.
-# x, y - Coordinates at which to create the tab stop.
+# c - The canvas window.
+# x, y - Coordinates at which to create the tab stop.
def rulerMkTab(c,x,y)
v = $demo_rulerInfo
@@ -32,14 +32,16 @@ $ruler_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($ruler_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($ruler_demo, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
- 'text'=>"This canvas widget shows a mock-up of a ruler. You can create tab stops by dragging them out of the well to the right of the ruler. You can also drag existing tab stops. If you drag a tab stop far enough up or down so that it turns dim, it will be deleted when you release the mouse button."){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
+ 'text'=>"This canvas widget shows a mock-up of a ruler. You can create tab stops by dragging them out of the well to the right of the ruler. You can also drag existing tab stops. If you drag a tab stop far enough up or down so that it turns dim, it will be deleted when you release the mouse button."){
pack('side'=>'top')
}
# frame
-$ruler_buttons = TkFrame.new($ruler_demo) {|frame|
+$ruler_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -57,14 +59,14 @@ $ruler_buttons = TkFrame.new($ruler_demo) {|frame|
$ruler_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# canvas
-$ruler_canvas = TkCanvas.new($ruler_demo, 'width'=>'14.8c', 'height'=>'2.5c')
+$ruler_canvas = TkCanvas.new(base_frame, 'width'=>'14.8c', 'height'=>'2.5c')
$ruler_canvas.pack('side'=>'top', 'fill'=>'x')
#
unless Struct.const_defined?("RulerInfo")
$demo_rulerInfo = Struct.new("RulerInfo", :grid, :left, :right, :x, :y,
- :top, :bottom, :size, :normalStyle,
- :activeStyle, :deleteStyle).new
+ :top, :bottom, :size, :normalStyle,
+ :activeStyle, :deleteStyle).new
end
$demo_rulerInfo.grid = '.25c'
$demo_rulerInfo.left = TkWinfo.fpixels($ruler_canvas, '1c')
@@ -76,15 +78,17 @@ $demo_rulerInfo.normalStyle = {'fill'=>'black'}
if TkWinfo.depth($ruler_canvas) > 1
$demo_rulerInfo.activeStyle = {'fill'=>'red', 'stipple'=>''}
$demo_rulerInfo.deleteStyle = {'fill'=>'red',
- 'stipple'=>'@'+[$demo_dir, 'images', 'gray25.xbm'].join(File::Separator)}
+ 'stipple'=>'@'+[$demo_dir, '..',
+ 'images', 'gray25.xbm'].join(File::Separator)}
else
$demo_rulerInfo.activeStyle = {'fill'=>'black', 'stipple'=>''}
$demo_rulerInfo.deleteStyle = {'fill'=>'black',
- 'stipple'=>'@'+[$demo_dir, 'images', 'gray25.xbm'].join(File::Separator)}
+ 'stipple'=>'@'+[$demo_dir, '..',
+ 'images', 'gray25.xbm'].join(File::Separator)}
end
TkcLine.new($ruler_canvas,
- '1c', '0.5c', '1c', '1c', '13c', '1c', '13c', '0.5c', 'width'=>1)
+ '1c', '0.5c', '1c', '1c', '13c', '1c', '13c', '0.5c', 'width'=>1)
(0..11).each{|i|
x = i+1
TkcLine.new($ruler_canvas, "#{x}c", '1c', "#{x}c", '0.6c', 'width'=>1)
@@ -97,22 +101,22 @@ TkcLine.new($ruler_canvas,
$rulerTag_well = TkcTag.new($ruler_canvas)
$ruler_canvas\
.addtag_withtag($rulerTag_well,
- TkcRectangle.new($ruler_canvas,
- '13.2c', '1c', '13.8c', '0.5c',
- 'outline'=>'black',
- 'fill'=>($ruler_canvas\
- .configinfo('background'))[4]) )
+ TkcRectangle.new($ruler_canvas,
+ '13.2c', '1c', '13.8c', '0.5c',
+ 'outline'=>'black',
+ 'fill'=>($ruler_canvas\
+ .configinfo('background'))[4]) )
$ruler_canvas\
.addtag_withtag($rulerTag_well,
- rulerMkTab($ruler_canvas,
- TkWinfo.pixels($ruler_canvas, '13.5c'),
- TkWinfo.pixels($ruler_canvas, '.65c') ) )
+ rulerMkTab($ruler_canvas,
+ TkWinfo.pixels($ruler_canvas, '13.5c'),
+ TkWinfo.pixels($ruler_canvas, '.65c') ) )
$rulerTag_well.bind('1', proc{|x,y| rulerNewTab($ruler_canvas,x,y)}, '%x %y')
$ruler_canvas.itembind('tab', '1',
- proc{|x,y| rulerSelectTab($ruler_canvas,x,y)}, '%x %y')
+ proc{|x,y| rulerSelectTab($ruler_canvas,x,y)}, '%x %y')
$ruler_canvas.bind('B1-Motion',
- proc{|x,y| rulerMoveTab($ruler_canvas,x,y)}, '%x %y')
+ proc{|x,y| rulerMoveTab($ruler_canvas,x,y)}, '%x %y')
$ruler_canvas.bind('Any-ButtonRelease-1', proc{rulerReleaseTab($ruler_canvas)})
# rulerNewTab --
@@ -120,8 +124,8 @@ $ruler_canvas.bind('Any-ButtonRelease-1', proc{rulerReleaseTab($ruler_canvas)})
# triangle object and adding tags to it to give it tab behavior.
#
# Arguments:
-# c - The canvas window.
-# x, y - The coordinates of the tab stop.
+# c - The canvas window.
+# x, y - The coordinates of the tab stop.
def rulerNewTab(c,x,y)
v = $demo_rulerInfo
@@ -138,9 +142,9 @@ end
# be dragged interactively.
#
# Arguments:
-# c - The canvas widget.
-# x, y - The coordinates of the mouse (identifies the point by
-# which the tab was picked up for dragging).
+# c - The canvas widget.
+# x, y - The coordinates of the mouse (identifies the point by
+# which the tab was picked up for dragging).
def rulerSelectTab(c,x,y)
v = $demo_rulerInfo
@@ -157,8 +161,8 @@ end
# it is about to be dragged out of the ruler.
#
# Arguments:
-# c - The canvas widget.
-# x, y - The coordinates of the mouse.
+# c - The canvas widget.
+# x, y - The coordinates of the mouse.
def rulerMoveTab(c,x,y)
v = $demo_rulerInfo
@@ -185,8 +189,8 @@ end
# it was dragged out of the ruler.
#
# Arguments:
-# c - The canvas widget.
-# x, y - The coordinates of the mouse.
+# c - The canvas widget.
+# x, y - The coordinates of the mouse.
def rulerReleaseTab(c)
v = $demo_rulerInfo
diff --git a/ext/tk/sample/demos-en/sayings.rb b/ext/tk/sample/demos-en/sayings.rb
index 4ba3097bed..06ec7c1e75 100644
--- a/ext/tk/sample/demos-en/sayings.rb
+++ b/ext/tk/sample/demos-en/sayings.rb
@@ -20,8 +20,10 @@ $sayings_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($sayings_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($sayings_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -30,7 +32,7 @@ msg = TkLabel.new($sayings_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($sayings_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -49,7 +51,7 @@ TkFrame.new($sayings_demo) {|frame|
# frame
sayings_lbox = nil
-TkFrame.new($sayings_demo, 'borderwidth'=>10) {|w|
+TkFrame.new(base_frame, 'borderwidth'=>10) {|w|
sv = TkScrollbar.new(w)
sh = TkScrollbar.new(w, 'orient'=>'horizontal')
sayings_lbox = TkListbox.new(w) {
@@ -69,11 +71,11 @@ TkFrame.new($sayings_demo, 'borderwidth'=>10) {|w|
else
sayings_lbox.grid('row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
sv.grid('row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
sh.grid('row'=>1, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
TkGrid.rowconfigure(w, 0, 'weight'=>1, 'minsize'=>0)
TkGrid.columnconfigure(w, 0, 'weight'=>1, 'minsize'=>0)
end
diff --git a/ext/tk/sample/demos-en/search.rb b/ext/tk/sample/demos-en/search.rb
index 2b27cdbb42..e1fc565e9d 100644
--- a/ext/tk/sample/demos-en/search.rb
+++ b/ext/tk/sample/demos-en/search.rb
@@ -13,9 +13,9 @@
# not affected, however.
#
# Arguments:
-# w - The window into which to load the file. Must be a
-# text widget.
-# file - The name of the file to load. Must be readable.
+# w - The window into which to load the file. Must be a
+# text widget.
+# file - The name of the file to load. Must be readable.
def textLoadFile(w,file)
w.delete('1.0', 'end')
@@ -31,10 +31,10 @@ end
# apply a given tag to each instance found.
#
# Arguments:
-# w - The window in which to search. Must be a text widget.
-# string - The string to search for. The search is done using
-# exact matching only; no special characters.
-# tag - Tag to apply to each instance of a matching string.
+# w - The window in which to search. Must be a text widget.
+# string - The string to search for. The search is done using
+# exact matching only; no special characters.
+# tag - Tag to apply to each instance of a matching string.
def textSearch(w, string, tag)
tag.remove('0.0', 'end')
@@ -55,15 +55,15 @@ end
# deleted) then it doesn't reschedule itself.
#
# Arguments:
-# cmd1 - Command to execute when method is called.
-# sleep1 - Ms to sleep after executing cmd1 before executing cmd2.
-# cmd2 - Command to execute in the *next* invocation of this method.
-# sleep2 - Ms to sleep after executing cmd2 before executing cmd1 again.
+# cmd1 - Command to execute when method is called.
+# sleep1 - Ms to sleep after executing cmd1 before executing cmd2.
+# cmd2 - Command to execute in the *next* invocation of this method.
+# sleep2 - Ms to sleep after executing cmd2 before executing cmd1 again.
def textToggle(cmd1,sleep1,cmd2,sleep2)
sleep_list = [sleep2, sleep1]
TkAfter.new(proc{sleep = sleep_list.shift; sleep_list.push(sleep); sleep},
- -1, cmd1, cmd2).start(sleep1)
+ -1, cmd1, cmd2).start(sleep1)
end
# toplevel widget
@@ -79,8 +79,10 @@ $search_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($search_demo).pack(:fill=>:both, :expand=>true)
+
# frame
-$search_buttons = TkFrame.new($search_demo) {|frame|
+$search_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -98,95 +100,88 @@ $search_buttons = TkFrame.new($search_demo) {|frame|
$search_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
-TkFrame.new($search_demo) {|f|
+TkFrame.new(base_frame) {|f|
TkLabel.new(f, 'text'=>'File name:',
- 'width'=>13, 'anchor'=>'w').pack('side'=>'left')
+ 'width'=>13, 'anchor'=>'w').pack('side'=>'left')
$search_fileName = TkVariable.new
TkEntry.new(f, 'width'=>40,
- 'textvariable'=>$search_fileName) {
+ 'textvariable'=>$search_fileName) {
pack('side'=>'left')
bind('Return', proc{textLoadFile($search_text, $search_fileName.value)
- $search_string_entry.focus})
+ $search_string_entry.focus})
focus
}
TkButton.new(f, 'text'=>'Load File',
- 'command'=>proc{textLoadFile($search_text,
- $search_fileName.value)})\
+ 'command'=>proc{textLoadFile($search_text,
+ $search_fileName.value)})\
.pack('side'=>'left', 'pady'=>5, 'padx'=>10)
}.pack('side'=>'top', 'fill'=>'x')
-TkFrame.new($search_demo) {|f|
+TkFrame.new(base_frame) {|f|
TkLabel.new(f, 'text'=>'Search string:',
- 'width'=>13, 'anchor'=>'w').pack('side'=>'left')
+ 'width'=>13, 'anchor'=>'w').pack('side'=>'left')
$search_searchString = TkVariable.new
$search_string_entry = TkEntry.new(f, 'width'=>40,
- 'textvariable'=>$search_searchString) {
+ 'textvariable'=>$search_searchString) {
pack('side'=>'left')
bind('Return', proc{textSearch($search_text, $search_searchString.value,
- $search_Tag)})
+ $search_Tag)})
}
TkButton.new(f, 'text'=>'Highlight',
- 'command'=>proc{textSearch($search_text,
- $search_searchString.value,
- $search_Tag)}) {
+ 'command'=>proc{textSearch($search_text,
+ $search_searchString.value,
+ $search_Tag)}) {
pack('side'=>'left', 'pady'=>5, 'padx'=>10)
}
}.pack('side'=>'top', 'fill'=>'x')
-$search_text = TkText.new($search_demo, 'setgrid'=>true) {|t|
+$search_text = TkText.new(base_frame, 'setgrid'=>true, 'wrap'=>'word') {|t|
$search_Tag = TkTextTag.new(t)
- TkScrollbar.new($search_demo, 'command'=>proc{|*args| t.yview(*args)}) {|sc|
+ TkScrollbar.new(base_frame, 'command'=>proc{|*args| t.yview(*args)}) {|sc|
t.yscrollcommand(proc{|first,last| sc.set first,last})
pack('side'=>'right', 'fill'=>'y')
}
pack('expand'=>'yes', 'fill'=>'both')
-}
+}
# Set up display styles for text highlighting.
if TkWinfo.depth($search_demo) > 1
textToggle(proc{
- begin
- $search_Tag.configure('background'=>'#ce5555',
- 'foreground'=>'white')
- rescue
- end
- },
- 800,
- proc{
- begin
- $search_Tag.configure('background'=>'', 'foreground'=>'')
- rescue
- end
- },
- 200 )
+ $search_Tag.configure('background'=>'#ce5555',
+ 'foreground'=>'white')
+ },
+ 800,
+ proc{
+ $search_Tag.configure('background'=>'', 'foreground'=>'')
+ },
+ 200 )
else
textToggle(proc{
- begin
- $search_Tag.configure('background'=>'black',
- 'foreground'=>'white')
- rescue
- end
- },
- 800,
- proc{
- begin
- $search_Tag.configure('background'=>'', 'foreground'=>'')
- rescue
- end
- },
- 200 )
+ $search_Tag.configure('background'=>'black',
+ 'foreground'=>'white')
+ },
+ 800,
+ proc{
+ $search_Tag.configure('background'=>'', 'foreground'=>'')
+ },
+ 200 )
end
-$search_text.insert('1.0', '\
-This window demonstrates how to use the tagging facilities in text
-widgets to implement a searching mechanism. First, type a file name
-in the top entry, then type <Return> or click on "Load File". Then
-type a string in the lower entry and type <Return> or click on
-"Load File". This will cause all of the instances of the string to
-be tagged with the tag "search", and it will arrange for the tag\'s
-display attributes to change to make all of the strings blink.')
+$search_text.insert('1.0', "\
+This window demonstrates how to use the tagging facilities in text \
+widgets to implement a searching mechanism. First, type a file name \
+in the top entry, then type <Return> or click on \"Load File\". Then \
+type a string in the lower entry and type <Return> or click on \
+\"Load File\". This will cause all of the instances of the string to \
+be tagged with the tag \"search\", and it will arrange for the tag\'s \
+display attributes to change to make all of the strings blink.")
+$search_text.insert('end', "\
+The current directory to load a file is \"#{Dir.pwd}\".\
+")
$search_text.set_insert '0.0'
$search_fileName.value = ''
$search_searchString.value = ''
+$search_text.width = 60
+$search_text.height = 20
diff --git a/ext/tk/sample/demos-en/spin.rb b/ext/tk/sample/demos-en/spin.rb
index 5d32454170..c2a3a8949b 100644
--- a/ext/tk/sample/demos-en/spin.rb
+++ b/ext/tk/sample/demos-en/spin.rb
@@ -15,9 +15,11 @@ $spin_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($spin_demo,
- :font=>$font, :wraplength=>'5i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+base_frame = TkFrame.new($spin_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'5i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
Three different spin-boxes are displayed below. \
You can add characters by pointing, clicking and typing. \
The normal Motif editing characters are supported, along with \
@@ -34,17 +36,17 @@ this demo doesn't work. Please use later version of Tk \
which supports a 'spinbox' widget.
EOL
-TkFrame.new($spin_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
TkButton.new(f, :text=>'Dismiss', :width=>15, :command=>proc{
- $spin_demo.destroy
- $spin_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ $spin_demo.destroy
+ $spin_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'See Code', :width=>15, :command=>proc{
- showCode 'spin'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'spin'
+ }).pack(:side=>:left, :expand=>true)
}
australianCities = [
@@ -53,11 +55,11 @@ australianCities = [
]
[
- TkSpinbox.new($spin_demo, :from=>1, :to=>10, :width=>10, :validate=>:key,
- :validatecommand=>[
- proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
- ]),
- TkSpinbox.new($spin_demo, :from=>0, :to=>3, :increment=>0.5,
- :format=>'%05.2f', :width=>10),
- TkSpinbox.new($spin_demo, :values=>australianCities, :width=>10)
+ TkSpinbox.new(base_frame, :from=>1, :to=>10, :width=>10, :validate=>:key,
+ :validatecommand=>[
+ proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
+ ]),
+ TkSpinbox.new(base_frame, :from=>0, :to=>3, :increment=>0.5,
+ :format=>'%05.2f', :width=>10),
+ TkSpinbox.new(base_frame, :values=>australianCities, :width=>10)
].each{|sbox| sbox.pack(:side=>:top, :pady=>5, :padx=>10)}
diff --git a/ext/tk/sample/demos-en/states.rb b/ext/tk/sample/demos-en/states.rb
index d38c1245af..add0e84800 100644
--- a/ext/tk/sample/demos-en/states.rb
+++ b/ext/tk/sample/demos-en/states.rb
@@ -19,8 +19,10 @@ $states_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($states_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($states_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -29,7 +31,7 @@ msg = TkLabel.new($states_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($states_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -48,7 +50,7 @@ TkFrame.new($states_demo) {|frame|
# frame
states_lbox = nil
-TkFrame.new($states_demo, 'borderwidth'=>'.5c') {|w|
+TkFrame.new(base_frame, 'borderwidth'=>'.5c') {|w|
s = TkScrollbar.new(w)
states_lbox = TkListbox.new(w) {
setgrid 1
diff --git a/ext/tk/sample/demos-en/style.rb b/ext/tk/sample/demos-en/style.rb
index 8bf9c09662..c2fed23926 100644
--- a/ext/tk/sample/demos-en/style.rb
+++ b/ext/tk/sample/demos-en/style.rb
@@ -19,8 +19,10 @@ $style_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($style_demo).pack(:fill=>:both, :expand=>true)
+
# frame
-TkFrame.new($style_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -37,13 +39,14 @@ TkFrame.new($style_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# text
-TkText.new($style_demo){|t|
+txt = TkText.new(base_frame){|t|
#
setgrid 'true'
- width 70
- height 32
+ #width 70
+ #height 32
wrap 'word'
- TkScrollbar.new($style_demo) {|s|
+ font $font
+ TkScrollbar.new(base_frame) {|s|
pack('side'=>'right', 'fill'=>'y')
command proc{|*args| t.yview(*args)}
t.yscrollcommand proc{|first,last| s.set first,last}
@@ -51,11 +54,20 @@ TkText.new($style_demo){|t|
pack('expand'=>'yes', 'fill'=>'both')
#
- style_tag_bold = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-O-Normal--*-120-*-*-*-*-*-*')
- style_tag_big = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*', 'kanjifont'=>$msg_kanji_font)
+ family = 'Courier'
+
+ if $tk_version =~ /^4.*/
+ style_tag_bold = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-O-Normal--*-120-*-*-*-*-*-*')
+ style_tag_big = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*', 'kanjifont'=>$msg_kanji_font)
style_tag_verybig = TkTextTag.new(t, 'font'=>'-*-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*')
-# style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*', 'kanjifont'=>$kanji_font)
+ # style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*', 'kanjifont'=>$kanji_font)
style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*')
+ else
+ style_tag_bold = TkTextTag.new(t, 'font'=>[family, 12, :bold, :italic])
+ style_tag_big = TkTextTag.new(t, 'font'=>[family, 14, :bold])
+ style_tag_verybig = TkTextTag.new(t, 'font'=>['Helvetica', 24, :bold])
+ style_tag_small = TkTextTag.new(t, 'font'=>'Times 8 bold')
+ end
###
# case($tk_version)
# when /^4.*/
@@ -65,13 +77,13 @@ TkText.new($style_demo){|t|
# unless $style_demo_do_first
# $style_demo_do_first = true
# Tk.tk_call('font', 'create', '@bigascii',
-# '-copy', '-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*')
+# '-copy', '-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*')
# Tk.tk_call('font', 'create', '@smallascii',
-# '-copy', '-Adobe-Helvetica-Bold-R-Normal-*-100-*')
+# '-copy', '-Adobe-Helvetica-Bold-R-Normal-*-100-*')
# Tk.tk_call('font', 'create', '@cBigFont',
-# '-compound', '@bigascii @msg_knj')
+# '-compound', '@bigascii @msg_knj')
# Tk.tk_call('font', 'create', '@cSmallFont',
-# '-compound', '@smallascii @kanji')
+# '-compound', '@smallascii @kanji')
# end
# style_tag_big = TkTextTag.new(t, 'font'=>'@cBigFont')
# style_tag_small = TkTextTag.new(t, 'font'=>'@cSmallFont')
@@ -85,37 +97,42 @@ TkText.new($style_demo){|t|
style_tag_sunken = TkTextTag.new(t, 'relief'=>'sunken', 'borderwidth'=>1)
else
style_tag_color1 = TkTextTag.new(t, 'background'=>'black',
- 'foreground'=>'white')
+ 'foreground'=>'white')
style_tag_color2 = TkTextTag.new(t, 'background'=>'black',
- 'foreground'=>'white')
+ 'foreground'=>'white')
style_tag_raised = TkTextTag.new(t, 'background'=>'white',
- 'relief'=>'raised', 'borderwidth'=>1)
+ 'relief'=>'raised', 'borderwidth'=>1)
style_tag_sunken = TkTextTag.new(t, 'background'=>'white',
- 'relief'=>'sunken', 'borderwidth'=>1)
+ 'relief'=>'sunken', 'borderwidth'=>1)
end
- # ¥Æ¥­¥¹¥È¥¿¥°ÀßÄê (¤½¤Î¾)
+ #
if $tk_version =~ /^4\.[01]/
style_tag_bgstipple = TkTextTag.new(t, 'background'=>'black',
- 'borderwidth'=>0,
- 'bgstipple'=>'gray25')
+ 'borderwidth'=>0,
+ 'bgstipple'=>'gray25')
else
style_tag_bgstipple = TkTextTag.new(t, 'background'=>'black',
- 'borderwidth'=>0,
- 'bgstipple'=>'gray12')
+ 'borderwidth'=>0,
+ 'bgstipple'=>'gray12')
end
style_tag_fgstipple = TkTextTag.new(t, 'fgstipple'=>'gray50')
style_tag_underline = TkTextTag.new(t, 'underline'=>'on')
style_tag_overstrike = TkTextTag.new(t, 'overstrike'=>'on')
style_tag_right = TkTextTag.new(t, 'justify'=>'right')
style_tag_center = TkTextTag.new(t, 'justify'=>'center')
- style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
- style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ if $tk_version =~ /^4.*/
+ style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ else
+ style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>[family, 10])
+ style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>[family, 10])
+ end
style_tag_margins = TkTextTag.new(t, 'lmargin1'=>'12m', 'lmargin2'=>'6m',
- 'rmargin'=>'10m')
+ 'rmargin'=>'10m')
style_tag_spacing = TkTextTag.new(t, 'spacing1'=>'10p', 'spacing2'=>'2p',
- 'lmargin1'=>'12m', 'lmargin2'=>'6m',
- 'rmargin'=>'10m')
+ 'lmargin1'=>'12m', 'lmargin2'=>'6m',
+ 'rmargin'=>'10m')
#
insert('end', 'Text widgets like this one allow you to display information in a
@@ -132,7 +149,8 @@ available display styles are:
insert('end', " You can choose any X font, ")
insert('end', "large", style_tag_verybig)
insert('end', " or ")
- insert('end', "small.\n")
+ insert('end', "small", style_tag_small)
+ insert('end', ".\n")
insert('end', "\n2. Color.", style_tag_big)
insert('end', " You can change either the ")
insert('end', "background", style_tag_color1)
@@ -209,3 +227,5 @@ available display styles are:
}
+txt.width 70
+txt.height 32
diff --git a/ext/tk/sample/demos-en/tcolor b/ext/tk/sample/demos-en/tcolor
index 6d023f0f8b..3c63d6730d 100644
--- a/ext/tk/sample/demos-en/tcolor
+++ b/ext/tk/sample/demos-en/tcolor
@@ -1,30 +1,28 @@
#!/usr/bin/env ruby
#
# tcolor --
-# ¤³¤Î¥¹¥¯¥ê¥×¥È¤ÏRGB,HSB,CYM·Á¼°¤ò¥µ¥Ý¡¼¥È¤¹¤ë
-# ´Ê°×¥«¥é¡¼¥¨¥Ç¥£¥¿¤Ç¤¹¡£
+# simple color editor which supports RGB, HSB and CYM color space
#
# Copyright (C) 1998 Takaaki Tateishi(ttate@jaist.ac.jp)
# last update: Thu Jun 18 06:32:35 JST 1998
#
-# ¤Þ¤º¤Ïtk.rb¤òÆÉ¤ß¹þ¤à¡£
-
require "tk"
-# Tk¤Ë¤è¤Ã¤ÆÊѹ¹¤µ¤ì¤ëÊÑ¿ô¤ÏTkVariable¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤ò»È¤¦¡£
+# use TkVariable instance for the variable which is changed by Tk interpreter
$colorSpace = TkVariable.new(:rgb)
+$master = nil
$red = 65535
$green = 0
$blue = 0
$color = "#ffff00000000"
$updating = TkVariable.new(0)
$autoUpdate = TkVariable.new(1)
-$name = TkVariable.new("")
-# $command = TkVariable.new("print(%%,\"\n\")")
-$command = TkVariable.new("")
+$name = TkVariable.new($color)
+$command = TkVariable.new("print(%%,\"\n\")")
+# $command = TkVariable.new("")
$label1 = TkVariable.new("label1")
$label2 = TkVariable.new("label2")
$label3 = TkVariable.new("label3")
@@ -36,7 +34,7 @@ if (TkVarAccess.new('tcl_platform')['platform'] == 'unix')
end
-# ³Æ¥¤¥Ù¥ó¥ÈÍѤΥ᥽¥Ã¥É
+# methods for events
def rgbToHsv(red,green,blue)
@@ -123,9 +121,14 @@ def hsbToRgb(hue,sat,value)
end
+def _null_binding
+ Module.new.instance_eval{binding}
+end
+private :_null_binding
+
def doUpdate
newCmd = $command.to_s.gsub("%%","\"#{$color}\"")
- eval(newCmd)
+ eval(newCmd, _null_binding)
end
@@ -134,6 +137,8 @@ def tc_scaleChanged
return
end
+ $master = :scale if $master == nil
+
scale1 = $root.middle.middle.scale1
scale2 = $root.middle.middle.scale2
scale3 = $root.middle.middle.scale3
@@ -158,11 +163,13 @@ def tc_scaleChanged
raise(Exception,"unknown colorSpace")
end
$color = format("#%04x%04x%04x",$red.to_i,$green.to_i,$blue.to_i)
+ $name.value = $color if $master == :scale
$root.middle.right.set_color($color)
if( $autoUpdate.to_i == 1 )
doUpdate
end
- Tk.update(TRUE)
+ Tk.update(true)
+ $master = nil if $master == :scale
end
@@ -196,6 +203,8 @@ end
def tc_loadNamedColor(name)
+ $name.value = name
+ $master = :name if $master == nil
if name[0,1] != "#"
list = TkWinfo.rgb($root.middle.right.swatch,name)
$red = list[0]
@@ -204,27 +213,27 @@ def tc_loadNamedColor(name)
else
case name.length
when 4
- format = /#(.{1})(.{1})(.{1})/
+ fmt = /#(.{1})(.{1})(.{1})/
shift = 12
when 7
- format = /#(.{2})(.{2})(.{2})/
+ fmt = /#(.{2})(.{2})(.{2})/
shift = 8
when 10
- format = /#(.{3})(.{3})(.{3})/
+ fmt = /#(.{3})(.{3})(.{3})/
shift = 4
when 13
- format = /#(.{4})(.{4})(.{4})/
+ fmt = /#(.{4})(.{4})(.{4})/
shift = 0
else
raise(eException,"syntax error in color name \"#{name}\"")
end
- name.scan(format){|strlist|
+ name.scan(fmt){|strlist|
if strlist.length != 3
raise(eException,"syntax error in color name \"#{name}\"")
end
- $red = strlist[0].to_i
- $green = strlist[1].to_i
- $blue = strlist[2].to_i
+ $red = strlist[0].hex
+ $green = strlist[1].hex
+ $blue = strlist[2].hex
}
$red = $red << shift
$green = $green << shift
@@ -237,6 +246,8 @@ def tc_loadNamedColor(name)
if $autoUpdate.to_i == 1
doUpdate
end
+ Tk.update(true)
+ $master = nil if $master == :name
end
@@ -259,10 +270,7 @@ def changeColorSpace(space)
end
-
-
-
-# tcolorÍѤΥá¥Ë¥å¡¼
+# menu
class TkColorMenuFrame<TkFrame
def initialize(parent)
@@ -270,10 +278,10 @@ class TkColorMenuFrame<TkFrame
"relief"=>"raised",
"borderwidth"=>"2")
- # File¥á¥Ë¥å¡¼¥Ü¥¿¥ó¤ÎÀ¸À®
+ # File menubutton
@file = TkMenubutton.new(self){|button|
- # File¥á¥Ë¥å¡¼¤ÎºîÀ®
+ # File menu
@file_menu = TkMenu.new(button){
add "radio",
"label" => "RGB color space",
@@ -311,7 +319,7 @@ class TkColorMenuFrame<TkFrame
"command" => proc{exit}
}
- # File¥á¥Ë¥å¡¼¤ÈFile¥Ü¥¿¥ó¤ò´ØÏ¢ÉÕ¤±¤ë
+ # assign File menu to File button
menu @file_menu
text "File"
@@ -323,7 +331,7 @@ class TkColorMenuFrame<TkFrame
end
-# ²¼Éô¤Î¥Õ¥ì¡¼¥à¤Î¤¿¤á¤Î¥¯¥é¥¹
+# bottom frame
class TkColorBotFrame<TkFrame
def initialize(parent)
super(parent,
@@ -349,7 +357,7 @@ class TkColorBotFrame<TkFrame
end
-# ÃæÃʺ¸¤Î¥Õ¥ì¡¼¥à
+# left side frame of middle level
class TkColorMiddleLeftFrame<TkFrame
def initialize(parent)
super(parent)
@@ -393,9 +401,8 @@ class TkColorMiddleLeftFrame<TkFrame
end
-# ÃæÃÊÃæ±û¤Î¥Õ¥ì¡¼¥à
+# middle frame of middle level
class TkColorMiddleMiddleFrame<TkFrame
- # @scale1,@scale2,@scale3¤ò³°Éô¤«¤é»²¾È¤Î¤ßµö²Ä¤¹¤ë¡£(Êѹ¹ÉÔ²Ä)
attr_reader :scale1, :scale2, :scale3
def initialize(parent)
@@ -470,7 +477,7 @@ end
-# ÃæÃʤΥե졼¥à
+# middle level frame
class TkColorMiddleFrame<TkFrame
attr_reader :left, :middle, :right
@@ -513,7 +520,7 @@ end
$root = TkColor.new
-
-# ¥¤¥Ù¥ó¥È¤òÂԤİ٤˥롼¥×¤ËÆþ¤ë¡£
changeColorSpace :rgb
+
+# start eventloop
Tk.mainloop
diff --git a/ext/tk/sample/demos-en/tcolor.bak b/ext/tk/sample/demos-en/tcolor.bak
deleted file mode 100644
index 5464aebae2..0000000000
--- a/ext/tk/sample/demos-en/tcolor.bak
+++ /dev/null
@@ -1,513 +0,0 @@
-#!/usr/local/bin/ruby
-#
-# tcolor --
-# ¤³¤Î¥¹¥¯¥ê¥×¥È¤ÏRGB,HSB,CYM·Á¼°¤ò¥µ¥Ý¡¼¥È¤¹¤ë
-# ´Ê°×¥«¥é¡¼¥¨¥Ç¥£¥¿¤Ç¤¹¡£
-#
-# Copyright (C) 1998 Takaaki Tateishi(ttate@jaist.ac.jp)
-# last update: Thu Jun 18 06:32:35 JST 1998
-#
-
-# ¤Þ¤º¤Ïtk.rb¤òÆÉ¤ß¹þ¤à¡£
-
-require "tk"
-
-
-# Tk¤Ë¤è¤Ã¤ÆÊѹ¹¤µ¤ì¤ëÊÑ¿ô¤ÏTkVariable¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤ò»È¤¦¡£
-
-$colorSpace = TkVariable.new(:rgb)
-$red = 65535
-$green = 0
-$blue = 0
-$color = "#ffff00000000"
-$updating = TkVariable.new(0)
-$autoUpdate = TkVariable.new(1)
-$name = TkVariable.new("")
-# $command = TkVariable.new("print(%%,\"\n\")")
-$command = TkVariable.new("")
-$label1 = TkVariable.new("label1")
-$label2 = TkVariable.new("label2")
-$label3 = TkVariable.new("label3")
-
-
-# ³Æ¥¤¥Ù¥ó¥ÈÍѤΥ᥽¥Ã¥É
-
-def rgbToHsv(red,green,blue)
-
- if ( red > green )
- max = red
- min = green
- else
- max = green
- min = red
- end
-
- if ( blue > max )
- max = blue
- else
- if ( blue < min )
- min = blue
- end
- end
-
- range = max - min
-
- if ( max == 0 )
- sat = 0.0
- else
- sat = (max-min)/max
- end
-
- if ( sat == 0 )
- hue = 0.0
- else
- rc = (max-red)/range
- gc = (max-green)/range
- bc = (max-blue)/range
- if ( red == max )
- hue = 0.166667 * (bc - gc)
- else
- if ( green == max )
- hue = 0.166667 * (2.0 + rc - bc)
- else
- hue = 0.166667 * (4.0 + gc - rc)
- end
- end
- if ( hue < 0.0 )
- hue = hue + 1.0
- end
- end
-
- [hue,sat,max/65535]
-end
-
-
-def hsbToRgb(hue,sat,value)
- v = 65535.0 * value
- if( sat == 0 )
- ans = [v,v,v]
- else
- hue = hue*6.0
- if ( hue >= 6 )
- hue = 0.0
- end
- i = hue.to_i
- f = hue - i
- p = 65535.0 * value * (1.0 - sat)
- q = 65535.0 * value * (1.0 - (sat * f))
- t = 65535.0 * value * (1.0 - (sat * (1.0 - f)))
- case i
- when 0
- ans = [v,t,p]
- when 1
- ans = [q,v,p]
- when 2
- ans = [p,v,t]
- when 3
- ans = [p,q,v]
- when 4
- ans = [t,p,v]
- when 5
- ans = [v,p,q]
- else
- raise(eException,"i value #{i} is out of range")
- end
- end
- return ans
-end
-
-
-def doUpdate
- newCmd = $command.to_s.gsub("%%","\"#{$color}\"")
- eval(newCmd)
-end
-
-
-def tc_scaleChanged
- if( $updating.to_i == 1 )
- return
- end
-
- scale1 = $root.middle.middle.scale1
- scale2 = $root.middle.middle.scale2
- scale3 = $root.middle.middle.scale3
-
- case $colorSpace.to_i
- when :rgb
- $red = (scale1.get * 65.535).to_i
- $green = (scale2.get * 65.535).to_i
- $blue = (scale3.get * 65.535).to_i
- when :cmy
- $red = (65535 - scale1.get * 65.535).to_i
- $green = (65535 - scale2.get * 65.535).to_i
- $blue = (65535 - scale3.get * 65.535).to_i
- when :hsb
- list = hsbToRgb(scale1.get / 1000.0,
- scale2.get / 1000.0,
- scale3.get / 1000.0)
- $red = list[0]
- $green = list[1]
- $blue = list[2]
- else
- raise(Exception,"unknown colorSpace")
- end
- $color = format("#%04x%04x%04x",$red.to_i,$green.to_i,$blue.to_i)
- $root.middle.right.set_color($color)
- if( $autoUpdate.to_i == 1 )
- doUpdate
- end
- Tk.update(TRUE)
-end
-
-
-def tc_setScales
- $updating.value = 1
-
- scale1 = $root.middle.middle.scale1
- scale2 = $root.middle.middle.scale2
- scale3 = $root.middle.middle.scale3
-
- case $colorSpace.to_i
- when :rgb
- scale1.set($red / 65.535)
- scale2.set($green / 65.535)
- scale3.set($blue / 65.535)
- when :cmy
- scale1.set((65535 - $red) / 65.535)
- scale2.set((65535 - $green) / 65.535)
- scale3.set((65535 - $blue) / 65.535)
- when :hsb
- list = rgbToHsv($red,$green,$blue)
- scale1.set( list[0] * 1000.0 )
- scale2.set( list[1] * 1000.0 )
- scale3.set( list[2] * 1000.0 )
- else
- raise(Exception,"unknown colorSpace")
- end
-
- $updating.value = 0
-end
-
-
-def tc_loadNamedColor(name)
- if name[0,1] != "#"
- list = TkWinfo.rgb($root.middle.right.swatch,name)
- $red = list[0]
- $green = list[1]
- $blue = list[2]
- else
- case name.length
- when 4
- format = /#(.{1})(.{1})(.{1})/
- shift = 12
- when 7
- format = /#(.{2})(.{2})(.{2})/
- shift = 8
- when 10
- format = /#(.{3})(.{3})(.{3})/
- shift = 4
- when 13
- format = /#(.{4})(.{4})(.{4})/
- shift = 0
- else
- raise(eException,"syntax error in color name \"#{name}\"")
- end
- name.scan(format){|strlist|
- if strlist.length != 3
- raise(eException,"syntax error in color name \"#{name}\"")
- end
- $red = strlist[0].to_i
- $green = strlist[1].to_i
- $blue = strlist[2].to_i
- }
- $red = $red << shift
- $green = $green << shift
- $blue = $blue << shift
- end
-
- tc_setScales
- $color = format("#%04x%04x%04x",$red,$green,$blue)
- $root.middle.right.set_color($color)
- if $autoUpdate.to_i == 1
- doUpdate
- end
-end
-
-
-def changeColorSpace(space)
- case space
- when :rgb
- $label1.value = "Red"
- $label2.value = "Green"
- $label3.value = "Blue"
- when :cmy
- $label1.value = "Cyan"
- $label2.value = "Magenta"
- $label3.value = "Yellow"
- when :hsb
- $label1.value = "Hue"
- $label2.value = "Saturation"
- $label3.value = "Brightness"
- end
- tc_setScales
-end
-
-
-
-
-
-# tcolorÍѤΥá¥Ë¥å¡¼
-
-class TkColorMenuFrame<TkFrame
- def initialize(parent)
- super(parent,
- "relief"=>"raised",
- "borderwidth"=>"2")
-
- # File¥á¥Ë¥å¡¼¥Ü¥¿¥ó¤ÎÀ¸À®
- @file = TkMenubutton.new(self){|button|
-
- # File¥á¥Ë¥å¡¼¤ÎºîÀ®
- @file_menu = TkMenu.new(button){
- add "radio",
- "label" => "RGB color space",
- "variable" => $colorSpace,
- "value" => :rgb,
- "underline" => "0",
- "command" => proc{changeColorSpace(:rgb)}
- add "radio",
- "label" => "CMY color space",
- "variable" => $colorSpace,
- "value" => :cmy,
- "underline" => "0",
- "command" => proc{changeColorSpace(:cmy)}
- add "radio",
- "label" => "HSB color space",
- "variable" => $colorSpace,
- "value" => :hsb,
- "underline" => "0",
- "command" => proc{changeColorSpace(:hsb)}
- add "separator"
- add "radio",
- "label" => "Qutomatic updates",
- "variable" => $autoUpdate,
- "value" => "1",
- "underline" => "0"
- add "radio",
- "label" => "Manual updates",
- "variable" => $autoUpdate,
- "value" => "0",
- "underline" => "0"
- add "separator"
- add "command",
- "label" => "Exit program",
- "underline" => "0",
- "command" => proc{exit}
- }
-
- # File¥á¥Ë¥å¡¼¤ÈFile¥Ü¥¿¥ó¤ò´ØÏ¢ÉÕ¤±¤ë
- menu @file_menu
-
- text "File"
- underline "0"
- }.pack("side"=>"left")
-
- self
- end
-end
-
-
-# ²¼Éô¤Î¥Õ¥ì¡¼¥à¤Î¤¿¤á¤Î¥¯¥é¥¹
-class TkColorBotFrame<TkFrame
- def initialize(parent)
- super(parent,
- "relief"=> "raised",
- "borderwidth"=> 2)
-
- @commandLabel = TkLabel.new(self,
- "text"=> "Command:")
- @command = TkEntry.new(self,
- "relief"=> "sunken",
- "borderwidth"=> "2",
- "textvariable"=> $command,
- "font"=> "-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*")
- @update = TkButton.new(self,
- "text"=> "Update",
- "command"=> proc{doUpdate})
- @commandLabel.pack("side"=>"left")
- @update.pack("side"=>"right","pady"=>".1c","padx"=>".25c")
- @command.pack("expand"=>"yes","fill"=>"x","ipadx"=>".25c")
-
- self
- end
-end
-
-
-# ÃæÃʺ¸¤Î¥Õ¥ì¡¼¥à
-class TkColorMiddleLeftFrame<TkFrame
- def initialize(parent)
- super(parent)
-
- for i in ["/usr/local/lib/X11rgb.txt","/usr/lib/X11/rgb.txt",
- "/X11/R5/lib/X11/rgb.txt","/X11/R4/lib/rgb/rgb.txt",
- "/usr/openwin/lib/X11/rgb.txt"]
- if !File.readable?(i)
- next
- end
- f = File.open(i)
- @scroll = TkScrollbar.new(self,
- "orient"=>"vertical",
- "relief"=>"sunken",
- "borderwidth"=>"2")
- @scroll.pack("side"=>"right","fill"=>"y")
- @names = TkListbox.new(self,
- "width"=>"20",
- "height"=>"12",
- "yscrollcommand"=> proc{|first,last| @scroll.set first,last},
- "relief"=>"sunken",
- "borderwidth"=>"2",
- "exportselection"=>"false")
- @scroll.command(proc{|*args| @names.yview *args})
- @names.bind("Double-1",proc{
- tc_loadNamedColor(@names.get(@names.curselection))})
- @names.pack("side"=>"left")
- while (line = f.gets)
- line.chop!
- linelist = line.split(/[ \t]+/)
- if linelist.length == 4
- @names.insert("end",linelist[3])
- end
- end
- f.close
- break
- end
-
- self
- end
-end
-
-
-# ÃæÃÊÃæ±û¤Î¥Õ¥ì¡¼¥à
-class TkColorMiddleMiddleFrame<TkFrame
- # @scale1,@scale2,@scale3¤ò³°Éô¤«¤é»²¾È¤Î¤ßµö²Ä¤¹¤ë¡£(Êѹ¹ÉÔ²Ä)
- attr_reader :scale1, :scale2, :scale3
-
- def initialize(parent)
- super(parent)
-
- @f1 = TkFrame.new(self)
- @f2 = TkFrame.new(self)
- @f3 = TkFrame.new(self)
- @f4 = TkFrame.new(self)
-
- for f in [@f1,@f2,@f3]
- f.pack("side"=>"top","expand"=>"yes")
- end
- @f4.pack("side"=>"top","expand"=>"yes","fill"=>"x")
-
- @label1 = TkLabel.new(self,"textvariable"=>$label1)
- @scale1 = TkScale.new(self,"from"=>"0","to"=>"1000","length"=>"6c",
- "orient"=>"horizontal",
- "command"=>proc{tc_scaleChanged})
- @scale1.pack("side"=>"top","anchor"=>"w")
- @label1.pack("side"=>"top","anchor"=>"w")
-
- @label2 = TkLabel.new(self,"textvariable"=>$label2)
- @scale2 = TkScale.new(self,"from"=>"0","to"=>"1000","length"=>"6c",
- "orient"=>"horizontal",
- "command"=>proc{tc_scaleChanged})
- @scale2.pack("side"=>"top","anchor"=>"w")
- @label2.pack("side"=>"top","anchor"=>"w")
-
- @label3 = TkLabel.new(self,"textvariable"=>$label3)
- @scale3 = TkScale.new(self,"from"=>"0","to"=>"1000","length"=>"6c",
- "orient"=>"horizontal",
- "command"=>proc{tc_scaleChanged})
- @scale3.pack("side"=>"top","anchor"=>"w")
- @label3.pack("side"=>"top","anchor"=>"w")
-
- @nameLabel = TkLabel.new(self,"text"=>"Name:")
- @name = TkEntry.new(self,"relief"=>"sunken","borderwidth"=>"2",
- "textvariable"=>$name,"width"=>"10",
- "font"=>"-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*")
- @nameLabel.pack("side"=>"left")
- @name.pack("side"=>"right", "expand"=>"1", "fill"=>"x")
- @name.bind("Return",proc{tc_loadNamedColor $name.to_s})
-
- self
- end
-end
-
-
-class TkColorMiddleRightFrame<TkFrame
- attr_reader :swatch
-
- def initialize(parent)
- super(parent)
- @swatch = TkFrame.new(self, "width"=>"2c", "height"=>"5c",
- "background"=>$color)
- @value = TkLabel.new(self,
- "text"=>$color,
- "width"=>"13",
- "font"=>"-Adobe-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*")
- @swatch.pack("side"=>"top","expand"=>"yes","fill"=>"both")
- @value.pack("side"=>"bottom","pady"=>".25c")
-
- self
- end
-
- def set_color(color)
- @swatch["background"] = color
- @value["text"] = color
- end
-end
-
-
-
-# ÃæÃʤΥե졼¥à
-class TkColorMiddleFrame<TkFrame
- attr_reader :left, :middle, :right
-
- def initialize(parent)
- super(parent,
- "relief"=> "raised",
- "borderwidth"=> "2")
-
- @left = TkColorMiddleLeftFrame.new(self)
- @left.pack("side"=>"left","padx"=>".25c","pady"=>".25c")
-
- @middle = TkColorMiddleMiddleFrame.new(self)
- @middle.pack("side"=>"left","expand"=>"yes","fill"=>"y")
-
- @right = TkColorMiddleRightFrame.new(self)
- @right.pack("side"=>"left","padx"=>".25c","pady"=>".25c","anchor"=>"s")
-
- self
- end
-end
-
-
-class TkColor<TkRoot
- attr_reader :menu, :bottom, :middle
-
- def initialize
- super
- @menu = TkColorMenuFrame.new(self)
- @menu.pack("side"=>"top", "fill"=>"x")
-
- @bottom = TkColorBotFrame.new(self)
- @bottom.pack("side"=>"bottom","fill"=>"x")
-
- @middle = TkColorMiddleFrame.new(self)
- @middle.pack("side"=>"top","fill"=>"both")
-
- self
- end
-end
-
-
-$root = TkColor.new
-
-# ¥¤¥Ù¥ó¥È¤òÂԤİ٤˥롼¥×¤ËÆþ¤ë¡£
-changeColorSpace :rgb
-Tk.mainloop
diff --git a/ext/tk/sample/demos-en/text.rb b/ext/tk/sample/demos-en/text.rb
index 2ed53e6938..3ce8cdfda8 100644
--- a/ext/tk/sample/demos-en/text.rb
+++ b/ext/tk/sample/demos-en/text.rb
@@ -19,6 +19,8 @@ $text_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($text_demo).pack(:fill=>:both, :expand=>true)
+
# version check
if ((Tk::TK_VERSION.split('.').collect{|n| n.to_i} <=> [8,4]) < 0)
undo_support = false
@@ -27,7 +29,7 @@ else
end
# frame
-TkFrame.new($text_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -44,7 +46,7 @@ TkFrame.new($text_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# text
-TkText.new($text_demo){|t|
+TkText.new(base_frame){|t|
relief 'sunken'
bd 2
setgrid 1
@@ -53,7 +55,7 @@ TkText.new($text_demo){|t|
undo true
autoseparators true
end
- TkScrollbar.new($text_demo) {|s|
+ TkScrollbar.new(base_frame) {|s|
pack('side'=>'right', 'fill'=>'y')
command proc{|*args| t.yview(*args)}
t.yscrollcommand proc{|first,last| s.set first,last}
@@ -102,16 +104,16 @@ a new line by inserting a newline character to the right of the insertion
cursor. Control-t transposes the two characters on either side of the
insertion cursor. #{
if undo_support
- undo_text = "Control-z undoes the last editing action performed,\nand "
- case $tk_platform['platform']
- when "unix", "macintosh"
- undo_text << "Control-Shift-z"
- else # 'windows'
- undo_text << "Control-y"
- end
- undo_text << "redoes undone edits."
+ undo_text = "Control-z undoes the last editing action performed,\nand "
+ case $tk_platform['platform']
+ when "unix", "macintosh"
+ undo_text << "Control-Shift-z"
+ else # 'windows'
+ undo_text << "Control-y"
+ end
+ undo_text << "redoes undone edits."
else
- ""
+ ""
end
}
diff --git a/ext/tk/sample/demos-en/textpeer.rb b/ext/tk/sample/demos-en/textpeer.rb
new file mode 100644
index 0000000000..c25ce15e5c
--- /dev/null
+++ b/ext/tk/sample/demos-en/textpeer.rb
@@ -0,0 +1,76 @@
+#
+# text widget peering demo (called by 'widget')
+#
+# based on Tcl/Tk8.5.0 widget demos
+
+if defined?($textpeer_demo) && $textpeer_demo
+ $textpeer_demo.destroy
+ $textpeer_demo = nil
+end
+
+# demo toplevel widget
+$textpeer_demo = TkToplevel.new {|w|
+ title("Text Wdget Peering Demonstration")
+ iconname("textpeer")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($textpeer_demo).pack(:fill=>:both, :expand=>true)
+
+count = [0]
+
+## Define a widget that we peer from; it won't ever actually be shown though
+first = TkText.new(base_frame, :widgetname=>"text#{count[0] += 1}")
+first.insert :end,"This is a coupled pair of text widgets; they are peers to "
+first.insert :end,"each other. They have the same underlying data model, but "
+first.insert :end,"can show different locations, have different current edit "
+first.insert :end,"locations, and have different selections. You can also "
+first.insert :end,"create additional peers of any of these text widgets using "
+first.insert :end,"the Make Peer button beside the text widget to clone, and "
+first.insert :end,"delete a particular peer widget using the Delete Peer "
+first.insert :end,"button."
+
+Tk.update_idletasks ## for 'first' widget
+
+## Procedures to make and kill clones; most of this is just so that the demo
+## looks nice...
+def makeClone(count, win, txt)
+ cnt = (count[0] += 1)
+ peer = TkText::Peer.new(txt, win, :widgetname=>"text#{cnt}")
+ sbar = TkScrollbar.new(win, :widgetname=>"sb#{cnt}")
+ peer.yscrollbar sbar
+ b1 = TkButton.new(win, :widgetname=>"clone#{cnt}", :text=>'Make Peer',
+ :command=>proc{makeClone(count, win, peer)})
+ b2 = TkButton.new(win, :widgetname=>"kill#{cnt}", :text=>'Delete Peer',
+ :command=>proc{killClone(win, cnt)})
+ row = cnt * 2
+ TkGrid.configure(peer, sbar, b1, :sticky=>'nsew', :row=>row)
+ TkGrid.configure('^', '^', b2, :sticky=>'nsew', :row=>(row+=1))
+ TkGrid.configure(b1, b2, :sticky=>'new')
+ TkGrid.rowconfigure(win, b2, :weight=>1)
+end
+
+def killClone(win, cnt)
+ Tk.destroy("#{win.path}.text#{cnt}", "#{win.path}.sb#{cnt}",
+ "#{win.path}.clone#{cnt}", "#{win.path}.kill#{cnt}")
+end
+
+## Now set up the GUI
+makeClone(count, base_frame, first)
+makeClone(count, base_frame, first)
+first.destroy
+
+## See Code / Dismiss buttons
+TkFrame.new(base_frame){|f|
+ TkButton.new(f, :text=>'Dismiss', :width=>15, :command=>proc{
+ $textpeer_demo.destroy
+ $textpeer_demo = nil
+ }).pack(:side=>:left, :expand=>true)
+
+ TkButton.new(f, :text=>'See Code', :width=>15, :command=>proc{
+ showCode 'textpeer'
+ }).pack(:side=>:left, :expand=>true)
+
+ TkGrid.configure(f, '-', '-', :sticky=>'ew', :row=>5000)
+}
+TkGrid.columnconfigure(base_frame, 0, :weight=>1)
diff --git a/ext/tk/sample/demos-en/toolbar.rb b/ext/tk/sample/demos-en/toolbar.rb
new file mode 100644
index 0000000000..5cf863717b
--- /dev/null
+++ b/ext/tk/sample/demos-en/toolbar.rb
@@ -0,0 +1,130 @@
+# toolbar.rb --
+#
+# This demonstration script creates a toolbar that can be torn off.
+#
+# based on "Id: toolbar.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($toolbar_demo) && $toolbar_demo
+ $toolbar_demo.destroy
+ $toolbar_demo = nil
+end
+
+$toolbar_demo = TkToplevel.new {|w|
+ title("Ttk Menu Buttons")
+ iconname("toolbar")
+ positionWindow(w)
+}
+
+base_frame = Ttk::Frame.new($toolbar_demo).pack(:fill=>:both, :expand=>true)
+
+if Tk.windowingsystem != 'aqua'
+ msg = Ttk::Label.new(base_frame, :wraplength=>'4i',
+ :text=>Tk::UTF8_String.new(<<EOL))
+This is a demonstration of how to do \
+a toolbar that is styled correctly \
+and which can be torn off (this feature reqrires Tcl/Tk8.5). \
+The buttons are configured to be \\u201Ctoolbar style\\u201D buttons by \
+telling them that they are to use the Toolbutton style. At the left \
+end of the toolbar is a simple marker that the cursor changes to a \
+movement icon over; drag that away from the toolbar to tear off the \
+whole toolbar into a separate toplevel widget. When the dragged-off \
+toolbar is no longer needed, just close it like any normal toplevel \
+and it will reattach to the window it was torn off from.
+EOL
+else
+ msg = Ttk::Label.new(base_frame, :wraplength=>'4i',
+ :text=>Tk::UTF8_String.new(<<EOL))
+This is a demonstration of how to do \
+a toolbar that is styled correctly. The buttons are configured to \
+be \\u201Ctoolbar style\\u201D buttons by telling them that they are \
+to use the Toolbutton style.
+EOL
+end
+
+## Set up the toolbar hull
+tbar_base = Tk::Frame.new(base_frame, # Must be a starndard Tk frame!
+ :widgetname=>'toolbar') # for window title
+sep = Ttk::Separator.new(base_frame)
+to_base = Ttk::Frame.new(tbar_base, :cursor=>'fleur')
+if Tk.windowingsystem != 'aqua'
+ to = Ttk::Separator.new(to_base, :orient=>:vertical)
+ to2 = Ttk::Separator.new(to_base, :orient=>:vertical)
+ to.pack(:fill=>:y, :expand=>true, :padx=>2, :side=>:left)
+ to2.pack(:fill=>:y, :expand=>true, :side=>:left)
+end
+
+contents = Ttk::Frame.new(tbar_base)
+Tk.grid(to_base, contents, :sticky=>'nsew')
+tbar_base.grid_columnconfigure(contents, :weight=>1)
+contents.grid_columnconfigure(1000, :weight=>1)
+
+if Tk.windowingsystem != 'aqua'
+ ## Bindings so that the toolbar can be torn off and reattached
+ to_base.bind('B1-Motion', '%X %Y'){|x, y| tbar_base.tearoff(to_base, x, y)}
+ to. bind('B1-Motion', '%X %Y'){|x, y| tbar_base.tearoff(to_base, x, y)}
+ to2. bind('B1-Motion', '%X %Y'){|x, y| tbar_base.tearoff(to_base, x, y)}
+ def tbar_base.tearoff(w, x, y)
+ on_win = TkWinfo.containing(x, y)
+ return unless (on_win && on_win.path =~ /^#{@path}(\.|$)/)
+ self.grid_remove
+ w.grid_remove
+ self.wm_manage
+ # self.wm_title('Toolbar') # if you don't want to use its widget name as a window title.
+ self.wm_protocol('WM_DELETE_WINDOW'){ self.untearoff(self) }
+ end
+ def tbar_base.untearoff(w)
+ self.wm_forget
+ w.grid
+ self.grid
+ end
+end
+
+## Some content for the rest of the toplevel
+text = TkText.new(base_frame, :width=>40, :height=>10)
+
+## Toolbar contents
+tb_btn = Ttk::Button.new(tbar_base, :text=>'Button', :style=>'Toolbutton',
+ :command=>proc{text.insert(:end, "Button Pressed\n")})
+tb_chk = Ttk::Checkbutton.new(tbar_base, :text=>'Check', :style=>'Toolbutton',
+ :variable=>(check = TkVariable.new),
+ :command=>proc{
+ text.insert(:end, "Check is #{check.value}\n")
+ })
+tb_mbtn = Ttk::Menubutton.new(tbar_base, :text=>'Menu')
+tb_combo = Ttk::Combobox.new(tbar_base, :value=>TkFont.families,
+ :state=>:readonly)
+tb_mbtn.menu(menu = Tk::Menu.new(tb_mbtn))
+menu.add(:command, :label=>'Just', :command=>proc{text.insert(:end, "Just\n")})
+menu.add(:command, :label=>'An', :command=>proc{text.insert(:end, "An\n")})
+menu.add(:command, :label=>'Example',
+ :command=>proc{text.insert(:end, "Example\n")})
+tb_combo.bind('<ComboboxSelected>'){ text.font.family = tb_combo.get }
+
+## Arrange contents
+Tk.grid(tb_btn, tb_chk, tb_mbtn, tb_combo,
+ :in=>contents, :padx=>2, :sticky=>'ns')
+Tk.grid(tbar_base, :sticky=>'ew')
+Tk.grid(sep, :sticky=>'ew')
+Tk.grid(msg, :sticky=>'ew')
+Tk.grid(text, :sticky=>'nsew')
+base_frame.grid_rowconfigure(text, :weight=>1)
+base_frame.grid_columnconfigure(text, :weight=>1)
+
+## See Code / Dismiss buttons
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'toolbar'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $toolbar_demo.destroy
+ $toolbar_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ Tk.grid(frame, :sticky=>'ew')
+}
diff --git a/ext/tk/sample/demos-en/tree.rb b/ext/tk/sample/demos-en/tree.rb
new file mode 100644
index 0000000000..0c7f0e71a2
--- /dev/null
+++ b/ext/tk/sample/demos-en/tree.rb
@@ -0,0 +1,119 @@
+# tree.rb --
+#
+# This demonstration script creates a toplevel window containing a Ttk
+# tree widget.
+#
+# based on "Id: tree.tcl,v 1.4 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($tree_demo) && $tree_demo
+ $tree_demo.destroy
+ $tree_demo = nil
+end
+
+$tree_demo = TkToplevel.new {|w|
+ title("Directory Browser")
+ iconname("tree")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($tree_demo).pack(:fill=>:both, :expand=>true)
+
+## Explanatory text
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i',
+ :justify=>:left, :anchor=>'n', :padding=>[10, 2, 10, 6],
+ :text=><<EOL).pack(:fill=>:x)
+Ttk is the new Tk themed widget set. \
+One of the widgets it includes is a tree widget, \
+which allows the user to browse a hierarchical data-set such as a filesystem. \
+The tree widget not only allows for the tree part itself, \
+but it also supports an arbitrary number of additional columns \
+which can show additional data (in this case, the size of the files \
+found in your filesystem). \
+You can also change the width of the columns \
+by dragging the boundary between them.
+EOL
+
+## See Code / Dismiss
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'tree'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $tree_demo.destroy
+ $tree_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+## Code to populate the roots of the tree (can be more than one on Windows)
+def populate_roots(tree)
+ TkComm.simplelist(Tk.tk_call('file', 'volumes')).sort.each{|dir|
+ populate_tree(tree, tree.insert(nil, :end, :text=>dir,
+ :values=>[dir, 'directory']))
+ }
+end
+
+## Code to populate a node of the tree
+def populate_tree(tree, node)
+ return if tree.get(node, :type) != 'directory'
+
+ path = tree.get(node, :fullpath)
+ tree.delete(tree.children(node))
+ Dir.glob("#{path}/*").sort.each{|f|
+ type = File.ftype(f)
+ id = tree.insert(node, :end,
+ :text=>File.basename(f), :values=>[f, type]).id
+ if type == 'directory'
+ ## Make it so that this node is openable
+ tree.insert(id, 0, :text=>'dummy')
+ tree.itemconfigure(id, :text=>File.basename(f))
+ elsif type == 'file'
+ size = File.size(f)
+ if size >= 1024*1024*1024
+ size = '%.1f GB' % (size.to_f/1024/1024/1024)
+ elsif size >= 1024*1024
+ size = '%.1f MB' % (size.to_f/1024/1024)
+ elsif size >= 1024
+ size = '%.1f KB' % (size.to_f/1024)
+ else
+ size = '%.1f bytes' % (size.to_f/1024)
+ end
+ tree.set(id, :size, size)
+ end
+ }
+
+ # Stop this code from rerunning on the current node
+ tree.set(node, :type, 'processed_directory')
+end
+
+## Create the tree and set it up
+tree = Ttk::Treeview.new(base_frame, :columns=>%w(fullpath type size),
+ :displaycolumns=>['size'])
+if Tk.windowingsystem != 'aqua'
+ vsb = tree.yscrollbar(Ttk::Scrollbar.new(base_frame))
+ hsb = tree.xscrollbar(Ttk::Scrollbar.new(base_frame))
+else
+ vsb = tree.yscrollbar(Tk::Scrollbar.new(base_frame))
+ hsb = tree.xscrollbar(Tk::Scrollbar.new(base_frame))
+end
+
+tree.heading_configure('#0', :text=>'Directory Structure')
+tree.heading_configure('size', :text=>'File Size')
+tree.column_configure('size', :stretch=>0, :width=>70)
+populate_roots(tree)
+tree.bind('<TreeviewOpen>', '%W'){|w| populate_tree(w, w.focus_item)}
+
+## Arrange the tree and its scrollbars in the toplevel
+container = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+container.lower
+Tk.grid(tree, vsb, :in=>container, :sticky=>'nsew')
+Tk.grid(hsb, :in=>container, :sticky=>'nsew')
+container.grid_columnconfigure(0, :weight=>1)
+container.grid_rowconfigure(0, :weight=>1)
diff --git a/ext/tk/sample/demos-en/ttkbut.rb b/ext/tk/sample/demos-en/ttkbut.rb
new file mode 100644
index 0000000000..b5780f589a
--- /dev/null
+++ b/ext/tk/sample/demos-en/ttkbut.rb
@@ -0,0 +1,139 @@
+# ttkbut.rb
+#
+# This demonstration script creates a toplevel window containing several
+# simple Ttk widgets, such as labels, labelframes, buttons, checkbuttons and
+# radiobuttons.
+#
+# based on "Id: ttkbut.tcl,v 1.4 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttkbut_demo) && $ttkbut_demo
+ $ttkbut_demo.destroy
+ $ttkbut_demo = nil
+end
+
+$ttkbut_demo = TkToplevel.new {|w|
+ title("Simple Ttk Widgets")
+ iconname("ttkbut")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($ttkbut_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top, :fill=>:x)
+Ttk is the new Tk themed widget set. This is a Ttk themed label, \
+and below are three groups of Ttk widgets in Ttk labelframes. \
+The first group are all buttons that set the current application theme \
+when pressed. The second group contains three sets of checkbuttons, \
+with a separator widget between the sets. Note that the "Enabled" \
+button controls whether all the other themed widgets in this toplevel are \
+in the disabled state. The third group has a collection of linked \
+radiobuttons.
+EOL
+
+## Add buttons for setting the theme
+buttons = Ttk::Labelframe.new(base_frame, :text=>'Buttons')
+# Ttk::Style.theme_names.each{|theme|
+# Ttk::Button.new(buttons, :text=>theme,
+# :command=>proc{Ttk::Style.theme_use theme}).pack(:pady=>2)
+# }
+Ttk.themes.each{|theme|
+ Ttk::Button.new(buttons, :text=>theme,
+ :command=>proc{Ttk.set_theme theme}).pack(:pady=>2)
+}
+
+## Helper procedure for the top checkbutton
+def setState(root, value, *excepts)
+ return if excepts.member?(root)
+
+ ## Non-Ttk widgets (e.g. the toplevel) will fail, so make it silent
+ begin
+ root.state = value
+ rescue
+ end
+
+ ## Recursively invoke on all children of this root that are in the same
+ ## toplevel widget
+ root.winfo_children.each{|w|
+ setState(w, value, *excepts) if w.winfo_toplevel == root.winfo_toplevel
+ }
+end
+
+## Set up the checkbutton group
+checks = Ttk::Labelframe.new(base_frame, :text=>'Checkbuttons')
+enabled = TkVariable.new(true)
+e = Ttk::Checkbutton.new(checks, :text=>'Enabled', :variable=>enabled,
+ :command=>proc{
+ setState($ttkbut_demo,
+ ((enabled.bool)? "!disabled" : "disabled"),
+ e)
+ })
+
+## See ttk_widget(n) for other possible state flags
+sep1 = Ttk::Separator.new(checks)
+sep2 = Ttk::Separator.new(checks)
+
+cheese = TkVariable.new
+tomato = TkVariable.new
+basil = TkVariable.new
+oregano = TkVariable.new
+
+c1 = Ttk::Checkbutton.new(checks, :text=>'Cheese', :variable=>cheese)
+c2 = Ttk::Checkbutton.new(checks, :text=>'Tomato', :variable=>tomato)
+c3 = Ttk::Checkbutton.new(checks, :text=>'Basil', :variable=>basil)
+c4 = Ttk::Checkbutton.new(checks, :text=>'Oregano', :variable=>oregano)
+
+Tk.pack(e, sep1, c1, c2, sep2, c3, c4, :fill=>:x, :pady=>2)
+
+## Set up the radiobutton group
+radios = Ttk::Labelframe.new(base_frame, :text=>'Radiobuttons')
+
+happyness = TkVariable.new
+
+r1 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Great', :value=>'great')
+r2 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Good', :value=>'good')
+r3 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Ok', :value=>'ok')
+r4 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Poor', :value=>'poor')
+r5 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Awful', :value=>'awful')
+
+Tk.pack(r1, r2, r3, r4, r5, :fill=>:x, :padx=>3, :pady=>2)
+
+## See Code / Dismiss
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Variables',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{
+ showVars(base_frame, ['enabled', enabled],
+ ['cheese', cheese], ['tomato', tomato],
+ ['basil', basil], ['oregano', oregano],
+ ['happyness', happyness])
+ }),
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttkbut'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ tmppath = $ttkbut_demo
+ $ttkbut_demo = nil
+ $showVarsWin[tmppath.path] = nil
+ tmppath.destroy
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x, :expand=>true)
+}
+
+## Arrange things neatly
+f = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+f.lower
+Tk.grid(buttons, checks, radios, :in=>f, :sticky=>'nwe', :pady=>2, :padx=>3)
+f.grid_columnconfigure([0, 1, 2], :weight=>1, :uniform=>:yes)
diff --git a/ext/tk/sample/demos-en/ttkmenu.rb b/ext/tk/sample/demos-en/ttkmenu.rb
new file mode 100644
index 0000000000..75ecdb09c4
--- /dev/null
+++ b/ext/tk/sample/demos-en/ttkmenu.rb
@@ -0,0 +1,85 @@
+# ttkmenu.rb --
+#
+# This demonstration script creates a toplevel window containing several Ttk
+# menubutton widgets.
+#
+# based on "Id: ttkmenu.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttkmenu_demo) && $ttkmenu_demo
+ $ttkmenu_demo.destroy
+ $ttkmenu_demo = nil
+end
+
+$ttkmenu_demo = TkToplevel.new {|w|
+ title("Ttk Menu Buttons")
+ iconname("ttkmenu")
+ positionWindow(w)
+}
+
+base_frame = Ttk::Frame.new($ttkmenu_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top, :fill=>:x)
+Ttk is the new Tk themed widget set, \
+and one widget that is available in themed form is the menubutton. \
+Below are some themed menu buttons \
+that allow you to pick the current theme in use. \
+Notice how picking a theme changes the way \
+that the menu buttons themselves look, \
+and that the central menu button is styled differently \
+(in a way that is normally suitable for toolbars). \
+However, there are no themed menus; the standard Tk menus were judged \
+to have a sufficiently good look-and-feel on all platforms, \
+especially as they are implemented as native controls in many places.
+EOL
+
+Ttk::Separator.new(base_frame).pack(:side=>:top, :fill=>:x)
+
+## See Code / Dismiss
+Ttk::Frame.new($ttkmenu_demo) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttkmenu'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $ttkmenu_demo.destroy
+ $ttkmenu_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+b1 = Ttk::Menubutton.new(base_frame,:text=>'Select a theme',:direction=>:above)
+b2 = Ttk::Menubutton.new(base_frame,:text=>'Select a theme',:direction=>:left)
+b3 = Ttk::Menubutton.new(base_frame,:text=>'Select a theme',:direction=>:right)
+b4 = Ttk::Menubutton.new(base_frame,:text=>'Select a theme',:direction=>:flush,
+ :style=>Ttk::Menubutton.style('Toolbutton'))
+b5 = Ttk::Menubutton.new(base_frame,:text=>'Select a theme',:direction=>:below)
+
+b1.menu(m1 = Tk::Menu.new(b1, :tearoff=>false))
+b2.menu(m2 = Tk::Menu.new(b2, :tearoff=>false))
+b3.menu(m3 = Tk::Menu.new(b3, :tearoff=>false))
+b4.menu(m4 = Tk::Menu.new(b4, :tearoff=>false))
+b5.menu(m5 = Tk::Menu.new(b5, :tearoff=>false))
+
+Ttk.themes.each{|theme|
+ m1.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+ m2.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+ m3.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+ m4.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+ m5.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+}
+
+f = Ttk::Frame.new(base_frame).pack(:fill=>:x)
+f1 = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+f.lower
+
+f.grid_anchor(:center)
+TkGrid('x', b1, 'x', :in=>f, :padx=>3, :pady=>2)
+TkGrid(b2, b4, b3, :in=>f, :padx=>3, :pady=>2)
+TkGrid('x', b5, 'x', :in=>f, :padx=>3, :pady=>2)
diff --git a/ext/tk/sample/demos-en/ttknote.rb b/ext/tk/sample/demos-en/ttknote.rb
new file mode 100644
index 0000000000..c2a22b447a
--- /dev/null
+++ b/ext/tk/sample/demos-en/ttknote.rb
@@ -0,0 +1,89 @@
+# ttknote.rb --
+#
+# This demonstration script creates a toplevel window containing a Ttk
+# notebook widget.
+#
+# based on "Id: ttknote.tcl,v 1.5 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttknote_demo) && $ttknote_demo
+ $ttknote_demo.destroy
+ $ttknote_demo = nil
+end
+
+$ttknote_demo = TkToplevel.new {|w|
+ title("Ttk Notebook Widget")
+ iconname("ttknote")
+ positionWindow(w)
+}
+
+## See Code / Dismiss
+Ttk::Frame.new($ttknote_demo) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttknote'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $ttknote_demo.destroy
+ $ttknote_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+base_frame = Ttk::Frame.new($ttknote_demo).pack(:fill=>:both, :expand=>true)
+
+## Make the notebook and set up Ctrl+Tab traversal
+notebook = Ttk::Notebook.new(base_frame).pack(:fill=>:both, :expand=>true,
+ :padx=>2, :pady=>3)
+notebook.enable_traversal
+
+## Popuplate the first pane
+f_msg = Ttk::Frame.new(notebook)
+msg_m = Ttk::Label.new(f_msg, :font=>$font, :wraplength=>'4i',
+ :justify=>:left, :anchor=>'n', :text=><<EOL)
+Ttk is the new Tk themed widget set. \
+One of the widgets it includes is the notebook widget, \
+which provides a set of tabs that allow the selection of a group of panels, \
+each with distinct content. \
+They are a feature of many modern user interfaces. \
+Not only can the tabs be selected with the mouse, \
+but they can also be switched between using Ctrl+Tab \
+when the notebook page heading itself is selected. \
+Note that the second tab is disabled, and cannot be selected.
+EOL
+neat = TkVariable.new
+after_id = nil
+msg_b = Ttk::Button.new(f_msg, :text=>'Neat!', :underline=>0,
+ :command=>proc{
+ neat.value = 'Yeah, I know...'
+ Tk.after_cancel(after_id) if after_id
+ after_id = Tk.after(500){neat.value = ''}
+ })
+msg_b.winfo_toplevel.bind('Alt-n'){ msg_b.focus; msg_b.invoke }
+msg_l = Ttk::Label.new(f_msg, :textvariable=>neat)
+notebook.add(f_msg, :text=>'Description', :underline=>0, :padding=>2)
+Tk.grid(msg_m, '-', :sticky=>'new', :pady=>2)
+Tk.grid(msg_b, msg_l, :pady=>[2, 4])
+f_msg.grid_rowconfigure(1, :weight=>1)
+f_msg.grid_columnconfigure([0, 1], :weight=>1, :uniform=>1)
+
+## Populate the second pane. Note that the content doesn't really matter
+f_disabled = Ttk::Frame.new(notebook)
+notebook.add(f_disabled, :text=>'Disabled', :state=>:disabled)
+
+## Popuplate the third pane
+f_editor = Ttk::Frame.new(notebook)
+notebook.add(f_editor, :text=>'Text Editor', :underline=>0)
+editor_t = Tk::Text.new(f_editor, :width=>40, :height=>10, :wrap=>:char)
+if Tk.windowingsystem != 'aqua'
+ editor_s = editor_t.yscrollbar(Ttk::Scrollbar.new(f_editor))
+else
+ editor_s = editor_t.yscrollbar(Tk::Scrollbar.new(f_editor))
+end
+editor_s.pack(:side=>:right, :fill=>:y, :padx=>[0,2], :pady=>2)
+editor_t.pack(:fill=>:both, :expand=>true, :padx=>[2,0], :pady=>2)
diff --git a/ext/tk/sample/demos-en/ttkpane.rb b/ext/tk/sample/demos-en/ttkpane.rb
new file mode 100644
index 0000000000..56df613db4
--- /dev/null
+++ b/ext/tk/sample/demos-en/ttkpane.rb
@@ -0,0 +1,213 @@
+# ttkpane.rb --
+#
+# This demonstration script creates a Ttk pane with some content.
+#
+# based on "Id: ttkpane.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttkpane_demo) && $ttkpane_demo
+ $ttkpane_demo.destroy
+ $ttkpane_demo = nil
+end
+
+$ttkpane_demo = TkToplevel.new {|w|
+ title("Themed Nested Panes")
+ iconname("ttkpane")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($ttkpane_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top, :fill=>:x)
+This demonstration shows off a nested set of themed paned windows. \
+Their sizes can be changed by grabbing the area \
+between each contained pane and dragging the divider.
+EOL
+
+Ttk::Separator.new(base_frame).pack(:side=>:top, :fill=>:x)
+
+## See Code / Dismiss
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttkpane'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $ttkpane_demo.destroy
+ $ttkpane_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+frame = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+
+outer = Ttk::Panedwindow.new(frame, :orient=>:horizontal)
+outer.add(in_left = Ttk::Panedwindow.new(outer, :orient=>:vertical))
+outer.add(in_right = Ttk::Panedwindow.new(outer, :orient=>:vertical))
+in_left.add(left_top = Ttk::Labelframe.new(in_left, :text=>'Button'))
+in_left.add(left_bot = Ttk::Labelframe.new(in_left, :text=>'Clocks'))
+in_right.add(right_top = Ttk::Labelframe.new(in_right, :text=>'Progress'))
+in_right.add(right_bot = Ttk::Labelframe.new(in_right, :text=>'Text'))
+if Tk.windowingsystem == 'aqua'
+ [left_top, left_bot, right_top, right_bot].each{|w| w.padding(3) }
+end
+
+# Fill the button pane
+Ttk::Button.new(left_top, :text=>'Press Me',
+ :command=>proc{
+ Tk.messageBox(:type=>'ok', :icon=>'info', :message=>'Ouch!',
+ :detail=>'That hurt...', :parent=>base_frame,
+ :title=>'Button Pressed')
+ }).pack(:padx=>2, :pady=>5)
+
+
+zones_list = [
+ [':Europe/Berlin'],
+ [':America/Argentina/Buenos_Aires', ':America/Buenos_Aires'],
+ [':Africa/Johannesburg'],
+ [':Europe/London'],
+ [':America/Los_Angeles'],
+ [':Europe/Moscow'],
+ [':America/New_York'],
+ [':Asia/Singapore'],
+ [':Australia/Sydney'],
+ [':Asia/Tokyo'],
+]
+
+zones = []
+
+# Check tzinfo support
+if $tk_major_ver > 8 || ($tk_major_ver == 8 && $tk_minor_ver >= 5)
+ tzinfo = :tcl
+
+ # Force a pre-load of all the timezones needed; otherwise can end up
+ # poor-looking synch problems!
+ zones_list.each{|list|
+ list.each{|zone|
+ begin
+ Tk.tk_call('clock', 'format', '0', '-timezone', zone)
+ rescue RuntimeError
+ # ignore
+ else
+ zones << [zone, zone[%r<[^/:]+$>].tr('_', ' ')]
+ break
+ end
+ }
+ }
+
+else
+ begin
+ require 'tzinfo'
+ tzinfo = :tzinfo
+ rescue Exception
+ begin
+ require 'tzfile'
+ tzinfo = :tzfile
+ rescue Exception
+ tzinfo = nil
+ end
+ end
+
+ case tzinfo
+ when :tzinfo
+ zones_list.each{|list|
+ list.each{|zone|
+ begin
+ tz = TZInfo::Timezone.get(zone[%r<[^:]+$>])
+ rescue Exception
+ # ignore
+ else
+ zones << [tz, zone[%r<[^/:]+$>].tr('_', ' ')]
+ break
+ end
+ }
+ }
+
+ when :tzfile
+ zones_list.each{|list|
+ list.each{|zone|
+ begin
+ tz = TZFile.create(zone[%r<[^:]+$>])
+ rescue Exception
+ # ignore
+ else
+ zones << [tz, zone[%r<[^/:]+$>].tr('_', ' ')]
+ break
+ end
+ }
+ }
+
+ else
+ [ -7, -4, -2, -1, 0, +1, +3, +8, +9, +10 ].each{|zone|
+ zones << [zone, 'UTC%+03d00' % zone]
+ }
+ end
+end
+
+time = TkVariable.new_hash
+
+case tzinfo
+when :tcl
+ update_proc = proc{|now, tz, label|
+ time[label] = Tk.tk_call('clock', 'format', now.tv_sec,
+ '-timezone', tz, '-format', '%T')
+ }
+when :tzinfo
+ update_proc = proc{|now, tz, label|
+ time[label] = tz.utc_to_local(now).strftime('%H:%M:%S')
+ }
+when :tzfile
+ update_proc = proc{|now, tz, label|
+ time[label] = tz.at(now.tv_sec).strftime('%H:%M:%S')
+ }
+else
+ update_proc = proc{|now, tz, label|
+ time[label] = (now + (tz * 3600)).strftime('%H:%M:%S')
+ }
+end
+
+# Fill the clocks pane
+zones.each_with_index{|(zone, label), idx|
+ Ttk::Separator.new(left_bot).pack(:fill=>:x) if idx > 0
+ Ttk::Label.new(left_bot, :text=>label, :anchor=>'w').pack(:fill=>:x)
+ Ttk::Label.new(left_bot, :textvariable=>time.ref(label),
+ :anchor=>'w').pack(:fill=>:x)
+}
+
+# Timer start
+every = proc{
+ now = Time.now.utc
+ zones.each{|zone, label| update_proc.call(now, zone, label) }
+}
+TkRTTimer.new(1000, -1, every).start(0, every)
+
+# Fill the progress pane
+Ttk::Progressbar.new(right_top, :mode=>:indeterminate).pack(:fill=>:both, :expand=>true).start
+
+# Fill the text pane
+if Tk.windowingsystem != 'aqua'
+ # The trick with the ttk::frame makes the text widget look like it fits with
+ # the current Ttk theme despite not being a themed widget itself. It is done
+ # by styling the frame like an entry, turning off the border in the text
+ # widget, and putting the text widget in the frame with enough space to allow
+ # the surrounding border to show through (2 pixels seems to be enough).
+ f = Ttk::Frame.new(right_bot, :style=>Ttk::Entry)
+ txt = TkText.new(frame, :wrap=>:word, :width=>30, :borderwidth=>0)
+ txt.pack(:fill=>:both, :expand=>true, :in=>f, :pady=>2, :padx=>2)
+ scr = txt.yscrollbar(Ttk::Scrollbar.new(frame))
+ scr.pack(:side=>:right, :fill=>:y, :in=>right_bot)
+ f.pack(:fill=>:both, :expand=>true)
+ outer.pack(:fill=>:both, :expand=>true)
+else
+ txt = TkText.new(frame, :wrap=>:word, :width=>30, :borderwidth=>0)
+ scr = txt.yscrollbar(TkScrollbar.new(frame))
+ scr.pack(:side=>:right, :fill=>:y, :in=>right_bot)
+ txt.pack(:fill=>:both, :expand=>true, :in=>right_bot)
+ outer.pack(:fill=>:both, :expand=>true, :padx=>10, :pady=>[6, 10])
+end
diff --git a/ext/tk/sample/demos-en/ttkprogress.rb b/ext/tk/sample/demos-en/ttkprogress.rb
new file mode 100644
index 0000000000..3eb9a64a4a
--- /dev/null
+++ b/ext/tk/sample/demos-en/ttkprogress.rb
@@ -0,0 +1,66 @@
+# ttkprogress.rb --
+#
+# This demonstration script creates several progress bar widgets.
+#
+# based on "Id: ttkprogress.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttkprogress_demo) && $ttkprogress_demo
+ $ttkprogress_demo.destroy
+ $ttkprogress_demo = nil
+end
+
+$ttkprogress_demo = TkToplevel.new {|w|
+ title("Progress Bar Demonstration")
+ iconname("ttkprogress")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($ttkprogress_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=>Tk::UTF8_String.new(<<EOL)).pack(:side=>:top, :fill=>:x)
+Below are two progress bars. \
+The top one is a \\u201Cdeterminate\\u201D progress bar, \
+which is used for showing how far through a defined task the program has got. \
+The bottom one is an \\u201Cindeterminate\\u201D progress bar, \
+which is used to show that the program is busy \
+but does not know how long for. Both are run here in self-animated mode, \
+which can be turned on and off using the buttons underneath.
+EOL
+
+## See Code / Dismiss buttons
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttkprogress'}),
+ Ttk::Button.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $ttkprogress_demo.destroy
+ $ttkprogress_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+frame = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+
+p1 = Ttk::Progressbar.new(frame, :mode=>:determinate)
+p2 = Ttk::Progressbar.new(frame, :mode=>:indeterminate)
+
+start = Ttk::Button.new(frame, :text=>'Start Progress',
+ :command=>proc{ p1.start; p2.start })
+stop = Ttk::Button.new(frame, :text=>'Stop Progress',
+ :command=>proc{ p1.stop; p2.stop })
+
+Tk.grid(p1, '-', :pady=>5, :padx=>10)
+Tk.grid(p2, '-', :pady=>5, :padx=>10)
+Tk.grid(start, stop, :padx=>10, :pady=>5)
+start.grid_configure(:sticky=>'e')
+stop.grid_configure(:sticky=>'w')
+frame.grid_columnconfigure(:all, :weight=>1)
+
diff --git a/ext/tk/sample/demos-en/twind.rb b/ext/tk/sample/demos-en/twind.rb
index c841b7c317..65ee712ff7 100644
--- a/ext/tk/sample/demos-en/twind.rb
+++ b/ext/tk/sample/demos-en/twind.rb
@@ -19,8 +19,10 @@ $twind_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($twind_demo).pack(:fill=>:both, :expand=>true)
+
# frame
-$twind_buttons = TkFrame.new($twind_demo) {|frame|
+$twind_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -39,13 +41,13 @@ $twind_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
$twind_text = nil
-TkFrame.new($twind_demo, 'highlightthickness'=>2, 'borderwidth'=>2,
- 'relief'=>'sunken') {|f|
+TkFrame.new(base_frame, 'highlightthickness'=>2, 'borderwidth'=>2,
+ 'relief'=>'sunken') {|f|
$twind_text = TkText.new(f, 'setgrid'=>'true', 'font'=>$font,
- 'width'=>'70', 'height'=>35, 'wrap'=>'word',
- 'highlightthickness'=>0, 'borderwidth'=>0 ){|t|
+ 'width'=>'70', 'height'=>35, 'wrap'=>'word',
+ 'highlightthickness'=>0, 'borderwidth'=>0 ){|t|
TkScrollbar.new(f) {|s|
- command proc{|*args| t.yview(args)}
+ command proc{|*args| t.yview(*args)}
t.yscrollcommand proc{|first,last| s.set first,last}
}.pack('side'=>'right', 'fill'=>'y')
}.pack('expand'=>'yes', 'fill'=>'both')
@@ -53,16 +55,16 @@ TkFrame.new($twind_demo, 'highlightthickness'=>2, 'borderwidth'=>2,
#
$tag_center = TkTextTag.new($twind_text,
- 'justify' =>'center',
- 'spacing1'=>'5m',
- 'spacing3'=>'5m' )
+ 'justify' =>'center',
+ 'spacing1'=>'5m',
+ 'spacing3'=>'5m' )
$tag_buttons = TkTextTag.new($twind_text,
- 'lmargin1'=>'1c',
- 'lmargin2'=>'1c',
- 'rmargin' =>'1c',
- 'spacing1'=>'3m',
- 'spacing2'=>0,
- 'spacing3'=>0 )
+ 'lmargin1'=>'1c',
+ 'lmargin2'=>'1c',
+ 'rmargin' =>'1c',
+ 'spacing1'=>'3m',
+ 'spacing2'=>0,
+ 'spacing3'=>0 )
$twind_text.insert('end', "A text widget can contain other widgets embedded ")
$twind_text.insert('end', "it. These are called \"embedded windows\", ")
@@ -70,42 +72,42 @@ $twind_text.insert('end', "and they can consist of arbitrary widgets. ")
$twind_text.insert('end', "For example, here are two embedded button ")
$twind_text.insert('end', "widgets. You can click on the first button to ")
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- #text 'ON'
- text 'Turn On'
- command proc{textWindOn $twind_text,$twind_buttons}
- cursor 'top_left_arrow'
- })
+ 'window'=>TkButton.new($twind_text) {
+ #text 'ON'
+ text 'Turn On'
+ command proc{textWindOn $twind_text,$twind_buttons}
+ cursor 'top_left_arrow'
+ })
$twind_text.insert('end', " horizontal scrolling, which also turns off ")
$twind_text.insert('end', "word wrapping. Or, you can click on the second ")
$twind_text.insert('end', "button to\n")
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- #text 'OFF'
- text 'Turn Off'
- command proc{textWindOff $twind_text}
- cursor 'top_left_arrow'
- })
+ 'window'=>TkButton.new($twind_text) {
+ #text 'OFF'
+ text 'Turn Off'
+ command proc{textWindOff $twind_text}
+ cursor 'top_left_arrow'
+ })
$twind_text.insert('end', " horizontal scrolling and turn back on word wrapping.\n\n")
$twind_text.insert('end', "Or, here is another example. If you ")
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- text 'Click Here'
- command proc{textWindPlot $twind_text}
- cursor 'top_left_arrow'
- })
+ 'window'=>TkButton.new($twind_text) {
+ text 'Click Here'
+ command proc{textWindPlot $twind_text}
+ cursor 'top_left_arrow'
+ })
$twind_text.insert('end', " a canvas displaying an x-y plot will appear right here.")
$mark_plot = TkTextMark.new($twind_text, 'insert')
$mark_plot.gravity='left'
$twind_text.insert('end', " You can drag the data points around with the mouse, ")
$twind_text.insert('end', "or you can click here to ")
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- text 'Delete'
- command proc{textWindDel $twind_text}
- cursor 'top_left_arrow'
- })
+ 'window'=>TkButton.new($twind_text) {
+ text 'Delete'
+ command proc{textWindDel $twind_text}
+ cursor 'top_left_arrow'
+ })
$twind_text.insert('end', " the plot again.\n\n")
$twind_text.insert('end', "You may also find it useful to put embedded windows in ")
@@ -123,27 +125,27 @@ $twind_text.insert('end', "to restore the short string.\n")
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {|b|
- text 'Default'
- command proc{embDefBg $twind_text}
- cursor 'top_left_arrow'
- $tag_buttons.add('end')
- },
- 'padx'=>3 )
+ 'window'=>TkButton.new($twind_text) {|b|
+ text 'Default'
+ command proc{embDefBg $twind_text}
+ cursor 'top_left_arrow'
+ $tag_buttons.add('end')
+ },
+ 'padx'=>3 )
embToggle = TkVariable.new('Short')
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkCheckButton.new($twind_text) {
- textvariable embToggle
- indicatoron 0
- variable embToggle
- onvalue 'A much longer string'
- offvalue 'Short'
- cursor 'top_left_arrow'
- pady 5
- padx 2
- },
- 'padx'=>3,
- 'pady'=>2 )
+ 'window'=>TkCheckButton.new($twind_text) {
+ textvariable embToggle
+ indicatoron 0
+ variable embToggle
+ onvalue 'A much longer string'
+ offvalue 'Short'
+ cursor 'top_left_arrow'
+ pady 5
+ padx 2
+ },
+ 'padx'=>3,
+ 'pady'=>2 )
[ 'AntiqueWhite3', 'Bisque1', 'Bisque2', 'Bisque3', 'Bisque4',
'SlateBlue3', 'RoyalBlue1', 'SteelBlue2', 'DeepSkyBlue3', 'LightBlue1',
@@ -151,13 +153,13 @@ TkTextWindow.new($twind_text, 'end',
'Yellow1', 'IndianRed1', 'IndianRed2', 'Tan1', 'Tan4'
].each{|twind_color|
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- text twind_color
- cursor 'top_left_arrow'
- command proc{$twind_text.bg twind_color}
- },
- 'padx'=>3,
- 'pady'=>2 )
+ 'window'=>TkButton.new($twind_text) {
+ text twind_color
+ cursor 'top_left_arrow'
+ command proc{$twind_text.bg twind_color}
+ },
+ 'padx'=>3,
+ 'pady'=>2 )
}
#
@@ -206,44 +208,48 @@ def textWindPlot (t)
cursor 'top_left_arrow'
}
- font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ else
+ font = 'Helvetica 18'
+ end
TkcLine.new($twind_plot, 100, 250, 400, 250, 'width'=>2)
TkcLine.new($twind_plot, 100, 250, 100, 50, 'width'=>2)
TkcText.new($twind_plot, 225, 20,
- 'text'=>"A Simple Plot", 'font'=>font, 'fill'=>'brown')
+ 'text'=>"A Simple Plot", 'font'=>font, 'fill'=>'brown')
(0..10).each {|i|
x = 100 + (i * 30)
TkcLine.new($twind_plot, x, 250, x, 245, 'width'=>2)
TkcText.new($twind_plot, x, 254,
- 'text'=>10*i, 'font'=>font, 'anchor'=>'n')
+ 'text'=>10*i, 'font'=>font, 'anchor'=>'n')
}
(0..5).each {|i|
y = 250 - (i * 40)
TkcLine.new($twind_plot, 100, y, 105, y, 'width'=>2)
TkcText.new($twind_plot, 96, y,
- 'text'=>"#{i*50}.0", 'font'=>font, 'anchor'=>'e')
+ 'text'=>"#{i*50}.0", 'font'=>font, 'anchor'=>'e')
}
for xx, yy in [[12,56],[20,94],[33,98],[32,120],[61,180],[75,160],[98,223]]
x = 100 + (3*xx)
y = 250 - (4*yy)/5
item = TkcOval.new($twind_plot, x-6, y-6, x+6, y+6,
- 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
+ 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
item.addtag 'point'
end
$twind_plot.itembind('point', 'Any-Enter',
- proc{$twind_plot.itemconfigure 'current', 'fill', 'red'})
+ proc{$twind_plot.itemconfigure 'current', 'fill', 'red'})
$twind_plot.itembind('point', 'Any-Leave',
- proc{$twind_plot.itemconfigure 'current', 'fill', 'SkyBlue2'})
+ proc{$twind_plot.itemconfigure 'current', 'fill', 'SkyBlue2'})
$twind_plot.itembind('point', '1',
- proc{|x,y| embPlotDown $twind_plot,x,y}, "%x %y")
+ proc{|x,y| embPlotDown $twind_plot,x,y}, "%x %y")
$twind_plot.itembind('point', 'ButtonRelease-1',
- proc{$twind_plot.dtag 'selected'})
+ proc{$twind_plot.dtag 'selected'})
$twind_plot.bind('B1-Motion',
- proc{|x,y| embPlotMove $twind_plot,x,y}, "%x %y")
+ proc{|x,y| embPlotMove $twind_plot,x,y}, "%x %y")
while ($twind_text.get($mark_plot) =~ /[ \t\n]/)
$twind_text.delete $mark_plot
end
diff --git a/ext/tk/sample/demos-en/twind2.rb b/ext/tk/sample/demos-en/twind2.rb
new file mode 100644
index 0000000000..43990c1151
--- /dev/null
+++ b/ext/tk/sample/demos-en/twind2.rb
@@ -0,0 +1,384 @@
+#
+# text (embedded windows) widget demo 2 (called by 'widget')
+#
+
+# delete toplevel widget
+if defined?($twind2_demo) && $twind2_demo
+ $twind2_demo.destroy
+ $twind2_demo = nil
+end
+
+# demo toplevel widget
+$twind2_demo = TkToplevel.new {|w|
+ title("Text Demonstration - Embedded Windows 2")
+ iconname("Embedded Windows")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($twind2_demo).pack(:fill=>:both, :expand=>true)
+
+# frame
+$twind2_buttons = TkFrame.new(base_frame) {|frame|
+ TkGrid(TkFrame.new(frame, :height=>2, :relief=>:sunken, :bd=>2),
+ :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ TkButton.new(frame, :text=>'See Code',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'twind2'}),
+ TkButton.new(frame, :text=>'Dismiss',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ tmppath = $twind2_demo
+ $twind2_demo = nil
+ $showVarsWin[tmppath.path] = nil
+ tmppath.destroy
+ }),
+ :padx=>4, :pady=>4)
+ frame.grid_columnconfigure(0, :weight=>1)
+}
+$twind2_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# frame
+$twind2_text = nil
+TkFrame.new(base_frame, 'highlightthickness'=>2, 'borderwidth'=>2,
+ 'relief'=>'sunken') {|f|
+ $twind2_text = TkText.new(f, 'setgrid'=>true, 'font'=>$font,
+ # 'width'=>'70', 'height'=>35, 'wrap'=>'word',
+ 'width'=>'70', 'height'=>35, 'wrap'=>'char',
+ 'highlightthickness'=>0, 'borderwidth'=>0 ){|t|
+ TkScrollbar.new(f) {|s|
+ command proc{|*args| t.yview(*args)}
+ t.yscrollcommand proc{|first,last| s.set first,last}
+ }.pack('side'=>'right', 'fill'=>'y')
+ }.pack('expand'=>'yes', 'fill'=>'both')
+}.pack('expand'=>'yes', 'fill'=>'both')
+
+# text tags
+$tag2_center = TkTextTag.new($twind2_text,
+ 'justify' =>'center',
+ 'spacing1'=>'5m',
+ 'spacing3'=>'5m' )
+$tag2_buttons = TkTextTag.new($twind2_text,
+ 'lmargin1'=>'1c',
+ 'lmargin2'=>'1c',
+ 'rmargin' =>'1c',
+ 'spacing1'=>'3m',
+ 'spacing2'=>0,
+ 'spacing3'=>0 )
+
+# insert text
+$twind2_text.insert('end',
+ 'A text widget can contain many different kinds of items, ')
+$twind2_text.insert('end',
+ "both active and passive. It can lay these out in various ")
+$twind2_text.insert('end',
+ "ways, with wrapping, tabs, centering, etc. In addition, ")
+$twind2_text.insert('end',
+ "when the contents are too big for the window, smooth ")
+$twind2_text.insert('end', "scrolling in all directions is provided.\n\n")
+
+$twind2_text.insert('end', "A text widget can contain other widgets embedded ")
+$twind2_text.insert('end', "it. These are called \"embedded windows\", ")
+$twind2_text.insert('end', "and they can consist of arbitrary widgets. ")
+$twind2_text.insert('end', "For example, here are two embedded button ")
+$twind2_text.insert('end', "widgets. You can click on the first button to ")
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ text 'ON'
+ command proc{textWindOn2 $twind2_text,$twind2_buttons}
+ cursor 'top_left_arrow'
+ })
+$twind2_text.insert('end', " horizontal scrolling, which also turns off ")
+$twind2_text.insert('end', "word wrapping. Or, you can click on the second ")
+$twind2_text.insert('end', "button to\n")
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ text 'OFF'
+ command proc{textWindOff2 $twind2_text}
+ cursor 'top_left_arrow'
+ })
+$twind2_text.insert('end',
+ " horizontal scrolling and turn back on word wrapping.\n\n")
+
+$twind2_text.insert('end', "Or, here is another example. If you ")
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ text 'Click Here'
+ command proc{textWindPlot2 $twind2_text}
+ cursor 'top_left_arrow'
+ })
+$twind2_text.insert('end',
+ " a canvas displaying an x-y plot will appear right here.")
+$mark2_plot = TkTextMark.new($twind2_text, 'insert')
+$mark2_plot.gravity='left'
+$twind2_text.insert('end',
+ " You can drag the data points around with the mouse, ")
+$twind2_text.insert('end', "or you can click here to ")
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ text 'Delete'
+ command proc{textWindDel2 $twind2_text}
+ cursor 'top_left_arrow'
+ })
+$twind2_text.insert('end', " the plot again.\n\n")
+
+$twind2_text.insert('end',
+ "You may also find it useful to put embedded windows in ")
+$twind2_text.insert('end',
+ "a text without any actual text. In this case the ")
+$twind2_text.insert('end', "text widget acts like a geometry manager. For ")
+$twind2_text.insert('end',
+ "example, here is a collection of buttons laid out ")
+$twind2_text.insert('end',
+ "neatly into rows by the text widget. These buttons ")
+$twind2_text.insert('end',
+ "can be used to change the background color of the ")
+$twind2_text.insert('end', "text widget (\"Default\" restores the color to ")
+$twind2_text.insert('end',
+ "its default). If you click on the button labeled ")
+$twind2_text.insert('end', "\"Short\", it changes to a longer string so that ")
+$twind2_text.insert('end', "you can see how the text widget automatically ")
+$twind2_text.insert('end', "changes the layout. Click on the button again ")
+$twind2_text.insert('end', "to restore the short string.\n")
+
+btn_default = TkButton.new($twind2_text) {|b|
+ text 'Default'
+ command proc{embDefBg2 $twind2_text}
+ cursor 'top_left_arrow'
+}
+TkTextWindow.new($twind2_text, 'end', 'window'=>btn_default, 'padx'=>3)
+embToggle = TkVariable.new('Short')
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkCheckButton.new($twind2_text) {
+ textvariable embToggle
+ indicatoron 0
+ variable embToggle
+ onvalue 'A much longer string'
+ offvalue 'Short'
+ cursor 'top_left_arrow'
+ pady 5
+ padx 2
+ },
+ 'padx'=>3,
+ 'pady'=>2 )
+
+[ 'AntiqueWhite3', 'Bisque1', 'Bisque2', 'Bisque3', 'Bisque4',
+ 'SlateBlue3', 'RoyalBlue1', 'SteelBlue2', 'DeepSkyBlue3', 'LightBlue1',
+ 'DarkSlateGray1', 'Aquamarine2', 'DarkSeaGreen2', 'SeaGreen1',
+ 'Yellow1', 'IndianRed1', 'IndianRed2', 'Tan1', 'Tan4'
+].each{|twind_color|
+ TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ text twind_color
+ cursor 'top_left_arrow'
+ command proc{$twind2_text.bg twind_color}
+ },
+ 'padx'=>3,
+ 'pady'=>2 )
+}
+
+$tag2_buttons.add(btn_default, 'end')
+
+$text_normal2 = {}
+$text_normal2['border'] = $twind2_text.cget('borderwidth')
+$text_normal2['highlight'] = $twind2_text.cget('highlightthickness')
+$text_normal2['pad'] = $twind2_text.cget('padx')
+
+$twind2_text.insert('end', "\nYou can also change the usual border width and ")
+$twind2_text.insert('end', "highlightthickness and padding.\n")
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Big borders",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinBigB2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Small borders",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinSmallB2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Big highlight",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinBigH2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Small highlight",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinSmallH2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Big pad",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinBigP2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Small pad",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinSmallP2 $twind2_text
+ }))
+
+$twind2_text.insert('end',
+ "\n\nFinally, images fit comfortably in text widgets too:")
+
+TkTextImage.new($twind2_text, 'end',
+ 'image'=>TkBitmapImage.new(:file=>[
+ $demo_dir, '..',
+ 'images', 'face.xbm'
+ ].join(File::Separator)))
+
+# methods
+def textWinBigB2(w)
+ w.borderwidth 15
+end
+def textWinSmallB2(w)
+ w.borderwidth $text_normal2['border']
+end
+def textWinBigH2(w)
+ w.highlightthickness 15
+end
+def textWinSmallH2(w)
+ w.highlightthickness $text_normal2['highlight']
+end
+def textWinBigP2(w)
+ w.configure(:padx=>15, :pady=>15)
+end
+def textWinSmallP2(w)
+ w.configure(:padx=>$text_normal2['pad'], :pady=>$text_normal2['pad'])
+end
+
+def textWindOn2 (w,f)
+ if defined? $twind2_scroll
+ begin
+ $twind2_scroll.destroy
+ rescue
+ end
+ $twind2_scroll = nil
+ end
+
+ base = TkWinfo.parent( TkWinfo.parent(w) )
+ $twind2_scroll = TkScrollbar.new(base) {|s|
+ orient 'horizontal'
+ command proc{|*args| w.xview(*args)}
+ w.xscrollcommand proc{|first,last| s.set first,last}
+ w.wrap 'none'
+ pack('after'=>f, 'side'=>'bottom', 'fill'=>'x')
+ }
+
+ return nil
+end
+
+def textWindOff2 (w)
+ if defined? $twind2_scroll
+ begin
+ $twind2_scroll.destroy
+ rescue
+ end
+ $twind2_scroll = nil
+ end
+ w.xscrollcommand ''
+ #w.wrap 'word'
+ w.wrap 'char'
+end
+
+def textWindPlot2 (t)
+ if (defined? $twind2_plot) && (TkWinfo.exist?($twind2_plot))
+ return
+ end
+
+ $twind2_plot = TkCanvas.new(t) {
+ relief 'sunken'
+ width 450
+ height 300
+ cursor 'top_left_arrow'
+ }
+
+ #font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ font = 'Helvetica 18'
+
+ TkcLine.new($twind2_plot, 100, 250, 400, 250, 'width'=>2)
+ TkcLine.new($twind2_plot, 100, 250, 100, 50, 'width'=>2)
+ TkcText.new($twind2_plot, 225, 20,
+ 'text'=>"A Simple Plot", 'font'=>font, 'fill'=>'brown')
+
+ (0..10).each {|i|
+ x = 100 + (i * 30)
+ TkcLine.new($twind2_plot, x, 250, x, 245, 'width'=>2)
+ TkcText.new($twind2_plot, x, 254,
+ 'text'=>10*i, 'font'=>font, 'anchor'=>'n')
+ }
+ (0..5).each {|i|
+ y = 250 - (i * 40)
+ TkcLine.new($twind2_plot, 100, y, 105, y, 'width'=>2)
+ TkcText.new($twind2_plot, 96, y,
+ 'text'=>"#{i*50}.0", 'font'=>font, 'anchor'=>'e')
+ }
+
+ for xx, yy in [[12,56],[20,94],[33,98],[32,120],[61,180],[75,160],[98,223]]
+ x = 100 + (3*xx)
+ y = 250 - (4*yy)/5
+ item = TkcOval.new($twind2_plot, x-6, y-6, x+6, y+6,
+ 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
+ item.addtag 'point'
+ end
+
+ $twind2_plot.itembind('point', 'Any-Enter',
+ proc{$twind2_plot.itemconfigure 'current', 'fill', 'red'})
+ $twind2_plot.itembind('point', 'Any-Leave',
+ proc{$twind2_plot.itemconfigure 'current', 'fill', 'SkyBlue2'})
+ $twind2_plot.itembind('point', '1',
+ proc{|x,y| embPlotDown2 $twind2_plot,x,y}, "%x %y")
+ $twind2_plot.itembind('point', 'ButtonRelease-1',
+ proc{$twind2_plot.dtag 'selected'})
+ $twind2_plot.bind('B1-Motion',
+ proc{|x,y| embPlotMove2 $twind2_plot,x,y}, "%x %y")
+ while ($twind2_text.get($mark2_plot) =~ /[ \t\n]/)
+ $twind2_text.delete $mark2_plot
+ end
+ $twind2_text.insert $mark2_plot,"\n"
+ TkTextWindow.new($twind2_text, $mark2_plot, 'window'=>$twind2_plot)
+ $tag2_center.add $mark2_plot
+ $twind2_text.insert $mark2_plot,"\n"
+end
+
+$embPlot2 = {'lastX'=>0, 'lastY'=>0}
+
+def embPlotDown2 (w, x, y)
+ w.dtag 'selected'
+ w.addtag_withtag 'selected', 'current'
+ w.raise 'current'
+ $embPlot2['lastX'] = x
+ $embPlot2['lastY'] = y
+end
+
+def embPlotMove2 (w, x, y)
+ w.move 'selected', x - $embPlot2['lastX'], y - $embPlot2['lastY']
+ $embPlot2['lastX'] = x
+ $embPlot2['lastY'] = y
+end
+
+def textWindDel2 (w)
+ if (defined? $twind2_text) && TkWinfo.exist?($twind2_plot)
+ $twind2_text.delete $twind2_plot
+ $twind2_plot = nil
+ while ($twind2_text.get($mark2_plot) =~ /[ \t\n]/)
+ $twind2_text.delete $mark2_plot
+ end
+ $twind2_text.insert $mark2_plot," "
+ end
+end
+
+def embDefBg2 (w)
+ w['background'] = w.configinfo('background')[3]
+end
diff --git a/ext/tk/sample/demos-en/unicodeout.rb b/ext/tk/sample/demos-en/unicodeout.rb
index 7bb951c93c..9c230a2536 100644
--- a/ext/tk/sample/demos-en/unicodeout.rb
+++ b/ext/tk/sample/demos-en/unicodeout.rb
@@ -16,9 +16,11 @@ $unicodeout_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($unicodeout_demo,
- :font=>$font, :wraplength=>'5.4i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+base_frame = TkFrame.new($unicodeout_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'5.4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
This is a sample of Tk's support for languages that use non-Western \
character sets. However, what you will actually see below depends \
largely on what character sets you have installed, and what you see \
@@ -36,22 +38,22 @@ The strings are converted to the encoded string objects \
And the Tk::UTF8_String objects are passed to the label widgets.
EOL
-TkFrame.new($unicodeout_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
TkButton.new(f, :text=>'Dismiss', :width=>15, :command=>proc{
- $unicodeout_demo.destroy
- $unicodeout_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ $unicodeout_demo.destroy
+ $unicodeout_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'See Code', :width=>15, :command=>proc{
- showCode 'unicodeout'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'unicodeout'
+ }).pack(:side=>:left, :expand=>true)
}
-wait_msg = TkLabel.new($unicodeout_demo,
- :text=>"Please wait while loading fonts...",
- :font=>"Helvetica 12 italic").pack
+wait_msg = TkLabel.new(base_frame,
+ :text=>"Please wait while loading fonts...",
+ :font=>"Helvetica 12 italic").pack
class Unicodeout_SampleFrame < TkFrame
@@font = $font
@@ -63,23 +65,23 @@ class Unicodeout_SampleFrame < TkFrame
# @@font = 'Newspaper 12'
# @@font = '{New century schoolbook} 12'
- def initialize()
- super($unicodeout_demo)
+ def initialize(base)
+ super(base)
grid_columnconfig(1, :weight=>1)
end
def add_sample(lang, *args)
sample_txt = Tk::UTF8_String(args.join(''))
l = TkLabel.new(self, :font=>@@font, :text=>lang+':',
- :anchor=>:nw, :pady=>0)
+ :anchor=>:nw, :pady=>0)
#s = TkLabel.new(self, :font=>@@font, :text=>sample_txt,
s = TkLabel.new(self, :font=>TkFont.new(@@font), :text=>sample_txt,
- :anchor=>:nw, :width=>30, :pady=>0)
+ :anchor=>:nw, :width=>30, :pady=>0)
Tk.grid(l, s, :sticky=>:ew, :pady=>0)
l.grid_config(:padx, '1m')
end
end
-f = Unicodeout_SampleFrame.new
+f = Unicodeout_SampleFrame.new(base_frame)
f.pack(:expand=>true, :fill=>:both, :padx=>'2m', :pady=>'1m')
# Processing when some characters are missing might take a while, so make
@@ -90,23 +92,23 @@ $unicodeout_demo.cursor('watch')
Tk.update
f.add_sample('Arabic',
- '\uFE94\uFEF4\uFE91\uFEAE\uFECC\uFEDF\uFE8D\uFE94',
- '\uFEE4\uFEE0\uFEDC\uFEDF\uFE8D')
+ '\uFE94\uFEF4\uFE91\uFEAE\uFECC\uFEDF\uFE8D\uFE94',
+ '\uFEE4\uFEE0\uFEDC\uFEDF\uFE8D')
f.add_sample('Trad. Chinese', '\u4E2D\u570B\u7684\u6F22\u5B57')
f.add_sample('Simpl. Chinese', '\u6C49\u8BED')
f.add_sample('Greek',
- '\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE ',
- '\u03B3\u03BB\u03CE\u03C3\u03C3\u03B1')
+ '\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE ',
+ '\u03B3\u03BB\u03CE\u03C3\u03C3\u03B1')
f.add_sample('Hebrew',
- '\u05DD\u05D9\u05DC\u05E9\u05D5\u05E8\u05D9 ',
- '\u05DC\u05D9\u05D0\u05E8\u05E9\u05D9')
+ '\u05DD\u05D9\u05DC\u05E9\u05D5\u05E8\u05D9 ',
+ '\u05DC\u05D9\u05D0\u05E8\u05E9\u05D9')
f.add_sample('Japanese',
- '\u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A, ',
- '\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA')
+ '\u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A, ',
+ '\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA')
f.add_sample('Korean', '\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00')
f.add_sample('Russian',
- '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 ',
- '\u044F\u0437\u044B\u043A')
+ '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 ',
+ '\u044F\u0437\u044B\u043A')
wait_msg.destroy
$unicodeout_demo.cursor(oldCursor)
diff --git a/ext/tk/sample/demos-en/vscale.rb b/ext/tk/sample/demos-en/vscale.rb
index 636b85813b..b05ed12072 100644
--- a/ext/tk/sample/demos-en/vscale.rb
+++ b/ext/tk/sample/demos-en/vscale.rb
@@ -15,7 +15,9 @@ $vscale_demo = TkToplevel.new {|w|
}
positionWindow($vscale_demo)
-msg = TkLabel.new($vscale_demo) {
+base_frame = TkFrame.new($vscale_demo).pack(:fill=>:both, :expand=>true)
+
+msg = TkLabel.new(base_frame) {
font $font
wraplength '3.5i'
justify 'left'
@@ -23,7 +25,7 @@ msg = TkLabel.new($vscale_demo) {
}
msg.pack('side'=>'top', 'padx'=>'.5c')
-TkFrame.new($vscale_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc {
@@ -39,7 +41,17 @@ TkFrame.new($vscale_demo) {|frame|
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
-TkFrame.new($vscale_demo) {|frame|
+def setHeight(w, height)
+ height = height + 21
+ y2 = height - 30
+ if y2 < 21
+ y2 = 21
+ end
+ w.coords 'poly',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
+ w.coords 'line',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
+end
+
+TkFrame.new(base_frame) {|frame|
borderwidth 10
canvas = TkCanvas.new(frame) {|c|
width 50
@@ -65,14 +77,3 @@ TkFrame.new($vscale_demo) {|frame|
}.pack('side'=>'left', 'anchor'=>'ne')
scale.set 75
}.pack
-
-
-def setHeight(w, height)
- height = height + 21
- y2 = height - 30
- if y2 < 21
- y2 = 21
- end
- w.coords 'poly',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
- w.coords 'line',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
-end
diff --git a/ext/tk/sample/demos-en/widget b/ext/tk/sample/demos-en/widget
index aa702883de..9a0605d8b9 100644
--- a/ext/tk/sample/demos-en/widget
+++ b/ext/tk/sample/demos-en/widget
@@ -10,15 +10,12 @@
# as needed.
require 'tk'
-
-#unless /^8\.[1-9]/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK
-# require 'tkencoding'
-#end
-
-require 'tkafter'
+# require 'tkafter'
### $DEBUG=1 ##########
+$RubyTk_WidgetDemo = true
+
#----------------------------------------------------------------
# The code below create the main window, consisting of a menu bar
# and a text widget that explains how to use the program, plus lists
@@ -26,28 +23,104 @@ require 'tkafter'
#----------------------------------------------------------------
# widget demo directory
-$demo_dir = File.dirname($0)
+# $demo_dir = File.dirname($0)
+$demo_dir = File.dirname(__FILE__)
# root
$root = TkRoot.new{title "Ruby/Tk Widget Demonstration"}
# tk
$tk_version = Tk::TK_VERSION
+$tk_major_ver, $tk_minor_ver = $tk_version.split('.').map{|n| n.to_i}
+$tk_patchlevel = Tk::TK_PATCHLEVEL
# tcl_platform
$tk_platform = TkVarAccess.new('tcl_platform')
#
-$font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*', nil)
+case($tk_version)
+when /^4.*/
+ $font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*', nil)
+else
+ $font = TkFont.new('Helvetica -12')
+end
+
+# images
+$image = {}
+
+if $tk_major_ver >= 8
+$image['refresh'] = TkPhotoImage.new(:height=>16, :format=>'GIF', :data=><<EOD)
+ R0lGODlhEAAQAPMAAMz/zCpnKdb/1z9mPypbKBtLGy9NMPL/9Or+6+P+4j1Y
+ PwQKBP7//xMLFAYBCAEBASH5BAEAAAAALAAAAAAQABAAAwR0EAD3Gn0Vyw0e
+ ++CncU7IIAezMA/nhUqSLJizvSdCEEjy2ZIV46AwDAoDHwPYGSoEiUJAAGJ6
+ EDHBNCFINW5OqABKSFk/B9lUa94IDwIFgewFMwQDQwCZQCztTgM9Sl8SOEMG
+ KSAthiaOjBMPDhQONBiXABEAOw==
+EOD
+end
+
+if $tk_major_ver >= 8
+$image['view'] = TkPhotoImage.new(:height=>16, :format=>'GIF', :data=><<EOD)
+ R0lGODlhEAAQAPMAAMz/zP///8DAwICAgH9/fwAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAwRIcMhJB7h3hM33
+ KFjWdQQYap1QrCaGBmrRrS4nj5b53jOgbwXBKGACoYLDIuAoHCmZyYvR1rT5
+ RMAq8LqcIYGsrjPsW1XOmFUEADs=
+EOD
+end
+
+if $tk_major_ver >= 8
+$image['delete'] = TkPhotoImage.new(:height=>16, :format=>'GIF', :data=><<EOD)
+ R0lGODlhEAAOAKEAAIQAAO/n3v///////yH5BAEKAAIALAAAAAAQAA4AAAIm
+ lI9pAKHbIHNoVhYhTdjlJ2AWKG2g+CldmB6rxo2uybYhbS80eRQAOw==
+EOD
+end
+
+if $tk_major_ver >= 8
+$image['print'] = TkPhotoImage.new(:height=>19, :format=>'GIF', :data=><<EOD)
+ R0lGODlhGgATAPcAACEQOTEpQjEpUkIpc0IxY0I5c0oxjEo5SlJCY1JCe1JK
+ UlpChFpCjFpGkFpSc1paa2NKc2NKnGNja2tapWtjc29KnHNanHNjc3NjrXNr
+ jHNrnHNzc3tjpXtrtXtzhICAgIRzvYSEjIZzqox7tYyEnIyMjJSEtZSEvZSM
+ lJyMtZyMvZyUlJyUrZyUvZycnKWctaWlpa2czq2lzrWtvbWtzrW1tb21xr21
+ 1sa9zs693s7OztbO3tbO597W1t7W7+fe7+fn5////+/n7+/v7+/v9////wAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAACH5BAEAAEEALAAAAAAaABMAQAj/AIMIHBhkg0GC
+ CBMGIQEiQgseQT4oeCBBAokgRYYQ0JBixg8hRIiUUEBBYYmTByBwiCBCRYwH
+ CxY8cKFw4AogRXLqLAJkQ80gCBBg3BkxZswTNGh4MGqgQQUMJRHCwMkTSE+D
+ Pn8eCKBhxIMhO3ei2OHDBw6sWSlMMMoWgwwfMDZI8GBjx44NARZwEGGi5MkS
+ PcIWKRGz5YgLbAco+KkQBQoJIRgjdGEVq+SaJajqtNrzMgsPCmoIzqmDgmWE
+ KOBuUKAAwYabYTfs4OHjY0giGyhk4MAWRI4eKyRQqPgggYUXPH4A+XBAgwoK
+ DiIsCFxjA9sFEVQQCRJCAYAFDJxiKhAxvMTonEFimrhhYinTBgWiCvxLNX3M
+ DkkpsKV5OYhjBxCMYAICAigUEAA7
+EOD
+end
#
-TkMenubar.new($root,
- [[['File', 0],
- ['About ... ', proc{aboutBox}, 0, '<F1>'],
- '---',
- ['Quit', proc{exit}, 0, 'Meta-Q']
- ]]).pack('side'=>'top', 'fill'=>'x')
+if $tk_major_ver >= 8
+ $root.add_menubar([[['File', 0],
+ ['About ... ', proc{aboutBox}, 0, '<F1>'],
+ '---',
+ ['Quit', proc{exit}, 0, 'Ctrl-Q']
+ ]])
+else
+ TkMenubar.new($root,
+ [[['File', 0],
+ ['About ... ', proc{aboutBox}, 0, '<F1>'],
+ '---',
+ ['Quit', proc{exit}, 0, 'Ctrl-Q']
+ ]]).pack('side'=>'top', 'fill'=>'x')
+end
$root.bind('F1', proc{aboutBox})
+$root.bind('Control-q', proc{exit})
=begin
TkFrame.new($root){|frame|
@@ -67,7 +140,7 @@ if $tk_version =~ /^4\.[01]/
scr = TkScrollbar.new($root, 'orient'=>'vertical')
txt = TkText.new($root) {
wrap 'word'
- width 60
+ width 70
height 30
font $font
setgrid 'yes'
@@ -79,12 +152,12 @@ if $tk_version =~ /^4\.[01]/
else
textFrame = TkFrame.new($root)
scr = TkScrollbar.new($root, 'orient'=>'vertical',
- 'highlightthickness'=>0, 'takefocus'=>1) {
+ 'highlightthickness'=>0, 'takefocus'=>1) {
pack('in'=>textFrame, 'side'=>'right', 'fill'=>'y', 'padx'=>1)
}
txt = TkText.new($root) {
wrap 'word'
- width 60
+ width 70
height 30
font $font
setgrid 'yes'
@@ -92,6 +165,7 @@ else
padx 4
pady 2
takefocus 0
+ bd 1
yscrollcommand proc{|first,last| scr.set first,last}
}
scr.command(proc{|*args| txt.yview(*args)})
@@ -101,13 +175,18 @@ else
textFrame.pack('expand'=>'yes', 'fill'=>'both')
statusBar = TkFrame.new($root) {|f|
+ if $tk_version =~ /^4.*/
+ statusfont = '-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
+ else
+ statusfont = 'Helvetica 10'
+ end
$statusBarLabel = \
TkLabel.new(f, 'text'=>" ", 'relief'=>'sunken', 'bd'=>1, 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') \
- .pack('side'=>'left', 'padx'=>2, 'expand'=>'yes', 'fill'=>'both')
+ 'font'=>statusfont) \
+ .pack('side'=>'left', 'padx'=>2, 'expand'=>'yes', 'fill'=>'both')
TkLabel.new(f, 'width'=>8, 'relief'=>'sunken', 'bd'=>1, 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') \
- .pack('side'=>'left', 'padx'=>2)
+ 'font'=>statusfont) \
+ .pack('side'=>'left', 'padx'=>2)
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>2)
end
@@ -115,7 +194,11 @@ end
# section titles and demo descriptions. Also define the bindings for
# tags.
-tag_title = TkTextTag.new(txt, 'font'=>'-*-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*')
+if $tk_version =~ /^4.*/
+ tag_title = TkTextTag.new(txt, 'font'=>'-*-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*')
+else
+ tag_title = TkTextTag.new(txt, 'font'=>'Helvetica 18 bold')
+end
# We put some "space" characters to the left and right of each demo description
# so that the descriptions are highlighted only when the mouse cursor
@@ -123,55 +206,55 @@ tag_title = TkTextTag.new(txt, 'font'=>'-*-Helvetica-Bold-R-Normal--*-180-*-*-*-
tag_demospace = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c')
-if TkWinfo.depth($root) == '1'
+if TkWinfo.depth($root) == 1
tag_demo = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c',
- 'underline'=>1)
+ 'underline'=>1)
$tag_visited = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c',
- 'underline'=>1)
+ 'underline'=>1)
tag_hot = TkTextTag.new(txt, 'background'=>'black', 'foreground'=>'white')
else
tag_demo = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c',
- 'foreground'=>'blue', 'underline'=>1)
+ 'foreground'=>'blue', 'underline'=>1)
$tag_visited = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c',
- 'foreground'=>'#303080', 'underline'=>1)
+ 'foreground'=>'#303080', 'underline'=>1)
# tag_hot = TkTextTag.new(txt, 'relief'=>'raised', 'borderwidth'=>1,
-# 'background'=>'SeaGreen3')
+# 'background'=>'SeaGreen3')
tag_hot = TkTextTag.new(txt, 'borderwidth'=>1, 'foreground'=>'red')
end
#tag_demo.bind('Button-1', proc{invoke txt, txt.index('current')})
tag_demo.bind('ButtonRelease-1',
- proc{|x,y|invoke txt, txt.index("@#{x},#{y}")}, '%x %y')
+ proc{|x,y|invoke txt, txt.index("@#{x},#{y}")}, '%x %y')
lastLine = TkVariable.new("")
newLine = TkVariable.new("")
tag_demo.bind('Enter', proc{|x,y|
- lastLine.value = txt.index("@#{x},#{y} linestart")
- tag_hot.add(lastLine.value, "#{lastLine.value} lineend")
- showStatus txt, txt.index("@#{x},#{y}")
- },
- '%x %y')
+ lastLine.value = txt.index("@#{x},#{y} linestart")
+ tag_hot.add(lastLine.value, "#{lastLine.value} lineend")
+ showStatus txt, txt.index("@#{x},#{y}")
+ },
+ '%x %y')
tag_demo.bind('Leave',
- proc{
- tag_hot.remove('1.0','end')
- txt.configure('cursor','xterm')
- $statusBarLabel.configure('text'=>"")
- })
+ proc{
+ tag_hot.remove('1.0','end')
+ txt.configure('cursor','xterm')
+ $statusBarLabel.configure('text'=>"")
+ })
tag_demo.bind('Motion', proc{|x, y|
- newLine.value = txt.index("@#{x},#{y} linestart")
- if newLine.value != lastLine.value
- tag_hot.remove('1.0','end')
- lastLine.value = newLine.value
- if ( txt.tag_names("@#{x},#{y}").find{|t|
- t.kind_of?(String) && t =~ /^demo-/
- } )
- tag_hot.add(lastLine.value,
- "#{lastLine.value} lineend -1 chars")
- end
- end
- showStatus txt, txt.index("@#{x},#{y}")
- },
- '%x %y')
+ newLine.value = txt.index("@#{x},#{y} linestart")
+ if newLine.value != lastLine.value
+ tag_hot.remove('1.0','end')
+ lastLine.value = newLine.value
+ if ( txt.tag_names("@#{x},#{y}").find{|t|
+ t.kind_of?(String) && t =~ /^demo-/
+ } )
+ tag_hot.add(lastLine.value,
+ "#{lastLine.value} lineend -1 chars")
+ end
+ end
+ showStatus txt, txt.index("@#{x},#{y}")
+ },
+ '%x %y')
# Create the text for the text widget.
@@ -184,7 +267,10 @@ the demonstration. Once the demonstration window appears, you can \
click the "See Code" button to see the Ruby/Tk code that created the \
demonstration. If you wish, you can edit the code and click the \
"Rerun Demo" button in the code window to reinvoke the demonstration \
-with the modified code.
+with the modified code. \
+Don't worry about breaking the source code. \
+Your modifications are not reflected on the original file. \
+Please try many kind of changes.
Some demo scripts require the recent version of Tk library \
(e.g. Tk8.4 or later) \
@@ -193,6 +279,20 @@ required by the demo script, the demo doesn't work. \
In such a case, please re-compile tcltklib with the later Tk library \
which supports the required functions.
+If your Tk supports Ttk (Tile) extension (included or installed), \
+please try the demo of Ttk extension (sample/tkextlib/tile/demo.rb) too.
+( Probably, Ttk extension \
+#{
+begin
+ require 'tkextlib/tile'
+ "is already installed on your environment"
+rescue
+ "is not installed on your environment yet"
+end
+}\
+. )
+Ttk extension is a standard feature of Tk8.5 or later.
+
EOT
@@ -206,21 +306,27 @@ txt.insert('end', "3. Buttons.\n", tag_demo, "demo-button")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "4. Checkbuttons (select any of a group).\n", tag_demo, "demo-check")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "5. Radiobuttons (select one of a group).\n", tag_demo, "demo-radio")
+txt.insert('end', "5. Checkbuttons (if supported).\n", tag_demo, "demo-check2")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "6. Radiobuttons (select one of a group).\n", tag_demo, "demo-radio")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "7. Radiobuttons (if supported 'compound' option).\n", tag_demo, "demo-radio2")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "6. Radiobuttons (if supported 'compound' option).\n", tag_demo, "demo-radio2")
+txt.insert('end', "8. Radiobuttons (if supported).\n", tag_demo, "demo-radio3")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "7. A 15-puzzle game made out of buttons.\n", tag_demo, "demo-puzzle")
+txt.insert('end', "9. A 15-puzzle game made out of buttons.\n", tag_demo, "demo-puzzle")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "8. Iconic buttons that use bitmaps.\n", tag_demo, "demo-icon")
+txt.insert('end', "10. Iconic buttons that use bitmaps.\n", tag_demo, "demo-icon")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "9. Two labels displaying images.\n", tag_demo, "demo-image1")
+txt.insert('end', "11. Two labels displaying images.\n", tag_demo, "demo-image1")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "10. A simple user interface for viewing images.\n", tag_demo, "demo-image2")
+txt.insert('end', "12. A simple user interface for viewing images.\n", tag_demo, "demo-image2")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "11. A simple user interface for viewing images. (if supported)\n", tag_demo, "demo-image3")
+txt.insert('end', "13. A simple user interface for viewing images. (if supported)\n", tag_demo, "demo-image3")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "12. Labelled frames (if supported)\n", tag_demo, "demo-labelframe")
+txt.insert('end', "14. Labelled frames (if supported)\n", tag_demo, "demo-labelframe")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "15. The simple Themed Tk widgets (require Tile/Ttk extension)\n", tag_demo, "demo-ttkbut")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
@@ -232,6 +338,10 @@ txt.insert('end', "2. Colors: change the color scheme for the application.\n", "
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "3. A collection of famous sayings.\n", tag_demo, "demo-sayings")
txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "4. A multi-column list of contries. (require Tile/Ttk extension)\n", tag_demo, "demo-mclist")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "5. A directory browser tree. (require Tile/Ttk extension)\n", tag_demo, "demo-tree")
+txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
txt.insert('end', "Entries and Spin-boxes\n", tag_title)
@@ -241,12 +351,14 @@ txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. With scrollbars.\n", tag_demo, "demo-entry2")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end',
- "3. Validated entries and password fields. (if supported)\n",
- tag_demo, "demo-entry3")
+ "3. Validated entries and password fields. (if supported)\n",
+ tag_demo, "demo-entry3")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "4. Spin-boxes. (if supported)\n", tag_demo, "demo-spin")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "5. Simple Rolodex-like form.\n", tag_demo, "demo-form")
+txt.insert('end', "5. Combo-boxes. (require Tile/Ttk extension)\n", tag_demo, "demo-combo")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "6. Simple Rolodex-like form.\n", tag_demo, "demo-form")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
@@ -260,7 +372,11 @@ txt.insert('end', "3. Hypertext (tag bindings).\n", tag_demo, "demo-bind")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "4. A text widget with embedded windows.\n", tag_demo, "demo-twind")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "5. A search tool built with a text widget.\n", tag_demo, "demo-search")
+txt.insert('end', "5. A text widget with embedded windows. (if supported)\n", tag_demo, "demo-twind2")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "6. A search tool built with a text widget.\n", tag_demo, "demo-search")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "7. Peering text widgets. (if supported)\n", tag_demo, "demo-textpeer")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
@@ -278,33 +394,47 @@ txt.insert('end', "5. A ruler with adjustable tab stops.\n", tag_demo, "demo-rul
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "6. A building floor plan.\n", tag_demo, "demo-floor")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "7. A simple scrollable canvas.\n", tag_demo, "demo-cscroll")
+txt.insert('end', "7. A building floor plan. (another way to create canvas items)\n", tag_demo, "demo-floor2")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "8. A simple scrollable canvas.\n", tag_demo, "demo-cscroll")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "9. A Knight's tour of the chess board. (require Tile/Ttk extension)\n", tag_demo, "demo-knightstour")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
-txt.insert('end', "Scales\n", tag_title)
+txt.insert('end', "Scales and Progress Bars\n", tag_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. Vertical scale.\n", tag_demo.id, "demo-vscale")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. Horizontal scale.\n", tag_demo.id, "demo-hscale")
txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "3. Progress bar. (require Tile/Ttk extension)\n", tag_demo.id, "demo-ttkprogress")
+txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
-txt.insert('end', "Paned Windows\n", tag_title)
+txt.insert('end', "Paned Windows and Notebooks\n", tag_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. Horizontal paned window. (if supported)\n", tag_demo.id, "demo-paned1")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. Vertical paned window. (if supported)\n", tag_demo.id, "demo-paned2")
txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "3. Themed nested panes. (require Tile/Ttk extension)\n", tag_demo.id, "demo-ttkpane")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "4. Notebook widget. (require Tile/Ttk extension)\n", tag_demo.id, "demo-ttknote")
+txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
-txt.insert('end', "Menus\n", tag_title)
+txt.insert('end', "Menus and Toolbars\n", tag_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. Menus and cascades.\n", tag_demo, "demo-menu")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. Menus and cascades. (if supported)\n", tag_demo, "demo-menu84")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "3. Menubuttons\n", tag_demo, "demo-menubu")
+txt.insert('end', "3. Menubuttons.\n", tag_demo, "demo-menubu")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "4. Themed menu buttons. (require Tile/Ttk extension)\n", tag_demo, "demo-ttkmenu")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "5. Themed toolbar. (require Tile/Ttk extension)\n", tag_demo, "demo-toolbar")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
@@ -312,12 +442,25 @@ txt.insert('end', "Common Dialogs\n", tag_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. Message boxes.\n", tag_demo, "demo-msgbox")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "2. File selection dialog.\n", tag_demo, "demo-filebox")
+txt.insert('end', "2. Message boxes with detail text. (if supported)\n", tag_demo, "demo-msgbox2")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "3. File selection dialog.\n", tag_demo, "demo-filebox")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "3. Color picker.\n", tag_demo, "demo-clrpick")
+txt.insert('end', "4. Color picker.\n", tag_demo, "demo-clrpick")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
+txt.insert('end', "Animation\n", tag_title)
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "1. Animated labels (if supported)\n", tag_demo, "demo-anilabel")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "2. Animated wave (if supported)\n", tag_demo, "demo-aniwave")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "3. Pendulum simulation (if supported)\n", tag_demo, "demo-pendulum")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "4. A celebration of Rube Goldberg (if supported)\n", tag_demo, "demo-goldberg")
+
+txt.insert('end', "\n")
txt.insert('end', "Miscellaneous\n", tag_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. The built-in bitmaps.\n", tag_demo, "demo-bitmap")
@@ -335,7 +478,7 @@ scr.focus
# new demo window.
#
# Arguments:
-# w - The name of the window to position.
+# w - The name of the window to position.
def positionWindow(w)
w.geometry('+300+300')
@@ -346,11 +489,11 @@ end
# updates the display whenever any of the variables changes.
#
# Arguments:
-# w - Name of new window to create for display.
-# args - Any number of names of variables.
+# w - Name of new window to create for display.
+# args - Any number of names of variables.
$showVarsWin = {}
-def showVars (parent, *args)
+def showVars1(parent, *args)
if $showVarsWin[parent.path]
begin
$showVarsWin[parent.path].destroy
@@ -359,11 +502,16 @@ def showVars (parent, *args)
end
w = TkToplevel.new(parent) {|w|
title "Variable values"
- TkLabel.new(w) {
+ base = TkFrame.new(w).pack(:fill=>:both, :expand=>true)
+ TkLabel.new(base) {
text "Variable values:"
width 20
anchor 'center'
- font '-Adobe-helvetica-medium-r-normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ font '-Adobe-helvetica-medium-r-normal--*-180-*-*-*-*-*-*'
+ else
+ font 'Helvetica 14'
+ end
}.pack('side'=>'top', 'fill'=>'x')
len = 1
args.each{|vnam,vbody|
@@ -371,13 +519,13 @@ def showVars (parent, *args)
}
args.each{|vnam,vbody|
TkFrame.new(w){|f|
- #TkLabel.new(f, 'text'=>"#{vnam}: ").pack('side'=>'left')
- TkLabel.new(f, 'text'=>"#{vnam}: ",'width'=>len+2).pack('side'=>'left')
- TkLabel.new(f, 'textvariable'=>vbody, 'anchor'=>'w')\
- .pack('side'=>'left', 'expand'=>'yes', 'fill'=>'x')
+ #TkLabel.new(f, 'text'=>"#{vnam}: ").pack('side'=>'left')
+ TkLabel.new(f, 'text'=>"#{vnam}: ",'width'=>len+2).pack('side'=>'left')
+ TkLabel.new(f, 'textvariable'=>vbody, 'anchor'=>'w')\
+ .pack('side'=>'left', 'expand'=>'yes', 'fill'=>'x')
}.pack('side'=>'top', 'anchor'=>'w', 'fill'=>'x')
}
- TkButton.new(w) {
+ TkButton.new(base) {
text "OK"
command proc{w.destroy}
}.pack('side'=>'bottom', 'pady'=>2)
@@ -385,32 +533,198 @@ def showVars (parent, *args)
$showVarsWin[parent.path] = w
end
+def showVars2(parent, *args)
+ if $showVarsWin[parent.path]
+ begin
+ $showVarsWin[parent.path].destroy
+ rescue
+ end
+ end
+ $showVarsWin[parent.path] = TkToplevel.new(parent) {|top|
+ title "Variable values"
+
+ base = TkFrame.new(top).pack(:fill=>:both, :expand=>true)
+
+ TkLabelFrame.new(base, :text=>"Variable values:",
+ :font=>{:family=>'Helvetica', :size=>14}){|f|
+ args.each{|vnam,vbody|
+ TkGrid(TkLabel.new(f, :text=>"#{vnam}: ", :anchor=>'w'),
+ TkLabel.new(f, :textvariable=>vbody, :anchor=>'w'),
+ :padx=>2, :pady=>2, :sticky=>'w')
+ }
+
+ f.grid(:sticky=>'news', :padx=>4)
+ f.grid_columnconfig(1, :weight=>1)
+ f.grid_rowconfig(100, :weight=>1)
+ }
+ TkButton.new(base, :text=>"OK", :width=>8, :default=>:active,
+ :command=>proc{top.destroy}){|b|
+ top.bind('Return', proc{b.invoke})
+ top.bind('Escape', proc{b.invoke})
+
+ b.grid(:sticky=>'e', :padx=>4, :pady=>[6, 4])
+ }
+ base.grid_columnconfig(0, :weight=>1)
+ base.grid_rowconfig(0, :weight=>1)
+ }
+end
+
+if $tk_major_ver < 8
+ alias showVars showVars1
+elsif $tk_major_ver == 8 && $tk_minor_ver < 4
+ alias showVars showVars1
+else # ver >= 8.4
+ alias showVars showVars2
+end
+
+# Pseudo-Toplevel support
+module PseudoToplevel_Evaluable
+ def pseudo_toplevel_eval(body = Proc.new)
+ Thread.current[:TOPLEVEL] = self
+ begin
+ body.call
+ ensure
+ Thread.current[:TOPLEVEL] = nil
+ end
+ end
+
+ def pseudo_toplevel_evaluable?
+ @pseudo_toplevel_evaluable
+ end
+ def pseudo_toplevel_evaluable=(mode)
+ @pseudo_toplevel_evaluable = (mode)? true: false
+ end
+
+ def self.extended(mod)
+ mod.__send__(:extend_object, mod)
+ mod.instance_variable_set('@pseudo_toplevel_evaluable', true)
+ end
+end
+
+class Object
+ alias __method_missing__ method_missing
+ private :__method_missing__
+
+ def method_missing(id, *args)
+ begin
+ has_top = (top = Thread.current[:TOPLEVEL]) &&
+ top.respond_to?(:pseudo_toplevel_evaluable?) &&
+ top.pseudo_toplevel_evaluable? &&
+ top.respond_to?(id)
+ rescue Exception => e
+ has_top = false
+ end
+
+ if has_top
+ top.__send__(id, *args)
+ else
+ __method_missing__(id, *args)
+ end
+ end
+end
+
+class Proc
+ def initialize(*args, &b)
+ super
+ @__pseudo_toplevel__ = Thread.current[:TOPLEVEL]
+ end
+
+ alias __call__ call
+ def call(*args, &b)
+ if top = @__pseudo_toplevel__
+ orig_top = Thread.current[:TOPLEVEL]
+ Thread.current[:TOPLEVEL] = top
+ begin
+ __call__(*args, &b)
+ ensure
+ Thread.current[:TOPLEVEL] = orig_top
+ end
+ else
+ __call__(*args, &b)
+ end
+ end
+end
+
+def proc(&b)
+ Proc.new(&b)
+end
+def lambda(&b)
+ Proc.new(&b)
+end
+
+def _null_binding
+ Module.new.instance_eval{extend PseudoToplevel_Evaluable}
+ # binding
+ # Module.new.instance_eval{binding}
+end
+private :_null_binding
+
+def eval_samplecode(code, file=nil)
+ #eval(code)
+ #_null_binding.pseudo_toplevel_eval{ eval(code) }
+ #Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }
+ Thread.new{
+ _null_binding.pseudo_toplevel_eval{
+ begin
+ if file
+ eval(code, binding, "(eval:#{file})")
+ else
+ eval(code)
+ end
+ rescue Exception=>e
+ #p e
+ TkBgError.show(e.class.inspect + ': ' + e.message + "\n" +
+ "\n---< backtrace of Ruby side >-----\n" +
+ e.backtrace.join("\n") +
+ "\n---< backtrace of Tk side >-------")
+ end
+ }
+ }
+ Tk.update
+end
+
# invoke --
# This procedure is called when the user clicks on a demo description.
# It is responsible for invoking the demonstration.
#
# Arguments:
-# index - The index of the character that the user clicked on.
-
-def invoke (txt, index)
- tag = txt.tag_names(index).find{|t| t.kind_of?(String) && t =~ /^demo-/}
+# txt - Name of text widget
+# index - The index of the character that the user clicked on.
+def invoke(txt, idx)
+ tag = txt.tag_names(idx).find{|t| t.kind_of?(String) && t =~ /^demo-/}
return unless tag
+
cursor = txt.cget('cursor')
txt.cursor('watch')
Tk.update
+ # eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
+ # Tk.update
+ eval_samplecode(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, tag[5..-1] + '.rb')
+ txt.cursor(cursor)
+
+ $tag_visited.add("#{idx} linestart +1 chars", "#{idx} lineend +1 chars")
+end
+=begin
+def invoke (txt, idx)
+ tag = txt.tag_names(idx).find{|t| t.kind_of?(String) && t =~ /^demo-/}
+ return unless tag
+ current_cursor = txt.cget('cursor')
+ txt.cursor('watch')
+ Tk.update
# eval `cat #{tag[5..-1]}.rb`
- eval `cat #{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb`
+# eval `cat #{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb`
+ eval IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join
Tk.update
# txt.cursor('xterm')
- txt.cursor(cursor)
+ txt.cursor(current_cursor)
- $tag_visited.add("#{index} linestart +1 chars", "#{index} lineend +1 chars")
+ $tag_visited.add("#{idx} linestart +1 chars", "#{idx} lineend +1 chars")
end
-
+=end
# showStatus --
#
-# Show the name of the demo program in the status bar. This procedure
-# is called when the user moves the cursor over a demo description.
+# Show the name of the demo program in the status bar. This procedure
+# is called when the user moves the cursor over a demo description.
#
def showStatus (txt, index)
@@ -422,7 +736,7 @@ def showStatus (txt, index)
else
demoname = tag[5..-1]
$statusBarLabel.configure('text',
- "Run the \"#{demoname}\" sample program")
+ "Run the \"#{demoname}\" sample program")
newcursor = 'hand2'
end
txt.configure('cursor'=>newcursor) if cursor != newcursor
@@ -433,76 +747,100 @@ end
# a demonstration and allows it to be edited and reinvoked.
#
# Arguments:
-# w - The name of the demonstration's window, which can be
-# used to derive the name of the file containing its code.
+# demo - The name of the demonstration's window, which can be
+# used to derive the name of the file containing its code.
-def showCode (demo)
+def showCode1(demo)
file = "#{demo}.rb"
$code_window = nil unless defined? $code_window
- if $code_window == nil || TkWinfo.exist?($code_window) == '0'
+ if $code_window == nil || TkWinfo.exist?($code_window) == false
$code_window = TkToplevel.new(nil)
f = TkFrame.new($code_window)
+
TkButton.new(f) {
text "Dismiss"
command proc{
- $code_window.destroy
- $code_window = nil
+ $code_window.destroy
+ $code_window = nil
}
- }.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
+ }.pack('side'=>'right', 'expand'=>'false', 'pady'=>2, 'padx'=>25)
TkButton.new(f) {
text "Rerun Demo"
- command proc{eval($code_text.get('1.0','end'))}
- }.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
-# f.pack('side'=>'bottom', 'expand'=>'yes', 'fill'=>'x')
- f.pack('side'=>'bottom', 'fill'=>'x')
+ # command proc{eval($code_text.get('1.0','end'), _null_binding)}
+ command proc{eval_samplecode($code_text.get('1.0','end'), '<viewer>')}
+ }.pack('side'=>'right', 'expand'=>'false', 'pady'=>2)
+
+ TkLabel.new(f,'text'=>'line:').pack('side'=>'left')
+ linenum =TkLabel.new(f,'text'=>'').pack('side'=>'left')
+ TkLabel.new(f,'text'=>' pos:').pack('side'=>'left')
+ posnum =TkLabel.new(f,'text'=>'').pack('side'=>'left')
+
+ $set_linenum = proc{|w|
+ line, pos = w.index('insert').split('.')
+ linenum.text = line
+ posnum.text = pos
+ }
+
+ f.pack('side'=>'bottom', 'expand'=>'true', 'fill'=>'x')
if $tk_version =~ /^4\.[01]/
s = TkScrollbar.new($code_window, 'orient'=>'vertical')
$code_text = TkText.new($code_window) {
- height 40
- setgrid 'yes'
- yscrollcommand proc{|first,last| s.set first,last}
+ height 40
+ setgrid 'yes'
+ yscrollcommand proc{|first,last| s.set first,last}
}
s.command(proc{|*args| $code_text.yview(*args)})
s.pack('side'=>'right', 'fill'=>'y')
$code_text.pack('side'=>'left', 'expand'=>'yes', 'fill'=>'both')
else
TkFrame.new($code_window) {|f|
- pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
-
- hs = TkScrollbar.new($code_window, 'highlightthickness'=>0,
- 'orient'=>'horizontal')
- vs = TkScrollbar.new($code_window, 'highlightthickness'=>0,
- 'orient'=>'vertical')
- $code_text = TkText.new($code_window) {|t|
- height 40
- wrap 'word'
- xscrollcommand proc{|first,last| hs.set first,last}
- yscrollcommand proc{|first,last| vs.set first,last}
- setgrid 'yes'
- highlightthickness 0
- pady 2
- padx 3
- hs.command(proc{|*args| $code_text.xview(*args)})
- vs.command(proc{|*args| $code_text.yview(*args)})
- }
-
- $code_text.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
- vs.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
-# xs.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
-# 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
+
+ hs = TkScrollbar.new($code_window, 'highlightthickness'=>0,
+ 'orient'=>'horizontal')
+ vs = TkScrollbar.new($code_window, 'highlightthickness'=>0,
+ 'orient'=>'vertical')
+ $code_text = TkText.new($code_window) {|t|
+ height 40
+ wrap 'word'
+ xscrollcommand proc{|first,last| hs.set first,last}
+ yscrollcommand proc{|first,last| vs.set first,last}
+ setgrid 'yes'
+ highlightthickness 0
+ pady 2
+ padx 3
+ hs.command(proc{|*args| $code_text.xview(*args)})
+ vs.command(proc{|*args| $code_text.yview(*args)})
+ }
+
+ $code_text.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ vs.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+# xs.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
+# 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
# JKC 2001-07-26: segfaults under 1.7.1 (2001-06-19) [i686-linux]
- TkGrid.rowconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
- TkGrid.columnconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
+ TkGrid.rowconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
+ TkGrid.columnconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
}
end
+
+ btag = TkBindTag.new
+
+ btag.bind('Key', $set_linenum, '%W')
+ btag.bind('Button', $set_linenum, '%W')
+
+ btags = $code_text.bindtags
+ btags.insert(btags.index($code_text.class) + 1, btag)
+ $code_text.bindtags = btags
+
else
$code_window.deiconify
$code_window.raise
end
+
$code_window.title("Demo code: #{file}")
$code_window.iconname(file)
# fid = open(file, 'r')
@@ -513,19 +851,234 @@ def showCode (demo)
#$code_mark = TkTextMark.new($code_text, '1.0')
#$code_text.set_insert('1.0')
TkTextMarkInsert.new($code_text,'1.0')
+
+ $set_linenum.call($code_text)
+
+ fid.close
+end
+
+def showCode2(demo)
+ file = "#{demo}.rb"
+ $code_window = nil unless defined? $code_window
+ if $code_window == nil || TkWinfo.exist?($code_window) == false
+ $code_window = TkToplevel.new(nil)
+ tf = TkFrame.new($code_window)
+ $code_text = TkText.new(tf, :font=>'Courier 10', :height=>30,
+ :wrap=>'word', :bd=>1, :setgrid=>true,
+ :highlightthickness=>0, :pady=>2, :padx=>3)
+ xscr = TkScrollbar.new(tf, :bd=>1){assign($code_text)}
+ yscr = TkScrollbar.new(tf, :bd=>1){assign($code_text)}
+ TkGrid($code_text, yscr, :sticky=>'news')
+ #TkGrid(xscr)
+ tf.grid_rowconfigure(0, :weight=>1)
+ tf.grid_columnconfigure(0, :weight=>1)
+
+ bf = TkFrame.new($code_window)
+
+ lf = TkFrame.new(bf)
+ TkLabel.new(lf, :text=>'line:').pack(:side=>:left)
+ linenum =TkLabel.new(lf, :text=>'').pack(:side=>:left)
+ TkLabel.new(lf, :text=>' pos:').pack(:side=>:left)
+ posnum =TkLabel.new(lf, :text=>'').pack(:side=>:left)
+
+ $set_linenum = proc{|w|
+ line, pos = w.index('insert').split('.')
+ linenum.text = line
+ posnum.text = pos
+ }
+
+ b_dis = TkButton.new(bf, :text=>'Dismiss', :default=>:active,
+ :command=>proc{
+ $code_window.destroy
+ $code_window = nil
+ },
+ :image=>$image['delete'], :compound=>:left)
+ b_prn = TkButton.new(bf, :text=>'Print Code',
+ :command=>proc{printCode($code_text, file)},
+ :image=>$image['print'], :compound=>:left)
+ b_run = TkButton.new(bf, :text=>'Rerun Demo',
+ :command=>proc{
+ # eval($code_text.get('1.0','end'), _null_binding)
+ eval_samplecode($code_text.get('1.0','end'), '<viewer>')
+ },
+ :image=>$image['refresh'], :compound=>:left)
+
+ TkGrid(lf, 'x', b_run, b_prn, b_dis, :padx=>4, :pady=>[6,4])
+ bf.grid_columnconfigure(1, :weight=>1)
+
+ TkGrid(tf, :sticky=>'news')
+ TkGrid(bf, :sticky=>'ew')
+ $code_window.grid_columnconfigure(0, :weight=>1)
+ $code_window.grid_rowconfigure(0, :weight=>1)
+
+ $code_window.bind('Return', proc{|win|
+ b_dis.invoke unless win.kind_of?(TkText)
+ }, '%W')
+ $code_window.bindinfo('Return').each{|cmd, arg|
+ $code_window.bind_append('Escape', cmd, arg)
+ }
+
+ btag = TkBindTag.new
+
+ btag.bind('Key', $set_linenum, '%W')
+ btag.bind('Button', $set_linenum, '%W')
+ btag.bind('Configure', $set_linenum, '%W')
+
+ btags = $code_text.bindtags
+ btags.insert(btags.index($code_text.class) + 1, btag)
+ $code_text.bindtags = btags
+
+ else
+ $code_window.deiconify
+ $code_window.raise
+ end
+
+ $code_window.title("Demo code: #{file}")
+ $code_window.iconname(file)
+ fid = open([$demo_dir, file].join(File::Separator), 'r')
+ $code_text.delete('1.0', 'end')
+ $code_text.insert('1.0', fid.read)
+ TkTextMarkInsert.new($code_text,'1.0')
+
+ $set_linenum.call($code_text)
+
fid.close
end
+if $tk_major_ver < 8
+ alias showCode showCode1
+elsif $tk_major_ver == 8 && $tk_minor_ver < 4
+ alias showCode showCode1
+else # ver >= 8.4
+ alias showCode showCode2
+end
+
+
+# printCode --
+# Prints the source code currently displayed in the See Code dialog.
+# Much thanks to Arjen Markus for this.
+#
+# Arguments:
+# txt - Name of text widget containing code to print
+# file - Name of the original file (implicitly for title)
+
+def printCode(txt, file)
+ code = txt.get('1.0', 'end - 1c')
+ dir = '.'
+ dir = ENV['HOME'] if ENV['HOME']
+ dir = ENV['TMP'] if ENV['TMP']
+ dir = ENV['TEMP'] if ENV['TEMP']
+
+ fname = [dir, 'tkdemo-' + file].join(File::Separator)
+ open(fname, 'w'){|fid| fid.print(code)}
+ begin
+ case Tk::TCL_PLATFORM('platform')
+ when 'unix'
+ msg = `lp -c #{fname}`
+ unless $?.exitstatus == 0
+ Tk.messageBox(:title=>'Print spooling failure',
+ :message=>'Print spooling probably failed: ' + msg)
+ end
+ when 'windows'
+ begin
+ printTextWin32(fname)
+ rescue => e
+ Tk.messageBox(:title=>'Print spooling failure',
+ :message=>'Print spooling probably failed: ' +
+ e.message)
+ end
+ when 'macintosh'
+ Tk.messageBox(:title=>'Operation not Implemented',
+ :message=>'Oops, sorry: not implemented yet!')
+ else
+ Tk.messageBox(:title=>'Operation not Implemented',
+ :message=>'Wow! Unknown platform: ' +
+ Tk::TCL_PLATFORM('platform'))
+ end
+ ensure
+ File.delete(fname)
+ end
+end
+
+# printTextWin32 --
+# Print a file under Windows
+#
+# Arguments:
+# filename - Name of the file
+#
+def printTextWin32(fname)
+ require 'win32/registry'
+ begin
+ app = Win32::Registry::HKEY_CLASSES_ROOT['.txt']
+ pcmd = nil
+ Win32::Registry::HKEY_CLASSES_ROOT.open("#{app}\\shell\\print"){|reg|
+ pcmd = reg['command']
+ }
+ rescue
+ app = Tk.tk_call('auto_execok', 'notepad.exe')
+ pcmd = "#{app} /p %1"
+ end
+
+ pcmd.gsub!('%1', fname)
+ puts pcmd
+ cmd = Tk.tk_call('auto_execok', 'start') + ' /min ' + pcmd
+
+ msg = `#{cmd}`
+ unless $?.exitstatus == 0
+ fail RuntimeError, msg
+ end
+end
+
# aboutBox
#
# Pops up a message box with an "about" message
#
def aboutBox
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo',
- 'message'=>"Ruby/Tk widget demonstration Ver.1.3.2-en\n\n( based on Tk 8.1 Copyright (c) 1996-1997 Sun Microsystems, Inc. )\n\nRunning Version :: Ruby#{VERSION}/Tk#{$tk_version}")
+ 'message'=>"Ruby/Tk widget demonstration Ver.1.7.0-en\n\n" +
+ "based on demos of Tk8.1 -- 8.5 " +
+ "( Copyright of Tcl/Tk demos:: " +
+ "(c) 1996-1997 Sun Microsystems, Inc. / " +
+ "(c) 1997-2000 Ajuba Solutions, Inc. / " +
+ "(c) 2001-2007 Donal K. Fellows / " +
+ "(c) 2002-2007 Daniel A. Steffen )\n\n" +
+ "Your Ruby & Tk Version ::\n" +
+ "Ruby#{RUBY_VERSION}(#{RUBY_RELEASE_DATE})[#{RUBY_PLATFORM}] / Tk#{$tk_patchlevel}#{(Tk::JAPANIZED_TK)? '-jp': ''}\n\n" +
+ "Ruby/Tk release date :: tcltklib #{TclTkLib::RELEASE_DATE}; tk #{Tk::RELEASE_DATE}")
end
-################################
+#########################################
+# start demos if given at command line
+no_launcher = false
+if ARGV[0] == '-n'
+ ARGV.shift
+ no_launcher = true if ARGV.size > 0
+else
+ # show the root widget to make it lower then demo windows
+ Tk.update
+end
+ARGV.each{|cmd|
+ if cmd =~ /(.*).rb/
+ cmd = $1
+ end
+ #eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join,
+ # _null_binding)
+ eval_samplecode(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join, cmd + '.rb')
+}
+if no_launcher
+ $root.withdraw # hide root window
+ Thread.start{
+ loop do
+ count = 0
+ $root.winfo_children.each{|w|
+ count += 1 if w.kind_of?(TkToplevel)
+ }
+ $root.destroy if count == 0
+ end
+ }
+end
+#########################################
+# start eventloop
Tk.mainloop
diff --git a/ext/tk/sample/demos-jp/README.1st b/ext/tk/sample/demos-jp/README.1st
new file mode 100644
index 0000000000..60b278d7b6
--- /dev/null
+++ b/ext/tk/sample/demos-jp/README.1st
@@ -0,0 +1,20 @@
+¤³¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤Ï Ruby/Tk ¤Î¥Ç¥â¥¹¥¯¥ê¥×¥È¤¬¼ý¤á¤é¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+'.rb' ¤È¤¤¤¦³ÈÄ¥»Ò¤ò»ý¤Ã¤Æ¤¤¤ë¥Õ¥¡¥¤¥ë¤Ï¡¤¥é¥ó¥Á¥ã¨¡¥¹¥¯¥ê¥×¥È¤Ç
+¤¢¤ë 'widget' ¤«¤é¸Æ¤Ó½Ð¤µ¤ì¤ë¥µ¥Ö¥¹¥¯¥ê¥×¥È¤Ç¤¹¡¥¤½¤ì¤¾¤ìÆÈΩ¤Ë
+¤Ïư¤­¤Þ¤»¤ó¡¥'widget' ¥¹¥¯¥ê¥×¥È¤«¤é¸Æ¤Ó½Ð¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+¤â¤·¥é¥ó¥Á¥ã¨¡¥¹¥¯¥ê¥×¥È 'widget' ¤Îµ¯Æ°¤ÈƱ»þ¤Ë¤¤¤¯¤Ä¤«¤Î¥µ¥Ö¥¹
+¥¯¥ê¥×¥È¤òµ¯Æ°¤·¤¿¤±¤ì¤Ð¡¤¤½¤Î¥µ¥Ö¥¹¥¯¥ê¥×¥È¤Î̾Á°¤ò°ú¿ô¤È¤·¤ÆÍ¿
+¤¨¤Æ¤¯¤À¤µ¤¤¡¥
+( Îã: /usr/local/bin/ruby widget button.rb entry1.rb text.rb )
+¥µ¥Ö¥¹¥¯¥ê¥×¥È¤Î³ÈÄ¥»Ò '.rb' ¤Ï¾Êά¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡¥
+( Îã: /usr/local/bin/ruby widget button entry1 text )
+
+¤â¤·¥é¥ó¥Á¥ã¨¡¥¹¥¯¥ê¥×¥È¤Î¥¦¥£¥ó¥É¥¦¤¬É¬Íפʤ¤¾ì¹ç¤Ë¤Ï¡¤'-n' ¥ª
+¥×¥·¥ç¥ó¤òÍ¿¤¨¤Æ¤¯¤À¤µ¤¤¡¥
+( Îã: /usr/local/bin/ruby widget -n button.rb entry1.rb text.rb )
+
+¾¤Î¥Õ¥¡¥¤¥ë (browse1 ¤ä hello ¤Ê¤É) ¤ÏñÆÈ¤Çư¤«¤¹¤³¤È¤¬²Äǽ¤Ç¤¹¡¥
+
+ 2004/04/14 Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
diff --git a/ext/tk/sample/demos-jp/anilabel.rb b/ext/tk/sample/demos-jp/anilabel.rb
new file mode 100644
index 0000000000..aee57f9f6a
--- /dev/null
+++ b/ext/tk/sample/demos-jp/anilabel.rb
@@ -0,0 +1,177 @@
+# -*- coding: euc-jp -*-
+#
+# animated label widget demo (called by 'widget')
+#
+# based on Tcl/Tk8.5a2 widget demos
+
+# toplevel widget ¤¬Â¸ºß¤¹¤ì¤Ðºï½ü¤¹¤ë
+if defined?($anilabel_demo) && $anilabel_demo
+ $anilabel_demo.destroy
+ $anilabel_demo = nil
+end
+
+# demo ÍѤΠtoplevel widget ¤òÀ¸À®
+$anilabel_demo = TkToplevel.new {|w|
+ title("Animated Label Demonstration")
+ iconname("anilabel")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($anilabel_demo).pack(:fill=>:both, :expand=>true)
+
+# label À¸À®
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '4i'
+ justify 'left'
+ text "²¼¤Ë¤Ï4¤Ä¤Î¥¢¥Ë¥á¡¼¥·¥ç¥ó¥é¥Ù¥ë¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£º¸Â¦¤Ë¤¢¤ë¥é¥Ù¥ë¤Ï¡¢ÆâÉô¤Î¥Æ¥­¥¹¥È¥á¥Ã¥»¡¼¥¸¤ò¥¹¥¯¥í¡¼¥ë¤·¤¿¤è¤¦¤Ë¸«¤»¤ë¤³¤È¤Çư¤­¤òÉÕ¤±¤Æ¤¤¤Þ¤¹¡£±¦Â¦¤Î¥é¥Ù¥ë¤Ï¡¢É½¼¨¤¹¤ë¥¤¥á¡¼¥¸¤òÊѲ½¤µ¤»¤ë¤³¤È¤Çư¤­¤òÍ¿¤¨¤Æ¤¤¤Þ¤¹¡£"
+}
+msg.pack('side'=>'top')
+
+# frame À¸À®
+TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
+ command proc{
+ tmppath = $anilabel_demo
+ $anilabel_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text '¥³¡¼¥É»²¾È'
+ command proc{showCode 'anilabel'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# label demo Íѥե졼¥àÀ¸À®
+f_left = TkLabelFrame.new(base_frame, :text=>'Scrolling Texts')
+f_right = TkLabelFrame.new(base_frame, :text=>'GIF Image')
+Tk.pack(f_left, f_right, 'side'=>'left', 'expand'=>'yes', 'fill'=>'both',
+ 'padx'=>10, 'pady'=>10)
+
+# animated label
+class AnimatedTextLabel < TkLabel
+ def initialize(*args)
+ super(*args)
+ @timer = TkTimer.new{ _animation_callback }
+ @timer.loop_exec = -1
+ # bind('Destroy'){ @timer.stop }
+ @btag = TkBindTag.new('Destroy'){ @timer.stop }
+ self.bindtags_unshift(@btag)
+ end
+
+ def _animation_callback()
+ txt = self.text
+ self.text = (txt[1..-1] << txt[0])
+ end
+ private :_animation_callback
+
+ def start(interval)
+ @timer.set_interval(interval)
+ @timer.start
+ end
+
+ def stop
+ @timer.stop
+ end
+end
+
+# animated image
+class AnimatedImageLabel < AnimatedTextLabel
+ def initialize(*args)
+ super(*args)
+ @destroy_image = false
+ @btag.bind_append('Destroy'){
+ if @destroy_image
+ begin
+ self.image.delete
+ rescue
+ end
+ end
+ }
+ end
+ attr_accessor :destroy_image
+
+ def _animation_callback()
+ img = self.image
+
+ fmt = img.format
+ if fmt.kind_of?(Array)
+ if fmt[1].kind_of?(Hash)
+ # fmt == ['GIF', {'index'=>idx}]
+ idx = fmt[1]['index']
+ else
+ # fmt == ['GIF', '-index', idx] :: Ruby1.8.2 returns this.
+ idx = fmt[2]
+ end
+ elsif fmt.kind_of?(String) && fmt =~ /GIF -index (\d+)/
+ idx = $1.to_i
+ else
+ idx = -1
+ end
+
+ begin
+ img.format("GIF -index #{idx + 1}")
+ rescue => e
+ img.format("GIF -index 0")
+ end
+ end
+ private :_animation_callback
+end
+
+# label À¸À®
+l1 = AnimatedTextLabel.new(f_left, :borderwidth=>4, :relief=>:ridge,
+ :font=>{:family=>'Courier', :size=>10})
+l2 = AnimatedTextLabel.new(f_left, :borderwidth=>4, :relief=>:groove,
+ :font=>{:family=>'Courier', :size=>10})
+l3 = AnimatedTextLabel.new(f_left, :borderwidth=>4, :relief=>:flat,
+ :font=>{:family=>'Courier', :size=>10}, :width=>18)
+Tk.pack(l1, l2, l3,
+ :side=>:top, :expand=>true, :anchor=>:w, :padx=>10, :pady=>10)
+
+limg = AnimatedImageLabel.new(f_right, :borderwidth=>0)
+limg.pack(:side=>:top, :expand=>true, :padx=>10, :pady=>10)
+
+# base64-encoded animated GIF file
+tclPowerdData = <<EOD
+ R0lGODlhKgBAAPQAAP//////zP//AP/MzP/Mmf/MAP+Zmf+ZZv+ZAMz//8zM
+ zMyZmcyZZsxmZsxmAMwzAJnMzJmZzJmZmZlmmZlmZplmM5kzM2aZzGZmzGZm
+ mWZmZmYzZmYzMzNmzDMzZgAzmSH+IE1hZGUgd2l0aCBHSU1QIGJ5IExARGVt
+ YWlsbHkuY29tACH5BAVkAAEALAAAAAAqAEAAAAX+YCCOZEkyTKM2jOm66yPP
+ dF03bx7YcuHIDkGBR7SZeIyhTID4FZ+4Es8nQyCe2EeUNJ0peY2s9mi7PhAM
+ ngEAMGRbUpvzSxskLh1J+Hkg134OdDIDEB+GHxtYMEQMTjMGEYeGFoomezaC
+ DZGSHFmLXTQKkh8eNQVpZ2afmDQGHaOYSoEyhhcklzVmMpuHnaZmDqiGJbg0
+ qFqvh6UNAwB7VA+OwydEjgujkgrPNhbTI8dFvNgEYcHcHx0lB1kX2IYeA2G6
+ NN0YfkXJ2BsAMuAzHB9cZMk3qoEbRzUACsRCUBK5JxsC3iMiKd8GN088SIyT
+ 0RAFSROyeEg38caDiB/+JEgqxsODrZJ1BkT0oHKSmI0ceQxo94HDpg0qsuDk
+ UmRAMgu8OgwQ+uIJgUMVeGXA+IQkzEeHGvD8cIGlDXsLiRjQ+EHroQhea7xY
+ 8IQBSgYYDi1IS+OFBCgaDMGVS3fGi5BPJpBaENdQ0EomKGD56IHwO39EXiSC
+ Ysgxor5+Xfgq0qByYUpiXmwuoredB2aYH4gWWda0B7SeNENpEJHC1ghi+pS4
+ AJpIAwWvKPBi+8YEht5EriEqpFfMlhEdkBNpx0HUhwypx5T4IB1MBg/Ws2sn
+ wV3MSQOkzI8fUd48Aw3dOZto71x85hHtHijYv18Gf/3GqCdDCXHNoICBobSo
+ IqBqJLyCoH8JPrLgdh88CKCFD0CGmAiGYPgffwceZh6FC2ohIIklnkhehTNY
+ 4CIHHGzgwYw01ujBBhvAqKOLLq5AAk9kuSPkkKO40NB+h1gnypJIIvkBf09a
+ N5QIRz5p5ZJXJpmlIVhOGQA2TmIJZZhKKmmll2BqyWSXWUrZpQtpatlmk1c2
+ KaWRHeTZEJF8SqLDn/hhsOeQgBbqAh6DGqronxeARUIIACH5BAUeAAAALAUA
+ LgAFAAUAAAUM4CeKz/OV5YmqaRkCACH5BAUeAAEALAUALgAKAAUAAAUUICCK
+ z/OdJVCaa7p+7aOWcDvTZwgAIfkEBR4AAQAsCwAuAAkABQAABRPgA4zP95zA
+ eZqoWqqpyqLkZ38hACH5BAUKAAEALAcALgANAA4AAAU7ICA+jwiUJEqeKau+
+ r+vGaTmac63v/GP9HM7GQyx+jsgkkoRUHJ3Qx0cK/VQVTKtWwbVKn9suNunc
+ WkMAIfkEBQoAAAAsBwA3AAcABQAABRGgIHzk842j+Yjlt5KuO8JmCAAh+QQF
+ CgAAACwLADcABwAFAAAFEeAnfN9TjqP5oOWziq05lmUIACH5BAUKAAAALA8A
+ NwAHAAUAAAUPoPCJTymS3yiQj4qOcPmEACH5BAUKAAAALBMANwAHAAUAAAUR
+ oCB+z/MJX2o+I2miKimiawgAIfkEBQoAAAAsFwA3AAcABQAABRGgIHzfY47j
+ Q4qk+aHl+pZmCAAh+QQFCgAAACwbADcABwAFAAAFEaAgfs/zCV9qPiNJouo7
+ ll8IACH5BAUKAAAALB8ANwADAAUAAAUIoCB8o0iWZggAOw==
+EOD
+
+l1.text('* Slow Animation *').start(300)
+l2.text('* Fast Animation *').start(80)
+l3.text('This is a longer scrolling text in a widget that will not show the whole message at once. ').start(150)
+
+limg.destroy_image = true
+limg.image(TkPhotoImage.new(:format=>'GIF', :data=>tclPowerdData)).start(100)
diff --git a/ext/tk/sample/demos-jp/aniwave.rb b/ext/tk/sample/demos-jp/aniwave.rb
new file mode 100644
index 0000000000..8fa14f65fe
--- /dev/null
+++ b/ext/tk/sample/demos-jp/aniwave.rb
@@ -0,0 +1,120 @@
+# -*- coding: euc-jp -*-
+#
+# animated wave demo (called by 'widget')
+#
+# based on Tcl/Tk8.5a2 widget demos
+
+# destroy toplevel widget for this demo script
+if defined?($aniwave_demo) && $aniwave_demo
+ $aniwave_demo.destroy
+ $aniwave_demo = nil
+end
+
+# create toplevel widget
+$aniwave_demo = TkToplevel.new {|w|
+ title("Animated Wave Demonstration")
+ iconname("aniwave")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($aniwave_demo).pack(:fill=>:both, :expand=>true)
+
+# create label
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '4i'
+ justify 'left'
+ text '¤³¤Î¥Ç¥â¤Ç¤Ï¡¢¥é¥¤¥ó¥¢¥¤¥Æ¥à¤¬°ì¤Ä¤À¤±ÉÁ¤«¤ì¤¿¥­¥ã¥ó¥Ð¥¹¥¦¥£¥¸¥§¥Ã¥È¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥¢¥Ë¥á¡¼¥·¥ç¥ó½èÍý¤Ï¡¢¤½¤Î¥é¥¤¥ó¥¢¥¤¥Æ¥à¤ÎºÂɸÃͤòÊѹ¹¤¹¤ë¤³¤È¤Ç¼Â¸½¤·¤Æ¤¤¤Þ¤¹¡£'
+}
+msg.pack('side'=>'top')
+
+# create frame
+TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
+ command proc{
+ tmppath = $aniwave_demo
+ $aniwave_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text '¥³¡¼¥É»²¾È'
+ command proc{showCode 'aniwave'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# animated wave
+class AnimatedWaveDemo
+ def initialize(frame, dir=:left)
+ @direction = dir
+
+ # create canvas widget
+ @c = TkCanvas.new(frame, :width=>300, :height=>200,
+ :background=>'black')
+ @c.pack(:padx=>10, :pady=>10, :expand=>true)
+
+ # Creates a coordinates list of a wave.
+ @waveCoords = []
+ @backupCoords = []
+ n = 0
+ (-10..300).step(5){|n| @waveCoords << [n, 100]; @backupCoords << [n, 100] }
+ n = 305
+ @waveCoords << [n, 0]; @backupCoords << [n, 0]
+ @waveCoords << [n+5, 200]; @backupCoords << [n+5, 200]
+ @coordsLen = @waveCoords.length
+
+ # Create a smoothed line and arrange for its coordinates to be the
+ # contents of the variable waveCoords.
+ @line = TkcLine.new(@c, @waveCoords,
+ :width=>1, :fill=>'green', :smooth=>true)
+
+ # Main animation "loop".
+ # Theoretically 100 frames-per-second (==10ms between frames)
+ @timer = TkTimer.new(10){ basicMotion; reverser }
+
+ # Arrange for the animation loop to stop when the canvas is deleted
+ @c.bindtags_unshift(TkBindTag.new('Destroy'){ @timer.stop })
+ end
+
+ # Basic motion handler. Given what direction the wave is travelling
+ # in, it advances the y coordinates in the coordinate-list one step in
+ # that direction.
+ def basicMotion
+ @backupCoords, @waveCoords = @waveCoords, @backupCoords
+ (0...@coordsLen).each{|idx|
+ if @direction == :left
+ @waveCoords[idx][1] = @backupCoords[(idx+1 == @coordsLen)? 0: idx+1][1]
+ else
+ @waveCoords[idx][1] = @backupCoords[(idx == 0)? -1: idx-1][1]
+ end
+ }
+ @line.coords(@waveCoords)
+ end
+
+ # Oscillation handler. This detects whether to reverse the direction
+ # of the wave by checking to see if the peak of the wave has moved off
+ # the screen (whose size we know already.)
+ def reverser
+ if @waveCoords[0][1] < 10
+ @direction = :right
+ elsif @waveCoords[-1][1] < 10
+ @direction = :left
+ end
+ end
+
+ # animation control
+ def move
+ @timer.start
+ end
+
+ def stop
+ @timer.stop
+ end
+end
+
+# Start the animation processing
+AnimatedWaveDemo.new(base_frame, :left).move
diff --git a/ext/tk/sample/demos-jp/arrow.rb b/ext/tk/sample/demos-jp/arrow.rb
index 3640798db1..3c49e67b09 100644
--- a/ext/tk/sample/demos-jp/arrow.rb
+++ b/ext/tk/sample/demos-jp/arrow.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# arrowhead widget demo (called by 'widget')
#
@@ -9,7 +10,7 @@
# interactively.
#
# Arguments:
-# c - Name of the canvas widget.
+# c - Name of the canvas widget.
def arrowSetup(c)
v = $demo_arrowInfo
@@ -25,59 +26,67 @@ def arrowSetup(c)
# Create the arrow and outline.
c.delete('all')
TkcLine.new(c, v.x1, v.y, v.x2, v.y,
- { 'width'=>10 * v.width,
- 'arrowshape'=>[10*v.a, 10*v.b, 10*v.c],
- 'arrow'=>'last'
- }.update(v.bigLineStyle) )
+ { 'width'=>10 * v.width,
+ 'arrowshape'=>[10*v.a, 10*v.b, 10*v.c],
+ 'arrow'=>'last'
+ }.update(v.bigLineStyle) )
xtip = v.x2 - 10*v.b
deltaY = 10*v.c + 5*v.width
TkcLine.new(c, v.x2, v.y, xtip, v.y + deltaY,
- v.x2 - 10*v.a, v.y, xtip, v.y - deltaY, v.x2, v.y,
- 'width'=>2, 'capstyle'=>'round', 'joinstyle'=>'round')
+ v.x2 - 10*v.a, v.y, xtip, v.y - deltaY, v.x2, v.y,
+ 'width'=>2, 'capstyle'=>'round', 'joinstyle'=>'round')
# Create the boxes for reshaping the line and arrowhead.
TkcRectangle.new(c, v.x2-10*v.a-5, v.y-5, v.x2-10*v.a+5, v.y+5,
- {'tags'=>['box1', $arrowTag_box]}.update(v.boxStyle) )
+ {'tags'=>['box1', $arrowTag_box]}.update(v.boxStyle) )
TkcRectangle.new(c, xtip-5, v.y-deltaY-5, xtip+5, v.y-deltaY+5,
- {'tags'=>['box2', $arrowTag_box]}.update(v.boxStyle) )
+ {'tags'=>['box2', $arrowTag_box]}.update(v.boxStyle) )
TkcRectangle.new(c, v.x1-5, v.y-5*v.width-5, v.x1+5, v.y-5*v.width+5,
- {'tags'=>['box3', $arrowTag_box]}.update(v.boxStyle) )
+ {'tags'=>['box3', $arrowTag_box]}.update(v.boxStyle) )
c.itemconfigure cur, v.activeStyle if cur
# Create three arrows in actual size with the same parameters
TkcLine.new(c, v.x2+50, 0, v.x2+50, 1000, 'width'=>2)
tmp = v.x2+100
TkcLine.new(c, tmp, v.y-125, tmp, v.y-75, 'width'=>v.width,
- 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
+ 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
TkcLine.new(c, tmp-25, v.y, tmp+25, v.y, 'width'=>v.width,
- 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
+ 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
TkcLine.new(c, tmp-25, v.y+75, tmp+25, v.y+125, 'width'=>v.width,
- 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
+ 'arrow'=>'both', 'arrowshape'=>[v.a, v.b, v.c])
# Create a bunch of other arrows and text items showing the
# current dimensions.
tmp = v.x2+10
TkcLine.new(c, tmp, v.y-5*v.width, tmp, v.y-deltaY,
- 'arrow'=>'both', 'arrowshape'=>v.smallTips)
+ 'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x2+15, v.y-deltaY+5*v.c, 'text'=>v.c, 'anchor'=>'w')
tmp = v.x1-10
TkcLine.new(c, tmp, v.y-5*v.width, tmp, v.y+5*v.width,
- 'arrow'=>'both', 'arrowshape'=>v.smallTips)
+ 'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x1-15, v.y, 'text'=>v.width, 'anchor'=>'e')
tmp = v.y+5*v.width+10*v.c+10
TkcLine.new(c, v.x2-10*v.a, tmp, v.x2, tmp,
- 'arrow'=>'both', 'arrowshape'=>v.smallTips)
+ 'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x2-5*v.a, tmp+5, 'text'=>v.a, 'anchor'=>'n')
tmp = tmp+25
TkcLine.new(c, v.x2-10*v.b, tmp, v.x2, tmp,
- 'arrow'=>'both', 'arrowshape'=>v.smallTips)
+ 'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x2-5*v.b, tmp+5, 'text'=>v.b, 'anchor'=>'n')
- TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
- TkcText.new(c, v.x1, 330,
- 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]", 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ if $tk_version =~ /^4.*/
+ TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
+ 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ TkcText.new(c, v.x1, 330,
+ 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]",'anchor'=>'w',
+ 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ else
+ TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
+ 'font'=>'Helvetica 18')
+ TkcText.new(c, v.x1, 330,
+ 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]",
+ 'anchor'=>'w', 'font'=>'Helvetica 18')
+ end
v.count += 1
end
@@ -95,16 +104,19 @@ $arrow_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($arrow_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($arrow_demo, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
- 'text'=>"¤³¤Î widget ¤Ç¡¢¥­¥ã¥ó¥Ð¥¹¤Ç»È¤ï¤ì¤ë¥é¥¤¥ó¤Ë¤Ä¤¤¤ÆÍÍ¡¹¤ÊÉý¤äÌð°õ¤ÎƬ¤Î·Á¤ò»î¤·¤Æ¤ß¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£Àþ¤ÎÉý¤äÌð°õ¤Î·Á¤òÊѤ¨¤ë¤Ë¤Ï¡¢³ÈÂ礵¤ì¤¿Ìð°õ¤Ë¤Ä¤¤¤Æ¤¤¤ë 3¤Ä¤Î»Í³Ñ¤ò¥É¥é¥Ã¥°¤·¤Æ¤¯¤À¤µ¤¤¡£±¦Â¦¤ÎÌð°õ¤ÏÉáÄ̤ÎÂ礭¤µ¤Ç¤Î¥µ¥ó¥×¥ë¤ò¼¨¤·¤Æ¤¤¤Þ¤¹¡£²¼¤Î¥Æ¥­¥¹¥È¤Ï¥é¥¤¥ó¥¢¥¤¥Æ¥à¤ËÂФ¹¤ëÀßÄꥪ¥×¥·¥ç¥ó¤Ç¤¹¡£"){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
+ 'text'=>"¤³¤Î widget ¤Ç¡¢¥­¥ã¥ó¥Ð¥¹¤Ç»È¤ï¤ì¤ë¥é¥¤¥ó¤Ë¤Ä¤¤¤ÆÍÍ¡¹¤ÊÉý¤äÌð°õ¤ÎƬ¤Î·Á¤ò»î¤·¤Æ¤ß¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£Àþ¤ÎÉý¤äÌð°õ¤Î·Á¤òÊѤ¨¤ë¤Ë¤Ï¡¢³ÈÂ礵¤ì¤¿Ìð°õ¤Ë¤Ä¤¤¤Æ¤¤¤ë 3¤Ä¤Î»Í³Ñ¤ò¥É¥é¥Ã¥°¤·¤Æ¤¯¤À¤µ¤¤¡£±¦Â¦¤ÎÌð°õ¤ÏÉáÄ̤ÎÂ礭¤µ¤Ç¤Î¥µ¥ó¥×¥ë¤ò¼¨¤·¤Æ¤¤¤Þ¤¹¡£²¼¤Î¥Æ¥­¥¹¥È¤Ï¥é¥¤¥ó¥¢¥¤¥Æ¥à¤ËÂФ¹¤ëÀßÄꥪ¥×¥·¥ç¥ó¤Ç¤¹¡£"){
pack('side'=>'top')
}
# frame À¸À®
-$arrow_buttons = TkFrame.new($arrow_demo) {|frame|
+$arrow_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $arrow_demo
$arrow_demo = nil
@@ -120,15 +132,15 @@ $arrow_buttons = TkFrame.new($arrow_demo) {|frame|
$arrow_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# canvas ÀßÄê
-$arrow_canvas = TkCanvas.new($arrow_demo, 'width'=>500, 'height'=>350,
- 'relief'=>'sunken', 'borderwidth'=>2)
+$arrow_canvas = TkCanvas.new(base_frame, 'width'=>500, 'height'=>350,
+ 'relief'=>'sunken', 'borderwidth'=>2)
$arrow_canvas.pack('expand'=>'yes', 'fill'=>'both')
# ÃÍÀßÄê
unless Struct.const_defined?("ArrowInfo")
$demo_arrowInfo = Struct.new("ArrowInfo", :a, :b, :c, :width, :motionProc,
- :x1, :x2, :y, :smallTips, :count,
- :bigLineStyle, :boxStyle, :activeStyle).new
+ :x1, :x2, :y, :smallTips, :count,
+ :bigLineStyle, :boxStyle, :activeStyle).new
end
$demo_arrowInfo.a = 8
$demo_arrowInfo.b = 10
@@ -146,7 +158,7 @@ if TkWinfo.depth($arrow_canvas) > 1
$demo_arrowInfo.activeStyle = {'fill'=>'red', 'outline'=>'black', 'width'=>1}
else
$demo_arrowInfo.bigLineStyle = {'fill'=>'black',
- 'stipple'=>'@'+[$demo_dir, 'images', 'grey.25'].join(File::Separator)}
+ 'stipple'=>'@'+[$demo_dir,'..','images','grey.25'].join(File::Separator)}
$demo_arrowInfo.boxStyle = {'fill'=>'', 'outline'=>'black', 'width'=>1}
$demo_arrowInfo.activeStyle = {'fill'=>'black','outline'=>'black','width'=>1}
end
@@ -157,16 +169,16 @@ $arrowTag_box.bind('Leave', proc{$arrow_canvas.itemconfigure('current', $demo_ar
$arrowTag_box.bind('B1-Enter', proc{})
$arrowTag_box.bind('B1-Leave', proc{})
$arrow_canvas.itembind('box1', '1',
- proc{$demo_arrowInfo.motionProc \
- = proc{|x,y| arrowMove1 $arrow_canvas, x, y}})
+ proc{$demo_arrowInfo.motionProc \
+ = proc{|x,y| arrowMove1 $arrow_canvas, x, y}})
$arrow_canvas.itembind('box2', '1',
- proc{$demo_arrowInfo.motionProc \
- = proc{|x,y| arrowMove2 $arrow_canvas, x, y}})
+ proc{$demo_arrowInfo.motionProc \
+ = proc{|x,y| arrowMove2 $arrow_canvas, x, y}})
$arrow_canvas.itembind('box3', '1',
- proc{$demo_arrowInfo.motionProc \
- = proc{|x,y| arrowMove3 $arrow_canvas, x, y}})
+ proc{$demo_arrowInfo.motionProc \
+ = proc{|x,y| arrowMove3 $arrow_canvas, x, y}})
$arrowTag_box.bind('B1-Motion',
- proc{|x,y| $demo_arrowInfo.motionProc.call(x,y)}, "%x %y")
+ proc{|x,y| $demo_arrowInfo.motionProc.call(x,y)}, "%x %y")
$arrow_canvas.bind('Any-ButtonRelease-1', proc{arrowSetup $arrow_canvas})
# arrowMove1 --
@@ -175,8 +187,8 @@ $arrow_canvas.bind('Any-ButtonRelease-1', proc{arrowSetup $arrow_canvas})
# for the line and arrowhead.
#
# Arguments:
-# c - The name of the canvas window.
-# x, y - The coordinates of the mouse.
+# c - The name of the canvas window.
+# x, y - The coordinates of the mouse.
def arrowMove1(c,x,y)
v = $demo_arrowInfo
@@ -195,8 +207,8 @@ end
# parameters for the line and arrowhead.
#
# Arguments:
-# c - The name of the canvas window.
-# x, y - The coordinates of the mouse.
+# c - The name of the canvas window.
+# x, y - The coordinates of the mouse.
def arrowMove2(c,x,y)
v = $demo_arrowInfo
@@ -219,8 +231,8 @@ end
# controlling parameters for the line and arrowhead.
#
# Arguments:
-# c - The name of the canvas window.
-# x, y - The coordinates of the mouse.
+# c - The name of the canvas window.
+# x, y - The coordinates of the mouse.
def arrowMove3(c,x,y)
v = $demo_arrowInfo
diff --git a/ext/tk/sample/demos-jp/bind.rb b/ext/tk/sample/demos-jp/bind.rb
index 1f221a6293..a1bcfdd2e7 100644
--- a/ext/tk/sample/demos-jp/bind.rb
+++ b/ext/tk/sample/demos-jp/bind.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# text (tag bindings) widget demo (called by 'widget')
#
@@ -15,10 +16,13 @@ $bind_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($bind_demo).pack(:fill=>:both, :expand=>true)
+
# frame À¸À®
-TkFrame.new($bind_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $bind_demo
$bind_demo = nil
@@ -39,14 +43,14 @@ def tag_binding_for_bind_demo(tag, enter_style, leave_style)
end
# text À¸À®
-TkText.new($bind_demo){|t|
+txt = TkText.new(base_frame){|t|
# À¸À®
setgrid 'true'
- width 60
- height 24
+ #width 60
+ #height 24
font $font
wrap 'word'
- TkScrollbar.new($bind_demo) {|s|
+ TkScrollbar.new(base_frame) {|s|
pack('side'=>'right', 'fill'=>'y')
command proc{|*args| t.yview(*args)}
t.yscrollcommand proc{|first,last| s.set first,last}
@@ -72,35 +76,50 @@ TkText.new($bind_demo){|t|
insert('end', '2. ´Êñ¤Ê 2¼¡¸µ¤Î¥×¥í¥Ã¥È¡£¥Ç¡¼¥¿¤òɽ¤¹ÅÀ¤òư¤«¤¹¤³¤È¤¬¤Ç¤­¤ë¡£', (d2 = TkTextTag.new(t)) )
insert('end', "\n\n")
insert('end', '3. ¥Æ¥­¥¹¥È¥¢¥¤¥Æ¥à¤Î¥¢¥ó¥«¡¼¤È¹Ô·¤¨¡£',
- (d3 = TkTextTag.new(t)) )
+ (d3 = TkTextTag.new(t)) )
insert('end', "\n\n")
insert('end', '4. ¥é¥¤¥ó¥¢¥¤¥Æ¥à¤Î¤¿¤á¤ÎÌð°õ¤ÎƬ¤Î·Á¤Î¥¨¥Ç¥£¥¿¡£',
- (d4 = TkTextTag.new(t)) )
+ (d4 = TkTextTag.new(t)) )
insert('end', "\n\n")
insert('end', '5. ¥¿¥Ö¥¹¥È¥Ã¥×¤òÊѹ¹¤¹¤ë¤¿¤á¤Îµ¡Ç½¤Ä¤­¤Î¥ë¡¼¥é¡¼¡£',
- (d5 = TkTextTag.new(t)) )
+ (d5 = TkTextTag.new(t)) )
insert('end', "\n\n")
insert('end',
- '6. ¥­¥ã¥ó¥Ð¥¹¤¬¤É¤¦¤ä¤Ã¤Æ¥¹¥¯¥í¡¼¥ë¤¹¤ë¤Î¤«¤ò¼¨¤¹¥°¥ê¥Ã¥É¡£',
- (d6 = TkTextTag.new(t)) )
+ '6. ¥­¥ã¥ó¥Ð¥¹¤¬¤É¤¦¤ä¤Ã¤Æ¥¹¥¯¥í¡¼¥ë¤¹¤ë¤Î¤«¤ò¼¨¤¹¥°¥ê¥Ã¥É¡£',
+ (d6 = TkTextTag.new(t)) )
# binding
[d1, d2, d3, d4, d5, d6].each{|tag|
tag_binding_for_bind_demo(tag, tagstyle_bold, tagstyle_normal)
}
d1.bind('1',
- proc{eval `cat #{[$demo_dir,'items.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'items.rb'].join(File::Separator)}`, 'items.rb')
+ })
d2.bind('1',
- proc{eval `cat #{[$demo_dir,'plot.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'plot.rb'].join(File::Separator)}`, 'plot.rb')
+ })
d3.bind('1',
- proc{eval `cat #{[$demo_dir,'ctext.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'ctext.rb'].join(File::Separator)}`, 'ctext.rb')
+ })
d4.bind('1',
- proc{eval `cat #{[$demo_dir,'arrow.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'arrow.rb'].join(File::Separator)}`, 'arrow.rb')
+ })
d5.bind('1',
- proc{eval `cat #{[$demo_dir,'ruler.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'ruler.rb'].join(File::Separator)}`, 'ruler.rb')
+ })
d6.bind('1',
- proc{eval `cat #{[$demo_dir,'cscroll.rb'].join(File::Separator)}`})
+ proc{
+ eval_samplecode(`cat #{[$demo_dir,'cscroll.rb'].join(File::Separator)}`, 'cscroll.rb')
+ })
TkTextMarkInsert.new(t, '0.0')
configure('state','disabled')
}
+
+txt.width 60
+txt.height 24
diff --git a/ext/tk/sample/demos-jp/bitmap.rb b/ext/tk/sample/demos-jp/bitmap.rb
index a400862881..b6b0e54bbe 100644
--- a/ext/tk/sample/demos-jp/bitmap.rb
+++ b/ext/tk/sample/demos-jp/bitmap.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# bitmap widget demo (called by 'widget')
#
@@ -6,19 +7,19 @@
# Create a row of bitmap items in a window.
#
# Arguments:
-# w - The parent window that is to contain the row.
-# args - The names of one or more bitmaps, which will be displayed
-# in a new row across the bottom of w along with their
-# names.
+# w - The parent window that is to contain the row.
+# args - The names of one or more bitmaps, which will be displayed
+# in a new row across the bottom of w along with their
+# names.
def bitmapRow(w,*args)
TkFrame.new(w){|row|
pack('side'=>'top', 'fill'=>'both')
for bitmap in args
TkFrame.new(row){|base|
- pack('side'=>'left', 'fill'=>'both', 'pady'=>'.25c', 'padx'=>'.25c')
- TkLabel.new(base, 'text'=>bitmap, 'width'=>9).pack('side'=>'bottom')
- TkLabel.new(base, 'bitmap'=>bitmap).pack('side'=>'bottom')
+ pack('side'=>'left', 'fill'=>'both', 'pady'=>'.25c', 'padx'=>'.25c')
+ TkLabel.new(base, 'text'=>bitmap, 'width'=>9).pack('side'=>'bottom')
+ Tk::Label.new(base, 'bitmap'=>bitmap).pack('side'=>'bottom')
}
end
}
@@ -37,16 +38,19 @@ $bitmap_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($bitmap_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($bitmap_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
- 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¡¢Tk ¤ËÁȤ߹þ¤Þ¤ì¤¿¤¹¤Ù¤Æ¤Î¥Ó¥Ã¥È¥Þ¥Ã¥×¤¬¡¢¤½¤ì¤é¤Î̾Á°¤È¶¦¤Ëɽ¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£Tcl ¤Î¥¹¥¯¥ê¥×¥ÈÃæ¤Ç¤Ï¡¢¤½¤ì¤¾¤ì¤Î̾Á°¤òÍѤ¤¤Æ»²¾È¤·¤Þ¤¹¡£"){
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
+ 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¡¢Tk ¤ËÁȤ߹þ¤Þ¤ì¤¿¤¹¤Ù¤Æ¤Î¥Ó¥Ã¥È¥Þ¥Ã¥×¤¬¡¢¤½¤ì¤é¤Î̾Á°¤È¶¦¤Ëɽ¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£Tcl ¤Î¥¹¥¯¥ê¥×¥ÈÃæ¤Ç¤Ï¡¢¤½¤ì¤¾¤ì¤Î̾Á°¤òÍѤ¤¤Æ»²¾È¤·¤Þ¤¹¡£"){
pack('side'=>'top')
}
# frame À¸À®
-$bitmap_buttons = TkFrame.new($bitmap_demo) {|frame|
+$bitmap_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $bitmap_demo
$bitmap_demo = nil
@@ -62,7 +66,7 @@ $bitmap_buttons = TkFrame.new($bitmap_demo) {|frame|
$bitmap_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame ÀßÄê
-TkFrame.new($bitmap_demo){|f|
+TkFrame.new(base_frame){|f|
bitmapRow(f,'error','gray25','gray50','hourglass')
bitmapRow(f,'info','question','questhead','warning')
pack('side'=>'top', 'expand'=>'yes', 'fill'=>'both')
diff --git a/ext/tk/sample/demos-jp/browse2 b/ext/tk/sample/demos-jp/browse2
index 304a5f547e..edad04dbcb 100644
--- a/ext/tk/sample/demos-jp/browse2
+++ b/ext/tk/sample/demos-jp/browse2
@@ -39,11 +39,11 @@ class Browse
}
# Set up bindings for the browser.
- base.bind('Control-c',
- proc{
- base.destroy
+ base.bind('Destroy', proc{
Browse::BROWSE_WIN_COUNTER.value = \
- Browse::BROWSE_WIN_COUNTER.to_i - 1})
+ Browse::BROWSE_WIN_COUNTER.to_i - 1
+ })
+ base.bind('Control-c', proc{base.destroy})
list.bind('Double-Button-1',
proc{TkSelection.get.each{|f| self.browse dir, f}})
end
diff --git a/ext/tk/sample/demos-jp/button.rb b/ext/tk/sample/demos-jp/button.rb
index 33247261f2..18e42008c9 100644
--- a/ext/tk/sample/demos-jp/button.rb
+++ b/ext/tk/sample/demos-jp/button.rb
@@ -1,6 +1,8 @@
+# -*- coding: euc-jp -*-
#
# button widget demo (called by 'widget')
#
+#
# toplevel widget ¤¬Â¸ºß¤¹¤ì¤Ðºï½ü¤¹¤ë
if defined?($button_demo) && $button_demo
@@ -25,9 +27,10 @@ msg = TkLabel.new($button_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-$button_buttons = TkFrame.new($button_demo) {|frame|
+$button_buttons = Tk::Frame.new($button_demo) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $button_demo
$button_demo = nil
diff --git a/ext/tk/sample/demos-jp/check.rb b/ext/tk/sample/demos-jp/check.rb
index 50c21fac0e..b953e7f623 100644
--- a/ext/tk/sample/demos-jp/check.rb
+++ b/ext/tk/sample/demos-jp/check.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# checkbutton widget demo (called by 'widget')
#
@@ -15,12 +16,14 @@ $check_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($check_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($check_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
- text "²¼¤Ë¤Ï 3 ¤Ä¤Î¥Á¥§¥Ã¥¯¥Ü¥¿¥ó¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥¯¥ê¥Ã¥¯¤¹¤ë¤È¥Ü¥¿¥ó¤ÎÁªÂò¾õÂÖ¤¬ÊѤï¤ê¡¢Tcl ÊÑ¿ô¤Ë¤½¤Î¥Ü¥¿¥ó¤Î¾õÂÖ¤ò¼¨¤¹ÃͤòÀßÄꤷ¤Þ¤¹¡£¸½ºß¤ÎÊÑ¿ô¤ÎÃͤò¸«¤ë¤Ë¤Ï¡ÖÊÑ¿ô»²¾È¡×¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£"
+ text "²¼¤Ë¤Ï 3 ¤Ä¤Î¥Á¥§¥Ã¥¯¥Ü¥¿¥ó¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥¯¥ê¥Ã¥¯¤¹¤ë¤È¥Ü¥¿¥ó¤ÎÁªÂò¾õÂÖ¤¬ÊѤï¤ê¡¢Tcl ÊÑ¿ô ( TkVariable ¥ª¥Ö¥¸¥§¥¯¥È¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤¹ ) ¤Ë¤½¤Î¥Ü¥¿¥ó¤Î¾õÂÖ¤ò¼¨¤¹ÃͤòÀßÄꤷ¤Þ¤¹¡£¸½ºß¤ÎÊÑ¿ô¤ÎÃͤò¸«¤ë¤Ë¤Ï¡ÖÊÑ¿ô»²¾È¡×¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£"
}
msg.pack('side'=>'top')
@@ -30,9 +33,10 @@ brakes = TkVariable.new(0)
sober = TkVariable.new(0)
# frame À¸À®
-TkFrame.new($check_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $check_demo
$check_demo = nil
@@ -50,8 +54,8 @@ TkFrame.new($check_demo) {|frame|
TkButton.new(frame) {
text 'ÊÑ¿ô»²¾È'
command proc{
- showVars($check_demo,
- ['wipers', wipers], ['brakes', brakes], ['sober', sober])
+ showVars(base_frame,
+ ['wipers', wipers], ['brakes', brakes], ['sober', sober])
}
}.pack('side'=>'left', 'expand'=>'yes')
@@ -59,8 +63,8 @@ TkFrame.new($check_demo) {|frame|
# checkbutton À¸À®
-[ TkCheckButton.new($check_demo, 'text'=>'¥ï¥¤¥Ñ¡¼ OK', 'variable'=>wipers),
- TkCheckButton.new($check_demo, 'text'=>'¥Ö¥ì¡¼¥­ OK', 'variable'=>brakes),
- TkCheckButton.new($check_demo, 'text'=>'¥É¥é¥¤¥Ð¡¼ÁÇÌÌ', 'variable'=>sober)
+[ TkCheckButton.new(base_frame, 'text'=>'¥ï¥¤¥Ñ¡¼ OK', 'variable'=>wipers),
+ TkCheckButton.new(base_frame, 'text'=>'¥Ö¥ì¡¼¥­ OK', 'variable'=>brakes),
+ TkCheckButton.new(base_frame, 'text'=>'±¿Å¾¼ê ÁÇÌÌ', 'variable'=>sober)
].each{|w| w.relief('flat'); w.pack('side'=>'top', 'pady'=>2, 'anchor'=>'w')}
diff --git a/ext/tk/sample/demos-jp/check2.rb b/ext/tk/sample/demos-jp/check2.rb
new file mode 100644
index 0000000000..7f7cb9e932
--- /dev/null
+++ b/ext/tk/sample/demos-jp/check2.rb
@@ -0,0 +1,110 @@
+# -*- coding: euc-jp -*-
+#
+# checkbutton widget demo2 (called by 'widget')
+#
+
+# toplevel widget ¤¬Â¸ºß¤¹¤ì¤Ðºï½ü¤¹¤ë
+if defined?($check2_demo) && $check2_demo
+ $check2_demo.destroy
+ $check2_demo = nil
+end
+
+# demo ÍѤΠtoplevel widget ¤òÀ¸À®
+$check2_demo = TkToplevel.new {|w|
+ title("Checkbutton Demonstration 2")
+ iconname("check2")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($check2_demo).pack(:fill=>:both, :expand=>true)
+
+# label À¸À®
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '4i'
+ justify 'left'
+ text "²¼¤Ë¤Ï£´¤Ä¤Î¥Á¥§¥Ã¥¯¥Ü¥¿¥ó¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥¯¥ê¥Ã¥¯¤¹¤ë¤È¥Ü¥¿¥ó¤ÎÁªÂò¾õÂÖ¤¬ÊѤï¤ê¡¢TclÊÑ¿ô¡ÊTkVariable¥ª¥Ö¥¸¥§¥¯¥È¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤¹¡Ë¤Ë¤½¤Î¥Ü¥¿¥ó¤Î¾õÂÖ¤ò¼¨¤¹ÃͤòÀßÄꤷ¤Þ¤¹¡£ºÇ½é¤Î¥Ü¥¿¥ó¤Î¾õÂ֤Ͼ¤Î£³¤Ä¤Î¥Ü¥¿¥ó¤Î¾õÂ֤ˤâ°Í¸¤·¤ÆÊѲ½¤·¤Þ¤¹¡£¤â¤·£³¤Ä¤Î¥Ü¥¿¥ó¤Î°ìÉô¤À¤±¤Ë¥Á¥§¥Ã¥¯¤¬ÉÕ¤±¤é¤ì¤Æ¤¤¤ë¾ì¹ç¡¢ºÇ½é¤Î¥Ü¥¿¥ó¤Ï¥È¥é¥¤¥¹¥Æ¡¼¥È¡Ê£³¾õÂ֡˥⡼¥É¤Ç¤Îɽ¼¨¤ò¹Ô¤¤¤Þ¤¹¡£¸½ºß¤ÎÊÑ¿ô¤ÎÃͤò¸«¤ë¤Ë¤Ï¡ÖÊÑ¿ô»²¾È¡×¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£"
+}
+msg.pack('side'=>'top')
+
+# ÊÑ¿ôÀ¸À®
+safety = TkVariable.new(0)
+wipers = TkVariable.new(0)
+brakes = TkVariable.new(0)
+sober = TkVariable.new(0)
+
+# frame À¸À®
+TkFrame.new(base_frame) {|frame|
+ TkGrid(TkFrame.new(frame, :height=>2, :relief=>:sunken, :bd=>2),
+ :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ TkButton.new(frame, :text=>'ÊÑ¿ô»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{
+ showVars($check2_demo,
+ ['safety', safety], ['wipers', wipers],
+ ['brakes', brakes], ['sober', sober])
+ }),
+ TkButton.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'check2'}),
+ TkButton.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ tmppath = $check2_demo
+ $check2_demo = nil
+ $showVarsWin[tmppath.path] = nil
+ tmppath.destroy
+ }),
+ :padx=>4, :pady=>4)
+ frame.grid_columnconfigure(0, :weight=>1)
+}.pack('side'=>'bottom', 'fill'=>'x')
+
+
+# checkbutton À¸À®
+TkCheckButton.new(base_frame, :text=>'°ÂÁ´À­¸¡ºº', :variable=>safety,
+ :relief=>:flat, :onvalue=>'all', :offvalue=>'none',
+ :tristatevalue=>'partial'){
+ pack('side'=>'top', 'pady'=>2, 'anchor'=>'w')
+}
+
+[ TkCheckButton.new(base_frame, 'text'=>'¥ï¥¤¥Ñ¡¼ OK', 'variable'=>wipers),
+ TkCheckButton.new(base_frame, 'text'=>'¥Ö¥ì¡¼¥­ OK', 'variable'=>brakes),
+ TkCheckButton.new(base_frame, 'text'=>'±¿Å¾¼ê ÁÇÌÌ', 'variable'=>sober)
+].each{|w|
+ w.relief('flat')
+ w.pack('side'=>'top', 'padx'=>15, 'pady'=>2, 'anchor'=>'w')
+}
+
+# tristate check
+in_check = false
+tristate_check = proc{|n1,n2,op|
+ unless in_check
+ in_check = true
+ begin
+ if n1 == safety
+ if safety == 'none'
+ wipers.value = 0
+ brakes.value = 0
+ sober.value = 0
+ elsif safety == 'all'
+ wipers.value = 1
+ brakes.value = 1
+ sober.value = 1
+ end
+ else
+ if wipers == 1 && brakes == 1 && sober == 1
+ safety.value = 'all'
+ elsif wipers == 1 || brakes == 1 || sober == 1
+ safety.value = 'partial'
+ else
+ safety.value = 'none'
+ end
+ end
+ ensure
+ in_check = false
+ end
+ end
+}
+
+[wipers, brakes, sober, safety].each{|v| v.trace('w', tristate_check)}
diff --git a/ext/tk/sample/demos-jp/clrpick.rb b/ext/tk/sample/demos-jp/clrpick.rb
index 55cfd9c7c6..ce6b99ab94 100644
--- a/ext/tk/sample/demos-jp/clrpick.rb
+++ b/ext/tk/sample/demos-jp/clrpick.rb
@@ -1,6 +1,9 @@
+# -*- coding: euc-jp -*-
#
# widget demo prompts the user to select a color (called by 'widget')
#
+# Note: don't support ttk_wrapper. work with standard widgets only.
+#
# toplevel widget ¤¬Â¸ºß¤¹¤ì¤Ðºï½ü¤¹¤ë
if defined?($clrpick_demo) && $clrpick_demo
@@ -16,13 +19,17 @@ $clrpick_demo = TkToplevel.new {|w|
}
# label À¸À®
-TkLabel.new($clrpick_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
- 'text'=>"°Ê²¼¤Î¥Ü¥¿¥ó¤ò²¡¤·¤Æ¡¢¤³¤Î¥¦¥£¥ó¥É¥¦¾å¤Ë¤¢¤ë¥¦¥£¥¸¥§¥Ã¥È¤ÎÁ°·Ê¿§¤ÈÇØ·Ê¿§¤òÁªÂò¤·¤Æ²¼¤µ¤¤¡£").pack('side'=>'top')
+#TkLabel.new($clrpick_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
+Tk::Label.new($clrpick_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
+ 'text'=>"°Ê²¼¤Î¥Ü¥¿¥ó¤ò²¡¤·¤Æ¡¢¤³¤Î¥¦¥£¥ó¥É¥¦¾å¤Ë¤¢¤ë¥¦¥£¥¸¥§¥Ã¥È¤ÎÁ°·Ê¿§¤ÈÇØ·Ê¿§¤òÁªÂò¤·¤Æ²¼¤µ¤¤¡£").pack('side'=>'top')
# frame À¸À®
-TkFrame.new($clrpick_demo) {|frame|
- TkButton.new(frame) {
- text 'λ²ò'
+# TkFrame.new($clrpick_demo) {|frame|
+Tk::Frame.new($clrpick_demo) {|frame|
+ # TkButton.new(frame) {
+ Tk::Button.new(frame) {
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $clrpick_demo
$clrpick_demo = nil
@@ -30,20 +37,23 @@ TkFrame.new($clrpick_demo) {|frame|
}
}.pack('side'=>'left', 'expand'=>'yes')
- TkButton.new(frame) {
+ # TkButton.new(frame) {
+ Tk::Button.new(frame) {
text '¥³¡¼¥É»²¾È'
command proc{showCode 'clrpick'}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# button À¸À®
-TkButton.new($clrpick_demo, 'text'=>'ÇØ·Ê¿§¤òÀßÄê ...') {|b|
+# TkButton.new($clrpick_demo, 'text'=>'ÇØ·Ê¿§¤òÀßÄê ...') {|b|
+Tk::Button.new($clrpick_demo, 'text'=>'ÇØ·Ê¿§¤òÀßÄê ...') {|b|
command(proc{setColor $clrpick_demo, b, 'background',
- ['background', 'highlightbackground']})
+ ['background', 'highlightbackground']})
pack('side'=>'top', 'anchor'=>'c', 'pady'=>'2m')
}
-TkButton.new($clrpick_demo, 'text'=>'Á°·Ê¿§¤òÀßÄê ...') {|b|
+# TkButton.new($clrpick_demo, 'text'=>'Á°·Ê¿§¤òÀßÄê ...') {|b|
+Tk::Button.new($clrpick_demo, 'text'=>'Á°·Ê¿§¤òÀßÄê ...') {|b|
command(proc{setColor $clrpick_demo, b, 'foreground', ['foreground']})
pack('side'=>'top', 'anchor'=>'c', 'pady'=>'2m')
}
@@ -52,7 +62,7 @@ def setColor(w,button,name,options)
w.grab
initialColor = button[name]
color = Tk.chooseColor('title'=>"Choose a #{name} color", 'parent'=>w,
- 'initialcolor'=>initialColor)
+ 'initialcolor'=>initialColor)
if color != ""
setColor_helper(w,options,color)
end
diff --git a/ext/tk/sample/demos-jp/colors.rb b/ext/tk/sample/demos-jp/colors.rb
index f9a5983e75..91817a947b 100644
--- a/ext/tk/sample/demos-jp/colors.rb
+++ b/ext/tk/sample/demos-jp/colors.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# listbox widget demo 'colors' (called by 'widget')
#
@@ -15,8 +16,10 @@ $colors_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($colors_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($colors_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($colors_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($colors_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $colors_demo
$colors_demo = nil
@@ -44,7 +48,7 @@ TkFrame.new($colors_demo) {|frame|
# frame À¸À®
colors_lbox = nil
-TkFrame.new($colors_demo, 'borderwidth'=>10) {|w|
+TkFrame.new(base_frame, 'borderwidth'=>10) {|w|
s = TkScrollbar.new(w)
colors_lbox = TkListbox.new(w) {
setgrid 1
@@ -57,7 +61,15 @@ TkFrame.new($colors_demo, 'borderwidth'=>10) {|w|
colors_lbox.pack('side'=>'left', 'expand'=>1, 'fill'=>'both')
}.pack('side'=>'top', 'expand'=>'yes', 'fill'=>'y')
-colors_lbox.bind('Double-1', proc{TkPalette.setPalette TkSelection.get})
+#colors_lbox.bind('Double-1', proc{TkPalette.setPalette TkSelection.get})
+colors_lbox.bind('Double-1', proc{
+ begin
+ TkPalette.setPalette TkSelection.get
+ rescue => e
+ p e
+ Tk.tk_call_without_enc('destroy', '.___tk_set_palette')
+ end
+ })
ins_data = [
'gray60','gray70','gray80','gray85','gray90','gray95',
diff --git a/ext/tk/sample/demos-jp/combo.rb b/ext/tk/sample/demos-jp/combo.rb
new file mode 100644
index 0000000000..da00d712ba
--- /dev/null
+++ b/ext/tk/sample/demos-jp/combo.rb
@@ -0,0 +1,98 @@
+# -*- coding: euc-jp -*-
+#
+# combo.rb --
+#
+# This demonstration script creates several combobox widgets.
+#
+# based on "Id: combo.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($combo_demo) && $combo_demo
+ $combo_demo.destroy
+ $combo_demo = nil
+end
+
+$combo_demo = TkToplevel.new {|w|
+ title("Combobox Demonstration")
+ iconname("combo")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($combo_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'5i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top, :fill=>:x)
+°Ê²¼¤Ç¤Ï3¼ïÎà¤Î¥³¥ó¥Ü¥Ü¥Ã¥¯¥¹¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥\
+ºÇ½é¤Î¤â¤Î¤Ï¡¤¥¨¥ó¥È¥ê¥¦¥£¥¸¥§¥Ã¥È¤ÈƱ¤¸Íͤˡ¤\
+¥Ý¥¤¥ó¥È¤·¤¿¤ê¡¤¥¯¥ê¥Ã¥¯¤·¤¿¤ê¡¤¥¿¥¤¥×¤·¤¿¤ê¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥\
+¤Þ¤¿¡¤Return¥­¡¼¤òÆþÎϤ¹¤ì¤Ð¸½ºß¤ÎÃͤ¬¥ê¥¹¥È¤ËÄɲ䵤졤\
+¥É¥í¥Ã¥×¥À¥¦¥ó¥ê¥¹¥È¤«¤éÁªÂò¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡¥\
+¢­(²¼¸þ¤­Ìð°õ)¥­¡¼¤ò²¡¤·¤ÆÉ½¼¨¤µ¤ì¤¿¥ê¥¹¥È¤«¤é\
+Ìð°õ¥­¡¼¤Ç¾¤Î¸õÊä¤òÁª¤ó¤ÇReturn¥­¡¼¤ò²¡¤»¤Ð¡¤ÃͤòÁªÂò¤Ç¤­¤Þ¤¹¡¥\
+2ÈÖÌܤΥ³¥ó¥Ü¥Ü¥Ã¥¯¥¹¤ÏÆÃÄê¤ÎÃͤ˸ÇÄꤵ¤ì¤Æ¤ª¤ê¡¤°ìÀÚÊѹ¹¤Ç¤­¤Þ¤»¤ó¡¥\
+3ÈÖÌܤΤâ¤Î¤Ï¥ª¡¼¥¹¥È¥é¥ê¥¢¤ÎÅԻԤΥɥí¥Ã¥×¥À¥¦¥ó¥ê¥¹¥È¤«¤é\
+ÁªÂò¤¹¤ë¤³¤È¤À¤±¤¬²Äǽ¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+EOL
+
+## variables
+firstValue = TkVariable.new
+secondValue = TkVariable.new
+ozCity = TkVariable.new
+
+## See Code / Dismiss buttons
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'ÊÑ¿ô»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{
+ showVars(base_frame,
+ ['firstVariable', firstValue],
+ ['secondVariable', secondValue],
+ ['ozCity', ozCity])
+ }),
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'combo'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $combo_demo.destroy
+ $combo_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+frame = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+
+australianCities = [
+ '¥­¥ã¥ó¥Ù¥é', '¥·¥É¥Ë¡¼', '¥á¥ë¥Ü¥ë¥ó', '¥Ñ¡¼¥¹', '¥¢¥Ç¥ì¡¼¥É',
+ '¥Ö¥ê¥¹¥Ù¡¼¥ó', '¥Û¥Ð¡¼¥È', '¥À¡¼¥¦¥£¥ó', '¥¢¥ê¥¹ ¥¹¥×¥ê¥ó¥°¥¹'
+]
+
+
+secondValue.value = 'Êѹ¹ÉÔ²Ä'
+ozCity.value = '¥·¥É¥Ë¡¼'
+
+Tk.pack(Ttk::Labelframe.new(frame, :text=>'Fully Editable'){|f|
+ Ttk::Combobox.new(f, :textvariable=>firstValue){|b|
+ b.bind('Return', '%W'){|w|
+ w.values <<= w.value unless w.values.include?(w.value)
+ }
+ }.pack(:pady=>5, :padx=>10)
+ },
+
+ Ttk::LabelFrame.new(frame, :text=>'Disabled'){|f|
+ Ttk::Combobox.new(f, :textvariable=>secondValue, :state=>:disabled) .
+ pack(:pady=>5, :padx=>10)
+ },
+
+ Ttk::LabelFrame.new(frame, :text=>'Defined List Only'){|f|
+ Ttk::Combobox.new(f, :textvariable=>ozCity, :state=>:readonly,
+ :values=>australianCities) .
+ pack(:pady=>5, :padx=>10)
+ },
+
+ :side=>:top, :pady=>5, :padx=>10)
diff --git a/ext/tk/sample/demos-jp/cscroll.rb b/ext/tk/sample/demos-jp/cscroll.rb
index 7f5ffa2f02..845952679a 100644
--- a/ext/tk/sample/demos-jp/cscroll.rb
+++ b/ext/tk/sample/demos-jp/cscroll.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# simple scrollable canvas widget demo (called by 'widget')
#
@@ -15,16 +16,19 @@ $cscroll_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($cscroll_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($cscroll_demo, 'font'=>$font, 'wraplength'=>'4i',
- 'justify'=>'left', 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥¹¥¯¥í¡¼¥ë¥Ð¡¼¤ä¥Þ¥¦¥¹¤Î¥Ü¥¿¥ó2 ¤Ç¥¹¥¯¥í¡¼¥ë¤Ç¤­¤ë¥­¥ã¥ó¥Ð¥¹ widget ¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£»Í³Ñ¤Î¾å¤Ç¥Ü¥¿¥ó1 ¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢¤½¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤¬É¸½à½ÐÎϤ˽ÐÎϤµ¤ì¤Þ¤¹¡£"){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'4i',
+ 'justify'=>'left', 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥¹¥¯¥í¡¼¥ë¥Ð¡¼¤ä¥Þ¥¦¥¹¤Î¥Ü¥¿¥ó2 ¤Ç¥¹¥¯¥í¡¼¥ë¤Ç¤­¤ë¥­¥ã¥ó¥Ð¥¹ widget ¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£»Í³Ñ¤Î¾å¤Ç¥Ü¥¿¥ó1 ¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢¤½¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤¬É¸½à½ÐÎϤ˽ÐÎϤµ¤ì¤Þ¤¹¡£"){
pack('side'=>'top')
}
# frame À¸À®
-$cscroll_buttons = TkFrame.new($cscroll_demo) {|frame|
+$cscroll_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $cscroll_demo
$cscroll_demo = nil
@@ -41,7 +45,7 @@ $cscroll_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame ÀßÄê
unless $tk_version =~ /^4\.[01]/
- $cscroll_grid = TkFrame.new($cscroll_demo) {
+ $cscroll_grid = TkFrame.new(base_frame) {
pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
}
TkGrid.rowconfigure($cscroll_grid, 0, 'weight'=>1, 'minsize'=>0)
@@ -49,35 +53,35 @@ unless $tk_version =~ /^4\.[01]/
end
# canvas ÀßÄê
-$cscroll_canvas = TkCanvas.new($cscroll_demo,
- 'relief'=>'sunken', 'borderwidth'=>2,
- 'scrollregion'=>['-11c', '-11c', '50c', '20c']
- ) {|c|
+$cscroll_canvas = TkCanvas.new(base_frame,
+ 'relief'=>'sunken', 'borderwidth'=>2,
+ 'scrollregion'=>['-11c', '-11c', '50c', '20c']
+ ) {|c|
if $tk_version =~ /^4\.[01]/
pack('expand'=>'yes', 'fill'=>'both')
else
grid('in'=>$cscroll_grid, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
end
- TkScrollbar.new($cscroll_demo, 'command'=>proc{|*args| c.yview(*args)}) {|vs|
+ TkScrollbar.new(base_frame, 'command'=>proc{|*args| c.yview(*args)}) {|vs|
c.yscrollcommand(proc{|first,last| vs.set first,last})
if $tk_version =~ /^4\.[01]/
pack('side'=>'right', 'fill'=>'y')
else
grid('in'=>$cscroll_grid, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
end
}
- TkScrollbar.new($cscroll_demo, 'orient'=>'horiz',
- 'command'=>proc{|*args| c.xview(*args)}) {|hs|
+ TkScrollbar.new(base_frame, 'orient'=>'horiz',
+ 'command'=>proc{|*args| c.xview(*args)}) {|hs|
c.xscrollcommand(proc{|first,last| hs.set first,last})
if $tk_version =~ /^4\.[01]/
pack('side'=>'bottom', 'fill'=>'x')
else
grid('in'=>$cscroll_grid, 'padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
end
}
}
@@ -88,9 +92,9 @@ bg = $cscroll_canvas.configinfo('bg')[4]
y = -10
(0..9).each{|j|
TkcRectangle.new($cscroll_canvas, "#{x}c", "#{y}c", "#{x+2}c", "#{y+2}c",
- 'outline'=>'black', 'fill'=>bg, 'tags'=>'rect')
+ 'outline'=>'black', 'fill'=>bg, 'tags'=>'rect')
TkcText.new($cscroll_canvas, "#{x+1}c", "#{y+1}c",
- 'text'=>"#{i},#{j}", 'anchor'=>'center', 'tags'=>'text')
+ 'text'=>"#{i},#{j}", 'anchor'=>'center', 'tags'=>'text')
y += 3
}
}
@@ -101,7 +105,7 @@ $cscroll_canvas.itembind('all', '1', proc{scrollButton $cscroll_canvas})
$cscroll_canvas.itembind('all', 'Any-Enter', proc{scrollEnter $cscroll_canvas})
$cscroll_canvas.bind('2', proc{|x,y| $cscroll_canvas.scan_mark(x,y)}, '%x %y')
$cscroll_canvas.bind('B2-Motion',
- proc{|x,y| $cscroll_canvas.scan_dragto(x,y)}, '%x %y')
+ proc{|x,y| $cscroll_canvas.scan_dragto(x,y)}, '%x %y')
def scrollEnter(c)
id = c.find_withtag('current')[0].id
diff --git a/ext/tk/sample/demos-jp/ctext.rb b/ext/tk/sample/demos-jp/ctext.rb
index 6d9355e2f8..05ca732cfd 100644
--- a/ext/tk/sample/demos-jp/ctext.rb
+++ b/ext/tk/sample/demos-jp/ctext.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# Canvas Text widget demo (called by 'widget')
#
@@ -15,9 +16,11 @@ $ctext_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($ctext_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($ctext_demo, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
- 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥­¥ã¥ó¥Ð¥¹widget¤Î¥Æ¥­¥¹¥Èµ¡Ç½¤ò¥Ç¥â¤¹¤ë¤¿¤á¤Î¥Æ¥­¥¹¥Èʸ»úÎó¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥Þ¥¦¥¹¤ò»Í³Ñ¤ÎÃæ¤Ë»ý¤Ã¤Æ¤¤¤­¡¢¥¯¥ê¥Ã¥¯¤¹¤ë¤È°ÌÃÖ¤®¤áÍѤÎÅÀ¤«¤é¤ÎÁêÂаÌÃÖ¤òÊѤ¨¤¿¤ê¡¢¹Ô·¤¨¤òÊѤ¨¤¿¤ê¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤Þ¤¿°Ê²¼¤Î¤è¤¦¤ÊÊÔ½¸¤Î¤¿¤á¤Î´Êñ¤Ê¥Ð¥¤¥ó¥Ç¥£¥ó¥°¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤¹¡£
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
+ 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥­¥ã¥ó¥Ð¥¹widget¤Î¥Æ¥­¥¹¥Èµ¡Ç½¤ò¥Ç¥â¤¹¤ë¤¿¤á¤Î¥Æ¥­¥¹¥Èʸ»úÎó¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥Þ¥¦¥¹¤ò»Í³Ñ¤ÎÃæ¤Ë»ý¤Ã¤Æ¤¤¤­¡¢¥¯¥ê¥Ã¥¯¤¹¤ë¤È°ÌÃÖ¤®¤áÍѤÎÅÀ¤«¤é¤ÎÁêÂаÌÃÖ¤òÊѤ¨¤¿¤ê¡¢¹Ô·¤¨¤òÊѤ¨¤¿¤ê¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤Þ¤¿°Ê²¼¤Î¤è¤¦¤ÊÊÔ½¸¤Î¤¿¤á¤Î´Êñ¤Ê¥Ð¥¤¥ó¥Ç¥£¥ó¥°¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤¹¡£
1. ¥Þ¥¦¥¹¤ò»ý¤Ã¤Æ¤¤¤­¡¢¥¯¥ê¥Ã¥¯¤·¡¢ÆþÎϤǤ­¤Þ¤¹¡£
2. ¥Ü¥¿¥ó1¤ÇÁªÂò¤Ç¤­¤Þ¤¹¡£
@@ -28,9 +31,10 @@ TkLabel.new($ctext_demo, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
}
# frame À¸À®
-$ctext_buttons = TkFrame.new($ctext_demo) {|frame|
+$ctext_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $ctext_demo
$ctext_demo = nil
@@ -46,46 +50,55 @@ $ctext_buttons = TkFrame.new($ctext_demo) {|frame|
$ctext_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# canvas À¸À®
-$ctext_canvas = TkCanvas.new($ctext_demo, 'relief'=>'flat',
- 'borderwidth'=>0, 'width'=>500, 'height'=>350)
+$ctext_canvas = TkCanvas.new(base_frame, 'relief'=>'flat',
+ 'borderwidth'=>0, 'width'=>500, 'height'=>350)
$ctext_canvas.pack('side'=>'top', 'expand'=>'yes', 'fill'=>'both')
# font ÀßÄê
-textFont = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+if $tk_version =~ /^4.*/
+ textFont = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+else
+ textFont = 'Helvetica 24'
+end
# canvas ÀßÄê
TkcRectangle.new($ctext_canvas, 245, 195, 255, 205,
- 'outline'=>'black', 'fill'=>'red')
+ 'outline'=>'black', 'fill'=>'red')
+ctag_text_param = {
+ 'text'=>"¤³¤ì¤Ï¥­¥ã¥ó¥Ð¥¹widget¤Î¥Æ¥­¥¹¥Èµ¡Ç½¤ò¥Ç¥â¤¹¤ë¤¿¤á¤Îʸ»úÎó¤Ç¤¹¡£\n¾å¤Ç½Ò¤Ù¤¿¤è¤¦¤ÊÊÔ½¸¤ò²Äǽ¤È¤¹¤ë¤¿¤á¤Î¥Ð¥¤¥ó¥Ç¥£¥ó¥°¤ò»Ü¤·¤Æ¤¤¤Þ¤¹¡£",
+ 'width'=>440, 'anchor'=>'n', 'justify'=>'left'
+}
+if $tk_version =~ /^4.*/
+ ctag_text_param['font'] = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+ ctag_text_param['kanjifont'] = '-*-r-*--24-*-jisx0208.1983-0'
+else
+ ctag_text_param['font'] = 'Helvetica 24'
+end
$ctag_text = TkcTag.new($ctext_canvas)
-$ctag_text.withtag(TkcText.new($ctext_canvas, 250, 200,
- 'text'=>"¤³¤ì¤Ï¥­¥ã¥ó¥Ð¥¹widget¤Î¥Æ¥­¥¹¥Èµ¡Ç½¤ò¥Ç¥â¤¹¤ë¤¿¤á¤Îʸ»úÎó¤Ç¤¹¡£¥Þ¥¦¥¹¤ò»ý¤Ã¤Æ¤¤¤­¡¢¥¯¥ê¥Ã¥¯¤·¤ÆÆþÎϤǤ­¤Þ¤¹¡£ÁªÂò¤·¤Æ¥³¥ó¥È¥í¡¼¥ë-D¤Ç¾Ãµî¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡£",
- 'width'=>440, 'anchor'=>'n',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*',
- 'kanjifont'=>'-*-r-*--24-*-jisx0208.1983-0',
- 'justify'=>'left') )
+$ctag_text.withtag(TkcText.new($ctext_canvas, 250, 200, ctag_text_param))
$ctag_text.bind('1', proc{|x,y| textB1Press $ctext_canvas,x,y}, "%x %y")
$ctag_text.bind('B1-Motion', proc{|x,y| textB1Move $ctext_canvas,x,y}, "%x %y")
$ctag_text.bind('Shift-1',
- proc{|x,y| $ctext_canvas.seleect_adjust 'current', "@#{x},#{y}"},
- "%x %y")
+ proc{|x,y| $ctext_canvas.seleect_adjust 'current', "@#{x},#{y}"},
+ "%x %y")
$ctag_text.bind('Shift-B1-Motion',
- proc{|x,y| textB1Move $ctext_canvas,x,y}, "%x %y")
+ proc{|x,y| textB1Move $ctext_canvas,x,y}, "%x %y")
$ctag_text.bind('KeyPress', proc{|a| textInsert $ctext_canvas,a}, "%A")
$ctag_text.bind('Return', proc{textInsert $ctext_canvas,"\n"})
$ctag_text.bind('Control-h', proc{textBs $ctext_canvas})
$ctag_text.bind('BackSpace', proc{textBs $ctext_canvas})
$ctag_text.bind('Delete', proc{textDel $ctext_canvas})
$ctag_text.bind('2', proc{|x,y| textPaste $ctext_canvas, "@#{x},#{y}"},
- "%x %y")
+ "%x %y")
# Next, create some items that allow the text's anchor position
# to be edited.
def mkTextConfig(w,x,y,option,value,color)
item = TkcRectangle.new(w, x, y, x+30, y+30,
- 'outline'=>'black', 'fill'=>color, 'width'=>1)
+ 'outline'=>'black', 'fill'=>color, 'width'=>1)
item.bind('1', proc{$ctag_text.configure option, value})
w.addtag_withtag('config', item)
end
@@ -103,11 +116,16 @@ mkTextConfig $ctext_canvas, x, y+60, 'anchor', 'ne', color
mkTextConfig $ctext_canvas, x+30, y+60, 'anchor', 'n', color
mkTextConfig $ctext_canvas, x+60, y+60, 'anchor', 'nw', color
item = TkcRectangle.new($ctext_canvas, x+40, y+40, x+50, y+50,
- 'outline'=>'black', 'fill'=>'red')
+ 'outline'=>'black', 'fill'=>'red')
item.bind('1', proc{$ctag_text.configure 'anchor', 'center'})
-TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position', 'anchor'=>'s',
- 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
- 'fill'=>'brown')
+if $tk_version =~ /^4.*/
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position',
+ 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
+ 'anchor'=>'s', 'fill'=>'brown')
+else
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position',
+ 'font'=>'Times 24', 'anchor'=>'s', 'fill'=>'brown')
+end
# Lastly, create some items that allow the text's justification to be
# changed.
@@ -118,15 +136,20 @@ color = 'SeaGreen2'
mkTextConfig $ctext_canvas, x, y, 'justify', 'left', color
mkTextConfig $ctext_canvas, x+30, y, 'justify', 'center', color
mkTextConfig $ctext_canvas, x+60, y, 'justify', 'right', color
-TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification', 'anchor'=>'s',
- 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
- 'fill'=>'brown')
+if $tk_version =~ /^4.*/
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification',
+ 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
+ 'anchor'=>'s', 'fill'=>'brown')
+else
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification',
+ 'font'=>'Times 24', 'anchor'=>'s', 'fill'=>'brown')
+end
$ctext_canvas.itembind('config', 'Enter', proc{textEnter $ctext_canvas})
$ctext_canvas.itembind('config', 'Leave',
- proc{$ctext_canvas\
- .itemconfigure('current',
- 'fill'=>$textConfigFill)})
+ proc{$ctext_canvas\
+ .itemconfigure('current',
+ 'fill'=>$textConfigFill)})
$textConfigFill = ''
diff --git a/ext/tk/sample/demos-jp/dialog1.rb b/ext/tk/sample/demos-jp/dialog1.rb
index 317b6d9eb3..07e50306ab 100644
--- a/ext/tk/sample/demos-jp/dialog1.rb
+++ b/ext/tk/sample/demos-jp/dialog1.rb
@@ -1,7 +1,11 @@
+# -*- coding: euc-jp -*-
#
# a dialog box with a local grab (called by 'widget')
#
class TkDialog_Demo1 < TkDialog
+ ###############
+ private
+ ###############
def title
"Dialog with local grab"
end
@@ -31,5 +35,5 @@ when 0
when 1
print "¤¢¤Ê¤¿¤Ï¡Ö¥­¥ã¥ó¥»¥ë¡×¤ò²¡¤·¤Þ¤·¤¿¤Í¡£\n"
when 2
- showCode dialog1
+ showCode 'dialog1'
end
diff --git a/ext/tk/sample/demos-jp/dialog2.rb b/ext/tk/sample/demos-jp/dialog2.rb
index 295522e562..f747f8d6a8 100644
--- a/ext/tk/sample/demos-jp/dialog2.rb
+++ b/ext/tk/sample/demos-jp/dialog2.rb
@@ -1,7 +1,11 @@
+# -*- coding: euc-jp -*-
#
# a dialog box with a global grab (called by 'widget')
#
class TkDialog_Demo2 < TkDialog
+ ###############
+ private
+ ###############
def title
"Dialog with global grab"
end
@@ -25,15 +29,15 @@ class TkDialog_Demo2 < TkDialog
end
ret = TkDialog_Demo2.new('message_config'=>{'wraplength'=>'4i'},
- 'prev_command'=>proc{|dialog|
- Tk.after 100, proc{dialog.grab('global')}
- }).value
+ 'prev_command'=>proc{|dialog|
+ Tk.after 100, proc{dialog.grab('global')}
+ }).value
case ret
when 0
print "¤¢¤Ê¤¿¤Ï¡Öλ²ò¡×¤ò²¡¤·¤Þ¤·¤¿¤Í¡£\n"
when 1
print "¤¢¤Ê¤¿¤Ï¡Ö¥­¥ã¥ó¥»¥ë¡×¤ò²¡¤·¤Þ¤·¤¿¤Í¡£\n"
when 2
- showCode dialog2
+ showCode 'dialog2'
end
diff --git a/ext/tk/sample/demos-jp/entry1.rb b/ext/tk/sample/demos-jp/entry1.rb
index 273b6728df..2be29c18d3 100644
--- a/ext/tk/sample/demos-jp/entry1.rb
+++ b/ext/tk/sample/demos-jp/entry1.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# entry (no scrollbars) widget demo (called by 'widget')
#
@@ -15,8 +16,10 @@ $entry1_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($entry1_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($entry1_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($entry1_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($entry1_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $entry1_demo
$entry1_demo = nil
@@ -42,9 +46,9 @@ TkFrame.new($entry1_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# entry À¸À®
-e1 = TkEntry.new($entry1_demo, 'relief'=>'sunken')
-e2 = TkEntry.new($entry1_demo, 'relief'=>'sunken')
-e3 = TkEntry.new($entry1_demo, 'relief'=>'sunken')
+e1 = TkEntry.new(base_frame, 'relief'=>'sunken')
+e2 = TkEntry.new(base_frame, 'relief'=>'sunken')
+e3 = TkEntry.new(base_frame, 'relief'=>'sunken')
[e1,e2,e3].each{|w| w.pack('side'=>'top', 'padx'=>10, 'pady'=>5, 'fill'=>'x')}
# ½é´üÃÍÁÞÆþ
diff --git a/ext/tk/sample/demos-jp/entry2.rb b/ext/tk/sample/demos-jp/entry2.rb
index 7efac005f0..2675b5d324 100644
--- a/ext/tk/sample/demos-jp/entry2.rb
+++ b/ext/tk/sample/demos-jp/entry2.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# entry (with scrollbars) widget demo (called by 'widget')
#
@@ -15,8 +16,10 @@ $entry2_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($entry2_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($entry2_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($entry2_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($entry2_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $entry2_demo
$entry2_demo = nil
@@ -42,7 +46,7 @@ TkFrame.new($entry2_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame À¸À®
-TkFrame.new($entry2_demo, 'borderwidth'=>10) {|w|
+TkFrame.new(base_frame, 'borderwidth'=>10) {|w|
# entry 1
s1 = TkScrollbar.new(w, 'relief'=>'sunken', 'orient'=>'horiz')
e1 = TkEntry.new(w, 'relief'=>'sunken') {
diff --git a/ext/tk/sample/demos-jp/entry3.rb b/ext/tk/sample/demos-jp/entry3.rb
index 9bf3f62097..6b9cd4cf37 100644
--- a/ext/tk/sample/demos-jp/entry3.rb
+++ b/ext/tk/sample/demos-jp/entry3.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
# entry3.rb --
#
# This demonstration script creates several entry widgets whose
@@ -17,9 +18,11 @@ $entry3_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($entry3_demo,
- :font=>$font, :wraplength=>'5i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+base_frame = TkFrame.new($entry3_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'5i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
°Ê²¼¤Ë¤Ï£´¼ïÎà¤Î¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥³Æ¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤Ï¡¤\
¥Þ¥¦¥¹¥¯¥ê¥Ã¥¯¤ÇÁªÂò¤·Ê¸»ú¤òÂǤÁ¹þ¤à¤³¤È¤¬²Äǽ¤Ç¤¹¤¬¡¤¤½¤ì¤¾¤ì¤¬¤É¤Î¤è¤¦¤Ê\
ÆþÎϤò¼õ¤±ÉÕ¤±¤ë¤³¤È¤¬¤Ç¤­¤ë¤«¤Ë¤ÏÀ©Ìó¤¬Àߤ±¤é¤ì¤Æ¤¤¤Þ¤¹¡¥\
@@ -38,17 +41,17 @@ TkLabel.new($entry3_demo,
ÆþÎϤµ¤ì¤¿Ê¸»ú¤Ï¥¢¥¹¥¿¥ê¥¹¥¯µ­¹æ¤ËÃÖ¤­´¹¤¨¤ÆÉ½¼¨¤µ¤ì¤Þ¤¹¡¥
EOL
-TkFrame.new($entry3_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
- TkButton.new(f, :text=>'λ²ò', :width=>15, :command=>proc{
- $entry3_demo.destroy
- $entry3_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ TkButton.new(f, :text=>'ÊĤ¸¤ë', :width=>15, :command=>proc{
+ $entry3_demo.destroy
+ $entry3_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'¥³¡¼¥É»²¾È', :width=>15, :command=>proc{
- showCode 'entry3'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'entry3'
+ }).pack(:side=>:left, :expand=>true)
}
# focusAndFlash --
@@ -58,32 +61,50 @@ TkFrame.new($entry3_demo){|f|
# 2.5Hz).
#
# Arguments:
-# widget - entry widget to flash
-# fg - Initial foreground colour
-# bg - Initial background colour
-# count - Counter to control the number of times flashed
+# widget - entry widget to flash
+# fg - Initial foreground colour
+# bg - Initial background colour
+# count - Counter to control the number of times flashed
def focusAndFlash(widget, fg, bg, count=5)
return if count <= 0
- TkTimer.new(200, count,
- proc{widget.configure(:foreground=>bg, :background=>fg)},
- proc{widget.configure(:foreground=>fg, :background=>bg)}
- ).start
+ if fg && !fg.empty? && bg && !bg.empty?
+ TkTimer.new(200, count,
+ proc{widget.configure(:foreground=>bg, :background=>fg)},
+ proc{widget.configure(:foreground=>fg, :background=>bg)}
+ ).start
+ else
+ # TkTimer.new(150, 3){Tk.bell}.start
+ Tk.bell
+ TkTimer.new(200, count,
+ proc{widget.configure(:foreground=>'white',
+ :background=>'black')},
+ proc{widget.configure(:foreground=>'black',
+ :background=>'white')}
+ ).at_end{begin
+ widget.configure(:foreground=>fg,
+ :background=>bg)
+ rescue
+ # ignore
+ end}.start
+ end
widget.focus(true)
end
-l1 = TkLabelFrame.new($entry3_demo, :text=>"À°¿ô¥¨¥ó¥È¥ê")
+l1 = TkLabelFrame.new(base_frame, :text=>"À°¿ô¥¨¥ó¥È¥ê")
TkEntry.new(l1, :validate=>:focus,
- :vcmd=>[
- proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
- ]) {|e|
- invalidcommand [proc{|w| focusAndFlash(w, e.fg, e.bg)}, '%W']
+ :vcmd=>[
+ proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
+ ]) {|e|
+ fg = e.foreground
+ bg = e.background
+ invalidcommand [proc{|w| focusAndFlash(w, fg, bg)}, '%W']
pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
}
-l2 = TkLabelFrame.new($entry3_demo, :text=>"ŤµÀ©ÌóÉÕ¤­¥¨¥ó¥È¥ê")
+l2 = TkLabelFrame.new(base_frame, :text=>"ŤµÀ©ÌóÉÕ¤­¥¨¥ó¥È¥ê")
TkEntry.new(l2, :validate=>:key, :invcmd=>proc{Tk.bell},
- :vcmd=>[proc{|s| s.length < 10}, '%P']
- ).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
+ :vcmd=>[proc{|s| s.length < 10}, '%P']
+ ).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
### PHONE NUMBER ENTRY ###
# Note that the source to this is quite a bit longer as the behaviour
@@ -105,7 +126,7 @@ Hash[*(%w(abc 2 def 3 ghi 4 jkl 5 mno 6 pqrs 7 tuv 8 wxyz 9))].each{|chars, n|
# Skip over fixed characters in a phone-number string when moving left.
#
# Arguments:
-# widget - The entry widget containing the phone-number.
+# widget - The entry widget containing the phone-number.
def phoneSkipLeft(widget)
idx = widget.index('insert')
if idx == 8
@@ -125,7 +146,7 @@ end
# Skip over fixed characters in a phone-number string when moving right.
#
# Arguments:
-# widget - The entry widget containing the phone-number.
+# widget - The entry widget containing the phone-number.
# add - Offset to add to index before calculation (used by validation.)
def phoneSkipRight(widget, add = 0)
idx = widget.index('insert')
@@ -149,51 +170,53 @@ end
#
# widget - entry widget to validate
# vmode - The widget's validation mode
-# idx - The index where replacement is to occur
+# idx - The index where replacement is to occur
# char - The character (or string, though that will always be
-# refused) to be overwritten at that point.
+# refused) to be overwritten at that point.
def validatePhoneChange(widget, vmode, idx, char)
return true if idx == nil
Tk.after_idle(proc{widget.configure(:validate=>vmode,
- :invcmd=>proc{Tk.bell})})
+ :invcmd=>proc{Tk.bell})})
if !(idx<3 || idx==6 || idx==7 || idx==11 || idx>15) && char =~ /[0-9A-Za-z]/
widget.delete(idx)
widget.insert(idx, $phoneNumberMap[char] || char)
Tk.after_idle(proc{phoneSkipRight(widget, -1)})
+ # Tk.update(true) # <- Don't work 'update' inter validation callback.
+ # It depends on Tcl/Tk side (tested on Tcl/Tk8.5a1).
return true
end
return false
end
-l3 = TkLabelFrame.new($entry3_demo, :text=>"ÊÆ¹ñÅÅÏÃÈֹ楨¥ó¥È¥ê")
+l3 = TkLabelFrame.new(base_frame, :text=>"ÊÆ¹ñÅÅÏÃÈֹ楨¥ó¥È¥ê")
TkEntry.new(l3, :validate=>:key, :invcmd=>proc{Tk.bell},
- :textvariable=>entry3content,
- :vcmd=>[
- proc{|w,v,i,s| validatePhoneChange(w,v,i,s)},
- "%W %v %i %S"
- ]){|e|
+ :textvariable=>entry3content,
+ :vcmd=>[
+ proc{|w,v,i,s| validatePhoneChange(w,v,i,s)},
+ "%W %v %i %S"
+ ]){|e|
# Click to focus goes to the first editable character...
bind('FocusIn', proc{|d,w|
- if d != "NotifyAncestor"
- w.cursor = 3
- Tk.after_idle(proc{w.selection_clear})
- end
+ if d != "NotifyAncestor"
+ w.cursor = 3
+ Tk.after_idle(proc{w.selection_clear})
+ end
}, '%d %W')
bind('Left', proc{|w| phoneSkipLeft(w)}, '%W')
bind('Right', proc{|w| phoneSkipRight(w)}, '%W')
pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
}
-l4 = TkLabelFrame.new($entry3_demo, :text=>"¥Ñ¥¹¥ï¡¼¥É¥¨¥ó¥È¥ê")
+l4 = TkLabelFrame.new(base_frame, :text=>"¥Ñ¥¹¥ï¡¼¥É¥¨¥ó¥È¥ê")
TkEntry.new(l4, :validate=>:key, :show=>'*',
- :vcmd=>[
- proc{|s| s.length <= 8},
- '%P'
- ]).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
+ :vcmd=>[
+ proc{|s| s.length <= 8},
+ '%P'
+ ]).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
-TkFrame.new($entry3_demo){|f|
+TkFrame.new(base_frame){|f|
lower
TkGrid.configure(l1, l2, :in=>f, :padx=>'3m', :pady=>'1m', :sticky=>:ew)
TkGrid.configure(l3, l4, :in=>f, :padx=>'3m', :pady=>'1m', :sticky=>:ew)
diff --git a/ext/tk/sample/demos-jp/filebox.rb b/ext/tk/sample/demos-jp/filebox.rb
index 1754596706..b8846d08a0 100644
--- a/ext/tk/sample/demos-jp/filebox.rb
+++ b/ext/tk/sample/demos-jp/filebox.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# widget demo prompts the user to select a file (called by 'widget')
#
@@ -15,14 +16,17 @@ $filebox_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($filebox_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($filebox_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
- 'text'=>"¥¨¥ó¥È¥ê¤Ë¥Õ¥¡¥¤¥ë̾¤òľÀÜÆþÎϤ¹¤ë¤«¡¢\"Browse\" ¥Ü¥¿¥ó¤ò²¡¤·¤Æ¥Õ¥¡¥¤¥ëÁªÂò¥À¥¤¥¢¥í¥°¤«¤é¥Õ¥¡¥¤¥ë̾¤òÁª¤ó¤Ç²¼¤µ¤¤¡£").pack('side'=>'top')
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
+ 'text'=>"¥¨¥ó¥È¥ê¤Ë¥Õ¥¡¥¤¥ë̾¤òľÀÜÆþÎϤ¹¤ë¤«¡¢\"Browse\" ¥Ü¥¿¥ó¤ò²¡¤·¤Æ¥Õ¥¡¥¤¥ëÁªÂò¥À¥¤¥¢¥í¥°¤«¤é¥Õ¥¡¥¤¥ë̾¤òÁª¤ó¤Ç²¼¤µ¤¤¡£").pack('side'=>'top')
# frame À¸À®
-TkFrame.new($filebox_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $filebox_demo
$filebox_demo = nil
@@ -38,7 +42,7 @@ TkFrame.new($filebox_demo) {|frame|
# frame À¸À®
['³«¤¯', 'Êݸ'].each{|type|
- TkFrame.new($filebox_demo) {|f|
+ TkFrame.new(base_frame) {|f|
TkLabel.new(f, 'text'=>"¥Õ¥¡¥¤¥ë¤ò#{type}: ", 'anchor'=>'e')\
.pack('side'=>'left')
@@ -46,7 +50,7 @@ TkFrame.new($filebox_demo) {|frame|
pack('side'=>'left', 'expand'=>'yes', 'fill'=>'x')
TkButton.new(f, 'text'=>'Browse ...',
- 'command'=>proc{fileDialog $filebox_demo,e,type})\
+ 'command'=>proc{fileDialog base_frame,e,type})\
.pack('side'=>'left')
}
@@ -56,10 +60,10 @@ TkFrame.new($filebox_demo) {|frame|
$tk_strictMotif = TkVarAccess.new('tk_strictMotif')
if ($tk_platform['platform'] == 'unix')
- TkCheckButton.new($filebox_demo,
- 'text'=>'Motif¥¹¥¿¥¤¥ë¤Î¥À¥¤¥¢¥í¥°¤òÍѤ¤¤ë',
- 'variable'=>$tk_strictMotif,
- 'onvalue'=>1, 'offvalue'=>0 ).pack('anchor'=>'c')
+ TkCheckButton.new(base_frame,
+ 'text'=>'Motif¥¹¥¿¥¤¥ë¤Î¥À¥¤¥¢¥í¥°¤òÍѤ¤¤ë',
+ 'variable'=>$tk_strictMotif,
+ 'onvalue'=>1, 'offvalue'=>0 ).pack('anchor'=>'c')
end
def fileDialog(w,ent,operation)
@@ -83,13 +87,16 @@ def fileDialog(w,ent,operation)
file = Tk.getOpenFile('filetypes'=>types, 'parent'=>w)
else
file = Tk.getSaveFile('filetypes'=>types, 'parent'=>w,
- 'initialfile'=>'Untitled',
- 'defaultextension'=>'.txt')
+ 'initialfile'=>'Untitled',
+ 'defaultextension'=>'.txt')
end
if file != ""
ent.delete 0, 'end'
ent.insert 0, file
- ent.xview 'end'
+ # ent.xview 'end'
+ Tk.update_idletasks # need this for Tk::Tile::Entry
+ # (to find right position of 'xview').
+ ent.xview(ent.index('end'))
end
end
diff --git a/ext/tk/sample/demos-jp/floor.rb b/ext/tk/sample/demos-jp/floor.rb
index bb655d5b55..a2ec2e9969 100644
--- a/ext/tk/sample/demos-jp/floor.rb
+++ b/ext/tk/sample/demos-jp/floor.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# floorDisplay widget demo (called by 'widget')
#
@@ -8,8 +9,8 @@
# visible.
#
# Arguments:
-# w - Name of the canvas window.
-# active - Number of active floor (1, 2, or 3).
+# w - Name of the canvas window.
+# active - Number of active floor (1, 2, or 3).
def floorDisplay(w,active)
return if $activeFloor == active
@@ -59,7 +60,7 @@ end
# highlighted.
#
# Arguments:
-# w - The name of the canvas window.
+# w - The name of the canvas window.
def newRoom(w)
id = w.find_withtag('current')[0]
@@ -72,8 +73,8 @@ end
# It highlights the current room and unhighlights any previous room.
#
# Arguments:
-# w - The canvas window displaying the floorplan.
-# args - Not used.
+# w - The canvas window displaying the floorplan.
+# args - Not used.
def roomChanged(w,*args)
w.delete('highlight')
@@ -90,24 +91,24 @@ end
# floor.
#
# Arguments:
-# w - The canvas window.
-# fill - Fill color to use for the floor's background.
-# outline - Color to use for the floor's outline.
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
def floor_bg1(w,fill,outline)
TkcPolygon.new(w,347,80,349,82,351,84,353,85,363,92,375,99,386,104,
- 386,129,398,129,398,162,484,162,484,129,559,129,559,133,725,
- 133,725,129,802,129,802,389,644,389,644,391,559,391,559,327,
- 508,327,508,311,484,311,484,278,395,278,395,288,400,288,404,
- 288,409,290,413,292,418,297,421,302,422,309,421,318,417,325,
- 411,330,405,332,397,333,344,333,340,334,336,336,335,338,332,
- 342,331,347,332,351,334,354,336,357,341,359,340,360,335,363,
- 331,365,326,366,304,366,304,355,258,355,258,387,60,387,60,391,
- 0,391,0,337,3,337,3,114,8,114,8,25,30,25,30,5,93,5,98,5,104,7,
- 110,10,116,16,119,20,122,28,123,32,123,68,220,68,220,34,221,
- 22,223,17,227,13,231,8,236,4,242,2,246,0,260,0,283,1,300,5,
- 321,14,335,22,348,25,365,29,363,39,358,48,352,56,337,70,
- 344,76,347,80, 'tags'=>['floor1','bg'], 'fill'=>fill)
+ 386,129,398,129,398,162,484,162,484,129,559,129,559,133,725,
+ 133,725,129,802,129,802,389,644,389,644,391,559,391,559,327,
+ 508,327,508,311,484,311,484,278,395,278,395,288,400,288,404,
+ 288,409,290,413,292,418,297,421,302,422,309,421,318,417,325,
+ 411,330,405,332,397,333,344,333,340,334,336,336,335,338,332,
+ 342,331,347,332,351,334,354,336,357,341,359,340,360,335,363,
+ 331,365,326,366,304,366,304,355,258,355,258,387,60,387,60,391,
+ 0,391,0,337,3,337,3,114,8,114,8,25,30,25,30,5,93,5,98,5,104,7,
+ 110,10,116,16,119,20,122,28,123,32,123,68,220,68,220,34,221,
+ 22,223,17,227,13,231,8,236,4,242,2,246,0,260,0,283,1,300,5,
+ 321,14,335,22,348,25,365,29,363,39,358,48,352,56,337,70,
+ 344,76,347,80, 'tags'=>['floor1','bg'], 'fill'=>fill)
TkcLine.new(w,386,129,398,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
TkcLine.new(w,258,355,258,387, 'fill'=>outline, 'tags'=>['floor1','bg'])
TkcLine.new(w,60,387,60,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
@@ -214,17 +215,17 @@ end
# floor.
#
# Arguments:
-# w - The canvas window.
-# fill - Fill color to use for the floor's background.
-# outline - Color to use for the floor's outline.
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
def floor_bg2(w,fill,outline)
TkcPolygon.new(w,559,129,484,129,484,162,398,162,398,129,315,129,
- 315,133,176,133,176,129,96,129,96,133,3,133,3,339,0,339,0,391,
- 60,391,60,387,258,387,258,329,350,329,350,311,395,311,395,280,
- 484,280,484,311,508,311,508,327,558,327,558,391,644,391,644,
- 367,802,367,802,129,725,129,725,133,559,133,559,129,
- 'tags'=>['floor2','bg'], 'fill'=>fill)
+ 315,133,176,133,176,129,96,129,96,133,3,133,3,339,0,339,0,391,
+ 60,391,60,387,258,387,258,329,350,329,350,311,395,311,395,280,
+ 484,280,484,311,508,311,508,327,558,327,558,391,644,391,644,
+ 367,802,367,802,129,725,129,725,133,559,133,559,129,
+ 'tags'=>['floor2','bg'], 'fill'=>fill)
TkcLine.new(w,350,311,350,329, 'fill'=>outline, 'tags'=>['floor2','bg'])
TkcLine.new(w,398,129,398,162, 'fill'=>outline, 'tags'=>['floor2','bg'])
TkcLine.new(w,802,367,802,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
@@ -269,17 +270,17 @@ end
# floor.
#
# Arguments:
-# w - The canvas window.
-# fill - Fill color to use for the floor's background.
-# outline - Color to use for the floor's outline.
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
def floor_bg3(w,fill,outline)
TkcPolygon.new(w,159,300,107,300,107,248,159,248,159,129,96,129,96,
- 133,21,133,21,331,0,331,0,391,60,391,60,370,159,370,159,300,
- 'tags'=>['floor3','bg'], 'fill'=>fill)
+ 133,21,133,21,331,0,331,0,391,60,391,60,370,159,370,159,300,
+ 'tags'=>['floor3','bg'], 'fill'=>fill)
TkcPolygon.new(w,258,370,258,329,350,329,350,311,399,311,399,129,
- 315,129,315,133,176,133,176,129,159,129,159,370,258,370,
- 'tags'=>['floor3','bg'], 'fill'=>fill)
+ 315,129,315,133,176,133,176,129,159,129,159,370,258,370,
+ 'tags'=>['floor3','bg'], 'fill'=>fill)
TkcLine.new(w,96,133,96,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
TkcLine.new(w,176,129,96,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
TkcLine.new(w,176,129,176,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
@@ -299,7 +300,7 @@ def floor_bg3(w,fill,outline)
TkcLine.new(w,21,331,21,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
TkcLine.new(w,96,133,21,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
TkcLine.new(w,107,300,159,300,159,248,107,248,107,300,
- 'fill'=>outline, 'tags'=>['floor3','bg'])
+ 'fill'=>outline, 'tags'=>['floor3','bg'])
end
# floor_fg1 --
@@ -308,321 +309,321 @@ end
# floor (office outlines and numbers).
#
# Arguments:
-# w - The canvas window.
-# color - Color to use for drawing foreground information.
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
def floor_fg1(w,color)
i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '101'
$floorItems['101'] = i
TkcText.new(w,358,209, 'text'=>'101', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Pub Lift1'
$floorItems['Pub Lift1'] = i
TkcText.new(w,323,223, 'text'=>'Pub Lift1', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Priv Lift1'
$floorItems['Priv Lift1'] = i
TkcText.new(w,323,188, 'text'=>'Priv Lift1', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,42,389,42,337,1,337,1,389,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '110'
$floorItems['110'] = i
TkcText.new(w,21.5,363, 'text'=>'110', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,59,389,59,385,90,385,90,337,44,337,44,389,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '109'
$floorItems['109'] = i
TkcText.new(w,67,363, 'text'=>'109', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,51,300,51,253,6,253,6,300,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '111'
$floorItems['111'] = i
TkcText.new(w,28.5,276.5, 'text'=>'111', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,98,248,98,309,79,309,79,248,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '117B'
$floorItems['117B'] = i
TkcText.new(w,88.5,278.5, 'text'=>'117B', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,51,251,51,204,6,204,6,251,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '112'
$floorItems['112'] = i
TkcText.new(w,28.5,227.5, 'text'=>'112', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,6,156,51,156,51,203,6,203,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '113'
$floorItems['113'] = i
TkcText.new(w,28.5,179.5, 'text'=>'113', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,85,169,79,169,79,192,85,192,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '117A'
$floorItems['117A'] = i
TkcText.new(w,82,180.5, 'text'=>'117A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,77,302,77,168,53,168,53,302,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '117'
$floorItems['117'] = i
TkcText.new(w,65,235, 'text'=>'117', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,51,155,51,115,6,115,6,155,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '114'
$floorItems['114'] = i
TkcText.new(w,28.5,135, 'text'=>'114', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,95,115,53,115,53,168,95,168,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '115'
$floorItems['115'] = i
TkcText.new(w,74,141.5, 'text'=>'115', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,87,113,87,27,10,27,10,113,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '116'
$floorItems['116'] = i
TkcText.new(w,48.5,70, 'text'=>'116', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,89,91,128,91,128,113,89,131,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '118'
$floorItems['118'] = i
TkcText.new(w,108.5,102, 'text'=>'118', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,178,128,178,132,216,132,216,91,
- 163,91,163,112,149,112,149,128,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 163,91,163,112,149,112,149,128,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '120'
$floorItems['120'] = i
TkcText.new(w,189.5,111.5, 'text'=>'120', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,79,193,87,193,87,169,136,169,136,192,
- 156,192,156,169,175,169,175,246,79,246,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 156,192,156,169,175,169,175,246,79,246,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '122'
$floorItems['122'] = i
TkcText.new(w,131,207.5, 'text'=>'122', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,138,169,154,169,154,191,138,191,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '121'
$floorItems['121'] = i
TkcText.new(w,146,180, 'text'=>'121', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,99,300,126,300,126,309,99,309,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '106A'
$floorItems['106A'] = i
TkcText.new(w,112.5,304.5, 'text'=>'106A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,128,299,128,309,150,309,150,248,99,248,99,299,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '105'
$floorItems['105'] = i
TkcText.new(w,124.5,278.5, 'text'=>'105', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,174,309,174,300,152,300,152,309,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '106B'
$floorItems['106B'] = i
TkcText.new(w,163,304.5, 'text'=>'106B', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,176,299,176,309,216,309,216,248,152,248,152,299,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '104'
$floorItems['104'] = i
TkcText.new(w,184,278.5, 'text'=>'104', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,138,385,138,337,91,337,91,385,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '108'
$floorItems['108'] = i
TkcText.new(w,114.5,361, 'text'=>'108', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,256,337,140,337,140,385,256,385,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '107'
$floorItems['107'] = i
TkcText.new(w,198,361, 'text'=>'107', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,300,353,300,329,260,329,260,353,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Smoking'
$floorItems['Smoking'] = i
TkcText.new(w,280,341, 'text'=>'Smoking', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,314,135,314,170,306,170,306,246,177,246,177,135,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '123'
$floorItems['123'] = i
TkcText.new(w,245.5,190.5, 'text'=>'123', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,217,248,301,248,301,326,257,326,257,310,217,310,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '103'
$floorItems['103'] = i
TkcText.new(w,259,287, 'text'=>'103', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,396,188,377,188,377,169,316,169,316,131,396,131,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '124'
$floorItems['124'] = i
TkcText.new(w,356,150, 'text'=>'124', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,397,226,407,226,407,189,377,189,377,246,397,246,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '125'
$floorItems['125'] = i
TkcText.new(w,392,217.5, 'text'=>'125', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,399,187,409,187,409,207,474,207,474,164,399,164,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '126'
$floorItems['126'] = i
TkcText.new(w,436.5,185.5, 'text'=>'126', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,409,209,409,229,399,229,399,253,
- 486,253,486,239,474,239,474,209,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 486,253,486,239,474,239,474,209,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '127'
$floorItems['127'] = i
TkcText.new(w,436.5,'231', 'text'=>'127', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,501,164,501,174,495,174,495,188,
- 490,188,490,204,476,204,476,164,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 490,188,490,204,476,204,476,164,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'MShower'
$floorItems['MShower'] = i
TkcText.new(w,488.5,'184', 'text'=>'MShower', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,497,176,513,176,513,204,492,204,492,190,497,190,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Closet'
$floorItems['Closet'] = i
TkcText.new(w,502.5,190, 'text'=>'Closet', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,476,237,476,206,513,206,513,254,488,254,488,237,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'WShower'
$floorItems['WShower'] = i
TkcText.new(w,494.5,230, 'text'=>'WShower', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,486,131,558,131,558,135,724,135,724,166,
- 697,166,697,275,553,275,531,254,515,254,
- 515,174,503,174,503,161,486,161,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 697,166,697,275,553,275,531,254,515,254,
+ 515,174,503,174,503,161,486,161,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '130'
$floorItems['130'] = i
TkcText.new(w,638.5,205, 'text'=>'130', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,308,242,339,242,339,248,342,248,
- 342,246,397,246,397,276,393,276,
- 393,309,300,309,300,248,308,248,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 342,246,397,246,397,276,393,276,
+ 393,309,300,309,300,248,308,248,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '102'
$floorItems['102'] = i
TkcText.new(w,367.5,278.5, 'text'=>'102', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,397,255,486,255,486,276,397,276,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '128'
$floorItems['128'] = i
TkcText.new(w,441.5,265.5, 'text'=>'128', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,510,309,486,309,486,255,530,255,
- 552,277,561,277,561,325,510,325,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 552,277,561,277,561,325,510,325,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '129'
$floorItems['129'] = i
TkcText.new(w,535.5,293, 'text'=>'129', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,696,281,740,281,740,387,642,387,
- 642,389,561,389,561,277,696,277,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 642,389,561,389,561,277,696,277,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '133'
$floorItems['133'] = i
TkcText.new(w,628.5,335, 'text'=>'133', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,742,387,742,281,800,281,800,387,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '132'
$floorItems['132'] = i
TkcText.new(w,771,334, 'text'=>'132', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,800,168,800,280,699,280,699,168,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '134'
$floorItems['134'] = i
TkcText.new(w,749.5,224, 'text'=>'134', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,726,131,726,166,800,166,800,131,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '135'
$floorItems['135'] = i
TkcText.new(w,763,148.5, 'text'=>'135', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,340,360,335,363,331,365,326,366,304,366,
- 304,312,396,312,396,288,400,288,404,288,
- 409,290,413,292,418,297,421,302,422,309,
- 421,318,417,325,411,330,405,332,397,333,
- 344,333,340,334,336,336,335,338,332,342,
- 331,347,332,351,334,354,336,357,341,359,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 304,312,396,312,396,288,400,288,404,288,
+ 409,290,413,292,418,297,421,302,422,309,
+ 421,318,417,325,411,330,405,332,397,333,
+ 344,333,340,334,336,336,335,338,332,342,
+ 331,347,332,351,334,354,336,357,341,359,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Ramona Stair'
$floorItems['Ramona Stair'] = i
TkcText.new(w,368,323, 'text'=>'Ramona Stair', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,30,23,30,5,93,5,98,5,104,7,110,10,116,16,119,20,
- 122,28,123,32,123,68,220,68,220,87,90,87,90,23,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 122,28,123,32,123,68,220,68,220,87,90,87,90,23,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'University Stair'
$floorItems['University Stair'] = i
TkcText.new(w,155,77.5, 'text'=>'University Stair', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,282,37,295,40,312,49,323,56,337,70,352,56,
- 358,48,363,39,365,29,348,25,335,22,321,14,
- 300,5,283,1,260,0,246,0,242,2,236,4,231,8,
- 227,13,223,17,221,22,220,34,260,34,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 358,48,363,39,365,29,348,25,335,22,321,14,
+ 300,5,283,1,260,0,246,0,242,2,236,4,231,8,
+ 227,13,223,17,221,22,220,34,260,34,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Plaza Stair'
$floorItems['Plaza Stair'] = i
TkcText.new(w,317.5,28.5, 'text'=>'Plaza Stair', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,220,34,260,34,282,37,295,40,312,49,
- 323,56,337,70,350,83,365,94,377,100,
- 386,104,386,128,220,128,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 323,56,337,70,350,83,365,94,377,100,
+ 386,104,386,128,220,128,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = 'Plaza Deck'
$floorItems['Plaza Deck'] = i
TkcText.new(w,303,81, 'text'=>'Plaza Deck', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,257,336,77,336,6,336,6,301,77,301,77,310,257,310,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '106'
$floorItems['106'] = i
TkcText.new(w,131.5,318.5, 'text'=>'106', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
i = TkcPolygon.new(w,146,110,162,110,162,91,130,91,130,115,95,115,
- 95,128,114,128,114,151,157,151,157,153,112,153,
- 112,130,97,130,97,168,175,168,175,131,146,131,
- 'fill'=>'', 'tags'=>['floor1','room'])
+ 95,128,114,128,114,151,157,151,157,153,112,153,
+ 112,130,97,130,97,168,175,168,175,131,146,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
$floorLabels[i.id] = '119'
$floorItems['119'] = i
TkcText.new(w,143.5,133, 'text'=>'119', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor1','label'])
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
TkcLine.new(w,155,191,155,189, 'fill'=>color, 'tags'=>['floor1','wall'])
TkcLine.new(w,155,177,155,169, 'fill'=>color, 'tags'=>['floor1','wall'])
TkcLine.new(w,96,129,96,169, 'fill'=>color, 'tags'=>['floor1','wall'])
@@ -789,327 +790,327 @@ end
# floor (office outlines and numbers).
#
# Arguments:
-# w - The canvas window.
-# color - Color to use for drawing foreground information.
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
def floor_fg2(w,color)
i = TkcPolygon.new(w,748,188,755,188,755,205,758,205,758,222,
- 800,222,800,168,748,168,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 800,222,800,168,748,168,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '238'
$floorItems['238'] = i
TkcText.new(w,774,195, 'text'=>'238', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,726,188,746,188,746,166,800,166,800,131,726,131,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '237'
$floorItems['237'] = i
TkcText.new(w,763,148.5, 'text'=>'237', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,497,187,497,204,559,204,559,324,641,324,
- 643,324,643,291,641,291,641,205,696,205,
- 696,291,694,291,694,314,715,314,715,291,
- 715,205,755,205,755,190,724,190,724,187,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 643,324,643,291,641,291,641,205,696,205,
+ 696,291,694,291,694,314,715,314,715,291,
+ 715,205,755,205,755,190,724,190,724,187,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '246'
$floorItems['246'] = i
TkcText.new(w,600,264, 'text'=>'246', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,694,279,643,279,643,314,694,314,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '247'
$floorItems['247'] = i
TkcText.new(w,668.5,296.5, 'text'=>'247', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,232,250,308,250,308,242,339,242,339,246,
- 397,246,397,255,476,255,476,250,482,250,559,250,
- 559,274,482,274,482,278,396,278,396,274,232,274,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 397,246,397,255,476,255,476,250,482,250,559,250,
+ 559,274,482,274,482,278,396,278,396,274,232,274,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '202'
$floorItems['202'] = i
TkcText.new(w,285.5,260, 'text'=>'202', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,53,228,53,338,176,338,233,338,233,196,
- 306,196,306,180,175,180,175,169,156,169,
- 156,196,176,196,176,228,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 306,196,306,180,175,180,175,169,156,169,
+ 156,196,176,196,176,228,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '206'
$floorItems['206'] = i
TkcText.new(w,143,267, 'text'=>'206', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,51,277,6,277,6,338,51,338,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '212'
$floorItems['212'] = i
TkcText.new(w,28.5,307.5, 'text'=>'212', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,557,276,486,276,486,309,510,309,510,325,557,325,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '245'
$floorItems['245'] = i
TkcText.new(w,521.5,300.5, 'text'=>'245', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,560,389,599,389,599,326,560,326,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '244'
$floorItems['244'] = i
TkcText.new(w,579.5,357.5, 'text'=>'244', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,601,389,601,326,643,326,643,389,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '243'
$floorItems['243'] = i
TkcText.new(w,622,357.5, 'text'=>'243', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,688,316,645,316,645,365,688,365,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '242'
$floorItems['242'] = i
TkcText.new(w,666.5,340.5, 'text'=>'242', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,802,367,759,367,759,226,802,226,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = 'Barbecue Deck'
$floorItems['Barbecue Deck'] = i
TkcText.new(w,780.5,296.5, 'text'=>'Barbecue Deck', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,755,262,755,314,717,314,717,262,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '240'
$floorItems['240'] = i
TkcText.new(w,736,288, 'text'=>'240', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,755,316,689,316,689,365,755,365,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '241'
$floorItems['241'] = i
TkcText.new(w,722,340.5, 'text'=>'241', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,755,206,717,206,717,261,755,261,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '239'
$floorItems['239'] = i
TkcText.new(w,736,233.5, 'text'=>'239', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,695,277,643,277,643,206,695,206,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '248'
$floorItems['248'] = i
TkcText.new(w,669,241.5, 'text'=>'248', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,676,135,676,185,724,185,724,135,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '236'
$floorItems['236'] = i
TkcText.new(w,700,160, 'text'=>'236', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,675,135,635,135,635,145,628,145,628,185,675,185,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '235'
$floorItems['235'] = i
TkcText.new(w,651.5,160, 'text'=>'235', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,626,143,633,143,633,135,572,135,
- 572,143,579,143,579,185,626,185,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 572,143,579,143,579,185,626,185,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '234'
$floorItems['234'] = i
TkcText.new(w,606,160, 'text'=>'234', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,557,135,571,135,571,145,578,145,
- 578,185,527,185,527,131,557,131,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 578,185,527,185,527,131,557,131,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '233'
$floorItems['233'] = i
TkcText.new(w,552.5,158, 'text'=>'233', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,476,249,557,249,557,205,476,205,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '230'
$floorItems['230'] = i
TkcText.new(w,516.5,227, 'text'=>'230', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,476,164,486,164,486,131,525,131,525,185,476,185,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '232'
$floorItems['232'] = i
TkcText.new(w,500.5,158, 'text'=>'232', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,476,186,495,186,495,204,476,204,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '229'
$floorItems['229'] = i
TkcText.new(w,485.5,195, 'text'=>'229', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,474,207,409,207,409,187,399,187,399,164,474,164,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '227'
$floorItems['227'] = i
TkcText.new(w,436.5,185.5, 'text'=>'227', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,399,228,399,253,474,253,474,209,409,209,409,228,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '228'
$floorItems['228'] = i
TkcText.new(w,436.5,231, 'text'=>'228', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,397,246,397,226,407,226,407,189,377,189,377,246,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '226'
$floorItems['226'] = i
TkcText.new(w,392,217.5, 'text'=>'226', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,377,169,316,169,316,131,397,131,397,188,377,188,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '225'
$floorItems['225'] = i
TkcText.new(w,356.5,150, 'text'=>'225', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,234,198,306,198,306,249,234,249,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '224'
$floorItems['224'] = i
TkcText.new(w,270,223.5, 'text'=>'224', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,270,179,306,179,306,170,314,170,314,135,270,135,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '223'
$floorItems['223'] = i
TkcText.new(w,292,157, 'text'=>'223', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,268,179,221,179,221,135,268,135,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '222'
$floorItems['222'] = i
TkcText.new(w,244.5,157, 'text'=>'222', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,177,179,219,179,219,135,177,135,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '221'
$floorItems['221'] = i
TkcText.new(w,198,157, 'text'=>'221', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,299,327,349,327,349,284,341,284,341,276,299,276,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '204'
$floorItems['204'] = i
TkcText.new(w,324,301.5, 'text'=>'204', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,234,276,297,276,297,327,257,327,257,338,234,338,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '205'
$floorItems['205'] = i
TkcText.new(w,265.5,307, 'text'=>'205', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,256,385,256,340,212,340,212,385,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '207'
$floorItems['207'] = i
TkcText.new(w,234,362.5, 'text'=>'207', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,210,340,164,340,164,385,210,385,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '208'
$floorItems['208'] = i
TkcText.new(w,187,362.5, 'text'=>'208', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,115,340,162,340,162,385,115,385,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '209'
$floorItems['209'] = i
TkcText.new(w,138.5,362.5, 'text'=>'209', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,89,228,89,156,53,156,53,228,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '217'
$floorItems['217'] = i
TkcText.new(w,71,192, 'text'=>'217', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,89,169,97,169,97,190,89,190,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '217A'
$floorItems['217A'] = i
TkcText.new(w,93,179.5, 'text'=>'217A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,89,156,89,168,95,168,95,135,53,135,53,156,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '216'
$floorItems['216'] = i
TkcText.new(w,71,145.5, 'text'=>'216', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,51,179,51,135,6,135,6,179,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '215'
$floorItems['215'] = i
TkcText.new(w,28.5,157, 'text'=>'215', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,51,227,6,227,6,180,51,180,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '214'
$floorItems['214'] = i
TkcText.new(w,28.5,203.5, 'text'=>'214', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,51,275,6,275,6,229,51,229,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '213'
$floorItems['213'] = i
TkcText.new(w,28.5,252, 'text'=>'213', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,114,340,67,340,67,385,114,385,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '210'
$floorItems['210'] = i
TkcText.new(w,90.5,362.5, 'text'=>'210', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,59,389,59,385,65,385,65,340,1,340,1,389,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '211'
$floorItems['211'] = i
TkcText.new(w,33,364.5, 'text'=>'211', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,393,309,350,309,350,282,342,282,342,276,393,276,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '203'
$floorItems['203'] = i
TkcText.new(w,367.5,292.5, 'text'=>'203', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,99,191,91,191,91,226,174,226,174,198,
- 154,198,154,192,109,192,109,169,99,169,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 154,198,154,192,109,192,109,169,99,169,
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '220'
$floorItems['220'] = i
TkcText.new(w,132.5,208.5, 'text'=>'220', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = 'Priv Lift2'
$floorItems['Priv Lift2'] = i
TkcText.new(w,323,188, 'text'=>'Priv Lift2', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = 'Pub Lift 2'
$floorItems['Pub Lift 2'] = i
TkcText.new(w,323,223, 'text'=>'Pub Lift 2', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,175,168,97,168,97,131,175,131,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '218'
$floorItems['218'] = i
TkcText.new(w,136,149.5, 'text'=>'218', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,154,191,111,191,111,169,154,169,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '219'
$floorItems['219'] = i
TkcText.new(w,132.5,180, 'text'=>'219', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
- 'fill'=>'', 'tags'=>['floor2','room'])
+ 'fill'=>'', 'tags'=>['floor2','room'])
$floorLabels[i.id] = '201'
$floorItems['201'] = i
TkcText.new(w,358,209, 'text'=>'201', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor2','label'])
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
TkcLine.new(w,641,186,678,186, 'fill'=>color, 'tags'=>['floor2','wall'])
TkcLine.new(w,757,350,757,367, 'fill'=>color, 'tags'=>['floor2','wall'])
TkcLine.new(w,634,133,634,144, 'fill'=>color, 'tags'=>['floor2','wall'])
@@ -1271,215 +1272,215 @@ end
# floor (office outlines and numbers).
#
# Arguments:
-# w - The canvas window.
-# color - Color to use for drawing foreground information.
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
def floor_fg3(w,color)
i = TkcPolygon.new(w,89,228,89,180,70,180,70,228,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '316'
$floorItems['316'] = i
TkcText.new(w,79.5,204, 'text'=>'316', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,115,368,162,368,162,323,115,323,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '309'
$floorItems['309'] = i
TkcText.new(w,138.5,345.5, 'text'=>'309', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,164,323,164,368,211,368,211,323,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '308'
$floorItems['308'] = i
TkcText.new(w,187.5,345.5, 'text'=>'308', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,256,368,212,368,212,323,256,323,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '307'
$floorItems['307'] = i
TkcText.new(w,234,345.5, 'text'=>'307', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,244,276,297,276,297,327,260,327,260,321,244,321,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '305'
$floorItems['305'] = i
TkcText.new(w,270.5,301.5, 'text'=>'305', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,251,219,251,203,244,203,244,219,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '324B'
$floorItems['324B'] = i
TkcText.new(w,247.5,211, 'text'=>'324B', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,251,249,244,249,244,232,251,232,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '324A'
$floorItems['324A'] = i
TkcText.new(w,247.5,240.5, 'text'=>'324A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,223,135,223,179,177,179,177,135,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '320'
$floorItems['320'] = i
TkcText.new(w,200,157, 'text'=>'320', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,114,368,114,323,67,323,67,368,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '310'
$floorItems['310'] = i
TkcText.new(w,90.5,345.5, 'text'=>'310', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,23,277,23,321,68,321,68,277,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '312'
$floorItems['312'] = i
TkcText.new(w,45.5,299, 'text'=>'312', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,23,229,68,229,68,275,23,275,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '313'
$floorItems['313'] = i
TkcText.new(w,45.5,252, 'text'=>'313', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,68,227,23,227,23,180,68,180,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '314'
$floorItems['314'] = i
TkcText.new(w,40.5,203.5, 'text'=>'314', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,95,179,95,135,23,135,23,179,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '315'
$floorItems['315'] = i
TkcText.new(w,59,157, 'text'=>'315', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,99,226,99,204,91,204,91,226,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '316B'
$floorItems['316B'] = i
TkcText.new(w,95,215, 'text'=>'316B', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,91,202,99,202,99,180,91,180,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '316A'
$floorItems['316A'] = i
TkcText.new(w,95,191, 'text'=>'316A', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,97,169,109,169,109,192,154,192,154,198,
- 174,198,174,226,101,226,101,179,97,179,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 174,198,174,226,101,226,101,179,97,179,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '319'
$floorItems['319'] = i
TkcText.new(w,141.5,209, 'text'=>'319', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,65,368,58,368,58,389,1,389,1,333,23,333,23,323,65,323,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '311'
$floorItems['311'] = i
TkcText.new(w,29.5,361, 'text'=>'311', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,154,191,111,191,111,169,154,169,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '318'
$floorItems['318'] = i
TkcText.new(w,132.5,180, 'text'=>'318', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,175,168,97,168,97,131,175,131,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '317'
$floorItems['317'] = i
TkcText.new(w,136,149.5, 'text'=>'317', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,274,194,274,221,306,221,306,194,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '323'
$floorItems['323'] = i
TkcText.new(w,290,207.5, 'text'=>'323', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,306,222,274,222,274,249,306,249,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '325'
$floorItems['325'] = i
TkcText.new(w,290,235.5, 'text'=>'325', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,263,179,224,179,224,135,263,135,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '321'
$floorItems['321'] = i
TkcText.new(w,243.5,157, 'text'=>'321', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,314,169,306,169,306,192,273,192,
- 264,181,264,135,314,135,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 264,181,264,135,314,135,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '322'
$floorItems['322'] = i
TkcText.new(w,293.5,163.5, 'text'=>'322', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = 'Pub Lift3'
$floorItems['Pub Lift3'] = i
TkcText.new(w,323,223, 'text'=>'Pub Lift3', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = 'Priv Lift3'
$floorItems['Priv Lift3'] = i
TkcText.new(w,323,188, 'text'=>'Priv Lift3', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,350,284,376,284,376,276,397,276,397,309,350,309,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '303'
$floorItems['303'] = i
TkcText.new(w,373.5,292.5, 'text'=>'303', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,272,203,272,249,252,249,252,230,
- 244,230,244,221,252,221,252,203,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 244,230,244,221,252,221,252,203,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '324'
$floorItems['324'] = i
TkcText.new(w,262,226, 'text'=>'324', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,299,276,299,327,349,327,349,284,341,284,341,276,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '304'
$floorItems['304'] = i
TkcText.new(w,324,301.5, 'text'=>'304', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '301'
$floorItems['301'] = i
TkcText.new(w,358,209, 'text'=>'301', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,397,246,377,246,377,185,397,185,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '327'
$floorItems['327'] = i
TkcText.new(w,387,215.5, 'text'=>'327', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,316,131,316,169,377,169,377,185,397,185,397,131,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '326'
$floorItems['326'] = i
TkcText.new(w,365.5,150, 'text'=>'326', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,308,251,242,251,242,274,342,274,342,282,375, 282,
- 375,274,397,274,397,248,339,248,339,242,308,242,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 375,274,397,274,397,248,339,248,339,242,308,242,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '302'
$floorItems['302'] = i
TkcText.new(w,319.5,261, 'text'=>'302', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
i = TkcPolygon.new(w,70,321,242,321,242,200,259,200,259,203,272,203,
- 272,193,263,180,242,180,175,180,175,169,156,169,
- 156,196,177,196,177,228,107,228,70,228,70,275,107,275,
- 107,248,160,248,160,301,107,301,107,275,70,275,
- 'fill'=>'', 'tags'=>['floor3','room'])
+ 272,193,263,180,242,180,175,180,175,169,156,169,
+ 156,196,177,196,177,228,107,228,70,228,70,275,107,275,
+ 107,248,160,248,160,301,107,301,107,275,70,275,
+ 'fill'=>'', 'tags'=>['floor3','room'])
$floorLabels[i.id] = '306'
$floorItems['306'] = i
TkcText.new(w,200.5,284.5, 'text'=>'306', 'fill'=>color,
- 'anchor'=>'c', 'tags'=>['floor3','label'])
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
TkcLine.new(w,341,275,341,283, 'fill'=>color, 'tags'=>['floor3','wall'])
TkcLine.new(w,162,197,155,197, 'fill'=>color, 'tags'=>['floor3','wall'])
TkcLine.new(w,396,247,399,247, 'fill'=>color, 'tags'=>['floor3','wall'])
@@ -1586,16 +1587,19 @@ $floor_demo = TkToplevel.new {|w|
minsize(100,100)
}
+base_frame = TkFrame.new($floor_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($floor_demo, 'font'=>$font, 'wraplength'=>'8i', 'justify'=>'left',
- 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥Ç¥£¥¸¥¿¥ë¥¨¥¯¥¤¥Ã¥×¥á¥ó¥È¼Ò¤Î¥¦¥§¥¹¥¿¥ó¥ê¥µ¡¼¥Á¥é¥Ü¥é¥È¥ê (DECWRL) ¤Î´Ö¼è¤ê¤¬½ñ¤«¤ì¤¿¥­¥ã¥ó¥Ð¥¹ widget ¤¬Æþ¤Ã¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ï 3³¬·ú¤Æ¤Ç¡¢¾ï¤Ë¤½¤Î¤¦¤Á¤Î1³¬Ê¬¤¬ÁªÂò¡¢¤Ä¤Þ¤ê¤½¤Î´Ö¼è¤ê¤¬É½¼¨¤µ¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£¤¢¤ë³¬¤òÁªÂò¤¹¤ë¤Ë¤Ï¡¢¤½¤Î¾å¤Ç¥Þ¥¦¥¹¤Îº¸¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£¥Þ¥¦¥¹¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤ë³¬¤Î¾å¤òư¤¯¤È¡¢¤½¤Î²¼¤Ë¤¢¤ëÉô²°¤Î¿§¤¬ÊѤï¤ê¡¢Éô²°Èֹ椬¡ÖÉô²°ÈÖ¹æ:¡×¥¨¥ó¥È¥ê¤Ëɽ¼¨¤µ¤ì¤Þ¤¹¡£¤Þ¤¿¡¢¥¨¥ó¥È¥ê¤ËÉô²°ÈÖ¹æ¤ò½ñ¤¯¤È¤½¤ÎÉô²°¤Î¿§¤¬ÊѤï¤ê¤Þ¤¹¡£"){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'8i', 'justify'=>'left',
+ 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥Ç¥£¥¸¥¿¥ë¥¨¥¯¥¤¥Ã¥×¥á¥ó¥È¼Ò¤Î¥¦¥§¥¹¥¿¥ó¥ê¥µ¡¼¥Á¥é¥Ü¥é¥È¥ê (DECWRL) ¤Î´Ö¼è¤ê¤¬½ñ¤«¤ì¤¿¥­¥ã¥ó¥Ð¥¹ widget ¤¬Æþ¤Ã¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ï 3³¬·ú¤Æ¤Ç¡¢¾ï¤Ë¤½¤Î¤¦¤Á¤Î1³¬Ê¬¤¬ÁªÂò¡¢¤Ä¤Þ¤ê¤½¤Î´Ö¼è¤ê¤¬É½¼¨¤µ¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£¤¢¤ë³¬¤òÁªÂò¤¹¤ë¤Ë¤Ï¡¢¤½¤Î¾å¤Ç¥Þ¥¦¥¹¤Îº¸¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£¥Þ¥¦¥¹¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤ë³¬¤Î¾å¤òư¤¯¤È¡¢¤½¤Î²¼¤Ë¤¢¤ëÉô²°¤Î¿§¤¬ÊѤï¤ê¡¢Éô²°Èֹ椬¡ÖÉô²°ÈÖ¹æ:¡×¥¨¥ó¥È¥ê¤Ëɽ¼¨¤µ¤ì¤Þ¤¹¡£¤Þ¤¿¡¢¥¨¥ó¥È¥ê¤ËÉô²°ÈÖ¹æ¤ò½ñ¤¯¤È¤½¤ÎÉô²°¤Î¿§¤¬ÊѤï¤ê¤Þ¤¹¡£"){
pack('side'=>'top')
}
# frame À¸À®
-$floor_buttons = TkFrame.new($floor_demo) {|frame|
+$floor_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $floor_demo
$floor_demo = nil
@@ -1616,17 +1620,17 @@ $floorItems = {}
# canvas ÀßÄê
if $tk_version =~ /^4\.[01]/
- $floor_canvas_frame = TkFrame.new($floor_demo,'bd'=>2,'relief'=>'sunken',
- 'highlightthickness'=>2)
+ $floor_canvas_frame = TkFrame.new(base_frame,'bd'=>2,'relief'=>'sunken',
+ 'highlightthickness'=>2)
$floor_canvas = TkCanvas.new($floor_canvas_frame,
- 'width'=>900, 'height'=>500, 'borderwidth'=>0,
- 'highlightthickness'=>0) {|c|
- TkScrollbar.new($floor_demo, 'orient'=>'horiz',
- 'command'=>proc{|*args| c.xview(*args)}){|hs|
+ 'width'=>900, 'height'=>500, 'borderwidth'=>0,
+ 'highlightthickness'=>0) {|c|
+ TkScrollbar.new(base_frame, 'orient'=>'horiz',
+ 'command'=>proc{|*args| c.xview(*args)}){|hs|
c.xscrollcommand(proc{|first,last| hs.set first,last})
pack('side'=>'bottom', 'fill'=>'x')
}
- TkScrollbar.new($floor_demo, 'command'=>proc{|*args| c.yview(*args)}){|vs|
+ TkScrollbar.new(base_frame, 'command'=>proc{|*args| c.yview(*args)}){|vs|
c.yscrollcommand(proc{|first,last| vs.set first,last})
pack('side'=>'right', 'fill'=>'y')
}
@@ -1635,7 +1639,7 @@ if $tk_version =~ /^4\.[01]/
$floor_canvas.pack('expand'=>'yes', 'fill'=>'both')
else
- TkFrame.new($floor_demo) {|f|
+ TkFrame.new(base_frame) {|f|
pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes')
h = TkScrollbar.new(f, 'highlightthickness'=>0, 'orient'=>'horizontal')
@@ -1643,28 +1647,28 @@ else
TkFrame.new(f, 'bd'=>2, 'relief'=>'sunken') {|f1|
$floor_canvas = TkCanvas.new(f1, 'width'=>900, 'height'=>500,
- 'borderwidth'=>0,
- 'highlightthickness'=>0) {
- xscrollcommand(proc{|first,last| h.set first,last})
- yscrollcommand(proc{|first,last| v.set first,last})
- pack('expand'=>'yes', 'fill'=>'both')
+ 'borderwidth'=>0,
+ 'highlightthickness'=>0) {
+ xscrollcommand(proc{|first,last| h.set first,last})
+ yscrollcommand(proc{|first,last| v.set first,last})
+ pack('expand'=>'yes', 'fill'=>'both')
}
grid('padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
}
v.grid('padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
h.grid('padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
TkGrid.rowconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
TkGrid.columnconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
- v.command(proc{|*args| c.yview(*args)})
- h.command(proc{|*args| c.xview(*args)})
+ v.command(proc{|*args| $floor_canvas.yview(*args)})
+ h.command(proc{|*args| $floor_canvas.xview(*args)})
}
end
@@ -1673,7 +1677,7 @@ end
$currentRoom = TkVariable.new
$floor_entry = TkEntry.new($floor_canvas, 'width'=>10, 'relief'=>'sunken',
- 'bd'=>2, 'textvariable'=>$currentRoom)
+ 'bd'=>2, 'textvariable'=>$currentRoom)
# Choose colors, then fill in the floorplan.
@@ -1710,7 +1714,7 @@ $floor_canvas.itembind('room', 'Enter', proc{newRoom $floor_canvas})
$floor_canvas.itembind('room', 'Leave', proc{$currentRoom.value = ''})
$floor_canvas.bind('2', proc{|x,y| $floor_canvas.scan_mark x,y}, '%x %y')
$floor_canvas.bind('B2-Motion',
- proc{|x,y| $floor_canvas.scan_dragto x,y}, '%x %y')
+ proc{|x,y| $floor_canvas.scan_dragto x,y}, '%x %y')
$floor_canvas.bind('Destroy', proc{$currentRoom.unset})
$currentRoom.value = ''
$currentRoom.trace('w',proc{roomChanged $floor_canvas})
diff --git a/ext/tk/sample/demos-jp/floor2.rb b/ext/tk/sample/demos-jp/floor2.rb
new file mode 100644
index 0000000000..d4381c5543
--- /dev/null
+++ b/ext/tk/sample/demos-jp/floor2.rb
@@ -0,0 +1,1719 @@
+# -*- coding: euc-jp -*-
+#
+# floorDisplay widget demo 2 (called by 'widget')
+#
+
+# floorDisplay2 --
+# Recreate the floorplan display in the canvas given by "w". The
+# floor given by "active" is displayed on top with its office structure
+# visible.
+#
+# Arguments:
+# w - Name of the canvas window.
+# active - Number of active floor (1, 2, or 3).
+
+def floorDisplay2(w,active)
+ return if $activeFloor2 == active
+
+ w.delete('all')
+ $activeFloor2 = active
+
+ # First go through the three floors, displaying the backgrounds for
+ # each floor.
+
+ floor2_bg1(w,$floor2_colors['bg1'],$floor2_colors['outline1'])
+ floor2_bg2(w,$floor2_colors['bg2'],$floor2_colors['outline2'])
+ floor2_bg3(w,$floor2_colors['bg3'],$floor2_colors['outline3'])
+
+ # Raise the background for the active floor so that it's on top.
+
+ w.raise("floor#{active}")
+
+ # Create a dummy item just to mark this point in the display list,
+ # so we can insert highlights here.
+
+ w.create(TkcRectangle,0,100,1,101,'fill'=>'','outline'=>'','tags'=>'marker')
+
+ # Add the walls and labels for the active floor, along with
+ # transparent polygons that define the rooms on the floor.
+ # Make sure that the room polygons are on top.
+
+ $floorLabels2.clear
+ $floorItems2.clear
+ send("floor2_fg#{active}", w, $floor2_colors['offices'])
+ w.raise('room')
+
+ # Offset the floors diagonally from each other.
+
+ w.move('floor1', '2c', '2c')
+ w.move('floor2', '1c', '1c')
+
+ # Create items for the room entry and its label.
+ w.create(TkcWindow, 600, 100, 'anchor'=>'w', 'window'=>$floor2_entry)
+ w.create(TkcText, 600, 100, 'anchor'=>'e', 'text'=>"Éô²°ÈÖ¹æ: ")
+ w['scrollregion'] = w.bbox('all')
+end
+
+# newRoom2 --
+# This method is invoked whenever the mouse enters a room
+# in the floorplan. It changes tags so that the current room is
+# highlighted.
+#
+# Arguments:
+# w - The name of the canvas window.
+
+def newRoom2(w)
+ id = w.find_withtag('current')[0]
+ $currentRoom2.value = $floorLabels2[id.id] if id != ""
+ Tk.update(true)
+end
+
+# roomChanged2 --
+# This method is invoked whenever the currentRoom variable changes.
+# It highlights the current room and unhighlights any previous room.
+#
+# Arguments:
+# w - The canvas window displaying the floorplan.
+# args - Not used.
+
+def roomChanged2(w,*args)
+ w.delete('highlight')
+ item = $floorItems2[$currentRoom2.value]
+ return if item == nil
+ new = TkcPolygon.new(w, *(w.coords(item)))
+ new.configure('fill'=>$floor2_colors['active'], 'tags'=>'highlight')
+ w.raise(new, 'marker')
+end
+
+# floor2_bg1 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the background information for the first
+# floor.
+#
+# Arguments:
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
+
+def floor2_bg1(w,fill,outline)
+ w.create(TkcPolygon,347,80,349,82,351,84,353,85,363,92,375,99,386,104,
+ 386,129,398,129,398,162,484,162,484,129,559,129,559,133,725,
+ 133,725,129,802,129,802,389,644,389,644,391,559,391,559,327,
+ 508,327,508,311,484,311,484,278,395,278,395,288,400,288,404,
+ 288,409,290,413,292,418,297,421,302,422,309,421,318,417,325,
+ 411,330,405,332,397,333,344,333,340,334,336,336,335,338,332,
+ 342,331,347,332,351,334,354,336,357,341,359,340,360,335,363,
+ 331,365,326,366,304,366,304,355,258,355,258,387,60,387,60,391,
+ 0,391,0,337,3,337,3,114,8,114,8,25,30,25,30,5,93,5,98,5,104,7,
+ 110,10,116,16,119,20,122,28,123,32,123,68,220,68,220,34,221,
+ 22,223,17,227,13,231,8,236,4,242,2,246,0,260,0,283,1,300,5,
+ 321,14,335,22,348,25,365,29,363,39,358,48,352,56,337,70,
+ 344,76,347,80, 'tags'=>['floor1','bg'], 'fill'=>fill)
+ w.create(TkcLine,386,129,398,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,258,355,258,387, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,60,387,60,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,0,337,0,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,3,114,3,337, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,258,387,60,387, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,162,398,162, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,398,162,398,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,278,484,311, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,311,508,311, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,508,327,508,311, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,559,327,508,327, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,644,391,559,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,644,389,644,391, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,559,129,484,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,162,484,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,725,133,559,133, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,559,129,559,133, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,725,129,802,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,802,389,802,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,3,337,0,337, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,559,391,559,327, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,802,389,644,389, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,725,133,725,129, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,8,25,8,114, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,8,114,3,114, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,30,25,8,25, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,484,278,395,278, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,30,25,30,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,93,5,30,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,98,5,93,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,104,7,98,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,110,10,104,7, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,116,16,110,10, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,119,20,116,16, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,122,28,119,20, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,123,32,122,28, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,123,68,123,32, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,220,68,123,68, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,386,129,386,104, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,386,104,375,99, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,375,99,363,92, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,353,85,363,92, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,220,68,220,34, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,337,70,352,56, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,352,56,358,48, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,358,48,363,39, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,363,39,365,29, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,365,29,348,25, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,348,25,335,22, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,335,22,321,14, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,321,14,300,5, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,300,5,283,1, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,283,1,260,0, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,260,0,246,0, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,246,0,242,2, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,242,2,236,4, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,236,4,231,8, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,231,8,227,13, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,223,17,227,13, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,221,22,223,17, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,220,34,221,22, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,340,360,335,363, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,335,363,331,365, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,331,365,326,366, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,326,366,304,366, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,304,355,304,366, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,395,288,400,288, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,404,288,400,288, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,409,290,404,288, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,413,292,409,290, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,418,297,413,292, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,421,302,418,297, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,422,309,421,302, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,421,318,422,309, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,421,318,417,325, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,417,325,411,330, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,411,330,405,332, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,405,332,397,333, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,397,333,344,333, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,344,333,340,334, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,340,334,336,336, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,336,336,335,338, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,335,338,332,342, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,331,347,332,342, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,332,351,331,347, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,334,354,332,351, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,336,357,334,354, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,341,359,336,357, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,341,359,340,360, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,395,288,395,278, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,304,355,258,355, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,347,80,344,76, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,344,76,337,70, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,349,82,347,80, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,351,84,349,82, 'fill'=>outline, 'tags'=>['floor1','bg'])
+ w.create(TkcLine,353,85,351,84, 'fill'=>outline, 'tags'=>['floor1','bg'])
+end
+
+# floor2_bg2 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the background information for the first
+# floor.
+#
+# Arguments:
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
+
+def floor2_bg2(w,fill,outline)
+ w.create(TkcPolygon,559,129,484,129,484,162,398,162,398,129,315,129,
+ 315,133,176,133,176,129,96,129,96,133,3,133,3,339,0,339,0,391,
+ 60,391,60,387,258,387,258,329,350,329,350,311,395,311,395,280,
+ 484,280,484,311,508,311,508,327,558,327,558,391,644,391,644,
+ 367,802,367,802,129,725,129,725,133,559,133,559,129,
+ 'tags'=>['floor2','bg'], 'fill'=>fill)
+ w.create(TkcLine,350,311,350,329, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,398,129,398,162, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,802,367,802,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,802,129,725,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,725,133,725,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,559,129,559,133, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,559,133,725,133, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,484,162,484,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,559,129,484,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,802,367,644,367, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,644,367,644,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,644,391,558,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,558,327,558,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,558,327,508,327, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,508,327,508,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,484,311,508,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,484,280,484,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,398,162,484,162, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,484,280,395,280, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,395,280,395,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,258,387,60,387, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,3,133,3,339, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,3,339,0,339, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,0,339,0,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,60,387,60,391, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,258,329,258,387, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,350,329,258,329, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,395,311,350,311, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,398,129,315,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,176,133,315,133, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,176,129,96,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,3,133,96,133, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,315,133,315,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,176,133,176,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+ w.create(TkcLine,96,133,96,129, 'fill'=>outline, 'tags'=>['floor2','bg'])
+end
+
+# floor2_bg3 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the background information for the first
+# floor.
+#
+# Arguments:
+# w - The canvas window.
+# fill - Fill color to use for the floor's background.
+# outline - Color to use for the floor's outline.
+
+def floor2_bg3(w,fill,outline)
+ w.create(TkcPolygon,159,300,107,300,107,248,159,248,159,129,96,129,96,
+ 133,21,133,21,331,0,331,0,391,60,391,60,370,159,370,159,300,
+ 'tags'=>['floor3','bg'], 'fill'=>fill)
+ w.create(TkcPolygon,258,370,258,329,350,329,350,311,399,311,399,129,
+ 315,129,315,133,176,133,176,129,159,129,159,370,258,370,
+ 'tags'=>['floor3','bg'], 'fill'=>fill)
+ w.create(TkcLine,96,133,96,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,176,129,96,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,176,129,176,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,315,133,176,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,315,133,315,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,399,129,315,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,399,311,399,129, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,399,311,350,311, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,350,329,350,311, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,350,329,258,329, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,258,370,258,329, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,60,370,258,370, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,60,370,60,391, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,0,391,0,331, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,21,331,0,331, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,21,331,21,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,96,133,21,133, 'fill'=>outline, 'tags'=>['floor3','bg'])
+ w.create(TkcLine,107,300,159,300,159,248,107,248,107,300,
+ 'fill'=>outline, 'tags'=>['floor3','bg'])
+end
+
+# floor2_fg1 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the foreground information for the first
+# floor (office outlines and numbers).
+#
+# Arguments:
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
+
+def floor2_fg1(w,color)
+ i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '101'
+ $floorItems2['101'] = i
+ w.create(TkcText,358,209, 'text'=>'101', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Pub Lift1'
+ $floorItems2['Pub Lift1'] = i
+ w.create(TkcText,323,223, 'text'=>'Pub Lift1', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Priv Lift1'
+ $floorItems2['Priv Lift1'] = i
+ w.create(TkcText,323,188, 'text'=>'Priv Lift1', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,42,389,42,337,1,337,1,389,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '110'
+ $floorItems2['110'] = i
+ w.create(TkcText,21.5,363, 'text'=>'110', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,59,389,59,385,90,385,90,337,44,337,44,389,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '109'
+ $floorItems2['109'] = i
+ w.create(TkcText,67,363, 'text'=>'109', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,51,300,51,253,6,253,6,300,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '111'
+ $floorItems2['111'] = i
+ w.create(TkcText,28.5,276.5, 'text'=>'111', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,98,248,98,309,79,309,79,248,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '117B'
+ $floorItems2['117B'] = i
+ w.create(TkcText,88.5,278.5, 'text'=>'117B', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,51,251,51,204,6,204,6,251,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '112'
+ $floorItems2['112'] = i
+ w.create(TkcText,28.5,227.5, 'text'=>'112', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,6,156,51,156,51,203,6,203,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '113'
+ $floorItems2['113'] = i
+ w.create(TkcText,28.5,179.5, 'text'=>'113', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,85,169,79,169,79,192,85,192,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '117A'
+ $floorItems2['117A'] = i
+ w.create(TkcText,82,180.5, 'text'=>'117A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,77,302,77,168,53,168,53,302,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '117'
+ $floorItems2['117'] = i
+ w.create(TkcText,65,235, 'text'=>'117', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,51,155,51,115,6,115,6,155,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '114'
+ $floorItems2['114'] = i
+ w.create(TkcText,28.5,135, 'text'=>'114', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,95,115,53,115,53,168,95,168,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '115'
+ $floorItems2['115'] = i
+ w.create(TkcText,74,141.5, 'text'=>'115', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,87,113,87,27,10,27,10,113,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '116'
+ $floorItems2['116'] = i
+ w.create(TkcText,48.5,70, 'text'=>'116', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,89,91,128,91,128,113,89,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '118'
+ $floorItems2['118'] = i
+ w.create(TkcText,108.5,102, 'text'=>'118', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,178,128,178,132,216,132,216,91,
+ 163,91,163,112,149,112,149,128,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '120'
+ $floorItems2['120'] = i
+ w.create(TkcText,189.5,111.5, 'text'=>'120', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,79,193,87,193,87,169,136,169,136,192,
+ 156,192,156,169,175,169,175,246,79,246,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '122'
+ $floorItems2['122'] = i
+ w.create(TkcText,131,207.5, 'text'=>'122', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,138,169,154,169,154,191,138,191,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '121'
+ $floorItems2['121'] = i
+ w.create(TkcText,146,180, 'text'=>'121', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,99,300,126,300,126,309,99,309,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '106A'
+ $floorItems2['106A'] = i
+ w.create(TkcText,112.5,304.5, 'text'=>'106A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,128,299,128,309,150,309,150,248,99,248,99,299,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '105'
+ $floorItems2['105'] = i
+ w.create(TkcText,124.5,278.5, 'text'=>'105', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,174,309,174,300,152,300,152,309,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '106B'
+ $floorItems2['106B'] = i
+ w.create(TkcText,163,304.5, 'text'=>'106B', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,176,299,176,309,216,309,216,248,152,248,152,299,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '104'
+ $floorItems2['104'] = i
+ w.create(TkcText,184,278.5, 'text'=>'104', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,138,385,138,337,91,337,91,385,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '108'
+ $floorItems2['108'] = i
+ w.create(TkcText,114.5,361, 'text'=>'108', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,256,337,140,337,140,385,256,385,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '107'
+ $floorItems2['107'] = i
+ w.create(TkcText,198,361, 'text'=>'107', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,300,353,300,329,260,329,260,353,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Smoking'
+ $floorItems2['Smoking'] = i
+ w.create(TkcText,280,341, 'text'=>'Smoking', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,314,135,314,170,306,170,306,246,177,246,177,135,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '123'
+ $floorItems2['123'] = i
+ w.create(TkcText,245.5,190.5, 'text'=>'123', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,217,248,301,248,301,326,257,326,257,310,217,310,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '103'
+ $floorItems2['103'] = i
+ w.create(TkcText,259,287, 'text'=>'103', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,396,188,377,188,377,169,316,169,316,131,396,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '124'
+ $floorItems2['124'] = i
+ w.create(TkcText,356,150, 'text'=>'124', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,397,226,407,226,407,189,377,189,377,246,397,246,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '125'
+ $floorItems2['125'] = i
+ w.create(TkcText,392,217.5, 'text'=>'125', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,399,187,409,187,409,207,474,207,474,164,399,164,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '126'
+ $floorItems2['126'] = i
+ w.create(TkcText,436.5,185.5, 'text'=>'126', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,409,209,409,229,399,229,399,253,
+ 486,253,486,239,474,239,474,209,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '127'
+ $floorItems2['127'] = i
+ w.create(TkcText,436.5,'231', 'text'=>'127', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,501,164,501,174,495,174,495,188,
+ 490,188,490,204,476,204,476,164,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'MShower'
+ $floorItems2['MShower'] = i
+ w.create(TkcText,488.5,'184', 'text'=>'MShower', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,497,176,513,176,513,204,492,204,492,190,497,190,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Closet'
+ $floorItems2['Closet'] = i
+ w.create(TkcText,502.5,190, 'text'=>'Closet', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,476,237,476,206,513,206,513,254,488,254,488,237,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'WShower'
+ $floorItems2['WShower'] = i
+ w.create(TkcText,494.5,230, 'text'=>'WShower', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,486,131,558,131,558,135,724,135,724,166,
+ 697,166,697,275,553,275,531,254,515,254,
+ 515,174,503,174,503,161,486,161,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '130'
+ $floorItems2['130'] = i
+ w.create(TkcText,638.5,205, 'text'=>'130', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,308,242,339,242,339,248,342,248,
+ 342,246,397,246,397,276,393,276,
+ 393,309,300,309,300,248,308,248,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '102'
+ $floorItems2['102'] = i
+ w.create(TkcText,367.5,278.5, 'text'=>'102', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,397,255,486,255,486,276,397,276,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '128'
+ $floorItems2['128'] = i
+ w.create(TkcText,441.5,265.5, 'text'=>'128', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,510,309,486,309,486,255,530,255,
+ 552,277,561,277,561,325,510,325,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '129'
+ $floorItems2['129'] = i
+ w.create(TkcText,535.5,293, 'text'=>'129', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,696,281,740,281,740,387,642,387,
+ 642,389,561,389,561,277,696,277,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '133'
+ $floorItems2['133'] = i
+ w.create(TkcText,628.5,335, 'text'=>'133', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,742,387,742,281,800,281,800,387,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '132'
+ $floorItems2['132'] = i
+ w.create(TkcText,771,334, 'text'=>'132', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,800,168,800,280,699,280,699,168,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '134'
+ $floorItems2['134'] = i
+ w.create(TkcText,749.5,224, 'text'=>'134', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,726,131,726,166,800,166,800,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '135'
+ $floorItems2['135'] = i
+ w.create(TkcText,763,148.5, 'text'=>'135', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,340,360,335,363,331,365,326,366,304,366,
+ 304,312,396,312,396,288,400,288,404,288,
+ 409,290,413,292,418,297,421,302,422,309,
+ 421,318,417,325,411,330,405,332,397,333,
+ 344,333,340,334,336,336,335,338,332,342,
+ 331,347,332,351,334,354,336,357,341,359,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Ramona Stair'
+ $floorItems2['Ramona Stair'] = i
+ w.create(TkcText,368,323, 'text'=>'Ramona Stair', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,30,23,30,5,93,5,98,5,104,7,110,10,116,16,119,20,
+ 122,28,123,32,123,68,220,68,220,87,90,87,90,23,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'University Stair'
+ $floorItems2['University Stair'] = i
+ w.create(TkcText,155,77.5, 'text'=>'University Stair', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,282,37,295,40,312,49,323,56,337,70,352,56,
+ 358,48,363,39,365,29,348,25,335,22,321,14,
+ 300,5,283,1,260,0,246,0,242,2,236,4,231,8,
+ 227,13,223,17,221,22,220,34,260,34,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Plaza Stair'
+ $floorItems2['Plaza Stair'] = i
+ w.create(TkcText,317.5,28.5, 'text'=>'Plaza Stair', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,220,34,260,34,282,37,295,40,312,49,
+ 323,56,337,70,350,83,365,94,377,100,
+ 386,104,386,128,220,128,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = 'Plaza Deck'
+ $floorItems2['Plaza Deck'] = i
+ w.create(TkcText,303,81, 'text'=>'Plaza Deck', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,257,336,77,336,6,336,6,301,77,301,77,310,257,310,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '106'
+ $floorItems2['106'] = i
+ w.create(TkcText,131.5,318.5, 'text'=>'106', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ i = TkcPolygon.new(w,146,110,162,110,162,91,130,91,130,115,95,115,
+ 95,128,114,128,114,151,157,151,157,153,112,153,
+ 112,130,97,130,97,168,175,168,175,131,146,131,
+ 'fill'=>'', 'tags'=>['floor1','room'])
+ $floorLabels2[i.id] = '119'
+ $floorItems2['119'] = i
+ w.create(TkcText,143.5,133, 'text'=>'119', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor1','label'])
+ w.create(TkcLine,155,191,155,189, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,155,177,155,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,96,129,96,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,169,176,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,176,247,176,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,206,307,206, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,187,340,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,210,340,201, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,247,340,224, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,340,241,307,241, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,376,246,376,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,307,247,307,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,376,170,307,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,315,129,315,170, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,147,129,176,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,202,133,176,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,398,129,315,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,352,258,387, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,60,387,60,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,0,337,0,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,3,114,3,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,387,60,387, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,237,52,273, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,189,52,225, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,140,52,177, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,395,306,395,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,531,254,398,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,475,178,475,238, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,502,162,398,162, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,398,129,398,188, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,383,188,376,188, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,188,408,194, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,398,227,398,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,227,398,227, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,222,408,227, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,206,408,210, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,408,208,475,208, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,484,278,484,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,484,311,508,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,508,327,508,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,559,327,508,327, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,644,391,559,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,644,389,644,391, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,514,205,475,205, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,496,189,496,187, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,559,129,484,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,484,162,484,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,725,133,559,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,559,129,559,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,725,149,725,167, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,725,129,802,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,802,389,802,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,739,167,802,167, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,396,188,408,188, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,0,337,9,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,58,337,21,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,43,391,43,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,105,337,75,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,91,387,91,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,154,337,117,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,139,387,139,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,227,337,166,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,337,251,337, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,328,302,328, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,302,355,302,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,395,311,302,311, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,484,278,395,278, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,395,294,395,278, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,473,278,473,275, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,473,256,473,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,533,257,531,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,553,276,551,274, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,698,276,553,276, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,559,391,559,327, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,802,389,644,389, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,741,314,741,389, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,698,280,698,167, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,707,280,698,280, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,802,280,731,280, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,741,280,741,302, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,698,167,727,167, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,725,137,725,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,514,254,514,175, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,496,175,514,175, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,502,175,502,162, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,475,166,475,162, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,496,176,496,175, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,491,189,496,189, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,491,205,491,189, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,487,238,475,238, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,487,240,487,238, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,487,252,487,254, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,315,133,304,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,256,133,280,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,247,270,247, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,307,247,294,247, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,214,133,232,133, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,217,247,217,266, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,217,309,217,291, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,217,309,172,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,154,309,148,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,175,300,175,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,151,300,175,300, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,151,247,151,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,237,78,265, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,286,78,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,106,309,78,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,130,309,125,309, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,99,309,99,247, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,127,299,99,299, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,127,309,127,299, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,155,191,137,191, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,137,169,137,191, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,171,78,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,78,190,78,218, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,86,192,86,169, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,86,192,78,192, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,301,3,301, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,286,52,301, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,252,3,252, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,203,3,203, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,3,156,52,156, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,8,25,8,114, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,63,114,3,114, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,75,114,97,114, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,108,114,129,114, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,129,114,129,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,52,114,52,128, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,132,89,88,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,88,25,88,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,88,114,88,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,218,89,144,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,147,111,147,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,162,111,147,111, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,162,109,162,111, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,162,96,162,89, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,218,89,218,94, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,218,89,218,119, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,8,25,88,25, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,258,337,258,328, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,113,129,96,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,302,355,258,355, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,386,104,386,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,377,100,386,104, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,365,94,377,100, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,350,83,365,94, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,337,70,350,83, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,337,70,323,56, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,312,49,323,56, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,295,40,312,49, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,282,37,295,40, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,260,34,282,37, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,253,34,260,34, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,386,128,386,104, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,113,152,156,152, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,113,152,156,152, 'fill'=>color, 'tags'=>['floor1','wall'])
+ w.create(TkcLine,113,152,113,129, 'fill'=>color, 'tags'=>['floor1','wall'])
+end
+
+# floor2_fg2 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the foreground information for the second
+# floor (office outlines and numbers).
+#
+# Arguments:
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
+
+def floor2_fg2(w,color)
+ i = TkcPolygon.new(w,748,188,755,188,755,205,758,205,758,222,
+ 800,222,800,168,748,168,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '238'
+ $floorItems2['238'] = i
+ w.create(TkcText,774,195, 'text'=>'238', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,726,188,746,188,746,166,800,166,800,131,726,131,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '237'
+ $floorItems2['237'] = i
+ w.create(TkcText,763,148.5, 'text'=>'237', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,497,187,497,204,559,204,559,324,641,324,
+ 643,324,643,291,641,291,641,205,696,205,
+ 696,291,694,291,694,314,715,314,715,291,
+ 715,205,755,205,755,190,724,190,724,187,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '246'
+ $floorItems2['246'] = i
+ w.create(TkcText,600,264, 'text'=>'246', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,694,279,643,279,643,314,694,314,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '247'
+ $floorItems2['247'] = i
+ w.create(TkcText,668.5,296.5, 'text'=>'247', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,232,250,308,250,308,242,339,242,339,246,
+ 397,246,397,255,476,255,476,250,482,250,559,250,
+ 559,274,482,274,482,278,396,278,396,274,232,274,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '202'
+ $floorItems2['202'] = i
+ w.create(TkcText,285.5,260, 'text'=>'202', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,53,228,53,338,176,338,233,338,233,196,
+ 306,196,306,180,175,180,175,169,156,169,
+ 156,196,176,196,176,228,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '206'
+ $floorItems2['206'] = i
+ w.create(TkcText,143,267, 'text'=>'206', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,51,277,6,277,6,338,51,338,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '212'
+ $floorItems2['212'] = i
+ w.create(TkcText,28.5,307.5, 'text'=>'212', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,557,276,486,276,486,309,510,309,510,325,557,325,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '245'
+ $floorItems2['245'] = i
+ w.create(TkcText,521.5,300.5, 'text'=>'245', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,560,389,599,389,599,326,560,326,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '244'
+ $floorItems2['244'] = i
+ w.create(TkcText,579.5,357.5, 'text'=>'244', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,601,389,601,326,643,326,643,389,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '243'
+ $floorItems2['243'] = i
+ w.create(TkcText,622,357.5, 'text'=>'243', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,688,316,645,316,645,365,688,365,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '242'
+ $floorItems2['242'] = i
+ w.create(TkcText,666.5,340.5, 'text'=>'242', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,802,367,759,367,759,226,802,226,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = 'Barbecue Deck'
+ $floorItems2['Barbecue Deck'] = i
+ w.create(TkcText,780.5,296.5, 'text'=>'Barbecue Deck', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,755,262,755,314,717,314,717,262,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '240'
+ $floorItems2['240'] = i
+ w.create(TkcText,736,288, 'text'=>'240', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,755,316,689,316,689,365,755,365,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '241'
+ $floorItems2['241'] = i
+ w.create(TkcText,722,340.5, 'text'=>'241', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,755,206,717,206,717,261,755,261,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '239'
+ $floorItems2['239'] = i
+ w.create(TkcText,736,233.5, 'text'=>'239', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,695,277,643,277,643,206,695,206,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '248'
+ $floorItems2['248'] = i
+ w.create(TkcText,669,241.5, 'text'=>'248', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,676,135,676,185,724,185,724,135,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '236'
+ $floorItems2['236'] = i
+ w.create(TkcText,700,160, 'text'=>'236', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,675,135,635,135,635,145,628,145,628,185,675,185,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '235'
+ $floorItems2['235'] = i
+ w.create(TkcText,651.5,160, 'text'=>'235', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,626,143,633,143,633,135,572,135,
+ 572,143,579,143,579,185,626,185,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '234'
+ $floorItems2['234'] = i
+ w.create(TkcText,606,160, 'text'=>'234', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,557,135,571,135,571,145,578,145,
+ 578,185,527,185,527,131,557,131,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '233'
+ $floorItems2['233'] = i
+ w.create(TkcText,552.5,158, 'text'=>'233', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,476,249,557,249,557,205,476,205,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '230'
+ $floorItems2['230'] = i
+ w.create(TkcText,516.5,227, 'text'=>'230', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,476,164,486,164,486,131,525,131,525,185,476,185,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '232'
+ $floorItems2['232'] = i
+ w.create(TkcText,500.5,158, 'text'=>'232', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,476,186,495,186,495,204,476,204,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '229'
+ $floorItems2['229'] = i
+ w.create(TkcText,485.5,195, 'text'=>'229', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,474,207,409,207,409,187,399,187,399,164,474,164,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '227'
+ $floorItems2['227'] = i
+ w.create(TkcText,436.5,185.5, 'text'=>'227', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,399,228,399,253,474,253,474,209,409,209,409,228,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '228'
+ $floorItems2['228'] = i
+ w.create(TkcText,436.5,231, 'text'=>'228', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,397,246,397,226,407,226,407,189,377,189,377,246,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '226'
+ $floorItems2['226'] = i
+ w.create(TkcText,392,217.5, 'text'=>'226', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,377,169,316,169,316,131,397,131,397,188,377,188,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '225'
+ $floorItems2['225'] = i
+ w.create(TkcText,356.5,150, 'text'=>'225', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,234,198,306,198,306,249,234,249,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '224'
+ $floorItems2['224'] = i
+ w.create(TkcText,270,223.5, 'text'=>'224', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,270,179,306,179,306,170,314,170,314,135,270,135,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '223'
+ $floorItems2['223'] = i
+ w.create(TkcText,292,157, 'text'=>'223', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,268,179,221,179,221,135,268,135,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '222'
+ $floorItems2['222'] = i
+ w.create(TkcText,244.5,157, 'text'=>'222', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,177,179,219,179,219,135,177,135,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '221'
+ $floorItems2['221'] = i
+ w.create(TkcText,198,157, 'text'=>'221', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,299,327,349,327,349,284,341,284,341,276,299,276,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '204'
+ $floorItems2['204'] = i
+ w.create(TkcText,324,301.5, 'text'=>'204', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,234,276,297,276,297,327,257,327,257,338,234,338,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '205'
+ $floorItems2['205'] = i
+ w.create(TkcText,265.5,307, 'text'=>'205', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,256,385,256,340,212,340,212,385,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '207'
+ $floorItems2['207'] = i
+ w.create(TkcText,234,362.5, 'text'=>'207', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,210,340,164,340,164,385,210,385,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '208'
+ $floorItems2['208'] = i
+ w.create(TkcText,187,362.5, 'text'=>'208', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,115,340,162,340,162,385,115,385,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '209'
+ $floorItems2['209'] = i
+ w.create(TkcText,138.5,362.5, 'text'=>'209', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,89,228,89,156,53,156,53,228,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '217'
+ $floorItems2['217'] = i
+ w.create(TkcText,71,192, 'text'=>'217', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,89,169,97,169,97,190,89,190,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '217A'
+ $floorItems2['217A'] = i
+ w.create(TkcText,93,179.5, 'text'=>'217A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,89,156,89,168,95,168,95,135,53,135,53,156,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '216'
+ $floorItems2['216'] = i
+ w.create(TkcText,71,145.5, 'text'=>'216', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,51,179,51,135,6,135,6,179,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '215'
+ $floorItems2['215'] = i
+ w.create(TkcText,28.5,157, 'text'=>'215', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,51,227,6,227,6,180,51,180,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '214'
+ $floorItems2['214'] = i
+ w.create(TkcText,28.5,203.5, 'text'=>'214', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,51,275,6,275,6,229,51,229,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '213'
+ $floorItems2['213'] = i
+ w.create(TkcText,28.5,252, 'text'=>'213', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,114,340,67,340,67,385,114,385,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '210'
+ $floorItems2['210'] = i
+ w.create(TkcText,90.5,362.5, 'text'=>'210', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,59,389,59,385,65,385,65,340,1,340,1,389,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '211'
+ $floorItems2['211'] = i
+ w.create(TkcText,33,364.5, 'text'=>'211', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,393,309,350,309,350,282,342,282,342,276,393,276,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '203'
+ $floorItems2['203'] = i
+ w.create(TkcText,367.5,292.5, 'text'=>'203', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,99,191,91,191,91,226,174,226,174,198,
+ 154,198,154,192,109,192,109,169,99,169,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '220'
+ $floorItems2['220'] = i
+ w.create(TkcText,132.5,208.5, 'text'=>'220', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = 'Priv Lift2'
+ $floorItems2['Priv Lift2'] = i
+ w.create(TkcText,323,188, 'text'=>'Priv Lift2', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = 'Pub Lift 2'
+ $floorItems2['Pub Lift 2'] = i
+ w.create(TkcText,323,223, 'text'=>'Pub Lift 2', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,175,168,97,168,97,131,175,131,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '218'
+ $floorItems2['218'] = i
+ w.create(TkcText,136,149.5, 'text'=>'218', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,154,191,111,191,111,169,154,169,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '219'
+ $floorItems2['219'] = i
+ w.create(TkcText,132.5,180, 'text'=>'219', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
+ 'fill'=>'', 'tags'=>['floor2','room'])
+ $floorLabels2[i.id] = '201'
+ $floorItems2['201'] = i
+ w.create(TkcText,358,209, 'text'=>'201', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor2','label'])
+ w.create(TkcLine,641,186,678,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,350,757,367, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,634,133,634,144, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,634,144,627,144, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,572,133,572,144, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,572,144,579,144, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,129,398,162, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,174,197,175,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,175,197,175,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,206,757,221, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,396,188,408,188, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,727,189,725,189, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,747,167,802,167, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,747,167,747,189, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,755,189,739,189, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,769,224,757,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,802,224,802,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,802,129,725,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,725,189,725,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,725,186,690,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,676,133,676,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,627,144,627,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,629,186,593,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,579,144,579,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,559,129,559,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,725,133,559,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,484,162,484,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,559,129,484,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,526,129,526,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,540,186,581,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,528,186,523,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,511,186,475,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,496,190,496,186, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,496,205,496,202, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,475,205,527,205, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,205,539,205, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,205,558,249, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,249,475,249, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,662,206,642,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,695,206,675,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,695,278,642,278, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,642,291,642,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,695,291,695,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,716,208,716,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,206,716,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,221,757,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,793,224,802,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,262,716,262, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,716,220,716,264, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,716,315,716,276, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,315,703,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,325,757,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,757,367,644,367, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,689,367,689,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,647,315,644,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,659,315,691,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,600,325,600,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,627,325,644,325, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,644,391,644,315, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,615,325,575,325, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,644,391,558,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,563,325,558,325, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,391,558,314, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,327,508,327, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,275,484,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,558,302,558,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,508,327,508,311, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,484,311,508,311, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,484,275,484,311, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,475,208,408,208, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,408,206,408,210, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,408,222,408,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,408,227,398,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,227,398,254, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,408,188,408,194, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,383,188,376,188, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,188,398,162, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,162,484,162, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,475,162,475,254, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,254,475,254, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,484,280,395,280, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,395,311,395,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,307,197,293,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,278,197,233,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,233,197,233,249, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,307,179,284,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,233,249,278,249, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,269,179,269,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,220,179,220,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,155,191,110,191, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,90,190,98,190, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,98,169,98,190, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,133,52,165, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,214,52,177, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,226,52,262, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,274,52,276, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,234,275,234,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,226,339,258,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,211,387,211,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,214,339,177,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,258,387,60,387, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,3,133,3,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,165,339,129,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,117,339,80,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,68,339,59,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,0,339,46,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,0,339,0,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,60,387,60,391, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,258,329,258,387, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,350,329,258,329, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,395,311,350,311, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,398,129,315,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,176,133,315,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,176,129,96,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,3,133,96,133, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,66,387,66,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,115,387,115,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,163,387,163,339, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,234,275,276,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,288,275,309,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,298,275,298,329, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,341,283,350,283, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,321,275,341,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,375,275,395,275, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,315,129,315,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,376,170,307,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,307,250,307,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,376,245,376,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,241,307,241, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,245,340,224, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,210,340,201, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,187,340,170, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,340,206,307,206, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,293,250,307,250, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,271,179,238,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,226,179,195,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,176,129,176,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,182,179,176,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,174,169,176,169, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,162,169,90,169, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,96,169,96,129, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,175,227,90,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,90,190,90,227, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,179,3,179, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,228,3,228, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,52,276,3,276, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,155,177,155,169, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,110,191,110,169, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,155,189,155,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,350,283,350,329, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,162,197,155,197, 'fill'=>color, 'tags'=>['floor2','wall'])
+ w.create(TkcLine,341,275,341,283, 'fill'=>color, 'tags'=>['floor2','wall'])
+end
+
+# floor2_fg3 --
+# This method represents part of the floorplan database. When
+# invoked, it instantiates the foreground information for the third
+# floor (office outlines and numbers).
+#
+# Arguments:
+# w - The canvas window.
+# color - Color to use for drawing foreground information.
+
+def floor2_fg3(w,color)
+ i = TkcPolygon.new(w,89,228,89,180,70,180,70,228,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '316'
+ $floorItems2['316'] = i
+ w.create(TkcText,79.5,204, 'text'=>'316', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,115,368,162,368,162,323,115,323,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '309'
+ $floorItems2['309'] = i
+ w.create(TkcText,138.5,345.5, 'text'=>'309', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,164,323,164,368,211,368,211,323,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '308'
+ $floorItems2['308'] = i
+ w.create(TkcText,187.5,345.5, 'text'=>'308', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,256,368,212,368,212,323,256,323,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '307'
+ $floorItems2['307'] = i
+ w.create(TkcText,234,345.5, 'text'=>'307', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,244,276,297,276,297,327,260,327,260,321,244,321,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '305'
+ $floorItems2['305'] = i
+ w.create(TkcText,270.5,301.5, 'text'=>'305', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,251,219,251,203,244,203,244,219,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '324B'
+ $floorItems2['324B'] = i
+ w.create(TkcText,247.5,211, 'text'=>'324B', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,251,249,244,249,244,232,251,232,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '324A'
+ $floorItems2['324A'] = i
+ w.create(TkcText,247.5,240.5, 'text'=>'324A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,223,135,223,179,177,179,177,135,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '320'
+ $floorItems2['320'] = i
+ w.create(TkcText,200,157, 'text'=>'320', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,114,368,114,323,67,323,67,368,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '310'
+ $floorItems2['310'] = i
+ w.create(TkcText,90.5,345.5, 'text'=>'310', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,23,277,23,321,68,321,68,277,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '312'
+ $floorItems2['312'] = i
+ w.create(TkcText,45.5,299, 'text'=>'312', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,23,229,68,229,68,275,23,275,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '313'
+ $floorItems2['313'] = i
+ w.create(TkcText,45.5,252, 'text'=>'313', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,68,227,23,227,23,180,68,180,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '314'
+ $floorItems2['314'] = i
+ w.create(TkcText,40.5,203.5, 'text'=>'314', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,95,179,95,135,23,135,23,179,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '315'
+ $floorItems2['315'] = i
+ w.create(TkcText,59,157, 'text'=>'315', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,99,226,99,204,91,204,91,226,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '316B'
+ $floorItems2['316B'] = i
+ w.create(TkcText,95,215, 'text'=>'316B', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,91,202,99,202,99,180,91,180,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '316A'
+ $floorItems2['316A'] = i
+ w.create(TkcText,95,191, 'text'=>'316A', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,97,169,109,169,109,192,154,192,154,198,
+ 174,198,174,226,101,226,101,179,97,179,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '319'
+ $floorItems2['319'] = i
+ w.create(TkcText,141.5,209, 'text'=>'319', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,65,368,58,368,58,389,1,389,1,333,23,333,23,323,65,323,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '311'
+ $floorItems2['311'] = i
+ w.create(TkcText,29.5,361, 'text'=>'311', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,154,191,111,191,111,169,154,169,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '318'
+ $floorItems2['318'] = i
+ w.create(TkcText,132.5,180, 'text'=>'318', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,175,168,97,168,97,131,175,131,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '317'
+ $floorItems2['317'] = i
+ w.create(TkcText,136,149.5, 'text'=>'317', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,274,194,274,221,306,221,306,194,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '323'
+ $floorItems2['323'] = i
+ w.create(TkcText,290,207.5, 'text'=>'323', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,306,222,274,222,274,249,306,249,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '325'
+ $floorItems2['325'] = i
+ w.create(TkcText,290,235.5, 'text'=>'325', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,263,179,224,179,224,135,263,135,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '321'
+ $floorItems2['321'] = i
+ w.create(TkcText,243.5,157, 'text'=>'321', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,314,169,306,169,306,192,273,192,
+ 264,181,264,135,314,135,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '322'
+ $floorItems2['322'] = i
+ w.create(TkcText,293.5,163.5, 'text'=>'322', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,307,240,339,240,339,206,307,206,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = 'Pub Lift3'
+ $floorItems2['Pub Lift3'] = i
+ w.create(TkcText,323,223, 'text'=>'Pub Lift3', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,339,205,307,205,307,171,339,171,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = 'Priv Lift3'
+ $floorItems2['Priv Lift3'] = i
+ w.create(TkcText,323,188, 'text'=>'Priv Lift3', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,350,284,376,284,376,276,397,276,397,309,350,309,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '303'
+ $floorItems2['303'] = i
+ w.create(TkcText,373.5,292.5, 'text'=>'303', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,272,203,272,249,252,249,252,230,
+ 244,230,244,221,252,221,252,203,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '324'
+ $floorItems2['324'] = i
+ w.create(TkcText,262,226, 'text'=>'324', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,299,276,299,327,349,327,349,284,341,284,341,276,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '304'
+ $floorItems2['304'] = i
+ w.create(TkcText,324,301.5, 'text'=>'304', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,375,246,375,172,341,172,341,246,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '301'
+ $floorItems2['301'] = i
+ w.create(TkcText,358,209, 'text'=>'301', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,397,246,377,246,377,185,397,185,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '327'
+ $floorItems2['327'] = i
+ w.create(TkcText,387,215.5, 'text'=>'327', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,316,131,316,169,377,169,377,185,397,185,397,131,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '326'
+ $floorItems2['326'] = i
+ w.create(TkcText,365.5,150, 'text'=>'326', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,308,251,242,251,242,274,342,274,342,282,375, 282,
+ 375,274,397,274,397,248,339,248,339,242,308,242,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '302'
+ $floorItems2['302'] = i
+ w.create(TkcText,319.5,261, 'text'=>'302', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ i = TkcPolygon.new(w,70,321,242,321,242,200,259,200,259,203,272,203,
+ 272,193,263,180,242,180,175,180,175,169,156,169,
+ 156,196,177,196,177,228,107,228,70,228,70,275,107,275,
+ 107,248,160,248,160,301,107,301,107,275,70,275,
+ 'fill'=>'', 'tags'=>['floor3','room'])
+ $floorLabels2[i.id] = '306'
+ $floorItems2['306'] = i
+ w.create(TkcText,200.5,284.5, 'text'=>'306', 'fill'=>color,
+ 'anchor'=>'c', 'tags'=>['floor3','label'])
+ w.create(TkcLine,341,275,341,283, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,162,197,155,197, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,396,247,399,247, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,399,129,399,311, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,258,202,243,202, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,350,283,350,329, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,251,231,243,231, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,243,220,251,220, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,243,250,243,202, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,155,197,155,190, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,110,192,110,169, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,155,192,110,192, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,155,177,155,169, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,176,197,176,227, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,69,280,69,274, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,276,69,276, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,69,262,69,226, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,228,69,228, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,179,75,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,69,179,69,214, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,220,90,227, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,204,90,202, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,203,100,203, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,187,90,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,90,227,176,227, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,100,179,100,227, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,100,179,87,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,96,179,96,129, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,162,169,96,169, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,173,169,176,169, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,182,179,176,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,176,129,176,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,195,179,226,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,224,133,224,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,264,179,264,133, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,238,179,264,179, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,207,273,193, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,235,273,250, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,224,273,219, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,193,307,193, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,222,307,222, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,250,307,250, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,384,247,376,247, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,206,307,206, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,187,340,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,210,340,201, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,247,340,224, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,340,241,307,241, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,376,247,376,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,307,250,307,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,376,170,307,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,315,129,315,170, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,376,283,366,283, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,376,283,376,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,399,275,376,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,341,275,320,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,341,283,350,283, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,298,275,298,329, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,308,275,298,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,243,322,243,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,243,275,284,275, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,258,322,226,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,212,370,212,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,214,322,177,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,163,370,163,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,165,322,129,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,84,322,117,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,71,322,64,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,115,322,115,370, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,66,322,66,370, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,52,322,21,322, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,331,0,331, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,21,331,21,133, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,96,133,21,133, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,176,129,96,129, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,315,133,176,133, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,315,129,399,129, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,399,311,350,311, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,350,329,258,329, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,258,322,258,370, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,60,370,258,370, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,60,370,60,391, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,0,391,0,331, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,60,391,0,391, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,307,250,307,242, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,273,250,307,250, 'fill'=>color, 'tags'=>['floor3','wall'])
+ w.create(TkcLine,258,250,243,250, 'fill'=>color, 'tags'=>['floor3','wall'])
+end
+
+# Below is the "main program" that creates the floorplan demonstration.
+
+# toplevel widget ¤¬Â¸ºß¤¹¤ì¤Ðºï½ü¤¹¤ë
+if defined?($floor2_demo) && $floor2_demo
+ $floor2_demo.destroy
+ $floor2_demo = nil
+end
+
+# demo ÍѤΠtoplevel widget ¤òÀ¸À®
+$floor2_demo = TkToplevel.new {|w|
+ title("Floorplan Canvas Demonstration 2")
+ iconname("Floorplan2")
+ positionWindow(w)
+ geometry('+20+20')
+ minsize(100,100)
+}
+
+base_frame = TkFrame.new($floor2_demo).pack(:fill=>:both, :expand=>true)
+
+# label À¸À®
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'8i', 'justify'=>'left',
+ 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥Ç¥£¥¸¥¿¥ë¥¨¥¯¥¤¥Ã¥×¥á¥ó¥È¼Ò¤Î¥¦¥§¥¹¥¿¥ó¥ê¥µ¡¼¥Á¥é¥Ü¥é¥È¥ê (DECWRL) ¤Î´Ö¼è¤ê¤¬½ñ¤«¤ì¤¿¥­¥ã¥ó¥Ð¥¹ widget ¤¬Æþ¤Ã¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ï 3³¬·ú¤Æ¤Ç¡¢¾ï¤Ë¤½¤Î¤¦¤Á¤Î1³¬Ê¬¤¬ÁªÂò¡¢¤Ä¤Þ¤ê¤½¤Î´Ö¼è¤ê¤¬É½¼¨¤µ¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£¤¢¤ë³¬¤òÁªÂò¤¹¤ë¤Ë¤Ï¡¢¤½¤Î¾å¤Ç¥Þ¥¦¥¹¤Îº¸¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£¥Þ¥¦¥¹¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤ë³¬¤Î¾å¤òư¤¯¤È¡¢¤½¤Î²¼¤Ë¤¢¤ëÉô²°¤Î¿§¤¬ÊѤï¤ê¡¢Éô²°Èֹ椬¡ÖÉô²°ÈÖ¹æ:¡×¥¨¥ó¥È¥ê¤Ëɽ¼¨¤µ¤ì¤Þ¤¹¡£¤Þ¤¿¡¢¥¨¥ó¥È¥ê¤ËÉô²°ÈÖ¹æ¤ò½ñ¤¯¤È¤½¤ÎÉô²°¤Î¿§¤¬ÊѤï¤ê¤Þ¤¹¡£"){
+ pack('side'=>'top')
+}
+
+# frame À¸À®
+$floor2_buttons = TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
+ command proc{
+ tmppath = $floor2_demo
+ $floor2_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text '¥³¡¼¥É»²¾È'
+ command proc{showCode 'floor2'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+}
+$floor2_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# ÊÑ¿ôÀßÄê
+$floorLabels2 = {}
+$floorItems2 = {}
+
+# canvas ÀßÄê
+if $tk_version =~ /^4\.[01]/
+ $floor2_canvas_frame = TkFrame.new(base_frame,'bd'=>2,'relief'=>'sunken',
+ 'highlightthickness'=>2)
+ $floor2_canvas = TkCanvas.new($floor2_canvas_frame,
+ 'width'=>900, 'height'=>500, 'borderwidth'=>0,
+ 'highlightthickness'=>0) {|c|
+ TkScrollbar.new(base_frame, 'orient'=>'horiz',
+ 'command'=>proc{|*args| c.xview(*args)}){|hs|
+ c.xscrollcommand(proc{|first,last| hs.set first,last})
+ pack('side'=>'bottom', 'fill'=>'x')
+ }
+ TkScrollbar.new(base_frame, 'command'=>proc{|*args| c.yview(*args)}){|vs|
+ c.yscrollcommand(proc{|first,last| vs.set first,last})
+ pack('side'=>'right', 'fill'=>'y')
+ }
+ }
+ $floor2_canvas_frame.pack('side'=>'top','fill'=>'both', 'expand'=>'yes')
+ $floor2_canvas.pack('expand'=>'yes', 'fill'=>'both')
+
+else
+ TkFrame.new(base_frame) {|f|
+ pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes')
+
+ h = TkScrollbar.new(f, 'highlightthickness'=>0, 'orient'=>'horizontal')
+ v = TkScrollbar.new(f, 'highlightthickness'=>0, 'orient'=>'vertical')
+
+ TkFrame.new(f, 'bd'=>2, 'relief'=>'sunken') {|f1|
+ $floor2_canvas = TkCanvas.new(f1, 'width'=>900, 'height'=>500,
+ 'borderwidth'=>0,
+ 'highlightthickness'=>0) {
+ xscrollcommand(proc{|first,last| h.set first,last})
+ yscrollcommand(proc{|first,last| v.set first,last})
+ pack('expand'=>'yes', 'fill'=>'both')
+ }
+ grid('padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ }
+
+ v.grid('padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ h.grid('padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+
+ TkGrid.rowconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
+ TkGrid.columnconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
+
+ pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
+
+ v.command(proc{|*args| $floor2_canvas.yview(*args)})
+ h.command(proc{|*args| $floor2_canvas.xview(*args)})
+ }
+end
+
+# Create an entry for displaying and typing in current room.
+
+$currentRoom2 = TkVariable.new
+$floor2_entry = TkEntry.new($floor2_canvas, 'width'=>10, 'relief'=>'sunken',
+ 'bd'=>2, 'textvariable'=>$currentRoom2)
+
+# Choose colors, then fill in the floorplan.
+
+$floor2_colors = {}
+if TkWinfo.depth($floor2_canvas) > 1
+ $floor2_colors['bg1'] = '#a9c1da'
+ $floor2_colors['outline1'] = '#77889a'
+ $floor2_colors['bg2'] = '#9ab0c6'
+ $floor2_colors['outline2'] = '#687786'
+ $floor2_colors['bg3'] = '#8ba0b3'
+ $floor2_colors['outline3'] = '#596673'
+ $floor2_colors['offices'] = 'Black'
+ $floor2_colors['active'] = '#c4d1df'
+else
+ $floor2_colors['bg1'] = 'white'
+ $floor2_colors['outline1'] = 'black'
+ $floor2_colors['bg2'] = 'white'
+ $floor2_colors['outline2'] = 'black'
+ $floor2_colors['bg3'] = 'white'
+ $floor2_colors['outline3'] = 'black'
+ $floor2_colors['offices'] = 'Black'
+ $floor2_colors['active'] = 'black'
+end
+
+$activeFloor2 = ''
+floorDisplay2 $floor2_canvas,3
+
+# Set up event bindings for canvas:
+
+$floor2_canvas.itembind('floor1', '1', proc{floorDisplay2 $floor2_canvas,1})
+$floor2_canvas.itembind('floor2', '1', proc{floorDisplay2 $floor2_canvas,2})
+$floor2_canvas.itembind('floor3', '1', proc{floorDisplay2 $floor2_canvas,3})
+$floor2_canvas.itembind('room', 'Enter', proc{newRoom2 $floor2_canvas})
+$floor2_canvas.itembind('room', 'Leave', proc{$currentRoom2.value = ''})
+$floor2_canvas.bind('2', proc{|x,y| $floor2_canvas.scan_mark x,y}, '%x %y')
+$floor2_canvas.bind('B2-Motion',
+ proc{|x,y| $floor2_canvas.scan_dragto x,y}, '%x %y')
+$floor2_canvas.bind('Destroy', proc{$currentRoom2.unset})
+$currentRoom2.value = ''
+$currentRoom2.trace('w',proc{roomChanged2 $floor2_canvas})
diff --git a/ext/tk/sample/demos-jp/form.rb b/ext/tk/sample/demos-jp/form.rb
index 35baeed46b..4de7056764 100644
--- a/ext/tk/sample/demos-jp/form.rb
+++ b/ext/tk/sample/demos-jp/form.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# form widget demo (called by 'widget')
#
@@ -15,8 +16,10 @@ $form_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($form_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($form_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($form_demo) {
msg.pack('side'=>'top', 'fill'=>'x')
# frame À¸À®
-TkFrame.new($form_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $form_demo
$form_demo = nil
@@ -44,7 +48,7 @@ TkFrame.new($form_demo) {|frame|
# entry À¸À®
form_data = []
(1..5).each{|i|
- f = TkFrame.new($form_demo, 'bd'=>2)
+ f = TkFrame.new(base_frame, 'bd'=>2)
e = TkEntry.new(f, 'relief'=>'sunken', 'width'=>40)
l = TkLabel.new(f)
e.pack('side'=>'right')
diff --git a/ext/tk/sample/demos-jp/goldberg.rb b/ext/tk/sample/demos-jp/goldberg.rb
new file mode 100644
index 0000000000..a81c7ec70c
--- /dev/null
+++ b/ext/tk/sample/demos-jp/goldberg.rb
@@ -0,0 +1,2011 @@
+# -*- coding: euc-jp -*-
+#
+# Ruby/Tk Goldverg demo (called by 'widget')
+#
+# Based on Tcl/Tk8.5a2 widget demos.
+# The following is the original comment of TkGoldberg.tcl.
+#
+#>>##+#################################################################
+#>>#
+#>># TkGoldberg.tcl
+#>># by Keith Vetter, March 13, 2003
+#>>#
+#>># "Man will always find a difficult means to perform a simple task"
+#>># Rube Goldberg
+#>>#
+#>># Reproduced here with permission.
+#>>#
+#>>##+#################################################################
+#>>#
+#>># Keith Vetter 2003-03-21: this started out as a simple little program
+#>># but was so much fun that it grew and grew. So I apologize about the
+#>># size but I just couldn't resist sharing it.
+#>>#
+#>># This is a whizzlet that does a Rube Goldberg type animation, the
+#>># design of which comes from an New Years e-card from IncrediMail.
+#>># That version had nice sound effects which I eschewed. On the other
+#>># hand, that version was in black and white (actually dark blue and
+#>># light blue) and this one is fully colorized.
+#>>#
+#>># One thing I learned from this project is that drawing filled complex
+#>># objects on a canvas is really hard. More often than not I had to
+#>># draw each item twice--once with the desired fill color but no
+#>># outline, and once with no fill but with the outline. Another trick
+#>># is erasing by drawing with the background color. Having a flood fill
+#>># command would have been extremely helpful.
+#>>#
+#>># Two wiki pages were extremely helpful: Drawing rounded rectangles
+#>># which I generalized into Drawing rounded polygons, and regular
+#>># polygons which allowed me to convert ovals and arcs into polygons
+#>># which could then be rotated (see Canvas Rotation). I also wrote
+#>># Named Colors to aid in the color selection.
+#>>#
+#>># I could comment on the code, but it's just 26 state machines with
+#>># lots of canvas create and move calls.
+
+if defined?($goldberg_demo) && $goldberg_demo
+ $goldberg_demo.destroy
+ $goldberg_demo = nil
+end
+
+# demo toplevel widget
+$goldberg_demo = TkToplevel.new {|w|
+ title("Tk Goldberg (demonstration)")
+ iconname("goldberg")
+# positionWindow(w)
+}
+
+base_frame = TkFrame.new($goldberg_demo).pack(:fill=>:both, :expand=>true)
+
+=begin
+# label
+msg = TkLabel.new($goldberg_demo) {
+ font 'Arial 10'
+ wraplength '4i'
+ justify 'left'
+ text "¤³¤ì¤Ï¡¢¤¢¤Ê¤¿¤¬¼«Ê¬¤Î¥¢¥Ë¥á¡¼¥·¥ç¥ó¤ò¤¤¤«¤ËÆþ¤êÁȤó¤À¤â¤Î¤Ë¤Ç¤­¤ë¤«¤ò¼¨¤¹¤È¤¤¤¦¤À¤±¤Î¤¿¤á¤Î¥Ç¥â¤Ç¤¹¡£¥Ü¡¼¥ë¤ò¥¯¥ê¥Ã¥¯¤¹¤ì¤Ðʪ¤¬Æ°¤­»Ï¤á¤Þ¤¹¡ª\n\n\"Man will always find a difficult means to perform a simple task\"\n - Rube Goldberg"
+}
+msg.pack('side'=>'top')
+=end
+
+=begin
+# frame
+TkFrame.new($goldberg_demo) {|frame|
+ TkButton.new(frame) {
+ text 'ÊĤ¸¤ë'
+ command proc{
+ tmppath = $goldberg_demo
+ $goldberg_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text '¥³¡¼¥É»²¾È'
+ command proc{showCode 'goldberg'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+=end
+
+#########################################
+
+class TkGoldberg_Demo
+ def initialize(parent)
+ @parent = parent
+
+ @S = {}
+ @S['title'] = 'Tk Goldberg'
+ @S['speed'] = TkVariable.new(5)
+ @S['cnt'] = TkVariable.new(0)
+ # @S['message'] = TkVariable.new("\\nWelcome\\nto\\nRuby/Tk")
+ @S['message'] = TkVariable.new("\\n ¤è¤¦¤³¤½¡ª\\nRuby/Tk\\n¤Î\\nÀ¤³¦¤Ø")
+ @S['pause'] = TkVariable.new
+ @S['details'] = TkVariable.new(true)
+
+ @S['mode'] = TkVariable.new(:MSTART, :symbol)
+ # :MSTART, :MGO, :MPAUSE, :MSSTEP, :MBSTEP, :MDONE, :MDEBUG
+
+ # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+ @speed = [1, 10, 20, 50, 80, 100, 150, 200, 300, 400, 500]
+
+ # colors
+ @C = {}
+ @C['fg'] = 'black'
+ # @C['bg'] = 'gray75'
+ @C['bg'] = 'cornflowerblue'
+
+ @C['0'] = 'white'; @C['1a'] = 'darkgreen'; @C['1b'] = 'yellow'
+ @C['2'] = 'red'; @C['3a'] = 'green'; @C['3b'] = 'darkblue'
+ @C['4'] = @C['fg']; @C['5a'] = 'brown'; @C['5b'] = 'white'
+ @C['6'] = 'magenta'; @C['7'] = 'green'; @C['8'] = @C['fg']
+ @C['9'] = 'blue4'; @C['10a'] = 'white'; @C['10b'] = 'cyan'
+ @C['11a'] = 'yellow'; @C['11b'] = 'mediumblue'; @C['12'] = 'tan2'
+ @C['13a'] = 'yellow'; @C['13b'] = 'red'; @C['14'] = 'white'
+ @C['15a'] = 'green'; @C['15b'] = 'yellow'; @C['16'] = 'gray65'
+ @C['17'] = '#A65353'; @C['18'] = @C['fg']; @C['19'] = 'gray50'
+ @C['20'] = 'cyan'; @C['21'] = 'gray65'; @C['22'] = @C['20']
+ @C['23a'] = 'blue'; @C['23b'] = 'red'; @C['23c'] = 'yellow'
+ @C['24a'] = 'red'; @C['24b'] = 'white';
+
+ @STEP = TkVariable.new_hash
+ @STEP.default_value_type = :numeric
+
+ @XY = {}
+
+ @XY6 = {
+ '-1'=>[366, 207], '-2'=>[349, 204], '-3'=>[359, 193], '-4'=>[375, 192],
+ '-5'=>[340, 190], '-6'=>[349, 177], '-7'=>[366, 177], '-8'=>[380, 176],
+ '-9'=>[332, 172], '-10'=>[342, 161], '-11'=>[357, 164],
+ '-12'=>[372, 163], '-13'=>[381, 149], '-14'=>[364, 151],
+ '-15'=>[349, 146], '-16'=>[333, 148], '0'=>[357, 219],
+ '1'=>[359, 261], '2'=>[359, 291], '3'=>[359, 318], '4'=>[361, 324],
+ '5'=>[365, 329], '6'=>[367, 334], '7'=>[367, 340], '8'=>[366, 346],
+ '9'=>[364, 350], '10'=>[361, 355], '11'=>[359, 370], '12'=>[359, 391],
+ '13,0'=>[360, 456], '13,1'=>[376, 456], '13,2'=>[346, 456],
+ '13,3'=>[330, 456], '13,4'=>[353, 444], '13,5'=>[368, 443],
+ '13,6'=>[339, 442], '13,7'=>[359, 431], '13,8'=>[380, 437],
+ '13,9'=>[345, 428], '13,10'=>[328, 434], '13,11'=>[373, 424],
+ '13,12'=>[331, 420], '13,13'=>[360, 417], '13,14'=>[345, 412],
+ '13,15'=>[376, 410], '13,16'=>[360, 403]
+ }
+
+ @timer = TkTimer.new(@speed[@S['speed'].numeric]){|timer|
+ timer.set_interval(go)
+ }
+
+ do_display
+ reset
+
+ # Start everything going
+ @timer.start
+ end
+
+ def do_display()
+ @ctrl = TkFrame.new(@parent, :relief=>:ridge, :bd=>2, :padx=>5, :pady=>5)
+ @screen = TkFrame.new(@parent, :bd=>2,
+ :relief=>:raised).pack(:side=>:left, :fill=>:both,
+ :expand=>true)
+
+ @canvas = TkCanvas.new(@parent, :width=>850, :height=>700,
+ :bg=>@C['bg'], :highlightthickness=>0){
+ scrollregion([0, 0, 1000, 1000]) # Kludge to move everything up
+ yview_moveto(0.05)
+ }.pack(:in=>@screen, :side=>:top, :fill=>:both, :expand=>true)
+
+ @canvas.bind('3'){ @pause.invoke }
+ @canvas.bind('Destroy'){ @timer.stop }
+
+ do_ctrl_frame
+ do_detail_frame
+
+ # msg = TkLabel.new(@parent, :bg=>@C['bg'], :fg=>'white') {
+ msg = Tk::Label.new(@parent, :bg=>@C['bg'], :fg=>'white') {
+ font 'Arial 10'
+ wraplength 600
+ justify 'left'
+ text "¤³¤ì¤Ï¡¢¤¢¤Ê¤¿¤¬¼«Ê¬¤Î¥¢¥Ë¥á¡¼¥·¥ç¥ó¤ò¤¤¤«¤ËÆþ¤êÁȤó¤À¤â¤Î¤Ë¤Ç¤­¤ë¤«¤ò¼¨¤¹¤È¤¤¤¦¤À¤±¤Î¤¿¤á¤Î¥Ç¥â¤Ç¤¹¡£¥Ü¡¼¥ë¤ò¥¯¥ê¥Ã¥¯¤¹¤ì¤Ðʪ¤¬Æ°¤­»Ï¤á¤Þ¤¹¡ª\n\"Man will always find a difficult means to perform a simple task\" - Rube Goldberg"
+ }
+ msg.place(:in=>@canvas, :relx=>0, :rely=>0, :anchor=>:nw)
+
+ frame = TkFrame.new(@parent, :bg=>@C['bg'])
+
+ # TkButton.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ Tk::Button.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ text 'ÊĤ¸¤ë'
+ command proc{
+ tmppath = $goldberg_demo
+ $goldberg_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left')
+
+ # TkButton.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ Tk::Button.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ text '¥³¡¼¥É»²¾È'
+ command proc{showCode 'goldberg'}
+ }.pack('side'=>'left', 'padx'=>5)
+
+ # @show = TkButton.new(frame, :text=>'>>', :command=>proc{show_ctrl},
+ @show = Tk::Button.new(frame, :text=>'>>', :command=>proc{show_ctrl},
+ :bg=>@C['bg'], :activebackground=>@C['bg'])
+ @show.pack('side'=>'left')
+ frame.place(:in=>@canvas, :relx=>1, :rely=>0, :anchor=>:ne)
+
+ Tk.update
+ end
+
+ def do_ctrl_frame
+ @start = Tk::Button.new(@parent, :text=>'Start', :bd=>6,
+ :command=>proc{do_button(0)})
+ if font = @start['font']
+ @start.font(font.weight('bold'))
+ end
+
+ @pause = TkCheckbutton.new(@parent, :text=>'Pause', :font=>font,
+ :command=>proc{do_button(1)}, :relief=>:raised,
+ :variable=>@S['pause'])
+
+ @step = TkButton.new(@parent, :text=>'Single Step', :font=>font,
+ :command=>proc{do_button(2)})
+ @bstep = TkButton.new(@parent, :text=>'Big Step', :font=>font,
+ :command=>proc{do_button(4)})
+ @reset = TkButton.new(@parent, :text=>'Reset', :font=>font,
+ :command=>proc{do_button(3)})
+
+ @details = TkFrame.new(@parent, :bd=>2, :relief=>:ridge)
+ @detail = TkCheckbutton.new(@parent, :text=>'Details', :font=>font,
+ :relief=>:raised, :variable=>@S['details'])
+
+ @msg_entry = TkEntry.new(@parent, :textvariable=>@S['message'],
+ :justify=>:center)
+ @speed_scale = TkScale.new(@parent, :orient=>:horizontal,
+ :from=>1, :to=>10, :font=>font,
+ :variable=>@S['speed'], :bd=>2,
+ :relief=>:ridge, :showvalue=>false)
+ @about = TkButton.new(@parent, :text=>'About',
+ :command=>proc{about}, :font=>font)
+
+ Tk.grid(@start, :in=>@ctrl, :row=>0, :sticky=>:ew)
+ @ctrl.grid_rowconfigure(1, :minsize=>10)
+ Tk.grid(@pause, :in=>@ctrl, :row=>2, :sticky=>:ew)
+ Tk.grid(@step, :in=>@ctrl, :sticky=>:ew)
+ Tk.grid(@bstep, :in=>@ctrl, :sticky=>:ew)
+ Tk.grid(@reset, :in=>@ctrl, :sticky=>:ew)
+ @ctrl.grid_rowconfigure(10, :minsize=>20)
+ Tk.grid(@details, :in=>@ctrl, :row=>11, :sticky=>:ew)
+ Tk.grid(@detail, :in=>@details, :row=>0, :sticky=>:ew)
+ @ctrl.grid_rowconfigure(50, :weight=>1)
+
+ @S['mode'].trace('w', proc{|*args| active_GUI(*args)})
+ @S['details'].trace('w', proc{|*args| active_GUI(*args)})
+ @S['speed'].trace('w', proc{|*args| active_GUI(*args)})
+
+ Tk.grid(@msg_entry, :in=>@ctrl, :row=>98, :sticky=>:ew, :pady=>5)
+ Tk.grid(@speed_scale, :in=>@ctrl, :row=>99, :sticky=>:ew)
+ Tk.grid(@about, :in=>@ctrl, :row=>100, :sticky=>:ew)
+
+ @reset.bind('3'){@S['mode'].value = -1} # Debugging
+ end
+
+ def do_detail_frame
+ @f_details = TkFrame.new(@details)
+
+ @label = TkLabel.new(@f_details, :textvariable=>@S['cnt'],
+ :bd=>1, :relief=>:solid, :bg=>'white')
+ Tk.grid(@label, '-', '-', '-', :sticky=>:ew, :row=>0)
+
+ idx = 1
+ loop {
+ break unless respond_to?("move#{idx}")
+ l = TkLabel.new(@f_details, :text=>idx, :anchor=>:e,
+ :width=>2, :bd=>1, :relief=>:solid, :bg=>'white')
+ @STEP[idx] = 0
+ ll = TkLabel.new(@f_details, :textvariable=>@STEP.ref(idx),
+ :width=>5, :bd=>1, :relief=>:solid, :bg=>'white')
+ row = (idx + 1)/2
+ col = ((idx + 1) & 1) * 2
+ Tk.grid(l, :sticky=>:ew, :row=>row, :column=>col)
+ Tk.grid(ll, :sticky=>:ew, :row=>row, :column=>(col + 1))
+ idx += 1
+ }
+ @f_details.grid_columnconfigure(1, :weight=>1)
+ end
+
+ def show_ctrl
+ if @ctrl.winfo_mapped?
+ @ctrl.pack_forget
+ @show.text('>>')
+ else
+ @ctrl.pack(:side=>:right, :fill=>:both, :ipady=>5)
+ @show.text('<<')
+ end
+ end
+
+ def draw_all
+ reset_step
+ @canvas.delete(:all)
+ idx = 0
+ loop{
+ m = "draw#{idx}"
+ break unless respond_to?(m)
+ send(m)
+ idx += 1
+ }
+ end
+
+ def active_GUI(var1, var2, op)
+ st = {false=>:disabled, true=>:normal}
+
+ m = @S['mode'].to_sym
+ @S['pause'].value = (m == :MPAUSE)
+ @start.state(st[m != :MGO])
+ @pause.state(st[m != :MSTART && m != :MDONE])
+ @step.state(st[m != :MGO && m != :MDONE])
+ @bstep.state(st[m != :MGO && m != :MDONE])
+ @reset.state(st[m != :MSTART])
+
+ if @S['details'].bool
+ Tk.grid(@f_details, :in=>@details, :row=>2, :sticky=>:ew)
+ else
+ Tk.grid_forget(@f_details)
+ end
+ @speed_scale.label("Speed: #{@S['speed'].value}")
+ end
+
+ def start
+ @S['mode'].value = :MGO
+ end
+
+ def do_button(what)
+ case what
+ when 0 # Start
+ reset if @S['mode'].to_sym == :MDONE
+ @S['mode'].value = :MGO
+
+ when 1 # Pause
+ @S['mode'].value = ((@S['pause'].bool)? :MPAUSE: :MGO)
+
+ when 2 # Step
+ @S['mode'].value = :MSSTEP
+
+ when 3 # Reset
+ reset
+
+ when 4 # Big step
+ @S['mode'].value = :MBSTEP
+ end
+ end
+
+ def go(who = nil)
+ now = Tk::Clock.clicks(:miliseconds)
+ if who # Start here for debugging
+ @S['active'] = [who]
+ @S['mode'].value = :MGO
+ end
+ return if @S['mode'].to_sym == :MDEBUG # Debugging
+ # If not paused, do the next move
+ n = next_step if @S['mode'].to_sym != :MPAUSE
+ @S['mode'].value = :MPAUSE if @S['mode'].to_sym == :MSSTEP # Single step
+ @S['mode'].value = :MSSTEP if @S['mode'].to_sym == :MBSTEP && n # big step
+ elapsed = Tk::Clock.clicks(:miliseconds) - now
+ delay = @speed[@S['speed'].to_i] - elapsed
+ delay = 1 if delay <= 0
+ return delay
+ end
+
+ def next_step
+ retval = false # Return value
+
+ if @S['mode'].to_sym != :MSTART && @S['mode'].to_sym != :MDONE
+ @S['cnt'].numeric += 1
+ end
+ alive = []
+ @S['active'].each{|who|
+ who = who.to_i
+ n = send("move#{who}")
+ if (n & 1).nonzero? # This guy still alive
+ alive << who
+ end
+ if (n & 2).nonzero? # Next guy is active
+ alive << (who + 1)
+ retval = true
+ end
+ if (n & 4).nonzero? # End of puzzle flag
+ @S['mode'].value = :MDONE # Done mode
+ @S['active'] = [] # No more animation
+ return true
+ end
+ }
+ @S['active'] = alive
+ return retval
+ end
+
+ def about
+ msg = "Ruby/Tk Version ::\nby Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)\n\n"
+ msg += "Original Version ::\n"
+ msg += "#{@S['title']}\nby Keith Vetter, March 2003\n(Reproduced by kind permission of the author)\n\n"
+ msg += "Man will always find a difficult means to perform a simple task"
+ msg += "\nRube Goldberg"
+ Tk.messageBox(:message=>msg, :title=>'About')
+ end
+
+ ################################################################
+ #
+ # All the drawing and moving routines
+ #
+
+ # START HERE! banner
+ def draw0
+ color = @C['0']
+ TkcText.new(@canvas,
+ # [579, 119], :text=>'START HERE!',
+ [558, 119], :text=>'¤³¤³¤«¤é¥¹¥¿¡¼¥È¡ª',
+ :fill=>color, :anchor=>:w,
+ :tag=>'I0', :font=>['Times Roman', 12, :italic, :bold])
+ TkcLine.new(@canvas, [719, 119, 763, 119], :tag=>'I0', :fill=>color,
+ :width=>5, :arrow=>:last, :arrowshape=>[18, 18, 5])
+ @canvas.itembind('I0', '1'){ start }
+ end
+
+ def move0(step = nil)
+ step = get_step(0, step)
+
+ if @S['mode'].to_sym != :MSTART # Start the ball rolling
+ move_abs('I0', [-100, -100]) # Hide the banner
+ return 2
+ end
+
+ pos = [
+ [673, 119], [678, 119], [683, 119], [688, 119],
+ [693, 119], [688, 119], [683, 119], [678, 119]
+ ]
+ step = step % pos.length
+ move_abs('I0', pos[step])
+ return 1
+ end
+
+ # Dropping ball
+ def draw1
+ color = @C['1a']
+ color2 = @C['1b']
+ TkcPolygon.new(@canvas,
+ [ 844, 133, 800, 133, 800, 346, 820, 346,
+ 820, 168, 844, 168, 844, 133 ],
+ :width=>3, :fill=>color, :outline=>'')
+ TkcPolygon.new(@canvas,
+ [ 771, 133, 685, 133, 685, 168, 751, 168,
+ 751, 346, 771, 346, 771, 133 ],
+ :width=>3, :fill=>color, :outline=>'')
+ TkcOval.new(@canvas, box(812, 122, 9),
+ :tag=>'I1', :fill=>color2, :outline=>'')
+
+ @canvas.itembind('I1', '1'){ start }
+ end
+
+ def move1(step = nil)
+ step = get_step(1, step)
+ pos = [
+ [807, 122], [802, 122], [797, 123], [793, 124], [789, 129], [785, 153],
+ [785, 203], [785, 278, :x], [785, 367], [810, 392], [816, 438],
+ [821, 503], [824, 585, :y], [838, 587], [848, 593], [857, 601],
+ [-100, -100]
+ ]
+ return 0 if step >= pos.length
+ where = pos[step]
+ move_abs('I1', where)
+ move15a if where[2] == :y
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Lighting the match
+ def draw2
+ color = @C['2']
+
+ # Fulcrum
+ TkcPolygon.new(@canvas, [750, 369, 740, 392, 760, 392],
+ :fill=>@C['fg'], :outline=>@C['fg'])
+
+ # Strike box
+ TkcRectangle.new(@canvas, [628, 335, 660, 383],
+ :fill=>'', :outline=>@C['fg'])
+ (0..2).each{|y|
+ yy = 335 + y*16
+ TkcBitmap.new(@canvas, [628, yy], :bitmap=>'gray25',
+ :anchor=>:nw, :foreground=>@C['fg'])
+ TkcBitmap.new(@canvas, [644, yy], :bitmap=>'gray25',
+ :anchor=>:nw, :foreground=>@C['fg'])
+ }
+
+ # Lever
+ TkcLine.new(@canvas, [702, 366, 798, 366],
+ :fill=>@C['fg'], :width=>6, :tag=>'I2_0')
+
+ # R strap
+ TkcLine.new(@canvas, [712, 363, 712, 355],
+ :fill=>@C['fg'], :width=>3, :tag=>'I2_1')
+
+ # L strap
+ TkcLine.new(@canvas, [705, 363, 705, 355],
+ :fill=>@C['fg'], :width=>3, :tag=>'I2_2')
+
+ # Match stick
+ TkcLine.new(@canvas, [679, 356, 679, 360, 717, 360, 717, 356, 679, 356],
+ :fill=>@C['fg'], :width=>3, :tag=>'I2_3')
+
+ # Match head
+ TkcPolygon.new(@canvas,
+ [ 671, 352, 677.4, 353.9, 680, 358.5, 677.4, 363.1,
+ 671, 365, 664.6, 363.1, 662, 358.5, 664.6, 353.9 ],
+ :fill=>color, :outline=>color, :tag=>'I2_4')
+ end
+
+ def move2(step = nil)
+ step = get_step(2, step)
+
+ stages = [0, 0, 1, 2, 0, 2, 1, 0, 1, 2, 0, 2, 1]
+ xy = []
+ xy[0] = [
+ 686, 333, 692, 323, 682, 316, 674, 309, 671, 295, 668, 307,
+ 662, 318, 662, 328, 671, 336
+ ]
+ xy[1] = [
+ 687, 331, 698, 322, 703, 295, 680, 320, 668, 297, 663, 311,
+ 661, 327, 671, 335
+ ]
+ xy[2] = [
+ 686, 331, 704, 322, 688, 300, 678, 283, 678, 283, 674, 298,
+ 666, 309, 660, 324, 672, 336
+ ]
+
+ if step >= stages.length
+ @canvas.delete('I2')
+ return 0
+ end
+
+ if step == 0 # Rotate the match
+ beta = 20
+
+ ox, oy = anchor('I2_0', :s) # Where to pivot
+
+ i = 0
+ until @canvas.find_withtag("I2_#{i}").empty?
+ rotate_item("I2_#{i}", ox, oy, beta)
+ i += 1
+ end
+
+ # For the flame
+ TkcPolygon.new(@canvas, [], :tag=>'I2', :smooth=>true, :fill=>@C['2'])
+
+ return 1
+ end
+ @canvas.coords('I2', xy[stages[step]])
+ return ((step == 7)? 3: 1)
+ end
+
+ # Weight and pulleys
+ def draw3
+ color = @C['3a']
+ color2 = @C['3b']
+
+ xy = [ [602, 296], [577, 174], [518, 174] ]
+ xy.each{|x, y| # 3 Pulleys
+ TkcOval.new(@canvas, box(x, y, 13),
+ :fill=>color, :outline=>@C['fg'], :width=>3)
+ TkcOval.new(@canvas, box(x, y, 2), :fill=>@C['fg'], :outline=>@C['fg'])
+ }
+
+ # Wall to flame
+ TkcLine.new(@canvas, [750, 309, 670, 309], :tag=>'I3_s',
+ :width=>3, :fill=>@C['fg'], :smooth=>true)
+
+ # Flame to pulley 1
+ TkcLine.new(@canvas, [670, 309, 650, 309], :tag=>'I3_0',
+ :width=>3, :fill=>@C['fg'], :smooth=>true)
+ TkcLine.new(@canvas, [650, 309, 600, 309], :tag=>'I3_1',
+ :width=>3, :fill=>@C['fg'], :smooth=>true)
+
+ # Pulley 1 half way to 2
+ TkcLine.new(@canvas, [589, 296, 589, 235], :tag=>'I3_2',
+ :width=>3, :fill=>@C['fg'])
+
+ # Pulley 1 other half to 2
+ TkcLine.new(@canvas, [589, 235, 589, 174], :width=>3, :fill=>@C['fg'])
+
+ # Across the top
+ TkcLine.new(@canvas, [577, 161, 518, 161], :width=>3, :fill=>@C['fg'])
+
+ # Down to weight
+ TkcLine.new(@canvas, [505, 174, 505, 205], :tag=>'I3_w',
+ :width=>3, :fill=>@C['fg'])
+
+ # Draw the weight as 2 circles, two rectangles and 1 rounded rectangle
+ x1, y1, x2, y2 = [515, 207, 495, 207]
+ TkcOval.new(@canvas, box(x1, y1, 6),
+ :tag=>'I3_', :fill=>color2, :outline=>color2)
+ TkcOval.new(@canvas, box(x2, y2, 6),
+ :tag=>'I3_', :fill=>color2, :outline=>color2)
+ TkcRectangle.new(@canvas, x1, y1 - 6, x2, y2 + 6,
+ :tag=>'I3_', :fill=>color2, :outline=>color2)
+
+ TkcPolygon.new(@canvas, round_rect([492, 220, 518, 263], 15),
+ :smooth=>true, :tag=>'I3_', :fill=>color2, :outline=>color2)
+
+ TkcLine.new(@canvas, [500, 217, 511, 217],
+ :tag=>'I3_', :fill=>color2, :width=>10)
+
+ # Bottom weight target
+ TkcLine.new(@canvas, [502, 393, 522, 393, 522, 465],
+ :tag=>'I3__', :fill=>@C['fg'], :joinstyle=>:miter, :width=>10)
+ end
+
+ def move3(step = nil)
+ step = get_step(3, step)
+
+ pos = [ [505, 247], [505, 297], [505, 386.5], [505, 386.5] ]
+ rope = []
+ rope[0] = [750, 309, 729, 301, 711, 324, 690, 300]
+ rope[1] = [750, 309, 737, 292, 736, 335, 717, 315, 712, 320]
+ rope[2] = [750, 309, 737, 309, 740, 343, 736, 351, 725, 340]
+ rope[3] = [750, 309, 738, 321, 746, 345, 742, 356]
+
+ return 0 if step >= pos.length
+
+ @canvas.delete("I3_#{step}") # Delete part of the rope
+ move_abs('I3_', pos[step]) # Move weight down
+ @canvas.coords('I3_s', rope[step]) # Flapping rope end
+ @canvas.coords('I3_w', [505, 174].concat(pos[step]))
+ if step == 2
+ @canvas.move('I3__', 0, 30)
+ return 2
+ end
+ return 1
+ end
+
+ # Cage and door
+ def draw4
+ color = @C['4']
+ x0, y0, x1, y1 = [527, 356, 611, 464]
+
+ # Horizontal bars
+ y0.step(y1, 12){|y|
+ TkcLine.new(@canvas, [x0, y, x1, y], :fill=>color, :width=>1)
+ }
+
+ # Vertical bars
+ x0.step(x1, 12){|x|
+ TkcLine.new(@canvas, [x, y0, x, y1], :fill=>color, :width=>1)
+ }
+
+ # Swing gate
+ TkcLine.new(@canvas, [518, 464, 518, 428],
+ :tag=>'I4', :fill=>color, :width=>1)
+ end
+
+ def move4(step = nil)
+ step = get_step(4, step)
+
+ angles = [-10, -20, -30, -30]
+ return 0 if step >= angles.length
+
+ rotate_item('I4', 518, 464, angles[step])
+ @canvas.raise('I4')
+
+ return((step == 3)? 3: 1)
+ end
+
+ # Mouse
+ def draw5
+ color = @C['5a']
+ color2 = @C['5b']
+
+ xy = [377, 248, 410, 248, 410, 465, 518, 465] # Mouse course
+ xy.concat [518, 428, 451, 428, 451, 212, 377, 212]
+
+ TkcPolygon.new(@canvas, xy, :fill=>color2, :outline=>@C['fg'], :width=>3)
+
+ xy = [
+ 534.5, 445.5, 541, 440, 552, 436, 560, 436, 569, 440, 574, 446,
+ 575, 452, 574, 454, 566, 456, 554, 456, 545, 456, 537, 454, 530, 452
+ ]
+ TkcPolygon.new(@canvas, xy, :tag=>['I5', 'I5_0'], :fill=>color)
+
+ TkcLine.new(@canvas, [573, 452, 592, 458, 601, 460, 613, 456], # Tail
+ :tag=>['I5', 'I5_1'], :fill=>color, :smooth=>true, :width=>3)
+
+ xy = box(540, 446, 2) # Eye
+ xy = [540, 444, 541, 445, 541, 447, 540, 448, 538, 447, 538, 445]
+ TkcPolygon.new(@canvas, xy, :tag=>['I5', 'I5_2'], :fill=>@C['bg'],
+ :outline=>'', :smooth=>true)
+
+ xy = [538, 454, 535, 461] # Front leg
+ TkcLine.new(@canvas, xy, :tag=>['I5', 'I5_3'], :fill=>color, :width=>2)
+
+ xy = [566, 455, 569, 462] # Back leg
+ TkcLine.new(@canvas, xy, :tag=>['I5', 'I5_4'], :fill=>color, :width=>2)
+
+ xy = [544, 455, 545, 460] # 2nd front leg
+ TkcLine.new(@canvas, xy, :tag=>['I5', 'I5_5'], :fill=>color, :width=>2)
+
+ xy = [560, 455, 558, 460] # 2nd back leg
+ TkcLine.new(@canvas, xy, :tag=>['I5', 'I5_6'], :fill=>color, :width=>2)
+ end
+
+ def move5(step = nil)
+ step = get_step(5, step)
+
+ pos = [
+ [553, 452], [533, 452], [513, 452], [493, 452], [473, 452],
+ [463, 442, 30], [445.5, 441.5, 30], [425.5, 434.5, 30], [422, 414],
+ [422, 394], [422, 374], [422, 354], [422, 334], [422, 314], [422, 294],
+ [422, 274, -30], [422, 260.5, -30, :x], [422.5, 248.5, -28], [425, 237]
+ ]
+
+ return 0 if step >= pos.length
+
+ x, y, beta, nxt = pos[step]
+ move_abs('I5', [x, y])
+ if beta
+ ox, oy = centroid('I5_0')
+ (0..6).each{|id| rotate_item("I5_#{id}", ox, oy, beta) }
+ end
+ return 3 if nxt == :x
+ return 1
+ end
+
+ # Dropping gumballs
+ def draw6
+ color = @C['6']
+ xy = [324, 130, 391, 204] # Ball holder
+ xy = round_rect(xy, 10)
+ TkcPolygon.new(@canvas, xy, :smooth=>true,
+ :outline=>@C['fg'], :width=>3, :fill=>color)
+ xy = [339, 204, 376, 253] # Below the ball holder
+ TkcRectangle.new(@canvas, xy, :outline=>@C['fg'], :width=>3,
+ :fill=>color, :tag=>'I6c')
+ xy = box(346, 339, 28)
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'') # Roter
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>2, :style=>:arc,
+ :start=>80, :extent=>205)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>2, :style=>:arc,
+ :start=>-41, :extent=>85)
+
+ xy = box(346, 339, 15) # Center of rotor
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>@C['fg'], :tag=>'I6m')
+ xy = [352, 312, 352, 254, 368, 254, 368, 322] # Top drop to rotor
+ TkcPolygon.new(@canvas, xy, :fill=>color, :outline=>'')
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2)
+
+ xy = [353, 240, 367, 300] # Poke bottom hole
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>'')
+ xy = [341, 190, 375, 210] # Poke another hole
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>'')
+
+ xy = [
+ 368, 356, 368, 403, 389, 403, 389, 464, 320, 464, 320, 403,
+ 352, 403, 352, 366
+ ]
+ TkcPolygon.new(@canvas, xy, :fill=>color, :outline=>'',
+ :width=>2) # Below rotor
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2)
+ xy = box(275, 342, 7) # On/off rotor
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>@C['fg'])
+ xy = [276, 334, 342, 325] # Fan belt top
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = [276, 349, 342, 353] # Fan belt bottom
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+
+ xy = [337, 212, 337, 247] # What the mouse pushes
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I6_')
+ xy = [392, 212, 392, 247]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I6_')
+ xy = [337, 230, 392, 230]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>7, :tag=>'I6_')
+
+ who = -1 # All the balls
+ colors = %w(red cyan orange green blue darkblue)
+ colors *= 3
+
+ (0..16).each{|i|
+ loc = -i
+ color = colors[i]
+ x, y = @XY6["#{loc}"]
+ TkcOval.new(@canvas, box(x, y, 5),
+ :fill=>color, :outline=>color, :tag=>"I6_b#{i}")
+ }
+ draw6a(12) # The wheel
+ end
+
+ def draw6a(beta)
+ @canvas.delete('I6_0')
+ ox, oy = [346, 339]
+ (0..3).each{|i|
+ b = beta + i * 45
+ x, y = rotate_c(28, 0, 0, 0, b)
+ xy = [ox + x, oy + y, ox - x, oy - y]
+ TkcLine.new(@canvas, xy, :tag=>'I6_0', :fill=>@C['fg'], :width=>2)
+ }
+ end
+
+ def move6(step = nil)
+ step = get_step(6, step)
+
+ return 0 if step > 62
+
+ if step < 2 # Open gate for balls to drop
+ @canvas.move('I6_', -7, 0)
+ if step == 1 # Poke a hole
+ xy = [348, 226, 365, 240]
+ TkcRectangle.new(@canvas, xy, :fill=>@canvas.itemcget('I6c', :fill),
+ :outline=>'')
+ end
+ return 1
+ end
+
+ s = step - 1 # Do the gumball drop dance
+ (0..(((s - 1)/3).to_i)).each{|i|
+ tag = "I6_b#{i}"
+ break if @canvas.find_withtag(tag).empty?
+ loc = s - 3*i
+
+ if @XY6["#{loc},#{i}"]
+ move_abs(tag, @XY6["#{loc},#{i}"])
+ elsif @XY6["#{loc}"]
+ move_abs(tag, @XY6["#{loc}"])
+ end
+ }
+ if s % 3 == 1
+ first = (s + 2)/3
+ i = first
+ loop {
+ tag = "I6_b#{i}"
+ break if @canvas.find_withtag(tag).empty?
+ loc = first - i
+ move_abs(tag, @XY6["#{loc}"])
+ i += 1
+ }
+ end
+ if s >= 3 # Rotate the motor
+ idx = s % 3
+ draw6a(12 + s * 15)
+ end
+ return((s == 3)? 3 : 1)
+ end
+
+ # On/off switch
+ def draw7
+ color = @C['7']
+ xy = [198, 306, 277, 374] # Box
+ TkcRectangle.new(@canvas, xy, :outline=>@C['fg'], :width=>2,
+ :fill=>color, :tag=>'I7z')
+ @canvas.lower('I7z')
+ xy = [275, 343, 230, 349]
+ TkcLine.new(@canvas, xy, :tag=>'I7', :fill=>@C['fg'], :arrow=>:last,
+ :arrowshape=>[23, 23, 8], :width=>6)
+ xy = [225, 324] # On button
+ x, y = xy
+ TkcOval.new(@canvas, box(x, y, 3), :fill=>@C['fg'], :outline=>@C['fg'])
+ xy = [218, 323] # On text
+ font = ['Times Roman', 8]
+ TkcText.new(@canvas, xy, :text=>'on', :anchor=>:e,
+ :fill=>@C['fg'], :font=>font)
+ xy = [225, 350] # Off button
+ x, y = xy
+ TkcOval.new(@canvas, box(x, y, 3), :fill=>@C['fg'], :outline=>@C['fg'])
+ xy = [218, 349] # Off text
+ TkcText.new(@canvas, xy, :text=>'off', :anchor=>:e,
+ :fill=>@C['fg'], :font=>font)
+ end
+
+ def move7(step = nil)
+ step = get_step(7, step)
+
+ numsteps = 30
+ return 0 if step > numsteps
+ beta = 30.0 / numsteps
+ rotate_item('I7', 275, 343, beta)
+
+ return((step == numsteps)? 3: 1)
+ end
+
+ # Electricity to the fan
+ def draw8
+ sine([271, 248, 271, 306], 5, 8, :tag=>'I8_s', :fill=>@C['8'], :width=>3)
+ end
+
+ def move8(step = nil)
+ step = get_step(8, step)
+
+ return 0 if step > 3
+ if step == 0
+ sparkle(anchor('I8_s', :s), 'I8')
+ return 1
+ elsif step == 1
+ move_abs('I8', anchor('I8_s', :c))
+ elsif step == 2
+ move_abs('I8', anchor('I8_s', :n))
+ else
+ @canvas.delete('I8')
+ end
+ return((step == 2)? 3: 1)
+ end
+
+ # Fan
+ def draw9
+ color = @C['9']
+ xy = [266, 194, 310, 220]
+ TkcOval.new(@canvas, xy, :outline=>color, :fill=>color)
+ xy = [280, 209, 296, 248]
+ TkcOval.new(@canvas, xy, :outline=>color, :fill=>color)
+ xy = [
+ 288, 249, 252, 249, 260, 240, 280, 234,
+ 296, 234, 316, 240, 324, 249, 288, 249
+ ]
+ TkcPolygon.new(@canvas, xy, :fill=>color, :smooth=>true)
+
+ xy = [248, 205, 265, 214, 264, 205, 265, 196] # Spinner
+ TkcPolygon.new(@canvas, xy, :fill=>color)
+
+ xy = [255, 206, 265, 234] # Fan blades
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'],
+ :width=>3, :tag=>'I9_0')
+ xy = [255, 176, 265, 204]
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'],
+ :width=>3, :tag=>'I9_0')
+ xy = [255, 206, 265, 220]
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'],
+ :width=>1, :tag=>'I9_1')
+ xy = [255, 190, 265, 204]
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'],
+ :width=>1, :tag=>'I9_1')
+ end
+
+ def move9(step = nil)
+ step = get_step(9, step)
+
+ if (step & 1).nonzero?
+ @canvas.itemconfigure('I9_0', :width=>4)
+ @canvas.itemconfigure('I9_1', :width=>1)
+ @canvas.lower('I9_1', 'I9_0')
+ else
+ @canvas.itemconfigure('I9_0', :width=>1)
+ @canvas.itemconfigure('I9_1', :width=>4)
+ @canvas.lower('I9_0', 'I9_1')
+ end
+ return 3 if step == 0
+ return 1
+ end
+
+ # Boat
+ def draw10
+ color = @C['10a']
+ color2 = @C['10b']
+ xy = [191, 230, 233, 230, 233, 178, 191, 178] # Sail
+ TkcPolygon.new(@canvas, xy, :fill=>color, :width=>3, :outline=>@C['fg'],
+ :tag=>'I10')
+ xy = box(209, 204, 31) # Front
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :style=>:pie,
+ :start=>120, :extent=>120, :tag=>'I10')
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>120, :extent=>120, :tag=>'I10')
+ xy = box(249, 204, 31) # Back
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>@C['bg'], :width=>3,
+ :style=>:pie, :start=>120, :extent=>120, :tag=>'I10')
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>120, :extent=>120, :tag=>'I10')
+
+ xy = [200, 171, 200, 249] # Mast
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I10')
+ xy = [159, 234, 182, 234] # Bow sprit
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I10')
+ xy = [180, 234, 180, 251, 220, 251] # Hull
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>6, :tag=>'I10')
+
+ xy = [92, 255, 221, 255] # Waves
+ sine(xy, 2, 25, :fill=>color2, :width=>1, :tag=>'I10w')
+
+ xy = @canvas.coords('I10w')[4..-5] # Water
+ xy.concat([222, 266, 222, 277, 99, 277])
+ TkcPolygon.new(@canvas, xy, :fill=>color2, :outline=>color2)
+ xy = [222, 266, 222, 277, 97, 277, 97, 266] # Water bottom
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+
+ xy = box(239, 262, 17)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>95, :extent=>103)
+ xy = box(76, 266, 21)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :extent=>190)
+ end
+
+ def move10(step = nil)
+ step = get_step(10, step)
+
+ pos = [
+ [195, 212], [193, 212], [190, 212], [186, 212], [181, 212], [176, 212],
+ [171, 212], [166, 212], [161, 212], [156, 212], [151, 212], [147, 212],
+ [142, 212], [137, 212], [132, 212, :x], [127, 212], [121, 212],
+ [116, 212], [111, 212]
+ ]
+
+ return 0 if step >= pos.length
+
+ where = pos[step]
+ move_abs('I10', where)
+
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # 2nd ball drop
+ def draw11
+ color = @C['11a']
+ color2 = @C['11b']
+ xy = [23, 264, 55, 591] # Color the down tube
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>'')
+ xy = box(71, 460, 48) # Color the outer loop
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'')
+
+ xy = [55, 264, 55, 458] # Top right side
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = [55, 504, 55, 591] # Bottom right side
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = box(71, 460, 48) # Outer loop
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>110, :extent=>-290, :tag=>'I11i')
+ xy = box(71, 460, 16) # Inner loop
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>'',
+ :width=>3, :tag=>'I11i')
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>@C['bg'], :width=>3)
+
+ xy = [23, 264, 23, 591] # Left side
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = box(1, 266, 23) # Top left curve
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3,
+ :style=>:arc, :extent=>90)
+
+ xy = box(75, 235, 9) # The ball
+ TkcOval.new(@canvas, xy, :fill=>color2, :outline=>'',
+ :width=>3, :tag=>'I11')
+ end
+
+ def move11(step = nil)
+ step = get_step(11, step)
+
+ pos = [
+ [75, 235], [70, 235], [65, 237], [56, 240], [46, 247], [38, 266],
+ [38, 296], [38, 333], [38, 399], [38, 475], [74, 496], [105, 472],
+ [100, 437], [65, 423], [-100, -100], [38, 505], [38, 527, :x], [38, 591]
+ ]
+
+ return 0 if step >= pos.length
+ where = pos[step]
+ move_abs('I11', where)
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Hand
+ def draw12
+ xy = [
+ 20, 637, 20, 617, 20, 610, 20, 590, 40, 590, 40, 590,
+ 60, 590, 60, 610, 60, 610
+ ]
+ xy.concat([60, 610, 65, 620, 60, 631]) # Thumb
+ xy.concat([60, 631, 60, 637, 60, 662, 60, 669, 52, 669,
+ 56, 669, 50, 669, 50, 662, 50, 637])
+
+ y0 = 637 # Bumps for fingers
+ y1 = 645
+ 50.step(21, -10){|x|
+ x1 = x - 5
+ x2 = x - 10
+ xy << x << y0 << x1 << y1 << x2 << y0
+ }
+ TkcPolygon.new(@canvas, xy, :fill=>@C['12'], :outline=>@C['fg'],
+ :smooth=>true, :tag=>'I12', :width=>3)
+ end
+
+ def move12(step = nil)
+ step = get_step(12, step)
+
+ pos = [[42.5, 641, :x]]
+ return 0 if step >= pos.length
+ where = pos[step]
+ move_abs('I12', where)
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Fax
+ def draw13
+ color = @C['13a']
+ xy = [86, 663, 149, 663, 149, 704, 50, 704, 50, 681, 64, 681, 86, 671]
+ xy2 = [
+ 784, 663, 721, 663, 721, 704, 820, 704, 820, 681, 806, 681, 784, 671
+ ]
+ radii = [2, 9, 9, 8, 5, 5, 2]
+
+ round_poly(@canvas, xy, radii, :width=>3,
+ :outline=>@C['fg'], :fill=>color)
+ round_poly(@canvas, xy2, radii, :width=>3,
+ :outline=>@C['fg'], :fill=>color)
+
+ xy = [56, 677]
+ x, y = xy
+ TkcRectangle.new(@canvas, box(x, y, 4), :fill=>'', :outline=>@C['fg'],
+ :width=>3, :tag=>'I13')
+ xy = [809, 677]
+ x, y = xy
+ TkcRectangle.new(@canvas, box(x, y, 4), :fill=>'', :outline=>@C['fg'],
+ :width=>3, :tag=>'I13R')
+
+ xy = [112, 687] # Label
+ TkcText.new(@canvas, xy, :text=>'FAX', :fill=>@C['fg'],
+ :font=>['Times Roman', 12, :bold])
+ xy = [762, 687]
+ TkcText.new(@canvas, xy, :text=>'FAX', :fill=>@C['fg'],
+ :font=>['Times Roman', 12, :bold])
+
+ xy = [138, 663, 148, 636, 178, 636] # Paper guide
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>@C['fg'], :width=>3)
+ xy = [732, 663, 722, 636, 692, 636]
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>@C['fg'], :width=>3)
+
+ sine([149, 688, 720, 688], 5, 15,
+ :tag=>'I13_s', :fill=>@C['fg'], :width=>3)
+ end
+
+ def move13(step = nil)
+ step = get_step(13, step)
+
+ numsteps = 7
+
+ if step == numsteps + 2
+ move_abs('I13_star', [-100, -100])
+ @canvas.itemconfigure('I13R', :fill=>@C['13b'], :width=>2)
+ return 2
+ end
+ if step == 0 # Button down
+ @canvas.delete('I13')
+ sparkle([-100, -100], 'I13_star') # Create off screen
+ return 1
+ end
+ x0, y0 = anchor('I13_s', :w)
+ x1, y1 = anchor('I13_s', :e)
+ x = x0 + (x1 - x0) * (step - 1) / numsteps.to_f
+ move_abs('I13_star', [x, y0])
+ return 1
+ end
+
+ # Paper in fax
+ def draw14
+ color = @C['14']
+ xy = [102, 661, 113, 632, 130, 618] # Left paper edge
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>color,
+ :width=>3, :tag=>'I14L_0')
+ xy = [148, 629, 125, 640, 124, 662] # Right paper edge
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>color,
+ :width=>3, :tag=>'I14L_1')
+ draw14a('L')
+
+ xy = [
+ 768.0, 662.5, 767.991316225, 662.433786215, 767.926187912, 662.396880171
+ ]
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>color,
+ :width=>3, :tag=>'I14R_0')
+ @canvas.lower('I14R_0')
+ # NB. these numbers are VERY sensitive, you must start with final size
+ # and shrink down to get the values
+ xy = [
+ 745.947897349, 662.428358855, 745.997829056, 662.452239237, 746.0, 662.5
+ ]
+ TkcLine.new(@canvas, xy, :smooth=>true, :fill=>color,
+ :width=>3, :tag=>'I14R_1')
+ @canvas.lower('I14R_1')
+ end
+
+ def draw14a(side)
+ color = @C['14']
+ xy = @canvas.coords("I14#{side}_0")
+ xy2 = @canvas.coords("I14#{side}_1")
+ x0, y0, x1, y1, x2, y2 = xy
+ x3, y3, x4, y4, x5, y5 = xy2
+
+ zz = [
+ x0, y0, x0, y0, xy, x2, y2, x2, y2,
+ x3, y3, x3, y3, xy2, x5, y5, x5, y5
+ ].flatten
+ @canvas.delete("I14#{side}")
+ TkcPolygon.new(@canvas, zz, :tag=>"I14#{side}", :smooth=>true,
+ :fill=>color, :outline=>color, :width=>3)
+ @canvas.lower("I14#{side}")
+ end
+
+ def move14(step = nil)
+ step = get_step(14, step)
+
+ # Paper going down
+ sc = 0.9 - 0.05*step
+ if sc < 0.3
+ @canvas.delete('I14L')
+ return 0
+ end
+
+ ox, oy = @canvas.coords('I14L_0')
+ @canvas.scale('I14L_0', ox, oy, sc, sc)
+ ox, oy = @canvas.coords('I14L_1')[-2..-1]
+ @canvas.scale('I14L_1', ox, oy, sc, sc)
+ draw14a('L')
+
+ # Paper going up
+ sc = 0.35 + 0.05*step
+ sc = 1/sc
+
+ ox, oy = @canvas.coords('I14R_0')
+ @canvas.scale('I14R_0', ox, oy, sc, sc)
+ ox, oy = @canvas.coords('I14R_1')[-2..-1]
+ @canvas.scale('I14R_1', ox, oy, sc, sc)
+ draw14a('R')
+
+ return((step == 10)? 3: 1)
+ end
+
+ # Light beam
+ def draw15
+ color = @C['15a']
+ xy = [824, 599, 824, 585, 820, 585, 829, 585]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I15a')
+ xy = [789, 599, 836, 643]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>3)
+ xy = [778, 610, 788, 632]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>3)
+ xy = [766, 617, 776, 625]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>3)
+
+ xy = [633, 600, 681, 640]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>3)
+ xy = [635, 567, 657, 599]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>2)
+ xy = [765, 557, 784, 583]
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>2)
+
+ sine([658, 580, 765, 580], 3, 15,
+ :tag=>'I15_s', :fill=>@C['fg'], :width=>3)
+ end
+
+ def move15a
+ color = @C['15b']
+ @canvas.scale('I15a', 824, 599, 1, 0.3) # Button down
+ xy = [765, 621, 681, 621]
+ TkcLine.new(@canvas, xy, :dash=>'-', :width=>3, :fill=>color, :tag=>'I15')
+ end
+
+ def move15(step = nil)
+ step = get_step(15, step)
+
+ numsteps = 6
+
+ if step == numsteps + 2
+ move_abs('I15_star', [-100, -100])
+ return 2
+ end
+ if step == 0 # Break the light beam
+ sparkle([-100, -100], 'I15_star')
+ xy = [765, 621, 745, 621]
+ @canvas.coords('I15', xy)
+ return 1
+ end
+ x0, y0 = anchor('I15_s', :w)
+ x1, y1 = anchor('I15_s', :e)
+ x = x0 + (x1 - x0) * (step - 1) / numsteps.to_f
+ move_abs('I15_star', [x, y0])
+ return 1
+ end
+
+ # Bell
+ def draw16
+ color = @C['16']
+ xy = [722, 485, 791, 556]
+ TkcRectangle.new(@canvas, xy, :fill=>'', :outline=>@C['fg'], :width=>3)
+ xy = box(752, 515, 25) # Bell
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'black',
+ :tag=>'I16b', :width=>2)
+ xy = box(752, 515, 5) # Bell button
+ TkcOval.new(@canvas, xy, :fill=>'black', :outline=>'black', :tag=>'I16b')
+
+ xy = [784, 523, 764, 549] # Clapper
+ TkcLine.new(@canvas, xy, :width=>3, :tag=>'I16c', :fill=>@C['fg'])
+ xy = box(784, 523, 4)
+ TkcOval.new(@canvas, xy, :fill=>@C['fg'], :outline=>@C['fg'], :tag=>'I16d')
+ end
+
+ def move16(step = nil)
+ step = get_step(16, step)
+
+ # Note: we never stop
+ ox, oy = [760, 553]
+ if (step & 1).nonzero?
+ beta = 12
+ @canvas.move('I16b', 3, 0)
+ else
+ beta = -12
+ @canvas.move('I16b', -3, 0)
+ end
+ rotate_item('I16c', ox, oy, beta)
+ rotate_item('I16d', ox, oy, beta)
+
+ return ((step == 1)? 3: 1)
+ end
+
+ # Cat
+ def draw17
+ color = @C['17']
+
+ xy = [584, 556, 722, 556]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+ xy = [584, 485, 722, 485]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3)
+
+ xy = [664, 523, 717, 549] # Body
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :fill=>color, :width=>3,
+ :style=>:chord, :start=>128, :extent=>260, :tag=>'I17')
+
+ xy = [709, 554, 690, 543] # Paw
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>color,
+ :width=>3, :tag=>'I17')
+ xy = [657, 544, 676, 555]
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :fill=>color,
+ :width=>3, :tag=>'I17')
+
+ xy = box(660, 535, 15) # Lower face
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :style=>:arc,
+ :start=>150, :extent=>240, :tag=>'I17_')
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :width=>1,
+ :style=>:chord, :start=>150, :extent=>240, :tag=>'I17_')
+ xy = [674, 529, 670, 513, 662, 521, 658, 521, 650, 513, 647, 529] # Ears
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ TkcPolygon.new(@canvas, xy, :fill=>color, :outline=>'', :width=>1,
+ :tag=>['I17_', 'I17_c'])
+ xy = [652, 542, 628, 539] # Whiskers
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [652, 543, 632, 545]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [652, 546, 632, 552]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+
+ xy = [668, 543, 687, 538]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :tag=>['I17_', 'I17_w'])
+ xy = [668, 544, 688, 546]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :tag=>['I17_', 'I17_w'])
+ xy = [668, 547, 688, 553]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :tag=>['I17_', 'I17_w'])
+
+ xy = [649, 530, 654, 538, 659, 530] # Left eye
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2,
+ :smooth=>true, :tag=>'I17')
+ xy = [671, 530, 666, 538, 661, 530] # Right eye
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2,
+ :smooth=>true, :tag=>'I17')
+ xy = [655, 543, 660, 551, 665, 543] # Mouth
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2,
+ :smooth=>true, :tag=>'I17')
+ end
+
+ def move17(step = nil)
+ step = get_step(17, step)
+
+ if step == 0
+ @canvas.delete('I17') # Delete most of the cat
+ xy = [655, 543, 660, 535, 665, 543] # Mouth
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :smooth=>true, :tag=>'I17_')
+ xy = box(654, 530, 4) # Left eye
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :fill=>'',
+ :tag=>'I17_')
+ xy = box(666, 530, 4) # Right eye
+ TkcOval.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :fill=>'',
+ :tag=>'I17_')
+
+ @canvas.move('I17_', 0, -20) # Move face up
+ xy = [652, 528, 652, 554] # Front leg
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [670, 528, 670, 554] # 2nd front leg
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+
+ xy = [ # Body
+ 675, 506, 694, 489, 715, 513, 715, 513, 715, 513, 716, 525,
+ 716, 525, 716, 525, 706, 530, 695, 530, 679, 535, 668, 527,
+ 668, 527, 668, 527, 675, 522, 676, 517, 677, 512
+ ]
+ TkcPolygon.new(@canvas, xy, :fill=>@canvas.itemcget('I17_c', :fill),
+ :outline=>@C['fg'], :width=>3, :smooth=>true,
+ :tag=>'I17_')
+ xy = [716, 514, 716, 554] # Back leg
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [694, 532, 694, 554] # 2nd back leg
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I17_')
+ xy = [715, 514, 718, 506, 719, 495, 716, 488] # Tail
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3,
+ :smooth=>true, :tag=>'I17_')
+
+ @canvas.raise('I17w') # Make whiskers visible
+ @canvas.move('I17_', -5, 0) # Move away from the wall a bit
+ return 2
+ end
+ return 0
+ end
+
+ # Sling shot
+ def draw18
+ color = @C['18']
+ xy = [721, 506, 627, 506] # Sling hold
+ TkcLine.new(@canvas, xy, :width=>4, :fill=>@C['fg'], :tag=>'I18')
+
+ xy = [607, 500, 628, 513] # Sling rock
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'', :tag=>'I18a')
+
+ xy = [526, 513, 606, 507, 494, 502] # Sling band
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>4, :tag=>'I18b')
+ xy = [485, 490, 510, 540, 510, 575, 510, 540, 535, 491] # Sling
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>6)
+ end
+
+ def move18(step = nil)
+ step = get_step(18, step)
+
+ pos = [
+ [587, 506], [537, 506], [466, 506], [376, 506], [266, 506, :x],
+ [136, 506], [16, 506], [-100, -100]
+ ]
+
+ b = []
+ b[0] = [490, 502, 719, 507, 524, 512] # Band collapsing
+ b[1] = [
+ 491, 503, 524, 557, 563, 505, 559, 496, 546, 506, 551, 525,
+ 553, 536, 538, 534, 532, 519, 529, 499
+ ]
+ b[2] = [
+ 491, 503, 508, 563, 542, 533, 551, 526, 561, 539, 549, 550, 530, 500
+ ]
+ b[3] = [
+ 491, 503, 508, 563, 530, 554, 541, 562, 525, 568, 519, 544, 530, 501
+ ]
+
+ return 0 if step >= pos.length
+
+ if step == 0
+ @canvas.delete('I18')
+ @canvas.itemconfigure('I18b', :smooth=>true)
+ end
+ if b[step]
+ @canvas.coords('I18b', b[step])
+ end
+
+ where = pos[step]
+ move_abs('I18a', where)
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Water pipe
+ def draw19
+ color = @C['19']
+ xx = [[249, 181], [155, 118], [86, 55], [22, 0]]
+ xx.each{|x1, x2|
+ TkcRectangle.new(@canvas, x1, 453, x2, 467,
+ :fill=>color, :outline=>'', :tag=>'I19')
+ TkcLine.new(@canvas, x1, 453, x2, 453,
+ :fill=>@C['fg'], :width=>1) # Pipe top
+ TkcLine.new(@canvas, x1, 467, x2, 467,
+ :fill=>@C['fg'], :width=>1) # Pipe bottom
+ }
+ @canvas.raise('I11i')
+
+ xy = box(168, 460, 16) # Bulge by the joint
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'')
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1, :style=>:arc,
+ :start=>21, :extent=>136)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1, :style=>:arc,
+ :start=>-21, :extent=>-130)
+
+ xy = [249, 447, 255, 473] # First joint 26x6
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+
+ xy = box(257, 433, 34) # Bend up
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :width=>1,
+ :style=>:pie, :start=>0, :extent=>-91)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>0, :extent=>-90)
+ xy = box(257, 433, 20)
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>@C['bg'], :width=>1,
+ :style=>:pie, :start=>0, :extent=>-92)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>0, :extent=>-90)
+ xy = box(257, 421, 34) # Bend left
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :width=>1,
+ :style=>:pie, :start=>0, :extent=>91)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>0, :extent=>90)
+ xy = box(257, 421, 20)
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>@C['bg'], :width=>1,
+ :style=>:pie, :start=>0, :extent=>90)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>0, :extent=>90)
+ xy = box(243, 421, 34) # Bend down
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>color, :width=>1,
+ :style=>:pie, :start=>90, :extent=>90)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>90, :extent=>90)
+ xy = box(243, 421, 20)
+ TkcArc.new(@canvas, xy, :outline=>'', :fill=>@C['bg'], :width=>1,
+ :style=>:pie, :start=>90, :extent=>90)
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>1,
+ :style=>:arc, :start=>90, :extent=>90)
+
+ xy = [270, 427, 296, 433] # 2nd joint bottom
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+ xy = [270, 421, 296, 427] # 2nd joint top
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+ xy = [249, 382, 255, 408] # Third joint right
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+ xy = [243, 382, 249, 408] # Third joint left
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+ xy = [203, 420, 229, 426] # Last joint
+ TkcRectangle.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>1)
+
+ xy = box(168, 460, 6) # Handle joint
+ TkcOval.new(@canvas, xy, :fill=>@C['fg'], :outline=>'', :tag=>'I19a')
+ xy = [168, 460, 168, 512] # Handle bar
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>5, :tag=>'I19b')
+ end
+
+ def move19(step = nil)
+ step = get_step(19, step)
+
+ angles = [30, 30, 30]
+ return 2 if step == angles.length
+ ox, oy = centroid('I19a')
+ rotate_item('I19b', ox, oy, angles[step])
+
+ return 1
+ end
+
+ # Water pouring
+ def draw20
+ # do nothing
+ end
+
+ def move20(step = nil)
+ step = get_step(20, step)
+
+ pos = [451, 462, 473, 484, 496, 504, 513, 523, 532]
+ freq = [20, 40, 40, 40, 40, 40, 40, 40, 40]
+ pos = [
+ [451, 20], [462, 40], [473, 40], [484, 40], [496, 40],
+ [504, 40], [513, 40], [523, 40], [532, 40, :x]
+ ]
+ return 0 if step >= pos.length
+
+ @canvas.delete('I20')
+ where = pos[step]
+ y, f = where
+ h20(y, f)
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ def h20(y, f)
+ color = @C['20']
+ @canvas.delete('I20')
+
+ sine([208, 428, 208, y], 4, f, :tag=>['I20', 'I20s'],
+ :width=>3, :fill=>color, :smooth=>true)
+ TkcLine.new(@canvas, @canvas.coords('I20s'), :width=>3,
+ :fill=>color, :smooth=>1, :tag=>['I20', 'I20a'])
+ TkcLine.new(@canvas, @canvas.coords('I20s'), :width=>3,
+ :fill=>color, :smooth=>1, :tag=>['I20', 'I20b'])
+ @canvas.move('I20a', 8, 0)
+ @canvas.move('I20b', 16, 0)
+ end
+
+ # Bucket
+ def draw21
+ color = @C['21']
+ xy = [217, 451, 244, 490] # Right handle
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2, :tag=>'I21_a')
+ xy = [201, 467, 182, 490] # Left handle
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2, :tag=>'I21_a')
+
+ xy = [245, 490, 237, 535] # Right side
+ xy2 = [189, 535, 181, 490] # Left side
+ TkcPolygon.new(@canvas, xy + xy2, :fill=>color, :outline=>'',
+ :tag=>['I21', 'I21f'])
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>2, :tag=>'I21')
+ TkcLine.new(@canvas, xy2, :fill=>@C['fg'], :width=>2, :tag=>'I21')
+
+ xy = [182, 486, 244, 498] # Top
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>'', :width=>2,
+ :tag=>['I21', 'I21f'])
+ TkcOval.new(@canvas, xy, :fill=>'', :outline=>@C['fg'], :width=>2,
+ :tag=>['I21', 'I21t'])
+ xy = [189, 532, 237, 540] # Bottom
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>@C['fg'], :width=>2,
+ :tag=>['I21', 'I21b'])
+ end
+
+ def move21(step = nil)
+ step = get_step(21, step)
+
+ numsteps = 30
+ return 0 if step >= numsteps
+
+ x1, y1, x2, y2 = @canvas.coords('I21b')
+ # lx1, ly1, lx2, ly2 = @canvas.coords('I21t')
+ lx1, ly1, lx2, ly2 = [183, 492, 243, 504]
+
+ f = step / numsteps.to_f
+ y2 = y2 - 3
+ xx1 = x1 + (lx1 - x1) * f
+ yy1 = y1 + (ly1 - y1) * f
+ xx2 = x2 + (lx2 - x2) * f
+ yy2 = y2 + (ly2 - y2) * f
+
+ @canvas.itemconfigure('I21b', :fill=>@C['20'])
+ @canvas.delete('I21w')
+ TkcPolygon.new(@canvas, x2, y2, x1, y1, xx1, yy1, xx2, yy1,
+ :tag=>['I21', 'I21w'], :outline=>'', :fill=>@C['20'])
+ @canvas.lower('I21w', 'I21')
+ @canvas.raise('I21b')
+ @canvas.lower('I21f')
+
+ return((step == numsteps - 1)? 3: 1)
+ end
+
+ # Bucket drop
+ def draw22
+ # do nothing
+ end
+
+ def move22(step = nil)
+ step = get_step(22, step)
+ pos = [[213, 513], [213, 523], [213, 543, :x], [213, 583], [213, 593]]
+
+ @canvas.itemconfigure('I21f', :fill=>@C['22']) if step == 0
+ return 0 if step >= pos.length
+ where = pos[step]
+ move_abs('I21', where)
+ h20(where[1], 40)
+ @canvas.delete('I21_a') # Delete handles
+
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Blow dart
+ def draw23
+ color = @C['23a']
+ color2 = @C['23b']
+ color3 = @C['23c']
+
+ xy = [185, 623, 253, 650] # Block
+ TkcRectangle.new(@canvas, xy, :fill=>'black', :outline=>@C['fg'],
+ :width=>2, :tag=>'I23a')
+ xy = [187, 592, 241, 623] # Balloon
+ TkcOval.new(@canvas, xy, :outline=>'', :fill=>color, :tag=>'I23b')
+ TkcArc.new(@canvas, xy, :outline=>@C['fg'], :width=>3, :tag=>'I23b',
+ :style=>:arc, :start=>12, :extent=>336)
+ xy = [239, 604, 258, 589, 258, 625, 239, 610] # Balloon nozzle
+ TkcPolygon.new(@canvas, xy, :outline=>'', :fill=>color, :tag=>'I23b')
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I23b')
+
+ xy = [285, 611, 250, 603] # Dart body
+ TkcOval.new(@canvas, xy, :fill=>color2, :outline=>@C['fg'],
+ :width=>3, :tag=>'I23d')
+ xy = [249, 596, 249, 618, 264, 607, 249, 596] # Dart tail
+ TkcPolygon.new(@canvas, xy, :fill=>color3, :outline=>@C['fg'],
+ :width=>3, :tag=>'I23d')
+ xy = [249, 607, 268, 607] # Dart detail
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I23d')
+ xy = [285, 607, 305, 607] # Dart needle
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I23d')
+ end
+
+ def move23(step = nil)
+ step = get_step(23, step)
+
+ pos = [
+ [277, 607], [287, 607], [307, 607, :x], [347, 607], [407, 607],
+ [487, 607], [587, 607], [687, 607], [787, 607], [-100, -100]
+ ]
+
+ return 0 if step >= pos.length
+ if step <= 1
+ ox, oy = anchor('I23a', :n)
+ @canvas.scale('I23b', ox, oy, 0.9, 0.5)
+ end
+ where = pos[step]
+ move_abs('I23d', where)
+
+ return 3 if where[2] == :x
+ return 1
+ end
+
+ # Balloon
+ def draw24
+ color = @C['24a']
+ xy = [366, 518, 462, 665] # Balloon
+ TkcOval.new(@canvas, xy, :fill=>color, :outline=>@C['fg'],
+ :width=>3, :tag=>'I24')
+ xy = [414, 666, 414, 729] # String
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :width=>3, :tag=>'I24')
+ xy = [410, 666, 404, 673, 422, 673, 418, 666] # Nozzle
+ TkcPolygon.new(@canvas, xy, :fill=>color, :outline=>@C['fg'],
+ :width=>3, :tag=>'I24')
+
+ xy = [387, 567, 390, 549, 404, 542] # Reflections
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :smooth=>true,
+ :width=>2, :tag=>'I24')
+ xy = [395, 568, 399, 554, 413, 547]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :smooth=>true,
+ :width=>2, :tag=>'I24')
+ xy = [403, 570, 396, 555, 381, 553]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :smooth=>true,
+ :width=>2, :tag=>'I24')
+ xy = [408, 564, 402, 547, 386, 545]
+ TkcLine.new(@canvas, xy, :fill=>@C['fg'], :smooth=>true,
+ :width=>2, :tag=>'I24')
+ end
+
+ def move24(step = nil)
+ step = get_step(24, step)
+
+ return 0 if step > 4
+ return 2 if step == 4
+
+ if step == 0
+ @canvas.delete('I24') # Exploding balloon
+ xy = [
+ 347, 465, 361, 557, 271, 503, 272, 503, 342, 574, 259, 594,
+ 259, 593, 362, 626, 320, 737, 320, 740, 398, 691, 436, 738,
+ 436, 739, 476, 679, 528, 701, 527, 702, 494, 627, 548, 613,
+ 548, 613, 480, 574, 577, 473, 577, 473, 474, 538, 445, 508,
+ 431, 441, 431, 440, 400, 502, 347, 465, 347, 465
+ ]
+ TkcPolygon.new(@canvas, xy, :tag=>'I24', :fill=>@C['24b'],
+ :outline=>@C['24a'], :width=>10, :smooth=>true)
+ msg = Tk.subst(@S['message'].value)
+ TkcText.new(@canvas, centroid('I24'), :text=>msg, :tag=>['I24', 'I24t'],
+ :justify=>:center, :font=>['Times Roman', 18, :bold])
+ return 1
+ end
+
+ @canvas.itemconfigure('I24t', :font=>['Times Roman', 18 + 6*step, :bold])
+ @canvas.move('I24', 0, -60)
+ ox, oy = centroid('I24')
+ @canvas.scale('I24', ox, oy, 1.25, 1.25)
+ return 1
+ end
+
+ # Displaying the message
+ def move25(step = nil)
+ step = get_step(25, step)
+
+ if step == 0
+ @XY['25'] = Tk::Clock.clicks(:miliseconds)
+ return 1
+ end
+ elapsed = Tk::Clock.clicks(:miliseconds) - @XY['25']
+ return 1 if elapsed < 5000
+ return 2
+ end
+
+ # Collapsing balloon
+ def move26(step = nil)
+ step = get_step(26, step)
+
+ if step >= 3
+ @canvas.delete('I24', 'I26')
+ TkcText.new(@canvas, 430, 735, :anchor=>:s, :tag=>'I26',
+ #:text=>'click to continue',
+ :text=>'¥¯¥ê¥Ã¥¯¤Ç¥ê¥»¥Ã¥È¤·¤Þ¤¹',
+ :font=>['Times Roman', 20, :bold])
+ @canvas.bind('1', proc{reset})
+ return 4
+ end
+
+ ox, oy = centroid('I24')
+ @canvas.scale('I24', ox, oy, 0.8, 0.8)
+ @canvas.move('I24', 0, 60)
+ @canvas.itemconfigure('I24t', :font=>['Times Roman', 30 - 6*step, :bold])
+ return 1
+ end
+
+ ################################################################
+ #
+ # Helper functions
+ #
+ def box(x, y, r)
+ [x - r, y - r, x + r, y + r]
+ end
+
+ def move_abs(item, xy)
+ x, y = xy
+ ox, oy = centroid(item)
+ dx = x - ox
+ dy = y - oy
+ @canvas.move(item, dx, dy)
+ end
+
+ def rotate_item(item, ox, oy, beta)
+ xy = @canvas.coords(item)
+ xy2 = []
+ 0.step(xy.length - 1, 2){|idx|
+ x, y = xy[idx, 2]
+ xy2.concat(rotate_c(x, y, ox, oy, beta))
+ }
+ @canvas.coords(item, xy2)
+ end
+
+ def rotate_c(x, y, ox, oy, beta)
+ # rotates vector (ox,oy)->(x,y) by beta degrees clockwise
+
+ x -= ox # Shift to origin
+ y -= oy
+
+ beta = beta * Math.atan(1) * 4 / 180.0 # Radians
+ xx = x * Math.cos(beta) - y * Math.sin(beta) # Rotate
+ yy = x * Math.sin(beta) + y * Math.cos(beta)
+
+ xx += ox # Shift back
+ yy += oy
+
+ [xx, yy]
+ end
+
+ def reset
+ draw_all
+ @canvas.bind_remove('1')
+ @S['mode'].value = :MSTART
+ @S['active'] = [0]
+ end
+
+ # Each Move## keeps its state info in STEP, this retrieves and increments it
+ def get_step(who, step)
+ if step
+ @STEP[who] = step
+ else
+ if !@STEP.exist?(who) || @STEP[who] == ""
+ @STEP[who] = 0
+ else
+ @STEP[who] += 1
+ end
+ end
+ @STEP[who]
+ end
+
+ def reset_step
+ @S['cnt'].value = 0
+ @STEP.keys.each{|k| @STEP[k] = ''}
+ end
+
+ def sine(xy0, amp, freq, opts = {})
+ x0, y0, x1, y1 = xy0
+ step = 2
+ xy = []
+ if y0 == y1 # Horizontal
+ x0.step(x1, step){|x|
+ beta = (x - x0) * 2 * Math::PI / freq
+ y = y0 + amp * Math.sin(beta)
+ xy << x << y
+ }
+ else
+ y0.step(y1, step){|y|
+ beta = (y - y0) * 2 * Math::PI / freq
+ x = x0 + amp * Math.sin(beta)
+ xy << x << y
+ }
+ end
+ TkcLine.new(@canvas, xy, opts)
+ end
+
+ def round_rect(xy, radius, opts={})
+ x0, y0, x3, y3 = xy
+ r = @canvas.winfo_pixels(radius)
+ d = 2 * r
+
+ # Make sure that the radius of the curve is less than 3/8 size of the box!
+ maxr = 0.75
+ if d > maxr * (x3 - x0)
+ d = maxr * (x3 - x0)
+ end
+ if d > maxr * (y3 - y0)
+ d = maxr * (y3 - y0)
+ end
+
+ x1 = x0 + d
+ x2 = x3 - d
+ y1 = y0 + d
+ y2 = y3 - d
+
+ xy = [x0, y0, x1, y0, x2, y0, x3, y0, x3, y1, x3, y2]
+ xy.concat([x3, y3, x2, y3, x1, y3, x0, y3, x0, y2, x0, y1])
+ return xy
+ end
+
+ def round_poly(canv, xy, radii, opts)
+ lenXY = xy.length
+ lenR = radii.length
+ if lenXY != 2*lenR
+ raise "wrong number of vertices and radii"
+ end
+
+ knots = []
+ x0 = xy[-2]; y0 = xy[-1]
+ x1 = xy[0]; y1 = xy[1]
+ xy << xy[0] << xy[1]
+
+ 0.step(lenXY - 1, 2){|i|
+ radius = radii[i/2]
+ r = canv.winfo_pixels(radius)
+
+ x2 = xy[i+2]; y2 = xy[i+3]
+ z = _round_poly2(x0, y0, x1, y1, x2, y2, r)
+ knots.concat(z)
+
+ x0 = x1; y0 = y1
+ x1 = x2; y1 = y2
+ }
+ TkcPolygon.new(canv, knots, {:smooth=>true}.update(opts))
+ end
+
+ def _round_poly2(x0, y0, x1, y1, x2, y2, radius)
+ d = 2 * radius
+ maxr = 0.75
+
+ v1x = x0 - x1
+ v1y = y0 - y1
+ v2x = x2 - x1
+ v2y = y2 - y1
+
+ vlen1 = Math.sqrt(v1x*v1x + v1y*v1y)
+ vlen2 = Math.sqrt(v2x*v2x + v2y*v2y)
+
+ if d > maxr * vlen1
+ d = maxr * vlen1
+ end
+ if d > maxr * vlen2
+ d = maxr * vlen2
+ end
+
+ xy = []
+ xy << (x1 + d * v1x / vlen1) << (y1 + d * v1y / vlen1)
+ xy << x1 << y1
+ xy << (x1 + d * v2x / vlen2) << (y1 + d * v2y / vlen2)
+
+ return xy
+ end
+
+ def sparkle(oxy, tag)
+ xy = [
+ [299, 283], [298, 302], [295, 314], [271, 331],
+ [239, 310], [242, 292], [256, 274], [281, 273]
+ ]
+ xy.each{|x, y|
+ TkcLine.new(@canvas, 271, 304, x, y,
+ :fill=>'white', :width=>3, :tag=>tag)
+ }
+ move_abs(tag, oxy)
+ end
+
+ def centroid(item)
+ anchor(item, :c)
+ end
+
+ def anchor(item, where)
+ x1, y1, x2, y2 = @canvas.bbox(item)
+ case(where)
+ when :n
+ y = y1
+ when :s
+ y = y2
+ else
+ y = (y1 + y2) / 2.0
+ end
+ case(where)
+ when :w
+ x = x1
+ when :e
+ x = x2
+ else
+ x = (x1 + x2) / 2.0
+ end
+ return [x, y]
+ end
+end
+
+TkGoldberg_Demo.new(base_frame)
diff --git a/ext/tk/sample/demos-jp/hello b/ext/tk/sample/demos-jp/hello
index 859ebd950e..08f154d499 100644
--- a/ext/tk/sample/demos-jp/hello
+++ b/ext/tk/sample/demos-jp/hello
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# -*- coding: euc-jp -*-
require 'tk'
TkButton.new(nil,
diff --git a/ext/tk/sample/demos-jp/hscale.rb b/ext/tk/sample/demos-jp/hscale.rb
index 4333239c73..5615aa50bd 100644
--- a/ext/tk/sample/demos-jp/hscale.rb
+++ b/ext/tk/sample/demos-jp/hscale.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
require "tkcanvas"
if defined?($hscale_demo) && $hscale_deom
@@ -11,8 +12,9 @@ $hscale_demo = TkToplevel.new {|w|
}
positionWindow($hscale_demo)
+base_frame = TkFrame.new($hscale_demo).pack(:fill=>:both, :expand=>true)
-msg = TkLabel.new($hscale_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '3.5i'
justify 'left'
@@ -22,9 +24,10 @@ msg = TkLabel.new($hscale_demo) {
}
msg.pack('side'=>'top')
-TkFrame.new($hscale_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc {
tmppath = $hscale_demo
$hscale_demo = nil
@@ -38,7 +41,17 @@ TkFrame.new($hscale_demo) {|frame|
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
-TkFrame.new($hscale_demo) {|frame|
+def setWidth(w, width)
+ width = width + 21
+ x2 = width - 30
+ if x2 < 21
+ x2 = 21
+ end
+ w.coords 'poly',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
+ w.coords 'line',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
+end
+
+TkFrame.new(base_frame) {|frame|
canvas = TkCanvas.new(frame) {|c|
width 50
height 50
@@ -63,14 +76,3 @@ TkFrame.new($hscale_demo) {|frame|
}.pack('side'=>'bottom', 'expand'=>'yes', 'anchor'=>'n')
scale.set 75
}.pack('side'=>'top', 'fill'=>'x')
-
-
-def setWidth(w, width)
- width = width + 21
- x2 = width - 30
- if x2 < 21
- x2 = 21
- end
- w.coords 'poly',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
- w.coords 'line',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
-end
diff --git a/ext/tk/sample/demos-jp/icon.rb b/ext/tk/sample/demos-jp/icon.rb
index 9b39d33847..a2ca6651dc 100644
--- a/ext/tk/sample/demos-jp/icon.rb
+++ b/ext/tk/sample/demos-jp/icon.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# iconic button widget demo (called by 'widget')
#
@@ -15,8 +16,10 @@ $icon_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($icon_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($icon_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($icon_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($icon_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $icon_demo
$icon_demo = nil
@@ -44,45 +48,53 @@ TkFrame.new($icon_demo) {|frame|
# image À¸À®
flagup = \
-TkBitmapImage.new('file'=>[$demo_dir,
- 'images','flagup.bmp'].join(File::Separator),
- 'maskfile'=>\
- [$demo_dir,'images','flagup.bmp'].join(File::Separator))
+TkBitmapImage.new('file'=>[$demo_dir,'..',
+ 'images','flagup.xbm'].join(File::Separator),
+ 'maskfile'=>\
+ [$demo_dir,'..','images','flagup.xbm'].join(File::Separator))
flagdown = \
-TkBitmapImage.new('file'=>[$demo_dir,
- 'images','flagdown.bmp'].join(File::Separator),
- 'maskfile'=>\
- [$demo_dir,'images','flagdown.bmp'].join(File::Separator))
+TkBitmapImage.new('file'=>[$demo_dir,'..',
+ 'images','flagdown.xbm'].join(File::Separator),
+ 'maskfile'=>\
+ [$demo_dir,'..',
+ 'images','flagdown.xbm'].join(File::Separator))
# ÊÑ¿ôÀ¸À®
letters = TkVariable.new
# frame À¸À®
-TkFrame.new($icon_demo, 'borderwidth'=>10){|w|
+TkFrame.new(base_frame, 'borderwidth'=>10){|w|
TkFrame.new(w) {|f|
- TkRadioButton.new(f){
- bitmap '@' + [$demo_dir,'images','letters.bmp'].join(File::Separator)
+ # TkRadioButton.new(f){
+ Tk::RadioButton.new(f){
+ bitmap '@' + [$demo_dir,'..',
+ 'images','letters.xbm'].join(File::Separator)
variable letters
value 'full'
}.pack('side'=>'top', 'expand'=>'yes')
- TkRadioButton.new(f){
- bitmap '@' + [$demo_dir,'images','noletter.bmp'].join(File::Separator)
+ # TkRadioButton.new(f){
+ Tk::RadioButton.new(f){
+ bitmap '@' + [$demo_dir,'..',
+ 'images','noletter.xbm'].join(File::Separator)
variable letters
value 'empty'
}.pack('side'=>'top', 'expand'=>'yes')
}.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'5m')
- TkCheckButton.new(w) {
+ # TkCheckButton.new(w) {
+ Tk::CheckButton.new(w) {
image flagdown
selectimage flagup
indicatoron 0
selectcolor self['background']
}.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'5m')
- TkCheckButton.new(w) {
- bitmap '@' + [$demo_dir,'images','letters.bmp'].join(File::Separator)
+ # TkCheckButton.new(w) {
+ Tk::CheckButton.new(w) {
+ bitmap '@' + [$demo_dir,'..',
+ 'images','letters.xbm'].join(File::Separator)
indicatoron 0
selectcolor 'SeaGreen1'
}.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'5m')
diff --git a/ext/tk/sample/demos-jp/image1.rb b/ext/tk/sample/demos-jp/image1.rb
index bfe47c47af..d9435cc1a2 100644
--- a/ext/tk/sample/demos-jp/image1.rb
+++ b/ext/tk/sample/demos-jp/image1.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# two image widgets demo (called by 'widget')
#
@@ -15,8 +16,10 @@ $image1_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($image1_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($image1_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($image1_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($image1_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $image1_demo
$image1_demo = nil
@@ -44,14 +48,17 @@ TkFrame.new($image1_demo) {|frame|
# image À¸À®
image1a = \
-TkPhotoImage.new('file'=>[$demo_dir,
+TkPhotoImage.new('file'=>[$demo_dir,'..',
'images','earth.gif'].join(File::Separator))
image1b = \
-TkPhotoImage.new('file'=>[$demo_dir,
+TkPhotoImage.new('file'=>[$demo_dir,'..',
'images','earthris.gif'].join(File::Separator))
# label À¸À®
-[ TkLabel.new($image1_demo, 'image'=>image1a, 'bd'=>1, 'relief'=>'sunken'),
- TkLabel.new($image1_demo, 'image'=>image1b, 'bd'=>1, 'relief'=>'sunken')
+#[ TkLabel.new(base_frame, 'image'=>image1a, 'bd'=>1, 'relief'=>'sunken'),
+# TkLabel.new(base_frame, 'image'=>image1b, 'bd'=>1, 'relief'=>'sunken')
+#].each{|w| w.pack('side'=>'top', 'padx'=>'.5m', 'pady'=>'.5m')}
+[ Tk::Label.new(base_frame, 'image'=>image1a, 'bd'=>1, 'relief'=>'sunken'),
+ Tk::Label.new(base_frame, 'image'=>image1b, 'bd'=>1, 'relief'=>'sunken')
].each{|w| w.pack('side'=>'top', 'padx'=>'.5m', 'pady'=>'.5m')}
diff --git a/ext/tk/sample/demos-jp/image2.rb b/ext/tk/sample/demos-jp/image2.rb
index 07f9b17ebe..1bb2c9e9c3 100644
--- a/ext/tk/sample/demos-jp/image2.rb
+++ b/ext/tk/sample/demos-jp/image2.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# widget demo 'load image' (called by 'widget')
#
@@ -15,8 +16,10 @@ $image2_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($image2_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($image2_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($image2_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($image2_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $image2_demo
$image2_demo = nil
@@ -43,27 +47,27 @@ TkFrame.new($image2_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# ÊÑ¿ôÀ¸À®
-$dirName = TkVariable.new([$demo_dir,'images'].join(File::Separator))
+$dirName = TkVariable.new([$demo_dir,'..','images'].join(File::Separator))
# image À¸À®
$image2a = TkPhotoImage.new
# ¥Õ¥¡¥¤¥ë̾ÆþÎÏÉô
-TkLabel.new($image2_demo, 'text'=>'¥Ç¥£¥ì¥¯¥È¥ê:')\
+TkLabel.new(base_frame, 'text'=>'¥Ç¥£¥ì¥¯¥È¥ê:')\
.pack('side'=>'top', 'anchor'=>'w')
-image2_e = TkEntry.new($image2_demo) {
+image2_e = TkEntry.new(base_frame) {
width 30
textvariable $dirName
}.pack('side'=>'top', 'anchor'=>'w')
-TkFrame.new($image2_demo, 'height'=>'3m', 'width'=>20)\
+TkFrame.new(base_frame, 'height'=>'3m', 'width'=>20)\
.pack('side'=>'top', 'anchor'=>'w')
-TkLabel.new($image2_demo, 'text'=>'¥Õ¥¡¥¤¥ë:')\
+TkLabel.new(base_frame, 'text'=>'¥Õ¥¡¥¤¥ë:')\
.pack('side'=>'top', 'anchor'=>'w')
-TkFrame.new($image2_demo){|w|
+TkFrame.new(base_frame){|w|
s = TkScrollbar.new(w)
l = TkListbox.new(w) {
width 20
@@ -82,9 +86,10 @@ TkFrame.new($image2_demo){|w|
}.pack('side'=>'top', 'anchor'=>'w')
# image ÇÛÃÖ
-[ TkFrame.new($image2_demo, 'height'=>'3m', 'width'=>20),
- TkLabel.new($image2_demo, 'text'=>'²èÁü:'),
- TkLabel.new($image2_demo, 'image'=>$image2a)
+[ TkFrame.new(base_frame, 'height'=>'3m', 'width'=>20),
+ TkLabel.new(base_frame, 'text'=>'²èÁü:'),
+ # TkLabel.new(base_frame, 'image'=>$image2a)
+ Tk::Label.new(base_frame, 'image'=>$image2a)
].each{|w| w.pack('side'=>'top', 'anchor'=>'w')}
# ¥á¥½¥Ã¥ÉÄêµÁ
diff --git a/ext/tk/sample/demos-jp/image3.rb b/ext/tk/sample/demos-jp/image3.rb
index 84257a2b32..12b8aafd8e 100644
--- a/ext/tk/sample/demos-jp/image3.rb
+++ b/ext/tk/sample/demos-jp/image3.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
# image3.rb
#
# This demonstration script creates a simple collection of widgets
@@ -19,36 +20,39 @@ $image3_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($image3_demo).pack(:fill=>:both, :expand=>true)
+
#
-def loadDir(w)
+def loadDir3(w)
w.delete(0,'end')
Dir.glob([$dirName,'*'].join(File::Separator)).sort.each{|f|
w.insert('end',File.basename(f))
}
end
-# selectAndLoadDir --
+# selectAndLoadDir3 --
# This procedure pops up a dialog to ask for a directory to load into
# the listobx and (if the user presses OK) reloads the directory
# listbox from the directory named in the demo's entry.
#
# Arguments:
-# w - Name of the toplevel window of the demo.
-def selectAndLoadDir(w, lbox)
- dir = Tk.chooseDirectory(:initialdir=>$dirName, :parent=>w, :mustexist=>true)
+# w - Name of the toplevel window of the demo.
+def selectAndLoadDir3(w, lbox)
+ dir = Tk.chooseDirectory(:initialdir=>$dirName.value,
+ :parent=>w, :mustexist=>true)
if dir.length > 0
$dirName.value = dir
- loadDir(lbox)
+ loadDir3(lbox)
end
end
-def loadImage(w,x,y)
+def loadImage3(w,x,y)
$image3a.file([$dirName, w.get("@#{x},#{y}")].join(File::Separator))
end
# label
-msg = TkLabel.new($image3_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -57,9 +61,10 @@ msg = TkLabel.new($image3_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($image3_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $image3_demo
$image3_demo = nil
@@ -75,7 +80,7 @@ TkFrame.new($image3_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# variable
-$dirName = TkVariable.new([$demo_dir,'images'].join(File::Separator))
+$dirName = TkVariable.new([$demo_dir,'..','images'].join(File::Separator))
# image
begin
@@ -85,37 +90,38 @@ end
$image3a = TkPhotoImage.new
#
-image3_f = TkFrame.new($image3_demo).pack(:fill=>:both, :expand=>true)
+image3_f = TkFrame.new(base_frame).pack(:fill=>:both, :expand=>true)
-image3_df = TkLabelFrame.new($image3_demo, :text=>'¥Ç¥£¥ì¥¯¥È¥ê:')
+image3_df = TkLabelFrame.new(base_frame, :text=>'¥Ç¥£¥ì¥¯¥È¥ê:')
-image3_ff = TkLabelFrame.new($image3_demo, :text=>'¥Õ¥¡¥¤¥ë:',
- :padx=>'2m', :pady=>'2m')
+image3_ff = TkLabelFrame.new(base_frame, :text=>'¥Õ¥¡¥¤¥ë:',
+ :padx=>'2m', :pady=>'2m')
image3_lbx = TkListbox.new(image3_ff, :width=>20, :height=>10) {
pack(:side=>:left, :fill=>:y, :expand=>true)
yscrollbar(TkScrollbar.new(image3_ff).pack(:side=>:left, :fill=>:y,
- :expand=>true))
+ :expand=>true))
insert(0, *(%w(earth.gif earthris.gif teapot.ppm)))
- bind('Double-1', proc{|x,y| loadImage(self, x, y)}, '%x %y')
+ bind('Double-1', proc{|x,y| loadImage3(self, x, y)}, '%x %y')
}
image3_ent = TkEntry.new(image3_df, :width=>30, :textvariable=>$dirName){
pack(:side=>:left, :fill=>:both, :padx=>'2m', :pady=>'2m', :expand=>true)
- bind('Return', proc{loadDir(image3_lbx)})
+ bind('Return', proc{loadDir3(image3_lbx)})
}
TkButton.new(image3_df, :pady=>0, :padx=>'2m', :text=>"¥Ç¥£¥ì¥¯¥È¥êÁªÂò",
- :command=>proc{selectAndLoadDir(image3_ent, image3_lbx)}) {
+ :command=>proc{selectAndLoadDir3(image3_ent, image3_lbx)}) {
pack(:side=>:left, :fill=>:y, :padx=>[0, '2m'], :pady=>'2m')
}
-image3_if = TkLabelFrame.new($image3_demo, :text=>'¥¤¥á¡¼¥¸:') {|f|
- TkLabel.new(f, :image=>$image3a).pack(:padx=>'2m', :pady=>'2m')
+image3_if = TkLabelFrame.new(base_frame, :text=>'¥¤¥á¡¼¥¸:') {|f|
+ # TkLabel.new(f, :image=>$image3a).pack(:padx=>'2m', :pady=>'2m')
+ Tk::Label.new(f, :image=>$image3a).pack(:padx=>'2m', :pady=>'2m')
}
Tk.grid(image3_df, '-',
- :sticky=>:ew, :padx=>'1m', :pady=>'1m', :in=>image3_f)
+ :sticky=>:ew, :padx=>'1m', :pady=>'1m', :in=>image3_f)
Tk.grid(image3_ff, image3_if,
- :sticky=>:nw, :padx=>'1m', :pady=>'1m', :in=>image3_f)
+ :sticky=>:nw, :padx=>'1m', :pady=>'1m', :in=>image3_f)
TkGrid.columnconfigure(image3_f, 1, :weight=>1)
diff --git a/ext/tk/sample/demos-jp/images/earth.gif b/ext/tk/sample/demos-jp/images/earth.gif
deleted file mode 100644
index 3ae4a9ce01..0000000000
--- a/ext/tk/sample/demos-jp/images/earth.gif
+++ /dev/null
Binary files differ
diff --git a/ext/tk/sample/demos-jp/images/earthris.gif b/ext/tk/sample/demos-jp/images/earthris.gif
deleted file mode 100644
index 48f08c4421..0000000000
--- a/ext/tk/sample/demos-jp/images/earthris.gif
+++ /dev/null
Binary files differ
diff --git a/ext/tk/sample/demos-jp/images/face.bmp b/ext/tk/sample/demos-jp/images/face.bmp
deleted file mode 100644
index 03d829f4d1..0000000000
--- a/ext/tk/sample/demos-jp/images/face.bmp
+++ /dev/null
@@ -1,173 +0,0 @@
-#define face_width 108
-#define face_height 144
-#define face_x_hot 48
-#define face_y_hot 80
-static char face_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09,
- 0x20, 0x80, 0x24, 0x05, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x88,
- 0x24, 0x20, 0x80, 0x24, 0x00, 0x00, 0x00, 0x10, 0x80, 0x04, 0x00, 0x01,
- 0x00, 0x01, 0x40, 0x0a, 0x09, 0x00, 0x92, 0x04, 0x80, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x10, 0x40, 0x12, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x84,
- 0x24, 0x40, 0x22, 0xa8, 0x02, 0x14, 0x84, 0x92, 0x40, 0x42, 0x12, 0x04,
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x52, 0x11, 0x00, 0x12, 0x00,
- 0x40, 0x02, 0x00, 0x20, 0x00, 0x08, 0x00, 0xaa, 0x02, 0x54, 0x85, 0x24,
- 0x00, 0x10, 0x12, 0x00, 0x00, 0x81, 0x44, 0x00, 0x90, 0x5a, 0x00, 0xea,
- 0x1b, 0x00, 0x80, 0x40, 0x40, 0x02, 0x00, 0x08, 0x00, 0x20, 0xa2, 0x05,
- 0x8a, 0xb4, 0x6e, 0x45, 0x12, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10, 0x02,
- 0xa8, 0x92, 0x00, 0xda, 0x5f, 0x10, 0x00, 0x10, 0xa1, 0x04, 0x20, 0x41,
- 0x02, 0x00, 0x5a, 0x25, 0xa0, 0xff, 0xfb, 0x05, 0x41, 0x02, 0x04, 0x00,
- 0x00, 0x08, 0x40, 0x80, 0xec, 0x9b, 0xec, 0xfe, 0x7f, 0x01, 0x04, 0x20,
- 0x90, 0x02, 0x04, 0x00, 0x08, 0x20, 0xfb, 0x2e, 0xf5, 0xff, 0xff, 0x57,
- 0x00, 0x04, 0x02, 0x00, 0x00, 0x20, 0x01, 0xc1, 0x6e, 0xab, 0xfa, 0xff,
- 0xff, 0x05, 0x90, 0x20, 0x48, 0x02, 0x00, 0x04, 0x20, 0xa8, 0xdf, 0xb5,
- 0xfe, 0xff, 0xff, 0x0b, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x04, 0xe0,
- 0xbb, 0xef, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x04, 0x48, 0x02, 0x00, 0x20,
- 0x80, 0xf4, 0x6f, 0xfb, 0xff, 0xff, 0xff, 0x20, 0x90, 0x40, 0x02, 0x00,
- 0x00, 0x04, 0x08, 0xb8, 0xf6, 0xff, 0xff, 0xdf, 0xbe, 0x12, 0x45, 0x10,
- 0x90, 0x04, 0x90, 0x00, 0x22, 0xfa, 0xff, 0xff, 0xff, 0xbb, 0xd7, 0xe9,
- 0x3a, 0x02, 0x02, 0x00, 0x04, 0x90, 0x80, 0xfe, 0xdf, 0xf6, 0xb7, 0xef,
- 0xbe, 0x56, 0x57, 0x40, 0x48, 0x09, 0x00, 0x04, 0x00, 0xfa, 0xf5, 0xdf,
- 0xed, 0x5a, 0xd5, 0xea, 0xbd, 0x09, 0x00, 0x00, 0x40, 0x00, 0x92, 0xfe,
- 0xbf, 0x7d, 0xb7, 0x6a, 0x55, 0xbf, 0xf7, 0x02, 0x11, 0x01, 0x00, 0x91,
- 0x00, 0xff, 0xff, 0xaf, 0x55, 0x55, 0x5b, 0xeb, 0xef, 0x22, 0x04, 0x04,
- 0x04, 0x00, 0xa4, 0xff, 0xf7, 0xad, 0xaa, 0xaa, 0xaa, 0xbe, 0xfe, 0x03,
- 0x20, 0x00, 0x10, 0x44, 0x80, 0xff, 0x7f, 0x55, 0x12, 0x91, 0x2a, 0xeb,
- 0xbf, 0x0b, 0x82, 0x02, 0x00, 0x00, 0xd1, 0x7f, 0xdf, 0xa2, 0xa4, 0x54,
- 0x55, 0xfd, 0xfd, 0x47, 0x08, 0x08, 0x00, 0x21, 0xe4, 0xff, 0x37, 0x11,
- 0x09, 0xa5, 0xaa, 0xb6, 0xff, 0x0d, 0x80, 0x00, 0x00, 0x04, 0xd0, 0xff,
- 0x4f, 0x44, 0x20, 0x48, 0x55, 0xfb, 0xff, 0x27, 0x11, 0x02, 0x40, 0x40,
- 0xe2, 0xfb, 0x15, 0x11, 0x4a, 0x55, 0x4a, 0x7d, 0xf7, 0x0f, 0x00, 0x00,
- 0x04, 0x08, 0xf8, 0xdf, 0x52, 0x44, 0x01, 0x52, 0xb5, 0xfa, 0xff, 0x0f,
- 0x49, 0x02, 0x00, 0x02, 0xe9, 0xf6, 0x0a, 0x11, 0xa4, 0x88, 0x4a, 0x6d,
- 0xff, 0x5f, 0x00, 0x00, 0x10, 0x20, 0xf0, 0x2f, 0x21, 0x44, 0x10, 0x52,
- 0xb5, 0xfa, 0xff, 0x0f, 0x44, 0x04, 0x80, 0x08, 0xf8, 0xab, 0x8a, 0x00,
- 0x81, 0xa4, 0xd4, 0xd6, 0xfe, 0x2f, 0x00, 0x00, 0x04, 0x40, 0xb5, 0x2d,
- 0x21, 0x08, 0x04, 0x90, 0xaa, 0xfa, 0xff, 0x1f, 0x11, 0x01, 0x00, 0x04,
- 0xf0, 0x57, 0x0a, 0x22, 0x40, 0x4a, 0xda, 0x5e, 0xfb, 0x1f, 0x40, 0x00,
- 0x40, 0x20, 0xba, 0x95, 0x90, 0x00, 0x01, 0xa0, 0xaa, 0xea, 0xff, 0x5f,
- 0x02, 0x02, 0x00, 0x01, 0xe8, 0x57, 0x05, 0x00, 0x00, 0x12, 0xd5, 0xfe,
- 0xfd, 0x1f, 0x48, 0x00, 0x04, 0x48, 0x7a, 0x95, 0x08, 0x02, 0x10, 0x40,
- 0xaa, 0x55, 0xf7, 0x1f, 0x00, 0x09, 0x20, 0x00, 0xf8, 0x57, 0x22, 0x10,
- 0x00, 0x28, 0xa9, 0xfa, 0xff, 0x5f, 0x02, 0x00, 0x00, 0x49, 0xdd, 0x29,
- 0x01, 0x00, 0x80, 0x80, 0xaa, 0xd7, 0xff, 0x0f, 0x10, 0x00, 0x08, 0x00,
- 0xf8, 0x96, 0x08, 0x00, 0x00, 0x20, 0x54, 0xfa, 0xee, 0x3f, 0x81, 0x04,
- 0x40, 0x24, 0xfe, 0x55, 0x82, 0x00, 0x00, 0x82, 0xd2, 0xad, 0xff, 0x0f,
- 0x08, 0x00, 0x04, 0x80, 0x6c, 0x97, 0x00, 0x00, 0x02, 0x20, 0xa9, 0xf6,
- 0xdf, 0x5f, 0x00, 0x02, 0x20, 0x09, 0xfa, 0x49, 0x12, 0x00, 0x20, 0x84,
- 0x54, 0xdb, 0xfe, 0x1f, 0x91, 0x00, 0x00, 0x00, 0xf8, 0x2b, 0x00, 0x20,
- 0x00, 0x40, 0xa4, 0xf6, 0xbb, 0x1f, 0x04, 0x00, 0x44, 0x92, 0x7e, 0x95,
- 0x02, 0x00, 0x00, 0x89, 0xaa, 0xdd, 0xff, 0x1f, 0x20, 0x09, 0x10, 0x00,
- 0xf4, 0x57, 0x20, 0x01, 0x08, 0x20, 0xa9, 0x76, 0xff, 0x5f, 0x02, 0x00,
- 0x00, 0x21, 0xfc, 0x4a, 0x05, 0x00, 0x01, 0x80, 0x54, 0xdb, 0xff, 0x1e,
- 0x08, 0x02, 0x04, 0x08, 0xf9, 0x2b, 0x00, 0x00, 0x40, 0x28, 0xd2, 0xf6,
- 0xff, 0xbf, 0x80, 0x00, 0x90, 0x00, 0xbc, 0x92, 0x08, 0x10, 0x00, 0x82,
- 0x54, 0xdb, 0xff, 0x1f, 0x20, 0x00, 0x00, 0x44, 0xf9, 0x55, 0x02, 0x01,
- 0x00, 0x20, 0xaa, 0xbd, 0xfd, 0x3f, 0x08, 0x04, 0x04, 0x10, 0xf4, 0x2a,
- 0x01, 0x00, 0x22, 0x80, 0xd4, 0xf6, 0xff, 0x5f, 0x82, 0x00, 0x40, 0x02,
- 0xf8, 0x55, 0x20, 0x00, 0x00, 0x50, 0x6a, 0xdf, 0xfe, 0x3f, 0x00, 0x00,
- 0x00, 0x48, 0xe9, 0x4a, 0x05, 0x08, 0x00, 0xa5, 0xd5, 0xf5, 0xff, 0x3f,
- 0x10, 0x01, 0x10, 0x01, 0xb0, 0xab, 0x92, 0x02, 0x40, 0xf8, 0xbf, 0xde,
- 0xfe, 0x5f, 0x02, 0x04, 0x04, 0x48, 0xfa, 0xd4, 0x6f, 0x20, 0x84, 0xef,
- 0xff, 0xfb, 0xff, 0x1f, 0x20, 0x00, 0x00, 0x00, 0xe0, 0xed, 0xbf, 0x0b,
- 0xa1, 0x7e, 0xff, 0xbf, 0xfd, 0x5f, 0x04, 0x01, 0x20, 0x49, 0xd2, 0xfb,
- 0xfe, 0x55, 0xd4, 0xff, 0xff, 0xf6, 0xff, 0x07, 0x00, 0x04, 0x00, 0x00,
- 0xc0, 0xaa, 0xfb, 0x2b, 0xa2, 0xfe, 0xff, 0xdf, 0xee, 0x1f, 0x91, 0x00,
- 0x82, 0xa4, 0xa4, 0xf5, 0xff, 0x57, 0xd5, 0xff, 0xbf, 0xfd, 0xff, 0x4d,
- 0x00, 0x00, 0x20, 0x00, 0x88, 0x5b, 0xff, 0x2f, 0x69, 0xff, 0xff, 0xdb,
- 0xfe, 0x1f, 0x24, 0x02, 0x00, 0x49, 0xa2, 0xd6, 0xff, 0x5f, 0xea, 0xff,
- 0x7f, 0x7f, 0x7f, 0x0d, 0x00, 0x00, 0x10, 0x00, 0x40, 0xab, 0xf7, 0xbb,
- 0xf0, 0xdf, 0xff, 0xd5, 0xff, 0xbf, 0x82, 0x04, 0x42, 0x24, 0x91, 0xd5,
- 0xaa, 0xae, 0xd4, 0xaa, 0x52, 0x7b, 0xff, 0x15, 0x08, 0x00, 0x00, 0x01,
- 0x04, 0x55, 0xd5, 0x55, 0x70, 0x5b, 0x75, 0xdd, 0xdf, 0x1f, 0x40, 0x00,
- 0x08, 0x48, 0xa0, 0x4a, 0xa9, 0x56, 0xea, 0x56, 0xad, 0x6a, 0x7d, 0x9b,
- 0x04, 0x01, 0x00, 0x02, 0x42, 0x2a, 0xd5, 0xaa, 0xa8, 0xaa, 0xaa, 0xfa,
- 0xdf, 0x2f, 0x10, 0x04, 0x22, 0x48, 0x08, 0x45, 0x2a, 0x15, 0x68, 0x55,
- 0x55, 0xd7, 0x76, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x40, 0x2a, 0x80, 0xa0,
- 0xb2, 0x09, 0x48, 0xb9, 0xdf, 0x17, 0x22, 0x01, 0x00, 0x24, 0x45, 0x8a,
- 0x24, 0x4a, 0x54, 0x51, 0x91, 0xf6, 0x6e, 0x4b, 0x00, 0x04, 0x90, 0x00,
- 0x80, 0x52, 0x00, 0x20, 0x69, 0x05, 0xa4, 0xaa, 0xff, 0x1e, 0x48, 0x00,
- 0x02, 0x92, 0x08, 0x05, 0x81, 0x94, 0xd4, 0x92, 0x40, 0xfd, 0xb6, 0x8b,
- 0x00, 0x01, 0x40, 0x00, 0x82, 0x54, 0x00, 0x48, 0x68, 0x05, 0x90, 0xa4,
- 0xef, 0x06, 0x24, 0x00, 0x08, 0x12, 0x10, 0x05, 0x00, 0x10, 0xb5, 0x01,
- 0x42, 0xfb, 0xbf, 0x43, 0x00, 0x09, 0x00, 0x40, 0x81, 0xa8, 0x08, 0x4a,
- 0xaa, 0x96, 0x90, 0xac, 0x6d, 0x15, 0x22, 0x00, 0x20, 0x09, 0x04, 0x15,
- 0x80, 0x28, 0xdc, 0x01, 0x24, 0xfb, 0xbf, 0x01, 0x80, 0x04, 0x09, 0x00,
- 0x40, 0x48, 0x02, 0x45, 0xb2, 0x2e, 0x41, 0x6d, 0xef, 0x05, 0x11, 0x00,
- 0x40, 0x52, 0x02, 0x15, 0x29, 0x2a, 0xac, 0x42, 0x54, 0xfb, 0x3b, 0x51,
- 0x84, 0x00, 0x08, 0x00, 0x20, 0x54, 0x80, 0x05, 0xb5, 0x3d, 0xa2, 0xb6,
- 0xdf, 0x00, 0x20, 0x04, 0x20, 0x49, 0x89, 0xa8, 0x6a, 0x29, 0xac, 0xd6,
- 0x54, 0xff, 0x3f, 0x84, 0x00, 0x01, 0x04, 0x10, 0x00, 0x94, 0xa8, 0x56,
- 0xda, 0x5f, 0xab, 0xd5, 0x1e, 0x10, 0x48, 0x00, 0x90, 0x82, 0x48, 0xa8,
- 0xb2, 0xac, 0xfd, 0x55, 0xd5, 0xfe, 0x9f, 0x80, 0x00, 0x0a, 0x02, 0x08,
- 0x02, 0x55, 0x5a, 0x75, 0xff, 0xaf, 0xb6, 0xf7, 0x2d, 0x12, 0x92, 0x00,
- 0x10, 0x20, 0x10, 0xa8, 0x54, 0xd5, 0xbf, 0x5d, 0xad, 0xdd, 0x0f, 0x00,
- 0x00, 0x04, 0x40, 0x09, 0x84, 0xa8, 0xaa, 0x5a, 0xed, 0xeb, 0x6a, 0xff,
- 0x9f, 0xa4, 0x24, 0x01, 0x02, 0xa0, 0x20, 0x50, 0x55, 0xd5, 0xbe, 0xae,
- 0xad, 0xfd, 0x16, 0x00, 0x10, 0x04, 0x20, 0x0a, 0x08, 0xb4, 0xaa, 0x95,
- 0xaa, 0x7b, 0xb7, 0xdb, 0x5f, 0x92, 0x04, 0x01, 0x84, 0x20, 0x21, 0x51,
- 0xd5, 0x2a, 0xa9, 0xee, 0xd5, 0xfe, 0x0d, 0x00, 0x20, 0x04, 0x10, 0x00,
- 0x08, 0x50, 0xe9, 0xd7, 0xd4, 0xfb, 0xb5, 0xff, 0x9f, 0x24, 0x09, 0x01,
- 0x42, 0x4a, 0xa2, 0x64, 0xd5, 0x55, 0x7b, 0x7f, 0xda, 0x7d, 0x4f, 0x00,
- 0x20, 0x04, 0x00, 0x80, 0x00, 0xa0, 0x2a, 0x13, 0x84, 0x6a, 0x55, 0xff,
- 0x1d, 0x48, 0x8a, 0x00, 0x94, 0x24, 0x8a, 0xc8, 0xaa, 0x42, 0x20, 0x5d,
- 0xf5, 0xff, 0x5f, 0x01, 0x00, 0x02, 0x01, 0x00, 0x20, 0xa2, 0x4a, 0x1a,
- 0x82, 0x56, 0xda, 0xbd, 0x3f, 0x92, 0x92, 0x00, 0x90, 0x92, 0x00, 0x40,
- 0x95, 0x6a, 0xf4, 0x55, 0x6d, 0xff, 0xd6, 0x00, 0x00, 0x0a, 0x04, 0x20,
- 0x14, 0x49, 0x4b, 0xaa, 0xaa, 0x56, 0xf5, 0xff, 0xbf, 0xab, 0xa4, 0x00,
- 0x20, 0x89, 0x40, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xde, 0xbf, 0xeb, 0x03,
- 0x00, 0x02, 0x04, 0x02, 0x0a, 0x10, 0x2b, 0x2a, 0x55, 0x5b, 0xf5, 0xff,
- 0xd7, 0x2f, 0x92, 0x00, 0x10, 0x28, 0x21, 0x01, 0x56, 0x95, 0xa0, 0x56,
- 0xdf, 0xef, 0xea, 0x87, 0x40, 0x0a, 0x42, 0x41, 0x00, 0x90, 0xaa, 0x52,
- 0xb6, 0xad, 0xfa, 0xff, 0xd5, 0x2f, 0x14, 0x00, 0x00, 0x04, 0x95, 0x04,
- 0xaa, 0xac, 0x55, 0x6b, 0xff, 0xb7, 0xea, 0x9f, 0x40, 0x02, 0x28, 0x51,
- 0x00, 0x40, 0x58, 0xd5, 0xda, 0xd6, 0x6e, 0x7f, 0xf9, 0x3f, 0x12, 0x04,
- 0x02, 0x04, 0x49, 0x25, 0x55, 0xaa, 0x77, 0xab, 0xff, 0x2b, 0xfd, 0x3f,
- 0x48, 0x01, 0x20, 0x41, 0x00, 0x00, 0x58, 0xa9, 0xda, 0xea, 0xfd, 0xaf,
- 0xfa, 0xff, 0x02, 0x04, 0x08, 0x14, 0x29, 0x49, 0x52, 0x55, 0x55, 0x55,
- 0xff, 0x8d, 0xfe, 0x3f, 0xa8, 0x00, 0x02, 0x41, 0x00, 0x02, 0xa0, 0xa2,
- 0xaa, 0xea, 0xff, 0x53, 0xfd, 0xff, 0x02, 0x04, 0x50, 0x04, 0x25, 0xa8,
- 0x54, 0x49, 0x52, 0xb5, 0xbf, 0x8a, 0xfe, 0xff, 0xa9, 0x08, 0x04, 0x50,
- 0x80, 0x02, 0xa1, 0x2a, 0x95, 0xea, 0xff, 0xa1, 0xff, 0xff, 0x03, 0x02,
- 0x90, 0x02, 0x09, 0x08, 0x44, 0x49, 0x52, 0xbd, 0x7f, 0xca, 0xff, 0xff,
- 0x2b, 0x09, 0x04, 0x48, 0x40, 0x82, 0x90, 0x56, 0xa9, 0xf6, 0xbf, 0xd0,
- 0xff, 0xff, 0x47, 0x00, 0x50, 0x02, 0x15, 0x11, 0x40, 0x95, 0xaa, 0xfd,
- 0x2f, 0xe9, 0xff, 0xff, 0x8f, 0x0a, 0x84, 0x50, 0x40, 0x84, 0x14, 0xaa,
- 0x6a, 0xff, 0x5f, 0xf2, 0xff, 0xff, 0x7f, 0x00, 0x10, 0x02, 0x09, 0x10,
- 0x40, 0x7d, 0xf7, 0xff, 0x0b, 0xfc, 0xff, 0xff, 0xaf, 0x02, 0x84, 0x50,
- 0x42, 0x85, 0x12, 0xd0, 0xdd, 0xff, 0xa7, 0xf2, 0xff, 0xff, 0xff, 0x04,
- 0x00, 0x0a, 0x08, 0x10, 0x48, 0xf8, 0xff, 0xff, 0x0a, 0xfe, 0xff, 0xff,
- 0x7f, 0x03, 0xa4, 0x80, 0xa2, 0x8a, 0x02, 0x68, 0xff, 0xff, 0x52, 0xfd,
- 0xff, 0xff, 0xff, 0x07, 0x00, 0x2a, 0x08, 0x20, 0x28, 0xdc, 0xff, 0x5f,
- 0x05, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x92, 0x40, 0x22, 0x09, 0x02, 0xea,
- 0xfb, 0xaf, 0x48, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x12, 0x81, 0xa0,
- 0x48, 0x9c, 0x6e, 0x93, 0xa2, 0xff, 0xff, 0xff, 0xff, 0x07, 0xa8, 0x40,
- 0x28, 0x0a, 0x02, 0x74, 0xb5, 0x45, 0x81, 0xff, 0xff, 0xff, 0xff, 0x0f,
- 0x02, 0x0a, 0x81, 0x20, 0x08, 0xae, 0xaa, 0x90, 0xe8, 0xff, 0xff, 0xff,
- 0xff, 0x0f, 0x90, 0x40, 0x28, 0x88, 0x12, 0x58, 0x15, 0x50, 0xd0, 0xff,
- 0xff, 0xff, 0xff, 0x0f, 0x44, 0x0a, 0x41, 0x21, 0x08, 0xae, 0x04, 0x14,
- 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x40, 0x14, 0x88, 0x04, 0xba,
- 0x02, 0x28, 0xe8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x42, 0x15, 0x41, 0x21,
- 0x05, 0xad, 0x00, 0x05, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x40,
- 0x24, 0x8a, 0x0e, 0x36, 0x00, 0x0a, 0xf4, 0xff, 0xff, 0xff, 0xff, 0x0f,
- 0x42, 0x25, 0x90, 0xd0, 0x8b, 0xc2, 0x41, 0x05, 0xfc, 0xff, 0xff, 0xff,
- 0xff, 0x0f, 0x10, 0x08, 0x05, 0xe8, 0x8e, 0x58, 0x80, 0x02, 0xfa, 0xff,
- 0xff, 0xff, 0xff, 0x0f, 0x4a, 0x20, 0xa8, 0xba, 0x0b, 0x2b, 0x51, 0x01,
- 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x8a, 0x02, 0xe8, 0xaf, 0x84,
- 0x90, 0x04, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x52, 0x21, 0x54, 0xbf,
- 0x1f, 0x15, 0xa5, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x08,
- 0x01, 0xfa, 0xb6, 0xa4, 0x52, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
- 0x4a, 0xa2, 0x54, 0xef, 0x5f, 0x4b, 0xa4, 0x80, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x0f, 0x80, 0x10, 0x82, 0xfe, 0xbf, 0x92, 0x52, 0x42, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x0f, 0x12, 0x42, 0xa8, 0xbf, 0x1f, 0x24, 0x80, 0xa0,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x84, 0x28, 0x8a, 0xf7, 0x37, 0x80,
- 0x52, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x82, 0xe0, 0xff,
- 0x1f, 0x00, 0x20, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x84, 0x28,
- 0xca, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
- 0x10, 0x42, 0xf0, 0xfd, 0x1b, 0x00, 0x50, 0xf0, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x0f, 0xa4, 0x10, 0xc5, 0xff, 0x1f, 0x00, 0x00, 0xe0, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x0f, 0x00, 0x22, 0xf8, 0xff, 0x0e, 0x00, 0x00, 0xf0,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xaa, 0x88, 0xe2, 0xff, 0x0f, 0x10,
- 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x25, 0xfa, 0xff,
- 0x0f, 0x01, 0x11, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xfb,
- 0xfb, 0xff, 0x7f, 0x5d, 0xd5, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f};
diff --git a/ext/tk/sample/demos-jp/images/flagdown.bmp b/ext/tk/sample/demos-jp/images/flagdown.bmp
deleted file mode 100644
index 55abc51825..0000000000
--- a/ext/tk/sample/demos-jp/images/flagdown.bmp
+++ /dev/null
@@ -1,27 +0,0 @@
-#define flagdown_width 48
-#define flagdown_height 48
-static char flagdown_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe1, 0x00, 0x00,
- 0x00, 0x00, 0x70, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x00,
- 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04,
- 0x00, 0x00, 0x03, 0x00, 0x06, 0x06, 0x00, 0x80, 0x01, 0x00, 0x06, 0x07,
- 0x00, 0xc0, 0x1f, 0x00, 0x87, 0x07, 0x00, 0xe0, 0x7f, 0x80, 0xc7, 0x07,
- 0x00, 0x70, 0xe0, 0xc0, 0xe5, 0x07, 0x00, 0x38, 0x80, 0xe1, 0x74, 0x07,
- 0x00, 0x18, 0x80, 0x71, 0x3c, 0x07, 0x00, 0x0c, 0x00, 0x3b, 0x1e, 0x03,
- 0x00, 0x0c, 0x00, 0x1f, 0x0f, 0x00, 0x00, 0x86, 0x1f, 0x8e, 0x07, 0x00,
- 0x00, 0x06, 0x06, 0xc6, 0x05, 0x00, 0x00, 0x06, 0x00, 0xc6, 0x05, 0x00,
- 0x00, 0x06, 0x00, 0xc6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,
- 0x7f, 0x06, 0x00, 0x06, 0xe4, 0xff, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,
- 0x00, 0x06, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x00,
- 0x00, 0x06, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,
- 0x00, 0x06, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x06, 0x00, 0x66, 0x00, 0x00,
- 0x00, 0x06, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x3e, 0x00, 0x00,
- 0x00, 0xfe, 0xff, 0x2f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x27, 0x00, 0x00,
- 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
- 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
- 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
- 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,
- 0xf7, 0xbf, 0x8e, 0xfc, 0xdf, 0xf8, 0x9d, 0xeb, 0x9b, 0x76, 0xd2, 0x7a,
- 0x46, 0x30, 0xe2, 0x0f, 0xe1, 0x47, 0x55, 0x84, 0x48, 0x11, 0x84, 0x19};
diff --git a/ext/tk/sample/demos-jp/images/flagup.bmp b/ext/tk/sample/demos-jp/images/flagup.bmp
deleted file mode 100644
index 6eb0d846a3..0000000000
--- a/ext/tk/sample/demos-jp/images/flagup.bmp
+++ /dev/null
@@ -1,27 +0,0 @@
-#define flagup_width 48
-#define flagup_height 48
-static char flagup_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00,
- 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xef, 0x6a, 0x00,
- 0x00, 0x00, 0xc0, 0x7b, 0x75, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x6a, 0x00,
- 0x00, 0x00, 0x30, 0x60, 0x75, 0x00, 0x00, 0x00, 0x18, 0xe0, 0x7f, 0x00,
- 0x00, 0x00, 0x0c, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x06, 0xe0, 0x04, 0x00,
- 0x00, 0x00, 0x03, 0xe0, 0x04, 0x00, 0x00, 0x80, 0x01, 0xe0, 0x06, 0x00,
- 0x00, 0xc0, 0x1f, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x7f, 0xe0, 0x07, 0x00,
- 0x00, 0x70, 0xe0, 0xe0, 0x05, 0x00, 0x00, 0x38, 0x80, 0xe1, 0x04, 0x00,
- 0x00, 0x18, 0x80, 0xf1, 0x04, 0x00, 0x00, 0x0c, 0x00, 0xfb, 0x04, 0x00,
- 0x00, 0x0c, 0x00, 0xff, 0x04, 0x00, 0x00, 0x86, 0x1f, 0xee, 0x04, 0x00,
- 0x00, 0x06, 0x06, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00,
- 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x66, 0x04, 0x00,
- 0x7f, 0x56, 0x52, 0x06, 0xe4, 0xff, 0x00, 0x76, 0x55, 0x06, 0x04, 0x00,
- 0x00, 0x56, 0x57, 0x06, 0x04, 0x00, 0x00, 0x56, 0x55, 0x06, 0x06, 0x00,
- 0x00, 0x56, 0xd5, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,
- 0x54, 0x06, 0x00, 0xc6, 0x54, 0x55, 0xaa, 0x06, 0x00, 0x66, 0xaa, 0x2a,
- 0x54, 0x06, 0x00, 0x36, 0x55, 0x55, 0xaa, 0x06, 0x00, 0xbe, 0xaa, 0x2a,
- 0x54, 0xfe, 0xff, 0x6f, 0x55, 0x55, 0xaa, 0xfc, 0xff, 0xa7, 0xaa, 0x2a,
- 0x54, 0x01, 0x88, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
- 0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
- 0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
- 0x54, 0x55, 0x8d, 0x50, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa8, 0xaa, 0x2a,
- 0x54, 0x55, 0x95, 0x54, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
- 0x54, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/ext/tk/sample/demos-jp/images/gray25.bmp b/ext/tk/sample/demos-jp/images/gray25.bmp
deleted file mode 100644
index b234b3cb0b..0000000000
--- a/ext/tk/sample/demos-jp/images/gray25.bmp
+++ /dev/null
@@ -1,6 +0,0 @@
-#define grey_width 16
-#define grey_height 16
-static char grey_bits[] = {
- 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
- 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
- 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44};
diff --git a/ext/tk/sample/demos-jp/images/grey.25 b/ext/tk/sample/demos-jp/images/grey.25
deleted file mode 100644
index b234b3cb0b..0000000000
--- a/ext/tk/sample/demos-jp/images/grey.25
+++ /dev/null
@@ -1,6 +0,0 @@
-#define grey_width 16
-#define grey_height 16
-static char grey_bits[] = {
- 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
- 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
- 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44};
diff --git a/ext/tk/sample/demos-jp/images/grey.5 b/ext/tk/sample/demos-jp/images/grey.5
deleted file mode 100644
index 37688893f0..0000000000
--- a/ext/tk/sample/demos-jp/images/grey.5
+++ /dev/null
@@ -1,6 +0,0 @@
-#define grey_width 16
-#define grey_height 16
-static char grey_bits[] = {
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};
diff --git a/ext/tk/sample/demos-jp/images/letters.bmp b/ext/tk/sample/demos-jp/images/letters.bmp
deleted file mode 100644
index 0f12568d1a..0000000000
--- a/ext/tk/sample/demos-jp/images/letters.bmp
+++ /dev/null
@@ -1,27 +0,0 @@
-#define letters_width 48
-#define letters_height 48
-static char letters_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20,
- 0x00, 0xfa, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2a,
- 0x00, 0x3a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2e,
- 0xe0, 0xff, 0xff, 0xff, 0xff, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x21,
- 0xa0, 0x03, 0x00, 0x00, 0x70, 0x21, 0x20, 0x00, 0x00, 0x00, 0x50, 0x21,
- 0xa0, 0x1f, 0x00, 0x00, 0x50, 0x21, 0x20, 0x00, 0x00, 0x00, 0x70, 0x21,
- 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x21, 0x02, 0x00, 0x00, 0x00, 0x08, 0x21,
- 0xfa, 0x01, 0x00, 0x80, 0x0b, 0x21, 0x02, 0x00, 0x00, 0x80, 0x0a, 0x21,
- 0xba, 0x01, 0x00, 0x80, 0x0a, 0x21, 0x02, 0x00, 0x00, 0x80, 0x0b, 0x21,
- 0x3a, 0x00, 0x00, 0x00, 0x08, 0x21, 0x02, 0x00, 0x00, 0x00, 0x08, 0x21,
- 0x02, 0xc0, 0xfb, 0x03, 0x08, 0x21, 0x02, 0x00, 0x00, 0x00, 0x08, 0x3f,
- 0x02, 0xc0, 0xbd, 0x0f, 0x08, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x01,
- 0x02, 0xc0, 0x7f, 0x7b, 0x08, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x01,
- 0x02, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00,
- 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/ext/tk/sample/demos-jp/images/noletter.bmp b/ext/tk/sample/demos-jp/images/noletter.bmp
deleted file mode 100644
index 5774124efe..0000000000
--- a/ext/tk/sample/demos-jp/images/noletter.bmp
+++ /dev/null
@@ -1,27 +0,0 @@
-#define noletters_width 48
-#define noletters_height 48
-static char noletters_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00,
- 0x00, 0xf0, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x7f, 0x00,
- 0x00, 0x3e, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xf0, 0x01,
- 0x80, 0x07, 0x00, 0x00, 0xc0, 0x03, 0xc0, 0x03, 0x00, 0x00, 0xe0, 0x07,
- 0xe0, 0x01, 0x00, 0x00, 0xf0, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x0e,
- 0xf0, 0x00, 0x00, 0x00, 0x3c, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x1e, 0x1c,
- 0x38, 0x00, 0x00, 0x00, 0x0f, 0x38, 0x38, 0x00, 0x00, 0x80, 0x07, 0x38,
- 0x3c, 0xfc, 0xff, 0xff, 0x7f, 0x78, 0x1c, 0x04, 0x00, 0xe0, 0x41, 0x70,
- 0x1c, 0x04, 0x00, 0xf0, 0x40, 0x70, 0x1c, 0x74, 0x00, 0x78, 0x4e, 0x70,
- 0x0e, 0x04, 0x00, 0x3c, 0x4a, 0xe0, 0x0e, 0x74, 0x03, 0x1e, 0x4a, 0xe0,
- 0x0e, 0x04, 0x00, 0x0f, 0x4e, 0xe0, 0x0e, 0x04, 0x80, 0x07, 0x40, 0xe0,
- 0x0e, 0x04, 0xf8, 0x0f, 0x40, 0xe0, 0x0e, 0x04, 0xe0, 0x01, 0x40, 0xe0,
- 0x0e, 0x04, 0xf8, 0x00, 0x40, 0xe0, 0x0e, 0x04, 0x78, 0x00, 0x40, 0xe0,
- 0x0e, 0x04, 0xfc, 0xf3, 0x40, 0xe0, 0x1c, 0x04, 0x1e, 0x00, 0x40, 0x70,
- 0x1c, 0x04, 0x0f, 0x00, 0x40, 0x70, 0x1c, 0x84, 0x07, 0x00, 0x40, 0x70,
- 0x3c, 0xfc, 0xff, 0xff, 0x7f, 0x78, 0x38, 0xe0, 0x01, 0x00, 0x00, 0x38,
- 0x38, 0xf0, 0x00, 0x00, 0x00, 0x38, 0x70, 0x78, 0x00, 0x00, 0x00, 0x1c,
- 0xf0, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0xe0, 0x1e, 0x00, 0x00, 0x00, 0x0e,
- 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x80, 0x07,
- 0x80, 0x07, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x1f, 0x00, 0x00, 0xf0, 0x01,
- 0x00, 0x3e, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x7f, 0x00,
- 0x00, 0xf0, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00};
diff --git a/ext/tk/sample/demos-jp/images/pattern.bmp b/ext/tk/sample/demos-jp/images/pattern.bmp
deleted file mode 100644
index df31baf789..0000000000
--- a/ext/tk/sample/demos-jp/images/pattern.bmp
+++ /dev/null
@@ -1,6 +0,0 @@
-#define foo_width 16
-#define foo_height 16
-static char foo_bits[] = {
- 0x60, 0x06, 0x90, 0x09, 0x90, 0x09, 0xb0, 0x0d, 0x4e, 0x72, 0x49, 0x92,
- 0x71, 0x8e, 0x8e, 0x71, 0x8e, 0x71, 0x71, 0x8e, 0x49, 0x92, 0x4e, 0x72,
- 0xb0, 0x0d, 0x90, 0x09, 0x90, 0x09, 0x60, 0x06};
diff --git a/ext/tk/sample/demos-jp/images/tcllogo.gif b/ext/tk/sample/demos-jp/images/tcllogo.gif
deleted file mode 100644
index 3fc7720b17..0000000000
--- a/ext/tk/sample/demos-jp/images/tcllogo.gif
+++ /dev/null
Binary files differ
diff --git a/ext/tk/sample/demos-jp/images/teapot.ppm b/ext/tk/sample/demos-jp/images/teapot.ppm
deleted file mode 100644
index 78afefbf82..0000000000
--- a/ext/tk/sample/demos-jp/images/teapot.ppm
+++ /dev/null
@@ -1,56 +0,0 @@
-P6
-256 256
-255
-\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[7 eOLjQLmSMoTMnSMlRMhPL_9 \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀnSMtVMzYN~[N~[N\N\O€\O€]O€]O€]O€]O€\O€\O}[NyYNtVM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-wXN}[N€]O„^O†_O†`O‡`Oˆ`Oˆ`OˆaO‰aO‰aO‰aO‰aO‰aO‰aOˆaOˆ`O†_Oƒ^O\N \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaMLyYN…_O‰aP‹bPcPŽcPŽdPŽdPdPdPdPdPdPdPdPeP‘eP’eP’eP‘ePdPcP…_OpUM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN…_OdP“fP•gQ–hQ˜hQ˜iQ™iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœjQœjQœjQ›jQœjQ™iQ“fP‡`O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJiQL‹bP—hQkQ¡mR¤nR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦pR¨pS©qSªqS«rS¬rS«rS©qS¤oRœjQ€]O\KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀfOLrUMcPŸlR©qS¯tS²uTµwT·xT¸xT¹yTºyT»zT»zU¼zU¼zU¼zU»zUºyT¸xT¶wT¯tS¡mR‰aOhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àa0 cNLqUM€\O”fQ¦pS²wVºzV¿|VÂ}VÄVÆVÇ€VÉ‚WÌ…[Õeæ w÷³‹êª…Ĉg§qT“fQ{ZNYIK9\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀO1{G#‘JkRMqUMtVN–iS¨v\·€d¹bµzZ±vU°uT®sSªqS¤nRœjQ’eP„^OrUMHh>!T4\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-V5wE"~I#†M%U+¥e7²l:°g2®b*­a(­`(©^(¥])¡^-›]1ŠS,qC$`9 R3G-\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@)J/i>!pA"tD"wF$yH&xH&tE$wE#yG%}M+ƒT4S5mE*Z7!K/B*;'\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‰aO¦oR½{UÇ€VÏ…X<(F-a: e<!h>!j@#k@$h>"d<!c=$hD-fF2[<)K0@);'5$Ë‚VÇ€V¿|U_LKYIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À…_O·xTÉ‚Wó«€ûµ‹Ö’k¼|X×>µf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&c<!b=%jH2_A/I0!<(8&5$”J¥Y’S%8&;'?)E,<:HA=HE?IJAISFJYIKXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À£nRÁ}UܘqÊŠe±vU²e,™V&¥V†C
-€@ |> y< u: r9 o7 l6
-j5
-h4
-g3
-5$D,K/b; h>"wM1tK.e="a<#cA,U8&E-<(9&.!a0 b1 c1    
-
-+3#@)46G<:HMCIXHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀU*´vT¿~X¸{YÃk+›W&‰N$|> u: p8 k5
-f3
-a0 _/ ]. [- I¡\*ª_(‘LkRMmSMmSMnSMnSMD,R3W5mA"|O0|P1j?"c<!a=%Y7"N1F,;'NCJNCJNDJODJODJODJh>!a: X/K%
-g3
-a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d<!yF#O+€N,rC#qB"pB#k?"a: Z7 6ODJPDJPEJQEJQEJREJREJREJRFJSFJSFJSFJSFJe<!X/
-^/ V+Q(L&I$r9  TlRMnSM46G47G47G46G46G46G46G46G36G36G25G25G15G04G/4F.3F
-ˆ`O~[NqUM[- ‰HUGJUGJVGJVGJVHJWHJWHJWHKWHKXHKXHKXHKXHKXHKXIKXIKXIKXIKXIKh>!Y0
-
-L&C!:4
-X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?<H@<HA=HC>HG@ILBIREJ[JKcNLjQL§pR±uTºzUÃ~VÈWË‚XÖŽcäsÒŽe¼{V²vT¨pSžkR•gQŒbP†_O‚^O]O€\O€\O€\O€\O€]O]O]O]O]O]O]O]O]O]O]O€\O€\O~\N}[N|ZNxXN•T%H$
-›W&rVMvWNyYNzYN|ZN}[N}[N><H?<H?<H?<H?<H?<H@<H@<H@<HA=HA=HB=HC>HE?IG@IIAIKBIODJSFJWHK—hQŸlR§pR°b(¾i*Én+Ù|7Û|6Ïr,Íq+Êp-Ãl+»g)±b(®sS§pS lRšiQ•gQePcPŠaPˆaO‡`O‡`O†_O†_O…_O…_O…_O…_O…_O…_O…_O„_O„^O„^Oƒ^Oƒ^O‚]O]O€\O~[N{ZN•T%
-
-
-
- 
-@%<-$G?@…pfdNLuWM\NdNL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJvWN‰aP./01„E}[N]O…_Oˆ`O‰aP‹bPŒbPcPcPŽcPdPdPdPeP‘eP’eP’eP“fP“fQ”fQ•gQ•gQ–gQ–hQ—hQ˜hQ™iQšiQ›jQœjQkQkRžlRŸlRžY&¤\'¨^'µ^½bÀcÃeÇi ÄgÀc½b¼a¹`µ^´]¯X¢[' Z'žY&¢mR¡mR¡mR lRŸlRŸlRžkRkQœkQœjQ›jQšjQšiQ™iQ™iQ˜iQ˜hQ—hQ—hQ—hQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘ePdPcP‰aP—O
- B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6
- 
-\À\À\À\À\À\À\À\À\À B B
-$5 ¬`(¶e)£nRœjQƒ^OJAI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXIK^KKdNLhPLuWM‚]OŒbP”fQeP
-m6
-†`OŽcP“fQ—hQ˜hQ™iQšiQšjQ›jQ›jQ›jQœjQœjQœjQœkQkQkQkRžkRžkRžkRžlRŸlRŸlRŸlR lR lR lR¡mR¡mR¡mR¡mRºg)³c(²c(±b(­V¿cÂeÅi!Åi!Àd¼bº`¹`·_·_¶^¢Q§]'ª_(­`(¹f)£nR£nR£nR£nR£nR£nR£nR¢nR¢nR¢nR¢nR¢nR¢nR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR¢mR¢mR£nR¢mR¢mR¡mR mRkR—hQˆGa0 ŠbP mRœjQ“fQ‰aP}[NrUMmSM…L$\À\À\À\À\À\À\À\À B B
-#C, 8&H.Z7 §pR›jQ{ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJ[JK`LKdNLhQLqUM{ZN…_OŽcP–gQ—hQ
-‹bP‘eP–hQšiQ›jQœjQkQkQkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlR lR lR lR mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢nR£nRÀj*ºg)·e)¶d)Âd°XÅgÅhÂe¿c½b½b¾bªU­`(®a(¯a(³c(¾i*¤oR¤oR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¥oR¥oR¤nR¡mR›jQŽQ%Z- œjQ£nRŸlR—hQŽdP…_OuWMpTMnSMkRLa: \À\À\À\À\À\À\À B B&D2
-@*S6#G@IPDJ˜hQmSM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ]KKbMLeOLiQLlRMvWN\OˆaO‘eP—hQœjQ•gQ
-\À\À\À\À\À B'D+E$(1 J/jH1NCJUGJYIKUGJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXHK]KKbNLfOLiQLkRMmSMoTMqUMxXN\N†_OŒbP’fP˜hQkQ¡mR¥oR§pS¦pR˜hQ¢mR¥oR¨pSªqS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rSªrSªrSªrS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS«rS¬rS¬rS¬rS¬rS¬rS¬rS¬rS¬sS¬sS­sS­sS­sS­sS­sS­sS®sS®sS®sS®sS®tS¯tS°tS°uS±uS±uT±uT²uT²uT²uT´vTµwT´vT³vT²uT¯tS¢mR¯tS±uT±uS®tS«rS§pR¢mRkQ—hQ‘ePŠaPƒ^O\N{ZNvXNqUMpTMnSMlRMP%\À\À\À\À B#C*E$.E- .!G$Y:%d<"SFJYIKZIKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀPDJZIK_LKdNLgPLjQLlRMnSMpTMqUMuWMyYN€\O†`OcP’fP—hQœjQ¡mR¥oR¨qS«rS«rSªrS mR
-!C+E'0F.4F7%8%U/lG.SFJZIK]KKZIKB=H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀREJZJK`LKdNLgPLjQLlRMnSMpTMqUMtWMxXN{ZN~[N]O„^O†`O‰aO‹bPdP•gQ™iQœkQ lR¤nR§pSªrS­sS¯tT²uT´vT¶wT·xT¹yT¹yTºyTºyT¹yT¶xT´vT¬rS¢nR—hQ¿|U¿|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ}UÀ}UÁ}UÁ}UÁ}UÁ}UÂ}UÂ~UÃ~UÃ~VÃ~VÄVÅ€WÆX®a(ŸlRªrS´vT¸yT¼zU¾|UÁ~VÃXÆ‚[Ɇ_΋dÓ‘jÔ“mÔ“nБlÊŒhĆd½_¶{[°vWªsU¦pS¢nRžkRšiQ˜hQ•gQ“fQ‘ePdPŒbP‰aO†_Oƒ^O€\O|ZNxXNsVMpTMnTMmSMjQL€C B)D&/F-3F47G6%>" Y7 kA$YIK]KK^KKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\KKbMLeOLhPLkRLmSMnTMpTMrUMuWNyYN|ZN\N‚]O„_O‡`OŠaPŒbPŽcPeP“fP—hQ›jQžlR¢nR¥oS©qT¬sT¯uU²vU´wV¶xV¸yV¹yUºzU»zU¼{U½{U¾{U¾|U¿|U¿|U¿|U¿|U¾{U½{U¼{U¼zU»zTºyT¹yT¸xTµwT³vT´vT´vT´vT´wT´wTµwT·xT¹yTºzT¼zU½{U¾{U¿|UÀ|UÂ}UÄVÅ€WÇ‚YÉ„\͈_ÑŒdÙ”láuç£|쩂ſt명æ¦ÞŸ{Õ—sËŽl†d¹^³yZ­uW¨qU¤oSŸlRžkRœjQšiQ˜hQ–gQ”fQ‘ePdPcPŠaP‡`O„^O]O}[NyYNuWMpTMoTMmSMkRLgPL&D#.E,3F46G;'<(D"iB(VGJ]KK`LK[JKB>H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRMmSMoTMqUMsVMvXNzYN}[N€\O‚^O…_Oˆ`OŠaPŒcPdP‘eP“fQ•gQ—hQ™iQkR mS¤oT¨rU¬tW°wY´zZ¸}\»]¾€^À^Á‚^‚^Â\Á€ZÁYÁXÁ~WÁ~WÂ~VÂ~VÂ~VÃ~VÃ~UÃ~UÄ~UÄ~UÄUÄUÅVÅVÅVÅVÆVÆ€VÆ€VÇ€WÇWÈ‚XɃZË…[͇^ЊaÓdØ’iÜ—nâtè£zî©ó¯‡ø´û¸‘üº“û¹“÷¶ñ±Œé©…à¡~Ö˜vËmÇf»€`´z[®vX©rU¥pT£oS¢nS lRžkRœkRšjQ˜iQ–hQ”fQ’ePdPcP‹bPˆ`O…_O‚]O~[NzYNvWNpTMoTMnSMkRMhQLo7 ,2F36G99HC+@ ]8 nA"\JK`ML_LKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_OˆaO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRžlR mS£oU§rW¬vZ²{]¹€a¿…fÅŠjËnГqÓ•sÕ–sÕ–rÕ–qÕ”oÓ’mÑjÏgÍŠcˈaɆ^È„\Ç‚[ÆYÅ€XÅ€WÅWÅWÅVÅVÅWÅ€WÆ€WÇXÈ‚YɃ[Ê…\͇_ÏŠaÒeÕ‘hÙ•mÝ™qávä¡zç¤}꧀멃몄騃奀ߠ|Ù›wÓ•rÌmƉh¿„c¸~^²yZ®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRœkR›jQ™iQ—hQ•gQ“fPePŽcP‹bPˆaO…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQL~I#26G99G?<HA*E$ i@$ZIKaMLbML[JK;:H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ]KKbMLeOLhPLjRLlSMnTMpTMrUMuWMxXN{ZN~\N]O„^O†`O‰aO‹bPŽcPdP’eP”fQ–gQ˜hQšiQœkRžlS mT£oU¦rWªuZ¯y]´~aºƒfŠlË’sÔšzÜ¡€ã§†è«‰ë®‹í¯Œí®‹ë¬ˆè¨„ã£~ßžyÚ™tÖ•oÒjÎŒfˈbÈ…_ƃ\ÅZÄ€YÃXÂWÂ~WÂ~WÂ~WÃXÀXÄ€YÅZƃ\Ç…^Ɇ`ˈbÌŠdÍ‹fÎgÎŽiÎŽjÎŽjÍŽjËŒiljgÆd¿ƒaº^¸}]¶|\´{[²yZ°xY®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRkR›jQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aO†_Oƒ^O€\O|ZNxXNtVMpTMnSMmSMjQLgPL99G?<HG-E&b;!YIK`MLdOM`LKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlRºyTÄ~UÊ‚XʃYÄXº{W­tUšW'¢[(—hQ lRcP€\OhQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRLmSMoTMqUMrVMvWNyYN|ZN\N‚]O„_O‡`O‰aPŒbPŽcPdP’fP”gQ–hQ˜iQšjRœkRžlS¡nT¤pU§sW«vZ°z]µb»„gŠlÉ‘sИyØžÞ¤…㩊è­ì±ï³‘ﳑ뭊穅⣀ݞzؘtÒ“nÎiɉdÆ…`Â]Á€[¿~Y¾}X½|W½|V¼{V¼{V¼{V¼{V¼{V¼|W¼|W½}X½}Y½~Z½~Z¼~Z»}[º}[º}[º~\º~\º~]º~]¹~]¸~]·}]¶|\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS mRŸlRkR›jQšiQ˜hQ–gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O}[NyYNuWNpTMnTMmSMkRLhPL|H$D>IQ2P+XHK_LLfQOcNLXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À©qSºyTÃ~VΈ`遲ޜv¾€]ªqS–LŽG|> g3
-S)?*%.—hQ—hQ‘eP‡`OuWM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMoTMqUMsVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽdP‘eP“fP•gQ—hQ˜iQšjRœkRŸlS¡nT¤pV§sX«vZ°z^¶b¼…gËmÊ’sјzØŸ€Þ¤…㩊è­ê¯ë°ê¯Žè¬‹å¨‡à¤‚Ûž|Ö™wÑ“qÌŽlljgÃ…bÀ‚_½\»}Zº{X¹zW¸yV·yU·xU·xU·xT·xT·xU·xU·xU·yV·yV·yW¸zW¸{X¹{Y¹|Zº}[º}[º}\º~\¹~]¹~]¸}]·|\µ{\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS¡mRŸlRkRœjQšiQ˜hQ–gQ”fQ’ePdPcPŠbP‡`O…_O‚]O~[NzZNvWNrUMoTMmSMlRMiQLeOLJAIJ(h>!]KKfQOgQN_LKD>I\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À™iQ°tS¸yT¼{UÂYÎŒeï­ˆô´Õ—u¶|\ Z'™LˆD
-|>
-
-+,!.! "`E6†iYŒlZo\“q]•s^^J™va›wbycŸzd {e¤}foTMqUMsVMuWNwXNyYN{ZN|ZN~[N\O]O‚]Oƒ^O…_O†_O‡`Oˆ`O‰aOŠaP‹bPŒbPŒcPcPŽcPŽdPdPdPdPeP‘eP‘eP‘eP’eP’eP’eP’eP’fP’fP’fP“fP’fP’fP’fP’eP’eP’eP‘eP‘eP‘ePePdPdPdPŽdPŽcPcPŒcPŒbP‹bPŠaP‰aOˆ`O‡`O†_O…_Oƒ^O‚]O]O\O~[N|[N{ZNyYNwXN®ƒi¬ƒiª‚i¨i¦€hŒhR‰fQ†dQ‚bP•wfx]Oˆpdkbtd_m`]OEDG?A;:@.S….S….S….S….S…/S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTx«Tx«Tx«Ty«/S†GlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž…ªÜ…ªÜ£Ö£Ö£Ö£Ö¤Ö¤Ö¤Ö¤Ö¤ÖEi›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×€¥×€¥×€¥×Bg™Bg™Bg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Af˜Af˜%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|
-+,YA5jPBpSD‹l[o]’q^–t`‚_Kšwbœycžze {f¡}g¤h¨i”lSrVMtWMvWNxXNyYN{ZN|[N~[N\O]O‚]Oƒ^O„_O…_O†`O‡`Oˆ`O‰aPŠaP‹bP‹bPŒbPcPcPŽcPŽcPdPdPdPdPdPdPdPdPePePePePePdPdPdPdPdPdPdPŽcPŽcPcPcPŒbP‹bP‹bPŠaP‰aOˆ`O‡`O†`O…_O„^Oƒ^O‚]O€]O\O~[N|[N{ZNyYNxXN°…j®„j¬„jªƒj¨‚j¦€jŒhSŠgS†eRƒcR|`QŒsf…oe}jcrd`k_]LCDC=@,,3(4F(4F.S….S…/S…/S…/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«…ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžChšChš¤Ö€¤Ö€¤Ö€¤Ö€¤ÖEi›Ei›Ei›€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤Ö€¤×€¤×€¤×€¤×Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|#5H71O;3V?4iOBoSDsVFo]{[I^Kƒ`L…bN‡dOŸ{f }g¢~h¥€j’kT•mU˜oVšqWrWwXNxXNzYN{ZN}[N~[N\O€]O‚]Oƒ^O„^O…_O…_O†`O‡`Oˆ`O‰aO‰aPŠaP‹bP‹bPŒbPŒbPŒcPcPcPcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPŽcPcPcPcPŒcPŒbP‹bP‹bP‹bPŠaP‰aP‰aOˆ`O‡`O†_O…_O„_O„^Oƒ^O]O€\O\N~[N|ZN{ZNyYN›oTšoT™oT—nT¬„lªƒl¨‚ljUŒiTŠhT†fT€cSvi‰rgnfyidqdah^^HBD?<@)+3OZkMYk(5F(5F(5F/S…/S…/S…/S…/S…TxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Ty«Uy«†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlž†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžHlžDhšDhšDhšChš&K}&K}&K}&K}&K}&K}ChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|&J|&J|&J|&J|&J|Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|A99N?;L:2T>4gNBlRD‡k\‹n^z[J~^LaN…cO‡dP‰fQŠgRŒhTjU’lV•nW˜pXšrXsY¶‹q¸qºŽr¼r½r¿s©z[©z[ªz[«{[¬{[¬{ZÅ“rÅ’qÅ’qÅ’pÅ’pÅ‘o­yV­xV¬xU¬wT¬wTŠaPŠbP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bP‹bPŠaPŠaPŠaP‰aP‰aOˆaOˆ`O‡`O‡`O†_O…_O„^Oƒ^O‚^O‚]O]O€\O~\N}[N|ZNzYNpTœpU›pUšpU˜oV—oV•nV“mV‘lVkVŒjVˆhVƒfU~cUuj†qh~mfugdkaad\^E@D98?$(2minffm^blV^lMYk(5F(5F/S…TxªTxªTxªTxªTxªTxªTxªTx«Tx«Ty«Ty«Ty«Uy«Uy«†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜ†ªÜHlžHlžHlžHlžHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸHlŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}ChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™&J|Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|Ae˜Ae˜;GY<68I=:I82Q=4XA6~fZ„j\‰m^p`|]L€`NƒcP†eQˆgS¡j£€l¦‚m©„n•oX˜qYšrZt[¶Œr¸sºs¼t½t¾‘t¨z]©{]ª{]«{\«{\¬{\¬{[Ä“sÄ“rÄ’rÄ’qÄ’pÄ‘p¬yWÄoÃnÃmÃlÂŽlÂŽkÁkˆaOˆaOˆaOˆaOˆaOˆaOˆaOˆ`Oˆ`O‡`O‡`O‡`O†`O†_O…_O…_O„_O„^Oƒ^O‚]O]O€]O\O~\N}[N|ZN¶‰l¶‰lµˆmœqV›qVšqV™pW˜pW–oW¬…nª…n§„n¤‚nŸ€n›~n€eW‘xlŠtk‚piykfodcf_`JDG@>C*,5$1MYktr~tstmolinadmX_lNZkMZkTxªTxªTxªTxªTx«Tx«Tx«Ty«Ty«Ty«Uy«Uy«Uy«†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†ªÝ†«Ý†«Ý†«Ý†«ÝHlŸHlŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ†«Ý†«Ý†«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«Ý‡«ÝHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸHmŸ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhšDhšDhšDhšChšChšChšChšChšChšChšCgšCgšCgšCgšCgšCgšCg™Cg™Cg™Cg™Cg™&J}&J}&J}Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Cg™Bg™Bg™Bg™Bg™Bg™Bg™Bf™Bf™Bf™Bf™Bf˜Bf˜Bf˜Bf˜Bf˜&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|Af˜Af˜Af˜Af˜;GY;GY;GY1'!D:9N?;N;3]I?zdY€h[†l^‹oasc“ue€bQ„dR‡fT l¢m¦ƒn©…o«‡p®ˆq±Šr³‹sžv] w]¹u»u¼‘u¾‘u¿’v¨{^©{^ª|^«|]«|]«{\¬{\¬{[¬{[¬zZ«zZ«yY«yX«xXÂoÂnÂnÁŽmÁŽm¨uT¨uS§tS§tS§tR¦sR¦sQ…_O…_O…_O„^O„^Oƒ^Oƒ^O‚^O‚]O]O€]O¢rS¡rS¡rS¸‰k·‰l·‰l¶‰m¶‰mµ‰m´‰n³‰n›qWšqX™qX®‡o­‡o«†p¨…p¤ƒp pœp—}o{cXv`Vp]U}nishfhaba\_DAF::B$)4
-., 7(8'A1&F4(L8*oXIw]Jpdasfcvhexkg{mi~oj€qll\Xn^Yp`Zpa[qa\rb]rc^sc^sd_ue`wf`xgayhayhayhbxy‘y‘y‘y‘yy~ywgbvfateasd`qd`pc`nb_la_€ut|ssxqrunpZUXVRWROUMMSHIRIC@967-/3'+0(*-ACF?AD;=@#%(
-.+>1(B3)B2&F4'E4)gTGlXJs^OzcTzaPqfethgvjhbVTcWUdXVeYWfZXg[Yh\Zi]Zi][j^\€us€ususts~tt~tt}tt|st{stut~tt|sszrsyqrwpquoqsmpqloXTXTQWPOULLSSJEA<:=99757335./2113)+.'),)+.8:="(
-"6*#5*">2)>0&A2'C3(I8-^OFbRHfUJjXMq^RwcVzfYfRDfQCdN@zdTqijrjksklrklrklrklqjmpjmpjmojmojmnimmimkhliflscYm`Xg\VbYT^VRE>;A<:>98:77645:873220/0,-/)+.*,/#%( &
-
-&3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!'
-
- %' %$#" ! !$
-
-
- 
-
-
-*  
-  ;?E7CU;HY=I[ 
diff --git a/ext/tk/sample/demos-jp/items.rb b/ext/tk/sample/demos-jp/items.rb
index e1007c5a8d..64ceeff3ec 100644
--- a/ext/tk/sample/demos-jp/items.rb
+++ b/ext/tk/sample/demos-jp/items.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# canvas item types widget demo (called by 'widget')
#
@@ -15,8 +16,10 @@ $items_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($items_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($items_demo) {
+TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -24,9 +27,10 @@ TkLabel.new($items_demo) {
}.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($items_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $items_demo
$items_demo = nil
@@ -42,7 +46,7 @@ TkFrame.new($items_demo) {|frame|
# frame À¸À®
cvs = nil
-TkFrame.new($items_demo) {|cf|
+TkFrame.new(base_frame) {|cf|
# canvas À¸À®
cvs = TkCanvas.new(cf) {|c|
focus
@@ -70,11 +74,11 @@ TkFrame.new($items_demo) {|cf|
else
c.grid('in'=>cf, 'row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
vs.grid('row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
hs.grid('row'=>1, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
TkGrid.rowconfigure(cf, 0, 'weight'=>1, 'minsize'=>0)
TkGrid.columnconfigure(cf, 0, 'weight'=>1, 'minsize'=>0)
@@ -90,8 +94,13 @@ TkcLine.new(cvs, '0c', '16c', '30c', '16c', 'width'=>2)
TkcLine.new(cvs, '10c', '0c', '10c', '24c', 'width'=>2)
TkcLine.new(cvs, '20c', '0c', '20c', '24c', 'width'=>2)
-font1 = '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
-font2 = '-Adobe-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*'
+if $tk_version =~ /^4.*/
+ font1 = '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
+ font2 = '-Adobe-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*'
+else
+ font1 = 'Helvetica 12'
+ font2 = 'Helvetica 24 bold'
+end
if TkWinfo.depth($root).to_i > 1
blue = 'DeepSkyBlue3'
red = 'red'
@@ -110,131 +119,129 @@ $tag_item = TkcGroup.new(cvs)
# Set up demos within each of the areas of the grid.
TkcText.new(cvs, '5c', '.2c', 'text'=>'¥é¥¤¥ó', 'anchor'=>'n')
TkcLine.new(cvs, '1c', '1c', '3c', '1c', '1c', '4c', '3c', '4c',
- 'width'=>2, 'fill'=>blue, 'capstyle'=>'butt',
- 'join'=>'miter', 'tags'=>$tag_item )
+ 'width'=>2, 'fill'=>blue, 'capstyle'=>'butt',
+ 'join'=>'miter', 'tags'=>$tag_item )
TkcLine.new(cvs, '4.67c','1c','4.67c','4c', 'arrow'=>'last', 'tags'=>$tag_item)
TkcLine.new(cvs, '6.33c','1c','6.33c','4c', 'arrow'=>'both', 'tags'=>$tag_item)
TkcLine.new(cvs, '5c','6c','9c','6c','9c','1c','8c','1c','8c','4.8c','8.8c',
- '4.8c','8.8c','1.2c','8.2c','1.2c','8.2c','4.6c','8.6c','4.6c',
- '8.6c','1.4c','8.4c','1.4c','8.4c','4.4c',
- 'width'=>3, 'fill'=>red, 'tags'=>$tag_item )
+ '4.8c','8.8c','1.2c','8.2c','1.2c','8.2c','4.6c','8.6c','4.6c',
+ '8.6c','1.4c','8.4c','1.4c','8.4c','4.4c',
+ 'width'=>3, 'fill'=>red, 'tags'=>$tag_item )
TkcLine.new(cvs, '1c','5c','7c','5c','7c','7c','9c','7c', 'width'=>'.5c',
- 'stipple'=>'@'+[$demo_dir,
- 'images','gray25.bmp'].join(File::Separator),
- 'arrow'=>'both', 'arrowshape'=>'15 15 7', 'tags'=>$tag_item )
+ 'stipple'=>'@'+[$demo_dir,'..',
+ 'images','gray25.xbm'].join(File::Separator),
+ 'arrow'=>'both', 'arrowshape'=>'15 15 7', 'tags'=>$tag_item )
TkcLine.new(cvs, '1c','7c','1.75c','5.8c','2.5c','7c','3.25c','5.8c','4c','7c',
- 'width'=>'.5c', 'capstyle'=>'round', 'join'=>'round',
- 'tags'=>$tag_item )
+ 'width'=>'.5c', 'capstyle'=>'round', 'join'=>'round',
+ 'tags'=>$tag_item )
TkcText.new(cvs, '15c', '.2c',
- 'text'=>'¶ÊÀþ (³ê¤é¤«¤Ë¤Ä¤Ê¤¤¤ÀľÀþ)', 'anchor'=>'n')
+ 'text'=>'¶ÊÀþ (³ê¤é¤«¤Ë¤Ä¤Ê¤¤¤ÀľÀþ)', 'anchor'=>'n')
TkcLine.new(cvs, '11c','4c','11.5c','1c','13.5c','1c','14c','4c',
- 'smooth'=>'on', 'fill'=>blue, 'tags'=>$tag_item )
+ 'smooth'=>'on', 'fill'=>blue, 'tags'=>$tag_item )
TkcLine.new(cvs, '15.5c','1c','19.5c','1.5c','15.5c','4.5c','19.5c','4c',
- 'smooth'=>'on', 'arrow'=>'both', 'width'=>3, 'tags'=>$tag_item )
+ 'smooth'=>'on', 'arrow'=>'both', 'width'=>3, 'tags'=>$tag_item )
TkcLine.new(cvs, '12c','6c','13.5c','4.5c','16.5c','7.5c','18c','6c',
- '16.5c','4.5c','13.5c','7.5c','12c','6c',
- 'smooth'=>'on', 'width'=>'3m', 'capstyle'=>'round',
- 'stipple'=>'@'+[$demo_dir,
- 'images', 'gray25.bmp'].join(File::Separator),
- 'fill'=>red, 'tags'=>$tag_item )
+ '16.5c','4.5c','13.5c','7.5c','12c','6c',
+ 'smooth'=>'on', 'width'=>'3m', 'capstyle'=>'round',
+ 'stipple'=>'@'+[$demo_dir, '..',
+ 'images', 'gray25.xbm'].join(File::Separator),
+ 'fill'=>red, 'tags'=>$tag_item )
TkcText.new(cvs, '25c', '.2c', 'text'=>'¿³Ñ·Á', 'anchor'=>'n')
TkcPolygon.new(cvs, '21c','1.0c','22.5c','1.75c','24c','1.0c','23.25c','2.5c',
- '24c','4.0c','22.5c','3.25c','21c','4.0c','21.75c','2.5c',
- 'fill'=>'green', 'outline'=>'black', 'width'=>4,
- 'tags'=>$tag_item )
+ '24c','4.0c','22.5c','3.25c','21c','4.0c','21.75c','2.5c',
+ 'fill'=>'green', 'outline'=>'black', 'width'=>4,
+ 'tags'=>$tag_item )
TkcPolygon.new(cvs, '25c','4c','25c','4c','25c','1c','26c','1c','27c','4c',
- '28c','1c','29c','1c','29c','4c','29c','4c',
- 'fill'=>red, 'smooth'=>'on', 'tags'=> $tag_item)
+ '28c','1c','29c','1c','29c','4c','29c','4c',
+ 'fill'=>red, 'smooth'=>'on', 'tags'=> $tag_item)
TkcPolygon.new(cvs, '22c','4.5c','25c','4.5c','25c','6.75c','28c','6.75c',
- '28c','5.25c','24c','5.25c','24c','6.0c','26c','6c','26c',
- '7.5c','22c','7.5c',
- 'stipple'=>'@' + [$demo_dir,
- 'images', 'gray25.bmp'].join(File::Separator),
- 'outline'=>'black', 'tags'=>$tag_item )
+ '28c','5.25c','24c','5.25c','24c','6.0c','26c','6c','26c',
+ '7.5c','22c','7.5c',
+ 'stipple'=>'@' + [$demo_dir, '..',
+ 'images', 'gray25.xbm'].join(File::Separator),
+ 'outline'=>'black', 'tags'=>$tag_item )
TkcText.new(cvs, '5c', '8.2c', 'text'=>'¶ë·Á', 'anchor'=>'n')
TkcRectangle.new(cvs, '1c','9.5c','4c','12.5c',
- 'outline'=>red, 'width'=>'3m', 'tags'=>$tag_item)
+ 'outline'=>red, 'width'=>'3m', 'tags'=>$tag_item)
TkcRectangle.new(cvs, '0.5c','13.5c','4.5c','15.5c',
- 'fill'=>green, 'tags'=>$tag_item )
+ 'fill'=>green, 'tags'=>$tag_item )
TkcRectangle.new(cvs, '6c','10c','9c','15c', 'outline'=>'',
- 'stipple'=>'@'+[$demo_dir,
- 'images','gray25.bmp'].join(File::Separator),
- 'fill'=>blue, 'tags'=>$tag_item )
+ 'stipple'=>'@'+[$demo_dir,'..',
+ 'images','gray25.xbm'].join(File::Separator),
+ 'fill'=>blue, 'tags'=>$tag_item )
TkcText.new(cvs, '15c', '8.2c', 'text'=>'Âʱß', 'anchor'=>'n')
TkcOval.new(cvs, '11c','9.5c','14c','12.5c',
- 'outline'=>red, 'width'=>'3m', 'tags'=>$tag_item)
+ 'outline'=>red, 'width'=>'3m', 'tags'=>$tag_item)
TkcOval.new(cvs, '10.5c','13.5c','14.5c','15.5c',
- 'fill'=>green, 'tags'=>$tag_item )
+ 'fill'=>green, 'tags'=>$tag_item )
TkcOval.new(cvs, '16c','10c','19c','15c', 'outline'=>'',
- 'stipple'=>'@'+[$demo_dir,
- 'images','gray25.bmp'].join(File::Separator),
- 'fill'=>blue, 'tags'=>$tag_item )
+ 'stipple'=>'@'+[$demo_dir,'..',
+ 'images','gray25.xbm'].join(File::Separator),
+ 'fill'=>blue, 'tags'=>$tag_item )
TkcText.new(cvs, '25c', '8.2c', 'text'=>'¥Æ¥­¥¹¥È', 'anchor'=>'n')
TkcRectangle.new(cvs, '22.4c','8.9c','22.6c','9.1c')
TkcText.new(cvs, '22.5c', '9c', 'anchor'=>'n', 'font'=>font1, 'width'=>'4c',
- 'text'=>'û¤¤¥Æ¥­¥¹¥È¡£¥ï¡¼¥É¥é¥Ã¥×¡¢º¸Â·¤¨¡¢¥¢¥ó¥«¡¼¤ÏËÌ (¾å)¡£\
-¢¢¤Ï³Æ¥Æ¥­¥¹¥È¤Î¥¢¥ó¥«¡¼¥Ý¥¤¥ó¥È¤ò¼¨¤¹¡£', 'tags'=>$tag_item )
+ 'text'=>'û¤¤¥Æ¥­¥¹¥È¡£¥ï¡¼¥É¥é¥Ã¥×¡¢º¸Â·¤¨¡¢¥¢¥ó¥«¡¼¤ÏËÌ(¾å)¡£¢¢¤Ï³Æ¥Æ¥­¥¹¥È¤Î¥¢¥ó¥«¡¼¥Ý¥¤¥ó¥È¤ò¼¨¤¹¡£', 'tags'=>$tag_item )
TkcRectangle.new(cvs, '25.4c','10.9c','25.6c','11.1c')
TkcText.new(cvs, '25.5c', '11c', 'anchor'=>'w', 'font'=>font1, 'fill'=>blue,
- 'text'=>'¤¤¤¯¤Ä¤«¤Î¹Ô¡£\n¤½¤ì¤¾¤ìÆÈΩ¤Ë\n¹Ô·¤¨¡£\n\
-Á´¤Æº¸Ã¼¤¬¥¢¥ó¥«¡¼¤µ¤ì¤Æ¤¤¤ë¡£', 'justify'=>'center', 'tags'=>$tag_item )
+ 'text'=>"¤¤¤¯¤Ä¤«¤Î¹Ô¡£\n¤½¤ì¤¾¤ìÆÈΩ¤Ë\n¹Ô·¤¨¡£\nÁ´¤Æº¸Ã¼¤¬¥¢¥ó¥«¡¼¤µ¤ì¤Æ¤¤¤ë¡£", 'justify'=>'center', 'tags'=>$tag_item )
TkcRectangle.new(cvs, '24.9c','13.9c','25.1c','14.1c')
if $tk_version =~ /^4\.[01]/
TkcText.new(cvs, '25c', '14c', 'anchor'=>'c', 'font'=>font2, 'fill'=>red,
- 'stipple'=>'@' + [$demo_dir,
+ 'stipple'=>'@' + [$demo_dir, '..',
'images', 'grey.5'].join(File::Separator),
- 'text'=>'Stippled characters', 'tags'=>$tag_item )
+ 'text'=>'Stippled characters', 'tags'=>$tag_item )
else
TkcText.new(cvs, '25c', '14c', 'anchor'=>'c', 'font'=>font2, 'fill'=>red,
- 'stipple'=>'gray50', 'text'=>'Stippled characters',
- 'tags'=>$tag_item )
+ 'stipple'=>'gray50', 'text'=>'Stippled characters',
+ 'tags'=>$tag_item )
end
TkcText.new(cvs, '5c', '16.2c', 'text'=>'¸Ì', 'anchor'=>'n')
TkcArc.new(cvs, '0.5c','17c','7c','20c', 'fill'=>green, 'outline'=>'black',
- 'start'=>45, 'extent'=>270, 'style'=>'pieslice', 'tags'=>$tag_item)
+ 'start'=>45, 'extent'=>270, 'style'=>'pieslice', 'tags'=>$tag_item)
#TkcArc.new(cvs, '6.5c','17c','9.5c','20c', 'width'=>'4m', 'style'=>'arc',
-# 'outline'=>blue, 'start'=>135, 'extent'=>270,
-# 'outlinestipple'=>'@' + ['images', 'grey.25'].join(File::Separator),
-# 'tags'=>$tag_item)
+# 'outline'=>blue, 'start'=>135, 'extent'=>270,
+# 'outlinestipple'=>'@' + ['images', 'grey.25'].join(File::Separator),
+# 'tags'=>$tag_item)
TkcArc.new(cvs, '6.5c','17c','9.5c','20c', 'width'=>'4m', 'style'=>'arc',
- 'outline'=>blue, 'start'=>135, 'extent'=>270,
- 'outlinestipple'=>'@'+[$demo_dir,
- 'images','gray25.bmp'].join(File::Separator),
- 'tags'=>$tag_item)
+ 'outline'=>blue, 'start'=>135, 'extent'=>270,
+ 'outlinestipple'=>'@'+[$demo_dir, '..',
+ 'images','gray25.xbm'].join(File::Separator),
+ 'tags'=>$tag_item)
TkcArc.new(cvs, '0.5c','20c','9.5c','24c', 'width'=>'4m', 'style'=>'pieslice',
- 'fill'=>'', 'outline'=>red, 'start'=>225, 'extent'=>90,
- 'tags'=>$tag_item)
+ 'fill'=>'', 'outline'=>red, 'start'=>225, 'extent'=>90,
+ 'tags'=>$tag_item)
TkcArc.new(cvs, '5.5c','20.5c','9.5c','23.5c', 'width'=>'4m', 'style'=>'chord',
- 'fill'=>blue, 'outline'=>'', 'start'=>45, 'extent'=>270,
- 'tags'=>$tag_item)
+ 'fill'=>blue, 'outline'=>'', 'start'=>45, 'extent'=>270,
+ 'tags'=>$tag_item)
TkcText.new(cvs, '15c', '16.2c', 'text'=>'¥Ó¥Ã¥È¥Þ¥Ã¥×', 'anchor'=>'n')
#TkcBitmap.new(cvs, '13c','20c',
-# 'bitmap'=>'@' + ['images', 'face'].join(File::Separator),
-# 'tags'=>$tag_item)
+# 'bitmap'=>'@' + ['images', 'face'].join(File::Separator),
+# 'tags'=>$tag_item)
TkcBitmap.new(cvs, '13c','20c',
- 'bitmap'=>'@' + [$demo_dir,
- 'images', 'face.bmp'].join(File::Separator),
- 'tags'=>$tag_item)
+ 'bitmap'=>'@' + [$demo_dir, '..',
+ 'images', 'face.xbm'].join(File::Separator),
+ 'tags'=>$tag_item)
#TkcBitmap.new(cvs, '17c','18.5c',
-# 'bitmap'=>'@' + ['images', 'noletters'].join(File::Separator),
-# 'tags'=>$tag_item)
+# 'bitmap'=>'@' + ['images', 'noletters'].join(File::Separator),
+# 'tags'=>$tag_item)
TkcBitmap.new(cvs, '17c','18.5c',
- 'bitmap'=>'@' + [$demo_dir,
- 'images', 'noletter.bmp'].join(File::Separator),
- 'tags'=>$tag_item)
+ 'bitmap'=>'@' + [$demo_dir, '..',
+ 'images', 'noletter.xbm'].join(File::Separator),
+ 'tags'=>$tag_item)
#TkcBitmap.new(cvs, '17c','21.5c',
-# 'bitmap'=>'@' + ['images', 'letters'].join(File::Separator),
-# 'tags'=>$tag_item)
+# 'bitmap'=>'@' + ['images', 'letters'].join(File::Separator),
+# 'tags'=>$tag_item)
# ¢­¤Î·Á¼°¤Ç¤â²Äǽ
TkcBitmap.new(cvs, '17c','21.5c') {
- bitmap '@' + [$demo_dir, 'images', 'letters.bmp'].join(File::Separator)
+ bitmap '@' + [$demo_dir, '..', 'images', 'letters.xbm'].join(File::Separator)
tags $tag_item
}
#TkcBitmap.new(cvs, '17c','21.5c') {
@@ -247,17 +254,17 @@ TkButton.new(cvs) {|b|
text '²¡¤·¤Æ¤Í'
command proc{butPress cvs, red}
TkcWindow.new(cvs, '21c','18c',
- 'window'=>b, 'anchor'=>'nw', 'tags'=>$tag_item)
+ 'window'=>b, 'anchor'=>'nw', 'tags'=>$tag_item)
}
TkEntry.new(cvs, 'width'=>20, 'relief'=>'sunken') {|e|
insert 'end', 'ÊÔ½¸¤·¤Æ¤Í'
TkcWindow.new(cvs, '21c','21c',
- 'window'=>e, 'anchor'=>'nw', 'tags'=>$tag_item)
+ 'window'=>e, 'anchor'=>'nw', 'tags'=>$tag_item)
}
TkScale.new(cvs, 'from'=>0, 'to'=>100, 'length'=>'6c', 'sliderlength'=>'.4c',
- 'width'=>'.5c', 'tickinterval'=>0 ) {|scl|
+ 'width'=>'.5c', 'tickinterval'=>0 ) {|scl|
TkcWindow.new(cvs, '28.5c','17.5c',
- 'window'=>scl, 'anchor'=>'n', 'tags'=>$tag_item)
+ 'window'=>scl, 'anchor'=>'n', 'tags'=>$tag_item)
}
TkcText.new(cvs, '21c', '17.9c', 'text'=>'¥Ü¥¿¥ó:', 'anchor'=>'sw')
TkcText.new(cvs, '21c', '20.9c', 'text'=>'¥¨¥ó¥È¥ê:', 'anchor'=>'sw')
@@ -322,7 +329,7 @@ def itemStroke(c,x,y)
if $areaX1 != x && $areaY1 != y
c.delete 'area'
c.addtag_withtag 'area', TkcRectangle.new(c, $areaX1, $areaY1, x, y,
- '-outline', 'black')
+ '-outline', 'black')
$areaX2 = x
$areaY2 = y
end
@@ -357,7 +364,7 @@ end
def itemDrag(c,x,y)
x = c.canvasx(x)
y = c.canvasy(y)
- c.move 'current', x - $lastX, y - $lastY
+ c.move('current', x - $lastX, y - $lastY)
$lastX = x
$lastY = y
end
@@ -367,6 +374,6 @@ end
def butPress(w,color)
i = TkcText.new(w, '25c', '18.1c',
- 'text'=>'¤¤¤Æ¤Æ!!', 'fill'=>color, 'anchor'=>'n')
+ 'text'=>'¤¤¤Æ¤Æ!!', 'fill'=>color, 'anchor'=>'n')
Tk.after(500, proc{w.delete i})
end
diff --git a/ext/tk/sample/demos-jp/ixset2 b/ext/tk/sample/demos-jp/ixset2
index 8947daa4b4..5b816e40b1 100644
--- a/ext/tk/sample/demos-jp/ixset2
+++ b/ext/tk/sample/demos-jp/ixset2
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# -*- coding: euc-jp -*-
#
# ixset --
# A nice interface to "xset" to change X server settings
diff --git a/ext/tk/sample/demos-jp/knightstour.rb b/ext/tk/sample/demos-jp/knightstour.rb
new file mode 100644
index 0000000000..d4595ea441
--- /dev/null
+++ b/ext/tk/sample/demos-jp/knightstour.rb
@@ -0,0 +1,273 @@
+# -*- coding: euc-jp -*-
+#
+# Based on the widget demo of Tcl/Tk8.5.2
+# The following is the original copyright text.
+#----------------------------------------------------------------------------
+# Copyright (C) 2008 Pat Thoyts <patthoyts@users.sourceforge.net>
+#
+# Calculate a Knight's tour of a chessboard.
+#
+# This uses Warnsdorff's rule to calculate the next square each
+# time. This specifies that the next square should be the one that
+# has the least number of available moves.
+#
+# Using this rule it is possible to get to a position where
+# there are no squares available to move into. In this implementation
+# this occurs when the starting square is d6.
+#
+# To solve this fault an enhancement to the rule is that if we
+# have a choice of squares with an equal score, we should choose
+# the one nearest the edge of the board.
+#
+# If the call to the Edgemost function is commented out you can see
+# this occur.
+#
+# You can drag the knight to a specific square to start if you wish.
+# If you let it repeat then it will choose random start positions
+# for each new tour.
+#----------------------------------------------------------------------------
+require 'tk'
+
+class Knights_Tour
+ # Return a list of accessible squares from a given square
+ def valid_moves(square)
+ moves = []
+ [
+ [-1,-2], [-2,-1], [-2,1], [-1,2], [1,2], [2,1], [2,-1], [1,-2]
+ ].each{|col_delta, row_delta|
+ col = (square % 8) + col_delta
+ row = (square.div(8)) + row_delta
+ moves << (row * 8 + col) if row > -1 && row < 8 && col > -1 && col < 8
+ }
+ moves
+ end
+
+ # Return the number of available moves for this square
+ def check_square(square)
+ valid_moves(square).find_all{|pos| ! @visited.include?(pos)}.length
+ end
+
+ # Select the next square to move to. Returns -1 if there are no available
+ # squares remaining that we can move to.
+ def next_square(square)
+ minimum = 9
+ nxt = -1
+ valid_moves(square).each{|pos|
+ unless @visited.include?(pos)
+ cnt = check_square(pos)
+ if cnt < minimum
+ minimum = cnt
+ nxt = pos
+ elsif cnt == minimum
+ nxt = edgemost(nxt, pos)
+ end
+ end
+ }
+ nxt
+ end
+
+ # Select the square nearest the edge of the board
+ def edgemost(nxt, pos)
+ col_A = 3 - ((3.5 - nxt % 8).abs.to_i)
+ col_B = 3 - ((3.5 - pos % 8).abs.to_i)
+ row_A = 3 - ((3.5 - nxt.div(8)).abs.to_i)
+ row_B = 3 - ((3.5 - pos.div(8)).abs.to_i)
+ (col_A * row_A < col_B * row_B)? nxt : pos
+ end
+
+ # Display a square number as a standard chess square notation.
+ def _N(square)
+ '%c%d' % [(97 + square % 8), (square.div(8) + 1)]
+ end
+
+ # Perform a Knight's move and schedule the next move.
+ def move_piece(last, square)
+ @log.insert(:end, "#{@visited.length}. #{_N last} -> #{_N square}\n", '')
+ @log.see(:end)
+ @board.itemconfigure(1+last, :state=>:normal, :outline=>'black')
+ @board.itemconfigure(1+square, :state=>:normal, :outline=>'red')
+ @knight.coords(@board.coords(1+square)[0..1])
+ @visited << square
+ if (nxt = next_square(square)) != -1
+ @after_id = Tk.after(@delay.numeric){move_piece(square, nxt) rescue nil}
+ else
+ @start_btn.state :normal
+ if @visited.length == 64
+ if @initial == square
+ @log.insert :end, '¼þÍ·(closed tour)À®¸ù¡ª'
+ else
+ @log.insert :end, "À®¸ù\n", {}
+ Tk.after(@delay.numeric * 2){tour(rand(64))} if @continuous.bool
+ end
+ else
+ @log.insert :end, "¼ºÇÔ¡ª\n", {}
+ end
+ end
+ end
+
+ # Begin a new tour of the board given a random start position
+ def tour(square = nil)
+ @visited.clear
+ @log.clear
+ @start_btn.state :disabled
+ 1.upto(64){|n|
+ @board.itemconfigure(n, :state=>:disabled, :outline=>'black')
+ }
+ unless square
+ square = @board.find_closest(*(@knight.coords << 0 << 65))[0].to_i - 1
+ end
+ @initial = square
+ Tk.after_idle{ move_piece(@initial, @initial) rescue nil }
+ end
+
+ def _stop
+ Tk.after_cancel(@after_id) rescue nil
+ end
+
+ def _exit
+ _stop
+ $knightstour.destroy
+ end
+
+ def set_delay(new)
+ @delay.numeric = new.to_i
+ end
+
+ def drag_start(w, x, y)
+ w.dtag('selected')
+ w.addtag('selected', :withtag, 'current')
+ @dragging = [x, y]
+ end
+
+ def drag_motion(w, x, y)
+ return unless @dragging
+ w.move('selected', x - @dragging[0], y - @dragging[1])
+ @dragging = [x, y]
+ end
+
+ def drag_end(w, x, y)
+ square = w.find_closest(x, y, 0, 65)
+ w.coords('selected', w.coords(square)[0..1])
+ w.dtag('selected')
+ @dragging = nil
+ end
+
+ def make_SeeDismiss
+ ## See Code / Dismiss
+ frame = Ttk::Frame.new($knightstour)
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'knightstour'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $knightstour.destroy
+ $knightstour = nil
+ }),
+ :padx=>4, :pady=>4)
+ frame.grid_columnconfigure(0, :weight=>1)
+ frame
+ end
+
+ def create_gui(parent = nil)
+ $knightstour.destroy rescue nil
+ $knightstour = Tk::Toplevel.new(parent, :title=>"Knight's tour")
+ $knightstour.withdraw
+ base_f = Ttk::Frame.new($knightstour)
+ @board = Tk::Canvas.new(base_f, :width=>240, :height=>240)
+ @log = Tk::Text.new(base_f, :width=>12, :height=>1,
+ :font=>'Arial 8', :background=>'white')
+ scr = @log.yscrollbar(Ttk::Scrollbar.new(base_f))
+
+ @visited = []
+ @delay = TkVariable.new(600)
+ @continuous = TkVariable.new(false)
+
+ tool_f = Ttk::Frame.new($knightstour)
+ label = Ttk::Label.new(tool_f, :text=>'¼Â¹Ô®ÅÙ')
+ scale = Ttk::Scale.new(tool_f, :from=>8, :to=>2000, :variable=>@delay,
+ :command=>proc{|n| set_delay(n)})
+ check = Ttk::Checkbutton.new(tool_f, :text=>'È¿Éü',
+ :variable=>@continuous)
+ @start_btn = Ttk::Button.new(tool_f, :text=>'³«»Ï',
+ :command=>proc{tour()})
+ @exit_btn = Ttk::Button.new(tool_f, :text=>'½ªÎ»',
+ :command=>proc{_exit()})
+
+ 7.downto(0){|row|
+ 0.upto(7){|col|
+ if ((col & 1) ^ (row & 1)).zero?
+ fill = 'bisque'
+ dfill = 'bisque3'
+ else
+ fill = 'tan3'
+ dfill = 'tan4'
+ end
+ coords = [col * 30 + 4, row * 30 + 4, col * 30 + 30, row * 30 + 30]
+ @board.create(TkcRectangle, coords,
+ :fill=>fill, :disabledfill=>dfill,
+ :width=>2, :state=>:disabled)
+ }
+ }
+
+ @knight_font = TkFont.new(:size=>-24)
+ @knight = TkcText.new(@board, 0, 0, :font=>@knight_font,
+ :text=>Tk::UTF8_String.new('\u265e'),
+ :anchor=>'nw', # :tags=>'knight',
+ :fill=>'black', :activefill=>'#600000')
+ @knight.coords(@board.coords(rand(64)+1)[0..1])
+ @knight.bind('ButtonPress-1', '%W %x %y'){|w,x,y| drag_start(w,x,y)}
+ @knight.bind('Motion', '%W %x %y'){|w,x,y| drag_motion(w,x,y)}
+ @knight.bind('ButtonRelease-1', '%W %x %y'){|w,x,y| drag_end(w,x,y)}
+
+ Tk.grid(@board, @log, scr, :sticky=>'news')
+ base_f.grid_rowconfigure(0, :weight=>1)
+ base_f.grid_columnconfigure(0, :weight=>1)
+
+ Tk.grid(base_f, '-', '-', '-', '-', '-', :sticky=>'news')
+ widgets = [label, scale, check, @start_btn]
+ sg = nil
+ unless $RubyTk_WidgetDemo
+ widgets << @exit_btn
+ if Tk.windowingsystem != 'aqua'
+ #widgets.unshift(Ttk::SizeGrip.new(tool_f))
+ Ttk::SizeGrip.new(tool_f).pack(:side=>:right, :anchor=>'se')
+ end
+ end
+ Tk.pack(widgets, :side=>:right)
+ if Tk.windowingsystem == 'aqua'
+ TkPack.configure(widgets, :padx=>[4, 4], :pady=>[12, 12])
+ TkPack.configure(widgets[0], :padx=>[4, 24])
+ TkPack.configure(widgets[-1], :padx=>[16, 4])
+ end
+
+ Tk.grid(tool_f, '-', '-', '-', '-', '-', :sticky=>'ew')
+
+ if $RubyTk_WidgetDemo
+ Tk.grid(make_SeeDismiss(), '-', '-', '-', '-', '-', :sticky=>'ew')
+ end
+
+ $knightstour.grid_rowconfigure(0, :weight=>1)
+ $knightstour.grid_columnconfigure(0, :weight=>1)
+
+ $knightstour.bind('Control-F2'){TkConsole.show}
+ $knightstour.bind('Return'){@start_btn.invoke}
+ $knightstour.bind('Escape'){@exit_btn.invoke}
+ $knightstour.bind('Destroy'){ _stop }
+ $knightstour.protocol('WM_DELETE_WINDOW'){ _exit }
+
+ $knightstour.deiconify
+ $knightstour.tkwait_destroy
+ end
+
+ def initialize(parent = nil)
+ create_gui(parent)
+ end
+end
+
+Tk.root.withdraw unless $RubyTk_WidgetDemo
+Thread.new{Tk.mainloop} if __FILE__ == $0
+Knights_Tour.new
diff --git a/ext/tk/sample/demos-jp/label.rb b/ext/tk/sample/demos-jp/label.rb
index 80ab5f3d8f..2e6b3e7e57 100644
--- a/ext/tk/sample/demos-jp/label.rb
+++ b/ext/tk/sample/demos-jp/label.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# label widget demo (called by 'widget')
#
@@ -15,8 +16,10 @@ $label_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($label_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($label_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($label_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($label_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $label_demo
$label_demo = nil
@@ -43,20 +47,21 @@ TkFrame.new($label_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# label demo Íѥե졼¥àÀ¸À®
-f_left = TkFrame.new($label_demo)
-f_right = TkFrame.new($label_demo)
+f_left = TkFrame.new(base_frame)
+f_right = TkFrame.new(base_frame)
[f_left, f_right].each{|w| w.pack('side'=>'left', 'expand'=>'yes',
- 'padx'=>10, 'pady'=>10, 'fill'=>'both')}
+ 'padx'=>10, 'pady'=>10, 'fill'=>'both')}
# label À¸À®
[ TkLabel.new(f_left, 'text'=>'ºÇ½é¤Î¥é¥Ù¥ë'),
TkLabel.new(f_left, 'text'=>'2 ÈÖÌÜ¡£¤Á¤ç¤Ã¤ÈÉ⤭¾å¤¬¤é¤»¤Æ¤ß¤Þ¤·¤¿',
- 'relief'=>'raised'),
+ 'relief'=>'raised'),
TkLabel.new(f_left, 'text'=>'3 ÈÖÌÜ¡£ÄÀ¤ó¤Ç¤¤¤Þ¤¹ ', 'relief'=>'sunken')
].each{|w| w.pack('side'=>'top', 'expand'=>'yes', 'pady'=>2, 'anchor'=>'w')}
-TkLabel.new(f_right) {
- bitmap('@' + [$demo_dir,'images','face.bmp'].join(File::Separator))
+# TkLabel.new(f_right) {
+Tk::Label.new(f_right) {
+ bitmap('@' + [$demo_dir,'..','images','face.xbm'].join(File::Separator))
borderwidth 2
relief 'sunken'
}.pack('side'=>'top')
diff --git a/ext/tk/sample/demos-jp/labelframe.rb b/ext/tk/sample/demos-jp/labelframe.rb
index 044fcd23ae..11b0d27308 100644
--- a/ext/tk/sample/demos-jp/labelframe.rb
+++ b/ext/tk/sample/demos-jp/labelframe.rb
@@ -1,3 +1,5 @@
+# -*- coding: euc-jp -*-
+#
# labelframe.rb
#
# This demonstration script creates a toplevel window containing
@@ -17,10 +19,12 @@ $labelframe_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($labelframe_demo).pack(:fill=>:both, :expand=>true)
+
# Some information
-TkLabel.new($labelframe_demo,
- :font=>$font, :wraplength=>'4i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
TkLabelFrame ¥¦¥£¥¸¥§¥Ã¥È¤Ï´ØÏ¢¤¹¤ë widget
·²¤ò¤Þ¤È¤á¤Æ¼è¤ê°·¤¦¤¿¤á¤ËÍѤ¤¤é¤ì¤Þ¤¹¡£¥é
¥Ù¥ë¤ÏÄ̾ï¤Îʸ»úÎó¤Ç¤â²¿¤é¤«¤Î¥¦¥£¥¸¥§¥Ã¥È
@@ -34,32 +38,32 @@ labelframe ¥¦¥£¥¸¥§¥Ã¥È¤ò¼ÂÁõ¤·¤Æ¤¤¤Ê¤¤
EOL
# The bottom buttons
-TkFrame.new($labelframe_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
- TkButton.new(f, :text=>'λ²ò', :width=>15, :command=>proc{
- $labelframe_demo.destroy
- $labelframe_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ TkButton.new(f, :text=>'ÊĤ¸¤ë', :width=>15, :command=>proc{
+ $labelframe_demo.destroy
+ $labelframe_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'¥³¡¼¥É»²¾È', :width=>15, :command=>proc{
- showCode 'labelframe'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'labelframe'
+ }).pack(:side=>:left, :expand=>true)
}
# Demo area
-w = TkFrame.new($labelframe_demo).pack(:side=>:bottom, :fill=>:both,
- :expand=>true)
+w = TkFrame.new(base_frame).pack(:side=>:bottom, :fill=>:both,
+ :expand=>true)
# A group of radiobuttons in a labelframe
TkLabelFrame.new(w, :text=>'ÁªÂòÃÍ',
- :padx=>2, :pady=>2) {|f|
+ :padx=>2, :pady=>2) {|f|
grid(:row=>0, :column=>0, :pady=>'2m', :padx=>'2m')
v = TkVariable.new
(1..4).each{|i|
TkRadiobutton.new(f, :text=>"This is value #{i}",
- :variable=>v, :value=>i) {
+ :variable=>v, :value=>i) {
pack(:side=>:top, :fill=>:x, :pady=>2)
}
}
@@ -82,7 +86,7 @@ end
TkLabelFrame.new(w, :pady=>2, :padx=>2){|f|
TkCheckButton.new(f, :widgetname=>'cb', :variable=>$lfdummy,
- :text=>"¥ª¥×¥·¥ç¥ó¤ò»ÈÍÑ", :padx=>0) {|cb|
+ :text=>"¥ª¥×¥·¥ç¥ó¤ò»ÈÍÑ", :padx=>0) {|cb|
command proc{lfEnableButtons(f)}
f.labelwidget(cb)
}
diff --git a/ext/tk/sample/demos-jp/mclist.rb b/ext/tk/sample/demos-jp/mclist.rb
new file mode 100644
index 0000000000..a7834d2668
--- /dev/null
+++ b/ext/tk/sample/demos-jp/mclist.rb
@@ -0,0 +1,121 @@
+# -*- coding: euc-jp -*-
+#
+# mclist.rb --
+#
+# This demonstration script creates a toplevel window containing a Ttk
+# tree widget configured as a multi-column listbox.
+#
+# based on "Id: mclist.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($mclist_demo) && $mclist_demo
+ $mclist_demo.destroy
+ $mclist_demo = nil
+end
+
+$mclist_demo = TkToplevel.new {|w|
+ title("Multi-Column List")
+ iconname("mclist")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($mclist_demo).pack(:fill=>:both, :expand=>true)
+
+## Explanatory text
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i',
+ :justify=>:left, :anchor=>'n', :padding=>[10, 2, 10, 6],
+ :text=><<EOL).pack(:fill=>:x)
+Ttk¤È¤Ï¡¤¥Æ¡¼¥Þ»ØÄê²Äǽ¤Ê¿·¤·¤¤¥¦¥£¥¸¥§¥Ã¥È½¸¹ç¤Ç¤¹¡¥\
+Ttk::Treeview¥¦¥£¥¸¥§¥Ã¥È¤Ï\
+Ttk¥¦¥£¥¸¥§¥Ã¥È¥»¥Ã¥È¤Ë´Þ¤Þ¤ì¤ë¥¦¥£¥¸¥§¥Ã¥È¤Î°ì¤Ä¤Ç¡¤\
+¤½¤ì¤¬ÊÝ»ý¤¹¤ëÌÚ¹½Â¤¤Î¥Ç¡¼¥¿¤½¤Î¤â¤Î¤Þ¤Ç¤Ïɽ¼¨¤¹¤ë¤³¤È¤Ê¤¯¡¤\
+¼¨¤·¤¿¤¤¾ðÊó¤ò¥Þ¥ë¥Á¥«¥é¥à¤Çɽ¼¨¤µ¤»¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥
+¤³¤Î¥µ¥ó¥×¥ë¤Ï¡¤Ê£¿ô¤Î¥«¥é¥à¤ò»ý¤Ã¤¿¥ê¥¹¥È¥Ü¥Ã¥¯¥¹¤òºîÀ®¤¹¤ë´Êñ¤ÊÎã¤Ç¤¹¡¥
+³Æ¥«¥é¥à¤Î¥¿¥¤¥È¥ë(heading)¤ò¥¯¥ê¥Ã¥¯¤¹¤ì¤Ð¡¤\
+¤½¤Î¥«¥é¥à¤Î¾ðÊó¤Ë´ð¤Å¤¤¤Æ¥ê¥¹¥È¤ÎʤÙÂØ¤¨¤¬¤Ê¤µ¤ì¤ë¤Ï¤º¤Ç¤¹¡¥\
+¤Þ¤¿¡¤¥«¥é¥à¤Î¥¿¥¤¥È¥ë´Ö¤Î¶èÀÚ¤êÉôʬ¤ò¥É¥é¥Ã¥°¤¹¤ë¤³¤È¤Ç¡¤\
+¥«¥é¥à¤ÎÉý¤òÊѹ¹¤¹¤ë¤³¤È¤â²Äǽ¤Ç¤¹¡¥
+EOL
+
+## See Code / Dismiss
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'mclist'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $mclist_demo.destroy
+ $mclist_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+container = Ttk::Frame.new(base_frame)
+tree = Ttk::Treeview.new(base_frame, :columns=>%w(country capital currency),
+ :show=>:headings)
+if Tk.windowingsystem != 'aquq'
+ vsb = tree.yscrollbar(Ttk::Scrollbar.new(base_frame))
+ hsb = tree.xscrollbar(Ttk::Scrollbar.new(base_frame))
+else
+ vsb = tree.yscrollbar(Tk::Scrollbar.new(base_frame))
+ hsb = tree.xscrollbar(Tk::Scrollbar.new(base_frame))
+end
+
+container.pack(:fill=>:both, :expand=>true)
+Tk.grid(tree, vsb, :in=>container, :sticky=>'nsew')
+Tk.grid(hsb, :in=>container, :sticky=>'nsew')
+container.grid_columnconfigure(0, :weight=>1)
+container.grid_rowconfigure(0, :weight=>1)
+
+## The data we're going to insert
+data = [
+ ['¥¢¥ë¥¼¥ó¥Á¥ó', '¥Ö¥¨¥Î¥¹¥¢¥¤¥ì¥¹', 'ARS'],
+ ['¥ª¡¼¥¹¥È¥é¥ê¥¢', '¥­¥ã¥ó¥Ù¥é', 'AUD'],
+ ['¥Ö¥é¥¸¥ë', '¥Ö¥é¥¸¥ê¥¢', 'BRL'],
+ ['¥«¥Ê¥À', '¥ª¥¿¥ï', 'CAD'],
+ ['Ãæ¹ñ', 'Ë̵þ', 'CNY'],
+ ['¥Õ¥é¥ó¥¹', '¥Ñ¥ê', 'EUR'],
+ ['¥É¥¤¥Ä', '¥Ù¥ë¥ê¥ó', 'EUR'],
+ ['¥¤¥ó¥É', '¥Ë¥å¡¼¥Ç¥ê¡¼', 'INR'],
+ ['¥¤¥¿¥ê¥¢', '¥í¡¼¥Þ', 'EUR'],
+ ['ÆüËÜ', 'Åìµþ', 'JPY'],
+ ['¥á¥­¥·¥³', '¥á¥­¥·¥³¥·¥Æ¥£', 'MXN'],
+ ['¥í¥·¥¢', '¥â¥¹¥¯¥ï', 'RUB'],
+ ['Æî¥¢¥Õ¥ê¥«', '¥×¥ì¥È¥ê¥¢', 'ZAR'],
+ ['±Ñ¹ñ', '¥í¥ó¥É¥ó', 'GBP'],
+ ['¥¢¥á¥ê¥«', '¥ï¥·¥ó¥È¥ó D.C.', 'USD'],
+]
+
+## Code to insert the data nicely
+font = Ttk::Style.lookup(tree[:style], :font)
+cols = %w(country capital currency)
+cols.zip(%w(¹ñ̾ ¼óÅÔ Ä̲ß)).each{|col, name|
+ tree.heading_configure(col, :text=>name,
+ :command=>proc{sort_by(tree, col, false)})
+ tree.column_configure(col, :width=>TkFont.measure(font, name))
+}
+
+data.each{|country, capital, currency|
+ #tree.insert('', :end, :values=>[country, capital, currency])
+ tree.insert(nil, :end, :values=>[country, capital, currency])
+ cols.zip([country, capital, currency]).each{|col, val|
+ len = TkFont.measure(font, "#{val} ")
+ if tree.column_cget(col, :width) < len
+ tree.column_configure(col, :width=>len)
+ end
+ }
+}
+
+## Code to do the sorting of the tree contents when clicked on
+def sort_by(tree, col, direction)
+ tree.children(nil).map!{|row| [tree.get(row, col), row.id]} .
+ sort(&((direction)? proc{|x, y| y <=> x}: proc{|x, y| x <=> y})) .
+ each_with_index{|info, idx| tree.move(info[1], nil, idx)}
+
+ tree.heading_configure(col, :command=>proc{sort_by(tree, col, ! direction)})
+end
diff --git a/ext/tk/sample/demos-jp/menu.rb b/ext/tk/sample/demos-jp/menu.rb
index fb32623cc8..c3d95176b4 100644
--- a/ext/tk/sample/demos-jp/menu.rb
+++ b/ext/tk/sample/demos-jp/menu.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# menus widget demo (called by 'widget')
#
@@ -15,13 +16,22 @@ $menu_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($menu_demo).pack(:fill=>:both, :expand=>true)
+
# menu frame À¸À®
-$menu_frame = TkFrame.new($menu_demo, 'relief'=>'raised', 'bd'=>2)
+$menu_frame = TkFrame.new(base_frame, 'relief'=>'raised', 'bd'=>2)
$menu_frame.pack('side'=>'top', 'fill'=>'x')
+begin
+ windowingsystem = Tk.windowingsystem()
+rescue
+ windowingsystem = ""
+end
+
# label À¸À®
-TkLabel.new($menu_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
- if $tk_platform['platform'] == 'macintosh'
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
+ if $tk_platform['platform'] == 'macintosh' ||
+ windowingsystem == "classic" || windowingsystem == "aqua"
text("¤³¤Î¥¦¥£¥ó¥É¥¦¤ÏÍÍ¡¹¤Ê¥á¥Ë¥å¡¼¤È¥«¥¹¥±¡¼¥É¥á¥Ë¥å¡¼¤«¤é¹½À®¤µ¤ì¤Æ¤¤¤Þ¤¹¡£Command-X ¤òÆþÎϤ¹¤ë¤È¡¢X¤¬¥³¥Þ¥ó¥É¥­¡¼µ­¹æ¤Ë³¤¤¤ÆÉ½¼¨¤µ¤ì¤Æ¤¤¤ëʸ»ú¤Ê¤é¤Ð¡¢¥¢¥¯¥»¥é¥ì¡¼¥¿¤ò»È¤Ã¤¿¹àÌܵ¯Æ°¤ò¹Ô¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¥á¥Ë¥å¡¼Í×ÁÇÃæ¡¢ºÇ¸å¤Î¤â¤Î¤Ï¡¢¤½¤Î¥á¥Ë¥å¡¼¤ÎºÇ½é¤Î¹àÌܤòÁªÂò¤¹¤ë¤³¤È¤ÇÆÈΩ¤µ¤»¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£")
else
text("¤³¤Î¥¦¥£¥ó¥É¥¦¤ÏÍÍ¡¹¤Ê¥á¥Ë¥å¡¼¤È¥«¥¹¥±¡¼¥É¥á¥Ë¥å¡¼¤«¤é¹½À®¤µ¤ì¤Æ¤¤¤Þ¤¹¡£Alt-X ¤òÆþÎϤ¹¤ë¤È¡¢X¤¬¥á¥Ë¥å¡¼¤Ë¥¢¥ó¥À¡¼¥é¥¤¥óÉÕ¤­¤Çɽ¼¨¤µ¤ì¤Æ¤¤¤ëʸ»ú¤Ê¤é¤Ð¡¢¥­¡¼¥Ü¡¼¥É¤«¤é¤Î»ØÄ꤬¤Ç¤­¤Þ¤¹¡£Ìð°õ¥­¡¼¤Ç¥á¥Ë¥å¡¼¤Î¥È¥é¥Ð¡¼¥¹¤â²Äǽ¤Ç¤¹¡£¥á¥Ë¥å¡¼¤¬»ØÄꤵ¤ì¤¿ºÝ¤Ë¤Ï¡¢¥¹¥Ú¡¼¥¹¥­¡¼¤Ç¼Â¹Ô¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤¢¤ë¤¤¤Ï¡¢¥¢¥ó¥À¡¼¥é¥¤¥óÉÕ¤­¤Îʸ»ú¤òÆþÎϤ¹¤ë¤³¤È¤Ç¤â¼Â¹Ô¤Ç¤­¤Þ¤¹¡£¥á¥Ë¥å¡¼¤Î¥¨¥ó¥È¥ê¤¬¥¢¥¯¥»¥é¥ì¡¼¥¿¤ò»ý¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ï¡¢¤½¤Î¥¢¥¯¥»¥é¥ì¡¼¥¿¤òÆþÎϤ¹¤ë¤³¤È¤Ç¥á¥Ë¥å¡¼¤ò»ØÄꤹ¤ë¤³¤È¤Ê¤·¤Ë¼Â¹Ô¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¥á¥Ë¥å¡¼Í×ÁÇÃæ¡¢ºÇ¸å¤Î¤â¤Î¤Ï¡¢¤½¤Î¥á¥Ë¥å¡¼¤ÎºÇ½é¤Î¹àÌܤòÁªÂò¤¹¤ë¤³¤È¤ÇÆÈΩ¤µ¤»¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£")
@@ -29,9 +39,10 @@ TkLabel.new($menu_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
}.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($menu_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $menu_demo
$menu_demo = nil
@@ -62,7 +73,8 @@ TkMenubutton.new($menu_frame, 'text'=>'File', 'underline'=>0) {|m|
}
}
-if $tk_platform['platform'] == 'macintosh'
+if $tk_platform['platform'] == 'macintosh' ||
+ windowingsystem == "classic" || windowingsystem == "aqua"
modifier = 'Command'
elsif $tk_platform['platform'] == 'windows'
modifier = 'Control'
@@ -78,8 +90,8 @@ TkMenubutton.new($menu_frame, 'text'=>'Basic', 'underline'=>0) {|m|
['A','B','C','D','E','F','G'].each{|c|
# add('command', 'label'=>"ʸ»ú \"#{c}\" ¤ò°õ»ú", 'underline'=>4,
add('command', 'label'=>"Print letter \"#{c}\" (ʸ»ú \"#{c}\" ¤ò°õ»ú)",
- 'underline'=>14, 'accelerator'=>"Meta+#{c}",
- 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
+ 'underline'=>14, 'accelerator'=>"Meta+#{c}",
+ 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
$menu_demo.bind("#{modifier}-#{c.downcase}", proc{print c,"\n"})
}
}
@@ -90,17 +102,18 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
TkMenu.new(m, 'tearoff'=>false) {|cascade_menu|
m.configure('menu'=>cascade_menu)
add('command', 'label'=>'Print hello(¤³¤ó¤Ë¤Á¤Ï)',
- 'command'=>proc{print "Hello(¤³¤ó¤Ë¤Á¤Ï)\n"},
- 'accelerator'=>"#{modifier}+H", 'underline'=>6)
+ 'command'=>proc{print "Hello(¤³¤ó¤Ë¤Á¤Ï)\n"},
+ 'accelerator'=>"#{modifier}+H", 'underline'=>6)
$menu_demo.bind("#{modifier}-h", proc{print "Hello(¤³¤ó¤Ë¤Á¤Ï)\n"})
add('command', 'label'=>'Print goodbye(¤µ¤è¤¦¤Ê¤é)',
- 'command'=>proc{print "Goodbye(¤µ¤è¤¦¤Ê¤é)\n"},
- 'accelerator'=>"#{modifier}+G", 'underline'=>6)
+ 'command'=>proc{print "Goodbye(¤µ¤è¤¦¤Ê¤é)\n"},
+ 'accelerator'=>"#{modifier}+G", 'underline'=>6)
$menu_demo.bind("#{modifier}-g", proc{print "Goodbye(¤µ¤è¤¦¤Ê¤é)\n"})
- TkMenu.new(m, 'tearoff'=>false) {|cascade_check|
+ # TkMenu.new(m, 'tearoff'=>false) {|cascade_check|
+ TkMenu.new(cascade_menu, 'tearoff'=>false) {|cascade_check|
cascade_menu.add('cascade', 'label'=>'Check buttons(¥Á¥§¥Ã¥¯¥Ü¥¿¥ó)',
- 'menu'=>cascade_check, 'underline'=>0)
+ 'menu'=>cascade_check, 'underline'=>0)
oil = TkVariable.new(0)
add('check', 'label'=>'¥ª¥¤¥ëÅÀ¸¡', 'variable'=>oil)
trans = TkVariable.new(0)
@@ -111,18 +124,19 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
add('check', 'label'=>'¥é¥¤¥ÈÅÀ¸¡', 'variable'=>lights)
add('separator')
add('command', 'label'=>'¸½ºß¤ÎÃͤòɽ¼¨',
- 'command'=>proc{showVars($menu_demo,
- ['¥ª¥¤¥ëÅÀ¸¡', oil],
- ['¥È¥é¥ó¥¹¥ß¥Ã¥·¥ç¥óÅÀ¸¡', trans],
- ['¥Ö¥ì¡¼¥­ÅÀ¸¡', brakes],
- ['¥é¥¤¥ÈÅÀ¸¡', lights])} )
+ 'command'=>proc{showVars($menu_demo,
+ ['¥ª¥¤¥ëÅÀ¸¡', oil],
+ ['¥È¥é¥ó¥¹¥ß¥Ã¥·¥ç¥óÅÀ¸¡', trans],
+ ['¥Ö¥ì¡¼¥­ÅÀ¸¡', brakes],
+ ['¥é¥¤¥ÈÅÀ¸¡', lights])} )
invoke 1
invoke 3
}
- TkMenu.new(m, 'tearoff'=>false) {|cascade_radio|
+ #TkMenu.new(m, 'tearoff'=>false) {|cascade_radio|
+ TkMenu.new(cascade_menu, 'tearoff'=>false) {|cascade_radio|
cascade_menu.add('cascade', 'label'=>'Radio buttons(¥é¥¸¥ª¥Ü¥¿¥ó)',
- 'menu'=>cascade_radio, 'underline'=>0)
+ 'menu'=>cascade_radio, 'underline'=>0)
pointSize = TkVariable.new
add('radio', 'label'=>'10 ¥Ý¥¤¥ó¥È', 'variable'=>pointSize, 'value'=>10)
add('radio', 'label'=>'14 ¥Ý¥¤¥ó¥È', 'variable'=>pointSize, 'value'=>14)
@@ -136,9 +150,9 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
add('radio', 'label'=>'¥¤¥¿¥ê¥Ã¥¯', 'variable'=>style, 'value'=>'italic')
add('separator')
add('command', 'label'=>'¸½ºß¤ÎÃͤòɽ¼¨',
- 'command'=>proc{showVars($menu_demo,
- ['¥Ý¥¤¥ó¥È¥µ¥¤¥º', pointSize],
- ['¥¹¥¿¥¤¥ë', style])} )
+ 'command'=>proc{showVars($menu_demo,
+ ['¥Ý¥¤¥ó¥È¥µ¥¤¥º', pointSize],
+ ['¥¹¥¿¥¤¥ë', style])} )
invoke 1
invoke 7
}
@@ -150,14 +164,15 @@ TkMenubutton.new($menu_frame, 'text'=>'Icons', 'underline'=>0) {|m|
TkMenu.new(m, 'tearoff'=>false) {|icon_menu|
m.configure('menu'=>icon_menu)
add('command',
- 'bitmap'=>'@'+[$demo_dir,'images','pattern.bmp'].join(File::Separator),
- 'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry',
- 'text'=>'º£¤¢¤Ê¤¿¤¬ÁªÂò¤·¤¿¥á¥Ë¥å¡¼¤Î¹àÌܤϥƥ­¥¹¥È¤Ç¤Ï¤Ê¤¯¥Ó¥Ã¥È¥Þ¥Ã¥×¤òɽ¼¨¤·¤Æ¤¤¤Þ¤·¤¿¡£¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï¾¤Î¥á¥Ë¥å¡¼¹àÌܤÈÊѤï¤ê¤Þ¤»¤ó¡£',
- 'bitmap'=>'', 'default'=>0,
- 'buttons'=>'λ²ò')} )
+ 'bitmap'=>'@'+[$demo_dir,'..',
+ 'images','pattern.xbm'].join(File::Separator),
+ 'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry',
+ 'text'=>'º£¤¢¤Ê¤¿¤¬ÁªÂò¤·¤¿¥á¥Ë¥å¡¼¤Î¹àÌܤϥƥ­¥¹¥È¤Ç¤Ï¤Ê¤¯¥Ó¥Ã¥È¥Þ¥Ã¥×¤òɽ¼¨¤·¤Æ¤¤¤Þ¤·¤¿¡£¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï¾¤Î¥á¥Ë¥å¡¼¹àÌܤÈÊѤï¤ê¤Þ¤»¤ó¡£',
+ 'bitmap'=>'', 'default'=>0,
+ 'buttons'=>'λ²ò')} )
['info', 'questhead', 'error'].each{|icon|
add('command', 'bitmap'=>icon,
- 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
+ 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
}
}
}
@@ -169,7 +184,7 @@ TkMenubutton.new($menu_frame, 'text'=>'More', 'underline'=>0) {|m|
[ '¥¨¥ó¥È¥ê','Ê̤Υ¨¥ó¥È¥ê','²¿¤â¤·¤Ê¤¤','¤Û¤È¤ó¤É²¿¤â¤·¤Ê¤¤',
'¿ÍÀ¸¤ò°ÕµÁ¤¢¤ë¤â¤Î¤Ë' ].each{|i|
add('command', 'label'=>i,
- 'command'=>proc{print "You invoked \"#{i}\"\n"})
+ 'command'=>proc{print "You invoked \"#{i}\"\n"})
}
}
}
@@ -180,7 +195,7 @@ TkMenubutton.new($menu_frame, 'text'=>'Colors', 'underline'=>0) {|m|
m.configure('menu'=>colors_menu)
['red', 'orange', 'yellow', 'green', 'blue'].each{|c|
add('command', 'label'=>c, 'background'=>c,
- 'command'=>proc{print "You invoked \"#{c}\"\n"})
+ 'command'=>proc{print "You invoked \"#{c}\"\n"})
}
}
}
diff --git a/ext/tk/sample/demos-jp/menu84.rb b/ext/tk/sample/demos-jp/menu84.rb
index ea5fdf6487..a631bacd43 100644
--- a/ext/tk/sample/demos-jp/menu84.rb
+++ b/ext/tk/sample/demos-jp/menu84.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# menus widget demo (called by 'widget')
#
@@ -15,6 +16,8 @@ $menu84_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($menu84_demo).pack(:fill=>:both, :expand=>true)
+
begin
windowingsystem = Tk.windowingsystem()
rescue
@@ -22,7 +25,7 @@ rescue
end
# label
-TkLabel.new($menu84_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
if $tk_platform['platform'] == 'macintosh' ||
windowingsystem == "classic" || windowingsystem == "aqua"
text("¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥«¥¹¥±¡¼¥É¥á¥Ë¥å¡¼¤ò»ý¤Ä¥á¥Ë¥å¡¼¥Ð¡¼¤¬ÉÕ¤±¤é¤ì¤Æ¤¤¤Þ¤¹¡£Command+x ('x'¤Ï¥³¥Þ¥ó¥É¥­¡¼¥·¥ó¥Ü¥ë¤Ë³¤±¤ÆÉ½¼¨¤µ¤ì¤Æ¤¤¤ëʸ»ú¤Ç¤¹) ¤È¥¿¥¤¥×¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¤â¹àÌܤε¡Ç½¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£ºÇ¸å¤Î¥á¥Ë¥å¡¼¤Ï¡¢¥Þ¥¦¥¹¤Ç¥¦¥£¥ó¥É¥¦¤Î³°¤Ë¥É¥é¥Ã¥°¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢ÆÈΩ¤·¤¿¥Ñ¥ì¥Ã¥È¤È¤Ê¤ë¤è¤¦¤ËÀÚ¤êÊü¤¹¤³¤È¤¬²Äǽ¤Ç¤¹¡£")
@@ -33,19 +36,20 @@ TkLabel.new($menu84_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
menustatus = TkVariable.new(" ")
-TkFrame.new($menu84_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkLabel.new(frame, 'textvariable'=>menustatus, 'relief'=>'sunken',
- 'bd'=>1, 'font'=>['Helvetica', '10'],
- 'anchor'=>'w').pack('side'=>'left', 'padx'=>2,
- 'expand'=>true, 'fill'=>'both')
+ 'bd'=>1, 'font'=>['Helvetica', '10'],
+ 'anchor'=>'w').pack('side'=>'left', 'padx'=>2,
+ 'expand'=>true, 'fill'=>'both')
pack('side'=>'bottom', 'fill'=>'x', 'pady'=>2)
}
# frame
-TkFrame.new($menu84_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $menu84_demo
$menu84_demo = nil
@@ -68,8 +72,8 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
$menu84_frame.add('cascade', 'label'=>'File', 'menu'=>m, 'underline'=>0)
add('command', 'label'=>'Open...', 'command'=>proc{fail '¤³¤ì¤Ïñ¤Ê¤ë¥Ç¥â¤Ç¤¹¤«¤é¡¢"Open..." ¹àÌܤε¡Ç½¤ÏÆÃ¤ËÄêµÁ¤µ¤ì¤Æ¤Ï¤¤¤Þ¤»¤ó¡£'})
add('command', 'label'=>'New', 'command'=>proc{fail '¤³¤ì¤Ïñ¤Ê¤ë¥Ç¥â¤Ç¤¹¤«¤é¡¢"New" ¹àÌܤε¡Ç½¤ÏÆÃ¤ËÄêµÁ¤µ¤ì¤Æ¤Ï¤¤¤Þ¤»¤ó¡£'})
- add('command', 'label'=>'Save', 'command'=>proc{fail '¤³¤ì¤Ïñ¤Ê¤ë¤Ç¤â¤Ç¤¹¤«¤é¡¢"Save" ¹àÌܤε¡Ç½¤ÏÆÃ¤ËÄêµÁ¤µ¤ì¤Æ¤Ï¤¤¤Þ¤»¤ó¡£'})
- add('command', 'label'=>'Save As...', 'command'=>proc{fail '¤³¤ì¤Ïñ¤Ê¤ë¤Ç¤â¤Ç¤¹¤«¤é¡¢"Save As..." ¹àÌܤε¡Ç½¤ÏÆÃ¤ËÄêµÁ¤µ¤ì¤Æ¤Ï¤¤¤Þ¤»¤ó¡£'})
+ add('command', 'label'=>'Save', 'command'=>proc{fail '¤³¤ì¤Ïñ¤Ê¤ë¥Ç¥â¤Ç¤¹¤«¤é¡¢"Save" ¹àÌܤε¡Ç½¤ÏÆÃ¤ËÄêµÁ¤µ¤ì¤Æ¤Ï¤¤¤Þ¤»¤ó¡£'})
+ add('command', 'label'=>'Save As...', 'command'=>proc{fail '¤³¤ì¤Ïñ¤Ê¤ë¥Ç¥â¤Ç¤¹¤«¤é¡¢"Save As..." ¹àÌܤε¡Ç½¤ÏÆÃ¤ËÄêµÁ¤µ¤ì¤Æ¤Ï¤¤¤Þ¤»¤ó¡£'})
add('separator')
add('command', 'label'=>'Print Setup...', 'command'=>proc{fail '¤³¤ì¤Ïñ¤Ê¤ë¥Ç¥â¤Ç¤¹¤«¤é¡¢"Print Setup..." ¹àÌܤε¡Ç½¤ÏÆÃ¤ËÄêµÁ¤µ¤ì¤Æ¤Ï¤¤¤Þ¤»¤ó¡£'})
add('command', 'label'=>'Print...', 'command'=>proc{fail '¤³¤ì¤Ïñ¤Ê¤ë¥Ç¥â¤Ç¤¹¤«¤é¡¢"Print..." ¹àÌܤε¡Ç½¤ÏÆÃ¤ËÄêµÁ¤µ¤ì¤Æ¤Ï¤¤¤Þ¤»¤ó¡£'})
@@ -91,8 +95,8 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
add('command', 'label'=>'Long entry that does nothing')
['A','B','C','D','E','F','G'].each{|c|
add('command', 'label'=>"Print letter \"#{c}\"",
- 'underline'=>14, 'accelerator'=>"Meta+#{c}",
- 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
+ 'underline'=>14, 'accelerator'=>"Meta+#{c}",
+ 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
$menu84_demo.bind("#{modifier}-#{c.downcase}", proc{print c,"\n"})
}
}
@@ -110,7 +114,7 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
TkMenu.new(m, 'tearoff'=>false) {|cascade_check|
m.add('cascade', 'label'=>'Check button',
- 'menu'=>cascade_check, 'underline'=>0)
+ 'menu'=>cascade_check, 'underline'=>0)
oil = TkVariable.new(0)
add('check', 'label'=>'¥ª¥¤¥ë¸¡ºº', 'variable'=>oil)
trans = TkVariable.new(0)
@@ -121,18 +125,18 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
add('check', 'label'=>'¥é¥¤¥È¸¡ºº', 'variable'=>lights)
add('separator')
add('command', 'label'=>'Show current values',
- 'command'=>proc{showVars($menu84_demo,
- ['¥ª¥¤¥ë', oil],
- ['¥È¥é¥ó¥¹¥ß¥Ã¥·¥ç¥ó', trans],
- ['¥Ö¥ì¡¼¥­', brakes],
- ['¥é¥¤¥È', lights])} )
+ 'command'=>proc{showVars($menu84_demo,
+ ['¥ª¥¤¥ë', oil],
+ ['¥È¥é¥ó¥¹¥ß¥Ã¥·¥ç¥ó', trans],
+ ['¥Ö¥ì¡¼¥­', brakes],
+ ['¥é¥¤¥È', lights])} )
invoke 1
invoke 3
}
TkMenu.new(m, 'tearoff'=>false) {|cascade_radio|
m.add('cascade', 'label'=>'Radio buttons',
- 'menu'=>cascade_radio, 'underline'=>0)
+ 'menu'=>cascade_radio, 'underline'=>0)
pointSize = TkVariable.new
add('radio', 'label'=>'10 point', 'variable'=>pointSize, 'value'=>10)
add('radio', 'label'=>'14 point', 'variable'=>pointSize, 'value'=>14)
@@ -146,9 +150,9 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
add('radio', 'label'=>'Italic', 'variable'=>style, 'value'=>'italic')
add('separator')
add('command', 'label'=>'¸½ºßÃͤÎɽ¼¨',
- 'command'=>proc{showVars($menu84_demo,
- ['pointSize', pointSize],
- ['style', style])} )
+ 'command'=>proc{showVars($menu84_demo,
+ ['pointSize', pointSize],
+ ['style', style])} )
invoke 1
invoke 7
}
@@ -157,14 +161,15 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
$menu84_frame.add('cascade', 'label'=>'Icons', 'menu'=>m, 'underline'=>0)
add('command', 'hidemargin'=>1,
- 'bitmap'=>'@'+[$demo_dir,'images','pattern.bmp'].join(File::Separator),
+ 'bitmap'=>'@'+[$demo_dir,'..',
+ 'images','pattern.xbm'].join(File::Separator),
'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry',
- 'text'=>'¤¢¤Ê¤¿¤¬ÁªÂò¤·¤¿¥á¥Ë¥å¡¼¹àÌܤϡ¢Ê¸»úÎó¤ÎÂå¤ï¤ê¤Ë¥Ó¥Ã¥È¥Þ¥Ã¥×¥¤¥á¡¼¥¸¤Ç¹àÌܤòɽ¼¨¤·¤¿¤â¤Î¤Ç¤¹¡£¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï¡¢¤Û¤«¤Î¥á¥Ë¥å¡¼¹àÌÜ¤È¤Î´Ö¤ÇÆÃ¤Ë°ã¤¤¤¬¤¢¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£',
- 'bitmap'=>'', 'default'=>0,
- 'buttons'=>'ÊĤ¸¤ë')} )
+ 'text'=>'¤¢¤Ê¤¿¤¬ÁªÂò¤·¤¿¥á¥Ë¥å¡¼¹àÌܤϡ¢Ê¸»úÎó¤ÎÂå¤ï¤ê¤Ë¥Ó¥Ã¥È¥Þ¥Ã¥×¥¤¥á¡¼¥¸¤Ç¹àÌܤòɽ¼¨¤·¤¿¤â¤Î¤Ç¤¹¡£¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï¡¢¤Û¤«¤Î¥á¥Ë¥å¡¼¹àÌÜ¤È¤Î´Ö¤ÇÆÃ¤Ë°ã¤¤¤¬¤¢¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£',
+ 'bitmap'=>'', 'default'=>0,
+ 'buttons'=>'ÊĤ¸¤ë')} )
['info', 'questhead', 'error'].each{|icon|
add('command', 'bitmap'=>icon, 'hidemargin'=>1,
- 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
+ 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
}
entryconfigure(2, :columnbreak=>true)
@@ -175,34 +180,34 @@ TkMenu.new($menu84_frame, 'tearoff'=>false) {|m|
[ 'An entry','Another entry','Does nothing','Does almost nothing',
'Make life meaningful' ].each{|i|
add('command', 'label'=>i,
- 'command'=>proc{print "You invoked \"#{i}\"\n"})
+ 'command'=>proc{print "You invoked \"#{i}\"\n"})
}
m.entryconfigure('Does almost nothing',
- 'bitmap'=>'questhead', 'compound'=>'left',
- 'command'=>proc{
- TkDialog.new('title'=>'Compound Menu Entry',
- 'message'=>'¤¢¤Ê¤¿¤¬ÁªÂò¤·¤¿¥á¥Ë¥å¡¼¹àÌܤϡ¢¥Ó¥Ã¥È¥Þ¥Ã¥×¥¤¥á¡¼¥¸¤Èʸ»úÎó¤È¤òƱ»þ¤Ë°ì¤Ä¤Î¹àÌܤËɽ¼¨¤¹¤ë¤è¤¦¤Ë¤·¤¿¤â¤Î¤Ç¤¹¡£¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï¡¢¤Û¤«¤Î¥á¥Ë¥å¡¼¹àÌÜ¤È¤Î´Ö¤ÇÆÃ¤Ë°ã¤¤¤¬¤¢¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£',
- 'buttons'=>['λ²ò'], 'bitmap'=>'')
- })
+ 'bitmap'=>'questhead', 'compound'=>'left',
+ 'command'=>proc{
+ TkDialog.new('title'=>'Compound Menu Entry',
+ 'message'=>'¤¢¤Ê¤¿¤¬ÁªÂò¤·¤¿¥á¥Ë¥å¡¼¹àÌܤϡ¢¥Ó¥Ã¥È¥Þ¥Ã¥×¥¤¥á¡¼¥¸¤Èʸ»úÎó¤È¤òƱ»þ¤Ë°ì¤Ä¤Î¹àÌܤËɽ¼¨¤¹¤ë¤è¤¦¤Ë¤·¤¿¤â¤Î¤Ç¤¹¡£¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï¡¢¤Û¤«¤Î¥á¥Ë¥å¡¼¹àÌÜ¤È¤Î´Ö¤ÇÆÃ¤Ë°ã¤¤¤¬¤¢¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£',
+ 'buttons'=>['λ²ò'], 'bitmap'=>'')
+ })
}
TkMenu.new($menu84_frame) {|m|
$menu84_frame.add('cascade', 'label'=>'Colors', 'menu'=>m, 'underline'=>0)
['red', 'orange', 'yellow', 'green', 'blue'].each{|c|
add('command', 'label'=>c, 'background'=>c,
- 'command'=>proc{print "You invoked \"#{c}\"\n"})
+ 'command'=>proc{print "You invoked \"#{c}\"\n"})
}
}
$menu84_demo.menu($menu84_frame)
TkMenu.bind('<MenuSelect>', proc{|w|
- begin
- label = w.entrycget('active', 'label')
- rescue
- label = " "
- end
- menustatus.value = label
- Tk.update(true)
- }, '%W')
+ begin
+ label = w.entrycget('active', 'label')
+ rescue
+ label = " "
+ end
+ menustatus.value = label
+ Tk.update(true)
+ }, '%W')
diff --git a/ext/tk/sample/demos-jp/menu8x.rb b/ext/tk/sample/demos-jp/menu8x.rb
index a6d3c5e09e..9249f2491a 100644
--- a/ext/tk/sample/demos-jp/menu8x.rb
+++ b/ext/tk/sample/demos-jp/menu8x.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# menus widget demo (called by 'widget')
#
@@ -15,18 +16,21 @@ $menu8x_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($menu8x_demo).pack(:fill=>:both, :expand=>true)
+
# version check
if $tk_version.to_f < 8.0
# label À¸À®
-TkLabel.new($menu8x_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
text("¼Â¹Ô¤·¤è¤¦¤È¤·¤¿¥¹¥¯¥ê¥×¥È¤Ï Tk8.0 °Ê¾å¤ÇÍøÍѤǤ­¤ëµ¡Ç½¤òÍøÍѤ·¤Æ¤¤¤ë¤¿¤á¡¢¤¢¤Ê¤¿¤Î Ruby#{VERSION}/Tk#{$tk_version}#{(Tk::JAPANIZED_TK)? 'jp': ''} ¤Ç¤ÏÀµ¾ï¤Ë¼Â¹Ô¤Ç¤­¤Þ¤»¤ó¡£¤è¤Ã¤Æ¥Ç¥â¤Î¼Â¹Ô¤òÃæ»ß¤·¤Þ¤·¤¿¡£¤¿¤À¤·¡¢²¼¤Î¥³¡¼¥É»²¾È¥Ü¥¿¥ó¤ò²¡¤¹¤³¤È¤Ç¡¢¼Â¹Ô¤¬Ãæ»ß¤µ¤ì¤¿¥¹¥¯¥ê¥×¥È¤Î¥½¡¼¥¹¤ò»²¾È¤¹¤ë¤³¤È¤Ï²Äǽ¤Ç¤¹¡£")
}.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($menu8x_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $menu8x_demo
$menu8x_demo = nil
@@ -36,15 +40,22 @@ TkFrame.new($menu8x_demo) {|frame|
TkButton.new(frame) {
text '¥³¡¼¥É»²¾È'
- command proc{showCode 'menu'}
+ command proc{showCode 'menu8x'}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
else ; # Tk8.x
+begin
+ windowingsystem = Tk.windowingsystem()
+rescue
+ windowingsystem = ""
+end
+
# label À¸À®
-TkLabel.new($menu8x_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
- if $tk_platform['platform'] == 'macintosh'
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
+ if $tk_platform['platform'] == 'macintosh' ||
+ windowingsystem == "classic" || windowingsystem == "aqua"
text("¤³¤Î¥¦¥£¥ó¥É¥¦¤ÏÍÍ¡¹¤Ê¥á¥Ë¥å¡¼¤È¥«¥¹¥±¡¼¥É¥á¥Ë¥å¡¼¤«¤é¹½À®¤µ¤ì¤Æ¤¤¤Þ¤¹¡£Command-X ¤òÆþÎϤ¹¤ë¤È¡¢X¤¬¥³¥Þ¥ó¥É¥­¡¼µ­¹æ¤Ë³¤¤¤ÆÉ½¼¨¤µ¤ì¤Æ¤¤¤ëʸ»ú¤Ê¤é¤Ð¡¢¥¢¥¯¥»¥é¥ì¡¼¥¿¤ò»È¤Ã¤¿¹àÌܵ¯Æ°¤ò¹Ô¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¥á¥Ë¥å¡¼Í×ÁÇÃæ¡¢ºÇ¸å¤Î¤â¤Î¤Ï¡¢¤½¤Î¥á¥Ë¥å¡¼¤ÎºÇ½é¤Î¹àÌܤòÁªÂò¤¹¤ë¤³¤È¤ÇÆÈΩ¤µ¤»¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£")
else
text("¤³¤Î¥¦¥£¥ó¥É¥¦¤ÏÍÍ¡¹¤Ê¥á¥Ë¥å¡¼¤È¥«¥¹¥±¡¼¥É¥á¥Ë¥å¡¼¤«¤é¹½À®¤µ¤ì¤Æ¤¤¤Þ¤¹¡£Alt-X ¤òÆþÎϤ¹¤ë¤È¡¢X¤¬¥á¥Ë¥å¡¼¤Ë¥¢¥ó¥À¡¼¥é¥¤¥óÉÕ¤­¤Çɽ¼¨¤µ¤ì¤Æ¤¤¤ëʸ»ú¤Ê¤é¤Ð¡¢¥­¡¼¥Ü¡¼¥É¤«¤é¤Î»ØÄ꤬¤Ç¤­¤Þ¤¹¡£Ìð°õ¥­¡¼¤Ç¥á¥Ë¥å¡¼¤Î¥È¥é¥Ð¡¼¥¹¤â²Äǽ¤Ç¤¹¡£¥á¥Ë¥å¡¼¤¬»ØÄꤵ¤ì¤¿ºÝ¤Ë¤Ï¡¢¥¹¥Ú¡¼¥¹¥­¡¼¤Ç¼Â¹Ô¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤¢¤ë¤¤¤Ï¡¢¥¢¥ó¥À¡¼¥é¥¤¥óÉÕ¤­¤Îʸ»ú¤òÆþÎϤ¹¤ë¤³¤È¤Ç¤â¼Â¹Ô¤Ç¤­¤Þ¤¹¡£¥á¥Ë¥å¡¼¤Î¥¨¥ó¥È¥ê¤¬¥¢¥¯¥»¥é¥ì¡¼¥¿¤ò»ý¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ï¡¢¤½¤Î¥¢¥¯¥»¥é¥ì¡¼¥¿¤òÆþÎϤ¹¤ë¤³¤È¤Ç¥á¥Ë¥å¡¼¤ò»ØÄꤹ¤ë¤³¤È¤Ê¤·¤Ë¼Â¹Ô¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¥á¥Ë¥å¡¼Í×ÁÇÃæ¡¢ºÇ¸å¤Î¤â¤Î¤Ï¡¢¤½¤Î¥á¥Ë¥å¡¼¤ÎºÇ½é¤Î¹àÌܤòÁªÂò¤¹¤ë¤³¤È¤ÇÆÈΩ¤µ¤»¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£")
@@ -53,16 +64,17 @@ TkLabel.new($menu8x_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
# ¾õÂÖɽ¼¨¤ÎÀ¸À®
$menu8xstatus = TkVariable.new(" ")
-TkFrame.new($menu8x_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkLabel.new(frame, 'textvariable'=>$menu8xstatus, 'relief'=>'sunken',
- 'bd'=>1, 'font'=>['Helvetica', '10'], 'anchor'=>'w')\
+ 'bd'=>1, 'font'=>['Helvetica', '10'], 'anchor'=>'w')\
.pack('side'=>'left', 'padx'=>2, 'expand'=>'yes', 'fill'=>'both')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>2)
# frame À¸À®
-TkFrame.new($menu8x_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $menu8x_demo
$menu8x_demo = nil
@@ -72,7 +84,7 @@ TkFrame.new($menu8x_demo) {|frame|
TkButton.new(frame) {
text '¥³¡¼¥É»²¾È'
- command proc{showCode 'menu'}
+ command proc{showCode 'menu8x'}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
@@ -91,7 +103,8 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m|
add('command', 'label'=>'½ªÎ»', 'command'=>proc{$menu8x_demo.destroy})
}
- if $tk_platform['platform'] == 'macintosh'
+ if $tk_platform['platform'] == 'macintosh' ||
+ windowingsystem == "classic" || windowingsystem == "aqua"
modifier = 'Command'
elsif $tk_platform['platform'] == 'windows'
modifier = 'Control'
@@ -105,8 +118,8 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m|
['A','B','C','D','E','F','G'].each{|c|
# add('command', 'label'=>"ʸ»ú \"#{c}\" ¤ò°õ»ú", 'underline'=>4,
add('command', 'label'=>"Print letter \"#{c}\" (ʸ»ú \"#{c}\" ¤ò°õ»ú)",
- 'underline'=>14, 'accelerator'=>"Meta+#{c}",
- 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
+ 'underline'=>14, 'accelerator'=>"Meta+#{c}",
+ 'command'=>proc{print c,"\n"}, 'accelerator'=>"#{modifier}+#{c}")
$menu8x_demo.bind("#{modifier}-#{c.downcase}", proc{print c,"\n"})
}
}
@@ -114,17 +127,17 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m|
TkMenu.new(m, 'tearoff'=>false) {|cascade_menu|
m.add('cascade', 'label'=>'Cascades', 'menu'=>cascade_menu, 'underline'=>0)
add('command', 'label'=>'Print hello(¤³¤ó¤Ë¤Á¤Ï)',
- 'command'=>proc{print "Hello(¤³¤ó¤Ë¤Á¤Ï)\n"},
- 'accelerator'=>"#{modifier}+H", 'underline'=>6)
+ 'command'=>proc{print "Hello(¤³¤ó¤Ë¤Á¤Ï)\n"},
+ 'accelerator'=>"#{modifier}+H", 'underline'=>6)
$menu8x_demo.bind("#{modifier}-h", proc{print "Hello(¤³¤ó¤Ë¤Á¤Ï)\n"})
add('command', 'label'=>'Print goodbye(¤µ¤è¤¦¤Ê¤é)',
- 'command'=>proc{print "Goodbye(¤µ¤è¤¦¤Ê¤é)\n"},
- 'accelerator'=>"#{modifier}+G", 'underline'=>6)
+ 'command'=>proc{print "Goodbye(¤µ¤è¤¦¤Ê¤é)\n"},
+ 'accelerator'=>"#{modifier}+G", 'underline'=>6)
$menu8x_demo.bind("#{modifier}-g", proc{print "Goodbye(¤µ¤è¤¦¤Ê¤é)\n"})
TkMenu.new(m, 'tearoff'=>false) {|cascade_check|
cascade_menu.add('cascade', 'label'=>'Check buttons(¥Á¥§¥Ã¥¯¥Ü¥¿¥ó)',
- 'menu'=>cascade_check, 'underline'=>0)
+ 'menu'=>cascade_check, 'underline'=>0)
oil = TkVariable.new(0)
add('check', 'label'=>'¥ª¥¤¥ëÅÀ¸¡', 'variable'=>oil)
trans = TkVariable.new(0)
@@ -135,18 +148,18 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m|
add('check', 'label'=>'¥é¥¤¥ÈÅÀ¸¡', 'variable'=>lights)
add('separator')
add('command', 'label'=>'¸½ºß¤ÎÃͤòɽ¼¨',
- 'command'=>proc{showVars($menu8x_demo,
- ['¥ª¥¤¥ëÅÀ¸¡', oil],
- ['¥È¥é¥ó¥¹¥ß¥Ã¥·¥ç¥óÅÀ¸¡', trans],
- ['¥Ö¥ì¡¼¥­ÅÀ¸¡', brakes],
- ['¥é¥¤¥ÈÅÀ¸¡', lights])} )
+ 'command'=>proc{showVars($menu8x_demo,
+ ['¥ª¥¤¥ëÅÀ¸¡', oil],
+ ['¥È¥é¥ó¥¹¥ß¥Ã¥·¥ç¥óÅÀ¸¡', trans],
+ ['¥Ö¥ì¡¼¥­ÅÀ¸¡', brakes],
+ ['¥é¥¤¥ÈÅÀ¸¡', lights])} )
invoke 1
invoke 3
}
TkMenu.new(m, 'tearoff'=>false) {|cascade_radio|
cascade_menu.add('cascade', 'label'=>'Radio buttons(¥é¥¸¥ª¥Ü¥¿¥ó)',
- 'menu'=>cascade_radio, 'underline'=>0)
+ 'menu'=>cascade_radio, 'underline'=>0)
pointSize = TkVariable.new
add('radio', 'label'=>'10 ¥Ý¥¤¥ó¥È', 'variable'=>pointSize, 'value'=>10)
add('radio', 'label'=>'14 ¥Ý¥¤¥ó¥È', 'variable'=>pointSize, 'value'=>14)
@@ -160,9 +173,9 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m|
add('radio', 'label'=>'¥¤¥¿¥ê¥Ã¥¯', 'variable'=>style, 'value'=>'italic')
add('separator')
add('command', 'label'=>'¸½ºß¤ÎÃͤòɽ¼¨',
- 'command'=>proc{showVars($menu8x_demo,
- ['¥Ý¥¤¥ó¥È¥µ¥¤¥º', pointSize],
- ['¥¹¥¿¥¤¥ë', style])} )
+ 'command'=>proc{showVars($menu8x_demo,
+ ['¥Ý¥¤¥ó¥È¥µ¥¤¥º', pointSize],
+ ['¥¹¥¿¥¤¥ë', style])} )
invoke 1
invoke 7
}
@@ -171,15 +184,16 @@ 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),
- 'hidemargin'=>1,
- 'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry',
- 'text'=>'º£¤¢¤Ê¤¿¤¬ÁªÂò¤·¤¿¥á¥Ë¥å¡¼¤Î¹àÌܤϥƥ­¥¹¥È¤Ç¤Ï¤Ê¤¯¥Ó¥Ã¥È¥Þ¥Ã¥×¤òɽ¼¨¤·¤Æ¤¤¤Þ¤·¤¿¡£¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï¾¤Î¥á¥Ë¥å¡¼¹àÌܤÈÊѤï¤ê¤Þ¤»¤ó¡£',
- 'bitmap'=>'', 'default'=>0,
- 'buttons'=>'λ²ò')} )
+ 'bitmap'=>'@'+[$demo_dir,'..',
+ 'images','pattern.xbm'].join(File::Separator),
+ 'hidemargin'=>1,
+ 'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry',
+ 'text'=>'º£¤¢¤Ê¤¿¤¬ÁªÂò¤·¤¿¥á¥Ë¥å¡¼¤Î¹àÌܤϥƥ­¥¹¥È¤Ç¤Ï¤Ê¤¯¥Ó¥Ã¥È¥Þ¥Ã¥×¤òɽ¼¨¤·¤Æ¤¤¤Þ¤·¤¿¡£¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï¾¤Î¥á¥Ë¥å¡¼¹àÌܤÈÊѤï¤ê¤Þ¤»¤ó¡£',
+ 'bitmap'=>'', 'default'=>0,
+ 'buttons'=>'λ²ò')} )
['info', 'questhead', 'error'].each{|icon|
add('command', 'bitmap'=>icon, 'hidemargin'=>1,
- 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
+ 'command'=>proc{print "You invoked the #{icon} bitmap\n"})
}
entryconfigure(2, 'columnbreak'=>1)
@@ -190,7 +204,7 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m|
[ '¥¨¥ó¥È¥ê','Ê̤Υ¨¥ó¥È¥ê','²¿¤â¤·¤Ê¤¤','¤Û¤È¤ó¤É²¿¤â¤·¤Ê¤¤',
'¿ÍÀ¸¤ò°ÕµÁ¤¢¤ë¤â¤Î¤Ë' ].each{|i|
add('command', 'label'=>i,
- 'command'=>proc{print "You invoked \"#{i}\"\n"})
+ 'command'=>proc{print "You invoked \"#{i}\"\n"})
}
}
@@ -198,7 +212,7 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m|
m.add('cascade', 'label'=>'Colors', 'menu'=>colors_menu, 'underline'=>1)
['red', 'orange', 'yellow', 'green', 'blue'].each{|c|
add('command', 'label'=>c, 'background'=>c,
- 'command'=>proc{print "You invoked \"#{c}\"\n"})
+ 'command'=>proc{print "You invoked \"#{c}\"\n"})
}
}
@@ -206,14 +220,14 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m|
}
TkMenu.bind('<MenuSelect>',
- proc{|w|
- begin
- label = w.entrycget('active', 'label')
- rescue
- label = ' '
- end
- $menu8xstatus.value = label
- Tk.update('idletasks')
- }, '%W')
+ proc{|w|
+ begin
+ label = w.entrycget('active', 'label')
+ rescue
+ label = ' '
+ end
+ $menu8xstatus.value = label
+ Tk.update('idletasks')
+ }, '%W')
end ; # Tk 8.x
diff --git a/ext/tk/sample/demos-jp/menubu.rb b/ext/tk/sample/demos-jp/menubu.rb
index 8b4d7980d2..90dc367305 100644
--- a/ext/tk/sample/demos-jp/menubu.rb
+++ b/ext/tk/sample/demos-jp/menubu.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
require "tkcanvas"
def optionMenu(menubutton, varName, firstValue, *rest)
@@ -32,18 +33,21 @@ $menubu_demo = TkToplevel.new {|w|
positionWindow($menubu_demo)
+base_frame = TkFrame.new($menubu_demo).pack(:fill=>:both, :expand=>true)
+
# version check
if $tk_version.to_f < 8.0
# label À¸À®
-TkLabel.new($menubu_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
+TkLabel.new(base_frame,'font'=>$font,'wraplength'=>'4i','justify'=>'left') {
text("¼Â¹Ô¤·¤è¤¦¤È¤·¤¿¥¹¥¯¥ê¥×¥È¤Ï Tk8.0 °Ê¾å¤ÇÍøÍѤǤ­¤ëµ¡Ç½¤òÍøÍѤ·¤Æ¤¤¤ë¤¿¤á¡¢¤¢¤Ê¤¿¤Î Ruby#{VERSION}/Tk#{$tk_version}#{(Tk::JAPANIZED_TK)? 'jp': ''} ¤Ç¤ÏÀµ¾ï¤Ë¼Â¹Ô¤Ç¤­¤Þ¤»¤ó¡£¤è¤Ã¤Æ¥Ç¥â¤Î¼Â¹Ô¤òÃæ»ß¤·¤Þ¤·¤¿¡£¤¿¤À¤·¡¢²¼¤Î¥³¡¼¥É»²¾È¥Ü¥¿¥ó¤ò²¡¤¹¤³¤È¤Ç¡¢¼Â¹Ô¤¬Ãæ»ß¤µ¤ì¤¿¥¹¥¯¥ê¥×¥È¤Î¥½¡¼¥¹¤ò»²¾È¤¹¤ë¤³¤È¤Ï²Äǽ¤Ç¤¹¡£")
}.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($menubu_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $menubu_demo
$menubu_demo = nil
@@ -53,13 +57,13 @@ TkFrame.new($menubu_demo) {|frame|
TkButton.new(frame) {
text '¥³¡¼¥É»²¾È'
- command proc{showCode 'menu'}
+ command proc{showCode 'menubu'}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
else ; # Tk8.x
-body = TkFrame.new($menubu_demo)
+body = TkFrame.new(base_frame)
body.pack('expand'=>'yes', 'fill'=>'both')
below = TkMenubutton.new(body) {
@@ -154,9 +158,10 @@ center = TkFrame.new(body) {
grid('row'=>1, 'column'=>1, 'sticky'=>'news')
}
-TkFrame.new($menubu_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc {
tmppath = $menubu_demo
$menubu_demo = nil
@@ -185,7 +190,7 @@ TkFrame.new(center) {|f|
menubuttonoptions = TkVariable.new
mbutton = TkMenubutton.new(f)
options = optionMenu(mbutton, menubuttonoptions,
- 'one', 'two', 'three')
+ 'one', 'two', 'three')
mbutton.pack('side'=>'left', 'padx'=>25, 'pady'=>25)
paletteColor = TkVariable.new
colors = ['Black','red4','DarkGreen','NavyBlue', 'gray75',
diff --git a/ext/tk/sample/demos-jp/msgbox.rb b/ext/tk/sample/demos-jp/msgbox.rb
index cf53d70487..88380e08bd 100644
--- a/ext/tk/sample/demos-jp/msgbox.rb
+++ b/ext/tk/sample/demos-jp/msgbox.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# message boxes widget demo (called by 'widget')
#
@@ -15,14 +16,17 @@ $msgbox_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($msgbox_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($msgbox_demo, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
- 'text'=>"ɽ¼¨¤¹¤ë¥¢¥¤¥³¥ó¤È¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹¤Î¼ïÎà¤òÁª¤ó¤Ç²¼¤µ¤¤¡£¤½¤·¤Æ \"¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹\" ¥Ü¥¿¥ó¤ò²¡¤¹¤È¡¢»ØÄꤷ¤¿¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹¤¬É½¼¨¤µ¤ì¤Þ¤¹¡£").pack('side'=>'top')
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
+ 'text'=>"¤Þ¤ºÉ½¼¨¤¹¤ë¥¢¥¤¥³¥ó¤È¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹¤Î¼ïÎà¤òÁª¤ó¤Ç²¼¤µ¤¤¡£¤½¤Î¸å¤Ë\"¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹\"¥Ü¥¿¥ó¤ò²¡¤¹¤È¡¢»ØÄꤷ¤¿¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹¤¬É½¼¨¤µ¤ì¤Þ¤¹¡£").pack('side'=>'top')
# frame À¸À®
-TkFrame.new($msgbox_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $msgbox_demo
$msgbox_demo = nil
@@ -42,12 +46,12 @@ TkFrame.new($msgbox_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame À¸À®
-$msgbox_leftframe = TkFrame.new($msgbox_demo)
-$msgbox_rightframe = TkFrame.new($msgbox_demo)
+$msgbox_leftframe = TkFrame.new(base_frame)
+$msgbox_rightframe = TkFrame.new(base_frame)
$msgbox_leftframe .pack('side'=>'left', 'expand'=>'yes', 'fill'=>'y',
- 'pady'=>'.5c', 'padx'=>'.5c')
+ 'pady'=>'.5c', 'padx'=>'.5c')
$msgbox_rightframe.pack('side'=>'left', 'expand'=>'yes', 'fill'=>'y',
- 'pady'=>'.5c', 'padx'=>'.5c')
+ 'pady'=>'.5c', 'padx'=>'.5c')
TkLabel.new($msgbox_leftframe, 'text'=>'¥¢¥¤¥³¥ó').pack('side'=>'top')
TkFrame.new($msgbox_leftframe, 'relief'=>'ridge', 'bd'=>1, 'height'=>2)\
@@ -56,9 +60,9 @@ TkFrame.new($msgbox_leftframe, 'relief'=>'ridge', 'bd'=>1, 'height'=>2)\
$msgboxIcon = TkVariable.new('info')
['error', 'info', 'question', 'warning'].each {|icon|
TkRadioButton.new($msgbox_leftframe, 'text'=>icon, 'variable'=>$msgboxIcon,
- 'relief'=>'flat', 'value'=>icon, 'width'=>16,
- 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
- 'anchor'=>'w', 'fill'=>'x')
+ 'relief'=>'flat', 'value'=>icon, 'width'=>16,
+ 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
+ 'anchor'=>'w', 'fill'=>'x')
}
TkLabel.new($msgbox_rightframe, 'text'=>'¼ïÎà').pack('side'=>'top')
@@ -69,17 +73,17 @@ $msgboxType = TkVariable.new('ok')
['abortretryignore', 'ok', 'okcancel',
'retrycancel', 'yesno', 'yesnocancel'].each {|type|
TkRadioButton.new($msgbox_rightframe, 'text'=>type, 'variable'=>$msgboxType,
- 'relief'=>'flat', 'value'=>type, 'width'=>16,
- 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
- 'anchor'=>'w', 'fill'=>'x')
+ 'relief'=>'flat', 'value'=>type, 'width'=>16,
+ 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
+ 'anchor'=>'w', 'fill'=>'x')
}
def showMessageBox(w)
button = Tk.messageBox('icon'=>$msgboxIcon.value, 'type'=>$msgboxType.value,
- 'title'=>'Message', 'parent'=>w,
- 'message'=>"¤³¤ì¤Ï \"#{$msgboxType.value}\" ¤È¤¤¤¦¼ïÎà¤Î¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹¤Ç¡¢\"#{$msgboxIcon.value}\" ¤Î¥¢¥¤¥³¥ó¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£")
+ 'title'=>'Message', 'parent'=>w,
+ 'message'=>"¤³¤ì¤Ï\"#{$msgboxType.value}\"¤È¤¤¤¦¼ïÎà¤Î¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹¤Ç¡¢\"#{$msgboxIcon.value}\"¤Î¥¢¥¤¥³¥ó¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£")
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'parent'=>w,
- 'message'=>"¤¢¤Ê¤¿¤Ï \"#{button}\" ¤ò²¡¤·¤Þ¤·¤¿¤Í¡£")
+ 'message'=>"¤¢¤Ê¤¿¤Ï \"#{button}\" ¤ò²¡¤·¤Þ¤·¤¿¤Í¡£")
end
diff --git a/ext/tk/sample/demos-jp/msgbox2.rb b/ext/tk/sample/demos-jp/msgbox2.rb
new file mode 100644
index 0000000000..d61f25129a
--- /dev/null
+++ b/ext/tk/sample/demos-jp/msgbox2.rb
@@ -0,0 +1,90 @@
+# -*- coding: euc-jp -*-
+#
+# message boxes widget demo (called by 'widget')
+#
+
+# toplevel widget ¤¬Â¸ºß¤¹¤ì¤Ðºï½ü¤¹¤ë
+if defined?($msgbox2_demo) && $msgbox2_demo
+ $msgbox2_demo.destroy
+ $msgbox2_demo = nil
+end
+
+# demo ÍѤΠtoplevel widget ¤òÀ¸À®
+$msgbox2_demo = TkToplevel.new {|w|
+ title("Message Box Demonstration")
+ iconname("messagebox")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($msgbox2_demo).pack(:fill=>:both, :expand=>true)
+
+# label À¸À®
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
+ 'text'=>"¤Þ¤ºÉ½¼¨¤¹¤ë¥¢¥¤¥³¥ó¤È¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹¤Î¼ïÎà¤òÁª¤ó¤Ç²¼¤µ¤¤¡£¤½¤Î¸å¤Ë\"¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹\"¥Ü¥¿¥ó¤ò²¡¤¹¤È¡¢»ØÄꤵ¤ì¤¿·Á¼°¤Ç¡¢¥á¥Ã¥»¡¼¥¸¤È¾ÜºÙ¥Æ¥­¥¹¥È¤È¤ò»ý¤Ã¤¿¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹¤¬É½¼¨¤µ¤ì¤Þ¤¹¡£").pack('side'=>'top')
+
+# frame À¸À®
+TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
+ command proc{
+ tmppath = $msgbox2_demo
+ $msgbox2_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text '¥³¡¼¥É»²¾È'
+ command proc{showCode 'msgbox2'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text '¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹'
+ command proc{showMessageBox $msgbox2_demo}
+ }.pack('side'=>'left', 'expand'=>'yes')
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# frame À¸À®
+$msgbox_leftframe = TkFrame.new(base_frame)
+$msgbox_rightframe = TkFrame.new(base_frame)
+$msgbox_leftframe .pack('side'=>'left', 'expand'=>'yes', 'fill'=>'y',
+ 'pady'=>'.5c', 'padx'=>'.5c')
+$msgbox_rightframe.pack('side'=>'left', 'expand'=>'yes', 'fill'=>'y',
+ 'pady'=>'.5c', 'padx'=>'.5c')
+
+TkLabel.new($msgbox_leftframe, 'text'=>'¥¢¥¤¥³¥ó').pack('side'=>'top')
+TkFrame.new($msgbox_leftframe, 'relief'=>'ridge', 'bd'=>1, 'height'=>2)\
+.pack('side'=>'top', 'fill'=>'x', 'expand'=>'no')
+
+$msgboxIcon = TkVariable.new('info')
+['error', 'info', 'question', 'warning'].each {|icon|
+ TkRadioButton.new($msgbox_leftframe, 'text'=>icon, 'variable'=>$msgboxIcon,
+ 'relief'=>'flat', 'value'=>icon, 'width'=>16,
+ 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
+ 'anchor'=>'w', 'fill'=>'x')
+}
+
+TkLabel.new($msgbox_rightframe, 'text'=>'¼ïÎà').pack('side'=>'top')
+TkFrame.new($msgbox_rightframe, 'relief'=>'ridge', 'bd'=>1, 'height'=>2)\
+.pack('side'=>'top', 'fill'=>'x', 'expand'=>'no')
+
+$msgboxType = TkVariable.new('ok')
+['abortretryignore', 'ok', 'okcancel',
+ 'retrycancel', 'yesno', 'yesnocancel'].each {|type|
+ TkRadioButton.new($msgbox_rightframe, 'text'=>type, 'variable'=>$msgboxType,
+ 'relief'=>'flat', 'value'=>type, 'width'=>16,
+ 'anchor'=>'w').pack('side'=>'top', 'pady'=>2,
+ 'anchor'=>'w', 'fill'=>'x')
+}
+
+def showMessageBox(w)
+ button = Tk.messageBox('icon'=>$msgboxIcon.value, 'type'=>$msgboxType.value,
+ 'title'=>'Message', 'parent'=>w,
+ 'message'=>"\"#{$msgboxType.value}\"¥¿¥¤¥×¤Î¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹",
+ 'detail'=>"¤³¤ì¤Ï\"#{$msgboxType.value}\"¤È¤¤¤¦¼ïÎà¤Î¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹¤Ç¡¢\"#{$msgboxIcon.value}\"¤Î¥¢¥¤¥³¥ó¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£²¼¤Î¥Ü¥¿¥ó¤Î¤¤¤º¤ì¤«¤òÁªÂò¤·¤Æ¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£")
+
+ Tk.messageBox('icon'=>'info', 'type'=>'ok', 'parent'=>w,
+ 'message'=>"¤¢¤Ê¤¿¤Ï \"#{button}\" ¤ò²¡¤·¤Þ¤·¤¿¤Í¡£")
+end
+
diff --git a/ext/tk/sample/demos-jp/paned1.rb b/ext/tk/sample/demos-jp/paned1.rb
index 99e6b6cddb..f994e83ff1 100644
--- a/ext/tk/sample/demos-jp/paned1.rb
+++ b/ext/tk/sample/demos-jp/paned1.rb
@@ -1,3 +1,5 @@
+# -*- coding: euc-jp -*-
+#
# paned1.rb
#
# This demonstration script creates a toplevel window containing
@@ -16,9 +18,11 @@ $paned1_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($paned1_demo,
- :font=>$font, :wraplength=>'4i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+base_frame = TkFrame.new($paned1_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
²¼¤Î¿§ÉÕ¤±¤µ¤ì¤¿Æó¤Ä¤Î¥¦¥£¥ó¥É¥¦¤Î´Ö¤Î»ÅÀÚ¤êÏȤϡ¢°ì¤Ä¤ÎÎΰè¤ò¤½¤ì¤¾¤ì¤Î¥¦¥£¥ó¥É¥¦¤Î¤¿¤á¤Ëʬ³ä¤¹¤ë¤¿¤á¤Î¤â¤Î¤Ç¤¹¡£º¸¥Ü¥¿¥ó¤Ç»ÅÀÚ¤ê¤òÁàºî¤¹¤ë¤È¡¢Ê¬³ä¥µ¥¤¥ºÊѹ¹¤ÎÁàºîÅÓÃæ¤Ç¤ÏºÆÉ½¼¨¤Ï¤Ê¤µ¤ì¤º¡¢³ÎÄꤵ¤»¤¿¤È¤­¤Ëɽ¼¨¤¬¹¹¿·¤µ¤ì¤Þ¤¹¡£¥Þ¥¦¥¹¤Ë¤è¤ë»ÅÀÚ¤ê¤ÎÁàºî¤ËÄɿ路¤Æ¥µ¥¤¥º¤òÊѹ¹¤·¤¿É½¼¨¤¬¤Ê¤ï¤ì¤ë¤è¤¦¤Ë¤·¤¿¤¤¾ì¹ç¤Ï¡¢¥Þ¥¦¥¹¤ÎÃæ±û¥Ü¥¿¥ó¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡£
¤â¤·¤¢¤Ê¤¿¤¬»È¤Ã¤Æ¤¤¤ë Ruby ¤Ë¥ê¥ó¥¯¤µ¤ì¤Æ¤¤¤ë Tk ¥é¥¤¥Ö¥é¥ê¤¬ panedwindow ¤ò¼ÂÁõ¤·¤Æ¤¤¤Ê¤¤
¾ì¹ç¡¢¤³¤Î¥Ç¥â¤Ï¤¦¤Þ¤¯Æ°¤«¤Ê¤¤¤Ï¤º¤Ç¤¹¡£¤½¤Î¾ì¹ç¤Ë¤Ï panedwindow ¤¬¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤è¤¦¤Ê
@@ -27,22 +31,22 @@ TkLabel.new($paned1_demo,
EOL
# The bottom buttons
-TkFrame.new($paned1_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
- TkButton.new(f, :text=>'λ²ò', :width=>15, :command=>proc{
- $paned1_demo.destroy
- $paned1_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ TkButton.new(f, :text=>'ÊĤ¸¤ë', :width=>15, :command=>proc{
+ $paned1_demo.destroy
+ $paned1_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'¥³¡¼¥É»²¾È', :width=>15, :command=>proc{
- showCode 'paned1'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'paned1'
+ }).pack(:side=>:left, :expand=>true)
}
-TkPanedwindow.new($paned1_demo){|f|
- pack(:side=>:top, :expand=>true, :fill=>:both, :pady=>2, :padx=>'2m')
+TkPanedwindow.new(base_frame, :orient=>:horizontal){|f|
+ add(Tk::Label.new(f, :text=>"This is the\nleft side", :bg=>'yellow'),
+ Tk::Label.new(f, :text=>"This is the\nright side", :bg=>'cyan'))
- add(TkLabel.new(f, :text=>"This is the\nleft side", :bg=>'yellow'),
- TkLabel.new(f, :text=>"This is the\nright side", :bg=>'cyan'))
+ pack(:side=>:top, :expand=>true, :fill=>:both, :pady=>2, :padx=>'2m')
}
diff --git a/ext/tk/sample/demos-jp/paned2.rb b/ext/tk/sample/demos-jp/paned2.rb
index 9df88c4b97..cdc8253402 100644
--- a/ext/tk/sample/demos-jp/paned2.rb
+++ b/ext/tk/sample/demos-jp/paned2.rb
@@ -1,3 +1,5 @@
+# -*- coding: euc-jp -*-
+#
# paned2.rb --
#
# This demonstration script creates a toplevel window containing
@@ -16,9 +18,11 @@ $paned2_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($paned2_demo,
- :font=>$font, :wraplength=>'4i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+base_frame = TkFrame.new($paned2_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
²¼¤Î¥¹¥¯¥í¡¼¥ë¥Ð¡¼ÉÕ¤­¤Î¥¦¥£¥¸¥§¥Ã¥È¤¬ÃÖ¤«¤ì¤¿Æó¤Ä¤Î¥¦¥£¥ó¥É¥¦¤Î´Ö¤Î»ÅÀÚ¤êÏȤϡ¢°ì¤Ä¤ÎÎΰè¤ò¤½¤ì¤¾¤ì¤Î¥¦¥£¥ó¥É¥¦¤Î¤¿¤á¤Ëʬ³ä¤¹¤ë¤¿¤á¤Î¤â¤Î¤Ç¤¹¡£º¸¥Ü¥¿¥ó¤Ç»ÅÀÚ¤ê¤òÁàºî¤¹¤ë¤È¡¢Ê¬³ä¥µ¥¤¥ºÊѹ¹¤ÎÁàºîÅÓÃæ¤Ç¤ÏºÆÉ½¼¨¤Ï¤Ê¤µ¤ì¤º¡¢³ÎÄꤵ¤»¤¿¤È¤­¤Ëɽ¼¨¤¬¹¹¿·¤µ¤ì¤Þ¤¹¡£¥Þ¥¦¥¹¤Ë¤è¤ë»ÅÀÚ¤ê¤ÎÁàºî¤ËÄɿ路¤Æ¥µ¥¤¥º¤òÊѹ¹¤·¤¿É½¼¨¤¬¤Ê¤ï¤ì¤ë¤è¤¦¤Ë¤·¤¿¤¤¾ì¹ç¤Ï¡¢¥Þ¥¦¥¹¤ÎÃæ±û¥Ü¥¿¥ó¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡£
¤â¤·¤¢¤Ê¤¿¤¬»È¤Ã¤Æ¤¤¤ë Ruby ¤Ë¥ê¥ó¥¯¤µ¤ì¤Æ¤¤¤ë Tk ¥é¥¤¥Ö¥é¥ê¤¬ panedwindow ¤ò¼ÂÁõ¤·¤Æ¤¤¤Ê¤¤
¾ì¹ç¡¢¤³¤Î¥Ç¥â¤Ï¤¦¤Þ¤¯Æ°¤«¤Ê¤¤¤Ï¤º¤Ç¤¹¡£¤½¤Î¾ì¹ç¤Ë¤Ï panedwindow ¤¬¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤è¤¦¤Ê
@@ -27,17 +31,17 @@ TkLabel.new($paned2_demo,
EOL
# The bottom buttons
-TkFrame.new($paned2_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
- TkButton.new(f, :text=>'λ²ò', :width=>15, :command=>proc{
- $paned2_demo.destroy
- $paned2_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ TkButton.new(f, :text=>'ÊĤ¸¤ë', :width=>15, :command=>proc{
+ $paned2_demo.destroy
+ $paned2_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'¥³¡¼¥É»²¾È', :width=>15, :command=>proc{
- showCode 'paned2'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'paned2'
+ }).pack(:side=>:left, :expand=>true)
}
paneList = TkVariable.new # define as normal variable (not array)
@@ -64,33 +68,33 @@ paneList.value = [ # ruby's array --> tcl's list
]
# Create the pane itself
-TkPanedwindow.new($paned2_demo, :orient=>:vertical){|f|
+TkPanedwindow.new(base_frame, :orient=>:vertical){|f|
pack(:side=>:top, :expand=>true, :fill=>:both, :pady=>2, :padx=>'2m')
add(TkFrame.new(f){|paned2_top|
- TkListbox.new(paned2_top, :listvariable=>paneList) {
- # Invert the first item to highlight it
- itemconfigure(0, :background=>self.cget(:foreground),
- :foreground=>self.cget(:background) )
- yscrollbar(TkScrollbar.new(paned2_top).pack(:side=>:right,
- :fill=>:y))
- pack(:fill=>:both, :expand=>true)
- }
+ TkListbox.new(paned2_top, :listvariable=>paneList) {
+ # Invert the first item to highlight it
+ itemconfigure(0, :background=>self.cget(:foreground),
+ :foreground=>self.cget(:background) )
+ yscrollbar(TkScrollbar.new(paned2_top).pack(:side=>:right,
+ :fill=>:y))
+ pack(:fill=>:both, :expand=>true)
+ }
},
- TkFrame.new(f) {|paned2_bottom|
- # The bottom window is a text widget with scrollbar
- paned2_xscr = TkScrollbar.new(paned2_bottom)
- paned2_yscr = TkScrollbar.new(paned2_bottom)
- paned2_text = TkText.new(paned2_bottom, :width=>30, :wrap=>:non) {
- insert('1.0', '¤³¤³¤ËÇÛÃÖ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ï¡¢' +
- '¤´¤¯ÉáÄ̤Υƥ­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤Ç¤¹¡£')
- xscrollbar(paned2_xscr)
- yscrollbar(paned2_yscr)
- }
- Tk.grid(paned2_text, paned2_yscr, :sticky=>'nsew')
- Tk.grid(paned2_xscr, :sticky=>'nsew')
- TkGrid.columnconfigure(paned2_bottom, 0, :weight=>1)
- TkGrid.rowconfigure(paned2_bottom, 0, :weight=>1)
+ 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)
+ paned2_text = TkText.new(paned2_bottom, :width=>30, :wrap=>:non) {
+ insert('1.0', '¤³¤³¤ËÇÛÃÖ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ï¡¢' +
+ '¤´¤¯ÉáÄ̤Υƥ­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤Ç¤¹¡£')
+ xscrollbar(paned2_xscr)
+ yscrollbar(paned2_yscr)
+ }
+ Tk.grid(paned2_text, paned2_yscr, :sticky=>'nsew')
+ Tk.grid(paned2_xscr, :sticky=>'nsew')
+ TkGrid.columnconfigure(paned2_bottom, 0, :weight=>1)
+ TkGrid.rowconfigure(paned2_bottom, 0, :weight=>1)
} )
}
diff --git a/ext/tk/sample/demos-jp/pendulum.rb b/ext/tk/sample/demos-jp/pendulum.rb
new file mode 100644
index 0000000000..b115f5be2c
--- /dev/null
+++ b/ext/tk/sample/demos-jp/pendulum.rb
@@ -0,0 +1,242 @@
+# -*- coding: euc-jp -*-
+#
+# This demonstration illustrates how Tcl/Tk can be used to construct
+# simulations of physical systems.
+# (called by 'widget')
+#
+# based on Tcl/Tk8.5a2 widget demos
+
+# destroy toplevel widget for this demo script
+if defined?($pendulum_demo) && $pendulum_demo
+ $pendulum_demo.destroy
+ $pendulum_demo = nil
+end
+
+# create toplevel widget
+$pendulum_demo = TkToplevel.new {|w|
+ title("Pendulum Animation Demonstration")
+ iconname("pendulum")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($pendulum_demo).pack(:fill=>:both, :expand=>true)
+
+# create label
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '4i'
+ justify 'left'
+ text '¤³¤Î¥Ç¥â¤Ï¡¢ÊªÍý·Ï¤Î¥·¥ß¥å¥ì¡¼¥·¥ç¥ó¤Ë´Ø¤ï¤ë¤è¤¦¤Ê¥¢¥Ë¥á¡¼¥·¥ç¥ó¼Â¹Ô¤¹¤ë¤¿¤á¤Ë Ruby/Tk ¤ò¤É¤Î¤è¤¦¤ËÍѤ¤¤ë¤³¤È¤¬¤Ç¤­¤ë¤«¤ò¼¨¤·¤Æ¤¤¤Þ¤¹¡£º¸Â¦¤Î¥­¥ã¥ó¥Ð¥¹¤Ïñ½ã¤Ê¿¶¤ê»Ò¤Ç¤¢¤ëʪÍý·Ï¼«ÂΤΥ°¥é¥Õ¥£¥«¥ëɽ¸½¤Ç¤¢¤ë¤Î¤ËÂФ·¡¢±¦Â¦¤Î¥­¥ã¥ó¥Ð¥¹¤Ï·Ï¤Î°ÌÁê¶õ´Ö¤Î¥°¥é¥Õ¡Ê³Ñ®Å٤ȳÑÅ٤Ȥò¥×¥í¥Ã¥È¤·¤¿¤â¤Î¡Ë¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£º¸Â¦¤Î¥­¥ã¥ó¥Ð¥¹¾å¤Ç¥¯¥ê¥Ã¥¯¤ª¤è¤Ó¥É¥é¥Ã¥°¤ò¹Ô¤Ã¤Æ¿¶¤ê»Ò¤Î½Å¤ê¤Î°ÌÃÖ¤òÊѤ¨¤Æ¤ß¤Æ¤¯¤À¤µ¤¤¡£'
+}
+msg.pack('side'=>'top')
+
+# create frame
+TkFrame.new(base_frame) {|frame|
+ TkButton.new(frame) {
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
+ command proc{
+ tmppath = $pendulum_demo
+ $pendulum_demo = nil
+ tmppath.destroy
+ }
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+ TkButton.new(frame) {
+ text '¥³¡¼¥É»²¾È'
+ command proc{showCode 'pendulum'}
+ }.pack('side'=>'left', 'expand'=>'yes')
+
+}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# animated wave
+class PendulumAnimationDemo
+ def initialize(frame)
+ # Create some structural widgets
+ @pane = TkPanedWindow.new(frame, :orient=>:horizontal).pack(:fill=>:both, :expand=>true)
+# @pane.add(@lf1 = TkLabelFrame.new(@pane, :text=>'Pendulum Simulation'))
+# @pane.add(@lf2 = TkLabelFrame.new(@pane, :text=>'Phase Space'))
+ @lf1 = TkLabelFrame.new(@pane, :text=>'Pendulum Simulation')
+ @lf2 = TkLabelFrame.new(@pane, :text=>'Phase Space')
+
+ # Create the canvas containing the graphical representation of the
+ # simulated system.
+ @c = TkCanvas.new(@lf1, :width=>320, :height=>200, :background=>'white',
+ :borderwidth=>2, :relief=>:sunken)
+ TkcText.new(@c, 5, 5, :anchor=>:nw,
+ :text=>'Click to Adjust Bob Start Position')
+ # Coordinates of these items don't matter; they will be set properly below
+ @plate = TkcLine.new(@c, 0, 25, 320, 25, :width=>2, :fill=>'grey50')
+ @rod = TkcLine.new(@c, 1, 1, 1, 1, :width=>3, :fill=>'black')
+ @bob = TkcOval.new(@c, 1, 1, 2, 2,
+ :width=>3, :fill=>'yellow', :outline=>'black')
+ TkcOval.new(@c, 155, 20, 165, 30, :fill=>'grey50', :outline=>'')
+
+ # pack
+ @c.pack(:fill=>:both, :expand=>true)
+
+ # Create the canvas containing the phase space graph; this consists of
+ # a line that gets gradually paler as it ages, which is an extremely
+ # effective visual trick.
+ @k = TkCanvas.new(@lf2, :width=>320, :height=>200, :background=>'white',
+ :borderwidth=>2, :relief=>:sunken)
+ @y_axis = TkcLine.new(@k, 160, 200, 160, 0, :fill=>'grey75', :arrow=>:last)
+ @x_axis = TkcLine.new(@k, 0, 100, 320, 100, :fill=>'grey75', :arrow=>:last)
+
+ @graph = {}
+ 90.step(0, -10){|i|
+ # Coordinates of these items don't matter;
+ # they will be set properly below
+ @graph[i] = TkcLine.new(@k, 0, 0, 1, 1, :smooth=>true, :fill=>"grey#{i}")
+ }
+
+ # labels
+ @label_theta = TkcText.new(@k, 0, 0, :anchor=>:ne,
+ :text=>'q', :font=>'Symbol 8')
+ @label_dtheta = TkcText.new(@k, 0, 0, :anchor=>:ne,
+ :text=>'dq', :font=>'Symbol 8')
+
+ # pack
+ @k.pack(:fill=>:both, :expand=>true)
+
+ # Initialize some variables
+ @points = []
+ @theta = 45.0
+ @dTheta = 0.0
+ @length = 150
+
+ # animation loop
+ @timer = TkTimer.new(15){ repeat }
+
+ # binding
+ @c.bindtags_unshift(btag = TkBindTag.new)
+ btag.bind('Destroy'){ @timer.stop }
+ btag.bind('1', proc{|x, y| @timer.stop; showPendulum(x.to_i, y.to_i)},
+ '%x %y')
+ btag.bind('B1-Motion', proc{|x, y| showPendulum(x.to_i, y.to_i)}, '%x %y')
+ btag.bind('ButtonRelease-1',
+ proc{|x, y| showPendulum(x.to_i, y.to_i); @timer.start },
+ '%x %y')
+
+ btag.bind('Configure', proc{|w| @plate.coords(0, 25, w.to_i, 25)}, '%w')
+
+ @k.bind('Configure', proc{|h, w|
+ h = h.to_i
+ w = w.to_i
+ @psh = h/2;
+ @psw = w/2
+ @x_axis.coords(2, @psh, w-2, @psh)
+ @y_axis.coords(@psw, h-2, @psw, 2)
+ @label_theta.coords(@psw-4, 6)
+ @label_dtheta.coords(w-6, @psh+4)
+ }, '%h %w')
+
+ # add
+ Tk.update
+ @pane.add(@lf1)
+ @pane.add(@lf2)
+
+ # init display
+ showPendulum
+
+ # animation start
+ @timer.start(500)
+ end
+
+ # This procedure makes the pendulum appear at the correct place on the
+ # canvas. If the additional arguments x, y are passed instead of computing
+ # the position of the pendulum from the length of the pendulum rod and its
+ # angle, the length and angle are computed in reverse from the given
+ # location (which is taken to be the centre of the pendulum bob.)
+ def showPendulum(x=nil, y=nil)
+ if x && y && (x != 160 || y != 25)
+ @dTheta = 0.0
+ x2 = x - 160
+ y2 = y - 25
+ @length = Math.hypot(x2, y2)
+ @theta = Math.atan2(x2,y2)*180/Math::PI
+ else
+ angle = @theta*Math::PI/180
+ x = 160 + @length*Math.sin(angle)
+ y = 25 + @length*Math.cos(angle)
+ end
+
+ @rod.coords(160, 25, x, y)
+ @bob.coords(x-15, y-15, x+15, y+15)
+ end
+
+ # Update the phase-space graph according to the current angle and the
+ # rate at which the angle is changing (the first derivative with
+ # respect to time.)
+ def showPhase
+ unless @psw && @psh
+ @psw = @k.width/2
+ @psh = @k.height/2
+ end
+ @points << @theta + @psw << -20*@dTheta + @psh
+ if @points.length > 100
+ @points = @points[-100..-1]
+ end
+ (0...100).step(10){|i|
+ first = - i
+ last = 11 - i
+ last = -1 if last >= 0
+ next if first > last
+ lst = @points[first..last]
+ @graph[i].coords(lst) if lst && lst.length >= 4
+ }
+ end
+
+ # This procedure is the "business" part of the simulation that does
+ # simple numerical integration of the formula for a simple rotational
+ # pendulum.
+ def recomputeAngle
+ scaling = 3000.0/@length/@length
+
+ # To estimate the integration accurately, we really need to
+ # compute the end-point of our time-step. But to do *that*, we
+ # need to estimate the integration accurately! So we try this
+ # technique, which is inaccurate, but better than doing it in a
+ # single step. What we really want is bound up in the
+ # differential equation:
+ # .. - sin theta
+ # theta + theta = -----------
+ # length
+ # But my math skills are not good enough to solve this!
+
+ # first estimate
+ firstDDTheta = -Math.sin(@theta * Math::PI/180) * scaling
+ midDTheta = @dTheta + firstDDTheta
+ midTheta = @theta + (@dTheta + midDTheta)/2
+ # second estimate
+ midDDTheta = -Math.sin(midTheta * Math::PI/180) * scaling
+ midDTheta = @dTheta + (firstDDTheta + midDDTheta)/2
+ midTheta = @theta + (@dTheta + midDTheta)/2
+ # Now we do a double-estimate approach for getting the final value
+ # first estimate
+ midDDTheta = -Math.sin(midTheta * Math::PI/180) * scaling
+ lastDTheta = midDTheta + midDDTheta
+ lastTheta = midTheta + (midDTheta+ lastDTheta)/2
+ # second estimate
+ lastDDTheta = -Math.sin(lastTheta * Math::PI/180) * scaling
+ lastDTheta = midDTheta + (midDDTheta + lastDDTheta)/2
+ lastTheta = midTheta + (midDTheta + lastDTheta)/2
+ # Now put the values back in our globals
+ @dTheta = lastDTheta
+ @theta = lastTheta
+ end
+
+ # This method ties together the simulation engine and the graphical
+ # display code that visualizes it.
+ def repeat
+ # Simulate
+ recomputeAngle
+
+ # Update the display
+ showPendulum
+ showPhase
+ end
+end
+
+# Start the animation processing
+PendulumAnimationDemo.new(base_frame)
diff --git a/ext/tk/sample/demos-jp/plot.rb b/ext/tk/sample/demos-jp/plot.rb
index 464dd4441d..9ff71904cd 100644
--- a/ext/tk/sample/demos-jp/plot.rb
+++ b/ext/tk/sample/demos-jp/plot.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# 2-D plot widget demo (called by 'widget')
#
@@ -15,16 +16,19 @@ $plot_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($plot_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($plot_demo, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
- 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ï´Êñ¤Ê2¼¡¸µ¤Î¥×¥í¥Ã¥È¤ò´Þ¤ó¤À¥­¥ã¥ó¥Ð¥¹ widget¤Ç¤¹¡£É½¼¨¤µ¤ì¤¿ÅÀ¤ò¥Þ¥¦¥¹¥Ü¥¿¥ó1¤Ç¥É¥é¥Ã¥°¤·¤Æ¥Ç¡¼¥¿¤ò¤¤¤¸¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£"){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'4i', 'justify'=>'left',
+ 'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ï´Êñ¤Ê2¼¡¸µ¤Î¥×¥í¥Ã¥È¤ò´Þ¤ó¤À¥­¥ã¥ó¥Ð¥¹ widget¤Ç¤¹¡£É½¼¨¤µ¤ì¤¿ÅÀ¤ò¥Þ¥¦¥¹¥Ü¥¿¥ó1¤Ç¥É¥é¥Ã¥°¤·¤Æ¥Ç¡¼¥¿¤ò¤¤¤¸¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£"){
pack('side'=>'top')
}
# frame À¸À®
-$plot_buttons = TkFrame.new($plot_demo) {|frame|
+$plot_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $plot_demo
$plot_demo = nil
@@ -40,49 +44,53 @@ $plot_buttons = TkFrame.new($plot_demo) {|frame|
$plot_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# font ÀßÄê
-plotFont = '-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ plotFont = '-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ else
+ font = 'Helvetica 18'
+ end
# canvas ÀßÄê
-$plot_canvas = TkCanvas.new($plot_demo,'relief'=>'raised','width'=>450,'height'=>300)
+$plot_canvas = TkCanvas.new(base_frame,'relief'=>'raised','width'=>450,'height'=>300)
$plot_canvas.pack('side'=>'top', 'fill'=>'x')
# plot À¸À®
TkcLine.new($plot_canvas, 100, 250, 400, 250, 'width'=>2)
TkcLine.new($plot_canvas, 100, 250, 100, 50, 'width'=>2)
TkcText.new($plot_canvas, 225, 20,
- 'text'=>"´Êñ¤Ê¥×¥í¥Ã¥È", 'font'=>plotFont, 'fill'=>'brown')
+ 'text'=>"´Êñ¤Ê¥×¥í¥Ã¥È", 'font'=>plotFont, 'fill'=>'brown')
(0..10).each {|i|
x = 100 + (i * 30)
TkcLine.new($plot_canvas, x, 250, x, 245, 'width'=>2)
TkcText.new($plot_canvas, x, 254,
- 'text'=>10*i, 'font'=>plotFont, 'anchor'=>'n')
+ 'text'=>10*i, 'font'=>plotFont, 'anchor'=>'n')
}
(0..5).each {|i|
y = 250 - (i * 40)
TkcLine.new($plot_canvas, 100, y, 105, y, 'width'=>2)
TkcText.new($plot_canvas, 96, y,
- 'text'=>"#{i*50}.0", 'font'=>plotFont, 'anchor'=>'e')
+ 'text'=>"#{i*50}.0", 'font'=>plotFont, 'anchor'=>'e')
}
for xx, yy in [[12,56],[20,94],[33,98],[32,120],[61,180],[75,160],[98,223]]
x = 100 + (3*xx)
y = 250 - (4*yy)/5
item = TkcOval.new($plot_canvas, x-6, y-6, x+6, y+6,
- 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
+ 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
item.addtag 'point'
end
$plot_canvas.itembind('point', 'Any-Enter',
- proc{$plot_canvas.itemconfigure 'current','fill','red'})
+ proc{$plot_canvas.itemconfigure 'current','fill','red'})
$plot_canvas.itembind('point', 'Any-Leave',
- proc{$plot_canvas.itemconfigure 'current','fill','SkyBlue2'})
+ proc{$plot_canvas.itemconfigure 'current','fill','SkyBlue2'})
$plot_canvas.itembind('point', '1',
- proc{|x,y| plotDown $plot_canvas,x,y}, "%x %y")
+ proc{|x,y| plotDown $plot_canvas,x,y}, "%x %y")
$plot_canvas.itembind('point', 'ButtonRelease-1',
- proc{$plot_canvas.dtag 'selected'})
+ proc{$plot_canvas.dtag 'selected'})
$plot_canvas.bind('B1-Motion',
- proc{|x,y| plotMove $plot_canvas,x,y}, "%x %y")
+ proc{|x,y| plotMove $plot_canvas,x,y}, "%x %y")
$plot = {'lastX'=>0, 'lastY'=>0}
@@ -91,8 +99,8 @@ $plot = {'lastX'=>0, 'lastY'=>0}
# data points. It sets up state to allow the point to be dragged.
#
# Arguments:
-# w - The canvas window.
-# x, y - The coordinates of the mouse press.
+# w - The canvas window.
+# x, y - The coordinates of the mouse press.
def plotDown (w, x, y)
w.dtag 'selected'
@@ -107,8 +115,8 @@ end
# current item.
#
# Arguments:
-# w - The canvas window.
-# x, y - The coordinates of the mouse.
+# w - The canvas window.
+# x, y - The coordinates of the mouse.
def plotMove (w, x, y)
w.move 'selected', x - $plot['lastX'], y - $plot['lastY']
diff --git a/ext/tk/sample/demos-jp/puzzle.rb b/ext/tk/sample/demos-jp/puzzle.rb
index 24c48693a9..2febc2c55a 100644
--- a/ext/tk/sample/demos-jp/puzzle.rb
+++ b/ext/tk/sample/demos-jp/puzzle.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# widet demo 'puzzle' (called by 'widget')
#
@@ -15,8 +16,10 @@ $puzzle_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($puzzle_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($puzzle_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($puzzle_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($puzzle_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $puzzle_demo
$puzzle_demo = nil
@@ -49,18 +53,27 @@ TkFrame.new($puzzle_demo) {|frame|
#
begin
if Tk.windowingsystem() == 'aqua'
- frameSize = 160
+ frameWidth = 168
+ frameHeight = 168
+ elsif Tk.default_widget_set == :Ttk
+ frameWidth = 148
+ frameHeight = 124
else
- frameSize = 120
+ frameWidth = 120
+ frameHeight = 120
end
rescue
- frameSize = 120
+ frameWidth = 120
+ frameHeight = 120
end
+
+# depend_on_button_width = true
+depend_on_button_width = false
-s = TkScrollbar.new($puzzle_demo)
-base = TkFrame.new($puzzle_demo) {
- width frameSize
- height frameSize
+s = TkScrollbar.new(base_frame)
+base = TkFrame.new(base_frame) {
+ width frameWidth
+ height frameHeight
borderwidth 2
relief 'sunken'
bg s['troughcolor']
@@ -87,8 +100,11 @@ order = [3,1,6,2,5,7,15,13,4,11,8,9,14,10,12]
text num
highlightthickness 0
command def_puzzleswitch_proc(w, num)
+ if depend_on_button_width && (w.winfo_reqwidth * 4 > base.width)
+ base.width = w.winfo_reqwidth * 4
+ end
}.place('relx'=>$xpos[num], 'rely'=>$ypos[num],
- 'relwidth'=>0.25, 'relheight'=>0.25)
+ 'relwidth'=>0.25, 'relheight'=>0.25)
}
$xpos['space'] = 0.75
$ypos['space'] = 0.75
@@ -100,9 +116,9 @@ def puzzleSwitch(w, num)
&& ($xpos[num] >= ($xpos['space'] - 0.26)) \
&& ($xpos[num] <= ($xpos['space'] + 0.26))) \
|| (($xpos[num] >= ($xpos['space'] - 0.01)) \
- && ($xpos[num] <= ($xpos['space'] + 0.01)) \
- && ($ypos[num] >= ($ypos['space'] - 0.26)) \
- && ($ypos[num] <= ($ypos['space'] + 0.26)))
+ && ($xpos[num] <= ($xpos['space'] + 0.01)) \
+ && ($ypos[num] >= ($ypos['space'] - 0.26)) \
+ && ($ypos[num] <= ($ypos['space'] + 0.26)))
tmp = $xpos['space']
$xpos['space'] = $xpos[num]
$xpos[num] = tmp
diff --git a/ext/tk/sample/demos-jp/radio.rb b/ext/tk/sample/demos-jp/radio.rb
index 871503029e..a61ad46d9b 100644
--- a/ext/tk/sample/demos-jp/radio.rb
+++ b/ext/tk/sample/demos-jp/radio.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# radiobutton widget demo (called by 'widget')
#
@@ -15,8 +16,10 @@ $radio_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($radio_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($radio_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -29,9 +32,10 @@ size = TkVariable.new
color = TkVariable.new
# frame À¸À®
-TkFrame.new($radio_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $radio_demo
$radio_demo = nil
@@ -48,14 +52,14 @@ TkFrame.new($radio_demo) {|frame|
TkButton.new(frame) {
text 'ÊÑ¿ô»²¾È'
command proc{
- showVars($radio_demo, ['size', size], ['color', color])
+ showVars(base_frame, ['size', size], ['color', color])
}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame À¸À®
-f_left = TkFrame.new($radio_demo)
-f_right = TkFrame.new($radio_demo)
+f_left = TkFrame.new(base_frame)
+f_right = TkFrame.new(base_frame)
f_left.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
f_right.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
diff --git a/ext/tk/sample/demos-jp/radio2.rb b/ext/tk/sample/demos-jp/radio2.rb
index 62425af90d..cf53e3e485 100644
--- a/ext/tk/sample/demos-jp/radio2.rb
+++ b/ext/tk/sample/demos-jp/radio2.rb
@@ -1,4 +1,6 @@
-# radio.rb
+# -*- coding: euc-jp -*-
+#
+# radio2.rb
#
# This demonstration script creates a toplevel window containing
# several radiobutton widgets.
@@ -14,17 +16,19 @@ end
# demo toplevel widget
$radio2_demo = TkToplevel.new {|w|
- title("Radiobutton Demonstration")
- iconname("radio")
+ title("Radiobutton Demonstration 2")
+ iconname("radio2")
positionWindow(w)
}
+base_frame = TkFrame.new($radio2_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($radio2_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
- text "²¼¤Ë¤Ï2¤Ä¤Î¥é¥¸¥ª¥Ü¥¿¥ó¥°¥ë¡¼¥×¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢¤½¤Î¥Ü¥¿¥ó¤À¤±¤¬¤½¤Î¥°¥ë¡¼¥×¤ÎÃæ¤ÇÁªÂò¤µ¤ì¤Þ¤¹¡£³Æ¥°¥ë¡¼¥×¤ËÂФ·¤Æ¤½¤Î¥°¥ë¡¼¥×¤ÎÃæ¤Î¤É¤Î¥Ü¥¿¥ó¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤ë¤«¤ò¼¨¤¹ÊÑ¿ô¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Þ¤¹¡£¸½ºß¤ÎÊÑ¿ô¤ÎÃͤò¸«¤ë¤Ë¤Ï¡ÖÊÑ¿ô»²¾È¡×¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£"
+ text "²¼¤Ë¤Ï3¤Ä¤Î¥é¥¸¥ª¥Ü¥¿¥ó¥°¥ë¡¼¥×¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢¤½¤Î¥Ü¥¿¥ó¤À¤±¤¬¤½¤Î¥°¥ë¡¼¥×¤ÎÃæ¤ÇÁªÂò¤µ¤ì¤Þ¤¹¡£³Æ¥°¥ë¡¼¥×¤ËÂФ·¤Æ¤½¤Î¥°¥ë¡¼¥×¤ÎÃæ¤Î¤É¤Î¥Ü¥¿¥ó¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤ë¤«¤ò¼¨¤¹ÊÑ¿ô¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Þ¤¹¡£¸½ºß¤ÎÊÑ¿ô¤ÎÃͤò¸«¤ë¤Ë¤Ï¡ÖÊÑ¿ô»²¾È¡×¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£"
}
msg.pack('side'=>'top')
@@ -34,9 +38,10 @@ color = TkVariable.new
align = TkVariable.new
# frame
-TkFrame.new($radio2_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $radio2_demo
$radio2_demo = nil
@@ -47,25 +52,25 @@ TkFrame.new($radio2_demo) {|frame|
TkButton.new(frame) {
text '¥³¡¼¥É»²¾È'
- command proc{showCode 'radio'}
+ command proc{showCode 'radio2'}
}.pack('side'=>'left', 'expand'=>'yes')
TkButton.new(frame) {
text 'ÊÑ¿ô»²¾È'
command proc{
- showVars($radio2_demo,
- ['size', size], ['color', color], ['compound', align])
+ showVars(base_frame,
+ ['size', size], ['color', color], ['compound', align])
}
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
-f_left = TkLabelFrame.new($radio2_demo, 'text'=>'ʸ»ú¥µ¥¤¥º',
- 'pady'=>2, 'padx'=>2)
-f_mid = TkLabelFrame.new($radio2_demo, 'text'=>'¿§',
- 'pady'=>2, 'padx'=>2)
-f_right = TkLabelFrame.new($radio2_demo, 'text'=>'¥Ó¥Ã¥È¥Þ¥Ã¥×ÇÛÃÖ',
- 'pady'=>2, 'padx'=>2)
+f_left = TkLabelFrame.new(base_frame, 'text'=>'ʸ»ú¥µ¥¤¥º',
+ 'pady'=>2, 'padx'=>2)
+f_mid = TkLabelFrame.new(base_frame, 'text'=>'¿§',
+ 'pady'=>2, 'padx'=>2)
+f_right = TkLabelFrame.new(base_frame, 'text'=>'¥Ó¥Ã¥È¥Þ¥Ã¥×ÇÛÃÖ',
+ 'pady'=>2, 'padx'=>2)
f_left.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
f_mid.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
f_right.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
@@ -90,15 +95,16 @@ f_right.pack('side'=>'left', 'expand'=>'yes', 'padx'=>'.5c', 'pady'=>'.5c')
}.pack('side'=>'top', 'pady'=>2, 'fill'=>'x')
}
-label = TkLabel.new(f_right, 'text'=>'¥é¥Ù¥ë', 'bitmap'=>'questhead',
- 'compound'=>'left')
+# label = TkLabel.new(f_right, 'text'=>'¥é¥Ù¥ë', 'bitmap'=>'questhead',
+label = Tk::Label.new(f_right, 'text'=>'¥é¥Ù¥ë', 'bitmap'=>'questhead',
+ 'compound'=>'left')
label.configure('width'=>TkWinfo.reqwidth(label), 'compound'=>'top')
label.height(TkWinfo.reqheight(label))
abtn = ['Top', 'Left', 'Right', 'Bottom'].collect{|a|
lower = a.downcase
TkRadioButton.new(f_right, 'text'=>a, 'variable'=>align, 'relief'=>'flat',
- 'value'=>lower, 'indicatoron'=>0, 'width'=>7,
- 'command'=>proc{label.compound(align.value)})
+ 'value'=>lower, 'indicatoron'=>0, 'width'=>7,
+ 'command'=>proc{label.compound(align.value)})
}
Tk.grid('x', abtn[0])
diff --git a/ext/tk/sample/demos-jp/radio3.rb b/ext/tk/sample/demos-jp/radio3.rb
new file mode 100644
index 0000000000..4bbc1b31f5
--- /dev/null
+++ b/ext/tk/sample/demos-jp/radio3.rb
@@ -0,0 +1,119 @@
+# -*- coding: euc-jp -*-
+#
+# radio3.rb
+#
+# This demonstration script creates a toplevel window containing
+# several radiobutton widgets.
+#
+# radiobutton widget demo (called by 'widget')
+#
+
+# toplevel widget
+if defined?($radio3_demo) && $radio3_demo
+ $radio3_demo.destroy
+ $radio3_demo = nil
+end
+
+# demo toplevel widget
+$radio3_demo = TkToplevel.new {|w|
+ title("Radiobutton Demonstration 3")
+ iconname("radio3")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($radio3_demo).pack(:fill=>:both, :expand=>true)
+
+# label
+msg = TkLabel.new(base_frame) {
+ font $font
+ wraplength '5i'
+ justify 'left'
+ text '²¼¤Ë¤Ï3¤Ä¤Î¥é¥¸¥ª¥Ü¥¿¥ó¥°¥ë¡¼¥×¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢¤½¤Î¥°¥ë¡¼¥×¤Ë°¤¹¤ë¤¹¤Ù¤Æ¤Î¥Ü¥¿¥ó¤ÎÃæ¤Ç¥¯¥ê¥Ã¥¯¤·¤¿¥Ü¥¿¥ó¤À¤±¤¬ÁªÂò¤µ¤ì¤¿¾õÂ֤ˤʤê¤Þ¤¹¡£³Æ¥°¥ë¡¼¥×¤Ë¤Ï¡¢¤½¤Î¥°¥ë¡¼¥×¤ÎÃæ¤Î¤É¤Î¥Ü¥¿¥ó¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤ë¤«¤ò¼¨¤¹ÊÑ¿ô¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Þ¤¹¡£¡Ö¥È¥é¥¤¥¹¥Æ¡¼¥È¡×¥Ü¥¿¥ó¤¬²¡¤µ¤ì¤¿¤È¤­¤Ë¤Ï¡¢¥é¥¸¥ª¥Ü¥¿¥ó¤Îɽ¼¨¤¬¥È¥é¥¤¥¹¥Æ¡¼¥È¥â¡¼¥É¤Ë¤Ê¤ê¤Þ¤¹¡£¤¤¤º¤ì¤«¤Î¥Ü¥¿¥ó¤òÁªÂò¤¹¤ì¤Ð¡¢¥Ü¥¿¥ó¤Î¾õÂ֤ϸµ¤Î¤è¤¦¤Ë¸Ä¡¹¤Î¥Ü¥¿¥ó¤Îon/off¾õÂÖ¤ò¼¨¤¹¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£¸½ºß¤ÎÊÑ¿ô¤ÎÃͤò¸«¤ë¤Ë¤Ï¡ÖÊÑ¿ô»²¾È¡×¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£'
+}
+msg.grid(:row=>0, :column=>0, :columnspan=>3, :sticky=>'nsew')
+
+# variable
+size = TkVariable.new
+color = TkVariable.new
+align = TkVariable.new
+
+# frame
+TkFrame.new(base_frame) {|frame|
+ TkGrid(TkFrame.new(frame, :height=>2, :relief=>:sunken, :bd=>2),
+ :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ TkButton.new(frame, :text=>'ÊÑ¿ô»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{
+ showVars(base_frame, ['size', size],
+ ['color', color], ['compound', align])
+ }),
+ TkButton.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'radio3'}),
+ TkButton.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ tmppath = $radio3_demo
+ $radio3_demo = nil
+ $showVarsWin[tmppath.path] = nil
+ tmppath.destroy
+ }),
+ :padx=>4, :pady=>4)
+ frame.grid_columnconfigure(0, :weight=>1)
+ TkGrid(frame, :row=>3, :column=>0, :columnspan=>3, :sticky=>'nsew')
+}
+
+# frame
+f_left = TkLabelFrame.new(base_frame, 'text'=>'ʸ»ú¥µ¥¤¥º',
+ 'pady'=>2, 'padx'=>2)
+f_mid = TkLabelFrame.new(base_frame, 'text'=>'¿§',
+ 'pady'=>2, 'padx'=>2)
+f_right = TkLabelFrame.new(base_frame, 'text'=>'¥Ó¥Ã¥È¥Þ¥Ã¥×ÇÛÃÖ',
+ 'pady'=>2, 'padx'=>2)
+f_left .grid('column'=>0, 'row'=>1, 'pady'=>'.5c', 'padx'=>'.5c', 'rowspan'=>2)
+f_mid .grid('column'=>1, 'row'=>1, 'pady'=>'.5c', 'padx'=>'.5c', 'rowspan'=>2)
+f_right.grid('column'=>2, 'row'=>1, 'pady'=>'.5c', 'padx'=>'.5c')
+
+TkButton.new(base_frame, 'text'=>'¥È¥é¥¤¥¹¥Æ¡¼¥È',
+ 'command'=>proc{size.value = 'multi'; color.value = 'multi'}){
+ grid('column'=>2, 'row'=>2, 'pady'=>'.5c', 'padx'=>'.5c')
+}
+
+# radiobutton
+[10, 12, 14, 18, 24].each {|sz|
+ TkRadioButton.new(f_left) {
+ text "¥Ý¥¤¥ó¥È¥µ¥¤¥º #{sz}"
+ variable size
+ relief 'flat'
+ value sz
+ tristatevalue 'multi'
+ }.pack('side'=>'top', 'pady'=>2, 'anchor'=>'w', 'fill'=>'x')
+}
+
+['Red', 'Green', 'Blue', 'Yellow', 'Orange', 'Purple'].each {|col|
+ TkRadioButton.new(f_mid) {
+ text col
+ variable color
+ relief 'flat'
+ value col.downcase
+ anchor 'w'
+ tristatevalue 'multi'
+ command proc{f_mid.fg(color.value)}
+ }.pack('side'=>'top', 'pady'=>2, 'fill'=>'x')
+}
+
+# label = TkLabel.new(f_right, 'text'=>'¥é¥Ù¥ë', 'bitmap'=>'questhead',
+label = Tk::Label.new(f_right, 'text'=>'¥é¥Ù¥ë', 'bitmap'=>'questhead',
+ 'compound'=>'left')
+label.configure('width'=>TkWinfo.reqwidth(label), 'compound'=>'top')
+label.height(TkWinfo.reqheight(label))
+a_btn = ['Top', 'Left', 'Right', 'Bottom'].collect{|a|
+ TkRadioButton.new(f_right, 'text'=>a, 'variable'=>align, 'relief'=>'flat',
+ 'value'=>a.downcase, 'indicatoron'=>0, 'width'=>7,
+ 'command'=>proc{label.compound(align.value)})
+}
+
+Tk.grid('x', a_btn[0])
+Tk.grid(a_btn[1], label, a_btn[2])
+Tk.grid('x', a_btn[3])
diff --git a/ext/tk/sample/demos-jp/rolodex-j b/ext/tk/sample/demos-jp/rolodex-j
index 1c482aafb2..6c3ea7a484 100644
--- a/ext/tk/sample/demos-jp/rolodex-j
+++ b/ext/tk/sample/demos-jp/rolodex-j
@@ -1,10 +1,11 @@
#!/usr/bin/env ruby
+# -*- coding: euc-jp -*-
#
# rolodex --
# ¤³¤Î¥¹¥¯¥ê¥×¥È¤Ï Tom LaStrange ¤Î rolodex ¤Î°ìÉô¤Ç¤¹¡£
#
# Copyright (C) 1998 by Takaaki Tateishi <ttate@jaist.ac.jp>
-# Time-stamp: "03/08/02 14:01:54 nagai"
+# Time-stamp: "04/04/09 00:32:12 nagai"
#
require "tk"
diff --git a/ext/tk/sample/demos-jp/ruler.rb b/ext/tk/sample/demos-jp/ruler.rb
index d1a7818be4..d6bc9e76d1 100644
--- a/ext/tk/sample/demos-jp/ruler.rb
+++ b/ext/tk/sample/demos-jp/ruler.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# ruler widget demo (called by 'widget')
#
@@ -7,8 +8,8 @@
# represent a tab stop.
#
# Arguments:
-# c - The canvas window.
-# x, y - Coordinates at which to create the tab stop.
+# c - The canvas window.
+# x, y - Coordinates at which to create the tab stop.
def rulerMkTab(c,x,y)
v = $demo_rulerInfo
@@ -28,16 +29,19 @@ $ruler_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($ruler_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($ruler_demo, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
- 'text'=>"¤³¤Î¥­¥ã¥ó¥Ð¥¹widget¤Ï¥ë¡¼¥é¡¼¤ÎÌÏ·¿¤Ç¤¹¡£¥ë¡¼¥é¡¼¤Î±¦¤Ë¤¢¤ë¤Î¤Ï¥¿¥Ö¥¹¥È¥Ã¥×¤Î°æ¸Í¤Ç¡¢¤³¤³¤«¤é°ú¤ÃÄ¥¤Ã¤Æ¤¯¤ë¤³¤È¤Ë¤è¤Ã¤Æ¥¿¥Ö¥¹¥È¥Ã¥×¤òºî¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤Þ¤¿¡¢¤¹¤Ç¤Ë¤¢¤ë¥¿¥Ö¥¹¥È¥Ã¥×¤òư¤«¤¹¤³¤È¤â¤Ç¤­¤Þ¤¹¡£¥¿¥Ö¥¹¥È¥Ã¥×¤ò¾åÊý¤Þ¤¿¤Ï²¼Êý¤Ë¤«¤¹¤ì¤ÆÉ½¼¨¤µ¤ì¤ë¤Þ¤Ç¥É¥é¥Ã¥°¤¹¤ë¤È¡¢¥Þ¥¦¥¹¥Ü¥¿¥ó¤òÎ¥¤·¤¿»þ¤Ë¤½¤Î¥¿¥Ö¥¹¥È¥Ã¥×¤Ï¾Ã¤¨¤Þ¤¹¡£"){
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
+ 'text'=>"¤³¤Î¥­¥ã¥ó¥Ð¥¹widget¤Ï¥ë¡¼¥é¡¼¤ÎÌÏ·¿¤Ç¤¹¡£¥ë¡¼¥é¡¼¤Î±¦¤Ë¤¢¤ë¤Î¤Ï¥¿¥Ö¥¹¥È¥Ã¥×¤Î°æ¸Í¤Ç¡¢¤³¤³¤«¤é°ú¤ÃÄ¥¤Ã¤Æ¤¯¤ë¤³¤È¤Ë¤è¤Ã¤Æ¥¿¥Ö¥¹¥È¥Ã¥×¤òºî¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤Þ¤¿¡¢¤¹¤Ç¤Ë¤¢¤ë¥¿¥Ö¥¹¥È¥Ã¥×¤òư¤«¤¹¤³¤È¤â¤Ç¤­¤Þ¤¹¡£¥¿¥Ö¥¹¥È¥Ã¥×¤ò¾åÊý¤Þ¤¿¤Ï²¼Êý¤Ë¤«¤¹¤ì¤ÆÉ½¼¨¤µ¤ì¤ë¤Þ¤Ç¥É¥é¥Ã¥°¤¹¤ë¤È¡¢¥Þ¥¦¥¹¥Ü¥¿¥ó¤òÎ¥¤·¤¿»þ¤Ë¤½¤Î¥¿¥Ö¥¹¥È¥Ã¥×¤Ï¾Ã¤¨¤Þ¤¹¡£"){
pack('side'=>'top')
}
# frame À¸À®
-$ruler_buttons = TkFrame.new($ruler_demo) {|frame|
+$ruler_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $ruler_demo
$ruler_demo = nil
@@ -53,14 +57,14 @@ $ruler_buttons = TkFrame.new($ruler_demo) {|frame|
$ruler_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# canvas ÀßÄê
-$ruler_canvas = TkCanvas.new($ruler_demo, 'width'=>'14.8c', 'height'=>'2.5c')
+$ruler_canvas = TkCanvas.new(base_frame, 'width'=>'14.8c', 'height'=>'2.5c')
$ruler_canvas.pack('side'=>'top', 'fill'=>'x')
# ÃÍÀßÄê
unless Struct.const_defined?("RulerInfo")
$demo_rulerInfo = Struct.new("RulerInfo", :grid, :left, :right, :x, :y,
- :top, :bottom, :size, :normalStyle,
- :activeStyle, :deleteStyle).new
+ :top, :bottom, :size, :normalStyle,
+ :activeStyle, :deleteStyle).new
end
$demo_rulerInfo.grid = '.25c'
$demo_rulerInfo.left = TkWinfo.fpixels($ruler_canvas, '1c')
@@ -72,15 +76,17 @@ $demo_rulerInfo.normalStyle = {'fill'=>'black'}
if TkWinfo.depth($ruler_canvas) > 1
$demo_rulerInfo.activeStyle = {'fill'=>'red', 'stipple'=>''}
$demo_rulerInfo.deleteStyle = {'fill'=>'red',
- 'stipple'=>'@'+[$demo_dir, 'images', 'gray25.bmp'].join(File::Separator)}
+ 'stipple'=>'@'+[$demo_dir, '..',
+ 'images', 'gray25.xbm'].join(File::Separator)}
else
$demo_rulerInfo.activeStyle = {'fill'=>'black', 'stipple'=>''}
$demo_rulerInfo.deleteStyle = {'fill'=>'black',
- 'stipple'=>'@'+[$demo_dir, 'images', 'gray25.bmp'].join(File::Separator)}
+ 'stipple'=>'@'+[$demo_dir, '..',
+ 'images', 'gray25.xbm'].join(File::Separator)}
end
TkcLine.new($ruler_canvas,
- '1c', '0.5c', '1c', '1c', '13c', '1c', '13c', '0.5c', 'width'=>1)
+ '1c', '0.5c', '1c', '1c', '13c', '1c', '13c', '0.5c', 'width'=>1)
(0..11).each{|i|
x = i+1
TkcLine.new($ruler_canvas, "#{x}c", '1c', "#{x}c", '0.6c', 'width'=>1)
@@ -93,22 +99,22 @@ TkcLine.new($ruler_canvas,
$rulerTag_well = TkcTag.new($ruler_canvas)
$ruler_canvas\
.addtag_withtag($rulerTag_well,
- TkcRectangle.new($ruler_canvas,
- '13.2c', '1c', '13.8c', '0.5c',
- 'outline'=>'black',
- 'fill'=>($ruler_canvas\
- .configinfo('background'))[4]) )
+ TkcRectangle.new($ruler_canvas,
+ '13.2c', '1c', '13.8c', '0.5c',
+ 'outline'=>'black',
+ 'fill'=>($ruler_canvas\
+ .configinfo('background'))[4]) )
$ruler_canvas\
.addtag_withtag($rulerTag_well,
- rulerMkTab($ruler_canvas,
- TkWinfo.pixels($ruler_canvas, '13.5c'),
- TkWinfo.pixels($ruler_canvas, '.65c') ) )
+ rulerMkTab($ruler_canvas,
+ TkWinfo.pixels($ruler_canvas, '13.5c'),
+ TkWinfo.pixels($ruler_canvas, '.65c') ) )
$rulerTag_well.bind('1', proc{|x,y| rulerNewTab($ruler_canvas,x,y)}, '%x %y')
$ruler_canvas.itembind('tab', '1',
- proc{|x,y| rulerSelectTab($ruler_canvas,x,y)}, '%x %y')
+ proc{|x,y| rulerSelectTab($ruler_canvas,x,y)}, '%x %y')
$ruler_canvas.bind('B1-Motion',
- proc{|x,y| rulerMoveTab($ruler_canvas,x,y)}, '%x %y')
+ proc{|x,y| rulerMoveTab($ruler_canvas,x,y)}, '%x %y')
$ruler_canvas.bind('Any-ButtonRelease-1', proc{rulerReleaseTab($ruler_canvas)})
# rulerNewTab --
@@ -116,8 +122,8 @@ $ruler_canvas.bind('Any-ButtonRelease-1', proc{rulerReleaseTab($ruler_canvas)})
# triangle object and adding tags to it to give it tab behavior.
#
# Arguments:
-# c - The canvas window.
-# x, y - The coordinates of the tab stop.
+# c - The canvas window.
+# x, y - The coordinates of the tab stop.
def rulerNewTab(c,x,y)
v = $demo_rulerInfo
@@ -134,9 +140,9 @@ end
# be dragged interactively.
#
# Arguments:
-# c - The canvas widget.
-# x, y - The coordinates of the mouse (identifies the point by
-# which the tab was picked up for dragging).
+# c - The canvas widget.
+# x, y - The coordinates of the mouse (identifies the point by
+# which the tab was picked up for dragging).
def rulerSelectTab(c,x,y)
v = $demo_rulerInfo
@@ -153,8 +159,8 @@ end
# it is about to be dragged out of the ruler.
#
# Arguments:
-# c - The canvas widget.
-# x, y - The coordinates of the mouse.
+# c - The canvas widget.
+# x, y - The coordinates of the mouse.
def rulerMoveTab(c,x,y)
v = $demo_rulerInfo
@@ -181,8 +187,8 @@ end
# it was dragged out of the ruler.
#
# Arguments:
-# c - The canvas widget.
-# x, y - The coordinates of the mouse.
+# c - The canvas widget.
+# x, y - The coordinates of the mouse.
def rulerReleaseTab(c)
v = $demo_rulerInfo
diff --git a/ext/tk/sample/demos-jp/sayings.rb b/ext/tk/sample/demos-jp/sayings.rb
index f627396e0f..aa24b3a2ad 100644
--- a/ext/tk/sample/demos-jp/sayings.rb
+++ b/ext/tk/sample/demos-jp/sayings.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# listbox widget demo 'sayings' (called by 'widget')
#
@@ -15,8 +16,10 @@ $sayings_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($sayings_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($sayings_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($sayings_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($sayings_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $sayings_demo
$sayings_demo = nil
@@ -44,7 +48,7 @@ TkFrame.new($sayings_demo) {|frame|
# frame À¸À®
sayings_lbox = nil
-TkFrame.new($sayings_demo, 'borderwidth'=>10) {|w|
+TkFrame.new(base_frame, 'borderwidth'=>10) {|w|
sv = TkScrollbar.new(w)
sh = TkScrollbar.new(w, 'orient'=>'horizontal')
sayings_lbox = TkListbox.new(w) {
@@ -64,11 +68,11 @@ TkFrame.new($sayings_demo, 'borderwidth'=>10) {|w|
else
sayings_lbox.grid('row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
sv.grid('row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
sh.grid('row'=>1, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
TkGrid.rowconfigure(w, 0, 'weight'=>1, 'minsize'=>0)
TkGrid.columnconfigure(w, 0, 'weight'=>1, 'minsize'=>0)
end
diff --git a/ext/tk/sample/demos-jp/search.rb b/ext/tk/sample/demos-jp/search.rb
index 538c607c01..9838ff5d19 100644
--- a/ext/tk/sample/demos-jp/search.rb
+++ b/ext/tk/sample/demos-jp/search.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# Text Search widget demo (called by 'widget')
#
@@ -8,9 +9,9 @@
# not affected, however.
#
# Arguments:
-# w - The window into which to load the file. Must be a
-# text widget.
-# file - The name of the file to load. Must be readable.
+# w - The window into which to load the file. Must be a
+# text widget.
+# file - The name of the file to load. Must be readable.
def textLoadFile(w,file)
w.delete('1.0', 'end')
@@ -26,10 +27,10 @@ end
# apply a given tag to each instance found.
#
# Arguments:
-# w - The window in which to search. Must be a text widget.
-# string - The string to search for. The search is done using
-# exact matching only; no special characters.
-# tag - Tag to apply to each instance of a matching string.
+# w - The window in which to search. Must be a text widget.
+# string - The string to search for. The search is done using
+# exact matching only; no special characters.
+# tag - Tag to apply to each instance of a matching string.
def textSearch(w, string, tag)
tag.remove('0.0', 'end')
@@ -50,15 +51,15 @@ end
# deleted) then it doesn't reschedule itself.
#
# Arguments:
-# cmd1 - Command to execute when method is called.
-# sleep1 - Ms to sleep after executing cmd1 before executing cmd2.
-# cmd2 - Command to execute in the *next* invocation of this method.
-# sleep2 - Ms to sleep after executing cmd2 before executing cmd1 again.
+# cmd1 - Command to execute when method is called.
+# sleep1 - Ms to sleep after executing cmd1 before executing cmd2.
+# cmd2 - Command to execute in the *next* invocation of this method.
+# sleep2 - Ms to sleep after executing cmd2 before executing cmd1 again.
def textToggle(cmd1,sleep1,cmd2,sleep2)
sleep_list = [sleep2, sleep1]
TkAfter.new(proc{sleep = sleep_list.shift; sleep_list.push(sleep); sleep},
- -1, cmd1, cmd2).start(sleep1)
+ -1, cmd1, cmd2).start(sleep1)
end
# toplevel widget ¤¬Â¸ºß¤¹¤ì¤Ðºï½ü¤¹¤ë
@@ -74,10 +75,13 @@ $search_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($search_demo).pack(:fill=>:both, :expand=>true)
+
# frame À¸À®
-$search_buttons = TkFrame.new($search_demo) {|frame|
+$search_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $search_demo
$search_demo = nil
@@ -93,44 +97,44 @@ $search_buttons = TkFrame.new($search_demo) {|frame|
$search_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame À¸À®
-TkFrame.new($search_demo) {|f|
+TkFrame.new(base_frame) {|f|
TkLabel.new(f, 'text'=>'¥Õ¥¡¥¤¥ë̾:',
- 'width'=>13, 'anchor'=>'w').pack('side'=>'left')
+ 'width'=>13, 'anchor'=>'w').pack('side'=>'left')
$search_fileName = TkVariable.new
TkEntry.new(f, 'width'=>40,
- 'textvariable'=>$search_fileName) {
+ 'textvariable'=>$search_fileName) {
pack('side'=>'left')
bind('Return', proc{textLoadFile($search_text, $search_fileName.value)
- $search_string_entry.focus})
+ $search_string_entry.focus})
focus
}
TkButton.new(f, 'text'=>'ÆÉ¤ß¹þ¤ß',
- 'command'=>proc{textLoadFile($search_text,
- $search_fileName.value)})\
+ 'command'=>proc{textLoadFile($search_text,
+ $search_fileName.value)})\
.pack('side'=>'left', 'pady'=>5, 'padx'=>10)
}.pack('side'=>'top', 'fill'=>'x')
-TkFrame.new($search_demo) {|f|
+TkFrame.new(base_frame) {|f|
TkLabel.new(f, 'text'=>'¸¡º÷ʸ»úÎó:',
- 'width'=>13, 'anchor'=>'w').pack('side'=>'left')
+ 'width'=>13, 'anchor'=>'w').pack('side'=>'left')
$search_searchString = TkVariable.new
$search_string_entry = TkEntry.new(f, 'width'=>40,
- 'textvariable'=>$search_searchString) {
+ 'textvariable'=>$search_searchString) {
pack('side'=>'left')
bind('Return', proc{textSearch($search_text, $search_searchString.value,
- $search_Tag)})
+ $search_Tag)})
}
TkButton.new(f, 'text'=>'ȿž',
- 'command'=>proc{textSearch($search_text,
- $search_searchString.value,
- $search_Tag)}) {
+ 'command'=>proc{textSearch($search_text,
+ $search_searchString.value,
+ $search_Tag)}) {
pack('side'=>'left', 'pady'=>5, 'padx'=>10)
}
}.pack('side'=>'top', 'fill'=>'x')
-$search_text = TkText.new($search_demo, 'setgrid'=>true) {|t|
+$search_text = TkText.new(base_frame, 'setgrid'=>true) {|t|
$search_Tag = TkTextTag.new(t)
- TkScrollbar.new($search_demo, 'command'=>proc{|*args| t.yview(*args)}) {|sc|
+ TkScrollbar.new(base_frame, 'command'=>proc{|*args| t.yview(*args)}) {|sc|
t.yscrollcommand(proc{|first,last| sc.set first,last})
pack('side'=>'right', 'fill'=>'y')
}
@@ -141,47 +145,40 @@ $search_text = TkText.new($search_demo, 'setgrid'=>true) {|t|
if TkWinfo.depth($search_demo) > 1
textToggle(proc{
- begin
- $search_Tag.configure('background'=>'#ce5555',
- 'foreground'=>'white')
- rescue
- end
- },
- 800,
- proc{
- begin
- $search_Tag.configure('background'=>'', 'foreground'=>'')
- rescue
- end
- },
- 200 )
+ $search_Tag.configure('background'=>'#ce5555',
+ 'foreground'=>'white')
+ },
+ 800,
+ proc{
+ $search_Tag.configure('background'=>'', 'foreground'=>'')
+ },
+ 200 )
else
textToggle(proc{
- begin
- $search_Tag.configure('background'=>'black',
- 'foreground'=>'white')
- rescue
- end
- },
- 800,
- proc{
- begin
- $search_Tag.configure('background'=>'', 'foreground'=>'')
- rescue
- end
- },
- 200 )
+ $search_Tag.configure('background'=>'black',
+ 'foreground'=>'white')
+ },
+ 800,
+ proc{
+ $search_Tag.configure('background'=>'', 'foreground'=>'')
+ },
+ 200 )
end
-$search_text.insert('1.0', '\
-¤³¤Î¥¦¥£¥ó¥É¥¦¤Ï¸¡º÷µ¡¹½¤ò¼Â¸½¤¹¤ë¤Î¤Ë¥Æ¥­¥¹¥È widget ¤Î¥¿¥°µ¡Ç½¤¬¤É¤Î
-¤è¤¦¤Ë»È¤ï¤ì¤ë¤Î¤«¤ò¥Ç¥â¤¹¤ë¤â¤Î¤Ç¤¹¡£¤Þ¤º¾å¤Î¥¨¥ó¥È¥ê¤Ë¥Õ¥¡¥¤¥ë̾¤òÆþ
-¤ì¡¢<¥ê¥¿¡¼¥ó> ¤ò²¡¤¹¤«¡Ö¥í¡¼¥É¡×¥Ü¥¿¥ó¤ò²¡¤·¤Æ¤¯¤À¤µ¤¤¡£¼¡¤Ë¤½¤Î²¼¤Î
-¥¨¥ó¥È¥ê¤Ëʸ»úÎó¤òÆþÎϤ·¡¢<¥ê¥¿¡¼¥ó> ¤ò²¡¤¹¤«¡Öȿž¡×¥Ü¥¿¥ó¤ò²¡¤·¤Æ¤¯
-¤À¤µ¤¤¡£¤¹¤ë¤È¥Õ¥¡¥¤¥ëÃæ¤Î¡¢¸¡º÷ʸ»úÎó¤È°ìÃפ¹¤ëÉôʬ¤ËÁ´¤Æ "search_Tag"
-¤È¤¤¤¦¥¿¥°¤¬¤Ä¤±¤é¤ì¡¢¥¿¥°¤Îɽ¼¨Â°À­¤È¤·¤Æ¤½¤Îʸ»úÎó¤¬ÅÀÌǤ¹¤ë¤è¤¦¤Ë
-ÀßÄꤵ¤ì¤Þ¤¹¡£')
+$search_text.insert('1.0', "\
+¤³¤Î¥¦¥£¥ó¥É¥¦¤Ï¸¡º÷µ¡¹½¤ò¼Â¸½¤¹¤ë¤Î¤Ë¥Æ¥­¥¹¥È widget ¤Î¥¿¥°µ¡Ç½¤¬¤É¤Î \
+¤è¤¦¤Ë»È¤ï¤ì¤ë¤Î¤«¤ò¥Ç¥â¤¹¤ë¤â¤Î¤Ç¤¹¡£¤Þ¤º¾å¤Î¥¨¥ó¥È¥ê¤Ë¥Õ¥¡¥¤¥ë̾¤òÆþ \
+¤ì¡¢<¥ê¥¿¡¼¥ó> ¤ò²¡¤¹¤«¡Ö¥í¡¼¥É¡×¥Ü¥¿¥ó¤ò²¡¤·¤Æ¤¯¤À¤µ¤¤¡£¼¡¤Ë¤½¤Î²¼¤Î \
+¥¨¥ó¥È¥ê¤Ëʸ»úÎó¤òÆþÎϤ·¡¢<¥ê¥¿¡¼¥ó> ¤ò²¡¤¹¤«¡Öȿž¡×¥Ü¥¿¥ó¤ò²¡¤·¤Æ¤¯ \
+¤À¤µ¤¤¡£¤¹¤ë¤È¥Õ¥¡¥¤¥ëÃæ¤Î¡¢¸¡º÷ʸ»úÎó¤È°ìÃפ¹¤ëÉôʬ¤ËÁ´¤Æ \"search_Tag\" \
+¤È¤¤¤¦¥¿¥°¤¬¤Ä¤±¤é¤ì¡¢¥¿¥°¤Îɽ¼¨Â°À­¤È¤·¤Æ¤½¤Îʸ»úÎó¤¬ÅÀÌǤ¹¤ë¤è¤¦¤Ë \
+ÀßÄꤵ¤ì¤Þ¤¹¡£\n")
+$search_text.insert('end', "\
+¥Õ¥¡¥¤¥ëÆÉ¤ß¹þ¤ß¤Î¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤Ï \"#{Dir.pwd}\" ¤Ç¤¹¡£\
+")
$search_text.set_insert '0.0'
$search_fileName.value = ''
$search_searchString.value = ''
+$search_text.width = 60
+$search_text.height = 20
diff --git a/ext/tk/sample/demos-jp/spin.rb b/ext/tk/sample/demos-jp/spin.rb
index 4f6edc13c0..8d4e33cda0 100644
--- a/ext/tk/sample/demos-jp/spin.rb
+++ b/ext/tk/sample/demos-jp/spin.rb
@@ -1,3 +1,5 @@
+# -*- coding: euc-jp -*-
+#
# spin.rb --
#
# This demonstration script creates several spinbox widgets.
@@ -15,10 +17,12 @@ $spin_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($spin_demo,
- :font=>$font, :wraplength=>'5i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
-²¼¤Ë¤Ï£³¼ïÎà¤Î¥¹¥Ô¥ó¥Ü¥Ã¥¯¥¹¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£\
+base_frame = TkFrame.new($spin_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'5i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
+²¼¤Ë¤Ï£³¼ïÎà¤Î¥¹¥Ô¥ó¥Ü¥Ã¥¯¥¹¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£
¤½¤ì¤¾¤ì¡¢¥Þ¥¦¥¹¤ÇÁªÂò¤·¤ÆÊ¸»ú¤òÆþÎϤ¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£
ÊÔ½¸Áàºî¤È¤·¤Æ¤Ï¡¢Emacs ·Á¼°¤Î¿¤¯¤Ë²Ã¤¨¤Æ¡¢°ìÈÌŪ¤Ê
Motif ·Á¼°¤Î¥­¡¼Áàºî¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¤¿¤È¤¨¤Ð¡¢
@@ -38,17 +42,17 @@ Backspace ¤È Control-h ¤È¤ÏÆþÎÏ¥«¡¼¥½¥ë¤Îº¸Â¦¤Îʸ»ú¤ò
¤òÁȤ߹ç¤ï¤»¤Æ»î¤¹¤è¤¦¤Ë¤·¤Æ¤¯¤À¤µ¤¤¡£
EOL
-TkFrame.new($spin_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
- TkButton.new(f, :text=>'λ²ò', :width=>15, :command=>proc{
- $spin_demo.destroy
- $spin_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ TkButton.new(f, :text=>'ÊĤ¸¤ë', :width=>15, :command=>proc{
+ $spin_demo.destroy
+ $spin_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'¥³¡¼¥É»²¾È', :width=>15, :command=>proc{
- showCode 'spin'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'spin'
+ }).pack(:side=>:left, :expand=>true)
}
australianCities = [
@@ -57,11 +61,11 @@ australianCities = [
]
[
- TkSpinbox.new($spin_demo, :from=>1, :to=>10, :width=>10, :validate=>:key,
- :validatecommand=>[
- proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
- ]),
- TkSpinbox.new($spin_demo, :from=>0, :to=>3, :increment=>0.5,
- :format=>'%05.2f', :width=>10),
- TkSpinbox.new($spin_demo, :values=>australianCities, :width=>10)
+ TkSpinbox.new(base_frame, :from=>1, :to=>10, :width=>10, :validate=>:key,
+ :validatecommand=>[
+ proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
+ ]),
+ TkSpinbox.new(base_frame, :from=>0, :to=>3, :increment=>0.5,
+ :format=>'%05.2f', :width=>10),
+ TkSpinbox.new(base_frame, :values=>australianCities, :width=>10)
].each{|sbox| sbox.pack(:side=>:top, :pady=>5, :padx=>10)}
diff --git a/ext/tk/sample/demos-jp/states.rb b/ext/tk/sample/demos-jp/states.rb
index cf8a6768b6..5e242b7c38 100644
--- a/ext/tk/sample/demos-jp/states.rb
+++ b/ext/tk/sample/demos-jp/states.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# listbox widget demo 'states' (called by 'widget')
#
@@ -15,8 +16,10 @@ $states_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($states_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($states_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,9 +28,10 @@ msg = TkLabel.new($states_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($states_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $states_demo
$states_demo = nil
@@ -44,7 +48,7 @@ TkFrame.new($states_demo) {|frame|
# frame À¸À®
states_lbox = nil
-TkFrame.new($states_demo, 'borderwidth'=>'.5c') {|w|
+TkFrame.new(base_frame, 'borderwidth'=>'.5c') {|w|
s = TkScrollbar.new(w)
states_lbox = TkListbox.new(w) {
setgrid 1
diff --git a/ext/tk/sample/demos-jp/style.rb b/ext/tk/sample/demos-jp/style.rb
index d58c6115ae..66b6de0251 100644
--- a/ext/tk/sample/demos-jp/style.rb
+++ b/ext/tk/sample/demos-jp/style.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# text (display styles) widget demo (called by 'widget')
#
@@ -8,6 +9,7 @@ if defined?($style_demo) && $style_demo
$style_demo = nil
end
+
# demo ÍѤΠtoplevel widget ¤òÀ¸À®
$style_demo = TkToplevel.new {|w|
title("Text Demonstration - Display Styles")
@@ -15,10 +17,13 @@ $style_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($style_demo).pack(:fill=>:both, :expand=>true)
+
# frame À¸À®
-TkFrame.new($style_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $style_demo
$style_demo = nil
@@ -32,14 +37,16 @@ TkFrame.new($style_demo) {|frame|
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
# text À¸À®
-TkText.new($style_demo){|t|
+txt = TkText.new(base_frame){|t|
# À¸À®
setgrid 'true'
- width 70
- height 32
+ #width 70
+ #height 32
wrap 'word'
- TkScrollbar.new($style_demo) {|s|
+ font $font
+ TkScrollbar.new(base_frame) {|s|
pack('side'=>'right', 'fill'=>'y')
command proc{|*args| t.yview(*args)}
t.yscrollcommand proc{|first,last| s.set first,last}
@@ -47,11 +54,20 @@ TkText.new($style_demo){|t|
pack('expand'=>'yes', 'fill'=>'both')
# ¥Æ¥­¥¹¥È¥¿¥°ÀßÄê (¥Õ¥©¥ó¥È´ØÏ¢)
- style_tag_bold = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-O-Normal--*-120-*-*-*-*-*-*')
- style_tag_big = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*', 'kanjifont'=>$msg_kanji_font)
+ family = 'Courier'
+
+ if $tk_version =~ /^4.*/
+ style_tag_bold = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-O-Normal--*-120-*-*-*-*-*-*')
+ style_tag_big = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*', 'kanjifont'=>$msg_kanji_font)
style_tag_verybig = TkTextTag.new(t, 'font'=>'-*-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*')
-# style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*', 'kanjifont'=>$kanji_font)
+ # style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*', 'kanjifont'=>$kanji_font)
style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*')
+ else
+ style_tag_bold = TkTextTag.new(t, 'font'=>[family, 12, :bold, :italic])
+ style_tag_big = TkTextTag.new(t, 'font'=>[family, 14, :bold])
+ style_tag_verybig = TkTextTag.new(t, 'font'=>['Helvetica', 24, :bold])
+ style_tag_small = TkTextTag.new(t, 'font'=>'Times 8 bold')
+ end
###
# case($tk_version)
# when /^4.*/
@@ -61,13 +77,13 @@ TkText.new($style_demo){|t|
# unless $style_demo_do_first
# $style_demo_do_first = true
# Tk.tk_call('font', 'create', '@bigascii',
-# '-copy', '-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*')
+# '-copy', '-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*')
# Tk.tk_call('font', 'create', '@smallascii',
-# '-copy', '-Adobe-Helvetica-Bold-R-Normal-*-100-*')
+# '-copy', '-Adobe-Helvetica-Bold-R-Normal-*-100-*')
# Tk.tk_call('font', 'create', '@cBigFont',
-# '-compound', '@bigascii @msg_knj')
+# '-compound', '@bigascii @msg_knj')
# Tk.tk_call('font', 'create', '@cSmallFont',
-# '-compound', '@smallascii @kanji')
+# '-compound', '@smallascii @kanji')
# end
# style_tag_big = TkTextTag.new(t, 'font'=>'@cBigFont')
# style_tag_small = TkTextTag.new(t, 'font'=>'@cSmallFont')
@@ -81,37 +97,42 @@ TkText.new($style_demo){|t|
style_tag_sunken = TkTextTag.new(t, 'relief'=>'sunken', 'borderwidth'=>1)
else
style_tag_color1 = TkTextTag.new(t, 'background'=>'black',
- 'foreground'=>'white')
+ 'foreground'=>'white')
style_tag_color2 = TkTextTag.new(t, 'background'=>'black',
- 'foreground'=>'white')
+ 'foreground'=>'white')
style_tag_raised = TkTextTag.new(t, 'background'=>'white',
- 'relief'=>'raised', 'borderwidth'=>1)
+ 'relief'=>'raised', 'borderwidth'=>1)
style_tag_sunken = TkTextTag.new(t, 'background'=>'white',
- 'relief'=>'sunken', 'borderwidth'=>1)
+ 'relief'=>'sunken', 'borderwidth'=>1)
end
# ¥Æ¥­¥¹¥È¥¿¥°ÀßÄê (¤½¤Î¾)
if $tk_version =~ /^4\.[01]/
style_tag_bgstipple = TkTextTag.new(t, 'background'=>'black',
- 'borderwidth'=>0,
- 'bgstipple'=>'gray25')
+ 'borderwidth'=>0,
+ 'bgstipple'=>'gray25')
else
style_tag_bgstipple = TkTextTag.new(t, 'background'=>'black',
- 'borderwidth'=>0,
- 'bgstipple'=>'gray12')
+ 'borderwidth'=>0,
+ 'bgstipple'=>'gray12')
end
style_tag_fgstipple = TkTextTag.new(t, 'fgstipple'=>'gray50')
style_tag_underline = TkTextTag.new(t, 'underline'=>'on')
style_tag_overstrike = TkTextTag.new(t, 'overstrike'=>'on')
style_tag_right = TkTextTag.new(t, 'justify'=>'right')
style_tag_center = TkTextTag.new(t, 'justify'=>'center')
- style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
- style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ if $tk_version =~ /^4.*/
+ style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ else
+ style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>[family, 10])
+ style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>[family, 10])
+ end
style_tag_margins = TkTextTag.new(t, 'lmargin1'=>'12m', 'lmargin2'=>'6m',
- 'rmargin'=>'10m')
+ 'rmargin'=>'10m')
style_tag_spacing = TkTextTag.new(t, 'spacing1'=>'10p', 'spacing2'=>'2p',
- 'lmargin1'=>'12m', 'lmargin2'=>'6m',
- 'rmargin'=>'10m')
+ 'lmargin1'=>'12m', 'lmargin2'=>'6m',
+ 'rmargin'=>'10m')
# ¥Æ¥­¥¹¥ÈÁÞÆþ
insert('end', '¤³¤Î¤è¤¦¤Ë¥Æ¥­¥¹¥È widget ¤Ï¾ðÊó¤òÍÍ¡¹¤Ê¥¹¥¿¥¤¥ë¤Çɽ¼¨¤¹¤ë¤³¤È
@@ -197,9 +218,9 @@ X')
insert('end', '¥Æ¥­¥¹¥È¤Îº¸Â¦¤Ë;ʬ¤Ê¶õÇò¤òÃÖ¤¯¤³¤È¤¬¤Ç¤­¤Þ¤¹:
')
insert('end', '¤³¤ÎÃÊÍî¤Ï¥Þ¡¼¥¸¥ó¤Î»ÈÍÑÎã¤Ç¤¹¡£¥¹¥¯¥ê¡¼¥ó',
- style_tag_margins)
+ style_tag_margins)
insert('end', '¾å¤ÇÀÞ¤êÊÖ¤µ¤ì¤ÆÉ½¼¨¤µ¤ì¤Æ¤¤¤ë1¹Ô¤Î¥Æ¥­¥¹¥È¤Ç¤¹¡£',
- style_tag_margins)
+ style_tag_margins)
insert('end', 'º¸Â¦¤Ë¤Ï2¼ïÎà¤Î¥Þ¡¼¥¸¥ó¤ò»ý¤Á¤Þ¤¹¡£', style_tag_margins)
insert('end', '1¹ÔÌܤËÂФ¹¤ë¤â¤Î¤È¡¢', style_tag_margins)
insert('end', '2¹ÔÌܰʹߤÎϢ³¤·¤¿¥Þ¡¼¥¸¥ó', style_tag_margins)
@@ -221,9 +242,9 @@ spacing3')
¤¯¤«¤ò¼¨¤·¤Þ¤¹¡£
')
insert('end', '¤³¤ì¤é¤Î¥¤¥ó¥Ç¥ó¥È¤µ¤ì¤¿ÃÊÍî¤Ï¤É¤Î¤è¤¦¤Ë',
- style_tag_spacing)
+ style_tag_spacing)
insert('end', '¥¹¥Ú¡¼¥·¥ó¥°¤¬¤¬¹Ô¤ï¤ì¤ë¤Î¤«¤ò¼¨¤·¤Þ¤¹¡£',
- style_tag_spacing)
+ style_tag_spacing)
insert('end', '³ÆÃÊÍî¤Ï¼ÂºÝ¤Ï¥Æ¥­¥¹¥Èwidget', style_tag_spacing)
insert('end', '¤Î1¹Ô¤Ç¡¢widget¤Ë¤è¤Ã¤ÆÀÞ¤ê¾ö¤Þ¤ì¤Æ¤¤¤Þ¤¹¡£
', style_tag_spacing)
@@ -233,11 +254,11 @@ spacing3')
insert('end', '¸ºß¤·¤Æ¤¤¤Þ¤¹¡£', style_tag_spacing)
insert('end', 'Spacing2¤Ï2point¤ËÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹¡£', style_tag_spacing)
insert('end', '¤³¤ì¤ÇÃÊÍî¤ÎÃæ¤Ë¤Û¤ó¤Î¾¯¤·´Ö³Ö¤¬Â¸ºß¤·¤Æ¤¤¤Þ¤¹¡£',
- style_tag_spacing)
+ style_tag_spacing)
insert('end', 'Spacing3¤Ï¤³¤ÎÎã¤Ç¤Ï»ÈÍѤµ¤ì¤Æ¤¤¤Þ¤»¤ó¡£
', style_tag_spacing)
insert('end', '´Ö³Ö¤¬¤É¤³¤Ë¤¢¤ë¤«¤ò¸«¤¿¤±¤ì¤Ð¡¢¤³¤ì¤é¤ÎÃÊÍî¤Î',
- style_tag_spacing)
+ style_tag_spacing)
insert('end', '¤Ê¤«¤Ç¥Æ¥­¥¹¥È¤òÁªÂò¤·¤Æ¤¯¤À¤µ¤¤¡£ÁªÂò¤Î', style_tag_spacing)
insert('end', 'ȿž¤·¤¿Éôʬ¤Ë¤Ï;ʬ¤Ë¤È¤é¤ì¤¿´Ö³Ö¤¬', style_tag_spacing)
insert('end', '´Þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¡£
@@ -245,3 +266,5 @@ spacing3')
}
+txt.width 70
+txt.height 32
diff --git a/ext/tk/sample/demos-jp/tcolor b/ext/tk/sample/demos-jp/tcolor
index 391ce4c446..17f7e1347e 100644
--- a/ext/tk/sample/demos-jp/tcolor
+++ b/ext/tk/sample/demos-jp/tcolor
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# -*- coding: euc-jp -*-
#
# tcolor --
# ¤³¤Î¥¹¥¯¥ê¥×¥È¤ÏRGB,HSB,CYM·Á¼°¤ò¥µ¥Ý¡¼¥È¤¹¤ë
@@ -16,15 +17,16 @@ require "tk"
# Tk¤Ë¤è¤Ã¤ÆÊѹ¹¤µ¤ì¤ëÊÑ¿ô¤ÏTkVariable¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤ò»È¤¦¡£
$colorSpace = TkVariable.new(:rgb)
+$master = nil
$red = 65535
$green = 0
$blue = 0
$color = "#ffff00000000"
$updating = TkVariable.new(0)
$autoUpdate = TkVariable.new(1)
-$name = TkVariable.new("")
-# $command = TkVariable.new("print(%%,\"\n\")")
-$command = TkVariable.new("")
+$name = TkVariable.new($color)
+$command = TkVariable.new("print(%%,\"\n\")")
+# $command = TkVariable.new("")
$label1 = TkVariable.new("label1")
$label2 = TkVariable.new("label2")
$label3 = TkVariable.new("label3")
@@ -123,9 +125,14 @@ def hsbToRgb(hue,sat,value)
end
+def _null_binding
+ Module.new.instance_eval{binding}
+end
+private :_null_binding
+
def doUpdate
newCmd = $command.to_s.gsub("%%","\"#{$color}\"")
- eval(newCmd)
+ eval(newCmd, _null_binding)
end
@@ -134,6 +141,8 @@ def tc_scaleChanged
return
end
+ $master = :scale if $master == nil
+
scale1 = $root.middle.middle.scale1
scale2 = $root.middle.middle.scale2
scale3 = $root.middle.middle.scale3
@@ -158,11 +167,13 @@ def tc_scaleChanged
raise(Exception,"unknown colorSpace")
end
$color = format("#%04x%04x%04x",$red.to_i,$green.to_i,$blue.to_i)
+ $name.value = $color if $master == :scale
$root.middle.right.set_color($color)
if( $autoUpdate.to_i == 1 )
doUpdate
end
- Tk.update(TRUE)
+ Tk.update(true)
+ $master = nil if $master == :scale
end
@@ -196,6 +207,8 @@ end
def tc_loadNamedColor(name)
+ $name.value = name
+ $master = :name if $master == nil
if name[0,1] != "#"
list = TkWinfo.rgb($root.middle.right.swatch,name)
$red = list[0]
@@ -204,27 +217,27 @@ def tc_loadNamedColor(name)
else
case name.length
when 4
- format = /#(.{1})(.{1})(.{1})/
+ fmt = /#(.{1})(.{1})(.{1})/
shift = 12
when 7
- format = /#(.{2})(.{2})(.{2})/
+ fmt = /#(.{2})(.{2})(.{2})/
shift = 8
when 10
- format = /#(.{3})(.{3})(.{3})/
+ fmt = /#(.{3})(.{3})(.{3})/
shift = 4
when 13
- format = /#(.{4})(.{4})(.{4})/
+ fmt = /#(.{4})(.{4})(.{4})/
shift = 0
else
raise(eException,"syntax error in color name \"#{name}\"")
end
- name.scan(format){|strlist|
+ name.scan(fmt){|strlist|
if strlist.length != 3
raise(eException,"syntax error in color name \"#{name}\"")
end
- $red = strlist[0].to_i
- $green = strlist[1].to_i
- $blue = strlist[2].to_i
+ $red = strlist[0].hex
+ $green = strlist[1].hex
+ $blue = strlist[2].hex
}
$red = $red << shift
$green = $green << shift
@@ -237,6 +250,8 @@ def tc_loadNamedColor(name)
if $autoUpdate.to_i == 1
doUpdate
end
+ Tk.update(true)
+ $master = nil if $master == :name
end
diff --git a/ext/tk/sample/demos-jp/text.rb b/ext/tk/sample/demos-jp/text.rb
index 179589d820..0ae480eb00 100644
--- a/ext/tk/sample/demos-jp/text.rb
+++ b/ext/tk/sample/demos-jp/text.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# text (basic facilities) widget demo (called by 'widget')
#
@@ -15,6 +16,8 @@ $text_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($text_demo).pack(:fill=>:both, :expand=>true)
+
# version check
if ((Tk::TK_VERSION.split('.').collect{|n| n.to_i} <=> [8,4]) < 0)
undo_support = false
@@ -23,9 +26,10 @@ else
end
# frame À¸À®
-TkFrame.new($text_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $text_demo
$text_demo = nil
@@ -40,13 +44,13 @@ TkFrame.new($text_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# text À¸À®
-TkText.new($text_demo){|t|
+TkText.new(base_frame){|t|
# À¸À®
relief 'sunken'
bd 2
setgrid 1
height 30
- TkScrollbar.new($text_demo) {|s|
+ TkScrollbar.new(base_frame) {|s|
pack('side'=>'right', 'fill'=>'y')
command proc{|*args| t.yview(*args)}
t.yscrollcommand proc{|first,last| s.set first,last}
@@ -91,16 +95,16 @@ TkText.new($text_demo){|t|
¥³¥ó¥È¥í¡¼¥ë-K ¤ÏÁÞÆþ¥«¡¼¥½¥ë¤«¤é¹ÔËö¤Þ¤Ç¤òºï½ü¤·¡¢¤½¤Î°ÌÃ֤˲þ¹Ô
¤·¤«¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï¡¢²þ¹Ô¤òºï½ü¤·¤Þ¤¹¡£#{
if undo_support
- undo_text = "Control-z ¤ÏºÇ¸å¤Ë¹Ô¤Ã¤¿Êѹ¹¤Î¼è¤ê¾Ã¤·(undo)¤ò¹Ô¤¤¡¢"
- case $tk_platform['platform']
- when "unix", "macintosh"
- undo_text << "Control-Shift-z"
- else # 'windows'
- undo_text << "Control-y"
- end
- undo_text << "¤Ïundo¤·¤¿Êѹ¹¤ÎºÆÅ¬ÍÑ(redo)¤ò¹Ô¤¤¤Þ¤¹¡£"
+ undo_text = "Control-z ¤ÏºÇ¸å¤Ë¹Ô¤Ã¤¿Êѹ¹¤Î¼è¤ê¾Ã¤·(undo)¤ò¹Ô¤¤¡¢"
+ case $tk_platform['platform']
+ when "unix", "macintosh"
+ undo_text << "Control-Shift-z"
+ else # 'windows'
+ undo_text << "Control-y"
+ end
+ undo_text << "¤Ïundo¤·¤¿Êѹ¹¤ÎºÆÅ¬ÍÑ(redo)¤ò¹Ô¤¤¤Þ¤¹¡£"
else
- ""
+ ""
end
}
diff --git a/ext/tk/sample/demos-jp/textpeer.rb b/ext/tk/sample/demos-jp/textpeer.rb
new file mode 100644
index 0000000000..4967a99c92
--- /dev/null
+++ b/ext/tk/sample/demos-jp/textpeer.rb
@@ -0,0 +1,82 @@
+# -*- coding: euc-jp -*-
+#
+# text widget peering demo (called by 'widget')
+#
+# based on Tcl/Tk8.5.0 widget demos
+
+if defined?($textpeer_demo) && $textpeer_demo
+ $textpeer_demo.destroy
+ $textpeer_demo = nil
+end
+
+# demo toplevel widget
+$textpeer_demo = TkToplevel.new {|w|
+ title("Text Wdget Peering Demonstration")
+ iconname("textpeer")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($textpeer_demo).pack(:fill=>:both, :expand=>true)
+
+count = [0]
+
+## Define a widget that we peer from; it won't ever actually be shown though
+first = TkText.new(base_frame, :widgetname=>"text#{count[0] += 1}")
+first.insert :end,"¤³¤Î¥Ç¥â¤Ï°ì¤Ä¤ÎÁȤòÀ®¤·¤¿¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤ò¼¨¤·¤Þ¤¹¡£"
+first.insert :end,"¤½¤ì¤é¤Î¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤ÏÂÐÅù(¥Ô¥¢;peer)¤Î´Ø·¸¤Ë"
+first.insert :end,"¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£"
+first.insert :end,"¤½¤ì¤é¤Ï¡¢´ðÈפȤʤë¥Ç¡¼¥¿¥â¥Ç¥ë¤Ï¶¦Ä̤Τâ¤Î¤ò»ý¤Á¤Þ¤¹¤¬¡¢"
+first.insert :end,"²èÌÌɽ¼¨°ÌÃÖ¡¢ÊÔ½¸°ÌÃÖ¡¢ÁªÂòÈϰÏ(selection)¤Ë¤Ä¤¤¤Æ¤Ï"
+first.insert :end,"ÆÈΩ¤Ë»ý¤Ä¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£"
+first.insert :end,"³Æ¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤ÎÏÆ¤Ë¤¢¤ë"
+first.insert :end,"¡Ö¥Ô¥¢(peer)¤ÎºîÀ®¡×¥Ü¥¿¥ó¤ò»È¤¨¤Ð¡¢"
+first.insert :end,"¿·¤¿¤Ê¥Ô¥¢¤òÄɲ乤뤳¤È¤¬²Äǽ¤Ç¤¹¡£"
+first.insert :end,"¤Þ¤¿¡Ö¥Ô¥¢(peer)¤Î¾Ãµî¡×¥Ü¥¿¥ó¤ò»È¤¨¤Ð¡¢"
+first.insert :end,"ÆÃÄê¤Î¥Ô¥¢¥¦¥£¥¸¥§¥Ã¥È¤ò¾Ãµî¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡£"
+
+Tk.update_idletasks ## for 'first' widget
+
+## Procedures to make and kill clones; most of this is just so that the demo
+## looks nice...
+def makeClone(count, win, txt)
+ cnt = (count[0] += 1)
+ peer = TkText::Peer.new(txt, win, :widgetname=>"text#{cnt}")
+ sbar = TkScrollbar.new(win, :widgetname=>"sb#{cnt}")
+ peer.yscrollbar sbar
+ b1 = TkButton.new(win, :widgetname=>"clone#{cnt}",
+ :text=>'¥Ô¥¢(peer)¤ÎºîÀ®',
+ :command=>proc{makeClone(count, win, peer)})
+ b2 = TkButton.new(win, :widgetname=>"kill#{cnt}",
+ :text=>'¥Ô¥¢(peer)¤Î¾Ãµî',
+ :command=>proc{killClone(win, cnt)})
+ row = cnt * 2
+ TkGrid.configure(peer, sbar, b1, :sticky=>'nsew', :row=>row)
+ TkGrid.configure('^', '^', b2, :sticky=>'nsew', :row=>(row+=1))
+ TkGrid.configure(b1, b2, :sticky=>'new')
+ TkGrid.rowconfigure(win, b2, :weight=>1)
+end
+
+def killClone(win, cnt)
+ Tk.destroy("#{win.path}.text#{cnt}", "#{win.path}.sb#{cnt}",
+ "#{win.path}.clone#{cnt}", "#{win.path}.kill#{cnt}")
+end
+
+## Now set up the GUI
+makeClone(count, base_frame, first)
+makeClone(count, base_frame, first)
+first.destroy
+
+## See Code / Dismiss buttons
+TkFrame.new(base_frame){|f|
+ TkButton.new(f, :text=>'ÊĤ¸¤ë', :width=>15, :command=>proc{
+ $textpeer_demo.destroy
+ $textpeer_demo = nil
+ }).pack(:side=>:left, :expand=>true)
+
+ TkButton.new(f, :text=>'¥³¡¼¥É»²¾È', :width=>15, :command=>proc{
+ showCode 'textpeer'
+ }).pack(:side=>:left, :expand=>true)
+
+ TkGrid.configure(f, '-', '-', :sticky=>'ew', :row=>5000)
+}
+TkGrid.columnconfigure(base_frame, 0, :weight=>1)
diff --git a/ext/tk/sample/demos-jp/toolbar.rb b/ext/tk/sample/demos-jp/toolbar.rb
new file mode 100644
index 0000000000..9cb3834c34
--- /dev/null
+++ b/ext/tk/sample/demos-jp/toolbar.rb
@@ -0,0 +1,136 @@
+# -*- coding: euc-jp -*-
+#
+# toolbar.rb --
+#
+# This demonstration script creates a toolbar that can be torn off.
+#
+# based on "Id: toolbar.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($toolbar_demo) && $toolbar_demo
+ $toolbar_demo.destroy
+ $toolbar_demo = nil
+end
+
+$toolbar_demo = TkToplevel.new {|w|
+ title("Ttk Menu Buttons")
+ iconname("toolbar")
+ positionWindow(w)
+}
+
+base_frame = Ttk::Frame.new($toolbar_demo).pack(:fill=>:both, :expand=>true)
+
+if Tk.windowingsystem != 'aqua'
+ msg = Ttk::Label.new(base_frame, :wraplength=>'4i', :text=><<EOL)
+¤³¤Î¥Ç¥â¤Ç¤Ï¡¤¥Ä¡¼¥ë¥Ð¡¼¤ò¤É¤Î¤è¤¦¤Ë¤·¤ÆÅ¬Àڤ˥ơ¼¥ÞÂбþ¤µ¤»¤ë¤«¡¤\
+¤Þ¤¿¡¤¤É¤Î¤è¤¦¤Ë¤·¤ÆÀÚ¤êÎ¥¤·²Äǽ¤Ë¤¹¤ë¤«¤ò¼¨¤·¤Æ¤¤¤Þ¤¹\
+¡Ê¤¿¤À¤·¡¤¥Ä¡¼¥ë¥Ð¡¼¤ÎÀÚ¤êÎ¥¤·¤Ë¤ÏTcl/Tk8.5°Ê¾å¤Îµ¡Ç½¤¬É¬ÍפǤ¹¡Ë¡¥\
+¥Ä¡¼¥ë¥Ð¡¼¤Î¥Ü¥¿¥ó¤Ï¡¤'Toolbutton'¥¹¥¿¥¤¥ë¤ò»ÈÍѤ¹¤ë¤è¤¦¤ËÌÀ¼¨¤¹¤ë¤³¤È¤Ç¡¤\
+"toolbar style"¥Ü¥¿¥ó¤È¤Ê¤ë¤è¤¦¤Ë°À­ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹¡¥\
+¥Ä¡¼¥ë¥Ð¡¼¤Îº¸Ã¼¤Ë¤Ï´Êñ¤Ê¥Þ¡¼¥«¡¼¤¬ÃÖ¤«¤ì¤Æ¤¤¤Þ¤¹¡¥\
+¥Þ¡¼¥«¡¼¾å¤Ë¥Þ¥¦¥¹¥«¡¼¥½¥ë¤¬Íè¤ë¤È°Üư¥¢¥¤¥³¥ó¤Ë¥«¡¼¥½¥ë¤¬ÊѲ½¤·¤Þ¤¹¡¥\
+¤½¤³¤Ç¥Ä¡¼¥ë¥Ð¡¼¤òư¤«¤¹¤è¤¦¤Ë¥É¥é¥Ã¥°¤¹¤ë¤È¡¤\
+¥Ä¡¼¥ë¥Ð¡¼Á´ÂΤòÀÚ¤êÎ¥¤·¤ÆÆÈΩ¤·¤¿¥È¥Ã¥×¥ì¥Ù¥ë¥¦¥£¥¸¥§¥Ã¥È¤Ë\
+¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥\
+ÀÚ¤êÎ¥¤·¤¿¥Ä¡¼¥ë¥Ð¡¼¤¬ÉÔÍפȤʤä¿»þ¤Ë¤Ï¡¤\
+°ìÈÌŪ¤Ê¥È¥Ã¥×¥ì¥Ù¥ë¥¦¥£¥¸¥§¥Ã¥È¤ÈƱÍͤËñ½ã¤ËÊĤ¸¤ë¤³¤È¤Ç¡¤
+ºÆ¤Ó¸µ¤Î¥¦¥£¥ó¥É¥¦¤ËÄ¥¤êÉÕ¤±¤é¤ì¤ë¤Ç¤·¤ç¤¦¡¥
+EOL
+else
+ msg = Ttk::Label.new(base_frame, :wraplength=>'4i', :text=><<EOL)
+¤³¤Î¥Ç¥â¤Ç¤Ï¡¤¥Ä¡¼¥ë¥Ð¡¼¤ò¤É¤Î¤è¤¦¤Ë¤·¤ÆÅ¬Àڤ˥ơ¼¥ÞÂбþ¤µ¤»¤ë¤«¤ò\
+¼¨¤·¤Æ¤¤¤Þ¤¹¡¥\
+¥Ä¡¼¥ë¥Ð¡¼¤Î¥Ü¥¿¥ó¤Ï¡¤'Toolbutton'¥¹¥¿¥¤¥ë¤ò»ÈÍѤ¹¤ë¤è¤¦¤ËÌÀ¼¨¤¹¤ë¤³¤È¤Ç¡¤\
+"toolbar style"¥Ü¥¿¥ó¤È¤Ê¤ë¤è¤¦¤Ë°À­ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹¡¥
+EOL
+end
+
+## Set up the toolbar hull
+tbar_base = Tk::Frame.new(base_frame, # Tk ɸ½à¤Î frame ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡¥
+ :widgetname=>'toolbar') # ¥¦¥£¥ó¥É¥¦¥¿¥¤¥È¥ëʸ»úÎó¤È¤¹¤ë¤¿¤á¤Ë¡¤¥¦¥£¥¸¥§¥Ã¥È̾¤òÌÀ¼¨¤·¤Æ¤¤¤Þ¤¹¡¥
+sep = Ttk::Separator.new(base_frame)
+to_base = Ttk::Frame.new(tbar_base, :cursor=>'fleur')
+if Tk.windowingsystem != 'aqua'
+ to = Ttk::Separator.new(to_base, :orient=>:vertical)
+ to2 = Ttk::Separator.new(to_base, :orient=>:vertical)
+ to.pack(:fill=>:y, :expand=>true, :padx=>2, :side=>:left)
+ to2.pack(:fill=>:y, :expand=>true, :side=>:left)
+end
+
+contents = Ttk::Frame.new(tbar_base)
+Tk.grid(to_base, contents, :sticky=>'nsew')
+tbar_base.grid_columnconfigure(contents, :weight=>1)
+contents.grid_columnconfigure(1000, :weight=>1)
+
+if Tk.windowingsystem != 'aqua'
+ ## Bindings so that the toolbar can be torn off and reattached
+ to_base.bind('B1-Motion', '%X %Y'){|x, y| tbar_base.tearoff(to_base, x, y)}
+ to. bind('B1-Motion', '%X %Y'){|x, y| tbar_base.tearoff(to_base, x, y)}
+ to2. bind('B1-Motion', '%X %Y'){|x, y| tbar_base.tearoff(to_base, x, y)}
+ def tbar_base.tearoff(w, x, y)
+ on_win = TkWinfo.containing(x, y)
+ return unless (on_win && on_win.path =~ /^#{@path}(\.|$)/)
+ self.grid_remove
+ w.grid_remove
+ self.wm_manage
+ # self.wm_title('Toolbar') # ¤â¤·¥¦¥£¥¸¥§¥Ã¥È̾¤ò¥¦¥£¥ó¥É¥¦¥¿¥¤¥È¥ë¤Ë¤·¤¿¤¯¤Ê¤¤¤Ê¤é¡¤¤³¤³¤ÇÀßÄꤷ¤Æ¤¯¤À¤µ¤¤
+ self.wm_protocol('WM_DELETE_WINDOW'){ self.untearoff(self) }
+ end
+ def tbar_base.untearoff(w)
+ self.wm_forget
+ w.grid
+ self.grid
+ end
+end
+
+## Some content for the rest of the toplevel
+text = TkText.new(base_frame, :width=>40, :height=>10)
+
+## Toolbar contents
+tb_btn = Ttk::Button.new(tbar_base, :text=>'¥Ü¥¿¥ó', :style=>'Toolbutton',
+ :command=>proc{
+ text.insert(:end, "¥Ü¥¿¥ó¤¬²¡¤µ¤ì¤Þ¤·¤¿¡¥\n")
+ })
+tb_chk = Ttk::Checkbutton.new(tbar_base, :text=>'¥Á¥§¥Ã¥¯¥Ü¥¿¥ó',
+ :style=>'Toolbutton',
+ :variable=>(check = TkVariable.new),
+ :command=>proc{
+ text.insert(:end, "¥Á¥§¥Ã¥¯¥Ü¥¿¥ó¤ÎÃͤÏ#{check.value}¤Ç¤¹¡¥\n")
+ })
+tb_mbtn = Ttk::Menubutton.new(tbar_base, :text=>'¥á¥Ë¥å¡¼')
+tb_combo = Ttk::Combobox.new(tbar_base, :value=>TkFont.families,
+ :state=>:readonly)
+tb_mbtn.menu(menu = Tk::Menu.new(tb_mbtn))
+menu.add(:command, :label=>'Just', :command=>proc{text.insert(:end, "Just\n")})
+menu.add(:command, :label=>'An', :command=>proc{text.insert(:end, "An\n")})
+menu.add(:command, :label=>'Example',
+ :command=>proc{text.insert(:end, "Example\n")})
+tb_combo.bind('<ComboboxSelected>'){ text.font.family = tb_combo.get }
+
+## Arrange contents
+Tk.grid(tb_btn, tb_chk, tb_mbtn, tb_combo,
+ :in=>contents, :padx=>2, :sticky=>'ns')
+Tk.grid(tbar_base, :sticky=>'ew')
+Tk.grid(sep, :sticky=>'ew')
+Tk.grid(msg, :sticky=>'ew')
+Tk.grid(text, :sticky=>'nsew')
+base_frame.grid_rowconfigure(text, :weight=>1)
+base_frame.grid_columnconfigure(text, :weight=>1)
+
+## See Code / Dismiss buttons
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'toolbar'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $toolbar_demo.destroy
+ $toolbar_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ Tk.grid(frame, :sticky=>'ew')
+}
diff --git a/ext/tk/sample/demos-jp/tree.rb b/ext/tk/sample/demos-jp/tree.rb
new file mode 100644
index 0000000000..c3b4191144
--- /dev/null
+++ b/ext/tk/sample/demos-jp/tree.rb
@@ -0,0 +1,120 @@
+# -*- coding: euc-jp -*-
+#
+# tree.rb --
+#
+# This demonstration script creates a toplevel window containing a Ttk
+# tree widget.
+#
+# based on "Id: tree.tcl,v 1.4 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($tree_demo) && $tree_demo
+ $tree_demo.destroy
+ $tree_demo = nil
+end
+
+$tree_demo = TkToplevel.new {|w|
+ title("Directory Browser")
+ iconname("tree")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($tree_demo).pack(:fill=>:both, :expand=>true)
+
+## Explanatory text
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i',
+ :justify=>:left, :anchor=>'n', :padding=>[10, 2, 10, 6],
+ :text=><<EOL).pack(:fill=>:x)
+Ttk¤È¤Ï¡¤¥Æ¡¼¥Þ»ØÄê²Äǽ¤Ê¿·¤·¤¤¥¦¥£¥¸¥§¥Ã¥È½¸¹ç¤Ç¤¹¡¥\
+¤³¤Î¥µ¥ó¥×¥ë¤Ï¡¤¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Î¤è¤¦¤Ê³¬ÁØÅª¤Ê¥Ç¡¼¥¿½¸¹ç¤ò\
+»²¾È¤Ç¤­¤ë¤è¤¦¤Ë¤·¤¿Ttk::Treeview¥¦¥£¥¸¥§¥Ã¥È¤ò´Þ¤ó¤Ç¤¤¤Þ¤¹¡¥\
+Ttk::Treeview¥¦¥£¥¸¥§¥Ã¥È¤Ï¡¤ÌÚ¹½Â¤¼«ÂΤÎɽ¼¨¤ò²Äǽ¤Ë¤¹¤ë¤À¤±¤Ç¤Ê¤¯¡¤\
+ÄɲþðÊó(¤³¤Î¥µ¥ó¥×¥ë¤Î¾ì¹ç¤Ï¥Õ¥¡¥¤¥ë¥µ¥¤¥º)¤òɽ¼¨¤¹¤ë¤¿¤á¤Ë\
+Ǥ°Õ¤Î¸Ä¿ô¤ÎÄɲå«¥é¥à¤â°·¤¦¤³¤È¤â¤Ç¤­¤Þ¤¹¡¥\
+¤Þ¤¿¡¤¥«¥é¥à¤Î¥¿¥¤¥È¥ë´Ö¤Î¶èÀÚ¤êÉôʬ¤ò¥É¥é¥Ã¥°¤¹¤ë¤³¤È¤Ç¡¤\
+¥«¥é¥à¤ÎÉý¤òÊѹ¹¤¹¤ë¤³¤È¤â²Äǽ¤Ç¤¹¡¥
+EOL
+
+## See Code / Dismiss
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'tree'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $tree_demo.destroy
+ $tree_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+## Code to populate the roots of the tree (can be more than one on Windows)
+def populate_roots(tree)
+ TkComm.simplelist(Tk.tk_call('file', 'volumes')).sort.each{|dir|
+ populate_tree(tree, tree.insert(nil, :end, :text=>dir,
+ :values=>[dir, 'directory']))
+ }
+end
+
+## Code to populate a node of the tree
+def populate_tree(tree, node)
+ return if tree.get(node, :type) != 'directory'
+
+ path = tree.get(node, :fullpath)
+ tree.delete(tree.children(node))
+ Dir.glob("#{path}/*").sort.each{|f|
+ type = File.ftype(f)
+ id = tree.insert(node, :end,
+ :text=>File.basename(f), :values=>[f, type]).id
+ if type == 'directory'
+ ## Make it so that this node is openable
+ tree.insert(id, 0, :text=>'dummy')
+ tree.itemconfigure(id, :text=>File.basename(f))
+ elsif type == 'file'
+ size = File.size(f)
+ if size >= 1024*1024*1024
+ size = '%.1f GB' % (size.to_f/1024/1024/1024)
+ elsif size >= 1024*1024
+ size = '%.1f MB' % (size.to_f/1024/1024)
+ elsif size >= 1024
+ size = '%.1f KB' % (size.to_f/1024)
+ else
+ size = '%.1f bytes' % (size.to_f/1024)
+ end
+ tree.set(id, :size, size)
+ end
+ }
+
+ # Stop this code from rerunning on the current node
+ tree.set(node, :type, 'processed_directory')
+end
+
+## Create the tree and set it up
+tree = Ttk::Treeview.new(base_frame, :columns=>%w(fullpath type size),
+ :displaycolumns=>['size'])
+if Tk.windowingsystem != 'aqua'
+ vsb = tree.yscrollbar(Ttk::Scrollbar.new(base_frame))
+ hsb = tree.xscrollbar(Ttk::Scrollbar.new(base_frame))
+else
+ vsb = tree.yscrollbar(Tk::Scrollbar.new(base_frame))
+ hsb = tree.xscrollbar(Tk::Scrollbar.new(base_frame))
+end
+
+tree.heading_configure('#0', :text=>'Directory Structure')
+tree.heading_configure('size', :text=>'File Size')
+tree.column_configure('size', :stretch=>0, :width=>70)
+populate_roots(tree)
+tree.bind('<TreeviewOpen>', '%W'){|w| populate_tree(w, w.focus_item)}
+
+## Arrange the tree and its scrollbars in the toplevel
+container = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+container.lower
+Tk.grid(tree, vsb, :in=>container, :sticky=>'nsew')
+Tk.grid(hsb, :in=>container, :sticky=>'nsew')
+container.grid_columnconfigure(0, :weight=>1)
+container.grid_rowconfigure(0, :weight=>1)
diff --git a/ext/tk/sample/demos-jp/ttkbut.rb b/ext/tk/sample/demos-jp/ttkbut.rb
new file mode 100644
index 0000000000..4d577120bb
--- /dev/null
+++ b/ext/tk/sample/demos-jp/ttkbut.rb
@@ -0,0 +1,145 @@
+# -*- coding: euc-jp -*-
+#
+# ttkbut.rb
+#
+# This demonstration script creates a toplevel window containing several
+# simple Ttk widgets, such as labels, labelframes, buttons, checkbuttons and
+# radiobuttons.
+#
+# based on "Id: ttkbut.tcl,v 1.4 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttkbut_demo) && $ttkbut_demo
+ $ttkbut_demo.destroy
+ $ttkbut_demo = nil
+end
+
+$ttkbut_demo = TkToplevel.new {|w|
+ title("Simple Ttk Widgets")
+ iconname("ttkbut")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($ttkbut_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top, :fill=>:x)
+Ttk¤È¤Ï¡¤¥Æ¡¼¥Þ»ØÄê²Äǽ¤Ê¿·¤·¤¤¥¦¥£¥¸¥§¥Ã¥È½¸¹ç¤Ç¤¹¡¥\
+º£¡¤¤¢¤Ê¤¿¤¬Ìܤˤ·¤Æ¤¤¤ë¤Î¤ÏTtk¤Î¥Æ¡¼¥Þ²½¥é¥Ù¥ë¤Ç¡¤\
+²¼¤Ë¤ÏTtk¤Î¥é¥Ù¥ë¥Õ¥ì¡¼¥à¤ÎÃæ¤Ë»°¤Ä¤Î¥°¥ë¡¼¥×¤ÎTtk¥¦¥£¥¸¥§¥Ã¥È¤¬\
+ɽ¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+ºÇ½é¤Î¥°¥ë¡¼¥×¤ÏÁ´¤Æ¥Ü¥¿¥ó¤Ç¤¢¤ê¡¤\
+¤½¤ì¤¾¤ì¥¯¥ê¥Ã¥¯¤¹¤ì¤Ð¸½ºß¤Î¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¥Æ¡¼¥Þ¤¬ÀßÄꤵ¤ì¤Þ¤¹¡¥
+£²ÈÖÌܤΥ°¥ë¡¼¥×¤Ï»°¤Ä¤Î¥Á¥§¥Ã¥¯¥Ü¥¿¥ó½¸¹ç¤Ç¤¹¡¥\
+³Æ½¸¹ç¤Î´Ö¤Ë¤Ï¡¤¥»¥Ñ¥ì¡¼¥¿¥¦¥£¥¸¥§¥Ã¥È¤¬ÃÖ¤«¤ì¤Æ¤¤¤Þ¤¹¡¥\
+¤Ê¤ª¡ÖÍ­¸ú²½¡×¥Ü¥¿¥ó¤Ï¡¤¤³¤Î¥È¥Ã¥×¥ì¥Ù¥ë¥¦¥£¥¸¥§¥Ã¥ÈÆâ¤Î\
+¾¤Î¤¹¤Ù¤Æ¤Î¥Æ¡¼¥Þ²½¥¦¥£¥¸¥§¥Ã¥È¤Î¾õÂÖ(state)¤¬"disabled"¤«¤É¤¦¤«¤ò\
+¥³¥ó¥È¥í¡¼¥ë¤¹¤ë¤³¤È¤ËÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡¥
+£³ÈÖÌܤΥ°¥ë¡¼¥×¤Ï´ØÏ¢ÉÕ¤±¤é¤ì¤¿¥é¥¸¥ª¥Ü¥¿¥ó½¸¹ç¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+EOL
+
+## Add buttons for setting the theme
+buttons = Ttk::Labelframe.new(base_frame, :text=>'¥Ü¥¿¥ó')
+# Ttk::Style.theme_names.each{|theme|
+# Ttk::Button.new(buttons, :text=>theme,
+# :command=>proc{Ttk::Style.theme_use theme}).pack(:pady=>2)
+# }
+Ttk.themes.each{|theme|
+ Ttk::Button.new(buttons, :text=>theme,
+ :command=>proc{Ttk.set_theme theme}).pack(:pady=>2)
+}
+
+## Helper procedure for the top checkbutton
+def setState(root, value, *excepts)
+ return if excepts.member?(root)
+
+ ## Non-Ttk widgets (e.g. the toplevel) will fail, so make it silent
+ begin
+ root.state = value
+ rescue
+ end
+
+ ## Recursively invoke on all children of this root that are in the same
+ ## toplevel widget
+ root.winfo_children.each{|w|
+ setState(w, value, *excepts) if w.winfo_toplevel == root.winfo_toplevel
+ }
+end
+
+## Set up the checkbutton group
+checks = Ttk::Labelframe.new(base_frame, :text=>'¥Á¥§¥Ã¥¯¥Ü¥¿¥ó')
+enabled = TkVariable.new(true)
+e = Ttk::Checkbutton.new(checks, :text=>'Í­¸ú²½', :variable=>enabled,
+ :command=>proc{
+ setState($ttkbut_demo,
+ ((enabled.bool)? "!disabled" : "disabled"),
+ e)
+ })
+
+## See ttk_widget(n) for other possible state flags
+sep1 = Ttk::Separator.new(checks)
+sep2 = Ttk::Separator.new(checks)
+
+cheese = TkVariable.new
+tomato = TkVariable.new
+basil = TkVariable.new
+oregano = TkVariable.new
+
+c1 = Ttk::Checkbutton.new(checks, :text=>'¥Á¡¼¥º', :variable=>cheese)
+c2 = Ttk::Checkbutton.new(checks, :text=>'¥È¥Þ¥È', :variable=>tomato)
+c3 = Ttk::Checkbutton.new(checks, :text=>'¥Ð¥¸¥ë', :variable=>basil)
+c4 = Ttk::Checkbutton.new(checks, :text=>'¥ª¥ì¥¬¥Î', :variable=>oregano)
+
+Tk.pack(e, sep1, c1, c2, sep2, c3, c4, :fill=>:x, :pady=>2)
+
+## Set up the radiobutton group
+radios = Ttk::Labelframe.new(base_frame, :text=>'¥é¥¸¥ª¥Ü¥¿¥ó')
+
+happyness = TkVariable.new
+
+r1 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Great', :value=>'great')
+r2 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Good', :value=>'good')
+r3 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Ok', :value=>'ok')
+r4 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Poor', :value=>'poor')
+r5 = Ttk::Radiobutton.new(radios, :variable=>happyness,
+ :text=>'Awful', :value=>'awful')
+
+Tk.pack(r1, r2, r3, r4, r5, :fill=>:x, :padx=>3, :pady=>2)
+
+## See Code / Dismiss
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'ÊÑ¿ô»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{
+ showVars(base_frame, ['Í­¸ú²½', enabled],
+ ['¥Á¡¼¥º', cheese], ['¥È¥Þ¥È', tomato],
+ ['¥Ð¥¸¥ë', basil], ['¥ª¥ì¥¬¥Î', oregano],
+ ['¹¬Ê¡ÅÙ', happyness])
+ }),
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttkbut'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ tmppath = $ttkbut_demo
+ $ttkbut_demo = nil
+ $showVarsWin[tmppath.path] = nil
+ tmppath.destroy
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x, :expand=>true)
+}
+
+## Arrange things neatly
+f = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+f.lower
+Tk.grid(buttons, checks, radios, :in=>f, :sticky=>'nwe', :pady=>2, :padx=>3)
+f.grid_columnconfigure([0, 1, 2], :weight=>1, :uniform=>:yes)
diff --git a/ext/tk/sample/demos-jp/ttkmenu.rb b/ext/tk/sample/demos-jp/ttkmenu.rb
new file mode 100644
index 0000000000..d349b42d11
--- /dev/null
+++ b/ext/tk/sample/demos-jp/ttkmenu.rb
@@ -0,0 +1,91 @@
+# -*- coding: euc-jp -*-
+#
+# ttkmenu.rb --
+#
+# This demonstration script creates a toplevel window containing several Ttk
+# menubutton widgets.
+#
+# based on "Id: ttkmenu.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttkmenu_demo) && $ttkmenu_demo
+ $ttkmenu_demo.destroy
+ $ttkmenu_demo = nil
+end
+
+$ttkmenu_demo = TkToplevel.new {|w|
+ title("Ttk Menu Buttons")
+ iconname("ttkmenu")
+ positionWindow(w)
+}
+
+base_frame = Ttk::Frame.new($ttkmenu_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top, :fill=>:x)
+Ttk¤È¤Ï¡¤¥Æ¡¼¥Þ»ØÄê²Äǽ¤Ê¿·¤·¤¤¥¦¥£¥¸¥§¥Ã¥È½¸¹ç¤Ç¤¹¡¥\
+¤³¤ì¤Ë¤è¤ê¥Æ¡¼¥Þ¤ËÂбþ¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¥¦¥£¥¸¥§¥Ã¥È¤Î¤Ò¤È¤Ä¤Ë\
+¥á¥Ë¥å¡¼¥Ü¥¿¥ó¤¬¤¢¤ê¤Þ¤¹¡¥\
+°Ê²¼¤Ç¤Ï¡¤¥Æ¡¼¥Þ¤ËÂбþ¤·¤¿¥á¥Ë¥å¡¼¥Ü¥¿¥ó¤¬¤¤¤¯¤Ä¤«É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥\
+¤½¤ì¤é¤ò»È¤Ã¤Æ¡¤¸½ºß»ÈÍÑÃæ¤Î¥Æ¡¼¥Þ¤òÊѹ¹¤¹¤ë¤³¤È¤¬²Äǽ¤Ç¤¹¡¥\
+¥Æ¡¼¥Þ¤ÎÁªÂò¤¬¥á¥Ë¥å¡¼¥Ü¥¿¥ó¼«¿È¤Î¸«³Ý¤±¤òÊѲ½¤µ¤»¤ëÍͻҤ䡤\
+Ãæ±û¤Î¥á¥Ë¥å¡¼¥Ü¥¿¥ó¤À¤±¤¬°Û¤Ê¤ë¥¹¥¿¥¤¥ë\
+(¥Ä¡¼¥ë¥Ð¡¼¤Ç¤Î°ìÈÌŪ¤Êɽ¼¨¤ËŬ¤·¤¿¤â¤Î)¤Çɽ¼¨¤µ¤ì¤Æ¤¤¤ëÍͻҤË\
+ÃíÌܤ·¤Æ¤¯¤À¤µ¤¤¡¥\
+¤Ê¤ª¡¤¥á¥Ë¥å¡¼¥Ü¥¿¥ó¤Ë¤Ä¤¤¤Æ¤Ï¥Æ¡¼¥Þ¤ËÂбþ¤·¤¿¥¦¥£¥¸¥§¥Ã¥È¤¬¤¢¤ê¤Þ¤¹¤¬¡¤\
+¥á¥Ë¥å¡¼¤Ë¤Ä¤¤¤Æ¤Ï¥Æ¡¼¥Þ¤ËÂбþ¤·¤¿¥¦¥£¥¸¥§¥Ã¥È¤Ï´Þ¤Þ¤ì¤Æ¤¤¤Þ¤»¤ó¡¥\
+¤½¤ÎÍýͳ¤Ï¡¤É¸½à¤ÎTk¤Î¥á¥Ë¥å¡¼¥¦¥£¥¸¥§¥Ã¥È¤¬\
+¤¹¤Ù¤Æ¤Î¥×¥é¥Ã¥È¥Û¡¼¥à¤Ç½½Ê¬¤ËÎɹ¥¤Ê¸«³Ý¤±¤ÈÁàºîÀ­¤ò»ý¤Ã¤Æ¤¤¤ë¡¤\
+ÆÃ¤Ë¡¤Â¿¤¯¤Î´Ä¶­¤Ç¤½¤Î´Ä¶­ËÜÍè¤ÎÁàºîÂηϤȤʤë¤è¤¦¤Ë¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤È\
+ȽÃǤµ¤ì¤¿¤³¤È¤Ë¤è¤ê¤Þ¤¹¡¥
+EOL
+
+Ttk::Separator.new(base_frame).pack(:side=>:top, :fill=>:x)
+
+## See Code / Dismiss
+Ttk::Frame.new($ttkmenu_demo) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttkmenu'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $ttkmenu_demo.destroy
+ $ttkmenu_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+b1 = Ttk::Menubutton.new(base_frame,:text=>'¥Æ¡¼¥Þ¤òÁªÂò',:direction=>:above)
+b2 = Ttk::Menubutton.new(base_frame,:text=>'¥Æ¡¼¥Þ¤òÁªÂò',:direction=>:left)
+b3 = Ttk::Menubutton.new(base_frame,:text=>'¥Æ¡¼¥Þ¤òÁªÂò',:direction=>:right)
+b4 = Ttk::Menubutton.new(base_frame,:text=>'¥Æ¡¼¥Þ¤òÁªÂò',:direction=>:flush,
+ :style=>Ttk::Menubutton.style('Toolbutton'))
+b5 = Ttk::Menubutton.new(base_frame,:text=>'¥Æ¡¼¥Þ¤òÁªÂò',:direction=>:below)
+
+b1.menu(m1 = Tk::Menu.new(b1, :tearoff=>false))
+b2.menu(m2 = Tk::Menu.new(b2, :tearoff=>false))
+b3.menu(m3 = Tk::Menu.new(b3, :tearoff=>false))
+b4.menu(m4 = Tk::Menu.new(b4, :tearoff=>false))
+b5.menu(m5 = Tk::Menu.new(b5, :tearoff=>false))
+
+Ttk.themes.each{|theme|
+ m1.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+ m2.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+ m3.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+ m4.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+ m5.add(:command, :label=>theme, :command=>proc{Ttk.set_theme theme})
+}
+
+f = Ttk::Frame.new(base_frame).pack(:fill=>:x)
+f1 = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+f.lower
+
+f.grid_anchor(:center)
+TkGrid('x', b1, 'x', :in=>f, :padx=>3, :pady=>2)
+TkGrid(b2, b4, b3, :in=>f, :padx=>3, :pady=>2)
+TkGrid('x', b5, 'x', :in=>f, :padx=>3, :pady=>2)
diff --git a/ext/tk/sample/demos-jp/ttknote.rb b/ext/tk/sample/demos-jp/ttknote.rb
new file mode 100644
index 0000000000..09cc7960a3
--- /dev/null
+++ b/ext/tk/sample/demos-jp/ttknote.rb
@@ -0,0 +1,97 @@
+# -*- coding: euc-jp -*-
+#
+# ttknote.rb --
+#
+# This demonstration script creates a toplevel window containing a Ttk
+# notebook widget.
+#
+# based on "Id: ttknote.tcl,v 1.5 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttknote_demo) && $ttknote_demo
+ $ttknote_demo.destroy
+ $ttknote_demo = nil
+end
+
+$ttknote_demo = TkToplevel.new {|w|
+ title("Ttk Notebook Widget")
+ iconname("ttknote")
+ positionWindow(w)
+}
+
+## See Code / Dismiss
+Ttk::Frame.new($ttknote_demo) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttknote'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $ttknote_demo.destroy
+ $ttknote_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+base_frame = Ttk::Frame.new($ttknote_demo).pack(:fill=>:both, :expand=>true)
+
+## Make the notebook and set up Ctrl+Tab traversal
+notebook = Ttk::Notebook.new(base_frame).pack(:fill=>:both, :expand=>true,
+ :padx=>2, :pady=>3)
+notebook.enable_traversal
+
+## Popuplate the first pane
+f_msg = Ttk::Frame.new(notebook)
+msg_m = Ttk::Label.new(f_msg, :font=>$font, :wraplength=>'5i',
+ :justify=>:left, :anchor=>'n', :text=><<EOL)
+Ttk¤È¤Ï¡¤¥Æ¡¼¥Þ»ØÄê²Äǽ¤Ê¿·¤·¤¤¥¦¥£¥¸¥§¥Ã¥È½¸¹ç¤Ç¤¹¡¥\
+¤½¤ÎÃæ¤Ë´Þ¤Þ¤ì¤ë¥¦¥£¥¸¥§¥Ã¥È¤Î¤Ò¤È¤Ä¤Ë¥Î¡¼¥È¥Ö¥Ã¥¯¥¦¥£¥¸¥§¥Ã¥È¤¬¤¢¤ê¤Þ¤¹¡¥\
+¥Î¡¼¥È¥Ö¥Ã¥¯¥¦¥£¥¸¥§¥Ã¥È¤Ï¡¤\
+¸ÄÊÌ¤ÎÆâÍÆ¤ò»ý¤Ã¤¿¥Ñ¥Í¥ë¤«¤é¤ÎÁªÂò¤ò²Äǽ¤Ë¤¹¤ë¤è¤¦¤Ê\
+¥¿¥Ö¤Î½¸¹ç¡Ê¥¿¥Ö¥»¥Ã¥È¡Ë¤òÄê¤á¤Þ¤¹¡¥\
+¥¿¥Ö¥»¥Ã¥È¤ÏºÇ¶á¤Î¿¤¯¤Î¥æ¡¼¥¶¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤Ç¸«¤é¤ì¤ëµ¡Ç½¤Ç¤¹¡¥\
+¥¿¥Ö¤ÎÁªÂò¤Ï¡¤¥Þ¥¦¥¹¤Ë¤è¤ë¤À¤±¤Ç¤Ê¤¯¡¤\
+¥Î¡¼¥È¥Ö¥Ã¥¯¥¦¥£¥¸¥§¥Ã¥È¤Î¥Ú¡¼¥¸¤Î¸«½Ð¤·¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤ë»þ¤Ç¤¢¤ì¤Ð\
+Ctrl+Tab¥­¡¼¤ÎÆþÎϤˤè¤Ã¤Æ¤â¹Ô¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥\
+¤³¤Î¥Ç¥â¤Ç¤Ï¡¤¸«½Ð¤·¤Ç²¼ÀþÉÕ¤­¤Îʸ»ú¤Î¥­¡¼¤ÈAlt¥­¡¼¤È¤òÁȤ߹ç¤ï¤»¤ë¤³¤È¤Ç\
+¥Ú¡¼¥¸¤òÁªÂò¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤âÀßÄꤷ¤Æ¤¤¤Þ¤¹¡¥\
+¤¿¤À¤·¡¤£²ÈÖÌܤΥ¿¥Ö¤Ï̵¸ú²½¤µ¤ì¤ÆÁªÂò¤Ç¤­¤Ê¤¤¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤³¤È¤Ë¤Ï\
+Ãí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡¥
+EOL
+neat = TkVariable.new
+after_id = nil
+msg_b = Ttk::Button.new(f_msg, :text=>'¤¹¤Æ¤­¤À¡ª(Neat!)', :underline=>6,
+ :command=>proc{
+ neat.value = '¤¢¤¡¡¤¤½¤Î¤È¤ª¤ê¤µ¡¥¡¥¡¥'
+ Tk.after_cancel(after_id) if after_id
+ after_id = Tk.after(500){neat.value = ''}
+ })
+msg_b.winfo_toplevel.bind('Alt-n'){ msg_b.focus; msg_b.invoke }
+msg_l = Ttk::Label.new(f_msg, :textvariable=>neat)
+notebook.add(f_msg, :text=>'ÀâÌÀ(Description)', :underline=>3, :padding=>2)
+Tk.grid(msg_m, '-', :sticky=>'new', :pady=>2)
+Tk.grid(msg_b, msg_l, :pady=>[2, 4], :padx=>20)
+msg_b.grid_configure(:sticky=>'e')
+msg_l.grid_configure(:sticky=>'w')
+f_msg.grid_rowconfigure(1, :weight=>1)
+f_msg.grid_columnconfigure([0, 1], :weight=>1, :uniform=>1)
+
+## Populate the second pane. Note that the content doesn't really matter
+f_disabled = Ttk::Frame.new(notebook)
+notebook.add(f_disabled, :text=>'̵¸ú²½¤µ¤ì¤¿¥¿¥Ö', :state=>:disabled)
+
+## Popuplate the third pane
+f_editor = Ttk::Frame.new(notebook)
+notebook.add(f_editor, :text=>'¥Æ¥­¥¹¥È¥¨¥Ç¥£¥¿(Text Editor)', :underline=>9)
+editor_t = Tk::Text.new(f_editor, :width=>40, :height=>10, :wrap=>:char)
+if Tk.windowingsystem != 'aqua'
+ editor_s = editor_t.yscrollbar(Ttk::Scrollbar.new(f_editor))
+else
+ editor_s = editor_t.yscrollbar(Tk::Scrollbar.new(f_editor))
+end
+editor_s.pack(:side=>:right, :fill=>:y, :padx=>[0,2], :pady=>2)
+editor_t.pack(:fill=>:both, :expand=>true, :padx=>[2,0], :pady=>2)
diff --git a/ext/tk/sample/demos-jp/ttkpane.rb b/ext/tk/sample/demos-jp/ttkpane.rb
new file mode 100644
index 0000000000..96670c0e5c
--- /dev/null
+++ b/ext/tk/sample/demos-jp/ttkpane.rb
@@ -0,0 +1,216 @@
+# -*- coding: euc-jp -*-
+#
+# ttkpane.rb --
+#
+# This demonstration script creates a Ttk pane with some content.
+#
+# based on "Id: ttkpane.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttkpane_demo) && $ttkpane_demo
+ $ttkpane_demo.destroy
+ $ttkpane_demo = nil
+end
+
+$ttkpane_demo = TkToplevel.new {|w|
+ title("Themed Nested Panes")
+ iconname("ttkpane")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($ttkpane_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top, :fill=>:x)
+¤³¤Î¥Ç¥â¤Ï¡¤Ëä¤á¹þ¤ß´Ø·¸¤Ë¤¢¤ë¥Æ¡¼¥ÞÉÕ¤­¥Ú¥¤¥ó¥É¥¦¥£¥ó¥É¥¦¤ò¼¨¤·¤Æ¤¤¤Þ¤¹¡¥\
+¤½¤ì¤¾¤ì¤ÎÂ礭¤µ¤Ï¡¤´Þ¤Þ¤ì¤Æ¤¤¤ë¥Ú¥¤¥ó¤Î´Ö¤Ë¤¢¤ë¥¨¥ê¥¢¤ò¤Ä¤«¤ó¤Ç\
+¶­³¦¤ò¥É¥é¥Ã¥°¤¹¤ë¤³¤È¤ÇÊѹ¹¤Ç¤­¤Þ¤¹¡¥
+EOL
+
+Ttk::Separator.new(base_frame).pack(:side=>:top, :fill=>:x)
+
+## See Code / Dismiss
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttkpane'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $ttkpane_demo.destroy
+ $ttkpane_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+frame = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+
+outer = Ttk::Panedwindow.new(frame, :orient=>:horizontal)
+outer.add(in_left = Ttk::Panedwindow.new(outer, :orient=>:vertical))
+outer.add(in_right = Ttk::Panedwindow.new(outer, :orient=>:vertical))
+in_left.add(left_top = Ttk::Labelframe.new(in_left, :text=>'¥Ü¥¿¥ó'))
+in_left.add(left_bot = Ttk::Labelframe.new(in_left, :text=>'»þ·×'))
+in_right.add(right_top = Ttk::Labelframe.new(in_right, :text=>'¥×¥í¥°¥ì¥¹'))
+in_right.add(right_bot = Ttk::Labelframe.new(in_right, :text=>'¥Æ¥­¥¹¥È'))
+if Tk.windowingsystem == 'aqua'
+ [left_top, left_bot, right_top, right_bot].each{|w| w.padding(3) }
+end
+
+# Fill the button pane
+Ttk::Button.new(left_top, :text=>'²¡¤·¤Æ¤Í',
+ :command=>proc{
+ Tk.messageBox(:type=>'ok', :icon=>'info',
+ :message=>'¤¤¤Æ¤Æ¡ª',
+ :detail=>'That hurt...', :parent=>base_frame,
+ :title=>'Button Pressed')
+ }).pack(:padx=>2, :pady=>5)
+
+
+zones_list = [
+ [':Europe/Berlin'],
+ [':America/Argentina/Buenos_Aires', ':America/Buenos_Aires'],
+ [':Africa/Johannesburg'],
+ [':Europe/London'],
+ [':America/Los_Angeles'],
+ [':Europe/Moscow'],
+ [':America/New_York'],
+ [':Asia/Singapore'],
+ [':Australia/Sydney'],
+ [':Asia/Tokyo'],
+]
+
+zones = []
+
+# Check tzinfo support
+if $tk_major_ver > 8 || ($tk_major_ver == 8 && $tk_minor_ver >= 5)
+ tzinfo = :tcl
+
+ zones_list.each{|list|
+ list.each{|zone|
+ begin
+ # Force a pre-load of all the timezones needed; otherwise can end up
+ # poor-looking synch problems!
+ Tk.tk_call('clock', 'format', '0', '-timezone', zone)
+ rescue RuntimeError
+ # ignore
+ else
+ zones << [zone, zone[%r<[^/:]+$>].tr('_', ' ')]
+ break
+ end
+ }
+ }
+
+else
+ begin
+ require 'tzinfo'
+ tzinfo = :tzinfo
+ rescue Exception
+ begin
+ require 'tzfile'
+ tzinfo = :tzfile
+ rescue Exception
+ tzinfo = nil
+ end
+ end
+
+ case tzinfo
+ when :tzinfo
+ zones_list.each{|list|
+ list.each{|zone|
+ begin
+ tz = TZInfo::Timezone.get(zone[%r<[^:]+$>])
+ rescue Exception
+ # ignore
+ else
+ zones << [tz, zone[%r<[^/:]+$>].tr('_', ' ')]
+ break
+ end
+ }
+ }
+
+ when :tzfile
+ zones_list.each{|list|
+ list.each{|zone|
+ begin
+ tz = TZFile.create(zone[%r<[^:]+$>])
+ rescue Exception
+ # ignore
+ else
+ zones << [tz, zone[%r<[^/:]+$>].tr('_', ' ')]
+ break
+ end
+ }
+ }
+
+ else
+ [ -7, -4, -2, -1, 0, +1, +3, +8, +9, +10 ].each{|zone|
+ zones << [zone, 'UTC%+03d00' % zone]
+ }
+ end
+end
+
+time = TkVariable.new_hash
+
+case tzinfo
+when :tcl
+ update_proc = proc{|now, tz, label|
+ time[label] = Tk.tk_call('clock', 'format', now.tv_sec,
+ '-timezone', tz, '-format', '%T')
+ }
+when :tzinfo
+ update_proc = proc{|now, tz, label|
+ time[label] = tz.utc_to_local(now).strftime('%H:%M:%S')
+ }
+when :tzfile
+ update_proc = proc{|now, tz, label|
+ time[label] = tz.at(now.tv_sec).strftime('%H:%M:%S')
+ }
+else
+ update_proc = proc{|now, tz, label|
+ time[label] = (now + (tz * 3600)).strftime('%H:%M:%S')
+ }
+end
+
+# Fill the clocks pane
+zones.each_with_index{|(zone, label), idx|
+ Ttk::Separator.new(left_bot).pack(:fill=>:x) if idx > 0
+ Ttk::Label.new(left_bot, :text=>label, :anchor=>'w').pack(:fill=>:x)
+ Ttk::Label.new(left_bot, :textvariable=>time.ref(label),
+ :anchor=>'w').pack(:fill=>:x)
+}
+
+# Timer start
+every = proc{
+ now = Time.now.utc
+ zones.each{|zone, label| update_proc.call(now, zone, label) }
+}
+TkRTTimer.new(1000, -1, every).start(0, every)
+
+# Fill the progress pane
+Ttk::Progressbar.new(right_top, :mode=>:indeterminate).pack(:fill=>:both, :expand=>true).start
+
+# Fill the text pane
+if Tk.windowingsystem != 'aqua'
+ # The trick with the ttk::frame makes the text widget look like it fits with
+ # the current Ttk theme despite not being a themed widget itself. It is done
+ # by styling the frame like an entry, turning off the border in the text
+ # widget, and putting the text widget in the frame with enough space to allow
+ # the surrounding border to show through (2 pixels seems to be enough).
+ f = Ttk::Frame.new(right_bot, :style=>Ttk::Entry)
+ txt = TkText.new(frame, :wrap=>:word, :width=>30, :borderwidth=>0)
+ txt.pack(:fill=>:both, :expand=>true, :in=>f, :pady=>2, :padx=>2)
+ scr = txt.yscrollbar(Ttk::Scrollbar.new(frame))
+ scr.pack(:side=>:right, :fill=>:y, :in=>right_bot)
+ f.pack(:fill=>:both, :expand=>true)
+ outer.pack(:fill=>:both, :expand=>true)
+else
+ txt = TkText.new(frame, :wrap=>:word, :width=>30, :borderwidth=>0)
+ scr = txt.yscrollbar(TkScrollbar.new(frame))
+ scr.pack(:side=>:right, :fill=>:y, :in=>right_bot)
+ txt.pack(:fill=>:both, :expand=>true, :in=>right_bot)
+ outer.pack(:fill=>:both, :expand=>true, :padx=>10, :pady=>[6, 10])
+end
diff --git a/ext/tk/sample/demos-jp/ttkprogress.rb b/ext/tk/sample/demos-jp/ttkprogress.rb
new file mode 100644
index 0000000000..43a9cbcd7e
--- /dev/null
+++ b/ext/tk/sample/demos-jp/ttkprogress.rb
@@ -0,0 +1,71 @@
+# -*- coding: euc-jp -*-
+#
+# ttkprogress.rb --
+#
+# This demonstration script creates several progress bar widgets.
+#
+# based on "Id: ttkprogress.tcl,v 1.3 2007/12/13 15:27:07 dgp Exp"
+
+if defined?($ttkprogress_demo) && $ttkprogress_demo
+ $ttkprogress_demo.destroy
+ $ttkprogress_demo = nil
+end
+
+$ttkprogress_demo = TkToplevel.new {|w|
+ title("Progress Bar Demonstration")
+ iconname("ttkprogress")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($ttkprogress_demo).pack(:fill=>:both, :expand=>true)
+
+Ttk::Label.new(base_frame, :font=>$font, :wraplength=>'4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top, :fill=>:x)
+²¼¤Ë¤¢¤ë¤Î¤ÏÆó¤Ä¤Î¥×¥í¥°¥ì¥¹¥Ð¡¼¤Ç¤¹¡¥\
+¾å¤Î¤â¤Î¤Ï"determinate"¥¿¥¤¥×¤Î¥×¥í¥°¥ì¥¹¥Ð¡¼¤Ç¡¤\
+Î㤨¤Ð¥×¥í¥°¥é¥à¤¬Í¿¤¨¤é¤ì¤¿¥¿¥¹¥¯¤ò½ªÎ»¤¹¤ë¤Þ¤Ç¤Ë¤É¤Î¤¯¤é¤¤¤«¤«¤ë¤«¤ò\
+¼¨¤¹¤È¤­¤Ê¤É¤ËÍѤ¤¤é¤ì¤Þ¤¹¡¥\
+²¼¤Î¤â¤Î¤Ï"indeterminate"¥¿¥¤¥×¤Î¥×¥í¥°¥ì¥¹¥Ð¡¼¤Ç¡¤\
+Î㤨¤Ð¥×¥í¥°¥é¥à¤¬¼Â¹ÔÃæ(busy)¤Ç¤¢¤ë¤â¤Î¤Î\
+½ªÎ»¤Þ¤Ç¤Ë¤É¤ì¤¯¤é¤¤¤«¤«¤ë¤«¤Ïʬ¤«¤é¤Ê¤¤¤È¤¤¤¦¾õÂÖ¤ò\
+¼¨¤¹¤È¤­¤Ê¤É¤ËÍѤ¤¤é¤ì¤Þ¤¹¡¥\
+¤¤¤º¤ì¤Î¥×¥í¥°¥ì¥¹¥Ð¡¼¤â¡¤¤¹¤°²¼¤Ë¤¢¤ë¥Ü¥¿¥ó¤ò»È¤¦¤³¤È¤Ç\
+¼«Æ°¥¢¥Ë¥á¡¼¥·¥ç¥ó¥â¡¼¥É¤ÎON/OFF¤òÀÚÂØ¤¨¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥
+EOL
+
+## See Code / Dismiss buttons
+Ttk::Frame.new(base_frame) {|frame|
+ sep = Ttk::Separator.new(frame)
+ Tk.grid(sep, :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ Ttk::Button.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'ttkprogress'}),
+ Ttk::Button.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ $ttkprogress_demo.destroy
+ $ttkprogress_demo = nil
+ }),
+ :padx=>4, :pady=>4)
+ grid_columnconfigure(0, :weight=>1)
+ pack(:side=>:bottom, :fill=>:x)
+}
+
+frame = Ttk::Frame.new(base_frame).pack(:fill=>:both, :expand=>true)
+
+p1 = Ttk::Progressbar.new(frame, :mode=>:determinate)
+p2 = Ttk::Progressbar.new(frame, :mode=>:indeterminate)
+
+start = Ttk::Button.new(frame, :text=>'Start Progress',
+ :command=>proc{ p1.start; p2.start })
+stop = Ttk::Button.new(frame, :text=>'Stop Progress',
+ :command=>proc{ p1.stop; p2.stop })
+
+Tk.grid(p1, '-', :pady=>5, :padx=>10)
+Tk.grid(p2, '-', :pady=>5, :padx=>10)
+Tk.grid(start, stop, :padx=>10, :pady=>5)
+start.grid_configure(:sticky=>'e')
+stop.grid_configure(:sticky=>'w')
+frame.grid_columnconfigure(:all, :weight=>1)
+
diff --git a/ext/tk/sample/demos-jp/twind.rb b/ext/tk/sample/demos-jp/twind.rb
index d35acd24d0..faefaefd6e 100644
--- a/ext/tk/sample/demos-jp/twind.rb
+++ b/ext/tk/sample/demos-jp/twind.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# text (embedded windows) widget demo (called by 'widget')
#
@@ -15,10 +16,13 @@ $twind_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($twind_demo).pack(:fill=>:both, :expand=>true)
+
# frame À¸À®
-$twind_buttons = TkFrame.new($twind_demo) {|frame|
+$twind_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc{
tmppath = $twind_demo
$twind_demo = nil
@@ -35,11 +39,11 @@ $twind_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame À¸À®
$twind_text = nil
-TkFrame.new($twind_demo, 'highlightthickness'=>2, 'borderwidth'=>2,
- 'relief'=>'sunken') {|f|
+TkFrame.new(base_frame, 'highlightthickness'=>2, 'borderwidth'=>2,
+ 'relief'=>'sunken') {|f|
$twind_text = TkText.new(f, 'setgrid'=>'true', 'font'=>$font,
- 'width'=>'70', 'height'=>35, 'wrap'=>'word',
- 'highlightthickness'=>0, 'borderwidth'=>0 ){|t|
+ 'width'=>'70', 'height'=>35, 'wrap'=>'word',
+ 'highlightthickness'=>0, 'borderwidth'=>0 ){|t|
TkScrollbar.new(f) {|s|
command proc{|*args| t.yview(*args)}
t.yscrollcommand proc{|first,last| s.set first,last}
@@ -49,60 +53,60 @@ TkFrame.new($twind_demo, 'highlightthickness'=>2, 'borderwidth'=>2,
# ¥¿¥°À¸À®
$tag_center = TkTextTag.new($twind_text,
- 'justify' =>'center',
- 'spacing1'=>'5m',
- 'spacing3'=>'5m' )
+ 'justify' =>'center',
+ 'spacing1'=>'5m',
+ 'spacing3'=>'5m' )
$tag_buttons = TkTextTag.new($twind_text,
- 'lmargin1'=>'1c',
- 'lmargin2'=>'1c',
- 'rmargin' =>'1c',
- 'spacing1'=>'3m',
- 'spacing2'=>0,
- 'spacing3'=>0 )
+ 'lmargin1'=>'1c',
+ 'lmargin2'=>'1c',
+ 'rmargin' =>'1c',
+ 'spacing1'=>'3m',
+ 'spacing2'=>0,
+ 'spacing3'=>0 )
# ¥Æ¥­¥¹¥È¤ÎÀ¸À®
$twind_text.insert('end',
- '¥Æ¥­¥¹¥Èwidget¾å¤Ë¾¤Îwidget¤òÁȤ߹þ¤à¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£')
+ '¥Æ¥­¥¹¥Èwidget¾å¤Ë¾¤Îwidget¤òÁȤ߹þ¤à¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£')
$twind_text.insert('end',
- 'ÁȤ߹þ¤ß¥¦¥£¥ó¥É¥¦¤È¸Æ¤Ð¤ì¡¢Ç¤°Õ¤Îwidget¤¬²Äǽ¤Ç¤¹¡£')
+ 'ÁȤ߹þ¤ß¥¦¥£¥ó¥É¥¦¤È¸Æ¤Ð¤ì¡¢Ç¤°Õ¤Îwidget¤¬²Äǽ¤Ç¤¹¡£')
$twind_text.insert('end',
- 'Î㤨¤Ð¡¢¤³¤³¤Ë2¤Ä¤Î¥Ü¥¿¥ówidget¤¬ÁȤ߹þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¡£')
+ 'Î㤨¤Ð¡¢¤³¤³¤Ë2¤Ä¤Î¥Ü¥¿¥ówidget¤¬ÁȤ߹þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¡£')
$twind_text.insert('end', 'ºÇ½é¤Î¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤È¿åÊ¿Êý¸þ¤Î¥¹¥¯¥í¡¼¥ë¤ò')
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- #text 'ON'
- text '¥ª¥ó'
- command proc{textWindOn $twind_text,$twind_buttons}
- cursor 'top_left_arrow'
- })
-$twind_text.insert('end', '¤Ë¤·¤Þ¤¹¡£¤Þ¤¿2¤Ä¤á¤Î¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È')
+ 'window'=>TkButton.new($twind_text) {
+ #text 'ON'
+ text '¥ª¥ó'
+ command proc{textWindOn $twind_text,$twind_buttons}
+ cursor 'top_left_arrow'
+ })
+$twind_text.insert('end', "¤Ë¤·¤Þ¤¹¡£¤Þ¤¿2¤Ä¤á¤Î¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È\n")
$twind_text.insert('end', '¿åÊ¿Êý¸þ¤Î¥¹¥¯¥í¡¼¥ë¤ò')
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- #text 'OFF'
- text '¥ª¥Õ'
- command proc{textWindOff $twind_text}
- cursor 'top_left_arrow'
- })
+ 'window'=>TkButton.new($twind_text) {
+ #text 'OFF'
+ text '¥ª¥Õ'
+ command proc{textWindOff $twind_text}
+ cursor 'top_left_arrow'
+ })
$twind_text.insert('end', '¤Ë¤·¤Þ¤¹¡£')
$twind_text.insert('end', '¤â¤¦¤Ò¤È¤Ä¤ÎÎã¤Ç¤¹¡£')
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- text '¤³¤³¤ò¥¯¥ê¥Ã¥¯'
- command proc{textWindPlot $twind_text}
- cursor 'top_left_arrow'
- })
+ 'window'=>TkButton.new($twind_text) {
+ text '¤³¤³¤ò¥¯¥ê¥Ã¥¯'
+ command proc{textWindPlot $twind_text}
+ cursor 'top_left_arrow'
+ })
$twind_text.insert('end', '¤¹¤ë¤È¡¢x-y¥×¥í¥Ã¥È¤¬¤³¤³¤Ë¸½¤ì¤Þ¤¹¡£')
$mark_plot = TkTextMark.new($twind_text, 'insert')
$mark_plot.gravity='left'
$twind_text.insert('end', '¥Þ¥¦¥¹¤Ç¥Ç¡¼¥¿¤òÉÁ²è¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£')
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- text '¾Ãµî'
- command proc{textWindDel $twind_text}
- cursor 'top_left_arrow'
- })
+ 'window'=>TkButton.new($twind_text) {
+ text '¾Ãµî'
+ command proc{textWindDel $twind_text}
+ cursor 'top_left_arrow'
+ })
$twind_text.insert('end', '¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¸µ¤ËÌá¤ê¤Þ¤¹¡£
')
@@ -122,27 +126,27 @@ $twind_text.insert('end', '¤â¤¦°ìÅÙÆ±¤¸¥Ü¥¿¥ó¤ò²¡¤¹¤È¸µ¤ËÌá¤ê¤Þ¤¹¡£
')
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {|b|
- text '¥Ç¥Õ¥©¥ë¥È'
- command proc{embDefBg $twind_text}
- cursor 'top_left_arrow'
- $tag_buttons.add('end')
- },
- 'padx'=>3 )
+ 'window'=>TkButton.new($twind_text) {|b|
+ text '¥Ç¥Õ¥©¥ë¥È'
+ command proc{embDefBg $twind_text}
+ cursor 'top_left_arrow'
+ $tag_buttons.add('end')
+ },
+ 'padx'=>3 )
embToggle = TkVariable.new('Short')
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkCheckButton.new($twind_text) {
- textvariable embToggle
- indicatoron 0
- variable embToggle
- onvalue 'A much longer string'
- offvalue 'Short'
- cursor 'top_left_arrow'
- pady 5
- padx 2
- },
- 'padx'=>3,
- 'pady'=>2 )
+ 'window'=>TkCheckButton.new($twind_text) {
+ textvariable embToggle
+ indicatoron 0
+ variable embToggle
+ onvalue 'A much longer string'
+ offvalue 'Short'
+ cursor 'top_left_arrow'
+ pady 5
+ padx 2
+ },
+ 'padx'=>3,
+ 'pady'=>2 )
[ 'AntiqueWhite3', 'Bisque1', 'Bisque2', 'Bisque3', 'Bisque4',
'SlateBlue3', 'RoyalBlue1', 'SteelBlue2', 'DeepSkyBlue3', 'LightBlue1',
@@ -150,13 +154,13 @@ TkTextWindow.new($twind_text, 'end',
'Yellow1', 'IndianRed1', 'IndianRed2', 'Tan1', 'Tan4'
].each{|twind_color|
TkTextWindow.new($twind_text, 'end',
- 'window'=>TkButton.new($twind_text) {
- text twind_color
- cursor 'top_left_arrow'
- command proc{$twind_text.bg twind_color}
- },
- 'padx'=>3,
- 'pady'=>2 )
+ 'window'=>TkButton.new($twind_text) {
+ text twind_color
+ cursor 'top_left_arrow'
+ command proc{$twind_text.bg twind_color}
+ },
+ 'padx'=>3,
+ 'pady'=>2 )
}
# ¥á¥½¥Ã¥ÉÄêµÁ
@@ -205,44 +209,48 @@ def textWindPlot (t)
cursor 'top_left_arrow'
}
- font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ else
+ font = 'Helvetica 18'
+ end
TkcLine.new($twind_plot, 100, 250, 400, 250, 'width'=>2)
TkcLine.new($twind_plot, 100, 250, 100, 50, 'width'=>2)
TkcText.new($twind_plot, 225, 20,
- 'text'=>"A Simple Plot", 'font'=>font, 'fill'=>'brown')
+ 'text'=>"A Simple Plot", 'font'=>font, 'fill'=>'brown')
(0..10).each {|i|
x = 100 + (i * 30)
TkcLine.new($twind_plot, x, 250, x, 245, 'width'=>2)
TkcText.new($twind_plot, x, 254,
- 'text'=>10*i, 'font'=>font, 'anchor'=>'n')
+ 'text'=>10*i, 'font'=>font, 'anchor'=>'n')
}
(0..5).each {|i|
y = 250 - (i * 40)
TkcLine.new($twind_plot, 100, y, 105, y, 'width'=>2)
TkcText.new($twind_plot, 96, y,
- 'text'=>"#{i*50}.0", 'font'=>font, 'anchor'=>'e')
+ 'text'=>"#{i*50}.0", 'font'=>font, 'anchor'=>'e')
}
for xx, yy in [[12,56],[20,94],[33,98],[32,120],[61,180],[75,160],[98,223]]
x = 100 + (3*xx)
y = 250 - (4*yy)/5
item = TkcOval.new($twind_plot, x-6, y-6, x+6, y+6,
- 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
+ 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
item.addtag 'point'
end
$twind_plot.itembind('point', 'Any-Enter',
- proc{$twind_plot.itemconfigure 'current', 'fill', 'red'})
+ proc{$twind_plot.itemconfigure 'current', 'fill', 'red'})
$twind_plot.itembind('point', 'Any-Leave',
- proc{$twind_plot.itemconfigure 'current', 'fill', 'SkyBlue2'})
+ proc{$twind_plot.itemconfigure 'current', 'fill', 'SkyBlue2'})
$twind_plot.itembind('point', '1',
- proc{|x,y| embPlotDown $twind_plot,x,y}, "%x %y")
+ proc{|x,y| embPlotDown $twind_plot,x,y}, "%x %y")
$twind_plot.itembind('point', 'ButtonRelease-1',
- proc{$twind_plot.dtag 'selected'})
+ proc{$twind_plot.dtag 'selected'})
$twind_plot.bind('B1-Motion',
- proc{|x,y| embPlotMove $twind_plot,x,y}, "%x %y")
+ proc{|x,y| embPlotMove $twind_plot,x,y}, "%x %y")
while ($twind_text.get($mark_plot) =~ /[ \t\n]/)
$twind_text.delete $mark_plot
end
diff --git a/ext/tk/sample/demos-jp/twind2.rb b/ext/tk/sample/demos-jp/twind2.rb
new file mode 100644
index 0000000000..2a26b28ef6
--- /dev/null
+++ b/ext/tk/sample/demos-jp/twind2.rb
@@ -0,0 +1,384 @@
+# -*- coding: euc-jp -*-
+#
+# text (embedded windows) widget demo 2 (called by 'widget')
+#
+
+# toplevel widget ¤¬Â¸ºß¤¹¤ì¤Ðºï½ü¤¹¤ë
+if defined?($twind2_demo) && $twind2_demo
+ $twind2_demo.destroy
+ $twind2_demo = nil
+end
+
+# demo ÍѤΠtoplevel widget ¤òÀ¸À®
+$twind2_demo = TkToplevel.new {|w|
+ title("Text Demonstration - Embedded Windows 2")
+ iconname("Embedded Windows")
+ positionWindow(w)
+}
+
+base_frame = TkFrame.new($twind2_demo).pack(:fill=>:both, :expand=>true)
+
+# frame À¸À®
+$twind2_buttons = TkFrame.new(base_frame) {|frame|
+ TkGrid(TkFrame.new(frame, :height=>2, :relief=>:sunken, :bd=>2),
+ :columnspan=>4, :row=>0, :sticky=>'ew', :pady=>2)
+ TkGrid('x',
+ TkButton.new(frame, :text=>'¥³¡¼¥É»²¾È',
+ :image=>$image['view'], :compound=>:left,
+ :command=>proc{showCode 'twind2'}),
+ TkButton.new(frame, :text=>'ÊĤ¸¤ë',
+ :image=>$image['delete'], :compound=>:left,
+ :command=>proc{
+ tmppath = $twind2_demo
+ $twind2_demo = nil
+ $showVarsWin[tmppath.path] = nil
+ tmppath.destroy
+ }),
+ :padx=>4, :pady=>4)
+ frame.grid_columnconfigure(0, :weight=>1)
+}
+$twind2_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
+# frame À¸À®
+$twind2_text = nil
+TkFrame.new(base_frame, 'highlightthickness'=>2, 'borderwidth'=>2,
+ 'relief'=>'sunken') {|f|
+ $twind2_text = TkText.new(f, 'setgrid'=>true, 'font'=>$font,
+ # 'width'=>'70', 'height'=>35, 'wrap'=>'word',
+ 'width'=>'70', 'height'=>35, 'wrap'=>'char',
+ 'highlightthickness'=>0, 'borderwidth'=>0 ){|t|
+ TkScrollbar.new(f) {|s|
+ command proc{|*args| t.yview(*args)}
+ t.yscrollcommand proc{|first,last| s.set first,last}
+ }.pack('side'=>'right', 'fill'=>'y')
+ }.pack('expand'=>'yes', 'fill'=>'both')
+}.pack('expand'=>'yes', 'fill'=>'both')
+
+# ¥¿¥°À¸À®
+$tag2_center = TkTextTag.new($twind2_text,
+ 'justify' =>'center',
+ 'spacing1'=>'5m',
+ 'spacing3'=>'5m' )
+$tag2_buttons = TkTextTag.new($twind2_text,
+ 'lmargin1'=>'1c',
+ 'lmargin2'=>'1c',
+ 'rmargin' =>'1c',
+ 'spacing1'=>'3m',
+ 'spacing2'=>0,
+ 'spacing3'=>0 )
+
+# ¥Æ¥­¥¹¥È¤ÎÀ¸À®
+$twind2_text.insert('end', '¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤Ë¤Ï¿§¡¹¤Ê¼ïÎà¤Î¥¢¥¤¥Æ¥à')
+$twind2_text.insert('end', '¡ÊưŪ¤Ê¤â¤Î¤äÀÅŪ¤Ê¤â¤Î¤ÎξÊý¤¬¤¢¤ê¤Þ¤¹¡Ë¤ò')
+$twind2_text.insert('end', '¿ô¿¤¯´Þ¤á¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤½¤¦¤·¤¿¥¢¥¤¥Æ¥à¤Ï')
+$twind2_text.insert('end', '¹ÔÂØ¤¨¡¢¥¿¥Ö¡¢Ãæ±û·¤¨¤Ê¤É¤ÎÍÍ¡¹¤ÊÊýË¡¤Ç')
+$twind2_text.insert('end', 'ÇÛÃÖ¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£')
+$twind2_text.insert('end', '²Ã¤¨¤Æ¡¢¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤ÎÆâÍÆÊª¤¬')
+$twind2_text.insert('end', '¥¦¥£¥ó¥É¥¦¥µ¥¤¥º¤ËÈæ¤Ù¤ÆÂ礭¤¹¤®¤ë¾ì¹ç¤Ç¤â')
+$twind2_text.insert('end', '¤¹¤Ù¤Æ¤ÎÊý¸þ¤Ë¥¹¥à¡¼¥º¤Ë¥¹¥¯¥í¡¼¥ë¤µ¤»¤Æ')
+$twind2_text.insert('end', '³Îǧ¤¹¤ë¤³¤È¤¬²Äǽ¤Ç¤¹¡£')
+$twind2_text.insert('end', "\n\n")
+$twind2_text.insert('end', '¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¾å¤Ë¤Ï¾¤Î¥¦¥£¥¸¥§¥Ã¥È¤ò')
+$twind2_text.insert('end', '´Þ¤á¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡£¤³¤¦¤·¤¿¤â¤Î¤Ï')
+$twind2_text.insert('end', '¡ÖËä¤á¹þ¤ß¥¦¥£¥ó¥É¥¦¡×¤È¸Æ¤Ð¤ì¡¢¤½¤ÎÃæ¤Ë')
+$twind2_text.insert('end', '¤¤¤«¤Ê¤ë¥¦¥£¥¸¥§¥Ã¥È¤Ç¤âµÍ¤á¹þ¤à¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£')
+$twind2_text.insert('end', 'Î㤨¤Ð¡¤¤³¤³¤Ë¤Ï£²¤Ä¤Î')
+$twind2_text.insert('end', '¥Ü¥¿¥ó¥¦¥£¥¸¥§¥Ã¥È¤¬Ëä¤á¹þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¡£')
+$twind2_text.insert('end', 'ºÇ½é¤Î¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢')
+$twind2_text.insert('end', '¿åÊ¿Êý¸þ¤Î¥¹¥¯¥í¡¼¥ë¤ò ')
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ #text 'ON'
+ text '¥ª¥ó'
+ command proc{textWindOn2 $twind2_text,$twind2_buttons}
+ cursor 'top_left_arrow'
+ })
+$twind2_text.insert('end', "¤Ë¤·¤Þ¤¹¡£¤Þ¤¿¡¢£²¤Ä¤á¤Î¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È\n")
+$twind2_text.insert('end', '¿åÊ¿Êý¸þ¤Î¥¹¥¯¥í¡¼¥ë¤ò')
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ #text 'OFF'
+ text '¥ª¥Õ'
+ command proc{textWindOff2 $twind2_text}
+ cursor 'top_left_arrow'
+ })
+$twind2_text.insert('end', "¤Ë¤·¤Þ¤¹¡£\n\n")
+
+$twind2_text.insert('end', '¼¡¤Ï¤â¤¦¤Ò¤È¤Ä¤ÎÎã¤Ç¤¹¡£')
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ text '¤³¤³¤ò¥¯¥ê¥Ã¥¯'
+ command proc{textWindPlot2 $twind2_text}
+ cursor 'top_left_arrow'
+ })
+$twind2_text.insert('end', '¤¹¤ë¤È¡¢x-y¥×¥í¥Ã¥È¤¬¤³¤³¤Ë¸½¤ì¤Þ¤¹¡£')
+$mark2_plot = TkTextMark.new($twind2_text, 'insert')
+$mark2_plot.gravity='left'
+$twind2_text.insert('end', '¥Þ¥¦¥¹¤Ç¥É¥é¥Ã¥°¤¹¤ë¤³¤È¤Ç¡¢')
+$twind2_text.insert('end', '¥×¥í¥Ã¥È¾å¤Î¥Ç¡¼¥¿ÅÀ¤ò°Üư¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£')
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ text '¾Ãµî'
+ command proc{textWindDel2 $twind2_text}
+ cursor 'top_left_arrow'
+ })
+$twind2_text.insert('end', '¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¸µ¤ËÌá¤ê¤Þ¤¹¡£')
+$twind2_text.insert('end', "\n\n")
+
+$twind2_text.insert('end', 'ɽ¼¨¤¹¤ë¥Æ¥­¥¹¥È¤Ê¤·¤ËËä¤á¹þ¤ß¥¦¥£¥ó¥É¥¦¤À¤±¤ò')
+$twind2_text.insert('end', '¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤Ë´Þ¤á¤ë¤³¤È¤âÍ­ÍѤǤ·¤ç¤¦¡£')
+$twind2_text.insert('end', '¤³¤Î¾ì¹ç¡¢¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤Ï')
+$twind2_text.insert('end', '¥¸¥ª¥á¥È¥ê¥Þ¥Í¡¼¥¸¥ã¤Î¤è¤¦¤ËƯ¤­¤Þ¤¹¡£')
+$twind2_text.insert('end', 'Î㤨¤Ð¡¢¤³¤³¤Ë¤Ï¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤Ë')
+$twind2_text.insert('end', '¤è¤Ã¤Æ¥Ü¥¿¥ó¤¬¤­¤ì¤¤¤ËÀ°Îó¤·¤ÆÇÛÃÖ¤µ¤ì¤Æ¤¤¤Þ¤¹¡£')
+$twind2_text.insert('end', '¤³¤ì¤é¤Î¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤³¤È¤Ç¡¢')
+$twind2_text.insert('end', '¤³¤Î¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤ÎÇØ·Ê¿§¤ò')
+$twind2_text.insert('end', 'ÊѤ¨¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹("¥Ç¥Õ¥©¥ë¥È"¥Ü¥¿¥ó¤Ç')
+$twind2_text.insert('end', '¸µ¤Î¿§¤ËÌ᤹¤³¤È¤¬¤Ç¤­¤Þ¤¹)¡£')
+$twind2_text.insert('end', '"Short"¤È¤¤¤¦¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤Èʸ»úÎó¤ÎŤµ¤¬')
+$twind2_text.insert('end', 'ÊѤï¤ê¡¢¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤¬¼«Æ°Åª¤Ë')
+$twind2_text.insert('end', '¥ì¥¤¥¢¥¦¥È¤òÀ°¤¨¤ëÍͻҤò¸«¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£')
+$twind2_text.insert('end', '¤â¤¦°ìÅÙÆ±¤¸¥Ü¥¿¥ó¤ò²¡¤¹¤È¸µ¤ËÌá¤ê¤Þ¤¹¡£')
+$twind2_text.insert('end', "\n")
+
+btn_default = TkButton.new($twind2_text) {|b|
+ text '¥Ç¥Õ¥©¥ë¥È'
+ command proc{embDefBg2 $twind2_text}
+ cursor 'top_left_arrow'
+}
+TkTextWindow.new($twind2_text, 'end', 'window'=>btn_default, 'padx'=>3)
+embToggle = TkVariable.new('Short')
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkCheckButton.new($twind2_text) {
+ textvariable embToggle
+ indicatoron 0
+ variable embToggle
+ onvalue 'A much longer string'
+ offvalue 'Short'
+ cursor 'top_left_arrow'
+ pady 5
+ padx 2
+ },
+ 'padx'=>3,
+ 'pady'=>2 )
+
+[ 'AntiqueWhite3', 'Bisque1', 'Bisque2', 'Bisque3', 'Bisque4',
+ 'SlateBlue3', 'RoyalBlue1', 'SteelBlue2', 'DeepSkyBlue3', 'LightBlue1',
+ 'DarkSlateGray1', 'Aquamarine2', 'DarkSeaGreen2', 'SeaGreen1',
+ 'Yellow1', 'IndianRed1', 'IndianRed2', 'Tan1', 'Tan4'
+].each{|twind_color|
+ TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text) {
+ text twind_color
+ cursor 'top_left_arrow'
+ command proc{$twind2_text.bg twind_color}
+ },
+ 'padx'=>3,
+ 'pady'=>2 )
+}
+
+$tag2_buttons.add(btn_default, 'end')
+
+$text_normal2 = {}
+$text_normal2['border'] = $twind2_text.cget('borderwidth')
+$text_normal2['highlight'] = $twind2_text.cget('highlightthickness')
+$text_normal2['pad'] = $twind2_text.cget('padx')
+
+$twind2_text.insert('end', "\nborder width ¤ä highlightthickness, ")
+$twind2_text.insert('end', "padding ¤òÄ̾ï¤ÎÃͤ«¤éÊѹ¹¤¹¤ë¤³¤È¤â²Äǽ¤Ç¤¹¡£\n")
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Big borders",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinBigB2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Small borders",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinSmallB2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Big highlight",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinBigH2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Small highlight",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinSmallH2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Big pad",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinBigP2 $twind2_text
+ }))
+
+TkTextWindow.new($twind2_text, 'end',
+ 'window'=>TkButton.new($twind2_text, :text=>"Small pad",
+ :cursor=>'top_left_arrow',
+ 'command'=>proc{
+ textWinSmallP2 $twind2_text
+ }))
+
+$twind2_text.insert('end', "\n\n¹¹¤Ë¥¤¥á¡¼¥¸¤â¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤Ë")
+$twind2_text.insert('end', "¤¦¤Þ¤¯ÇÛÃ֤Ǥ­¤Þ¤¹¡§")
+
+TkTextImage.new($twind2_text, 'end',
+ 'image'=>TkBitmapImage.new(:file=>[
+ $demo_dir, '..',
+ 'images', 'face.xbm'
+ ].join(File::Separator)))
+
+# ¥á¥½¥Ã¥ÉÄêµÁ
+def textWinBigB2(w)
+ w.borderwidth 15
+end
+def textWinSmallB2(w)
+ w.borderwidth $text_normal2['border']
+end
+def textWinBigH2(w)
+ w.highlightthickness 15
+end
+def textWinSmallH2(w)
+ w.highlightthickness $text_normal2['highlight']
+end
+def textWinBigP2(w)
+ w.configure(:padx=>15, :pady=>15)
+end
+def textWinSmallP2(w)
+ w.configure(:padx=>$text_normal2['pad'], :pady=>$text_normal2['pad'])
+end
+
+def textWindOn2 (w,f)
+ if defined? $twind2_scroll
+ begin
+ $twind2_scroll.destroy
+ rescue
+ end
+ $twind2_scroll = nil
+ end
+
+ base = TkWinfo.parent( TkWinfo.parent(w) )
+ $twind2_scroll = TkScrollbar.new(base) {|s|
+ orient 'horizontal'
+ command proc{|*args| w.xview(*args)}
+ w.xscrollcommand proc{|first,last| s.set first,last}
+ w.wrap 'none'
+ pack('after'=>f, 'side'=>'bottom', 'fill'=>'x')
+ }
+
+ return nil
+end
+
+def textWindOff2 (w)
+ if defined? $twind2_scroll
+ begin
+ $twind2_scroll.destroy
+ rescue
+ end
+ $twind2_scroll = nil
+ end
+ w.xscrollcommand ''
+ #w.wrap 'word'
+ w.wrap 'char'
+end
+
+def textWindPlot2 (t)
+ if (defined? $twind2_plot) && (TkWinfo.exist?($twind2_plot))
+ return
+ end
+
+ $twind2_plot = TkCanvas.new(t) {
+ relief 'sunken'
+ width 450
+ height 300
+ cursor 'top_left_arrow'
+ }
+
+ #font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ font = 'Helvetica 18'
+
+ TkcLine.new($twind2_plot, 100, 250, 400, 250, 'width'=>2)
+ TkcLine.new($twind2_plot, 100, 250, 100, 50, 'width'=>2)
+ TkcText.new($twind2_plot, 225, 20,
+ 'text'=>"A Simple Plot", 'font'=>font, 'fill'=>'brown')
+
+ (0..10).each {|i|
+ x = 100 + (i * 30)
+ TkcLine.new($twind2_plot, x, 250, x, 245, 'width'=>2)
+ TkcText.new($twind2_plot, x, 254,
+ 'text'=>10*i, 'font'=>font, 'anchor'=>'n')
+ }
+ (0..5).each {|i|
+ y = 250 - (i * 40)
+ TkcLine.new($twind2_plot, 100, y, 105, y, 'width'=>2)
+ TkcText.new($twind2_plot, 96, y,
+ 'text'=>"#{i*50}.0", 'font'=>font, 'anchor'=>'e')
+ }
+
+ for xx, yy in [[12,56],[20,94],[33,98],[32,120],[61,180],[75,160],[98,223]]
+ x = 100 + (3*xx)
+ y = 250 - (4*yy)/5
+ item = TkcOval.new($twind2_plot, x-6, y-6, x+6, y+6,
+ 'width'=>1, 'outline'=>'black', 'fill'=>'SkyBlue2')
+ item.addtag 'point'
+ end
+
+ $twind2_plot.itembind('point', 'Any-Enter',
+ proc{$twind2_plot.itemconfigure 'current', 'fill', 'red'})
+ $twind2_plot.itembind('point', 'Any-Leave',
+ proc{$twind2_plot.itemconfigure 'current', 'fill', 'SkyBlue2'})
+ $twind2_plot.itembind('point', '1',
+ proc{|x,y| embPlotDown2 $twind2_plot,x,y}, "%x %y")
+ $twind2_plot.itembind('point', 'ButtonRelease-1',
+ proc{$twind2_plot.dtag 'selected'})
+ $twind2_plot.bind('B1-Motion',
+ proc{|x,y| embPlotMove2 $twind2_plot,x,y}, "%x %y")
+ while ($twind2_text.get($mark2_plot) =~ /[ \t\n]/)
+ $twind2_text.delete $mark2_plot
+ end
+ $twind2_text.insert $mark2_plot,"\n"
+ TkTextWindow.new($twind2_text, $mark2_plot, 'window'=>$twind2_plot)
+ $tag2_center.add $mark2_plot
+ $twind2_text.insert $mark2_plot,"\n"
+end
+
+$embPlot2 = {'lastX'=>0, 'lastY'=>0}
+
+def embPlotDown2 (w, x, y)
+ w.dtag 'selected'
+ w.addtag_withtag 'selected', 'current'
+ w.raise 'current'
+ $embPlot2['lastX'] = x
+ $embPlot2['lastY'] = y
+end
+
+def embPlotMove2 (w, x, y)
+ w.move 'selected', x - $embPlot2['lastX'], y - $embPlot2['lastY']
+ $embPlot2['lastX'] = x
+ $embPlot2['lastY'] = y
+end
+
+def textWindDel2 (w)
+ if (defined? $twind2_text) && TkWinfo.exist?($twind2_plot)
+ $twind2_text.delete $twind2_plot
+ $twind2_plot = nil
+ while ($twind2_text.get($mark2_plot) =~ /[ \t\n]/)
+ $twind2_text.delete $mark2_plot
+ end
+ $twind2_text.insert $mark2_plot," "
+ end
+end
+
+def embDefBg2 (w)
+ w['background'] = w.configinfo('background')[3]
+end
diff --git a/ext/tk/sample/demos-jp/unicodeout.rb b/ext/tk/sample/demos-jp/unicodeout.rb
index d408a36aae..178077ec08 100644
--- a/ext/tk/sample/demos-jp/unicodeout.rb
+++ b/ext/tk/sample/demos-jp/unicodeout.rb
@@ -1,3 +1,5 @@
+# -*- coding: euc-jp -*-
+#
# unicodeout.rb --
#
# This demonstration script shows how you can produce output (in label
@@ -16,9 +18,11 @@ $unicodeout_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($unicodeout_demo,
- :font=>$font, :wraplength=>'5.4i', :justify=>:left,
- :text=><<EOL).pack(:side=>:top)
+base_frame = TkFrame.new($unicodeout_demo).pack(:fill=>:both, :expand=>true)
+
+TkLabel.new(base_frame,
+ :font=>$font, :wraplength=>'5.4i', :justify=>:left,
+ :text=><<EOL).pack(:side=>:top)
¤³¤ì¤Ï¡¤Tk¤Ë¤ª¤±¤ëÈó²¤ÊÆÊ¸»ú½¸¹ç¤òÍѤ¤¤ë¸À¸ì¤ËÂФ¹¤ë¥µ¥Ý¡¼¥È¤Ë¤Ä¤¤¤Æ¤Î\
¥µ¥ó¥×¥ë¤Ç¤¹¡¥¤¿¤À¤·¡¤²¼¤Îɽ¼¨¤Ë¤ª¤¤¤Æ¤¢¤Ê¤¿¤¬¼ÂºÝ¤Ë¤É¤Î¤è¤¦¤Êɽ¼¨¤ò\
Ìܤˤ¹¤ë¤«¤Ï¡¤¤¢¤Ê¤¿¤Î´Ä¶­¤Ë¤É¤Î¤è¤¦¤Êʸ»ú½¸¹ç¤¬¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤ë¤«¤Ë\
@@ -38,23 +42,23 @@ Tcl¤Î¥¨¥¹¥±¡¼¥×ɽ¸½¤òÍѤ¤¤¿UNICODEʸ»úÎó¤Ç½ñ¤«¤ì¤Æ¤¤¤Þ¤¹¡¥\
EOL
#'
-TkFrame.new($unicodeout_demo){|f|
+TkFrame.new(base_frame){|f|
pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
- TkButton.new(f, :text=>'λ²ò', :width=>15, :command=>proc{
- $unicodeout_demo.destroy
- $unicodeout_demo = nil
- }).pack(:side=>:left, :expand=>true)
+ TkButton.new(f, :text=>'ÊĤ¸¤ë', :width=>15, :command=>proc{
+ $unicodeout_demo.destroy
+ $unicodeout_demo = nil
+ }).pack(:side=>:left, :expand=>true)
TkButton.new(f, :text=>'¥³¡¼¥É»²¾È', :width=>15, :command=>proc{
- showCode 'unicodeout'
- }).pack(:side=>:left, :expand=>true)
+ showCode 'unicodeout'
+ }).pack(:side=>:left, :expand=>true)
}
-wait_msg = TkLabel.new($unicodeout_demo,
- :text=>"¥Õ¥©¥ó¥ÈÆÉ¤ß¹þ¤ß¤Î´°Î»¤Þ¤Ç" +
- "¤·¤Ð¤é¤¯¤ªÂÔ¤Á²¼¤µ¤¤¡¥¡¥¡¥",
- :font=>"Helvetica 12 italic").pack
+wait_msg = TkLabel.new(base_frame,
+ :text=>"¥Õ¥©¥ó¥ÈÆÉ¤ß¹þ¤ß¤Î´°Î»¤Þ¤Ç" +
+ "¤·¤Ð¤é¤¯¤ªÂÔ¤Á²¼¤µ¤¤¡¥¡¥¡¥",
+ :font=>"Helvetica 12 italic").pack
class Unicodeout_SampleFrame < TkFrame
@@font = $font
@@ -66,23 +70,23 @@ class Unicodeout_SampleFrame < TkFrame
# @@font = 'Newspaper 12'
# @@font = '{New century schoolbook} 12'
- def initialize()
- super($unicodeout_demo)
+ def initialize(base)
+ super(base)
grid_columnconfig(1, :weight=>1)
end
def add_sample(lang, *args)
sample_txt = Tk::UTF8_String(args.join(''))
l = TkLabel.new(self, :font=>@@font, :text=>lang+':',
- :anchor=>:nw, :pady=>0)
+ :anchor=>:nw, :pady=>0)
#s = TkLabel.new(self, :font=>@@font, :text=>sample_txt,
s = TkLabel.new(self, :font=>TkFont.new(@@font), :text=>sample_txt,
- :anchor=>:nw, :width=>30, :pady=>0)
+ :anchor=>:nw, :width=>30, :pady=>0)
Tk.grid(l, s, :sticky=>:ew, :pady=>0)
l.grid_config(:padx, '1m')
end
end
-f = Unicodeout_SampleFrame.new
+f = Unicodeout_SampleFrame.new(base_frame)
f.pack(:expand=>true, :fill=>:both, :padx=>'2m', :pady=>'1m')
# Processing when some characters are missing might take a while, so make
@@ -93,23 +97,23 @@ $unicodeout_demo.cursor('watch')
Tk.update
f.add_sample('Arabic',
- '\uFE94\uFEF4\uFE91\uFEAE\uFECC\uFEDF\uFE8D\uFE94',
- '\uFEE4\uFEE0\uFEDC\uFEDF\uFE8D')
+ '\uFE94\uFEF4\uFE91\uFEAE\uFECC\uFEDF\uFE8D\uFE94',
+ '\uFEE4\uFEE0\uFEDC\uFEDF\uFE8D')
f.add_sample('Trad. Chinese', '\u4E2D\u570B\u7684\u6F22\u5B57')
f.add_sample('Simpl. Chinese', '\u6C49\u8BED')
f.add_sample('Greek',
- '\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE ',
- '\u03B3\u03BB\u03CE\u03C3\u03C3\u03B1')
+ '\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE ',
+ '\u03B3\u03BB\u03CE\u03C3\u03C3\u03B1')
f.add_sample('Hebrew',
- '\u05DD\u05D9\u05DC\u05E9\u05D5\u05E8\u05D9 ',
- '\u05DC\u05D9\u05D0\u05E8\u05E9\u05D9')
+ '\u05DD\u05D9\u05DC\u05E9\u05D5\u05E8\u05D9 ',
+ '\u05DC\u05D9\u05D0\u05E8\u05E9\u05D9')
f.add_sample('Japanese',
- '\u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A, ',
- '\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA')
+ '\u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A, ',
+ '\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA')
f.add_sample('Korean', '\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00')
f.add_sample('Russian',
- '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 ',
- '\u044F\u0437\u044B\u043A')
+ '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 ',
+ '\u044F\u0437\u044B\u043A')
wait_msg.destroy
$unicodeout_demo.cursor(oldCursor)
diff --git a/ext/tk/sample/demos-jp/vscale.rb b/ext/tk/sample/demos-jp/vscale.rb
index 4cb8e0f6b7..a1097fd77f 100644
--- a/ext/tk/sample/demos-jp/vscale.rb
+++ b/ext/tk/sample/demos-jp/vscale.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
require "tkcanvas"
if defined?($vscale_demo) && $vscale_demo
@@ -11,7 +12,9 @@ $vscale_demo = TkToplevel.new {|w|
}
positionWindow($vscale_demo)
-msg = TkLabel.new($vscale_demo) {
+base_frame = TkFrame.new($vscale_demo).pack(:fill=>:both, :expand=>true)
+
+msg = TkLabel.new(base_frame) {
font $font
wraplength '3.5i'
justify 'left'
@@ -22,9 +25,10 @@ msg = TkLabel.new($vscale_demo) {
}
msg.pack('side'=>'top', 'padx'=>'.5c')
-TkFrame.new($vscale_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
- text 'λ²ò'
+ #text 'λ²ò'
+ text 'ÊĤ¸¤ë'
command proc {
tmppath = $vscale_demo
$vscale_demo = nil
@@ -38,7 +42,17 @@ TkFrame.new($vscale_demo) {|frame|
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
-TkFrame.new($vscale_demo) {|frame|
+def setHeight(w, height)
+ height = height + 21
+ y2 = height - 30
+ if y2 < 21
+ y2 = 21
+ end
+ w.coords 'poly',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
+ w.coords 'line',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
+end
+
+TkFrame.new(base_frame) {|frame|
borderwidth 10
canvas = TkCanvas.new(frame) {|c|
width 50
@@ -64,14 +78,3 @@ TkFrame.new($vscale_demo) {|frame|
}.pack('side'=>'left', 'anchor'=>'ne')
scale.set 75
}.pack
-
-
-def setHeight(w, height)
- height = height + 21
- y2 = height - 30
- if y2 < 21
- y2 = 21
- end
- w.coords 'poly',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
- w.coords 'line',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
-end
diff --git a/ext/tk/sample/demos-jp/widget b/ext/tk/sample/demos-jp/widget
index 696a9073cc..8eb699e513 100644
--- a/ext/tk/sample/demos-jp/widget
+++ b/ext/tk/sample/demos-jp/widget
@@ -1,62 +1,144 @@
#!/usr/bin/env ruby
+# -*- coding: euc-jp -*-
+
+# ´Á»ú¥³¡¼¥ÉÀßÄê ( tk.rb ¤Î¥í¡¼¥É»þ¤Î encoding ¿äÄê/ÀßÄê¤Ë»È¤ï¤ì¤ë )
+if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!!!!!
+ $KCODE = 'euc'
+else
+ DEFAULT_TK_ENCODING = 'EUC-JP'
+end
# tk ´Ø·¸¥é¥¤¥Ö¥é¥ê¤ÎÆÉ¤ß¹þ¤ß
require 'tk'
-require 'tkafter'
+# require 'tkafter'
+
+$RubyTk_WidgetDemo = true
# widget demo directory °ÌÃÖ¤Î³ÍÆÀ
-$demo_dir = File.dirname($0)
+# $demo_dir = File.dirname($0)
+$demo_dir = File.dirname(__FILE__)
# root ¤ÎÀ¸À®
-$root = TkRoot.new{title "Widget Demonstration"}
+$root = TkRoot.new{title "Ruby/Tk Widget Demonstration"}
# tk ¥Ð¡¼¥¸¥ç¥ó¤Î¼èÆÀ
$tk_version = Tk::TK_VERSION
+$tk_major_ver, $tk_minor_ver = $tk_version.split('.').map{|n| n.to_i}
+$tk_patchlevel = Tk::TK_PATCHLEVEL
# tcl_platform ¾ðÊó¤Ø¤Î¥¢¥¯¥»¥¹¥ª¥Ö¥¸¥§¥¯¥È
$tk_platform = TkVarAccess.new('tcl_platform')
# ¥Õ¥©¥ó¥ÈÀßÄê
-$font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*', nil)
-knjfont = '-*-r-*--16-*-jisx0208.1983-0'
-$kanji_font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*',
- knjfont)
-TkOption.add('*kanjiFont', knjfont, 'startupFile')
-$msg_kanji_font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*',
- '-*-r-*--24-*-jisx0208.1983-0')
#######
-#case($tk_version)
-#when /^4.*/
-# $font = '-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*'
-# $kanji_font = '-*--16-*-jisx0208.1983-0'
-# $msg_kanji_font = '-*--24-*-jisx0208.1983-0'
-# $knjfont_opt = 'kanjifont'
-# TkOption.add('*kanjiFont', $kanji_font, 'startupFile')
-#
-#when /^8.*/
-# Tk.tk_call('font', 'create', '@ascii',
-# '-copy', '-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*')
-# Tk.tk_call('font', 'create', '@kanji',
-# '-copy', '-*--16-*-jisx0208.1983-0')
-# Tk.tk_call('font', 'create', '@msg_knj',
-# '-copy', '-*--24-*-jisx0208.1983-0')
-# Tk.tk_call('font', 'create', '@cFont', '-compound', '@ascii @kanji')
-# Tk.tk_call('font', 'create', '@cMsgFont', '-compound', '@ascii @msg_knj')
-# $font = '-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*'
-# $kanji_font = '@cFont'
-# $msg_kanji_font = '@cMsgFont'
-# $knjfont_opt = 'font'
-#end
+case($tk_version)
+when /^4.*/
+ $font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*', nil)
+ knjfont = '-*--16-*-jisx0208.1983-0'
+ $kanji_font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*',
+ knjfont)
+ TkOption.add('*kanjiFont', knjfont, 'startupFile')
+ $msg_kanji_font=TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*',
+ '-*--24-*-jisx0208.1983-0')
+
+#when '8.0'
+# $font = TkFont.new('Helvetica -12')
+# $kanji_font = TkFont.new('Helvetica -12', 'Mincho -12')
+# TkOption.add('*kanjiFont', knjfont, 'startupFile')
+# $msg_kanji_font=TkFont.new('Helvetica 16', 'Gothic 16 bold')
+
+when /^8.*/
+ $font = TkFont.new('Helvetica -12')
+ $kanji_font = TkFont.new('Helvetica -12', 'Mincho -12')
+ TkOption.add('*kanjiFont', knjfont, 'startupFile')
+ $msg_kanji_font=TkFont.new('Helvetica 14 bold', 'Gothic 14 bold')
+
+else
+ $font = TkFont.new('Helvetica 14', nil)
+ knjfont = '-*--16-*-jisx0208.1983-0'
+ $kanji_font = TkFont.new('Helvetic 14', knjfont)
+ TkOption.add('*kanjiFont', knjfont, 'startupFile')
+ $msg_kanji_font=TkFont.new('Helvetica 14',
+ '-*--24-*-jisx0208.1983-0')
+end
#######
+# ¥¤¥á¡¼¥¸ÀßÄê
+$image = {}
+
+if $tk_major_ver >= 8
+$image['refresh'] = TkPhotoImage.new(:height=>16, :format=>'GIF', :data=><<EOD)
+ R0lGODlhEAAQAPMAAMz/zCpnKdb/1z9mPypbKBtLGy9NMPL/9Or+6+P+4j1Y
+ PwQKBP7//xMLFAYBCAEBASH5BAEAAAAALAAAAAAQABAAAwR0EAD3Gn0Vyw0e
+ ++CncU7IIAezMA/nhUqSLJizvSdCEEjy2ZIV46AwDAoDHwPYGSoEiUJAAGJ6
+ EDHBNCFINW5OqABKSFk/B9lUa94IDwIFgewFMwQDQwCZQCztTgM9Sl8SOEMG
+ KSAthiaOjBMPDhQONBiXABEAOw==
+EOD
+end
+
+if $tk_major_ver >= 8
+$image['view'] = TkPhotoImage.new(:height=>16, :format=>'GIF', :data=><<EOD)
+ R0lGODlhEAAQAPMAAMz/zP///8DAwICAgH9/fwAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAwRIcMhJB7h3hM33
+ KFjWdQQYap1QrCaGBmrRrS4nj5b53jOgbwXBKGACoYLDIuAoHCmZyYvR1rT5
+ RMAq8LqcIYGsrjPsW1XOmFUEADs=
+EOD
+end
+
+if $tk_major_ver >= 8
+$image['delete'] = TkPhotoImage.new(:height=>16, :format=>'GIF', :data=><<EOD)
+ R0lGODlhEAAOAKEAAIQAAO/n3v///////yH5BAEKAAIALAAAAAAQAA4AAAIm
+ lI9pAKHbIHNoVhYhTdjlJ2AWKG2g+CldmB6rxo2uybYhbS80eRQAOw==
+EOD
+end
+
+if $tk_major_ver >= 8
+$image['print'] = TkPhotoImage.new(:height=>19, :format=>'GIF', :data=><<EOD)
+ R0lGODlhGgATAPcAACEQOTEpQjEpUkIpc0IxY0I5c0oxjEo5SlJCY1JCe1JK
+ UlpChFpCjFpGkFpSc1paa2NKc2NKnGNja2tapWtjc29KnHNanHNjc3NjrXNr
+ jHNrnHNzc3tjpXtrtXtzhICAgIRzvYSEjIZzqox7tYyEnIyMjJSEtZSEvZSM
+ lJyMtZyMvZyUlJyUrZyUvZycnKWctaWlpa2czq2lzrWtvbWtzrW1tb21xr21
+ 1sa9zs693s7OztbO3tbO597W1t7W7+fe7+fn5////+/n7+/v7+/v9////wAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAACH5BAEAAEEALAAAAAAaABMAQAj/AIMIHBhkg0GC
+ CBMGIQEiQgseQT4oeCBBAokgRYYQ0JBixg8hRIiUUEBBYYmTByBwiCBCRYwH
+ CxY8cKFw4AogRXLqLAJkQ80gCBBg3BkxZswTNGh4MGqgQQUMJRHCwMkTSE+D
+ Pn8eCKBhxIMhO3ei2OHDBw6sWSlMMMoWgwwfMDZI8GBjx44NARZwEGGi5MkS
+ PcIWKRGz5YgLbAco+KkQBQoJIRgjdGEVq+SaJajqtNrzMgsPCmoIzqmDgmWE
+ KOBuUKAAwYabYTfs4OHjY0giGyhk4MAWRI4eKyRQqPgggYUXPH4A+XBAgwoK
+ DiIsCFxjA9sFEVQQCRJCAYAFDJxiKhAxvMTonEFimrhhYinTBgWiCvxLNX3M
+ DkkpsKV5OYhjBxCMYAICAigUEAA7
+EOD
+end
+
# ¥á¥Ë¥å¡¼ÀßÄê
-TkMenubar.new($root,
- [[['File', 0],
- ['About ... ', proc{aboutBox}, 0, '<F1>'],
- '---',
- ['Quit', proc{exit}, 0, 'Meta-Q']
- ]]).pack('side'=>'top', 'fill'=>'x')
+if $tk_major_ver >= 8
+ $root.add_menubar([[['File', 0],
+ ['About ... ', proc{aboutBox}, 0, '<F1>'],
+ '---',
+ ['Quit', proc{exit}, 0, 'Ctrl-Q']
+ ]])
+else
+ TkMenubar.new($root,
+ [[['File', 0],
+ ['About ... ', proc{aboutBox}, 0, '<F1>'],
+ '---',
+ ['Quit', proc{exit}, 0, 'Ctrl-Q']
+ ]]).pack('side'=>'top', 'fill'=>'x')
+end
$root.bind('F1', proc{aboutBox})
+$root.bind('Control-q', proc{exit})
=begin
TkFrame.new($root){|frame|
@@ -77,7 +159,7 @@ if $tk_version =~ /^4\.[01]/
txt = TkText.new($root) {
#wrap 'word'
wrap 'char'
- width 60
+ width 70
height 30
font $font
setgrid 'yes'
@@ -89,13 +171,13 @@ if $tk_version =~ /^4\.[01]/
else
textFrame = TkFrame.new($root)
scr = TkScrollbar.new($root, 'orient'=>'vertical',
- 'highlightthickness'=>0, 'takefocus'=>1) {
+ 'highlightthickness'=>0, 'takefocus'=>1) {
pack('in'=>textFrame, 'side'=>'right', 'fill'=>'y', 'padx'=>1)
}
txt = TkText.new($root) {
#wrap 'word'
wrap 'char'
- width 60
+ width 70
height 30
font $font
setgrid 'yes'
@@ -103,6 +185,7 @@ else
padx 4
pady 2
takefocus 0
+ bd 1
yscrollcommand proc{|first,last| scr.set first,last}
}
scr.command(proc{|*args| txt.yview(*args)})
@@ -112,71 +195,82 @@ else
textFrame.pack('expand'=>'yes', 'fill'=>'both')
statusBar = TkFrame.new($root) {|f|
+ if $tk_version =~ /^4.*/
+ statusfont = '-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
+ else
+ statusfont = 'Helvetica 10'
+ end
$statusBarLabel = \
TkLabel.new(f, 'text'=>" ", 'relief'=>'sunken', 'bd'=>1, 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') \
+ 'font'=>statusfont) \
.pack('side'=>'left', 'padx'=>2, 'expand'=>'yes', 'fill'=>'both')
TkLabel.new(f, 'width'=>8, 'relief'=>'sunken', 'bd'=>1, 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') \
+ 'font'=>statusfont) \
.pack('side'=>'left', 'padx'=>2)
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>2)
end
# ¥Æ¥­¥¹¥È¥¿¥°ÀßÄê
-tag_title = TkTextTag.new(txt, 'font'=>'-*-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*')
-tag_kanji_title = TkTextTag.new(txt, 'kanjifont'=>$msg_kanji_font)
-tag_middle = TkTextTag.new(txt, 'kanjifont'=>$kanji_font)
+if $tk_version =~ /^4.*/
+ tag_title = TkTextTag.new(txt, 'font'=>'-*-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*')
+else
+ tag_title = TkTextTag.new(txt, 'font'=>'Helvetica 18 bold')
+end
+#tag_kanji_title = TkTextTag.new(txt, 'kanjifont'=>$msg_kanji_font)
+#tag_middle = TkTextTag.new(txt, 'kanjifont'=>$kanji_font)
+tag_kanji_title = TkTextTag.new(txt, 'font'=>$msg_kanji_font)
+tag_middle = TkTextTag.new(txt, 'font'=>$kanji_font)
tag_demospace = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c')
-if TkWinfo.depth($root) == '1'
+if TkWinfo.depth($root) == 1
tag_demo = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c',
- 'underline'=>1)
+ 'underline'=>1)
$tag_visited = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c',
- 'underline'=>1)
+ 'underline'=>1)
tag_hot = TkTextTag.new(txt, 'background'=>'black', 'foreground'=>'white')
else
tag_demo = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c',
- 'foreground'=>'blue', 'underline'=>1)
+ 'foreground'=>'blue', 'underline'=>1)
$tag_visited = TkTextTag.new(txt, 'lmargin1'=>'1c', 'lmargin2'=>'1c',
- 'foreground'=>'#303080', 'underline'=>1)
+ 'foreground'=>'#303080', 'underline'=>1)
# tag_hot = TkTextTag.new(txt, 'relief'=>'raised', 'borderwidth'=>1,
-# 'background'=>'SeaGreen3')
+# 'background'=>'SeaGreen3')
tag_hot = TkTextTag.new(txt, 'borderwidth'=>1, 'foreground'=>'red')
end
#tag_demo.bind('Button-1', proc{invoke txt, txt.index('current')})
tag_demo.bind('ButtonRelease-1',
- proc{|x,y|invoke txt, txt.index("@#{x},#{y}")}, '%x %y')
+ proc{|x,y|invoke txt, txt.index("@#{x},#{y}")}, '%x %y')
lastLine = TkVariable.new("")
newLine = TkVariable.new("")
tag_demo.bind('Enter', proc{|x,y|
- lastLine.value = txt.index("@#{x},#{y} linestart")
- tag_hot.add(lastLine.value, "#{lastLine.value} lineend")
- showStatus txt, txt.index("@#{x},#{y}")
- },
- '%x %y')
+ lastLine.value = txt.index("@#{x},#{y} linestart")
+ tag_hot.add(lastLine.value, "#{lastLine.value} lineend")
+ showStatus txt, txt.index("@#{x},#{y}")
+ },
+ '%x %y')
tag_demo.bind('Leave',
- proc{
- tag_hot.remove('1.0','end')
- txt.configure('cursor','xterm')
- $statusBarLabel.configure('text'=>"")
- })
+ proc{
+ tag_hot.remove('1.0','end')
+ txt.configure('cursor','xterm')
+ $statusBarLabel.configure('text'=>"")
+ })
tag_demo.bind('Motion', proc{|x, y|
- newLine.value = txt.index("@#{x},#{y} linestart")
- if newLine.value != lastLine.value
- tag_hot.remove('1.0','end')
- lastLine.value = newLine.value
- if ( txt.tag_names("@#{x},#{y}").find{|t|
- t.kind_of?(String) && t =~ /^demo-/
- } )
- tag_hot.add(lastLine.value,
- "#{lastLine.value} lineend -1 chars")
- end
- end
- showStatus txt, txt.index("@#{x},#{y}")
- },
- '%x %y')
+ newLine.value = txt.index("@#{x},#{y} linestart")
+ if newLine.value != lastLine.value
+ tag_hot.remove('1.0','end')
+ lastLine.value = newLine.value
+ if ( txt.tag_names("@#{x},#{y}").find{|t|
+ t.kind_of?(String) && t =~ /^demo-/
+ } )
+ tag_hot.add(lastLine.value,
+ "#{lastLine.value} lineend -1 chars")
+ end
+ end
+ showStatus txt, txt.index("@#{x},#{y}")
+ },
+ '%x %y')
# ¥Æ¥­¥¹¥ÈÀ¸À®
txt.insert('end', 'Ruby/Tk : Widget', tag_title)
@@ -192,55 +286,81 @@ txt.insert('end', <<"EOT")
¤ë¤¿¤á¤Ë¡¢"¥³¡¼¥É»²¾È"¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤¢¤Ê¤¿¤¬\
˾¤à¤Ê¤é¡¢¤½¤Î¥³¡¼¥É¤ò½¤Àµ¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£½¤Àµ¤·¤¿¥³¡¼¥É¤Ç¥Ç¥â\
¥ó¥¹¥È¥ì¡¼¥·¥ç¥ó¤òºÆ¼Â¹Ô¤¹¤ë¤¿¤á¤Ë¤Ï¡¢¥³¡¼¥É¤¬½ñ¤«¤ì¤¿¥¦¥£¥ó¥É¥¦¤Ë\
-¤¢¤ë"¥Ç¥âºÆ¼Â¹Ô" ¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£
+¤¢¤ë"¥Ç¥âºÆ¼Â¹Ô" ¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£\
+¥³¡¼¥É¤ò½¤Àµ¤·¤Æ¤â¥ª¥ê¥¸¥Ê¥ë¤Î¥Õ¥¡¥¤¥ë¤¬½ñ¤­´¹¤¨¤é¤ì¤ë¤³¤È¤Ï\
+¤¢¤ê¤Þ¤»¤ó¤«¤é¡¢¿´ÇÛ¤»¤º¤Ë¿§¡¹¤ÊÊѹ¹¤ò»î¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤¡£
+
+°ìÉô¤Î¥Ç¥â¤Ç¤Ï¡¢Èæ³ÓŪºÇ¶á¤Î¥Ð¡¼¥¸¥ç¥ó¤Î Tk ¤Ç¤Ê¤±¤ì¤Ð¥µ¥Ý¡¼¥È¤·¤Æ\
+¤¤¤Ê¤¤µ¡Ç½¤ò»È¤Ã¤Æ¼ÂÁõ¤·¤Æ¤¤¤Þ¤¹(Î㤨¤Ð Tk8.4 °Ê¾å¤Ê¤É)¡£¤½¤Î¤¿¤á¡¢\
+¤½¤¦¤·¤¿µ¡Ç½¤ò»ý¤¿¤Ê¤¤ Tk ¥é¥¤¥Ö¥é¥ê¤ò»È¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¡¢¤½¤¦¤·¤¿\
+¥Ç¥â¤ÏÀµ¤·¤¯Æ°¤­¤Þ¤»¤ó¡£¤½¤Î¤è¤¦¤Êµ¡Ç½¤¬É¬ÍפǤ¢¤ì¤Ð¡¢¤½¤ì¤ò¥µ¥Ý¡¼¥È\
+¤·¤Æ¤¤¤ë Tk ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤Ë tcltklib ¤ò¥³¥ó¥Ñ¥¤¥ë¤·¤Ê¤ª¤·¤Æ\
+¤¯¤À¤µ¤¤¡£
-°ìÉô¤Î¥Ç¥â¤Ç¤Ï¡¤Èæ³ÓŪºÇ¶á¤Î¥Ð¡¼¥¸¥ç¥ó¤Î Tk ¤Ç¤Ê¤±¤ì¤Ð¥µ¥Ý¡¼¥È¤·¤Æ\
-¤¤¤Ê¤¤µ¡Ç½¤ò»È¤Ã¤Æ¼ÂÁõ¤·¤Æ¤¤¤Þ¤¹(Î㤨¤Ð Tk8.4 °Ê¾å¤Ê¤É)¡¥¤½¤Î¤¿¤á¡¤\
-¤½¤¦¤·¤¿µ¡Ç½¤ò»ý¤¿¤Ê¤¤ Tk ¥é¥¤¥Ö¥é¥ê¤ò»È¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¡¤¤½¤¦¤·¤¿\
-¥Ç¥â¤ÏÀµ¤·¤¯Æ°¤­¤Þ¤»¤ó¡¥¤½¤Î¤è¤¦¤Êµ¡Ç½¤¬É¬ÍפǤ¢¤ì¤Ð¡¤¤½¤ì¤ò¥µ¥Ý¡¼¥È\
-¤·¤Æ¤¤¤ë Tk ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤Ë¡¤tcltklib ¤ò¥³¥ó¥Ñ¥¤¥ë¤·¤Ê¤ª¤·¤Æ\
-¤¯¤À¤µ¤¤¡¥
+¤â¤·¤¢¤Ê¤¿¤Î Tk ¤¬ (ºÇ½é¤«¤é´Þ¤à¤«¥¤¥ó¥¹¥È¡¼¥ë¤·¤¿¤«¤Ë¤è¤ê) \
+Ttk (Tile) ³ÈÄ¥¤òÍøÍѤǤ­¤ë¾õÂ֤Ǥ¢¤ë¤Ê¤é¡¢\
+Ttk ³ÈÄ¥¤Î¥Ç¥â (sample/tkextlib/tile/demo.rb) ¤â¤¼¤Ò»î¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤¡£
+( ¿ʬ¡¤¸½ºß¤Î¤¢¤Ê¤¿¤Î´Ä¶­¤Ë¤Ï Ttk ³ÈÄ¥¤Ï\
+#{
+begin
+ require 'tkextlib/tile'
+ "¤¹¤Ç¤ËƳÆþ¤µ¤ì¤Æ¤¤¤Þ¤¹"
+rescue
+ "¤Þ¤À¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+end
+}\
+¡£)
+Ttk ³ÈÄ¥¤Ï¡¢Tk8.5 °Ê¾å¤Ç¤Ïɸ½à¤Îµ¡Ç½¤È¤·¤ÆÁȤ߹þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¡£
EOT
#txt.insert('end',"¥é¥Ù¥ë, ¥Ü¥¿¥ó, ¥Á¥§¥Ã¥¯¥Ü¥¿¥ó, ¥é¥¸¥ª¥Ü¥¿¥ó\n",tag_middle)
txt.insert('end', "¥é¥Ù¥ë, ¥Ü¥¿¥ó, ¥Á¥§¥Ã¥¯¥Ü¥¿¥ó, ¥é¥¸¥ª¥Ü¥¿¥ó\n",
- tag_kanji_title)
+ tag_kanji_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. ¥é¥Ù¥ë (¥Æ¥­¥¹¥È, ¥Ó¥Ã¥È¥Þ¥Ã¥×)\n",
- tag_demo, "demo-label")
+ tag_demo, "demo-label")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. ¥é¥Ù¥ë¤ÈUNICODE¥Æ¥­¥¹¥È (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n", tag_demo, "demo-unicodeout")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "3. ¥Ü¥¿¥ó \n", tag_demo, "demo-button")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "4. ¥Á¥§¥Ã¥¯¥Ü¥¿¥ó (Ê£¿ô¤òÁªÂò²Äǽ)\n",
- tag_demo, "demo-check")
+ tag_demo, "demo-check")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "5. £³¾õÂÖ¥Á¥§¥Ã¥¯¥Ü¥¿¥ó (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
+ tag_demo, "demo-check2")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "6. ¥é¥¸¥ª¥Ü¥¿¥ó (Ǥ°Õ¤Î°ì¤Ä¤òÁªÂò²Äǽ)\n",
+ tag_demo, "demo-radio")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "7. ¥é¥¸¥ª¥Ü¥¿¥ó (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
+ tag_demo, "demo-radio2")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "5. ¥é¥¸¥ª¥Ü¥¿¥ó (Ǥ°Õ¤Î°ì¤Ä¤òÁªÂò²Äǽ)\n",
- tag_demo, "demo-radio")
+txt.insert('end', "8. £³¾õÂ֥饸¥ª¥Ü¥¿¥ó (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
+ tag_demo, "demo-radio3")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "6. ¥é¥¸¥ª¥Ü¥¿¥ó (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
- tag_demo, "demo-radio2")
+txt.insert('end', "9. ¥Ü¥¿¥ó¤Çºî¤é¤ì¤¿15-¥Ñ¥º¥ë¥²¡¼¥à\n",
+ tag_demo, "demo-puzzle")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "7. ¥Ü¥¿¥ó¤Çºî¤é¤ì¤¿15-¥Ñ¥º¥ë¥²¡¼¥à\n",
- tag_demo, "demo-puzzle")
+txt.insert('end', "10. ¥Ó¥Ã¥È¥Þ¥Ã¥×¤ò»ÈÍѤ·¤¿¥¢¥¤¥³¥ó¥Ü¥¿¥ó\n",
+ tag_demo, "demo-icon")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "8. ¥Ó¥Ã¥È¥Þ¥Ã¥×¤ò»ÈÍѤ·¤¿¥¢¥¤¥³¥ó¥Ü¥¿¥ó\n",
- tag_demo, "demo-icon")
+txt.insert('end', "11. ²èÁü¤òɽ¼¨¤¹¤ëÆó¤Ä¤Î¥é¥Ù¥ë\n",
+ tag_demo, "demo-image1")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "9. ²èÁü¤òɽ¼¨¤¹¤ëÆó¤Ä¤Î¥é¥Ù¥ë\n",
- tag_demo, "demo-image1")
+txt.insert('end', "12. ²èÁü¤ò¸«¤ë¤¿¤á¤Î´Êñ¤Ê¥æ¡¼¥¶¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹\n",
+ tag_demo, "demo-image2")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "10. ²èÁü¤ò¸«¤ë¤¿¤á¤Î´Êñ¤Ê¥æ¡¼¥¶¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹\n",
- tag_demo, "demo-image2")
+txt.insert('end', "13. ²èÁü¤ò¸«¤ë¤¿¤á¤Î´Êñ¤Ê¥æ¡¼¥¶¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹ (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
+ tag_demo, "demo-image3")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "11. ²èÁü¤ò¸«¤ë¤¿¤á¤Î´Êñ¤Ê¥æ¡¼¥¶¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹ (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
- tag_demo, "demo-image3")
+txt.insert('end', "14. ¥é¥Ù¥ëÉÕ¤­¥Õ¥ì¡¼¥à (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
+ tag_demo, "demo-labelframe")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "12. ¥é¥Ù¥ëÉÕ¤­¥Õ¥ì¡¼¥à (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
- tag_demo, "demo-labelframe")
+txt.insert('end', "15. ¥Æ¡¼¥Þ¤ËÂбþ¤·¤¿¥¦¥£¥¸¥§¥Ã¥È¤Î´Êñ¤ÊÎã (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n",
+ tag_demo, "demo-ttkbut")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
@@ -250,10 +370,16 @@ txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. ÅÔÆ»Éܸ©.\n", tag_demo, "demo-states")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. ¿§: ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¤¿¤á¤ÎÇÛ¿§¤òÊѤ¨¤ë\n",
- "#{tag_demo.id} demo-colors")
+ "#{tag_demo.id} demo-colors")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "3. ³Ê¸À½¸\n", tag_demo, "demo-sayings")
txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "4. ¹ñ¤Ë¤Ä¤¤¤Æ¤Î¥Þ¥ë¥Á¥«¥é¥à¥ê¥¹¥È (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n",
+ tag_demo, "demo-mclist")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "5. ¥Ç¥£¥ì¥¯¥È¥ê¥Ö¥é¥¦¥¶ (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n",
+ tag_demo, "demo-tree")
+txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
#txt.insert('end', "¥¨¥ó¥È¥ê¤È¥¹¥Ô¥ó¥Ü¥Ã¥¯¥¹\n", tag_middle)
@@ -264,12 +390,15 @@ txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. ¥¹¥¯¥í¡¼¥ë¥Ð¡¼¤¢¤ê\n", tag_demo, "demo-entry2")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "3. ǧ¾Ú½èÍýÉÕ¤­¤Î¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤È¥Ñ¥¹¥ï¡¼¥É¥Õ¥£¡¼¥ë¥É (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
- tag_demo, "demo-entry3")
+ tag_demo, "demo-entry3")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "4. ¥¹¥Ô¥ó¥Ü¥Ã¥¯¥¹ (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
- tag_demo, "demo-spin")
+ tag_demo, "demo-spin")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "5. ¥³¥ó¥Ü¥Ü¥Ã¥¯¥¹ (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n",
+ tag_demo, "demo-combo")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "5. ´Êñ¤Ê¥Õ¥©¡¼¥à\n", tag_demo, "demo-form")
+txt.insert('end', "6. ´Êñ¤Ê¥Õ¥©¡¼¥à\n", tag_demo, "demo-form")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
@@ -281,12 +410,17 @@ txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. ɽ¼¨¥¹¥¿¥¤¥ë.\n", tag_demo, "demo-style")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "3. ¥Ï¥¤¥Ñ¡¼¥Æ¥­¥¹¥È(¥¿¥°¥Ð¥¤¥ó¥É).\n",
- tag_demo, "demo-bind")
+ tag_demo, "demo-bind")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "4. ¥¦¥£¥ó¥É¥¦¤òËä¤á¹þ¤ó¤À¥Æ¥­¥¹¥È\n",
- tag_demo, "demo-twind")
+ tag_demo, "demo-twind")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "5. ¸¡º÷\n", tag_demo, "demo-search")
+txt.insert('end', "5. ¥¦¥£¥ó¥É¥¦¤òËä¤á¹þ¤ó¤À¥Æ¥­¥¹¥È (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
+ tag_demo, "demo-twind2")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "6. ¸¡º÷\n", tag_demo, "demo-search")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "7. ¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤ÎÂÐÅù²½(peering) (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n", tag_demo, "demo-textpeer")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
@@ -305,44 +439,63 @@ txt.insert('end', "5. ¥ë¡¼¥é¡¼\n", tag_demo, "demo-ruler")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "6. ¥Õ¥í¥¢¥×¥é¥ó\n", tag_demo, "demo-floor")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "7. ¥¹¥¯¥í¡¼¥ë²Äǽ¤Ê¥­¥ã¥ó¥Ð¥¹\n",
- tag_demo, "demo-cscroll")
+txt.insert('end', "7. ¥Õ¥í¥¢¥×¥é¥ó (°Û¤Ê¤ë¥­¥ã¥ó¥Ð¥¹¥¢¥¤¥Æ¥àºîÀ®ÊýË¡¤ò»ÈÍÑ)\n", tag_demo, "demo-floor2")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "8. ¥¹¥¯¥í¡¼¥ë²Äǽ¤Ê¥­¥ã¥ó¥Ð¥¹\n",
+ tag_demo, "demo-cscroll")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "9. ¥Á¥§¥¹¥Ü¡¼¥É¾å¤Îµ³»Î¤Î½ä²ó (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n",
+ tag_demo, "demo-knightstour")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
-#txt.insert('end', "¥¹¥±¡¼¥ë\n", tag_middle)
-txt.insert('end', "¥¹¥±¡¼¥ë\n", tag_kanji_title)
+#txt.insert('end', "¥¹¥±¡¼¥ë¤È¥×¥í¥°¥ì¥¹¥Ð¡¼\n", tag_middle)
+txt.insert('end', "¥¹¥±¡¼¥ë¤È¥×¥í¥°¥ì¥¹¥Ð¡¼\n", tag_kanji_title)
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "1. ¿âľ¥¹¥±¡¼¥ë\n", tag_demo.id, "demo-vscale")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "1. ¿âľ\n", tag_demo.id, "demo-vscale")
+txt.insert('end', "2. ¿åÊ¿¥¹¥±¡¼¥ë\n", tag_demo.id, "demo-hscale")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "2. ¿åÊ¿\n", tag_demo.id, "demo-hscale")
+txt.insert('end', "3. ¥×¥í¥°¥ì¥¹¥Ð¡¼ (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n", tag_demo.id, "demo-ttkprogress")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
-txt.insert('end', "¥Ú¥¤¥ó¥É¥¦¥£¥ó¥É¥¦\n", tag_kanji_title)
+txt.insert('end', "¥Ú¥¤¥ó¥É¥¦¥£¥ó¥É¥¦¤È¥Î¡¼¥È¥Ö¥Ã¥¯\n", tag_kanji_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. ¿åÊ¿Êý¸þ (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
- tag_demo.id, "demo-paned1")
+ tag_demo.id, "demo-paned1")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. ¿âľÊý¸þ (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
- tag_demo.id, "demo-paned2")
+ tag_demo.id, "demo-paned2")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "3. ¥Æ¡¼¥Þ¤ËÂбþ¤·¤¿Ëä¤á¹þ¤ß¥Ú¥¤¥ó (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n",
+ tag_demo.id, "demo-ttkpane")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "4. ¥Î¡¼¥È¥Ö¥Ã¥¯¥¦¥£¥¸¥§¥Ã¥È (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n",
+ tag_demo.id, "demo-ttknote")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
-#txt.insert('end', "¥á¥Ë¥å¡¼\n", tag_middle)
-txt.insert('end', "¥á¥Ë¥å¡¼\n", tag_kanji_title)
+#txt.insert('end', "¥á¥Ë¥å¡¼¤È¥Ä¡¼¥ë¥Ð¡¼\n", tag_middle)
+txt.insert('end', "¥á¥Ë¥å¡¼¤È¥Ä¡¼¥ë¥Ð¡¼\n", tag_kanji_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. ¥á¥Ë¥å¡¼¤È¥«¥¹¥±¡¼¥É¤ò´Þ¤ó¤À¥¦¥£¥ó¥É¥¦\n",
- tag_demo, "demo-menu")
+ tag_demo, "demo-menu")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. ¥á¥Ë¥å¡¼¤È¥«¥¹¥±¡¼¥É¤ò´Þ¤ó¤À¥¦¥£¥ó¥É¥¦ (Tk8.x ÀìÍÑ)\n",
- tag_demo, "demo-menu8x")
+ tag_demo, "demo-menu8x")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "3. ¡· (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n",
- tag_demo, "demo-menu84")
+ tag_demo, "demo-menu84")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "4. ¥á¥Ë¥å¡¼¥Ü¥¿¥ó (Tk8.x ÀìÍÑ)\n",
- tag_demo, "demo-menubu")
+ tag_demo, "demo-menubu")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "5. ¥Æ¡¼¥Þ¤ËÂбþ¤·¤¿¥á¥Ë¥å¡¼¥Ü¥¿¥ó (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n",
+ tag_demo.id, "demo-ttkmenu")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "6. ¥Æ¡¼¥Þ¤ËÂбþ¤·¤¿¥Ä¡¼¥ë¥Ð¡¼ (Tile/Ttk³ÈÄ¥¤Ø¤ÎÂбþ¤¬É¬Í×)\n",
+ tag_demo.id, "demo-toolbar")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
@@ -351,22 +504,36 @@ txt.insert('end', "¥À¥¤¥¢¥í¥°¥¦¥£¥ó¥É¥¦\n", tag_kanji_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. ¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹\n", tag_demo, "demo-msgbox")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "2. ¥Õ¥¡¥¤¥ëÁªÂò¥À¥¤¥¢¥í¥°\n", tag_demo, "demo-filebox")
+txt.insert('end', "2. ¾ÜºÙ¥Æ¥­¥¹¥ÈÉÕ¤­¤Î¥á¥Ã¥»¡¼¥¸¥Ü¥Ã¥¯¥¹ (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n", tag_demo, "demo-msgbox2")
txt.insert('end', " \n ", tag_demospace)
-txt.insert('end', "3. ¿§ÁªÂò¥À¥¤¥¢¥í¥°\n", tag_demo, "demo-clrpick")
+txt.insert('end', "3. ¥Õ¥¡¥¤¥ëÁªÂò¥À¥¤¥¢¥í¥°\n", tag_demo, "demo-filebox")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "4. ¿§ÁªÂò¥À¥¤¥¢¥í¥°\n", tag_demo, "demo-clrpick")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
+#txt.insert('end', "¥¢¥Ë¥á¡¼¥·¥ç¥ó\n", tag_middle)
+txt.insert('end', "¥¢¥Ë¥á¡¼¥·¥ç¥ó\n", tag_kanji_title)
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "1. ¥¢¥Ë¥á¡¼¥·¥ç¥ó¥é¥Ù¥ë (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n", tag_demo, "demo-anilabel")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "2. ÇÈ·Á¤Î¥¢¥Ë¥á¡¼¥·¥ç¥ó (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n", tag_demo, "demo-aniwave")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "3. ¿¶¤ê»Ò¤Î¥·¥ß¥å¥ì¡¼¥·¥ç¥ó (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n", tag_demo, "demo-pendulum")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "4. A celebration of Rube Goldberg (µ¡Ç½¤ËÂбþ¤·¤¿¥Ð¡¼¥¸¥ç¥ó¤ÎTk¤¬É¬Í×)\n", tag_demo, "demo-goldberg")
+
+txt.insert('end', "\n")
#txt.insert('end', "¤½¤Î¾\n", tag_middle)
txt.insert('end', "¤½¤Î¾\n", tag_kanji_title)
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "1. ÁȤ߹þ¤ß¤Î¥Ó¥Ã¥È¥Þ¥Ã¥×\n", tag_demo, "demo-bitmap")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "2. ¥â¡¼¥À¥ë¥À¥¤¥¢¥í¥°(¥í¡¼¥«¥ë¥°¥é¥Ö)\n",
- tag_demo, "demo-dialog1")
+ tag_demo, "demo-dialog1")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "3. ¥â¡¼¥À¥ë¥À¥¤¥¢¥í¥°(¥°¥í¡¼¥Ð¥ë¥°¥é¥Ö)\n",
- tag_demo, "demo-dialog2")
+ tag_demo, "demo-dialog2")
txt.insert('end', " \n ", tag_demospace)
txt.state('disabled')
@@ -381,56 +548,228 @@ end
# ¿Æ¥¦¥£¥¸¥§¥Ã¥È¤È¡¤ÊÑ¿ô̾¤È TkVariable ¤È¤ÎÁÈ(ÇÛÎó)¤ÎʤӤòÅϤ¹
$showVarsWin = {}
-def showVars (parent, *args)
+def showVars1(parent, *args)
if $showVarsWin[parent.path]
begin
$showVarsWin[parent.path].destroy
rescue
end
end
- w = TkToplevel.new(parent) {|w|
+ top = TkToplevel.new(parent) {|w|
title "Variable values"
- TkLabel.new(w) {
+ base = TkFrame.new(w).pack(:fill=>:both, :expand=>true)
+ TkLabel.new(base) {
text "ÊÑ¿ôÃÍ:"
width 20
anchor 'center'
- font '-Adobe-helvetica-medium-r-normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ font '-Adobe-helvetica-medium-r-normal--*-180-*-*-*-*-*-*'
+ else
+ font 'Helvetica 14'
+ end
}.pack('side'=>'top', 'fill'=>'x')
len = 1
args.each{|vnam,vbody|
len = vnam.to_s.length if vnam.to_s.length > len
}
args.each{|vnam,vbody|
- TkFrame.new(w){|f|
- #TkLabel.new(f, 'text'=>"#{vnam}: ").pack('side'=>'left')
- TkLabel.new(f, 'text'=>"#{vnam}: ",'width'=>len+2).pack('side'=>'left')
- TkLabel.new(f, 'textvariable'=>vbody, 'anchor'=>'w')\
- .pack('side'=>'left', 'expand'=>'yes', 'fill'=>'x')
+ TkFrame.new(base){|f|
+ #TkLabel.new(f, 'text'=>"#{vnam}: ").pack('side'=>'left')
+ TkLabel.new(f, 'text'=>"#{vnam}: ",'width'=>len+2).pack('side'=>'left')
+ TkLabel.new(f, 'textvariable'=>vbody, 'anchor'=>'w')\
+ .pack('side'=>'left', 'expand'=>'yes', 'fill'=>'x')
}.pack('side'=>'top', 'anchor'=>'w', 'fill'=>'x')
}
- TkButton.new(w) {
+ TkButton.new(base) {
text "λ²ò"
command proc{w.destroy}
}.pack('side'=>'bottom', 'pady'=>2)
}
- $showVarsWin[parent.path] = w
+ $showVarsWin[parent.path] = top
+end
+
+def showVars2(parent, *args)
+ if $showVarsWin[parent.path]
+ begin
+ $showVarsWin[parent.path].destroy
+ rescue
+ end
+ end
+ $showVarsWin[parent.path] = TkToplevel.new(parent) {|top|
+ title "Variable values"
+
+ base = TkFrame.new(top).pack(:fill=>:both, :expand=>true)
+
+ TkLabelFrame.new(base, :text=>"ÊÑ¿ôÃÍ:",
+ :font=>{:family=>'Helvetica', :size=>14}){|f|
+ args.each{|vnam,vbody|
+ TkGrid(TkLabel.new(f, :text=>"#{vnam}: ", :anchor=>'w'),
+ TkLabel.new(f, :textvariable=>vbody, :anchor=>'w'),
+ :padx=>2, :pady=>2, :sticky=>'w')
+ }
+
+ f.grid(:sticky=>'news', :padx=>4)
+ f.grid_columnconfig(1, :weight=>1)
+ f.grid_rowconfig(100, :weight=>1)
+ }
+ TkButton.new(base, :text=>"λ²ò", :width=>8, :default=>:active,
+ :command=>proc{top.destroy}){|b|
+ top.bind('Return', proc{b.invoke})
+ top.bind('Escape', proc{b.invoke})
+
+ b.grid(:sticky=>'e', :padx=>4, :pady=>[6, 4])
+ }
+ base.grid_columnconfig(0, :weight=>1)
+ base.grid_rowconfig(0, :weight=>1)
+ }
+end
+
+if $tk_major_ver < 8
+ alias showVars showVars1
+elsif $tk_major_ver == 8 && $tk_minor_ver < 4
+ alias showVars showVars1
+else # ver >= 8.4
+ alias showVars showVars2
+end
+
+# µ¿»÷¥È¥Ã¥×¥ì¥Ù¥ë¥µ¥Ý¡¼¥È
+module PseudoToplevel_Evaluable
+ def pseudo_toplevel_eval(body = Proc.new)
+ Thread.current[:TOPLEVEL] = self
+ begin
+ body.call
+ ensure
+ Thread.current[:TOPLEVEL] = nil
+ end
+ end
+
+ def pseudo_toplevel_evaluable?
+ @pseudo_toplevel_evaluable
+ end
+ def pseudo_toplevel_evaluable=(mode)
+ @pseudo_toplevel_evaluable = (mode)? true: false
+ end
+
+ def self.extended(mod)
+ mod.__send__(:extend_object, mod)
+ mod.instance_variable_set('@pseudo_toplevel_evaluable', true)
+ end
+end
+
+class Object
+ alias __method_missing__ method_missing
+ private :__method_missing__
+
+ def method_missing(id, *args)
+ begin
+ has_top = (top = Thread.current[:TOPLEVEL]) &&
+ top.respond_to?(:pseudo_toplevel_evaluable?) &&
+ top.pseudo_toplevel_evaluable? &&
+ top.respond_to?(id)
+ rescue Exception => e
+ has_top = false
+ end
+
+ if has_top
+ top.__send__(id, *args)
+ else
+ __method_missing__(id, *args)
+ end
+ end
+end
+
+class Proc
+ def initialize(*args, &b)
+ super
+ @__pseudo_toplevel__ = Thread.current[:TOPLEVEL]
+ end
+
+ alias __call__ call
+ def call(*args, &b)
+ if top = @__pseudo_toplevel__
+ orig_top = Thread.current[:TOPLEVEL]
+ Thread.current[:TOPLEVEL] = top
+ begin
+ __call__(*args, &b)
+ ensure
+ Thread.current[:TOPLEVEL] = orig_top
+ end
+ else
+ __call__(*args, &b)
+ end
+ end
+end
+
+def proc(&b)
+ Proc.new(&b)
+end
+def lambda(&b)
+ Proc.new(&b)
+end
+
+def _null_binding
+ Module.new.instance_eval{extend PseudoToplevel_Evaluable}
+ # binding
+ # Module.new.instance_eval{binding}
+end
+private :_null_binding
+
+def eval_samplecode(code, file=nil)
+ #eval(code)
+ #_null_binding.pseudo_toplevel_eval{ eval(code) }
+ #Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }
+ Thread.new{
+ _null_binding.pseudo_toplevel_eval{
+ begin
+ if file
+ eval(code, binding, "(eval:#{file})")
+ else
+ eval(code)
+ end
+ rescue Exception=>e
+ #p e
+ TkBgError.show(e.message + "\n" +
+ "\n---< backtrace of Ruby side >-----\n" +
+ e.backtrace.join("\n") +
+ "\n---< backtrace of Tk side >-------")
+ end
+ }
+ }
+ Tk.update
end
# ¥Æ¥­¥¹¥È¾å¤Ç¤Î click ¤ËÂФ¹¤ëưºî
-def invoke (txt, index)
- tag = txt.tag_names(index).find{|t| t.kind_of?(String) && t =~ /^demo-/}
+def invoke(txt, idx)
+ tag = txt.tag_names(idx).find{|t| t.kind_of?(String) && t =~ /^demo-/}
return unless tag
+
cursor = txt.cget('cursor')
txt.cursor('watch')
Tk.update
+ # eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
+ # Tk.update
+ eval_samplecode(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, tag[5..-1] + '.rb')
+ txt.cursor(cursor)
+
+ $tag_visited.add("#{idx} linestart +1 chars", "#{idx} lineend +1 chars")
+end
+=begin
+def invoke (txt, idx)
+ tag = txt.tag_names(idx).find{|t| t.kind_of?(String) && t =~ /^demo-/}
+ return unless tag
+ current_cursor = txt.cget('cursor')
+ txt.cursor('watch')
+ Tk.update
# eval `cat #{tag[5..-1]}.rb`
- eval `cat #{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb`
+# eval `cat #{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb`
+ eval IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join
Tk.update
# txt.cursor('xterm')
- txt.cursor(cursor)
+ txt.cursor(current_cursor)
- $tag_visited.add("#{index} linestart +1 chars", "#{index} lineend +1 chars")
+ $tag_visited.add("#{idx} linestart +1 chars", "#{idx} lineend +1 chars")
end
+=end
# ¾õÂÖɽ¼¨
def showStatus (txt, index)
@@ -442,79 +781,104 @@ def showStatus (txt, index)
else
demoname = tag[5..-1]
$statusBarLabel.configure('text',
- "¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à \"#{demoname}\" ¤Î¼Â¹Ô ")
+ "¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à \"#{demoname}\" ¤Î¼Â¹Ô ")
newcursor = 'hand2'
end
txt.configure('cursor'=>newcursor) if cursor != newcursor
end
# ¥½¡¼¥¹¥³¡¼¥É¤Îɽ¼¨
-def showCode (demo)
+def showCode1(demo)
file = "#{demo}.rb"
$code_window = nil unless defined? $code_window
- if $code_window == nil || TkWinfo.exist?($code_window) == '0'
+ if $code_window == nil || TkWinfo.exist?($code_window) == false
$code_window = TkToplevel.new(nil)
f = TkFrame.new($code_window)
+
TkButton.new(f) {
- text "λ²ò"
+ #text "λ²ò"
+ text "ÊĤ¸¤ë"
command proc{
- $code_window.destroy
- $code_window = nil
+ $code_window.destroy
+ $code_window = nil
}
- }.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
+ }.pack('side'=>'right', 'expand'=>'false', 'pady'=>2)
TkButton.new(f) {
text "ºÆ¼Â¹Ô"
- command proc{eval($code_text.get('1.0','end'))}
- }.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
-# f.pack('side'=>'bottom', 'expand'=>'yes', 'fill'=>'x')
- f.pack('side'=>'bottom', 'fill'=>'x')
+ # command proc{eval($code_text.get('1.0','end'), _null_binding)}
+ command proc{eval_samplecode($code_text.get('1.0','end'), '<viewer>')}
+ }.pack('side'=>'right', 'expand'=>'false', 'pady'=>2)
+
+ TkLabel.new(f,'text'=>'line:').pack('side'=>'left')
+ linenum =TkLabel.new(f,'text'=>'').pack('side'=>'left')
+ TkLabel.new(f,'text'=>' pos:').pack('side'=>'left')
+ posnum =TkLabel.new(f,'text'=>'').pack('side'=>'left')
+
+ $set_linenum = proc{|w|
+ line, pos = w.index('insert').split('.')
+ linenum.text = line
+ posnum.text = pos
+ }
+
+ f.pack('side'=>'bottom', 'expand'=>'true', 'fill'=>'x')
if $tk_version =~ /^4\.[01]/
s = TkScrollbar.new($code_window, 'orient'=>'vertical')
$code_text = TkText.new($code_window) {
- height 40
- setgrid 'yes'
- yscrollcommand proc{|first,last| s.set first,last}
+ height 40
+ setgrid 'yes'
+ yscrollcommand proc{|first,last| s.set first,last}
}
s.command(proc{|*args| $code_text.yview(*args)})
s.pack('side'=>'right', 'fill'=>'y')
$code_text.pack('side'=>'left', 'expand'=>'yes', 'fill'=>'both')
else
TkFrame.new($code_window) {|f|
- pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
-
- hs = TkScrollbar.new($code_window, 'highlightthickness'=>0,
- 'orient'=>'horizontal')
- vs = TkScrollbar.new($code_window, 'highlightthickness'=>0,
- 'orient'=>'vertical')
- $code_text = TkText.new($code_window) {|t|
- height 40
- #wrap 'word'
- wrap 'char'
- xscrollcommand proc{|first,last| hs.set first,last}
- yscrollcommand proc{|first,last| vs.set first,last}
- setgrid 'yes'
- highlightthickness 0
- pady 2
- padx 3
- hs.command(proc{|*args| $code_text.xview(*args)})
- vs.command(proc{|*args| $code_text.yview(*args)})
- }
-
- $code_text.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
- vs.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
- 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
-# xs.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
-# 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
- TkGrid.rowconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
- TkGrid.columnconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
+ pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1)
+
+ hs = TkScrollbar.new($code_window, 'highlightthickness'=>0,
+ 'orient'=>'horizontal')
+ vs = TkScrollbar.new($code_window, 'highlightthickness'=>0,
+ 'orient'=>'vertical')
+ $code_text = TkText.new($code_window) {|t|
+ height 40
+ #wrap 'word'
+ wrap 'char'
+ xscrollcommand proc{|first,last| hs.set first,last}
+ yscrollcommand proc{|first,last| vs.set first,last}
+ setgrid 'yes'
+ highlightthickness 0
+ pady 2
+ padx 3
+ hs.command(proc{|*args| $code_text.xview(*args)})
+ vs.command(proc{|*args| $code_text.yview(*args)})
+ }
+
+ $code_text.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>0,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ vs.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>0, 'column'=>1,
+ 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+# xs.grid('in'=>f, 'padx'=>1, 'pady'=>1, 'row'=>1, 'column'=>0,
+# 'rowspan'=>1, 'columnspan'=>1, 'sticky'=>'news')
+ TkGrid.rowconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
+ TkGrid.columnconfigure(f, 0, 'weight'=>1, 'minsize'=>0)
}
end
+
+ btag = TkBindTag.new
+
+ btag.bind('Key', $set_linenum, '%W')
+ btag.bind('Button', $set_linenum, '%W')
+
+ btags = $code_text.bindtags
+ btags.insert(btags.index($code_text.class) + 1, btag)
+ $code_text.bindtags = btags
+
else
$code_window.deiconify
$code_window.raise
end
+
$code_window.title("Demo code: #{file}")
$code_window.iconname(file)
# fid = open(file, 'r')
@@ -525,16 +889,235 @@ def showCode (demo)
#$code_mark = TkTextMark.new($code_text, '1.0')
#$code_text.set_insert('1.0')
TkTextMarkInsert.new($code_text,'1.0')
+
+ $set_linenum.call($code_text)
+
fid.close
end
+def showCode2(demo)
+ file = "#{demo}.rb"
+ $code_window = nil unless defined? $code_window
+ if $code_window == nil || TkWinfo.exist?($code_window) == false
+ $code_window = TkToplevel.new(nil)
+ tf = TkFrame.new($code_window)
+ $code_text = TkText.new(tf, :font=>'Courier 10', :height=>30,
+ :wrap=>'word', :bd=>1, :setgrid=>true,
+ :highlightthickness=>0, :pady=>2, :padx=>3)
+ xscr = TkScrollbar.new(tf, :bd=>1){assign($code_text)}
+ yscr = TkScrollbar.new(tf, :bd=>1){assign($code_text)}
+ TkGrid($code_text, yscr, :sticky=>'news')
+ #TkGrid(xscr)
+ tf.grid_rowconfigure(0, :weight=>1)
+ tf.grid_columnconfigure(0, :weight=>1)
+
+ bf = TkFrame.new($code_window)
+
+ lf = TkFrame.new(bf)
+ TkLabel.new(lf, :text=>'line:').pack(:side=>:left)
+ linenum =TkLabel.new(lf, :text=>'').pack(:side=>:left)
+ TkLabel.new(lf, :text=>' pos:').pack(:side=>:left)
+ posnum =TkLabel.new(lf, :text=>'').pack(:side=>:left)
+
+ $set_linenum = proc{|w|
+ line, pos = w.index('insert').split('.')
+ linenum.text = line
+ posnum.text = pos
+ }
+
+ #b_dis = TkButton.new(bf, :text=>'λ²ò', :default=>:active,
+ b_dis = TkButton.new(bf, :text=>'ÊĤ¸¤ë', :default=>:active,
+ :command=>proc{
+ $code_window.destroy
+ $code_window = nil
+ },
+ :image=>$image['delete'], :compound=>:left)
+ b_prn = TkButton.new(bf, :text=>'°õºþ',
+ :command=>proc{printCode($code_text, file)},
+ :image=>$image['print'], :compound=>:left)
+ b_run = TkButton.new(bf, :text=>'ºÆ¼Â¹Ô',
+ :command=>proc{
+ # eval($code_text.get('1.0','end'), _null_binding)
+ eval_samplecode($code_text.get('1.0','end'), '<viewer>')
+ },
+ :image=>$image['refresh'], :compound=>:left)
+
+ TkGrid(lf, 'x', b_run, b_prn, b_dis, :padx=>4, :pady=>[6,4])
+ bf.grid_columnconfigure(1, :weight=>1)
+
+ TkGrid(tf, :sticky=>'news')
+ TkGrid(bf, :sticky=>'ew')
+ $code_window.grid_columnconfigure(0, :weight=>1)
+ $code_window.grid_rowconfigure(0, :weight=>1)
+
+ $code_window.bind('Return', proc{|win|
+ b_dis.invoke unless win.kind_of?(TkText)
+ }, '%W')
+ $code_window.bindinfo('Return').each{|cmd, arg|
+ $code_window.bind_append('Escape', cmd, arg)
+ }
+
+ btag = TkBindTag.new
+
+ btag.bind('Key', $set_linenum, '%W')
+ btag.bind('Button', $set_linenum, '%W')
+
+ btags = $code_text.bindtags
+ btags.insert(btags.index($code_text.class) + 1, btag)
+ $code_text.bindtags = btags
+
+ else
+ $code_window.deiconify
+ $code_window.raise
+ end
+
+ $code_window.title("Demo code: #{file}")
+ $code_window.iconname(file)
+ fid = open([$demo_dir, file].join(File::Separator), 'r')
+ $code_text.delete('1.0', 'end')
+ $code_text.insert('1.0', fid.read)
+ TkTextMarkInsert.new($code_text,'1.0')
+
+ $set_linenum.call($code_text)
+
+ fid.close
+end
+
+if $tk_major_ver < 8
+ alias showCode showCode1
+elsif $tk_major_ver == 8 && $tk_minor_ver < 4
+ alias showCode showCode1
+else # ver >= 8.4
+ alias showCode showCode2
+end
+
+
+# printCode --
+# Prints the source code currently displayed in the See Code dialog.
+# Much thanks to Arjen Markus for this.
+#
+# Arguments:
+# txt - Name of text widget containing code to print
+# file - Name of the original file (implicitly for title)
+
+def printCode(txt, file)
+ code = txt.get('1.0', 'end - 1c')
+ dir = '.'
+ dir = ENV['HOME'] if ENV['HOME']
+ dir = ENV['TMP'] if ENV['TMP']
+ dir = ENV['TEMP'] if ENV['TEMP']
+
+ fname = [dir, 'tkdemo-' + file].join(File::Separator)
+ open(fname, 'w'){|fid| fid.print(code)}
+ begin
+ case Tk::TCL_PLATFORM('platform')
+ when 'unix'
+ msg = `lp -c #{fname}`
+ unless $?.exitstatus == 0
+ Tk.messageBox(:title=>'Print spooling failure',
+ :message=>'¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿¡¥' +
+ '°õºþ¤Ë¼ºÇÔ¤·¤¿¤â¤Î¤È»×¤ï¤ì¤Þ¤¹ : ' + msg)
+ end
+ when 'windows'
+ begin
+ printTextWin32(fname)
+ rescue => e
+ Tk.messageBox(:title=>'Print spooling failure',
+ :message=>'¥¨¥é¡¼¤¬È¯À¸¤·¤Þ¤·¤¿¡¥' +
+ '°õºþ¤Ë¼ºÇÔ¤·¤¿¤â¤Î¤È»×¤ï¤ì¤Þ¤¹ : ' +
+ e.message)
+ end
+ when 'macintosh'
+ Tk.messageBox(:title=>'Operation not Implemented',
+ :message=>'°õºþµ¡Ç½¤Ï¤Þ¤À¼ÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó')
+ else
+ Tk.messageBox(:title=>'Operation not Implemented',
+ :message=>'¸¡½Ð¤µ¤ì¤¿´Ä¶­ ' +
+ Tk::TCL_PLATFORM('platform') +
+ ' ¤Ï̤ÃΤδĶ­¤Ç¤¢¤ë¤¿¤á¡¤' +
+ '°õºþµ¡Ç½¤Ï¼ÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó: ')
+ end
+ ensure
+ File.delete(fname)
+ end
+end
+
+# printTextWin32 --
+# Print a file under Windows
+#
+# Arguments:
+# filename - Name of the file
+#
+def printTextWin32(fname)
+ require 'win32/registry'
+ begin
+ app = Win32::Registry::HKEY_CLASSES_ROOT['.txt']
+ pcmd = nil
+ Win32::Registry::HKEY_CLASSES_ROOT.open("#{app}\\shell\\print"){|reg|
+ pcmd = reg['command']
+ }
+ rescue
+ app = Tk.tk_call('auto_execok', 'notepad.exe')
+ pcmd = "#{app} /p %1"
+ end
+
+ pcmd.gsub!('%1', fname)
+ puts pcmd
+ cmd = Tk.tk_call('auto_execok', 'start') + ' /min ' + pcmd
+
+ msg = `#{cmd}`
+ unless $?.exitstatus == 0
+ fail RuntimeError, msg
+ end
+end
+
# aboutBox
#
# Pops up a message box with an "about" message
#
def aboutBox
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo',
- 'message'=>"Ruby/Tk ¥¦¥£¥¸¥§¥Ã¥È¥Ç¥â Ver.1.3.2-jp\n\n( based on Tk ¥¦¥£¥¸¥§¥Ã¥È¥Ç¥â :: Copyright (c) 1996-1997 Sun Microsystems, Inc. )\n\nRunning Version :: Ruby#{VERSION}/Tk#{$tk_version}#{(Tk::JAPANIZED_TK)? 'jp': ''}")
+ 'message'=>"Ruby/Tk ¥¦¥£¥¸¥§¥Ã¥È¥Ç¥â Ver.1.7.0-jp\n\n" +
+ "based on demos of Tk8.1 -- 8.5 " +
+ "( Copyright of Tcl/Tk demos:: " +
+ "(c) 1996-1997 Sun Microsystems, Inc. / " +
+ "(c) 1997-2000 Ajuba Solutions, Inc. / " +
+ "(c) 2001-2007 Donal K. Fellows / " +
+ "(c) 2002-2007 Daniel A. Steffen )\n\n" +
+ "Your Ruby & Tk Version ::\n" +
+ "Ruby#{RUBY_VERSION}(#{RUBY_RELEASE_DATE})[#{RUBY_PLATFORM}] / Tk#{$tk_patchlevel}#{(Tk::JAPANIZED_TK)? '-jp': ''}\n\n" +
+ "Ruby/Tk release date :: tcltklib #{TclTkLib::RELEASE_DATE}; tk #{Tk::RELEASE_DATE}")
+end
+
+####################################
+# °ú¿ô¤Ç»ØÄꤵ¤ì¤¿¥Ç¥â¤òµ¯Æ°¤¹¤ë
+no_launcher = false
+if ARGV[0] == '-n'
+ ARGV.shift
+ no_launcher = true if ARGV.size > 0
+else
+ # show the root widget to make it lower then demo windows
+ Tk.update
+end
+ARGV.each{|cmd|
+ if cmd =~ /(.*).rb/
+ cmd = $1
+ end
+ #eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join,
+ # _null_binding)
+ eval_samplecode(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join, cmd + '.rb')
+}
+if no_launcher
+ $root.withdraw # hide root window
+ Thread.start{
+ loop do
+ count = 0
+ $root.winfo_children.each{|w|
+ count += 1 if w.kind_of?(TkToplevel)
+ }
+ $root.destroy if count == 0
+ end
+ }
end
################################
diff --git a/ext/tk/sample/editable_listbox.rb b/ext/tk/sample/editable_listbox.rb
new file mode 100644
index 0000000000..99345da380
--- /dev/null
+++ b/ext/tk/sample/editable_listbox.rb
@@ -0,0 +1,69 @@
+#
+# Editable_TkListbox class
+#
+# When "DoubleClick-1" on a listbox item, the entry box is opend on the
+# item. And when hit "Return" key on the entry box after modifying the
+# text, the entry box is closed and the item is changed. Or when hit
+# "Escape" key, the entry box is closed without modification.
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+
+class Editable_TkListbox < TkListbox
+ def _ebox_placer(coord_y)
+ idx = self.nearest(coord_y)
+ x, y, w, h = self.bbox(idx)
+ @ebox.place(:x => 0, :relwidth => 1.0,
+ :y => y - self.selectborderwidth,
+ :height => h + 2 * self.selectborderwidth)
+ @ebox.pos = idx
+ @ebox.value = self.listvariable.list[idx]
+ @ebox.focus
+ end
+ private :_ebox_placer
+
+
+ def create_self(keys)
+ super(keys)
+
+ unless self.listvariable
+ self.listvariable = TkVariable.new(self.get(0, :end))
+ end
+
+ @ebox = TkEntry.new(self){
+ @pos = -1
+ def self.pos; @pos; end
+ def self.pos=(idx); @pos = idx; end
+ }
+
+ @ebox.bind('Return'){
+ list = self.listvariable.list
+ list[@ebox.pos] = @ebox.value
+ self.listvariable.value = list
+ @ebox.place_forget
+ @ebox.pos = -1
+ }
+
+ @ebox.bind('Escape'){
+ @ebox.place_forget
+ @ebox.pos = -1
+ }
+
+ self.bind('Double-1', '%y'){|y| _ebox_placer(y) }
+ end
+end
+
+if $0 == __FILE__
+ scr = TkScrollbar.new.pack(:side=>:right, :fill=>:y)
+
+ lbox1 = Editable_TkListbox.new.pack(:side=>:left)
+ lbox2 = Editable_TkListbox.new.pack(:side=>:left)
+
+ scr.assign(lbox1, lbox2)
+
+ lbox1.insert(:end, *%w(a b c d e f g h i j k l m n))
+ lbox2.insert(:end, 0,1,2,3,4,5,6,7,8,9,0,1,2,3)
+
+ Tk.mainloop
+end
diff --git a/ext/tk/sample/encstr_usage.rb b/ext/tk/sample/encstr_usage.rb
new file mode 100644
index 0000000000..b22c2504ac
--- /dev/null
+++ b/ext/tk/sample/encstr_usage.rb
@@ -0,0 +1,30 @@
+require 'tk'
+
+TkMessage.new(:width=>400, :text=><<EOM).pack
+This sample shows how to use Tk::EncodedString class. \
+This reads 'iso2022-kr' text (from discription of \
+Korean language environment of GNU Emacs 20.7.2) \
+and inserts the text into the text widget.
+EOM
+
+t1 = TkText.new(:height=>5).pack
+t2 = TkText.new(:height=>5).pack
+t3 = TkText.new(:height=>5).pack
+
+src_str = IO.readlines(File.join(File.dirname(__FILE__),'iso2022-kr.txt')).join
+
+t1.insert('end',
+ "use neither Tk::EncodedString class nor Tk.encoding= method\n\n")
+t1.insert('end', src_str)
+
+enc_str = Tk::EncodedString(src_str, 'iso2022-kr')
+t2.insert('end',
+ "use Tk::EncodedString class (Tk.encoding => '#{Tk.encoding}')\n\n")
+t2.insert('end', enc_str)
+
+Tk.encoding = 'iso2022-kr'
+t3.insert('end', "use Tk.encoding = 'iso2022-kr' (Tk.force_default_encoding? == #{Tk.force_default_encoding?})\n\n")
+
+t3.insert('end', src_str)
+
+Tk.mainloop
diff --git a/ext/tk/sample/figmemo_sample.rb b/ext/tk/sample/figmemo_sample.rb
new file mode 100644
index 0000000000..1b6979d2dd
--- /dev/null
+++ b/ext/tk/sample/figmemo_sample.rb
@@ -0,0 +1,456 @@
+#!/usr/bin/env ruby
+require 'tk'
+
+begin
+ # try to use Img extension
+ require 'tkextlib/tkimg'
+rescue Exception
+ # cannot use Img extention --> ignore
+end
+
+
+############################
+# scrolled_canvas
+class TkScrolledCanvas < TkCanvas
+ include TkComposite
+
+ def initialize_composite(keys={})
+ @h_scr = TkScrollbar.new(@frame)
+ @v_scr = TkScrollbar.new(@frame)
+
+ @canvas = TkCanvas.new(@frame)
+ @path = @canvas.path
+
+ @canvas.xscrollbar(@h_scr)
+ @canvas.yscrollbar(@v_scr)
+
+ TkGrid.rowconfigure(@frame, 0, :weight=>1, :minsize=>0)
+ TkGrid.columnconfigure(@frame, 0, :weight=>1, :minsize=>0)
+
+ @canvas.grid(:row=>0, :column=>0, :sticky=>'news')
+ @h_scr.grid(:row=>1, :column=>0, :sticky=>'ew')
+ @v_scr.grid(:row=>0, :column=>1, :sticky=>'ns')
+
+ delegate('DEFAULT', @canvas)
+ delegate('background', @canvas, @h_scr, @v_scr)
+ delegate('activebackground', @h_scr, @v_scr)
+ delegate('troughcolor', @h_scr, @v_scr)
+ delegate('repeatdelay', @h_scr, @v_scr)
+ delegate('repeatinterval', @h_scr, @v_scr)
+ delegate('borderwidth', @frame)
+ delegate('relief', @frame)
+
+ delegate_alias('canvasborderwidth', 'borderwidth', @canvas)
+ delegate_alias('canvasrelief', 'relief', @canvas)
+
+ delegate_alias('scrollbarborderwidth', 'borderwidth', @h_scr, @v_scr)
+ delegate_alias('scrollbarrelief', 'relief', @h_scr, @v_scr)
+
+ configure(keys) unless keys.empty?
+ end
+end
+
+############################
+class PhotoCanvas < TkScrolledCanvas
+
+USAGE = <<EOT
+--- WHAT IS ---
+You can write comments on the loaded image, and save it as a Postscipt
+file (original image file is not modified). Each comment is drawn as a
+set of an indicator circle, an arrow, and a memo text. See the following
+how to write comments.
+This can save the list of memo texts to another file. It may useful to
+search the saved Postscript file by the comments on them.
+This may not support multibyte characters (multibyte texts are broken on
+a Postscript file). It depends on features of canvas widgets of Tcl/Tk
+libraries linked your Ruby/Tk. If you use Tcl/Tk8.0-jp (Japanized Tcl/Tk),
+you can (possibly) get a Japanese Postscript file.
+
+--- BINDINGS ---
+* Button-1 : draw comments by following steps
+ 1st - Set center of a indicator circle.
+ 2nd - Set head position of an arrow.
+ 3rd - Set tail position of an arrow, and show an entry box.
+ Input a memo text and hit 'Enter' key to entry the comment.
+
+* Button-2-drag : scroll the canvas
+
+* Button-3 : when drawing, cancel current drawing
+
+* Double-Button-3 : delete the clicked comment (text, arrow, and circle)
+EOT
+
+ def initialize(*args)
+ super(*args)
+
+ self.highlightthickness = 0
+ self.selectborderwidth = 0
+
+ @photo = TkPhotoImage.new
+ @img = TkcImage.new(self, 0, 0, :image=>@photo)
+
+ width = self.width
+ height = self.height
+ @scr_region = [-width, -height, width, height]
+ self.scrollregion(@scr_region)
+ self.xview_moveto(0.25)
+ self.yview_moveto(0.25)
+
+ @col = 'red'
+ @font = 'Helvetica -12'
+
+ @memo_id_num = -1
+ @memo_id_head = 'memo_'
+ @memo_id_tag = nil
+ @overlap_d = 2
+
+ @state = TkVariable.new
+ @border = 2
+ @selectborder = 1
+ @delta = @border + @selectborder
+ @entry = TkEntry.new(self, :relief=>:ridge, :borderwidth=>@border,
+ :selectborderwidth=>@selectborder,
+ :highlightthickness=>0)
+ @entry.bind('Return'){@state.value = 0}
+
+ @mode = old_mode = 0
+
+ _state0()
+
+ bind('2', :x, :y){|x,y| scan_mark(x,y)}
+ bind('B2-Motion', :x, :y){|x,y| scan_dragto(x,y)}
+
+ bind('3'){
+ next if (old_mode = @mode) == 0
+ @items.each{|item| item.delete }
+ _state0()
+ }
+
+ bind('Double-3', :widget, :x, :y){|w, x, y|
+ next if old_mode != 0
+ x = w.canvasx(x)
+ y = w.canvasy(y)
+ tag = nil
+ w.find_overlapping(x - @overlap_d, y - @overlap_d,
+ x + @overlap_d, y + @overlap_d).find{|item|
+ ! (item.tags.find{|name|
+ if name =~ /^(#{@memo_id_head}\d+)$/
+ tag = $1
+ end
+ }.empty?)
+ }
+ w.delete(tag) if tag
+ }
+ end
+
+ #-----------------------------------
+ private
+ def _state0() # init
+ @mode = 0
+
+ @memo_id_num += 1
+ @memo_id_tag = @memo_id_head + @memo_id_num.to_s
+
+ @target = nil
+ @items = []
+ @mark = [0, 0]
+ bind_remove('Motion')
+ bind('ButtonRelease-1', proc{|x,y| _state1(x,y)}, '%x', '%y')
+ end
+
+ def _state1(x,y) # set center
+ @mode = 1
+
+ @target = TkcOval.new(self,
+ [canvasx(x), canvasy(y)], [canvasx(x), canvasy(y)],
+ :outline=>@col, :width=>3, :tags=>[@memo_id_tag])
+ @items << @target
+ @mark = [x,y]
+
+ bind('Motion', proc{|x,y| _state2(x,y)}, '%x', '%y')
+ bind('ButtonRelease-1', proc{|x,y| _state3(x,y)}, '%x', '%y')
+ end
+
+ def _state2(x,y) # create circle
+ @mode = 2
+
+ r = Integer(Math.sqrt((x-@mark[0])**2 + (y-@mark[1])**2))
+ @target.coords([canvasx(@mark[0] - r), canvasy(@mark[1] - r)],
+ [canvasx(@mark[0] + r), canvasy(@mark[1] + r)])
+ end
+
+ def _state3(x,y) # set line start
+ @mode = 3
+
+ @target = TkcLine.new(self,
+ [canvasx(x), canvasy(y)], [canvasx(x), canvasy(y)],
+ :arrow=>:first, :arrowshape=>[10, 14, 5],
+ :fill=>@col, :tags=>[@memo_id_tag])
+ @items << @target
+ @mark = [x, y]
+
+ bind('Motion', proc{|x,y| _state4(x,y)}, '%x', '%y')
+ bind('ButtonRelease-1', proc{|x,y| _state5(x,y)}, '%x', '%y')
+ end
+
+ def _state4(x,y) # create line
+ @mode = 4
+
+ @target.coords([canvasx(@mark[0]), canvasy(@mark[1])],
+ [canvasx(x), canvasy(y)])
+ end
+
+ def _state5(x,y) # set text
+ @mode = 5
+
+ if x - @mark[0] >= 0
+ justify = 'left'
+ dx = - @delta
+
+ if y - @mark[1] >= 0
+ anchor = 'nw'
+ dy = - @delta
+ else
+ anchor = 'sw'
+ dy = @delta
+ end
+ else
+ justify = 'right'
+ dx = @delta
+
+ if y - @mark[1] >= 0
+ anchor = 'ne'
+ dy = - @delta
+ else
+ anchor = 'se'
+ dy = @delta
+ end
+ end
+
+ bind_remove('Motion')
+
+ @entry.value = ''
+ @entry.configure(:justify=>justify, :font=>@font, :foreground=>@col)
+
+ ewin = TkcWindow.new(self, [canvasx(x)+dx, canvasy(y)+dy],
+ :window=>@entry, :state=>:normal, :anchor=>anchor,
+ :tags=>[@memo_id_tag])
+
+ @entry.focus
+ @entry.grab
+ @state.wait
+ @entry.grab_release
+
+ ewin.delete
+
+ @target = TkcText.new(self, [canvasx(x), canvasy(y)],
+ :anchor=>anchor, :justify=>justify,
+ :fill=>@col, :font=>@font, :text=>@entry.value,
+ :tags=>[@memo_id_tag])
+
+ _state0()
+ end
+
+ #-----------------------------------
+ public
+ def load_photo(filename)
+ @photo.configure(:file=>filename)
+ end
+
+ def modified?
+ ! ((find_withtag('all') - [@img]).empty?)
+ end
+
+ def fig_erase
+ (find_withtag('all') - [@img]).each{|item| item.delete}
+ end
+
+ def reset_region
+ width = @photo.width
+ height = @photo.height
+
+ if width > @scr_region[2]
+ @scr_region[0] = -width
+ @scr_region[2] = width
+ end
+
+ if height > @scr_region[3]
+ @scr_region[1] = -height
+ @scr_region[3] = height
+ end
+
+ self.scrollregion(@scr_region)
+ self.xview_moveto(0.25)
+ self.yview_moveto(0.25)
+ end
+
+ def get_texts
+ ret = []
+ find_withtag('all').each{|item|
+ if item.kind_of?(TkcText)
+ ret << item[:text]
+ end
+ }
+ ret
+ end
+end
+############################
+
+# define methods for menu
+def open_file(canvas, fname)
+ if canvas.modified?
+ ret = Tk.messageBox(:icon=>'warning',:type=>'okcancel',:default=>'cancel',
+ :message=>'Canvas may be modified. Realy erase? ')
+ return if ret == 'cancel'
+ end
+
+ filetypes = [
+ ['GIF Files', '.gif'],
+ ['GIF Files', [], 'GIFF'],
+ ['PPM Files', '.ppm'],
+ ['PGM Files', '.pgm']
+ ]
+
+ begin
+ if Tk::Img::package_version != ''
+ filetypes << ['JPEG Files', ['.jpg', '.jpeg']]
+ filetypes << ['PNG Files', '.png']
+ filetypes << ['PostScript Files', '.ps']
+ filetypes << ['PDF Files', '.pdf']
+ filetypes << ['Windows Bitmap Files', '.bmp']
+ filetypes << ['Windows Icon Files', '.ico']
+ filetypes << ['PCX Files', '.pcx']
+ filetypes << ['Pixmap Files', '.pixmap']
+ filetypes << ['SGI Files', '.sgi']
+ filetypes << ['Sun Raster Files', '.sun']
+ filetypes << ['TGA Files', '.tga']
+ filetypes << ['TIFF Files', '.tiff']
+ filetypes << ['XBM Files', '.xbm']
+ filetypes << ['XPM Files', '.xpm']
+ end
+ rescue
+ end
+
+ filetypes << ['ALL Files', '*']
+
+ fpath = Tk.getOpenFile(:filetypes=>filetypes)
+ return if fpath.empty?
+
+ begin
+ canvas.load_photo(fpath)
+ rescue => e
+ Tk.messageBox(:icon=>'error', :type=>'ok',
+ :message=>"Fail to read '#{fpath}'.\n#{e.message}")
+ end
+
+ canvas.fig_erase
+ canvas.reset_region
+
+ fname.value = fpath
+end
+
+# --------------------------------
+def save_memo(canvas, fname)
+ initname = fname.value
+ if initname != '-'
+ initname = File.basename(initname, File.extname(initname))
+ fpath = Tk.getSaveFile(:filetypes=>[ ['Text Files', '.txt'],
+ ['ALL Files', '*'] ],
+ :initialfile=>initname)
+ else
+ fpath = Tk.getSaveFile(:filetypes=>[ ['Text Files', '.txt'],
+ ['ALL Files', '*'] ])
+ end
+ return if fpath.empty?
+
+ begin
+ fid = open(fpath, 'w')
+ rescue => e
+ Tk.messageBox(:icon=>'error', :type=>'ok',
+ :message=>"Fail to open '#{fname.value}'.\n#{e.message}")
+ end
+
+ begin
+ canvas.get_texts.each{|txt|
+ fid.print(txt, "\n")
+ }
+ ensure
+ fid.close
+ end
+end
+
+# --------------------------------
+def ps_print(canvas, fname)
+ initname = fname.value
+ if initname != '-'
+ initname = File.basename(initname, File.extname(initname))
+ fpath = Tk.getSaveFile(:filetypes=>[ ['Postscript Files', '.ps'],
+ ['ALL Files', '*'] ],
+ :initialfile=>initname)
+ else
+ fpath = Tk.getSaveFile(:filetypes=>[ ['Postscript Files', '.ps'],
+ ['ALL Files', '*'] ])
+ end
+ return if fpath.empty?
+
+ bbox = canvas.bbox('all')
+ canvas.postscript(:file=>fpath, :x=>bbox[0], :y=>bbox[1],
+ :width=>bbox[2] - bbox[0], :height=>bbox[3] - bbox[1])
+end
+
+# --------------------------------
+def quit(canvas)
+ ret = Tk.messageBox(:icon=>'warning', :type=>'okcancel',
+ :default=>'cancel',
+ :message=>'Realy quit? ')
+ exit if ret == 'ok'
+end
+
+# --------------------------------
+# setup root
+root = TkRoot.new(:title=>'Fig Memo')
+
+# create canvas frame
+canvas = PhotoCanvas.new(root).pack(:fill=>:both, :expand=>true)
+usage_frame = TkFrame.new(root, :relief=>:ridge, :borderwidth=>2)
+hide_btn = TkButton.new(usage_frame, :text=>'hide usage',
+ :font=>{:size=>8}, :pady=>1,
+ :command=>proc{usage_frame.unpack})
+hide_btn.pack(:anchor=>'e', :padx=>5)
+usage = TkLabel.new(usage_frame, :text=>PhotoCanvas::USAGE,
+ :font=>'Helvetica 8', :justify=>:left).pack
+
+show_usage = proc{
+ usage_frame.pack(:before=>canvas, :fill=>:x, :expand=>true)
+}
+
+fname = TkVariable.new('-')
+f = TkFrame.new(root, :relief=>:sunken, :borderwidth=>1).pack(:fill=>:x)
+label = TkLabel.new(f, :textvariable=>fname,
+ :font=>{:size=>-12, :weight=>:bold},
+ :anchor=>'w').pack(:side=>:left, :fill=>:x, :padx=>10)
+
+# create menu
+mspec = [
+ [ ['File', 0],
+ ['Show Usage', proc{show_usage.call}, 5],
+ '---',
+ ['Open Image File', proc{open_file(canvas, fname)}, 0],
+ ['Save Memo Texts', proc{save_memo(canvas, fname)}, 0],
+ '---',
+ ['Save Postscript', proc{ps_print(canvas, fname)}, 5],
+ '---',
+ ['Quit', proc{quit(canvas)}, 0]
+ ]
+]
+root.add_menubar(mspec)
+
+# manage wm_protocol
+root.protocol(:WM_DELETE_WINDOW){quit(canvas)}
+
+# show usage
+show_usage.call
+
+# --------------------------------
+# start eventloop
+Tk.mainloop
diff --git a/ext/tk/sample/images/earth.gif b/ext/tk/sample/images/earth.gif
new file mode 100644
index 0000000000..2c229eb110
--- /dev/null
+++ b/ext/tk/sample/images/earth.gif
Binary files differ
diff --git a/ext/tk/sample/images/earthris.gif b/ext/tk/sample/images/earthris.gif
new file mode 100644
index 0000000000..c4ee473727
--- /dev/null
+++ b/ext/tk/sample/images/earthris.gif
Binary files differ
diff --git a/ext/tk/sample/demos-en/images/face.xbm b/ext/tk/sample/images/face.xbm
index 03d829f4d1..03d829f4d1 100644
--- a/ext/tk/sample/demos-en/images/face.xbm
+++ b/ext/tk/sample/images/face.xbm
diff --git a/ext/tk/sample/demos-en/images/flagdown.xbm b/ext/tk/sample/images/flagdown.xbm
index 55abc51825..55abc51825 100644
--- a/ext/tk/sample/demos-en/images/flagdown.xbm
+++ b/ext/tk/sample/images/flagdown.xbm
diff --git a/ext/tk/sample/demos-en/images/flagup.xbm b/ext/tk/sample/images/flagup.xbm
index 6eb0d846a3..6eb0d846a3 100644
--- a/ext/tk/sample/demos-en/images/flagup.xbm
+++ b/ext/tk/sample/images/flagup.xbm
diff --git a/ext/tk/sample/demos-en/images/gray25.xbm b/ext/tk/sample/images/gray25.xbm
index b234b3cb0b..b234b3cb0b 100644
--- a/ext/tk/sample/demos-en/images/gray25.xbm
+++ b/ext/tk/sample/images/gray25.xbm
diff --git a/ext/tk/sample/demos-en/images/grey.25 b/ext/tk/sample/images/grey.25
index b234b3cb0b..b234b3cb0b 100644
--- a/ext/tk/sample/demos-en/images/grey.25
+++ b/ext/tk/sample/images/grey.25
diff --git a/ext/tk/sample/demos-en/images/grey.5 b/ext/tk/sample/images/grey.5
index 37688893f0..37688893f0 100644
--- a/ext/tk/sample/demos-en/images/grey.5
+++ b/ext/tk/sample/images/grey.5
diff --git a/ext/tk/sample/demos-en/images/letters.xbm b/ext/tk/sample/images/letters.xbm
index 0f12568d1a..0f12568d1a 100644
--- a/ext/tk/sample/demos-en/images/letters.xbm
+++ b/ext/tk/sample/images/letters.xbm
diff --git a/ext/tk/sample/demos-en/images/noletter.xbm b/ext/tk/sample/images/noletter.xbm
index 5774124efe..5774124efe 100644
--- a/ext/tk/sample/demos-en/images/noletter.xbm
+++ b/ext/tk/sample/images/noletter.xbm
diff --git a/ext/tk/sample/demos-en/images/pattern.xbm b/ext/tk/sample/images/pattern.xbm
index df31baf789..df31baf789 100644
--- a/ext/tk/sample/demos-en/images/pattern.xbm
+++ b/ext/tk/sample/images/pattern.xbm
diff --git a/ext/tk/sample/images/tcllogo.gif b/ext/tk/sample/images/tcllogo.gif
new file mode 100644
index 0000000000..4603d4ff41
--- /dev/null
+++ b/ext/tk/sample/images/tcllogo.gif
Binary files differ
diff --git a/ext/tk/sample/images/teapot.ppm b/ext/tk/sample/images/teapot.ppm
new file mode 100644
index 0000000000..b8ab85f3a5
--- /dev/null
+++ b/ext/tk/sample/images/teapot.ppm
@@ -0,0 +1,31 @@
+P6
+256 256
+255
+\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À[7 eOLjQLmSMoTMnSMlRMhPL_9 \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀnSMtVMzYN~[N~[N\N\O€\O€]O€]O€]O€]O€\O€\O}[NyYNtVM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-wXN}[N€]O„^O†_O†`O‡`Oˆ`Oˆ`OˆaO‰aO‰aO‰aO‰aO‰aO‰aOˆaOˆ`O†_Oƒ^O\N \À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀaMLyYN…_O‰aP‹bPcPŽcPŽdPŽdPdPdPdPdPdPdPdPeP‘eP’eP’eP‘ePdPcP…_OpUM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀwXN…_OdP“fP•gQ–hQ˜hQ˜iQ™iQ™iQšiQšiQšjQ›jQ›jQœjQœjQœjQœjQœjQ›jQœjQ™iQ“fP‡`O\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJiQL‹bP—hQkQ¡mR¤nR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¦pR¨pS©qSªqS«rS¬rS«rS©qS¤oRœjQ€]O\KK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀfOLrUMcPŸlR©qS¯tS²uTµwT·xT¸xT¹yTºyT»zT»zU¼zU¼zU¼zU»zUºyT¸xT¶wT¯tS¡mR‰aOhPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\Àa0 cNLqUM€\O”fQ¦pS²wVºzV¿|VÂ}VÄVÆVÇ€VÉ‚WÌ…[Õeæ w÷³‹êª…Ĉg§qT“fQ{ZNYIK9\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀO1{G#‘JkRMqUMtVN–iS¨v\·€d¹bµzZ±vU°uT®sSªqS¤nRœjQ’eP„^OrUMHh>!T4\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀG-V5wE"~I#†M%U+¥e7²l:°g2®b*­a(­`(©^(¥])¡^-›]1ŠS,qC$`9 R3G-\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À@)J/i>!pA"tD"wF$yH&xH&tE$wE#yG%}M+ƒT4S5mE*Z7!K/B*;'\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À‰aO¦oR½{UÇ€VÏ…X<(F-a: e<!h>!j@#k@$h>"d<!c=$hD-fF2[<)K0@);'5$Ë‚VÇ€V¿|U_LKYIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À…_O·xTÉ‚Wó«€ûµ‹Ö’k¼|X×>µf-¨^(¡Z'šW&–T&œN>)F-J/b; g>#nD(jB&c<!b=%jH2_A/I0!<(8&5$”J¥Y’S%8&;'?)E,<:HA=HE?IJAISFJYIKXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À£nRÁ}UܘqÊŠe±vU²e,™V&¥V†C €@ |> y< u: r9 o7 l6
+j5
+h4
+g3
+5$D,K/b; h>"wM1tK.e="a<#cA,U8&E-<(9&.!a0 b1 c1    
+
++3#@)46G<:HMCIXHK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀU*´vT¿~X¸{YÃk+›W&‰N$|> u: p8 k5
+f3
+a0 _/ ]. [- I¡\*ª_(‘LkRMmSMmSMnSMnSMD,R3W5mA"|O0|P1j?"c<!a=%Y7"N1F,;'NCJNCJNDJODJODJODJh>!a: X/K%
+g3
+a0 Z- \/ T*Q(ŠHµm8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5^9 d<!yF#O+€N,rC#qB"pB#k?"a: Z7 6ODJPDJPEJQEJQEJREJREJREJRFJSFJSFJSFJSFJe<!X/
+^/ V+Q(L&I$r9  TlRMnSM46G47G47G46G46G46G46G46G36G36G25G25G15G04G/4F.3F
+
+X&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?<H@<HA=HC>HG@ILBIREJ[JKcNLjQL§pR±uTºzUÃ~VÈWË‚XÖŽcäsÒŽe¼{V²vT¨pSžkR•gQŒbP†_O‚^O]O€\O€\O€\O€\O€]O]O]O]O]O]O]O]O]O]O]O€\O€\O~\N}[N|ZNxXN•T%H$
+›W&rVMvWNyYNzYN|ZN}[N}[N><H?<H?<H?<H?<H?<H@<H@<H@<HA=HA=HB=HC>HE?IG@IIAIKBIODJSFJWHK—hQŸlR§pR°b(¾i*Én+Ù|7Û|6Ïr,Íq+Êp-Ãl+»g)±b(®sS§pS lRšiQ•gQePcPŠaPˆaO‡`O‡`O†_O†_O…_O…_O…_O…_O…_O…_O…_O„_O„^O„^Oƒ^Oƒ^O‚]O]O€\O~[N{ZN•T%
+
+ 
+@%<-$G?@…pfdNLuWM\NdNL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀTFJvWN‰aP./01„E}[N]O…_Oˆ`O‰aP‹bPŒbPcPcPŽcPdPdPdPeP‘eP’eP’eP“fP“fQ”fQ•gQ•gQ–gQ–hQ—hQ˜hQ™iQšiQ›jQœjQkQkRžlRŸlRžY&¤\'¨^'µ^½bÀcÃeÇi ÄgÀc½b¼a¹`µ^´]¯X¢[' Z'žY&¢mR¡mR¡mR lRŸlRŸlRžkRkQœkQœjQ›jQšjQšiQ™iQ™iQ˜iQ˜hQ—hQ—hQ—hQ–gQ–gQ•gQ•gQ•gQ”fQ”fQ“fQ“fP’eP‘ePdPcP‰aP—O
+ B\À\À\À\À\À\À\À\À\À\À%7!!C*F#P) {dYœze»p€\OgPL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ`LKvWNŠaPm6
+ 
+$5 ¬`(¶e)£nRœjQƒ^OJAI\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀXIK^KKdNLhPLuWM‚]OŒbP”fQeP m6
+†`OŽcP“fQ—hQ˜hQ™iQšiQšjQ›jQ›jQ›jQœjQœjQœjQœkQkQkQkRžkRžkRžkRžlRŸlRŸlRŸlR lR lR lR¡mR¡mR¡mR¡mRºg)³c(²c(±b(­V¿cÂeÅi!Åi!Àd¼bº`¹`·_·_¶^¢Q§]'ª_(­`(¹f)£nR£nR£nR£nR£nR£nR£nR¢nR¢nR¢nR¢nR¢nR¢nR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢mR¢nR¢mR¢mR£nR¢mR¢mR¡mR mRkR—hQˆGa0 ŠbP mRœjQ“fQ‰aP}[NrUMmSM…L$\À\À\À\À\À\À\À\À B B #C, 8&H.Z7 §pR›jQ{ZN\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀQEJ[JK`LKdNLhQLqUM{ZN…_OŽcP–gQ—hQ
+‹bP‘eP–hQšiQ›jQœjQkQkQkRžkRžkRžlRžlRŸlRŸlRŸlRŸlRŸlR lR lR lR mR¡mR¡mR¡mR¡mR¡mR¢mR¢mR¢mR¢nR£nRÀj*ºg)·e)¶d)Âd°XÅgÅhÂe¿c½b½b¾bªU­`(®a(¯a(³c(¾i*¤oR¤oR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤nR¤oR¤oR¥oR¥oR¥oR¥oR¥oR¥oR¦oR¦oR¥oR¥oR¤nR¡mR›jQŽQ%Z- œjQ£nRŸlR—hQŽdP…_OuWMpTMnSMkRLa: \À\À\À\À\À\À\À B B&D2 @*S6#G@IPDJ˜hQmSM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ]KKbMLeOLiQLlRMvWN\OˆaO‘eP—hQœjQ•gQ
+!C+E'0F.4F7%8%U/lG.SFJZIK]KKZIKB=H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀREJZJK`LKdNLgPLjQLlRMnSMpTMqUMtWMxXN{ZN~[N]O„^O†`O‰aO‹bPdP•gQ™iQœkQ lR¤nR§pSªrS­sS¯tT²uT´vT¶wT·xT¹yT¹yTºyTºyT¹yT¶xT´vT¬rS¢nR—hQ¿|U¿|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ|UÀ}UÀ}UÁ}UÁ}UÁ}UÁ}UÂ}UÂ~UÃ~UÃ~VÃ~VÄVÅ€WÆX®a(ŸlRªrS´vT¸yT¼zU¾|UÁ~VÃXÆ‚[Ɇ_΋dÓ‘jÔ“mÔ“nБlÊŒhĆd½_¶{[°vWªsU¦pS¢nRžkRšiQ˜hQ•gQ“fQ‘ePdPŒbP‰aO†_Oƒ^O€\O|ZNxXNsVMpTMnTMmSMjQL€C B)D&/F-3F47G6%>" Y7 kA$YIK]KK^KKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀVGJ\KKbMLeOLhPLkRLmSMnTMpTMrUMuWNyYN|ZN\N‚]O„_O‡`OŠaPŒbPŽcPeP“fP—hQ›jQžlR¢nR¥oS©qT¬sT¯uU²vU´wV¶xV¸yV¹yUºzU»zU¼{U½{U¾{U¾|U¿|U¿|U¿|U¿|U¾{U½{U¼{U¼zU»zTºyT¹yT¸xTµwT³vT´vT´vT´vT´wT´wTµwT·xT¹yTºzT¼zU½{U¾{U¿|UÀ|UÂ}UÄVÅ€WÇ‚YÉ„\͈_ÑŒdÙ”láuç£|쩂ſt명æ¦ÞŸ{Õ—sËŽl†d¹^³yZ­uW¨qU¤oSŸlRžkRœjQšiQ˜hQ–gQ”fQ‘ePdPcPŠaP‡`O„^O]O}[NyYNuWMpTMoTMmSMkRLgPL&D#.E,3F46G;'<(D"iB(VGJ]KK`LK[JKB>H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRMmSMoTMqUMsVMvXNzYN}[N€\O‚^O…_Oˆ`OŠaPŒcPdP‘eP“fQ•gQ—hQ™iQkR mS¤oT¨rU¬tW°wY´zZ¸}\»]¾€^À^Á‚^‚^Â\Á€ZÁYÁXÁ~WÁ~WÂ~VÂ~VÂ~VÃ~VÃ~UÃ~UÄ~UÄ~UÄUÄUÅVÅVÅVÅVÆVÆ€VÆ€VÇ€WÇWÈ‚XɃZË…[͇^ЊaÓdØ’iÜ—nâtè£zî©ó¯‡ø´û¸‘üº“û¹“÷¶ñ±Œé©…à¡~Ö˜vËmÇf»€`´z[®vX©rU¥pT£oS¢nS lRžkRœkRšjQ˜iQ–hQ”fQ’ePdPcP‹bPˆ`O…_O‚]O~[NzYNvWNpTMoTMnSMkRMhQLo7 ,2F36G99HC+@ ]8 nA"\JK`ML_LKSFJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMpTMqUMtVMwXNzZN}[N€]Oƒ^O†_OˆaO‹bPcPdP‘eP“fQ•gQ—hQ™iQ›jRžlR mS£oU§rW¬vZ²{]¹€a¿…fÅŠjËnГqÓ•sÕ–sÕ–rÕ–qÕ”oÓ’mÑjÏgÍŠcˈaɆ^È„\Ç‚[ÆYÅ€XÅ€WÅWÅWÅVÅVÅWÅ€WÆ€WÇXÈ‚YɃ[Ê…\͇_ÏŠaÒeÕ‘hÙ•mÝ™qávä¡zç¤}꧀멃몄騃奀ߠ|Ù›wÓ•rÌmƉh¿„c¸~^²yZ®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRœkR›jQ™iQ—hQ•gQ“fPePŽcP‹bPˆaO…_O‚^O\N{ZNwXNsVMoTMnSMlRMiQL~I#26G99G?<HA*E$ i@$ZIKaMLbML[JK;:H\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀWHJ]KKbMLeOLhPLjRLlSMnTMpTMrUMuWMxXN{ZN~\N]O„^O†`O‰aO‹bPŽcPdP’eP”fQ–gQ˜hQšiQœkRžlS mT£oU¦rWªuZ¯y]´~aºƒfŠlË’sÔšzÜ¡€ã§†è«‰ë®‹í¯Œí®‹ë¬ˆè¨„ã£~ßžyÚ™tÖ•oÒjÎŒfˈbÈ…_ƃ\ÅZÄ€YÃXÂWÂ~WÂ~WÂ~WÃXÀXÄ€YÅZƃ\Ç…^Ɇ`ˈbÌŠdÍ‹fÎgÎŽiÎŽjÎŽjÍŽjËŒiljgÆd¿ƒaº^¸}]¶|\´{[²yZ°xY®vX¬tWªsV¨qU¦pT¤oS¢nS mRžlRkR›jQ™iQ—hQ•gQ“fP‘ePŽdPŒbP‰aO†_Oƒ^O€\O|ZNxXNtVMpTMnSMmSMjQLgPL99G?<HG-E&b;!YIK`MLdOM`LKNCJ\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀŸlRºyTÄ~UÊ‚XʃYÄXº{W­tUšW'¢[(—hQ lRcP€\OhQL\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀNCJYIK^LKcNLfOLiQLkRLmSMoTMqUMrVMvWNyYN|ZN\N‚]O„_O‡`O‰aPŒbPŽcPdP’fP”gQ–hQ˜iQšjRœkRžlS¡nT¤pU§sW«vZ°z]µb»„gŠlÉ‘sИyØžÞ¤…㩊è­ì±ï³‘ﳑ뭊穅⣀ݞzؘtÒ“nÎiɉdÆ…`Â]Á€[¿~Y¾}X½|W½|V¼{V¼{V¼{V¼{V¼{V¼|W¼|W½}X½}Y½~Z½~Z¼~Z»}[º}[º}[º~\º~\º~]º~]¹~]¸~]·}]¶|\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS mRŸlRkR›jQšiQ˜hQ–gQ“fQ‘ePdPŒcPŠaP‡`O„^O]O}[NyYNuWNpTMnTMmSMkRLhPL|H$D>IQ2P+XHK_LLfQOcNLXIK\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À©qSºyTÃ~VΈ`遲ޜv¾€]ªqS–LŽG|> g3
+S)?*%.—hQ—hQ‘eP‡`OuWM\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\ÀSFJ[JK`LKdNLgPLjQLlRMnSMoTMqUMsVMwXNzYN}[N€\O‚^O…_O‡`OŠaPŒbPŽdP‘eP“fP•gQ—hQ˜iQšjRœkRŸlS¡nT¤pV§sX«vZ°z^¶b¼…gËmÊ’sјzØŸ€Þ¤…㩊è­ê¯ë°ê¯Žè¬‹å¨‡à¤‚Ûž|Ö™wÑ“qÌŽlljgÃ…bÀ‚_½\»}Zº{X¹zW¸yV·yU·xU·xU·xT·xT·xU·xU·xU·yV·yV·yW¸zW¸{X¹{Y¹|Zº}[º}[º}\º~\¹~]¹~]¸}]·|\µ{\´z[²yZ°wY®vX¬tWªsV¨rU¦pT¤oS¢nS¡mRŸlRkRœjQšiQ˜hQ–gQ”fQ’ePdPcPŠbP‡`O…_O‚]O~[NzZNvWNrUMoTMmSMlRMiQLeOLJAIJ(h>!]KKfQOgQN_LKD>I\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À\À™iQ°tS¸yT¼{UÂYÎŒeï­ˆô´Õ—u¶|\ Z'™LˆD |>
+
+ &3#.$-% .% .& /&!,#,#@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+"(!'
+ %' %$#" ! !$ 
diff --git a/ext/tk/sample/irbtk.rb b/ext/tk/sample/irbtk.rb
new file mode 100644
index 0000000000..53ef10d0d1
--- /dev/null
+++ b/ext/tk/sample/irbtk.rb
@@ -0,0 +1,30 @@
+#!/usr/local/bin/ruby
+#
+# irbtk.rb - irb with Ruby/Tk
+#
+# If you want to use 'multi-tk.rb', give option '--multi-tk'.
+# And if you want to use 'remote-tk.rb', give option '--remote-tk'.
+# If you want both, you don't need to give both options, because
+# 'remote-tk.rb' includes 'multi-tk.rb'.
+# ( There is no trouble even if you give both options. )
+#
+require 'remote-tk' if ARGV.delete('--remote-tk')
+require 'multi-tk' if ARGV.delete('--multi-tk')
+
+require "tk"
+module Tk
+ MAINLOOP = Thread.new{ mainloop }
+end
+
+require "irb"
+
+if __FILE__ == $0
+ IRB.start(__FILE__)
+else
+ # check -e option
+ if /^-e$/ =~ $0
+ IRB.start(__FILE__)
+ else
+ IRB.setup(__FILE__)
+ end
+end
diff --git a/ext/tk/sample/irbtkw.rbw b/ext/tk/sample/irbtkw.rbw
new file mode 100644
index 0000000000..3fb6dde626
--- /dev/null
+++ b/ext/tk/sample/irbtkw.rbw
@@ -0,0 +1,146 @@
+#!/usr/bin/env ruby
+#
+# irbtkw.rb : IRB console with Ruby/Tk
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+release = '2008/03/08'
+
+require 'tk'
+begin
+ require 'tktextio'
+rescue LoadError
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'tktextio.rb')
+end
+
+require 'irb'
+
+if TkCore::WITH_ENCODING
+else
+ # $KCODE setup
+ case Tk.encoding
+ when 'shiftjis', 'cp932'
+ $KCODE='SJIS'
+ when 'euc-jp'
+ $KCODE='EUC'
+ when 'utf-8', 'unicode'
+ $KCODE='UTF8'
+ else
+ # unknown
+ end
+end
+
+# console setup
+top = TkToplevel.new(:title=>'IRB console')
+top.protocol(:WM_DELETE_WINDOW){ Tk.exit }
+
+case (Tk.windowingsystem)
+when 'win32'
+ fnt = ['MS Gothic', '-12']
+else
+ fnt = ['courier', '-12']
+end
+
+console = TkTextIO.new(top, :mode=>:console,
+ :width=>80).pack(:side=>:left,
+ :expand=>true, :fill=>:both)
+console.yscrollbar(TkScrollbar.new(top, :width=>10).pack(:before=>console,
+ :side=>:right,
+ :expand=>false,
+ :fill=>:y))
+irb_thread = nil
+ev_loop = Thread.new{
+ Tk.mainloop
+ irb_thread.kill if irb_thread
+}
+
+# window position control
+root = Tk.root
+
+r_x = root.winfo_rootx
+r_y = root.winfo_rooty
+r_w = root.winfo_width
+
+t_x = top.winfo_rootx
+t_y = top.winfo_rooty
+t_w = top.winfo_width
+
+delta = 10
+
+ratio = 0.8
+s_w = (ratio * root.winfo_screenwidth).to_i
+
+if r_x < t_x
+ r_x, t_x = t_x, r_x
+end
+if t_x + t_w + r_w + delta < s_w
+ r_x = t_x + t_w + delta
+elsif t_w + r_w + delta < s_w
+ r_x = s_w - r_w
+ t_x = r_x - t_w
+else
+ r_x = s_w - r_w
+ t_x = 0
+end
+
+root.geometry("+#{r_x}+#{r_y}")
+top.geometry("+#{t_x}+#{t_y}")
+
+root.raise
+console.focus
+
+# I/O setup
+$stdin = console
+$stdout = console
+$stderr = console
+
+# dummy for rubyw.exe on Windows
+def STDIN.tty?
+ true
+end
+
+# IRB setup
+IRB.init_config(nil)
+IRB.conf[:USE_READLINE] = false
+IRB.init_error
+irb = IRB::Irb.new
+IRB.conf[:MAIN_CONTEXT] = irb.context
+
+class IRB::StdioInputMethod
+ def gets
+ prompt = "\n" << @prompt
+ $stdin.instance_eval{
+ flush
+ @prompt = prompt
+ _set_console_line
+ @prompt = nil
+ _see_pos
+ }
+
+ @line[@line_no += 1] = $stdin.gets
+ end
+end
+
+# IRB start
+$stdout.print("*** IRB console on Ruby/Tk (#{release}) ")
+irb_thread = Thread.new{
+ catch(:IRB_EXIT){
+ loop {
+ begin
+ irb.eval_input
+ rescue Exception
+ end
+ }
+ }
+}
+
+console.bind('Control-c'){
+ console.insert('end', "^C\n")
+ irb_thread.raise RubyLex::TerminateLineInput
+}
+
+irb_thread.join
+
+# exit
+ev_thread.kill
+Tk.exit
diff --git a/ext/tk/sample/iso2022-kr.txt b/ext/tk/sample/iso2022-kr.txt
new file mode 100644
index 0000000000..2e3fe6ea2a
--- /dev/null
+++ b/ext/tk/sample/iso2022-kr.txt
@@ -0,0 +1,2 @@
+Sample text:
+$)C Hangul (GQ1[) >H3gGO<<?d, >H3gGO=J4O1n
diff --git a/ext/tk/sample/menubar1.rb b/ext/tk/sample/menubar1.rb
new file mode 100644
index 0000000000..9fa1201d41
--- /dev/null
+++ b/ext/tk/sample/menubar1.rb
@@ -0,0 +1,51 @@
+#
+# menubar sample 1 : use frame and menubuttons
+#
+
+require 'tk'
+
+radio_var = TkVariable.new('y')
+
+menu_spec = [
+ [['File', 0],
+ {:label=>'Open', :command=>proc{puts('Open clicked')}, :underline=>0},
+ '---',
+ ['Check_A', TkVariable.new(true), 6],
+ {:type=>'checkbutton', :label=>'Check_B',
+ :variable=>TkVariable.new, :underline=>6},
+ '---',
+ ['Radio_X', [radio_var, 'x'], 6, '', {:foreground=>'black'}],
+ ['Radio_Y', [radio_var, 'y'], 6],
+ ['Radio_Z', [radio_var, 'z'], 6],
+ '---',
+ ['cascade', [
+ ['sss', proc{p 'sss'}, 0],
+ ['ttt', proc{p 'ttt'}, 0],
+ ['uuu', proc{p 'uuu'}, 0],
+ ['vvv', proc{p 'vvv'}, 0],
+ ],
+ 0, '',
+ {:font=>'Courier 16 italic',
+ :menu_config=>{:font=>'Times -18 bold', :foreground=>'black'}}],
+ '---',
+ ['Quit', proc{exit}, 0]],
+
+ [['Edit', 0],
+ ['Cut', proc{puts('Cut clicked')}, 2],
+ ['Copy', proc{puts('Copy clicked')}, 0],
+ ['Paste', proc{puts('Paste clicked')}, 0]],
+
+ [['Help', 0, {:menu_name=>'help'}],
+ ['About This', proc{puts('Ruby/Tk menubar sample 1')}, 6]]
+]
+
+menubar = TkMenubar.new(nil, menu_spec,
+ 'tearoff'=>false,
+ 'foreground'=>'grey40',
+ 'activeforeground'=>'red',
+ 'font'=>'Helvetia 12 bold')
+menubar.pack('side'=>'top', 'fill'=>'x')
+
+TkText.new(:wrap=>'word').pack.insert('1.0', 'Please read the sample source, and check how to override default configure options of menu entries on a menu_spec. Maybe, on windows, this menubar does not work properly about keyboard shortcuts. Then, please use "menu" option of root/toplevel widget (see sample/menubar2.rb).')
+
+Tk.mainloop
diff --git a/ext/tk/sample/menubar2.rb b/ext/tk/sample/menubar2.rb
new file mode 100644
index 0000000000..4507d8b2fe
--- /dev/null
+++ b/ext/tk/sample/menubar2.rb
@@ -0,0 +1,56 @@
+#
+# menubar sample 2 : use 'menu' option of root/toplevel widget
+#
+
+require 'tk'
+
+radio_var = TkVariable.new('y')
+
+menu_spec = [
+ [['File', 0],
+ {:label=>'Open', :command=>proc{puts('Open clicked')}, :underline=>0},
+ '---',
+ ['Check_A', TkVariable.new(true), 6],
+ {:type=>'checkbutton', :label=>'Check_B',
+ :variable=>TkVariable.new, :underline=>6},
+ '---',
+ ['Radio_X', [radio_var, 'x'], 6, '', {:foreground=>'black'}],
+ ['Radio_Y', [radio_var, 'y'], 6],
+ ['Radio_Z', [radio_var, 'z'], 6],
+ '---',
+ ['cascade', [
+ ['sss', proc{p 'sss'}, 0],
+ ['ttt', proc{p 'ttt'}, 0],
+ ['uuu', proc{p 'uuu'}, 0],
+ ['vvv', proc{p 'vvv'}, 0],
+ ],
+ 0, '',
+ {:font=>'Courier 16 italic',
+ :menu_config=>{:font=>'Times -18 bold', :foreground=>'black'}}],
+ '---',
+ ['Quit', proc{exit}, 0]],
+
+ [['Edit', 0],
+ ['Cut', proc{puts('Cut clicked')}, 2],
+ ['Copy', proc{puts('Copy clicked')}, 0],
+ ['Paste', proc{puts('Paste clicked')}, 0]],
+
+ [['Help', 0, {:menu_name=>'help'}],
+ ['About This', proc{puts('Ruby/Tk menubar sample 2')}, 6]]
+]
+
+mbar = Tk.root.add_menubar(menu_spec,
+ # followings are default configure options
+ 'tearoff'=>'false',
+ 'foreground'=>'grey40',
+ 'activeforeground'=>'red',
+ 'font'=>'Helvetia 12 bold')
+# This (default configure options) is NOT same the following.
+#
+# mbar = Tk.root.add_menubar(menu_spec)
+# mbar.configure('foreground'=>'grey40', 'activeforeground'=>'red',
+# 'font'=>'Helvetia 12 bold')
+
+TkText.new(:wrap=>'word').pack.insert('1.0', 'Please read the sample source, and check how to override default configure options of menu entries on a menu_spec.')
+
+Tk.mainloop
diff --git a/ext/tk/sample/msgs_rb/README b/ext/tk/sample/msgs_rb/README
new file mode 100644
index 0000000000..2e3ff2a9c4
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/README
@@ -0,0 +1,3 @@
+Message catalogs in this directory depend on Tcl/Tk's message catalogs.
+Texts of each locale are copied from Tcl/Tk8.5a1 widget demos.
+Please refer '../msgs_tk/README'.
diff --git a/ext/tk/sample/msgs_rb/cs.msg b/ext/tk/sample/msgs_rb/cs.msg
new file mode 100644
index 0000000000..199f2a73bd
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/cs.msg
@@ -0,0 +1,84 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ cs "Application Error", "Chyba programu"
+ cs "Blue", "Modr\341"
+ cs "Color", "Barva"
+ cs "Delete", "Smazat"
+ cs "Error", "Chyba"
+ cs "Exit", "Konec"
+ cs "Green", "Zelen\341"
+ cs "Red", "\\u010cerven\341"
+ cs "blue", "modr\341"
+ cs "green", "zelen\341"
+ cs "red", "\\u010derven\341"
+}
+
+TkMsgCatalog.new('::tk') {
+ cs "&Abort", "&P\\u0159eru\\u0161it"
+ cs "About...", "O programu..."
+ cs "All Files", "V\\u0161echny soubory"
+ cs "Application Error", "Chyba programu"
+ cs "&Blue", "&Modr\341"
+ cs "&Cancel", "&Zru\\u0161it"
+ cs "Cannot change to the directory \"%1\$s\".\nPermission denied.", "Nemohu zm\\u011bnit atku\341ln\355 adres\341\\u0159 na \"%1\$s\".\nP\\u0159\355stup odm\355tnut."
+ cs "Choose Directory", "V\375b\\u011br adres\341\\u0159e"
+ cs "Clear", "Smazat"
+ cs "Color", "Barva"
+ cs "Console", "Konzole"
+ cs "Copy", "Kop\355rovat"
+ cs "Cut", "Vy\\u0159\355znout"
+ cs "Delete", "Smazat"
+ cs "Details >>", "Detaily >>"
+ cs "Directory \"%1\$s\" does not exist.", "Adres\341\\u0159 \"%1\$s\" neexistuje."
+ cs "&Directory:", "&Adres\341\\u0159:"
+ cs "Error: %1\$s", "Chyba: %1\$s"
+ cs "Exit", "Konec"
+ cs "File \"%1\$s\" already exists.\n\n", "Soubor \"%1\$s\" ji\\u017e existuje.\n\n"
+ cs "File \"%1\$s\" already exists.\nDo you want to overwrite it?", "Soubor \"%1\$s\" ji\\u017e existuje.\nChcete jej p\\u0159epsat?"
+ cs "File \"%1\$s\" does not exist.", "Soubor \"%1\$s\" neexistuje."
+ cs "File &name:", "&Jm\351no souboru:"
+ cs "File &names:", "&Jm\351na soubor\\u016f:"
+ cs "Files of &type:", "&Typy soubor\\u016f:"
+ cs "Fi&les:", "Sou&bory:"
+ cs "&Filter", "&Filtr"
+ cs "Fil&ter:", "Fil&tr:"
+ cs "&Green", "Ze&len\341"
+ cs "Hi"
+ cs "Hide Console", "Skr\375t konsolu"
+ cs "&Ignore", "&Ignorovat"
+ cs "Invalid file name \"%1\$s\".", "\\u0160patn\351 jm\351no souboru \"%1\$s\"."
+ cs "Log Files", "Log soubory"
+ cs "&No", "&Ne"
+ cs "&OK"
+ cs "Ok"
+ cs "Open", "Otev\\u0159\355t"
+ cs "&Open", "&Otev\\u0159\355t"
+ cs "Open Multiple Files", "Otev\\u0159\355t v\355ce soubor\\u016f"
+ cs "Paste", "Vlo\\u017eit"
+ cs "Quit", "Skon\\u010dit"
+ cs "&Red", " \\u010ce&rven\341"
+ cs "Replace existing file?", "Nahradit st\341vaj\355c\355 soubor?"
+ cs "&Retry", "Z&novu"
+ cs "&Save", "&Ulo\\u017eit"
+ cs "Save As", "Ulo\\u017eit jako"
+ cs "Save To Log", "Ulo\\u017eit do logu"
+ cs "Select Log File", "Vybrat log soubor"
+ cs "Select a file to source", "Vybrat soubor k nahr\341n\355"
+ cs "&Selection:", "&V\375b\\u011br:"
+ cs "Skip Messages", "P\\u0159esko\\u010dit zpr\341vy"
+ cs "Source...", "Nahr\341t..."
+ cs "Tcl Scripts", "Tcl skripty"
+ cs "Tcl for Windows", "Tcl pro Windows"
+ cs "Text Files", "Textov\351 soubory"
+ cs "&Yes", "&Ano"
+ cs "abort", "p\\u0159eru\\u0161it"
+ cs "blue", "modr\341"
+ cs "cancel", "zru\\u0161it"
+ cs "extension", "p\\u0159\355pona"
+ cs "extensions", "p\\u0159\355pony"
+ cs "green", "zelen\341"
+ cs "ignore", "ignorovat"
+ cs "ok"
+ cs "red", "\\u010derven\341"
+ cs "retry", "znovu"
+ cs "yes", "ano"
+}
diff --git a/ext/tk/sample/msgs_rb/de.msg b/ext/tk/sample/msgs_rb/de.msg
new file mode 100644
index 0000000000..283874df42
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/de.msg
@@ -0,0 +1,88 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ de "Application Error", "Applikationsfehler"
+ de "Blue", "Blau"
+ de "Color", "Farbe"
+ de "Delete", "L\\u00f6schen"
+ de "Error", "Fehler"
+ de "Exit", "Ende"
+ de "Green", "Gr\\u00fcn"
+ de "Red", "Rot"
+ de "blue", "blau"
+ de "green", "gr\\u00fcn"
+ de "red", "rot"
+}
+
+TkMsgCatalog.new('::tk') {
+ de "&Abort", "&Abbruch"
+ de "&About...", "&\\u00dcber..."
+ de "All Files", "Alle Dateien"
+ de "Application Error", "Applikationsfehler"
+ de "&Blue", "&Blau"
+ de "&Cancel", "&Abbruch"
+ de "Cannot change to the directory \"%1\$s\".\nPermission denied.", "Kann nicht in das Verzeichnis \"%1\$s\" wechseln.\nKeine Rechte vorhanden."
+ de "Choose Directory", "W\\u00e4hle Verzeichnis"
+ de "&Clear", "&R\\u00fccksetzen"
+ de "&Clear Console", "&Konsole l\\u00f6schen"
+ de "Color", "Farbe"
+ de "Console", "Konsole"
+ de "&Copy", "&Kopieren"
+ de "Cu&t", "Aus&schneiden"
+ de "&Delete", "&L\\u00f6schen"
+ de "Details >>"
+ de "Directory \"%1\$s\" does not exist.", "Das Verzeichnis \"%1\$s\" existiert nicht."
+ de "&Directory:", "&Verzeichnis:"
+ de "&Edit", "&Bearbieten"
+ de "Error: %1\$s", "Fehler: %1\$s"
+ de "E&xit", "&Ende"
+ de "&File", "&Datei"
+ de "File \"%1\$s\" already exists.\nDo you want to overwrite it?", "Die Datei \"%1\$s\" ist bereits vorhanden.\nWollen sie diese Datei \\u00fcberschreiben ?"
+ de "File \"%1\$s\" already exists.\n\n", "Die Datei \"%1\$s\" ist bereits vorhanden.\n\n"
+ de "File \"%1\$s\" does not exist.", "Die Datei \"%1\$s\" existiert nicht."
+ de "File &name:", "Datei&name:"
+ de "File &names:", "Datei&namen:"
+ de "Files of &type:", "Dateien des &Typs:"
+ de "Fi&les:", "Dat&eien:"
+ de "&Filter"
+ de "Fil&ter:"
+ de "&Green", "&Gr\\u00fcn"
+ de "&Help", "&Hilfe"
+ de "Hi", "Hallo"
+ de "&Hide Console", "&Konsole unsichtbar machen"
+ de "&Ignore", "&Ignorieren"
+ de "Invalid file name \"%1\$s\".", "Ung\\u00fcltiger Dateiname \"%1\$s\"."
+ de "Log Files", "Protokolldatei"
+ de "&No", "&Nein"
+ de "OK"
+ de "Ok"
+ de "Open", "\\u00d6ffnen"
+ de "&Open", "\\u00d6&ffnen"
+ de "Open Multiple Files"
+ de "P&aste", "E&inf\\u00fcgen"
+ de "&Quit", "&Beenden"
+ de "&Red", "&Rot"
+ de "Replace existing file?", "Existierende Datei ersetzen?"
+ de "&Retry", "&Wiederholen"
+ de "&Save", "&Speichern"
+ de "Save As", "Speichern unter"
+ de "Save To Log", "In Protokoll speichern"
+ de "Select Log File", "Protokolldatei ausw\\u00e4hlen"
+ de "Select a file to source", "Auszuf\\u00fchrende Datei ausw\\u00e4hlen"
+ de "&Selection:", "Auswah&l:"
+ de "Skip Messages", "Weitere Nachrichten \\u00fcberspringen"
+ de "&Source...", "&Ausf\\u00fchren..."
+ de "Tcl Scripts", "Tcl-Skripte"
+ de "Tcl for Windows", "Tcl f\\u00fcr Windows"
+ de "Text Files", "Textdateien"
+ de "&Yes", "&Ja"
+ de "abort", "abbrechen"
+ de "blue", "blau"
+ de "cancel", "abbrechen"
+ de "extension", "Erweiterung"
+ de "extensions", "Erweiterungen"
+ de "green", "gr\\u00fcn"
+ de "ignore", "ignorieren"
+ de "ok"
+ de "red", "rot"
+ de "retry", "wiederholen"
+ de "yes", "ja"
+}
diff --git a/ext/tk/sample/msgs_rb/el.msg b/ext/tk/sample/msgs_rb/el.msg
new file mode 100644
index 0000000000..f314ae03eb
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/el.msg
@@ -0,0 +1,98 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ el 'Application Error', '\u039b\u03ac\u03b8\u03bf\u03c2 \u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae\u03c2'
+ el 'Blue', '\u039c\u03c0\u03bb\u03b5'
+ el 'Color', '\u03a7\u03c1\u03ce\u03bc\u03b1'
+ el 'Delete', '\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae'
+ el 'Error', '\u039b\u03ac\u03b8\u03bf\u03c2'
+ el 'Exit', '\u0388\u03be\u03bf\u03b4\u03bf\u03c2'
+ el 'Green', '\u03a0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf'
+ el 'Red', '\u039a\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf'
+ el 'blue', '\u03bc\u03c0\u03bb\u03b5'
+ el 'green', '\u03c0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf'
+ el 'red', '\u03ba\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf'
+}
+
+TkMsgCatalog.new('::tk') {
+ el '&Abort', '\u03a4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2'
+ el 'About...', '\u03a3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac...'
+ el 'All Files', '\u038c\u03bb\u03b1 \u03c4\u03b1 \u0391\u03c1\u03c7\u03b5\u03af\u03b1'
+ el 'Application Error', '\u039b\u03ac\u03b8\u03bf\u03c2 \u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae\u03c2'
+ el '&Blue', '\u039c\u03c0\u03bb\u03b5'
+ el '&Cancel', '\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7'
+ el 'Cannot change to the directory "%1\$s".' "\n" 'Permission denied.', \
+ '\u0394\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae \u03b7 \u03b1\u03bb\u03bb\u03b1\u03b3\u03ae \u03ba\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5 \u03c3\u03b5 "%1\$s".' \
+ "\n" \
+ '\u0397 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03b4\u03b5\u03bd \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03c4\u03b1\u03b9.'
+ el 'Choose Directory', '\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u039a\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5'
+ el 'Clear', '\u039a\u03b1\u03b8\u03b1\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2'
+ el 'Color', '\u03a7\u03c1\u03ce\u03bc\u03b1'
+ el 'Console', '\u039a\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1'
+ el 'Copy', '\u0391\u03bd\u03c4\u03b9\u03b3\u03c1\u03b1\u03c6\u03ae'
+ el 'Cut', '\u0391\u03c0\u03bf\u03ba\u03bf\u03c0\u03ae'
+ el 'Delete', '\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae'
+ el 'Details >>', '\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 >>'
+ el 'Directory "%1\$s", does not exist.', \
+ '\u039f \u03ba\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2 \'%1\$s\' \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.'
+ el '&Directory:', '&\u039a\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2:'
+ el 'Error: %1\$s', '\u039b\u03ac\u03b8\u03bf\u03c2: %1\$s'
+ el 'Exit', '\u0388\u03be\u03bf\u03b4\u03bf\u03c2'
+ el 'File "%1\$s" already exists.' "\n" 'Do you want to overwrite it?', \
+ '\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf "%1\$s" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.' \
+ "\n" \
+ '\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03ba\u03b1\u03bb\u03c5\u03c6\u03b8\u03b5\u03af;'
+ el 'File "%1\$s" already exists.' "\n\n", \
+ '\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf "%1\$s" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.' "\n\n"
+ el 'File "%1\$s" does not exist.', \
+ '\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf "%1\$s" \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.'
+ el 'File &name:', '\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5:'
+ el 'File &names:', '\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd:'
+ el 'Files of &type:', '\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u03c4\u03bf\u03c5 &\u03c4\u03cd\u03c0\u03bf\u03c5:'
+ el 'Fi&les:', '\u0391\u03c1\u03c7\u03b5\u03af\u03b1:'
+ el '&Filter', '\u03a6\u03af\u03bb\u03c4\u03c1\u03bf'
+ el 'Fil&ter:', '\u03a6\u03af\u03bb\u03c4\u03c1\u03bf:'
+ el '&Green', '\u03a0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf'
+ el 'Hi', '\u0393\u03b5\u03b9\u03b1'
+ el 'Hide Console', '\u0391\u03c0\u03cc\u03ba\u03c1\u03c5\u03c8\u03b7 \u03ba\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1\u03c2'
+ el '&Ignore', '\u0391\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7'
+ el 'Invalid file name "%1\$s".', \
+ '\u0386\u03ba\u03c5\u03c1\u03bf \u03cc\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 "%1\$s".'
+ el 'Log Files', '\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2'
+ el '&No', '\u038c\u03c7\u03b9'
+ el '&OK', '\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9'
+ el '&Ok', '\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9'
+ el 'Open', '\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1'
+ el '&Open', '\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1'
+ el 'Open Multiple Files', \
+ '\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03ce\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd'
+ el 'Paste', '\u0395\u03c0\u03b9\u03ba\u03cc\u03bb\u03bb\u03b7\u03c3\u03b7'
+ el 'Quit', '\u0388\u03be\u03bf\u03b4\u03bf\u03c2'
+ el '&Red', '\u039a\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf'
+ el 'Replace existing file?', \
+ '\u0395\u03c0\u03b9\u03ba\u03ac\u03bb\u03c5\u03c8\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03bd\u03c4\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5;'
+ el '&Retry', '\u03a0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac'
+ el '&Save', '\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7'
+ el 'Save As', '\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03b1\u03bd'
+ el 'Save To Log', '\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2'
+ el 'Select Log File', '\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2'
+ el 'Select a file to source', \
+ '\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b3\u03b9\u03b1 \u03b5\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7'
+ el '&Selection:', '\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae:'
+ el 'Skip Messages', '\u0391\u03c0\u03bf\u03c6\u03c5\u03b3\u03ae \u03bc\u03c5\u03bd\u03b7\u03bc\u03ac\u03c4\u03c9\u03bd'
+ el 'Source...', '\u0395\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7...'
+ el 'Tcl Scripts', 'Tcl Scripts'
+ el 'Tcl for Windows', 'Tcl \u03b3\u03b9\u03b1 Windows'
+ el 'Text Files', '\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b5\u03b9\u03bc\u03ad\u03bd\u03bf\u03c5'
+ el '&Yes', '\u039d\u03b1\u03b9'
+ el 'abort', '\u03c4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2'
+ el 'blue', '\u03bc\u03c0\u03bb\u03b5'
+ el 'cancel', '\u03b1\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7'
+ el 'extension', '\u03b5\u03c0\u03ad\u03ba\u03c4\u03b1\u03c3\u03b7'
+ el 'extensions', '\u03b5\u03c0\u03b5\u03ba\u03c4\u03ac\u03c3\u03b5\u03b9\u03c2'
+ el 'green', '\u03c0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf'
+ el 'ignore', '\u03b1\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7'
+ el 'ok', '\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9'
+ el 'red', '\u03ba\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf'
+ el 'retry', '\u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac'
+ el 'yes', '\u03bd\u03b1\u03b9'
+}
+
diff --git a/ext/tk/sample/msgs_rb/en.msg b/ext/tk/sample/msgs_rb/en.msg
new file mode 100644
index 0000000000..9b70239511
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/en.msg
@@ -0,0 +1,83 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ en "Application Error"
+ en "Blue"
+ en "Color"
+ en "Delete"
+ en "Error"
+ en "Green"
+ en "Red"
+ en "blue"
+ en "green"
+ en "red"
+}
+
+TkMsgCatalog.new('::tk') {
+ en "&Abort"
+ en "About..."
+ en "All Files"
+ en "Application Error"
+ en "&Blue"
+ en "&Cancel"
+ en "Cannot change to the directory \"%1\$s\".\nPermission denied."
+ en "Choose Directory"
+ en "Clear"
+ en "Color"
+ en "Console"
+ en "Copy"
+ en "Cut"
+ en "Delete"
+ en "Details >>"
+ en "Directory \"%1\$s\" does not exist."
+ en "&Directory:"
+ en "Error: %1\$s"
+ en "Exit"
+ en "File \"%1\$s\" already exists.\nDo you want to overwrite it?"
+ en "File \"%1\$s\" already exists.\n\n"
+ en "File \"%1\$s\" does not exist."
+ en "File &name:"
+ en "File &names:"
+ en "Files of &type:"
+ en "Fi&les:"
+ en "&Filter"
+ en "Fil&ter:"
+ en "&Green"
+ en "Hi"
+ en "Hide Console"
+ en "&Ignore"
+ en "Invalid file name \"%1\$s\"."
+ en "Log Files"
+ en "&No"
+ en "&OK"
+ en "Ok"
+ en "Open"
+ en "&Open"
+ en "Open Multiple Files"
+ en "Paste"
+ en "Quit"
+ en "&Red"
+ en "Replace existing file?"
+ en "&Retry"
+ en "&Save"
+ en "Save As"
+ en "Save To Log"
+ en "Select Log File"
+ en "Select a file to source"
+ en "&Selection:"
+ en "Skip Messages"
+ en "Source..."
+ en "Tcl Scripts"
+ en "Tcl for Windows"
+ en "Text Files"
+ en "&Yes"
+ en "abort"
+ en "blue"
+ en "cancel"
+ en "extension"
+ en "extensions"
+ en "green"
+ en "ignore"
+ en "ok"
+ en "red"
+ en "retry"
+ en "yes"
+}
diff --git a/ext/tk/sample/msgs_rb/en_gb.msg b/ext/tk/sample/msgs_rb/en_gb.msg
new file mode 100644
index 0000000000..97c58959b1
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/en_gb.msg
@@ -0,0 +1,7 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ en_gb 'Color', 'Colour'
+}
+
+TkMsgCatalog.new('::tk') {
+ en_gb 'Color', 'Colour'
+}
diff --git a/ext/tk/sample/msgs_rb/eo.msg b/ext/tk/sample/msgs_rb/eo.msg
new file mode 100644
index 0000000000..1630df5e83
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/eo.msg
@@ -0,0 +1,87 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ eo 'Application Error', 'Aplikoerraro'
+ eo 'Blue', 'Blua'
+ eo 'Color', 'Farbo'
+ eo 'Delete', 'Forprenu'
+ eo 'Error', 'Eraro'
+ eo 'Exit', 'Eliru'
+ eo 'Green', 'Verda'
+ eo 'Red', 'Rosa'
+ eo 'blue', 'blua'
+ eo 'green', 'verda'
+ eo 'red', 'ru\u011da'
+}
+
+TkMsgCatalog.new('::tk') {
+ eo '&Abort', '&\u0108esigo'
+ eo '&About...', 'Pri...'
+ eo 'All Files', '\u0108ioj dosieroj'
+ eo 'Application Error', 'Aplikoerraro'
+ eo '&Blue', '&Blua'
+ eo '&Cancel', '&Rezignu'
+ eo 'Cannot change to the directory "%1\$s".' "\n" 'Permission denied.', 'Neeble \u0109angi al dosierulon "%1\$s".' "\n" 'Vi ne rajtas tion.'
+ eo 'Choose Directory', 'Elektu Dosierujo'
+ eo '&Clear', '&Klaru'
+ eo '&Clear Console', '&Klaru konzolon'
+ eo 'Color', 'Farbo'
+ eo 'Console', 'Konzolo'
+ eo '&Copy', '&Kopiu'
+ eo 'Cu&t', '&Enpo\u015digu'
+ eo '&Delete', '&Forprenu'
+ eo 'Details >>', 'Detaloj >>'
+ eo 'Directory "%1\$s" does not exist.', 'La dosierujo "%1\$s" ne ekzistas.'
+ eo '&Directory:', '&Dosierujo:'
+ eo '&Edit', '&Redaktu'
+ eo 'Error: %1\$s', 'Eraro: %1\$s'
+ eo 'E&xit', '&Eliru'
+ eo '&File', '&Dosiero'
+ eo 'File "%1\$s" already exists.' "\n" 'Do you want to overwrite it?', 'La dosiero "%1\$s" jam ekzistas.' "\n" '\u0108u vi volas anstata\u00fbigi la dosieron?'
+ eo 'File "%1\$s" already exists.' "\n\n", 'La dosiero "%1\$s" jam egzistas.' "\n\n"
+ eo 'File "%1\$s" does not exist.', 'La dosierp "%1\$s" ne estas.'
+ eo 'File &name:', 'Dosiero&nomo:'
+ eo 'File &names:', 'Dosiero&nomoj:'
+ eo 'Files of &type:', 'Dosieroj de &Typo:'
+ eo 'Fi&les:', 'Do&sieroj:'
+ eo '&Filter', '&Filtrilo'
+ eo 'Fil&ter:', '&Filtrilo:'
+ eo '&Green', '&Verda'
+ eo '&Help', '&Helpu'
+ eo 'Hi', 'Saluton'
+ eo '&Hide Console', '&Ka\u015du konzolon'
+ eo '&Ignore', '&Ignoru'
+ eo 'Invalid file name "%1\$s".', 'Malvalida dosieronomo "%1\$s".'
+ eo 'Log Files', 'Protokolo'
+ eo '&No', '&Ne'
+ eo 'OK'
+ eo 'Ok'
+ eo 'Open', 'Malfermu'
+ eo '&Open', '&Malfermu'
+ eo 'Open Multiple Files', 'Melfermu multan dosierojn'
+ eo 'P&aste', '&Elpo\u015digi'
+ eo '&Quit', '&Finigu'
+ eo '&Red', '&Rosa'
+ eo 'Replace existing file?', '\u0108u anstata\u00fbu ekzistantan dosieron?'
+ eo '&Retry', '&Ripetu'
+ eo '&Save', '&Savu'
+ eo 'Save As', 'Savu kiel'
+ eo 'Save To Log', 'Savu en protokolon'
+ eo 'Select Log File', 'Elektu prokolodosieron'
+ eo 'Select a file to source', 'Elektu dosieron por interpreti'
+ eo '&Selection:', '&Elekto:'
+ eo 'Skip Messages', 'transsaltu pluajn mesa\u011dojn'
+ eo '&Source...', '&Fontoprogramo...'
+ eo 'Tcl Scripts', 'Tcl-skriptoj'
+ eo 'Tcl for Windows', 'Tcl por vindoso'
+ eo 'Text Files', 'Tekstodosierojn'
+ eo '&Yes', '&Jes'
+ eo 'abort', '\u0109esigo'
+ eo 'blue', 'blua'
+ eo 'cancel', 'rezignu'
+ eo 'extension', 'ekspansio'
+ eo 'extensions', 'ekspansioj'
+ eo 'green', 'verda'
+ eo 'ignore', 'ignorieren'
+ eo 'red', 'ru\u011da'
+ eo 'retry', 'ripetu'
+ eo 'yes', 'jes'
+}
diff --git a/ext/tk/sample/msgs_rb/es.msg b/ext/tk/sample/msgs_rb/es.msg
new file mode 100644
index 0000000000..460dbe848c
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/es.msg
@@ -0,0 +1,84 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ es "Application Error", "Error de la aplicaci\\u00f3n"
+ es "Blue", "Azul"
+ es "Color", "Color"
+ es "Delete", "Borrar"
+ es "Error", "Error"
+ es "Exit", "Salir"
+ es "Green", "Verde"
+ es "Red", "Rojo"
+ es "blue", "azul"
+ es "green", "verde"
+ es "red", "rojo"
+}
+
+TkMsgCatalog.new('::tk') {
+ es "&Abort", "&Abortar"
+ es "About...", "Acerca de ..."
+ es "All Files", "Todos los archivos"
+ es "Application Error", "Error de la aplicaci\\u00f3n"
+ es "&Blue", "&Azul"
+ es "&Cancel", "&Cancelar"
+ es "Cannot change to the directory \"%1\$s\".\nPermission denied.", "No es posible acceder al directorio \"%1\$s\".\nPermiso denegado."
+ es "Choose Directory", "Elegir directorio"
+ es "Clear", "Borrar"
+ es "Color", "Color"
+ es "Console", "Consola"
+ es "Copy", "Copiar"
+ es "Cut", "Cortar"
+ es "Delete", "Borrar"
+ es "Details >>", "Detalles >>"
+ es "Directory \"%1\$s\" does not exist.", "El directorio \"%1\$s\" no existe."
+ es "&Directory:", "&Directorio:"
+ es "Error: %1\$s", "Error: %1\$s"
+ es "Exit", "Salir"
+ es "File \"%1\$s\" already exists.\nDo you want to overwrite it?", "El archivo \"%1\$s\" ya existe.\nDesea sobreescribirlo?"
+ es "File \"%1\$s\" already exists.\n\n", "El archivo \"%1\$s\" ya existe.\n\n"
+ es "File \"%1\$s\" does not exist.", "El archivo \"%1\$s\" no existe."
+ es "File &name:", "&Nombre de archivo:"
+ es "File &names:", "&Nombres de archivo:"
+ es "Files of &type:", "Archivos de &tipo:"
+ es "Fi&les:", "&Archivos:"
+ es "&Filter", "&Filtro"
+ es "Fil&ter:", "Fil&tro:"
+ es "&Green", "&Verde"
+ es "Hi", "Hola"
+ es "Hide Console", "Esconder la consola"
+ es "&Ignore", "&Ignorar"
+ es "Invalid file name \"%1\$s\".", "Nombre de archivo inv\\u00e1lido \"%1\$s\"."
+ es "Log Files", "Ficheros de traza"
+ es "&No", "&No"
+ es "&OK", "&OK"
+ es "Ok", "Ok"
+ es "Open", "Abrir"
+ es "&Open", "&Abrir"
+ es "Open Multiple Files", "Abrir m\\u00faltiples archivos"
+ es "Paste", "Pegar"
+ es "Quit", "Abandonar"
+ es "&Red", "&Rojo"
+ es "Replace existing file?", "Reemplazar el archivo existente?"
+ es "&Retry", "&Reintentar"
+ es "&Save", "&Salvar"
+ es "Save As", "Salvar como"
+ es "Save To Log", "Salvar al archivo de traza"
+ es "Select Log File", "Elegir un archivo de traza"
+ es "Select a file to source", "Seleccionar un archivo a evaluar"
+ es "&Selection:", "&Selecci\\u00f3n:"
+ es "Skip Messages", "Omitir los mensajes"
+ es "Source...", "Evaluar..."
+ es "Tcl Scripts", "Scripts Tcl"
+ es "Tcl for Windows", "Tcl para Windows"
+ es "Text Files", "Archivos de texto"
+ es "&Yes", "&S\\u00ed"
+ es "abort", "abortar"
+ es "blue", "azul"
+ es "cancel", "cancelar"
+ es "extension", "extensi\\u00f3n"
+ es "extensions", "extensiones"
+ es "green", "verde"
+ es "ignore", "ignorar"
+ es "ok", "ok"
+ es "red", "rojo"
+ es "retry", "reintentar"
+ es "yes", "s\\u00ed"
+}
diff --git a/ext/tk/sample/msgs_rb/fr.msg b/ext/tk/sample/msgs_rb/fr.msg
new file mode 100644
index 0000000000..ea85cf1a39
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/fr.msg
@@ -0,0 +1,84 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ fr 'Application Error', "Erreur d'application"
+ fr 'Blue', 'Bleu'
+ fr 'Color', 'Couleur'
+ fr 'Delete', 'Effacer'
+ fr 'Error', 'Erreur'
+ fr 'Exit', 'Quitter'
+ fr 'Green', 'Vert'
+ fr 'Red', 'Rouge'
+ fr 'blue', 'bleu'
+ fr 'green', 'vert'
+ fr 'red', 'rouge'
+}
+
+TkMsgCatalog.new('::tk') {
+ fr '&Abort', '&Annuler'
+ fr 'About...', '\u00c0 propos...'
+ fr 'All Files', 'Tous les fichiers'
+ fr 'Application Error', "Erreur d'application"
+ fr '&Blue', '&Bleu'
+ fr '&Cancel', '&Annuler'
+ fr 'Cannot change to the directory "%1\$s".' "\n" 'Permission denied.', 'Impossible d\'acc\u00e9der au r\u00e9pertoire "%1\$s".' "\n" 'Permission refus\u00e9e.'
+ fr 'Choose Directory', 'Choisir r\u00e9pertoire'
+ fr 'Clear', 'Effacer'
+ fr 'Color', 'Couleur'
+ fr 'Console'
+ fr 'Copy', 'Copier'
+ fr 'Cut', 'Couper'
+ fr 'Delete', 'Effacer'
+ fr 'Details >>', 'D\u00e9tails >>'
+ fr 'Directory "%1\$s" does not exist.', 'Le r\u00e9pertoire "%1\$s" n\'existe pas.'
+ fr '&Directory:', '&R\u00e9pertoire:'
+ fr 'Error: %1\$s', 'Erreur: %1\$s'
+ fr 'Exit', 'Quitter'
+ fr 'File "%1\$s" already exists.' "\n" 'Do you want to overwrite it?', 'Le fichier "%1\$s" existe d\u00e9j\u00e0.' "\n" 'Voulez-vous l\'\u00e9craser?'
+ fr 'File "%1\$s" already exists.' "\n\n", 'Le fichier "%1\$s" existe d\u00e9j\u00e0.' "\n\n"
+ fr 'File "%1\$s" does not exist.', 'Le fichier "%1\$s" n\'existe pas.'
+ fr 'File &name:', '&Nom de fichier:'
+ fr 'File &names:', '&Noms de fichiers:'
+ fr 'Files of &type:', '&Type de fichiers:'
+ fr 'Fi&les:', 'Fich&iers:'
+ fr '&Filter', '&Filtre'
+ fr 'Fil&ter:', 'Fil&tre:'
+ fr '&Green', '&Vert'
+ fr 'Hi', 'Salut'
+ fr 'Hide Console', 'Cacher la Console'
+ fr '&Ignore', '&Ignorer'
+ fr 'Invalid file name "%1\$s".', 'Nom de fichier invalide "%1\$s".'
+ fr 'Log Files', 'Fichiers de trace'
+ fr '&No', '&Non'
+ fr '&OK'
+ fr 'Ok'
+ fr 'Open', 'Ouvrir'
+ fr '&Open', '&Ouvrir'
+ fr 'Open Multiple Files', 'Ouvrir plusieurs fichiers'
+ fr 'Paste', 'Coller'
+ fr 'Quit', 'Quitter'
+ fr '&Red', '&Rouge'
+ fr 'Replace existing file?', 'Remplacer le fichier existant?'
+ fr '&Retry', '&R\u00e9-essayer'
+ fr '&Save', '&Sauvegarder'
+ fr 'Save As', 'Sauvegarder sous'
+ fr 'Save To Log', 'Sauvegarde au fichier de trace'
+ fr 'Select Log File', 'Choisir un fichier de trace'
+ fr 'Select a file to source', 'Choisir un fichier \u00e0 \u00e9valuer'
+ fr '&Selection:', '&S\u00e9lection:'
+ fr 'Skip Messages', 'Omettre les messages'
+ fr 'Source...', '\u00c9valuer...'
+ fr 'Tcl Scripts', 'Scripts Tcl'
+ fr 'Tcl for Windows', 'Tcl pour Windows'
+ fr 'Text Files', 'Fichiers texte'
+ fr '&Yes', '&Oui'
+ fr 'abort', 'abandonner'
+ fr 'blue', 'bleu'
+ fr 'cancel', 'annuler'
+ fr 'extension'
+ fr 'extensions'
+ fr 'green', 'vert'
+ fr 'ignore', 'ignorer'
+ fr 'ok'
+ fr 'red', 'rouge'
+ fr 'retry', 'r\u00e9essayer'
+ fr 'yes', 'oui'
+}
diff --git a/ext/tk/sample/msgs_rb/it.msg b/ext/tk/sample/msgs_rb/it.msg
new file mode 100644
index 0000000000..a180bdbd99
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/it.msg
@@ -0,0 +1,84 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ it "Application Error", "Errore dell' applicazione"
+ it "Blue", "Blu"
+ it "Color", "Colore"
+ it "Delete", "Incolla"
+ it "Error", "Errore"
+ it "Exit", "Esci"
+ it "Green", "Verde"
+ it "Red", "Rosso"
+ it "blue", "blu"
+ it "green", "verde"
+ it "red", "rosso"
+}
+
+TkMsgCatalog.new('::tk') {
+ it "&Abort", "&Interrompi"
+ it "About...", "Informazioni ..."
+ it "All Files", "Tutti i file"
+ it "Application Error", "Errore dell' applicazione"
+ it "&Blue", "&Blu"
+ it "&Cancel", "&Annulla"
+ it "Cannot change to the directory \"%1\$s\".\nPermission denied.", "Impossibile accedere alla directory \"%1\$s\".\nPermesso negato."
+ it "Choose Directory", "Scegli directory"
+ it "Clear", "Azzera"
+ it "Color", "Colore"
+ it "Console"
+ it "Copy", "Copia"
+ it "Cut", "Taglia"
+ it "Delete", "Incolla"
+ it "Details >>", "Dettagli >>"
+ it "Directory \"%1\$s\" does not exist.", "La directory \"%1\$s\" non esiste."
+ it "&Directory:"
+ it "Error: %1\$s", "Errore: %1\$s"
+ it "Exit", "Esci"
+ it "File \"%1\$s\" already exists.\nDo you want to overwrite it?", "Il file \"%1\$s\" esiste gi\\u00e0.\nVuoi sovrascriverlo?"
+ it "File \"%1\$s\" already exists.\n\n", "Il file \"%1\$s\" esiste gi\\u00e0.\n\n"
+ it "File \"%1\$s\" does not exist.", "Il file \"%1\$s\" non esiste."
+ it "File &name:", "&Nome del file:"
+ it "File &names:", "&Nomi dei file:"
+ it "Files of &type:", "File di &tipo:"
+ it "Fi&les:", "Fi&le:"
+ it "&Filter", "&Filtro"
+ it "Fil&ter:", "Fil&tro:"
+ it "&Green", "&Verde"
+ it "Hi", "Salve"
+ it "Hide Console", "Nascondi la console"
+ it "&Ignore", "&Ignora"
+ it "Invalid file name \"%1\$s\".", "Nome di file non valido \"%1\$s\"."
+ it "Log Files", "File di log"
+ it "&No"
+ it "&OK"
+ it "Ok"
+ it "&Open", "A&pri"
+ it "Open", "Apri"
+ it "Open Multiple Files", "Apri file multipli"
+ it "Paste", "Incolla"
+ it "Quit", "Esci"
+ it "&Red", "&Rosso"
+ it "Replace existing file?", "Sostituisci il file esistente?"
+ it "&Retry", "&Riprova"
+ it "&Save", "&Salva"
+ it "Save As", "Salva come"
+ it "Save To Log", "Salva il log"
+ it "Select Log File", "Scegli un file di log"
+ it "Select a file to source", "Scegli un file da eseguire"
+ it "&Selection:", "&Selezione:"
+ it "Skip Messages", "Salta i messaggi"
+ it "Source...", "Esegui..."
+ it "Tcl Scripts", "Scripts Tcl"
+ it "Tcl for Windows", "Tcl per Windows"
+ it "Text Files", "File di testo"
+ it "&Yes", "&Si"
+ it "abort", "interrompi"
+ it "blue", "blu"
+ it "cancel", "annulla"
+ it "extension", "estensione"
+ it "extensions", "estensioni"
+ it "green", "verde"
+ it "ignore", "ignora"
+ it "ok"
+ it "red", "rosso"
+ it "retry", "riprova"
+ it "yes", "si"
+}
diff --git a/ext/tk/sample/msgs_rb/ja.msg b/ext/tk/sample/msgs_rb/ja.msg
new file mode 100644
index 0000000000..40587c1f1d
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/ja.msg
@@ -0,0 +1,13 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ ja 'Application Error', '\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30A8\u30E9\u30FC'
+ ja 'Blue', '\u9752'
+ ja 'Color', '\u80CC\u666F\u8272'
+ ja 'Delete', '\u6D88\u53BB'
+ ja 'Error', '\u30A8\u30E9\u30FC'
+ ja 'Exit', '\u7D42\u4E86'
+ ja 'Green', '\u7DD1'
+ ja 'Red', '\u8D64'
+ ja 'blue', '\u9752'
+ ja 'green', '\u7DD1'
+ ja 'red', '\u8D64'
+}
diff --git a/ext/tk/sample/msgs_rb/nl.msg b/ext/tk/sample/msgs_rb/nl.msg
new file mode 100644
index 0000000000..24e41dae86
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/nl.msg
@@ -0,0 +1,123 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ nl "Application Error", "Toepassingsfout"
+ nl "Blue", "Blauw"
+ nl "Color", "Kleur"
+ nl "Delete", "Wissen"
+ nl "Error", "Fout"
+ nl "Exit", "Be\\u00ebindigen"
+ nl "Green", "Groen"
+ nl "Red", "Rood"
+ nl "blue", "blauw"
+ nl "green", "groen"
+ nl "red", "rood"
+}
+
+TkMsgCatalog.new('::tk') {
+ nl "\"%1\$s\" must be an absolute pathname", "\"%1\$s\" moet een absolute pad-naam zijn"
+ nl "%1\$s is not a toplevel window", "%1\$s is geen toplevel window"
+ nl ", or", ", of"
+ nl "-default, -icon, -message, -parent, -title, or -type", "-default, -icon, -message, -parent, -title, of -type"
+ nl "-initialdir, -mustexist, -parent, or -title", "-initialdir, -mustexist, -parent, of -title"
+ nl "&Abort", "&Afbreken"
+ nl "About...", "Over..."
+ nl "All Files", "Alle Bestanden"
+ nl "Application Error", "Toepassingsfout"
+ nl "&Blue", "&Blauw"
+ nl "&Cancel", "&Annuleren"
+ nl "Cannot change to the directory \"%1\$s\".\nPermission denied.", "Kan niet naar map \"%1\$s\" gaan.\nU heeft hiervoor geen toestemming."
+ nl "Choose Directory", "Kies map"
+ nl "Clear", "Wissen"
+ nl "Clear entry, Press OK; Enter %1\$s, press OK", "Wis veld, Druk op OK; typ %1\$s in, druk op OK"
+ nl "&Clear Console", "&Wis Console"
+ nl "Color", "Kleur"
+ nl "Console"
+ nl "Copy", "Kopi\\u00ebren"
+ nl "Cut", "Knippen"
+ nl "Delete", "Wissen"
+ nl "Details"
+ nl "Details >>"
+ nl "Directory \"%1\$s\" does not exist.", "Map \"%1\$s\" bestaat niet."
+ nl "&Directory:", "&Map:"
+ nl "Edit", "Bewerken"
+ nl "Enter \"%1\$s\", press OK", "Typ \"%1\$s\", druk op OK"
+ nl "Enter \"%1\$s\", press OK, enter \"%2\$s\", press OK", "Typ \"%1\$s\", druk op OK, typ \"%2\$s\", druk op OK"
+ nl "Error: %1\$s", "Fout: %1\$s"
+ nl "Exit", "Be\\u00ebindigen"
+ nl "File", "Bestand"
+ nl "File \"%1\$s\" already exists.\n\n", "Bestand \"%1\$s\" bestaat al.\n\n"
+ nl "File \"%1\$s\" already exists.\nDo you want to overwrite it?", "Bestand \"%1\$s\" bestaat al.\nWilt u het overschrijven?"
+ nl "File \"%1\$s\" does not exist.", "Bestand \"%1\$s\" bestaat niet."
+ nl "File &name:", "Bestands&naam:"
+ nl "File &names:", "Bestands&namen:"
+ nl "Files of &type:", "Bestanden van het &type:"
+ nl "Fi&les:", "&Bestanden:"
+ nl "&Filter"
+ nl "Fil&ter:"
+ nl "&Green", "&Groen"
+ nl "Hi", "H\\u00e9"
+ nl "Hide Console", "Verberg Console"
+ nl "&Ignore", "&Negeren"
+ nl "Invalid file name \"%1\$s\".", "Ongeldige bestandsnaam \"%1\$s\"."
+ nl "Log Files", "Log Bestanden"
+ nl "&No", "&Nee"
+ nl "&OK"
+ nl "Ok"
+ nl "&Open", "&Openen"
+ nl "Open", "Openen"
+ nl "Open Multiple Files", "Open meerdere bestanden"
+ nl "Paste", "Plakken"
+ nl "Please press %1\$s", "Druk op %1\$s, A.U.B."
+ nl "Please press ok", "Druk op ok, A.U.B."
+ nl "Press Cancel", "Druk op Annuleren"
+ nl "Press Ok", "Druk op Ok"
+ nl "Quit", "Stoppen"
+ nl "&Red", "&Rood"
+ nl "Replace existing file?", "Vervang bestaand bestand?"
+ nl "&Retry", "&Herhalen"
+ nl "&Save", "Op&slaan"
+ nl "Save As", "Opslaan als"
+ nl "Save To Log", "Opslaan naar Log"
+ nl "Select Log File", "Selecteer Log bestand"
+ nl "Select a file to source", "Selecteer bronbestand"
+ nl "&Selection:", "&Selectie:"
+ nl "Skip Messages", "Berichten overslaan"
+ nl "Source...", "Bron..."
+ nl "Tcl Scripts"
+ nl "Tcl for Windows", "Tcl voor Windows"
+ nl "Text Files", "Tekstbestanden"
+ nl "&Yes", "&Ja"
+ nl "abort", "afbreken"
+ nl "abort, retry, ignore, ok, cancel, no, or yes", "afbreken, opnieuw, negeren, ok, annuleren, nee, of ja"
+ nl "abortretryignore, ok, okcancel, retrycancel, yesno, or yesnocancel", "abortretryignore, ok, okcancel, retrycancel, yesno, of yesnocancel"
+ nl "bad %1\$s value \"%2\$s\": must be %3\$s", "verkeerde %1\$s waarde \"%2\$s\": moet zijn %3\$s"
+ nl "bad file type \"%1\$s\", should be", "verkeerd bestandstype \"%1\$s\", moet zijn"
+ nl "bad option \"%1\$s\": should be %2\$s", "verkeerde optie \"%1\$s\": moet zijn %2\$s"
+ nl "bad window path name \"%1\$s\"", "verkeerde window-padnaam \"%1\$s\""
+ nl "blue", "blauw"
+ nl "can't post %1\$s: it isn't a descendant of %2\$s (this is a new requirement in Tk versions 3.0 and later)", "kan %1\$s niet verzenden: het is geen afstammeling van %2\$s (dit is een nieuwe eis in Tk versies 3.0 en later)"
+ nl "cancel", "annuleren"
+ nl "default button index greater than number of buttons specified for tk_dialog", "default knop index is groter dan het aantal knoppen beschikbaar voor tk_dialog"
+ nl "display name to use (current one otherwise)", "te gebruiken schermnaam (anders huidige scherm)"
+ nl "error, info, question, or warning", "error, info, question, of warning"
+ nl "extension"
+ nl "extensions"
+ nl "focus group \"%1\$s\" doesn't exist", "focusgroep \"%1\$s\" bestaat niet"
+ nl "green", "groen"
+ nl "history event %1\$s"
+ nl "ignore", "negeren"
+ nl "invalid default button \"%1\$s\"", "ongeldige default knop \"%1\$s\""
+ nl "macType"
+ nl "macTypes"
+ nl "must specify a background color", "een achtergrondkleur is verplicht"
+ nl "name of the slave interpreter", "naam van de slaaf-interpreter"
+ nl "no winfo screen . nor env(DISPLAY)", "geen winfo scherm . noch env(DISPLAY)"
+ nl "ok"
+ nl "red", "rood"
+ nl "retry", "opnieuw"
+ nl "should contain 5 or 4 elements", "moet 4 of 5 elementen bevatten"
+ nl "spec"
+ nl "tk_chooseDirectory command", "tk_chooseDirectory opdracht"
+ nl "tk_chooseDirectory command, cancel gives null", "tk_chooseDirectory opdracht, annuleren geeft lege waarde"
+ nl "tk_chooseDirectory command, initialdir", "tk_chooseDirectory opdracht, initi\\u00eble map"
+ nl "yes", "ja"
+}
diff --git a/ext/tk/sample/msgs_rb/pl.msg b/ext/tk/sample/msgs_rb/pl.msg
new file mode 100644
index 0000000000..0b3b4445c2
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/pl.msg
@@ -0,0 +1,87 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ pl 'Application Error', 'Bl\u0105d w Programie'
+ pl 'Blue', 'Niebieski'
+ pl 'Color', 'Kolor'
+ pl 'Delete', 'Usu\u0144'
+ pl 'Error', 'B\u0142\u0105d'
+ pl 'Exit', 'Zako\u0144cz'
+ pl 'Green', 'Zielony'
+ pl 'Red', 'Czerwonz'
+ pl 'blue', 'niebieski'
+ pl 'green', 'zielony'
+ pl 'red', 'czerwony'
+}
+
+TkMsgCatalog.new('::tk') {
+ pl '&Abort', '&Anuluj'
+ pl '&About...', 'O Programie...'
+ pl 'All Files', 'Wszystkie pliki'
+ pl 'Application Error', 'Bl\u0105d w Programie'
+ pl '&Blue', '&Niebieski'
+ pl '&Cancel', '&Anuluj'
+ pl 'Cannot change to the directory "%1\$s".' "\n" 'Permission denied.', 'Katalog "%1\$s" nie mo\u017ce zosta\u0107 odczytany lub nie istnieje.'
+ pl 'Choose Directory', 'Wybierz katalog'
+ pl '&Clear', '&Wyczy\u015b\u0107'
+ pl '&Clear Console', '&Wyczy\u015b\u0107 konsol\u0119'
+ pl 'Color', 'Kolor'
+ pl 'Console', 'Konsola'
+ pl '&Copy', '&Kopiuj'
+ pl 'Cu&t', '&Wytnij'
+ pl '&Delete', '&Usu\u0144'
+ pl 'Details >>', 'Detale >>'
+ pl 'Directory "%1\$s" does not exist.', 'Katalog "%1\$s" nie istniej.'
+ pl '&Directory:', '&Katalog:'
+ pl '&Edit', '&Edytuj'
+ pl 'Error: %1\$s', 'B\u0142\u0105d: %1\$s'
+ pl 'E&xit', '&Zako\u0144cz'
+ pl '&File', '&Plik'
+ pl 'File "%1\$s" already exists.' "\n" 'Do you want to overwrite it?', 'Plik "%1\$s" ju\u017c istnieje.' "\n" 'Czy chcesz go zast\u0105pi\u0107?'
+ pl 'File "%1\$s" already exists.' "\n\n", 'Plik "%1\$s" ju\u017c istnieje. ' "\n\n"
+ pl 'File "%1\$s" does not exist.', 'Plik "%1\$s" nie istnieje.'
+ pl 'File &name:', 'Nazwa &pliku:'
+ pl 'File &names:', 'Nazwy &plik\u00f3w:'
+ pl 'Files of &type:', 'Pliki &typu:'
+ pl 'Fi&les:', 'Pli&ki:'
+ pl '&Filter', '&Filter'
+ pl 'Fil&ter:', '&Filter:'
+ pl '&Green', '&Zielony'
+ pl '&Help', '&Pomoc'
+ pl 'Hi', 'Witaj'
+ pl '&Hide Console', '&Schowaj konsol\u0119'
+ pl '&Ignore', '&Ignoruj'
+ pl 'Invalid file name "%1\$s".', 'Niew\u0142a\u015bciwa nazwa pliku "%1\$s".'
+ pl 'Log Files', 'Protoko\u0142uj'
+ pl '&No', '&Nie'
+ pl 'OK'
+ pl 'Ok'
+ pl 'Open', 'Wczytaj'
+ pl '&Open', '&Wczytaj'
+ pl 'Open Multiple Files', 'Wczytuj wiele plik\u00f3w'
+ pl 'P&aste', '&Wklej'
+ pl '&Quit', '&Zako\u0144cz'
+ pl '&Red', '&Czerwonz'
+ pl 'Replace existing file?', 'Czy zost\u0105pi\u0107 instniej\u0105cy plik?'
+ pl '&Retry', '&Powt\u00f3rz'
+ pl '&Save', '&Zapisz'
+ pl 'Save As', 'Zapisz jako'
+ pl 'Save To Log', 'Wpisz do protoko\u0142u'
+ pl 'Select Log File', 'Wybierz plik proko\u0142u'
+ pl 'Select a file to source', 'Wybierz plik do wykonania'
+ pl '&Selection:', '&Wyb\u00f3r:'
+ pl 'Skip Messages', 'Omi\u0144 pozosta\u0142e komunikaty'
+ pl '&Source...', '&Kod \u017ar\u00f3d\u0142owy...'
+ pl 'Tcl Scripts', 'Tcl-skrypty'
+ pl 'Tcl for Windows', 'Tcl dla Okienek (Windows)'
+ pl 'Text Files', 'Pliki Tekstowe'
+ pl '&Yes', '&Tak'
+ pl 'abort', 'zako\u0144cz'
+ pl 'blue', 'niebieski'
+ pl 'cancel', 'anuluj'
+ pl 'extension', 'rozszerzenie'
+ pl 'extensions', 'rozszerzenia'
+ pl 'green', 'zielony'
+ pl 'ignore', 'ignoruj'
+ pl 'red', 'czerwony'
+ pl 'retry', 'potw\u00f3rz'
+ pl 'yes', 'tak'
+}
diff --git a/ext/tk/sample/msgs_rb/ru.msg b/ext/tk/sample/msgs_rb/ru.msg
new file mode 100644
index 0000000000..f389dff0b6
--- /dev/null
+++ b/ext/tk/sample/msgs_rb/ru.msg
@@ -0,0 +1,87 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ ru 'Application Error', '\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435'
+ ru 'Blue', ' \u0413\u043e\u043b\u0443\u0431\u043e\u0439'
+ ru 'Color', '\u0426\u0432\u0435\u0442'
+ ru 'Delete', '\u0423\u0434\u0430\u043b\u0438\u0442\u044c'
+ ru 'Error', '\u041e\u0448\u0438\u0431\u043a\u0430'
+ ru 'Exit', '\u0412\u044b\u0445\u043e\u0434'
+ ru 'Green', '\u0417\u0435\u043b\u0435\u043d\u044b\u0439'
+ ru 'Red', '\u041a\u0440\u0430\u0441\u043d\u044b\u0439'
+ ru 'blue', ' \u0433\u043e\u043b\u0443\u0431\u043e\u0439'
+ ru 'green', ' \u0437\u0435\u043b\u0435\u043d\u044b\u0439'
+ ru 'red', ' \u043a\u0440\u0430\u0441\u043d\u044b\u0439'
+}
+
+TkMsgCatalog.new('::tk') {
+ ru '&Abort', '&\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c'
+ ru 'About...', '\u041f\u0440\u043e...'
+ ru 'All Files', '\u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b'
+ ru 'Application Error', '\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435'
+ ru '&Blue', ' &\u0413\u043e\u043b\u0443\u0431\u043e\u0439'
+ ru '&Cancel', '\u041e\u0442&\u043c\u0435\u043d\u0430'
+ ru 'Cannot change to the directory "%1\$s".' "\n" 'Permission denied.' \
+ '\u041d\u0435 \u043c\u043e\u0433\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 "%1\$s".' "\n" '\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430'
+ ru 'Choose Directory', '\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433'
+ ru 'Clear', '\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c'
+ ru 'Color', '\u0426\u0432\u0435\u0442'
+ ru 'Console', '\u041a\u043e\u043d\u0441\u043e\u043b\u044c'
+ ru 'Copy', '\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c'
+ ru 'Cut', '\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c'
+ ru 'Delete', '\u0423\u0434\u0430\u043b\u0438\u0442\u044c'
+ ru 'Details >>', '\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 >>'
+ ru 'Directory "%1\$s" does not exist.', '\u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 "%1\$s" \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.'
+ ru '&Directory:', '&\u041a\u0430\u0442\u0430\u043b\u043e\u0433:'
+ ru 'Error: %1\$s', '\u041e\u0448\u0438\u0431\u043a\u0430: %1\$s'
+ ru 'Exit', '\u0412\u044b\u0445\u043e\u0434'
+ ru 'File "%1\$s" already exists.' "\n" 'Do you want to overwrite it?' \
+ '\u0424\u0430\u0439\u043b "%1\$s" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.' "\n" '\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e?'
+ ru 'File "%1\$s" already exists.' "\n\n", '\u0424\u0430\u0439\u043b "%1\$s" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.' "\n\n"
+ ru 'File "%1\$s" does not exist.', '\u0424\u0430\u0439\u043b "%1\$s" \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d.'
+ ru 'File &name:', '&\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430:'
+ ru 'File &names:', '&\u0418\u043c\u0435\u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432:'
+ ru 'Files of &type:', '&\u0422\u0438\u043f \u0444\u0430\u0439\u043b\u043e\u0432:'
+ ru 'Fi&les:', '\u0424\u0430\u0439&\u043b\u044b:'
+ ru '&Filter', '&\u0424\u0438\u043b\u044c\u0442\u0440'
+ ru 'Fil&ter:', '\u0424\u0438\u043b\u044c&\u0442\u0440:'
+ ru '&Green', ' &\u0417\u0435\u043b\u0435\u043d\u044b\u0439'
+ ru 'Hi', '\u041f\u0440\u0438\u0432\u0435\u0442'
+ ru 'Hide Console', '\u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u043e\u043b\u044c'
+ ru '&Ignore', '&\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c'
+ ru 'Invalid file name "%1\$s".', '\u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 "%1\$s".'
+ ru 'Log Files', '\u0424\u0430\u0439\u043b\u044b \u0436\u0443\u0440\u043d\u0430\u043b\u0430'
+ ru '&No', '&\u041d\u0435\u0442'
+ ru '&OK', '&\u041e\u041a'
+ ru 'Ok', '\u0414\u0430'
+ ru 'Open', '\u041e\u0442\u043a\u0440\u044b\u0442\u044c'
+ ru '&Open', '&\u041e\u0442\u043a\u0440\u044b\u0442\u044c'
+ ru 'Open Multiple Files', '\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432'
+ ru 'Paste', '\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c'
+ ru 'Quit', '\u0412\u044b\u0445\u043e\u0434'
+ ru '&Red', ' &\u041a\u0440\u0430\u0441\u043d\u044b\u0439'
+ ru 'Replace existing file?', '\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b?'
+ ru '&Retry', '&\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c'
+ ru '&Save', '&\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c'
+ ru 'Save As', '\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a'
+ ru 'Save To Log', '\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0436\u0443\u0440\u043d\u0430\u043b'
+ ru 'Select Log File', '\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0436\u0443\u0440\u043d\u0430\u043b'
+ ru 'Select a file to source', '\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438'
+ ru '&Selection:', '&Selection:'
+ ru 'Skip Messages', '\u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f'
+ ru 'Source...', '\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b...'
+ ru 'Tcl Scripts', '\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 TCL'
+ ru 'Tcl for Windows', 'TCL \u0434\u043b\u044f Windows'
+ ru 'Text Files', '\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b'
+ ru '&Yes', '&\u0414\u0430'
+ ru 'abort', '\u043e\u0442\u043c\u0435\u043d\u0430'
+ ru 'blue', ' \u0433\u043e\u043b\u0443\u0431\u043e\u0439'
+ ru 'cancel', '\u043e\u0442\u043c\u0435\u043d\u0430'
+ ru 'extension', '\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435'
+ ru 'extensions', '\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f'
+ ru 'green', ' \u0437\u0435\u043b\u0435\u043d\u044b\u0439'
+ ru 'ignore', '\u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c'
+ ru 'ok', '\u043e\u043a'
+ ru 'red', ' \u043a\u0440\u0430\u0441\u043d\u044b\u0439'
+ ru 'retry', '\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c'
+ ru 'yes', '\u0434\u0430'
+}
+
diff --git a/ext/tk/sample/msgs_rb2/README b/ext/tk/sample/msgs_rb2/README
new file mode 100644
index 0000000000..b8aa114e1b
--- /dev/null
+++ b/ext/tk/sample/msgs_rb2/README
@@ -0,0 +1,5 @@
+Message catalogs in this directory are written in encodings except
+UTF-8. As if you have a trouble to edit UTF-8 text, you can write
+message catalogs in your familier encoding.
+
+Please see '../msgs_rb/README' too.
diff --git a/ext/tk/sample/msgs_rb2/de.msg b/ext/tk/sample/msgs_rb2/de.msg
new file mode 100644
index 0000000000..0d6c82d9e5
--- /dev/null
+++ b/ext/tk/sample/msgs_rb2/de.msg
@@ -0,0 +1,88 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ de 'Application Error', 'Applikationsfehler'
+ de 'Blue', 'Blau'
+ de 'Color', 'Farbe'
+ de 'Delete', 'Löschen', 'iso8859-1'
+ de 'Error', 'Fehler'
+ de 'Exit', 'Ende'
+ de 'Green', 'Grün', 'iso8859-1'
+ de 'Red', 'Rot'
+ de 'blue', 'blau'
+ de 'green', 'grün', 'iso8859-1'
+ de 'red', 'rot'
+}
+
+TkMsgCatalog.new('::tk') {
+ de "&Abort", "&Abbruch"
+ de "&About...", "&Über...", 'iso8859-1'
+ de "All Files", "Alle Dateien"
+ de "Application Error", "Applikationsfehler"
+ de "&Blue", "&Blau"
+ de "&Cancel", "&Abbruch"
+ de "Cannot change to the directory \"%1\$s\".\nPermission denied.", "Kann nicht in das Verzeichnis \"%1\$s\" wechseln.\nKeine Rechte vorhanden."
+ de "Choose Directory", "Wähle Verzeichnis", 'iso8859-1'
+ de "&Clear", "&Rücksetzen", 'iso8859-1'
+ de "&Clear Console", "&Konsole löschen", 'iso8859-1'
+ de "Color", "Farbe"
+ de "Console", "Konsole"
+ de "&Copy", "&Kopieren"
+ de "Cu&t", "Aus&schneiden"
+ de '&Delete', '&Löschen', 'iso8859-1'
+ de "Details >>"
+ de "Directory \"%1\$s\" does not exist.", "Das Verzeichnis \"%1\$s\" existiert nicht."
+ de "&Directory:", "&Verzeichnis:"
+ de "&Edit", "&Bearbieten"
+ de "Error: %1\$s", "Fehler: %1\$s"
+ de "E&xit", "&Ende"
+ de "&File", "&Datei"
+ de "File \"%1\$s\" already exists.\nDo you want to overwrite it?", "Die Datei \"%1\$s\" ist bereits vorhanden.\nWollen sie diese Datei überschreiben ?", 'iso8859-1'
+ de "File \"%1\$s\" already exists.\n\n", "Die Datei \"%1\$s\" ist bereits vorhanden.\n\n"
+ de "File \"%1\$s\" does not exist.", "Die Datei \"%1\$s\" existiert nicht."
+ de "File &name:", "Datei&name:"
+ de "File &names:", "Datei&namen:"
+ de "Files of &type:", "Dateien des &Typs:"
+ de "Fi&les:", "Dat&eien:"
+ de "&Filter"
+ de "Fil&ter:"
+ de '&Green', '&Grün', 'iso8859-1'
+ de "&Help", "&Hilfe"
+ de "Hi", "Hallo"
+ de "&Hide Console", "&Konsole unsichtbar machen"
+ de "&Ignore", "&Ignorieren"
+ de "Invalid file name \"%1\$s\".", "Ungültiger Dateiname \"%1\$s\".", 'iso8859-1'
+ de "Log Files", "Protokolldatei"
+ de "&No", "&Nein"
+ de "OK"
+ de "Ok"
+ de "Open", "Öffnen", 'iso8859-1'
+ de "&Open", "Ö&ffnen", 'iso8859-1'
+ de "Open Multiple Files"
+ de "P&aste", "E&infügen", 'iso8859-1'
+ de "&Quit", "&Beenden"
+ de "&Red", "&Rot"
+ de "Replace existing file?", "Existierende Datei ersetzen?"
+ de "&Retry", "&Wiederholen"
+ de "&Save", "&Speichern"
+ de "Save As", "Speichern unter"
+ de "Save To Log", "In Protokoll speichern"
+ de "Select Log File", "Protokolldatei auswählen", 'iso8859-1'
+ de "Select a file to source", "Auszuführende Datei auswählen", 'iso8859-1'
+ de "&Selection:", "Auswah&l:"
+ de "Skip Messages", "Weitere Nachrichten überspringen", 'iso8859-1'
+ de "&Source...", "&Ausführen...", 'iso8859-1'
+ de "Tcl Scripts", "Tcl-Skripte"
+ de "Tcl for Windows", "Tcl für Windows", 'iso8859-1'
+ de "Text Files", "Textdateien"
+ de "&Yes", "&Ja"
+ de "abort", "abbrechen"
+ de "blue", "blau"
+ de "cancel", "abbrechen"
+ de "extension", "Erweiterung"
+ de "extensions", "Erweiterungen"
+ de 'green', 'grün', 'iso8859-1'
+ de "ignore", "ignorieren"
+ de "ok"
+ de "red", "rot"
+ de "retry", "wiederholen"
+ de "yes", "ja"
+}
diff --git a/ext/tk/sample/msgs_rb2/ja.msg b/ext/tk/sample/msgs_rb2/ja.msg
new file mode 100644
index 0000000000..84e89aa6ef
--- /dev/null
+++ b/ext/tk/sample/msgs_rb2/ja.msg
@@ -0,0 +1,85 @@
+TkMsgCatalog.new('::tkmsgcat_demo') {
+ ja 'Application Error', '¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥¨¥é¡¼', 'euc-jp'
+ ja 'Blue', 'ÀÄ', 'euc-jp'
+ ja 'Color', '¿§ÁªÂò', 'euc-jp'
+ ja 'Delete', '¾Ãµî', 'euc-jp'
+ ja 'Error', '¥¨¥é¡¼', 'euc-jp'
+ ja 'Exit', '½ªÎ»', 'euc-jp'
+ ja 'Green', 'ÎÐ', 'euc-jp'
+ ja 'Red', 'ÀÖ', 'euc-jp'
+ ja 'blue', 'ÀÄ', 'euc-jp'
+ ja 'green', 'ÎÐ', 'euc-jp'
+ ja 'red', 'ÀÖ', 'euc-jp'
+}
+
+TkMsgCatalog.new('::tk') {
+ ja "&Abort", '̾ȧ', 'euc-jp'
+ ja "About..."
+ ja "All Files", '¤¹¤Ù¤Æ¤Î¥Õ¥¡¥¤¥ë', 'euc-jp'
+ ja "Application Error", '¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥¨¥é¡¼', 'euc-jp'
+ ja "&Blue", 'ÀÄ', 'euc-jp'
+ ja "&Cancel", '¼è¤ê¾Ã¤·', 'euc-jp'
+ ja "Cannot change to the directory \"%1\$s\".\nPermission denied.", "¥Ç¥£¥ì¥¯¥È¥ê \"%1\$s\" ¤ËÊѹ¹¤Ç¤­¤Þ¤»¤ó¡¥\nµö²Ä¤¬¤¢¤ê¤Þ¤»¤ó¡¥", 'euc-jp'
+ ja "Choose Directory", '¥Ç¥£¥ì¥¯¥È¥ê¤òÁªÂò', 'euc-jp'
+ ja "Clear", '¾Ãµî', 'euc-jp'
+ ja "Color", '¿§', 'euc-jp'
+ ja "Console", '¥³¥ó¥½¡¼¥ë', 'euc-jp'
+ ja "Copy", '¥³¥Ô¡¼', 'euc-jp'
+ ja "Cut", 'ÀÚ¤ê¼è¤ê', 'euc-jp'
+ ja "Delete", '¾Ãµî', 'euc-jp'
+ ja "Details >>", '¾ÜºÙ >>', 'euc-jp'
+ ja "Directory \"%1\$s\" does not exist.", '"%1$s" ¤È¤¤¤¦¥Ç¥£¥ì¥¯¥È¥ê¤Ï¸ºß¤·¤Þ¤»¤ó¡¥', 'euc-jp'
+ ja "&Directory:", '¥Ç¥£¥ì¥¯¥È¥ê', 'euc-jp'
+ ja "Error: %1\$s"
+ ja "Exit", '½ªÎ»', 'euc-jp'
+ ja "File \"%1\$s\" already exists.\nDo you want to overwrite it?", "\"%1\$s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï´û¤Ë¸ºß¤·¤Æ¤¤¤Þ¤¹¡¥\n½ñ¤­´¹¤¨¤Þ¤¹¤«¡©", 'euc-jp'
+ ja "File \"%1\$s\" already exists.\n\n", "\"%1\$s\" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï´û¤Ë¸ºß¤·¤Æ¤¤¤Þ¤¹¡¥\n\n", 'euc-jp'
+ ja "File \"%1\$s\" does not exist.", '"%1$s" ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï¸ºß¤·¤Þ¤»¤ó¡¥', 'euc-jp'
+ ja "File &name:", '¥Õ¥¡¥¤¥ë̾', 'euc-jp'
+ ja "File &names:", '¥Õ¥¡¥¤¥ë̾', 'euc-jp'
+ ja "Files of &type:", '¥Õ¥¡¥¤¥ë·Á¼°', 'euc-jp'
+ ja "Fi&les:", '¥Õ¥¡¥¤¥ë', 'euc-jp'
+ ja "&Filter", '¥Õ¥£¥ë¥¿¡¼', 'euc-jp'
+ ja "Fil&ter:", '¥Õ¥£¥ë¥¿¡¼', 'euc-jp'
+ ja "&Green", 'ÎÐ', 'euc-jp'
+ ja "Hi", '¤³¤ó¤Ë¤Á¤Ï', 'euc-jp'
+ ja "Hide Console", '¥³¥ó¥½¡¼¥ë¤ò±£¤¹', 'euc-jp'
+ ja "&Ignore", '̵»ë', 'euc-jp'
+ ja "Invalid file name \"%1\$s\".", '"%1$s" ¤ÏÉÔÀµ¤Ê¥Õ¥¡¥¤¥ë̾¤Ç¤¹¡¥', 'euc-jp'
+ ja "Log Files", '¥í¥°¥Õ¥¡¥¤¥ë', 'euc-jp'
+ ja "&No", '¤¤¤¤¤¨', 'euc-jp'
+ ja "&OK", 'λ²ò', 'euc-jp'
+ ja "OK", 'λ²ò', 'euc-jp'
+ ja "Ok", 'λ²ò', 'euc-jp'
+ ja "Open", '³«¤¯', 'euc-jp'
+ ja "&Open", '³«¤¯', 'euc-jp'
+ ja "Open Multiple Files", 'Ê£¿ô¤Î¥Õ¥¡¥¤¥ë¤ò³«¤¯', 'euc-jp'
+ ja "Paste", 'ޤêÉÕ¤±', 'euc-jp'
+ ja "Quit", '½ªÎ»', 'euc-jp'
+ ja "&Red", 'ÀÖ', 'euc-jp'
+ ja "Replace existing file?", '´û¸¤Î¥Õ¥¡¥¤¥ë¤òÃÖ¤­´¹¤¨¤Þ¤¹¤«¡©', 'euc-jp'
+ ja "&Retry", 'ºÆ¼Â¹Ô', 'euc-jp'
+ ja "&Save", 'Êݸ', 'euc-jp'
+ ja "Save As", '̾Á°¤òÉÕ¤±¤ÆÊݸ', 'euc-jp'
+ ja "Save To Log", '¥í¥°¤òÊݸ', 'euc-jp'
+ ja "Select Log File", '¥í¥°¥Õ¥¡¥¤¥ë¤òÁªÂò', 'euc-jp'
+ ja "Select a file to source", '¥½¡¼¥¹¥Õ¥¡¥¤¥ë¤òÁªÂò', 'euc-jp'
+ ja "&Selection:", 'ÁªÂò', 'euc-jp'
+ ja "Skip Messages", '¥á¥Ã¥»¡¼¥¸¤ò¤È¤Ð¤¹', 'euc-jp'
+ ja "Source...", '¥½¡¼¥¹...', 'euc-jp'
+ ja "Tcl Scripts", 'Tcl ¥¹¥¯¥ê¥×¥È', 'euc-jp'
+ ja "Tcl for Windows"
+ ja "Text Files", '¥Æ¥­¥¹¥È¥Õ¥¡¥¤¥ë', 'euc-jp'
+ ja "&Yes", '¤Ï¤¤', 'euc-jp'
+ ja "abort", '̾ȧ', 'euc-jp'
+ ja "blue", 'ÀÄ', 'euc-jp'
+ ja "cancel", '¼è¤ê¾Ã¤·', 'euc-jp'
+ ja "extension", '³ÈÄ¥»Ò', 'euc-jp'
+ ja "extensions", '³ÈÄ¥»Ò', 'euc-jp'
+ ja "green", 'ÎÐ', 'euc-jp'
+ ja "ignore", '̵»ë', 'euc-jp'
+ ja "ok", 'λ²ò', 'euc-jp'
+ ja "red", 'ÀÖ', 'euc-jp'
+ ja "retry", 'ºÆ¼Â¹Ô', 'euc-jp'
+ ja "yes", '¤Ï¤¤', 'euc-jp'
+}
diff --git a/ext/tk/sample/msgs_tk/README b/ext/tk/sample/msgs_tk/README
new file mode 100644
index 0000000000..c7422e3a9b
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/README
@@ -0,0 +1,4 @@
+Almost all of Message-Catalog files in this directory are quoted
+from Tcl/Tk8.5a1 source archive (only a little are modified for
+'tkmsgcat-load_tk.rb'). Please read the file 'license.terms' in
+this directry (That was included in demo directory of Tcl/Tk8.5a1).
diff --git a/ext/tk/sample/msgs_tk/cs.msg b/ext/tk/sample/msgs_tk/cs.msg
new file mode 100644
index 0000000000..697070985e
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/cs.msg
@@ -0,0 +1,84 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset cs "Application Error" "Chyba programu"
+ ::msgcat::mcset cs "Blue" "Modr\341"
+ ::msgcat::mcset cs "Color" "Barva"
+ ::msgcat::mcset cs "Delete" "Smazat"
+ ::msgcat::mcset cs "Error" "Chyba"
+ ::msgcat::mcset cs "Exit" "Konec"
+ ::msgcat::mcset cs "Green" "Zelen\341"
+ ::msgcat::mcset cs "Red" "\u010cerven\341"
+ ::msgcat::mcset cs "blue" "modr\341"
+ ::msgcat::mcset cs "green" "zelen\341"
+ ::msgcat::mcset cs "red" "\u010derven\341"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset cs "&Abort" "&P\u0159eru\u0161it"
+ ::msgcat::mcset cs "About..." "O programu..."
+ ::msgcat::mcset cs "All Files" "V\u0161echny soubory"
+ ::msgcat::mcset cs "Application Error" "Chyba programu"
+ ::msgcat::mcset cs "&Blue" "&Modr\341"
+ ::msgcat::mcset cs "&Cancel" "&Zru\u0161it"
+ ::msgcat::mcset cs "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nemohu zm\u011bnit atku\341ln\355 adres\341\u0159 na \"%1\$s\".\nP\u0159\355stup odm\355tnut."
+ ::msgcat::mcset cs "Choose Directory" "V\375b\u011br adres\341\u0159e"
+ ::msgcat::mcset cs "Clear" "Smazat"
+ ::msgcat::mcset cs "Color" "Barva"
+ ::msgcat::mcset cs "Console" "Konzole"
+ ::msgcat::mcset cs "Copy" "Kop\355rovat"
+ ::msgcat::mcset cs "Cut" "Vy\u0159\355znout"
+ ::msgcat::mcset cs "Delete" "Smazat"
+ ::msgcat::mcset cs "Details >>" "Detaily >>"
+ ::msgcat::mcset cs "Directory \"%1\$s\" does not exist." "Adres\341\u0159 \"%1\$s\" neexistuje."
+ ::msgcat::mcset cs "&Directory:" "&Adres\341\u0159:"
+ ::msgcat::mcset cs "Error: %1\$s" "Chyba: %1\$s"
+ ::msgcat::mcset cs "Exit" "Konec"
+ ::msgcat::mcset cs "File \"%1\$s\" already exists.\n\n" "Soubor \"%1\$s\" ji\u017e existuje.\n\n"
+ ::msgcat::mcset cs "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Soubor \"%1\$s\" ji\u017e existuje.\nChcete jej p\u0159epsat?"
+ ::msgcat::mcset cs "File \"%1\$s\" does not exist." "Soubor \"%1\$s\" neexistuje."
+ ::msgcat::mcset cs "File &name:" "&Jm\351no souboru:"
+ ::msgcat::mcset cs "File &names:" "&Jm\351na soubor\u016f:"
+ ::msgcat::mcset cs "Files of &type:" "&Typy soubor\u016f:"
+ ::msgcat::mcset cs "Fi&les:" "Sou&bory:"
+ ::msgcat::mcset cs "&Filter" "&Filtr"
+ ::msgcat::mcset cs "Fil&ter:" "Fil&tr:"
+ ::msgcat::mcset cs "&Green" "Ze&len\341"
+ ::msgcat::mcset cs "Hi"
+ ::msgcat::mcset cs "Hide Console" "Skr\375t konsolu"
+ ::msgcat::mcset cs "&Ignore" "&Ignorovat"
+ ::msgcat::mcset cs "Invalid file name \"%1\$s\"." "\u0160patn\351 jm\351no souboru \"%1\$s\"."
+ ::msgcat::mcset cs "Log Files" "Log soubory"
+ ::msgcat::mcset cs "&No" "&Ne"
+ ::msgcat::mcset cs "&OK"
+ ::msgcat::mcset cs "Ok"
+ ::msgcat::mcset cs "Open" "Otev\u0159\355t"
+ ::msgcat::mcset cs "&Open" "&Otev\u0159\355t"
+ ::msgcat::mcset cs "Open Multiple Files" "Otev\u0159\355t v\355ce soubor\u016f"
+ ::msgcat::mcset cs "Paste" "Vlo\u017eit"
+ ::msgcat::mcset cs "Quit" "Skon\u010dit"
+ ::msgcat::mcset cs "&Red" " \u010ce&rven\341"
+ ::msgcat::mcset cs "Replace existing file?" "Nahradit st\341vaj\355c\355 soubor?"
+ ::msgcat::mcset cs "&Retry" "Z&novu"
+ ::msgcat::mcset cs "&Save" "&Ulo\u017eit"
+ ::msgcat::mcset cs "Save As" "Ulo\u017eit jako"
+ ::msgcat::mcset cs "Save To Log" "Ulo\u017eit do logu"
+ ::msgcat::mcset cs "Select Log File" "Vybrat log soubor"
+ ::msgcat::mcset cs "Select a file to source" "Vybrat soubor k nahr\341n\355"
+ ::msgcat::mcset cs "&Selection:" "&V\375b\u011br:"
+ ::msgcat::mcset cs "Skip Messages" "P\u0159esko\u010dit zpr\341vy"
+ ::msgcat::mcset cs "Source..." "Nahr\341t..."
+ ::msgcat::mcset cs "Tcl Scripts" "Tcl skripty"
+ ::msgcat::mcset cs "Tcl for Windows" "Tcl pro Windows"
+ ::msgcat::mcset cs "Text Files" "Textov\351 soubory"
+ ::msgcat::mcset cs "&Yes" "&Ano"
+ ::msgcat::mcset cs "abort" "p\u0159eru\u0161it"
+ ::msgcat::mcset cs "blue" "modr\341"
+ ::msgcat::mcset cs "cancel" "zru\u0161it"
+ ::msgcat::mcset cs "extension" "p\u0159\355pona"
+ ::msgcat::mcset cs "extensions" "p\u0159\355pony"
+ ::msgcat::mcset cs "green" "zelen\341"
+ ::msgcat::mcset cs "ignore" "ignorovat"
+ ::msgcat::mcset cs "ok"
+ ::msgcat::mcset cs "red" "\u010derven\341"
+ ::msgcat::mcset cs "retry" "znovu"
+ ::msgcat::mcset cs "yes" "ano"
+}
diff --git a/ext/tk/sample/msgs_tk/de.msg b/ext/tk/sample/msgs_tk/de.msg
new file mode 100644
index 0000000000..437f2ed9e7
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/de.msg
@@ -0,0 +1,88 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset de "Application Error" "Applikationsfehler"
+ ::msgcat::mcset de "Blue" "Blau"
+ ::msgcat::mcset de "Color" "Farbe"
+ ::msgcat::mcset de "Delete" "L\u00f6schen"
+ ::msgcat::mcset de "Error" "Fehler"
+ ::msgcat::mcset de "Exit" "Ende"
+ ::msgcat::mcset de "Green" "Gr\u00fcn"
+ ::msgcat::mcset de "Red" "Rot"
+ ::msgcat::mcset de "blue" "blau"
+ ::msgcat::mcset de "green" "gr\u00fcn"
+ ::msgcat::mcset de "red" "rot"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset de "&Abort" "&Abbruch"
+ ::msgcat::mcset de "&About..." "&\u00dcber..."
+ ::msgcat::mcset de "All Files" "Alle Dateien"
+ ::msgcat::mcset de "Application Error" "Applikationsfehler"
+ ::msgcat::mcset de "&Blue" "&Blau"
+ ::msgcat::mcset de "&Cancel" "&Abbruch"
+ ::msgcat::mcset de "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kann nicht in das Verzeichnis \"%1\$s\" wechseln.\nKeine Rechte vorhanden."
+ ::msgcat::mcset de "Choose Directory" "W\u00e4hle Verzeichnis"
+ ::msgcat::mcset de "&Clear" "&R\u00fccksetzen"
+ ::msgcat::mcset de "&Clear Console" "&Konsole l\u00f6schen"
+ ::msgcat::mcset de "Color" "Farbe"
+ ::msgcat::mcset de "Console" "Konsole"
+ ::msgcat::mcset de "&Copy" "&Kopieren"
+ ::msgcat::mcset de "Cu&t" "Aus&schneiden"
+ ::msgcat::mcset de "&Delete" "&L\u00f6schen"
+ ::msgcat::mcset de "Details >>"
+ ::msgcat::mcset de "Directory \"%1\$s\" does not exist." "Das Verzeichnis \"%1\$s\" existiert nicht."
+ ::msgcat::mcset de "&Directory:" "&Verzeichnis:"
+ ::msgcat::mcset de "&Edit" "&Bearbieten"
+ ::msgcat::mcset de "Error: %1\$s" "Fehler: %1\$s"
+ ::msgcat::mcset de "E&xit" "&Ende"
+ ::msgcat::mcset de "&File" "&Datei"
+ ::msgcat::mcset de "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Die Datei \"%1\$s\" ist bereits vorhanden.\nWollen sie diese Datei \u00fcberschreiben ?"
+ ::msgcat::mcset de "File \"%1\$s\" already exists.\n\n" "Die Datei \"%1\$s\" ist bereits vorhanden.\n\n"
+ ::msgcat::mcset de "File \"%1\$s\" does not exist." "Die Datei \"%1\$s\" existiert nicht."
+ ::msgcat::mcset de "File &name:" "Datei&name:"
+ ::msgcat::mcset de "File &names:" "Datei&namen:"
+ ::msgcat::mcset de "Files of &type:" "Dateien des &Typs:"
+ ::msgcat::mcset de "Fi&les:" "Dat&eien:"
+ ::msgcat::mcset de "&Filter"
+ ::msgcat::mcset de "Fil&ter:"
+ ::msgcat::mcset de "&Green" "&Gr\u00fcn"
+ ::msgcat::mcset de "&Help" "&Hilfe"
+ ::msgcat::mcset de "Hi" "Hallo"
+ ::msgcat::mcset de "&Hide Console" "&Konsole unsichtbar machen"
+ ::msgcat::mcset de "&Ignore" "&Ignorieren"
+ ::msgcat::mcset de "Invalid file name \"%1\$s\"." "Ung\u00fcltiger Dateiname \"%1\$s\"."
+ ::msgcat::mcset de "Log Files" "Protokolldatei"
+ ::msgcat::mcset de "&No" "&Nein"
+ ::msgcat::mcset de "OK"
+ ::msgcat::mcset de "Ok"
+ ::msgcat::mcset de "Open" "\u00d6ffnen"
+ ::msgcat::mcset de "&Open" "\u00d6&ffnen"
+ ::msgcat::mcset de "Open Multiple Files"
+ ::msgcat::mcset de "P&aste" "E&inf\u00fcgen"
+ ::msgcat::mcset de "&Quit" "&Beenden"
+ ::msgcat::mcset de "&Red" "&Rot"
+ ::msgcat::mcset de "Replace existing file?" "Existierende Datei ersetzen?"
+ ::msgcat::mcset de "&Retry" "&Wiederholen"
+ ::msgcat::mcset de "&Save" "&Speichern"
+ ::msgcat::mcset de "Save As" "Speichern unter"
+ ::msgcat::mcset de "Save To Log" "In Protokoll speichern"
+ ::msgcat::mcset de "Select Log File" "Protokolldatei ausw\u00e4hlen"
+ ::msgcat::mcset de "Select a file to source" "Auszuf\u00fchrende Datei ausw\u00e4hlen"
+ ::msgcat::mcset de "&Selection:" "Auswah&l:"
+ ::msgcat::mcset de "Skip Messages" "Weitere Nachrichten \u00fcberspringen"
+ ::msgcat::mcset de "&Source..." "&Ausf\u00fchren..."
+ ::msgcat::mcset de "Tcl Scripts" "Tcl-Skripte"
+ ::msgcat::mcset de "Tcl for Windows" "Tcl f\u00fcr Windows"
+ ::msgcat::mcset de "Text Files" "Textdateien"
+ ::msgcat::mcset de "&Yes" "&Ja"
+ ::msgcat::mcset de "abort" "abbrechen"
+ ::msgcat::mcset de "blue" "blau"
+ ::msgcat::mcset de "cancel" "abbrechen"
+ ::msgcat::mcset de "extension" "Erweiterung"
+ ::msgcat::mcset de "extensions" "Erweiterungen"
+ ::msgcat::mcset de "green" "gr\u00fcn"
+ ::msgcat::mcset de "ignore" "ignorieren"
+ ::msgcat::mcset de "ok"
+ ::msgcat::mcset de "red" "rot"
+ ::msgcat::mcset de "retry" "wiederholen"
+ ::msgcat::mcset de "yes" "ja"
+}
diff --git a/ext/tk/sample/msgs_tk/el.msg b/ext/tk/sample/msgs_tk/el.msg
new file mode 100644
index 0000000000..1e3a539647
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/el.msg
@@ -0,0 +1,103 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset el "Application Error" "\u039b\u03ac\u03b8\u03bf\u03c2 \u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae\u03c2"
+ ::msgcat::mcset el "Blue" "\u039c\u03c0\u03bb\u03b5"
+ ::msgcat::mcset el "Color" "\u03a7\u03c1\u03ce\u03bc\u03b1"
+ ::msgcat::mcset el "Delete" "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae"
+ ::msgcat::mcset el "Error" "\u039b\u03ac\u03b8\u03bf\u03c2"
+ ::msgcat::mcset el "Exit" "\u0388\u03be\u03bf\u03b4\u03bf\u03c2"
+ ::msgcat::mcset el "Green" "\u03a0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "Red" "\u039a\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "blue" "\u03bc\u03c0\u03bb\u03b5"
+ ::msgcat::mcset el "green" "\u03c0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "red" "\u03ba\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf"
+}
+
+
+# followings are same to original file included into Tk8.5a1's widget demos.
+
+## Messages for the Greek (Hellenic - "el") language.
+## Please report any changes/suggestions to:
+## petasis@iit.demokritos.gr
+
+namespace eval ::tk {
+ ::msgcat::mcset el "&Abort" "\u03a4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2"
+ ::msgcat::mcset el "About..." "\u03a3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac..."
+ ::msgcat::mcset el "All Files" "\u038c\u03bb\u03b1 \u03c4\u03b1 \u0391\u03c1\u03c7\u03b5\u03af\u03b1"
+ ::msgcat::mcset el "Application Error" "\u039b\u03ac\u03b8\u03bf\u03c2 \u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae\u03c2"
+ ::msgcat::mcset el "&Blue" "\u039c\u03c0\u03bb\u03b5"
+ ::msgcat::mcset el "&Cancel" "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7"
+ ::msgcat::mcset el \
+"Cannot change to the directory \"%1\$s\".\nPermission denied." \
+"\u0394\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae \u03b7 \u03b1\u03bb\u03bb\u03b1\u03b3\u03ae \u03ba\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5 \u03c3\u03b5 \"%1\$s\".\n\u0397 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03b4\u03b5\u03bd \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03c4\u03b1\u03b9."
+ ::msgcat::mcset el "Choose Directory" "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u039a\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5"
+ ::msgcat::mcset el "Clear" "\u039a\u03b1\u03b8\u03b1\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2"
+ ::msgcat::mcset el "Color" "\u03a7\u03c1\u03ce\u03bc\u03b1"
+ ::msgcat::mcset el "Console" "\u039a\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1"
+ ::msgcat::mcset el "Copy" "\u0391\u03bd\u03c4\u03b9\u03b3\u03c1\u03b1\u03c6\u03ae"
+ ::msgcat::mcset el "Cut" "\u0391\u03c0\u03bf\u03ba\u03bf\u03c0\u03ae"
+ ::msgcat::mcset el "Delete" "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae"
+ ::msgcat::mcset el "Details >>" "\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 >>"
+ ::msgcat::mcset el "Directory \"%1\$s\" does not exist." \
+ "\u039f \u03ba\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2 \"%1\$s\" \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9."
+ ::msgcat::mcset el "&Directory:" "&\u039a\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2:"
+ ::msgcat::mcset el "Error: %1\$s" "\u039b\u03ac\u03b8\u03bf\u03c2: %1\$s"
+ ::msgcat::mcset el "Exit" "\u0388\u03be\u03bf\u03b4\u03bf\u03c2"
+ ::msgcat::mcset el \
+ "File \"%1\$s\" already exists.\nDo you want to overwrite it?" \
+ "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.\n\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03ba\u03b1\u03bb\u03c5\u03c6\u03b8\u03b5\u03af;"
+ ::msgcat::mcset el "File \"%1\$s\" already exists.\n\n" \
+ "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.\n\n"
+ ::msgcat::mcset el "File \"%1\$s\" does not exist." \
+ "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9."
+ ::msgcat::mcset el "File &name:" "\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5:"
+ ::msgcat::mcset el "File &names:" "\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd:"
+ ::msgcat::mcset el "Files of &type:" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u03c4\u03bf\u03c5 &\u03c4\u03cd\u03c0\u03bf\u03c5:"
+ ::msgcat::mcset el "Fi&les:" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1:"
+ ::msgcat::mcset el "&Filter" "\u03a6\u03af\u03bb\u03c4\u03c1\u03bf"
+ ::msgcat::mcset el "Fil&ter:" "\u03a6\u03af\u03bb\u03c4\u03c1\u03bf:"
+ ::msgcat::mcset el "&Green" "\u03a0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "Hi" "\u0393\u03b5\u03b9\u03b1"
+ ::msgcat::mcset el "Hide Console" "\u0391\u03c0\u03cc\u03ba\u03c1\u03c5\u03c8\u03b7 \u03ba\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1\u03c2"
+ ::msgcat::mcset el "&Ignore" "\u0391\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7"
+ ::msgcat::mcset el "Invalid file name \"%1\$s\"." \
+ "\u0386\u03ba\u03c5\u03c1\u03bf \u03cc\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \"%1\$s\"."
+ ::msgcat::mcset el "Log Files" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2"
+ ::msgcat::mcset el "&No" "\u038c\u03c7\u03b9"
+ ::msgcat::mcset el "&OK" "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
+ ::msgcat::mcset el "&Ok" "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
+ ::msgcat::mcset el "Open" "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1"
+ ::msgcat::mcset el "&Open" "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1"
+ ::msgcat::mcset el "Open Multiple Files" \
+ "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03ce\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd"
+ ::msgcat::mcset el "Paste" "\u0395\u03c0\u03b9\u03ba\u03cc\u03bb\u03bb\u03b7\u03c3\u03b7"
+ ::msgcat::mcset el "Quit" "\u0388\u03be\u03bf\u03b4\u03bf\u03c2"
+ ::msgcat::mcset el "&Red" "\u039a\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "Replace existing file?" \
+ "\u0395\u03c0\u03b9\u03ba\u03ac\u03bb\u03c5\u03c8\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03bd\u03c4\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5;"
+ ::msgcat::mcset el "&Retry" "\u03a0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac"
+ ::msgcat::mcset el "&Save" "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7"
+ ::msgcat::mcset el "Save As" "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03b1\u03bd"
+ ::msgcat::mcset el "Save To Log" "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2"
+ ::msgcat::mcset el "Select Log File" "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2"
+ ::msgcat::mcset el "Select a file to source" \
+ "\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b3\u03b9\u03b1 \u03b5\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7"
+ ::msgcat::mcset el "&Selection:" "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae:"
+ ::msgcat::mcset el "Skip Messages" "\u0391\u03c0\u03bf\u03c6\u03c5\u03b3\u03ae \u03bc\u03c5\u03bd\u03b7\u03bc\u03ac\u03c4\u03c9\u03bd"
+ ::msgcat::mcset el "Source..." "\u0395\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7..."
+ ::msgcat::mcset el "Tcl Scripts" "Tcl Scripts"
+ ::msgcat::mcset el "Tcl for Windows" "Tcl \u03b3\u03b9\u03b1 Windows"
+ ::msgcat::mcset el "Text Files" "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b5\u03b9\u03bc\u03ad\u03bd\u03bf\u03c5"
+ ::msgcat::mcset el "&Yes" "\u039d\u03b1\u03b9"
+ ::msgcat::mcset el "abort" "\u03c4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2"
+ ::msgcat::mcset el "blue" "\u03bc\u03c0\u03bb\u03b5"
+ ::msgcat::mcset el "cancel" "\u03b1\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7"
+ ::msgcat::mcset el "extension" "\u03b5\u03c0\u03ad\u03ba\u03c4\u03b1\u03c3\u03b7"
+ ::msgcat::mcset el "extensions" "\u03b5\u03c0\u03b5\u03ba\u03c4\u03ac\u03c3\u03b5\u03b9\u03c2"
+ ::msgcat::mcset el "green" "\u03c0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "ignore" "\u03b1\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7"
+ ::msgcat::mcset el "ok" "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
+ ::msgcat::mcset el "red" "\u03ba\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf"
+ ::msgcat::mcset el "retry" "\u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac"
+ ::msgcat::mcset el "yes" "\u03bd\u03b1\u03b9"
+}
+
diff --git a/ext/tk/sample/msgs_tk/en.msg b/ext/tk/sample/msgs_tk/en.msg
new file mode 100644
index 0000000000..de586d195e
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/en.msg
@@ -0,0 +1,83 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset en "Application Error"
+ ::msgcat::mcset en "Blue"
+ ::msgcat::mcset en "Color"
+ ::msgcat::mcset en "Delete"
+ ::msgcat::mcset en "Error"
+ ::msgcat::mcset en "Green"
+ ::msgcat::mcset en "Red"
+ ::msgcat::mcset en "blue"
+ ::msgcat::mcset en "green"
+ ::msgcat::mcset en "red"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset en "&Abort"
+ ::msgcat::mcset en "About..."
+ ::msgcat::mcset en "All Files"
+ ::msgcat::mcset en "Application Error"
+ ::msgcat::mcset en "&Blue"
+ ::msgcat::mcset en "&Cancel"
+ ::msgcat::mcset en "Cannot change to the directory \"%1\$s\".\nPermission denied."
+ ::msgcat::mcset en "Choose Directory"
+ ::msgcat::mcset en "Clear"
+ ::msgcat::mcset en "Color"
+ ::msgcat::mcset en "Console"
+ ::msgcat::mcset en "Copy"
+ ::msgcat::mcset en "Cut"
+ ::msgcat::mcset en "Delete"
+ ::msgcat::mcset en "Details >>"
+ ::msgcat::mcset en "Directory \"%1\$s\" does not exist."
+ ::msgcat::mcset en "&Directory:"
+ ::msgcat::mcset en "Error: %1\$s"
+ ::msgcat::mcset en "Exit"
+ ::msgcat::mcset en "File \"%1\$s\" already exists.\nDo you want to overwrite it?"
+ ::msgcat::mcset en "File \"%1\$s\" already exists.\n\n"
+ ::msgcat::mcset en "File \"%1\$s\" does not exist."
+ ::msgcat::mcset en "File &name:"
+ ::msgcat::mcset en "File &names:"
+ ::msgcat::mcset en "Files of &type:"
+ ::msgcat::mcset en "Fi&les:"
+ ::msgcat::mcset en "&Filter"
+ ::msgcat::mcset en "Fil&ter:"
+ ::msgcat::mcset en "&Green"
+ ::msgcat::mcset en "Hi"
+ ::msgcat::mcset en "Hide Console"
+ ::msgcat::mcset en "&Ignore"
+ ::msgcat::mcset en "Invalid file name \"%1\$s\"."
+ ::msgcat::mcset en "Log Files"
+ ::msgcat::mcset en "&No"
+ ::msgcat::mcset en "&OK"
+ ::msgcat::mcset en "Ok"
+ ::msgcat::mcset en "Open"
+ ::msgcat::mcset en "&Open"
+ ::msgcat::mcset en "Open Multiple Files"
+ ::msgcat::mcset en "Paste"
+ ::msgcat::mcset en "Quit"
+ ::msgcat::mcset en "&Red"
+ ::msgcat::mcset en "Replace existing file?"
+ ::msgcat::mcset en "&Retry"
+ ::msgcat::mcset en "&Save"
+ ::msgcat::mcset en "Save As"
+ ::msgcat::mcset en "Save To Log"
+ ::msgcat::mcset en "Select Log File"
+ ::msgcat::mcset en "Select a file to source"
+ ::msgcat::mcset en "&Selection:"
+ ::msgcat::mcset en "Skip Messages"
+ ::msgcat::mcset en "Source..."
+ ::msgcat::mcset en "Tcl Scripts"
+ ::msgcat::mcset en "Tcl for Windows"
+ ::msgcat::mcset en "Text Files"
+ ::msgcat::mcset en "&Yes"
+ ::msgcat::mcset en "abort"
+ ::msgcat::mcset en "blue"
+ ::msgcat::mcset en "cancel"
+ ::msgcat::mcset en "extension"
+ ::msgcat::mcset en "extensions"
+ ::msgcat::mcset en "green"
+ ::msgcat::mcset en "ignore"
+ ::msgcat::mcset en "ok"
+ ::msgcat::mcset en "red"
+ ::msgcat::mcset en "retry"
+ ::msgcat::mcset en "yes"
+}
diff --git a/ext/tk/sample/msgs_tk/en_gb.msg b/ext/tk/sample/msgs_tk/en_gb.msg
new file mode 100644
index 0000000000..1aa5b49380
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/en_gb.msg
@@ -0,0 +1,7 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset en_gb Color Colour
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset en_gb Color Colour
+}
diff --git a/ext/tk/sample/msgs_tk/eo.msg b/ext/tk/sample/msgs_tk/eo.msg
new file mode 100644
index 0000000000..e683cef297
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/eo.msg
@@ -0,0 +1,87 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset eo "Application Error" "Aplikoerraro"
+ ::msgcat::mcset eo "Blue" "Blua"
+ ::msgcat::mcset eo "Color" "Farbo"
+ ::msgcat::mcset eo "Delete" "Forprenu"
+ ::msgcat::mcset eo "Error" "Eraro"
+ ::msgcat::mcset eo "Exit" "Eliru"
+ ::msgcat::mcset eo "Green" "Verda"
+ ::msgcat::mcset eo "Red" "Rosa"
+ ::msgcat::mcset eo "blue" "blua"
+ ::msgcat::mcset eo "green" "verda"
+ ::msgcat::mcset eo "red" "ru\u011da"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset eo "&Abort" "&\u0108esigo"
+ ::msgcat::mcset eo "&About..." "Pri..."
+ ::msgcat::mcset eo "All Files" "\u0108ioj dosieroj"
+ ::msgcat::mcset eo "Application Error" "Aplikoerraro"
+ ::msgcat::mcset eo "&Blue" "&Blua"
+ ::msgcat::mcset eo "&Cancel" "&Rezignu"
+ ::msgcat::mcset eo "Cannot change to the directory \"%1\$s\".\nPermission denied." "Neeble \u0109angi al dosierulon \"%1\$s\".\nVi ne rajtas tion."
+ ::msgcat::mcset eo "Choose Directory" "Elektu Dosierujo"
+ ::msgcat::mcset eo "&Clear" "&Klaru"
+ ::msgcat::mcset eo "&Clear Console" "&Klaru konzolon"
+ ::msgcat::mcset eo "Color" "Farbo"
+ ::msgcat::mcset eo "Console" "Konzolo"
+ ::msgcat::mcset eo "&Copy" "&Kopiu"
+ ::msgcat::mcset eo "Cu&t" "&Enpo\u015digu"
+ ::msgcat::mcset eo "&Delete" "&Forprenu"
+ ::msgcat::mcset eo "Details >>" "Detaloj >>"
+ ::msgcat::mcset eo "Directory \"%1\$s\" does not exist." "La dosierujo \"%1\$s\" ne ekzistas."
+ ::msgcat::mcset eo "&Directory:" "&Dosierujo:"
+ ::msgcat::mcset eo "&Edit" "&Redaktu"
+ ::msgcat::mcset eo "Error: %1\$s" "Eraro: %1\$s"
+ ::msgcat::mcset eo "E&xit" "&Eliru"
+ ::msgcat::mcset eo "&File" "&Dosiero"
+ ::msgcat::mcset eo "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "La dosiero \"%1\$s\" jam ekzistas.\n\u0108u vi volas anstata\u00fbigi la dosieron?"
+ ::msgcat::mcset eo "File \"%1\$s\" already exists.\n\n" "La dosiero \"%1\$s\" jam egzistas. \n\n"
+ ::msgcat::mcset eo "File \"%1\$s\" does not exist." "La dosierp \"%1\$s\" ne estas."
+ ::msgcat::mcset eo "File &name:" "Dosiero&nomo:"
+ ::msgcat::mcset eo "File &names:" "Dosiero&nomoj:"
+ ::msgcat::mcset eo "Files of &type:" "Dosieroj de &Typo:"
+ ::msgcat::mcset eo "Fi&les:" "Do&sieroj:"
+ ::msgcat::mcset eo "&Filter" "&Filtrilo"
+ ::msgcat::mcset eo "Fil&ter:" "&Filtrilo:"
+ ::msgcat::mcset eo "&Green" "&Verda"
+ ::msgcat::mcset eo "&Help" "&Helpu"
+ ::msgcat::mcset eo "Hi" "Saluton"
+ ::msgcat::mcset eo "&Hide Console" "&Ka\u015du konzolon"
+ ::msgcat::mcset eo "&Ignore" "&Ignoru"
+ ::msgcat::mcset eo "Invalid file name \"%1\$s\"." "Malvalida dosieronomo \"%1\$s\"."
+ ::msgcat::mcset eo "Log Files" "Protokolo"
+ ::msgcat::mcset eo "&No" "&Ne"
+ ::msgcat::mcset eo "OK"
+ ::msgcat::mcset eo "Ok"
+ ::msgcat::mcset eo "Open" "Malfermu"
+ ::msgcat::mcset eo "&Open" "&Malfermu"
+ ::msgcat::mcset eo "Open Multiple Files" "Melfermu multan dosierojn"
+ ::msgcat::mcset eo "P&aste" "&Elpo\u015digi"
+ ::msgcat::mcset eo "&Quit" "&Finigu"
+ ::msgcat::mcset eo "&Red" "&Rosa"
+ ::msgcat::mcset eo "Replace existing file?" "\u0108u anstata\u00fbu ekzistantan dosieron?"
+ ::msgcat::mcset eo "&Retry" "&Ripetu"
+ ::msgcat::mcset eo "&Save" "&Savu"
+ ::msgcat::mcset eo "Save As" "Savu kiel"
+ ::msgcat::mcset eo "Save To Log" "Savu en protokolon"
+ ::msgcat::mcset eo "Select Log File" "Elektu prokolodosieron"
+ ::msgcat::mcset eo "Select a file to source" "Elektu dosieron por interpreti"
+ ::msgcat::mcset eo "&Selection:" "&Elekto:"
+ ::msgcat::mcset eo "Skip Messages" "transsaltu pluajn mesa\u011dojn"
+ ::msgcat::mcset eo "&Source..." "&Fontoprogramo..."
+ ::msgcat::mcset eo "Tcl Scripts" "Tcl-skriptoj"
+ ::msgcat::mcset eo "Tcl for Windows" "Tcl por vindoso"
+ ::msgcat::mcset eo "Text Files" "Tekstodosierojn"
+ ::msgcat::mcset eo "&Yes" "&Jes"
+ ::msgcat::mcset eo "abort" "\u0109esigo"
+ ::msgcat::mcset eo "blue" "blua"
+ ::msgcat::mcset eo "cancel" "rezignu"
+ ::msgcat::mcset eo "extension" "ekspansio"
+ ::msgcat::mcset eo "extensions" "ekspansioj"
+ ::msgcat::mcset eo "green" "verda"
+ ::msgcat::mcset eo "ignore" "ignorieren"
+ ::msgcat::mcset eo "red" "ru\u011da"
+ ::msgcat::mcset eo "retry" "ripetu"
+ ::msgcat::mcset eo "yes" "jes"
+}
diff --git a/ext/tk/sample/msgs_tk/es.msg b/ext/tk/sample/msgs_tk/es.msg
new file mode 100644
index 0000000000..ba981236a3
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/es.msg
@@ -0,0 +1,84 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset es "Application Error" "Error de la aplicaci\u00f3n"
+ ::msgcat::mcset es "Blue" "Azul"
+ ::msgcat::mcset es "Color" "Color"
+ ::msgcat::mcset es "Delete" "Borrar"
+ ::msgcat::mcset es "Error" "Error"
+ ::msgcat::mcset es "Exit" "Salir"
+ ::msgcat::mcset es "Green" "Verde"
+ ::msgcat::mcset es "Red" "Rojo"
+ ::msgcat::mcset es "blue" "azul"
+ ::msgcat::mcset es "green" "verde"
+ ::msgcat::mcset es "red" "rojo"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset es "&Abort" "&Abortar"
+ ::msgcat::mcset es "About..." "Acerca de ..."
+ ::msgcat::mcset es "All Files" "Todos los archivos"
+ ::msgcat::mcset es "Application Error" "Error de la aplicaci\u00f3n"
+ ::msgcat::mcset es "&Blue" "&Azul"
+ ::msgcat::mcset es "&Cancel" "&Cancelar"
+ ::msgcat::mcset es "Cannot change to the directory \"%1\$s\".\nPermission denied." "No es posible acceder al directorio \"%1\$s\".\nPermiso denegado."
+ ::msgcat::mcset es "Choose Directory" "Elegir directorio"
+ ::msgcat::mcset es "Clear" "Borrar"
+ ::msgcat::mcset es "Color" "Color"
+ ::msgcat::mcset es "Console" "Consola"
+ ::msgcat::mcset es "Copy" "Copiar"
+ ::msgcat::mcset es "Cut" "Cortar"
+ ::msgcat::mcset es "Delete" "Borrar"
+ ::msgcat::mcset es "Details >>" "Detalles >>"
+ ::msgcat::mcset es "Directory \"%1\$s\" does not exist." "El directorio \"%1\$s\" no existe."
+ ::msgcat::mcset es "&Directory:" "&Directorio:"
+ ::msgcat::mcset es "Error: %1\$s" "Error: %1\$s"
+ ::msgcat::mcset es "Exit" "Salir"
+ ::msgcat::mcset es "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "El archivo \"%1\$s\" ya existe.\nDesea sobreescribirlo?"
+ ::msgcat::mcset es "File \"%1\$s\" already exists.\n\n" "El archivo \"%1\$s\" ya existe.\n\n"
+ ::msgcat::mcset es "File \"%1\$s\" does not exist." "El archivo \"%1\$s\" no existe."
+ ::msgcat::mcset es "File &name:" "&Nombre de archivo:"
+ ::msgcat::mcset es "File &names:" "&Nombres de archivo:"
+ ::msgcat::mcset es "Files of &type:" "Archivos de &tipo:"
+ ::msgcat::mcset es "Fi&les:" "&Archivos:"
+ ::msgcat::mcset es "&Filter" "&Filtro"
+ ::msgcat::mcset es "Fil&ter:" "Fil&tro:"
+ ::msgcat::mcset es "&Green" "&Verde"
+ ::msgcat::mcset es "Hi" "Hola"
+ ::msgcat::mcset es "Hide Console" "Esconder la consola"
+ ::msgcat::mcset es "&Ignore" "&Ignorar"
+ ::msgcat::mcset es "Invalid file name \"%1\$s\"." "Nombre de archivo inv\u00e1lido \"%1\$s\"."
+ ::msgcat::mcset es "Log Files" "Ficheros de traza"
+ ::msgcat::mcset es "&No" "&No"
+ ::msgcat::mcset es "&OK" "&OK"
+ ::msgcat::mcset es "Ok" "Ok"
+ ::msgcat::mcset es "Open" "Abrir"
+ ::msgcat::mcset es "&Open" "&Abrir"
+ ::msgcat::mcset es "Open Multiple Files" "Abrir m\u00faltiples archivos"
+ ::msgcat::mcset es "Paste" "Pegar"
+ ::msgcat::mcset es "Quit" "Abandonar"
+ ::msgcat::mcset es "&Red" "&Rojo"
+ ::msgcat::mcset es "Replace existing file?" "Reemplazar el archivo existente?"
+ ::msgcat::mcset es "&Retry" "&Reintentar"
+ ::msgcat::mcset es "&Save" "&Salvar"
+ ::msgcat::mcset es "Save As" "Salvar como"
+ ::msgcat::mcset es "Save To Log" "Salvar al archivo de traza"
+ ::msgcat::mcset es "Select Log File" "Elegir un archivo de traza"
+ ::msgcat::mcset es "Select a file to source" "Seleccionar un archivo a evaluar"
+ ::msgcat::mcset es "&Selection:" "&Selecci\u00f3n:"
+ ::msgcat::mcset es "Skip Messages" "Omitir los mensajes"
+ ::msgcat::mcset es "Source..." "Evaluar..."
+ ::msgcat::mcset es "Tcl Scripts" "Scripts Tcl"
+ ::msgcat::mcset es "Tcl for Windows" "Tcl para Windows"
+ ::msgcat::mcset es "Text Files" "Archivos de texto"
+ ::msgcat::mcset es "&Yes" "&S\u00ed"
+ ::msgcat::mcset es "abort" "abortar"
+ ::msgcat::mcset es "blue" "azul"
+ ::msgcat::mcset es "cancel" "cancelar"
+ ::msgcat::mcset es "extension" "extensi\u00f3n"
+ ::msgcat::mcset es "extensions" "extensiones"
+ ::msgcat::mcset es "green" "verde"
+ ::msgcat::mcset es "ignore" "ignorar"
+ ::msgcat::mcset es "ok" "ok"
+ ::msgcat::mcset es "red" "rojo"
+ ::msgcat::mcset es "retry" "reintentar"
+ ::msgcat::mcset es "yes" "s\u00ed"
+}
diff --git a/ext/tk/sample/msgs_tk/fr.msg b/ext/tk/sample/msgs_tk/fr.msg
new file mode 100644
index 0000000000..ebbba48ca1
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/fr.msg
@@ -0,0 +1,84 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset fr "Application Error" "Erreur d'application"
+ ::msgcat::mcset fr "Blue" "Bleu"
+ ::msgcat::mcset fr "Color" "Couleur"
+ ::msgcat::mcset fr "Delete" "Effacer"
+ ::msgcat::mcset fr "Error" "Erreur"
+ ::msgcat::mcset fr "Exit" "Quitter"
+ ::msgcat::mcset fr "Green" "Vert"
+ ::msgcat::mcset fr "Red" "Rouge"
+ ::msgcat::mcset fr "blue" "bleu"
+ ::msgcat::mcset fr "green" "vert"
+ ::msgcat::mcset fr "red" "rouge"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset fr "&Abort" "&Annuler"
+ ::msgcat::mcset fr "About..." "\u00c0 propos..."
+ ::msgcat::mcset fr "All Files" "Tous les fichiers"
+ ::msgcat::mcset fr "Application Error" "Erreur d'application"
+ ::msgcat::mcset fr "&Blue" "&Bleu"
+ ::msgcat::mcset fr "&Cancel" "&Annuler"
+ ::msgcat::mcset fr "Cannot change to the directory \"%1\$s\".\nPermission denied." "Impossible d'acc\u00e9der au r\u00e9pertoire \"%1\$s\".\nPermission refus\u00e9e."
+ ::msgcat::mcset fr "Choose Directory" "Choisir r\u00e9pertoire"
+ ::msgcat::mcset fr "Clear" "Effacer"
+ ::msgcat::mcset fr "Color" "Couleur"
+ ::msgcat::mcset fr "Console"
+ ::msgcat::mcset fr "Copy" "Copier"
+ ::msgcat::mcset fr "Cut" "Couper"
+ ::msgcat::mcset fr "Delete" "Effacer"
+ ::msgcat::mcset fr "Details >>" "D\u00e9tails >>"
+ ::msgcat::mcset fr "Directory \"%1\$s\" does not exist." "Le r\u00e9pertoire \"%1\$s\" n'existe pas."
+ ::msgcat::mcset fr "&Directory:" "&R\u00e9pertoire:"
+ ::msgcat::mcset fr "Error: %1\$s" "Erreur: %1\$s"
+ ::msgcat::mcset fr "Exit" "Quitter"
+ ::msgcat::mcset fr "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Le fichier \"%1\$s\" existe d\u00e9j\u00e0.\nVoulez-vous l'\u00e9craser?"
+ ::msgcat::mcset fr "File \"%1\$s\" already exists.\n\n" "Le fichier \"%1\$s\" existe d\u00e9j\u00e0.\n\n"
+ ::msgcat::mcset fr "File \"%1\$s\" does not exist." "Le fichier \"%1\$s\" n'existe pas."
+ ::msgcat::mcset fr "File &name:" "&Nom de fichier:"
+ ::msgcat::mcset fr "File &names:" "&Noms de fichiers:"
+ ::msgcat::mcset fr "Files of &type:" "&Type de fichiers:"
+ ::msgcat::mcset fr "Fi&les:" "Fich&iers:"
+ ::msgcat::mcset fr "&Filter" "&Filtre"
+ ::msgcat::mcset fr "Fil&ter:" "Fil&tre:"
+ ::msgcat::mcset fr "&Green" "&Vert"
+ ::msgcat::mcset fr "Hi" "Salut"
+ ::msgcat::mcset fr "Hide Console" "Cacher la Console"
+ ::msgcat::mcset fr "&Ignore" "&Ignorer"
+ ::msgcat::mcset fr "Invalid file name \"%1\$s\"." "Nom de fichier invalide \"%1\$s\"."
+ ::msgcat::mcset fr "Log Files" "Fichiers de trace"
+ ::msgcat::mcset fr "&No" "&Non"
+ ::msgcat::mcset fr "&OK"
+ ::msgcat::mcset fr "Ok"
+ ::msgcat::mcset fr "Open" "Ouvrir"
+ ::msgcat::mcset fr "&Open" "&Ouvrir"
+ ::msgcat::mcset fr "Open Multiple Files" "Ouvrir plusieurs fichiers"
+ ::msgcat::mcset fr "Paste" "Coller"
+ ::msgcat::mcset fr "Quit" "Quitter"
+ ::msgcat::mcset fr "&Red" "&Rouge"
+ ::msgcat::mcset fr "Replace existing file?" "Remplacer le fichier existant?"
+ ::msgcat::mcset fr "&Retry" "&R\u00e9-essayer"
+ ::msgcat::mcset fr "&Save" "&Sauvegarder"
+ ::msgcat::mcset fr "Save As" "Sauvegarder sous"
+ ::msgcat::mcset fr "Save To Log" "Sauvegarde au fichier de trace"
+ ::msgcat::mcset fr "Select Log File" "Choisir un fichier de trace"
+ ::msgcat::mcset fr "Select a file to source" "Choisir un fichier \u00e0 \u00e9valuer"
+ ::msgcat::mcset fr "&Selection:" "&S\u00e9lection:"
+ ::msgcat::mcset fr "Skip Messages" "Omettre les messages"
+ ::msgcat::mcset fr "Source..." "\u00c9valuer..."
+ ::msgcat::mcset fr "Tcl Scripts" "Scripts Tcl"
+ ::msgcat::mcset fr "Tcl for Windows" "Tcl pour Windows"
+ ::msgcat::mcset fr "Text Files" "Fichiers texte"
+ ::msgcat::mcset fr "&Yes" "&Oui"
+ ::msgcat::mcset fr "abort" "abandonner"
+ ::msgcat::mcset fr "blue" "bleu"
+ ::msgcat::mcset fr "cancel" "annuler"
+ ::msgcat::mcset fr "extension"
+ ::msgcat::mcset fr "extensions"
+ ::msgcat::mcset fr "green" "vert"
+ ::msgcat::mcset fr "ignore" "ignorer"
+ ::msgcat::mcset fr "ok"
+ ::msgcat::mcset fr "red" "rouge"
+ ::msgcat::mcset fr "retry" "r\u00e9essayer"
+ ::msgcat::mcset fr "yes" "oui"
+}
diff --git a/ext/tk/sample/msgs_tk/it.msg b/ext/tk/sample/msgs_tk/it.msg
new file mode 100644
index 0000000000..b144fcc073
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/it.msg
@@ -0,0 +1,84 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset it "Application Error" "Errore dell' applicazione"
+ ::msgcat::mcset it "Blue" "Blu"
+ ::msgcat::mcset it "Color" "Colore"
+ ::msgcat::mcset it "Delete" "Incolla"
+ ::msgcat::mcset it "Error" "Errore"
+ ::msgcat::mcset it "Exit" "Esci"
+ ::msgcat::mcset it "Green" "Verde"
+ ::msgcat::mcset it "Red" "Rosso"
+ ::msgcat::mcset it "blue" "blu"
+ ::msgcat::mcset it "green" "verde"
+ ::msgcat::mcset it "red" "rosso"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset it "&Abort" "&Interrompi"
+ ::msgcat::mcset it "About..." "Informazioni ..."
+ ::msgcat::mcset it "All Files" "Tutti i file"
+ ::msgcat::mcset it "Application Error" "Errore dell' applicazione"
+ ::msgcat::mcset it "&Blue" "&Blu"
+ ::msgcat::mcset it "&Cancel" "&Annulla"
+ ::msgcat::mcset it "Cannot change to the directory \"%1\$s\".\nPermission denied." "Impossibile accedere alla directory \"%1\$s\".\nPermesso negato."
+ ::msgcat::mcset it "Choose Directory" "Scegli directory"
+ ::msgcat::mcset it "Clear" "Azzera"
+ ::msgcat::mcset it "Color" "Colore"
+ ::msgcat::mcset it "Console"
+ ::msgcat::mcset it "Copy" "Copia"
+ ::msgcat::mcset it "Cut" "Taglia"
+ ::msgcat::mcset it "Delete" "Incolla"
+ ::msgcat::mcset it "Details >>" "Dettagli >>"
+ ::msgcat::mcset it "Directory \"%1\$s\" does not exist." "La directory \"%1\$s\" non esiste."
+ ::msgcat::mcset it "&Directory:"
+ ::msgcat::mcset it "Error: %1\$s" "Errore: %1\$s"
+ ::msgcat::mcset it "Exit" "Esci"
+ ::msgcat::mcset it "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Il file \"%1\$s\" esiste gi\u00e0.\nVuoi sovrascriverlo?"
+ ::msgcat::mcset it "File \"%1\$s\" already exists.\n\n" "Il file \"%1\$s\" esiste gi\u00e0.\n\n"
+ ::msgcat::mcset it "File \"%1\$s\" does not exist." "Il file \"%1\$s\" non esiste."
+ ::msgcat::mcset it "File &name:" "&Nome del file:"
+ ::msgcat::mcset it "File &names:" "&Nomi dei file:"
+ ::msgcat::mcset it "Files of &type:" "File di &tipo:"
+ ::msgcat::mcset it "Fi&les:" "Fi&le:"
+ ::msgcat::mcset it "&Filter" "&Filtro"
+ ::msgcat::mcset it "Fil&ter:" "Fil&tro:"
+ ::msgcat::mcset it "&Green" "&Verde"
+ ::msgcat::mcset it "Hi" "Salve"
+ ::msgcat::mcset it "Hide Console" "Nascondi la console"
+ ::msgcat::mcset it "&Ignore" "&Ignora"
+ ::msgcat::mcset it "Invalid file name \"%1\$s\"." "Nome di file non valido \"%1\$s\"."
+ ::msgcat::mcset it "Log Files" "File di log"
+ ::msgcat::mcset it "&No"
+ ::msgcat::mcset it "&OK"
+ ::msgcat::mcset it "Ok"
+ ::msgcat::mcset it "&Open" "A&pri"
+ ::msgcat::mcset it "Open" "Apri"
+ ::msgcat::mcset it "Open Multiple Files" "Apri file multipli"
+ ::msgcat::mcset it "Paste" "Incolla"
+ ::msgcat::mcset it "Quit" "Esci"
+ ::msgcat::mcset it "&Red" "&Rosso"
+ ::msgcat::mcset it "Replace existing file?" "Sostituisci il file esistente?"
+ ::msgcat::mcset it "&Retry" "&Riprova"
+ ::msgcat::mcset it "&Save" "&Salva"
+ ::msgcat::mcset it "Save As" "Salva come"
+ ::msgcat::mcset it "Save To Log" "Salva il log"
+ ::msgcat::mcset it "Select Log File" "Scegli un file di log"
+ ::msgcat::mcset it "Select a file to source" "Scegli un file da eseguire"
+ ::msgcat::mcset it "&Selection:" "&Selezione:"
+ ::msgcat::mcset it "Skip Messages" "Salta i messaggi"
+ ::msgcat::mcset it "Source..." "Esegui..."
+ ::msgcat::mcset it "Tcl Scripts" "Scripts Tcl"
+ ::msgcat::mcset it "Tcl for Windows" "Tcl per Windows"
+ ::msgcat::mcset it "Text Files" "File di testo"
+ ::msgcat::mcset it "&Yes" "&Si"
+ ::msgcat::mcset it "abort" "interrompi"
+ ::msgcat::mcset it "blue" "blu"
+ ::msgcat::mcset it "cancel" "annulla"
+ ::msgcat::mcset it "extension" "estensione"
+ ::msgcat::mcset it "extensions" "estensioni"
+ ::msgcat::mcset it "green" "verde"
+ ::msgcat::mcset it "ignore" "ignora"
+ ::msgcat::mcset it "ok"
+ ::msgcat::mcset it "red" "rosso"
+ ::msgcat::mcset it "retry" "riprova"
+ ::msgcat::mcset it "yes" "si"
+}
diff --git a/ext/tk/sample/msgs_tk/ja.msg b/ext/tk/sample/msgs_tk/ja.msg
new file mode 100644
index 0000000000..44a25839db
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/ja.msg
@@ -0,0 +1,13 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset ja "Application Error" "\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30A8\u30E9\u30FC"
+ ::msgcat::mcset ja "Blue" "\u9752"
+ ::msgcat::mcset ja "Color" "\u80CC\u666F\u8272"
+ ::msgcat::mcset ja "Delete" "\u6D88\u53BB"
+ ::msgcat::mcset ja "Error" "\u30A8\u30E9\u30FC"
+ ::msgcat::mcset ja "Exit" "\u7D42\u4E86"
+ ::msgcat::mcset ja "Green" "\u7DD1"
+ ::msgcat::mcset ja "Red" "\u8D64"
+ ::msgcat::mcset ja "blue" "\u9752"
+ ::msgcat::mcset ja "green" "\u7DD1"
+ ::msgcat::mcset ja "red" "\u8D64"
+}
diff --git a/ext/tk/sample/msgs_tk/license.terms b/ext/tk/sample/msgs_tk/license.terms
new file mode 100644
index 0000000000..03ca6fcb31
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/license.terms
@@ -0,0 +1,39 @@
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., and other parties. The following
+terms apply to all files associated with the software unless explicitly
+disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
diff --git a/ext/tk/sample/msgs_tk/nl.msg b/ext/tk/sample/msgs_tk/nl.msg
new file mode 100644
index 0000000000..d9642e808c
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/nl.msg
@@ -0,0 +1,123 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset nl "Application Error" "Toepassingsfout"
+ ::msgcat::mcset nl "Blue" "Blauw"
+ ::msgcat::mcset nl "Color" "Kleur"
+ ::msgcat::mcset nl "Delete" "Wissen"
+ ::msgcat::mcset nl "Error" "Fout"
+ ::msgcat::mcset nl "Exit" "Be\u00ebindigen"
+ ::msgcat::mcset nl "Green" "Groen"
+ ::msgcat::mcset nl "Red" "Rood"
+ ::msgcat::mcset nl "blue" "blauw"
+ ::msgcat::mcset nl "green" "groen"
+ ::msgcat::mcset nl "red" "rood"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset nl "\"%1\$s\" must be an absolute pathname" "\"%1\$s\" moet een absolute pad-naam zijn"
+ ::msgcat::mcset nl "%1\$s is not a toplevel window" "%1\$s is geen toplevel window"
+ ::msgcat::mcset nl ", or" ", of"
+ ::msgcat::mcset nl "-default, -icon, -message, -parent, -title, or -type" "-default, -icon, -message, -parent, -title, of -type"
+ ::msgcat::mcset nl "-initialdir, -mustexist, -parent, or -title" "-initialdir, -mustexist, -parent, of -title"
+ ::msgcat::mcset nl "&Abort" "&Afbreken"
+ ::msgcat::mcset nl "About..." "Over..."
+ ::msgcat::mcset nl "All Files" "Alle Bestanden"
+ ::msgcat::mcset nl "Application Error" "Toepassingsfout"
+ ::msgcat::mcset nl "&Blue" "&Blauw"
+ ::msgcat::mcset nl "&Cancel" "&Annuleren"
+ ::msgcat::mcset nl "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan niet naar map \"%1\$s\" gaan.\nU heeft hiervoor geen toestemming."
+ ::msgcat::mcset nl "Choose Directory" "Kies map"
+ ::msgcat::mcset nl "Clear" "Wissen"
+ ::msgcat::mcset nl "Clear entry, Press OK; Enter %1\$s, press OK" "Wis veld, Druk op OK; typ %1\$s in, druk op OK"
+ ::msgcat::mcset nl "&Clear Console" "&Wis Console"
+ ::msgcat::mcset nl "Color" "Kleur"
+ ::msgcat::mcset nl "Console"
+ ::msgcat::mcset nl "Copy" "Kopi\u00ebren"
+ ::msgcat::mcset nl "Cut" "Knippen"
+ ::msgcat::mcset nl "Delete" "Wissen"
+ ::msgcat::mcset nl "Details"
+ ::msgcat::mcset nl "Details >>"
+ ::msgcat::mcset nl "Directory \"%1\$s\" does not exist." "Map \"%1\$s\" bestaat niet."
+ ::msgcat::mcset nl "&Directory:" "&Map:"
+ ::msgcat::mcset nl "Edit" "Bewerken"
+ ::msgcat::mcset nl "Enter \"%1\$s\", press OK" "Typ \"%1\$s\", druk op OK"
+ ::msgcat::mcset nl "Enter \"%1\$s\", press OK, enter \"%2\$s\", press OK" "Typ \"%1\$s\", druk op OK, typ \"%2\$s\", druk op OK"
+ ::msgcat::mcset nl "Error: %1\$s" "Fout: %1\$s"
+ ::msgcat::mcset nl "Exit" "Be\u00ebindigen"
+ ::msgcat::mcset nl "File" "Bestand"
+ ::msgcat::mcset nl "File \"%1\$s\" already exists.\n\n" "Bestand \"%1\$s\" bestaat al.\n\n"
+ ::msgcat::mcset nl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Bestand \"%1\$s\" bestaat al.\nWilt u het overschrijven?"
+ ::msgcat::mcset nl "File \"%1\$s\" does not exist." "Bestand \"%1\$s\" bestaat niet."
+ ::msgcat::mcset nl "File &name:" "Bestands&naam:"
+ ::msgcat::mcset nl "File &names:" "Bestands&namen:"
+ ::msgcat::mcset nl "Files of &type:" "Bestanden van het &type:"
+ ::msgcat::mcset nl "Fi&les:" "&Bestanden:"
+ ::msgcat::mcset nl "&Filter"
+ ::msgcat::mcset nl "Fil&ter:"
+ ::msgcat::mcset nl "&Green" "&Groen"
+ ::msgcat::mcset nl "Hi" "H\u00e9"
+ ::msgcat::mcset nl "Hide Console" "Verberg Console"
+ ::msgcat::mcset nl "&Ignore" "&Negeren"
+ ::msgcat::mcset nl "Invalid file name \"%1\$s\"." "Ongeldige bestandsnaam \"%1\$s\"."
+ ::msgcat::mcset nl "Log Files" "Log Bestanden"
+ ::msgcat::mcset nl "&No" "&Nee"
+ ::msgcat::mcset nl "&OK"
+ ::msgcat::mcset nl "Ok"
+ ::msgcat::mcset nl "&Open" "&Openen"
+ ::msgcat::mcset nl "Open" "Openen"
+ ::msgcat::mcset nl "Open Multiple Files" "Open meerdere bestanden"
+ ::msgcat::mcset nl "Paste" "Plakken"
+ ::msgcat::mcset nl "Please press %1\$s" "Druk op %1\$s, A.U.B."
+ ::msgcat::mcset nl "Please press ok" "Druk op ok, A.U.B."
+ ::msgcat::mcset nl "Press Cancel" "Druk op Annuleren"
+ ::msgcat::mcset nl "Press Ok" "Druk op Ok"
+ ::msgcat::mcset nl "Quit" "Stoppen"
+ ::msgcat::mcset nl "&Red" "&Rood"
+ ::msgcat::mcset nl "Replace existing file?" "Vervang bestaand bestand?"
+ ::msgcat::mcset nl "&Retry" "&Herhalen"
+ ::msgcat::mcset nl "&Save" "Op&slaan"
+ ::msgcat::mcset nl "Save As" "Opslaan als"
+ ::msgcat::mcset nl "Save To Log" "Opslaan naar Log"
+ ::msgcat::mcset nl "Select Log File" "Selecteer Log bestand"
+ ::msgcat::mcset nl "Select a file to source" "Selecteer bronbestand"
+ ::msgcat::mcset nl "&Selection:" "&Selectie:"
+ ::msgcat::mcset nl "Skip Messages" "Berichten overslaan"
+ ::msgcat::mcset nl "Source..." "Bron..."
+ ::msgcat::mcset nl "Tcl Scripts"
+ ::msgcat::mcset nl "Tcl for Windows" "Tcl voor Windows"
+ ::msgcat::mcset nl "Text Files" "Tekstbestanden"
+ ::msgcat::mcset nl "&Yes" "&Ja"
+ ::msgcat::mcset nl "abort" "afbreken"
+ ::msgcat::mcset nl "abort, retry, ignore, ok, cancel, no, or yes" "afbreken, opnieuw, negeren, ok, annuleren, nee, of ja"
+ ::msgcat::mcset nl "abortretryignore, ok, okcancel, retrycancel, yesno, or yesnocancel" "abortretryignore, ok, okcancel, retrycancel, yesno, of yesnocancel"
+ ::msgcat::mcset nl "bad %1\$s value \"%2\$s\": must be %3\$s" "verkeerde %1\$s waarde \"%2\$s\": moet zijn %3\$s"
+ ::msgcat::mcset nl "bad file type \"%1\$s\", should be" "verkeerd bestandstype \"%1\$s\", moet zijn"
+ ::msgcat::mcset nl "bad option \"%1\$s\": should be %2\$s" "verkeerde optie \"%1\$s\": moet zijn %2\$s"
+ ::msgcat::mcset nl "bad window path name \"%1\$s\"" "verkeerde window-padnaam \"%1\$s\""
+ ::msgcat::mcset nl "blue" "blauw"
+ ::msgcat::mcset nl "can't post %1\$s: it isn't a descendant of %2\$s (this is a new requirement in Tk versions 3.0 and later)" "kan %1\$s niet verzenden: het is geen afstammeling van %2\$s (dit is een nieuwe eis in Tk versies 3.0 en later)"
+ ::msgcat::mcset nl "cancel" "annuleren"
+ ::msgcat::mcset nl "default button index greater than number of buttons specified for tk_dialog" "default knop index is groter dan het aantal knoppen beschikbaar voor tk_dialog"
+ ::msgcat::mcset nl "display name to use (current one otherwise)" "te gebruiken schermnaam (anders huidige scherm)"
+ ::msgcat::mcset nl "error, info, question, or warning" "error, info, question, of warning"
+ ::msgcat::mcset nl "extension"
+ ::msgcat::mcset nl "extensions"
+ ::msgcat::mcset nl "focus group \"%1\$s\" doesn't exist" "focusgroep \"%1\$s\" bestaat niet"
+ ::msgcat::mcset nl "green" "groen"
+ ::msgcat::mcset nl "history event %1\$s"
+ ::msgcat::mcset nl "ignore" "negeren"
+ ::msgcat::mcset nl "invalid default button \"%1\$s\"" "ongeldige default knop \"%1\$s\""
+ ::msgcat::mcset nl "macType"
+ ::msgcat::mcset nl "macTypes"
+ ::msgcat::mcset nl "must specify a background color" "een achtergrondkleur is verplicht"
+ ::msgcat::mcset nl "name of the slave interpreter" "naam van de slaaf-interpreter"
+ ::msgcat::mcset nl "no winfo screen . nor env(DISPLAY)" "geen winfo scherm . noch env(DISPLAY)"
+ ::msgcat::mcset nl "ok"
+ ::msgcat::mcset nl "red" "rood"
+ ::msgcat::mcset nl "retry" "opnieuw"
+ ::msgcat::mcset nl "should contain 5 or 4 elements" "moet 4 of 5 elementen bevatten"
+ ::msgcat::mcset nl "spec"
+ ::msgcat::mcset nl "tk_chooseDirectory command" "tk_chooseDirectory opdracht"
+ ::msgcat::mcset nl "tk_chooseDirectory command, cancel gives null" "tk_chooseDirectory opdracht, annuleren geeft lege waarde"
+ ::msgcat::mcset nl "tk_chooseDirectory command, initialdir" "tk_chooseDirectory opdracht, initi\u00eble map"
+ ::msgcat::mcset nl "yes" "ja"
+}
diff --git a/ext/tk/sample/msgs_tk/pl.msg b/ext/tk/sample/msgs_tk/pl.msg
new file mode 100644
index 0000000000..2699e42bdf
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/pl.msg
@@ -0,0 +1,87 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset pl "Application Error" "Bl\u0105d w Programie"
+ ::msgcat::mcset pl "Blue" "Niebieski"
+ ::msgcat::mcset pl "Color" "Kolor"
+ ::msgcat::mcset pl "Delete" "Usu\u0144"
+ ::msgcat::mcset pl "Error" "B\u0142\u0105d"
+ ::msgcat::mcset pl "Exit" "Zako\u0144cz"
+ ::msgcat::mcset pl "Green" "Zielony"
+ ::msgcat::mcset pl "Red" "Czerwonz"
+ ::msgcat::mcset pl "blue" "niebieski"
+ ::msgcat::mcset pl "green" "zielony"
+ ::msgcat::mcset pl "red" "czerwony"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset pl "&Abort" "&Anuluj"
+ ::msgcat::mcset pl "&About..." "O Programie..."
+ ::msgcat::mcset pl "All Files" "Wszystkie pliki"
+ ::msgcat::mcset pl "Application Error" "Bl\u0105d w Programie"
+ ::msgcat::mcset pl "&Blue" "&Niebieski"
+ ::msgcat::mcset pl "&Cancel" "&Anuluj"
+ ::msgcat::mcset pl "Cannot change to the directory \"%1\$s\".\nPermission denied." "Katalog \"%1\$s\" nie mo\u017ce zosta\u0107 odczytany lub nie istnieje."
+ ::msgcat::mcset pl "Choose Directory" "Wybierz katalog"
+ ::msgcat::mcset pl "&Clear" "&Wyczy\u015b\u0107"
+ ::msgcat::mcset pl "&Clear Console" "&Wyczy\u015b\u0107 konsol\u0119"
+ ::msgcat::mcset pl "Color" "Kolor"
+ ::msgcat::mcset pl "Console" "Konsola"
+ ::msgcat::mcset pl "&Copy" "&Kopiuj"
+ ::msgcat::mcset pl "Cu&t" "&Wytnij"
+ ::msgcat::mcset pl "&Delete" "&Usu\u0144"
+ ::msgcat::mcset pl "Details >>" "Detale >>"
+ ::msgcat::mcset pl "Directory \"%1\$s\" does not exist." "Katalog \"%1\$s\" nie istniej."
+ ::msgcat::mcset pl "&Directory:" "&Katalog:"
+ ::msgcat::mcset pl "&Edit" "&Edytuj"
+ ::msgcat::mcset pl "Error: %1\$s" "B\u0142\u0105d: %1\$s"
+ ::msgcat::mcset pl "E&xit" "&Zako\u0144cz"
+ ::msgcat::mcset pl "&File" "&Plik"
+ ::msgcat::mcset pl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Plik \"%1\$s\" ju\u017c istnieje.\nCzy chcesz go zast\u0105pi\u0107?"
+ ::msgcat::mcset pl "File \"%1\$s\" already exists.\n\n" "Plik \"%1\$s\" ju\u017c istnieje. \n\n"
+ ::msgcat::mcset pl "File \"%1\$s\" does not exist." "Plik \"%1\$s\" nie istnieje."
+ ::msgcat::mcset pl "File &name:" "Nazwa &pliku:"
+ ::msgcat::mcset pl "File &names:" "Nazwy &plik\u00f3w:"
+ ::msgcat::mcset pl "Files of &type:" "Pliki &typu:"
+ ::msgcat::mcset pl "Fi&les:" "Pli&ki:"
+ ::msgcat::mcset pl "&Filter" "&Filter"
+ ::msgcat::mcset pl "Fil&ter:" "&Filter:"
+ ::msgcat::mcset pl "&Green" "&Zielony"
+ ::msgcat::mcset pl "&Help" "&Pomoc"
+ ::msgcat::mcset pl "Hi" "Witaj"
+ ::msgcat::mcset pl "&Hide Console" "&Schowaj konsol\u0119"
+ ::msgcat::mcset pl "&Ignore" "&Ignoruj"
+ ::msgcat::mcset pl "Invalid file name \"%1\$s\"." "Niew\u0142a\u015bciwa nazwa pliku \"%1\$s\"."
+ ::msgcat::mcset pl "Log Files" "Protoko\u0142uj"
+ ::msgcat::mcset pl "&No" "&Nie"
+ ::msgcat::mcset pl "OK"
+ ::msgcat::mcset pl "Ok"
+ ::msgcat::mcset pl "Open" "Wczytaj"
+ ::msgcat::mcset pl "&Open" "&Wczytaj"
+ ::msgcat::mcset pl "Open Multiple Files" "Wczytuj wiele plik\u00f3w"
+ ::msgcat::mcset pl "P&aste" "&Wklej"
+ ::msgcat::mcset pl "&Quit" "&Zako\u0144cz"
+ ::msgcat::mcset pl "&Red" "&Czerwonz"
+ ::msgcat::mcset pl "Replace existing file?" "Czy zost\u0105pi\u0107 instniej\u0105cy plik?"
+ ::msgcat::mcset pl "&Retry" "&Powt\u00f3rz"
+ ::msgcat::mcset pl "&Save" "&Zapisz"
+ ::msgcat::mcset pl "Save As" "Zapisz jako"
+ ::msgcat::mcset pl "Save To Log" "Wpisz do protoko\u0142u"
+ ::msgcat::mcset pl "Select Log File" "Wybierz plik proko\u0142u"
+ ::msgcat::mcset pl "Select a file to source" "Wybierz plik do wykonania"
+ ::msgcat::mcset pl "&Selection:" "&Wyb\u00f3r:"
+ ::msgcat::mcset pl "Skip Messages" "Omi\u0144 pozosta\u0142e komunikaty"
+ ::msgcat::mcset pl "&Source..." "&Kod \u017ar\u00f3d\u0142owy..."
+ ::msgcat::mcset pl "Tcl Scripts" "Tcl-skrypty"
+ ::msgcat::mcset pl "Tcl for Windows" "Tcl dla Okienek (Windows)"
+ ::msgcat::mcset pl "Text Files" "Pliki Tekstowe"
+ ::msgcat::mcset pl "&Yes" "&Tak"
+ ::msgcat::mcset pl "abort" "zako\u0144cz"
+ ::msgcat::mcset pl "blue" "niebieski"
+ ::msgcat::mcset pl "cancel" "anuluj"
+ ::msgcat::mcset pl "extension" "rozszerzenie"
+ ::msgcat::mcset pl "extensions" "rozszerzenia"
+ ::msgcat::mcset pl "green" "zielony"
+ ::msgcat::mcset pl "ignore" "ignoruj"
+ ::msgcat::mcset pl "red" "czerwony"
+ ::msgcat::mcset pl "retry" "potw\u00f3rz"
+ ::msgcat::mcset pl "yes" "tak"
+}
diff --git a/ext/tk/sample/msgs_tk/ru.msg b/ext/tk/sample/msgs_tk/ru.msg
new file mode 100644
index 0000000000..a1192b7095
--- /dev/null
+++ b/ext/tk/sample/msgs_tk/ru.msg
@@ -0,0 +1,87 @@
+namespace eval ::tkmsgcat_demo {
+ ::msgcat::mcset ru "Application Error" "\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435"
+ ::msgcat::mcset ru "Blue" " \u0413\u043e\u043b\u0443\u0431\u043e\u0439"
+ ::msgcat::mcset ru "Color" "\u0426\u0432\u0435\u0442"
+ ::msgcat::mcset ru "Delete" "\u0423\u0434\u0430\u043b\u0438\u0442\u044c"
+ ::msgcat::mcset ru "Error" "\u041e\u0448\u0438\u0431\u043a\u0430"
+ ::msgcat::mcset ru "Exit" "\u0412\u044b\u0445\u043e\u0434"
+ ::msgcat::mcset ru "Green" "\u0417\u0435\u043b\u0435\u043d\u044b\u0439"
+ ::msgcat::mcset ru "Red" "\u041a\u0440\u0430\u0441\u043d\u044b\u0439"
+ ::msgcat::mcset ru "blue" " \u0433\u043e\u043b\u0443\u0431\u043e\u0439"
+ ::msgcat::mcset ru "green" " \u0437\u0435\u043b\u0435\u043d\u044b\u0439"
+ ::msgcat::mcset ru "red" " \u043a\u0440\u0430\u0441\u043d\u044b\u0439"
+}
+
+namespace eval ::tk {
+ ::msgcat::mcset ru "&Abort" "&\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c"
+ ::msgcat::mcset ru "About..." "\u041f\u0440\u043e..."
+ ::msgcat::mcset ru "All Files" "\u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b"
+ ::msgcat::mcset ru "Application Error" "\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435"
+ ::msgcat::mcset ru "&Blue" " &\u0413\u043e\u043b\u0443\u0431\u043e\u0439"
+ ::msgcat::mcset ru "&Cancel" "\u041e\u0442&\u043c\u0435\u043d\u0430"
+ ::msgcat::mcset ru "Cannot change to the directory \"%1\$s\".\nPermission denied." \
+ "\u041d\u0435 \u043c\u043e\u0433\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \"%1\$s\".\n\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430"
+ ::msgcat::mcset ru "Choose Directory" "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433"
+ ::msgcat::mcset ru "Clear" "\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c"
+ ::msgcat::mcset ru "Color" "\u0426\u0432\u0435\u0442"
+ ::msgcat::mcset ru "Console" "\u041a\u043e\u043d\u0441\u043e\u043b\u044c"
+ ::msgcat::mcset ru "Copy" "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c"
+ ::msgcat::mcset ru "Cut" "\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c"
+ ::msgcat::mcset ru "Delete" "\u0423\u0434\u0430\u043b\u0438\u0442\u044c"
+ ::msgcat::mcset ru "Details >>" "\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 >>"
+ ::msgcat::mcset ru "Directory \"%1\$s\" does not exist." "\u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \"%1\$s\" \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442."
+ ::msgcat::mcset ru "&Directory:" "&\u041a\u0430\u0442\u0430\u043b\u043e\u0433:"
+ ::msgcat::mcset ru "Error: %1\$s" "\u041e\u0448\u0438\u0431\u043a\u0430: %1\$s"
+ ::msgcat::mcset ru "Exit" "\u0412\u044b\u0445\u043e\u0434"
+ ::msgcat::mcset ru "File \"%1\$s\" already exists.\nDo you want to overwrite it?" \
+ "\u0424\u0430\u0439\u043b \"%1\$s\" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\n\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e?"
+ ::msgcat::mcset ru "File \"%1\$s\" already exists.\n\n" "\u0424\u0430\u0439\u043b \"%1\$s\" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\n\n"
+ ::msgcat::mcset ru "File \"%1\$s\" does not exist." "\u0424\u0430\u0439\u043b \"%1\$s\" \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d."
+ ::msgcat::mcset ru "File &name:" "&\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430:"
+ ::msgcat::mcset ru "File &names:" "&\u0418\u043c\u0435\u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432:"
+ ::msgcat::mcset ru "Files of &type:" "&\u0422\u0438\u043f \u0444\u0430\u0439\u043b\u043e\u0432:"
+ ::msgcat::mcset ru "Fi&les:" "\u0424\u0430\u0439&\u043b\u044b:"
+ ::msgcat::mcset ru "&Filter" "&\u0424\u0438\u043b\u044c\u0442\u0440"
+ ::msgcat::mcset ru "Fil&ter:" "\u0424\u0438\u043b\u044c&\u0442\u0440:"
+ ::msgcat::mcset ru "&Green" " &\u0417\u0435\u043b\u0435\u043d\u044b\u0439"
+ ::msgcat::mcset ru "Hi" "\u041f\u0440\u0438\u0432\u0435\u0442"
+ ::msgcat::mcset ru "Hide Console" "\u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u043e\u043b\u044c"
+ ::msgcat::mcset ru "&Ignore" "&\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c"
+ ::msgcat::mcset ru "Invalid file name \"%1\$s\"." "\u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \"%1\$s\"."
+ ::msgcat::mcset ru "Log Files" "\u0424\u0430\u0439\u043b\u044b \u0436\u0443\u0440\u043d\u0430\u043b\u0430"
+ ::msgcat::mcset ru "&No" "&\u041d\u0435\u0442"
+ ::msgcat::mcset ru "&OK" "&\u041e\u041a"
+ ::msgcat::mcset ru "Ok" "\u0414\u0430"
+ ::msgcat::mcset ru "Open" "\u041e\u0442\u043a\u0440\u044b\u0442\u044c"
+ ::msgcat::mcset ru "&Open" "&\u041e\u0442\u043a\u0440\u044b\u0442\u044c"
+ ::msgcat::mcset ru "Open Multiple Files" "\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432"
+ ::msgcat::mcset ru "Paste" "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c"
+ ::msgcat::mcset ru "Quit" "\u0412\u044b\u0445\u043e\u0434"
+ ::msgcat::mcset ru "&Red" " &\u041a\u0440\u0430\u0441\u043d\u044b\u0439"
+ ::msgcat::mcset ru "Replace existing file?" "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b?"
+ ::msgcat::mcset ru "&Retry" "&\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c"
+ ::msgcat::mcset ru "&Save" "&\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c"
+ ::msgcat::mcset ru "Save As" "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a"
+ ::msgcat::mcset ru "Save To Log" "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0436\u0443\u0440\u043d\u0430\u043b"
+ ::msgcat::mcset ru "Select Log File" "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0436\u0443\u0440\u043d\u0430\u043b"
+ ::msgcat::mcset ru "Select a file to source" "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438"
+ ::msgcat::mcset ru "&Selection:" "&Selection:"
+ ::msgcat::mcset ru "Skip Messages" "\u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f"
+ ::msgcat::mcset ru "Source..." "\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b..."
+ ::msgcat::mcset ru "Tcl Scripts" "\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 TCL"
+ ::msgcat::mcset ru "Tcl for Windows" "TCL \u0434\u043b\u044f Windows"
+ ::msgcat::mcset ru "Text Files" "\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b"
+ ::msgcat::mcset ru "&Yes" "&\u0414\u0430"
+ ::msgcat::mcset ru "abort" "\u043e\u0442\u043c\u0435\u043d\u0430"
+ ::msgcat::mcset ru "blue" " \u0433\u043e\u043b\u0443\u0431\u043e\u0439"
+ ::msgcat::mcset ru "cancel" "\u043e\u0442\u043c\u0435\u043d\u0430"
+ ::msgcat::mcset ru "extension" "\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435"
+ ::msgcat::mcset ru "extensions" "\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f"
+ ::msgcat::mcset ru "green" " \u0437\u0435\u043b\u0435\u043d\u044b\u0439"
+ ::msgcat::mcset ru "ignore" "\u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c"
+ ::msgcat::mcset ru "ok" "\u043e\u043a"
+ ::msgcat::mcset ru "red" " \u043a\u0440\u0430\u0441\u043d\u044b\u0439"
+ ::msgcat::mcset ru "retry" "\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c"
+ ::msgcat::mcset ru "yes" "\u0434\u0430"
+}
+
diff --git a/ext/tk/sample/multi-ip_sample.rb b/ext/tk/sample/multi-ip_sample.rb
new file mode 100644
index 0000000000..8d6e1bc626
--- /dev/null
+++ b/ext/tk/sample/multi-ip_sample.rb
@@ -0,0 +1,102 @@
+#!/usr/bin/env ruby
+# This script is a sample of MultiTkIp class
+
+require "multi-tk"
+
+# create slave interpreters
+trusted_slave = MultiTkIp.new_slave
+safe_slave1 = MultiTkIp.new_safeTk
+safe_slave2 = MultiTkIp.new_safeTk('fill'=>:none, 'expand'=>false)
+#safe_slave2 = MultiTkIp.new_safeTk('fill'=>:none)
+#safe_slave2 = MultiTkIp.new_safeTk('expand'=>false)
+
+cmd = Proc.new{|txt|
+ #####################
+ ## from TkTimer2.rb
+
+ if TkCore::INTERP.safe?
+ # safeTk doesn't have permission to call 'wm' command
+ else
+ root = TkRoot.new(:title=>'timer sample')
+ end
+
+ label = TkLabel.new(:parent=>root, :relief=>:raised, :width=>10) \
+ .pack(:side=>:bottom, :fill=>:both)
+
+ tick = proc{|aobj|
+ cnt = aobj.return_value + 5
+ label.text format("%d.%02d", *(cnt.divmod(100)))
+ cnt
+ }
+
+ timer = TkTimer.new(50, -1, tick).start(0, proc{ label.text('0.00'); 0 })
+
+=begin
+ TkButton.new(:text=>'Start') {
+ command proc{ timer.continue unless timer.running? }
+ pack(:side=>:left, :fill=>:both, :expand=>true)
+ }
+ TkButton.new(:text=>'Restart') {
+ command proc{ timer.restart(0, proc{ label.text('0.00'); 0 }) }
+ pack('side'=>'right','fill'=>'both','expand'=>'yes')
+ }
+ TkButton.new(:text=>'Stop') {
+ command proc{ timer.stop if timer.running? }
+ pack('side'=>'right','fill'=>'both','expand'=>'yes')
+ }
+=end
+ b_start = TkButton.new(:text=>'Start', :state=>:disabled) {
+ pack(:side=>:left, :fill=>:both, :expand=>true)
+ }
+ b_stop = TkButton.new(:text=>'Stop', :state=>:normal) {
+ pack('side'=>'left', 'fill'=>'both', 'expand'=>'yes')
+ }
+
+ b_start.command {
+ timer.continue
+ b_stop.state(:normal)
+ b_start.state(:disabled)
+ }
+
+ b_stop.command {
+ timer.stop
+ b_start.state(:normal)
+ b_stop.state(:disabled)
+ }
+
+ TkButton.new(:text=>'Reset', :state=>:normal) {
+ command { timer.reset }
+ pack('side'=>'right', 'fill'=>'both', 'expand'=>'yes')
+ }
+
+ ev_quit = TkVirtualEvent.new('Control-c', 'Control-q')
+ Tk.root.bind(ev_quit, proc{Tk.exit}).focus
+}
+
+# call on the default master interpreter
+trusted_slave.eval_proc(cmd, 'trusted') # label -> .w00012
+safe_slave1.eval_proc(cmd, 'safe1') # label -> .w00016
+safe_slave2.eval_proc(cmd, 'safe2') # label -> .w00020
+cmd.call('master') # label -> .w00024
+
+#second_master = MultiTkIp.new(&cmd)
+
+TkTimer.new(2000, -1, proc{p ['safe1', safe_slave1.deleted?]}).start
+TkTimer.new(2000, -1, proc{p ['safe2', safe_slave2.deleted?]}).start
+TkTimer.new(2000, -1, proc{p ['trusted', trusted_slave.deleted?]}).start
+
+TkTimer.new(5000, 1,
+ proc{
+ safe_slave1.eval_proc{Tk.root.destroy}
+ safe_slave1.delete
+ print "*** The safe_slave1 is deleted by the timer.\n"
+ }).start
+
+TkTimer.new(10000, 1,
+ proc{
+ trusted_slave.eval_proc{Tk.root.destroy}
+ trusted_slave.delete
+ print "*** The trusted_slave is deleted by the timer.\n"
+ }).start
+
+Tk.mainloop
diff --git a/ext/tk/sample/multi-ip_sample2.rb b/ext/tk/sample/multi-ip_sample2.rb
new file mode 100644
index 0000000000..f4a45d8d9a
--- /dev/null
+++ b/ext/tk/sample/multi-ip_sample2.rb
@@ -0,0 +1,29 @@
+require 'multi-tk.rb'
+
+th = Thread.new{Tk.mainloop}
+
+TkLabel.new(:text=>'this is a primary master').pack
+
+ip1 = MultiTkIp.new_slave(:safe=>1)
+ip2 = MultiTkIp.new_slave(:safe=>2)
+
+cmd = proc{|s|
+ require 'tk'
+
+ TkButton.new(:text=>'b1: p self', :command=>proc{p self}).pack(:fill=>:x)
+ sleep s
+ TkButton.new(:text=>'b2: p $SAFE', :command=>proc{p $SAFE}).pack(:fill=>:x)
+ sleep s
+ TkButton.new(:text=>'b3: p MultiTkIp.ip_name',
+ :command=>proc{p MultiTkIp.ip_name}).pack(:fill=>:x)
+ sleep s
+ TkButton.new(:text=>'EXIT', :command=>proc{exit}).pack(:fill=>:x)
+
+ Tk.mainloop
+}
+
+Thread.new{ip1.eval_proc(cmd, 1.1)}
+Thread.new{ip2.eval_proc(cmd, 0.3)}
+cmd.call(0.7)
+
+th.join
diff --git a/ext/tk/sample/optobj_sample.rb b/ext/tk/sample/optobj_sample.rb
new file mode 100644
index 0000000000..cafacbdd17
--- /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/propagate.rb b/ext/tk/sample/propagate.rb
new file mode 100644
index 0000000000..800cef553d
--- /dev/null
+++ b/ext/tk/sample/propagate.rb
@@ -0,0 +1,30 @@
+#!/usr/bin/env ruby
+require 'tk'
+
+TkLabel.new(:text=>"Please click the bottom frame").pack
+
+f = TkFrame.new(:width=>400, :height=>100, :background=>'yellow',
+ :relief=>'ridge', :borderwidth=>5).pack
+
+# TkPack.propagate(f, false) # <== important!!
+f.pack_propagate(false) # <== important!!
+
+list = (1..3).collect{|n|
+ TkButton.new(f, :text=>"button#{'-X'*n}"){
+ command proc{
+ puts "button#{'-X'*n}"
+ self.unpack
+ }
+ }
+}
+
+list.unshift(nil)
+
+f.bind('1', proc{
+ w = list.shift
+ w.unpack if w
+ list.push(w)
+ list[0].pack(:expand=>true, :anchor=>:center) if list[0]
+ })
+
+Tk.mainloop
diff --git a/ext/tk/sample/remote-ip_sample.rb b/ext/tk/sample/remote-ip_sample.rb
new file mode 100644
index 0000000000..3696a20852
--- /dev/null
+++ b/ext/tk/sample/remote-ip_sample.rb
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+require 'remote-tk'
+
+puts <<EOM
+This sample controls the other Tk interpreter (Ruby/Tk, Tcl/Tk, and so on)
+which running on the other process. For this purpose, Ruby/Tk uses Tcl/Tk's
+'send' command. Availability of the command depends on your GUI environment.
+If this script doesn't work, please check your environment (see Tcl/Tk FAQ).
+EOM
+#'
+
+unless (wish = TkWinfo.interps.find{|ip| ip =~ /^wish/})
+ puts ''
+ puts 'Please start "wish" (Tcl/Tk shell) before running this sample script.'
+ exit 1
+end
+
+ip = RemoteTkIp.new(wish)
+ip.eval_proc{TkButton.new(:command=>proc{puts 'This procesure is on the controller-ip (Ruby/Tk)'}, :text=>'print on Ruby/Tk (controller-ip)').pack(:fill=>:x)}
+ip.eval_proc{TkButton.new(:command=>'puts {This procesure is on the remote-ip (wish)}', :text=>'print on wish (remote-ip)').pack(:fill=>:x)}
+
+# If your remote-ip is Ruby/Tk, you can control the remote Ruby by
+# 'ruby' or 'ruby_eval' or 'ruby_cmd' on the Tk interpreter.
+if ip.is_rubytk?
+ ip.eval_proc{TkButton.new(:command=>'ruby {p 111; p Array.new(3,"ruby")}', :text=>'ruby cmd on the remote-ip').pack(:fill=>:x)}
+end
+
+ip.eval_proc{TkButton.new(:command=>'exit', :text=>'QUIT').pack(:fill=>:x)}
+
+TkButton.new(:command=>proc{exit}, :text=>'QUIT',
+ :padx=>10, :pady=>7).pack(:padx=>10, :pady=>7)
+
+Tk.mainloop
diff --git a/ext/tk/sample/remote-ip_sample2.rb b/ext/tk/sample/remote-ip_sample2.rb
new file mode 100644
index 0000000000..e12b2a96c9
--- /dev/null
+++ b/ext/tk/sample/remote-ip_sample2.rb
@@ -0,0 +1,56 @@
+#!/usr/bin/env ruby
+
+require 'remote-tk'
+
+# start sub-process
+ip_name = 'remote_ip'
+ip_list = TkWinfo.interps
+fork{
+ exec "/usr/bin/env ruby -r tk -e \"Tk.appname('#{ip_name}');Tk.mainloop\""
+}
+sleep 1 until (app = (TkWinfo.interps - ip_list)[0]) && app =~ /^#{ip_name}/
+p TkWinfo.interps
+
+# create RemoteTkIp object
+ip = RemoteTkIp.new(app)
+
+# setup remote-ip window
+btns = []
+ip.eval_proc{
+ btns <<
+ TkButton.new(:command=>proc{
+ puts 'This procesure is on the controller-ip (Ruby-side)'
+ },
+ :text=>'print on controller-ip (Ruby-side)').pack(:fill=>:x)
+
+ btns <<
+ TkButton.new(:command=>
+ 'puts {This procesure is on the remote-ip (Tk-side)}',
+ :text=>'print on remote-ip (Tk-side)').pack(:fill=>:x)
+
+ btns <<
+ TkButton.new(:command=>
+ 'ruby {
+ puts "This procedure is on the remote-ip (Ruby-side)"
+ p Array.new(3,"ruby")
+ }',
+ :text=>'ruby cmd on the remote-ip').pack(:fill=>:x)
+
+ TkButton.new(:command=>'exit', :text=>'QUIT').pack(:fill=>:x)
+}
+
+# setup controller-ip window
+btns.each_with_index{|btn, idx|
+ # The scope of the eval-block of 'eval_proc' method is different from
+ # the enternal. If you want to pass local values to the eval-block,
+ # use arguments of eval_proc method. They are passed to block-arguments.
+ TkButton.new(:command=>proc{ip.eval_proc(btn){|b| b.flash}},
+ :text=>"flash button-#{idx}",
+ :padx=>10).pack(:padx=>10, :pady=>2)
+}
+
+TkButton.new(:command=>proc{exit}, :text=>'QUIT',
+ :padx=>10, :pady=>7).pack(:padx=>10, :pady=>7)
+
+# start eventloop
+Tk.mainloop
diff --git a/ext/tk/sample/safe-tk.rb b/ext/tk/sample/safe-tk.rb
index 0a25c804f0..e2289697e0 100644
--- a/ext/tk/sample/safe-tk.rb
+++ b/ext/tk/sample/safe-tk.rb
@@ -3,101 +3,113 @@
require "multi-tk"
-# create slave interpreters
-trusted_slave = MultiTkIp.new_slave
-safe_slave1 = MultiTkIp.new_safeTk
-safe_slave2 = MultiTkIp.new_safeTk('fill'=>:none, 'expand'=>false)
-#safe_slave2 = MultiTkIp.new_safeTk('fill'=>:none)
-#safe_slave2 = MultiTkIp.new_safeTk('expand'=>false)
-
-
-cmd = Proc.new{|txt|
- #####################
- ## from TkTimer2.rb
-
- if TkCore::INTERP.safe?
- # safeTk doesn't have permission to call 'wm' command
- else
- root = TkRoot.new(:title=>'timer sample')
- end
-
- label = TkLabel.new(:parent=>root, :relief=>:raised, :width=>10) \
- .pack(:side=>:bottom, :fill=>:both)
-
- tick = proc{|aobj|
- cnt = aobj.return_value + 5
- label.text format("%d.%02d", *(cnt.divmod(100)))
- cnt
- }
-
- timer = TkTimer.new(50, -1, tick).start(0, proc{ label.text('0.00'); 0 })
-
-=begin
- TkButton.new(:text=>'Start') {
- command proc{ timer.continue unless timer.running? }
- pack(:side=>:left, :fill=>:both, :expand=>true)
- }
- TkButton.new(:text=>'Restart') {
- command proc{ timer.restart(0, proc{ label.text('0.00'); 0 }) }
- pack('side'=>'right','fill'=>'both','expand'=>'yes')
- }
- TkButton.new(:text=>'Stop') {
- command proc{ timer.stop if timer.running? }
- pack('side'=>'right','fill'=>'both','expand'=>'yes')
- }
-=end
- b_start = TkButton.new(:text=>'Start', :state=>:disabled) {
- pack(:side=>:left, :fill=>:both, :expand=>true)
- }
- b_stop = TkButton.new(:text=>'Stop', :state=>:normal) {
- pack('side'=>'left', 'fill'=>'both', 'expand'=>'yes')
- }
-
- b_start.command {
- timer.continue
- b_stop.state(:normal)
- b_start.state(:disabled)
- }
-
- b_stop.command {
- timer.stop
- b_start.state(:normal)
- b_stop.state(:disabled)
- }
-
- TkButton.new(:text=>'Reset', :state=>:normal) {
- command { timer.reset }
- pack('side'=>'right', 'fill'=>'both', 'expand'=>'yes')
- }
-
- ev_quit = TkVirtualEvent.new('Control-c', 'Control-q')
- Tk.root.bind(ev_quit, proc{Tk.exit}).focus
+###############################
+
+TkLabel.new(:text=>'This is the Default Master Ipnterpreter').pack(:padx=>5, :pady=>3)
+TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack(:pady=>3)
+TkFrame.new(:borderwidth=>2, :height=>3,
+ :relief=>:sunken).pack(:fill=>:x, :expand=>true,
+ :padx=>10, :pady=>7)
+
+###############################
+
+puts "---- create a safe slave IP with Ruby's safe-level == 1 ----------"
+ip = MultiTkIp.new_safe_slave(1)
+
+puts "\n---- create procs ----------"
+puts 'x = proc{p [\'proc x\', "$SAFE==#{$SAFE}"]; exit}'
+x = proc{p ['proc x', "$SAFE==#{$SAFE}"]; exit}
+TkLabel.new(:text=>'x = proc{p [\'proc x\', "$SAFE==#{$SAFE}"]; exit}',
+ :anchor=>:w).pack(:fill=>:x)
+
+puts 'y = proc{|label| p [\'proc y\', "$SAFE==#{$SAFE}", label]; label.text($SAFE)}'
+y = proc{|label| p ['proc y', "$SAFE==#{$SAFE}", label]; label.text($SAFE)}
+TkLabel.new(:text=>'y = proc{|label| p [\'proc y\', "$SAFE==#{$SAFE}", label]; label.text($SAFE)}',
+ :anchor=>:w).pack(:fill=>:x)
+
+puts 'z = proc{p [\'proc z\', "$SAFE==#{$SAFE}"]; exit}'
+z = proc{p ['proc z', "$SAFE==#{$SAFE}"]; exit}
+TkLabel.new(:text=>'z = proc{p [\'proc z\', "$SAFE==#{$SAFE}"]; exit}',
+ :anchor=>:w).pack(:fill=>:x)
+
+puts "\n---- call 1st eval_proc ----------"
+print 'lbl = '
+p lbl = ip.eval_proc{
+ TkLabel.new(:text=>"1st eval_proc : $SAFE == #{$SAFE}").pack
+
+ f = TkFrame.new.pack
+ TkLabel.new(f, :text=>"$SAFE == ").pack(:side=>:left)
+ # TkLabel.new(f, :text=>" (<-- 'lbl' widget is here)").pack(:side=>:right)
+ l = TkLabel.new(f).pack(:side=>:right)
+
+ TkButton.new(:text=>':command=>proc{l.text($SAFE)}',
+ :command=>proc{l.text($SAFE)}).pack(:fill=>:x, :padx=>5)
+ TkButton.new(:text=>':command=>x', :command=>x).pack(:fill=>:x, :padx=>5)
+ TkButton.new(:text=>':command=>proc{exit}',
+ :command=>proc{exit}).pack(:fill=>:x, :padx=>5)
+ TkFrame.new(:borderwidth=>2, :height=>3,
+ :relief=>:sunken).pack(:fill=>:x, :expand=>true,
+ :padx=>10, :pady=>7)
+ l # return the label widget
}
-# call on the default master interpreter
-trusted_slave.eval_proc(cmd, 'trusted') # label -> .w00012
-safe_slave1.eval_proc(cmd, 'safe1') # label -> .w00016
-safe_slave2.eval_proc(cmd, 'safe2') # label -> .w00020
-cmd.call('master') # label -> .w00024
-
-#second_master = MultiTkIp.new(&cmd)
-
-TkTimer.new(2000, -1, proc{p ['safe1', safe_slave1.deleted?]}).start
-TkTimer.new(2000, -1, proc{p ['safe2', safe_slave2.deleted?]}).start
-TkTimer.new(2000, -1, proc{p ['trusted', trusted_slave.deleted?]}).start
-
-TkTimer.new(7000, 1,
- proc{
- safe_slave1.eval_proc{Tk.root.destroy}
- safe_slave1.delete
- print "*** The safe_slave1 is deleted by the timer.\n"
- }).start
-
-TkTimer.new(10000, 1,
- proc{
- trusted_slave.eval_proc{Tk.root.destroy}
- trusted_slave.delete
- print "*** The trusted_slave is deleted by the timer.\n"
- }).start
+puts "\n---- change the safe slave IP's safe-level ==> 3 ----------"
+ip.safe_level = 3
+
+puts "\n---- call 2nd eval_proc ----------"
+p ip.eval_proc(proc{
+ TkLabel.new(:text=>"2nd eval_proc : $SAFE == #{$SAFE}").pack
+ f = TkFrame.new.pack
+ TkLabel.new(f, :text=>"$SAFE == ").pack(:side=>:left)
+ l = TkLabel.new(f, :text=>$SAFE).pack(:side=>:right)
+ TkButton.new(:text=>':command=>proc{l.text($SAFE)}',
+ :command=>proc{l.text($SAFE)}).pack(:fill=>:x,
+ :padx=>5)
+ TkButton.new(:text=>':command=>proc{y.call(l)}',
+ :command=>proc{y.call(l)}).pack(:fill=>:x,
+ :padx=>5)
+ TkButton.new(:text=>':command=>proc{Thread.new(l, &y).value}',
+ :command=>proc{
+ Thread.new(l, &y).value
+ }).pack(:fill=>:x, :padx=>5)
+ TkButton.new(:text=>':command=>proc{z.call}',
+ :command=>proc{z.call}).pack(:fill=>:x, :padx=>5)
+ TkFrame.new(:borderwidth=>2, :height=>3,
+ :relief=>:sunken).pack(:fill=>:x, :expand=>true,
+ :padx=>10, :pady=>7)
+ })
+
+puts "\n---- call 1st and 2nd eval_str ----------"
+p bind = ip.eval_str('
+ TkLabel.new(:text=>"1st and 2nd eval_str : $SAFE == #{$SAFE}").pack
+ f = TkFrame.new.pack
+ TkLabel.new(f, :text=>"$SAFE == ").pack(:side=>:left)
+ l = TkLabel.new(f, :text=>$SAFE).pack(:side=>:right)
+ TkButton.new(:text=>":command=>proc{y.call(l)}",
+ :command=>proc{y.call(l)}).pack(:fill=>:x, :padx=>5)
+ binding
+', binding)
+
+p ip.eval_str("
+ TkButton.new(:text=>':command=>proc{ l.text = $SAFE }',
+ :command=>proc{ l.text = $SAFE }).pack(:fill=>:x, :padx=>5)
+ TkFrame.new(:borderwidth=>2, :height=>3,
+ :relief=>:sunken).pack(:fill=>:x, :expand=>true,
+ :padx=>10, :pady=>7)
+", bind)
+
+puts "\n---- change the safe slave IP's safe-level ==> 4 ----------"
+ip.safe_level = 4
+
+puts "\n---- call 3rd and 4th eval_proc ----------"
+p ip.eval_proc{
+ TkLabel.new(:text=>"3rd and 4th eval_proc : $SAFE == #{$SAFE}").pack
+}
+p ip.eval_proc{
+ TkButton.new(:text=>':command=>proc{ lbl.text = $SAFE }',
+ :command=>proc{ lbl.text = $SAFE }).pack(:fill=>:x, :padx=>5)
+}
+
+puts "\n---- start event-loop ( current $SAFE == #{$SAFE} ) ----------"
Tk.mainloop
diff --git a/ext/tk/sample/scrollframe.rb b/ext/tk/sample/scrollframe.rb
new file mode 100644
index 0000000000..b0ac6d3874
--- /dev/null
+++ b/ext/tk/sample/scrollframe.rb
@@ -0,0 +1,237 @@
+#
+# Tk::ScrollFrame class
+#
+# This widget class is a frame widget with scrollbars.
+# The ScrollFrame doesn't propagate the size of embedded widgets.
+# When it is configured, scrollregion of the container is changed.
+#
+# Scrollbars can be toggled by Tk::ScrollFrame#vscroll & hscroll.
+# If horizontal or virtical scrollbar is turned off, the horizontal
+# or virtical size of embedded widgets is propagated.
+#
+# Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+
+class Tk::ScrollFrame < TkFrame
+ include TkComposite
+
+ DEFAULT_WIDTH = 200
+ DEFAULT_HEIGHT = 200
+
+ def initialize_composite(keys={})
+ @frame.configure(:width=>DEFAULT_WIDTH, :height=>DEFAULT_HEIGHT)
+
+ # create scrollbars
+ @h_scroll = TkScrollbar.new(@frame, 'orient'=>'horizontal')
+ @v_scroll = TkScrollbar.new(@frame, 'orient'=>'vertical')
+
+ # create a canvas widget
+ @canvas = TkCanvas.new(@frame,
+ :borderwidth=>0, :selectborderwidth=>0,
+ :highlightthickness=>0)
+
+ # allignment
+ TkGrid.rowconfigure(@frame, 0, 'weight'=>1, 'minsize'=>0)
+ TkGrid.columnconfigure(@frame, 0, 'weight'=>1, 'minsize'=>0)
+ @canvas.grid('row'=>0, 'column'=>0, 'sticky'=>'news')
+ @frame.grid_propagate(false)
+
+ # assign scrollbars
+ @canvas.xscrollbar(@h_scroll)
+ @canvas.yscrollbar(@v_scroll)
+
+ # convert hash keys
+ keys = _symbolkey2str(keys)
+
+ # check options for the frame
+ framekeys = {}
+ if keys.key?('classname')
+ keys['class'] = keys.delete('classname')
+ end
+ if @classname = keys.delete('class')
+ framekeys['class'] = @classname
+ end
+ if @colormap = keys.delete('colormap')
+ framekeys['colormap'] = @colormap
+ end
+ if @container = keys.delete('container')
+ framekeys['container'] = @container
+ end
+ if @visual = keys.delete('visual')
+ framekeys['visual'] = @visual
+ end
+ if @classname.kind_of? TkBindTag
+ @db_class = @classname
+ @classname = @classname.id
+ elsif @classname
+ @db_class = TkDatabaseClass.new(@classname)
+ else
+ @db_class = self.class
+ @classname = @db_class::WidgetClassName
+ end
+
+ # create base frame
+ @base = TkFrame.new(@canvas, framekeys)
+
+ # embed base frame
+ @cwin = TkcWindow.new(@canvas, [0, 0], :window=>@base, :anchor=>'nw')
+ @canvas.scrollregion(@cwin.bbox)
+
+ # binding to reset scrollregion
+ @base.bind('Configure'){ _reset_scrollregion(nil, nil) }
+
+ # set default receiver of method calls
+ @path = @base.path
+
+ # scrollbars ON
+ vscroll(keys.delete('vscroll'){true})
+ hscroll(keys.delete('hscroll'){true})
+
+ # please check the differences of the following definitions
+ option_methods(
+ :scrollbarwidth
+ )
+
+ # set receiver widgets for configure methods (with alias)
+ delegate_alias('scrollbarrelief', 'relief', @h_scroll, @v_scroll)
+
+ # set receiver widgets for configure methods
+ delegate('DEFAULT', @base)
+ delegate('background', @frame, @base, @canvas, @h_scroll, @v_scroll)
+ delegate('width', @frame)
+ delegate('height', @frame)
+ delegate('activebackground', @h_scroll, @v_scroll)
+ delegate('troughcolor', @h_scroll, @v_scroll)
+ delegate('repeatdelay', @h_scroll, @v_scroll)
+ delegate('repeatinterval', @h_scroll, @v_scroll)
+ delegate('borderwidth', @frame)
+ delegate('relief', @frame)
+
+ # do configure
+ configure keys unless keys.empty?
+ end
+
+ # callback for Configure event
+ def _reset_scrollregion(h_mod=nil, v_mod=nil)
+ cx1, cy1, cx2, cy2 = @canvas.scrollregion
+ x1, y1, x2, y2 = @cwin.bbox
+ @canvas.scrollregion([x1, y1, x2, y2])
+
+ if h_mod.nil? && v_mod.nil?
+ if x2 != cx2 && TkGrid.info(@h_scroll).size == 0
+ @frame.grid_propagate(true)
+ @canvas.width = x2
+ Tk.update_idletasks
+ @frame.grid_propagate(false)
+ end
+ if y2 != cy2 && TkGrid.info(@v_scroll).size == 0
+ @frame.grid_propagate(true)
+ @canvas.height = y2
+ Tk.update_idletasks
+ @frame.grid_propagate(false)
+ end
+ else
+ @h_scroll.ungrid if h_mod == false
+ @v_scroll.ungrid if v_mod == false
+
+ h_flag = (TkGrid.info(@h_scroll).size == 0)
+ v_flag = (TkGrid.info(@v_scroll).size == 0)
+
+ @frame.grid_propagate(true)
+
+ @canvas.width = (h_flag)? x2: @canvas.winfo_width
+ @canvas.height = (v_flag)? y2: @canvas.winfo_height
+
+ @h_scroll.grid('row'=>1, 'column'=>0, 'sticky'=>'ew') if h_mod
+ @v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns') if v_mod
+
+ Tk.update_idletasks
+
+ @frame.grid_propagate(false)
+ end
+ end
+ private :_reset_scrollregion
+
+ # forbid to change binding of @base frame
+ def bind(*args)
+ @frame.bind(*args)
+ end
+ def bind_append(*args)
+ @frame.bind_append(*args)
+ end
+ def bind_remove(*args)
+ @frame.bind_remove(*args)
+ end
+ def bindinfo(*args)
+ @frame.bindinfo(*args)
+ end
+
+ # set width of scrollbar
+ def scrollbarwidth(width = nil)
+ if width
+ @h_scroll.width(width)
+ @v_scroll.width(width)
+ else
+ @h_scroll.width
+ end
+ end
+
+ # vertical scrollbar : ON/OFF
+ def vscroll(mode)
+ Tk.update_idletasks
+ st = TkGrid.info(@v_scroll)
+ if mode && st.size == 0 then
+ @v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns')
+ _reset_scrollregion(nil, true)
+ elsif !mode && st.size != 0 then
+ _reset_scrollregion(nil, false)
+ else
+ _reset_scrollregion(nil, nil)
+ end
+ self
+ end
+
+ # horizontal scrollbar : ON/OFF
+ def hscroll(mode)
+ Tk.update_idletasks
+ st = TkGrid.info(@h_scroll)
+ if mode && st.size == 0 then
+ _reset_scrollregion(true, nil)
+ elsif !mode && st.size != 0 then
+ _reset_scrollregion(false, nil)
+ else
+ _reset_scrollregion(nil, nil)
+ end
+ self
+ end
+end
+
+# test
+if __FILE__ == $0
+ f = Tk::ScrollFrame.new(:scrollbarwidth=>10, :width=>300, :height=>200)
+ f.pack(:expand=>true, :fill=>:both)
+
+ TkButton.new(f, :text=>'foo button', :command=>proc{puts 'foo'}).pack
+ TkButton.new(f, :text=>'baaar button', :command=>proc{puts 'baaar'}).pack
+ TkButton.new(f, :text=>'baz button', :command=>proc{puts 'baz'}).pack
+ TkButton.new(f, :text=>'hoge hoge button',
+ :command=>proc{puts 'hoge hoge'}).pack(:side=>:bottom)
+
+ # f.hscroll(false)
+
+ Tk.after(3000){
+ t = TkText.new(f).pack(:expand=>true, :fill=>:both)
+ t.insert(:end, 'Here is a text widget')
+ }
+
+ Tk.after(6000){ f.vscroll(false) }
+
+ Tk.after(9000){ f.vscroll(true) }
+
+ Tk.after(12000){ f.hscroll(false) }
+
+ Tk.after(15000){ f.hscroll(true) }
+
+ Tk.mainloop
+end
diff --git a/ext/tcltklib/sample/batsu.gif b/ext/tk/sample/tcltklib/batsu.gif
index 880cc73e09..880cc73e09 100644
--- a/ext/tcltklib/sample/batsu.gif
+++ b/ext/tk/sample/tcltklib/batsu.gif
Binary files differ
diff --git a/ext/tcltklib/demo/lines0.tcl b/ext/tk/sample/tcltklib/lines0.tcl
index 8ed3c5e1c1..8ed3c5e1c1 100644
--- a/ext/tcltklib/demo/lines0.tcl
+++ b/ext/tk/sample/tcltklib/lines0.tcl
diff --git a/ext/tcltklib/demo/lines2.rb b/ext/tk/sample/tcltklib/lines1.rb
index 9f21ae6377..9f21ae6377 100644
--- a/ext/tcltklib/demo/lines2.rb
+++ b/ext/tk/sample/tcltklib/lines1.rb
diff --git a/ext/tcltklib/demo/lines1.rb b/ext/tk/sample/tcltklib/lines2.rb
index e459589f50..e459589f50 100644
--- a/ext/tcltklib/demo/lines1.rb
+++ b/ext/tk/sample/tcltklib/lines2.rb
diff --git a/ext/tk/sample/tcltklib/lines3.rb b/ext/tk/sample/tcltklib/lines3.rb
new file mode 100644
index 0000000000..caa50f92e7
--- /dev/null
+++ b/ext/tk/sample/tcltklib/lines3.rb
@@ -0,0 +1,54 @@
+#! /usr/local/bin/ruby
+
+require "tk"
+
+def drawlines()
+ print Time.now, "\n"
+
+ for j in 0 .. 99
+ print "*"
+ $stdout.flush
+ if (j & 1) != 0
+ col = "blue"
+ else
+ col = "red"
+ end
+ for i in 0 .. 99
+# $a.create(TkcLine, i, 0, 0, 500 - i, "fill"=>col)
+ end
+ end
+
+ print Time.now, "\n"
+
+ for j in 0 .. 99
+ print "*"
+ $stdout.flush
+ if (j & 1) != 0
+ col = "blue"
+ else
+ col = "red"
+ end
+ for i in 0 .. 99
+ $a.create(TkcLine, i, 0, 0, 500 - i, "fill"=>col)
+ end
+ end
+
+ print Time.now, "\n"
+# Tk.root.destroy
+end
+
+$a = TkCanvas.new{
+ height(500)
+ width(500)
+}
+
+$b = TkButton.new{
+ text("draw")
+ command(proc{drawlines()})
+}
+
+TkPack.configure($a, $b, {"side"=>"left"})
+
+Tk.mainloop
+
+# eof
diff --git a/ext/tk/sample/tcltklib/lines4.rb b/ext/tk/sample/tcltklib/lines4.rb
new file mode 100644
index 0000000000..7a1175bce0
--- /dev/null
+++ b/ext/tk/sample/tcltklib/lines4.rb
@@ -0,0 +1,54 @@
+#! /usr/local/bin/ruby
+
+require "tk"
+
+def drawlines()
+ print Time.now, "\n"
+
+ for j in 0 .. 99
+ print "*"
+ $stdout.flush
+ if (j & 1) != 0
+ col = "blue"
+ else
+ col = "red"
+ end
+ for i in 0 .. 99
+# TkCore::INTERP.__invoke($a.path, "create", "line", i.to_s, '0', '0', (500 - i).to_s, "-fill", col)
+ end
+ end
+
+ print Time.now, "\n"
+
+ for j in 0 .. 99
+ print "*"
+ $stdout.flush
+ if (j & 1) != 0
+ col = "blue"
+ else
+ col = "red"
+ end
+ for i in 0 .. 99
+ TkCore::INTERP.__invoke($a.path, "create", "line", i.to_s, '0', '0', (500 - i).to_s, "-fill", col)
+ end
+ end
+
+ print Time.now, "\n"
+# Tk.root.destroy
+end
+
+$a = TkCanvas.new{
+ height(500)
+ width(500)
+}
+
+$b = TkButton.new{
+ text("draw")
+ command(proc{drawlines()})
+}
+
+TkPack.configure($a, $b, {"side"=>"left"})
+
+Tk.mainloop
+
+# eof
diff --git a/ext/tcltklib/sample/maru.gif b/ext/tk/sample/tcltklib/maru.gif
index 2c0202892e..2c0202892e 100644
--- a/ext/tcltklib/sample/maru.gif
+++ b/ext/tk/sample/tcltklib/maru.gif
Binary files differ
diff --git a/ext/tcltklib/demo/safeTk.rb b/ext/tk/sample/tcltklib/safeTk.rb
index 5d2c60e700..5d2c60e700 100644
--- a/ext/tcltklib/demo/safeTk.rb
+++ b/ext/tk/sample/tcltklib/safeTk.rb
diff --git a/ext/tcltklib/sample/sample0.rb b/ext/tk/sample/tcltklib/sample0.rb
index cd4c8069b4..cd4c8069b4 100644
--- a/ext/tcltklib/sample/sample0.rb
+++ b/ext/tk/sample/tcltklib/sample0.rb
diff --git a/ext/tk/sample/tcltklib/sample1.rb b/ext/tk/sample/tcltklib/sample1.rb
new file mode 100644
index 0000000000..13df440751
--- /dev/null
+++ b/ext/tk/sample/tcltklib/sample1.rb
@@ -0,0 +1,634 @@
+#! /usr/local/bin/ruby -d
+#! /usr/local/bin/ruby
+# -d ¥ª¥×¥·¥ç¥ó¤òÉÕ¤±¤ë¤È, ¥Ç¥Ð¥Ã¥°¾ðÊó¤òɽ¼¨¤¹¤ë.
+
+# tcltk ¥é¥¤¥Ö¥é¥ê¤Î¥µ¥ó¥×¥ë
+
+# ¤Þ¤º, ¥é¥¤¥Ö¥é¥ê¤ò require ¤¹¤ë.
+require "tcltk"
+
+# °Ê²¼¤Ï, Test1 ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Î initialize() ¤Ç,
+# tcl/tk ¤Ë´Ø¤¹¤ë½èÍý¤ò¹Ô¤¦Îã¤Ç¤¢¤ë.
+# ɬ¤º¤·¤â¤½¤Î¤è¤¦¤Ë¤¹¤ëɬÍפÏ̵¤¯,
+# (¤â¤·, ¤½¤¦¤·¤¿¤±¤ì¤Ð) class ¤Î³°¤Ç tcl/tk ¤Ë´Ø¤¹¤ë½èÍý¤ò¹Ô¤Ã¤Æ¤âÎɤ¤.
+
+class Test1
+ # ½é´ü²½(¥¤¥ó¥¿¥×¥ê¥¿¤òÀ¸À®¤·¤Æ¥¦¥£¥¸¥§¥Ã¥È¤òÀ¸À®¤¹¤ë).
+ def initialize()
+
+ #### »È¤¦Á°¤Î¤ª¤Þ¤¸¤Ê¤¤
+
+ # ¥¤¥ó¥¿¥×¥ê¥¿¤ÎÀ¸À®.
+ ip = TclTkInterpreter.new()
+ # ¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò c ¤ËÀßÄꤷ¤Æ¤ª¤¯.
+ c = ip.commands()
+ # »ÈÍѤ¹¤ë¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ÏÊÑ¿ô¤ËÆþ¤ì¤Æ¤ª¤¯.
+ append, bind, button, destroy, incr, info, label, place, set, wm =
+ c.values_at(
+ "append", "bind", "button", "destroy", "incr", "info", "label", "place",
+ "set", "wm")
+
+ #### tcl/tk ¤Î¥³¥Þ¥ó¥É¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkCommand)¤ÎÁàºî
+
+ # ¼Â¹Ô¤¹¤ë»þ¤Ï, e() ¥á¥½¥Ã¥É¤ò»È¤¦.
+ # (°Ê²¼¤Ï, tcl/tk ¤Ë¤ª¤±¤ë info command r* ¤ò¼Â¹Ô.)
+ print info.e("command", "r*"), "\n"
+ # °ú¿ô¤Ï, ¤Þ¤È¤á¤¿Ê¸»úÎó¤Ë¤·¤Æ¤âƱ¤¸.
+ print info.e("command r*"), "\n"
+ # ÊÑ¿ô¤òÍѤ¤¤Ê¤¯¤È¤â¼Â¹Ô¤Ç¤­¤ë¤¬, ¸«¤¿¤á¤¬°­¤¤.
+ print c["info"].e("command", "r*"), "\n"
+ # ¥¤¥ó¥¿¥×¥ê¥¿¤Î¥á¥½¥Ã¥É¤È¤·¤Æ¤â¼Â¹Ô¤Ç¤­¤ë¤¬, ¸úΨ¤¬°­¤¤.
+ print ip.info("command", "r*"), "\n"
+
+ ####
+
+ # °Ê²¼, À¸À®¤·¤¿¥ª¥Ö¥¸¥§¥¯¥È¤ÏÊÑ¿ô¤ËÂåÆþ¤·¤Æ¤ª¤«¤Ê¤¤¤È
+ # GC ¤ÎÂоݤˤʤäƤ·¤Þ¤¦.
+
+ #### tcl/tk ¤ÎÊÑ¿ô¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkVariable)¤ÎÁàºî
+
+ # À¸À®¤ÈƱ»þ¤ËÃͤòÀßÄꤹ¤ë.
+ v1 = TclTkVariable.new(ip, "20")
+ # ÆÉ¤ß½Ð¤·¤Ï get ¥á¥½¥Ã¥É¤ò»È¤¦.
+ print v1.get(), "\n"
+ # ÀßÄê¤Ï set ¥á¥½¥Ã¥É¤ò»È¤¦.
+ v1.set(40)
+ print v1.get(), "\n"
+ # set ¥³¥Þ¥ó¥É¤ò»È¤Ã¤ÆÆÉ¤ß½Ð¤·, ÀßÄê¤Ï²Äǽ¤À¤¬¸«¤¿¤á¤¬°­¤¤.
+ # e() ¥á¥½¥Ã¥ÉÅù¤Î°ú¿ô¤ËľÀÜ TclTkObject ¤ä¿ôÃͤò½ñ¤¤¤Æ¤âÎɤ¤.
+ set.e(v1, 30)
+ print set.e(v1), "\n"
+ # tcl/tk ¤Î¥³¥Þ¥ó¥É¤ÇÊÑ¿ô¤òÁàºî¤Ç¤­¤ë.
+ incr.e(v1)
+ print v1.get(), "\n"
+ append.e(v1, 10)
+ print v1.get(), "\n"
+
+ #### tcl/tk ¤Î¥¦¥£¥¸¥§¥Ã¥È¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkWidget)¤ÎÁàºî
+
+ # ¥ë¡¼¥È¥¦¥£¥¸¥§¥Ã¥È¤ò¼è¤ê½Ð¤¹.
+ root = ip.rootwidget()
+ # ¥¦¥£¥¸¥§¥Ã¥È¤ÎÁàºî.
+ root.e("configure -height 300 -width 300")
+ # ¥¿¥¤¥È¥ë¤òÉÕ¤±¤ë¤È¤­¤Ï wm ¤ò»È¤¦.
+ wm.e("title", root, $0)
+ # ¿Æ¥¦¥£¥¸¥§¥Ã¥È¤È¥³¥Þ¥ó¥É¤ò»ØÄꤷ¤Æ, ¥¦¥£¥¸¥§¥Ã¥È¤òºî¤ë.
+ l1 = TclTkWidget.new(ip, root, label, "-text {type `x' to print}")
+ # place ¤¹¤ë¤Èɽ¼¨¤µ¤ì¤ë.
+ place.e(l1, "-x 0 -rely 0.0 -relwidth 1 -relheight 0.1")
+ # ¥³¥Þ¥ó¥É̾¤Ïʸ»úÎó¤Ç»ØÄꤷ¤Æ¤âÎɤ¤¤¬, ¸«¤¿¤á¤¬°­¤¤.
+ # (¥³¥Þ¥ó¥É̾¤ÏÆÈΩ¤·¤¿°ú¿ô¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.)
+ l2 = TclTkWidget.new(ip, root, "label")
+ # ¥¦¥£¥¸¥§¥Ã¥È¤ÎÁàºî.
+ l2.e("configure -text {type `q' to exit}")
+ place.e(l2, "-x 0 -rely 0.1 -relwidth 1 -relheight 0.1")
+
+ #### tcl/tk ¤Î¥³¡¼¥ë¥Ð¥Ã¥¯¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkCallback)¤ÎÁàºî
+
+ # ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÀ¸À®¤¹¤ë.
+ c1 = TclTkCallback.new(ip, proc{sample(ip, root)})
+ # ¥³¡¼¥ë¥Ð¥Ã¥¯¤ò»ý¤Ä¥¦¥£¥¸¥§¥Ã¥È¤òÀ¸À®¤¹¤ë.
+ b1 = TclTkWidget.new(ip, root, button, "-text sample -command", c1)
+ place.e(b1, "-x 0 -rely 0.2 -relwidth 1 -relheight 0.1")
+ # ¥¤¥Ù¥ó¥È¥ë¡¼¥×¤òÈ´¤±¤ë¤Ë¤Ï destroy.e(root) ¤¹¤ë.
+ c2 = TclTkCallback.new(ip, proc{destroy.e(root)})
+ b2 = TclTkWidget.new(ip, root, button, "-text exit -command", c2)
+ place.e(b2, "-x 0 -rely 0.3 -relwidth 1 -relheight 0.1")
+
+ #### ¥¤¥Ù¥ó¥È¤Î¥Ð¥¤¥ó¥É
+ # script ¤ÎÄɲà (bind tag sequence +script) ¤Ïº£¤Î¤È¤³¤í¤Ç¤­¤Ê¤¤.
+ # (¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤ÎÀßÄ꤬¤¦¤Þ¤¯¤¤¤«¤Ê¤¤.)
+
+ # ´ðËÜŪ¤Ë¤Ï¥¦¥£¥¸¥§¥Ã¥È¤ËÂФ¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯¤ÈƱ¤¸.
+ c3 = TclTkCallback.new(ip, proc{print("q pressed\n"); destroy.e(root)})
+ bind.e(root, "q", c3)
+ # bind ¥³¥Þ¥ó¥É¤Ç % ÃÖ´¹¤Ë¤è¤ê¥Ñ¥é¥á¡¼¥¿¤ò¼õ¤±¼è¤ê¤¿¤¤¤È¤­¤Ï,
+ # proc{} ¤Î¸å¤í¤Ëʸ»úÎó¤Ç»ØÄꤹ¤ë¤È,
+ # ÃÖ´¹·ë²Ì¤ò¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤òÄ̤·¤Æ¼õ¤±¼è¤ë¤³¤È¤¬¤Ç¤­¤ë.
+ # ¤¿¤À¤· proc{} ¤Î¸å¤í¤Îʸ»úÎó¤Ï,
+ # bind ¥³¥Þ¥ó¥É¤ËÍ¿¤¨¤ë¥³¡¼¥ë¥Ð¥Ã¥¯°Ê³°¤Ç»ØÄꤷ¤Æ¤Ï¤¤¤±¤Ê¤¤.
+ c4 = TclTkCallback.new(ip, proc{|i| print("#{i} pressed\n")}, "%A")
+ bind.e(root, "x", c4)
+ # TclTkCallback ¤ò GC ¤ÎÂоݤˤ·¤¿¤±¤ì¤Ð,
+ # dcb() (¤Þ¤¿¤Ï deletecallbackkeys()) ¤¹¤ëɬÍפ¬¤¢¤ë.
+ cb = [c1, c2, c3, c4]
+ c5 = TclTkCallback.new(ip, proc{|w| TclTk.dcb(cb, root, w)}, "%W")
+ bind.e(root, "<Destroy>", c5)
+ cb.push(c5)
+
+ #### tcl/tk ¤Î¥¤¥á¡¼¥¸¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È(TclTkImage)¤ÎÁàºî
+
+ # ¥Ç¡¼¥¿¤ò»ØÄꤷ¤ÆÀ¸À®¤¹¤ë.
+ i1 = TclTkImage.new(ip, "photo", "-file maru.gif")
+ # ¥é¥Ù¥ë¤ËÄ¥¤êÉÕ¤±¤Æ¤ß¤ë.
+ l3 = TclTkWidget.new(ip, root, label, "-relief raised -image", i1)
+ place.e(l3, "-x 0 -rely 0.4 -relwidth 0.2 -relheight 0.2")
+ # ¶õ¤Î¥¤¥á¡¼¥¸¤òÀ¸À®¤·¤Æ¸å¤ÇÁàºî¤¹¤ë.
+ i2 = TclTkImage.new(ip, "photo")
+ # ¥¤¥á¡¼¥¸¤òÁàºî¤¹¤ë.
+ i2.e("copy", i1)
+ i2.e("configure -gamma 0.5")
+ l4 = TclTkWidget.new(ip, root, label, "-relief raised -image", i2)
+ place.e(l4, "-relx 0.2 -rely 0.4 -relwidth 0.2 -relheight 0.2")
+
+ ####
+ end
+
+ # ¥µ¥ó¥×¥ë¤Î¤¿¤á¤Î¥¦¥£¥¸¥§¥Ã¥È¤òÀ¸À®¤¹¤ë.
+ def sample(ip, parent)
+ bind, button, destroy, grid, toplevel, wm = ip.commands().values_at(
+ "bind", "button", "destroy", "grid", "toplevel", "wm")
+
+ ## toplevel
+
+ # ¿·¤·¤¤¥¦¥¤¥ó¥É¥¦¤ò³«¤¯¤Ë¤Ï, toplevel ¤ò»È¤¦.
+ t1 = TclTkWidget.new(ip, parent, toplevel)
+ # ¥¿¥¤¥È¥ë¤òÉÕ¤±¤Æ¤ª¤¯
+ wm.e("title", t1, "sample")
+
+ # ¥¦¥£¥¸¥§¥Ã¥È¤¬Ç˲õ¤µ¤ì¤¿¤È¤­, ¥³¡¼¥ë¥Ð¥Ã¥¯¤¬ GC ¤ÎÂоݤˤʤë¤è¤¦¤Ë¤¹¤ë.
+ cb = []
+ cb.push(c = TclTkCallback.new(ip, proc{|w| TclTk.dcb(cb, t1, w)}, "%W"))
+ bind.e(t1, "<Destroy>", c)
+
+ # ¥Ü¥¿¥ó¤ÎÀ¸À®.
+ wid = []
+ # toplevel ¥¦¥£¥¸¥§¥Ã¥È¤òÇ˲õ¤¹¤ë¤Ë¤Ï destroy ¤¹¤ë.
+ cb.push(c = TclTkCallback.new(ip, proc{destroy.e(t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text close -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_label(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text label -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_button(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text button -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_checkbutton(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text checkbutton -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_radiobutton(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text radiobutton -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_scale(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text scale -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_entry(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text entry -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_text(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text text -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_raise(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text raise/lower -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_modal(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text message/modal -command",
+ c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_menu(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text menu -command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_listbox(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text listbox/scrollbar",
+ "-command", c))
+ cb.push(c = TclTkCallback.new(ip, proc{test_canvas(ip, t1)}))
+ wid.push(TclTkWidget.new(ip, t1, button, "-text canvas -command", c))
+
+ # grid ¤Çɽ¼¨¤¹¤ë.
+ ro = co = 0
+ wid.each{|w|
+ grid.e(w, "-row", ro, "-column", co, "-sticky news")
+ ro += 1
+ if ro == 7
+ ro = 0
+ co += 1
+ end
+ }
+ end
+
+ # inittoplevel(ip, parent, title)
+ # °Ê²¼¤Î½èÍý¤ò¤Þ¤È¤á¤Æ¹Ô¤¦.
+ # 1. toplevel ¥¦¥£¥¸¥§¥Ã¥È¤òºîÀ®¤¹¤ë.
+ # 2. ¥³¡¼¥ë¥Ð¥Ã¥¯¤òÅÐÏ¿¤¹¤ëÇÛÎó¤òÍѰդ·, toplevel ¥¦¥£¥¸¥§¥Ã¥È¤Î
+ # <Destroy> ¥¤¥Ù¥ó¥È¤Ë¥³¡¼¥ë¥Ð¥Ã¥¯¤òºï½ü¤¹¤ë¼ê³¤­¤òÅÐÏ¿¤¹¤ë.
+ # 3. ¥¯¥í¡¼¥º¥Ü¥¿¥ó¤òºî¤ë.
+ # ºîÀ®¤·¤¿ toplevel ¥¦¥£¥¸¥§¥Ã¥È, ¥¯¥í¡¼¥º¥Ü¥¿¥ó, ¥³¡¼¥ë¥Ð¥Ã¥¯ÅÐÏ¿ÍÑÊÑ¿ô
+ # ¤òÊÖ¤¹.
+ # ip: ¥¤¥ó¥¿¥×¥ê¥¿
+ # parent: ¿Æ¥¦¥£¥¸¥§¥Ã¥È
+ # title: toplevel ¥¦¥£¥¸¥§¥Ã¥È¤Î¥¦¥¤¥ó¥É¥¦¤Î¥¿¥¤¥È¥ë
+ def inittoplevel(ip, parent, title)
+ bind, button, destroy, toplevel, wm = ip.commands().values_at(
+ "bind", "button", "destroy", "toplevel", "wm")
+
+ # ¿·¤·¤¤¥¦¥¤¥ó¥É¥¦¤ò³«¤¯¤Ë¤Ï, toplevel ¤ò»È¤¦.
+ t1 = TclTkWidget.new(ip, parent, toplevel)
+ # ¥¿¥¤¥È¥ë¤òÉÕ¤±¤Æ¤ª¤¯
+ wm.e("title", t1, title)
+
+ # ¥¦¥£¥¸¥§¥Ã¥È¤¬Ç˲õ¤µ¤ì¤¿¤È¤­, ¥³¡¼¥ë¥Ð¥Ã¥¯¤¬ GC ¤ÎÂоݤˤʤë¤è¤¦¤Ë¤¹¤ë.
+ cb = []
+ cb.push(c = TclTkCallback.new(ip, proc{|w| TclTk.dcb(cb, t1, w)}, "%W"))
+ bind.e(t1, "<Destroy>", c)
+ # close ¥Ü¥¿¥ó¤òºî¤Ã¤Æ¤ª¤¯.
+ # toplevel ¥¦¥£¥¸¥§¥Ã¥È¤òÇ˲õ¤¹¤ë¤Ë¤Ï destroy ¤¹¤ë.
+ cb.push(c = TclTkCallback.new(ip, proc{destroy.e(t1)}))
+ b1 = TclTkWidget.new(ip, t1, button, "-text close -command", c)
+
+ return t1, b1, cb
+ end
+
+ # label ¤Î¥µ¥ó¥×¥ë.
+ def test_label(ip, parent)
+ button, global, label, pack = ip.commands().values_at(
+ "button", "global", "label", "pack")
+ t1, b1, cb = inittoplevel(ip, parent, "label")
+
+ ## label
+
+ # ¤¤¤í¤¤¤í¤Ê·Á¤Î¥é¥Ù¥ë.
+ l1 = TclTkWidget.new(ip, t1, label, "-text {default(flat)}")
+ l2 = TclTkWidget.new(ip, t1, label, "-text raised -relief raised")
+ l3 = TclTkWidget.new(ip, t1, label, "-text sunken -relief sunken")
+ l4 = TclTkWidget.new(ip, t1, label, "-text groove -relief groove")
+ l5 = TclTkWidget.new(ip, t1, label, "-text ridge -relief ridge")
+ l6 = TclTkWidget.new(ip, t1, label, "-bitmap error")
+ l7 = TclTkWidget.new(ip, t1, label, "-bitmap questhead")
+
+ # pack ¤·¤Æ¤âɽ¼¨¤µ¤ì¤ë.
+ pack.e(b1, l1, l2, l3, l4, l5, l6, l7, "-pady 3")
+
+ ## -textvariable
+
+ # tcltk ¥é¥¤¥Ö¥é¥ê¤Î¼ÂÁõ¤Ç¤Ï, ¥³¡¼¥ë¥Ð¥Ã¥¯¤Ï tcl/tk ¤Î``¼ê³¤­''¤òÄ̤·¤Æ
+ # ¸Æ¤Ð¤ì¤ë. ¤·¤¿¤¬¤Ã¤Æ, ¥³¡¼¥ë¥Ð¥Ã¥¯¤ÎÃæ¤Ç(Âç°è)ÊÑ¿ô¤Ë¥¢¥¯¥»¥¹¤¹¤ë¤È¤­¤Ï,
+ # global ¤¹¤ëɬÍפ¬¤¢¤ë.
+ # global ¤¹¤ëÁ°¤ËÊÑ¿ô¤ËÃͤòÀßÄꤷ¤Æ¤·¤Þ¤¦¤È¥¨¥é¡¼¤Ë¤Ê¤ë¤Î¤Ç,
+ # tcl/tk ¤Ë¤ª¤±¤ëɽ¸½·Á¤À¤±À¸À®¤·¤Æ, ¼ÂºÝ¤ËÃͤòÀßÄꤷ¤Ê¤¤¤è¤¦¤Ë,
+ # 2 ÈÖÌܤΰú¿ô¤Ë¤Ï nil ¤òÍ¿¤¨¤ë.
+ v1 = TclTkVariable.new(ip, nil)
+ global.e(v1)
+ v1.set(100)
+ # -textvariable ¤ÇÊÑ¿ô¤òÀßÄꤹ¤ë.
+ l6 = TclTkWidget.new(ip, t1, label, "-textvariable", v1)
+ # ¥³¡¼¥ë¥Ð¥Ã¥¯¤ÎÃæ¤«¤éÊÑ¿ô¤òÁàºî¤¹¤ë.
+ cb.push(c = TclTkCallback.new(ip, proc{
+ global.e(v1); v1.set(v1.get().to_i + 10)}))
+ b2 = TclTkWidget.new(ip, t1, button, "-text +10 -command", c)
+ cb.push(c = TclTkCallback.new(ip, proc{
+ global.e(v1); v1.set(v1.get().to_i - 10)}))
+ b3 = TclTkWidget.new(ip, t1, button, "-text -10 -command", c)
+ pack.e(l6, b2, b3)
+ end
+
+ # button ¤Î¥µ¥ó¥×¥ë.
+ def test_button(ip, parent)
+ button, pack = ip.commands().values_at("button", "pack")
+ t1, b1, cb = inittoplevel(ip, parent, "button")
+
+ ## button
+
+ # ¥³¡¼¥ë¥Ð¥Ã¥¯Æâ¤Ç»²¾È¤¹¤ëÊÑ¿ô¤ÏÀè¤ËÀë¸À¤·¤Æ¤ª¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.
+ b3 = b4 = nil
+ cb.push(c = TclTkCallback.new(ip, proc{b3.e("flash"); b4.e("flash")}))
+ b2 = TclTkWidget.new(ip, t1, button, "-text flash -command", c)
+ cb.push(c = TclTkCallback.new(ip, proc{b2.e("configure -state normal")}))
+ b3 = TclTkWidget.new(ip, t1, button, "-text normal -command", c)
+ cb.push(c = TclTkCallback.new(ip, proc{b2.e("configure -state disabled")}))
+ b4 = TclTkWidget.new(ip, t1, button, "-text disable -command", c)
+ pack.e(b1, b2, b3, b4)
+ end
+
+ # checkbutton ¤Î¥µ¥ó¥×¥ë.
+ def test_checkbutton(ip, parent)
+ checkbutton, global, pack = ip.commands().values_at(
+ "checkbutton", "global", "pack")
+ t1, b1, cb = inittoplevel(ip, parent, "checkbutton")
+
+ ## checkbutton
+
+ v1 = TclTkVariable.new(ip, nil)
+ global.e(v1)
+ # -variable ¤ÇÊÑ¿ô¤òÀßÄꤹ¤ë.
+ ch1 = TclTkWidget.new(ip, t1, checkbutton, "-onvalue on -offvalue off",
+ "-textvariable", v1, "-variable", v1)
+ pack.e(b1, ch1)
+ end
+
+ # radiobutton ¤Î¥µ¥ó¥×¥ë.
+ def test_radiobutton(ip, parent)
+ global, label, pack, radiobutton = ip.commands().values_at(
+ "global", "label", "pack", "radiobutton")
+ t1, b1, cb = inittoplevel(ip, parent, "radiobutton")
+
+ ## radiobutton
+
+ v1 = TclTkVariable.new(ip, nil)
+ global.e(v1)
+ # ¥Ì¥ë¥¹¥È¥ê¥ó¥°¤Ï "{}" ¤Ç»ØÄꤹ¤ë.
+ v1.set("{}")
+ l1 = TclTkWidget.new(ip, t1, label, "-textvariable", v1)
+ # -variable ¤ÇƱ¤¸ÊÑ¿ô¤ò»ØÄꤹ¤ë¤ÈƱ¤¸¥°¥ë¡¼¥×¤Ë¤Ê¤ë.
+ ra1 = TclTkWidget.new(ip, t1, radiobutton,
+ "-text radio1 -value r1 -variable", v1)
+ ra2 = TclTkWidget.new(ip, t1, radiobutton,
+ "-text radio2 -value r2 -variable", v1)
+ cb.push(c = TclTkCallback.new(ip, proc{global.e(v1); v1.set("{}")}))
+ ra3 = TclTkWidget.new(ip, t1, radiobutton,
+ "-text clear -value r3 -variable", v1, "-command", c)
+ pack.e(b1, l1, ra1, ra2, ra3)
+ end
+
+ # scale ¤Î¥µ¥ó¥×¥ë.
+ def test_scale(ip, parent)
+ global, pack, scale = ip.commands().values_at(
+ "global", "pack", "scale")
+ t1, b1, cb = inittoplevel(ip, parent, "scale")
+
+ ## scale
+
+ v1 = TclTkVariable.new(ip, nil)
+ global.e(v1)
+ v1.set(219)
+ # ¥³¡¼¥ë¥Ð¥Ã¥¯Æâ¤Ç»²¾È¤¹¤ëÊÑ¿ô¤ÏÀè¤ËÀë¸À¤·¤Æ¤ª¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.
+ sca1 = nil
+ cb.push(c = TclTkCallback.new(ip, proc{global.e(v1); v = v1.get();
+ sca1.e("configure -background", format("#%02x%02x%02x", v, v, v))}))
+ sca1 = TclTkWidget.new(ip, t1, scale,
+ "-label scale -orient h -from 0 -to 255 -variable", v1, "-command", c)
+ pack.e(b1, sca1)
+ end
+
+ # entry ¤Î¥µ¥ó¥×¥ë.
+ def test_entry(ip, parent)
+ button, entry, global, pack = ip.commands().values_at(
+ "button", "entry", "global", "pack")
+ t1, b1, cb = inittoplevel(ip, parent, "entry")
+
+ ## entry
+
+ v1 = TclTkVariable.new(ip, nil)
+ global.e(v1)
+ # ¥Ì¥ë¥¹¥È¥ê¥ó¥°¤Ï "{}" ¤Ç»ØÄꤹ¤ë.
+ v1.set("{}")
+ en1 = TclTkWidget.new(ip, t1, entry, "-textvariable", v1)
+ cb.push(c = TclTkCallback.new(ip, proc{
+ global.e(v1); print(v1.get(), "\n"); v1.set("{}")}))
+ b2 = TclTkWidget.new(ip, t1, button, "-text print -command", c)
+ pack.e(b1, en1, b2)
+ end
+
+ # text ¤Î¥µ¥ó¥×¥ë.
+ def test_text(ip, parent)
+ button, pack, text = ip.commands().values_at(
+ "button", "pack", "text")
+ t1, b1, cb = inittoplevel(ip, parent, "text")
+
+ ## text
+
+ te1 = TclTkWidget.new(ip, t1, text)
+ cb.push(c = TclTkCallback.new(ip, proc{
+ # 1 ¹ÔÌܤΠ0 ʸ»úÌܤ«¤éºÇ¸å¤Þ¤Ç¤òɽ¼¨¤·, ºï½ü¤¹¤ë.
+ print(te1.e("get 1.0 end")); te1.e("delete 1.0 end")}))
+ b2 = TclTkWidget.new(ip, t1, button, "-text print -command", c)
+ pack.e(b1, te1, b2)
+ end
+
+ # raise/lower ¤Î¥µ¥ó¥×¥ë.
+ def test_raise(ip, parent)
+ button, frame, lower, pack, raise = ip.commands().values_at(
+ "button", "frame", "lower", "pack", "raise")
+ t1, b1, cb = inittoplevel(ip, parent, "raise/lower")
+
+ ## raise/lower
+
+ # button ¤ò±£¤¹¥Æ¥¹¥È¤Î¤¿¤á¤Ë, frame ¤ò»È¤¦.
+ f1 = TclTkWidget.new(ip, t1, frame)
+ # ¥³¡¼¥ë¥Ð¥Ã¥¯Æâ¤Ç»²¾È¤¹¤ëÊÑ¿ô¤ÏÀè¤ËÀë¸À¤·¤Æ¤ª¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.
+ b2 = nil
+ cb.push(c = TclTkCallback.new(ip, proc{raise.e(f1, b2)}))
+ b2 = TclTkWidget.new(ip, t1, button, "-text raise -command", c)
+ cb.push(c = TclTkCallback.new(ip, proc{lower.e(f1, b2)}))
+ b3 = TclTkWidget.new(ip, t1, button, "-text lower -command", c)
+ lower.e(f1, b3)
+
+ pack.e(b2, b3, "-in", f1)
+ pack.e(b1, f1)
+ end
+
+ # modal ¤Ê¥¦¥£¥¸¥§¥Ã¥È¤Î¥µ¥ó¥×¥ë.
+ def test_modal(ip, parent)
+ button, frame, message, pack, tk_chooseColor, tk_getOpenFile,
+ tk_messageBox = ip.commands().values_at(
+ "button", "frame", "message", "pack", "tk_chooseColor",
+ "tk_getOpenFile", "tk_messageBox")
+ # ºÇ½é¤Ë load ¤µ¤ì¤Æ¤¤¤Ê¤¤¥é¥¤¥Ö¥é¥ê¤Ï ip.commands() ¤Ë¸ºß¤·¤Ê¤¤¤Î¤Ç,
+ # TclTkLibCommand ¤òÀ¸À®¤¹¤ëɬÍפ¬¤¢¤ë.
+ tk_dialog = TclTkLibCommand.new(ip, "tk_dialog")
+ t1, b1, cb = inittoplevel(ip, parent, "message/modal")
+
+ ## message
+
+ mes = "¤³¤ì¤Ï message ¥¦¥£¥¸¥§¥Ã¥È¤Î¥Æ¥¹¥È¤Ç¤¹."
+ mes += "°Ê²¼¤Ï modal ¤Ê¥¦¥£¥¸¥§¥Ã¥È¤Î¥Æ¥¹¥È¤Ç¤¹."
+ me1 = TclTkWidget.new(ip, t1, message, "-text {#{mes}}")
+
+ ## modal
+
+ # tk_messageBox
+ cb.push(c = TclTkCallback.new(ip, proc{
+ print tk_messageBox.e("-type yesnocancel -message messageBox",
+ "-icon error -default cancel -title messageBox"), "\n"}))
+ b2 = TclTkWidget.new(ip, t1, button, "-text messageBox -command", c)
+ # tk_dialog
+ cb.push(c = TclTkCallback.new(ip, proc{
+ # ¥¦¥£¥¸¥§¥Ã¥È̾¤òÀ¸À®¤¹¤ë¤¿¤á¤Ë¥À¥ß¡¼¤Î frame ¤òÀ¸À®.
+ print tk_dialog.e(TclTkWidget.new(ip, t1, frame),
+ "dialog dialog error 2 yes no cancel"), "\n"}))
+ b3 = TclTkWidget.new(ip, t1, button, "-text dialog -command", c)
+ # tk_chooseColor
+ cb.push(c = TclTkCallback.new(ip, proc{
+ print tk_chooseColor.e("-title chooseColor"), "\n"}))
+ b4 = TclTkWidget.new(ip, t1, button, "-text chooseColor -command", c)
+ # tk_getOpenFile
+ cb.push(c = TclTkCallback.new(ip, proc{
+ print tk_getOpenFile.e("-defaultextension .rb",
+ "-filetypes {{{Ruby Script} {.rb}} {{All Files} {*}}}",
+ "-title getOpenFile"), "\n"}))
+ b5 = TclTkWidget.new(ip, t1, button, "-text getOpenFile -command", c)
+
+ pack.e(b1, me1, b2, b3, b4, b5)
+ end
+
+ # menu ¤Î¥µ¥ó¥×¥ë.
+ def test_menu(ip, parent)
+ global, menu, menubutton, pack = ip.commands().values_at(
+ "global", "menu", "menubutton", "pack")
+ tk_optionMenu = TclTkLibCommand.new(ip, "tk_optionMenu")
+ t1, b1, cb = inittoplevel(ip, parent, "menu")
+
+ ## menu
+
+ # menubutton ¤òÀ¸À®¤¹¤ë.
+ mb1 = TclTkWidget.new(ip, t1, menubutton, "-text menu")
+ # menu ¤òÀ¸À®¤¹¤ë.
+ me1 = TclTkWidget.new(ip, mb1, menu)
+ # mb1 ¤«¤é me1 ¤¬µ¯Æ°¤µ¤ì¤ë¤è¤¦¤Ë¤¹¤ë.
+ mb1.e("configure -menu", me1)
+
+ # cascade ¤Çµ¯Æ°¤µ¤ì¤ë menu ¤òÀ¸À®¤¹¤ë.
+ me11 = TclTkWidget.new(ip, me1, menu)
+ # radiobutton ¤Î¥µ¥ó¥×¥ë.
+ v1 = TclTkVariable.new(ip, nil); global.e(v1); v1.set("r1")
+ me11.e("add radiobutton -label radio1 -value r1 -variable", v1)
+ me11.e("add radiobutton -label radio2 -value r2 -variable", v1)
+ me11.e("add radiobutton -label radio3 -value r3 -variable", v1)
+ # cascade ¤Ë¤è¤ê mb11 ¤¬µ¯Æ°¤µ¤ì¤ë¤è¤¦¤Ë¤¹¤ë.
+ me1.e("add cascade -label cascade -menu", me11)
+
+ # checkbutton ¤Î¥µ¥ó¥×¥ë.
+ v2 = TclTkVariable.new(ip, nil); global.e(v2); v2.set("none")
+ me1.e("add checkbutton -label check -variable", v2)
+ # separator ¤Î¥µ¥ó¥×¥ë.
+ me1.e("add separator")
+ # command ¤Î¥µ¥ó¥×¥ë.
+ v3 = nil
+ cb.push(c = TclTkCallback.new(ip, proc{
+ global.e(v1, v2, v3); print "v1: ", v1.get(), ", v2: ", v2.get(),
+ ", v3: ", v3.get(), "\n"}))
+ me1.e("add command -label print -command", c)
+
+ ## tk_optionMenu
+
+ v3 = TclTkVariable.new(ip, nil); global.e(v3); v3.set("opt2")
+ om1 = TclTkWidget.new(ip, t1, tk_optionMenu, v3, "opt1 opt2 opt3 opt4")
+
+ pack.e(b1, mb1, om1, "-side left")
+ end
+
+ # listbox ¤Î¥µ¥ó¥×¥ë.
+ def test_listbox(ip, parent)
+ clipboard, frame, grid, listbox, lower, menu, menubutton, pack, scrollbar,
+ selection = ip.commands().values_at(
+ "clipboard", "frame", "grid", "listbox", "lower", "menu", "menubutton",
+ "pack", "scrollbar", "selection")
+ t1, b1, cb = inittoplevel(ip, parent, "listbox")
+
+ ## listbox/scrollbar
+
+ f1 = TclTkWidget.new(ip, t1, frame)
+ # ¥³¡¼¥ë¥Ð¥Ã¥¯Æâ¤Ç»²¾È¤¹¤ëÊÑ¿ô¤ÏÀè¤ËÀë¸À¤·¤Æ¤ª¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤.
+ li1 = sc1 = sc2 = nil
+ # ¼Â¹Ô»þ¤Ë, ¸å¤í¤Ë¥Ñ¥é¥á¡¼¥¿¤¬¤Ä¤¯¥³¡¼¥ë¥Ð¥Ã¥¯¤Ï,
+ # ¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤Ç¤½¤Î¥Ñ¥é¥á¡¼¥¿¤ò¼õ¤±¼è¤ë¤³¤È¤¬¤Ç¤­¤ë.
+ # (Ê£¿ô¤Î¥Ñ¥é¥á¡¼¥¿¤Ï¤Ò¤È¤Ä¤Îʸ»úÎó¤Ë¤Þ¤È¤á¤é¤ì¤ë.)
+ cb.push(c1 = TclTkCallback.new(ip, proc{|i| li1.e("xview", i)}))
+ cb.push(c2 = TclTkCallback.new(ip, proc{|i| li1.e("yview", i)}))
+ cb.push(c3 = TclTkCallback.new(ip, proc{|i| sc1.e("set", i)}))
+ cb.push(c4 = TclTkCallback.new(ip, proc{|i| sc2.e("set", i)}))
+ # listbox
+ li1 = TclTkWidget.new(ip, f1, listbox,
+ "-xscrollcommand", c3, "-yscrollcommand", c4,
+ "-selectmode extended -exportselection true")
+ for i in 1..20
+ li1.e("insert end {line #{i} line #{i} line #{i} line #{i} line #{i}}")
+ end
+ # scrollbar
+ sc1 = TclTkWidget.new(ip, f1, scrollbar, "-orient horizontal -command", c1)
+ sc2 = TclTkWidget.new(ip, f1, scrollbar, "-orient vertical -command", c2)
+
+ ## selection/clipboard
+
+ mb1 = TclTkWidget.new(ip, t1, menubutton, "-text edit")
+ me1 = TclTkWidget.new(ip, mb1, menu)
+ mb1.e("configure -menu", me1)
+ cb.push(c = TclTkCallback.new(ip, proc{
+ # clipboard ¤ò¥¯¥ê¥¢.
+ clipboard.e("clear")
+ # selection ¤«¤éʸ»úÎó¤òÆÉ¤ß¹þ¤ß clipboard ¤ËÄɲ乤ë.
+ clipboard.e("append {#{selection.e('get')}}")}))
+ me1.e("add command -label {selection -> clipboard} -command",c)
+ cb.push(c = TclTkCallback.new(ip, proc{
+ # li1 ¤ò¥¯¥ê¥¢.
+ li1.e("delete 0 end")
+ # clipboard ¤«¤éʸ»úÎó¤ò¼è¤ê½Ð¤·, 1 ¹Ô¤º¤Ä
+ selection.e("get -selection CLIPBOARD").split(/\n/).each{|line|
+ # li1 ¤ËÁÞÆþ¤¹¤ë.
+ li1.e("insert end {#{line}}")}}))
+ me1.e("add command -label {clipboard -> listbox} -command",c)
+
+ grid.e(li1, "-row 0 -column 0 -sticky news")
+ grid.e(sc1, "-row 1 -column 0 -sticky ew")
+ grid.e(sc2, "-row 0 -column 1 -sticky ns")
+ grid.e("rowconfigure", f1, "0 -weight 100")
+ grid.e("columnconfigure", f1, "0 -weight 100")
+ f2 = TclTkWidget.new(ip, t1, frame)
+ lower.e(f2, b1)
+ pack.e(b1, mb1, "-in", f2, "-side left")
+ pack.e(f2, f1)
+ end
+
+ # canvas ¤Î¥µ¥ó¥×¥ë.
+ def test_canvas(ip, parent)
+ canvas, lower, pack = ip.commands().values_at("canvas", "lower", "pack")
+ t1, b1, cb = inittoplevel(ip, parent, "canvas")
+
+ ## canvas
+
+ ca1 = TclTkWidget.new(ip, t1, canvas, "-width 400 -height 300")
+ lower.e(ca1, b1)
+ # rectangle ¤òºî¤ë.
+ idr = ca1.e("create rectangle 10 10 20 20")
+ # oval ¤òºî¤ë.
+ ca1.e("create oval 60 10 100 50")
+ # polygon ¤òºî¤ë.
+ ca1.e("create polygon 110 10 110 30 140 10")
+ # line ¤òºî¤ë.
+ ca1.e("create line 150 10 150 30 190 10")
+ # arc ¤òºî¤ë.
+ ca1.e("create arc 200 10 250 50 -start 0 -extent 90 -style pieslice")
+ # i1 ¤ÏËÜÅö¤Ï, ¤É¤³¤«¤ÇÇ˲õ¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤¬, ÌÌÅݤʤΤÇÊü¤Ã¤Æ¤¢¤ë.
+ i1 = TclTkImage.new(ip, "photo", "-file maru.gif")
+ # image ¤òºî¤ë.
+ ca1.e("create image 100 100 -image", i1)
+ # bitmap ¤òºî¤ë.
+ ca1.e("create bitmap 260 50 -bitmap questhead")
+ # text ¤òºî¤ë.
+ ca1.e("create text 320 50 -text {drag rectangle}")
+ # window ¤òºî¤ë(¥¯¥í¡¼¥º¥Ü¥¿¥ó).
+ ca1.e("create window 200 200 -window", b1)
+
+ # bind ¤Ë¤è¤ê rectangle ¤ò drag ¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë.
+ cb.push(c = TclTkCallback.new(ip, proc{|i|
+ # i ¤Ë x ¤È y ¤ò¼õ¤±¼è¤ë¤Î¤Ç, ¼è¤ê½Ð¤¹.
+ x, y = i.split(/ /); x = x.to_f; y = y.to_f
+ # ºÂɸ¤òÊѹ¹¤¹¤ë.
+ ca1.e("coords current #{x - 5} #{y - 5} #{x + 5} #{y + 5}")},
+ # x, y ºÂɸ¤ò¶õÇò¤Ç¶èÀڤ俤â¤Î¤ò¥¤¥Æ¥ì¡¼¥¿ÊÑ¿ô¤ØÅϤ¹¤è¤¦¤Ë»ØÄê.
+ "%x %y"))
+ # rectangle ¤Ë bind ¤¹¤ë.
+ ca1.e("bind", idr, "<B1-Motion>", c)
+
+ pack.e(ca1)
+ end
+end
+
+# test driver
+
+if ARGV.size == 0
+ print "#{$0} n ¤Ç, n ¸Ä¤Î¥¤¥ó¥¿¥×¥ê¥¿¤òµ¯Æ°¤·¤Þ¤¹.\n"
+ n = 1
+else
+ n = ARGV[0].to_i
+end
+
+print "start\n"
+ip = []
+
+# ¥¤¥ó¥¿¥×¥ê¥¿, ¥¦¥£¥¸¥§¥Ã¥ÈÅù¤ÎÀ¸À®.
+for i in 1 .. n
+ ip.push(Test1.new())
+end
+
+# ÍѰդ¬¤Ç¤­¤¿¤é¥¤¥Ù¥ó¥È¥ë¡¼¥×¤ËÆþ¤ë.
+TclTk.mainloop()
+print "exit from mainloop\n"
+
+# ¥¤¥ó¥¿¥×¥ê¥¿¤¬ GC ¤µ¤ì¤ë¤«¤Î¥Æ¥¹¥È.
+ip = []
+print "GC.start\n" if $DEBUG
+GC.start() if $DEBUG
+print "end\n"
+
+exit
+
+# end
diff --git a/ext/tk/sample/tcltklib/sample2.rb b/ext/tk/sample/tcltklib/sample2.rb
new file mode 100644
index 0000000000..110e81ebc4
--- /dev/null
+++ b/ext/tk/sample/tcltklib/sample2.rb
@@ -0,0 +1,451 @@
+#!/usr/local/bin/ruby
+#----------------------> pretty simple othello game <-----------------------
+# othello.rb
+#
+# version 0.3
+# maeda shugo (shuto@po.aianet.ne.jp)
+#---------------------------------------------------------------------------
+
+# Sep. 17, 1997 modified by Y. Shigehiro for tcltk library
+# maeda shugo (shugo@po.aianet.ne.jp) »á¤Ë¤è¤ë
+# (ruby/tk ¤Ç½ñ¤«¤ì¤Æ¤¤¤¿) ruby ¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à
+# http://www.aianet.or.jp/~shugo/ruby/othello.rb.gz
+# ¤ò tcltk ¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤è¤¦¤Ë, µ¡³£Åª¤ËÊѹ¹¤·¤Æ¤ß¤Þ¤·¤¿.
+#
+# ¤Ê¤ë¤Ù¤¯¥ª¥ê¥¸¥Ê¥ë¤ÈƱ¤¸¤Ë¤Ê¤ë¤è¤¦¤Ë¤·¤Æ¤¢¤ê¤Þ¤¹.
+
+require "observer"
+require "tcltk"
+$ip = TclTkInterpreter.new()
+$root = $ip.rootwidget()
+$button, $canvas, $checkbutton, $frame, $label, $pack, $update, $wm =
+ $ip.commands().values_at(
+ "button", "canvas", "checkbutton", "frame", "label", "pack", "update", "wm")
+
+class Othello
+
+ EMPTY = 0
+ BLACK = 1
+ WHITE = - BLACK
+
+ attr :in_com_turn
+ attr :game_over
+
+ class Board
+
+ include Observable
+
+ DIRECTIONS = [
+ [-1, -1], [-1, 0], [-1, 1],
+ [ 0, -1], [ 0, 1],
+ [ 1, -1], [ 1, 0], [ 1, 1]
+ ]
+
+ attr_accessor :com_disk
+
+ def initialize(othello)
+ @othello = othello
+ reset
+ end
+
+ def notify_observers(*arg)
+ if @observer_peers != nil
+ super(*arg)
+ end
+ end
+
+ def reset
+ @data = [
+ [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
+ [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
+ [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
+ [EMPTY, EMPTY, EMPTY, WHITE, BLACK, EMPTY, EMPTY, EMPTY],
+ [EMPTY, EMPTY, EMPTY, BLACK, WHITE, EMPTY, EMPTY, EMPTY],
+ [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
+ [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
+ [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY]
+ ]
+ changed
+ notify_observers
+ end
+
+ def man_disk
+ return - @com_disk
+ end
+
+ def other_disk(disk)
+ return - disk
+ end
+
+ def get_disk(row, col)
+ return @data[row][col]
+ end
+
+ def reverse_to(row, col, my_disk, dir_y, dir_x)
+ y = row
+ x = col
+ begin
+ y += dir_y
+ x += dir_x
+ if y < 0 || x < 0 || y > 7 || x > 7 ||
+ @data[y][x] == EMPTY
+ return
+ end
+ end until @data[y][x] == my_disk
+ begin
+ @data[y][x] = my_disk
+ changed
+ notify_observers(y, x)
+ y -= dir_y
+ x -= dir_x
+ end until y == row && x == col
+ end
+
+ def put_disk(row, col, disk)
+ @data[row][col] = disk
+ changed
+ notify_observers(row, col)
+ DIRECTIONS.each do |dir|
+ reverse_to(row, col, disk, *dir)
+ end
+ end
+
+ def count_disk(disk)
+ num = 0
+ @data.each do |rows|
+ rows.each do |d|
+ if d == disk
+ num += 1
+ end
+ end
+ end
+ return num
+ end
+
+ def count_point_to(row, col, my_disk, dir_y, dir_x)
+ return 0 if @data[row][col] != EMPTY
+ count = 0
+ loop do
+ row += dir_y
+ col += dir_x
+ break if row < 0 || col < 0 || row > 7 || col > 7
+ case @data[row][col]
+ when my_disk
+ return count
+ when other_disk(my_disk)
+ count += 1
+ when EMPTY
+ break
+ end
+ end
+ return 0
+ end
+
+ def count_point(row, col, my_disk)
+ count = 0
+ DIRECTIONS.each do |dir|
+ count += count_point_to(row, col, my_disk, *dir)
+ end
+ return count
+ end
+
+ def corner?(row, col)
+ return (row == 0 && col == 0) ||
+ (row == 0 && col == 7) ||
+ (row == 7 && col == 0) ||
+ (row == 7 && col == 7)
+ end
+
+ def search(my_disk)
+ max = 0
+ max_row = nil
+ max_col = nil
+ for row in 0 .. 7
+ for col in 0 .. 7
+ buf = count_point(row, col, my_disk)
+ if (corner?(row, col) && buf > 0) || max < buf
+ max = buf
+ max_row = row
+ max_col = col
+ end
+ end
+ end
+ return max_row, max_col
+ end
+ end #--------------------------> class Board ends here
+
+ class BoardView < TclTkWidget
+
+ BACK_GROUND_COLOR = "DarkGreen"
+ HILIT_BG_COLOR = "green"
+ BORDER_COLOR = "black"
+ BLACK_COLOR = "black"
+ WHITE_COLOR = "white"
+ STOP_COLOR = "red"
+
+ attr :left
+ attr :top
+ attr :right
+ attr :bottom
+
+ class Square
+
+ attr :oval, TRUE
+ attr :row
+ attr :col
+
+ def initialize(view, row, col)
+ @view = view
+ @id = @view.e("create rectangle",
+ *(view.tk_rect(view.left + col,
+ view.top + row,
+ view.left + col + 1,
+ view.top + row + 1) \
+ << "-fill #{BACK_GROUND_COLOR}") )
+ @row = row
+ @col = col
+ @view.e("itemconfigure", @id,
+ "-width 0.5m -outline #{BORDER_COLOR}")
+ @view.e("bind", @id, "<Any-Enter>", TclTkCallback.new($ip, proc{
+ if @oval == nil
+ view.e("itemconfigure", @id, "-fill #{HILIT_BG_COLOR}")
+ end
+ }))
+ @view.e("bind", @id, "<Any-Leave>", TclTkCallback.new($ip, proc{
+ view.e("itemconfigure", @id, "-fill #{BACK_GROUND_COLOR}")
+ }))
+ @view.e("bind", @id, "<ButtonRelease-1>", TclTkCallback.new($ip,
+ proc{
+ view.click_square(self)
+ }))
+ end
+
+ def blink(color)
+ @view.e("itemconfigure", @id, "-fill #{color}")
+ $update.e()
+ sleep(0.1)
+ @view.e("itemconfigure", @id, "-fill #{BACK_GROUND_COLOR}")
+ end
+ end #-----------------------> class Square ends here
+
+ def initialize(othello, board)
+ super($ip, $root, $canvas)
+ @othello = othello
+ @board = board
+ @board.add_observer(self)
+
+ @squares = Array.new(8)
+ for i in 0 .. 7
+ @squares[i] = Array.new(8)
+ end
+ @left = 1
+ @top = 0.5
+ @right = @left + 8
+ @bottom = @top + 8
+
+ i = self.e("create rectangle", *tk_rect(@left, @top, @right, @bottom))
+ self.e("itemconfigure", i,
+ "-width 1m -outline #{BORDER_COLOR} -fill #{BACK_GROUND_COLOR}")
+
+ for row in 0 .. 7
+ for col in 0 .. 7
+ @squares[row][col] = Square.new(self, row, col)
+ end
+ end
+
+ update
+ end
+
+ def tk_rect(left, top, right, bottom)
+ return left.to_s + "c", top.to_s + "c",
+ right.to_s + "c", bottom.to_s + "c"
+ end
+
+ def clear
+ each_square do |square|
+ if square.oval != nil
+ self.e("delete", square.oval)
+ square.oval = nil
+ end
+ end
+ end
+
+ def draw_disk(row, col, disk)
+ if disk == EMPTY
+ if @squares[row][col].oval != nil
+ self.e("delete", @squares[row][col].oval)
+ @squares[row][col].oval = nil
+ end
+ return
+ end
+
+ $update.e()
+ sleep(0.05)
+ oval = @squares[row][col].oval
+ if oval == nil
+ oval = self.e("create oval", *tk_rect(@left + col + 0.2,
+ @top + row + 0.2,
+ @left + col + 0.8,
+ @top + row + 0.8))
+ @squares[row][col].oval = oval
+ end
+ case disk
+ when BLACK
+ color = BLACK_COLOR
+ when WHITE
+ color = WHITE_COLOR
+ else
+ fail format("Unknown disk type: %d", disk)
+ end
+ self.e("itemconfigure", oval, "-outline #{color} -fill #{color}")
+ end
+
+ def update(row = nil, col = nil)
+ if row && col
+ draw_disk(row, col, @board.get_disk(row, col))
+ else
+ each_square do |square|
+ draw_disk(square.row, square.col,
+ @board.get_disk(square.row, square.col))
+ end
+ end
+ @othello.show_point
+ end
+
+ def each_square
+ @squares.each do |rows|
+ rows.each do |square|
+ yield(square)
+ end
+ end
+ end
+
+ def click_square(square)
+ if @othello.in_com_turn || @othello.game_over ||
+ @board.count_point(square.row,
+ square.col,
+ @board.man_disk) == 0
+ square.blink(STOP_COLOR)
+ return
+ end
+ @board.put_disk(square.row, square.col, @board.man_disk)
+ @othello.com_turn
+ end
+
+ private :draw_disk
+ public :update
+ end #----------------------> class BoardView ends here
+
+ def initialize
+ @msg_label = TclTkWidget.new($ip, $root, $label)
+ $pack.e(@msg_label)
+
+ @board = Board.new(self)
+ @board_view = BoardView.new(self, @board)
+ #### added by Y. Shigehiro
+ ## board_view ¤ÎÂ礭¤µ¤òÀßÄꤹ¤ë.
+ x1, y1, x2, y2 = @board_view.e("bbox all").split(/ /).collect{|i| i.to_f}
+ @board_view.e("configure -width", x2 - x1)
+ @board_view.e("configure -height", y2 - y1)
+ ## scrollregion ¤òÀßÄꤹ¤ë.
+ @board_view.e("configure -scrollregion {", @board_view.e("bbox all"),
+ "}")
+ #### ¤³¤³¤Þ¤Ç
+ $pack.e(@board_view, "-fill both -expand true")
+
+ panel = TclTkWidget.new($ip, $root, $frame)
+
+ @play_black = TclTkWidget.new($ip, panel, $checkbutton,
+ "-text {com is black} -command", TclTkCallback.new($ip, proc{
+ switch_side
+ }))
+ $pack.e(@play_black, "-side left")
+
+ quit = TclTkWidget.new($ip, panel, $button, "-text Quit -command",
+ TclTkCallback.new($ip, proc{
+ exit
+ }))
+ $pack.e(quit, "-side right -fill x")
+
+ reset = TclTkWidget.new($ip, panel, $button, "-text Reset -command",
+ TclTkCallback.new($ip, proc{
+ reset_game
+ }))
+ $pack.e(reset, "-side right -fill x")
+
+ $pack.e(panel, "-side bottom -fill x")
+
+# root = Tk.root
+ $wm.e("title", $root, "Othello")
+ $wm.e("iconname", $root, "Othello")
+
+ @board.com_disk = WHITE
+ @game_over = FALSE
+
+ TclTk.mainloop
+ end
+
+ def switch_side
+ if @in_com_turn
+ @play_black.e("toggle")
+ else
+ @board.com_disk = @board.man_disk
+ com_turn unless @game_over
+ end
+ end
+
+ def reset_game
+ if @board.com_disk == BLACK
+ @board.com_disk = WHITE
+ @play_black.e("toggle")
+ end
+ @board_view.clear
+ @board.reset
+ $wm.e("title", $root, "Othello")
+ @game_over = FALSE
+ end
+
+ def com_turn
+ @in_com_turn = TRUE
+ $update.e()
+ sleep(0.5)
+ begin
+ com_disk = @board.count_disk(@board.com_disk)
+ man_disk = @board.count_disk(@board.man_disk)
+ if @board.count_disk(EMPTY) == 0
+ if man_disk == com_disk
+ $wm.e("title", $root, "{Othello - Draw!}")
+ elsif man_disk > com_disk
+ $wm.e("title", $root, "{Othello - You Win!}")
+ else
+ $wm.e("title", $root, "{Othello - You Loose!}")
+ end
+ @game_over = TRUE
+ break
+ elsif com_disk == 0
+ $wm.e("title", $root, "{Othello - You Win!}")
+ @game_over = TRUE
+ break
+ elsif man_disk == 0
+ $wm.e("title", $root, "{Othello - You Loose!}")
+ @game_over = TRUE
+ break
+ end
+ row, col = @board.search(@board.com_disk)
+ break if row == nil || col == nil
+ @board.put_disk(row, col, @board.com_disk)
+ end while @board.search(@board.man_disk) == [nil, nil]
+ @in_com_turn = FALSE
+ end
+
+ def show_point
+ black = @board.count_disk(BLACK)
+ white = @board.count_disk(WHITE)
+ @msg_label.e("configure -text",
+ %Q/{#{format("BLACK: %.2d WHITE: %.2d", black, white)}}/)
+ end
+end #----------------------> class Othello ends here
+
+Othello.new
+
+#----------------------------------------------> othello.rb ends here
diff --git a/ext/tk/sample/tkalignbox.rb b/ext/tk/sample/tkalignbox.rb
new file mode 100644
index 0000000000..32915a5e69
--- /dev/null
+++ b/ext/tk/sample/tkalignbox.rb
@@ -0,0 +1,225 @@
+#
+# tkalignbox.rb : align widgets with same width/height
+#
+# by Hidetoshi NAGAI
+#
+# The box size depends on 'reqheight' and 'reqwidth' of contained widgets.
+# If you want to give the box size when those requested sizes are 0,
+# please set box.propagate = false (See the test routine at the tail of
+# this file).
+
+require 'tk'
+
+class TkAlignBox < TkFrame
+ def initialize(*args)
+ if self.class == TkAlignBox
+ fail RuntimeError, "TkAlignBox is an abstract class"
+ end
+ @padx = 0
+ @pady = 0
+ if args[-1].kind_of? Hash
+ keys = _symbolkey2str(args.pop)
+ @padx = keys.delete('padx') || 0
+ @pady = keys.delete('pady') || 0
+ args.push(keys)
+ end
+ super(*args)
+ @max_width = 0
+ @max_height = 0
+ @propagate = true
+ @widgets = []
+ end
+
+ def _set_framesize
+ fail RuntimeError, "TkAlignBox is an abstract class"
+ end
+ private :_set_framesize
+
+ def _place_config(widget, idx, cnt)
+ fail RuntimeError, "TkAlignBox is an abstract class"
+ end
+ private :_place_config
+
+ def align
+ widgets = []
+ @widgets.each{|w| widgets << w if w.winfo_exist?}
+ @widgets = widgets
+ cnt = @widgets.size.to_f
+ @widgets.each_with_index{|w, idx| _place_config(w, idx, cnt)}
+ @widgets = widgets
+ _set_framesize if @propagate
+ self
+ end
+
+ def add(*widgets)
+ widgets.each{|w|
+ unless w.kind_of? TkWindow
+ fail RuntimeError, "#{w.inspect} is not a widget instance."
+ end
+ @widgets.delete(w)
+ @widgets << w
+ sz = w.winfo_reqwidth
+ @max_width = sz if @max_width < sz
+ sz = w.winfo_reqheight
+ @max_height = sz if @max_height < sz
+ }
+ align
+ end
+
+ def <<(widget)
+ add(widget)
+ end
+
+ def insert(idx, widget)
+ unless widget.kind_of? TkWindow
+ fail RuntimeError, "#{widget.inspect} is not a widget instance."
+ end
+ @widgets.delete(widget)
+ @widgets[idx,0] = widget
+ sz = widget.winfo_reqwidth
+ @max_width = sz if @max_width < sz
+ sz = widget.winfo_reqheight
+ @max_height = sz if @max_height < sz
+ align
+ end
+
+ def delete(idx)
+ ret = @widgets.delete_at(idx)
+ @req_size = 0
+ @widget.each{|w|
+ sz = w.winfo_reqwidth
+ @max_width = sz if @max_width < sz
+ sz = w.winfo_reqheight
+ @max_height = sz if @max_height < sz
+ }
+ align
+ ret
+ end
+
+ def padx(size = nil)
+ if size
+ @padx = size
+ align
+ else
+ @padx
+ end
+ end
+
+ def pady(size = nil)
+ if size
+ @pady = size
+ align
+ else
+ @pady
+ end
+ end
+
+ attr_accessor :propagate
+end
+
+class TkHBox < TkAlignBox
+ def _set_framesize
+ bd = self.borderwidth
+ self.width((@max_width + 2*@padx) * @widgets.size + 2*bd)
+ self.height(@max_height + 2*@pady + 2*bd)
+ end
+ private :_set_framesize
+
+ def _place_config(widget, idx, cnt)
+ widget.place_in(self,
+ 'relx'=>idx/cnt, 'x'=>@padx,
+ 'rely'=>0, 'y'=>@pady,
+ 'relwidth'=>1.0/cnt, 'width'=>-2*@padx,
+ 'relheight'=>1.0, 'height'=>-2*@pady)
+ end
+ private :_place_config
+end
+TkHLBox = TkHBox
+
+class TkHRBox < TkHBox
+ def _place_config(widget, idx, cnt)
+ widget.place_in(self,
+ 'relx'=>(cnt - idx - 1)/cnt, 'x'=>@padx,
+ 'rely'=>0, 'y'=>@pady,
+ 'relwidth'=>1.0/cnt, 'width'=>-2*@padx,
+ 'relheight'=>1.0, 'height'=>-2*@pady)
+ end
+ private :_place_config
+end
+
+class TkVBox < TkAlignBox
+ def _set_framesize
+ bd = self.borderwidth
+ self.width(@max_width + 2*@padx + 2*bd)
+ self.height((@max_height + 2*@pady) * @widgets.size + 2*bd)
+ end
+ private :_set_framesize
+
+ def _place_config(widget, idx, cnt)
+ widget.place_in(self,
+ 'relx'=>0, 'x'=>@padx,
+ 'rely'=>idx/cnt, 'y'=>@pady,
+ 'relwidth'=>1.0, 'width'=>-2*@padx,
+ 'relheight'=>1.0/cnt, 'height'=>-2*@pady)
+ end
+ private :_place_config
+end
+TkVTBox = TkVBox
+
+class TkVBBox < TkVBox
+ def _place_config(widget, idx, cnt)
+ widget.place_in(self,
+ 'relx'=>0, 'x'=>@padx,
+ 'rely'=>(cnt - idx - 1)/cnt, 'y'=>@pady,
+ 'relwidth'=>1.0, 'width'=>-2*@padx,
+ 'relheight'=>1.0/cnt, 'height'=>-2*@pady)
+ end
+ private :_place_config
+end
+
+################################################
+# test
+################################################
+if __FILE__ == $0
+ f = TkHBox.new(:borderwidth=>3, :relief=>'ridge').pack
+ f.add(TkButton.new(f, :text=>'a'),
+ TkButton.new(f, :text=>'aa', :font=>'Helvetica 16'),
+ TkButton.new(f, :text=>'aaa'),
+ TkButton.new(f, :text=>'aaaa'))
+
+ f = TkHBox.new(:borderwidth=>3, :relief=>'ridge',
+ :padx=>7, :pady=>3, :background=>'yellow').pack
+ f.add(TkButton.new(f, :text=>'a'),
+ TkButton.new(f, :text=>'aa', :font=>'Helvetica 16'),
+ TkButton.new(f, :text=>'aaa'),
+ TkButton.new(f, :text=>'aaaa'))
+
+ f = TkVBox.new(:borderwidth=>5, :relief=>'groove').pack
+ f.add(TkButton.new(f, :text=>'a'),
+ TkButton.new(f, :text=>'aa', :font=>'Helvetica 30'),
+ TkButton.new(f, :text=>'aaa'),
+ TkButton.new(f, :text=>'aaaa'))
+
+ f = TkHRBox.new(:borderwidth=>3, :relief=>'raised').pack(:fill=>:x)
+ f.add(TkButton.new(f, :text=>'a'),
+ TkButton.new(f, :text=>'aa'),
+ TkButton.new(f, :text=>'aaa'))
+
+ f = TkVBBox.new(:borderwidth=>3, :relief=>'ridge').pack(:fill=>:x)
+ f.propagate = false
+ f.height 100
+ f.add(TkFrame.new(f){|ff|
+ TkButton.new(ff, :text=>'a').pack(:pady=>4, :padx=>6,
+ :fill=>:both, :expand=>true)
+ },
+ TkFrame.new(f){|ff|
+ TkButton.new(ff, :text=>'aa').pack(:pady=>4, :padx=>6,
+ :fill=>:both, :expand=>true)
+ },
+ TkFrame.new(f){|ff|
+ TkButton.new(ff, :text=>'aaaa').pack(:pady=>4, :padx=>6,
+ :fill=>:both, :expand=>true)
+ })
+
+ Tk.mainloop
+end
diff --git a/ext/tk/sample/tkballoonhelp.rb b/ext/tk/sample/tkballoonhelp.rb
index 312e376a07..c2c95f771d 100644
--- a/ext/tk/sample/tkballoonhelp.rb
+++ b/ext/tk/sample/tkballoonhelp.rb
@@ -24,13 +24,17 @@ class TkBalloonHelp<TkLabel
@bindtag.bind('Leave', proc{@timer.stop; erase})
tags = @parent.bindtags
idx = tags.index(@parent)
+ unless idx
+ ppath = TkComm.window(@parent.path)
+ idx = tags.index(ppath) || 0
+ end
tags[idx,0] = @bindtag
@parent.bindtags(tags)
end
private :_balloon_binding
def initialize(parent=nil, keys={})
- @parent = parent
+ @parent = parent || Tk.root
@frame = TkToplevel.new(@parent)
@frame.withdraw
@@ -38,7 +42,13 @@ class TkBalloonHelp<TkLabel
@frame.transient(TkWinfo.toplevel(@parent))
@epath = @frame.path
- keys = {} unless keys
+ if keys
+ keys = _symbolkey2str(keys)
+ else
+ keys = {}
+ end
+
+ @command = keys.delete('command')
@interval = keys.delete('interval'){1000}
_balloon_binding(@interval)
@@ -60,10 +70,31 @@ class TkBalloonHelp<TkLabel
end
end
+ def command(cmd = Proc.new)
+ @command = cmd
+ self
+ end
+
def show
x = TkWinfo.pointerx(@parent)
y = TkWinfo.pointery(@parent)
@frame.geometry("+#{x+1}+#{y+1}")
+
+ if @command
+ case @command.arity
+ when 0
+ @command.call
+ when 2
+ @command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent))
+ when 3
+ @command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent),
+ self)
+ else
+ @command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent),
+ self, @parent)
+ end
+ end
+
@frame.deiconify
@frame.raise
@@ -92,8 +123,72 @@ if __FILE__ == $0
TkButton.new('text'=>'This button has another balloon help') {|b|
pack('fill'=>'x')
TkBalloonHelp.new(b, 'text'=>'configured message',
- 'interval'=>500, 'font'=>'courier',
- 'background'=>'gray', 'foreground'=>'red')
+ 'interval'=>200, 'font'=>'courier',
+ 'background'=>'gray', 'foreground'=>'red')
}
+
+ sb = TkScrollbox.new.pack(:fill=>:x)
+ sb.insert(:end, *%w(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm))
+=begin
+ # CASE1 : command takes no arguemnt
+ bh = TkBalloonHelp.new(sb, :interval=>500,
+ :relief=>:ridge, :background=>'white',
+ :command=>proc{
+ y = TkWinfo.pointery(sb) - TkWinfo.rooty(sb)
+ bh.text "current index == #{sb.nearest(y)}"
+ })
+=end
+=begin
+ # CASE2 : command takes 2 arguemnts
+ bh = TkBalloonHelp.new(sb, :interval=>500,
+ :relief=>:ridge, :background=>'white',
+ :command=>proc{|x, y|
+ bh.text "current index == #{sb.nearest(y)}"
+ })
+=end
+=begin
+ # CASE3 : command takes 3 arguemnts
+ TkBalloonHelp.new(sb, :interval=>500,
+ :relief=>:ridge, :background=>'white',
+ :command=>proc{|x, y, bhelp|
+ bhelp.text "current index == #{sb.nearest(y)}"
+ })
+=end
+=begin
+ # CASE4a : command is a Proc object and takes 4 arguemnts
+ cmd = proc{|x, y, bhelp, parent|
+ bhelp.text "current index == #{parent.nearest(y)}"
+ }
+
+ TkBalloonHelp.new(sb, :interval=>500,
+ :relief=>:ridge, :background=>'white',
+ :command=>cmd)
+
+ sb2 = TkScrollbox.new.pack(:fill=>:x)
+ sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM))
+ TkBalloonHelp.new(sb2, :interval=>500,
+ :padx=>5, :relief=>:raised,
+ :background=>'gray25', :foreground=>'white',
+ :command=>cmd)
+=end
+#=begin
+ # CASE4b : command is a Method object and takes 4 arguemnts
+ def set_msg(x, y, bhelp, parent)
+ bhelp.text "current index == #{parent.nearest(y)}"
+ end
+ cmd = self.method(:set_msg)
+
+ TkBalloonHelp.new(sb, :interval=>500,
+ :relief=>:ridge, :background=>'white',
+ :command=>cmd)
+
+ sb2 = TkScrollbox.new.pack(:fill=>:x)
+ sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM))
+ TkBalloonHelp.new(sb2, :interval=>500,
+ :padx=>5, :relief=>:raised,
+ :background=>'gray25', :foreground=>'white',
+ :command=>cmd)
+#=end
+
Tk.mainloop
end
diff --git a/ext/tk/sample/tkbiff.rb b/ext/tk/sample/tkbiff.rb
index e89644bd9d..c6699629cc 100644
--- a/ext/tk/sample/tkbiff.rb
+++ b/ext/tk/sample/tkbiff.rb
@@ -40,13 +40,13 @@ class Mail
@body = []
while line = f.gets()
line.chop!
- next if /^From / =~ line # skip From-line
- break if /^$/ =~ line # end of header
+ next if /^From / =~ line # skip From-line
+ break if /^$/ =~ line # end of header
if /^(\S+):\s*(.*)/ =~ line
- @header[attr = $1.capitalize] = $2
+ @header[attr = $1.capitalize] = $2
elsif attr
- sub(/^\s*/, '')
- @header[attr] += "\n" + $_
+ sub(/^\s*/, '')
+ @header[attr] += "\n" + $_
end
end
@@ -112,7 +112,7 @@ if defined? Thread
loop do
sleep 600
if Time.now - $check_time > 200
- Tk.after 5000, proc{check}
+ Tk.after 5000, proc{check}
end
end
end
diff --git a/ext/tk/sample/tkbrowse.rb b/ext/tk/sample/tkbrowse.rb
index 7395688e97..4893f57f95 100644
--- a/ext/tk/sample/tkbrowse.rb
+++ b/ext/tk/sample/tkbrowse.rb
@@ -41,8 +41,8 @@ def browsedir (dir)
list.bind "Double-Button-1", proc{
for i in TkSelection.get.split
- print "clicked ", i, "\n"
- browse dir, i
+ print "clicked ", i, "\n"
+ browse dir, i
end
}
$dirlist[dir] = list
@@ -56,9 +56,9 @@ def browse (dir, file)
else
if File.file? file
if ENV['EDITOR']
- system format("%s %s&", ENV['EDITOR'], file)
+ system format("%s %s&", ENV['EDITOR'], file)
else
- system "xedit #{file}&"
+ system "xedit #{file}&"
end
else
STDERR.print "\"#{file}\" isn't a directory or regular file"
diff --git a/ext/tk/sample/tkcombobox.rb b/ext/tk/sample/tkcombobox.rb
index 08a2dd73a7..1840270951 100644
--- a/ext/tk/sample/tkcombobox.rb
+++ b/ext/tk/sample/tkcombobox.rb
@@ -24,6 +24,9 @@ static unsigned char down_arrow_bits[] = {
0x10, 0x00, 0x10, 0x00, 0x00, 0x00};
EOD
+ ############################
+ private
+ ############################
def initialize_composite(keys={})
keys = _symbolkey2str(keys)
@@ -42,9 +45,9 @@ EOD
@scr.command(proc{|*args| @lbox.yview(*args); _config_proc})
@up_arrow = TkLabel.new(@lbox, :image=>@@up_bmp,
- :relief=>:raised, :borderwidth=>1)
+ :relief=>:raised, :borderwidth=>1)
@down_arrow = TkLabel.new(@lbox, :image=>@@down_bmp,
- :relief=>:raised, :borderwidth=>1)
+ :relief=>:raised, :borderwidth=>1)
_init_binding
@@ -59,14 +62,14 @@ 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?
end
- ############################
- private
- ############################
def _show_up_arrow
unless @up_arrow.winfo_mapped?
@up_arrow.pack(:side=>:top, :fill=>:x)
@@ -195,10 +198,10 @@ EOD
@lbox.bind('Configure', proc{_config_proc})
@lbox.bind('Enter', proc{|y| _set_sel(@lbox.nearest(y))}, '%y')
@lbox.bind('Motion', proc{|y|
- @up_timer.stop if @up_timer.running?
- @down_timer.stop if @down_timer.running?
- _check_sel(@lbox.nearest(y))
- }, '%y')
+ @up_timer.stop if @up_timer.running?
+ @down_timer.stop if @down_timer.running?
+ _check_sel(@lbox.nearest(y))
+ }, '%y')
@lbox.bind('Up', proc{_key_UP_proc})
@lbox.bind('Down', proc{_key_DOWN_proc})
@@ -264,7 +267,7 @@ EOD
begin
@var.tkwait
if (idx = @var.to_i) >= 0
- @ent.value = @lst.get(idx)
+ @ent.value = @lst.get(idx)
end
@top.withdraw
@btn.relief(:raised)
@@ -272,8 +275,8 @@ EOD
rescue
ensure
begin
- @top.grab(:release)
- @ent.focus
+ @top.grab(:release)
+ @ent.focus
rescue
end
end
@@ -296,8 +299,8 @@ EOD
keys = _symbolkey2str(keys)
@btn = TkLabel.new(@frame, :relief=>:raised, :borderwidth=>3,
- :image=>@@down_btn_bmp).pack(:side=>:right,
- :ipadx=>2, :fill=>:y)
+ :image=>@@down_btn_bmp).pack(:side=>:right,
+ :ipadx=>2, :fill=>:y)
@ent = TkEntry.new(@frame).pack(:side=>:left)
@path = @ent.path
@@ -310,9 +313,9 @@ EOD
startwait = keys.delete('startwait'){300}
interval = keys.delete('interval'){150}
@lst = TkAutoScrollbox.new(@top,
- :startwait=>startwait,
- :interval=>interval).pack(:fill=>:both,
- :expand=>true)
+ :startwait=>startwait,
+ :interval=>interval).pack(:fill=>:both,
+ :expand=>true)
@ent_list = []
@var = TkVariable.new
@@ -324,12 +327,16 @@ EOD
delegate('relief', @frame)
delegate('borderwidth', @frame)
+ delegate('arrowrelief', @lst)
+ delegate('arrowborderwidth', @lst)
+
if mode = keys.delete('scrollbar')
scrollbar(mode)
end
configure keys unless keys.empty?
end
+ private :initialize_composite
def scrollbar(mode)
@lst.scrollbar(mode)
@@ -390,7 +397,8 @@ end
if __FILE__ == $0
v = TkVariable.new
e = TkCombobox.new(:height=>7, :scrollbar=>true, :textvariable=>v,
- :startwait=>400, :interval=>200).pack
+ :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)
e.value = 'cc'
@@ -401,17 +409,17 @@ if __FILE__ == $0
}.pack
TkFrame.new(:relief=>:raised, :borderwidth=>2,
- :height=>3).pack(:fill=>:x, :expand=>true, :padx=>5, :pady=>3)
+ :height=>3).pack(:fill=>:x, :expand=>true, :padx=>5, :pady=>3)
l = TkAutoScrollbox.new(nil, :relief=>:groove, :borderwidth=>4,
- :width=>20).pack(:fill=>:both, :expand=>true)
+ :width=>20).pack(:fill=>:both, :expand=>true)
(0..20).each{|i| l.insert('end', "line #{i}")}
TkFrame.new(:relief=>:ridge, :borderwidth=>3){
TkButton.new(self, :text=>'ON',
- :command=>proc{l.scrollbar(true)}).pack(:side=>:left)
+ :command=>proc{l.scrollbar(true)}).pack(:side=>:left)
TkButton.new(self, :text=>'OFF',
- :command=>proc{l.scrollbar(false)}).pack(:side=>:right)
+ :command=>proc{l.scrollbar(false)}).pack(:side=>:right)
pack(:fill=>:x)
}
Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/ICONS/Orig_LICENSE.txt b/ext/tk/sample/tkextlib/ICONS/Orig_LICENSE.txt
new file mode 100644
index 0000000000..71e359559a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/ICONS/Orig_LICENSE.txt
@@ -0,0 +1,61 @@
+
+ #########################################################################
+ ### The following text is the original file of the Tcl/Tk extension. ###
+ ### Icon data files ( those are 'tkIcons', 'tkIcons-sample.kde', and ###
+ ### 'tkIcons.kde' ) are quoted from the source archive of ICONS ###
+ ### extension. As the following document describes, those icon images ###
+ ### are not applied the license. ###
+ #########################################################################
+
+
+IMPORTANT LICENSE INFORMATION
+=============================
+
+The following terms (based on the standard TCL/TK license) apply to all files
+contained in this package, <b>except</b> the icon images.
+
+The icon images can be freely distributed. If you require clarification of
+copyright/license details for the images, please contact the appropriate
+creator/maintainer.
+
+ICONS: LICENSE TERMS
+====================
+
+This software (ICONS) is Copyright 2002 by Adrian Davis (adrian@satisoft.com).
+The following terms apply to all files associated with the software except
+where noted above.
+
+The author hereby grants permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that
+this notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file
+where they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+OR MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense,
+the software shall be classified as "Commercial Computer Software"
+and the Government shall have only "Restricted Rights" as defined in
+Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing,
+the authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
diff --git a/ext/tk/sample/tkextlib/ICONS/tkIcons b/ext/tk/sample/tkextlib/ICONS/tkIcons
new file mode 100644
index 0000000000..0d5b2c8695
--- /dev/null
+++ b/ext/tk/sample/tkextlib/ICONS/tkIcons
@@ -0,0 +1,195 @@
+actattach16:act act16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBPz+/AQCBAAAACH5BAEAAAAALAAAAAAQABAAAAI2hAOCxg2h0nJHyEshi9HpxU1GOCLdZoKpQ15nibUoprKp9lh2oucUxsBRXsJh4Hjs/QTMpr8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actbookmark16:act act16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCwqLLSytLy+vERGRFRWVDQ2NKSmpAQCBKyurMTGxISChJyanHR2dIyKjGxubHRydGRmZIyOjFxeXHx6fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVbICACwWieY1CibCCsrBkMb0zchSEcNYskCtqBBzshFkOGQFk0IRqOxqPBODRHCMhCQKteRc9FI/KQWGOIyFYgkDC+gPR4snCcfRGKOIKIgSMQE31+f4OEYCZ+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actbookmarknew16:act act16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCwqLLSytLy6vERGRFRWVDQyNKSipAQCBMTGxKyurISChJSSlJyanHR2dIyKjPz+xISGhPz+BGxubMTCBHx+fPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVfICACwWieY1CibCCsrBkMb0zchTEcNYsIiYHiwIOdEAvigdFQGE0Ix4NBbSAgsWjk+jBIAlcUYrJASChnSXZSoUDelKfoKpFALJA61ueGI2IAZmhogGFmCGGAgXsifiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actcheck16:act act16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBMT+xATCBASCBARCBAQCBEQCBAAAACH5BAEAAAAALAAAAAAQABAAAAM2CLrc/itAF8RkdVyVye4FpzUgJwijORCGUhDDOZbLG6Nd2xjwibIQ2y80sRGIl4IBuWk6Af4EACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actcross16:act act16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/PwCBMQCBEQCBIQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMuCLrc/hCGFyYLQjQsquLDQ2ScEEJjZkYfyQKlJa2j7AQnMM7NfucLze1FLD78CQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actexit16:act act16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBDQyNHR2dCH5BAEAAAAALAAAAAAQABAAAAI4hI+pFrHb3nEg1iWiDiINCwYDko0V9XUTda6I1TIsUMpGinyzbB6ZeGuoEr+GUDL4CXqSphPhLwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+acthelp16:act act16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQ6XAQCBCyCvARSjAQ+ZGSm1ARCbEyWzESOxIy63ARalAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAQ/EEgQqhUz00GEJx2WFUY3BZw5HYh4cu6mSkEy06B72LHkiYFST0NRLIaa4I0oQyZhTKInSq2eAlaaMAuYEv0RACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actitemadd16:act act16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBARCZPz+/Mzq9BTC3ITC1HSyzGSivAw+XBSStIS6zHy2zAQCDFyatAQOHFSStEyOtAQSJBSq1DR2nCxunCRmlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVbICCOQTmeaCAMRIC+AVu47xkTBl2Ld16XQNYBQTQBVIOkMHFQJBeMI4tAbSSu2IRDSnhAvFfI97sFRM6RwOMacbjLKckVvgvIJ5EdSU7J648VgXQ7Dmd/hyJ+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actitemdelete16:act act16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBARCZPz+/Mzq9BTC3AQCDAQOHFSStAQSJAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAQwEMhJq704681n+GAISoEwnGg6EAUQrEQsz4ThEkeu77kNIAagMEj0dY7IpHI58UcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actlock16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaVAQCBKSipDQyNMTCxISChFxaLFxSJEQ+FExGHCQiDBwaDGxiLHxyNHRuPIR+TIyGZJSSfFxaRFxWJGRiLJyaXNzWpNTOnMzGnLy2hJSKTGReLKyqjPTu1NzarMS+jLSyfKyibJySXIyGVCQeDLSytPT29Ozu7OTi5NTS1KyurJSSjGxqVFxaXLS2tKSebOzuzLSufJSOXExGLGRiTExONAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaTQIBwGCgGhkhkQDBoEpLKQoBACAyOUID1qTVwoQGvMPxNFgVjAxp6QCQUicSCwVgkG44HJCKRRCYUCAxIFRYXhxgZGhYbHINEHR4fGCAhIiMkFSVKJicoKSoFKwMsLZtDLison6GjLA92qCueoAUvpC2xQhWqrLYDErmEMDEXlDIwMxAHukI0NS01EzY2NAmPAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actredo16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBxOHBxSHBRGHKzCtNzu3MTSzBQ2FLzSxIzCjCSKFCyeHDzCLAxGHAwuFDSCNBxKLES+NHSmfBQ6FBxWJAQaDAQWFAw+HDSyLJzOnISyjMTexAQOBAwmDAw+FMzizAQODDymNKzWrAQKDAwaDEy6TFTGTFSyXDyKTAQCBAwiFBQyHAwSFAwmHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ2QIBwSCwaj0hAICBICgcDQsEgaB4PiIRiW0AEiE3sdsFgcK2CBsCheEAcjgYjoigwJRM2pUK0XDAKGRobDRwKHUcegAsfExUdIEcVCgshImojfEUkCiUmJygHACkqHEQpqKkpogAgK5FOQywtprFDKRwptrZ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actreload16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCRaJBxWJBxOHBRGBCxeLLTatCSKFCymJBQ6BAwmBNzu3AQCBAQOBCRSJKzWrGy+ZDy+NBxSHFSmTBxWHLTWtCyaHCSSFCx6PETKNBQ+FBwaHCRKJMTixLy6vExOTKyqrFxaXDQyNDw+PBQSFHx6fCwuLJyenDQ2NISChLSytJSSlFxeXAwODCQmJBweHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaBQIBQGBAMBALCcCksGA4IQkJBUDIDC6gVwGhshY5HlMn9DiCRL1MyYE8iiapaSKlALBdMRiPckDkdeXt9HgxkGhWDXB4fH4ZMGnxcICEiI45kQiQkDCUmJZskmUIiJyiPQgyoQwwpH35LqqgMKiEjq5obqh8rLCMtowAkLqovuH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actrun16:act act16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/ISChKSipMTCxLS2tLy+vMzOzMTGxNTS1AAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARlEMgJQqDYyiDGrR8oWJxnCcQXDMU4GEYqFN4UEHB+FEhtv7EBIYEohkjBkwJBqggEMB+ncHhaBsDUZmbAXq67EecQ02x2CMWzkAs504gCO3qcDZjkl11FMJVIN0cqHSpuGYYSfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actstop16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/Gw6NGQuLHQ6NGQmJFweHFQaFPTm5PTa3PTW1Oy+vOS6tNSinKReVDQWFPz+/Nx6fNyCfNyGhNR+dMxybMRiXLxGRIwWFNx2dNx+fNx2bMxuZLQWFBwWFPTu7Pzy9NRqZNRuZMRSVLwmJGwWFNR2dMQiHPTKxMxmXMQyLMxmZNx6dMxiXMRSRMRaVKxybMxaVEQWFMQuJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaaQIAQEBAMCAWDYcgkHhAJxYLRcDQBggckIplQKpaLdRh4YDIaSWa94Vw6woAHgv6AMKGPaMQhwQMJJRkfhHmEJhdvRCcgGSCEkCgpbnAECiorGYYfLCItlAAFCygQj5AfbYlwBQwVE5AukG6KBi8tMC0fLi0pHxyzcAAxFxwmMny/wEwOxMm/qlcdJCSJ1H5XQh3a28HY3kx+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actundo16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBxSHBxOHMTSzNzu3KzCtBRGHCSKFIzCjLzSxBQ2FAxGHDzCLCyeHBQ+FHSmfAwuFBxKLDSCNMzizISyjJzOnDSyLAw+FAQSDAQeDBxWJAwmDAQOBKzWrDymNAQaDAQODAwaDDyKTFSyXFTGTEy6TAQCBAQKDAwiFBQyHAwSFAwmHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ1QIBwSCwaj0hiQCBICpcDQsFgGAaIguhhi0gohIsrQEDYMhiNrRfgeAQC5fMCAolIDhD2hFI5WC4YRBkaBxsOE2l/RxsHHA4dHmkfRyAbIQ4iIyQlB5NFGCAACiakpSZEJyinTgAcKSesACorgU4mJ6uxR35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actunlock16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaVAQCBKSipDQyNMTCxISChFxaLFxSJExGHEQ+FCQiDBwaDBweDGxiLHxyNHRuPIR+RIyGZJSSfFxaRGxmLJyaXNzWpNTOnMzGnMS+jJSKTGReLKyqjPTu1NzarLSufKyibJySXIyGVGxiNFxaXLSytPT29Ozu7OTi5NTS1KyurGxqVCQeDJSSjLS2tNTW1KSmpGRiLKSebOzuzJSOXExONExGLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaVQIBwOAwYA8SkMCAYOAnKYiFAIAQGyOgVCggYuEovVxztMpdnwAGRSCgUCwOjIeQ6HpCIZDKRUNYMRBUWF4UYGRoWGxyBRR0eHxgaICEiIyR0QyUmJygpKgUrAxMsLUQlKyieoKIuEAunK52fBS8DLiywQySpnjC1Mbi6QjIzNBeSIBY1EQfDQgosLAEUNjY3Co1DfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appbook16:app app16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBDyKhDSChGSinFSWlEySjCx+fHSqrGSipESOjCR6dKTGxISytIy6vFSalBxydAQeHHyurAxubARmZCR+fBx2dDyKjPz+/MzKzLTS1IyOjAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVkICCOZGmKQXCWqTCoa0oUxnDAZIrsSaEMCxwgwGggHI3E47eA4AKRogQxcy0mFFhgEW3MCoOKBZsdUrhFxSUMyT7P3bAlhcnk4BoHvb4RBuABGHwpJn+BGX1CLAGJKzmKjpF+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+appbookopen16:app app16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBExCNGSenHRmVCwqJPTq1GxeTHRqXPz+/DwyJPTq3Ny+lOzexPzy5HRuVFSWlNzClPTexIR2ZOzevPz29AxqbPz6/IR+ZDyKjPTy5IyCZPz27ESOjJySfDSGhPTm1PTizJSKdDSChNzWxMS2nIR6ZKyijNzOrOzWtIx+bLSifNTGrMy6lIx+ZCRWRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaeQEAAQCwWBYJiYEAoGAFIw0E5QCScAIVikUgQqNargtFwdB9KSDhxiEjMiUlgHlB3E48IpdKdLCxzEAQJFxUTblwJGH9zGQgVGhUbbhxdG4wBHQQaCwaTb10emB8EBiAhInp8CSKYIw8kDRSfDiUmJ4xCIxMoKSoRJRMrJyy5uhMtLisTLCQkC8bHGBMj1daARgEjLyN03kPZc09FfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appboxes16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMT+xAT+BASCBATCBMT+/AT+/ASChATCxPz+xPz+BISCBMTCBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEEgZwrwYBCFqvhs3DNYXjChRlWBRjIRqGN4UuEUczMZxsDeXykdEsDQVVSLhQxhBCkVlmXA+KVHFYhFYOoHbMGN6pTQaW8YYiQmcG+q16a0+Zipw+4e9B/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+appbox16:app app16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+xISCBMTCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANECKoR6ys2IVqokF08yMTA1gwkYX5WQK5ma4VceTYPxXnBWdtY6+0834/Bowgzm6APWRQcH4TiMhPK2WYRiZWW7XK7/gQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appbrowser16:app app16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxONCROfCRKfKx6LNy+bNTOpGSS1DRupAwyXBRSnPTSjPTqvOzqzMzSvHSSlKy6ZDxutAxCpBQ2XBxepLTKvPzqzPzy5OTShLS2dLSqRFR2jBRerBQ+jOTixOzetNS2XHx6XDR2tCRexBwyTDyKzOTavPzq1OzKdCx23BRKtCQ6VCQmHFSa7IyirOzSnGSGpIR+bFSO1DyK7DR+5CRixBw2VDQuHFye7IS27NzGXISuhEyS5DR25BRWxBQ+lBQyXCQqPCxSfGyu7GyerKy2ZFR+rERqfCRmxBROtBQ+fBwuTBwmNDSW9JyabLyqRIx+TExSXBQ6bAQCBBQ6ZBxapDR+zBxq3LyaLJySRHxqPGxeNBxGbCRmrHRyRERONDRKNDQ2JCQuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAeygACCg4SFhgABAQIDh4MBBAUGBwgDCYcKCwwNDg8QERIThRQVFhcNGBkaGxwdoYMDHhcXHxggISIjEiSvJSYXJwsoISkpIyorLIIDLS4WLzAxMjM0NSo2N8o4OS46OzwzPSk+P0BBgkI8Q0NERUZHCEhJSktMgwk4Qy1NTk9QUVJLphCiUsWKlStYsmjZQiJgIS4KuijQ4iXAFxYCDVFJwGUFmDBhMjYSw0KMyEYoBfkJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+appcalc16:app app16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBISChPz+/AQCBCH5BAEAAAAALAAAAAAQABAAAAI4hI9pwe0Ogpi00hHF2LzzzFlTsIHD45SSx6oCeW4wjK2tl83y7t64pIsJaxrfh2bEAJIlhRPhLwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appclock16:app app16 16:photo:16 16:R0lGODlhEAAQAIIAALy+vAQCBPwCBMQCBIQCBISChPz+/MTCxCH5BAAAAAAALAAAAAAQABAAAANbCLHcrSLKOZcYmDSCsR1aUABAsXDDJwJGa5SBFwgaWxbCG3CWaBwG3C8Y67FawpYiNQscg65fsVkYuoAmJs1pBR522lQB6ILJLqHRwQQOZzYdZnw+dzruDIA/AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+appdate16:app app16 16:photo:16 16:R0lGODlhEAAQAIQAAASC/AQCBPzerPyqXMRaBIQCBISChPz+/KSipMTCxPz+BMTCBPwCBPz+xPzCxMQCBISCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVxICCOQGCeJjkGwkC8RFEEavkax2G8dB0QuRyhhzoBg8MSYsncJXKJZIDZHCoWP1ogGIwGrtnSgUFmHLyNRHhrdpjRamnO/SYkromHdnxwnwkKVxByZW8DgQsQM2JcfwZXO0MBCZSVBgMuLzJaRZ0pfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+apppencil16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/IQCBMQCBPzCxAQCBPz+/MTCxISChDQyNKSipEQCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARDEMhJZRBD1H2z3lMnjKCFjUJQimOgcmcbELCXzjXq0hV785WCQYcDFQjDXeloMByKG6YTAdwIDAlqSZJSVFeKLcUfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+appsheet16:app app16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBAT+/Pz+/KSipPz+BAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANFCBDc7iqIKUW98WkWpx1DAIphR41ouWya+YVpoBAaCKtMoRfsyue8WGC3YxBii5+RtiEWmASFdDVs6GRTKfCa7UK6AH8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+apptool16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBISChGRmZMTCxKSipLS2tHx6fPz+/OTm5FxaXOzu7DQyNMzOzAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAReEMhAq7wYBDECKVSGBcbRfcEYauSZXgFCrEEXgDCSeIEyzKSXZoBYVCoJVIqBGByKu0Cy8QHxmgNngWCkGgqsGWFseu6oMApoXHAWhWnKrv0UqeYDe0YO10/6fhJ+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+apptools16:app app16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBExKTERCRAQCBOzu7Nze3MzKzLy+vCxqZBQ2NJyanKyqrGRiZDRydKza3FRWVPT29LSytDw6PMTm5EySjCxaXGRaJFSanCRSVGxqbPTmvMSqVJTW1GSurHS6vOzq7KSipISChFRKHJSGNPz23GxKFBQ6PKyurCwqLMyufJx2RAQGBJSWlEwyDIRiLNy+lLSKVDwmDJRuNOTOrLyabGRCFDx2dKSCVOzWtHzCxOTGnNSyhAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAahQIBwCAgIBAOiUiggFAyHASKxDAwUC8Zg0HAglA9IZPGQABoTSqJCFTIOEIsFgHBcEhhHUpKJFCwaGxYYHB0VEx4IEh8gIQwiIyQbJRMcHokmEicfDygAkCkqJQgIGG0rLElCLS4vMCWqQwMCQg0UMTIzNDVLQjaIGDE3ODQlS785CEkxKjowvEOHybG4O6JDCdNKuDUxRAmxRDHeveUAfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appuser16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/MTCxISChMT+/ATCxASChFxaXAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMg5gw00yyDGIAR1YUDggeFWFIZhnSBZrsZxdIOFEGTA2oeBAHeyuGwvzxBlYdUOLROMFzDQntJPrNoqAKUBaqnV+k57ZORruykHDj2LqIzUVKp1u0iuB/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+appusers16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxISChAT+BMRaBPyqXARCBPz+/FxaXAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARLEIRJa5Ui673nsGAgeKE1Bl9AUEXbiqTlFlZaGUZoszm4BzhDAVf5BYbAXI+TAR6CS2ZGSZSEiIIqYIsSIEaJ7GRrlY7J1lKA7I8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+appwp16:app app16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBKSinJyOfPz27Pzy7AwKDExOTJyWlERCRKSelPz69LyyrKymnPz+/MS2fDQyJAQCBOTazLSiXOzivMS2jKSSVOzmxPz25NzSpPTu5KyebOzixNTGjOTWpMSydMSybCwqFGReVKyaXNzSnGxeNJSCVMS2nPz23MSuZIR+bJyShLyqnOTOtGxiXIR6XOTSvIx6RMSubIyCdKSalMS6pOTWxMzKvKSabJyKTOzezHxuPGRmZKyurMTCvPTq3AAAACH5BAEAAAAALAAAAAAQABAAAAajQIBwCAgIiEhiYEA4FgwHRDKhIBAWz4OhgGQ0FAPHA7qFEBONb0Qy0ULeQ2+aUrFcMI+3GYBOZzQbHB0eHyAhIQByDREiEwMjFRIkJQImAgJ+jScjHigkKSorLC0AKg2NFSMoki4qCy+IQgITKDAxkjIzNDWkQxQoJaskMgk2Eb1DNzgoOCoHDDY5yEIwJToAOzw9ET7TQiREAhkZ3kmy5QB+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+cal1day16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANOCLrMEUDIOUS9AFLLhx8LIRZjKYZmMRCkaChFLHty/AIiS3y6q+QtT49wq8VotRtQJGwRf6Zmrlj7DJLQXsupTJmeEIN4TB5nII20wp8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+cal5days16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANMCLrMEUDIOUS9AFLLhx8LIRZjKYbj55GioRRwoQ5x4QIiIdMmcec7jy53q81qP9OO5VMAj8RXTFWzOZW95HDLdEEM4LA4nIE0zgp/AgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+cal7days16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANPCLrMEUDIOUS9AFLLhx8LIRZjKYbj55GioRRwoQ5x4QIiwcp0fucsj873qvGMv5Jw2FIACUsW4WakGW1O046I05qmGYBhTC6TM5CGWuFPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+calappointment16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBAQC/AQCjPz+/MTCxPz+BISCBISChKSipAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARbEMhJaQhA6D1E/wDGeeRgDhOhFoTBEi+REgdrIHScSEVvAD9Xr7cDqGSGpFEnQSqTv2NxCFQOiU1VEAiTZmstHFg1vQKuw+LxxfYaV/AuOQRI2O/4ewhT6Uv8EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+calbell16:cal cal16 16:photo:16 16:R0lGODlhDwAOAIIAAPwCBISCBPz+BIQCBMTCxISChPz+/AQCBCH5BAEAAAAALAAAAAAPAA4AAAM+CLrR+zCIAWsgLVRGRBhOVQiG94WPVAbHaZHYAWqRYLbge88RsbInGuBCEhRYrZYm4xk4nYdoKzKIbiKHawIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+callist16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBAQC/AQCjPz+/KSipPzerMRaBEQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARDEMhJaQhA6D1E/wDGeeRgDhOhruyatjBRSIRxxOsMEAdC0BUZDcfSEYvDo3Bn++2Cxt7RqFxWhZiCdsvdhjCVsMQfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+calmonth16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANSCLrMEUDIOUS9AFLLhx8LIRZjKYbiRxLFIBpK0Q6z7MkwkJIe8b0KEeuWchFysuStVsjtfMbeMQitWpG25YfmNK1WU53XNIUYzug0OgNpuBX+BAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+caltoday16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBAQC/AQCjPz+/MTCxKSipPyCBMRaBPyqXAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARTEMhJaQhA6D1E/wDGeeRgDhOhFmurpi5LyIQhFfiBIAfuFzaAioBIJBCummRYPCaDPh3vhwsOZdihNfa8Ub/AJXemFZPPNBvGwG672yFMZS7xRwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+caltodo16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBAT+BAQC/AQCjPz+/MTCxPzCxKSipPwCBMQCBIQCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARaEMhJaQhA6D1E/wDGeeRgDhOhFmurpi5LyMYhFXiuFwZiA6qZYbbqJX5BIw2RAPxwAAWCyWMCCsiXFGEEErKz6LQZfOqiTR1YJiGq1rFyyHmo2+/1EKbCl/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+connecting16:connect connect16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBPz+BMTCBISCBAQCBPz+/MTCxMTGxISChFxaXMzGzKSipAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMhJZbihUiz60FPnfaA0iBpBVGdHEYWxToEoSHBRHHM9AgSEQRcj+AYkYAJxIPKQFUJiOdTJQFIDU6dYzKKFhTCM+E5g4mXaDAyrlogEG+DGTecA7wsP8EcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+connectno16:connect connect16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBPz+BMTCBAQCBERCBPz+/MTCxMTGxISChFxaXMzGzKSipAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARPEMhJq704axBEHoPUEdhQGMNYFuwxkKInDYjBniEnwMCQIIebSzXx/WwsFK+YMABZikWuYlrUCtZpEYv4WRPaHhb064YB41kCfJFSQBh/BAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+connectyes16:connect connect16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/KSipDQyNMTCxMTGxISChFxaXMzGzAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMhJZxCjgsAtDtUlCOA1gJQ4kl/IDatAoF7xxkS6GgEBr6jAobCyBX42SQBxMOx6A8MhiGASR8YDgrYsNEeJ0zaEGZY7uoH2oB6nOUwtbdLaVOeTUwo/8UcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+devcdmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tOzOvNTqvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/LzKvMTCxDQyNASCBARCBDTSJIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAa0QIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTBqUiuUCVmAeiYzmsKlwOt/AAKFIFAIIFx4WHyAhUwIDIgsZFyMkFxchJSYmiBkSBBoIJJwIGgOhiCYFJSEnFyQjFwNZewABISAfFiYnCAEmCREIrwAIFhwVGwcaBAkPGApsQsAVFA0GBQMRbxBTKM0ODQwTEq192ClDgROkBHvYKuNJUu5CKCorX1RDKCkpUn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+devcdunmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tNzmvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/MTCxLy6vDQyNOTm5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAapQIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTLqUigWsuDwSmMxBQ9lwvoEBQpEoBBAWHRseHyBTAgMhCxgWIiMWFiASJCSHEgQSGQgjmwglGKCHBQUSICYWIyIWAwshIVMBIB8eFSQmCAEFCREIekIIFRsUGgcZEgkPFydrvxUUDg0GBSEREGJfv9AMEySsJxDYQ4DcEhh64UpS6lTs7QB+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+devdiskmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBDQyNIRuVKyCXMSKROzSrOzKpOTGnLSafLySZKxuLMSOVPTWvPzixLSehNyibOzOrGxaVJx+XOzGnFw2FJRuPKx+TPTSrHRWPKyKZPTOpHxOJKyKXFw+HKSipISChMTCxFxaXIRiPNSWXExOTOS2hLR+PLRyLPTWtMyOTASCBARCBPz+/DTSJIyKjIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaTQIBwCAgYA8SkMCAYDARI5ZJQMBwQiWgyoFgwrA3HQ7scQAqFAcEQOUi0zAkFUSFYLghMBloUCDQNGxwdHhwHekcfICEhICIfIxkLJBABJUYCICABIhAOBiYnKJaXmH4CGSkYCCqkSAEfTKenrkOwsrQll0IrS7G5uwArLLaxLbXCLsTFLyDBKy4wZEVHvCwsRn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+devdiskunmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBDQyNIRuVKyCXMSKRPTWtOzKpOTGnLSafLySZKxuLMSOVOzOrPzm1LSehNyibGxaVJx+XOzGnFw2FJRuPKx+TPTSrHRWPKyKZPTWvHxOJKyKXFw+HPTOpKSipISChMTCxFxaXIRiPHxaNLRyLNSWXExOTPzixOS2hLR+PMyOTPz+/IyKjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaIQIBwCAgYA8SkMCAYDARI5ZJQMBwQiWgyoFgwGgiD46FdDiCFwoDQAEe0TMkEQSFULIcLBloUCDIaDRscHRsNHhhHHyAhISAiHyMkJSYQASdGAiAgASIQKA0pKguXmJl+AiQGFwgrpUgBH0yoqK9DsbO1J5hbsrq8SrgstlJFHy0gwMVFR1J+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+devfloppymount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBMTCxARmZPz+/FSWlLSytKSipERCRIyOjISChOTm5HRydNza3GRiZFRSVASCBARCBDTSJIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVrICCOQBCQKBkIw5mqLFG47zoQ+FwbN57TosDhgPD5dMEEIqE04kwlBWKBUEiNVYFpyqAyGEUCgqEtERiNNMLhQKzLQYJg7n7Y4aMAwbCUPvAQeWNgfzQQETAIhSMQEogwgBITQEGGEREmfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+devfloppyunmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxARmZPz+/FSWlLSytKSipERCRIyOjISChOTm5HRydNza3GRiZFRSVCH5BAEAAAAALAAAAAAQABAAAARcEMgJQqCYBjFu1hxReN82EOhYGieaklJwHIjrqnGCJLqNWhUFYoFQCG1FgWXIIDIYNQKCoawQGI0swuFAbKsxgmDsfZjBkwDBsNM90Jot9A3DbBD0Dwiur9QnfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+devnetwork16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBISChPz+/Nza3ARaZESanCyKlARudARGTLy+vNzq7ARmbMTCxARufAROVMzOzKSipARyfOzq7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVmICAGZFmKQiACweCSBImq41AYB5IodLq2hwWO0ejRWDac48Gb/QKNqNRoqspmrVcAUuIJBANS8sBIFCORUgooPEh4J8B67NgdsVBp9C5XWfl9LRMTCyReX19hARNojWlWLH+AAH4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+devpc16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBISChHx+fPz+/AQCBAQC/AT+/AQCxAQChAT+BLy+vAR+BAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARYEIAgqK1YzsG754QUDERpmkEpkkXrtoK6EcVgHIibhnNx564Yb0TDvQq7FQ34EiqPOhnREqhWSUPsyZSQAbbg7GcMEgwUiYVivTa1R+y4XEGoWO/4AMAfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+devscanner16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/MT+/ASChARCRATCxMTCxFxaXKSipDQyNAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARTEMgJgqWBVivEldkUdKSXhVjZfenommglDERh3Tc4E4ZRHAGgkEPr9X6H5AHBERSMRyWzkug8jQXFEhWoOo8dRYxqLXSmGjIJnVaz29Q3fAP3RwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+devscreen16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXFRSVPz+/PT29OTm5OTi5DQyNDw+PERGRExKTHx+fISChIyKjHRydFxeXDQ2NCQmJBQSFAQCBERCRMTGxHR2dGRiZExOTDw6PCQiJAwODCwuLFRWVOzu7BweHAwKDCwqLHx6fBQWFGxqbGRmZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAanQIBwSCwKAwKkMslEAgSDqDRKqBYKhkNgcDggEorkMrDQchkNhuOhgEQkk0l5S2lUGpYLJqPZTAwMHB0DCmhqAW0Rfh5zAxgOkBcCFAcfIBMECxwBBAEPFw8dChkhcBMDDAcdnQqtFKSWcQMimx4dGRkQBxGxsg6bBQEawx8jl3GnJFoFHRNXVVNRJYIFDAsL1tgiDiQXFx0HABwcXeQH5OjkRutEfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+devspeaker16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXAT+/DQyNATCxMTCxPz+/AQCBKSipASChAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARWEMgJQqCXziDG2JoUEENhZBkmHIWJVptAmqcIW/Js1MiF56TBzkckAAcHoa9nMRKeA4TyJk0knsHhTeK5khBaH2VwLYVh40TJhQ6RzeIQV32Quz8hfwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editcopy16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIUAAFxaXPwCBNze3GxubERCRPz+/Pz29Pzy5OTe3LS2tAQCBPTq3PTizLyulKyqrOzexLymhLy+vPTy9OzWvLyifMTCxHRydOzSrLyihPz6/OTKpLyabOzu7OTm5MS2nMSqjKSipDQyNJyenLSytOTi5NTS1JyanNTW1JSWlLy6vKyurAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAAaUQIBwCAgYj0eAYLkcEJBIZWFaGBie0ICUOnBiowKq4YBIKIbJcGG8YDQUDoHTKGU/HhBFpHrVIiQHbQ8TFAoVBRZeSoEIgxcYhhkSAmZKghcXGht6EhwdDmcRHh4NHxgbmwkcCwIgZwqwsbAhCR0CCiIKWQAOCQkjJAolJrpQShK2wicoxVEJKSMqDiAizLuysiF+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editcut16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/ISChCH5BAEAAAAALAAAAAAQABAAAAIwhI9pwaHrGFRBNDdPlYB3bWHQ1YXPtYln+iCpmqCDp6El7Ylsp6ssR1uYSKuW0V8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+editdelete16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbPT29GxubMzOzDQyNIyKjHRydERCROTi3IyKhPz29Ox6bPzCxPzy7PTm3NS6rIQCBMxCNPTq3PTi1PTezMyynPTm1PTaxOzWvMyulOzGrMymhPTq5OzOtNTKxNTOzNTCtNS+rMSehAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaKQAAgQCwahcihYMkcBAiBpLJApRoOBWgyIKhSEQkFgrBAcr1URiPhKAsDD3QB8RhA3FM0IlLHnyUTVBMSFBUWfl0XGBMTGBcZGodmcQWKjpAbHIgIBY2LHRoempOdjooTGx8giIOPFYofISJ+DyMXI6AfFySyfiUmJSUnKBYcICIpfgELzM3OZX5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+edit16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaVMR+RPzKjNze3AQCBMR6RPzGjPyODPz+/MzOzPyKDPyKBPz29OTWzPyGDPyGBOx6BOza1OR2BKROBNSOXKRKBBwOBOzu7PTWxPzizOySZPyCDFxaXOy2lNRyRMxmJCQOBPTm1OzStPTKrMR+XIRWLFxGNCQSBDQyNIRSNDQuJERGRLyqlNzSvIx6ZKRuVEw6LLSyrLymhKSShBwaFFROTJyWjMS+vNzW1OTazNzKrHRqXOzezOTOpPTq3OzWvOTStLyedMS+rLy2pMSynMSulAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAewgAAAAYSFhoQCA4IBBI2OjgUGBwiLBAmXlpcKkgsMlZcJBA0JDpIPEBGVjwkSBgOnExSfmBIVBxAMExYXswkYGRobHLq8gh2PHhoeHyAWIYKzIiMkJSYnKCnQg5YNHtQqKywtK9qMBC4vMDEBMjIz2dCMDTQ1Njc4OToz5PEEOzw3ZPToMcLHO23HfogQ0QMIkCA+hPBbhAPHECJFjMyYIUQIvEUpUqwQOXKkSEF+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editpaste16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQiFHRqNIx+LFxSBDw6PKSaRPz+/NTOjKyiZDw+POTe3AQCBIR2HPT23Ly2dIR2FMTCxLS2tCQmJKSipExGLHx+fHR2dJyenJyanJSSlERCRGRmZNTW1ERGRNze3GxubBweHMzOzJSWlIyOjHRydPz29MzKzIyKjPTq3Ly2rLy+vISGhPzy5LymhISChPTizOzWvKyurPTexOzSrDQyNHx6fCwuLGxqbOzKpMSabAQGBMS2nLyulMSidAAAACH5BAEAAAAALAAAAAAQABAAAAa7QIBQGBAMCMMkoMAsGA6IBKFZECoWDEbDgXgYIIRIRDJZMigUMKHCrlgul7KCgcloNJu8fsMpFzoZgRoeHx0fHwsgGyEACiIjIxokhAeVByUmG0snkpIbC5YHF4obBREkJCgon5YmKQsqDAUrqiwsrAcmLSkpLrISLC/CrCYOKTAxvgUywhYvGx+6xzM0vjUSNhdvn7zIMdUMNxw4IByKH8fINDk6DABZWTsbYzw9Li4+7UoAHvD+4X6CAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editshred16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbGxubMzOzPz69DQyNIyKjERCRPz29PT29OTi3IyKhPz27PTu5PTy5Pz6/Pzy7PTq3OzexLyqlPTm1PTizOzavLyqjOzWvOzaxLyifOzizOTOpAQCBOzezAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaEQAAgQCwahcihYMkcBAiBpLJApRoOBWgyIKhWEQkFYYHkeqkMxKFBFpq9jgdkEGlPqwrJhCIY2N8FFRYUFxcYGX9dgRKEGhiHiYEOhBcbGBwdiQEOARcBGwEeAZllAgEUnQEfoQEgmp4hrCKtrwEYsrRlTiMBJAG8syN/IyMAxMXHSH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+edittrash16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBKSipFxaXPz+/MTCxISChDQyNCH5BAEAAAAALAAAAAAQABAAAANQCKrRsZA5EYZ7K5BdugkdlQVCsRHdoGLMRwqw8UWvIKvGwTICQdmGgY7W+92GEJKPdNwBlMYgMlNkSp3QgOxKXAKFWE0UHHlObI3yyFH2JwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+fileclose16:file file16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCQiJBwaHAQCBDQyNDw6PFxaXFRSVERGRCwqLAwODGRiZHx6fPz+/GxqbAwKDCQmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVaICCOZGmeqBgEwjCkRGEcSKK4JrEcBrMgAdeLVDg0GguGsYEbBQyGYyN6FDoPDIf0+LCKBIgetQERDgGDBGIpNY8GioAU0m6KXFw883w3+/l9f4AkfimGIn4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+filedocument16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJSWjPz+/Ozq7GxqbJyanPT29HRydMzOzDQyNIyKjERCROTi3Pz69PTy7Pzy7PTu5Ozm3LyqlJyWlJSSjJSOhOzi1LyulPz27PTq3PTm1OzezLyqjIyKhJSKfOzaxPz29OzizLyidIyGdIyCdOTOpLymhOzavOTStMTCtMS+rMS6pMSynMSulLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaQQIAQECgajcNkQMBkDgKEQFK4LFgLhkMBIVUKroWEYlEgMLxbBKLQUBwc52HgAQ4LBo049atWQyIPA3pEdFcQEhMUFYNVagQWFxgZGoxfYRsTHB0eH5UJCJAYICEinUoPIxIcHCQkIiIllQYEGCEhJicoKYwPmiQeKisrKLFKLCwtLi8wHyUlMYwM0tPUDH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+filefind16:file file16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBCQmJDw+PBQSFAQCBMza3NTm5MTW1HyChOT29Ozq7MTq7Kze5Kzm7Oz6/NTy9Iza5GzGzKzS1Nzy9Nz29Kzq9HTGzHTK1Lza3AwKDLzu9JTi7HTW5GTCzITO1Mzq7Hza5FTK1ESyvHzKzKzW3DQyNDyqtDw6PIzW5HzGzAT+/Dw+RKyurNTOzMTGxMS+tJSGdATCxHRydLSqpLymnLSijBweHERCRNze3Pz69PTy9Oze1OTSxOTGrMSqlLy+vPTu5OzSvMymjNTGvNS+tMy2pMyunMSefAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe4gACCAAECA4OIiAIEBQYHBAKJgwIICQoLDA0IkZIECQ4PCxARCwSSAxITFA8VEBYXGBmJAQYLGhUbHB0eH7KIGRIMEBAgISIjJKaIJQQLFxERIialkieUGigpKRoIBCqJKyyLBwvJAioEyoICLS4v6QQwMQQyLuqLli8zNDU2BCf1lN3AkUPHDh49fAQAAEnGD1MCCALZEaSHkIUMBQS8wWMIkSJGhBzBmFEGgRsBUqpMiSgdAD+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+filenew16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbPz6/GxubNTKxDQyNIyKhHRydERCROTi3PT29Pz29Pzy7PTq3My2pPzu5PTi1NS+rPTq5PTezMyynPTm1Pz69OzWvMyqjPTu5PTm3OzOtOzGrMSehNTCtNS+tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ/QAAgQCwWhUhhQMBkDgKEQFIpKFgLhgMiOl1eC4iEYrtIer+MxsFRRgYe3wLkMWC0qXE5/T6sfiMSExR8Z1YRFRMWF4RwYIcYFhkahH6AGBuRk2YCCBwSFZgdHR6UgB8gkR0hpJsSGCAZoiEiI4QKtyQlFBQeHrVmC8HCw21+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fileopen16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBOSmZPzSnPzChPzGhPyuZEwyHExOTFROTFxaVFRSTMSGTPT29Ozu7Nze3NTS1MzKzMTGxLy6vLS2tLSytDQyNOTm5OTi5Ly+vKyqrKSmpIyOjLR+RNTW1MzOzJyenGxqZBweHKSinJSWlExKTMTCxKyurGxubBQSFAwKDJyanERCRERGRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaRQIBwGCgGhkhkEWA8HpNPojFJFU6ryitTiw0IBgRBkxsYFAiGtDodDZwPCERCEV8sEk0CI9FoOB4BEBESExQVFgEEBw8PFxcYEBIZGhscCEwdCxAPGA8eHxkUGyAhIkwHEREQqxEZExUjJCVWCBAZJhEmGRUnoygpQioZGxsnxsQrHByzQiJxz3EsLSwWpkJ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fileprint16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFRKNAQCBPz+/MTCxExKLPTq5Pz29Pz6/OzezPT29PTu7PTy7NzClOzm1PTu5LSabJyanPTm3FxaXOzCjOTKrOzi1OzaxOTSvJyenGRmZLyyTKSipDQyNERCROTi5Hx+fMzKzJSSlIyOjISChLS2tAT+BDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaYQIBwKAwIBMTkMDAYEApIpVBgOCAOg4RRGlAoEAuGIdGITgWOq4LxcCQgZkEkIHksHgYJOR6ZQCgVFhYJFxgTBVMZihoCfxUYDWUbUBGKGREcjBoQEB2TAB4CAx+Vl5WMhyACHiEhH6IfIiMktCQgE0cZJQStr6O2t6EARxO6vK6iEx4dZsMCxbsmBB4nzUTEutVSSUdmfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filesave16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBFRSVMTCxKyurPz+/JSWlFRWVJyenKSipJSSlOzu7ISChISGhIyOjHR2dJyanIyKjHx6fMzOzGRiZAQGBFxeXGRmZHRydGxqbAwODOTm5ExOTERGRExKTHx+fGxubNza3Dw+PDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaAQIAQECgOj0jBgFAoBpBHpaFAbRqRh0F1a30ClAhuNZHwZhViqgFhJizSjIZXQCAoHOKHYw5xRBiAElQTFAoVQgINFBYXGBkZFxYHGRqIDBQbmRwdHgKeH2YgHpmkIR0HAhFeTqSZIhwCFIdIrBsjAgcPXlBERZ4Gu7xCRZVDfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBwWHMzKzOzq7ERCRExGTCwqLARqnAQ+ZHR2dKyqrNTOzHx2fCQiJMTi9NTu9HzC3AxmnAQ+XPTm7Dy67DymzITC3IzG5AxypHRydKymrMzOzOzu7BweHByy9AyGtFyy1IzG3NTu/ARupFRSVByazBR6rAyGvFyuzJTK3MTm9BR+tAxWhHS61MTi7Pz+/IymvCxulBRelAx2rHS63Pz6/PTy9PTu9Nza3ISitBRupFSixNTS1CxqnDQyNMzGzOTi5MTCxMTGxGxubGxqbLy2vLSutGRiZLy6vLSytKyurDQuNFxaXKSipDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAECg4eIAAMEBQYHCImDBgkKCwwNBQIBBw4Bhw8QERITFJYEFQUFnoIPFhcYoRkaFBscHR4Ggh8gIRciEiMQJBkltCa6JyUoKSkXKhIrLCQYuQAPLS4TEyUhKb0qLzDVAjEFMjMuNBMoNcw21QY3ODkFOjs82RM1PfDzFRU3fOggcM7Fj2pAgggRokOHDx9DhhAZUqQaISBGhjwMEvEIkiIHEgUAkgSJkiNLmFSMJChAEydPGBSBwvJQgAc0/QQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folderhtml16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBERGRBQWFMzKzOzq7CwqLDw6NARqnAQ+XHR2dKyqrOTm5ExKTERCRHRydMTi7NTu9HS+1KSmpBweHDy67DyixHS61ITG3AxypByu7DxinBw+ZERmdIySjITC3ARypExOTDRurIR2RPTSdJyulEyGvBw+bFSyzJTK3LzKvPzivOTixNTChLSybGyCfCRSnBQqRASGtFyuzDw+PCRShPzy5OzerOTShKyaTEx6pCxerGRufBR+rOTezPTShNy6bER+1BxCfBQuRAxelFSixBw2VISq3GySrPTWlHyanIyitFSO3IymtCRujAxWhCRqlCQ6XGyWvNS2bFyGvDxuvCRSpLy+vMS+vGxqbFyO1GSi3EyO1FRaVCQuPLS2tDxyzKyWNFxaNCQyPGxubCxajERSVExKNJyenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfZgACCAAECg4eIAAMEBQICBomDBwgJCgsEDA0BDg8BhwYQERKUDxOYDAyeghQVFhehGBmVlwwOqxobHB0eH6EfIAkPIYIiIyQlJhsnKBcpvrYiKissLS4vMDEyFjOvNAA1LDY3ODk6Oyc8PTIyFzQ1Jj42P0A6QTtCQ0REIEUORkdIkihZwsSekBhNnDyBciCKiSNSplDRUcWKkRhXCGDJYgiGli1cpuTocsILjytfFmRpACAGRTBhRogZgzHlAjKGWnIoY+bMgRgBDHRBo/LAIZoxuhwKatRPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folderlocked16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQSFMzKzOTm5CwuLERCRARqnAQ+XHR2dKSmpOzm5GxqbCQiJMTi7NTu9HS+1HRydOTm1Ozq7Dy67DyixHS61ITC3AxypERGRBweHByu7ASGtFyy1DSOtDRmfExOTBSazBR+rCwqLAxWhAxelByGtDSaxAwODHy+1Dw+PPT29IyqvCxujOzu7NTW1Nza3ExGJJyebKyqfMTCpFRSPOTi5DQqHOTezDw2NMTGxKyqhMTGrGxmXDQ2NMTCxMTGpHx6bHx2bBQWFIyOXDQuDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAECg4eIAAMEBQICBomDBwgJCgsEDAKFDQGHDg8QEZQSlxMUDJ2CDhUWF6AYGZWXFBqCGxwdFh4XGK8fIAohtiIIIx25EZwBDREHgiQjJSYmGScoKSoRKQ8rggIsDC0uJS4oGygoAyjdAAcsLxQUMDEyMzQ1EzapBy8MDDc36tFwgONFjlQ6dgCEEZBHDx8+ctRIRehHAyAwZASZIGRIEBoUBwUwIGMCiwFEaBQJichIjo9FZLBsacRIAB0A/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+foldernew16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBPz+hPz+BOSmZPzSnPzChFxaXMTCBPyuZPz+xPzGhEwyHExOTPz+/MSGTFROTPT29OTm5KyurDQyNNza3Ozq5Nze3LR+RLy+vJyenMzKzNTS1Ly6vJSWlFRSTMzOzMTGxLS2tKSmpGxubBQSFAwKDKSinJyanIyOjCQiJERCRERGRBweHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaNQIBwSCwaj8ikcokMCIqBaEDoBAQG1meAUDAQpIcBQoy1dg2JdBqhECgQ1IWB0WgcBIOBwIHXBwwPEBEREhIBbG4IExR/DBUVFhIXV2NjDVYYDY8SFU4ZVxpVAQwbGxynGxkdTh6XVh8gGSGzGSITIxokJUImGSMTwLcnKCkprgAqDSt1zCssKxQtQ35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folderopen16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFOzi1Ozq7ERCRCwqLPz+/PT29Ozu7OTm5FRSVHRydIR+fISCfMTCvAQ6XARqnJSKfIx6XPz6/MzKxJTa9Mzq9JzO5PTy7OzizJSOhIyCdOTi5Dy65FTC7HS2zMzm7OTSvNTCnIRyVNza3Dw+PASq5BSGrFyqzMyyjMzOzAR+zBRejBxqnBx+rHRmTPTy9IyqvDRylFxaXNze3DRujAQ2VLSyrDQ2NNTW1NTS1AQ6VJyenGxqbMTGxLy6vGRiZKyurKyqrKSmpDw6PDw6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfCgACCAAECg4eIAAMEBQYCB4mHAQgJCgsLDAEGDQGIkw4PBQkJBYwQnRESEREIoRMUE6IVChYGERcYGaoRGhsbHBQdHgu2HyAhGSK6qxsjJCUmJwARKCkpKsjKqislLNIRLS4vLykw2MkRMRAGhDIJMzTiLzDXETUQ0gAGCgU2HjM35N3AkYMdAB0EbCjcwcPCDBguevjIR0jHDwgWLACBECRIBB8GJekQMiRIjhxEIlBMFOBADR9FIhiJ5OnAEQB+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailforward16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRydHxubHxmZGxiXHRmZFxOTFxGPFxKTPwCBLymlMy+pOze3PTq3PTu5Pzy7LSmnOTaxOzm5LyqlNzOtPz69Pz27MzCtLyqrPT27IRubPzuzNTGvNTCxLSelPz25Bw+ZFxKPPzy1Pz65LyupBxKdCxWfPTm1Pz23LyinBxGbGzO5DRafBxWfBxajCymxHTS5BxSdBxKbFTK3EzG1CSGvCyKvCSSxCSavGTO5GRaVPzqzFzK5EzG3BSCtAwiPGxaVPTivPzy3NzKpBxObCRefBxqlPTmzJR2bKyahAwyRPzmvOTOpKyObNS+nPz21AQOFKyOfPzuxAQCBGRORLSadPzyzLymjMy2lOzetDwuJFRCPEw6NEQ6LEQyLEQ6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAAAQABAAAAfhgAABAgIDBAQFBgcIBwmOCQIKCwwNDg8OEBESjY8CDBMUFRYVFxgZDJyOGhsPChwVHR4fFSAhjwkaIiMOJBQQDRUVJSa3GicoHw4pEA8SGSorLI8tLtQu19gqLzDECTEyMzQ14zY1Njc3ODkqCTo7MjIxNCs5PD03PjctPwlAQUIihhBpQbCIihtG+CUocASFkAhIkogQ8kFJwkcFlogIkoRJEydPnkBR6GiAxiQLgiiIIkXElFQJqESoMsRKkAhXqkhhApNKFSxZggTJ4nHIEJhaDhzYwoVLFy1avHyB6ScQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mailget16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAxKdBRSfCyGvFSm1BxKfCSWzCyWzBRCXCRKfBwuRAQGDDw6PHy23Cym1CSSxByCxBxunBQSFKyurMTCxExihNza3NTW1JSSlMzKzFxaXLS2tNze3KSipCQmJGxmbNTS1KSepLy2vISGhJSWlHx+fERGRPz6/IyKjDw+POzq7JyenMzOzKSmpCwuLDQyNIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaeQIBwGBAIAsOkUjAgFJRQQMHgjC4PBIEVgAh4D4aEYrGAMhINxwPyiCgYSsmEUmk82grLRZJkYCgXaAEKFxYZcEISGhsZFxwFeY0WHR5CDB8dGCAXG5shGxQicBIMpSMUGxgTGSQlpQwSJicnEwwdI7gdKAwTsykpKiobr8QMKxeHDBcsGRvOzxsT0i0uL9HSHdkT2ZkoMJXF4a8AfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mail16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBGxaVOTe1Oze3OTWxOTWvNzStNzKpEQ6LOTezPz+/Pzy7Pz69Pz27Pz25Pz21PzuzPzuxEQyLLyinLSmnPz67Pz23LSafKyObDwuJMzCtLSelPzy1My6nLymjNTCxLyqnPzq1LyihKyOfOzavOzetEQ6NPTq3NzOtLymnNTGxJR2bOTOpPTivNTGvLymlKSShKyahEw+NOTe3PTm1Pzu1Pzy3FRCPPz65LSadFxGPOzm3PzqzPTmzPzmvEw6NCH5BAEAAAAALAAAAAAQABAAAAaqQIBwSCwaj8ikMhloOp/QpmAgqAoIhELBUDgcEIGEYrFgNBoLx+IBiRwkgQnFoWAwKhWLhX3BZAILGhsCDXgODhwdGB5vgAofICBlDiEiIx4kJSYBJ2UoEykqHSMrLC0nLWAnFS4UCycvMAcEMR0RLTIBMwaSahw0NTYtFwclNwEdLws4eoc2DxwQOR06ASk7PBAhIRE9Pj0tLSUY1T8I5gjn6Qgy7D8SfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailreplyall16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRubHxubHxqbHxmZGxeXHRmZGROTFRCPFxKTFxGPPwCBLymlMy6pOTa1PTq3PTu5Pz27Dw+POzi3PTm1OTWvPz25FRSVERCRLympPzuzPTu7NTGvFxaXKSmpPzu1Pz65Hx6fHxqZPzq1Pz23HR2dBw+ZHx+fISChJSWlDQmJHRydCxWfBxGbJyenExKTHRiXPzqzPzy3CQmJDRafGTO5ExOTERKTGxWVCRSfHTS5CymxBxajBxWfPTmvPzy1CyixCSaxCySxDSaxDSWxDSSvDyaxGS21PTmzPz21AwiPBRejCSavByGtCSezEzG3FzK5FzG3GzO5FTK3CQ2bPTixBxqlCRefBxSdBxSfBx2nCQ+dHxmXPzmvLSafAwmRAwyRPzyzDw6POzavNzKpAQOFPzuxBwWTBw2ZGRORLyWdMy2lOzetPTivAQCBKyObOTOpAweNBwWVEQyLEw2LEQ2LDwuJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAQABAAAAf4gAABAgMEBQUGBwgJCguOCwEMDQ4PEBESDA4TjY8DFAwVERYXGBkRm4+QGhsMHB0eGB8bDpyOARogEBceIRgXv8COIiMkGB4lJSYnIcwoKb/DGyoXKywtKS4pHinMLzAxJDIzNDUtNjcv6B0hLzgfMh85OjstPDw99zwd7T4/LTVAgggZQqSIECNHevSAgSSJkiVMmjh5AiWKlClAiFARUeVHFSVWmLS40gNLlh5agGzh0kWDlwZfrIDREKaCAjEqrFA5MMYLmTAxlJTxYoZMozNozqRRs4ZNmy5s3LwhA0dBnDNn5MxBoAABnTp17IitowDrmQV+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailreply16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRubHxubHxqbHxmZGxeXHRmZGROTEw+NFxKTFxGPPwCBLymnMy6pOTa1PTm1Pzy7LymlOzi3HxqZOTWvPz69Pz25My+tLympFRGRHxuZPzu1LymjNTGvNTCxBw+ZPz23PzuzPz65PTu5NzOtCxWfBxKbPzq1DRafGTO5BxGbPzy9HTS5CymxBxajHRiXPzqzCyixCSaxCySxDSaxDSSvGS21GxWVAwmRBRejCSavByGtCSezEzG3FzK5FzG3CQ2bPzuxAwiPBxqlBxKdCRefBxWfBxSdBxSfBx2nCQ+dPzy1CRqlAwyRDQmJPTmvPTixLSafOTOpAQOFPz21BwWTBw2ZPzmvNS6nPTivAQCBAweNBwWVNzKpPzyzLyihGRORLyWdMy2lOzetKyObEQyLEw6NEw2LDwuJEQ2LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAQABAAAAfqgAABAgMEBQUGBwgJCguOCwEMDQ4PEJYRDhKNjxMPDBQVFhAXGBUSGY8LGhsQHB0VHh8gFQ6bjgEhIiMMJCUmFbS2CwMnG6IoKSorI7WpEycWFiUsLSou1yXXji8wFiopMTIzNDUz4zbZNxsbODk6Ozw9Pj8pPzEzQDdB60JDOkRFjBw5giRJDCWdlmxwIIRJExAWKDRyMgTIiydLoESRImQKlSUSF1SxUoXAlSBRsGSJoCVICIlbqlThcoBClC5eYFD4EiVIFwUyqywAE0ZMlqNjpJDpIkUBl0dlFChAYOZMmTJoyqQR5icQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mailsend16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRubHxubHxqbHxmZGxeXHRmZGROTFRCPFxKTFxGPPwCBHxqZLyqlMy6pOze3PTq3PTu5Pz27Pzy7LyinOTaxOzi3Ozq3LymlOTOtPz69Pzy5My+tLympPzqzNTGvLSelPzy3BxGbBQ6VPzuzPz65LyupNzOtPz+/GzO5BRejPzq1Pz23LymjHTS5CyixCSavBxqlPz25LymnGTO5CymxCSaxByGtHRiXPzy1CySxCSezGxWVPzuxKyOhMy6nDSaxEzG3PTivNzKpKyOfPzu1FzK5PTmzJR2ZLyihLSWfKyObOzmzPzmvDyaxOzavLSafGRORMy2lOzetDwuJEw6NEw2LEQyLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAQABAAAAfUgAABAgMEBQUGBwgJCguOCwwNDg8QERITFBUWjY8DFxgZGhsaHB0aD5yODB4TGB+kICEaIiOPCwEkJRcmJyYPKCIpKrWqKywTmC0SIi4vMDHEDCsyMg8zEyI0NTY3z7U4Hhs5Mx+0IyI6OyPrIzw9Gys+PxIy2EBBxAs8Qjk5Q0RFWFxAZySfgSMsilRAkiRECHQ08hHgJ0TJkCU/mECU2ISEkowUlpAQ4QTfowNPoAzJIeRJCyjm8kVRIkWIzSkXhwxJtYAKgp9VrFi5QoWKFZ5+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav1downarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIYhI+py+0PUZi0zmTtypflV0VdRJbm6fgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+nav1leftarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAP///wAAACH5BAEAAAAALAAAAAAQABAAAAIdhI+pyxqdwoNGTmgvy9px/IEWBWRkKZ2oWrKu4hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav1rightarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIdhI+pyxCtwoNHTmpvy3rxnnwQh1mUI52o6rCu6hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav1uparrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIYhI+py+0PWwhxzmetzFpxnnxfRJbmufgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+nav2downarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIfhI+pq+EPXYpxUckoO3AjbF3dJwahllXe6AFgC8d+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav2leftarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+pyxf5VohmSlsxmpjTzAHeN5ak6UHpqKRi2GpwvH3Q3eT64RcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav2rightarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+pq5HOAjQyVnqfhHue7oAaKH5kiW0AmnLqaHomkj02g+e6XwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav2uparrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIghI+pyxfR0HsRzNnuXVqn3mVQZWFRyIDjp65Ga5Ly4hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+navback16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRSdBRObCQ2TBxObISevAQCBNzu/BRGZPz6/FzC3Pz+/HTS5ByyzJze7Mzq9ITC3AQWLAyWvBSavFyuxAwaLAwSHBRafBSOrDzW5AyixCS61ETW3CzG1AQeLAweLAxefBSStEze7CSWtCyatBSCnBRWfAwmPBRWdByixAQSHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZiQIBwSCwah4HjUTBQFgkFg3MoKBykU0QhoUAIAuAksbpgNByPxQMSGVsVDYlkIqdUiJYLJqORbDgcHRseRR8gISIaEyMkGCVYRBEmeyAnlgaQkSgpmU4RAZ1OKqFOpFNGfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+navdown16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRObCRKZBxCXAwyTKTK3Ozy/NTm9GSivAQWHNzu/FzC3IzO5CySrAQOHAyuzETS3CSWtAyOtETa5Aw2VLze7ByWtBy61BSavAxWdBRCXAwqPAQCBDR+nKTe7FS+1Eze7ByixBRmjPz+/AyexAyixAQKFBRqjAQGDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZeQIBwSCwaj0hAYCkYEJLKguGASEADigWj4bgaHpBINykwSCYRa5HCFFQsF0xGo9lwhpSOwfORYC4gISJ3RAQdIyQYJSAlImNrh4uNJkl5CoKUUBQnjlB4KJ6hokN+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+navforward16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAwyTBRObAw2VDR+nCRKZOzy/KTe7Pz+/KTK3Nzu/Lze7FS+1AyexAyuzBSavAyOtBSmzOTy/BRqjNTm9IzO5ETS3ETa5By61AyixByixBRmjAQGDBxCXGSivCySrCSWtBTC3AQOHAQWHAxWdEze7AQKFBRCXAwqPAQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZjQIBwSCwahYGjUjBQGgWEpHNYMBCaT4G2UDggos+EwmBYMBpf6VBgYDgeEMgjIpmoAQVKxXLBPDIXGhscRB0eHyAgDSGBGyJFASMiIiMkJYImUwAnmJqbjp4AKCmhAKSlTn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+navhome16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBDw6PBQWFCQiJAQCBFxeXMTCxJyanDwyLDQqLFRSVLSytJSSlISChCQmJERGRFRWVGxubKSmpJyenGRmZLy+vOzq7OTi5Ly6vGRiZPTy9Pz6/OTm5ExOTPT29BwaHNza3NS6tJRqRGQqBNy6pIyKjDwGBPTe1JSWlDQyNOTGrNRiBGwmBIRaLNymdLxWBHxGFNySXCwqLKyqrNR6LKxGBNTS1NTW1Jw+BEweDDQ2NAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaoQIBwCAgIiEjAgAAoGA6I5DBBUBgWjIZDqnwYGgVIoTGQQgyRiGRCgZCR1nTFcsFkHm9hBp2paDYbHAsZHW9eERkYGh4eGx4ag3gfSgMTIBshIiMkGyAlCCZTEpciJyQjGxcoKUQBEhcbIiorLB4XEltDrhcaLS4vtbcJra8bMDHAGrcyrTMXHjA0NSypEsO6EzY3IzU4OdoTzK0BCAkDMgkIOjJlAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+navup16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRObAwSHBRSdISevBRWfAweLNzu/BSOrAQWLPz6/FzC3DzW5BxObHTS5ByyzAyixEze7BSStBRWdAyWvByixAQSHCQ2TAQCBBRGZJze7CS61BSavAxefMzq9ETW3CSWtAwmPPz+/CzG1ITC3FyuxBSCnAQeLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZfQIBwSCwaj8hhQJAkDggFQxMQIBwQhUSyqlgwsFpjg6BwPCARySSstC4eFAqEURlYhoMLBpPRUDYcHXt7RgUeFB8gIU0BIoiKjAcUIwiLSQUkJRsmGIwJJwmEU6OkfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+playeject16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+py+0R3IFQUtruXVqn3kkWyIARR4rqKvoFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+playend16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIjhI+py8Eb3ENRggrxjRnrVIWcIoYd91FaenysMU6wTNeLXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+playpause16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIfhI+py+1vgoxzyUCxrZd18ClfmIyVyJ1lqkHuC0N+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+playstart16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIjhI+pyxudwlNyguqkqRZh3h0gl43hpoElqlHt9UKw7NG27BcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+playstop16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+py+1vgpySUWpvXXqrHmSaeJEYhKYq6hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textblock16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+py40Bo5SOzRvrwlgrfnkJOIkPaaaJXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textbold16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIihI+py70BowPQ1HZpwNv212Vg9IGHmIjoWa4ey5DSRNd+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+textbottom16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIVhI+py+0Po5y0hYtzrkB7zH0fN/kFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textcenter16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+pm+EPIZsnRkqtDnhu1zHfFSpjaY4PavgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textitalic16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+py+0BgztwUmmjBXX3jE0auHHhM5Yq4xcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textleft16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+pm+EPIZsgRoqr3Vnt102fFSJjUC6nlPoFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textmiddle16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIXhI+py+0PT5i01pisphjt3UmfFZYm5hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textmove16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+pm+EPIZsg2kfZvblXbwTg10WlA4rjyvgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textright16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+pm+EPIZstSrqsDhhv1ylfFE5jiYwX6hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textsortdec16:text text16 16:photo:16 16:R0lGODlhEAAQAIIAAAT+BPwCBAQCBAQC/FxaXAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM5CBDM+uKp8KiMsmaAs82dtnGeCHnNp4TjNQ4jq8CbDNOroIe3ROyEx2A4vOgkOBzgFxQ6Xa0owJ8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textsortinc16:text text16 16:photo:16 16:R0lGODlhEAAQAIIAAAT+BAQC/AQCBPwCBFxaXAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM4CAqxLm61CGBs81FMrQxgpnhKJlaXFJHUGg0w7DrDUmvtPQo8qyuEHoHW6hEVv+DQFvuhWtCFPwEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIlhI8Jwe2/AmpTynqPTXSqrnBM+I0kdmpmGmUp+K4nPMvhYx9+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+texttop16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIWhI9pwe2uYnq0yQtqxbz7D4biSIZ+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+textunder16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIjhI+pu+FxXoOIKpds1oBH7hlYxYxRCaIZ01lhJbHy9tTv7BcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewchoose16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMzCLrcGlAs6UAYgwLdLtEcI4ygQo7VVp2oupGpG4vmaUVTemX523qlFcw0a4RqNlkx5k8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewdetailed16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMmCLrc/i1IAVkYg1Z1iRYUKCqitp1oikqBWV3ZOnhkWNagqu+qnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewicon16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMwCLrcG1AwGOQbw6qANeCEB3pCSZpO6pgowJZqLKuUGE0dnuEhf8IL1kz1shSHDX8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewmag-16:view view16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1HyChOTy9Mzq7Kze5Kzm7OT29Oz6/Nzy9Lzu7JTW3GTCzLza3NTy9Nz29Ize7HTGzHzK1AwKDMTq7Kzq9JTi7HTW5HzGzMzu9KzS1IzW5Iza5FTK1ESyvLTa3HTK1GzGzGzG1DyqtIzK1AT+/AQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ+QIAQEBAMhkikgFAwHAiC5FCASCQUCwYiKiU0HA9IRAIhSAcTSuXBsFwwk0wyYNBANpyOxPMxIzMgCyEiHSMkGCV+SAQQJicoJCllUgBUECEeKhAIBCuUSxMKIFArBIpJBCxmLQQuL6eUAFCusJSzr7Kmpl0CtLGLvbW2Zn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewmag16:view view16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1HyChOTy9Mzq7Kze5Kzm7OT29Oz6/Nzy9Lzu7JTW3GTCzLza3NTy9Nz29Ize7HTGzHzK1AwKDMTq7Kzq9JTi7HTW5HzGzMzu9KzS1IzW5Iza5FTK1ESyvLTa3HTK1GzGzGzG1DyqtIzK1AT+/AQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ8QIAQEBAMhkikgFAwHAiC5FCASCQUCwYiKiU0HA9IRAIhSAcTSuXBsFwwk0wyYNBANpyOxPMxIzMgCyEiHSMkGCV+SAQQJicoJCllUgBUECEeKhAIBCuUSxMKIFArBIpJBCxmLQQuL6eUAFCusJSzr7GLArS5Q7O1tmZ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewmag+16:view view16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1HyChOTy9Mzq7Kze5Kzm7OT29Oz6/Nzy9Lzu7JTW3GTCzLza3NTy9Nz29Ize7HTGzHzK1AwKDMTq7Kzq9JTi7HTW5HzGzMzu9KzS1IzW5Iza5FTK1ESyvLTa3HTK1GzGzGzG1DyqtIzK1AT+/AQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaBQIAQEBAMhkikgFAwHAiC5FCASCQUCwYiKiU0HA9IRAIhSAcTSuXBsFwwk0wyYNBANpyOxPMxIzMgCyEiHSMkGCV+SAQQJicoJCllUgBUECEeKhAIBCuUSxMKIFArBIpJBCxmLQQuL6cAsLECrqeys7WxpqZdtK9Ct8C0fsHAZn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewmulticolumn16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMwCLrc/ixI0WSgKoyBl+beQFACpo1AqXbKCr1wLAMWS08hGG3dSZqin4sxnBmPD38CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewtext16:view view16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIchI+py40BTQSwuovp3DXkv1ia1IHmIXLiyWJ+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewtree16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBDQyNPz+/PzerAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAAMuCLHcri4yGISlj4kxcANgNRBQCIbL6U1Su7bB62rXvGydG25kqpwfIGxILBr9CQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actattach22:act act22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBMTCxPz+/DQyNKSipAQCBISChFxaXDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARrEMgJgqA4zzus/gLhFd5HCcZAXqsphYPUdhcYFNRcZnvdtpnDqPTbUWgAJKBYwzBlw+bRo3xmkNWoBgm0OrVLn3GC9RgCk8DhUw7c0rHPr4CDu5SYQNyEt7uSY3p/UAKFhYKDSQOLiwgFdhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actbookmark22:act act22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBCQmJCwqLMTGxAQCBBwaHMTCxLSytERGRFRWVLy+vKyqrKSmpHR2dJSSlJyanISGhGxubIyOjKyurGxqbFxeXGRmZHx+fKSipLy6vGRiZLS2tFRSVHRydJSWlHx6fCH5BAEAAAAALAAAAAAWABYAAAWWICCOZGmewamaQrq+wUC8azHINGocOI38iIRAceDNaISFYklkGHOEhoNBfUAOhuOLEJE8HoPiRKFdESiQBqViuTDIUAsEcyAeGJmyiqC5RCwJGg0YcEh9D0V3Dxt6JwQVDRYVHBUdi40mjw0PTgwQHgeYJQQJfxUXFxAOoTkFpQ0fsRSimQkWEQ0VtI62HLt7vjl7JQYhACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actbookmarknew22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBCwqLCQiJCQmJMTGxAQCBLy+vLSytERGRFRWVKyurKyqrLS2tKSmpHR2dJSWlKSipISGhGxubIyOjGxqbIyKjFxaXGRmZHx+fPz+NGRiZPz+ZPz+HMTCBKSiHPz+jFxeXPz+XPz+tPz+zPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAamQIBwSCwaj4Gj0hgQLJ+AAaEAVQoI06pRYDhkoYgwIhEgKBTfZ2FhaBsYDS8VWnA8Go0FJIKeqyUTDw8EDHBpSwUUFQ4UFhcYDQYFfkoFFxEQDG8KEAUZlEeWGBIakw4FG1STiBoYBRwdBR4fHgUdHKBEBSCnIR8iIyIfIblFu6ceIyQjtcXGCbLKzAUKzrq+wMLEVa+xs7W31kOTk6nkWuOf6Ea5QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actexit22:act act22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBHR2dDQyNCH5BAEAAAAALAAAAAAWABYAAAJOhI+py90RnIMyRUOxhDfzJkACdoXBuEDDkQFDi5go0MrKx16kns80b7qdELCgBYaEGWwL5nG1ePFiKp9A6kuYRNuho8vxVrrZivmMRtMLACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+acthelp22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBCQuNBwiJAwiLAwaJAwSHAwSFIy+3ERynCw2PCQuPAwmPCxOZCxWdJzG3FSazBwmNAQKDAQGBDRmhBQyTDxujDR2rIy21AwWJDyGxCxmjAwmNDRihAQOFDxmhCxunBQWFAwaLCRahDR6rESGvDQ2PCRWdDRunDSGvCRSdAwWHCwuLDSOzHSmxDyKxBxCZBwqNHSu1DyOzAQSHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAahQIBwCAgIBAPCoGAgOoeBAyKhWCwYDUf0CX1AIhLiJEGpBLiAAaRxdgYsl7Ybk8igBZoN5xmAdDxoanp8HyANISF8EBsiXBMjJBolBEQmGHFoRScbKHIKDykqK5lFAZRCnyknTaROLA8tq61OChgtKqyzQgEYEJi6UC4vI3LAASkbMBPARAEBdszR0sACEaPSMTIQM8W6KzNl3bo0NOJDdEEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actlock22:act act22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBHRudFxaXExGTERCRAwGDGxubPz+/Pz2/Ozm7Nza3NTS1KympFRSVHR2dNTO1JSSlKyqrKSipDQyNMTGxDw+PLSutKymrMTCxAQCBHRqLBQODJyanDQuFFxSJFRSJFRGJERCHExCHISChHxyLEQ6HGRaJExKHLSmbLy2fOzitPz23KSiZHxuNHxyNJSOTNTOnMTCjLSudKSaXJSKRJyOTOTetNzWpHxuPOTi5MzKzLS2tFxWXOzq7Ly6vOTe5Ix+RLSqdNzSpLyydKyqbKyiZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4IBAgMEBQKEjI0GBwgJCgsMDY2XjwkOAgQBDxCLl4QNCaGCBBGWooINCAqqrBKgqwATFKaDFRYVtBMXsIMNGBm0GRADjQIJxKIaGxwdHh8gISIhGyMZzIwkGholJiYfJiAfJyEZISDbg90oKCkqKwcHKyooLC0f7IIuLzD2YMSQgW8GDRri+AFoUMOGvRsxUhSsQQPHvmQSchyQtEAHhh0WJHDQcJERjwsKDvRI0BGDjwgicXhQyCOjSgUKPO6AObIkIQESfmxk6REDT4s0bfaYpDNkT4VAha5s+TLmzEYtatwIOHAiDZIKNQAJYk9IjCFEisyoocFEB4UACtBpm0t3LiF4gQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actredo22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBCReDJzGjMzivOTu3Pz+/JTWbHy+VHTCTMTivPT69BxGDESuJDyiHESiHEymJIzKZAQCBFS2LFzKNGzWPDRqHCxqDFSqLHy2XESCHAwaBAQOBBQqBDyWJHyqZDyKFGSiVESeJBQ6BAwSBGTGPFyWPFSSLEyOLESGJBQiDAwiBBQmDCRGFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaoQIBwSCwaj8hkMcBkKpcBwYAwEDif0YLhwEUkFItFMkAwMBoOR+PxgHwjRDggamhIJpQ8ZbKGKOQLcgEFdhUWEYgRF3sNfhELBHALAhgZFhobRBwREhQdEAIEHpIKHwsaSJwUDQgQIJINARxKESESDQ0dgCIjSpAkDAwPco+ZSJAlJicnKHIAIrNHidOIQxunT0kpCyrZSCss0d5Fj6jjRonn6uvs2QZBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actreload22:act act22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBCRSFCRSHBw+DBxCFCQ6FBwyDBQWBBxGFCxyLGTChMzqzLzmvHzKjDyOTER+RERyNDSqXNzy3LzivFS+fCyCPBQmBCQiBBxKFBQqDOTy3LTitES2dDR+PCxuJOT25KTarCx+PESSTCxKHDSeVCyKRNT21ESWVDSGPBQyDAQCBBQSFDRuLDSyZDySTGzChCRiJKSmpExKTDS2ZGzGhLy+vGxqbISChDSKRMzKzGxubDQ2NIyOjCQiJCwqLBQWFCwuLKSipERCRERGRHR2dAwKDDw6PFRWVIyKjCQmJFRSVBwaHKyurAQGBExOTBweHFxeXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf9gACCg4IBAgMEBQYHhI2ECAkKCwwNDg8QBAOOhAQREhMUFQgWBxcHGBmbggkaGxwPB4yDB6SbBJIKHQaqtY0eHyAhsqrDgx4aCiKpqoQHAyMjJBMKJaSxzAAHIRsmJgonKA0LHSmDKiuOBywRLSQuLyEwwyoxMuiN6iUzNBXy5jU2bsgoJugABBz95uXQsUMGD3vpPPgTpKIGwx4+HMr4kW4YkCA2hAzxAQSIECI+imBTwVIFESNHerRUgc0cEiFHkjiiyYzeDiVLdvLcySSkkKGEWiZVweSGkIHMmvQosoQlkaZOjvhosvKJjIAxoOAsgpRZkQNLnvSoqspAIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actrun22:act act22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBAwKDAwKBCQiHNze3AQCBBwWFDw6NPTy9PTy/Dw2NKyytOTi3LS2tMTKzMzOxLy+tLy+vBQODNze5NTS1JyalIyCbIx6VIRyVISGfJyelOTq7EQ+NMTGxKyurGxeRLyKPOSmROSuVOy2XOSiTLzCzNTOzDw+NCwqLHxuVOy6bPzGfOSuXNTW1LSyrMSWRNymTOSmTKSCTPTGjPzSnPzWnMyaVBQSDMTCxPz+/KyahNSeRHxeLJRyTPzmtPzarOy6fJyajNza1Ly6vLyulFRCJPzirPTOlMS2pNTSzMTCvJyenBQWFNzKtPz6vPzyvPzqtOzGlOTe1AwGBFxWTLy6tPTm1PzSpPzutPz2xPTSnOTSxOy2dPzapPzerOzm5IR+dPzu5Pzu1PzqxPzy5Pz+9GRiXGxuZKympHR2bOTm5Pz6/MzSzBwaFJSSjCQmHPz2/AwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeEAQKIjIIDBAQDjYMFBoMHCAkKgwYFhwULDAUKCg0ODxCkBQgRnoUSExMUDxUWFxgZGpAbFIuGHB0eHyAhIiMkIB8lJieIKCUpJCTGIyorLCktKIUDpC4YLzAxIjIyMzQ1NhgdpJI3ODktJTowOyM8Ejc9Pj9AQUIEclAocCMIBQhDiOwgoaKIoCI+jBxBkkSJkCWemIyq0GSHCBVHihRx8gRKFCmpKhGaQqWKFYZXsGR5kkXLFgRUXBUqkCGCFS5AjnTx0sXKlyA6CRVgAAHMAilhxIwhU6ZFkBY5kgKYUoXBAzMKzixZ4AJNGgVm1KxhM0WpmQpUMtooaOPGxAM3Nw60oYLGjNYCbzYJOgAnRzNBJ95oPYQCgpJtkwzFoULlRuRPiy9fNhAIACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actstop22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAASC/CQKDBwKDCwODNyKjPzq7My+vIxiXAQCBOSOjPz6/OSelNySjNyGhMR+fLRaTGQ2LPz+/Nx+dNR2bNRybMxuZMxeXMxiZLQSFJQaHFwqJNyKhOSCfNyCfNR6dMxmXMxWVMRORLQODOR+fOSSjNR2dMQ2LJQWFMRWTLwWDNSCfMxeVLwaFKQODNR+fNx+fMxiXKQSDOSWlMRSTMxaVMQ6NMxORMQyJOTS1MxqXLwWFLRORMxKPMQaHMxKTLQWFCH5BAEAAAAALAAAAAAWABYAAAb2QIBwSCwajwGBcikIHIsDQmFKNRwQT2EgoVgsGOCG4wHBIgmRhWRCqVQsF0xGYyYGNgoGh9PpeCQfICEic3UAAWgLIxwRJBsbHSUREyYYJ3RDAQULexGejhueESgpl3WaCxsqJKKsChEUKywtmFoFDC4vCayikzCyMbWHt38NCTKiHhUfMyzBdQIFKsodob0VNDWzwppuKxMRrx6iNjcitNA4bh+iEzkwojc66JkOOxcf7G35PBE9KS1MEUGgIQOIFfk++KjRw9wJgUUIZvhRoyLDFCliQDQisUWLGCJOeNx4hKCGkyhPGnqCoKVLl1liypyZxUAQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actundo22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBCReDJzGjMzivOTu3PT69MTivHy+VJTWbIzKZEymJESmFESiHDyiHESqLAQCBFzKNGzWPFS2LNTmzCxqDDRqHPz+/KTGnBQqBAQOBAwaBESCHHy2XBxGDOzy7HTCTEyyJDSqFHzWTAwSBBQ6BIy+dESKJFySPFSSNAwiBCRGFBQmDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAalQIBwSCwaj8ikMsBkKotMwYAwEDiXgYLhwD0gCFZiQKxNKBYMRqPh+D6G16y5AYnYIxBJAyF4AwITTAUJdBESD4gPFBV6Fn6ABBcJDIYPGEQZGhQbHAIdfx4JHw2VSBodGwWfAR4LDSALfkgYAQurBiAhICKfSSMkvQElGyYnGyi9Rxkdj4nOskUYyU9FpxnURikdGtjRKivdRKfQ2Inh5+jpRwZBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actunlock22:act act22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBGxqbFxaXExOTEQ+RAQCBPz+/PTy9Ozq7Nza3NTS1KSipFRSVOTi5Hx2fJSSlKyqrJyenJyWnDw6PMzKzKyurDQyNFxWXMTCxJyanHRuLHxuLGReJFxSLFROJFxWJExCHERCHBQODISChHxyLHRqNIRyNHRmLLSqbKyiZLy6fOTarPz67Pzy3OzitKymZFxSJJySTNTSnPTy3NzSpMTChLSydKyqbKSaXJySVIyGRGReLPz23NTOnMzCjHxuPLy2vKSmpOTe5LS2tLSutHxuNHRuPMS+xFxWLIR+RDw2HFRKJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SDAQIDBAUChY2EAQYHCAkKCwyOjZANDgIEAQoPjJiDAg2iggQQp5gMBwmrDBESl6MTFKuoFQSjABYRF40CGAW8BRm7hQwNxBobHB0eHx4gISIjBdiEAhYFJBslHOHSHh4hBSHlxIUmJygpKissBiwtLi8pGjDqhBoxMjMuaNSwcSMFjhw6dnjYRyrGCh4ueviw4Q5HDB0/PjAUJCBCAwMIGiiggAEIBFk/FgYLIgRkggQkhxAJkqGExkYMFnxsIGRkSQgLHhRRWUjAggQgG8AsSWRBBiP6VrYMOfKIyaBDNwLo+HHSUplOSyDRqiEHjRkretRQkcLgxayNF0wksQGQxsSKMTIq0QpgCba/gAE7IhMIACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+appbook22:app app22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBDyGhCyCfFSWlESOjDyKjDSGhCx+fGSinGSenFyanEySjHSqpHSqrGympEySlBx2dISytHyyrCR6dKTGxHyurHSurHyytGSipCR6fARmZFSalEyWlBRubAxubBRydDyKhDSChLSytPz+/MzKzIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbFQIBwSCwaj8ikMhBQIpmCQdM5ZBIKhgNiugwkFAsCI7pNMhuOxkNBgBgEiAi3GkBLJpJHYgEpaClyREwVFhcSEhgOGQoMfgMaERtcARQBFRMYExZ6HB0FUYAekkIBHxqWFmlrC1haESAfG6MBGx+VFRgKYH0hInGRklO0ppYXCwwMWQiQHkwjgrWnFRdYZHIBJCTP0LaWGAcDW9jZ2nMAw9IWTOQkJSZMRsOV49nu8E+19PbmR7TY+1TovONH5V7Ag0QMBAEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appbookopen22:app app22 22:photo:22 22:R0lGODlhFgAWAIYAAAQCBAQ2NPwCBHSurIS2tBx2dBweHPz+/Ozm1GxiTGyqpPz6/Pz69GSqpOzaxPzy5HxuVLSmlOTazPz27PT29NzClPTexHxuXLSmjAxqbFSinPTy9KyehNy+lPTy5Pz29HxyXNzWxKSahOzexPzy7IR2ZOTWtESenPTy7KSWfIyCbKyijAQGBDyalPTu3KSSdDSOjJyOdCSGhPzu3OzizJSGdPTq1PTq3JySdMy6lAyKhOzWtOzi1OTOrJyKbMS2nJySfMS+rAwCBNzOrNTCpNzKpJSGZKyafLSifLyylIx+ZHx6ZDSChAQuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAAWABYAAAf/gAABAoSFhoeHAAMAiI2IAAQFjI6EAAaJkQeTjwAICYkKBQcLm5WdBwyfhgChB66bp64HCQC1lQ2irqQCAA4PowsLEBESE4wAuLIHFAAVFr+uDBcYxRm1GrmuGxwdFh4Mrh8gGCET1gDYyhsiFSMkDAsMDCUYJhvnJ9kHKCnODwwfPlBQsULCPRYAWogK9sHFiwoOPEyQh0JFPXO1YBSYwBEFghjdHkwQOYGgwQwIZRR44GHGDBogabhAsYEEihrUMAIoUMCEDRs3HODIYQHFA6MPcJA7KICFjgw7eIzo4cOfiwc/gKwIUm2SkKdDdlDt4AABDaU/iIRwwbTSUyJFOow4S3Hkx9oNDDZgXPU0h1wcSIgEGUw4ibVET5WoWMKksePHpdxmyKADAEIWly9HJtQkQJMmlAgZCAQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+apppencil22:app app22 22:photo:22 22:R0lGODlhFgAWAIMAAASC/IQCBPwCBPyChMQCBPzCxAQCBPz+/MzKzISChKyqrDQyNEQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARYEMhJ6wxiEMtpIAWxddwXiqRlikSQeiAbuC+wirNR322gv7zcLobzDU+9XypoBBKTR1lz+RTWDgip8nUwZK1XLyIx5XoVicX2RUAo1DVKi7GOBxjxfNwQAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+apptool22:app app22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBISChFxaXNze3NTS1Ly6vKSipNTO1Ly2vNza3Pz+/MzOzOTe5DQyNOzu7MTCxGRmZMTGxPTy9Ozm7Hx6fPTu9MzGzGxmbAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAW1ICCOZGmeaEoGbBsI6joMRGEcbQwESDIrtVtAF1gwDLNaAmfKiVgLBJKgwB1KxQZrBHU0FAXmavFoQLYiB6TxFXMj5AZBwnJI2I3wcNWALyYEcgoKXxRhOHs7XxEVCwsWFgoUDRYUFwwQB25ZCxiNjo6GkwUXN2NsCxEYqhUHoQ0MEglYRQQXErcHrI55FycuB2YSmoyOBTEtB2sXuhU6XAENC2a6z9AKCwq+1tAN3E2J3ySkIQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+connecting22:connect connect22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBPz+BMTCBISCBAQCBPz+/MTCxOTi5AQGBNze3Ly6vISChNza3FxaXKSipAAAACH5BAEAAAAALAAAAAAWABYAAAR4EMhJqwzY6omD+MNGdR8YilNZnug0qGzrqrL1lnV1fyJBVB6VQEMoGH4ADGwQkxQPBwMiKGA2J8VEAnq0tgiKg5aL/C7C2gTjKCM0zowDQ8tuNQznNL7cKzjOUQsNfER+gguIg19+Pm6ChBZFDmWNi5M5FIyYFHQRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+connectno22:connect connect22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBPz+BMTCBERCBAQCBPz+/MTCxOTi5Nze3OTm5Ly6vNza3ISChFxaXKSipAAAACH5BAEAAAAALAAAAAAWABYAAARiEMhJq7046827/+AVCKE0Dh9BAGdaGISAToFGFMcBU+11I4hDYseSZQiKwwKoI/QwBIYiuFDCZseGdIlYEjUNg1SpY6w2N4cUIW6cjwW1lsFwo+MqgtZuw0/ydw5vH34lBhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+connectyes22:connect connect22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBKyirPz+/KymrOTi5KSipMzCzNza3OTe5Ozi7MzGzPTq9OTm5ISChMS+xFxaXNze3GReZIyCjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAWLICCOZGmeaBkAQpoGg7C6JizTQT7CxPwOwFWgYPChYIXkIHC4uQKGAiKRKCyNpxxUUVViVYNFLkqtLo+DAkMMLXQPXwAy2WCTF4544FGtKuwPDhB6DnxuUmyCcXIQhV1uYoMuEAcOBxEKCHg6TzGFCJUSizuejROKOAM9OY2SnUU7nD89NCcDsLUnIQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+devscreen22:dev dev22 22:photo:22 22:R0lGODlhFgAWAIcAAPwCBAQCBPTy9PTu9Ozq7OTi5Nze3OTe5Nza3NzW3NTS1MzOzMzKzMzGzMTCxMTGxOzm7AwGDBQOFBQSFCQeHCwmLCwuLDQyNDw6PERCRFROVEQ+RDQ2NLy+vKSipISChGxqbExKTOzu7OTm5Pz+/GRiZMS+xLy6vBQWFLy2vCwiHFQ+NMSmfNSyhIxmTDwuLJx+bLS2tCwmHMyyhMyqfPTqpPzyvLSWbLSWfPzitIx+ZDw2PAwKDCQiJGxWRPTmrPTerMyuhPzqtPz63PTWnPz6zNy+nIRiVDQuLKyWbOTanPz21NS2jNS6lDQqJHRaTPzmrPTSnPzyxOTClPz2xNSuhPTqxPzuvOzSpAQGDOTKnMy2jOzSrPTu1NzKnOzOnBwWHJRuXLSWdPTatPzqvNzClCwmJOzSnOTOnPTuxOzKlOzerOzarOzitJR6ZNTO1IxmXPTWrNSyjPzOjPTSpLSehHRqZOzirOTCjPS+fPzGhOy6bOzKhGROPMy2lPz+1PzmtKRyRHRiNNTCdPz+zNzCjEQ2NKySdDQmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAj/AAEIHEiwoMGBARIqXMhQIUIBAwYQIFCggIEDCBIoULBgAYMGDgIIDEBAwMSKBRBk3NjxAciQIwdACBBBwgQKFSxcwJBBwwYMHBx0EAmA5EwPH0CEsCChoYgOQ0cSGCHhA4kSS5syJGDiBNEAFVGUKKEBAwWFFM6SNJHi64gDFEKE4FBBggoKK1i0cPECxokYXw0gsECYggQZM2jAqGHjBo4cOtqOxLhDAg8ePXz8ABJEyBAWRIoYOfJipEoMCZEkuaFkSAslS5jUGJKkSRAnRREo0JDwCZQoTKQAmUKlihQrVa5gKZ1lI+oAK7QM2cJlSZMuU4Z4+TJEx0iNOwKAggkjZkyOFmS8kClzpcUQLRRGbjRD4MgZNEzSqKG+ZgobI2248dUbDDDwABzcxSEHEFpgEcUcdMRRhx1fFejAAx0cgcYdSxiBRx566LEHH0d8QFRRNC3Uhx985CHEH0MAEkhCBxWkgiCDFEFIEYUYUmONMhyCRxVH/PgjBYioYJAdAQEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editcopy22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFPz+/DQyNISChDw6PMzKzMTGxERGRIyKjFxaXMTCvKSmpHR2dPz6/Pz29PTq3MS2rPz69MTCxFxWVHx6dJyWjNzSzPz27Pzy7Pzu5PTm3NTKvIR+fJyGfHxuZHxqXNTCtPTq5PTi1PTezNS+rExOTFRORMyylPTaxOzWxOzSvNze3NTOxMy2nMyulMyqjAQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbYQIBwSCwahYGkUnk0BgTQ6IAQaBKfUWhBYKhaAU+CgXAQIAyChLeJzSIQhcH6GFaM0QtGY5kstqEODw8QEQELAhJTc08KBBMEFBUWDRcBE1pca20SGBkaEBscAY5maFRIAgoLHRQRHh8gIQFlZnByqA8ZGSIQIyQjJQEmYgJ5p2ACrK4gJx4gKIZZAgdeAQ4ZI9kjKSor0AwEjeAs1S0cHAslLi4vMDDRWeRIfEsxMeET4ATyVoYLC5fizXEiAR84BeMG+pEm8EsAFhAjSlR4hR6fLxiF0AkCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+editcut22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBAwCBPz+/OTi5JyanOzq7DQyNGxqbAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARbEMhJq704gxBE0Bf3cZo4kRJqBQNRfBucyudgvJS6VaxLzyMa6/bLiWA9HOg4VIIkL5vzuRkcpkvRIIAorphJLzBW84WEuRZWp6uaT7J2Sh1Hit3OY/ZO7WvsEQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editdelete22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIYAAASC/FRSVExKTERCRDw6PDQyNCwuLBweHBwaHAwODAwKDAQCBExOTNze3NTW1MTGxLS2tJyanPz+/Ozu7BQSFCwqLDw+POTi5PTu7MzKxIR+fCQmJPz6/Oze1NTGvPz69Pzy7Pz29LyyrPy+vPyupPTm1BQWFIQCBPwCBMS6rPzSzNTOxPTi1NS+rPTezNzOxPTizOzWxMy2pOzaxMy2nPTaxOzOtMyynOzSvMyqjPx+fOzGpMSihPTq3OzKrOTCpNzKxNTCtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf8gACCAQIDBAUGBwgJCgsLgpCRAAwNlZYODxALEY+SkAMNEqKjEw0UD5yegqCjrRMVEqidkgWhraMWF7GptLa3EgEWFRSOnhW+vxgZEBqzkBvItxwdHryRCNGjHyAhHSLOgtgSI60c2yQjJd+eJqEnKK0hJCgnJSngAO0SF+8qEvL0VrBogW+BLX4oVKgIyMIFQU8KfDV4R+8FDBcxZBREthAFiRIsOsygsVEUh4Un3pGoUcPGjZInK65QicPlxg8oX5RwqNJGjo0hdJwQ6EIkjRM6dvDYCKIHSBc1Ztjw4eOH0oIrsgIJEqSFDBo0cuTgsdSTo7No0xYTZCcQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+edit22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBISGhISChHx+fHx6fHR2dGxqbGxubGRmZGRiZFxeXFxaXFRSVIxSLPyuXMzKzMzKxMTCtExOTPzqrPz+/NTS1MS+tOSaVPyWNPz6/IxeNPzavPyKBNTW1PyCBPyGBJxmNPzOpLx6PNRqBMSCRNySTPyCDPSGBMxiBKROBHRydPSylOyydMxmBJxKBAwODPS2lPTq3OyabJxGBPTy5PTGrOyOXPR+DPz69PzmzPzevNxuPORqLMReFPzy7MyCXKxiNIRKHBQWFNTOxPzixJRaPFxONHRqVPz27PTy7PzStCwqJDQyLJSGdIx6ZPz29PTu5HRmTLSKbMSGZHROPFxKPJSKfJyShKyehMyuhDQmHEQuJJyOfLSijMSynMS6pLSefDQyNHx2bKSahLyqhLymhOzi1FRGNIR+bNzKtOTOtOTKrOTKpLyedAQCBFRWVPTq5NzOvLyunLSmlNTCrOTOrNzGrLyidMS+rLyynKyijLymjLyqjAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gAAAAQECAwQFBQYHBggJCgsLDAwADQ6CAQ8QD5ydEJ+gERKWE4ICDxSpqhWqqhYNFxMYphCtqaytGRoXGxgcggSoth25u70eH8APFR0VzMzNziAXIRjIvwAFwq3EqSLUGB/iI4LathS4JCXVJh8nKCmCKrXDFCss1eIfLS4v8ssdmgWsAGNDDBnt3s3wJ+jAtlUhaNSwccNEi4WCBBl4SAHHihw6ZOzg0QNjRgAG6KXK4CNEjBU/gDQI8kLISQAIADobAoMIzCINjLw4YvNkAno4kCRRUuNHESNLmDRxUjSjAlRPfECJImUKlSpMrFzBIqWqoKtJaWSJomULAy5XXrp4+QKGYcYFoCBEWRImi5gmY7CQyVLGriAGD2jEMHMmCxc0Xb6kUbOGTRs3N988gLM4jpw5Y+iwqcOGjZ07mE8yiGABz5c8c/Ts4cOnDJkybS7fdMO7t+/fvDMaCAQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editpaste22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQWFDw6FHRuFGRaBFxSBAQCBAQKBCQiBIx6HPz6/NTOfKyiXDQuFOTm5Pz+/Ozu7PTq5Pz63PTyxNTOjKSeRExGLMTGxMzKzNTS1NTW1Dw2NKSmpKyqrKSipJyanNzWlLy6ZLSuVIx6FISChIyKhJSSlCQiJLS2tDw6NDQyNCQiFCQmHBQSDGRiZHRydGxubHx6dGxqbFxeXGRmZFxaXCwuLOzq7KyurHx+fDwmFEQuFCweFCQWDBQODBwaHBweHKSinJSWlOTi5JyepHR2dDw6PBQSFNze3ERGRIyKjIyOjISGhPz29Pzy7MS2rMzOzFRWVHx2dHxybDQiFPz27Pzu5PTq3PTm1NTCtJyGdHxuZHxqXPzq3PTaxNS6pFxWVFRKRNS2nPTi1PTStNSulNzOxNSynMymhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCgwABAgMEBYSLggaOjgcICQoLDA2Pj4MGDg8QEZ4FDxITFBUWFxcYGRobjQ8cHR4fCQ8gCyEiFSMWJCUkJieNEB4dKB4pKissK8wrLS4vMDHBAAYQHx8dFx0fJDIzNDU0M+IyHzaNNyg43Ng5Ojs7Ojw9Pj9AMkCNDiZB/h9CSOx4QLCgihItqBkYgqIDESElitAYWJCgkQcXjjRCgi1Ihw4BB5LAQOLCgyQYHihpUU3DBw5ElpAgAYNixSRJjKjQaECDCRPZPDB5IbIGSQwKLnh4wbInLA4kmJB4oaPiAwVNnER40hRK1BIAaVatUZJEFCkmpmjgCeWDCalFe4q4oFKwSRUrEa5gycLzwq8lUnPQ4PEgSpYcUZ5o2cIlS1O/JHLEDdfjQZMIVrpgweLFy5e+M6WSmBGlxYMYYBRzCaOFi5imHWBIfOEiShLTVjaP6eyFTBmN1TA5OvLDjJksWb58OVMGDRqWjAYdmU79SIvpjqJr104nEAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editshred22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBFRSVExKTERCRDw6PDQyNCwuLBweHBwaHAwODAwKDAQCBExOTNze3NTW1MTGxLS2tJyanOze1Pz+/Ozu7BQSFCwqLDw+POTi5MzKxPTu7LyyrIR+fCQmJPz6/Pz69Pzy7Pz29OzaxPTu5PTq3PTm3My6pPzu5PTq5NS+rPTm1PTi1PTezOzWxPz27MyynOzSvMyulOzOtOzKrMymhOzGpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbpQIAwIBgMCAXDAZFQLBbCqJTRqFobjgdkEYFKowPJZEyeUBqVR/crHDTKZYplovZKCW84+YKZZNZSBXl6EwEEBhVPXxZihGMaGRscdkIdg4QeEnVfCH2OHyAhIhuUAAiXZSEhIyQlJqWnjiEnKCWupRWoYyEgJK0SKaUKjam0JCorLMFfC6iqx8giLa/MGAsT1wsuCyULKwssC9RSzdkfCyALKuALLQsvpeXYIQso3gsiCzALMfENC+dGcMNHUAY/f+jq3ctncMYCGggFrsvHcEGNh/EyPFmg8cmrJxAVkVO0EUDJklHoBAEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+edittrash22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBERGRExOTDQyNISChBQSFCQiJCwuLPT29Nze3GxqbDw6PGxubHR2dJyanLSytJSWlJSSlOzq7Pz6/Nza3Ly6vFRWVBQWFIyKjMTCxHx6fIyOjLS2tOTi5PTy9OTm5Hx+fNTW1KyurKSmpJyenExKTMzKzKSipFxeXCwqLMzOzKyqrMTGxLy+vHRydBwaHNTS1DQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAb8QIBwSCwaj8KAMoA8LgUDQsFwQByay4RiwWg4GA9IRGk0SCYJSsUCsVwwGQ1EsmESD5xOp+L5gDwhBRIZDhcDdkMGDgEiIxAkJQ8Ok5MmAohDAQ1xJxUlKCUlEg0pKpiZJRoLCxmtCw1eURhOcR4rbQ8cGRwLAwgGtBYTDywtGRKjvQTARgEZLhMcKC0OrQMvAirMRc7CHCTU1g2+20TO0NIn1RwDCya/wdHT1Rnt5LToKOq79trx0tR02YPX7Jm8fRxMOIhSLhOJE/LCJSTlr5kFEBQsWDiR4UGGBgsuHDg1BEYAfTE6oEBR4AIBAiS5yWBAAAGBAyaPGAgCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+fileclose22:file file22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBERGRERCRDw6PCwqLExOTFRWVHRydGxqbGRiZCQiJISChIyKjHx6fDQyNBwaHJSWlKSipBQWFJyanPz+/JSSlCQmJAwKDCwuLBweHBQSFGxubExKTISGhDQ2NFxeXFRSVDw+PAwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbZQIBwSCwaj8jkMSAYDAgEJbFgOBwQCUOAoJAaFgvGonHIBhyP5BcSgUAYDWxggD4WFmx3e3HQngkSRgYMEBMUFG4MCId0BGlEAQeEhocVDYcUdBYKF0QCB3gRlJgUAQEYBBkaRAMbDZMMpAYcT46rQwMJrgsdC6QcfwoPnUMOBgkIV6SHHg6bw0QEAQYfBpggBZjPGsRD0gEchxwCIR6HChnQRQ8DIU4DTR4Em+ncRw8O+fmoXPXdRg+gQLFgIYM/KRIkoDP4QMKFf0o0aBAh4qGUixgzCrETBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+filefind22:file file22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQSFJyanLS6vLzCxISChNTe3OTu9Oz6/Nzy9Nzy/NTy/OT2/Nzi5Mzu9Lzq9KTe7LTq9PT+/Pz+/Nz2/Mzu/Kzm9Jza5HzK1LTi9PTu9IzW5ITO3FxaXNT2/KTi7Iza7GzC1LzW3FRSVMzO1MTq7HTS3Fy6zFS2vKzm7Lze5MTGzHzS5FTG1Ey2xEyyvJze7JzW3ITa5FTK3EymrGS+zFxWXKymrMzi7ESirEyqvLSyrKze7MzOzMTCxKSepAz+/NzW3MzKzBwWHLzS3ERCRAzi3KyurNze3MzGzLy2vLSutCQiJAyytHRydOTe5MTGxLy6tLyqpKyelJSCdOze3NS+tLyupLSmnKSOhCwuLPzy9Pzu7Oze1OzazOTOvMyihOTi5PTm3Pzi1PTazPTWxOzOtNSunDQyNPzy7Pzu5OzKrNzSzNzGvNS6rMyynMymjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCgwGFhYOIiYQBAgMEAwKHiokBBQYHCAkKCwwFAZOEBQ0IDAsODxARCZ6gAAEGEhMSFBUWFxgZCJ+TjBoMEpkRERscGBGRih0BBAgeFBQOER8gISEfIruIIwEkCCUVwhcgJicoKSrZg9srCRkRGdMsLS4vMNiK2wIKMRsbMiwzXtCocSydIBs3AuCIwIFDiBMucugAoWvSiB2VNPDg0ELHwA0MkCXr4aNSggg8NoDIQOFHgBtAkgURMiDAEAFEVBCJFKCIkSMGOyDRkETJEkOFmABoUsRJQkQdnkzQACWKlBtTplBR6qopxkFRJ0ytYuWKFCxZtBBq+hRA2AlbRrh08fLlCxi1a51g+dQhDFwuYsaQKWPmDBpKXgNETaNGjJgyhNfcVdTTiWI2XpK0cePmzRk4YA5T5otGixY0qFOXbgXAQCAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filenew22:file file22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBExOTERCRDw6PCwuLBwaHAwODAQCBOze1NTW1OTi5Nze3MTGxLS2tJyanPz+/Ozu7OTi3BQSFCwqLDw+PDQyNFRSVPTu7MzKxLyyrIR+fCQmJPz6/NTOxPz69Pzy7PTu5Pz29Pzu5PTq5PTm1My6pBQWFPTq3PTm3NS+rAwKDPTi1PTezOzWxMy2pPz27PTazOzSvMyynOzaxOzOtPTaxOzKrMyqjOzGpMymhPTizOTCpNzSzNTGvMymjMSihCH5BAEAAAAALAAAAAAWABYAAAboQIBwSCwaiYGAYEAgFAqGg/Q4DCASCsTiymgcHAcqQLB4mM+QiIQBppLPcMjkwQ4bB2X4maKgt4sVCHpnFhQTElNFE3mDDxcYGRp2RBuMgxwIHX9EBZZwHh8gCBmTQ52NISEiIyQlpUImng8hHyInKAgprwAqgnC0IKwrLLpGB4wctLYkwy0uuwd9Z8AnJywsLcVFx2YcL7UnJCwwLTEy0GXJoSgrCCwzNDTnxgjeH9UrKzXwNDY36LRGhEOwLx4NHDmgJbh3QoeOgv127EhojEeHDj16pEhRQoZHHzl+QJNCsqTJSXaCAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fileopen22:file file22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBAQCBCQWDCwaDDwmFPSubPzGhPzCfPy2dOSmZPzKlPzSnPzOlPzKjBQODPzChPzWnPy2bPSmXPyuZOyeXIRSLEQuFEwyHEQqFDQiFCweDKRuPFRSTPT29PTy9Ozq7OTi3Nze3NTW1MzOzMTGxMTCxLy6tLSytKyurDQyNMzKxOTm5OTi5Nza1NTS1MTCvLS2tLSyrKSmpJyenJSWlIyKjHx+fFxeXBwaHKxuPMzKzLy6vIyOjHx6fDw6NPy6dGxubLy+vISChCQmJNza3KyqrBQSFLR2RKSinJyanGxqZAwGBJSSlCwqLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeDAYqKiIeLj4wBjQCMhY+NkoiLk5qbhQIDoJyGBAUGBwgEo4MECQoLDA2pDrS1tKQPEAwHERITE77AvxKqhAQNDA8UFRYXFs8YBAQZGqGPxw0RGxwdHR4eHyAhIiMkJSYnKCgpBAYPEhcqHyssLS4kLzAxMjM0NTY3cBA4UCAHBw8gVnhgEcKFjhc7UPDj0cMHAAI/KFgY4YLFio/jRpTYsW8GDyCSCEQw2DChOHIqgsCQSEPIEEEEJFhAoUNECCJEyOk4d6KIyRtGcB7hIJKjixEjHu4oimSGEIs4d8IIUoKECnNB0ElMwkNJJgBLlJBAcQKGiR07KGAURVGViY0mhIwwSTKjr99+THjUoIg0r48hTRIrRtxkiOMhDgrZCQQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+fileprint22:file file22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBFxaXDQyNFxSTPTizOzi1FxORDw2NExKLPTi1Pzy9Pz6/FRWVPz29Pz2/PTy7PTu9OzezPzu5OzavAQCBPzy7PTm3OzazOzKrPTu5FxSRERCRGReXPTq5Pzu7ExGTMS+xKSmpOTKpPTq3JSCDNzSfHRydLyadOzCjOzOtOzSvLyyTMTCxKSipGRiZFROLPz+/KyurJyenJyWnGxmbLSabOzClOzm7LSutJSWlJSSlJyanGxqbNze3OTm5IyGjNTO1Nza3NzW3OTe5IyKjHx6fMzGzMTGxMzOzNTW1IR+hISGhKymrLy6vLSytERGRGxubKyqrLy2vLS2tDQ2NEQ+RASKBAT+BFxeXHRudAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4QBAgOEiYqEAgQFBgcGi5MICQoLmAQDh5OEDA2YCw4ODxARApKUCaGYEAsSCRMUnQysCwoVEhYXGLOLCBCgDqK5GQUXGooCAhscBB0euBUZEAUJvQgIgx8gIR8iCSPiHuIFEREDJCXaANwhJhsnKCnWERcRKiopFCvsBywhQrRwQWGAPAz5EhpQ9wIABRgKYsiYMTEEDQocatiwkUIEP18fbkCAAcMBjhwzdOyQwYNCgBMfKJSgMItBjxs+btwgCSGGjhw/ZoRgQKGZCRMUPgABEgSIkCE3SZok8qNqkR85NtDUEcPIkaVAkCR5SrJBDCVKlmzQ6pCCiRlMTJo4YUH3K5AeMBYYWctW0BOaUH60cBJFypQmII6wyEpFQBVFMSm4UAI3hJUrOGh8oOJrklYKWIromJGDR99Ogz5j4ZGlM+pEnwmBCwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filesave22:file file22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBGxqbAQCBLy+vERCRExKTHRydIyKjMTCxFxaXGRiZFRSVFRWVPz6/Nze3Nzm5Pz+/JyanDw+PExOTHR2dMTGxBQWFLSytHx+fISChOzy9Ly6vAQGBJSWlMzKzAwODJSSlHx6fIyOjOTi5DQ2NISGhGxubCwuLOzq7ERGRFxeXNTW1CwqLPT29Dw6PGRmZKSmpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAb/QIBQGBAMj8ikUDAgFAzKKCBwQCQUCcICKh0SEAhGw5EIZAmBrgCxeDQgcDJWyz0GIggJfL+XGwQJRxNgC3yGDwwUFUZDFhdthnwMGAZNQwEZFwQakXANBBQbHIIdERIBnRAOiR4ERx8gsSEMBBmGCyEGG3YGBwcgIr8UCwQHECOgG4xCtRkEJAvBJRklJgkSFBQeJ68hJiEoESkFKiEZIbkGARsLlwEGExENGhorGSkpFAYm66NDLAECpGiBYsUIFA8wLHBBQMWLVkdUCFCwaYVFBOymkVCgYEMgOykEpICBccMBAhhELFigTEqAAgIIwCiQ4eRKDyS6EAlJIAI0EpaudF4iIKDAAn9CkRT5eMROEAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+foldernew22:folder folder22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBNzaTPT2FISCBCQaDPz+BExKBDwmFPSubPzChPzCfPy2dPz6BMzOTAQCBOSmZPzKlPzSnPzOlPzKjBQODPz+rPz+3PzWnPyuZPSmXNyaXPTyhISCLIRSLEQuFEwyHPy2bKRuPFRSTPT29PTy9Ozq7Pz+xJyanDQyNPzGhMzKzOTi3Nza3OTiVBQWFDwqFKxuPOTi5JSSjISChHR2dGRmZFxeXPS2dNTSzNTS1OTm5KSipLS2tLSytKyqpIyKhGRiZNze3NTW1MTGxMTCvLy6tIyKjCQmJMTCxMzOzMzKxJyenHx6fLR2RLy6vJSSlHx+fDw6NLy+vIyOjAwGBGxqZKyurCwuLBQSFJSWlCwqLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeIiYqLjI2MAY6HAgOHBJYEhJCDBQaDmgcICQoLB4MGDA0OAQUBDg2cAAcPEBESE6QUuQasFRYVq5SxCRcSCggYGRjIGgYbFs8bHIMHExIJGR0eHx7cB83PFhsDDuTUEyAhIiMjJCQluwEmvsAnKAcp1x4qKyUrLLupWrByxcnFiwQIYIggEaNEiRgBZMyYQaNADRs2REA6cCODBxw5+OnQgWMHjx4+BND4MQOIg1gI0gUREkTHiplDhhApEoCGkRlHBL3I8MEHEhz+WAhJogTJySVMfthwIehAExE5jubAkYQpESc8fOx4AiXKNA8+ekhBgqSpzh5hPHcsmVLjpSAqVZBY6VGkiJMiPQKLnTvjCiEsWU4o3nGC8YksMmT8YCmC6iAXKLRc2cz5yGYtR0JjKWQgEAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+mailforward22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIcAAJR6fIxydIxubIRqbIRmZHxeXHRaXHRWVGxSVGROTFxGRFxCRFQ+PEw6PEw2NEQuLPwCBJR2dLyijPTixPz69Pzq3Pzy3Pzu5PTu7Ozi1LyelOzavPz+/DwqLLyafPTmvPz67Pz29Pzy7LSWlPzmzPz6/LyajPTitOTSzMyurPz25PTatPTi3KyOjPzuxAwqVDQiJHxiZPTetKySlPzqvPz27BQ6bAwmTPTexLyinNzGxDRunPzy5KySjCQ+ZNzq9KTO7JzC3Nzq/Ozu/LzW7FSm1BR6vGSWvFyq1AyGxAxytAx6vBSKxAxSjMyujLSunES+5BSi1ByGvAQCBNzCrOTaxNTOvMS6rKyelCx6rBx6tBQKDOTWvPzu1PTq1OzezAQOHAxGdBROhAQGFPzy1NzOvIRqXLyynOzarPz21Jx2XPTWrLSShAw2XKSCbPzuzAwePAQCDPzyzPzqzPTmxOzWtAwGBKyObOTSrNzGrKyGbOzatEQyNKyCZOzWrOTGpNS2lCweHCQaHCQWFBwSFBQODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBhBwgQKFSpY0HgBQwYNGzh0mDhRAAUPHziACEGBpYgRJDiUGEkSwoCQJk6opNASRQoOFETQJDkggwoOJlYApcCihQuVL2DUhBDjhIqjJmRwwDCDhswaNm5MjYHjKggOOU7o0CGTA9gdYknG2KCCBw8VJVL0uBgihAUfP+CSNGCjsI/DiBPbAMJBsEQbQYQM+UG5smUiRYw0jlvYxhEkSYyIHm1EyRLTTH40EZvAyZPOR4pAmU07ipIkUKQ0mQIhAZUqVq5gKXzkSBYtyLVEyd1ki8QFXLp4+WJFQowbYLJnD5NbzJiJCjaQnhnvpYwZM0/OPFlvQ/f3iQvQpBlvQc0aCWy4VKnCpY0Y5yQxgEYXZFjghgwZUOHGCW90YQEccUwloBwGyjAHHXUoSAMZb0xhx1QOoMHDHSfIwSEOdTjhAQ1d4MFbTQ6Q4MYacrzxhhx04JCHHhvQsMeLJPHRBxpr+LHCGnusgccfgKixQR1ATtTBlDDAEIggggxCCCGFbLGFHVFKZEdAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mailget22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQ6bCQ+ZAwePKTC5Ozu/NTi9GSWvAwSJGSu3JS+5CR+rAQOHPTy/AyKzES23AwOHCw+bOTq/BR6xES+5AwmTBw6ZMTW9Ax6tByi1BRGdAw2XAQCBDQuNDRupKzS9FSm1BR2vBym3EzC7CSGxBROhNTW1Pz+/OTm5NTO1AQGFNzW3Ozq7Ozm7IyKjJyWnMzOzNzq9Nze3OTa5Ly6vCQiJGReZISChKyqrAwqVBRWlOTi5MS6xJSWlNza3OTe5Ly2vGxmbKymrIyGjMzGzISGhKSepCQmJDw6PHR2dJSOlPTy9MTGxLy+vLS2tMzKzLSutMTCxLSytKSipJyenKyurJyanCwqLCwmLCwuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4IBhgIBA4SLjAABBAUGBwiNlY4FCQoLDJaNAQ0ODwsQnYwREhMUE5ylFYYRFhcYGRgaGxsDHJUdFR4SHyAhEyIjJCUcuo0cJr0nExihxgwoyYscKSnMHicOIw4lKissLdWDHC4vMCu9McYqMjMyNOUANTY3OPEoOTolDCszdrSgwaMcBxs9TMxYOCMHBx8zfPj48QNINQ5BbMBIIUShDIUoTAhR94PHPEEHbQwZckOGjBQviMxYUWQIDCMmdXE4gqRnkiFETAxR8iKFjJU2evZEdmLJkgJIbqS4wXJIUapImj5FtuSEVyRVV1IVi4RIChhEkLVAgcJHEqVwVJUmYdKkiRNkALMRecKECRG/ff8CEQJFCA5kMKJEoUHDCQ/HkB9LmWKECpUeyKoIMSLEyosen0OD7iH2xg1dV7BkqXGlBpbWNTq4Zn2khu0aAAwEAgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+mail22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBDQyNCwqLCQiJBwaHBQSFAwKDAQCBDw6PPz+/Pz69Pz27PTy7PTy5PTu5PTu3PTu1PTq1PTqzOzmzPzuvOzitPTmvOzivAQGBDw+POzevPz67Pz25Pz23Pzy1PzyzPzqvOTavERCRKSilPz21OTevIR+ZExKTOTi3JyanLS2tPz6/Pz65KyihJSKbMS6lExOTNTW1JSWlJSKZMSylNTOrNTKpFRSVPz29MTCxPTmzKymjIyCdOTWxOzexOTWrBQWFFRWVOzu7MzKxJyalOzatLSulMzKtOzmxOTarFxaXKyqnPTmtIyGdIR+bOzetOzixBweHGRiZOzm3NzWzNzSrOTetGRmZOzizOTexOzm1JSKdGxqbHRydJySdHR2dOzapHx6fKyijOTixCwuLHx+fFxeXERGRDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeIiYqLAQECjwORAwSUBZYFBpkHmwgJCgsMDA0OD6UQERITFBMVFhcVGBkangq1ChsLGxwcHQ0dHR4fICEGIiMSCbS3uLq8wCQUJSYGJygpKhQJKyvLLM4Nwi0uLwUwDQsxMtmeuQveHR8UMzQ1NgU3Dgo41jk6ns0cKOzgYaOHjx9AgjTAUUvIECLZNmxoUISHkSM9KiBJQkCJA4kKEoBQoWJJAiYtmjh5AmVCsCJRpHzckKCCySlUUvBYUqUHDysSPnxIEuXKA5pPRiRwxwFLFhRaIEDYUoEChCcDuECoOWKFuwW7nHkg4WELkw8/BHRRwESpt10dU8SSHevlRxIBX6C0WBE27q8GZMkKbTADjIAwYlb4GLMYShYoPTRo6FGiSJEKPyzMIFMmzJcvXbhwkSLFjJkbQW6cOHNGhAgEAdAsmk27tm0ABgIBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mailreplyall22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIcAAJR6fIxydIxubIRqbIRmZHxeXHRaXHRWVGxSVGROTFxGRFxCRFQ+PEw6PEw2NEQuLPwCBLyejPTixPz29PTu3Pzu5Pzy7Ozi1LyelPTavPz+/DwqLPz67PTetPz69ERCRLSWlPTmzPz6/OzexLyajPzqvDw+PDQ2NMyurDQiJPz23PTatJyenAQCBPTevPz25LSajOzq7HxiZPTexPz65JyanBQ6bKSmpBwuTOTi5OzaxBRCdHySvGRiZHx6fBQSFERGRNzq9IyOjHx+fGxqbPzu3BwaHFSq3Aw6XAxKfPzy3Gy63ByWzJzO7Mzi9OzavBRytAx6vCSazGRKTPzy1AQKHBRGdBRyrDy63ES+3Cym1CR6rBwWVAQSLAx+xCyCtBRmnPzuzAQWLAwePPzyzKSCbAQOJByGvOTWvPTmxBQODFQ6PPTWrPzqzOzatAwGBKyObLSWfPTivKyCZEQyNKyGZOzWrOzWtOTSrOTGpNS2lJx2XDQmJCweHCQaHCQWFBwSFBQKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBgggoQJFCpkzGjhAoYMGjZMpMghQgcNFjh4mODhA4gQGkSIHAmBwAgNJEpo8KDSxAkUGjhMSEGz5gUVIiKs2PmBRQudHiwQpUnAxYsXImB0aBqjBcuoU0fKmPGChgUNH2qIqGHjg9u3bicWIFs2rYgbNnDkyGFhb8cccQ3ouJqWQo0dPFr0WMy4h48LFj4gsKriB5AeNngEaSGks+chPnwQOXFAh4oXRYxk9nAEyY7XO2wksWHDx5ATCDIoUXEBsYclTJo4cWJhuIjhSXacSPBEiZLMQY4wgRKluvXqUpyIsDElAxUqVaxcwcGCPQuWLOixaNHCZAsXBU+oqKDSxQqULF6ifNmyn/8VMOtxwcAK36kQRhdJQIFFEmKM4eCDYGyhhYAEkqFEGSuYYcUZLaDxXRpqSNRCEu6twYaFZXTQhgRd2NCCG9918AYELTjoXgNuKAFHB2RQEUYHVbQQRwlUpPHGGFwkyQUEDsgxx4lh9BhCBy2U8UQJcrSg5JIQ0FEHG3bc0QGYK+CRhx57PEGlkhM9sAEffKTQhx9+/AEIIIGoEUgLLRRFR0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailreply22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIcAAJR6fIxydIxubIRqbIRmZHxeXHRaXHRWVGxSVGROTFxGRFxCRFQ+PEw6PEw2NEQuLPwCBMSihPTixPz69PTq5Pzy1Pzu5PTq1Pzy7Pzu7Ozi1LyelPTavPz+/DwqLLSajPTetPz27LSWlPzmzPz6/PTexPz67Pz29OTSzMyurPz25LyajBRCdPzuvDQmJOzexPTevOzq5BQ6bBwuTDQiJHxiZPz23Pz65LyinPzmvBxCbHySvAQCBOTi3OTq9CweHOzaxFSq3Aw6XGy63ByWzJzO7Mzi9OzavNzq9BRytAx6vBR6tPzy3AwOHDy63Ax+xCSazCym1CR6rBwWVOzizAQSLES+3CyCtBRyrBRmnGRKTPzu1MzGtAxKfAQWLAwePPTizMy6nByGvNzWxOzWrNzOtBQKDJR2ZNS2lPTmvBQODPTatKSCbOTaxLyqlAQKHFQ6PPzyzPzqzPTu1PTivOzWtKyObPzuzOTOtLSWfPzqvAwGBKyCZPTWrPTmxNzKrEQyNOzatOTGpJx2XCQaHCQWFBwSFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBgggoQJFCpYuIDBQgYNGzh08DCR4oQPIDqEmDBhJQYRIzqQIFkSAoESJCKkDGFiwgkUKTpMwECz5IASKjqsSMlSA4sWQjG4qGnzhYoQSmF0iCFjBgmWGWhQrVHCxg2sOHLo2MGjB0sLYmsWQHq1p4wdPtqemGDhB1UDQFSouKHi7oQgQmSwUMyYxcQDZQWz2EFiCJEiRoyQyLzZyGIIB47YKLwDSRAiSZSoXq1kCRHNLBK8YGKjCYskTp4ogeKkt+8oUaBImZKAAxMmVKrctqL7ihTnz7FkAT5FC4cKFbZwadIFdxcvX8KLss8iJcoUBUcq2KgAJoxyMTy4jCFTxoxEHl2GLyCDncmWM2hUIQMPY2CXhhoTfTEcA2tgVwEba7Thxhs88FdBD/ZB8MUUHMJBRhw2sAGCHBKU4UaFc1RAhxnhcdhhHUzYAUIcFdxRAh4R5KGHinu4OIVEDqTBRx81xhGHHzD8wQYQetDRI4cTAcIHGWT0EQgZa1ApCBqDcBAID1Q94IEHLtBAAyGEFGKIIWqYYQYPYNZkQEAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailsend22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIcAAIR6fIRydHxubHRqbHRmZGxeXGxaXGRWVFxSVFxOTFRGRExCREw+PEQ6PDw2NDwuLPwCBLSijOzixPz69PTq3PTu5PTu3PTu7OTi1KyelOzavPz+/DQqLPz67LSafOzetPz27Pz29KyajPTmzPz6/NzSzLyurCwiJPz25Ozi3JyOjPzuxBRGbAwSHOzexPz23KSSlPzqvBROdISavBxSdAwaLHRiZLSinNTGxMy+vBxGZNzu9BSGrAwWJMSyrKSSjFy61ETO3BRWfPz65PTqzHTK3ByqzBSWxEzW5AQWJOTWxBRCXOTu9BSOvDzO3ByavBRKbOzaxOzizKSWlCQ2TAQCBJza7BRWdNzSxJSCbMzq9BSOtCSKrAwiPOTavPzy3LymlCySrAwmPFRKTPzy1NTGrPzu1JR+bOzatPzyzCy61ByGpOzWtJyCbPTmvPzuzIS+3FymxCSuzBR6nJyCZOTWvKSObMSujOzivAwKDOTSrNzKrJyGbDwyNOzWrMy2lIx2XBwWFBQSFBQODAwGBAQGBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBgggoQJFCpYqMDxAoYMGjZwmEixg4cPGzqA6BBiAggRIzaQGEkSwgAMJCKgnNBhQogSJlKGOFHTpgYUG0TsnJBCxQoSE1i0KErAxYsOJJRuuAAjhkwZM2jUqGnDBQoUHTbciIEjx4YNOmbs4CGjB8kCZlGAALHBx4+YcTcACcJDyFSJBo6iGNIhhQkiG8BOKGLkCBK6SSQisHoWhZIbG5bMYALECI8mTZw8gTL1QJQXZ6VMiUylSpUlVpoYaXLFtm0EGmCjwJLlA2O9MrRsccKlC8kEXr7AdgEmwtkhX2SQ2BIkjBiSYzSQr/nyhUKZLIrJJOcexvlEBV7IvCBjRkmAMzHOaufhxDvJBWiQISAFxUUQQRovJNeEGmu4JxEDbKQhXxsfuFDGGW68IQMcccgxRxUkNRDhC3R8QMQIdZwXQ11JJGFbiB+QYccHaaTxhgt13OFBDGTgkUdRDrhAhx5k2JjGCB/swYcXMXwAYk190OGHHx/4wUaVepTxByAaoPEkSQ5wwMEJZAZipiCDDJIHIYV8OZEdAQEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav1downarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBBQSFAQGBDQyNExKTHx6fGxqbFxeXGRiZFRWVDw+PAwKDJSWlOzu7LSytJyenJSSlISGhISChIyOjFxaXDw6PPz+/MTCxLS2tIyKjKSmpKSipJyanAwODDQ2NHRydERCRFRSVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZzQIBwSCwaj8ikcslsOp/OgHRKlQoCgymRUDAcEIkwYgxWFBYERpHQcDwgEclEQmk8DhWL2kiIXDBwExMNGRoJaUkEEH8bEQ0cGgcWAksEHX8QHBKSHk1sfxMHH5ROBBsOICGkT2wiq1CIULKztLW2t0h2QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav1leftarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAQCBExKTJSSlHx6fAQGBOzu7GxqbJyenPz+/LSytFxaXMTCxGRiZKSmpISGhFxeXISChAwKDFRWVHRydJSWlBQSFERCRIyKjDQ2NIyOjLS2tDw6PBwaHFRSVDw+PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZ5QIBwSCwaj8ikchgQLJGBgfNZDBAKBirRekBMtYGEYsHIgsWNhOO7tCrShDU18Hg/CJAIG0o4wCUQcksTFBUSCRYSEnpUFxgIGQkJGYyNGggbHBaVjR2QCxEeWkITHQ4IH3tPFwEMA2ajAKUgqlQTTbFEE7W5vUgGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav1rightarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNGReZAQCBMTCxGRiZMzGzOTm5LSytPTy9Pz+/CwqLOTi5Ly6vCwmLMzKzJyanJSSlBQWFKymrIyGjCQeJJyWnISChISGhHx2fKyurDw6PAwODHx6fHRydDw2PERCRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZ2QIBwSCwaj8hkMRBQKgOCgRMZIBSk06XhEM0SA4iE4uoVLhCMhqLrdSAekMgYO5VM4BQ521mxIC4UFxBWdEkSERYYFxETGQGFSBKCGBEaGRuQSBwdeZaPXpsQCB6YZQMdEI6ZSgMepKusHh+wrCC0rLdlursGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav1uparrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBFxeXDw+PMTGxHRudPz+/JSSlLSytIyKjHR2dISChIyGjIyOjLSutLy6vKSepJyanISGhJSOlOzm7Ozu7MzGzKyurJyenDQyNGReZKSmpIR+hCwuLCQiJBwaHBQSFAwKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZtQIBwSCwaj8ikcslsOp9QYyAQFQYEAyr0Sihkn1fDAeHVLsOJNELxVaITC0bDUU6GH5AIQ8KYrNtFVxQVFBYWFxgRCREYdUQZGhYEDwgIGxAHCQocCgWOQhmhGR0epR8gqCFTq1Wtrq+wsUt0QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav2downarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBAQGBBwaHDQyNExKTHx6fGxqbFxeXGRiZFRSVDw+PAwKDJSWlOzu7LSytJyenJSSlISGhISChIyOjFRWVDw6PPz+/MTCxLS2tGRmZDQ2NAwODJyanKSmpKSipIyKjHRydBQSFERCRExOTFxaXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAasQIBwSCwah4FkQKBsDpoBIqFgOCASCYRWm1AUFgRGkdBwPCARiWRCaTwOFYvYSIhcMOiJpJGZaDYcR0IEHXceEQ0fICEWIoJDhHcQHxIHgI9SEHeVG46YUh8OISOen1INCqWmUnOYTUxQAU9NUlRWWFtbCiRgrYNlZ2lriG8lYUd1khETE24gCZeCkRgeFBAQIAeNn9OTlXKrBJoYnKrcoaPmpmSpq3S+7u50QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav2leftarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAQCBExKTJSSlHx6fAQGBOzu7GxqbJyenPz+/LSytFxaXMTCxGRiZKSmpISGhFxeXISChAwKDFRWVHRydJSWlBQSFERCRIyKjDQ2NIyOjLS2tDw6PBwaHFRSVDw+PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAavQIBwSCwaj8gkMiBYNpeDZzEQXRIKBmPgmtUSDgipcAsWjxOKBaN7Tq+n6EbCIQ3E5+KtQk6gjwl7CX11D3sPBBARTQGFDYeJT2R8EhB0koKUfgATFBUSCRYSEoqcnqCiikMXGAgZCQkZqautr7FiFxoIGxwWqQC4ury+qh2tCxEexMbIRhMdDggfYs7Q0kcXAQwDbELY2txEziBmmx3jSRNMR+nk4e2b70ry80QGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav2rightarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNFxeXAQCBMTGxOzm7CwqLLy2vPTy9Pz+/Ly6vCQiJLSytLS2tLSutOTi5MzGzKSepIyKjJSOlKSmpMzKzJyanIyOjBwaHIyGjISGhJSSlISChBQSFJyenIR+hGxubDw+PHRydHR2dEQ+RHx6fERCRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa6QIBwSCwaj8hkIIBcJgEBweAYnTYJUmMAa9USClniFtwlGg6IRFhoUKTXwwWj0FB3F46Hwl6UQyISfAB+EROCQgsUFRYSF3yJEIyBaxgWDBkaGRtclQwSHBIbEGEdGx4fGhcOICEDGBsWHBmqIq1CHRIWGRMMIyRTHRy6Er22tyONq8YdJRe0xkIDwr2/QwMfliMmZQADIxasZd4e4UYDIr7c59rc0eVFA+/m0EQD9PDt0flP/P3+BkEAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+nav2uparrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBGReZDQyNMTCxHx6fPz+/JyWnKyurHx2fDw6PJSSlISGhIyKjIyGjISChLy6vJyanOTm5PTy9OTi5MzKzLSytKSepMTGxMzGzLS2tLSutKymrHRydCQiJCwmLBwWHAwODLy2vHx+fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAajQIBwSCwaj8RAAMkUBgSDZdP4JBSi06TAcEAkFNLp07BgLLzY5njRcDzO3zB1C4lEGI83Wj58SiYUFRUWdg0XEXFFAwIYGRoWGxwRZQUFHZdgRAObmx4fHiChISFKpVlKWUdPaalOAlasp1sHG4myZGZ7Yltsbgu1mUhjdRF5egmxfQJ/gYOFdrZDi40iFgiSCw8jBQmYcpydn6Ego6WorUwGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+navback22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VCRGZAxCZGyavExmjHyatOTy9CxihISevPz+/KzO3BRylAw+XAQCBDRWbPz6/FzC3CSuzDyexJzO5Mzq9CxSdAQOFISmxNzu9HTS5BSmxAyexDSuzJTa7Mzu9Kzi7GS21CRmjAQOHHSWtLze7AyWvHzG3BRihAQKFCTO3BS+1AyixBSWvBSOtBSStAQWJBSixDzW5BTC3BSqzBS21CTC1ETW3AQSHEze7BRqlBRmjAQCDBR+pBRefBRSdCH5BAEAAAAALAAAAAAWABYAAAalQIBwSCwaj8ikMqBcMpvHgGAANQYIhWdVGDAcENQtIJBQLBgNx0MQaDuQXcghIplQDhBIxXKJYiAZGhscHR4VHyAhIiNWJBklGhIbJoQnFCcTKIxFKSgbKissJi0mJi4vLiYoMEcXKDEyMzQ1Nje2NisoOEg4KDU5K6g6OwwoKAN9SCOeMmgwz884PEq9PT4NYkPLP9jZQikN3d4AKVrjKePp3gZBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+navdown22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VCRKZDRSbBxCXJTC1Mzi7Nzq9NTm9Bx2nAQCBNzu9JzG3Hy+1HzG3IzO5BRmjPz6/LTe7Dy61AyStCTC1FzC1AyGrETS3ETC1ETa5BRulAyuzBRylAw+XMTe7Gy+3CSqzAyexBTC3DR+nIS21KTW5Nzu/KzO3FzC3Pz+/ByixEze7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaRQIBwSCwaj8ikcnkMBAQDgjPAFAYKhsMBkVBUAYEFo+F4QLzVQEQyoVTOX/XBcsHA0+vMRbNBMwkRDhxuHX5GTlIeHh8gISIjFAEeiVRECiQlDAUmgxQjIhwiJHdFlycoKSIUFCEjGiGkRpcqCxYijxorsUezcxYsuoZJsxLAu0qXB7DCTJfHVQrMX9PU1Uh0QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+navforward22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VAQCBBxCXDR+nIS21Aw+XJTC1Nzu/KzO3Pz+/Nzq9Pz6/MTe7KTW5FzC1Nzu9CRKZMzi7IzK3Lzi7LTe7HzG3Gy+3AyuzAyexFzC3DRSbHy+1Dy61CSqzAySvAyStLze7IzO5AyGrETa5ByixBRmjCTC1ETS3BTC3Bx2nAyWvEze7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaYQIBwSCwaj8hkMqBsBgTN5IAAjRoDBaq1aDggtMuAWDzoJhTgY+CwYLgZDccDwkgXI5IJZVGxXDAZGnR2QxsLHB0PHRgeHyAZDyFfVUQDCyIgIyCPIB+QJCUmlEMBEiInKCQnKSkeKSQeomoqJrUmKiArKSwZsmoCwMEBGCyxo1EGHr3HUQEEvltCBtDRAAbMW0zV29xDBkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+navhome22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBAQCBCQiJNze3ERCROTi5MzGzLy6vDw6PKyqrKyurBQSFGRiZGxqbGRmZISChEQ+RExKTExOTHRydDQyNOTe5FROVLSurCwqLMTCxPT29Pz6/LSutFxeXLyytLSytPz+/JSWlKympPTq7KSipNzW3BwaHHx6fKx2VJRWNHQmBFweDOzq7Ly+vNTW1JxWNLSajPTe1Ny6pKxWJNTS1IyOjJRmbPTi3OzKrNSSXMSGVHQiBHx+fJSSlPzy9IxOVOzWxOSyjNSCPLxeDJyWnIRGTOTGtMxmDLRWBHwqBIxGTLRSDDQuNNSunKxKBGwyNMSafMxqHMReDKRGDPTu9LxuPLxaDJQ+DIR+hGQqNIQyBGQiBNTO1EQKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4QBAYSIiYQCAwQCiokEhwACBQYHBAiQhAiHlQYJCgkEC5uCkp8MDQ4NDwylmwgQlgQRERIEBBOkmxQVBgQWFwUFFxEEDLyJGAUZtQoFGhsFHLYdyoOVHsEf0SAbIAUex8mwlAUhtSIFG+3uIyTWvAIGJMEkJe76GyXbEeWUBJg4USKaBhQpVKzYoIFFiwYUBBJa8MAFCw0vYMSQMWOhBhoTKCQSUKMEiw02buDIoWOHBg0GeIhEFKAHDR8afgAJImSIioYliMws1MPkhiJGchxBkmTDCBo1hg4KQMTiBiUyhBxZ8pNFiR5MEtU0WqSJVidJNDyNKraHC5xPNKBEkTLlJ5WvUgWNvfikyhArV34+7ZEXQAAsB2iUyHLlihYtW0pwOYAFgyJDmDNr7jIIWiAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+navup22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VAQCBHSWtBRmjAQOHISmxNzu9BSmxBRihHyatPz6/Lze7CTO3BSixHTS5BTC3DzW5ByyzPz+/OTy9AyexEze7ByixGyavKzO3FzC3AyWvBS+1BR+pAQKFCRGZExmjCxihBRylCSuzBSWvBS21BSOtBRSdAw+XAxCZDyexDSyzCTC1JzO5JTa7DSuzETW3BRqlAQWJDRWbOT2/Mzq9HzG3JzS5Kzi7BSStGS21CxSdCRmjAQOFAQSHAAAACH5BAEAAAAALAAAAAAWABYAAAaeQIBwSCwaj8ikcqkMCJjHwIBQgBIDhgMiUbUGFAtGw0GFfheHByQi4S6/E8pDUoFYLm5kAEPJaBAVGxIcER0JHlEfICEiIxUkGyUmIgknKIhXASkonCorgSwmKQGcKE9IAi0uLxUwMTJWMzQ1NiYwBLBQHws1N7avXgs4NjkcCblMATU6KhvGyG87PAnUKV1MAj0+2zIFp1bg4eJJdkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+playeject22:play play22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAwKDJSWlFRSVBQSFKymrOzq7HRydERCRPz+/MzGzISGhJyenKSmpGxqbJyWnJSOlKSepLy2vIyOjGRiZPTu9IyGjLSutFxaXExOTHx2fGReZAQCBAQGBBwaHCQiJLSytKyurJSSlFxeXNze3LS2tIyKjFxWXHRudAwGDBQOFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa1QIBwSCwaj8ikcqkMCJjHwIBQgBIDhgMiUbVKFQsGItBdBhpgh4PxIJvRC8cA4oiMy8bvQhJhMAYTFBVOURAWEw0QFxcMERAYCBluVxobDxkVHJocmBwEGgmEQx0dHh0CpKmkH6odVlanBR8FtAIFtiCkSB0LISEiGCIGIxAPDySuRwIOBwrOzwoHJRHJRh0jJgMj2gMnERQUCNVFHQQoCBvo6CkICATjRB0qp7b1K6qv+foyQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+playend22:play play22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNFxeXAQCBMTCxGReZBQSFOzm7AwKDKymrJSSlFRSVCwqLLy6vPTy9OTe5Ozq7CQiJLSytOTi5BwaHPz+/HRydMzKzKSepJSOlKSipJyanIyGjIyKjKyurISGhMzGzJyWnHR2dISChIyOjLSutDw+PERCRHx6fJSWlIR+hJyenGRmZHx2fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa6QIBwSCwaj8ikMBBQKgOCgRMZIBSkxYHWoDVWD9EigpBQLLBERsPxCA8NDUhjgTBGJJNGG02RVBQWdUV3FxgZe0IGfoAGdhoXGxwdiAYef4FGFBoeHB8dGSBRihUhIo1FBhkbIyMkJRYmAwYal4JEBh2RChIWJ1IIGxUZFqdECCgkHR6wWAYpFR2YWSobvL5vFgfDaEMDIivMRBEsD9HcQgMWvecDLB0tZ0btsfJa9vLXU/X6/P3+b0EAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+playpause22:play play22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBAwODMTCxKSmpJSWlFRSVAQGBBwaHLSutOzq7Ly6vCQeJPz+/Hx2fBQWFGxubLSytJSOlBQOFAwKDJSSlJyWnIyOjHRydNze3GRiZAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAWBICCOZGmeaKqubOumQSDEgRjPMSoMRGEcol3vh0IkFAtDDWBEKlGMRKPgEIii0yrqIS1ArADu9KuLNCSOSdCMVp8ohEZFC4DL6SaBpXGh6/l4JX8XZACDhXkYCn1LAoqMUBAZEhBLDJKUSyYBGmhPAJyemiU0NDaloy+qq6ytI8whACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+playstart22:play play22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAQCBExOTAwKDAQGBJSSlHx+fBQSFMTCxKymrFRSVOzu7GxqbLSytLy6vJyanPz+/GReZBwaHHRydKSepKSipGRiZJyWnAwODLSutKSmpISChPTu9ISGhFxaXJSWlIyGjJSOlERCRIyKjDw2PIyOjLy2vOzm7Dw6PLS2tCQmJOTe5GxmbDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa7QIBwSCwaj8ik0hgQLJGBgbMoqBIKU2LAcMgOEQmFYeEFbBmNMgDhYDwWBC0k4pCoJ46IgRIXBioRCRYXamwRGBQIfgaBFhiERhkaenxmCoEbBhyQRYaIGVsdghgem4UWegcEBB8UHhsgIaZGBBgRIpUIIxQhChginEQIIBEklWslFyYnBsFfFCi4WQgpFBwqFxNGKxcsxl4IAS0NZEYCF3vlwgEfUuZV8JEuI2pPAARN9kcE9fr+SwaCAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+playstop22:play play22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBAwKDBQSFBwaHCQmJJSSlISChJSOlJSWlGxqbGRiZNTS1PTy9Pz+/Ozm7OTi5FRSVIyKjOTe5MTCxIR+hExOTHR2dLy6vLSytLy2vHRydFxWXIyGjIyOjPz2/FRWVHx6fExKTMzOzJyanKSmpKyqrKSipAQGBLSutHx2fDw6PAwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa1QIBwSCwaj8ikcslsAgKCAWEQjQ4KgSwyYDAcugZEQqFYYJECA6PhaLcfEEUkgJZAGJB8fkKpWOhHAxcOGBQZGBoaGQgbHIBGAhUOGR0SBxISBh4Xf0iCHxQSlRIIXhsgj0UCIaCXmJgHGyKpRJ+hmB5dHQqOaCENIx0epBIkBhdzngoPGCQlJifQJBvJRygRKRcKGxcXGypys1srEREc5SLnICLiR1koLFVUWfRO9vf4+UwyQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+textblock22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py30Bo5zBWUWzvNzo33GfFl5jVlonlTrr1DbvFi9vjeeNUQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textbold22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIxhI+py+0Powm0VnknjVkH2AEhE45LZ55Wqn6e65TsMc5eYosbksswubJIhsSiccgvAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+textcenter22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py30Bo5zBWUbz3Sh7yIWfFHKjVl4nmFrr1Lpr7LwkjeeIUQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textitalic22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py+0P4wqUSlQvttrkDnyaOHIdeaGRupplAIauVM3xjeeOUQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textleft22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+pyw0Bo5zB2UXz3Sp7yG2fFJajVjonmIor2TJvfL0wjecIXQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textright22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py30Bo5zBWUfz3SZ7yIXdF4kWqZkbCqoMO7kXLC+wVOe6YRQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text22:text text22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBBwaHAwKDBQSFLy+vLS2tJSWlBQWFKyqrFRSVCwqLDQyNNTS1GxqbFxaXJyanIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAVcICCOZGmKQSoMaZsShBsQBdAapHvgaIDUqUPJlRjSbAoT0fRDKgODRbF0PLUYjZO2F2Bst9evNix+dsvDlGKK5jraudQb7qbX6a2HEJ+ycyF+LRE8ZTI+fX5oGCEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textunder22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIvhI+py+0PowmUnhpeVVnb1DkbCI1I2JhX+Z0sOr2cTHpwK7a4rUr+hAnufsTirwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewchoose22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBFRSVExKTDQyNPz69PTq5Pz+/OzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARTEMhJq70466Cl+AMxBVwnFIVRAmQHCIeBrC1L3tQgJ/SaEbeeC1PLBHE2ybFI9A1HzstHEIK6YCmhDTmBybQaHYJn7QC5zKeytIQe1+pKNE6P2yMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewdetailed22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBFRSVExKTDQyNPz+/Pz69PTq5AQCBOzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAQ+EMhJq7046817+MLQUQFRGMc4lQaSAkcMx3QltMmrDrSu/sCgEPgJhIiFk89DaL1qPRnlhsgBebWhdstVESIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewicon22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBFRSVExKTDQyNPz69PTq5AQCBPz+/OzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARWEMhJq7046z2DF0PlBeAVEERhiKhqHgWyUgEsX0KczFOO7JeBYciTCImc5ITIXDKHyqhU9AnRqq9UEVDTvmLbGhin2/qAliOUot5OLc81IO5+2+8WewQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewmag-22:view view22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFJyanKy2tLzCxHyChNTa3Nzq7Nz29Nzy9Mzy9MTu9OTy9Nzi5Oz6/OT29MTi5Kzi7NTy9KTm7JzW3ITO1Lzq7IzW5HzK1LS+vMTq7Jze7ITW3GTCzGS+zLTS1MzOzLzq9Kzm7Jze5ITW5HTS3FS2vLze5EzCzEyyvEyutJTa5NTu9ITa5FTK1ESirLTm7Mzi5FS6xEy2vESerESmtFSutESmrKyqrAz+/Dw+RAzi3ASutHRydAQCBAAAACH5BAEAAAAALAAAAAAWABYAAAbKQIBQGCgWh8jksCgYEAaCozIZKBgOiIRiwSgEpstCw/HYQiKRhBcMCBgQDodkMaFU0t9pQHCIyy0TFxgYEVF6GQ4LCQkaERscHR4RH3lUIAkWCyEiIyQlHiYjEJVIAQQJJ2gjJSUoKSorlHoCLBQcHC0lLikvHjCGejEiHBgeMjM0NRwPpFQFDBHFNjceHAjAYFWoI7cnCVE4OWxtex8QH1EBOjs4zUpGUjw6Pe3j2fP19u/47vrq9P3s/avno2BBf/MCClSob4iBIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewmag22:view view22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFJyanKy2tLzCxHyChNTa3Nzq7Nz29Nzy9Mzy9MTu9OTy9Nzi5Oz6/OT29MTi5Kzi7NTy9KTm7JzW3ITO1Lzq7IzW5HzK1LS+vMTq7Jze7ITW3GTCzGS+zLTS1MzOzLzq9Kzm7Jze5ITW5HTS3FS2vLze5EzCzEyyvEyutJTa5NTu9ITa5FTK1ESirLTm7Mzi5FS6xEy2vESerESmtFSutESmrKyqrAz+/Dw+RAzi3ASutHRydAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbIQIBQGCgWh8jksCgYEAaCozIZKBgOiIRiwSgEpstCw/HYQiKRhBcMCBgQDodkMaFU0t9pQHCIyy0TFxgYEVF6GQ4LCQkaERscHR4RH3lUIAkWCyEiIyQlHiYjEJVIAQQJJ2gjJSUoKSorlHoCLBQcHC0lLikvHjCGejEiHBgeMjM0NRwPpFQFDBHFNjceHAjAYFWoI7cnCVE4OWxtex8QH1EBOjs4zUpGUjw6Pe3j2fP19u/47vrq9P3s/cunr9S8gAIRFhTCLAgAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewmag+22:view view22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFJyanKy2tLzCxHyChNTa3Nzq7Nz29Nzy9Mzy9MTu9OTy9Nzi5Oz6/OT29MTi5Kzi7NTy9KTm7JzW3ITO1Lzq7IzW5HzK1LS+vMTq7Jze7ITW3GTCzGS+zLTS1MzOzLzq9Kzm7Jze5ITW5HTS3FS2vLze5EzCzEyyvEyutJTa5NTu9ITa5FTK1ESirLTm7Mzi5FS6xEy2vESerESmtFSutESmrKyqrAz+/Dw+RAzi3ASutHRydAQCBAAAACH5BAEAAAAALAAAAAAWABYAAAbQQIBQGCgWh8jksCgYEAaCozIZKBgOiIRiwSgEpstCw/HYQiKRhBcMCBgQDodkMaFU0t9pQHCIyy0TFxgYEVF6GQ4LCQkaERscHR4RH3lUIAkWCyEiIyQlHiYjEJVIAQQJJ2gjJSUoKSorlHoCLBQcHC0lLikvHjCGejEiHBgeMjM0NRwPpFQFDBHFNjceHAjAYFWoI7cnCVE4OWxtex8QH1EBOjs4zUpGUjw6Pe3j2fP19u/4zT766vRI+fvHD4CPgwcJ9qg0UB85JA0dDjEQBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewmulticolumn22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBFRSVExKTDQyNPz+/Pz69PTq5AQCBOzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARTEMhJq7046813+MJQfUF4BURhHGO6noSBsEcNoDJtS4KcsJQe4ncZ1HYT47HDbDqfUAnJRJmKLIGCCjjJbmE5wBI3EyOFxKCPS1EiJW52dE6vZyIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewtext22:view view22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIkhI+py+0Po2ShBlOxzbP7n2yaJoLm+ZTcxqHuC6hXzML2HVEFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewtree22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBFRSVExKTDQyNPz+/Pz69Pzu5PTq5OzaxBQOFOzKpFRWVFxWXOzexPTexCH5BAEAAAAALAAAAAAWABYAAARPEMhJq704g6A779kHCORAgNskFMYhakE8FkjyBcoWv+JwJItXaELYCTFHlCSpZKKcoB5jYHpOGgUadLKbIRw3jhEzQDyCSuI4zW673yhDBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
diff --git a/ext/tk/sample/tkextlib/ICONS/tkIcons-sample.kde b/ext/tk/sample/tkextlib/ICONS/tkIcons-sample.kde
new file mode 100644
index 0000000000..51f76a0488
--- /dev/null
+++ b/ext/tk/sample/tkextlib/ICONS/tkIcons-sample.kde
@@ -0,0 +1,658 @@
+1downarrow-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIYhI+py+0PUZi0zmTtypflV0VdRJbm6fgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+1leftarrow-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAP///wAAACH5BAEAAAAALAAAAAAQABAAAAIdhI+pyxqdwoNGTmgvy9px/IEWBWRkKZ2oWrKu4hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+1rightarrow-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIdhI+pyxCtwoNHTmpvy3rxnnwQh1mUI52o6rCu6hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+1uparrow-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIYhI+py+0PWwhxzmetzFpxnnxfRJbmufgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+2downarrow-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIfhI+pq+EPXYpxUckoO3AjbF3dJwahllXe6AFgC8d+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+2leftarrow-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+pyxf5VohmSlsxmpjTzAHeN5ak6UHpqKRi2GpwvH3Q3eT64RcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+2rightarrow-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+pq5HOAjQyVnqfhHue7oAaKH5kiW0AmnLqaHomkj02g+e6XwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+2uparrow-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIghI+pyxfR0HsRzNnuXVqn3mVQZWFRyIDjp65Ga5Ly4hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+abs-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBIQChAQCBBQSFCH5BAEAAAAALAAAAAAQABAAAAIwhI95ocn2GlySTiME1iC+DIKdNWxANl4HaqWr055cy6Bs6dahmJsyXVFFJJ7gyF8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+airbrush-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBPzCxMQCBIQCBPz+/MTCxKSipFxaXDQyNISChAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARUEMhJZxCjanBH3hY2EFJgVt0YcEW7liLxBoVxzPHL2msqUzSeT2c5HBC5jQmROKgAhCgKEVBQo6YAqVQIHBQ93ZbmBWt+nDJRgiYMvmuoThWXT/wRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+attach-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBPz+/AQCBAAAACH5BAEAAAAALAAAAAAQABAAAAI2hAOCxg2h0nJHyEshi9HpxU1GOCLdZoKpQ15nibUoprKp9lh2oucUxsBRXsJh4Hjs/QTMpr8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+back-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRSdBRObCQ2TBxObISevAQCBNzu/BRGZPz6/FzC3Pz+/HTS5ByyzJze7Mzq9ITC3AQWLAyWvBSavFyuxAwaLAwSHBRafBSOrDzW5AyixCS61ETW3CzG1AQeLAweLAxefBSStEze7CSWtCyatBSCnBRWfAwmPBRWdByixAQSHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZiQIBwSCwah4HjUTBQFgkFg3MoKBykU0QhoUAIAuAksbpgNByPxQMSGVsVDYlkIqdUiJYLJqORbDgcHRseRR8gISIaEyMkGCVYRBEmeyAnlgaQkSgpmU4RAZ1OKqFOpFNGfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+blend-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBARCRAQCBASChATCxATCBASCBAAAACH5BAEAAAAALAAAAAAQABAAAANHCLrc/izISauYI5NduvlXMIjEQBSnUYCYxnmsSJrouhqh6J4wLo0mWuqWy5heN58seBrGdEdeMgQsNW0ggXbL7Qog4HDDnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+bookmark_add-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCwqLLSytLy6vERGRFRWVDQyNKSipAQCBMTGxKyurISChJSSlJyanHR2dIyKjPz+xISGhPz+BGxubMTCBHx+fPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVfICACwWieY1CibCCsrBkMb0zchTEcNYsIiYHiwIOdEAvigdFQGE0Ix4NBbSAgsWjk+jBIAlcUYrJASChnSXZSoUDelKfoKpFALJA61ueGI2IAZmhogGFmCGGAgXsifiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+bookmark_folder-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBExKTBQWFOTi5OTm5CwqLPz+/PTy9Ozu7FRSVNza3PT29KSmpAQ6XARqnNTS1JyenGRiZJTa9Mzq9JzO5MTGxIyOjKSipFxeXMzOzDw+PDy65FTC7HS2zMzm7MzKzKSenASq5Bx+rBSGrFyqzLSytDw6NAR+zBRejBxqnLSyrERCRIyqvDRujKyurMTCvOzq7AQ2VDQ2NNze3KyqrGxqbLS2tLy6vCwuLDw6PAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAawQIAQEBAMh4GjcEAoCAQGYSCpDBwQiQJBEVhQj1YGo1DoNqZTx8PhODAWZUik0ZAkHRNKZe0IWC4RGBkBGhsOHB0eFR97bBdcICEbAA4iIyQlioxrGhEmJ5QoKSoqJCOZiw4rGixEYi0uo6WYDi8wkwAsCTFksLIuMi+tADMLNAsLEBAgLSMpMjW4RCc2MCAgFjA3MA4R0kgzGS84Ny8vDqBKSDkKETUOOurqAQagfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+bookmark-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCwqLLSytLy+vERGRFRWVDQ2NKSmpAQCBKyurMTGxISChJyanHR2dIyKjGxubHRydGRmZIyOjFxeXHx6fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVbICACwWieY1CibCCsrBkMb0zchSEcNYskCtqBBzshFkOGQFk0IRqOxqPBODRHCMhCQKteRc9FI/KQWGOIyFYgkDC+gPR4snCcfRGKOIKIgSMQE31+f4OEYCZ+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+bookmark_toolbar-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCwqLLSytLy6vERGRFRWVDQ2NKSipAQCBKyqrMTCxKyurISGhJSSlJyanHR2dIyKjGxubIyOjISChHx+fPz+/MTGxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVpICACwWieY1CibCCsrBkMb0zchTEcNYskCsXiwIOdEAzioeFIGE2IB6RBbT5HiAhEIpk6Y9kJBMJoHK6iLIU8kZxFlXhlIp/XJ4BKUIGoWIJ9f3x5e32FeoB5goGAfokTCJEIFJKTlX4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+bottom-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRObCRKZBxCXAwyTKTK3Ozy/NTm9GSivAQWHNzu/FzC3IzO5CySrAQOHAyuzETS3CSWtAyOtETa5Aw2VLze7ByWtBy61BSavAxWdBRCXAwqPAQCBDR+nKTe7FS+1Eze7ByixBRmjPz+/AyexAyixAQKFBRqjAQGDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZhQIBwSCwaj0hAYCkYEJLKguGASEADigWj4bgaHpBINykwSCYRa5HCFFQsF0xGo9lwhpSOwfORYC4gISJ3RAQdIyQYJSAlImNrh4uNJkl5CoKUUBQnjlB4KFAcoqOknkh+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+brace-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBIQChAQCBBQSFCH5BAEAAAAALAAAAAAQABAAAAI2hI9pEXq8mnsNzggsEMJwbHGimFXS4HUfpKUIq3QJ036vuakyWvbjCJLYbL2WgyW5WIw3g78AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+brackets-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBIQChAQCBBQSFCH5BAEAAAAALAAAAAAQABAAAAIzhI8JwXocllMxTlSREGY/2W2iJ1nAEAJklpCfeXAJG8sY6JGowY7jW0sBL0NiqTGBAPwFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+charset-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAInhI+pqxH8kFsvsgtm1vvEaoBZSH6j5FSaRY4me4pyq1ochuf6fvgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+colorize-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIQAAPz+BAQCBPz+/MTCxISC/AQChMTC/ERCBPyqXMRaBATCxASChPzerKSipMT+/MQCBATCBASCBARCRISChMT+xDQyNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVnICAGgWieZyCQKGuqZPkGgwyv60gONRDvNlqt9Pv5BgRCYVj8IQ3L4qE4KFiZzRiP90MgEj+FYtGLIRiJQaMxUDjIxFoi8YBAIo3FQjIJ7iAUERNqDTI6PBGJfT0oFVpsMSgzkSh+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+colorpicker-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBARCBDQyNMT+xATCBASCBPz+/FxaXISChAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAQ/EMhJZRCjahBIMdlmeV8gBl3xCabWGarBihwBz+eB2O0WHIFEp1f5BU1EilFI4wCZtGWy+JwWj00OynrNTvwRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+completion-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/Ly+vHx+fAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM/CLrcGjBKCYK4+NoMs+jWIBIdZ50QuWGgMASD+oGnO5beR+x7UE3AyGKV0wxnpeSxyDoGN74Hszl8QhxYhj8BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+configure-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBISChGRmZMTCxKSipLS2tHx6fPz+/OTm5FxaXOzu7DQyNMzOzAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAReEMhAq7wYBDECKVSGBcbRfcEYauSZXgFCrEEXgDCSeIEyzKSXZoBYVCoJVIqBGByKu0Cy8QHxmgNngWCkGgqsGWFseu6oMApoXHAWhWnKrv0UqeYDe0YO10/6fhJ+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+connect_creating-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBPz+BMTCBISCBAQCBPz+/MTCxMTGxISChFxaXMzGzKSipAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMhJZbihUiz60FPnfaA0iBpBVGdHEYWxToEoSHBRHHM9AgSEQRcj+AYkYAJxIPKQFUJiOdTJQFIDU6dYzKKFhTCM+E5g4mXaDAyrlogEG+DGTecA7wsP8EcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+connect_established-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/KSipDQyNMTCxMTGxISChFxaXMzGzAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMhJZxCjgsAtDtUlCOA1gJQ4kl/IDatAoF7xxkS6GgEBr6jAobCyBX42SQBxMOx6A8MhiGASR8YDgrYsNEeJ0zaEGZY7uoH2oB6nOUwtbdLaVOeTUwo/8UcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+connect_no-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBPz+BMTCBAQCBERCBPz+/MTCxMTGxISChFxaXMzGzKSipAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARPEMhJq704axBEHoPUEdhQGMNYFuwxkKInDYjBniEnwMCQIIebSzXx/WwsFK+YMABZikWuYlrUCtZpEYv4WRPaHhb064YB41kCfJFSQBh/BAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+contents2-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBDyKhDSChGSinFSWlEySjCx+fHSqrGSipESOjCR6dKTGxISytIy6vFSalBxydAQeHHyurAxubARmZCR+fBx2dDyKjPz+/MzKzLTS1IyOjAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVkICCOZGmKQXCWqTCoa0oUxnDAZIrsSaEMCxwgwGggHI3E47eA4AKRogQxcy0mFFhgEW3MCoOKBZsdUrhFxSUMyT7P3bAlhcnk4BoHvb4RBuABGHwpJn+BGX1CLAGJKzmKjpF+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+contents-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBExCNGSenHRmVCwqJPTq1GxeTHRqXPz+/DwyJPTq3Ny+lOzexPzy5HRuVFSWlNzClPTexIR2ZOzevPz29AxqbPz6/IR+ZDyKjPTy5IyCZPz27ESOjJySfDSGhPTm1PTizJSKdDSChNzWxMS2nIR6ZKyijNzOrOzWtIx+bLSifNTGrMy6lIx+ZCRWRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaeQEAAQCwWBYJiYEAoGAFIw0E5QCScAIVikUgQqNargtFwdB9KSDhxiEjMiUlgHlB3E48IpdKdLCxzEAQJFxUTblwJGH9zGQgVGhUbbhxdG4wBHQQaCwaTb10emB8EBiAhInp8CSKYIw8kDRSfDiUmJ4xCIxMoKSoRJRMrJyy5uhMtLisTLCQkC8bHGBMj1daARgEjLyN03kPZc09FfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+contexthelp-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQChAQCBAAAACH5BAEAAAAALAAAAAAQABAAAAIzhH+hIeiwVmtOUcjENaxqjVjhByaBSZZVl24Y1V6iEVMzkD4bqD700bshgh1fzwd0IfwFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+crop-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBMT+xATCBASCBISChPz+/AAAACH5BAEAAAAALAAAAAAQABAAAAM0CLrc/iG+FsQgYapKbp7c4IFCZ2FQOQQE6oSl9Koxabrz/eVDDXat3atAlEEMSKFmyfAnAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+decrypted-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaVAQCBKSipDQyNMTCxISChFxaLFxSJExGHEQ+FCQiDBwaDBweDGxiLHxyNHRuPIR+RIyGZJSSfFxaRGxmLJyaXNzWpNTOnMzGnMS+jJSKTGReLKyqjPTu1NzarLSufKyibJySXIyGVGxiNFxaXLSytPT29Ozu7OTi5NTS1KyurGxqVCQeDJSSjLS2tNTW1KSmpGRiLKSebOzuzJSOXExONExGLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaVQIBwOAwYA8SkMCAYOAnKYiFAIAQGyOgVCggYuEovVxztMpdnwAGRSCgUCwOjIeQ6HpCIZDKRUNYMRBUWF4UYGRoWGxyBRR0eHxgaICEiIyR0QyUmJygpKgUrAxMsLUQlKyieoKIuEAunK52fBS8DLiywQySpnjC1Mbi6QjIzNBeSIBY1EQfDQgosLAEUNjY3Co1DfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+down-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRObCRKZBxCXAwyTKTK3Ozy/NTm9GSivAQWHNzu/FzC3IzO5CySrAQOHAyuzETS3CSWtAyOtETa5Aw2VLze7ByWtBy61BSavAxWdBRCXAwqPAQCBDR+nKTe7FS+1Eze7ByixBRmjPz+/AyexAyixAQKFBRqjAQGDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZeQIBwSCwaj0hAYCkYEJLKguGASEADigWj4bgaHpBINykwSCYRa5HCFFQsF0xGo9lwhpSOwfORYC4gISJ3RAQdIyQYJSAlImNrh4uNJkl5CoKUUBQnjlB4KJ6hokN+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editclear-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/ISChCH5BAEAAAAALAAAAAAQABAAAAIuhI+pm+EPnwmi2msDoLgLzQWDV4HlSJof6qki+W0n7LKdCpdyrm/Rr2EIhwp/AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editcopy-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAFxaXPwCBNze3GxubERCRPz+/Pz29Pzy5OTe3LS2tAQCBPTq3PTizLyulKyqrOzexLymhLy+vPTy9OzWvLyifMTCxHRydOzSrLyihPz6/OTKpLyabOzu7OTm5MS2nMSqjKSipDQyNJyenLSytOTi5NTS1JyanNTW1JSWlLy6vKyurAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAAaUQIBwCAgYj0eAYLkcEJBIZWFaGBie0ICUOnBiowKq4YBIKIbJcGG8YDQUDoHTKGU/HhBFpHrVIiQHbQ8TFAoVBRZeSoEIgxcYhhkSAmZKghcXGht6EhwdDmcRHh4NHxgbmwkcCwIgZwqwsbAhCR0CCiIKWQAOCQkjJAolJrpQShK2wicoxVEJKSMqDiAizLuysiF+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editcut-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/ISChCH5BAEAAAAALAAAAAAQABAAAAIwhI9pwaHrGFRBNDdPlYB3bWHQ1YXPtYln+iCpmqCDp6El7Ylsp6ssR1uYSKuW0V8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+editdelete-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbPT29GxubMzOzDQyNIyKjHRydERCROTi3IyKhPz29Ox6bPzCxPzy7PTm3NS6rIQCBMxCNPTq3PTi1PTezMyynPTm1PTaxOzWvMyulOzGrMymhPTq5OzOtNTKxNTOzNTCtNS+rMSehAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaKQAAgQCwahcihYMkcBAiBpLJApRoOBWgyIKhSEQkFgrBAcr1URiPhKAsDD3QB8RhA3FM0IlLHnyUTVBMSFBUWfl0XGBMTGBcZGodmcQWKjpAbHIgIBY2LHRoempOdjooTGx8giIOPFYofISJ+DyMXI6AfFySyfiUmJSUnKBYcICIpfgELzM3OZX5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+edit-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaVMR+RPzKjNze3AQCBMR6RPzGjPyODPz+/MzOzPyKDPyKBPz29OTWzPyGDPyGBOx6BOza1OR2BKROBNSOXKRKBBwOBOzu7PTWxPzizOySZPyCDFxaXOy2lNRyRMxmJCQOBPTm1OzStPTKrMR+XIRWLFxGNCQSBDQyNIRSNDQuJERGRLyqlNzSvIx6ZKRuVEw6LLSyrLymhKSShBwaFFROTJyWjMS+vNzW1OTazNzKrHRqXOzezOTOpPTq3OzWvOTStLyedMS+rLy2pMSynMSulAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAewgAAAAYSFhoQCA4IBBI2OjgUGBwiLBAmXlpcKkgsMlZcJBA0JDpIPEBGVjwkSBgOnExSfmBIVBxAMExYXswkYGRobHLq8gh2PHhoeHyAWIYKzIiMkJSYnKCnQg5YNHtQqKywtK9qMBC4vMDEBMjIz2dCMDTQ1Njc4OToz5PEEOzw3ZPToMcLHO23HfogQ0QMIkCA+hPBbhAPHECJFjMyYIUQIvEUpUqwQOXKkSEF+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editpaste-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQiFHRqNIx+LFxSBDw6PKSaRPz+/NTOjKyiZDw+POTe3AQCBIR2HPT23Ly2dIR2FMTCxLS2tCQmJKSipExGLHx+fHR2dJyenJyanJSSlERCRGRmZNTW1ERGRNze3GxubBweHMzOzJSWlIyOjHRydPz29MzKzIyKjPTq3Ly2rLy+vISGhPzy5LymhISChPTizOzWvKyurPTexOzSrDQyNHx6fCwuLGxqbOzKpMSabAQGBMS2nLyulMSidAAAACH5BAEAAAAALAAAAAAQABAAAAa7QIBQGBAMCMMkoMAsGA6IBKFZECoWDEbDgXgYIIRIRDJZMigUMKHCrlgul7KCgcloNJu8fsMpFzoZgRoeHx0fHwsgGyEACiIjIxokhAeVByUmG0snkpIbC5YHF4obBREkJCgon5YmKQsqDAUrqiwsrAcmLSkpLrISLC/CrCYOKTAxvgUywhYvGx+6xzM0vjUSNhdvn7zIMdUMNxw4IByKH8fINDk6DABZWTsbYzw9Li4+7UoAHvD+4X6CAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editshred-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbGxubMzOzPz69DQyNIyKjERCRPz29PT29OTi3IyKhPz27PTu5PTy5Pz6/Pzy7PTq3OzexLyqlPTm1PTizOzavLyqjOzWvOzaxLyifOzizOTOpAQCBOzezAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaEQAAgQCwahcihYMkcBAiBpLJApRoOBWgyIKhWEQkFYYHkeqkMxKFBFpq9jgdkEGlPqwrJhCIY2N8FFRYUFxcYGX9dgRKEGhiHiYEOhBcbGBwdiQEOARcBGwEeAZllAgEUnQEfoQEgmp4hrCKtrwEYsrRlTiMBJAG8syN/IyMAxMXHSH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+edittrash-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBKSipFxaXPz+/MTCxISChDQyNCH5BAEAAAAALAAAAAAQABAAAANQCKrRsZA5EYZ7K5BdugkdlQVCsRHdoGLMRwqw8UWvIKvGwTICQdmGgY7W+92GEJKPdNwBlMYgMlNkSp3QgOxKXAKFWE0UHHlObI3yyFH2JwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+encrypted-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaVAQCBKSipDQyNMTCxISChFxaLFxSJEQ+FExGHCQiDBwaDGxiLHxyNHRuPIR+TIyGZJSSfFxaRFxWJGRiLJyaXNzWpNTOnMzGnLy2hJSKTGReLKyqjPTu1NzarMS+jLSyfKyibJySXIyGVCQeDLSytPT29Ozu7OTi5NTS1KyurJSSjGxqVFxaXLS2tKSebOzuzLSufJSOXExGLGRiTExONAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaTQIBwGCgGhkhkQDBoEpLKQoBACAyOUID1qTVwoQGvMPxNFgVjAxp6QCQUicSCwVgkG44HJCKRRCYUCAxIFRYXhxgZGhYbHINEHR4fGCAhIiMkFSVKJicoKSoFKwMsLZtDLison6GjLA92qCueoAUvpC2xQhWqrLYDErmEMDEXlDIwMxAHukI0NS01EzY2NAmPAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+eraser-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAAT+BMTC/AQCBISC/AQChPzCxPz+/MQCBIQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAQ/EMhJZRA120GwnsEgdh8QiqKXnSi5oqNKsbFWGEYrT8Vx4JydpOf7uSrEIkIISPqWtkIS+pH2qCUptgTYavwRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+exec-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBEQ+PBwaHLy+vMzOzGxqZHx+dKyqnKymnIR+dNTW1MTCxJyOfLySVMSaVMSeVMSebJyWhOSmTOSuVNyubPS+dKSWhHR2dDw+PIyKhNymTNSaTEw+JOy+fPzSnLSyrISChDQyNDw6NMzKzLy2rMyiXGxWLAQCBHRqTPzerNy+lMzGvCwuLAwKDDQyLJyWlNy6jPTGhGxaRGxiRPz2vOTStLy2tFRSTMS+tOzGlPzmtPTixGRiXCwqJLy6tOTWxPTq1MzKxMzOxISCfHRybLS2tHR2bCQmJExORMTCvMTGxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAeogACCg4SFhoIBAYeDAogDA4oAjYQCBAEFBgcICQUBCpODAQsMDQ4PEBGWhgUMDxITFBUUFheDGAYZCA0aGxwcHR4QHwwgISILIyQlGiYnJygpKisEIywALS4vMBoxMjM0KTU2LC2ENzg5wDo6Owo8hT0+Lx8/OztAQR9C1oInQz4FMBAp8sEIhgIEMpwYdASJCwAYkihR5OLGkUUAMmTACK8Hx4+C/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+exit-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBDQyNHR2dCH5BAEAAAAALAAAAAAQABAAAAI4hI+pFrHb3nEg1iWiDiINCwYDko0V9XUTda6I1TIsUMpGinyzbB6ZeGuoEr+GUDL4CXqSphPhLwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+fileclose-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCQiJBwaHAQCBDQyNDw6PFxaXFRSVERGRCwqLAwODGRiZHx6fPz+/GxqbAwKDCQmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVaICCOZGmeqBgEwjCkRGEcSKK4JrEcBrMgAdeLVDg0GguGsYEbBQyGYyN6FDoPDIf0+LCKBIgetQERDgGDBGIpNY8GioAU0m6KXFw883w3+/l9f4AkfimGIn4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+filefind-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBCQmJDw+PBQSFAQCBMza3NTm5MTW1HyChOT29Ozq7MTq7Kze5Kzm7Oz6/NTy9Iza5GzGzKzS1Nzy9Nz29Kzq9HTGzHTK1Lza3AwKDLzu9JTi7HTW5GTCzITO1Mzq7Hza5FTK1ESyvHzKzKzW3DQyNDyqtDw6PIzW5HzGzAT+/Dw+RKyurNTOzMTGxMS+tJSGdATCxHRydLSqpLymnLSijBweHERCRNze3Pz69PTy9Oze1OTSxOTGrMSqlLy+vPTu5OzSvMymjNTGvNS+tMy2pMyunMSefAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe4gACCAAECA4OIiAIEBQYHBAKJgwIICQoLDA0IkZIECQ4PCxARCwSSAxITFA8VEBYXGBmJAQYLGhUbHB0eH7KIGRIMEBAgISIjJKaIJQQLFxERIialkieUGigpKRoIBCqJKyyLBwvJAioEyoICLS4v6QQwMQQyLuqLli8zNDU2BCf1lN3AkUPHDh49fAQAAEnGD1MCCALZEaSHkIUMBQS8wWMIkSJGhBzBmFEGgRsBUqpMiSgdAD+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+filenew-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbPz6/GxubNTKxDQyNIyKhHRydERCROTi3PT29Pz29Pzy7PTq3My2pPzu5PTi1NS+rPTq5PTezMyynPTm1Pz69OzWvMyqjPTu5PTm3OzOtOzGrMSehNTCtNS+tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ/QAAgQCwWhUhhQMBkDgKEQFIpKFgLhgMiOl1eC4iEYrtIer+MxsFRRgYe3wLkMWC0qXE5/T6sfiMSExR8Z1YRFRMWF4RwYIcYFhkahH6AGBuRk2YCCBwSFZgdHR6UgB8gkR0hpJsSGCAZoiEiI4QKtyQlFBQeHrVmC8HCw21+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fileopen-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBOSmZPzSnPzChPzGhPyuZEwyHExOTFROTFxaVFRSTMSGTPT29Ozu7Nze3NTS1MzKzMTGxLy6vLS2tLSytDQyNOTm5OTi5Ly+vKyqrKSmpIyOjLR+RNTW1MzOzJyenGxqZBweHKSinJSWlExKTMTCxKyurGxubBQSFAwKDJyanERCRERGRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaRQIBwGCgGhkhkEWA8HpNPojFJFU6ryitTiw0IBgRBkxsYFAiGtDodDZwPCERCEV8sEk0CI9FoOB4BEBESExQVFgEEBw8PFxcYEBIZGhscCEwdCxAPGA8eHxkUGyAhIkwHEREQqxEZExUjJCVWCBAZJhEmGRUnoygpQioZGxsnxsQrHByzQiJxz3EsLSwWpkJ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fileprint-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFRKNAQCBPz+/MTCxExKLPTq5Pz29Pz6/OzezPT29PTu7PTy7NzClOzm1PTu5LSabJyanPTm3FxaXOzCjOTKrOzi1OzaxOTSvJyenGRmZLyyTKSipDQyNERCROTi5Hx+fMzKzJSSlIyOjISChLS2tAT+BDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaYQIBwKAwIBMTkMDAYEApIpVBgOCAOg4RRGlAoEAuGIdGITgWOq4LxcCQgZkEkIHksHgYJOR6ZQCgVFhYJFxgTBVMZihoCfxUYDWUbUBGKGREcjBoQEB2TAB4CAx+Vl5WMhyACHiEhH6IfIiMktCQgE0cZJQStr6O2t6EARxO6vK6iEx4dZsMCxbsmBB4nzUTEutVSSUdmfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filequickprint-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBPz+/ISChERCBDQyNPz+xPz+BFxaXPwCBMTCxAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARWEMhAq5UYBME7D9kkBMNGjqHmeWBoDhwsEIS7coVx1NhbCrmdzROk9SyU4GEJ2twECISOUNokEopsVrobKCgCrZa73IHFYy4VyZ5WNIO4vBhvse8gfwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filesave-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBFRSVMTCxKyurPz+/JSWlFRWVJyenKSipJSSlOzu7ISChISGhIyOjHR2dJyanIyKjHx6fMzOzGRiZAQGBFxeXGRmZHRydGxqbAwODOTm5ExOTERGRExKTHx+fGxubNza3Dw+PDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaAQIAQECgOj0jBgFAoBpBHpaFAbRqRh0F1a30ClAhuNZHwZhViqgFhJizSjIZXQCAoHOKHYw5xRBiAElQTFAoVQgINFBYXGBkZFxYHGRqIDBQbmRwdHgKeH2YgHpmkIR0HAhFeTqSZIhwCFIdIrBsjAgcPXlBERZ4Gu7xCRZVDfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+fill-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBMT+xASCBMQCBATCBPwCBIQCBISCBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARSEMhJq50hXBvE0JsUEMXwhYFBmOeVDsVqgpS6luRc32RR6hLCTSCQ/VqEwwDhK5Z+Ao3wEPAViL6BR6PSZKyCa6uLAbcAZEznLDHQ1BZDiOKPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+filter-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBKSipMTCxISChMTGxAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM3CLrcDiGGt6IQQ7pI8PjSVHUeqFVBNxRfFjXSZYqwENoUNFx4rve+wI6WEwKLQ5/CSCw2lQ9/AgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+find-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1ISChOTy9Mzq7Kze5Kzm7HyChOT29Oz6/Nzy9Lzu7JTW3GTCzERCRLza3NTy9Nz29Mzu9Kzq9Ize7HTGzHzK1AwKDMTq7JTi7HTW5HzGzKzS1IzW5Hza5FTK1ESyvLTa3HTK1GzG1DyqtLzu9IzK1AT+/Dw+RAQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaSQIAQEBAMhkjBUEAoGA4EJXKJSCQUC0ZDCmg0hATHAxKRTCIEYYMiMFYsF0xGs+FUOl0BJRAweCIRHyATIRhpRAEAHSILIyQgJSYhJ4dIBBEoISkmKiuVSQgRIyEsEQgELVNCLgQVCiJRLQSfli9pMAQxMrRcQ1G6tAC9AL+7al+qxALACG1Kw8oxBGt7yWBpfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+finish-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAwyTBRObAw2VDR+nAQCBCRKZOzy/KTe7Pz+/KTK3Nzu/Lze7FS+1AyexAyuzBSavAyOtBSmzOTy/BRqjNTm9IzO5ETS3ETa5By61AyixByixBRmjAQGDBxCXGSivCySrCSWtBTC3AQOHAQWHAxWdEze7AQKFBRCXAwqPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZtQIBwSCwahYGjUjBQGgWE5LCgNBwITSFVKOgKDAZEIqodChSLw4HRcIyTW4Dg0HhAIhGIZEIJxA0VFhcYGRAaGBscHXEeHyAhIQ4iiBwjAHEBJCMjJCUmiSdlRyigU0oolURxRSmrTpevsUN+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+flag-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/AQCBMTCxPz+/MQCBPzCxPwCBAAAACH5BAEAAAAALAAAAAAQABAAAAM5CLrcruG9QCULokqKR44NJQykQGgXSRaEcYJLsLLu6wSFoRMvCuk1kO9ni8GMt6MForQMl89NxJ8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_new-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBPz+hPz+BOSmZPzSnPzChFxaXMTCBPyuZPz+xPzGhEwyHExOTPz+/MSGTFROTPT29OTm5KyurDQyNNza3Ozq5Nze3LR+RLy+vJyenMzKzNTS1Ly6vJSWlFRSTMzOzMTGxLS2tKSmpGxubBQSFAwKDKSinJyanIyOjCQiJERCRERGRBweHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaNQIBwSCwaj8ikcokMCIqBaEDoBAQG1meAUDAQpIcBQoy1dg2JdBqhECgQ1IWB0WgcBIOBwIHXBwwPEBEREhIBbG4IExR/DBUVFhIXV2NjDVYYDY8SFU4ZVxpVAQwbGxynGxkdTh6XVh8gGSGzGSITIxokJUImGSMTwLcnKCkprgAqDSt1zCssKxQtQ35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+forward-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAwyTBRObAw2VDR+nCRKZOzy/KTe7Pz+/KTK3Nzu/Lze7FS+1AyexAyuzBSavAyOtBSmzOTy/BRqjNTm9IzO5ETS3ETa5By61AyixByixBRmjAQGDBxCXGSivCySrCSWtBTC3AQOHAQWHAxWdEze7AQKFBRCXAwqPAQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZjQIBwSCwahYGjUjBQGgWEpHNYMBCaT4G2UDggos+EwmBYMBpf6VBgYDgeEMgjIpmoAQVKxXLBPDIXGhscRB0eHyAgDSGBGyJFASMiIiMkJYImUwAnmJqbjp4AKCmhAKSlTn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+frac-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBAQGBIQChCH5BAEAAAAALAAAAAAQABAAAAInhA9hig0SAmQOxeouPrFTzHzbCAzmiZ4k2S1ryHKsoo3tptXg3fgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+frameprint-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFRKNAQCBPz+/MTCxExKLPTq5Pz29Pz6/OzezPTy7PT29NzClPTu7PTu5PTm3LSabJyanOzi1FxaXOzCjOTKrOTSvJyenGRmZLyyTKSipDQyNERCROTi5MzKzIyOjLS2tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaPQIBwKAwIBMTkMDAYEApIpVBgOCAOg4RRGlAsEAqFIcGITqnWRcPxSEDMgkhAonA4DO3yMD6BUCoSCYIWEwVTF4gYAhAMFRUMZRlQEYgXERqKGBAQG5IAHAIDHYiUEUcDpwIcHh4doR0fH02zqAIXIASsrqi0TQBHE7e5HqG0Zr8CwSC9qFJHxbRSU7W1fkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+gear-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBISChMTCxDQyNFxaXKSipPz+/CH5BAEAAAAALAAAAAAQABAAAANdCLobwbAFMciLwBFSihBEFHSG8QnmpQQEBX6loI5G5QTlcMgrZSmEmsGxKqRWNV3hMrFlBtDoA1eTEaKHJdMYhR6+gxkF++UMGbiDzvDVioyHAJSHcchuGLQq4k8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+gohome-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBDw6PBQWFCQiJAQCBFxeXMTCxJyanDwyLDQqLFRSVLSytJSSlISChCQmJERGRFRWVGxubKSmpJyenGRmZLy+vOzq7OTi5Ly6vGRiZPTy9Pz6/OTm5ExOTPT29BwaHNza3NS6tJRqRGQqBNy6pIyKjDwGBPTe1JSWlDQyNOTGrNRiBGwmBIRaLNymdLxWBHxGFNySXCwqLKyqrNR6LKxGBNTS1NTW1Jw+BEweDDQ2NAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaoQIBwCAgIiEjAgAAoGA6I5DBBUBgWjIZDqnwYGgVIoTGQQgyRiGRCgZCR1nTFcsFkHm9hBp2paDYbHAsZHW9eERkYGh4eGx4ag3gfSgMTIBshIiMkGyAlCCZTEpciJyQjGxcoKUQBEhcbIiorLB4XEltDrhcaLS4vtbcJra8bMDHAGrcyrTMXHjA0NSypEsO6EzY3IzU4OdoTzK0BCAkDMgkIOjJlAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+goto-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBEQCBAAAACH5BAEAAAAALAAAAAAQABAAAAIohI8RyKciVnMwTlrlDfkm5QFgaHBWMo0lp22dZ57wO8vpGrLk2iJ+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+help-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQ6XAQCBCyCvARSjAQ+ZGSm1ARCbEyWzESOxIy63ARalAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAQ/EEgQqhUz00GEJx2WFUY3BZw5HYh4cu6mSkEy06B72LHkiYFST0NRLIaa4I0oQyZhTKInSq2eAlaaMAuYEv0RACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+history-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBEQ2LEw6POTSrOzWtNS2lAQCBOzatPTm3PTq3MyyjEw+NOzm1Pz29Pz+/Pz6/Pz27FRGPFxKRPTu3Pzy7Pz69Pz67KSGbPzy3Pzu3PTizPzu1Pzq1PTmzOzaxPTixPTmxOzWvOTOtKyWdOTGpOTStNS+nIRmVLymhNzCnOzavLyefAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaHQIBwGCgOj0jBgFAwGJDJAyJBUDihwgWj4XhAqhEJNDKhVLwUSUDyPJIrlgYlLSG0hYELhgLJTBJOd1kaGxgYHB0egkQfHBwgHyEigkUBIwMkBwcEJSZ3ARYWJCcnKCYpJJ5HAQUqFhSjJysoKItOCgehJBISI4tCtyERa79HTrx2WEiBUH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+idea-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+BPzerPz+xPyqXPz+/ISChFxaXKSipDQyNAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARMEEgZap14BjG6CJkmEMVQCF+4mQPBpthWtuYJxkJJGK6dbQRCgMBB3XCDzQamMhpDGlvuCFUyoQDLBUsJHBDUKuKQCKsUCIVZtc34IwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+int-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBIQChAQCBAwODAQGBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMwCKqx/iw0CNukzuJ8d1yCAAziIyliCKjck1ZuaV4igZ1r+raongE4j8YT6QiJC38CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+locationbar_erase-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/AAAACH5BAEAAAAALAAAAAAQABAAAAIshI+py40Bo1SywgSFiDq+oG3hZHDhVpUmagFrl7pgN3oqPNuqpe+8Awwi/AUAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+lock-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaVAQCBKSipDQyNMTCxISChFxaLFxSJEQ+FExGHCQiDBwaDGxiLHxyNHRuPIR+TIyGZJSSfFxaRFxWJGRiLJyaXNzWpNTOnMzGnLy2hJSKTGReLKyqjPTu1NzarMS+jLSyfKyibJySXIyGVCQeDLSytPT29Ozu7OTi5NTS1KyurJSSjGxqVFxaXLS2tKSebOzuzLSufJSOXExGLGRiTExONAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaTQIBwGCgGhkhkQDBoEpLKQoBACAyOUID1qTVwoQGvMPxNFgVjAxp6QCQUicSCwVgkG44HJCKRRCYUCAxIFRYXhxgZGhYbHINEHR4fGCAhIiMkFSVKJicoKSoFKwMsLZtDLison6GjLA92qCueoAUvpC2xQhWqrLYDErmEMDEXlDIwMxAHukI0NS01EzY2NAmPAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+lsub-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBIQChAAAACH5BAEAAAAALAAAAAAQABAAAAImhI+pFu2+QpxKVppsxkh3fnhh9DyGcC6IwLbqir4HK58tLcfx6xcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+lsup-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBIQChAQCBAAAACH5BAEAAAAALAAAAAAQABAAAAIlhI95YawYonwp0uoukFO7rCXCSJKPcKYKuqqii7BvS892XJZ+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+mail_forward-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRydHxubHxmZGxiXHRmZFxOTFxGPFxKTPwCBLymlMy+pOze3PTq3PTu5Pzy7LSmnOTaxOzm5LyqlNzOtPz69Pz27MzCtLyqrPT27IRubPzuzNTGvNTCxLSelPz25Bw+ZFxKPPzy1Pz65LyupBxKdCxWfPTm1Pz23LyinBxGbGzO5DRafBxWfBxajCymxHTS5BxSdBxKbFTK3EzG1CSGvCyKvCSSxCSavGTO5GRaVPzqzFzK5EzG3BSCtAwiPGxaVPTivPzy3NzKpBxObCRefBxqlPTmzJR2bKyahAwyRPzmvOTOpKyObNS+nPz21AQOFKyOfPzuxAQCBGRORLSadPzyzLymjMy2lOzetDwuJFRCPEw6NEQ6LEQyLEQ6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAAAQABAAAAfhgAABAgIDBAQFBgcIBwmOCQIKCwwNDg8OEBESjY8CDBMUFRYVFxgZDJyOGhsPChwVHR4fFSAhjwkaIiMOJBQQDRUVJSa3GicoHw4pEA8SGSorLI8tLtQu19gqLzDECTEyMzQ14zY1Njc3ODkqCTo7MjIxNCs5PD03PjctPwlAQUIihhBpQbCIihtG+CUocASFkAhIkogQ8kFJwkcFlogIkoRJEydPnkBR6GiAxiQLgiiIIkXElFQJqESoMsRKkAhXqkhhApNKFSxZggTJ4nHIEJhaDhzYwoVLFy1avHyB6ScQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mail_generic-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBGxaVOTe1Oze3OTWxOTWvNzStNzKpEQ6LOTezPz+/Pzy7Pz69Pz27Pz25Pz21PzuzPzuxEQyLLyinLSmnPz67Pz23LSafKyObDwuJMzCtLSelPzy1My6nLymjNTCxLyqnPzq1LyihKyOfOzavOzetEQ6NPTq3NzOtLymnNTGxJR2bOTOpPTivNTGvLymlKSShKyahEw+NOTe3PTm1Pzu1Pzy3FRCPPz65LSadFxGPOzm3PzqzPTmzPzmvEw6NCH5BAEAAAAALAAAAAAQABAAAAaqQIBwSCwaj8ikMhloOp/QpmAgqAoIhELBUDgcEIGEYrFgNBoLx+IBiRwkgQnFoWAwKhWLhX3BZAILGhsCDXgODhwdGB5vgAofICBlDiEiIx4kJSYBJ2UoEykqHSMrLC0nLWAnFS4UCycvMAcEMR0RLTIBMwaSahw0NTYtFwclNwEdLws4eoc2DxwQOR06ASk7PBAhIRE9Pj0tLSUY1T8I5gjn6Qgy7D8SfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mail_get-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAxKdBRSfCyGvFSm1BxKfCSWzCyWzBRCXCRKfBwuRAQGDDw6PHy23Cym1CSSxByCxBxunBQSFKyurMTCxExihNza3NTW1JSSlMzKzFxaXLS2tNze3KSipCQmJGxmbNTS1KSepLy2vISGhJSWlHx+fERGRPz6/IyKjDw+POzq7JyenMzOzKSmpCwuLDQyNIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaeQIBwGBAIAsOkUjAgFJRQQMHgjC4PBIEVgAh4D4aEYrGAMhINxwPyiCgYSsmEUmk82grLRZJkYCgXaAEKFxYZcEISGhsZFxwFeY0WHR5CDB8dGCAXG5shGxQicBIMpSMUGxgTGSQlpQwSJicnEwwdI7gdKAwTsykpKiobr8QMKxeHDBcsGRvOzxsT0i0uL9HSHdkT2ZkoMJXF4a8AfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mail_replyall-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRubHxubHxqbHxmZGxeXHRmZGROTFRCPFxKTFxGPPwCBLymlMy6pOTa1PTq3PTu5Pz27Dw+POzi3PTm1OTWvPz25FRSVERCRLympPzuzPTu7NTGvFxaXKSmpPzu1Pz65Hx6fHxqZPzq1Pz23HR2dBw+ZHx+fISChJSWlDQmJHRydCxWfBxGbJyenExKTHRiXPzqzPzy3CQmJDRafGTO5ExOTERKTGxWVCRSfHTS5CymxBxajBxWfPTmvPzy1CyixCSaxCySxDSaxDSWxDSSvDyaxGS21PTmzPz21AwiPBRejCSavByGtCSezEzG3FzK5FzG3GzO5FTK3CQ2bPTixBxqlCRefBxSdBxSfBx2nCQ+dHxmXPzmvLSafAwmRAwyRPzyzDw6POzavNzKpAQOFPzuxBwWTBw2ZGRORLyWdMy2lOzetPTivAQCBKyObOTOpAweNBwWVEQyLEw2LEQ2LDwuJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAQABAAAAf4gAABAgMEBQUGBwgJCguOCwEMDQ4PEBESDA4TjY8DFAwVERYXGBkRm4+QGhsMHB0eGB8bDpyOARogEBceIRgXv8COIiMkGB4lJSYnIcwoKb/DGyoXKywtKS4pHinMLzAxJDIzNDUtNjcv6B0hLzgfMh85OjstPDw99zwd7T4/LTVAgggZQqSIECNHevSAgSSJkiVMmjh5AiWKlClAiFARUeVHFSVWmLS40gNLlh5agGzh0kWDlwZfrIDREKaCAjEqrFA5MMYLmTAxlJTxYoZMozNozqRRs4ZNmy5s3LwhA0dBnDNn5MxBoAABnTp17IitowDrmQV+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mail_reply-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRubHxubHxqbHxmZGxeXHRmZGROTEw+NFxKTFxGPPwCBLymnMy6pOTa1PTm1Pzy7LymlOzi3HxqZOTWvPz69Pz25My+tLympFRGRHxuZPzu1LymjNTGvNTCxBw+ZPz23PzuzPz65PTu5NzOtCxWfBxKbPzq1DRafGTO5BxGbPzy9HTS5CymxBxajHRiXPzqzCyixCSaxCySxDSaxDSSvGS21GxWVAwmRBRejCSavByGtCSezEzG3FzK5FzG3CQ2bPzuxAwiPBxqlBxKdCRefBxWfBxSdBxSfBx2nCQ+dPzy1CRqlAwyRDQmJPTmvPTixLSafOTOpAQOFPz21BwWTBw2ZPzmvNS6nPTivAQCBAweNBwWVNzKpPzyzLyihGRORLyWdMy2lOzetKyObEQyLEw6NEw2LDwuJEQ2LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAQABAAAAfqgAABAgMEBQUGBwgJCguOCwEMDQ4PEJYRDhKNjxMPDBQVFhAXGBUSGY8LGhsQHB0VHh8gFQ6bjgEhIiMMJCUmFbS2CwMnG6IoKSorI7WpEycWFiUsLSou1yXXji8wFiopMTIzNDUz4zbZNxsbODk6Ozw9Pj8pPzEzQDdB60JDOkRFjBw5giRJDCWdlmxwIIRJExAWKDRyMgTIiydLoESRImQKlSUSF1SxUoXAlSBRsGSJoCVICIlbqlThcoBClC5eYFD4EiVIFwUyqywAE0ZMlqNjpJDpIkUBl0dlFChAYOZMmTJoyqQR5icQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mail_send-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRubHxubHxqbHxmZGxeXHRmZGROTFRCPFxKTFxGPPwCBHxqZLyqlMy6pOze3PTq3PTu5Pz27Pzy7LyinOTaxOzi3Ozq3LymlOTOtPz69Pzy5My+tLympPzqzNTGvLSelPzy3BxGbBQ6VPzuzPz65LyupNzOtPz+/GzO5BRejPzq1Pz23LymjHTS5CyixCSavBxqlPz25LymnGTO5CymxCSaxByGtHRiXPzy1CySxCSezGxWVPzuxKyOhMy6nDSaxEzG3PTivNzKpKyOfPzu1FzK5PTmzJR2ZLyihLSWfKyObOzmzPzmvDyaxOzavLSafGRORMy2lOzetDwuJEw6NEw2LEQyLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAQABAAAAfUgAABAgMEBQUGBwgJCguOCwwNDg8QERITFBUWjY8DFxgZGhsaHB0aD5yODB4TGB+kICEaIiOPCwEkJRcmJyYPKCIpKrWqKywTmC0SIi4vMDHEDCsyMg8zEyI0NTY3z7U4Hhs5Mx+0IyI6OyPrIzw9Gys+PxIy2EBBxAs8Qjk5Q0RFWFxAZySfgSMsilRAkiRECHQ08hHgJ0TJkCU/mECU2ISEkowUlpAQ4QTfowNPoAzJIeRJCyjm8kVRIkWIzSkXhwxJtYAKgp9VrFi5QoWKFZ5+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+matrix-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBIQChCH5BAEAAAAALAAAAAAQABAAAAIrhI9pwQHt4Jru2Vsjna919lXKeEimh6UZp1lrCEvkfILyirOby3q1OEv4CwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+misc-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBISChMTCxDQyNFxaXKSipPz+/CH5BAEAAAAALAAAAAAQABAAAANdCLobwbAFMciLwBFSihBEFHSG8QnmpQQEBX6loI5G5QTlcMgrZSmEmsGxKqRWNV3hMrFlBtDoA1eTEaKHJdMYhR6+gxkF++UMGbiDzvDVioyHAJSHcchuGLQq4k8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+move-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhA8RyKja2HtRrmrxNfDszm3JMpXmiULg6Hyto4kYO49Tfdc04xcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+news_subscribe-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/ERCBDQyNAQCBPz+/FxaXIQCBMQCBKSipMTCxATCBMT+xISChASCBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARsEEgZxLxYDlJsvsJGDN0nFQRhpKR3DSJxrGMphYQgpDI9WLhdTtjjAFApXZI30m2UQwICVigcEzzolKAYIAIFBAKbQjQX3YGGISZvFtzFQr1uDxT4PH0yYE8FCg0/Jn0MAwsNOiY3IQMBEn4RACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+news_unsubscribe-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/ERCBDQyNAQCBPz+/FxaXIQCBMQCBMTCxPzCxKSipAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARiEEgZxLxYDlJsvsJGDN0nFQRhpKR3DSJxrGMphYQgpDI9WLhdTtjjAFApXZI30m2UwxjsiOApB4kNLFtQKKopxeCQxR4GAJIXPCInzmhN9zvCljNq8ZvswmzhZHEfOhpofhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+next-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFwyXAQCBOze9BwCHNx21LQCvPSi5NRi7AAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAQ3EMhJqwUhAMG7DQOxdVwFFuI1nYZIethwIK0aFwjtwrfh15cAYUjcvWyvkm1Z4TGfkyN0avFHAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+ok-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBMT+xATCBASCBARCBAQCBEQCBAAAACH5BAEAAAAALAAAAAAQABAAAAM2CLrc/itAF8RkdVyVye4FpzUgJwijORCGUhDDOZbLG6Nd2xjwibIQ2y80sRGIl4IBuWk6Af4EACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+openterm-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXFRSVPz+/PT29OTm5OTi5DQyNDw+PERGRExKTHx+fISChIyKjHRydFxeXDQ2NCQmJBQSFAQCBERCRMTGxHR2dGRiZExOTDw6PCQiJAwODCwuLFRWVOzu7BweHAwKDCwqLHx6fBQWFGxqbGRmZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAanQIBwSCwKAwKkMslEAgSDqDRKqBYKhkNgcDggEorkMrDQchkNhuOhgEQkk0l5S2lUGpYLJqPZTAwMHB0DCmhqAW0Rfh5zAxgOkBcCFAcfIBMECxwBBAEPFw8dChkhcBMDDAcdnQqtFKSWcQMimx4dGRkQBxGxsg6bBQEawx8jl3GnJFoFHRNXVVNRJYIFDAsL1tgiDiQXFx0HABwcXeQH5OjkRutEfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+paintbrush-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBMTC/AQChPz+/MTCxKSipDQyNCH5BAEAAAAALAAAAAAQABAAAAM7CLrMIS2qN2Sj1U4xugaYZxFE1wUaURQnKpFBYQTuFRiyXDsCd8y7RYhmCQ2IkiHywmkFN84ibfrxJwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+paren-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBIQChAQCBBQSFCH5BAEAAAAALAAAAAAQABAAAAI3hI+JEQq8mnvyzSOhEWJ3CgLcOILV4IlfUx1cwirfYiEvXL83arANSer5UipM5tIzXjRCh8ZfAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+pencil-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/IQCBMQCBPzCxAQCBPz+/MTCxISChDQyNKSipEQCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARDEMhJZRBD1H2z3lMnjKCFjUJQimOgcmcbELCXzjXq0hV785WCQYcDFQjDXeloMByKG6YTAdwIDAlqSZJSVFeKLcUfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+player_eject-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+py+0R3IFQUtruXVqn3kkWyIARR4rqKvoFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+player_end-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIjhI+py8Eb3ENRggrxjRnrVIWcIoYd91FaenysMU6wTNeLXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+player_pause-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIfhI+py+1vgoxzyUCxrZd18ClfmIyVyJ1lqkHuC0N+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+player_start-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIjhI+pyxudwlNyguqkqRZh3h0gl43hpoElqlHt9UKw7NG27BcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+player_stop-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+py+1vgpySUWpvXXqrHmSaeJEYhKYq6hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+previous-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBFwyXOzC7PTq9OTK7IQyhBwCHNRi7LQCzPSi5IQ6jLwKzORy7AAAAAAAACH5BAEAAAAALAAAAAAQABAAAAQ8EMhJKwg4W5o1EGAIbt8wEERhHJ0mIEmiLAH5IYxi1JcnvTOeTdDYcVo1gfHY+hxs0IkvSpV2qtgswB8BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+prod-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBIQChCH5BAEAAAAALAAAAAAQABAAAAIihI+py50Bo4SKHlsDwk9fn21gJzIcV37miKpuZ0nOTBt+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+queue-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBMTC/Pz+/CH5BAEAAAAALAAAAAAQABAAAAI5hI+pFrEahGgPtCinS2GMlknU0Xkflm2l6YEiw8aRGssTXLe3lZsznvuRViwholEcLZCfynGT8BcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+redo-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBxOHBxSHBRGHKzCtNzu3MTSzBQ2FLzSxIzCjCSKFCyeHDzCLAxGHAwuFDSCNBxKLES+NHSmfBQ6FBxWJAQaDAQWFAw+HDSyLJzOnISyjMTexAQOBAwmDAw+FMzizAQODDymNKzWrAQKDAwaDEy6TFTGTFSyXDyKTAQCBAwiFBQyHAwSFAwmHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ2QIBwSCwaj0hAICBICgcDQsEgaB4PiIRiW0AEiE3sdsFgcK2CBsCheEAcjgYjoigwJRM2pUK0XDAKGRobDRwKHUcegAsfExUdIEcVCgshImojfEUkCiUmJygHACkqHEQpqKkpogAgK5FOQywtprFDKRwptrZ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+reload-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCRaJBxWJBxOHBRGBCxeLLTatCSKFCymJBQ6BAwmBNzu3AQCBAQOBCRSJKzWrGy+ZDy+NBxSHFSmTBxWHLTWtCyaHCSSFCx6PETKNBQ+FBwaHCRKJMTixLy6vExOTKyqrFxaXDQyNDw+PBQSFHx6fCwuLJyenDQ2NISChLSytJSSlFxeXAwODCQmJBweHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaBQIBQGBAMBALCcCksGA4IQkJBUDIDC6gVwGhshY5HlMn9DiCRL1MyYE8iiapaSKlALBdMRiPckDkdeXt9HgxkGhWDXB4fH4ZMGnxcICEiI45kQiQkDCUmJZskmUIiJyiPQgyoQwwpH35LqqgMKiEjq5obqh8rLCMtowAkLqovuH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+remove-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/PwCBMQCBEQCBIQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMuCLrc/hCGFyYLQjQsquLDQ2ScEEJjZkYfyQKlJa2j7AQnMM7NfucLze1FLD78CQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+revert-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIQAAAQCBPwCBPz+/PTizCQeHDQyNBweHAQGBAwKBDQ2NPzu5PTi3ERGRCQiJHR2dPTi1CwqLPz6/Mya/Mxm/GQCzFRWVGRmZAwODFxeXExOTExKTERCRBQWFMTCxKSipMzKzCH5BAEAAAEALAAAAAAQABAAAAV9ICCOQWkGIiqsQloCKCqy7UC8MC4URSsMhsDBNWOJEK4TYJfoGU8vmmJBGI5SyyYj0XDQjMvVQwBxRCQTilowFGwrjG5kTo+0x4OdpcLvV0YXIhcGGH0ZFRobOSccfB2PHR4FiyYAGQwdAI8eEAdQKBsZmR+RBpSVVyMHfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+rotate_ccw-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBFxaXIQChEQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM0CLrcHjA6JcK4ET68MrNDoIgjOYbdJ4IXagIa3IqVFAMEOqpfn067ErBxG0qGsCJyyQT4EwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+rotate_cw-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBIQChFxaXEQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMzCLrcHjA6FaG4YbS6At5BR31UKI4mADGhd31rpbmCuZ6qQLA8XvqT2+QhHLKKxqSy4U8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+rotate-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBFxaXIQChEQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM0CLrcHjA6JcK4ET68MrNDoIgjOYbdJ4IXagIa3IqVFAMEOqpfn067ErBxG0qGsCJyyQT4EwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+rsub-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBIQChAAAACH5BAEAAAAALAAAAAAQABAAAAInhI8Jwd26YJBUTVvT1Rlt3x2f6DjQeQiGigLCC7crK7+yC9sty/oFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+rsup-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBIQChAQCBAAAACH5BAEAAAAALAAAAAAQABAAAAImhI+pGtZ7gpwQyWofnnQ7I4SiuAjlqZgpmqgti7gxfMh1OY6LXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+run-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/ISChKSipMTCxLS2tLy+vMzOzMTGxNTS1AAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARlEMgJQqDYyiDGrR8oWJxnCcQXDMU4GEYqFN4UEHB+FEhtv7EBIYEohkjBkwJBqggEMB+ncHhaBsDUZmbAXq67EecQ02x2CMWzkAs504gCO3qcDZjkl11FMJVIN0cqHSpuGYYSfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+signature-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAFxaXPwCBAQCBDQyNPz+/KSipERCBAQChISCBMTCBPz+xMTC/AQC/MTCxPzerAAAACH5BAEAAAEALAAAAAAQABAAAARwEMhJZwgCiM17DoMkEGRpAmGhmSxhAOrakim6DgeLJApRhCPCgJRT8AhGEVFIQigAxgSQsBgwms8oIrDKDZNGxJY7GuYQULHhQj4shAmAuNAQsFc9xY4uUNgvMiQOBIMOfncjeUhICocXAx6RfwF+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+spellcheck-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/AQCBPzCxPwCBMQCBIQCBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM7CLrcGuHBNZ+NIOJ9O4MTaH2e1nDoiFYZJjgwIAzwy8yEgy84RhWDQa4HCwAHxJgxSPApC83YyQnwJwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+sqrt-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBIQChAQCBAwODAQGBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMyCLrcDiHK6eIL9WmsmwWCAAyiwkGKGILihzLq8p1s9onE9a48Iy28ko/WgRCLyGTDnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+stamp-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+xMTCBISCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANCCLrR+zAIMQKMguh6GR2g1QEBCBLiGGjo+DSpS3IqXNqxNAnwzisSk3BowRltM8IAZVMqi84lLNoqUVfLrOhoVPgTACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+start-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRSdBRObCQ2TAQCBBxObISevNzu/BRGZPz6/FzC3Pz+/HTS5ByyzJze7Mzq9ITC3AQWLAyWvBSavFyuxAwaLAQSHBRWfBSOrDzW5AyixCS61ETW3CzG1AQeLAweLAxefBSStEze7CSWtCyatBSCnAwmPBRWdByixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZrQIBwSCwah4HjUTBQEogFw/M4BQgMh2pxijAkFAhBYJwUPq8LRsPxWDwgkSHhelA0JJIJnlKRWy4YGRoSGxwcHRsecgAfICEiGhMjJBglVVMRgBkgJp0El0MRJyhaRFqipUoAFqmqrapHfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+stop-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/Gw6NGQuLHQ6NGQmJFweHFQaFPTm5PTa3PTW1Oy+vOS6tNSinKReVDQWFPz+/Nx6fNyCfNyGhNR+dMxybMRiXLxGRIwWFNx2dNx+fNx2bMxuZLQWFBwWFPTu7Pzy9NRqZNRuZMRSVLwmJGwWFNR2dMQiHPTKxMxmXMQyLMxmZNx6dMxiXMRSRMRaVKxybMxaVEQWFMQuJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaaQIAQEBAMCAWDYcgkHhAJxYLRcDQBggckIplQKpaLdRh4YDIaSWa94Vw6woAHgv6AMKGPaMQhwQMJJRkfhHmEJhdvRCcgGSCEkCgpbnAECiorGYYfLCItlAAFCygQj5AfbYlwBQwVE5AukG6KBi8tMC0fLi0pHxyzcAAxFxwmMny/wEwOxMm/qlcdJCSJ1H5XQh3a28HY3kx+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+sum-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBIQChCH5BAEAAAAALAAAAAAQABAAAAIdhI+py60BowyPJriwQ3qb7oGNyJCZtZHixHpu4xcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_block-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+py40Bo5SOzRvrwlgrfnkJOIkPaaaJXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_bold-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIihI+py70BowPQ1HZpwNv212Vg9IGHmIjoWa4ey5DSRNd+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+text-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIlhI8Jwe2/AmpTynqPTXSqrnBM+I0kdmpmGmUp+K4nPMvhYx9+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+text_italic-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+py+0BgztwUmmjBXX3jE0auHHhM5Yq4xcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_under-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIjhI+pu+FxXoOIKpds1oBH7hlYxYxRCaIZ01lhJbHy9tTv7BcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+toggle_log-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBATCxMTCBPz+xPz+/ERCBASChISCBARCRAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEIQJqpXBBjFI1oGncYU4EUXxSWQZlum6DXDQpeo0tR6KqqgdLXiLBWepHgyYIxF/TKHv9XvtDDfb0So5YHuTgThYCXgH4Q6hqvEGEIm4PLGSyHX4OkZv8UcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+top-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBBRObAQSHBRSdISevBRWfAweLNzu/BSOrAQWLPz6/FzC3DzW5BxObHTS5ByyzAyixEze7BSStBRWdAyWvByixCQ2TBRGZJze7CS61BSavAxefMzq9ETW3CSWtAwmPPz+/CzG1ITC3FyuxBSCnAQeLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZjQIBwSCwSA8ik0kgUDJhGQsFwgA4FBUTCoLBiF4zGtmt0FBYPSEQyoZCvWQakUok0LISnkHBBYjIVGhscS0UGHRUeHyBWAAIhiYuNAggVIgmMVgYjJBolAZMKJgpIjaanRH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+transform-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBMTCBPz+/Pz+xFxaXAQChAAAACH5BAEAAAAALAAAAAAQABAAAANOCLrcEDAGt4K4F46wmcVCQIzE4F1DukksehVkiUlDYcdfCAyEGI+D2aP3G+UmPF/MAJpwnpuNgMmcKHKgabWSvRi+ums3a32wzmWKw58AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+undo-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBxSHBxOHMTSzNzu3KzCtBRGHCSKFIzCjLzSxBQ2FAxGHDzCLCyeHBQ+FHSmfAwuFBxKLDSCNMzizISyjJzOnDSyLAw+FAQSDAQeDBxWJAwmDAQOBKzWrDymNAQaDAQODAwaDDyKTFSyXFTGTEy6TAQCBAQKDAwiFBQyHAwSFAwmHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ1QIBwSCwaj0hiQCBICpcDQsFgGAaIguhhi0gohIsrQEDYMhiNrRfgeAQC5fMCAolIDhD2hFI5WC4YRBkaBxsOE2l/RxsHHA4dHmkfRyAbIQ4iIyQlB5NFGCAACiakpSZEJyinTgAcKSesACorgU4mJ6uxR35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+unlock-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaVAQCBKSipDQyNMTCxISChFxaLFxSJExGHEQ+FCQiDBwaDBweDGxiLHxyNHRuPIR+RIyGZJSSfFxaRGxmLJyaXNzWpNTOnMzGnMS+jJSKTGReLKyqjPTu1NzarLSufKyibJySXIyGVGxiNFxaXLSytPT29Ozu7OTi5NTS1KyurGxqVCQeDJSSjLS2tNTW1KSmpGRiLKSebOzuzJSOXExONExGLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaVQIBwOAwYA8SkMCAYOAnKYiFAIAQGyOgVCggYuEovVxztMpdnwAGRSCgUCwOjIeQ6HpCIZDKRUNYMRBUWF4UYGRoWGxyBRR0eHxgaICEiIyR0QyUmJygpKgUrAxMsLUQlKyieoKIuEAunK52fBS8DLiywQySpnjC1Mbi6QjIzNBeSIBY1EQfDQgosLAEUNjY3Co1DfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+up-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRObAwSHBRSdISevBRWfAweLNzu/BSOrAQWLPz6/FzC3DzW5BxObHTS5ByyzAyixEze7BSStBRWdAyWvByixAQSHCQ2TAQCBBRGZJze7CS61BSavAxefMzq9ETW3CSWtAwmPPz+/CzG1ITC3FyuxBSCnAQeLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZfQIBwSCwaj8hhQJAkDggFQxMQIBwQhUSyqlgwsFpjg6BwPCARySSstC4eFAqEURlYhoMLBpPRUDYcHXt7RgUeFB8gIU0BIoiKjAcUIwiLSQUkJRsmGIwJJwmEU6OkfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+view_choose-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMzCLrcGlAs6UAYgwLdLtEcI4ygQo7VVp2oupGpG4vmaUVTemX523qlFcw0a4RqNlkx5k8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+view_detailed-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMmCLrc/i1IAVkYg1Z1iRYUKCqitp1oikqBWV3ZOnhkWNagqu+qnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+view_icon-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMwCLrcG1AwGOQbw6qANeCEB3pCSZpO6pgowJZqLKuUGE0dnuEhf8IL1kz1shSHDX8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewmag--16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1HyChOTy9Mzq7Kze5Kzm7OT29Oz6/Nzy9Lzu7JTW3GTCzLza3NTy9Nz29Ize7HTGzHzK1AwKDMTq7Kzq9JTi7HTW5HzGzMzu9KzS1IzW5Iza5FTK1ESyvLTa3HTK1GzGzGzG1DyqtIzK1AT+/AQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ+QIAQEBAMhkikgFAwHAiC5FCASCQUCwYiKiU0HA9IRAIhSAcTSuXBsFwwk0wyYNBANpyOxPMxIzMgCyEiHSMkGCV+SAQQJicoJCllUgBUECEeKhAIBCuUSxMKIFArBIpJBCxmLQQuL6eUAFCusJSzr7Kmpl0CtLGLvbW2Zn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewmag-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1HyChOTy9Mzq7Kze5Kzm7OT29Oz6/Nzy9Lzu7JTW3GTCzLza3NTy9Nz29Ize7HTGzHzK1AwKDMTq7Kzq9JTi7HTW5HzGzMzu9KzS1IzW5Iza5FTK1ESyvLTa3HTK1GzGzGzG1DyqtIzK1AT+/AQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ8QIAQEBAMhkikgFAwHAiC5FCASCQUCwYiKiU0HA9IRAIhSAcTSuXBsFwwk0wyYNBANpyOxPMxIzMgCyEiHSMkGCV+SAQQJicoJCllUgBUECEeKhAIBCuUSxMKIFArBIpJBCxmLQQuL6eUAFCusJSzr7GLArS5Q7O1tmZ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewmag+-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1HyChOTy9Mzq7Kze5Kzm7OT29Oz6/Nzy9Lzu7JTW3GTCzLza3NTy9Nz29Ize7HTGzHzK1AwKDMTq7Kzq9JTi7HTW5HzGzMzu9KzS1IzW5Iza5FTK1ESyvLTa3HTK1GzGzGzG1DyqtIzK1AT+/AQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaBQIAQEBAMhkikgFAwHAiC5FCASCQUCwYiKiU0HA9IRAIhSAcTSuXBsFwwk0wyYNBANpyOxPMxIzMgCyEiHSMkGCV+SAQQJicoJCllUgBUECEeKhAIBCuUSxMKIFArBIpJBCxmLQQuL6cAsLECrqeys7WxpqZdtK9Ct8C0fsHAZn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+view_multicolumn-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMwCLrc/ixI0WSgKoyBl+beQFACpo1AqXbKCr1wLAMWS08hGG3dSZqin4sxnBmPD38CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+view_text-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIchI+py40BTQSwuovp3DXkv1ia1IHmIXLiyWJ+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+view_tree-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBDQyNPz+/PzerAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAAMuCLHcri4yGISlj4kxcANgNRBQCIbL6U1Su7bB62rXvGydG25kqpwfIGxILBr9CQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+window_fullscreen-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIQAAASC/AQCBNTW1MzOzMTGxLy6vKyurJyenHR2dOTm5Pz+/IQCBOTm1Pz+9Pz+7Pz+5OTmzOTmxOTm3Pz+3OTmvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVuICCOZAkEaKquqzAQRWEYR32gSK7vO5oowKAQmPAtjkPFccEwLoaNhuPYDCSeT2B0+lhAfMHF1kF+PL5W7ZhrjqAk4gW53J0s3AG4nP6Y2BcUKAxLZn1+S4EBDAwQEIsUDBQRFJSJLJcoJpojfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+window_new-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIUAAFxaXGRmZFRWVGQmhFwmfFxeXOTm5MTCxLyWzLySzKyCvKSCvJxyrJRmrIxipIxWpNze3AQCBMTGxJRWtJRatIxOrIRCpHw+pHw6nHQ2lGwulOzu7Pz+/Pz+9Ozu5Pz+7NzexPz+5Pz+hPz+3NzevPz+BMTCBNzetMTCDPz+xNze1NzezPwCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACwALAAAAAAQABAAAAaVQEBAMCAUj0aCYFkwHBAJhWLBYDQcD8ghIjhIJhRKxXLBZDQaiYQLABDe8PiSu+HY7/dOh+PhQvB4eh8fIH6Adh2DHyGFAn+BiQAiISMkhnmSIQAlI5KXHIkfAiUmpCUnhoKLISgpIikmAlwqtCArkiUlIhwiuSKyEcHCESausMEsycrJEaaly9ARIizN1NPQ0dfJfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+window_nofullscreen-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIQAAASC/AQCBNTW1MzOzMTGxLy6vKyurJyenHR2dIQCBPz+/OTm5Pz+9OTm1Pz+7OTmzPz+5OTmxPz+3OTmvOTm3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVsICCOZAkEaKquqzAQRWEYR32gSK7vO5oowKAQmEAtfr9hgpFoGBWJpDDqcAaOUSHDEU08nkOG2AGBfK/aMYQMiRi7Ywe5674yE3I2JCqZoChLeGwSEgmFfgFNDQ8NjQ0TEROSRSyVKSaYI34hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+wizard-16:actions actions16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+xPz+BMTCBPz+/MTCxISChDQyNAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAREEMhJg6BYWhAGv5k2EKMXToSgEqc1DEIhvGAWpOvJFSXZyoXOxxY0BDahQDGg4xgOxmbgiWDqpoeqlGrVcZuSbLfpjwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+abbrowser-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBKSipMTCxISChPyqXPzerPz+xPz+/FxaXAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARhEMgJQqC4Xms1tkIgDEMYXpMYEEJRCIT6Ea5R2DHFtQZBG6dNoHQrsAyH14DDWiENBsQhBtskEs4Dohe4oiqE5So2zElECEKCrCYgQmcRVnRKnFIdC0L4/az7GXiBg4N+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+access-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBGRufLzi7PT6/NTq9OTy9MTm7LTW5LTS5LTO5KzC1FyGrExSXHzG3Gy+3FSStPz+/ESGpFSmxEySvEyKrER6nERylExqjFSSrKze7EyCrDxulKzG3GSuzGSitEyWvER2nEx6pKzO5DxmhLze7DxqjExihERadLS6xERulEyOrLTC1KzK3ERWbERujFRefGR+nKTO3LS6zLS+zFRmbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQABAAAAa1QEBgSCwWhYIBocA0CA6IhEKwYAQKDccDAolIJpSK5aKwFhyYDGSQoWgqm4uFYyV0PAeIIPIeayZlVw4OFV19FxoSGoFnH1tcayASIRciVgYfEWoQIxcLk4gHlxQCnJBcJBUSdAEHhQediSV5ExWBBxYQGSZelLkHJyhWsHmSISkHKpsrViwWJ1xPXCAtesIBCiUaGHm6LiYvLybXMAQCMQosBwcoMjIzMTQMAC0M9vf49wB+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+acroread-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAASC/PwCBPz+/AAAACH5BAEAAAAALAAAAAAQABAAAAIlhI+pELshmkOhzmTvyZrFDglRxVEiGUoUualtx7gOC36gDGt+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+agent-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBKSipISChPz+BMTCBISCBERCBCH5BAEAAAAALAAAAAAQABAAAANLCLrcHkFBt4IY8EYKYCAT9xVBYRhbM5KFeaRVy56oSsgQ/TLrB567ym10ChiCnRIRaJx8lDdd86UkEWjHaURZwlKRHpM0xPOYGf4EACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+aktion-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/AAAACH5BAEAAAAALAAAAAAQABAAAAI5hG+hIuigAmMvLTlfnJiePQndt4SMFFioeaagaEbvySlQF6I2BLPRwYntDLlaylH8VXLDpaiJ8BcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+alevt-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/Pz+/AQCBAT+BPwCBAT+/Pz+BMTCxCH5BAEAAAAALAAAAAAQABAAAANFCLrc/i3ISadQYQhSehFecAGiYJ6oiJmaZrymSrKCJhinXLYmHo+l2skn0KGOPwyBUHPhOrqKVIWsmhqHyqhhPUG+Cn8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+applixware-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBKSipAAAACH5BAEAAAAALAAAAAAQABAAAAIyhI+pGbsBHYtHCGARbMhms1HVB0TieJhcl23liXkinAmhy7732UL9GnsZeixczChB+AsAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+ark-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/PwCBAQCBPyCBPzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANCCLoQwTBK6dy8WNQgptAbB33DQGzlx3xE65RpBwgtCw9sR7e1gO8EGYs3DMoUH5rPqFylSrzaygcjHqdQVUYL8ScAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+arts-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPz+/KSipPwCBISChAT+BARCBMTCxDQyNAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAMALAAAAAAQABAAAARTEIQ5xbgYAwJksFhhaFTVdeLpURYwAOL7cp6gpmcZHEQPGyIOLRAkiI4GTqmIDG5QwGihuRIBU8boasLzZbEd082QK7VkrvTwo2pvP5m4GxHP+CMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+background-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAAQCBJx6NJR2LIxyNJR6NKSORKyaTJyGRJyORKSWTJyKRKSWRKyOPKSKPHRKLEwiFDwSDEQeDGxGJLSeTKSSRKyaVLyaPLyaTGQqFFwyHGwyFEQWFDQKDDQKFEwmFMSiTMyiVJRuNLx+LOS2VOy2ZNSKTFQeFGRGJLyqXMymVOSiVOy6ZOymZKxyTEQODDQOFLymVKxuNMRyJOSeNMx2FLxiJLRiHFQaDDwOFDQODFw+HLSiVHxSLFQiFIQ+HKxmNJxOLJRSLIxGHDwODGw+HNSSPOSWNNRyFOyyVOSOPARihNSORKRSFLR6TPz+/MTCxKTi9JTW7GSy1Lx2THw+FNSOXJRWNISChASq3ASWxARynEQaFMx+JJRSJFRWVARafARSdHxeLFw6HPz+7Pz+5GxKJDwSFIRSNHxGNPz+3MSCPNSWTMyGNPz+9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQABAAAAfXgACCg4SFggECAgMEBQYHBwgJCAoLggsMDA0ODxAREg0TCxQVghYWFxgZGhscHR4LE7GCHyAhIiMkJSatJyi+giApGCokKywtLhwvBzAwgiMxGDIzNDU2Nzg5OjsTghc8PT4/QEFC2EMeCZUARKpFRkdISUr09YIYET0qS0wqTUpOnkCJIkWQhxsbpsigUsWKkidXsGTRIkjHgy0YuMjoYkKJFy9KvoARFEZMBAg3UkIA6MTJGDKCBpQ5aebMGTQsx4xJU/FBBIxq1rAB4KTNS56Gkg7yEwgAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+bell-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBEwuFLR6PLRqJHQ6DNyuhLx6LKxiHDwiDMSOXLx2NKxaHAQCBHxSLGw+FKRyLFRSHLR6NIRKFExGHNTStOzm1KyqfIRmNHx6PIyGRFxeJNzavOzq1MTGpKymfKyqhKSmdGxqNDw+FPTy7KyuhNzevISGTJSSXLy6jOzq3Ly+lJyabHRyNCQmDKSifAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ6QIBwGCgOj8iAYEAIIJ+BguGAeCYTigXDegw0DI4tl/gQj4WB8hkAgUQeEsaEC6FULBdMRjN/QjYcHR4fICEiVn8jFCAkHxiHfiUjHRYfHyZmR4kdICAeJ5lCECgVKSorJysrLC1IEBgVFSgunSAaoWwTIi28DL5HfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+blender-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBDwiDPSyNOyKLDweBFQuDFQyDPSeNEQmDIxSHFQ2DEQqDARWjARGdASO5AR6xAQiPOymNAQ2XARqtAQKHOSmNEQiDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVqICCOQBCQKBkIA5G+63C+RW3UrIsSQt8fA+CMREAQgIkaUEdSsBK6hZBUeJ4YjRLQIKoOBgVAw/GAAAqRk+EJBkgmDQrAUDGxTAMBAgCR89oFOgF5YQAWdy8EeTeILyV5jY5nBAGFkpJ+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+clock-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAASC/AQCBPzerPyqXMRaBIQCBISChPz+/KSipMTCxPz+BMTCBPwCBPz+xPzCxMQCBISCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVxICCOQGCeJjkGwkC8RFEEavkax2G8dB0QuRyhhzoBg8MSYsncJXKJZIDZHCoWP1ogGIwGrtnSgUFmHLyNRHhrdpjRamnO/SYkromHdnxwnwkKVxByZW8DgQsQM2JcfwZXO0MBCZSVBgMuLzJaRZ0pfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+colors-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BAQCBAQC/MQCxATCxATCBPyqXPwCBPzerAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARWEMgZ6rwYBCFsvtXWeWA1DBU3ggRhomJQBm14dlJYFFXrbjKNwVDZ9Vw4TWWoKyCDgcNhyXQClVLpMmANIRAhLdGa+36j07GrfM4GiKTAGfsOlmYZfwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+cookie-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBNzeDJR+BOzmVNSqPOSmBNSCBKRCJFwuBOSOjMRSTLRaXFQODMxiXOS6vIwiJGwKDHx6fKyqrMSOjNRWVLRaVFwCBJyanJSKhHRydPTy9PT29OyytIQSFPz+/JSSlOTGxIQyLMTGxNTW1Nze3Ozq7OTe3FxSTGxqZNza3Ozu7OTm5MzKzLy6vLS2tNTS1FRKPGxWRMSypJyOhKSOfPTu7LyupFQ6HMzOzEw+NJR2XKyOdFxGNHRSNJx6XGRCLHRCDMy+tGxONDwaBHRiVDwyLEQuHJRyVJyCZLSilIxiPIRePHxOJIRWJFwyFEwqDCwWBBQOBDweBKSCbHRKLHRKHIROHGQyBFwyDDQaBIxqTHxOLGQ2DDwiDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe4gACCgwABAoSIiAMEiY0ABQaHjoQHCJOECQoLDJeCDQ4PEJMRERITFBUWFxgZhKQaGhsKHB0WHrcfEQARGxu3HiAKIRgiIyQlJicoGym+KissLRIuIi8jJTAwJjEyGzIYKxszNDU2Nzg5MDY6OyQ8PT4jP0BBQkNERUZHOkhJSktMZDQBcsTJEyhRpOybcuSIEipVrFxBgEVKFigATkiRgkSLki1UgFzh8kRKFEQbN3aR0qULIT+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+date-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAASC/AQCBPzerPyqXMRaBIQCBISChPz+/KSipMTCxPz+BMTCBPwCBPz+xPzCxMQCBISCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVxICCOQGCeJjkGwkC8RFEEavkax2G8dB0QuRyhhzoBg8MSYsncJXKJZIDZHCoWP1ogGIwGrtnSgUFmHLyNRHhrdpjRamnO/SYkromHdnxwnwkKVxByZW8DgQsQM2JcfwZXO0MBCZSVBgMuLzJaRZ0pfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+dlgedit-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBMTCxFxaXKSipPz+/AQChAAAACH5BAEAAAAALAAAAAAQABAAAANLCLHcrSLKOVccAuvMLf2Rlw0bYRKFGBGZWQioRc4kPKfB+qFFL9ODF+EmKxh6vZOreETCbLiMESkcxnIgATXK2XgFqmxI4SgvAP4EACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+emacs-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBDQyNKSipPz+/FxaXISChMTCxCH5BAEAAAAALAAAAAAQABAAAANJCBASoXCFoVi8VdL6HHQeB4YjSAxnYQygSLzoSTjbEs9vMF86cbyH34NX+AELQ4zO+Nopm6cBC1PBEQwG6gd3SGo7Xa1STIb4EwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+email-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBGRWVAQCBOTWvKSShDwyLOTazOTaxPTuzLSilOzi1OzezPzy7Pzu1NTKtKySfPzy5Ozm3Pzy3PTq1NTCrMS2rNzWvNzOvMy+rLSmlPz69LSejIx2bPz29ISChPz6/Oze1HR2dOTi5Pz+/EQyLJyanKSipOTm5MTCxHx+fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaGQIBwSAQEAoJi8RgYEApK49FgOCAS0CFTsVAwEA2CIysMJB6QCEQyoVQsZOMFk3loJoeNAk4MGBQOFAQcDw8IfFoLDB0cEBMICIRxAV6NEB4aHwICk4wLIBYhIiObSxwLBSQkJaOlfQUFpCYnIyMoSVGbtQK3UQCbKCYprkq8m8S+uL4AfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+energy-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBBQSFASiBHS2/JzK/KzW/JzO/ASWBATCBASKBHy+/Hy6/ByuHASCBAR+BATOBARyBIzC/MS+BASeBASOBARaBFym/Pz6BASuBEyW5AR2BJS+7Gyq7PT2BARKBDyC1FSS3IR+BJyaBLy2BPz+BCxuxAQ+BDw+BOzmBARiBCxyxBxetPTyBAQCPAxOpAQ6BAQ6jAQ2fAQ2hLy6BAQubAQydAQmXAQmVAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAahQIBwSCwaj0hAYBkQBJDLAaFgOBCWxcAAkVAsGIyG4/EUBh4ICCIicUAgkwTZjKBULISL3oHJzAMaDhscHYEODhMeExEfSyAhGxsgICIYHiMWJCUYSyYYJw8kIigoKSomKxgmSywYfC0YGCJ8rSwuS7EYJBYYLi+xE5tkARMoMCoYEzEiJDIzMjQiSzExMxGkNTY2NTc4NTNPTOLjWElHfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+enhanced_browsing-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBOTWzIyCrFRSTMy+tCQmVOzi3ExKhAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARFEMhJq6UhyHy3GNmnAeNEFAZwpuRRBiIMkkOBjKuKTsHtgbISybTLYX6hGc+lSxk3tVtMVOkFck9MMNjB7jqkEQdMlvgjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+filetypes-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMT+/ISChKSipPz+/PyqXMTCxFxaXPzerPz+xAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARfEEgZqg0zV8EHF5XWEUMxkBwGBB9REIZLfBgrkEaen+l6F4cYgpA4vEC+ASIYSxQRnlrncEgoFFQP0laCHpSmnk+AEJQ8ZeRkw0mDVJT3JZQZw+trC77Ouu8pfn8AfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+fonts-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/AQCBPz+/KSipMTCxPwCBFxaXMQCBCH5BAEAAAAALAAAAAAQABAAAANBCLoQ/C+I4GAMY1ZGN80UJ2jA0BFbUxhjF6BWsQroawEyWhN37vKxQo0ChPhOPaGDIhhADr5FinE4TG5PrBbiTwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+gimp-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBISChPz+/FxaXMTCxAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM6CLrc/izAJVWoD4MgtL2R0F2k6HFiOgjDSRBq0FLUKxYDTmKBnf6gGqz3egWFhEvSQ9kxJ9CotOFPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+go-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBERGRFRSVDw6PDQ2NDw+PPz+/ERCROTi5Pz6/AQCBKyurERGPOzq7ISGhNTS1DQyNLSytExKTLy+vKx+RGRiZPTipEQ6LOzu7PT29JSOjOzWlEw+LIyKjIx+dLy6vOy6ZEwuFHQ+DCwqLGQ6HNSWPMymfIxmPMyqjKSipCwuLMzKzHx+fBweHOTm5GxubJSSlAQGBHR2dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAadQIBwGAgIiMXhgAAoGAwH4QCRKAgVCwSB8AwwCo2n9ZpwMMSFhyEBGQoLEa5BMnkO3G/Kef2sMIdfCxYXT2oGGAIHCk0ZCBobHE8dHk8MFR+LgSAhXSIRdmNCBxScBiObCAYZI25wJE8SJSYECVVDCg8dERchJygPKSqsQgQNKwQFCw8fLC0KLi+LxH9YMDFX0ngAzzLZ2m4K3kN+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+gv-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/AAAACH5BAEAAAAALAAAAAAQABAAAAIxhI+pwaHZ2jNMWMFmvXk1GznHF4DhWF4cJlKpynpwB73ms3Etiq00EAr+hJGJ0eAvAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+gvim-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBAT+BPz+/ASCBMTCxISChAQChCH5BAEAAAAALAAAAAAQABAAAANUCBDMEqupNWoNJNgBV/mfwYCFqASgmA1h57VaO71lXLtPytZEBggZ0E7Vy2BQJEaRcDghP6iGb/IsNKBWKghZzb5EUau4g1KFz1QId+ydRRZwiD8BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+help_index-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BAQCBPwCBAQC/IQCBATCxMT+/Pz+/ISChAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARTEIRJJZ1ACjF3GGAYaKNFDNfXldLJqmQWcKhcW6tkl1NhFJhdRmIwHIq8m8R3LAIlykCxiZQNl8XsU3eVZg0Y2LD3CyAQlassbEaz1N32Gz5m+SMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+hwinfo-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBBQ+XBRCZAw+XAw6XBRCXCRObCxihCxqjCRijBRSfAwyVCxehDx6nER+pPz+/BxKZAwmPFyWtGyevCRSbBxWfAxGbHSqxGSatCxulBxahBRKbAQiNEyKrBRKdAw6ZAwiNESSLCyCDBxWBDRulBwyRHS6ZDSWHCyKFDQyNCxqlAQmRAwiPMzalPyCBMQCBCx+DAwuRBQqPITCdFxaXCyOFAQeNAwmRAxKdPz6/GyyVMTCxKSirAQCBGzKZAwqTAweNFyuRDyeJFzCTITOdAQiPAQaNHzCbES6NEy6PESyNDyqLDymJPz+xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfBgACCAAECAwSDiYMFBgcICQoLC4qCBQwNDg8PEJERlAYNEhOaFBUWnokBBw4SFxgOGRobCxyJBQkNHZoPpR4fICEiIiMBCSSYmgoKFgslJicoKQQKCSoZmgW+KywtLi8pMDEbFRqaAcwyMyc0NSkiNjc4ObsrKyU6Ozw97j4lNhGSfsgAEkQIDxr7YAwh0qKIDSM2jgRpgbDHPhFIMiZRsoTJkhMgobUDMKKkySYjUKockYJSypcrWypKQbOmTT+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+icons-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAASC/AQCBPz+/ISChIQChFxaXKSipPzCxPzC/MQCBISCBPyqXMT+/MTCxPwCBMQCxMT+xPz+xMTCBPzerPz+BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAV+IBCMZBkAqCgMa8uyJxoMRFHUtz3Eqk0MBhxBwJsRaqTcLhUQ3AyHAMI0EtEI0pGrpU38SANFQazYGY+LqUChYDQUxCbB8YjOFJAIpGEePOpZAhITIxJxAg8JDwQPMxISERESfXSVTRIQAZKHLyuOFI8US1RNnTApqCJUAH4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+iconthemes-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAASC/AQCBPz+xISCBPz+/ISChPz+BIQChFxaXMRaBPyqXIQCBPzC/MT+/MTCxMQCxPzCxMT+xMTCBPzerMQCBPwCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAWLIBCMwhgMJqCKRBEIpWAMBRGsQXG8sIAiLpwNZpAFEAcbjlc0OI9BVcAWSDgHT9MtF1AsZrmamNpNBAyjwgCxpo0U5h1jOhg0HAMbPHB4QNIDEQIRDi5xfgFzBBITIxJUBQ8UD305EhIwEi45FQ+dFVMSES+PIy2nLgUSBpcGQVomqKc3K7WwIwB+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+input_devices_settings-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/MTCxHx+fISChKSipKSirATCxAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARQEMgQpL03iEEx1gOxdR5YbCJXZUbqjusUhGitZkFri0VFUodXoTfjWCi6oY8Skxl6k4FhxZRRRxMC1TBdWn0CAbcZQFAH4WnGjDPiPICYPwIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kab-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBISChFxaXKSipDQyNAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANICLocHiyqIMQYUE5Ses8S1V0FGInFIJTalKpsS5FxKDxB/EzV4GUBQsXR87BQnRtNtxphfJ9FAAqbRqUXVfPaMH5MDRx44U8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kappfinder-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBExOTDw+PExKTPz+/ISChAQCBPz6/FRSVIyKjJSSlIyOjGRmZNTS1Ozq7Ozu7AxyzPTy9ERCRBQWFIyqxPT29AQ2vOTi5IzG7DR2zNze3Nza3BQSFISy5CRyvBQenISmvBQitMzOzAQGBAw6rDR61Hx6fMzKzAz+/IzW7ASyvCwuLMTGxMTCxBwWFDQyNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAahQAAgEBAYj0ahckAoEJ5QgkE5fBYO0SeCOigkFE2DeEFgUAUNBwGBeBAcCMHirF4gnhBCBCE5PydqBBQVFhdTSgJPBk8YGRQaG4dCiQQcDh0eHyAhIiN+BHYXJCUNIggmfhUOAQgbJ6YCKGcVKSUaChwGHCYqCyuIDhkhGyIsLcccCL6TFxsNJ8fRLS7KvyNi2GIrAQwK1AsvVOJULi4AfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+karm-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BAQCBPz+/ISChMTC/MTCxPzCxMQCBPwCBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARTEIRJa5Ui66H3FETHdcTwdcIofkVbUIJbmAEoZl95aoXxUrNdpnAIDFomgRA3yxxhIdxAlaKhAgUNYshyYVGxnMZInS6VzVSQPG0bkWaJZT4B+CMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kcalc-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BAQCBATCxARCRASChAT+BMTCxFxaXEQCBPzCxPwCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARPEIBAq5U4iM17wJMwjORIfJkYFCs7nKA2rJQLp0Su66ikGcAg8OYTGA6BA/KAIIYsFudPGJQal8uAFVqxUg2JxBYbUGh7k5J6BppwKyB/BAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kcharselect-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBISChPz+/MTCxAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANBCLrR+zCIGWCcI1cLpNCa5YHZsCmj2QTlxrZmmRFVSs4E7X13TqMTXsl36gSHuSIQQ+QYP0kncPCTokzWh3LhTwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kchart-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBPz+/ATCBAS6BPyqXPzerPz6/Pz+BPwC/MQCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARcEMgJQqB4WiFulhvXfaEwiJ4mEgExFCMVcENgBEXepdVhG7dcABGr/IJCQ8ICAt4IUIuSKAW2XMOD0qC42AIHV4277YIqKHKCy5txbIoyDy2Nr80yjyVwn5OYfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kcmdevices-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPyCBPyqXPzerPz+xPz+/AAAACH5BAEAAAAALAAAAAAQABAAAANMCLrcHjA6BcW4Q8AWLL7EFSwdOIRoOAKBiZ5EPJYvBMeDba5BQfg52ik4KPgKOVYqZiwYjLzb7/c0JCnSo3VFasFEXE5kMymbzwp/AgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kcmdf-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMT+xAT+BASCBATCBMT+/AT+/ASChATCxPz+xPz+BISCBMTCBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEEgZwrwYBCFqvhs3DNYXjChRlWBRjIRqGN4UuEUczMZxsDeXykdEsDQVVSLhQxhBCkVlmXA+KVHFYhFYOoHbMGN6pTQaW8YYiQmcG+q16a0+Zipw+4e9B/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kcmdrkonqi-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPzerPz+/PyqXMTCxPz+xAAAACH5BAEAAAAALAAAAAAQABAAAANKCAoRy+6pIESkVuLaKl8b53lOaA3EyIXBUBjpWHKDYNhxNrWv/aaRiWBwKwoIDZCH2EN+TMQjyzR0yhgqiyo4vT4wl48E8g0C/AkAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kcmkicker-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBFxaXPz+/ISChMTCxPzerPyqXDQyNAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEEgQqr11AjG6/4FGDEVZBOapWSXbToFhoKkZUjJGEEJvyUDDYQaKATElBOJklB0OgY5SWgnmpFJm4PkMjDxLFYXFGSCyN8mocDaD0xsSO6wUS6K1FBzDD/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kcmkwm-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCRiXCRaVPz+/CRmZFRWVISGhMTCxESSjPT29DR6dDyOhDyCfPTy9CxqZOzu7Ozq7ERubOTm5ARehAxefPz6/ByaxBSOvBSGrAxynAxqlBR6nBRylAxmhARWdFxaXCH5BAEAAAAALAAAAAAQABAAAAWHICCKQTCeqCgMhJCihXEYSPuKRWIoC6PYsEZikHA4FA4CEJdoJh4QgXRwiOAeQudDIpEZIpPwhCImhyGGAmBSOVgumExG055w1ZPZhpPpUDwzExBqAAUDhxUVTQ0QEgWOOIcDiU1QjoSFFYiKDZYFmAWJlE9bkCM5iouWpiIfBa6frrKYAH4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kcmmemory-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBISChAQCBMTCxCH5BAEAAAAALAAAAAAQABAAAAI6hA+Bu+HCmgiiRuNoHZBRXQlc84TmcHzm2WVryE1YvMaZIdbVd2zw7lj4bDKGbxK8hHgX3K2JUDD8BQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kcmmidi-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBFxaXKSipMTCxPz+/AAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM7CLEL/pDJAONs1V2W1ebWJ46kKJxomi5D2QZEwRSyVMNyngf7Eg8FYHAIZMRoyCSNMSA0n85oszTxJwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kcmpartitions-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMT+xAT+BASCBATCBMT+/AT+/ASChATCxPz+xPz+BISCBMTCBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEEgZwrwYBCFqvhs3DNYXjChRlWBRjIRqGN4UuEUczMZxsDeXykdEsDQVVSLhQxhBCkVlmXA+KVHFYhFYOoHbMGN6pTQaW8YYiQmcG+q16a0+Zipw+4e9B/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kcmpci-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAADQyNATCBASCBKSipFxaXAQCBMTC/ISChAQC/IQCBPyCBPz+xPwCBMTCxPz+/AAAACH5BAEAAAwALAAAAAAQABAAAARVEMhJqww4a33F+EL4jUI3EEXoEWzaFbAKzyUQeLihDqrpHQhBQkHyqY49iWCxbDKfJQbASYUCpJbslcHter+NQ3gsLo8bBYd6zWYf0u24GjWr22f+CAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kcmprocessor-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBKSipMTCxISChFxaXDQyNAAAACH5BAEAAAAALAAAAAAQABAAAAM7CLrc/jDGQCWgIleH88jCdgXgB4JVQJxsVgQXIQvrWdwwJc/0jcOG0Y7gqwQVQR3R+EgyJcGjZUoF+BMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kcmscsi-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/MTCxKSipISChAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANCCLoQwZAFIV6UYgxi79Qa52WDE3bKV6YOpFpO3L5pJcckLBB8/wQEDezWAQpZqIWxFNAUkqkg6HmJOqGuArUqwfoTACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kcmsound-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQC/AQCxFxaXAQChAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM7CLrcDiE+F4SQU4UBLH6VoHjT1okQR6mnuTYuJMWaGlkXW2u4QOipRYDws82AjJsHKez9MgrigAkF+BMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kcmsystem-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBGxqFAQCBPz+/PTqtOTOfMSyPNze3Ozi5KyeLMTCxMzGzKSipOTe5MTGxAAAACH5BAEAAAAALAAAAAAQABAAAARfEMhJQah4ihFunsFAEIVXCVJACIJhoBK6CerawsA8HAhbuAnYZrBDKBYMWpCy4S2QSRazyBIwrrjcoNFQzK4KR1bQcHhZjGM2BgWLMYJ2enForHPJtNj+kfHvcB8AfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kcmx-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIAAAASC/PwCBCH5BAEAAAAALAAAAAAQABAAAAIlhI+pm+HB4HkS1flszOCq7C2Qw0wdJ2Lk16BGeK5dSZX2jS9+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kcontrol-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/CRyBBxSBExOTNzipOTijOz67NT21LzutJTmlGzaXPz+/OTi5AQCBLy+JKSiJES2NES2LESyLDQyNLy+vLzWhLzWjLS2tGRiZDymJASChIQCBDyuLLzShDyiJMQ2LATCxMQKDDSaHDSWFCQ6tMT+/PzCxLzuvCyKDDSSFKyqrMTCxGzabDw+PISChASSBAT+BDzOPNTW3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAacQEBgSAwIBsikkFAwHBAJhWBBpTIaAccDAolEJIKJWEzBMiuWCyYjaLjd5exDIsE02A1NY9OIMzkcHRkebW99WFoVahkfbSANIYdCBh52IiOFb2VCByIWIh0kbSUNJpIBJ6CgKJlwDUIJKSooswIUt7crrwEsKC2+rC7CLzAuuzEoycmtbgAAAtDR0DLGztYALbm426/Wht9vzn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kcron-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAADxePARCBAQuBNTS1OTi3LSytAQeBMTC/Pz+/AQCBOTi5MTCtISCZAQiBISCfKSipFRWZGRiZERCRHRyZMTOxDxOPMTCxIyCjCQiJAQOBLS2tAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQABAAAAWFIBCMpCCQpDgQLFusLVEYAXEgOJIQOXIkNF5v19MFWQrCgsFYxIC1InEYvOWmuF9QKrw2aoSkYtksOBwEaBeXeEAiiIdD8rUNJw8EBUGobIcQFggXLglgCohLGA95CQMOGVFDEQ4YGhERdAEWCZ2dDwsSEHMOEA0ABqmqGRkGDQ2pDRV+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kdevelop-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBGSKXEx6RFR+RFSORISidJzCjJS+hISydHSqZDxuNIyuhKzOpLTSrKTGlHyybGyqVDx2LHyedKzKpLzWtMzexLzavIS2fFyWTDyCLCxiHNTmzPT29PT69NTm1GSWVESKNCRmFOz27Pz69PT27MTKxJymnIS6dESGNDR6HFyCTIy2fNzm1Ozy5JyenISKhISOhMTKvESGLBxaFOzy7JSWlIySjCx2FBxGDIyOjOTu5BQ+DFSGRDR+JCx6FBxODDx2NGyaXCRyFCx2HCRqFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAexgACCg4SFhgABAgMEh4MFBQYHCAkCCocLDA0MDgcPEAQRhRITFBUWDAcXEBgZGoQIFBscHRweBgkfICGDAQcUIiMdJCUmJxgoKbsAKissLSQuLzAxFgQyKTOCKgk0NS/fNiQtBBk3OIIEEC0cMDkvJiQ6ICk3O4M8FCQcNjAcJBM9fPwgBCQICxI0XtBgQeCGEHuEFGCYwILFBAJCHh7SEGJIRiI/IDaagSNko5OF/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kdisknav-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBERCBBQWFPz+xPz+BISCBERCRPz+/OTm5HRydAQ+XHR2dKSmpNTS1Hy+1AxypNTu9ITC3ARypExOTFSyzHS61JTK3MTi7CwqLBR+rASGtDyixFyuzDw+PAxWhAxmnBRypISitCRujAxelAxmlFSixMzKzCRqlMzOzMTGxMS+vGxubLy+vLy6vKyurCwuLGRiZLSytFxaXJyenGxqbDw6PDw6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAafQIAQEBAYh0jkQEAoFAxJ5EGAaAoSh8BBEUBSrQtGw5EodwHfgsBgeEAWijGW2XTaDRHJJExBrwl1AhUWFxgRDwdCGWkCGhsbHB0WGB5CjB8fICGOGxaJaWwGIiMfJCUTJh50dk4ODiejHyiff2oGDikqK7osiUIGai0pJyouxi+9v2pEMDEyLTIyDckCy0gBMDM0DTU2flFDARk3AH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kdmconfig-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/MTCxISChMT+/ATCxASChFxaXAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMg5gw00yyDGIAR1YUDggeFWFIZhnSBZrsZxdIOFEGTA2oeBAHeyuGwvzxBlYdUOLROMFzDQntJPrNoqAKUBaqnV+k57ZORruykHDj2LqIzUVKp1u0iuB/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kdvi-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/MTCxCH5BAEAAAAALAAAAAAQABAAAAJCRI4ZwCYPo1gsiIHHxY86KXmWdiGkCA1Wp6Htc07NOsEv2oVyldLHbuBgEhORJhOxGEkkiLJybCZ3iqrD08hmF/4CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+keditbookmarks-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCwqLLSytLy+vERGRFRWVDQ2NKSmpAQCBKyurMTGxISChJyanHR2dIyKjGxubHRydGRmZIyOjFxeXHx6fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVbICACwWieY1CibCCsrBkMb0zchSEcNYskCtqBBzshFkOGQFk0IRqOxqPBODRHCMhCQKteRc9FI/KQWGOIyFYgkDC+gPR4snCcfRGKOIKIgSMQE31+f4OEYCZ+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kedit-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBASCBPz+xPyqXERCBARCBISChMTCxPz+/FxaXAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARXEMgpQ6B4WnGzDgJHWWMYdkAwEF1QFKe2oqDZztr7GpfKjrvAAeFDpQq8ISIRYBotSoTUkiC2ostqYps49BSKIVfaBbcC4MMWcTAbU+iw21NBk+gjuj8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+key_bindings-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBISChPz+/MTCxAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANMCAoRy2IEuYIQDsrBld0NN4XaJF5iCppWxBGtCscEAbkDfH2wh+ogiudD5AhvoZWoJEFtckBTE1dzKKfQjMtUjfQUzizjeBN7HgB/AgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+keyboard-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBISChPz+/MTCxAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANBCLrR+zCIGWCcI1cLpNCa5YHZsCmj2QTlxrZmmRFVSs4E7X13TqMTXsl36gSHuSIQQ+QYP0kncPCTokzWh3LhTwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+keyboard_layout-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BAQCBPwCBMT+/AQC/Pz+/PzCxKSipISChAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARSEEgZqr1hUjFIEQXBZVogDt/XYWxgoEVFzEUt3MGNm7SND4aarPfBFQYCQmtpiTErh+ahMK1SqVHoYcvtUptX67SWDXTPXWltva5q0WfEs+WPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+keystone-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBMTCxISChPz+/MT+/AAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM/CBDcHkoFQasVUIrBe8fRNDwMAWpjUThmtmxk0IYwOaPx/V6XG3hAjmsRa0Qkg6NSOVo6F0nG88g4TUNDpT8BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kfax-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBPz+/MTCxISChERCBFxaXPwCBAT+BARCRAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARVEMhJQ6C4imEzDkLIXR4ADqFAThYRoFu4ti6YbhfdFm+aEzWgAWhB5QyGAMEwWA4PlpyFCWwOkAhCgla1EqxXKbD7vSJnyuUXyV5JuOxtqZV0z+3+CAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kfind-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBExOTDw+PExKTPz+/ISChAQCBPz6/FRSVIyKjJSSlIyOjGRmZNTS1Ozq7Ozu7AxyzPTy9ERCRBQWFIyqxPT29AQ2vOTi5IzG7DR2zNze3Nza3BQSFISy5CRyvBQenISmvBQitMzOzAQGBAw6rDR61Hx6fMzKzAz+/IzW7ASyvCwuLMTGxMTCxBwWFDQyNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAahQAAgEBAYj0ahckAoEJ5QgkE5fBYO0SeCOigkFE2DeEFgUAUNBwGBeBAcCMHirF4gnhBCBCE5PydqBBQVFhdTSgJPBk8YGRQaG4dCiQQcDh0eHyAhIiN+BHYXJCUNIggmfhUOAQgbJ6YCKGcVKSUaChwGHCYqCyuIDhkhGyIsLcccCL6TFxsNJ8fRLS7KvyNi2GIrAQwK1AsvVOJULi4AfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kfloppy-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BAQCBISChKSipFxaXPyCBAQChMQCBPz+/AQC/MTCxATCxAQCxAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARWEMgZgggz5zAIBp9GFV8oSqRkikFanapBVgccGAiJBDWL74jd4UUxGBI/IcJQMigSimPSsMDcEFCFVkptKhCDgSBB7m4sA2y5eqqMF2YYKMBgys8nfwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kfm-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBGRiZERGRPz+/MTCxAQCBMTGxPzerLy+vLy6vPyqXLS2tLSytKyurKyqrKSmpKSipJyenISChJyanJSWlJSSlIyOjIyKjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAV+IBCMZCAIQKoGw0C8MFEUqmgYrTwXL50GhtegcCgedr4AIpEYHhQKopEWSCwYw1fUeBQxGo3hiBCIUR2OxyAwG8OoD0hkICFABMiZKBKZ0GNkPiIUFBUuEoiIMisVFRZ/MWwqAheVfxICdZIpmZZ1kYIAMxcuJWWhKXl5Kn4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kfm_home-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBDw6PBQWFCQiJAQCBFxeXMTCxJyanDwyLDQqLFRSVLSytJSSlISChCQmJERGRFRWVGxubKSmpJyenGRmZLy+vOzq7OTi5Ly6vGRiZPTy9Pz6/OTm5ExOTPT29BwaHNza3NS6tJRqRGQqBNy6pIyKjDwGBPTe1JSWlDQyNOTGrNRiBGwmBIRaLNymdLxWBHxGFNySXCwqLKyqrNR6LKxGBNTS1NTW1Jw+BEweDDQ2NAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaoQIBwCAgIiEjAgAAoGA6I5DBBUBgWjIZDqnwYGgVIoTGQQgyRiGRCgZCR1nTFcsFkHm9hBp2paDYbHAsZHW9eERkYGh4eGx4ag3gfSgMTIBshIiMkGyAlCCZTEpciJyQjGxcoKUQBEhcbIiorLB4XEltDrhcaLS4vtbcJra8bMDHAGrcyrTMXHjA0NSypEsO6EzY3IzU4OdoTzK0BCAkDMgkIOjJlAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kfract-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBAQCxAAAACH5BAEAAAAALAAAAAAQABAAAAInhI+pyxudwoNACiFbuBzHt3XeEYbiBF5mN5HpyayqVrY0hdj4vvgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kghostview-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/MTCxCH5BAEAAAAALAAAAAAQABAAAAJCRI4ZwCYPo1gsiIHHxY86KXmWdiGkCA1Wp6Htc07NOsEv2oVyldLHbuBgEhORJhOxGEkkiLJybCZ3iqrD08hmF/4CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+khelpcenter-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/FRWVExOTKwCBJQCBIwaHFRSVPz6/LxSVOSqrNyanIQKDHwKDHwCBPz+/OTm5Ozu7JwCBMRKTMxubLxCRNTW1IyOjDQyNEwCBGQCBJyanMRaXNyOjKQODIRydKQqLOzCxEQCBNze3Ly6vJQKDDQ2NIQCBCwCBGwCBFwCBDw6PNyipDwCBKSipEQ6PDw+PJR2dMRiZHwSFPz29BQSFIwODJwuLMTGxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAabQIBwSCwaAQHBgFA4Cg2BwwGRUCwYxobD8YBEBpLJoEGMUA4VywWTaUQOmstww+l45MKM5/DAf0AIDSFFBiIHI3IEHCSDRgEOFSUAJhQNJ0coYikAKpB4RQwrJiycWy0uRQ2AKKQAL3wwKEMCMDEdGEMvWxIKDTICIzMQKZdDKQ0dMSAxBzMPGjRGGCkoNTYaNzTRThgnJ9pFfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+khexedit-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTC/Pz+/MTCxFxaXPz+xPyCBKSipAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARZEEgZ6rw4CB3wrJUggt03nANIoCUQoDDcvqJAaHXqunBxywFDZWArDHy4lOEwTBEKgYJRyeQJEIEnYrQsvU63abBKIYq2m+4s5mTeTLVRSFdmyy6kvGXijwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kicker-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/FxaXMTCxDQyNAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANECLrcEDDKGYQV4+qbie9eGIJEVxTe+QmjUFgnXLLr615oF8x2v0I8DWpF2GV6slkLKSMdYT4nS0WgSkXYAWUbcXgX/gQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kiconedit-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwC/AQCBMRaBPyqXPzerPyCBPzCxPwCBPz+xMTCBPz+BISCBMT+xATCBAT+BASCBMTC/AQCxAQC/AQChAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVkICCOpBicZQoEwjAE6hgQQwvH81AU8OnfuR3QYDgcgAKhjGj8+UgzQkHHw+2mQlQpgEAkFInEYnGDhr/h8VPGYDQcjcZj/iiv4u84vQ6FQCISERETgxN2AX6AgoQThlBOkCR+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+killustrator-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBAT+/Pz+/KSipPzerPyqXAAAACH5BAEAAAAALAAAAAAQABAAAANHCLrcGzBK+YK4OAcAx4AXIURj4J2fJYhWh35pOHKoG8+mFxS5HimmXU8HBH4MQyJD+FI+kM3Ug9eENALQk9VhDW4c1y/YnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kit-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCxCH5BAEAAAAALAAAAAAQABAAAAIghI+pFrHbXmpRMmoBxXB75IWcKIKk022ZunJtdlSw5BcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kjots-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPzerISChPz+/MTCxMTC/AAAACH5BAEAAAAALAAAAAAQABAAAAM8CAHc7kGsR1mc9d1Md/icIgXDB1YXMZQnZBJEIbdKABPGTbSfnuc8mw8W1OlotYER2fgod5iMKRqiNvwJACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+klaptopdaemon-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/KSipAT+BISChFxaXPz+BMRaBPyCBMTCBDQyNAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARtEIBAq5w1TBGEGIM2ESTlVUNhaAFJUAcXgAXCZkFyJEoiIArWYQjj+Xi2yfBA0SU6CuAts4MCk4EdcxbznFhOCsjrWUxRhbRBBk48Z6kCZ2GeuN9xucF8FqcEBnt1OW4saSp7IoRPEjgiGBV+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+klipper-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFQyDEwuFEQuDISGhFRSVEQqFEQuFPz+/PTy7Nze3PT29Ozu7DQyNJx6VIxuRIRiLEwuDIxSFHxSHKSipLSytGRiZGRCHDwmFOzm3HxOHIRWHOTazHRCFHxOFEwyFNTKvHROHFxeXJRqLIxWFFw6DFQ2DNTCrIRaJJxuPMSynHRKHIxqRMSqjGRGHMSifJxeFKyGXHxKFLyaXKyObGxGFEwyDKyOXIxeHKSOdFQ6FIx2THRKFFw+FKx6NKRmFKxuFLyCPLyOTLyabLSefLyijFw6FJRmJIxWHHRGFFQ2FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfFgAAAAQIDBAWIiAMGA4IABwgJCgUICwwKDQ4PEBGCEQsSEwUUFQQWDRepGJ4ZEggIDbENrxobAZ4cHa+7uxAeH4IGICEIIsbGFggjJCWCJicovLwpIcAAGCorCBbc3AoILB2rgy2u0q8OLrcAJS8wr8nJrzEy6yUz79sivDQ1jQA2buB4tU8eghw6xgnYwePcqxcdbAjq4eMHECA+ggiZMYRIESPjShyBgQPJBB48OsiokaTDOoACItgwYULJhw8BbIzzEwgAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kljettool-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/MTCxKSipISChFxaXATCBDQyNATCxASChAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAReEMg5Q6CYBiFsxhvXXZklimRlDWenBQNRzKJRXCsxHPFcIDGcILYbGHqzAY41NCQSiuNgMLPAmNTElFoFWKecqe8mCRAIq6nt5imb0TC2wZByny3zdslMr3+8fgB+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+klpq-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxFxaXISChPz+/ISCBPz+BKSipAT+BAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMhJqwUh3xqEz8EWDKT3aVNAFAVBDqYQYitbjARhGDJt34Nc4SBAZAomoDAhKAwyTZZp5XE+O0lp9QVFeLNWUpflJXheTww2ijiLKSBPW/C+xOmzjQRU8UcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kmail-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPyqXPz+/PzerMTCxFxaXIQCBPyCBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAReEMgJgrWU4iAGIUFWFYMldF+okUPJeeAUDEY7FFzXqnNdkIGDgHAKzWgsDuJAFBhbtd1peTAWDFjpaZg6skonYfOZzC3HlduuMj1UZUDZ6RMblTTDokylQYsyFwB+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kmenuedit-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxAT+/ATCxASChPyqXPz+xMRaBISChAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARLEMhAq5UY2B3yFGDIYcFgnuNErGwQCl1VzHSJBsbBUSxBIbnEC0YrxICHhFKZCiATlldn8gSlNE7YEurRQHdd19Aa3m6nmV0F448AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kmid-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBKSipISChMTCxPz+BAT+BFxaXPwCBATCxARCRAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARUEMgJgqVYWsFv3lwoeFMwEIQYkkFhouoQlIFhHvCgz9oxjoeDblc6+Q4B4ZBXCSBQx+GIZhNAOURaACsYypq0kNeSSLC2uxm5fGZqAgqFO0OjT/wRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kmidi-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/Lz+/CH5BAEAAAAALAAAAAAQABAAAAIzhI+By7oBo5RH2GvDRRhre0xiVHXZVpqfEI5iKkQxalzQIIPGhI+pSAN4cjqA68VIHvwFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kmix-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXAT+/DQyNATCxMTCxPz+/AQCBKSipASChAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARWEMgJQqCXziDG2JoUEENhZBkmHIWJVptAmqcIW/Js1MiF56TBzkckAAcHoa9nMRKeA4TyJk0knsHhTeK5khBaH2VwLYVh40TJhQ6RzeIQV32Quz8hfwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+knewsticker-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBMTCBPz+xPzCxISCBKSipISChCH5BAEAAAEALAAAAAAQABAAAANTCBCsysEpseQDI08KSPdYNmwUYSraUDRC64iAMbIuLGtOS423BhKFmgj2C+5EhsOoWEsOnB0FsKl0jnLUp3IG0O2sMNpRVHBAJpjyA8KOmNsMfwIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+knode-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAABwaDAQCBPwCBDw6NERCFJSWJAwGBLy+rPz+7IyOJJyeLBQWDIRqZIxydPzCxDQuHPTWzOSypBweDKyqLJyWJKySjPTOxKSCfOyCfOyKhJSSJJSSLFRWTDw+NOSqnOR+dOyWjOzGvNza1ERGFJSWLLy+ZPTGvOTOxOSSjOy6rLSypJSWjKSinAwODHR2HISCJOTWtPTe1Pz+9Ozu5IyKfNzazPy6tExCHMzKfPTy7KyupKSmnEQ2HHx+HKSiLKSiJPz65OzuzOTmrKSmLIyKJLS2TPTyxOzuvNTSlLy6fHx6RLy+RJyaNLS2NNTSnLy6lLy6dMzKpGxqXCQiDKyuNMS+PLy6VMTGPMzKrOzq1CwmDLy+PMzGTNTWxMzOxERCPKSiNCQmJERCRERCHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAAQABAAAAffgAABAoQBhoOEAgOGBAUEAocBBoOLBwgBBAkKBAsMAQ0ODwOWEBEBEhMUFAQVFhejCBYYGRCGGhsKFBwdlh4fICEIIoMjBRQkJSYnKCkWCCorLIMtLgUvCjAxMjIzNCw1KoY2NxovFDjbMjk6OjuHNjw9Pj8lMggIQEFCATaDBD4JhhApgsDIESFIkigxJGDEkiJFmDQB4uQJFBxPokgRMIVKkypFrFxBgCVjlnuXtARQUGTLFS4yunipgRLBF0I3moChgsQeAg5hxDBMNCUAlyAcOCBKxJTQmKVNBfgJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+knotes-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBISChMTCxPz+xPwCBPz+/ISCBPz+BMTCBIQCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARIEMhJZQg1z6vzxR0VCKE4gCE2lhcRnF1LuAInBjNRfDMn64WCQRCcHS6IRE6nyB0Sx0ACkcwloFiflKp8Pm2bbRblkYJZHX8EACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+knotify-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/Pz+BPyqXMRaBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMyCLoQznAFIUKE09krZ+VS9XBaMBBbZKIBUaSYa40kTIPNhyvazje+G2gFI8l8jaLCnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+konqueror-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxONCROfCRKfKx6LNy+bNTOpGSS1DRupAwyXBRSnPTSjPTqvOzqzMzSvHSSlKy6ZDxutAxCpBQ2XBxepLTKvPzqzPzy5OTShLS2dLSqRFR2jBRerBQ+jOTixOzetNS2XHx6XDR2tCRexBwyTDyKzOTavPzq1OzKdCx23BRKtCQ6VCQmHFSa7IyirOzSnGSGpIR+bFSO1DyK7DR+5CRixBw2VDQuHFye7IS27NzGXISuhEyS5DR25BRWxBQ+lBQyXCQqPCxSfGyu7GyerKy2ZFR+rERqfCRmxBROtBQ+fBwuTBwmNDSW9JyabLyqRIx+TExSXBQ6bAQCBBQ6ZBxapDR+zBxq3LyaLJySRHxqPGxeNBxGbCRmrHRyRERONDRKNDQ2JCQuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAeygACCg4SFhgABAQIDh4MBBAUGBwgDCYcKCwwNDg8QERIThRQVFhcNGBkaGxwdoYMDHhcXHxggISIjEiSvJSYXJwsoISkpIyorLIIDLS4WLzAxMjM0NSo2N8o4OS46OzwzPSk+P0BBgkI8Q0NERUZHCEhJSktMgwk4Qy1NTk9QUVJLphCiUsWKlStYsmjZQiJgIS4KuijQ4iXAFxYCDVFJwGUFmDBhMjYSw0KMyEYoBfkJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+konsole-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXFRSVPz+/PT29OTm5OTi5DQyNDw+PERGRExKTHx+fISChIyKjHRydFxeXDQ2NCQmJBQSFAQCBERCRMTGxHR2dGRiZExOTDw6PCQiJAwODCwuLFRWVOzu7BweHAwKDCwqLHx6fBQWFGxqbGRmZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAanQIBwSCwKAwKkMslEAgSDqDRKqBYKhkNgcDggEorkMrDQchkNhuOhgEQkk0l5S2lUGpYLJqPZTAwMHB0DCmhqAW0Rfh5zAxgOkBcCFAcfIBMECxwBBAEPFw8dChkhcBMDDAcdnQqtFKSWcQMimx4dGRkQBxGxsg6bBQEawx8jl3GnJFoFHRNXVVNRJYIFDAsL1tgiDiQXFx0HABwcXeQH5OjkRutEfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+korganizer-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBASCBISChFxaXPz+/Pz+vKSipLy+/MTCxPz+BPyqXLxaBAQ+BPy+vAAAACH5BAEAAAAALAAAAAAQABAAAARmEIRJqw1ikM37FsFQjMZ4lAVKBESBjCYsFiuBkkk5KG1dJL+CZjBYMES+l2x3RCBqtxHBOFD6DkHmAQj0yXgzmFdIhY2erBJBwTiczDSWq0Eg1gvYrvyHxcMdUEojYWIYHocbDX4RACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+korn-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBMTCxPz+/PwCBMQCBFxaXISChKSipAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARSEMgQpL03CEExDkO4dR6ghSFBkJa2CSlRcNX0voNQ5Ebn3pvdAWHo/W6IHUJwGFCAm+SrSTm+ZgcY6XnDhlim3wwxKNYymiX17HmCSxO4/OKPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kpackage-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+xERCBMTCBISCBDQyNAAAACH5BAEAAAAALAAAAAAQABAAAANPCLoR+7AJ0SALYkxd79za12FgOTlAQBDhRxUFqrKEG8PyOqwEfMeKwGDI8zVGul0vFsAFdaxB43ecKZfUKm1lZD6ERZgBZWn0OpYvGeJPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kpager-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBFxaXISChASChATCxKSipMTCxDQyNERCBPz+/MTC/AAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARWEMhJZ7hADFI4+RpwBYBxFJ1HmMiYJUgiJPI8Bwmp7HyvyBOfMCHR+QwzhAAhMvZKSFgRIOwtJczqboFoBasGGVNUKVNGaEyTlEYL1sX2pYXOyO8XfwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kpaint-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPz+BAQCBMTCxPz+/PwCBPzCxPz+xPyqXASCBMQCxAQC/AQChPyCBATCBMT+/ATCxASChIQCBKSipISChAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAV1ICCOYxCI5kmigTCYBKGW7WAH8QyYrn3LNFesYDgEjCVXIRYzGgWqgA2BICQUx9pMSkUssgsbFOWighW+7c24KDAKDccjCjVCHAEGo/GYl+wPLwwRfF8oT2mDAwuGWVJiARERAxITJkhaJhMSlJY7NDQpAH4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kpixmap2bitmap-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwC/AQCBMRaBPyqXPzerPyCBPzCxPwCBPz+xMTCBPz+BISCBMT+xATCBAT+BASCBMTC/AQCxAQC/AQChAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVkICCOpBicZQoEwjAE6hgQQwvH81AU8OnfuR3QYDgcgAKhjGj8+UgzQkHHw+2mQlQpgEAkFInEYnGDhr/h8VPGYDQcjcZj/iiv4u84vQ6FQCISERETgxN2AX6AgoQThlBOkCR+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kpm-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxKSipPz+/ISChAQChMTCBATCBPyqXAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARbEIBAa5BYUsHF+FQ2EUTHfUOoFQVpeuAVGAbrnmg603U7FD8UxXDgGQgoYMyAIBoSyI9Sx2seoj/lRlDFTmUBDs0L0gg2CGwFs93oWJdMOwCPiybhguout2f8EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kppp-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAAT+BGSOhERadDxKbDRKZExWXKzG/KzO9KS+tER+lBQyNERaVOTu5PT6/OTy9Lza5LTatISylHSilCQ6LNzq9MTa/LzevKzKzIS6dBwuZISi9MzizLTW3Iyy1IymjHyGbCwuLDRGXHya3HSe9Jy+/MTe5Pz+nPzmhOTSbGyGXGx+XCwyLHyinISe/NzifFRKTFRqXCQmJExSVFyafFyC9MTCvAQCBMTCxExKTDw+PMTGxLy+vNTS1Ly6vMzOzNza3MzKzHRybERCPDQyNPzCxPQODHR6dAwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAengACCggECAwQBg4qDBQIGBwgJCouDCwwNDg8QERITlIUUDhUWFxgBC4mKGRoGFQcbHB0eHyCLISIjJCUmJygpKiuLEywjLRYuLy8pMDGLATIzNMk1Nck2lCDJN9TcLziKOTg63DvcPD0ygjk+P9zcQDVBQekAQkMgPjzcPfLy1wAgiBQBAYIHkH5BbPwTBGKIQBBBjAQBsXCRDYJGZFSkJOhIM45+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kpresenter-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwC/AQCBMQCxPwCBAT+/MTCBASChATCxPz+BPz+/ASCBAT+BKSipAQC/AQChARCBCH5BAEAAAAALAAAAAAQABAAAARhEMhJq70YhM2D5UIYDARHBUWxEcRgHKgncWyLuPEc1MOAJLfBRsNSEBYbH8kw3BEUyABjZHzJdsiGI6AYLBQG5qykDSy+jwdLpimj1aVhe7tIr00a6Q4uP02dfRVygRZ+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kruler-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBFRGDPTijPzmnKSGDOzWdPTahOTGXOzOZOTKXNzCTNy6RNS2NMyqHNSuJCH5BAEAAAAALAAAAAAQABAAAARkEMhJKwg4643FEIQHimHRfaiYmoFxvMLhwi5r3IaA37rBIomgABhEDBM/hHLJVCBYCwFjYVxQBdYFi8GQertSLqshaJgFZbK5wXI4BO63W/Bwt+HzON7BKvj/gIAcgxoWhhN+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kscd-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBKSipFxaXARCRPyqXPwCBAT+BMTCxMT+/AT+/PzCxASCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARbEIRJa5Ui672nsNYgegFhFoRhCuJAEgcsE+wYfHIc0y3JbT2QsOJCGG+/zyShMCICregEsUgEnNCe6/rsPkPTY2LxZLEOh4DEqbBmRQyGen0kjgB4ySSPp+D9EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kscreensaver-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXAQCBOzu7Ozq7OTi5Pz+7Pz+xISChHx+fMTCBARWlARepOTm5ISCBNze3ARalARanKSmpARSlHzC9ARGfLy+vKSipARKhAROhARKfJyenNTW1AROjARSjMTCxJyanNTS1JSWlMzOzNza3MzKzJSSlMTGxLy6vLSytKyqrAT+BIyOjPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAalQEBgOBQYj0fhYEAoCAyHqPRgDAyIggPikOAeFFVCYMHImqnfaiPAKH8VcLij+ghAGJFFlnuUCAJ1ExR5AnACFRUWF39/CxETXQoYGRoaFht/HAEdE2AeGRgVFBUfIH8hmx4doBihGokifyMPAiQcISEjJR+7HyZ/JScfFigpKSoSFxsiKywCAEjR0QDU1AIJFi0tFgnP1dYJ4QgJ4+Xe1tLTAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+ksirc-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAAT+BMROTPz+/KQGBFxaXAQCBDQyNGSGzDRivAw6lAQmbCRGlAw2jHSS1BxGpAwiVGyO1CRWvBRKtJSq3AxCrEx2xAxGtAw+pAw6nDRmxAQmZAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVYICCOQBCQKCoMaRsMbCvPNE3cRA0QRWEciIQigQLyfAtGqtFwPI6GFgQReex60WJEYr36UpOtQgQlUQAVieUyLoskY8Bhi3liEZJ6MaOmWCgJGjYGhCl+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+ksnapshot-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBATCBFxaXISChAT+BASCBAT+/PwCBPzCxAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARLEMhJKw3YViw6HkRgBUVnCkG4GUV5otthsO6A3KJEHm6R3AOYTtAy2QqzHCDwMpiSk8DsxIFGpc6T9YJ9GpSb7laDSYI1yzNa448AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kspreadcalc-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BAQCBATCxARCRASChAT+BMTCxFxaXEQCBPzCxPwCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARPEIBAq5U4iM17wJMwjORIfJkYFCs7nKA2rJQLp0Su66ikGcAg8OYTGA6BA/KAIIYsFudPGJQal8uAFVqxUg2JxBYbUGh7k5J6BppwKyB/BAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kspread-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBAT+/Pz+/KSipPz+BAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANFCBDc7iqIKUW98WkWpx1DAIphR41ouWya+YVpoBAaCKtMoRfsyue8WGC3YxBii5+RtiEWmASFdDVs6GRTKfCa7UK6AH8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+ksysctrl-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBISChHx+fPz+/AQCBAQC/AT+/AQCxAQChAT+BLy+vAR+BAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARYEIAgqK1YzsG754QUDERpmkEpkkXrtoK6EcVgHIibhnNx564Yb0TDvQq7FQ34EiqPOhnREqhWSUPsyZSQAbbg7GcMEgwUiYVivTa1R+y4XEGoWO/4AMAfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+ksysguard-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBExKTERCRERGRAQCBFxeXKSinIyOjJSWlKyurKyqrKSqxPTy9LSmxNzS1Nzm7JyitJyipMzOzLS2tOz6/OzW1Ozy9Oy6vNyCjNRydMR+lNza3LSurFReZMTG3Pz29OSmrMx6hDw6PKS2zMTCvOyytOSWnMzi5MTa3NTS1LzCvNTe5Pzm7PTK1PS6vOSapMyKjNTy9KzCzMzS1GxqbISKxOzq7Ozm5Oza3MyytLzS1Nz29OTy9LTS5GyGtOTe3MzKzOT29OTm5KS2vKSurNzy9LTW5OTi5Mza7NTm5KS61KyytOT2/HyChHSChHx6fNTy/LzKzMTCxLS+vMze5KSmpLzS3Ky61JSSlLTGzLTa5FRSVJyanKSipJSWnJyWlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfagACCggECAQEDBIOLAAEFBgcHCAgJAYqLAQoICwwNDg8QERKXjQYTFBUWFxgZGhsJHJcdHB4fHxUgrCEiIyQCjRwWthUlJiG7IycoKQQBKisfLC0uLzACJzExMjMBNBI1Njc4FTkBOjs8PT4/3UBBQjc8FkNEQTtFRUZHhyQySEkHOAyxgOCcEhkSLC1ZwSRGEx1OnBx4EgNKFCmKAkyh0uNADBpDOpyQ0YNEAEJVIFjBZg/bFRIRSAXAwiFLDyNaesiYEJMRgS1cupDg4OXLFlI+DwkQgBSAn0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+ksysv-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/MTCxISChIQCBAT+BAAAACH5BAEAAAAALAAAAAAQABAAAANWCLoQzlA5IVyIK1S9L7PDsFHBIJXDFFaViYYEUQpy6orEqq12Aw+FmkjQQxEKwQCBSCz5BrGYkuc06nKU4s8gW4q0UAN3+q3CZJfJRhJ6fDwZOGbhTwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+ktalkd-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBKSipMTCxARCRFxaXASChDQyNATCxISChAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARYEMgZqqXU6gCuDIJQDQTBBQX3hUFpmN2hFaxhIPCJDrRo46dPglf7BTvDXsB2OwaSCd8tZ0kWgZ3Uk+hDvHRV5bfyybACPNmkY2EVZKpM5UBPre8fD94fAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kthememgr-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBASCBATCBAQCBDQyNPz+/MTCBPz+xISCBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAReEMhJaw1V6Bs0HgIWYFMnhSERkiU6ekM1FO9IGMcxIFK3jgGDzRADhAypQipI7A0OId1IaGhKntHDjWogTLCB3JbpvULD2ir5i0SPDYjy9ZgWDuQUwqBLLFq+ehZ+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+ktimemon-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPz+BHSG5PxSVDRW9PwuLPQKDFze1AQi7CH5BAEAAAAALAAAAAAQABAAAANDCLrc/lCFGeKi1YktAH5c92mcR4HloA4P4RLAyjovLLdvvD5FX+gqgGFoUPh+N2IRcAQcngch0ehzQqVDas/6xBb9CQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+ktip-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBGxubFxeXAQCBOzu7OTi5NTS1PT29Pz6/Ozq7Nza3PTy9Pz+/Nze3MzKzMzOzOTm5MTCxLS2tKSipNTW1Ly+vKyqrMTGxJyenISChAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVwICCOQRkIY0oORFEYqCoGw4EcSaHEarAgDESu4RioBIMfA1doPIwpZGJBhTQMEWh04GoqDBLtCKkYNL5hGUAwoZQfFYs46lBQLnK1SICJUCR5egMZGBgZcyoDGAwTh3oiAxMMhogpioyOjwADnIh+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+kuser-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxISChAT+BMRaBPyqXARCBPz+/FxaXAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARLEIRJa5Ui673nsGAgeKE1Bl9AUEXbiqTlFlZaGUZoszm4BzhDAVf5BYbAXI+TAR6CS2ZGSZSEiIIqYIsSIEaJ7GRrlY7J1lKA7I8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kview-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPz+BAQCBPz+/PzCxFxaXPwCBPyCBPzerPz+xASCBMTC/PyqXATCxMT+/ATCBASChIQCBAQChISChMTCxKSipARCRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAV0ICCOYxCQaBkIwpmKJsu6qDkIREDMZFwUAYNwRVuxgLfDAUGEsRIJo2LRapUE0ABDsa1aAcZoo+stsnIMwcDQcDQUV9MjF4Q4GJFiQJJuGSYOFHkwezJ+ExUUEicmYDITARATAoomLiuQJhKTlTRgepYBfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kwin-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBFxaXISChASChATCxKSipMTCxDQyNERCBPz+/MTC/AAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARWEMhJZ7hADFI4+RpwBYBxFJ1HmMiYJUgiJPI8Bwmp7HyvyBOfMCHR+QwzhAAhMvZKSFgRIOwtJczqboFoBasGGVNUKVNGaEyTlEYL1sX2pYXOyO8XfwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kword-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BAQCBPz+/FxaXISChPwCBEQCBIQCBMQCBMTC/ASChARCRAQC/AQChMTCxAAAACH5BAEAAAAALAAAAAAQABAAAARiEMgpQ6B4WnGzDkLIeVs4DAIBWFcpnKJVzCUcz8ZxVOKN/AWNKRQo5HQYELHwQxQSHR7HqDuwMIRisxBQLBbRFdUaYCwYjUZHywIxGI53K0jolRkJdLkhtKwaeWpJYW0AfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+kwrite-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBKSinJyOfPz27Pzy7AwKDExOTJyWlERCRKSelPz69LyyrKymnPz+/MS2fDQyJAQCBOTazLSiXOzivMS2jKSSVOzmxPz25NzSpPTu5KyebOzixNTGjOTWpMSydMSybCwqFGReVKyaXNzSnGxeNJSCVMS2nPz23MSuZIR+bJyShLyqnOTOtGxiXIR6XOTSvIx6RMSubIyCdKSalMS6pOTWxMzKvKSabJyKTOzezHxuPGRmZKyurMTCvPTq3AAAACH5BAEAAAAALAAAAAAQABAAAAajQIBwCAgIiEhiYEA4FgwHRDKhIBAWz4OhgGQ0FAPHA7qFEBONb0Qy0ULeQ2+aUrFcMI+3GYBOZzQbHB0eHyAhIQByDREiEwMjFRIkJQImAgJ+jScjHigkKSorLC0AKg2NFSMoki4qCy+IQgITKDAxkjIzNDWkQxQoJaskMgk2Eb1DNzgoOCoHDDY5yEIwJToAOzw9ET7TQiREAhkZ3kmy5QB+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+laptop_battery-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/KSipAT+BISChFxaXPz+BMRaBPyCBMTCBDQyNAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARtEIBAq5w1TBGEGIM2ESTlVUNhaAFJUAcXgAXCZkFyJEoiIArWYQjj+Xi2yfBA0SU6CuAts4MCk4EdcxbznFhOCsjrWUxRhbRBBk48Z6kCZ2GeuN9xucF8FqcEBnt1OW4saSp7IoRPEjgiGBV+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+laptop_pcmcia-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwC/AQCBMRaBMTCxPyqXKSipFxaXASChISChMTCBPz+BPz+/PwCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARfEMhJaw3Y2iDGyJoUEIVRfIHGEcaBHCc4jcWbGG2cAuuhKIZE4mX68EgI3M/wORgQGAHr4HICD4NCKoBIJqsv7w6DKDgNi0VuN+O+GIxFl00hlxjakIhbo4cwfnoWfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+locale-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/AQCBPz+/MTCxISChMxKTKSipFxaXERGRGxqbCQiJDQ2NJQaHMwmJDQyNFRSVOR6fGwSFNxSVKQqLFQODJwaHOyGhOySlNRCRMSuBPz65PzupPyCBJyOLMxyJOTKRLSiNIR6JExCFGxaHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaPQEBgGAAYhcWjUMAUEAMDQtIIZRauBaZhKhwIsFjBgFu9HgKHrHNI9QYQCQQarWB313D5Ik68BxgIDQwOCgcJD2wBWwENEBANEQwMEBITFEIOQhWNkhENFhcYl0l/GRobHB0MGBAeo1QdHxsaICEfpyAiQlQhICMiHyMgs8FKASMjRiK/yLrGStDRXNFGfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+looknfeel-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAASC/ERGRExKTLy+vKSmpAQCBPTy9Pz+/IwKFLQWNPT29GwOFExOTIyKPHx2NPz2pIQSHLwWNMzGXFxaLLSytERCHCQmJNze3GxubLS2tHR2dAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAWNICCKgVCWYwoEwUAMhXEQhhocRuHCMpIgiJVBptC9DojDIrFYwRS4wgGJZAIYuwL00Ej6FjOGEXZwPByQCNjAyrnKj4NkAqYUBIIoXC5pVGYUFgIXU2Z8fgdGFhgZiRqHf1EDFgCJGAcafX9aUSIFlxoFBX8vMYmemKJSY6Ijn6oHF26tKbAEGCaUKX4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+lyx-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBAQChARCRKSipASChFxaXISChPyCBATCxPyqXMT+/Pz+xPzerPz+/AAAACH5BAEAAAAALAAAAAAQABAAAARZEMg5Q6C4BnGzHsRgeVZRGIbYaekxuAFijUGRBOqMKPxlJQsLQxjoVWyWBsMxNEp+iRuj2VvVCklHLCZjiRrawGFmNQUajQ129RwYyCMSau2pcNh1AB7jjwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mathematica-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBISChPwC/FxaXIQCBAQCxAQC/KSipAQChPyqXPyCBEQCBARCBASCBDQyNCH5BAEAAAAALAAAAAAQABAAAARlEMhJ6wxChiFFCBUhENtQGIcBUghWDsHxWck7wMpKfXz/ZYBAYeCpKRQLWwkjMCpQJQ3TE8gdUgxPUMDlflINhzfocJB6BNEDqLnKpgRLTJZjBuIUAf1TExR0EyRASWmAFocAfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mouse-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBDQyNKSipPz+/MTCxISChPzCxATCBISC/MTC/AAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARSEIRJqw0Sg32rAANBFNwlhIQhGkNGAaSaouW0iYUBEIdYgzsUIqHAuWAoQlGEE9gMJKaU8IPupqLWy3qVkioAFqkLc9nCg3G5oxFr2ecavOOPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+mozilla-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/JxqBHRKBGw6BHwuBHQuBKwmBKQmBIRWBGRGBMQeBKwaBHxSBFQ6BDwaBEwqBEQuBGQuBFQOBGwSBGxGBHQ+BOQiBPQmBLQaBKQaBCQGBIwWBLQeBDwKBHQSBGQ+BIRaBHweBIQWBNQiBKQeBJw6BPxGBNQuBLwiBPwmBKweBIQiBJQmBHwyBIxeBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZzQIBwSCwahYHA8SgYLI2EwpMoMBwQU2FCsRAYGQ3HwwGJSCYPCNnRoAgrlgsmo8hkLJpNpEjhbBYdHhYZEh9HICEiGRMjJAxPJSYmJxkoSocjKSorExYNSwMXLAwgDhYVSwUtRAMORwGfRR8uRpdGWEJ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+multimedia-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBIR+hKSipPz+/MTCxMRaBMTGxOTe5MzGzNyytPyqrPyurLz+tKzqrPTy9LSytNTS1Pz6/Nze3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAWAICCKQWmOKFAKQ9uWacAOJcEWQjDKrxHYJZxONRAQaL+c76DjyY4D4A+RC9B8xkPiQKCySsjAQZAojHMva9pk8iGrCsWC0Wg4HCvT4wApyO0FEAcRJhKGhzUEioolDw8TgYQBEYITCIQqE4IRCnQOEXyYJAFxCwt1dzAxbCcjfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nedit-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAAQChPwCBAQCBPz+/MTCxKSipFxaXAAAACH5BAEAAAEALAAAAAAQABAAAANDCBoK8TAC8Vy8QUyGr9BaFwmDZonZp66sIhBwLBMFlRl4rhv1IxiDoHDYuw1yw2Dxl0wugTqnjdkUPmezJWv7QXX8CQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+netscape-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAEyStPwCBNTKrHRqPAxSfLR6VNzWvAQCBEyOrFxGPMSWdKx6XPz69Ozm1PTy7NTOtOTOxKRqRGxCJPz6/MzGnMS6jDwmHEyGpPz+/Hx2bGxiPOTexFxWNLSmhMy6jLyGXNSqjHxSLLyuhMSyhLSqhDQeDJyWdJyOVNTKtPTu5KSONMS+rLyqdMy+lFxSNOTezKySPEw+FEQ6JKSOPDw6LNSylHxSNKyWPLSeXExGLDQuFIRiRCRCVEwyJAwODLyyjIx+TNzaxMy+jBwaHNzGvMS2hMS2jKSWXGw+JFw6LKR2XCQ6TDw2HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAAfVgAABg4QCA4SIBAQFiAYHiIQICQoLAQwNDg0PgxARg4oSChMOBg0UAgYVBRaDFxcIGA4ZGhscHB0eHISKoxkfARsHICEiI7oBrg0kGiUfpCEBJiIngygbKQ0bG5kjKisbFSwtAi4HLx0cBwYiMDEyJh4zMjSKKBQuNTY3Mb8vODk6kLky0GEHjxUyeiigMMPHJ0UCKvw4sQFIECEqhgQUSCSChRFFWhg5MkMjkk9JlJRY4uIEixk5fOhAsuOkqyFLXF1oQYOJTiQIAigaqohCD6JD/QQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+noatun-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBCQ2PARehAwODASCtASi5ASq7JTK5PT29MzS1JyipISGjAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARlEMgJgrg3zDHkCEQoEhrnVYXBDUVRdmagHjT7AnExHPtg3LldzYXr4FA6juHnMXZkqaiGMpEtOdOmETpAIEy473fV9Xphq7P6DEgMFIpFWm1sJ+4JBec8SFAnd3pveH+AeHcSfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+package_applications-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAFxaXGRmZFRWVARehAxehFxeXOTm5MTGxKze7JzO3ITC1HSyzGSmvFSWtESKpCx6nBxulNze3MTCxAQCBByezByWxBSOtBSGrAx2nAxqlARijARafARWdARSdARKbARGZARCXOzu7Pz+/Pz+9Ozu5Nza3Pz+7NzexPz+5NzivGxqbGxubNze1NS+vPTCvMzKzLz6vLzevPwCBNzevAwOBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADIALAAAAAAQABAAAAamQEBAMCAMikfjQMAsGA6IhGLBaDgeEEJEMhFIJBRKxXLBYDKajeTQBQAGG05n7vl8QABBNyTq+/8iIyRdJSJrgCMjJiYnhCIHEn+JiygpXQaGB32JKgErKiuNAoV+iQIGLBItLhOOgYkrmAYvLikwl6+Lo5gTtjFdLMHCKy8vEyITxV2tzBMFMTCWIgYlEzLX2NcwMy4vstngAS4tLyUGNODprdl+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+package_development-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/GxKFAQCBNSyhFQ2FOTGnJRuNOzWtPz23FRWVERGRJSGNMyyZHRydOzu7PTy9Ly6vOzq7Nza3JyanMTCxHQCBLxWVKQaHOTm5NyOjMxqbJQSFHwGBDw+POTi5LQiJJwWFPz+/Pz6/PT29NyWlMReXNyenLQqLIwSFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ9QIBwSCQGBMWkMDAgKIuBgsH5FBIO0+oSka0mFAsGtdpwLMbPxONBgCDJEQkEMnkn1RLKRGF3+CtCDRJ7AoUSEgAWFw+AChB8hYUYGRobHIwAHZGbHh8gayEhIqGiIw9+GBgSJBoliiGUrhcOJq0WJyAbKBUhnrocDr4ofkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+package_editors-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBLS2tHx6fOTm5Ozq7OTi5Hx+fPTy9Ozu7PT29Ly+vMTCxPz6/IRuPHROLPz+/LyOdLSCTNSmnOS6vPzmzISGhExOTJSCZPTSxPTKtPS6jPSujNyKZGxqbDQyNDw+PHRaTKRqVLRqRLxqTMxmPOR6NKyurDQqLExCRFxKLKRSFNza3KyqrKSmpDQ6PGwyBNze3NTS1LSytAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaWQIBwSCwahwFA8kgMOAVLpjMgGBCixamgECAYsELtoUAuXJtPRCCRMBu44ecBoVC0F2aC8qkIKBAICQx5X3INh3UMbQMOD05/AQ0QDQoMERITFBUVThZ1Cg0XFxgZGhobHB1KHp4NCR8gISIjJCQlJmGsCAULAicoKSoqDytIrAkGBCwMLS4vKTBNrAUJCzEBMjMuM35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+package_favourite-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBPz+xISCBMTCBPyCBMQCBIQCBPwCBPzCxAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARYEEgZwrQzVyFq6Bj1gQOxgcBYDSzhnl7Azm7tpWT7VhdHmoFXzweqmYZE4I5C5AQKhkMAYbCMfM9EIWBAIKzNLNRbTRHCBUT6ewn6TOlyJuX2sOftS8YfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+package_games-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBPz+xISCBMTCBPwCBMTCxMQCBPz+/KSipISChAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEEgZwrQzVyFq6Bj1gQMxgsBYDSxhqunKtu5bpSQdFDfFkS9DgHD5cTwBIdFnFLiSw2IzGGX+AocDNHQ6GhCJQCJsGRqThm/CoMBUCNc1W9HWmD2Jdsh+CfkjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+package-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+xISCBMTCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANECKoR6ys2IVqokF08yMTA1gwkYX5WQK5ma4VceTYPxXnBWdtY6+0834/Bowgzm6APWRQcH4TiMhPK2WYRiZWW7XK7/gQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+package_graphics-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAASC/MQmJPz+/LwuLLw2NLQiJNTKVNTOZOyydNRaXMxGRJQmJFQuXFRypFySdHS+VLTOfNzWhJQeHFwCBGyGtHyqlIzKdPTapAQCBGRCbKTSjOzqxLzG3MzmxJyanBQSFJSSlBwaHCQmJGxqbFxaXNzmxPzmzOSenExKTLSytAwKDAQGBMTS5LzerOSaTFRWVHR2dJzOhLTKdNyiNDw6PFxeXDw+PLSmvKS2zIyynLzSjNTKXNSGNIx2lIx6tISavNzSbLwmJHRWfNzWfIRurIyexOSmPJweHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAejgACCg4SFAYWIgwECAQMEA4mCBYwGBwgICQoFhowLDA0ODxARCAQSkp0TgwwUFRYHFxeLARITGIUZFBobEgUBC7aRHB0eBcC3iRgfGAIgISKRGCMeIhgkJSYniBkoKSgqKywtES6bgy8iMCgYyhwxMjOb7Bg0NTYr7Dc4OTo7PPIrQoRgJ6iHjx8xgMwIEgmAkIMxhsw4lYgBkSI5LEQwcsRPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+package_multimedia-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXHx+fHR2dGxubISChNTS1MzKzLS2tLSmpNSytAQCBOzu7Ozm1Nza3MTGxNS+vOy6vPy2tOTStOzq7Pz6/Nze3MTCxOzOvNTqvLT2tDw+BOTm5MzOzPy+tLz+tLz2tOTi5LSynLz6tPz+/NTW1KSipMy6THx6fMTKxKyOLNTGVPTmbLTOtBQOBBQSBKySLHReFLzKvLzavAQGBCQiDNzKVOTSXLSWLNzGVLyiPNTCTOTaZLymPMSqROzebOzeZMSuPBwaDMyyRFRKHAwKBOzibMSmPMy6RLSaNLyaNDwyFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfKgACCgwECAwQBg4qCBQUGBwgJCgsLiwAFDA0OBg8QERITlYMFFBUMFgYXEBIYGRoboxwMFRQdCAoeGR8glAABBgshFA8BCxsiI5QklY4lJQYbJiQbypQnACgpB5ALy92UKissAAQXDyktlBUuLzALMeG+MjPKNDU2LDc47yqC1Qs5dODYwYJHj3f/Yrxb4QPHiR9Aqr0I4kNFDCExdgxRQaSItyA8jJw4YvFFjBdCGtCotECFjhssVgRR8W8QkgVJlOBb8k3UID+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+package_network-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBPz+/CRKfERCRAQCBFxONKx6LDw+PDR2rAwyXMzOzOzq7AwKDHSSlKy2ZDxutAxCpExOTBRavBQ+fBQ2XOTi5OzWhFRSVBw2VGRmZDw6POzKdCQ6ZBRKrCQmHAwODIyirGSGpIR+bCRixBRKtCQ6VDQ2JBw2XIS27DRKNISuhESK5DR+5BQ+jCQqPCxSfFSa5Gyu7GyerOzetBw+XBwuTBwmNFSa7Eye7DSW9JyabLyqRBQ+dBRerDR+zDx+3Bxq3LyaLJySRHxqPGxeNBRSnCRmrHRyRERONDw+NCQuLCwqHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAeygACCg4SFhoeEAQGJigIChQEDBIIFBgEHBAgCCYMBCgQBCwyhDA0ODxCcAAqRihGXiooSExSCsYoVDBYEFwEEEBiCrBmgGgUbigMcHRgeth8gAR8hIgQECyMkJSaCAicoICkqASssvi0YLoIvMDExMg4zrjQTNTaDCTcxODk6OwQYJmCYNIhHDx8/gAQRMoRIDRcEBwkoYqTIkSMFkNiISCjBCR40UiQxwdGQEg9LSvoJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+package_settings-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBISChGRmZMTCxKSipLS2tHx6fPz+/OTm5FxaXOzu7DQyNMzOzAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAReEMhAq7wYBDECKVSGBcbRfcEYauSZXgFCrEEXgDCSeIEyzKSXZoBYVCoJVIqBGByKu0Cy8QHxmgNngWCkGgqsGWFseu6oMApoXHAWhWnKrv0UqeYDe0YO10/6fhJ+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+package_system-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBGxqFAQCBPz+/PTqtOTOfMSyPNze3Ozi5KyeLMTCxMzGzKSipOTe5MTGxAAAACH5BAEAAAAALAAAAAAQABAAAARfEMhJQah4ihFunsFAEIVXCVJACIJhoBK6CerawsA8HAhbuAnYZrBDKBYMWpCy4S2QSRazyBIwrrjcoNFQzK4KR1bQcHhZjGM2BgWLMYJ2enForHPJtNj+kfHvcB8AfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+package_toys-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBJxyLJRqJGxKFIReHKR6NJx2NMSmbEwyFKyGTMSibFw6FMSqdCQWDIxeHNS6hAQCBDQiDNS+jOzexCwiDCQiHLyeXFxGHLSWXJwuJGweFHQiFMx2bLRGNGQeFNTClOzSrLxKPLQ+LLxOPGxOHIxmLEwWDOzatNS+lKyKTIRiJJx2PIRmPJRuNKyGRIReJJxuLKyKRMSqbKSCPEw6HNzKnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAauQIAQEBAMhITCcTg0CA6IhGJwICyYwgWjEQg4HIgHBCuMBCCSM6FBHiIOk4cg0hYiKAFFxUJBtC8YGQgBFhAaBVdMAw8bHB0eHh0cGh9LAAMgAxAhHiKPIxAkH1cXEiVjJiQnKCljECoWCAgEFGUrKBYsYwARKnQIRxG0Ky0QtAAIvwcuAwQpLxDCGDAIMTKyMSczs7sQATQz2mMIMyAXu0IQNDUu6AgQ6EPwu35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+package_utilities-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBExKTERCRAQCBOzu7Nze3MzKzLy+vCxqZBQ2NJyanKyqrGRiZDRydKza3FRWVPT29LSytDw6PMTm5EySjCxaXGRaJFSanCRSVGxqbPTmvMSqVJTW1GSurHS6vOzq7KSipISChFRKHJSGNPz23GxKFBQ6PKyurCwqLMyufJx2RAQGBJSWlEwyDIRiLNy+lLSKVDwmDJRuNOTOrLyabGRCFDx2dKSCVOzWtHzCxOTGnNSyhAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAahQIBwCAgIBAOiUiggFAyHASKxDAwUC8Zg0HAglA9IZPGQABoTSqJCFTIOEIsFgHBcEhhHUpKJFCwaGxYYHB0VEx4IEh8gIQwiIyQbJRMcHokmEicfDygAkCkqJQgIGG0rLElCLS4vMCWqQwMCQg0UMTIzNDVLQjaIGDE3ODQlS785CEkxKjowvEOHybG4O6JDCdNKuDUxRAmxRDHeveUAfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+package_wordprocessing-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBHx6fPT29FxaXPTy9AQCBHRydPT25Pz6/ERGRIR6PJyORHR2LDQyNLy+vNTW1Ozq7Ozu7LSiVKSiTIyKJJyenMTCxMTGxNTGlNTSjLyyRExGTExKTBwaHOzivMy+XBQWFExOTNzOhIyKjFxeXDQuNMSyjNzOnBQSFNTGjDQuLCQiJAwODCwqLGRmZHR2dAwKDCwmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAafQIAwQCwWhcihYMkUDJLIAKG5fEILhoOAgGAmCgXFgsEoNByOxwMCiTTAEsmEAq5ULJbLxQEuYCQZGn0JGwkcCR1gCUIeHyCJfX2JIUIHIiANCQMGIwYkCSUgi0KPHSYdJyAnKCkdHQ1IrhgdGCC1s7UqSCsdKLi0wL2xHY/FxMcssS0JIS4vIy8uIQktHUkgKygsMNwwKCAxUOLjAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+panel-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/FxaXMTCxDQyNAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANECLrcEDDKGYQV4+qbie9eGIJEVxTe+QmjUFgnXLLr615oF8x2v0I8DWpF2GV6slkLKSMdYT4nS0WgSkXYAWUbcXgX/gQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+panel_settings-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBMTCxPz+/PzerISChPyqXAAAACH5BAEAAAAALAAAAAAQABAAAANKCLobwRAG4SJw7w5BswoEkQXbRn0h5ggF14FhbIhb68SiOgnbLRsPEovjwwVLRIdhCfwMiR/VZ1A7WS4tntWyynquq+01+h1//AkAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+password-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/MTCBPz+BISCBPz+xAAAACH5BAEAAAAALAAAAAAQABAAAANECLrcGi6CIAKUKwxSb/ZasXWPMFwBQRQiZwlqAVnEGbRwKz/ndMep3QNUqKV6kpQh6HFoCIaBMDmQTpOsJsaC6XoZ/gQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+penguin-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/ISChPz+BMTCBISCBAAAACH5BAEAAAAALAAAAAAQABAAAANHCLrRsTC6F6UId1TYiNtMQRQNqARDOlAgJrzlhr7vqlUufbHMoMO8k+8XY4yGtc9pREIORKRTYVoYDgxUVmBqmGCLJzDYnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+pixie-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXPz+/DQyNAQCBKSipPz+xPzerPyqXPyCBERCBISCBMTCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARdEMg5Q6C4BjEGyZIlCEFHfJQonEERnB8sE6RxIMkAnGtPBzacjqBQLBiMxS+Y2xmRx+WtSTgmkwQLcwhNKqRCz3VRBOeGvh5wqpPMzO3JQFBguWAYxeiNwnRAEn4RACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+plan-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxPz+/Pz+xMTCBISChASCBMRaBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEIRJKwU4iD23FwEmDeAwBGYaZiehWutEFK6JqtlM7KZhHhOJbuizIUKBHVGFOOaUPgPlGEsSDNjbKWBgcT0oX5CV2qakIg24OTGA0sxjeSWpUC2ivESf90cAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+proxy-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/KSipFxaXAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANGCAHcziuIuFy44045WxhZpkxCB4GEKA1lpIAiVG7XB1bjPMHxqds3y++S6nGOL1ikpYlkbBSZM/oYfXBVaS8LuXCr2IY/AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+pybliographic-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBMTG5OTi7Nze/NTS5LSuxOTm/MTCxGxaFIRmFJR6JLy+zOzq9IRqJJR2HLSaNKSirNTOxKySLIR6VLS2vOzu/LSqhNzOXHxqNMzK1KSGJHxmFKSabLy2pIx2JJyCJIRyNNS+VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZhQIBwSCwaj8WAEplULpkAZ0AQgEaVA4K0alQWDAdEQrHgNguMRsHxgJiJgcEg0pA4Jk84ZVCoWC4TGG9CAQkZGnUIG3lDAQocCh0eFB+MjRsgIAsLIYNwASKCnk2WVkR+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+realplayer-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIYAAAwWVBwC7BwC9BQC3BQOvBQCtBQCrBQCvBQO1AwKPAwOVBwC/AwGnAwCXAQGNAQCJAQCHAQGLAQGTAwKjBwG7AQCNAQKRAQGDAQCBAQGJAQGPAQGFAQKVAQGBGRiZBweHFxaXDw+PExKRBQSFERGPFxeXCQqJLy+vAwCjJSanFRSVLzCxJSSjIyGhGxubNTW1KyurAQGHAwODKyqrHR2dBwO7AwSZCwqRDQyLCwuLAQKFAwSjAQCLAQCFAQCDAwSbAwGbBQKvBQCzBQC1AQSNBQKtAwOdBQKnBQCxAQabCwOLDQSNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQABAAAAe/gAABAgGFAwQFBgcIgwEJCguRDA0ODxCXERITFBUWCwMNDxcYpKUYGRobFQEcFx0dGLCxrx6kFQcYHyAhIiIhIyQlJiekESgYHikqKywtLi0vIDCkMQQbLiQyMzQgLDQzJSCkMjU2NzIYOCYyOSYmH+gYOjUBOzw9PT6mGD4P/AORahj4IaECBFI9gAQhJSSSw0g2fGggsEAIw4eRhhBhEGBBgCKkjAgZSRLFESFIRibZx5KlkpYtlbyEuW+Jn0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+remote-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBDQyNISChJyGPGReLAQCBMy+hERCHKSipAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARFEEgZqp0Y1KxD9twEapg1kqhwBgKFvqIIjgMRdy4wFIaNbiiCYXDIAUcH328EQsxiIBXAqWn9MtTSTZLNybizEweY8UcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+samba-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIUAAAQCBDQyNFRWVASC/Pz+/PTW1OyytNTW9LSy7PTGxOSenNx2dMTG9Jye5OSKjNxiZMw6PIyK5GRi3AwODMwmJLQCBCQmzPS+DPTejPTaJLR+DPT21OzqtNT21MTCxPTyxOTmnNzedMTyxPz6/ISChOTijNzaZMzOPIzijMzKJLS2BPT29Nza3PTmxKSipOzu7LyGJPTKRNSeDFxaXERCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAMALAAAAAAQABAAAAacQIBwCAgIBsjkAEAoGJgHxFC5TCgWAEajyFUCHA8IICJhTggAr4NSGVsAF8wlnSQWBYLMRUNHMjccTB0AGh5dfh8gIQAiAAJCIyRCfiUmJwEokARok0slKSqPApukAZNDRpqbkZMjSROOI5srLAGwS34tGgEuBCMvAjCBA64ALRgxuyzAMnItQmgaMRcypjMByNR9QjQ0adzeaX5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+scsi-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/MTCxKSipISChAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANCCLoQwZAFIV6UYgxi79Qa52WDE3bKV6YOpFpO3L5pJcckLBB8/wQEDezWAQpZqIWxFNAUkqkg6HmJOqGuArUqwfoTACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+style-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBOzqBLS2BPz+HPz+rPz+BPz+lPz+zPz+9Pz+1Pz+nPz+hNyuhPz+pIQCBMTCBIQyBPz+/MTCxFwmfCQiJIxOrHw6nJRWtJxmvJxuvJxyvAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVvICACwWieYiCUwVCiKVEEhjHA6YEcxooHBURCsXihaAYGglEzngKBhsMmMDhH0YcBAu16SY2IKiApm81RMXTCblPelDCrXJlI6hSL5SJOSewVdRMUGHtGZICChHsmZHeAgxkaG41/bWxnjV6bUH4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+terminal-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBMTCxISChPz+/MT+/AAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM/CBDcHkoFQasVUIrBe8fRNDwMAWpjUThmtmxk0IYwOaPx/V6XG3hAjmsRa0Qkg6NSOVo6F0nG88g4TUNDpT8BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+wabi-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/ISChPz+xAQC/AQCxPz+BFxaXAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARUEMhJgw20XsHxvIEwcKQHBESaDkShmqhKsMb7tW1RHPwOH4ZdYcBDGH+8A2JgLH2MzZHAJgmRBAgZAabNqg7cJMGb5BKSZF4Yfb5Uzmp3piqfS/wRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+window_list-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCRiXCRaVPz+/CRmZFRWVISGhMTCxESSjPT29DR6dDyOhDyCfPTy9CxqZOzu7Ozq7ERubOTm5ARehAxefPz6/ByaxBSOvBSGrAxynAxqlBR6nBRylAxmhARWdFxaXCH5BAEAAAAALAAAAAAQABAAAAWHICCKQTCeqCgMhJCihXEYSPuKRWIoC6PYsEZikHA4FA4CEJdoJh4QgXRwiOAeQudDIpEZIpPwhCImhyGGAmBSOVgumExG055w1ZPZhpPpUDwzExBqAAUDhxUVTQ0QEgWOOIcDiU1QjoSFFYiKDZYFmAWJlE9bkCM5iouWpiIfBa6frrKYAH4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+winprops-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPz+/ASChATCxISChFxaXKSipPz+xMTCxMTCBPwCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAoALAAAAAAQABAAAARXEMhJqwxAjM23wBMhjGQJEFKhriwrGUcsE3JsvPWBFAAiT7BaIYAA/HAxWk9CO9wAwd0SkJA9g8NiomnDoYqnHDAGroqRyVy3F2i7326LnKKo2+94hT8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+wp-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBAQCxAQChKSipPz+xPz+/ARCRFxaXEQCBMTCxPyqXDQyNPzerISChISCBASCBERCBMTC/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAV1ICCOZDkGgSgMg0AUZWAExyHc7YCQclLYtxtieAoUEApFUIBgnRYMhUHRCDYcDoUIRUhOlYLkYwcIDLvSpAsBiYx0CPQUgXNv4V0ZWEByDBgRcTMGDislTX+CMgISJk1+AQ4zWiYiCCiRDmRbmJ2eKZWhAH4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+xapp-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBISChAQCBAAAACH5BAEAAAAALAAAAAAQABAAAAIyhI9pIa0nYAtPUGlTRszJ10UA8xiNRZZmJKoA25boqW7npeHvlKRHyIn9aKYaz6XwFwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+xcalc-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBISChPz+/AQCBCH5BAEAAAAALAAAAAAQABAAAAI4hI9pwe0Ogpi00hHF2LzzzFlTsIHD45SSx6oCeW4wjK2tl83y7t64pIsJaxrfh2bEAJIlhRPhLwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+xclipboard-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/MTCxPz+xPzerMRaBISChCH5BAEAAAAALAAAAAAQABAAAANICLoQwdBJIaRjgYbBR66Lo1nfowTER61aWGRd1y5GyrLm+QrxMJ81FQ4T2MV+jUPwBgpVdrdcQ6AUIj8Ha/N06Hq/UpLY5E8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+xclock-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAALy+vAQCBPwCBMQCBIQCBISChPz+/MTCxCH5BAAAAAAALAAAAAAQABAAAANbCLHcrSLKOZcYmDSCsR1aUABAsXDDJwJGa5SBFwgaWxbCG3CWaBwG3C8Y67FawpYiNQscg65fsVkYuoAmJs1pBR522lQB6ILJLqHRwQQOZzYdZnw+dzruDIA/AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+xconsole-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/ISChMTCxAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM7CLrcGjBKCYK4OGcohv/gxw2aRgyjYJXCmVpr5loke82dfaO03vI5Ha5mwxGOyOSRF2qKKpMoxEFl+BMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+xedit-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBMRaBPyCBMQCBMTCxPz+BPz+/KSipFxaXPzerPyqXIQCBARCRDQyNISChCH5BAEAAAAALAAAAAAQABAAAARnEMg5gw00yyDGIJi2FUHhDWEWeEXrgaphHEOBJF8KBLKyLINEIAHbyA6/hbDACDSMBt9PIBA6n4HfIElFXTeKg2LbtTSeu7BiPegIvuA1mwrfOB5r4PusCjimZmgUF4F8IhJnhiJ+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+xemacs-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBDQyNKSipPz+/FxaXISChMTCxCH5BAEAAAAALAAAAAAQABAAAANJCBASoXCFoVi8VdL6HHQeB4YjSAxnYQygSLzoSTjbEs9vMF86cbyH34NX+AELQ4zO+Nopm6cBC1PBEQwG6gd3SGo7Xa1STIb4EwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+xeyes-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/ISChCH5BAEAAAAALAAAAAAQABAAAAI4hI+py50Bw4lyBiEggFjvi2VcqIFhdnaDSabZKrbjS3W1OHz2CkJD/vHlKD/Er2g4Ah3MptPgLwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+xfig-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+BMTCBISCBARCBATCBASCBCH5BAEAAAAALAAAAAAQABAAAANQCLocwbAJ8SIMYgwHHO9Opk2V5xGEplZK0alaui0eDLOB8QTykOKGQ6mnKQWFPILDN8sdng7l69c5CjuKAHNnZb2KnUOhcG3MsmMv7aK2+BMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+xfmail-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPyqXMRaBPz+/AAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANACLHcAVCJSWcYLwaxSPAXBj2bswyiIlUWSr5muGhbdaZjTd1ZzvKMFaOFcbCIpiOnGGs2FM5gLkLrTalQLMCfAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+xload-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+py+3hEoxnUmBpyBjNzWXfJnkGKJ4dBlbjS7Jni9Zsjec66hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+xmag-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBKSipMTCxPz+/IQCBPyCBMRaBCH5BAEAAAAALAAAAAAQABAAAANICKrR+6+JIRxkc4RBww1TQBBNB21io2rRRKpltaDvis4hvJmzBmuslo+zkZ0yu0rBcwJ1AgXD8gJQMaJTaqRwyGqvzO9M4U8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+xosview-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIMAAPwC/AQCBPz+/MTCxAQChPyCBAT+BPz+BAT+/PwCBAQC/AAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARFEIRJa5Ui663HFEQojqEXCAVhrCxLmGB4kCJM03aIHEdC5rfaJ6UotlavT3AEIxaNLuAyd2wlT0thYMDter0BiWU8AfgjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+xpaint-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBPzerMQCBPz+/AQCxPz+BMTCBASCBPyCBPzC/PyqXMQCxIQChKSipMRaBDQyNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVtICCOYmCaZGoKLBuMbykMA1EURFwCgWAQwKBAxxMQDocgAjEkrYAsoS6QGEYJCgWhWVq4tgJGY+iAVbcBB5jLq/aMbzJsYXK0Arky7JFY+BcJDyckDgEPh4d1aUSFJ2l6ARApDpSUKkQpmSJ+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+xv-16:apps apps16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/AQCBPyqXPz+xPyCBPwCBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM8CLrc/jC+oIK9Lgg7RuietWhCSWkkVZUbEBBnWxXFSVP1eLt7kPM3X86nEhJrtx/P0tuNilCVZEqtNvwJACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+3floppy_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBMTCxARmZPz+/FSWlLSytKSipERCRIyOjISChOTm5HRydNza3GRiZFRSVASCBARCBDTSJIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVrICCOQBCQKBkIw5mqLFG47zoQ+FwbN57TosDhgPD5dMEEIqE04kwlBWKBUEiNVYFpyqAyGEUCgqEtERiNNMLhQKzLQYJg7n7Y4aMAwbCUPvAQeWNgfzQQETAIhSMQEogwgBITQEGGEREmfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+3floppy_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxARmZPz+/FSWlLSytKSipERCRIyOjISChOTm5HRydNza3GRiZFRSVCH5BAEAAAAALAAAAAAQABAAAARcEMgJQqCYBjFu1hxReN82EOhYGieaklJwHIjrqnGCJLqNWhUFYoFQCG1FgWXIIDIYNQKCoawQGI0swuFAbKsxgmDsfZjBkwDBsNM90Jot9A3DbBD0Dwiur9QnfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+5floppy_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBFxaXPz+/DQyNISChASCBARCBMT+xAT+BAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARMEMgJQqCYBiFu1sIwdJ+0hSKZnZw4ehPLoW88c0Q7X7JABLlbp+eT/UyzgpADqwgKxKYpeIMZQNWJ4YBhWRHcrgpgQCSkJu3hYPFHAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+5floppy_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBFxaXPz+/DQyNISChAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM+CLoQwZAFIV6UYox61cwaF32UtlkLSYFnulJEuT6qQATxW9W2enurgo6CaggKvKIn91K6mh0gMepydqwAfwIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+cdaudio_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tOzOvNTqvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/LzKvMTCxDQyNASCBARCBDTSJIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAa0QIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTBqUiuUCVmAeiYzmsKlwOt/AAKFIFAIIFx4WHyAhUwIDIgsZFyMkFxchJSYmiBkSBBoIJJwIGgOhiCYFJSEnFyQjFwNZewABISAfFiYnCAEmCREIrwAIFhwVGwcaBAkPGApsQsAVFA0GBQMRbxBTKM0ODQwTEq192ClDgROkBHvYKuNJUu5CKCorX1RDKCkpUn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+cdaudio_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tNzmvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/MTCxLy6vDQyNOTm5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAapQIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTLqUigWsuDwSmMxBQ9lwvoEBQpEoBBAWHRseHyBTAgMhCxgWIiMWFiASJCSHEgQSGQgjmwglGKCHBQUSICYWIyIWAwshIVMBIB8eFSQmCAEFCREIekIIFRsUGgcZEgkPFydrvxUUDg0GBSEREGJfv9AMEySsJxDYQ4DcEhh64UpS6lTs7QB+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+cdrom_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tOzOvNTqvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/LzKvMTCxDQyNASCBARCBDTSJIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAa0QIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTBqUiuUCVmAeiYzmsKlwOt/AAKFIFAIIFx4WHyAhUwIDIgsZFyMkFxchJSYmiBkSBBoIJJwIGgOhiCYFJSEnFyQjFwNZewABISAfFiYnCAEmCREIrwAIFhwVGwcaBAkPGApsQsAVFA0GBQMRbxBTKM0ODQwTEq192ClDgROkBHvYKuNJUu5CKCorX1RDKCkpUn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+cdrom_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tNzmvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/MTCxLy6vDQyNOTm5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAapQIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTLqUigWsuDwSmMxBQ9lwvoEBQpEoBBAWHRseHyBTAgMhCxgWIiMWFiASJCSHEgQSGQgjmwglGKCHBQUSICYWIyIWAwshIVMBIB8eFSQmCAEFCREIekIIFRsUGgcZEgkPFydrvxUUDg0GBSEREGJfv9AMEySsJxDYQ4DcEhh64UpS6lTs7QB+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+cdwriter_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBFxaXISChERCBMTCxKSipAQCBMTCBPzCxPz+xPzerMT+xDQyNMTC/ASCBPyqXPz+BARCBAT+BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAWIICCKgWAGYyoKA+EWhGGogOAaB6Lr8ygUCYWCkEMoEovBSHZUFI8LGYloODJkhWijMbMdiAwBQEbYxmpExFlkgN3QrliXAcvNAuVt4coYKtQ9BlwLCQQFMAlVSmwEUX8IB1UJiQAObEE6BA9VEDMOEUsDDzoHkZ4LoCkyqyIOCxI9NCOfETJ+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+cdwriter_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXISChERCBMTCxKSipAQCBMTCBPzCxPz+xPzerMT+xDQyNMTC/PyqXPz+BCH5BAEAAAAALAAAAAAQABAAAAR3EEgZhA0zSzGIL4RhaIDgGQeiquMkFImiECmiJMswibdS3wsRhWa4MUSFYKMxMh1oDAFARFiGSjTEVWIAnbCeUJMBSo0C1WXhyJgptC0Dc5EgFECJoo5LCL4RB0UJeRkGMSoEDkUPLYUDDioHgY0kIpYkmJkAfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+dvd_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tOzOvNTqvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/LzKvMTCxDQyNASCBARCBDTSJIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAa0QIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTBqUiuUCVmAeiYzmsKlwOt/AAKFIFAIIFx4WHyAhUwIDIgsZFyMkFxchJSYmiBkSBBoIJJwIGgOhiCYFJSEnFyQjFwNZewABISAfFiYnCAEmCREIrwAIFhwVGwcaBAkPGApsQsAVFA0GBQMRbxBTKM0ODQwTEq192ClDgROkBHvYKuNJUu5CKCorX1RDKCkpUn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+dvd_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tNzmvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/MTCxLy6vDQyNOTm5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAapQIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTLqUigWsuDwSmMxBQ9lwvoEBQpEoBBAWHRseHyBTAgMhCxgWIiMWFiASJCSHEgQSGQgjmwglGKCHBQUSICYWIyIWAwshIVMBIB8eFSQmCAEFCREIekIIFRsUGgcZEgkPFydrvxUUDg0GBSEREGJfv9AMEySsJxDYQ4DcEhh64UpS6lTs7QB+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+hdd_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBDQyNIRuVKyCXMSKROzSrOzKpOTGnLSafLySZKxuLMSOVPTWvPzixLSehNyibOzOrGxaVJx+XOzGnFw2FJRuPKx+TPTSrHRWPKyKZPTOpHxOJKyKXFw+HKSipISChMTCxFxaXIRiPNSWXExOTOS2hLR+PLRyLPTWtMyOTASCBARCBPz+/DTSJIyKjIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaTQIBwCAgYA8SkMCAYDARI5ZJQMBwQiWgyoFgwrA3HQ7scQAqFAcEQOUi0zAkFUSFYLghMBloUCDQNGxwdHhwHekcfICEhICIfIxkLJBABJUYCICABIhAOBiYnKJaXmH4CGSkYCCqkSAEfTKenrkOwsrQll0IrS7G5uwArLLaxLbXCLsTFLyDBKy4wZEVHvCwsRn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+hdd_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBDQyNIRuVKyCXMSKRPTWtOzKpOTGnLSafLySZKxuLMSOVOzOrPzm1LSehNyibGxaVJx+XOzGnFw2FJRuPKx+TPTSrHRWPKyKZPTWvHxOJKyKXFw+HPTOpKSipISChMTCxFxaXIRiPHxaNLRyLNSWXExOTPzixOS2hLR+PMyOTPz+/IyKjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaIQIBwCAgYA8SkMCAYDARI5ZJQMBwQiWgyoFgwGgiD46FdDiCFwoDQAEe0TMkEQSFULIcLBloUCDIaDRscHRsNHhhHHyAhISAiHyMkJSYQASdGAiAgASIQKA0pKguXmJl+AiQGFwgrpUgBH0yoqK9DsbO1J5hbsrq8SrgstlJFHy0gwMVFR1J+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+memory-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBISChAQCBMTCxCH5BAEAAAAALAAAAAAQABAAAAI6hA+Bu+HCmgiiRuNoHZBRXQlc84TmcHzm2WVryE1YvMaZIdbVd2zw7lj4bDKGbxK8hHgX3K2JUDD8BQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+mo_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBKSipDQyNPz+/MTC/PzC/ISChASCBARCBMT+xAT+BAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARTEMgJQqCYBjFu1hxBeN82iCIJDgWaYhtntC4ZCzItdhWOD7mdwHLrAAczoKViIh6Vto5lcDjglppp9UpCTALULRaASGS5E4TCnB2rFyqJO5Gw+CMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mo_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBKSipDQyNPz+/MTC/PzC/ISChCH5BAEAAAAALAAAAAAQABAAAANHCLoQwZAFMV6UlBB759Aahw0FGEITZZQmlwoqq1UNDA/xLDhvhQ8rnKPh4f2EropjcDjAhpJl8ylaBJhTaCelvRC7XqLXnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nfs_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBExKTGRmZPz+/ExOTMTCxAQCBDw6PCwqLIyCRHxyNCQiJOzmxMSybFxSHHRmLIx+NFROHERCRFxaXASCBARCBDTSJIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVWICCOZGmeaEoGKiCwwUAI5zsUBnAUQ0CLNhxLFEDwDAnFzTAsBRYJRsORSwUeDUiEWYtJIhFj7+eKCUdPHmxyNj0nFABXRam0RBSLvZW/VFN1FQYGfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nfs_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBExKTGRmZPz+/ExOTMTCxAQCBDw6PCwqLIyCRHxyNCQiJOzmxMSybFxSHHRmLIx+NFROHERCRFxaXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVLICCOZGmeaEoGKiCwwUAI5zsUBnAUQ0CLNhxLFEDwDAnFzTAsBRYJRsORSwUeDUiEWYtJIhFj7+eKCUdPHmxyNj0nOa6q2qrbW/4QACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+printer1-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBFRWVPz+/Ly+vISChMTCxFxaXPT29DQyNJSSlHR2dERCRFRSVERGRBSmnExOTExKTAT+/NTW1MzOzMzKzMTGxLy6vLS2tGRiZFxeXOTm5IyKjISGhLSytKyqrGRmZNTS1Nze3Nza3Hx6fKSmpKSipAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaUQIBwSCwaA0ikkRgQDJCE5LFgOAicUKUwUCAgBuDE9RkFcL3ggbgQUCwYyIIA8VU32ASDwoEcIAoHCQkHbA8EBBARSX0DXQEPEgQCDYpJExQVAWCHBwcNDUkKChQWBBcYARkanaABExsbHB0FGB4fIKoHAWYhpCIBIyQLJSAJGbtbULUTISa4yEVJJSbO0EtmUkR+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+printer2-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBKSipAQCBPz+xPz+/MTCBISCBISChMTCxFxaXAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMggqrwYVDGGzRLXEZ0HhgMpFIXxZZzRBsHxXquAUHqCCBgB6YcoFhNAXMWISCQOv6Dt6DMmQwQntHjwXTVL6mH83Ry31qBO8CSQSmVg2GM74aAVij2UTPojACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+scanner-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/MT+/ASChARCRATCxMTCxFxaXKSipDQyNAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARTEMgJgqWBVivEldkUdKSXhVjZfenommglDERh3Tc4E4ZRHAGgkEPr9X6H5AHBERSMRyWzkug8jQXFEhWoOo8dRYxqLXSmGjIJnVaz29Q3fAP3RwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+tablet-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBMTC/Pz+/MTCxFxaXKSipAAAACH5BAEAAAAALAAAAAAQABAAAANECLrc/iosCUEQlEYdRp6dZ4lgKBBEp1kmmpLRMBQu6qWLEdYBn+81F0wnC8oCK+LAQDgGDIaG0vOMPnRIaEUBtW6//gQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+zip_mount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BAQCBFxaXMTCxPz+/ASChPwCBKSipASCBARCBMT+xAT+BAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARTEMgJQqCYBiFs1lwwdF8VEsR4YVuXoirYFcWbkmY31wPqma2ZwReqBEODQutwEY04oeWqMniGOEzW4HAVZAEImVSCSLDGYIX5/EMoFtNSOWHxRwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+zip_unmount-16:devices devices16 16:photo:16 16:R0lGODlhEAAQAIIAAPz+BAQCBFxaXMTCxPz+/ASChPwCBKSipCH5BAEAAAAALAAAAAAQABAAAANICLoQwZAFIVyUNIx6WybE9kBTFYIiVhXFGXJetbYDaHnlathZk2eDQunw0GwomeGoMThmKETS4PAURCMlZccHXXYct60Y4E8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+blockdevice-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMT+xAT+BASCBMT+/ATCBAT+/ARCRPz+xARCBPz+BATCxISCBDQyNMTCBCH5BAEAAAAALAAAAAAQABAAAARhEMgZwrwYBCFsvhs3eF8wDMJAVBVmnupazKRmGDFxzMVBBjcDQXfYHRA/QmKpKBYRSMoysVgwGEeoJ1ClLhpXhlbiqJobjcA1Sn48qug06+JwP+I1UMCNzmcqaR8lghN+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+chardevice-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/AQCBMTCxISChPz+/MQCBPwCBAAAACH5BAEAAAAALAAAAAAQABAAAANCCBDcHkoFQasVUIrBe8fRNDwMAWojMTZmtmzByp6v7LQhTOLadbkxj3AUWZAcxcUgyYwQm8wYoOCCLgoGK5Nq9ScAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+desktop-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBExKTDQyNHRydFRWVKyqpGxubExOTERCRLy6vFxaXBweHFRKPFxeXAQCBIyKjCwqLMS+tKyurDw+PNze3ERGPPTu5Pz+/Pz6/Nza3MzOzKSipISChOzq7NTW1Ly+vHx2ZOzm3Ix2XJx2XIyOjKyqrJSSlPTexPTixKR2VKxyPCQiJPTy9JSWlHRmTOzSrMzKzJyCbKR+XCwuLOTi5CQmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaeQIBwKAwIiEjkgJBsAgoGwcE5RCQUgAWj0WwcHA8FRLhAcIcKhyIiMSwcwglc2ABTDA2Eo9KQoy0PFxgYGRobDxwBDHRgF44YHQ4bHgkfHBUMHQ8gFp2dISIjEQwfBwIkJR0mICcoJycpKgweCisAEAcPGSwtLi8vsQkNtkMrBxswCQ8uMTINY0kzBCQwNB/DVAArBC0NNdlDM9BDfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+file_broken-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXDQyNAQCBMTCxPz+/KSipPz+xPzerAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARWEEgQahVijMmD/oRAbBw1FCgaFFrppeo5didsZTSMDoRBSi/dgfUz6Va7HPIQGB6KnpW0EEB4Oshp5ZlTFRBfFs3ZLDihtTAYwZ14nGbzoS3JfO4ffwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+file_important-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBExGTKQqLPz+/KQqNAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM7CLoQwZAFIV6Es15Jqd2ZtzXUMIhXZqJYaZ5aK7zwp6h0zc05i+c6Eg8oCnWOR0eHQGEKnEWHdDoF+BMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+file_locked-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXDQyNAQCBMTCxPz+/KSipPz+xISCBERCBAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARTEEgQahVijMmD/oRAbBw1FCgaFFrppeo5didsZTSMDoRBSi/dgfUz6Sq7XGp1CByKQZUUWjsgrtcENYXNUodWhAahVRa65G9hmGgnnpzMZ/7xRwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_blue-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBwWHMzKzOzq7ERCRExGTCwqLARqnAQ+ZHR2dKyqrNTOzHx2fCQiJMTi9NTu9HzC3AxmnAQ+XPTm7Dy67DymzITC3IzG5AxypHRydKymrMzOzOzu7BweHByy9AyGtFyy1IzG3NTu/ARupFRSVByazBR6rAyGvFyuzJTK3MTm9BR+tAxWhHS61MTi7Pz+/IymvCxulBRelAx2rHS63Pz6/PTy9PTu9Nza3ISitBRupFSixNTS1CxqnDQyNMzGzOTi5MTCxMTGxGxubGxqbLy2vLSutGRiZLy6vLSytKyurDQuNFxaXKSipDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAECg4eIAAMEBQYHCImDBgkKCwwNBQIBBw4Bhw8QERITFJYEFQUFnoIPFhcYoRkaFBscHR4Ggh8gIRciEiMQJBkltCa6JyUoKSkXKhIrLCQYuQAPLS4TEyUhKb0qLzDVAjEFMjMuNBMoNcw21QY3ODkFOjs82RM1PfDzFRU3fOggcM7Fj2pAgggRokOHDx9DhhAZUqQaISBGhjwMEvEIkiIHEgUAkgSJkiNLmFSMJChAEydPGBSBwvJQgAc0/QQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_blue_open-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFOzi1Ozq7ERCRCwqLPz+/PT29Ozu7OTm5FRSVHRydIR+fISCfMTCvAQ6XARqnJSKfIx6XPz6/MzKxJTa9Mzq9JzO5PTy7OzizJSOhIyCdOTi5Dy65FTC7HS2zMzm7OTSvNTCnIRyVNza3Dw+PASq5BSGrFyqzMyyjMzOzAR+zBRejBxqnBx+rHRmTPTy9IyqvDRylFxaXNze3DRujAQ2VLSyrDQ2NNTW1NTS1AQ6VJyenGxqbMTGxLy6vGRiZKyurKyqrKSmpDw6PDw6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfCgACCAAECg4eIAAMEBQYCB4mHAQgJCgsLDAEGDQGIkw4PBQkJBYwQnRESEREIoRMUE6IVChYGERcYGaoRGhsbHBQdHgu2HyAhGSK6qxsjJCUmJwARKCkpKsjKqislLNIRLS4vLykw2MkRMRAGhDIJMzTiLzDXETUQ0gAGCgU2HjM35N3AkYMdAB0EbCjcwcPCDBguevjIR0jHDwgWLACBECRIBB8GJekQMiRIjhxEIlBMFOBADR9FIhiJ5OnAEQB+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_cyan-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBwWHNTKzOzq7ExGTCwqLERCRBSKjBRSVGxubKymrNTS1Hx2fCQiJMzq7NTy7IzKxHR2dFTW1Ey2rITKzNzy9JTSzBySlHRydKSipDTW1ByelGzCvIzOzByOjFRSVCy2rCSalGS+tJzSzBxudCR6hCSCjITGxMTm5Pz+/JSutDyChBxydCyOlITKxPz6/PTy9Nza3ISqrGSyrOzm7MzKzDQyNMzGzNze3OTi5MTCxNTO1Ly6vLSutGRiZKyurHRudDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe2gACCAAECg4eIAAMEBQYGB4mDCAkKCwwNjYUOAYcPEBESlBMMjAUFnIIPFBUWEBcYGQoaG5gGggMcHRUeFh+fGCCVIakiICMduiQWJa4fCKkdJicoCcjJKSrPAAIrBSwtLtMv1jDaCDEyMgUzNC3SKCA12gYFMjY2KzMzN98uLdo4cujYoa9BAx4IeSywJSgAjgU8evTIgdDHj4WJHAL54cPiDyAMIzkMsSGIkCGREAU4gAOAn0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_cyan_open-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFNze3Ozq7ERCRCwqLPz+/PT29Ozu7OTm5FRSVHRydIR+fIyCdMzGxAxOTBSGhIx6XJSKfMzKzERGRAxOVKTq5Mzy7KTW1Ozi1OzizEzSxGTWzHzCvNTq5OTSvNTCnIRyVNTS1BzKvCSalGy6tAQ6XMyyjMzOzDw+PByqtCR6fCyGjHRmTMS+vJSytDyChCyWlGReVOTi5AxGRKyurDQ2NNza3NTW1AxKTJyenGxqbMTCxMTGxLy6vLS2tLSurKyqrCwuLFxaXKSmpDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfEgACCAAECg4eIAAMEBQYCB4mHAQgJCgsLDAEGDQGIkw4PBQkJBZcQnRESEREIDwoPExSipBUWFxgZGhIXFwkbHBQToQQGFx0eHxoguhEXHCEiIyQGABclJiYnycsSKCkjKisAESwtLi7Y2soXLzDUAaMxMuYuM9kXNDDiAAYFBTU15NGTYeMGNQA4ahAgkEMHiQoxZrTYwWMfIRw9fKio8MMHECAReByUhIPGDSBBhAyJYDFRACJFeBi5cCSSpwM4APgJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folder-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBwWHMzKzOzq7ERCRExGTCwqLARqnAQ+ZHR2dKyqrNTOzHx2fCQiJMTi9NTu9HzC3AxmnAQ+XPTm7Dy67DymzITC3IzG5AxypHRydKymrMzOzOzu7BweHByy9AyGtFyy1IzG3NTu/ARupFRSVByazBR6rAyGvFyuzJTK3MTm9BR+tAxWhHS61MTi7Pz+/IymvCxulBRelAx2rHS63Pz6/PTy9PTu9Nza3ISitBRupFSixNTS1CxqnDQyNMzGzOTi5MTCxMTGxGxubGxqbLy2vLSutGRiZLy6vLSytKyurDQuNFxaXKSipDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAECg4eIAAMEBQYHCImDBgkKCwwNBQIBBw4Bhw8QERITFJYEFQUFnoIPFhcYoRkaFBscHR4Ggh8gIRciEiMQJBkltCa6JyUoKSkXKhIrLCQYuQAPLS4TEyUhKb0qLzDVAjEFMjMuNBMoNcw21QY3ODkFOjs82RM1PfDzFRU3fOggcM7Fj2pAgggRokOHDx9DhhAZUqQaISBGhjwMEvEIkiIHEgUAkgSJkiNLmFSMJChAEydPGBSBwvJQgAc0/QQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_green-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBwWHNTK1Ozq7ExGTCwqLERCRByGRBROLGxubKymrNTS1Hx2fCQiJMzm1NTy3ITGnKSipFzShFSydIzKnMzq1Nzy5JzSrByKTBweHDzOdCSaTGy+jJTOrFRSVDSuZCySVMzq3IzKpBxuRCR+TCSCVGy6hPz+/JSunDyCXCSOTCyWVCyeVPz6/PTy9IyqlCSCTGSuhPTu9Ozm7Nza3Dx+VBxyRDQyNMzGzNze3OTi5MTGxMTCxLy6vLSutGRiZLSytDQuNKyqrHRudDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe+gACCAAECg4eIAAMEBQYGB4mDCAkKCwwNjYUOAYcPEBESlA4TjAUFnIIPFBUWFxgZGpWXjYIbHB0VHhKtER+UCyC1ISIdxbkSGSMYJAiCByIlJicaxbgoEhDNAAYpBSorJScnLC0uHRLaCC8wMAUNMeAnMgkz2gY0NDUFKTYNBDE3cKzQlkPHDh42djRo0KNhjwUGBgXIscAHgQY6fPz4AQRioolBhGwUIiRIxEiEhoCYQKSIEZSHAhzIAcBPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folder_green_open-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFNze3Ozq7ERCRCwqLPz+/PTy9PT29FRSVHRydIR+fISCfOzu7OTm5OTi5MzGxAxOLByCRJSKfIRyVERGRKTmvNTu3KTWvOzi1OzizIx6XIyCdFTOfGzSjITClAxGJOTSvNTCnNTW1Dw+PAxKJCTCVCyWVGy2jAQ6XMyyjMzKzByuZCR+TCyGVNTm3HRmTLy6vJSypESCXGReVLSurDQ2NNTS1MzOzKSipGRiZMTGxMTCxJyanDQyNLSytKyqrCwuLDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfCgACCAAECg4eIAAMEBQYCB4mHAQgJCowLAQYMAYiTDQ4FCgoPEBESnBMUExMIoBUWFaEKBRIXExgZGqoTChscFR0epQYTHyAhGrkUIhMcIyQWJSYAJygpKSrIyissFi0GABMuLzAv19kaMRMyM+ABojQ15ObYEzYz0wAGBQUbBPHkYNQQcQMcABwEEhLIkUMHjRQvTuzIRwgHjx45evTwMWPGiR8GJQGxcWNGkBtCTlBMFGDIgh9CJhCJ1OkADgB+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_grey-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBExKTBwWHMzKzOzq7ERCRExGTCwqLHx2fKyqrNTS1PTy9CQiJNza3OTi5GxubJSSlISChLSytFxWXDQuNKSipBweHISGhFxaXIR+hLSutFROVHR2dFRSVGReZKymrLy6vFxeXNTW1Pz+/KSepERGRPz6/PTu9Ozm7DQyNMzGzMTCxMTGxGxqbNTO1Ly2vHRydKyurHRudDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAawQIAQEBAMj0jAgFAwHBDJoUGASCgWDEMxETg2HA8FFaJgFgpdYSMiUYAnlErCsmgKL5iMJqJwPzYcCB0eahAZH4gSESAhYAoGQggiBh4eFB8iehEWI5AABiQFFpMeHCIiiCWeJicMDAUOEZMcHBkSngYMKCkpJA4OBCWTk0IqKw8PvwsLLCwtLBCeRCouLC8vK80wGzEHSQEqHxMhMBMyLtLfKh4WCjM0UUgBCCoAfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_grey_open-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBExOTBQWFNze3Ozq7ERGRCwqLPz+/PTy9Ozu7OTi5HRydIR+fISCfPT29Pz6/PTy7MTCxCwuLJSKfIx6XMzKzDQyNOzizJSOhIyCdOTm5Dw+PJSSlKSipLy+vOzi1OTSvNTCnIRyVNTW1GRiZFxaXAQ6XMyyjNTS1GRmZFxeXHRmTFRWVKSmpKyurMzOzGxqbMTGxLS2tJyenKyqrDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAauQIAQEBAMj0jAgFAwCA7JYwCRUCwWgoCBEUBOG47CAxJhSrqT5wERplQoC8ijYDEcJASJ4HKIYDAZFRoFGxwXHR4eH3lqICEiIyQcAAcMJSaIeHonKCMpkxMqAismKyuIixMsH5MBDw8eJS0mJpcdByYSkwAcEQUEBC4lo7UHL7sXwMAkKTAeogceu0QXMRIwFjISMxITNNNDARcmLx8zNTUH4F64NDUTNlHsk35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_home-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBDw6PBQWFCQiJAQCBFxeXMTCxJyanDwyLDQqLFRSVLSytJSSlISChCQmJERGRFRWVGxubKSmpJyenGRmZLy+vOzq7OTi5Ly6vGRiZPTy9Pz6/OTm5ExOTPT29BwaHNza3NS6tKx6XGQqBNy6pIyKjDwGBOzOvJSWlDQyNIRaLNRiBGwmBNyidLxWBHxGFNySXCwqLKyqrNR6LKxGBNTS1NTW1Jw+BEweDDQ2NAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaoQIBwCAgIiEjAgAAoGA6I5DBBUBgWjIZDqnwYGgVIoTGQQgyRiGRCgZCR1nTFcsFkHm9hBp2paDYbHAsZHW9eERkYGh4eGx4ag3gfSgMTIBshIiMkGyAlCCZTEpciJyQjGxcoKUQBEhcbKiQrLB4XEltDrhcaKi0utbcJra8bLzDAGrcxrTIXHi8zNCypEsO6EzU2IzQ3ONoTzK0BCAkDMQkIOTFlAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_html-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBERGRBQWFMzKzOzq7CwqLDw6NARqnAQ+XHR2dKyqrOTm5ExKTERCRHRydMTi7NTu9HS+1KSmpBweHDy67DyixHS61ITG3AxypByu7DxinBw+ZERmdIySjITC3ARypExOTDRurIR2RPTSdJyulEyGvBw+bFSyzJTK3LzKvPzivOTixNTChLSybGyCfCRSnBQqRASGtFyuzDw+PCRShPzy5OzerOTShKyaTEx6pCxerGRufBR+rOTezPTShNy6bER+1BxCfBQuRAxelFSixBw2VISq3GySrPTWlHyanIyitFSO3IymtCRujAxWhCRqlCQ6XGyWvNS2bFyGvDxuvCRSpLy+vMS+vGxqbFyO1GSi3EyO1FRaVCQuPLS2tDxyzKyWNFxaNCQyPGxubCxajERSVExKNJyenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfZgACCAAECg4eIAAMEBQICBomDBwgJCgsEDA0BDg8BhwYQERKUDxOYDAyeghQVFhehGBmVlwwOqxobHB0eH6EfIAkPIYIiIyQlJhsnKBcpvrYiKissLS4vMDEyFjOvNAA1LDY3ODk6Oyc8PTIyFzQ1Jj42P0A6QTtCQ0REIEUORkdIkihZwsSekBhNnDyBciCKiSNSplDRUcWKkRhXCGDJYgiGli1cpuTocsILjytfFmRpACAGRTBhRogZgzHlAjKGWnIoY+bMgRgBDHRBo/LAIZoxuhwKatRPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folder_image-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPz+BAQCBExKTBQWFMzKzOTm5CwuLERCRARqnAQ+XHR2dKSmpHRydCQiJMTi7NTu9HS+1Dy67DyixITC3BR2pBweHByu7ASGtFSyzHS61AxypExOTBSazBRupJQOFBSCtDxKfKTa9AxelNz61MTaxDw+PPzGpLweHJTO3ESu3DRilFymXCxKRBRypBR+rDwCBNxmVORiRKQWFCyKvJTWhDSOPCRONFSixDQaHNROPNQ2JLRubHTC5DR6rHx6fFSqRCRyLGRmXGxqbIymtCRujAxWhMySjMQ2JMyqrKTW5ERijJSenFSGXGRmZLy+vMTGxMTCvERGRMxCNOzq7NTe5LSurISKhHR2fLy6vLS2tKyurGxubCwqLOSKfOzy9Nza3KSmrIyGjGxmZKyqrIRqZIyKjFxaXJyenDw6PDw6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAffgACCAAECg4eIAAMEBQICBomDBwgJCguMAoUMAYcNDg8QlAyXBaWcgg0REhCfExSVpIYAFRYXEhgZE60aCQwbghUcHRQXtri6DxMHgh4fICEiIyTFtxkOJQAeJicoKSojKywtLsUZJS8wMTIpMyA0NTYKIiIaNwc4OTo7PD0+P0BBhAwhUkTFAQNGjiBJomQJExsMmjh5AkVIFANQpEyhsqSKlStXmmDJomVLFC5Gunj5QiALmDAKxGSpMsYiAC5kqjhZUOaKmUdmzoAJgkaQgQYCmogJEmRQAC5pAPgJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folder_important-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBExGTKQqLPz+/KQqNAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM7CLoQwZAFIV6Es15Jqd2ZtzXUMIhXZqJYaZ5aK7zwp6h0zc05i+c6Eg8oCnWOR0eHQGEKnEWHdDoF+BMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_locked-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQSFMzKzOTm5CwuLERCRARqnAQ+XHR2dKSmpOzm5GxqbCQiJMTi7NTu9HS+1HRydOTm1Ozq7Dy67DyixHS61ITC3AxypERGRBweHByu7ASGtFyy1DSOtDRmfExOTBSazBR+rCwqLAxWhAxelByGtDSaxAwODHy+1Dw+PPT29IyqvCxujOzu7NTW1Nza3ExGJJyebKyqfMTCpFRSPOTi5DQqHOTezDw2NMTGxKyqhMTGrGxmXDQ2NMTCxMTGpHx6bHx2bBQWFIyOXDQuDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAECg4eIAAMEBQICBomDBwgJCgsEDAKFDQGHDg8QEZQSlxMUDJ2CDhUWF6AYGZWXFBqCGxwdFh4XGK8fIAohtiIIIx25EZwBDREHgiQjJSYmGScoKSoRKQ8rggIsDC0uJS4oGygoAyjdAAcsLxQUMDEyMzQ1EzapBy8MDDc36tFwgONFjlQ6dgCEEZBHDx8+ctRIRehHAyAwZASZIGRIEBoUBwUwIGMCiwFEaBQJichIjo9FZLBsacRIAB0A/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_man-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFMzKzOzq5ERCRCwqLARqnAQ+XHR2dKSmpHRydCQiJMTi7NTu9HS+1KyqrMzOzOTi5Ozu5Dy67DyixHS61ITC3ARypOzq7ERGRFRWVJyanByu7ASGtFyy1Hy+1FRSVOzu7BSazBR+rFSyzJTK3Dw+PFxaXPTy7LSyrAxWhAxelLy6vMTGxNTS1Ly6tFyuzMS+vPz69NTW1MTCvIyOjPT29OTm5HRybFSixLy+tLS2tISGhGxubIymtCRujCRqlHx6fNza1GRiZMTCxGxqZLy+vFxeXLSytKyurGxqbISChFxeZDw6PDw6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAffgACCAAECg4eIAAMEBQYCB4mDBggJCguMBgEGDAGHDQ4PEJQKERITFBOdgg0VFhegGBmVlxobABwdHh8WIBchsLIKIiIjCyQZJR+7JhcnoBAoKSoqKywtLi8wMbsyrwYpGhowHTMqNCqkyR8XKBwTNTY3KjgFOTopLS0ZO98wPD0+JhR490MAkCAshHyTsCLCEAlEYEgoIsCIjRlHDNzy0UFBDBtIbBzZ4KJHBB0aAQhIoqCHESQ9dAjooWQJE1uCBBRpkoSDExEcUnRYwOTJIQECNmwQwEFQgANQAPgJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folder_open-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFOzi1Ozq7ERCRCwqLPz+/PT29Ozu7OTm5FRSVHRydIR+fISCfMTCvAQ6XARqnJSKfIx6XPz6/MzKxJTa9Mzq9JzO5PTy7OzizJSOhIyCdOTi5Dy65FTC7HS2zMzm7OTSvNTCnIRyVNza3Dw+PASq5BSGrFyqzMyyjMzOzAR+zBRejBxqnBx+rHRmTPTy9IyqvDRylFxaXNze3DRujAQ2VLSyrDQ2NNTW1NTS1AQ6VJyenGxqbMTGxLy6vGRiZKyurKyqrKSmpDw6PDw6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfCgACCAAECg4eIAAMEBQYCB4mHAQgJCgsLDAEGDQGIkw4PBQkJBYwQnRESEREIoRMUE6IVChYGERcYGaoRGhsbHBQdHgu2HyAhGSK6qxsjJCUmJwARKCkpKsjKqislLNIRLS4vLykw2MkRMRAGhDIJMzTiLzDXETUQ0gAGCgU2HjM35N3AkYMdAB0EbCjcwcPCDBguevjIR0jHDwgWLACBECRIBB8GJekQMiRIjhxEIlBMFOBADR9FIhiJ5OnAEQB+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_orange-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBwWHNTO1Ozq7ExGTDQuNERCRJxmDFw6DGxubKymrMzOzOzu7Hx2fCwqLOzaxPTm1NSyfKSipBweHOSmRMSKRNy2jJxuFFw+DKyqrOSeJKxqFMyaXNSyhNSufFRSVMSCJKRyHLRuFMSORNy6nPTezHxaFIxmFJxqDJxyHPz+/LyqjJR2NPz6/NTS1KyehIxqNJRmDLyWXPTu9PTy9Ozm7Nza3MzKzMzK1OTi5MTCxMTGxDQ2NMzGzLy+vLy2vKyurGRiZLSytLy6vFxaXHRudDw6PDQyNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe/gACCAAECg4eIAAMEBQYGB4mDCAkKCwwNDgYBBg8BhxAREhOUDxSMBQWeghUWFxOhGBkaCxuMBqscHRceHyCwCbMhqyIZIx0kJR4gJicSIAiCECMoKSorKyS6yhHQAAYsBS0uKSkZHSsdHc+CCC8vqDAxMtQzJDTdBjU2NwUsODg5Wsxz0e2ADhw7/sEgwKOHwwW3BAXwsYAHARg/eAAJIgRiogAHhhApEoSIkCERI4E0QmHDESSREAWAkASAn0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_orange_open-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFOTm5ERCRCwqLPz+/PTy9PTy7OTi5FRSVHRydISCfIR+fPT29Ozu7MTCxFw+BJxqBFQ+BJSOhIRyVMTGxPzSlPzmxOTGnOzizIx6XIyCdOyeLPSuTNSubOTSvNTCnNza3Dw+POSGBLRyDMyeXAQ6XMyyjMzKzMyWBKx6FJx2FHRmTLy+xDw6PLyqjJR2LJRyDFxaXOzq7JRuLEw2BKyurDQyNNze3NTW1NTS1MzOzJyenDQ2NGxqbLy6vJyanGRiZLS2tKyqrCwuLKSmpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfEgACCAAECg4eIAAMEBAUCBomHAQcICQoECwEFDAGIkw0OBA8PEIwRnRITFBIHDRAVFhWipBcFEhgZGhMSEg8bGxUcHQQKth4fIBoburwbISIWIyQAEiUmJicnyrooKRYqBdQrEywt1yfJGxQuLzCEozEyM+XnEjQv4QAFEDUKCjE2JrRoYeMGjmkAchAYoWPEDh49YrBQ5SMfoR9AXvRQcSFCkBcUhFgcFCDHEBxBiOAoQgFhpABGaPg4IiFHJE8GbPoJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folder_red-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBExKTBwWHMzKzOzm7ERCRExGTCwqLIw6FFQiDHx2fKyqrOzu7CQiJOzOxPTe1MySfKymrOzq7Nx2TLxmTNSelJQ+FMzOzNxiNKw+HMR6ZMyWhNSajHRydFRSVLxSLJRKJKRKJKQ+HNSWhNSmnHQ6FIRGHJRCHPz6/LSajIRONPTu9Nza3KyShLR6ZPz+/DQyNOTi5NTS1MTCxGxubGxqbMzGzLy6vLSytGRiZHRudDw6PAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAanQIAQEBAMj0jAgFAwHBDJoSGhWDAIDUHgsAgcHQ9IhLqQMAsTr9BBqUTClktVgmkYhIOMprLhdOBUHh9rICEiIyN8JCVwdwAOIiYnJyiHiRtvjgYpBSorJgknIpYRmikpLAUtLp+hIy+aLKkFMC0tGJ4mK44xBDKqLTMEBDTFNY5EMTY0MzM3NDg4OR7IQwExOjnROTk6B1FC1x8SEjs84EcBCDEAfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_red_open-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFOTi5OTm5CwqLPz+/PTy9Ozu7Nze3Ozq7HRydISCfPT29PTy7MTGxFQiDIw6FJSKfIx6XPz6/MzKzERGRNyypPTWzOzi1OzizIyCdDw+PNRuTNyCZMSSfOzW1OTSvNTCnIRyVNTS1ERCRMxGFJxGJIRKJLyCbAQ6XMyyjLRWFHRmTLy+xLSelIxWPEQeBGReVIxOJIRSPKyurDQyNNTW1JxOLEwiDKSipGRiZMTCxLy6vJyenLS2tCwuLFxaXKSmpDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe+gACCAAECg4eIAAMEBQICBomHAQcICQoLAoUMAYiTDQ0LDg4PCgQQnBESEREHoBMUEwUVDgsWFxEYGRiqEQ8aG68cBQQdER4fIBghu6saIiMkJSYAEScoKSrJyxIrLNEd1C0p1ygo2coRLi/gAaIwMSnx5SoyM+uCHQ8LChrv8TQ1ZNiYBuCGgoMKcJSwACNHCh07wAkK0IFHj4UQevjwEeGHREk3ZtjwAcSGjQgfEwUIIuTHEJSROhkgAsBPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folder_sound-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFMzOzOTm5ERCRCwqLARqnAQ+XHR2dKyqrMzKzHRydCQiJMTi7NTu9HS61KSmpDy67DyexExSVITC3AxypBweHByu7FRiZDRiZHy+1ARypExaXBy2xGRqZFSyzJTK3AQ+RByqtASCtASGtFyuzDw+PATC1ByGlFxeXISGhJSWlFRWVAxmlBR2pBR+rAQ2PAS2xHS2vMTCxJyenLS2tCRujAxWhAxelFSixAQaHARibARudAR2hEySnPTy9Nza3GRiZNTS1IymtCRqlARWXDyCjPz6/MTGxLy+vMS+vGxqbAQiJARaZEx+hLy6vKyurERGRBQuNCw6PISanFxaXDw6PCQ2NDRGRDw6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfYgACCAAECg4eIAAMEBQYCB4mDBggJCgsMBQIBBg0Bhw4PEBGUDRKMBQWegg4TFBUVEBYXlZeNghgZGhsCFRyhFh0JDRWCAx4fGg0gCiERIqEcBoIjHyQeDcMlJhQnEQ8oANQpKissLS4vMDEmJhEoMjPxNDU2Ny44OTo6FzsGPD0+fgABEUTIECIMiuAzIk3GkR5IbgRJMoSAkiVKmDSRBsDJEyg1hBQYUqNGlBtSGkwZRGUDEyILWCxYcmPBgiYrB1WxEsBTgANXbCwYggVRFi2Ifm4B4CcQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_tar-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFMzKzOTm5ERCRCwqLARqnAQ+XHR2dKSmpHRydCQiJMTi7NTu9Hy+1ARypDy67DyixHS61ITC3Ozq7BweHJySbJyWbAxypExOTPz21KyqjPz67OzmxFSyzJTK3LSujASGtDw+PKSehPz69Pz23OzitPTqvOzerKSaZBR2pBR+rKSefMy+dKyeTIR2NAxWhAxelFSixJyadOzirLyubLyqVJySPHRmJIymtCRujCRqlPTqzOzW5OzSzNzSrLyqXLSeTJSGNMTGxMS+vLy6vGxqbJSKZOzOxNzGtNzOhKSSRIR+LGReHLy+vKyurOTWlHxyJFxSFLS2tKyqrERGRHRuRNzKfNTGdGxeJGxiNFxaXJyenDw6PDw6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfcgACCAAECg4eIAAMEBQYCB4mDBggJCguMAgEGDAGHDQ4PEBEJDJcFp52CDRITFKAVo6UEFgaCFxgZGRgUFa8apBsAuhwdHh+5IBQhrwYZIh3PHdAdGSMTyQ4kJR4mJycdKCkqKywtIyMUJC4cKR7EKC8wMTIzMxE0BjUmJjY2NzgwcuggsIOHjB7NfPwAEkTIkBxEdBQxUuQIEgNJgihZwgRGEyJOnhyBciTKxSRSpDBh0iRGjClUjlSJYgXJFQBYbmTREmOLDi4BDnTxsgDJl0E5uXBBFBQMAD+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folder_txt-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAMR6RPwCBAQCBExKTPzGjBQWFMzOzOTm5ERCRCwqLPyGBPzKjARqnAQ+XHR2dKSmpMzKzHRydPyGDNTu9Hy+1OR2BNSOXHS+1MTi7ITC3AxypOzq7KRKBPyCDOySZPzizPTWxFSyzHS61ITG3FROTCQSBMxmJNRyROy2lOy2nASGtDyixJTK3FxGNIRWLMR+XPzStPTKrBRupBR+tFyuzDw+PDQuJIRSNAxWhAxmnBR2pBR+rPT29FxaVEw6LKRuVIx6ZISitCRujAxelAxmlFSixOzu7JyWjBwaFKSShNTW1MTGxDQ2NMTCxNze3Nza3HRqXMS+vGxubGRiZLSytCwuLERGRJyenGxqbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAAfLgAABgwIDg4eIAQSCBQYHCAMJiYMKCwAMDQ4PEAcDAggRApQSlhMUmJqOBweiFQoKBBYXGBMZGpkPBhsIHBUdHh8gISIjtCOoJCUcJicoHykqK8MstBQIASUtLi8wMTIzKtE0Ihg1gwg2Ny8xKDg5OjvhItcBCDw9Pj9AQUI4Q0QMipirZ2TDERJIkihZwg+HEHpMmjg58OQIFANLomSUQi+AACZTohiAkDEKFSocJwmoMoWKSSoPpFiZdEhAgh5XHmBhQjORTZ5+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_video-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExOTBQWFMzKzOTm5ERCRCwqLARqnAQ+XHR2dKSmpHRydCQiJMTi7NTu9Hy+1Hx6dJyenLy6vIyOjDy67DyixHS61ITC3ARypOzq7ERGRFxaPKyqrBweHByu7ASGtFSyzITG3KSOPKyurBSazBR+rJTK3HS+1Hx6ZNzObAxWhAxelAxmlBRupBR+tFyuzDw+POzibNzOZIyqvCRujLyiPJyCPJSWlNTS1ISitFSixHxiFGxeJFxWLExKNCRqlDw2BFROHHxqPMSqVISChMzOzGxqZISCbLSaRKSWTFxWPNzGZNTCZLy+vLSytGxubJSSfGRiTMyyVLymTLyiRMSqTEQ+JGxqbNS+XNzKZOTWbLy2ZFxaXDw6PIyGbOzidOzifMy6XCwmFGxmXDw6LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfigACCAAECg4eIAAMEBQYCB4mDBggJCguMAgEGDAGHDQ4PEJQREowFBZ0TFA0VFhegGBkJEZcaGxwdHh8gFiEXGKAiowIjHCQlCCYgvL4noCgGKSoGCyssLS4vyxYwrzEyM9MSNDUrK9jKIBcGNiMjNwY4Gjk65dcIOwY8PT0+PwYUAuTIQaDeCiAGgggZMoQDEQNFchghMIHiEQNIkihZwoRJkx8RCDhxMuEJFAMGokiZQoRKFStXjpQk0QHLBgDRrEzJomULlwFHukhYgMWLIANfwIAJw+WKmDFkAjQoA8BPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folder_violet-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBExKTBwWHMzKzOzq7ERCRExGTCwqLHQWhEQOVHR2dKyqrNTS1PTy9Hx2fCQiJOTK7OzW9LyKzGxubLRW1JxOtLyCzMSS1HwijKSipLQ61HwinKxuvHQajFRSVJQytIQqlKRqvMSe1GQebHQihLSCxNzG5Pz+/KyStHQ6hPz6/PTu9Nza3KSGrJxmrOzm7MzOzDw6PDQyNOTi5MzGzMTCxGxqbLy6vLSytHRudGRiZLy2vDQuNFxaXDQ6NCH5BAEAAAAALAAAAAAQABAAAAaoQIAQEBAMj0jAgFAwHBDJoSGhWDAaDkPxEThCIpIJlcJgFgpdIaRiuYAxGcVD02gKBxuOpXPBvD1VH2ogISEceiIXI2ATBmohJAklGYaIJieOAAIoBSkqJCUlHJUmmQYrDiwFLS6foRwvpqkwMCstDTGtJCoyQjMELTQttw01Nsc3B0MBMxQ2DSfGNjg5OplHzDs5ODw5DMlRQgE9PhoMOjPh2BA/AH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_violet_open-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFOTi5OTm5CwqLPz+/PTy7Ozu7HRydISCfPT29Ozq7Nze3MTGxEQOTGwahDwKRJSKfIx6XOzi1Pz6/MTKxNSi5OTS7Mym1OzizJSOhIyCdDw+PKxSzLRq1LSCxOTSvNTCnIRyVNTW1JwixHwqlKRutOTS5AQ6XMyyjNTS1JwerHQmfIQylHRmTLzCvKyWtHRChHwuhFxaXERCRHQ+fLSytDQ2NKSmpGxqbLy6vDwOTJyenDQyNKyqrCwuLDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAECg4eIAAMEBQICBomHAQcICYwChQoBiJMLCwUMBw0NDg+bEBESEAcLDRMUExUMFggXAhAYGRoREBAIGxscFB0EBB4QHyAhGrq8EBsiIyQlHgAQJicnKMspuyorJCzVEi0uLy7Z2xopEDAx1QEMDDIzLjTZ2hI174I2CQ0EHMi4ge7EDQk4qgHI4aChAxYsLsg4J0GHQkI5dsSIeCFGDB49fFwcFOBHDRw8cOAAAmEkpyA1fOjoISQSJwPV/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_wordprocessing-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExOTBQSFMzKzOTm5ERCRDQuLARqnAQ+XHRydKSmpExKTCQiHMTi7NTu9HS+1HR2dCQiJDy67DyixHS61ITC3AxypKyqrBweHGxqbGRmZFxaXFRSVERGRPz+/ITG3JyalOze1PTm3Ozi1PTm1Hx2bJTK3IyOjPTy9CQqJFyuzDw+PNTGnDQyNPTq3Ozq7MS2hASGtKyaXCwqHBwaHFxWTKyahLSijKyehHRmXHRqNFSixHxyNAwKDERCPAQGBCwqLIymtCRujAxWhCRqlMS+vMTGxIyCVJSSfLy6vLS2tLSytGxubCwqJExGJEQ+JBQWFJyanDw6NDQ2NBQaFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfUgACCAAECg4eIAAMEBQIGB4mDBggJCguMDAEGCgGHDQ4PEJQRlwWmnYISExQVoBYXCREYjAaCGREaGxwdHh8PIJQKhgAhIiMkJSQkJhUnrrUGKCkf1B8pGyoUK60sLSouIS8vMCUhBw0xMjIVBjM0NTY3ODk5Og0NOwgXPCw9AD4BBvwwMABIgCBChhApUqtBhgw1INaIWMPIESMaGiIRsbFjkhpKlmDQYKgGx5MdDyxhgqFJLSdPoMiU+YRGFA5SRk4RRCWDix9TnFRxISiAE6J+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_yellow-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBwWHMzKzOzq7ExGTCwqLERCRJSSDFxWDGxubKyqrNTS1Hx2fCQiJOzqzPTy1NTKfHRydOTWTMSyTNTKjNzOjJyWFHR2dKymrOTaLKyaFLyyRMS6ZFRSVLy2JKSeHNTOnNTKhHR2FISGHIyKHKyeFOzmxPz+/LS2lIyCNJSWJMzKfPz6/PTy9Nze3KyqhLS2XPTu9Ozm7Nza3MzK1LSyjIyONDQyNOTi5NTO1MTGxMTCxMzGzLy6vLSutGRiZLy2vKyurKSipAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe0gACCAAECg4eIAAMEBQYGB4mDCAkKCwwNjYUOAYcPEBESlBMMjAUFnIIPFBUWnxcYChkajAaCAxscHR4SrREWlBkfqSAYIRy5uyKfIwipISQlJhgnx7oSKM0ABikFKivQCSwn1C3ZCC4vLwUwMd/RGDLZBjPqNCk1NTY33zjZOQQ1dOBrsIMHjx49FtQSFCDHgh47GvhA+AOIwkQNgwARUnHIxUiEcnwgwmBBDpCHAjw46ScQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folder_yellow_open-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFNze3Ozq7ERCRCwqLPz+/PTy9PT29FRSVHRydIR+fISCfOzu7OTm5MTCxFRWBIyOFFRSBJSKfIRyVOzqnPTuzNzapOzi1OzizIx6XIyCdNzORNzSZMTCfOzqzOTSvNTCnNTW1NTGFKSaHLy6ZAQ6XMyyjMzKzDw+PLS+DHyGHIySJHRmTLy+xLS2lIyKPISGJGReVOTi5ISGNExKBKyqrDQyNNza3NTS1JyeJKSipGxqbMzOzLS2tJyanKyurLy6vKyutCwuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAECg4eIAAMEBQYCB4mHAQgJCowLAQYMAYiTDQ4FCgoPEBARnBITFBIIoBUWFaEKBREGFBcYGaoUChobFRwdBRAGEh4fIBkhuqsbIiMWJAYAFCUmJifJG7ooKRYqK9QsLS4T19kZGxIvMNMBojEyMy4u5xQ0EeEABgUFBDUxbJBzYeMGjmkAchBYqGPHjggxeMy40UMfoRw+IvxQoSICEBgUgiCUlIOGkCFAiOCgYDFRgCILgqxsGYnQgRwA/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+ftp-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNze3LSyrJyanPz+/Ozq7GxqbDxinBw+ZERmdIySjHRydMzOzPT29CwuNDRurIR2RPTSdJyulEyGvBw+bLzCxIyKhGxubERCRLzKvPzivPTmxNTChLSybGyCfCRSnBQqPLy6vLy2rCRShOTixPzy5OzerOTShLyaVEx6nCxerGRyhOTi3OzaxPTShNy6bEx6rER6zDRitBxCfPTq3LyulBw2VISq3GySrPTWlHyanIyitFSO3PTm1Ozi1LyqjDQyNCQ6XHSq3GyWvDxuvCRSpLSqpOzezAQCBCxGZCRKZExGLDQuHAwaLBQWHKymnOzexARCBJzOnGy2bDyePCxKJOzWvLymhAx6DAyGDDROLOTOpHRmVLyidLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfRgACCAAGFhoaDiQECjIwDAQQBiYKLBZYFBgcFkZMICQoLlwwNDgQPghAREhMUCBUWBRcMGBmnEBobHB0eHyAhIg4CIxenJCUmJygpKisVLAIGLSMPJBQuJi8wMTIzNCEWJjU2Dzc4OTo7PD0yK94DPj9AQUIUQ0QwFDFFRjchRz5IbARJEkLJkiVMmDRx8uQBlCgbgDyQMmUKlYpTqlSsYsXFFSwTK2bRMmWkyCxbuICkmKVlySwvpXTh4mWilJs4c3bB8uXLqUEBHggdSvSBn0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+link-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBFxaXPz+/AQCBKSipAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMgCLrc/jDKSau9OL/AuwxCKAzfOIwlcZIRKLJQMMyz5CcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+network-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBISChPz+/Nza3ARaZESanCyKlARudARGTLy+vNzq7ARmbMTCxARufAROVMzOzKSipARyfOzq7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVmICAGZFmKQiACweCSBImq41AYB5IodLq2hwWO0ejRWDac48Gb/QKNqNRoqspmrVcAUuIJBANS8sBIFCORUgooPEh4J8B67NgdsVBp9C5XWfl9LRMTCyReX19hARNojWlWLH+AAH4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+pipe-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBISChMTCxPz+/ARCBFxaXASChCH5BAEAAAAALAAAAAAQABAAAAM2CLoazpAFIV6UYZB6Yd5BtwRbEYqkYIqAQRir6KpnN8cdCddXivcbAy+S2qEOAuPx8MtZRP4EACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+shredder-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBERCBAQCBMTCBPz+xFxaXPz+/AQChISCBISC/DQyNPz+BARCRAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARcEMgZhBUzgzuIH4G2FYThnZUlCab5Ed0hC6nZ3Yh8JIKyLjCYboeZKIK6BDHTGwyViopEoWAkdwfqoKhIKLFUwXY79coUtLG4CFAcOOstWyNWyEXMO57p2/vxfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+socket-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+xMTCBFxaXKSipDQyNPz+/MTCxISChAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARKEMgZpr1SjFqx1QHoTaA4AuV2EmmHEUUxsKoHB7FMGPbhI7gCgnchII6+AyJBtBhjx0KC2TsIp9QXcpm1HafNEQF8mhAOCdfEHwEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+trashcan_empty-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBKSipERCBARCRPz+/MTCxISChFxaXAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARREEgZapiYWjGIvVNQjEZ5BKUAApVgjEWJzCtAnIGgC8eZ5bre7ICosQQFVY9Y/CGVwiYmlwwsac7qVRp6WqNGKpQZ9m7DojH2t+lVMtMP3B8BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+trashcan_full-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/Pz+xATCxMTCxMTCBKSipPyqXISCBFxaXISChAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARbEIAQJJU4BzEoIdSFbcNQnIVhBJ02GAeFIGxZjUl8KoHRagfeYqgo3kaxQOEwXPAyk4Mgtgg6jxYp1foETgPEKzSgBXOx0W9VIfZu2d3R5t3WhA5BEdQSQgP8EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+www-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNze3LSyrJyanPz+/Ozq7GxqbDxinBw+ZERmdIySjHRydMzOzPT29CwuNDRurIR2RPTSdJyulEyGvBw+bLzCxIyKhGxubERCPLzKvPzivOTixNTChLSybGyCfCRSnBQqPLy6vOTi3Ly2rCRShPzy5OzerLyaVEx6nCxerGRyhOTezPTShNy6bEx6rER6zDRitBxCfPTu5PTq3LyqjBw2VISq3GySrPTWlHyanIyitFSO3LSqpPTm1DQyNCQ6XHSq3GyWvDxuvCRSpKyurOzizAQCBCxGZCRKZExGLDQuHAwaLBQWHKymnPTmxOzaxHx+fMTCvOzWvLymhHRmVExGPOTOpExOTERCRLyedBwaHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfWgACCAAGFhoaDiQECjIwDAQQBiYKLBZYFBgcFkZMICQoLlwwNDgQPghAREhMUCBUWBRcMGBmnEBobHB0eHyAhIg4jJBenJRwmJxIoKSoVKwIGwg8lFCwmLS4vMDEyIRYzNDUPNjc4OTo7PDAq3T0+Pj0/QBRBQi4UL0NENiFFPkbijoRAkiSJEiVLmDR54OQJFHEPREQRIWWihYlRMkCZQuXBgyIBihSpIjLAowBWroj7gaUIlpYvXWLJUuWKlgdbHvz44XHnzgdVami5qUinR50/efoJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+zip-16:filesystems filesystems16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBIQChPzC/AQCBMQCxAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMeCBCh/i+IAesShNo4+v5gKI5kaZ7oxzCilLVvq/kJACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+cal1day-16:korganizer korganizer16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANOCLrMEUDIOUS9AFLLhx8LIRZjKYZmMRCkaChFLHty/AIiS3y6q+QtT49wq8VotRtQJGwRf6Zmrlj7DJLQXsupTJmeEIN4TB5nII20wp8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+cal5days-16:korganizer korganizer16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANMCLrMEUDIOUS9AFLLhx8LIRZjKYbj55GioRRwoQ5x4QIiIdMmcec7jy53q81qP9OO5VMAj8RXTFWzOZW95HDLdEEM4LA4nIE0zgp/AgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+cal7days-16:korganizer korganizer16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANPCLrMEUDIOUS9AFLLhx8LIRZjKYbj55GioRRwoQ5x4QIiwcp0fucsj873qvGMv5Jw2FIACUsW4WakGW1O046I05qmGYBhTC6TM5CGWuFPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+calappointment-16:korganizer korganizer16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBAQC/AQCjPz+/MTCxPz+BISCBISChKSipAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARbEMhJaQhA6D1E/wDGeeRgDhOhFoTBEi+REgdrIHScSEVvAD9Xr7cDqGSGpFEnQSqTv2NxCFQOiU1VEAiTZmstHFg1vQKuw+LxxfYaV/AuOQRI2O/4ewhT6Uv8EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+calbell-16:korganizer korganizer16 16:photo:16 16:R0lGODlhDwAOAIIAAPwCBISCBPz+BIQCBMTCxISChPz+/AQCBCH5BAEAAAAALAAAAAAPAA4AAAM+CLrR+zCIAWsgLVRGRBhOVQiG94WPVAbHaZHYAWqRYLbge88RsbInGuBCEhRYrZYm4xk4nYdoKzKIbiKHawIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+callist-16:korganizer korganizer16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBAQC/AQCjPz+/KSipPzerMRaBEQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARDEMhJaQhA6D1E/wDGeeRgDhOhruyatjBRSIRxxOsMEAdC0BUZDcfSEYvDo3Bn++2Cxt7RqFxWhZiCdsvdhjCVsMQfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+calmonth-16:korganizer korganizer16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANSCLrMEUDIOUS9AFLLhx8LIRZjKYbiRxLFIBpK0Q6z7MkwkJIe8b0KEeuWchFysuStVsjtfMbeMQitWpG25YfmNK1WU53XNIUYzug0OgNpuBX+BAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+caltoday-16:korganizer korganizer16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBAQC/AQCjPz+/MTCxKSipPyCBMRaBPyqXAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARTEMhJaQhA6D1E/wDGeeRgDhOhFmurpi5LyIQhFfiBIAfuFzaAioBIJBCummRYPCaDPh3vhwsOZdihNfa8Ub/AJXemFZPPNBvGwG672yFMZS7xRwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+caltodo-16:korganizer korganizer16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBAT+BAQC/AQCjPz+/MTCxPzCxKSipPwCBMQCBIQCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARaEMhJaQhA6D1E/wDGeeRgDhOhFmurpi5LyMYhFXiuFwZiA6qZYbbqJX5BIw2RAPxwAAWCyWMCCsiXFGEEErKz6LQZfOqiTR1YJiGq1rFyyHmo2+/1EKbCl/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+adjustcol-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBGRiZAQCBPz+/CH5BAEAAAAALAAAAAAQABAAAAI7hI8JAWL+IgvwUSSY2Lz7VTXXkS2NdJ6TwiSaB3PNQNdCbc/4cO9OjwPmhDQiTxfcHY1MpE35g0IB/gIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+adjustrow-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBGRiZAQCBPz+/CH5BAEAAAAALAAAAAAQABAAAAI5hI8JEcItooxG1oEzBoJ7oWlHd4VbNZpbx3LqUFGuajTPhI8kSLfsO0rRUCXT5wPkyHhGhsOJs/gLACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+black_sum-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIdhI+py60BY2QwhVYdytpw/WFXF1LjcW6S1LVu6xcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_all-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAIjhI+pq+FuHjwyRInqfRkDTXkgQ5YLOH6it00pyqqcPJk26RcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_bottom-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAInRIynGe0PFTQz2kdxzHf72iSiRDpc2F1niaafBroYQNe2fdx6HfgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+border_fall-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAIrRIyneRYP4wPUKWmr3E5b+DVh9GkYuFALiqnsJp6nObYZB5ow2a3Jvwv6CwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+border_horizontal-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAImRIynGe0PFTQz2kdxzHf7CoTiSB7kKUpa1Vlc86rtSjvxnOSL4hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_inside-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAIrRIygxxYPF4zzyenqxfVk2m0g9lnKiabqqoYl43YwGcqiFWv22zRnD/AXAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+border_left-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAInBHKJmxYPY3TyVCozsjMbrk3gM27KyZDlioVQS3qwO7Nl6KC6q/kFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+border_outline-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAIrhI8ZybgQYoTy2YqtwVTunVVfN3HQsaTnc5Kp2Ibw5Zm0PHJ2w7O8I5P5CwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+border_remove-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAIjRIynGe0PFTQz2kdxzHf72iSiRDpc2F1niaafBrraSMuQXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_right-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAInRIynaOEPH5hRRVrzbJBLn32g1TXJuWBdpYYiy47hBl+yRqH6HfoFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+border_top-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAImhI8ZyRgPo3xgVnmnprbvnUEhx1XmgpLRmH7e+rowFssleuaBXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_up-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAItRIynwOEPH0vRuGkjnFKjpmgX2FVkuBwNhapZKZ3VyMKcGJPv5eJmAkz5RP4CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+border_vertical-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAAQCBPwCBCH5BAEAAAEALAAAAAAQABAAAAIrRIygxxYPF4zzyenqxfVk2m0g9llmsiCmVjJh65Jh59GtGMuzqqQNDQz4CwAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+cell_edit-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/ISChCH5BAEAAAAALAAAAAAQABAAAAIshI+pm+EPnwmi2msDoLgLzQWDV4HlSJof6qki+W0nrMKlbN9bxGvMDwwG/QUAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+cell_layout-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+/PzerMTCxPyqXHx+fAAAACH5BAEAAAAALAAAAAAQABAAAANCCLrc/i3ISacKIuutA8ACxWUeJg0DqBHhd6ZiRpQBag9F2n13FRis0q1QUAmCvFuKRTAYWhIi0bhz+SqQrHbL9ScAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+chart-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBAQCxAQC/AT+/MTC/Pz+BAAAACH5BAEAAAAALAAAAAAQABAAAANMCLocHiyuIASU6lE7Xx7DdgEBQVwBKE4mqlZjeT4vl7VFkYZUjOuGkMFiuJ1yKUNAWTQGkEKDknUESpdXkkYjnWIWzOVX0SyPJwx/AgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+comment-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+BPz+/Hx+BAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM5CLrc/i3ISacKYuStuwhAMBATKRHkAGJeu60qagqmuHK4B6Pn3N0u147Ha8FyOVCowlRCntAo1J8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+deletecell-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/AQCBPz+/PwCBMQCBISChAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANICLrc/i3ISacKIuutA8BcKAwfNwwmQYDZoJ6tWrBZoRKuXIb2XRS7UG4wC25yOIGHFvu9PJ8KcRbQOVzAheoxbRCyDOKj4E8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+delete_table-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/AQCBPz+/PwCBMQCBISChAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANPCLHcDDCIOSUVAaqLeY5O+G2XRQVDdA0DNxCEwrwEu9AFORVw3ee6Cu8HFKFgA2AQQ6uNTJNXYZgCNZKFBay4IhQuMBUFW/LKZlkHoOBPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+dissociatecell-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAASC/AQCBPz+/PwCBCH5BAEAAAAALAAAAAAQABAAAAI0hI+pm+EPoQlC0GqxnfV2HUzR6HDWgA5Bqppr+qIhcMUqO5Oki+M87KN1ejCRTsJIKhP+AgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+first_letter_upper-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIohI+py72RIJOHRmBt3QaGz2GVBGJfKW4aiXhX2sHxbKKneDv6zht+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fontsizedown-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAInhI+pELHqmIkQNZrwfXYvzE1fBUrWoZniOjWdp0agjLL2i7rhDvgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+fontsizeup-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+pEeoNIFyIzXStw3q/T4VVhJHHlDGjgZ6n1bLyCrqPyuJe4hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+funct-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+py60R3IkRVHQzo9BwD1qhqGneRU4gSqlVJ8Zy0mKPhOe6XwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+insertcell-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBPz+/Pz+BATCBAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAAM7CLoa/k7IKQCEdNobc+UOMCijCD5jGjAMOowrIc/Wm77ATIe2leuETcrEYpSOJ88HpNxwmqdi40Tl+BMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+inserttable-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/AAAACH5BAEAAAAALAAAAAAQABAAAAIuRI6JwCH/HBSBmUlxbarvO0nQJ0aa5XWodjZsiKbJGrbgaMuzW8M87jPoDgx/AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+lower-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIqhI+pELHqmIkQNZrwfXYvzE0QKGniQWmNhbYSeqXn6zJOBJLTuuuh4i8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mergecell-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/ATCBCH5BAEAAAAALAAAAAAQABAAAAIyhI+pm+EPoQlC0GqxnfV2HUzR6HDWgKZpCFyBCrMurMoPvZovPsgd39MBbaQI44hU+AsAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+money-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/AQCBPz+BPwCBASCBATCBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM+CLrcHMHJIEaUD16sqIUcQAne5pQaBglkZS6lxb6dRoIAQTzuphcFXWeW0xl/utIPGDQOSUdnA7IUhoocfwIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+oscilloscope-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBOTm5Hx+fLy+vAQCfAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANKCLrcGjDK+IS9494AgrbEJ3CeUBRWpp2daaHhhZKuq75jh8pxTRaEQbAgFAIHv1VvR/vsdrnSCmdpagYnjfXS27Q+N29nQuYA/AkAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+percent-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIkhI+py70RUHxxQmosu6BOdWkNR35PVm1etqEsaKXnwTn2DfgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+precminus-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/AAAACH5BAEAAAAALAAAAAAQABAAAAIthH8RiJvrmHogVoXNtFRDpjUf6JWkeUoXlpGBAMfC+cowbd+uwL54/rMFZf4CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+precplus-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/AAAACH5BAEAAAAALAAAAAAQABAAAAI2hG8Rp4y9IGgszqhyspLueYHih43hiX7Iui5XprGTQNeCPNNBje86L9vBdr2a7xY0AllHm78AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+removecell-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAAQCBASC/Pz+/PwCBCH5BAEAAAEALAAAAAAQABAAAAI5hG+hq+IvAGPwydlqxAohvnjHMChkR6YDcKaougZqCMdyGYqSG+jXKQtoNkGTUHPBDJMTH+jJ8RcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+removecomment-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/AQCBPz+BPz+/Hx+BPwCBMQCBISChCH5BAEAAAAALAAAAAAQABAAAANVCLrc/i3ISacKYuStuwhAMBATKRHkUIScUBSeahhigBbzK+HGgXmHmYHXC41MqKDwcGDFMryCz4gi3YQwkKiFY+ZAoYrUF5g1HV3G7DFuFBvSx8GfAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+resizecol-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBFxaXAQCBDQyNPz+/AAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMyCLrcG0A4CZ90saohuv+XEgxYxkDhQp2lyIBwKhB0bct2TuB6zfe7F5D26xV1x9zFnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+resizerow-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBFxaXAQCBPz+/CH5BAEAAAAALAAAAAAQABAAAAIyhI+pmxHinph0GnqH3hoIDwocd3zZ2F0lmoInWq5s/I60xw5hmF8WPnNAhJUK44hM+AsAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+series-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBGRiZAAAACH5BAEAAAAALAAAAAAQABAAAAIjhI+py+0fUGRhGrswVtr1FgiGsGlhZVWAuarr9byyB8f24hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+sort_decrease-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAAT+BPwCBAQCBAQC/FxaXAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM5CBDM+uKp8KiMsmaAs82dtnGeCHnNp4TjNQ4jq8CbDNOroIe3ROyEx2A4vOgkOBzgFxQ6Xa0owJ8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+sort_incr-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIIAAAT+BAQC/AQCBPwCBFxaXAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM4CAqxLm61CGBs81FMrQxgpnhKJlaXFJHUGg0w7DrDUmvtPQo8qyuEHoHW6hEVv+DQFvuhWtCFPwEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+special_paste-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+xPz+BNTS1MzGLMRaBMzOzPz+rPyqXPz+/MzGNDQyNKSipAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARoEMgJQhBySGx7IEQwFKMWGKgRHNZRIAJSVAm6usIwCEo+BDWVJ/CKzYAplWJZItGSgSVPZBEgU9EFQyGyWoK25XJ4DTO2iob6CxVLe2ys4rw9e8HKd8ybVJ7ndgEVQz09e1YUEmQefhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+strike_out-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBGRiZAAAACH5BAEAAAAALAAAAAAQABAAAAIghI+py+0BgwOS1gXnuS/b6ClCpCUcclJMmKIGWcby5BcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_bottom-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIVhI+py+0Po5y0hYtzrkB7zH0fN/kFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+text_center-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+pm+EPIZsnRkqtDnhu1zHfFSpjaY4PavgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+text_left-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+pm+EPIZsgRoqr3Vnt102fFSJjUC6nlPoFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+text_middle-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIXhI+py+0PT5i01pisphjt3UmfFZYm5hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_multirow-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+pm+EPIZsg2kfZvblXbwTg10WlA4rjyvgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+text_right-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+pm+EPIZstSrqsDhhv1ylfFE5jiYwX6hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_top-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIWhI9pwe2uYnq0yQtqxbz7D4biSIZ+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+upper-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+pEeoNIFyIzXStw3q/dR2hhEVcJqamuq6Z9brlNtKMeHuKXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+vertical_text-16:kspread kspread16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIihI+pFrHqQHynTRrvyxQ12YWQWJGMpC0f2E1psr4eaj5+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+applix-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFRSVFxaXFxeXNze3Ly2rJyanOTi3Pz+/Ozq7HRydFxaVISGhGxubMzOzDQuLExKTCwqLIyKjGxqbERCRCwuLJSSlOTi5BQSFPT29IyKhDQyNISChDw6PBweHMS6pPz69Pz29PTq3Ozm3MSynMTGxAwKDPTu5Ozi1LyulExOTCQiJPTm1OzezLyqlLSyrDw2NOTazOzizOzaxLyqjKSipBwaHOTStLymhLymfGRmXNzKtOTOpLyidMTCtMS+rCH5BAEAAAAALAAAAAAQABAAAAa9QIAQEBAMikfjcCkgOJ2FgCGwFAYOiCwioUAYFtUrgtFFNBzeB5OAgESyEsWEUjFYAJYJ4hLBoDMHBRobAAaGehwdHnoZCQcfEUKHCBQBAxsgISIjJIRCeSUmHAYmJSInKCmRkgYqGw4ZKxMiLC0unoUvFBQQMBQRMTIzNBVDFjUrGwO9Nh8zNzi4BhM2LyIvGhgLNzc5akM6DsEyMjsfPDw9uAALPj4/HyQ0ND31q0ICFRv6FTAb/xE2+AkCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+binary2-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFRSVFxaXFxeXFRWVNze3Ly2tJyalHR2dISCfLSyrPTy9Pz+/Ozq7GxubJyanKSmpMTCxMzKzLy6vNTS1JSSlCwuLLy6tMzGxOTi3KSipKyurHx6fOTi5IyKjGxqbERGRDQyNMzOzOzu7GxmZIyKhHRydLS2tNTW1ERCROzm5MS6pIyOjDw+PPTu5PTq3LSqnOTazOzi1GRmZJSWlCQeHPTm1OzizLyqjISGhExOTGxqZDw6PNzSxOzaxGRiZExKTCQiHEQ+NLyulOzavOzWvLymhHRybLyypNTGtOTOpOzexLyidMTCtMS+rMSynLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfqgACCAAECAwQCiIiDjAIFj48GAgcBjIIICQoLDAwNDgwPA4MIBhAREgkTmw4UDBUWAxcYFAUZGggbHB0eDh8gIQkiHSMeFRoUDyQRIxkGJRYmFScTKCcHCCkgJyoNGSsWHCwKCCgIASAgLQoZLi8wISUbEyQUJAEDKQEKMS8yMBYeZmCgMcEcghog9tm4gSNEjgEPdEDYEQJEDR4aetzwgcPCjw8VfiAAwqNFECFDehApYiSEoCMQBVjQkQBJkpVKjFhgNGBGzSRLVhZRwsTloAFNmjhZ8WQIDiZQoOwcFMCCVQshrmYN4ScQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+binary-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbPz69HRydMzOzDQyNIyKhERCRPT29GxubPTy7Pzy7PTu5Ozm3LyulPTq3Ozi1OzezLyqjPz27OzaxLymhPz29OTStLyifPTm1OzavOTOpLyedMS+rMS6pMSynAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaJQIAQECgajcNkQMBkDgKEQFK4LFgLhgMiOq0WDgVEQrFdKAXfhJWRODTMQ6+64BAMGHAq+pB4hCF2eURoVwgREhMUgl5/EBUWimdWB4cVDxcYiwJiGQcVfBobmhwPEgkWFg8dmWcQEgcWFw99HpoVFR8XGiAhISKLI8EkJRgYGyK/SgvLzM0LfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+colorscm-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIcAAPz+BFxaXNze3Ly2rJyanPz+/Ozq7GxqbJxaLLxOFLQ+HLQ6NMSOnOzi5GxubMzOzDQyNMx6JOSSXOSedNx+ZMxaXLQ6ZKRalNzW3IyKjERCRNSWPPTKnNReNMRGVLxalJRGpHRanNTS3PTy9OTi3ISGfLySNOzCfPTatOy2dNxuFMw6DJxGrHROvEROnHyKrMSmTOzanNzShOSqRNyCFMxCHJxGnFxavDxqxCRmrCxijPTq3Ozm3LyulLyyZOTenNTGZMS6VISKbCyCzASGxAR6rBxmhKyqpOzi1JyuXLTShJzKdHS+XES2XCy6pDSy3Bym3AySxAR2pBxadKyinPTm1OzezLyqjGSWTHS6ZFy+ZCyyVCS2dDy61Dyq1CSOtBRqjExqZKyilOzaxLymhDyeTCSuVByyZCS6hDS2vDSatCx2lCxabIR+dBSKTByeZCSmhCymnCyanCR6hNTCrOTOpLyedCxmVCR+bCR2bCRmZExqbMy+pOTStKSelKyejMSynLyqlLymfLyifAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAjqAAEIBBCgoEGDAxMGEMCQ4YAABAIkFLiwgMUCBg4UiJgQQQIFCxg0sOjgwUYIAiNImEChgoULGApkcHBAA8oNHDhI6ODhA4gQIkaQGFACgokTKFKoWGGBRQsXLwQIHQABRgwZM2jUsHEDRw4dA3bw6AHBxw8ZQIIIGUKESBEjR3YgIZtEyRImTZw8gRJFyhQqVaxcgYAli5YtXJx08fIFTBgxVsaQQVnGzBk0TtKoWcOmzZExklECcPMGThw5czqLoYOijh3RAO7gyaNnTxsxfOr0cQ2boBg/f44AChRI0KDXCiEoX84cgp+AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+core-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAASC/PzuBFxaVNza3Ly2tJyanPyuBPQCBPz+/Ozq7GxqbFRSVHx6dKSmpHRybMzOzDQyNGRiZHRydHx2fExKRCwqLPTy9ISGhERCRCwuLERGTIyOjBQSFGReXJSSlFRSTDQ2NAwKDNze3OTi3Ly2rFxaXAQCBFxeXMzKxOzm3LyqlDw6NCQiJFROTLy2pDw+PGRiXMS2pOzi1CwqJBwaHAwODAQGDJSOhOzWvLymhKSajNTGrJyWhOTOpLSyrKymlKSelMS+rLyidMTCtMS6tMS6pMSynLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfVgAAAAQAChoeHgoqCAgOOjgQCBQKCBoMABwMImwgJCggFC4sGDAQNDZoIDg+gEAcABhESEwoUFQsWFw4KGBmCGhsFGwoLEBwYCRYEFxCEHRceFwofIBwhDSIjJBCCCxISDiUaGRwmJygpKr4AGAIl4issISYtLuncgi8YLxAs5SYwYshQgQ8AixksaNSwYYLDDRc4chS0USMEQxMhHOjYEbEggBUWTQhwwANiD4mLBPj4AYTHjyA9cPQQsq7bkCFEihhRkSPHkSMeBUDIAGFo0aMZ/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+deb-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/FxaXNza3Nze3Ly2rJyanPz+/Ozu7GxqbPz6/JwCBMw+PMQCBLQCBNx6fPT29GxubMzOzIyKhDQyNLwqLLRWVLxaXNyurERCRMzKxOzq5Ozq7MQ2NMRmZLwCDOTi3Ly2tMReXOS2tMTCvPTu5Ozm3LyulMSSlNTOxPTq3Ozi1OSytPTm1OzezLyqjNyqpLxaVNzSxOzaxPTy9Ozm1OzexOzavLymhOzWvOTOpOTStLyidMyShMSulLyifLyedCH5BAEAAAAALAAAAAAQABAAAAa0QIAQECgajcNkQDAYCASEQCGQFC4NWMMBkZhWFQtGw/EwQCIGyWSoaFAqFgblIkEgMGthQ5HRbAQcFAcaBGp6DQEJCx0XFx4ZGx8geQ1ECyECByIMIyQlJnkMRBwnBwYODSgpKqB6RCIcK6gEKiwtLpQKiS8WMAQxKi0yuEOICTM0LSo0NTY2N3kAbhoHBzQ0zjg50EkKHC80LCo2ODo5O9FEBCE8Pe49Pj8/6QET9vf4E35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+document2-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJSWjPz+/Ozq7GxqbJyanPT29HRydMzOzDQyNIyKjERCROTi3Pz69PTy7Pzy7PTu5Ozm3LyqlJyWlJSSjJSOhOzi1LyulPz27PTq3PTm1OzezLyqjIyKhJSKfOzaxPz29OzizLyidIyGdIyCdOTOpLymhOzavOTStMTCtMS+rMS6pMSynMSulLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaQQIAQECgajcNkQMBkDgKEQFK4LFgLhkMBIVUKroWEYlEgMLxbBKLQUBwc52HgAQ4LBo049atWQyIPA3pEdFcQEhMUFYNVagQWFxgZGoxfYRsTHB0eH5UJCJAYICEinUoPIxIcHCQkIiIllQYEGCEhJicoKYwPmiQeKisrKLFKLCwtLi8wHyUlMYwM0tPUDH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+document-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbPz69HRydMzOzDQyNIyKhERCRFQ6LJSKfNTOxJSOhPT29PTy7PTu5Ozm3LyulOzi1PTq3OzezLyqjOzavPz29Pzy7OzWvLymhOTOpOzaxOTStLyedMS+rMTCtMS6pMSynAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaLQIAQECgajcNkQMBkDgKEQFK4LFgLhgMiOq0WCAREQrFdKAVXKyNxaJgBjgck4khLBAPGm4r+ghETeHtEfVaAFBUWg15gjReKZ4YTFBgYGRpvcQoPDggRnwwMG5hnHB2UFxcbHh+LAh0YDA+zDyCtZ5UXIRsiIiAjiyQlJCYnGhofI8BKC83Ozwt+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+dvi-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAASC/FxaXNze3Ly2pJyanKyijPz+/Ozq7GxubIx+RIRyLHRyVGxqbMzOzDQyNHxyTHRqNGxiJHRiLJySVIyKhERCRGQmLMy6ZNS+TMSuPLSePIRaNGReLHRuTPT29FxOFKymdIRmLHRiHGxKLDQuDPTy7Ly2tHQqLLwyPIxqVGw6LIx2LGRSHDwyDDwyFNTOxOzm3LyqlIQuNLy+zKSGdKSSfJRSRKSSNExKJLSmnOzi1LyulIyCZIxiPJyGLExGFOTSvOzezLyqjLyyXAQCBNzGRLyeREw+DFRONNzSvOzaxGxqVKSelJSCNEQ6DFRKFKSajMS2pNzOtOTStLyidEQ+FLSunOTOpIyKdMSulLymhLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfVgACCAAGFhoaDiQECjIwDAQQBiYIBBQUGmAcIBpGTCQqgC5gMDZwOgw8KEBESEwkGFAgMFacAFhcYGRobEBwdHgIDFKcWHwYgBiEhIiMkAyUCJg4nKCgp1SorLC0uBC8wMQ4yMzQnNTM2Nx84LTkNOjunNjY88z0+Hz8kOUBBQqdDiHQoYiREhBZHkORIouSfIAghjCiI8IHEEiYDgAApUAtAEwgfnDzBASWKFCBTqHQE8ONIFRwErFxRcuWKSkU8sBTIkSWLFi1btqwM4KCo0aMO/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+font_bitmap-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAASC/FRWVFxaXNze3Ly2tJyanPz+/Ozq7GxubGxqbNTS1DQyNPS+vPw2NNQeHFw6PPTy9IyKjERCRPzi5PyGhHRWVOTi5PT29OTi3IyKhPza3LySlLQGBGQCBNza3Pz69PTy7MS6pKRubPy6vGQ2NKRSVIxmZPTq3LyqjLQqLHRydPxydHwCBNTSzPTu5Ozi1MSynKQCBOQ+PKwCBIReXJwCBExOTMzGtOzezOzWvEQeHLSytOR+fIxaTOzexLymhEwCBDweHNTOzPTm1LRORIQ6PJyOfOTOpOTe1OTSvLyedMTCtMS+rLyulLyifAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe6gACCAAEChYeGg4oCA42NBAEFAYqCAQMGmAYHCAaSlJaZmAkKnQuKAQwNDg8QBhEJCRKmgwITFA4VFgYXGAQZs5UaGxwdHgYfIAMhwAAiIyQlHCYgECcnKMwpKSoKKywtLicvMMwcHDEyMjM0L+3YgzUsNgH0HCw3ODnvgjU6OwMvBvCQ0cNHjh+zOgAJIqTaECJFOhg5gvAUEmsvksBAAeOIEmYBbixhEgJGExROlHw8taCly5cL/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+font_truetype-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFRSTFxaXFxeXNze3Ly6vJyanPz+/Ozq7GxubHx6fCwuLDQyNIyKjKSmpPTy9PT29HRydMzOzCQmJAQCBKyqrFRSVLy+vGRiZNTS1GxqbERCRMzKzJyenOTm5JSWlLy2rIyKhMzK9KSm1Kyq3OTi3OTi5JyezBQSJExOTLy6/CwuXLy+5LyulMTC3LSytHx+7Ly2pLSyxLyqlNza3Gxq1OTWxMS6pLyqjPzy7OzexPTq3LyynOzWvLymhPTy7DQ2bOTOpGRmhERCfNzGpLyedMTCtMy+rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfIgACCAAECA4WHhoOLAgSOjgUBBgGLggEEB5kHCAkHBgKCCgsKBgwNDg8HEBESngwAExQVBhYXGBmZDREaGwuDHB0CHh+4qgQgIa+CBMEiIyQiJNAlIMoAJgYDJygpKisWLAMtvoIe2S4pLzArMTIBM9YHBRUeNAQ1KwU2NzjWFAwDDEDIgS+GDh39Fl3ykGMHPh46evggJ2gAgR87HAKZYSOID2uECGQUMkRIAiJBioAUYMTIkRs8cODwUUSlQgY4GSzQuVOnn0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+font_type1-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAASC/FxaXNze3Ly2rJyanExKRPz+/Ozq7GRmZPz6/HRydMzOzDQyNJRmZPSmpIQuLGwWFKxeXPTy7IyKhNxSVGxCRLy6vPQ+PPT29GQ2LPTCxOROTPz69KQ2NPSGhPTq3Ozm5LyqlGwODPxiZOzi1LyulLwKDORydBQSDOx+fNw+PNS2tOzi3PTm1OzezLyqjNQaHPRubJx+fMS6rOzizOzaxMwuLKQWFHRaXOQuLJSShNzOvOzavOzWvLymfCwiHHx6dOzexOTOpOTStLyedMTCtMS+rMS6pMSulLymhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfFgACCAAGFhoaDiQECjIwDAQQBiYIFAgaXBgcIBgQFk4uYBgkKC5wMiQ0ODxAOERITCggFp4MUFRYCFxUCGAIDE7QAFBkWCRobChIcEr60HR0IHAYeHQQYEh8gIbQbIgjGIw8WEtgkJacmJyjfKSoFKywfLS4vpzAxEAgnHSYyJjMkaNSoB0CEChs3cMjIYULHDho8evig9aPiAQFAHAap0UPIREXYPpAIEnGIECLBABQoYmTGESRIfCQhglIRg5s4czLwEwgAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+gf-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIMAAPz+BFxaXDQyNAQCBMTCxPz+/ISChKSipERCBMTC/Pz+xPzerMQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARwEEgQahVijMmD/oRAbBw1FCgaFFrppeo5UtILWxlAGNWZHocA4bAxGAnDg9GA8LQCxGTQoHwVNYYEMEHtKYrEA0tctVIOo0Fl2Ct8AQLlKMnzLFg1KIHBCGoUbiR5VSd3C28TThpubgqIEhkfkh9+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+html-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFRaVNze3Ly2tJyanPz+/Ozq7GxqbDxinBw+ZERmdIySjMzOzPT29DQyNDRurIR2RPTSdJyulFSGxLzCxIyKjHRydERCRLzKvPzivPTmxNTChLSybGyCfCRSpBQqRLy6vPTy7OTi3IyKhCRShOTixPzy5OzerOTShLyaVEx6nCxerGRyhOzi1LSyrEyGvOzaxPTShNy6bEx6rDxyzDRitCRCfPTq3LyulBw2VISq3GySrPTWlHyanIyitEyO1ER6zBxCfLSqnCQ6XHSq3GyWvFyGvDxuvLSqpPTm1OzezLyqjCxajFyO1GSi3NS2bKyaTCQuPGRufOzexLSmlER2vKyWNFxaNHx6dLyunOzWvLymfERSVExKNDRCNKyilMy+pOTOpLyifFxaVLyidMSynMSulLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfYgACCAAGFhoaDiQECjIwDAQQBiYKLBZYFBgcFkZMICQoLlwcMDQQOgg8QERITnhQFFRYHF6cPGBkaGxwdHh8gISIDI6ckJSYnKCkqKwksAiEtLg4kLzAhMTIzNDU2HxQ3NzgOOTo7PD0+P0A1QR8uNy1CDkMvREUyRjNHHjkfSElKlpxi0sTJjydQAiSIIkXIFBhUTn14UIWGFQhXHHzAkgWGli2nAHxIwIRLFy8bv4DREkZMSEEfYo4hQAVMGJZkXhIaIERImTJmlogRc0ZnAAdIkyp14CcQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+image-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPz+BFxaXNze3Nza3Nza1LS2tJyanPz+/PTu5GRqZOTi3HRydMzOzDQyNJQOFDxKfKTW5OTy/OT23MTaxISKhGxmZERCRCwuLJQSFPzGpLweHJTO3ESu3DRilNz61FymXCxKRMTCxPTy7Ly2rIyKhDwCBORiRKQWFEy23CyKvJTWhDSOPCRONDQaHNROPNQ2JLRubHTC5DR6rHR+jFSqRCRyLGxqbOzm3LyulCwqLMySjMQ2JMyqrERijJSenFSGXGRmXMS6tPTq3Ozi1MS+vMxCNKyqrHR2dPTm1OzezOSKfNTe5KSmpIyGjLy2pOzWvLyqjIRqZIyKjHR2fExKTHx2bLyynOzexLymhERGRGRmZKSWhMS6pOTOpLyedMTCtMS6rMSulLymfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfcgACCAAGFhoaDiQECAwICBAUBBgGJggEEB5kHCAkHk5UBCpqZCwyeDYIOAA8QERITmRQLFRYXABgZGhscHR4fICEiAiMkDSUmJicoKQ8qKywLAwgKIxctLi8wMTIzNDUJNiEINzgNOTo7PBA9Pj/QQEFCQzg5F0RFEQQ+RhRHswVIkpS7oEMJgiUhCjBpcqSCkyFPoNjKEYVJCCNSpgSgUsXKlSdYUAG4kCOLlgpAgFTZwuVJFyy2Bi0gEsSJzZYuvYi09OULGC44wmAR48VLDkU5zClt0OACUz+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+info-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNze3Ly2rJyanDROXHSSpISetPz+/Nzm7GxqbGyGnMTS3MzW3JyuvERujLzG1HRydMzOzPT29DQyNMze5Iy2zLTS3Cx+pCRijLS+zIyKhGxubERCRFR6lGSivFyavISuxAxajBRejAxGdDxihJyyvCR6pBRqnAxelAxOfPTu5OTi3IyqvFSOtJy+1IyyzFxyhOzm3LyqlGySrAxejAQ6ZFxqfMzKxPTq3Ozi1LyulCxulAQuVISKjMzGvPTm1OzezLyqjBwmLBROdExOTKSinNTOvOzexBQeLAw2XAQmTCwyPLy2pOzaxOTWxLyedCQmJAQKFAQWJKSalOzavOzWvOTOpLymhKyqpMS+rOTStMSulLymfLyidAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfVgACCAAGFhoaDiQECjIwDAQQBiYIFBgcImAkKCJGJCwwNDg8QmBESEwQUgg4VFhcYGBkaCBsRHB2qHgwfIAghIiMkAhMCAxsUJSYhJygiKc4qCysrLAPILS4oLwgwKcExEisyMxQFNBg1Nb7ONjc4OTo7yAU8IiIIDiIqPT4/QEFCVA0hooJBAg0eehQxciQIEnKCktiYqGQJEwJNnCB5AkWVoChSpkwpQmXAkypWrmDxKAhSlixaTlrZcqWjIi0/BmjhsgNLFy82BwWgQDQK0aNE/QQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+kmultiple-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXPz+/AQCBISChPz+xMTCxPzerKSipAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARWEIRJgb04iLEJwaAmjMTwgVbAjeaESmNcGMGrxmOhDqE8HAOVJ7MSFH4qhOmiOQIPNIGB4JJwnIaDaFaTUL4iYxc0MJidQVvROc4Yfz+a+g3V2sAVfwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+log-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNze3Ly2rJyanPz+/OTm5GxqbMTCxARiTARSPARCNAQ6LAQyJGx+fGxubMzOzDQyNCxGPARyVARqTARaRLSyBCRGHFRuZIyKhERCRDRuXAx+ZPz+BIyOBFRybOTi3AyGbAx2XExaDBROLOzm3PTy7DRORDyeXBx2VEymVHyuJGRyDPTu5LyqlFyGTBxaNAxqVDR6PARKNPTq3Ozi1LyulCRuTCxeNBSCZDxmJEx6bOzWvPTm1OzezLyqjCSSdCSmhBySdBR+ZARqVEx+bNzSxOzizESCdAQCBNzOvOzexLymhOTStOTOpMS6pLyedMS+rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfIgACCAAGFhoaDiQECjIwDAQQBiYKLBZYFBgcFkYIICQkKCgsLDA0ODxCbEQASExQJFRYXpBgZDwcaqxscrgkdHqMfBiADGasIIRwiHSMdJB0YJSYCA6snKCkqFgorHSwdIC0lLqsvvx0wMTIWMxgCNDU2xzcdOBw5EzoKOzw9Pj/WgAQRIiTEkAlEihg5wgMgACRBkpwQIpGDRCVLeDCJACGJx48gAzRxspHQoZNPRkJZNSjAkygDntiwwYQJlJWKIujcyTOCn0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+make-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxWVFxaVOTi3Nza3LS2tJyalGRmZMTCxPTy9Pz69Pz+/Ozq7GxubJyWnFRWVHx6fHRydMzKzDQyNHx2bHx+dIyKjERCRGRiZKyilLSifMTCtLy+tISGhOS2bPzerPzuvOzetJSSjFxaXOzu7PTy7MS6pGxqbKSWdPS+dMSidOTerPzqtISCfKyurOzq5LSqnMzKxPS6ZEw6HJSKbOTStHR2dMzGvPTq3OzizLyulFRSTOyyVNymXOy+dKyqpPTm1OzezLyqjJyCTOSqTOSmRLSupNzSxOzaxOzexOzWvOTOpKyinMS6rNTGrLyedMSynAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfagACCAAEChoeGg4oCAwQEjQUCBgGKggcICQoKCwwNCg4CiwQPCBAFmRESCwYTghQCEgYHDBUSChYNDRetGAQZGhscHAIFDAoDHB2tAQYeHyAhIiMIJAolBCYTAicoKSorLBItGC4DLy8wExExKjIzNB81CBI2Nzg5Oq07KDw9Ph4mdgj4IQFIECGtHrgYQqRIjQoPjBzJkQMJQgANkrngYGFAhB8UkyjR0EpQAAkUKkQQkCGHEiVLLg6y8IDJhiZOXsJ8UtLkhpsmoAgRouIJT0UPJihdynSCn0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+man-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXFRWVNze3OTi3Ly2tJyanNza1Pz+/Ozq7GxubMzOzDQyNOzq5KSmpNTS1IyKjGxqbERCRPTy7PT29LSytOTi5MTCvMTCxLy6vMS6rISChLy+vPz69HR2dLSyrLy2rNTW1IyOjOzu7OTm5HRybHx2ZNTOxLyulLS2tIyKhHRuVMS+tHx6fGRmZLyqjISGhJyenMTCtGxqZGxmVMS2pFxeZGxiTMSynLymhHx6dGRiZFxeXFRSVLyifGxmTKSSfLyidMS+rLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAEChYeGg4oBAwMEjQUCBgGKggEHCJkICQoIBgKKkgSamQoLngyWDQ4PpAgQChESqQACExQVFgkXGA8ZBBobtAENDQsGHB0dEx4fBCC0AhYhGCIjFA0kJSYnKMMPHCkqFg0DIQorLN6WCx8OLQsHIQsuKxovtIQwMR4ZHDIYZtCogU+RjQAeUmDAkELBDRw58hHSsWMDjx4XV6DwIZGYCRc/aNz4AeRFkI4sZAipgePFCx9BhkgUwKCmzZsM/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+metafont-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNze3Ly2rJSWlPz+/Ozq7GxqbKSajPT29GxubNTS1DQyNIyKjERCROzi5Ly+vKyqrKSipKSmpKyurISChKyinHRybISGhGRiXJyanIyOjFxeXJyenJSSjMzGxMzOzMTGxLS2tISGjExOTLyulMTCxISWpGx6jExifFxufJyepJymrFRSVLSupLyqjERKROza1OTKzNS6vGRmZLy6vPz29Hx6dMTCvHRydJSKfOTStLymhNTCxLSOjKx6fMS6pLyifLSytHx+fOzWvOTOpLyedMSulLyidAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAGFhoaDiQECjIwDAQQBiYKLBZYFBgcFCJKKApcFCQoLBQQMnqAFDQoHDqeDAQ8QERITBhQVFhWnF4IVsxgKGRobHB0DrxUeHyAhIiMeGCQVFCWvACYCJygWKSoTFxcD1oMJGissJiwjFC0ZLi+nMBoLMTIPFDMzDS00FvEAYlyQUMNGiBs4OuQgoWMHj2sDe/j44aNCBh1AdgS5BoCGBhNChlxAQGRHESMcYXCI5sHCkRdIkKBUxKCmzZsM/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+midi-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Nza3Ly2tJyanPz69Pz+/ISChOzm3GxqbKSipAQCBHRydMzOzDQyNIyKhERCRPT29OTi3PTu5PTy7LyqjOzi1OzezOzWvLyidOzaxOTOpMS6pMSynLymhLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaOQIAQECgajcOjUTAYEAKFgDBgOFQNiMHhkFAYosQFg2HNbg0Nx/dB3W7NW0hDEWEjxm+BWzIhINhVbnBUFH12eAeDFRQUFoBuiVoGRRQXjgGQiQQLCwELBZaHZJGMARgLGZeZCARRUKgaom8DCAEZGwscqm5YrZyfHLFKRQQdHhYWHxogD0NED9DR0g9+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+mime_empty-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbPz69HRydMzOzDQyNIyKhERCRPT29PTy7Pzy7PTu5Ozm3LyulPTq3Ozi1PTm1OzezLyqjOzexOzavPz29OzWvLymhOzizOTOpOTStLyedMS+rMTCtMSynLymfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaBQIAQECgajcNkQMBkDgKEQFK4LFgLhgMiOq1eEQnFdqEUXK2MxKFBHnqvDsGA0aaaz4iHvE68WxEQERITfG+ADxQVhGV/DxEWFBcYhQIIgBEUFBkak2UbgYkZHBwdlIgUHh4aHB+lZZkVF6sgHyGFIiMiAyQYGCUhtkoLw8TFC35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+misc_doc-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFRSVFxaXFxeXFRWVOTi3NzW1Nze3Ly2rJyanPz+/Ozq7GxqbMzOzDQyNHRydExKRERGRExKTERCRCQiJIyKjCwuLGxubDw+PDw6PDQ2NBweHAQCBPT29IyKhNz+3HzmfDTCNASaBBxaHCQmJPz69PTu5JTqlGTOZCSmJAR+BBxSHOzm3LyqlFTKVASCBARmBBxGHNTSzPTq3Ozi1MSynAyeDAROBCQ+JBQSFNTOxPTm1OzezLyqjCwuNAQyBCQ2JMzGtOzexAwODOzaxOzWvLymhMzCrOTOpNTKvMS+rLyifMTCtLyulLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfcgACCAAECAwQCiIiDjAMFBgeRCAMJAYyCAQUKmwoLDAoJA5eZnJsMDaAOAA8BEBESExETFAsVDwwTFgAXAhgOGBkaGhscHQUIHqoDAR8gISIjJBQGJSbHugMSJygpKisU0x0mLC2qAhEuKS8wMRsbMiYzNDW6ARM26zc4ORQ6Mzs8evgAACGDChg3fgDhF6SAECE9VEXQYKGiDwtDKAQRQqSIEV25KGzIQZIDhSNFiiAxomoQAwM6kgRRgiQlkiW6BgVIwkQJghpNeixx4qQlJiAWHCh1kFSpBT+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+netscape_doc-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNTW1Nze3Ly2rJyanPz+/Ozq7GxubPz6/OTi1Ozq3GxiTMzOzCwuLMSijGROLLSqjGRiZOze1LSOdIyKjEw+NHxGJNSqjMTGxPTy7Ozm1NzWxLSSfFw+LMzKvHRuVKyeZHxybOTazOTi3Ly2tDQyNOzm3MS6jFxaRPTu5LyulOzi1KSehMTCxKSOdHxuRMzCpJSGXOTStLyqlHRqRIR2TFRKLLyedLyqdGxWLIR6XOzezJyCZJySbEQqHKyKdFRONJSKfOzaxNTCpKSWbJSSjExKNHxuNOzWvLymhIyKhOTOpHRydHx6bIR+dOTOrLyidAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfVgACCAAGFhoaDiQECA40CBAEFAYmCAQMGmAYHCAmSlAEKCwyZCA2dDoIPEIsREgkTFBUICBaoABcYGRobHAodHhkDBBW2AB8fIBwMESEiIxokJSaDJxAUKAwQESkaKicrqBssLS4vBzAfMTIRMwo00zU2LTc4OToQOzU3DDwr04Ixeljw8QNIiCBCYgyJUIxIESMfjuxAwoDDkCRK/j244CNHjhBIPDxYMoPJA1sXIDRxkuOIkycXHsyAEqUYoRk7GDAh8uJFDhw4/lUy4aCo0aJE/QQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+news-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/AQCBERCBPz+/FxaXIQCBMQCBMTCxISChKSipDQyNAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARXEEgZwrxYikFsvtUwBN0nEWIhkh4YiIOhjiX1hqIsHlb4jr8VwoJa/XCCBG4ZZA2bRxEi0QkgeLAloUZKYGEDhLgG6H5JBEFrYg4ItmsMCaGomFyEiz8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+pdf-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAASC/FxaXNze3Nza3LyypJSSlPz+/Pz69Pzq5Ozq7GxqbJyanNyGhNx6dGxubMzOzDQyNERCRPz6/My+vLxaVJxeXKSmpNTGxIyKjNTS1OTi5OzCxLRSVMTCxKyWjOTi3Ly2tIyKhLxmZLSWlOTe3MzKzOza3MyytNyOjAQCBKyqrOzm3LyulPSajMRWXOSGhOyGhKxiXOzi1OxyXKRORIxSTNTKzMy6vLyenLRubLwqLMxiZNSurJRybOzezLyqjJxCRGxSTLy6vGQiJMw+LJR+dMzCrOzaxIyOjKyurHxydNxWPNTCrOTStLymhIR2dKyKhIxuZIR+dJyShOTOpHRmZKSKhJyCdKyilMSulNTCpLyedMS+rMS6pLyidAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfQgACCAAGFhoaDiQECAwKMBAEFAYmCAQMGBwgHCQoGC5OKAgYMDZcODwYFEIkREhMUFRYXGA4OEauCGRkaGxwZHR4ZHyAhuAAdCQgiFR8aHSMkHwS4JRomIicoJykqHh0rLKstLhQcFC8wMR0FHgQy4TM0HDU2Nzg5Ojs8PQQ+P6tAggjRVaLEjiFEihg58k+QBSQdQCTpoITIkhBMmjgxVsBCxydQokiZYoTKxkRVrFy5EgJLFi1NqGwxRohLBy5dsmT54cXLTEUQggodCsFPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+pk-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/IQChFxaXDQyNAQCBPzC/MTCxMQCxPz+/ISChKSipERCBMTC/Pz+xPzerMQCBCH5BAEAAAAALAAAAAAQABAAAAR6EIAQhLVjECJlKISwjcZgcFNxhATiugKyTaP4wu0JiOyNXBqAIWFpvRQKgUHBSTgNS4UzseBxBMxoMiG1NTcJBpLBLTaaTIVM3fXuFKeQMmk7AwbSU5QocsgkFnAPD0kbFBQdO1hELQ4fK4lWLQ0IASsoEhojIwEjfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+postscript-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxWVFRWVFxaXOTi3Nze3LS2tKSajPT29Pz+/Ozq7GxqbJyanISChPz6/HRydNTS1CwqLMTCxISGhOzu7ERCRDQyNERGRLy2rIyKhExOTAQCBKyqrOTm5KSmpHR2dNza3AQGBNzSxOzm3LyulBweHBQSFKSilOzaxAwKDOzezDw6PJSSlDw+PKSelNzOvLymhAwODNzGrOTStLyqjExKRHRqZLymfMTCvMS+tMS6rLyynMS6pOTOpLyifMTCtMS+rMS2pMSynLyidLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfPgACCAAECA4aIA4OLAgSOBQQGAgcBi4KNCAmaCgsJDAKWjQkNCA4JDxCeEYwSDQ4TFKMPCxUWAA0BEQ0GDggQDxcIBBgZthobExwICB0eFRsSHcOrER8QCwYIIA8bIRwiIyS2JSYVHgsQzhsbJygEJKsl6ykeH9zrJyIq4gAp6xsrWLT45+IFChi2YqwLwcLEvxgHZMygsarBOgsCBGioUcNGxBk3bA0SgCOHjh0oeczo4WPVoAA/fgAJIoQGjSFEiIgUNCCCBZ8Wggq14CcQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+readme-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNze3Ly2rJyanDROXHSSpISetPz+/Nzm7GxqbGyGnMTS3MzW3JyuvERujLzG1HRydMzOzPT29DQyNMze5Iy2zLTS3Cx+pCRijLS+zIyKhGxubERCRFR6lGSivFyavISuxAxajBRejAxGdDxihJyyvCR6pBRqnAxelAxOfPTu5OTi3IyqvFSOtJy+1IyyzFxyhOzm3LyqlGySrAxejAQ6ZFxqfMzKxPTq3Ozi1LyulCxulAQuVISKjMzGvPTm1OzezLyqjBwmLBROdExOTKSinNTOvOzexBQeLAw2XAQmTCwyPLy2pOzaxOTWxLyedCQmJAQKFAQWJKSalOzavOzWvOTOpLymhKyqpMS+rOTStMSulLymfLyidAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfVgACCAAGFhoaDiQECjIwDAQQBiYIFBgcImAkKCJGJCwwNDg8QmBESEwQUgg4VFhcYGBkaCBsRHB2qHgwfIAghIiMkAhMCAxsUJSYhJygiKc4qCysrLAPILS4oLwgwKcExEisyMxQFNBg1Nb7ONjc4OTo7yAU8IiIIDiIqPT4/QEFCVA0hooJBAg0eehQxciQIEnKCktiYqGQJEwJNnCB5AkWVoChSpkwpQmXAkypWrmDxKAhSlixaTlrZcqWjIi0/BmjhsgNLFy82BwWgQDQK0aNE/QQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+recycled-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNze3Ly2rJyanGRmZKyqrMTGxPz+/Ozq7KSinOTi3LzatLTGpJSSlMzKzGxubMzWzPT29DQyNMS+rOTy5KzWlEymLDSSDKTClIyKjGxqbERCRGx+bNzu1Hy+ZESeHDSWDCyKDCyGFMTKxHx6fOTi5ISCfFRuVKzGnJzKjDSOFJy2lNTSzJSSjPTy7Ozm3FR6RJzChGSqRFSePHyqdMzOzLSytNTOvLyulExyREyWPESSJMS+vKyurMzKxPTq3Ozi1BxeDDSCHNTS1Ly+vHx+dIyOfPTm1OzezLyqjBw6FBxmDFSKRMzGxERONOzavBQ6DBROBHSOdCxeLDRCJKSelOzexOzWvLymfCw6LBxGHFRiTOTOpERGRKyqpMy+rLyedMTCtLy2pMSynMSulAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfWgACCAAGFhoaDiQECjIwDAQQBiYIFBgcImAkFCJGJCgsMDQ4PmBAREgQTghQVFhcYGZYIGhAbHKodHh8gISIjJCUCEiYDJxMoKSogGCsjLC0GLgkvMAMTMTIzIjQ1LDYHNxo4CTA5Ezo7PDstEQ8HPT4nP0BB5jpCQxFE7kU3RkcHkCRRomoJkyYHnBQZ0OEJARxJoBAUFEWKjilUolSxMiDJFSxZVAnSEmVLFC4EBnzE0iVkIi8EvnwBs5JlGJGCAogRQ2EMmTJZsoS5qWiC0aNIJ/gJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+resource-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFRSVFxaXFxeXFRWVOTi3NzW1Nze3Ly2rJyanPz+/Ozq7GxqbMzOzDQyNHRydExKRERGRExKTERCRCQiJIyKjCwuLGxubDw+PDw6PDQ2NBweHAQCBPT29IyKhNz+3HzmfDTCNASaBBxaHCQmJPz69PTu5JTqlGTOZCSmJAR+BBxSHOzm3LyqlFTKVASCBARmBBxGHNTSzPTq3Ozi1MSynAyeDAROBCQ+JBQSFNTOxPTm1OzezLyqjCwuNAQyBCQ2JMzGtOzexAwODOzaxOzWvLymhMzCrOTOpNTKvMS+rLyifMTCtLyulLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfcgACCAAECAwQCiIiDjAMFBgeRCAMJAYyCAQUKmwoLDAoJA5eZnJsMDaAOAA8BEBESExETFAsVDwwTFgAXAhgOGBkaGhscHQUIHqoDAR8gISIjJBQGJSbHugMSJygpKisU0x0mLC2qAhEuKS8wMRsbMiYzNDW6ARM26zc4ORQ6Mzs8evgAACGDChg3fgDhF6SAECE9VEXQYKGiDwtDKAQRQqSIEV25KGzIQZIDhSNFiiAxomoQAwM6kgRRgiQlkiW6BgVIwkQJghpNeixx4qQlJiAWHCh1kFSpBT+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+rpm-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/FRaVNze3Ly2tJyanFRSVOTi3PT29Pz+/Ozq7GxqbFxaXHRydNzazDQyNIyKjERCRGRmZExOTLyipOSytLy6vIyCfBweHMzOzNS+vMRqZMRSTNzGxAQCBLxCPMzGvLyulCQmJPz69IxKRIwWFLSGfLyynAwODERGRMTGxGRiXLyqjHR6dIyOjBQWFLSqnNTCpNTKtLyidPTm1OzezOzavOzWvOTOpMTCtMy+rMSynLymfLyedAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAazQIAQECgajcNkQMBkDgKEQFJYMBwQ2ITiEJ0uDFjsgdHgOpIFQRj7UCggZyEksIgoJBPKwVCxnBUXEgwYBgkGGRobHAYDDgUdFx1fawceHh8gDiEdnEthIgcjJCUmDh0nKJwdCCmcKh0WJiumQh0sFR0tFyYuLycwK5u1nBYsFwMuJicTs0MdEhUpDRkxMRkwMDJxQl8zBjM0NTY3N9poKTg5JjorKzsyPNtEDvT19CH0fkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+shellscript2-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNze3LyypJyanPz+/Ozq7GxqbPT29HRydMzOzPz69DQyNHRaJKyONJR2LJyCJKyCHKSCHMSqZNTOvIyKjGxubERCRGxSFIxyRKR+HMyeHOTCLMSOHLyWFMzGtIyKhHx2bKSGZNyiFHxeDOTi3Ly2rMyudOTCpOTKxLyqjJR2VJxuDLSGHLSunPTu5Ozm3LyulJx6NNSyXOTCjOzWvPzi3MyqhGxSLFQ2DLSKLNSqTPTWtPzq7NS2nIxyVIx6ZOzezFxCFOy2POSyROTGlPTazPTWxLSiZLSSVMy+rOzaxKyCJMyeNOSyTNy+dLymXLyePNyqPKSWfOTStLymfKR6HMyaPMyaNJR6TMy6pFxKLHxWFKR2FIxiDOTOpLyedMTCtIyCbMSulAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfQgACCAAGFhoaDiQECjIwDAQQBiYKLBZYFBgcFkZOVlwgJCgsEDIINDg8QERITFAUVFgcXpYIYGRobHB0eHwgCAyC0giEiIg8bIyQCCCUmtCInKCkpKissLS4vMDGlMjM0NQsINjc4OQ0U26U6OzQ8CAg9Pj8uQBRBKgxCQ0QzRUY2jiDRkURJkCX5ADBp4uQJjRNQokhpMSUIlSqlcFjpQOQKESlYWmTRQuUirS1cumy04qWBlhpUvoARRihMGDFaBoxRUQXMTEUMggodysBPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+shellscript-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFRWVFxaXNza3OTi3Nze3Ly2tJyanPz+/Ozq7GxubNzSxMzOzMTGxHRybDQyNLy+vHRydHx6fKSipISChIyKjGxqbERCRCwuLLy6vGRiZExKTCQiJAwKDLSytLy2rJSSlHx+fDw6PKyqrBQWFPTu5Ozm3LyulLS2tCQmJAQCBPTq3Ozi1MSynCwqLAQGBOTazOzizOzezLyqjBweHNzSvOzaxKyurHRuZNzOtLymhDw+PIyCdOzWvOTOpLyidNzKtOTStLyifMTCtMS+rLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfZgACCAAEChYeGg4oCAwQFjgYBBwGKggEECJkICQoIkwADCwwNDY2mDA4Lng8QDhESsLARExQVDhYXGBkWExIaGw8cHR4SCQQfFQ8eFgUgIQEiwiMSBMYfGB4atwEXDyQd0wQlJicPKAHoFyIpJCoeDgMrLC0YKBsX6i4kL+4OMDEyZijr5oLGNxUqUCioEcPGDAwjPNyI6MEDChQjcOSwsUDHgw07RIgI4KCkAgs8cvTw8eOBogAxQtXIASTISiEuBwUYMoRIixYnZggpUgTDywdIkWJIitRPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+sound-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXFRWVExSVNze3Ozi1Ly2rJSWlPz+/Gx6dNTS1Ozq7GxubGxqbDRmbDQyNFRiXBy6xFRmZLy6vIyKjERCRAQ+RBy2xByqtHRydIyOjPT29PTy9OTi3ISGhAQ2PATC1ByGlPz6/MS2pAS2xHS2vMTCxJyenLS2tPTq3Ozm3LSmnAQaHARibARudAR2hEySnOTm5MzGvLyulARKTARWXDyCjOzaxAQiJEx+hNza3MzCtOzexOzavLymhBQuNCxqdLy+vKSelOzWvLymfDxOVISipAQCBNzOtOTOpFRybKSejMS6pOTStLyedMS+rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfLgACCAAEChYeGg4oDBAUEjwYBBwGKggEICQkKCAsMCJOVAw0OA4wIDZsHD4oQERINDRMIFA0MFauCFhcYARkJGhscHRMeuB8RICEQHgcaBCIcBSOrHyTWJSYnKB4KHCkqK6ssLS4vMA0LMRoyKe0zuDQ1LTYoHBwU7Ck374M4NTkmdHDIsKMAjx4+cAn6ASSIAhRCdvDgMYSIQkJFjBzJsALJjSFJLCoSUKCIkiVMegxpksTJxQATnjwZMWMGER9OXI58wLOnzwd+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+source_c-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbIyKjMTCtPT29GxubMzOzPz69DQyNHRydERCROTi3IyKhIyOjPzy7PTu5Ozm3LyqjPz29PTq3Ozi1LyqlPTm1OzizOzWvLymhGxudGRmdFxedFRWdERKdDQ+dHR2dFxidAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaHQIAQECgajcNkQMBkDgKEQFK4LFgLhkMhOl0iElbFgtEgOJQC8BXxOEDOw0DkGhYMJHCq4FuYJBQUEQN5RGlWYBQVFheEVWEYFRkaG40RXw2JGX6MaIiRHGCccQKAkRodHh4fjQ+tICEiIyQkJY0mJg8FJwWzJbVKD7gnI7K+v3EOycrLDn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+source_cpp-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbIyKjMTCtPT29GxubMzOzPz69DQyNHR2bERCROTi3IyKhIyOjPTy7Pz29PTq3Ozm3LyqlPTu5Ozi1LyulPzy7LyqjPTm1OzizOzWvLymhHRydHR2ZHR2XHRyTHRyRHRyPHR2dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaHQIAQECgajcNkQMBkDgKEQFK4LFgLhkMhOl0iElbFgtEgOJQC8BXxOEDOw0DkGhYMJHCq4FuYJBQUEQN5RGlWYBUWFxiEVWEVGRYaG40RXw0ckV8djYaZFh5gnGgKnx4fICAhjSIPrSMkJCUmJ6woBQ8FJAUlJ7VKDygPD7G9vo0OycrLDn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+source_f-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbIyKjMTCtPT29GxubMzOzPz69DQyNGR2ZERCROTi3IyKhIyOjPTy7PTm1LyqlPzy7PTq3LyulLyqjPTu5OzexOzWvLymhHRydHR2bFx2XFx2VFR2TEx2RHR2dFR2VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaHQIAQECgajcNkQMBkDgKEQFK4LFgLhkMhOl0iElbFgtEgOJQC8BXxOEDOw0DkGo4MJHCq4FuYJBQUdnlEaVZgCgYVFoNVYRcYGBEZjBFfDRePEgkajIUXGxgVYJxoCp+hHBwdHowfIK4PDyEiIyStJSUFDwUmJiS2Sq8PILG+v4wOycrLDn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+source-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbIyKjMS+rPT29GxubMzOzPz69DQyNMTCtHRydERCROTi3IyKhIyOjPzy7PTu5Ozm3LyqjPz29PTq3Ozi1MSynPz27PTm1OzizOzaxOzWvLymhLyifOzexLyedLymfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaJQIAQECgajcNkQMBkDgKEQFK4LFgLhkMhOl0iElbFgtEgOJSCx7WAgBwi52FAsi4oBINJnCpAqCkPChUSA3tEEmoFahUWFxiGSwphGRYaGxyQEn4NHZVfj2iLlR5qoHICGYyWHyAhIpB9Dxp+IYAjsGokaiFqJZAJDwkDHBwYJiW+Sg7LzM0OfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+source_h-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxubPT29IyKjMTCtMzOzDQyNHRydERCROTi3IyChIyOjPzy7Pz27PTu5Ozm3LyulPz29PTq3Ozi1Pz69LymhOzizLyqjPTm1OzWvIyGhIR6dIRubIRmZHxaVHxSTHxCPIRydIReXHxWVHxKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaIQIAQECgajcNkQMBkDgKEQFK4LFgLhgMiOl0mFFbEYVEgMJQC8DXRODjOw8DjGhYMIHCq4FuIKBASDwN5RGlWYBMUFRaEVWEXFBgZjEoPXxoSkX4bjYaZGBxgHZ2AkR4cHx+cSiAJCRAhIiMkJSaNCREgBScFKCkqtkq4sLK0JsFxDMrLzAx+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+source_java-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFRWVFxaXNza3OTi3Nze3Ly2tJyanPz+/Ozq7GxubFRWXHRydMzOzDQyLIyKjGxqbERCRCwuLHx6dKSinKymnLyyrNza1PTy9Ly2rIyKhDQyNGReXKyejKSWhIx+bJSCdIRuZCQiJISCfGxaPJSKdHxuVHReRHxiVHxeVGRGPKSajMS+tMSynAQCBFxeXGROLFxCLFxCNFw6LGxiXFxiZMTCtOzi1ERGRLSytJSWlERKTNzSxOzaxKymlOTi5JSSjISChBwaFNzGrLyqjKSmpDw+PMS+rOTStLyqlLyifGRmZKyqpLyidAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfWgACCAAEChYeGg4oCAwQFjgYBBwGKggEECJkICQoIk5ULmJoIDA2eDoqXowgPDBAREoIRExQVFhYEBA0XGBkaGwAcHR4dHx4gIRMGDBcEFg4iIyQlJicoISkqISssBC0OLi8lMDAxMiozNDUUNjctEjg5OjklDCEcOy4OFDw9Pg4QfuQAEgTCDglCHAQYMaQHEVRFBhRhIACHAyMLIHg4guShIAg6KDwYMYHBhBVJhiBRgmrQkhxMKlBo0ULlkCYtLbGwYYNmCyJNguYk5KBoUQlGi/oJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+source_l-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbIyKjMTCtPT29GxubMzOzPz69DQyNHRydERCROTi3IyKhIyOjPzy7PTu5Ozm3LyqjPz29PTq3Ozi1LyqlPTm1OzizOzWvLymhGxudGRmdFxedFRWdERKdDQ+dHR2dFxidAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaHQIAQECgajcNkQMBkDgKEQFK4LFgLhkMhOl0iElbFgtEgOJQC8BXxOEDOw0DkGhYMJHCq4FuYJBQUEQN5RGlWYBQVFheEVWEYFRkaG40RXw2JGX6MaIiRHGCccQKAkRodHh4fjQ+tICEiIyQkJY0mJg8FJwWzJbVKD7gnI7K+v3EOycrLDn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+source_moc-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIQAAPz+BKSipISChERCBPz+/AQCBMTC/MTCxISC/FxaXDQyNASChARCRPzCxAQC/PzerMRaBPyCBPyqXISCBPwC/MQCxIQChATCxMT+xATCBASCBIQCBARCBPwCBMQCBMTCBCH5BAEAAAAALAAAAAAQABAAAAWOICACQRkI6DCuJOG+JysGL1wIMm0YNHEUBNwqsDMgEL5AIqEYIhZPxqtwUI0CzwRDSih4E6KGeLl1vB4FMAASkTC1icmjmxZBKBXL4YLJaAoPgWoQEBsbGX4JHHR1Ih0eChkTGoqADQ9qMwR+GhwcXlSZAAJzDQNogZeiAUBeaAcNHw2iAygocQkCuQN+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+source_o-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbIyKjMTCtPT29GxubMzOzPz69DQyNGR2ZERCROTi3IyKhIyOjPTy7PTm1LyqlPzy7PTq3LyulLyqjPTu5OzexOzWvLymhHRydHR2bFx2XFx2VFR2TEx2RHR2dFR2VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaHQIAQECgajcNkQMBkDgKEQFK4LFgLhkMhOl0iElbFgtEgOJQC8BXxOEDOw0DkGo4MJHCq4FuYJBQUdnlEaVZgCgYVFoNVYRcYGBEZjBFfDRePEgkajIUXGxgVYJxoCp+hHBwdHowfIK4PDyEiIyStJSUFDwUmJiS2Sq8PILG+v4wOycrLDn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+source_p-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxDQyNPz+/FxaXKSipPz+xPzerISChATCBARCBASCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARVEEgQqrUz3yqGCJlUESRZEFVooWZAfJpbEkU9gNMqo4KBi7vSAfWjyFxIUnEkJAwPy9EugEDFSE+nMzojVKvLREGsKCgWjMVybDaj0eH2OZ2Objb+CAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+source_pl-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbIyKjMS+rPT29GxubMzOzPz69DQyNMTCtHRydERCROTi3IyKhIyOjPzy7PTu5Ozm3LyqjPz29PTq3Ozi1MSynPz27PTm1OzizOzaxOzWvLymhLyifOzexLyedLymfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaJQIAQECgajcNkQMBkDgKEQFK4LFgLhkMhOl0iElbFgtEgOJSCx7WAgBwi52FAsi4oBINJnCpAqCkPChUSA3tEEmoFahUWFxiGSwphGRYaGxyQEn4NHZVfj2iLlR5qoHICGYyWHyAhIpB9Dxp+IYAjsGokaiFqJZAJDwkDHBwYJiW+Sg7LzM0OfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+source_py-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNza1Nze3Ly2rJyanPz+/Ozq7GxqbPz6/NTSzDQyNKSujIyKhHRydERCRGR2PHyaLLzObIyqNKzCZIymRKy6jPTy7OTi3ISChFx+HISaNKyuPJyaBKTCRKS+VISiVGyKJHSGPLzWdKS+TMzefISCJHRiBGySJJSyNLTGbKzKRHSaHJSWhLyulHSKNJy6RKzCXISWRLTOZJSuVIyuJGyOHHyWLOzaxJSqTGyGJJSmXHySPJS+JHSOHIy2JHR2XLyqlERaHGSGHFRqJHSOJGR+JFxmPNTOxIySbHyORHSWJPTm1ISiHHyiJFRuHMSqjPTu5OzexFx6LMTCtMS+rJyidISqJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfKgACCAAGFhoaDiQECAwMCAgQBBQGJggEDBpkGBwgJk5WXmgYJCAqeC4kFAwysCQYNDggPqIMQERITFBUWFxgEGagaGhsVHB0eH8ggvQQLISIjJCUmJygpKissLRcuCy8wMSMqMhszMzQ1Njc43QA5Njo0Ozw9Pig/LCxAQbRCOkM2iBQxgsLGjyJH+CXKoEABkiRKWCxhQYQBLUsYLhxgwkRJEydPoFwkhCEKRylKbNSYIlIRASpVCFj5UeMKhJaDAizYybPnAj+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+source_s-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbIyKjMTCtPT29GxubMzOzPz69DQyNHRydERCROTi3IyKhIyOjPzy7PTu5Ozm3LyqjPz29PTq3Ozi1LyqlPTm1OzizOzWvLymhGxudGRmdFxedFRWdERKdDQ+dHR2dFxidAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaHQIAQECgajcNkQMBkDgKEQFK4LFgLhkMhOl0iElbFgtEgOJQC8BXxOEDOw0DkGhYMJHCq4FuYJBQUEQN5RGlWYBQVFheEVWEYFRkaG40RXw2JGX6MaIiRHGCccQKAkRodHh4fjQ+tICEiIyQkJY0mJg8FJwWzJbVKD7gnI7K+v3EOycrLDn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+source_y-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxubPT29IyKjMTCtMzOzDQyNHRydERCROTi3IyChIyOjPzy7Pz27PTu5Ozm3LyulPz29PTq3Ozi1Pz69LymhOzizLyqjPTm1OzWvIyGhIR6dIRubIRmZHxaVHxSTHxCPIRydIReXHxWVHxKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaIQIAQECgajcNkQMBkDgKEQFK4LFgLhgMiOl0mFFbEYVEgMJQC8DXRODjOw8DjGhYMIHCq4FuIKBASDwN5RGlWYBMUFRaEVWEXFBgZjEoPXxoSkX4bjYaZGBxgHZ2AkR4cHx+cSiAJCRAhIiMkJSaNCREgBScFKCkqtkq4sLK0JsFxDMrLzAx+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+tar-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaXNze3Ly2tJyanPz+/Ozq7GxqbJySbJyadPT29Pz69GxubMzOzDQyNPz21LSujPz25OzmxNTS1IyKhERCRKyqjLy2rKSehPz67Pz23OzerKSaZMzGxPTy7PTqvOzirMy+dKyeTIR2NPTq3LyubLyqVJySPHxyJOzi1LyunPTqzOzW5OzSzNzOrJSGNGxiNLy2pPTm1OzezLyqjJSKZOTStOzOxNzGtOTSjKSSRIR+LGReHLyynOzexLymhOTWlNzOhFxSFHRuRNzKfNTGdHxuLGxeJIyCbMy6pLyifLyqlNS+pOTOpLyedHRydJySfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfLgACCAAGFhoaDiQECjIwDAQQBiYKLBZYFBgcFkZMICAkICgULDA0LBA6Cnw8QERKgExQHDBWpCBAQFrm4EAkKAhcUqRgRGRqsGxIbHB0eAgOpCRofCw8WICEiIwMkJBDRCwsgICUmIico3CkqtissLS7mJy8wMTIzNKk1Njc4OSI6Xuzg0WOGjx/6gOQIEkTHiB0ohKjwYQOhoCEliBQxcuQIDCRJbNhQkmoQRhgflzAR2cRJSUFPekDpQbMHjR9OXCpywLOnTwd+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+tex-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxDQyNPz+/FxaXAQChKSipPz+xPzerAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARgEEgQqrUz3yqGCJlUESRZEFU4lkQREJ/2skU9BEaezzmRCwccwDCc+XwIFGhI0ZEMxiURxzIQkghp0+qjJlDDHdRnQPSyGu4oEfguRTrs9fqmWAjfPHpSkWMReyIbg34RACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+tgz-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBIQChFxaXMQCxNze3Ly2tJyanPzC/Pz+/OTi3GxubJySbJyWbPT29MzOzPz69DQyNPz21LSujPz67OzmxJyadNTS1IyKjGxqbERCRKyqjLymhLy2rIyKhKSehPz23Pz+9OTevOzmtKSaZMzGxPTu5PTqzMy+dKyeTIR2NPTq3LyulOzirLyubLyqVJySPHxyJOzi1OzW5OzOxNzOrJSGNHRmJOzezJSKZOTSjGReHLyunOzaxOTWlNzOhKSSRIR+LFxSFLyynOzWvHRuRNzKfNTGdGxeJGxiNIyCbMy6pNS+pNzSrAQCBHRydLSunMSynAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfYgACCAQKFhoaCiQOEBI2NBQIGAooHjAiXCAkKCJIAAZ8BCwsMCw2XCg4PBhCCohESExQVCxYXChgZrAsSvBIaGxIbDA0JHB2sHh8gHx8SISIiIyQlBBysFR8mzBIiJygpBSUqK9cPEywiLS4oLzAFKjHkAAwmMjM06y81NgUmNxuscNCYQSIHuxopdOy4wQMgABw9cvjw8SMFEBhBhPAY4hAAkRZFjKQ4cgRJEiWgAiTy2AKJSSFLmAQ4MKDJSidPFggRAmXFhgADNthMJACC0aMQAjRZ6icQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+txt-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaVPzKjMR6RNze3Ly2tJyanPyODPz+/Ozq7GxqbPyKBPyGDPzGjPT29HRydMzOzDQuJOx6BPyGBPyKDOTWzIyKjERGRDQyNKROBOR2BOzezIyKhBwOBKRKBNSOXOza1CQOBPyCDOySZPzizPTWxPTy7Pz69Pz29PTq3LyqlMxmJNRyROy2lPTu5OTi3MSulFxGNIRWLMR+XPTKrOzStPTm3IRSNOzizOzavLymhLSyrEw6LKRuVIx6ZNzSvOzexNzWxNzW1FROTBwaFKSShOzWvOTOpOTazJyWjHRqXNzKrOTStLyifMS+vMS+rMS6pLymfLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfOgACCAAGFhoaDAgOCAQSOjgUBBgGCB4qEBAiaCAkKCJMACwwNA42bCA4PEA4GERITFKQVpwgWDwoXGBkaE6MDG6cOBAUcGB0eGgsTDR8gmw4OGwURACHIIiMkJSYIJygpKSoYgtYrLC0kLdAuKS8w1IIdMTIzNDUbLjYpG+KDABcRbtRrYWMDjhw6xg0KsCMAjx4+fmwAEiShvwBCChgYQqSIkRpHdMBjZCIFkh1JlCxhcqSJQkZOnjyBAgOGjihSpLwkhAFDBJ9Ae0bwEwgAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+unknown-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXIyKjNTW1Nze3LS2tJyanER2RGS+VPz+/PTu5GxqbPz69BQ6BCxeLFSqRPT29HRydMzOzDQyNERmPKSypCRWHIyKhERCRDyGPKz2nESiLBxGHCyCHGxubPz6/PTy7Ozi1Ly2rKSipOzm3LyqlKSWhCRyFOzizLymhNTKtNzOvOzaxOTStPz27OzWvOTOpLSupLyedMS+rMS6pMSulLyqjLymfLyifAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAamQIAQECgajcOkYEBoDgoBQyAJOCCuiENCsWBIh9aGw9F4HCARiXciRDQoBUnlYRlcIgsMG5CxXAgMGhscBRAEBRd7AB0eBBoIgxUfICEiikSPgyMMIAokJZcBkBybJgomIaBJAZoMpyCmqkMBFCcVCrgKKAwpoSorKqchKCwtvasIFBIhLiYvLzDHsxQNMcMKLDAwMqEz3jQ1NTY3ONyrE+jp6hN+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+vcalendar-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXDQyNAQCBMTCxPz+/ISChAQChKSipAQC/Pz+xPzerPyqXMRaBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARyEEgQahVijMmD/oRAbBw1FCgaFFrpEbB6jt1g3OpFAscxwATUiIAgBRKJXiqIYJEMBQNSWSAYgptrMDo9FJqKrHArTR4WLGisSkbebE12gXFFGRBFyd3eaFSvbx1xCDBXC2E1e1EECo07ABkaBh4fGn4RACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+vcard-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXDQyNAQCBMTCxPz+/ISChKSipISC/ERCBMTC/Pz+xPzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARvEEgQahVijMmD/oRAbBw1FCgaFFrppeo5drKhXqQUEIfREyweqWIoHo4GDYtkGxwQ0CjitEkUrCyfYjtdbJoFW/agmLJWWZSY3B0EbGJ4uAwcHlK2HpTg7YgHBgQjDH0THoGBCwULjDkAGR+RH34RACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+video-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaTFxaXIxuHJyCLHx6ZLy6vJSSlNze3Ly2rMy2RNS+TKyqrMzKzPz+/Ozq7GxubJyanLSePKySNKSSPNTS1JSWlDQyNMSqPLSmVNzKZJyenIyKjHRydGxqbERCROTWXNS6XOzidNzOZPT29MS6rISChLSulMy2TLyeNKSOPJyCPOTi3JSSfHxiFGxaJFxWLFROLPTu5Ozm3ISCdDw2BFRKHHxqPFxWPLymTMzCvPTq3OzezKSWTMzCbNzGZExKNHx6dLyqjMy6XMSqTMSmTEQ+JHRybMSynISCbMyyVOTWbLy2ZBQWFGxqZOzifDw6LCwiDISCZJR6LIRqJBwWDExKRHRuXHxmJGxeJFxSHCQiFFRGFGRSHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfhgACCAAECAoWHhoMDBAUGBwiRkQkCBwGCCgsLBQwNDp8ODxAOEQIAChITFJwVoA4QnhYXEhgZBRoFG62fHB0eHxcgIQUiIyO5uyQIJSYXJwUoKSoUKwEWniQkLCUXHy0DLi8vMDEfBw0kMjMnFwAfNDU2Nzc4OTgmOjs87ILvEj04NPj4ASRICR5C2vVrEWAIEQwSihg5giThIHdJiCgJMWIJkyZOLA4K8CHJkycimEAJEcWJQkECEHyQEqIHFAJTqFSxcjGAjhIfrlzAkkWLDS1bel5Y+mELly5YCEyQ4CcQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+wordprocessing-16:mimetypes mimetypes16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFRSVFxaXFxWTNze3Ly2rJyanPz+/Ozq7GxqbHR2dHRydGRmZERGRMzOzCwqLJyWjOzi1Oze1PTm1PTm3IyKjDQyNERCPPTy7HRmXCwqJPT29DQ2NNTGnOzm3PTq3CQqJMS2hDQuLKyaXCQmHBwaHKyahLSijKyehBQaFCQiHHRqNPTu5LyulCwuLHxyNAQGBBQSFERCRBweHOzezIyCVJSSfOzavLyqjOzexOzWvLymhExGJEQ+JExCJExGLCwqHOTOpDw6POTStLyifMTCtMSynMSulLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfWgACCAAECAwIChYeDjAIEj48FAgYBjIIBBAeaBwgJBwYDjAoLDIkNmgsOnw+CEBESExQSEgsHFQsJDRYAFxWbmhgZGhsEBRUcHQ8cEB4fzhAWICEYxSIjJCUDJicnKBkpKissFC0uLwAwMDEyFzHpDxgfES27DyozMyX6+TMTEzQtWJWoIYGgQRsl/t3AsStFQRoGIYrIkUPHDhcANPDo0cMHxx9AUtzQEWQHKwAcSDy4IAQbh5FDghDZNShAkZsFjBzBgaQnh0YcHojgIMIFBwtBXfgJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+1downarrow-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBBQSFAQGBDQyNExKTHx6fGxqbFxeXGRiZFRWVDw+PAwKDJSWlOzu7LSytJyenJSSlISGhISChIyOjFxaXDw6PPz+/MTCxLS2tIyKjKSmpKSipJyanAwODDQ2NHRydERCRFRSVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZzQIBwSCwaj8ikcslsOp/OgHRKlQoCgymRUDAcEIkwYgxWFBYERpHQcDwgEclEQmk8DhWL2kiIXDBwExMNGRoJaUkEEH8bEQ0cGgcWAksEHX8QHBKSHk1sfxMHH5ROBBsOICGkT2wiq1CIULKztLW2t0h2QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+1leftarrow-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAQCBExKTJSSlHx6fAQGBOzu7GxqbJyenPz+/LSytFxaXMTCxGRiZKSmpISGhFxeXISChAwKDFRWVHRydJSWlBQSFERCRIyKjDQ2NIyOjLS2tDw6PBwaHFRSVDw+PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZ5QIBwSCwaj8ikchgQLJGBgfNZDBAKBirRekBMtYGEYsHIgsWNhOO7tCrShDU18Hg/CJAIG0o4wCUQcksTFBUSCRYSEnpUFxgIGQkJGYyNGggbHBaVjR2QCxEeWkITHQ4IH3tPFwEMA2ajAKUgqlQTTbFEE7W5vUgGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+1rightarrow-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNGReZAQCBMTCxGRiZMzGzOTm5LSytPTy9Pz+/CwqLOTi5Ly6vCwmLMzKzJyanJSSlBQWFKymrIyGjCQeJJyWnISChISGhHx2fKyurDw6PAwODHx6fHRydDw2PERCRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZ2QIBwSCwaj8hkMRBQKgOCgRMZIBSk06XhEM0SA4iE4uoVLhCMhqLrdSAekMgYO5VM4BQ521mxIC4UFxBWdEkSERYYFxETGQGFSBKCGBEaGRuQSBwdeZaPXpsQCB6YZQMdEI6ZSgMepKusHh+wrCC0rLdlursGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+1uparrow-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBFxeXDw+PMTGxHRudPz+/JSSlLSytIyKjHR2dISChIyGjIyOjLSutLy6vKSepJyanISGhJSOlOzm7Ozu7MzGzKyurJyenDQyNGReZKSmpIR+hCwuLCQiJBwaHBQSFAwKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZtQIBwSCwaj8ikcslsOp9QYyAQFQYEAyr0Sihkn1fDAeHVLsOJNELxVaITC0bDUU6GH5AIQ8KYrNtFVxQVFBYWFxgRCREYdUQZGhYEDwgIGxAHCQocCgWOQhmhGR0epR8gqCFTq1Wtrq+wsUt0QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+2downarrow-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBAQGBBwaHDQyNExKTHx6fGxqbFxeXGRiZFRSVDw+PAwKDJSWlOzu7LSytJyenJSSlISGhISChIyOjFRWVDw6PPz+/MTCxLS2tGRmZDQ2NAwODJyanKSmpKSipIyKjHRydBQSFERCRExOTFxaXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAasQIBwSCwah4FkQKBsDpoBIqFgOCASCYRWm1AUFgRGkdBwPCARiWRCaTwOFYvYSIhcMOiJpJGZaDYcR0IEHXceEQ0fICEWIoJDhHcQHxIHgI9SEHeVG46YUh8OISOen1INCqWmUnOYTUxQAU9NUlRWWFtbCiRgrYNlZ2lriG8lYUd1khETE24gCZeCkRgeFBAQIAeNn9OTlXKrBJoYnKrcoaPmpmSpq3S+7u50QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+2leftarrow-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAQCBExKTJSSlHx6fAQGBOzu7GxqbJyenPz+/LSytFxaXMTCxGRiZKSmpISGhFxeXISChAwKDFRWVHRydJSWlBQSFERCRIyKjDQ2NIyOjLS2tDw6PBwaHFRSVDw+PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAavQIBwSCwaj8gkMiBYNpeDZzEQXRIKBmPgmtUSDgipcAsWjxOKBaN7Tq+n6EbCIQ3E5+KtQk6gjwl7CX11D3sPBBARTQGFDYeJT2R8EhB0koKUfgATFBUSCRYSEoqcnqCiikMXGAgZCQkZqautr7FiFxoIGxwWqQC4ury+qh2tCxEexMbIRhMdDggfYs7Q0kcXAQwDbELY2txEziBmmx3jSRNMR+nk4e2b70ry80QGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+2rightarrow-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNFxeXAQCBMTGxOzm7CwqLLy2vPTy9Pz+/Ly6vCQiJLSytLS2tLSutOTi5MzGzKSepIyKjJSOlKSmpMzKzJyanIyOjBwaHIyGjISGhJSSlISChBQSFJyenIR+hGxubDw+PHRydHR2dEQ+RHx6fERCRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa6QIBwSCwaj8hkIIBcJgEBweAYnTYJUmMAa9USClniFtwlGg6IRFhoUKTXwwWj0FB3F46Hwl6UQyISfAB+EROCQgsUFRYSF3yJEIyBaxgWDBkaGRtclQwSHBIbEGEdGx4fGhcOICEDGBsWHBmqIq1CHRIWGRMMIyRTHRy6Er22tyONq8YdJRe0xkIDwr2/QwMfliMmZQADIxasZd4e4UYDIr7c59rc0eVFA+/m0EQD9PDt0flP/P3+BkEAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+2uparrow-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBGReZDQyNMTCxHx6fPz+/JyWnKyurHx2fDw6PJSSlISGhIyKjIyGjISChLy6vJyanOTm5PTy9OTi5MzKzLSytKSepMTGxMzGzLS2tLSutKymrHRydCQiJCwmLBwWHAwODLy2vHx+fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAajQIBwSCwaj8RAAMkUBgSDZdP4JBSi06TAcEAkFNLp07BgLLzY5njRcDzO3zB1C4lEGI83Wj58SiYUFRUWdg0XEXFFAwIYGRoWGxwRZQUFHZdgRAObmx4fHiChISFKpVlKWUdPaalOAlasp1sHG4myZGZ7Yltsbgu1mUhjdRF5egmxfQJ/gYOFdrZDi40iFgiSCw8jBQmYcpydn6Ego6WorUwGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+abs-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBIQChAQCBBQSFCH5BAEAAAAALAAAAAAWABYAAAJLhI+pF+vW4HMR1InqxbJzBiLCeIxCaIkneQJk6rkl+2qlONzeNi+2YvKhEIOW4iczvJSoSDDIbCpbq2oGBXUtd59r7IPshsHdB70AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+airbrush-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAASC/AQCBPyChMwCBIQCBPz+/MzKzKyqrISChDQyNPwCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAR8EMhJKw3BahvEyNvWDV+ojQMBAhgmeukaFHSxTqh6FYZx3CyYbtf7XYRAFs8nQ56WxiBpyOEdjLkkrnA9IAKGqXbnTYAP1NDMe0Z8JYR4nPP1seEqTHpWZMupVHx2by03Q4JXbxuBfYoaaVZ3i4YKbo4WaQAKBCxjcEAGEQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+appearance-22:actions actions22 22:photo:22 22:R0lGODlhFwAWAIYAAPz+BAQCBBweHPTy7Ozq5ExKRPTu5NzStLy2lCQmJAQGBOTezNTKrLyylNTKpOzm3NzWvOzm1MTCpNzaxISuvBSGvLy+pKSehOTexISutKTa7IzS7GSarJTW9HTK7CyazBRypMzGpDw2LOTaxEyKpCSSxARGbERCROTizMS6nDx2jARajIR+bOzi1OTi1MzCnLy6lOSupNx6dGS2rJS6pMy+pOS2pNxGTKwaLDSmpHTOzES2tIyuhLSmjPyqrMw6RLSOhLzSrGyqbFSmXJSyhNTOtGTCvLzm5CyOjEQ+NPRqbOxOVKyKfMzizKzepFyuZJSqlBR6fCRmZJSKdDw6NLxqZLQiNIwyNLSejDSCRJzWnEyiVHySbBRiZDQyJMSijGS6ZHSCZJyafDRmPISKbJyifDw6LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAXABYAAAf/gACCg4SFhoYBAgGHjIQBAwQEBYwBlYiQAwYGi4UBBwcInIIJA6WRBAqdCwcMDA2pggEEDpUODwSiAAEQnwwHnI8RwBIGsLoLExQVFg4XiwEPD6IKGBjAExkaGxUcocfSgwHV1uITFR0eHyAhIroRERLAC/PVIxMkJSUgJvHH1RAKTixAgQzZhAkpVKwwwYKWrgnzFrRY4IIgBoMTRryQAGPjs4zzYsgYQdIgsgMzaNRw0CCBLgn2bNzAceMgSZITcujYwaNGj2sjcPjw8QNIECFDiEgoYuSIDiQOkoSTMAGHkiU4mAhp4uQJDyhRjOSQMiUXFQdVrOC4giWLFidbRri8QBKlyxQviIp8udKjRhYwYLKEedFAjJgvucI5cFBEgoMxkMm82PjFmCERix1wLCNmcg8viRGZ6aHZcQ8zoRtVWp16UCAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+attach-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBMTCxPz+/DQyNKSipAQCBISChFxaXDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARrEMgJgqA4zzus/gLhFd5HCcZAXqsphYPUdhcYFNRcZnvdtpnDqPTbUWgAJKBYwzBlw+bRo3xmkNWoBgm0OrVLn3GC9RgCk8DhUw7c0rHPr4CDu5SYQNyEt7uSY3p/UAKFhYKDSQOLiwgFdhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+back-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VCRGZAxCZGyavExmjHyatOTy9CxihISevPz+/KzO3BRylAw+XAQCBDRWbPz6/FzC3CSuzDyexJzO5Mzq9CxSdAQOFISmxNzu9HTS5BSmxAyexDSuzJTa7Mzu9Kzi7GS21CRmjAQOHHSWtLze7AyWvHzG3BRihAQKFCTO3BS+1AyixBSWvBSOtBSStAQWJBSixDzW5BTC3BSqzBS21CTC1ETW3AQSHEze7BRqlBRmjAQCDBR+pBRefBRSdCH5BAEAAAAALAAAAAAWABYAAAalQIBwSCwaj8ikMqBcMpvHgGAANQYIhWdVGDAcENQtIJBQLBgNx0MQaDuQXcghIplQDhBIxXKJYiAZGhscHR4VHyAhIiNWJBklGhIbJoQnFCcTKIxFKSgbKissJi0mJi4vLiYoMEcXKDEyMzQ1Nje2NisoOEg4KDU5K6g6OwwoKAN9SCOeMmgwz884PEq9PT4NYkPLP9jZQikN3d4AKVrjKePp3gZBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+blend-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQmJAQyNAQ6PARGRARSVARmZARubARuXARmTARiPAReLARaHARKBAROBAQCBERydESChESOjESanESmpESytES+vETKzETKtETCpES+lES2fESybESqXESiRAQ+PARiZARybASGhASWlASmpAS6tASynASqhASiZASaTASSNASKHAR+BARiBARydAR+fAS2tARKTDRaXARaXASOjASKdASCZAR+TAR2PARuJARqFAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa3QIBwSCwaj8ikcslcBp6CAaFQMBwOiIRiwWg4HA9hAAKJSCaUiuVywWQ0G07H4wkDxp8CKCQakUolJicoKSorLC12eHouL34lMIKEhoiKEFMgLn0kMIGDhSyVYhADjJuAkoWHiaMEMXuOnJ6Tq5alBpp+nSeflKx3l6a6s6CiwKWZm52pvpaue8rEzaPIubLMta2Mscu9ob8BMgIfBDPJNDQ1Njc4OTotDXYP8/T19vZN+fr7SXRBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+bookmark_add-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBCwqLCQiJCQmJMTGxAQCBLy+vLSytERGRFRWVKyurKyqrLS2tKSmpHR2dJSWlKSipISGhGxubIyOjGxqbIyKjFxaXGRmZHx+fPz+NGRiZPz+ZPz+HMTCBKSiHPz+jFxeXPz+XPz+tPz+zPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAamQIBwSCwaj4Gj0hgQLJ+AAaEAVQoI06pRYDhkoYgwIhEgKBTfZ2FhaBsYDS8VWnA8Go0FJIKeqyUTDw8EDHBpSwUUFQ4UFhcYDQYFfkoFFxEQDG8KEAUZlEeWGBIakw4FG1STiBoYBRwdBR4fHgUdHKBEBSCnIR8iIyIfIblFu6ceIyQjtcXGCbLKzAUKzrq+wMLEVa+xs7W31kOTk6nkWuOf6Ea5QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+bookmark-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBCQmJCwqLMTGxAQCBBwaHMTCxLSytERGRFRWVLy+vKyqrKSmpHR2dJSSlJyanISGhGxubIyOjKyurGxqbFxeXGRmZHx+fKSipLy6vGRiZLS2tFRSVHRydJSWlHx6fCH5BAEAAAAALAAAAAAWABYAAAWWICCOZGmewamaQrq+wUC8azHINGocOI38iIRAceDNaISFYklkGHOEhoNBfUAOhuOLEJE8HoPiRKFdESiQBqViuTDIUAsEcyAeGJmyiqC5RCwJGg0YcEh9D0V3Dxt6JwQVDRYVHBUdi40mjw0PTgwQHgeYJQQJfxUXFxAOoTkFpQ0fsRSimQkWEQ0VtI62HLt7vjl7JQYhACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+border_all-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI+hI+pyw0Bo5wR0TttUJDv0yWhRopfaYzguaKt6aasrGFYbVPxM/O7Snv9WEAfTIgMKpNGWU63emYc1GrVUAAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_bottom-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIyhI+pyw3xIpwyOgOv1dvl+2lhMzIlyZ1KQLUVm8Zch4ozbcq6l7L+D4QhgsTf7Xi0FwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_fall-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI/hI+pyw3xIpwypgBRdg/v9h2eyBnZCIKYxX2oEsJruVKjHS8vk3duKZnpHKjeRSTU0HYpTcxWgRqB1KrVYC8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+border_horizontal-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIyhI+pyw3xIpwyOgOv1dvl+2lhMzIlyZ1KwLbuyybw7KY216Einpv377FRhhUV78igFwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_inside-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI7hI+pyw3xIgxTRvcg1oku3njbBx4liV3dqYbsSsXyLBr0Pad1iCovsmOwgjbdz9TrGHWWSeWZikoXhgIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_left-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI6hI+pyw0Rnox0ygNXdG9z43Xal30gUiYhk5LoenJQRVtti5FwE+Kx4+O9RrIda6gwDmvMi+kJjTIMBQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+border_outline-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI8hI+pyw0Bo5ww0SttcKci/ymgMTZl+Yjbt3Jn26lautX0A+OizHJkjsrper7XbkZ0ATEYDZPii0qnU3sBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+border_remove-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIthI+pyw3xIpwyOgOv1dvl+2lhMzIlyZ1KQLUVm8Zch4ozbcq6F7s+fgsKb4YCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+border_right-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI7hI+pyw3xIpzyQRdVuIZj+3nHhogOiZng+I1qoqIdRVfbWy5y1u5M7MFphB1dsDULGXO15goJjUoRhgIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_top-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIyhI+pyw0Bo5ww0SvdCdrw7oGfNnZlczIpKorc+8RwZbZgXOc2uevOqpjJhrCb8QgwFAAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+border_up-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI/hI+pyw3xIpwyOgNRyPq+zTkcuIQKaV3T1pgHinmfm7AUedMa64Vw3bLJMr9TiZcSFUsnkw54q0Rl1KrVYSgAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+border_vertical-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI6hI+pyw3xIgxTRvcg1oku3njbBx4liV3dqYbsalFeJTp1iCovcjNsb9iZhMFcJwXUxTJLYuoJjR7sBQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+bottom-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VCRKZDRSbBxCXJTC1Mzi7Nzq9NTm9Bx2nAQCBNzu9JzG3Hy+1HzG3IzO5BRmjPz6/LTe7Dy61AyStCTC1FzC1AyGrETS3ETC1ETa5BRulAyuzBRylAw+XMTe7Gy+3CSqzAyexBTC3DR+nIS21KTW5Nzu/KzO3FzC3Pz+/ByixEze7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaXQIBwSCwaj8ikcnkMBAQDgjPAFAYKhsMBkVBUAYEFo+F4QLzVQEQyoVTOX/XBcsHA0+vMRbNBMwkRDhxuHX5GTlIeHh8gISIjFAEeiVRECiQlDAUmgxQjIhwiJHdFlycoKSIUFCEjGiGkRpcqCxYijxorsUezcxYsuoZJsxLAu0qXB7DCTJfHvArR0tPSSNTX1V/a20J2QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+brace-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBIQChAQCBBQSFCH5BAEAAAAALAAAAAAWABYAAAJRhI+pGbHYVHzQnUnrtXn7/gEYIJRHKRgYZraGuXLp28LcNL/Dqd4cYmJYRqegsKcY5DRIUhHYFDlQJGMuVn1ljdhqjhoiZrogKbMjFh/LHUMBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+brackets-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBIQChAQCBBQSFCH5BAEAAAAALAAAAAAWABYAAAJRhI+pyw0Bg3vxwImu0Zha2XkbaAjmYQrjh6qnCpwcB8evTGp1PKDrnzglZqTWDsg5DI5IUE1Yatpc0BrRFr2xfiljJlecXEPjDjG5iIRDCHsBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+centrejust-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIhhI+py+1vgpy0TogztlT7j3CiBJbZWJlqg4rry7jw/BoFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+charset-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIIAAPwCBAQCBAQGBFxaXAwKDBQWFAAAAAAAACH5BAEAAAAALAAAAAAWABYAAANLCLrc/jDKuQK1zmKo3/YVJSpBSZYmKaTkAAwYoQwFELjvpisyaTM7H6AH+3lQMZQwExrOOiBh7/cJGokaXHGpQVaUo7B4TC6bw4AEACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+colorize-22:actions actions22 22:photo:22 22:R0lGODlhFwAWAIYAAPz+BAQCBBweHPTy7Ozq5ExKRPTu5NzStLy2lCQmJAQGBOTezNTKrLyylNTKpOzm3NzWvOzm1MTCpNzaxISuvBSGvLy+pKSehOTexISutKTa7IzS7GSarJTW9HTK7CyazBRypMzGpDw2LOTaxEyKpCSSxARGbERCROTizMS6nDx2jARajIR+bOzi1OTi1MzCnLy6lOSupNx6dGS2rJS6pMy+pOS2pNxGTKwaLDSmpHTOzES2tIyuhLSmjPyqrMw6RLSOhLzSrGyqbFSmXJSyhNTOtGTCvLzm5CyOjEQ+NPRqbOxOVKyKfMzizKzepFyuZJSqlBR6fCRmZJSKdDw6NLxqZLQiNIwyNLSejDSCRJzWnEyiVHySbBRiZDQyJMSijGS6ZHSCZJyafDRmPISKbJyifDw6LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAXABYAAAf/gACCg4SFhoYBAgGHjIQBAwQEBYwBlYiQAwYGi4UBBwcInIIJA6WRBAqdCwcMDA2pggEEDpUODwSiAAEQnwwHnI8RwBIGsLoLExQVFg4XiwEPD6IKGBjAExkaGxUcocfSgwHV1uITFR0eHyAhIroRERLAC/PVIxMkJSUgJvHH1RAKTixAgQzZhAkpVKwwwYKWrgnzFrRY4IIgBoMTRryQAGPjs4zzYsgYQdIgsgMzaNRw0CCBLgn2bNzAceMgSZITcujYwaNGj2sjcPjw8QNIECFDiEgoYuSIDiQOkoSTMAGHkiU4mAhp4uQJDyhRjOSQMiUXFQdVrOC4giWLFidbRri8QBKlyxQviIp8udKjRhYwYLKEedFAjJgvucI5cFBEgoMxkMm82PjFmCERix1wLCNmcg8viRGZ6aHZcQ8zoRtVWp16UCAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+colorpicker-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBMT+xASaBASyBASCBARCBPz+/KyqrISChAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARZEMhJ6wzBahvEyNvWEcMXcgJBFuApjavRhlgaz6J9u5dQDAUZ73VA+FhDQOAQQCQEQt6ymcjgREznlZatJpXdLZYq1ky137M3qS5zwl8lOR5IIDBx5TpviAAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+configure-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBISChFxaXNze3NTS1Ly6vKSipNTO1Ly2vNza3Pz+/MzOzOTe5DQyNOzu7MTCxGRmZMTGxPTy9Ozm7Hx6fPTu9MzGzGxmbAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAW1ICCOZGmeaEoGbBsI6joMRGEcbQwESDIrtVtAF1gwDLNaAmfKiVgLBJKgwB1KxQZrBHU0FAXmavFoQLYiB6TxFXMj5AZBwnJI2I3wcNWALyYEcgoKXxRhOHs7XxEVCwsWFgoUDRYUFwwQB25ZCxiNjo6GkwUXN2NsCxEYqhUHoQ0MEglYRQQXErcHrI55FycuB2YSmoyOBTEtB2sXuhU6XAENC2a6z9AKCwq+1tAN3E2J3ySkIQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+connect_creating-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBPz+BMTCBISCBAQCBPz+/MTCxOTi5AQGBNze3Ly6vISChNza3FxaXKSipAAAACH5BAEAAAAALAAAAAAWABYAAAR4EMhJqwzY6omD+MNGdR8YilNZnug0qGzrqrL1lnV1fyJBVB6VQEMoGH4ADGwQkxQPBwMiKGA2J8VEAnq0tgiKg5aL/C7C2gTjKCM0zowDQ8tuNQznNL7cKzjOUQsNfER+gguIg19+Pm6ChBZFDmWNi5M5FIyYFHQRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+connect_established-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBKyirPz+/KymrOTi5KSipMzCzNza3OTe5Ozi7MzGzPTq9OTm5ISChMS+xFxaXNze3GReZIyCjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAWLICCOZGmeaBkAQpoGg7C6JizTQT7CxPwOwFWgYPChYIXkIHC4uQKGAiKRKCyNpxxUUVViVYNFLkqtLo+DAkMMLXQPXwAy2WCTF4544FGtKuwPDhB6DnxuUmyCcXIQhV1uYoMuEAcOBxEKCHg6TzGFCJUSizuejROKOAM9OY2SnUU7nD89NCcDsLUnIQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+connect_no-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBPz+BMTCBERCBAQCBPz+/MTCxOTi5Nze3OTm5Ly6vNza3ISChFxaXKSipAAAACH5BAEAAAAALAAAAAAWABYAAARiEMhJq7046827/+AVCKE0Dh9BAGdaGISAToFGFMcBU+11I4hDYseSZQiKwwKoI/QwBIYiuFDCZseGdIlYEjUNg1SpY6w2N4cUIW6cjwW1lsFwo+MqgtZuw0/ydw5vH34lBhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+contents2-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBDyGhCyCfFSWlESOjDyKjDSGhCx+fGSinGSenFyanEySjHSqpHSqrGympEySlBx2dISytHyyrCR6dKTGxHyurHSurHyytGSipCR6fARmZFSalEyWlBRubAxubBRydDyKhDSChLSytPz+/MzKzIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbFQIBwSCwaj8ikMhBQIpmCQdM5ZBIKhgNiugwkFAsCI7pNMhuOxkNBgBgEiAi3GkBLJpJHYgEpaClyREwVFhcSEhgOGQoMfgMaERtcARQBFRMYExZ6HB0FUYAekkIBHxqWFmlrC1haESAfG6MBGx+VFRgKYH0hInGRklO0ppYXCwwMWQiQHkwjgrWnFRdYZHIBJCTP0LaWGAcDW9jZ2nMAw9IWTOQkJSZMRsOV49nu8E+19PbmR7TY+1TovONH5V7Ag0QMBAEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+contents-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAAQCBAQ2NPwCBHSurIS2tBx2dBweHPz+/Ozm1GxiTGyqpPz6/Pz69GSqpOzaxPzy5HxuVLSmlOTazPz27PT29NzClPTexHxuXLSmjAxqbFSinPTy9KyehNy+lPTy5Pz29HxyXNzWxKSahOzexPzy7IR2ZOTWtESenPTy7KSWfIyCbKyijAQGBDyalPTu3KSSdDSOjJyOdCSGhPzu3OzizJSGdPTq1PTq3JySdMy6lAyKhOzWtOzi1OTOrJyKbMS2nJySfMS+rAwCBNzOrNTCpNzKpJSGZKyafLSifLyylIx+ZHx6ZDSChAQuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAAWABYAAAf/gAABAoSFhoeHAAMAiI2IAAQFjI6EAAaJkQeTjwAICYkKBQcLm5WdBwyfhgChB66bp64HCQC1lQ2irqQCAA4PowsLEBESE4wAuLIHFAAVFr+uDBcYxRm1GrmuGxwdFh4Mrh8gGCET1gDYyhsiFSMkDAsMDCUYJhvnJ9kHKCnODwwfPlBQsULCPRYAWogK9sHFiwoOPEyQh0JFPXO1YBSYwBEFghjdHkwQOYGgwQwIZRR44GHGDBogabhAsYEEihrUMAIoUMCEDRs3HODIYQHFA6MPcJA7KICFjgw7eIzo4cOfiwc/gKwIUm2SkKdDdlDt4AABDaU/iIRwwbTSUyJFOow4S3Hkx9oNDDZgXPU0h1wcSIgEGUw4ibVET5WoWMKksePHpdxmyKADAEIWly9HJtQkQJMmlAgZCAQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+contexthelp-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBAQChAAAACH5BAEAAAAALAAAAAAWABYAAAJQhI8Qy5F/ghBsLuOgpHHy+0hZ94HINiqWwoQrtjYpNqJ0A8Hcjbs73yPNZEHVDygTJohJWqiZe0JPM5ajtXxFMkXnklqNgsPiWzmHPatzhgIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+crop-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBMT+xASyBASCBASaBISChMTCxPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARUEMhJq704681r+EFHBcIwEKFImmfKkURhoh1cyO0rxEWZa7bezIUJ7gg04O62A22MyeeyF1XymrUSs5pZmbA61u+FLBOBhrThozq4D2cgYo6IawwRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+decrypted-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBGxqbFxaXExOTEQ+RAQCBPz+/PTy9Ozq7Nza3NTS1KSipFRSVOTi5Hx2fJSSlKyqrJyenJyWnDw6PMzKzKyurDQyNFxWXMTCxJyanHRuLHxuLGReJFxSLFROJFxWJExCHERCHBQODISChHxyLHRqNIRyNHRmLLSqbKyiZLy6fOTarPz67Pzy3OzitKymZFxSJJySTNTSnPTy3NzSpMTChLSydKyqbKSaXJySVIyGRGReLPz23NTOnMzCjHxuPLy2vKSmpOTe5LS2tLSutHxuNHRuPMS+xFxWLIR+RDw2HFRKJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SDAQIDBAUChY2EAQYHCAkKCwyOjZANDgIEAQoPjJiDAg2iggQQp5gMBwmrDBESl6MTFKuoFQSjABYRF40CGAW8BRm7hQwNxBobHB0eHx4gISIjBdiEAhYFJBslHOHSHh4hBSHlxIUmJygpKissBiwtLi8pGjDqhBoxMjMuaNSwcSMFjhw6dnjYRyrGCh4ueviw4Q5HDB0/PjAUJCBCAwMIGiiggAEIBFk/FgYLIgRkggQkhxAJkqGExkYMFnxsIGRkSQgLHhRRWUjAggQgG8AsSWRBBiP6VrYMOfKIyaBDNwLo+HHSUplOSyDRqiEHjRkretRQkcLgxayNF0wksQGQxsSKMTIq0QpgCba/gAE7whEIACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+down-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VCRKZDRSbBxCXJTC1Mzi7Nzq9NTm9Bx2nAQCBNzu9JzG3Hy+1HzG3IzO5BRmjPz6/LTe7Dy61AyStCTC1FzC1AyGrETS3ETC1ETa5BRulAyuzBRylAw+XMTe7Gy+3CSqzAyexBTC3DR+nIS21KTW5Nzu/KzO3FzC3Pz+/ByixEze7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaRQIBwSCwaj8ikcnkMBAQDgjPAFAYKhsMBkVBUAYEFo+F4QLzVQEQyoVTOX/XBcsHA0+vMRbNBMwkRDhxuHX5GTlIeHh8gISIjFAEeiVRECiQlDAUmgxQjIhwiJHdFlycoKSIUFCEjGiGkRpcqCxYijxorsUezcxYsuoZJsxLAu0qXB7DCTJfHVQrMX9PU1Uh0QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editclear-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBPz+/ISChCH5BAEAAAAALAAAAAAWABYAAAJBhI+py+0PYZi0WnqC2Lx7HhjaR3YhMArBUHpnuramCLLy9tY3TuP2nfPtVD3VTxY0DpNDHqo5E12mlYj1is1e7QUAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editcopy-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFPz+/DQyNISChDw6PMzKzMTGxERGRIyKjFxaXMTCvKSmpHR2dPz6/Pz29PTq3MS2rPz69MTCxFxWVHx6dJyWjNzSzPz27Pzy7Pzu5PTm3NTKvIR+fJyGfHxuZHxqXNTCtPTq5PTi1PTezNS+rExOTFRORMyylPTaxOzWxOzSvNze3NTOxMy2nMyulMyqjAQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbYQIBwSCwahYGkUnk0BgTQ6IAQaBKfUWhBYKhaAU+CgXAQIAyChLeJzSIQhcH6GFaM0QtGY5kstqEODw8QEQELAhJTc08KBBMEFBUWDRcBE1pca20SGBkaEBscAY5maFRIAgoLHRQRHh8gIQFlZnByqA8ZGSIQIyQjJQEmYgJ5p2ACrK4gJx4gKIZZAgdeAQ4ZI9kjKSor0AwEjeAs1S0cHAslLi4vMDDRWeRIfEsxMeET4ATyVoYLC5fizXEiAR84BeMG+pEm8EsAFhAjSlR4hR6fLxiF0AkCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+editcut-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBAwCBPz+/OTi5JyanOzq7DQyNGxqbAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARbEMhJq704gxBE0Bf3cZo4kRJqBQNRfBucyudgvJS6VaxLzyMa6/bLiWA9HOg4VIIkL5vzuRkcpkvRIIAorphJLzBW84WEuRZWp6uaT7J2Sh1Hit3OY/ZO7WvsEQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editdelete-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAASC/FRSVExKTERCRDw6PDQyNCwuLBweHBwaHAwODAwKDAQCBExOTNze3NTW1MTGxLS2tJyanPz+/Ozu7BQSFCwqLDw+POTi5PTu7MzKxIR+fCQmJPz6/Oze1NTGvPz69Pzy7Pz29LyyrPy+vPyupPTm1BQWFIQCBPwCBMS6rPzSzNTOxPTi1NS+rPTezNzOxPTizOzWxMy2pOzaxMy2nPTaxOzOtMyynOzSvMyqjPx+fOzGpMSihPTq3OzKrOTCpNzKxNTCtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf8gACCAQIDBAUGBwgJCgsLgpCRAAwNlZYODxALEY+SkAMNEqKjEw0UD5yegqCjrRMVEqidkgWhraMWF7GptLa3EgEWFRSOnhW+vxgZEBqzkBvItxwdHryRCNGjHyAhHSLOgtgSI60c2yQjJd+eJqEnKK0hJCgnJSngAO0SF+8qEvL0VrBogW+BLX4oVKgIyMIFQU8KfDV4R+8FDBcxZBREthAFiRIsOsygsVEUh4Un3pGoUcPGjZInK65QicPlxg8oX5RwqNJGjo0hdJwQ6EIkjRM6dvDYCKIHSBc1Ztjw4eOH0oIrsgIJEqSFDBo0cuTgsdSTo7No0xYTZCcQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+edit-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBISGhISChHx+fHx6fHR2dGxqbGxubGRmZGRiZFxeXFxaXFRSVIxSLPyuXMzKzMzKxMTCtExOTPzqrPz+/NTS1MS+tOSaVPyWNPz6/IxeNPzavPyKBNTW1PyCBPyGBJxmNPzOpLx6PNRqBMSCRNySTPyCDPSGBMxiBKROBHRydPSylOyydMxmBJxKBAwODPS2lPTq3OyabJxGBPTy5PTGrOyOXPR+DPz69PzmzPzevNxuPORqLMReFPzy7MyCXKxiNIRKHBQWFNTOxPzixJRaPFxONHRqVPz27PTy7PzStCwqJDQyLJSGdIx6ZPz29PTu5HRmTLSKbMSGZHROPFxKPJSKfJyShKyehMyuhDQmHEQuJJyOfLSijMSynMS6pLSefDQyNHx2bKSahLyqhLymhOzi1FRGNIR+bNzKtOTOtOTKrOTKpLyedAQCBFRWVPTq5NzOvLyunLSmlNTCrOTOrNzGrLyidMS+rLyynKyijLymjLyqjAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gAAAAQECAwQFBQYHBggJCgsLDAwADQ6CAQ8QD5ydEJ+gERKWE4ICDxSpqhWqqhYNFxMYphCtqaytGRoXGxgcggSoth25u70eH8APFR0VzMzNziAXIRjIvwAFwq3EqSLUGB/iI4LathS4JCXVJh8nKCmCKrXDFCss1eIfLS4v8ssdmgWsAGNDDBnt3s3wJ+jAtlUhaNSwccNEi4WCBBl4SAHHihw6ZOzg0QNjRgAG6KXK4CNEjBU/gDQI8kLISQAIADobAoMIzCINjLw4YvNkAno4kCRRUuNHESNLmDRxUjSjAlRPfECJImUKlSpMrFzBIqWqoKtJaWSJomULAy5XXrp4+QKGYcYFoCBEWRImi5gmY7CQyVLGriAGD2jEMHMmCxc0Xb6kUbOGTRs3N988gLM4jpw5Y+iwqcOGjZ07mE8yiGABz5c8c/Ts4cOnDJkybS7fdMO7t+/fvDMaCAQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editpaste-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQWFDw6FHRuFGRaBFxSBAQCBAQKBCQiBIx6HPz6/NTOfKyiXDQuFOTm5Pz+/Ozu7PTq5Pz63PTyxNTOjKSeRExGLMTGxMzKzNTS1NTW1Dw2NKSmpKyqrKSipJyanNzWlLy6ZLSuVIx6FISChIyKhJSSlCQiJLS2tDw6NDQyNCQiFCQmHBQSDGRiZHRydGxubHx6dGxqbFxeXGRmZFxaXCwuLOzq7KyurHx+fDwmFEQuFCweFCQWDBQODBwaHBweHKSinJSWlOTi5JyepHR2dDw6PBQSFNze3ERGRIyKjIyOjISGhPz29Pzy7MS2rMzOzFRWVHx2dHxybDQiFPz27Pzu5PTq3PTm1NTCtJyGdHxuZHxqXPzq3PTaxNS6pFxWVFRKRNS2nPTi1PTStNSulNzOxNSynMymhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCgwABAgMEBYSLggaOjgcICQoLDA2Pj4MGDg8QEZ4FDxITFBUWFxcYGRobjQ8cHR4fCQ8gCyEiFSMWJCUkJieNEB4dKB4pKissK8wrLS4vMDHBAAYQHx8dFx0fJDIzNDU0M+IyHzaNNyg43Ng5Ojs7Ojw9Pj9AMkCNDiZB/h9CSOx4QLCgihItqBkYgqIDESElitAYWJCgkQcXjjRCgi1Ihw4BB5LAQOLCgyQYHihpUU3DBw5ElpAgAYNixSRJjKjQaECDCRPZPDB5IbIGSQwKLnh4wbInLA4kmJB4oaPiAwVNnER40hRK1BIAaVatUZJEFCkmpmjgCeWDCalFe4q4oFKwSRUrEa5gycLzwq8lUnPQ4PEgSpYcUZ5o2cIlS1O/JHLEDdfjQZMIVrpgweLFy5e+M6WSmBGlxYMYYBRzCaOFi5imHWBIfOEiShLTVjaP6eyFTBmN1TA5OvLDjJksWb58OVMGDRqWjAYdmU79SIvpjqJr104nEAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editshred-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBFRSVExKTERCRDw6PDQyNCwuLBweHBwaHAwODAwKDAQCBExOTNze3NTW1MTGxLS2tJyanOze1Pz+/Ozu7BQSFCwqLDw+POTi5MzKxPTu7LyyrIR+fCQmJPz6/Pz69Pzy7Pz29OzaxPTu5PTq3PTm3My6pPzu5PTq5NS+rPTm1PTi1PTezOzWxPz27MyynOzSvMyulOzOtOzKrMymhOzGpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbpQIAwIBgMCAXDAZFQLBbCqJTRqFobjgdkEYFKowPJZEyeUBqVR/crHDTKZYplovZKCW84+YKZZNZSBXl6EwEEBhVPXxZihGMaGRscdkIdg4QeEnVfCH2OHyAhIhuUAAiXZSEhIyQlJqWnjiEnKCWupRWoYyEgJK0SKaUKjam0JCorLMFfC6iqx8giLa/MGAsT1wsuCyULKwssC9RSzdkfCyALKuALLQsvpeXYIQso3gsiCzALMfENC+dGcMNHUAY/f+jq3ctncMYCGggFrsvHcEGNh/EyPFmg8cmrJxAVkVO0EUDJklHoBAEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+edittrash-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBERGRExOTDQyNISChBQSFCQiJCwuLPT29Nze3GxqbDw6PGxubHR2dJyanLSytJSWlJSSlOzq7Pz6/Nza3Ly6vFRWVBQWFIyKjMTCxHx6fIyOjLS2tOTi5PTy9OTm5Hx+fNTW1KyurKSmpJyenExKTMzKzKSipFxeXCwqLMzOzKyqrMTGxLy+vHRydBwaHNTS1DQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAb8QIBwSCwaj8KAMoA8LgUDQsFwQByay4RiwWg4GA9IRGk0SCYJSsUCsVwwGQ1EsmESD5xOp+L5gDwhBRIZDhcDdkMGDgEiIxAkJQ8Ok5MmAohDAQ1xJxUlKCUlEg0pKpiZJRoLCxmtCw1eURhOcR4rbQ8cGRwLAwgGtBYTDywtGRKjvQTARgEZLhMcKC0OrQMvAirMRc7CHCTU1g2+20TO0NIn1RwDCya/wdHT1Rnt5LToKOq79trx0tR02YPX7Jm8fRxMOIhSLhOJE/LCJSTlr5kFEBQsWDiR4UGGBgsuHDg1BEYAfTE6oEBR4AIBAiS5yWBAAAGBAyaPGAgCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+encrypted-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBHRudFxaXExGTERCRAwGDGxubPz+/Pz2/Ozm7Nza3NTS1KympFRSVHR2dNTO1JSSlKyqrKSipDQyNMTGxDw+PLSutKymrMTCxAQCBHRqLBQODJyanDQuFFxSJFRSJFRGJERCHExCHISChHxyLEQ6HGRaJExKHLSmbLy2fOzitPz23KSiZHxuNHxyNJSOTNTOnMTCjLSudKSaXJSKRJyOTOTetNzWpHxuPOTi5MzKzLS2tFxWXOzq7Ly6vOTe5Ix+RLSqdNzSpLyydKyqbKyiZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4IBAgMEBQKEjI0GBwgJCgsMDY2XjwkOAgQBDxCLl4QNCaGCBBGWooINCAqqrBKgqwATFKaDFRYVtBMXsIMNGBm0GRADjQIJxKIaGxwdHh8gISIhGyMZzIwkGholJiYfJiAfJyEZISDbg90oKCkqKwcHKyooLC0f7IIuLzD2YMSQgW8GDRri+AFoUMOGvRsxUhSsQQPHvmQSchyQtEAHhh0WJHDQcJERjwsKDvRI0BGDjwgicXhQyCOjSgUKPO6AObIkIQESfmxk6REDT4s0bfaYpDNkT4VAha5s+TLmzEYtatwIOHAiDZIKNQAJYk9IjCFEisyoocFEB4UACtBpm0t3LiEsgQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+eraser-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBMTC/AQChAQCBISC/PzCxPz+/MQCBIQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARfEMhJKwhi2F0DIRnHeR+oiRRZmqikrmD7wgI6r+EI4+d2l7lNwWDYsTiFw4FI61mSymXxE3xGo8xqBXpVGrQUbveAcG7H0bKowEar12wx2SyMp+lI+7s1ie/5fX8tBhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+exec-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBAwKDAwKBCQiHNze3AQCBBwWFDw6NPTy9PTy/Dw2NKyytOTi3LS2tMTKzMzOxLy+tLy+vBQODNze5NTS1JyalIyCbIx6VIRyVISGfJyelOTq7EQ+NMTGxKyurGxeRLyKPOSmROSuVOy2XOSiTLzCzNTOzDw+NCwqLHxuVOy6bPzGfOSuXNTW1LSyrMSWRNymTOSmTKSCTPTGjPzSnPzWnMyaVBQSDMTCxPz+/KyahNSeRHxeLJRyTPzmtPzarOy6fJyajNza1Ly6vLyulFRCJPzirPTOlMS2pNTSzMTCvJyenBQWFNzKtPz6vPzyvPzqtOzGlOTe1AwGBFxWTLy6tPTm1PzSpPzutPz2xPTSnOTSxOy2dPzapPzerOzm5IR+dPzu5Pzu1PzqxPzy5Pz+9GRiXGxuZKympHR2bOTm5Pz6/MzSzBwaFJSSjCQmHPz2/AwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeEAQKIjIIDBAQDjYMFBoMHCAkKgwYFhwULDAUKCg0ODxCkBQgRnoUSExMUDxUWFxgZGpAbFIuGHB0eHyAhIiMkIB8lJieIKCUpJCTGIyorLCktKIUDpC4YLzAxIjIyMzQ1NhgdpJI3ODktJTowOyM8Ejc9Pj9AQUIEclAocCMIBQhDiOwgoaKIoCI+jBxBkkSJkCWemIyq0GSHCBVHihRx8gRKFCmpKhGaQqWKFYZXsGR5kkXLFgRUXBUqkCGCFS5AjnTx0sXKlyA6CRVgAAHMAilhxIwhU6ZFkBY5kgKYUoXBAzMKzixZ4AJNGgVm1KxhM0WpmQpUMtooaOPGxAM3Nw60oYLGjNYCbzYJOgAnRzNBJ95oPYQCgpJtkwzFoULlRuRPiy9fNhAIACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+exit-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBHR2dDQyNCH5BAEAAAAALAAAAAAWABYAAAJOhI+py90RnIMyRUOxhDfzJkACdoXBuEDDkQFDi5go0MrKx16kns80b7qdELCgBYaEGWwL5nG1ePFiKp9A6kuYRNuho8vxVrrZivmMRtMLACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+fileclose-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBERGRERCRDw6PCwqLExOTFRWVHRydGxqbGRiZCQiJISChIyKjHx6fDQyNBwaHJSWlKSipBQWFJyanPz+/JSSlCQmJAwKDCwuLBweHBQSFGxubExKTISGhDQ2NFxeXFRSVDw+PAwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbZQIBwSCwaj8jkMSAYDAgEJbFgOBwQCUOAoJAaFgvGonHIBhyP5BcSgUAYDWxggD4WFmx3e3HQngkSRgYMEBMUFG4MCId0BGlEAQeEhocVDYcUdBYKF0QCB3gRlJgUAQEYBBkaRAMbDZMMpAYcT46rQwMJrgsdC6QcfwoPnUMOBgkIV6SHHg6bw0QEAQYfBpggBZjPGsRD0gEchxwCIR6HChnQRQ8DIU4DTR4Em+ncRw8O+fmoXPXdRg+gQLFgIYM/KRIkoDP4QMKFf0o0aBAh4qGUixgzCrETBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+filefind-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQSFJyanLS6vLzCxISChNTe3OTu9Oz6/Nzy9Nzy/NTy/OT2/Nzi5Mzu9Lzq9KTe7LTq9PT+/Pz+/Nz2/Mzu/Kzm9Jza5HzK1LTi9PTu9IzW5ITO3FxaXNT2/KTi7Iza7GzC1LzW3FRSVMzO1MTq7HTS3Fy6zFS2vKzm7Lze5MTGzHzS5FTG1Ey2xEyyvJze7JzW3ITa5FTK3EymrGS+zFxWXKymrMzi7ESirEyqvLSyrKze7MzOzMTCxKSepAz+/NzW3MzKzBwWHLzS3ERCRAzi3KyurNze3MzGzLy2vLSutCQiJAyytHRydOTe5MTGxLy6tLyqpKyelJSCdOze3NS+tLyupLSmnKSOhCwuLPzy9Pzu7Oze1OzazOTOvMyihOTi5PTm3Pzi1PTazPTWxOzOtNSunDQyNPzy7Pzu5OzKrNzSzNzGvNS6rMyynMymjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCgwGFhYOIiYQBAgMEAwKHiokBBQYHCAkKCwwFAZOEBQ0IDAsODxARCZ6gAAEGEhMSFBUWFxgZCJ+TjBoMEpkRERscGBGRih0BBAgeFBQOER8gISEfIruIIwEkCCUVwhcgJicoKSrZg9srCRkRGdMsLS4vMNiK2wIKMRsbMiwzXtCocSydIBs3AuCIwIFDiBMucugAoWvSiB2VNPDg0ELHwA0MkCXr4aNSggg8NoDIQOFHgBtAkgURMiDAEAFEVBCJFKCIkSMGOyDRkETJEkOFmABoUsRJQkQdnkzQACWKlBtTplBR6qopxkFRJ0ytYuWKFCxZtBBq+hRA2AlbRrh08fLlCxi1a51g+dQhDFwuYsaQKWPmDBpKXgNETaNGjJgyhNfcVdTTiWI2XpK0cePmzRk4YA5T5otGixY0qFOXbgXAQCAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filenew-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBExOTERCRDw6PCwuLBwaHAwODAQCBOze1NTW1OTi5Nze3MTGxLS2tJyanPz+/Ozu7OTi3BQSFCwqLDw+PDQyNFRSVPTu7MzKxLyyrIR+fCQmJPz6/NTOxPz69Pzy7PTu5Pz29Pzu5PTq5PTm1My6pBQWFPTq3PTm3NS+rAwKDPTi1PTezOzWxMy2pPz27PTazOzSvMyynOzaxOzOtPTaxOzKrMyqjOzGpMymhPTizOTCpNzSzNTGvMymjMSihCH5BAEAAAAALAAAAAAWABYAAAboQIBwSCwaiYGAYEAgFAqGg/Q4DCASCsTiymgcHAcqQLB4mM+QiIQBppLPcMjkwQ4bB2X4maKgt4sVCHpnFhQTElNFE3mDDxcYGRp2RBuMgxwIHX9EBZZwHh8gCBmTQ52NISEiIyQlpUImng8hHyInKAgprwAqgnC0IKwrLLpGB4wctLYkwy0uuwd9Z8AnJywsLcVFx2YcL7UnJCwwLTEy0GXJoSgrCCwzNDTnxgjeH9UrKzXwNDY36LRGhEOwLx4NHDmgJbh3QoeOgv127EhojEeHDj16pEhRQoZHHzl+QJNCsqTJSXaCAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fileopen-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBAQCBCQWDCwaDDwmFPSubPzGhPzCfPy2dOSmZPzKlPzSnPzOlPzKjBQODPzChPzWnPy2bPSmXPyuZOyeXIRSLEQuFEwyHEQqFDQiFCweDKRuPFRSTPT29PTy9Ozq7OTi3Nze3NTW1MzOzMTGxMTCxLy6tLSytKyurDQyNMzKxOTm5OTi5Nza1NTS1MTCvLS2tLSyrKSmpJyenJSWlIyKjHx+fFxeXBwaHKxuPMzKzLy6vIyOjHx6fDw6NPy6dGxubLy+vISChCQmJNza3KyqrBQSFLR2RKSinJyanGxqZAwGBJSSlCwqLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeDAYqKiIeLj4wBjQCMhY+NkoiLk5qbhQIDoJyGBAUGBwgEo4MECQoLDA2pDrS1tKQPEAwHERITE77AvxKqhAQNDA8UFRYXFs8YBAQZGqGPxw0RGxwdHR4eHyAhIiMkJSYnKCgpBAYPEhcqHyssLS4kLzAxMjM0NTY3cBA4UCAHBw8gVnhgEcKFjhc7UPDj0cMHAAI/KFgY4YLFio/jRpTYsW8GDyCSCEQw2DChOHIqgsCQSEPIEEEEJFhAoUNECCJEyOk4d6KIyRtGcB7hIJKjixEjHu4oimSGEIs4d8IIUoKECnNB0ElMwkNJJgBLlJBAcQKGiR07KGAURVGViY0mhIwwSTKjr99+THjUoIg0r48hTRIrRtxkiOMhDgrZCQQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+fileprint-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBFxaXDQyNFxSTPTizOzi1FxORDw2NExKLPTi1Pzy9Pz6/FRWVPz29Pz2/PTy7PTu9OzezPzu5OzavAQCBPzy7PTm3OzazOzKrPTu5FxSRERCRGReXPTq5Pzu7ExGTMS+xKSmpOTKpPTq3JSCDNzSfHRydLyadOzCjOzOtOzSvLyyTMTCxKSipGRiZFROLPz+/KyurJyenJyWnGxmbLSabOzClOzm7LSutJSWlJSSlJyanGxqbNze3OTm5IyGjNTO1Nza3NzW3OTe5IyKjHx6fMzGzMTGxMzOzNTW1IR+hISGhKymrLy6vLSytERGRGxubKyqrLy2vLS2tDQ2NEQ+RASKBAT+BFxeXHRudAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4QBAgOEiYqEAgQFBgcGi5MICQoLmAQDh5OEDA2YCw4ODxARApKUCaGYEAsSCRMUnQysCwoVEhYXGLOLCBCgDqK5GQUXGooCAhscBB0euBUZEAUJvQgIgx8gIR8iCSPiHuIFEREDJCXaANwhJhsnKCnWERcRKiopFCvsBywhQrRwQWGAPAz5EhpQ9wIABRgKYsiYMTEEDQocatiwkUIEP18fbkCAAcMBjhwzdOyQwYNCgBMfKJSgMItBjxs+btwgCSGGjhw/ZoRgQKGZCRMUPgABEgSIkCE3SZok8qNqkR85NtDUEcPIkaVAkCR5SrJBDCVKlmzQ6pCCiRlMTJo4YUH3K5AeMBYYWctW0BOaUH60cBJFypQmII6wyEpFQBVFMSm4UAI3hJUrOGh8oOJrklYKWIromJGDR99Ogz5j4ZGlM+pEnwmBCwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filesave-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBGxqbAQCBLy+vERCRExKTHRydIyKjMTCxFxaXGRiZFRSVFRWVPz6/Nze3Nzm5Pz+/JyanDw+PExOTHR2dMTGxBQWFLSytHx+fISChOzy9Ly6vAQGBJSWlMzKzAwODJSSlHx6fIyOjOTi5DQ2NISGhGxubCwuLOzq7ERGRFxeXNTW1CwqLPT29Dw6PGRmZKSmpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAb/QIBQGBAMj8ikUDAgFAzKKCBwQCQUCcICKh0SEAhGw5EIZAmBrgCxeDQgcDJWyz0GIggJfL+XGwQJRxNgC3yGDwwUFUZDFhdthnwMGAZNQwEZFwQakXANBBQbHIIdERIBnRAOiR4ERx8gsSEMBBmGCyEGG3YGBwcgIr8UCwQHECOgG4xCtRkEJAvBJRklJgkSFBQeJ68hJiEoESkFKiEZIbkGARsLlwEGExENGhorGSkpFAYm66NDLAECpGiBYsUIFA8wLHBBQMWLVkdUCFCwaYVFBOymkVCgYEMgOykEpICBccMBAhhELFigTEqAAgIIwCiQ4eRKDyS6EAlJIAI0EpaudF4iIKDAAn9CkRT5eMROEAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fill-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAASC/AQCBMT+xASCBMQCBASaBPyChASyBATCBPwCBARmBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAASCEMhJq704axB2DkLnVeAwiCNHDMWZcsbaul5ZyCaKBcZwFDcgDRNbHX7AmW4SMx2MSOFQQlitEAhosrVcDQQE7NMXzVGqA6xAgCUckabQpJoIYBFsxBspUKBiHQEHaoNvBQJTgBIBdnh5B4hLihONeJBTc0uMaphMS4uRGQYfny9EEQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+filter-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBAwKDMzKzMTGxNTS1MzOzAQGBLS2tLy+vKyqrLSytLy6vMTCxBQWFKyurCQmJBweHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAV7ICCOZGmeaHoGbKuOAjsQhVG764EgyT7YhaCBVQogFMhFImEABoUBknFxRDAazac2Kg00djystkA0sQ4BgzgYK6+Ch/bBseOmAmMD4gF5ifBCDwoRfiOABgyEhYYFCA6LUo19kH+Nj5QAaQh2kHibmJkFBJydpKCnfnYhACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+find-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQSFJSWlFxaXJyanKy2tLzCxDw+PHyChNTa3Nzq7Nz29NTy9Mzu9OT29Nzi5Oz6/Mzy9Kzi7Jze5Lze5Nzy9JyenIyKjHR2dMTu9Kzm7JzW3ITW3ISChGxubERGROz+/Lzq9IzW5HzK1LTm7FRSVHTS3GS+zLTS1DQ2NMzOzMTq7Lzq7ITW5FS2vMTi5ExOTKTm7EzCzEy2vEyutJTa5FTK1ESirGy+zMzi5ESerESmtITa5OTy9KTe5KyqrAz+/Azi3ASutERCRExKTFRWVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCggGFhYOIAAIDiYUEBQYFAoeJAweKhAgJCgsLDA0OCAGJg4wBCA8QDhENEhMUFaKDFhcYgwEJCxAQDBkaGxwSFaMAFh0eAx8AAQIKECAODCEaIiMjJJMAtQMlygEGEBkVva4mJycTKKMYJd0pyyoOKyssGhMtIycuGi/EMB/vlhmoQEFDjHsmZMygUUMdqWUCGgCbYMKEjRk3cEjI9jBADg3Wzs3QsYOHA2IdO1SQkI/GjRMtFhBA2RFBDwk+OASrMPMHkIe3AhBA8QLFzAAHgvyg2dEQMSEHPCwltQgooSFSmVpSxKjjh6wPtwINgHVqsVpWESEFeywZ17RkED2s40YEgFirlIq4SwvUQCAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+finish-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VAQCBBxCXDR+nIS21Aw+XJTC1Nzu/KzO3Pz+/Nzq9Pz6/MTe7KTW5FzC1Nzu9CRKZMzi7IzK3Lzi7LTe7HzG3Gy+3AyuzAyexFzC3DRSbHy+1Dy61CSqzAySvAyStLze7IzO5AyGrEze7BRmjCTC1ETS3ETa5BTC3Bx2nAyWvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAakQIBwSCwaj8hkMqBsBgTN5IAAJQqqykCBasUmDQcEV3gtBs7oATihGJeJgcOCQWc0HA8Ig/seRiQTFAsVFhcYGRp6VH1CGwscHQ8dGB4fIBkPIWKMAAMLIiAjIJcgH5gkGSWcARIiJicoJikpHikoHqqrKiW8JSogKymoqgCrV8cCARgkuFWcRwYeqVjPRgEExEPVRQbZ2l5IBuBRQ0zk5+hRBkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder_new-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBNzaTPT2FISCBCQaDPz+BExKBDwmFPSubPzChPzCfPy2dPz6BMzOTAQCBOSmZPzKlPzSnPzOlPzKjBQODPz+rPz+3PzWnPyuZPSmXNyaXPTyhISCLIRSLEQuFEwyHPy2bKRuPFRSTPT29PTy9Ozq7Pz+xJyanDQyNPzGhMzKzOTi3Nza3OTiVBQWFDwqFKxuPOTi5JSSjISChHR2dGRmZFxeXPS2dNTSzNTS1OTm5KSipLS2tLSytKyqpIyKhGRiZNze3NTW1MTGxMTCvLy6tIyKjCQmJMTCxMzOzMzKxJyenHx6fLR2RLy6vJSSlHx+fDw6NLy+vIyOjAwGBGxqZKyurCwuLBQSFJSWlCwqLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeIiYqLjI2MAY6HAgOHBJYEhJCDBQaDmgcICQoLB4MGDA0OAQUBDg2cAAcPEBESE6QUuQasFRYVq5SxCRcSCggYGRjIGgYbFs8bHIMHExIJGR0eHx7cB83PFhsDDuTUEyAhIiMjJCQluwEmvsAnKAcp1x4qKyUrLLupWrByxcnFiwQIYIggEaNEiRgBZMyYQaNADRs2REA6cCODBxw5+OnQgWMHjx4+BND4MQOIg1gI0gUREkTHiplDhhApEoCGkRlHBL3I8MEHEhz+WAhJogTJySVMfthwIehAExE5jubAkYQpESc8fOx4AiXKNA8+ekhBgqSpzh5hPHcsmVLjpSAqVZBY6VGkiJMiPQKLnTvjCiEsWU4o3nGC8YksMmT8YCmC6iAXKLRc2cz5yGYtR0JjKWQgEAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+forward-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VAQCBBxCXDR+nIS21Aw+XJTC1Nzu/KzO3Pz+/Nzq9Pz6/MTe7KTW5FzC1Nzu9CRKZMzi7IzK3Lzi7LTe7HzG3Gy+3AyuzAyexFzC3DRSbHy+1Dy61CSqzAySvAyStLze7IzO5AyGrETa5ByixBRmjCTC1ETS3BTC3Bx2nAyWvEze7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaYQIBwSCwaj8hkMqBsBgTN5IAAjRoDBaq1aDggtMuAWDzoJhTgY+CwYLgZDccDwkgXI5IJZVGxXDAZGnR2QxsLHB0PHRgeHyAZDyFfVUQDCyIgIyCPIB+QJCUmlEMBEiInKCQnKSkeKSQeomoqJrUmKiArKSwZsmoCwMEBGCyxo1EGHr3HUQEEvltCBtDRAAbMW0zV29xDBkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+frac-22:actions actions22 22:photo:22 22:R0lGODlhFwAWAIIAAPwCBAQCBAwODAwKDAQGBIQChAAAAAAAACH5BAEAAAAALAAAAAAXABYAAANICLrc/iwEJSEUQA45LcOKMHWeU5XWiUYZsZClOIjj+naqrS9F7/9A326YCYBypREOpMPBVifjkBRw7SpIG+eJIg2IWC5UikoAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+frameprint-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBFxaXDQyNFxSTPTizOzi1FxORDw2NExKLPTi1Pzy9Pz6/FRWVPz29Pz2/PTu9PTu5OzezPzu5OzavAQCBPzy7PTm3OzazOzOtPTu7ERCRGReXPzu7PTq5OzKrExGTMS+xKSmpOTKpPTq3JSCDNzSfHRydLyadOzCjOzSvLyyTMTCxKSipGxmbOzClFROLPz+/LSutJSWlJyWnOzm7JSSlJyenOTe5OTi5MzKzASKBAT+BNzW3OTm5KyurMzGzMTGxMzOzNTW1KyqrLy2vERGRGxubIyGjLSytGRiZISChAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4QBAgOEiYqEAgQFBgcGi5MICQoLmAQDh5OEDA2YCw4LDxARApKUCaGYDwsSCRMUnQysCxUKEhYXGLOLCBCgow4VEhkFF6mMAhobBRAcChUVGR0FCR4UCAiDHyAhHyIJCRAjHOUJEREDJCXcAN4hJhonKBjXESn5Kdkq7wcrQoRg0YLCgBMuRFxIwTCFgXYvAFCA0SCGjBkYQxQMUE8EBhEUVPj6QOMBDBgLLM6oYYMFhYkvYcSkwOAGDho3TyqIUaPGyZ9AKXzIoWMHDx44bvQ4+WAi0KA1fPwAEiTIjyBCkDp9KlMiBRMzhhAhsqLsD64/fQEo8tLIERZIH8Ru5arow8skSmTMDdpJQ0y0XTsJ2gtU8GCZMBMbCAQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+funct-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI+hI+py+0PIwhUohpMXfl6103h1nTUNproEU6am62v1pLsPX/siO9Jiou9TD2XyHfMGUs65aVmiUqn1CrCUAAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+gear-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFCQiJERGRBwaHFxeXHx+fDw+PGRmZExOTGxubKSipDQyNHx6fIyKjJSSlJyanISGhISChLS2tIyOjHR2dAwKDAQGBJyenAQCBCwqLLy+vKyqrAwODMTGxKyurFRWVLSytLy6vMTCxMzOzGRiZNTW1CwuLMzKzFxaXJSWlOTm5Nze3Ozu7OTi5Ozq7GxqbDw6PHRydAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAb/QIBwSBwGBMVkMjAgFAwHBFJpPB4SiQJCsWAQqEJB4prdNhQNx7QYIFwLD0ikQZdMHgelOPGYULQVDg4QEAVfRAEBBwUTEE0WFwcYhAuNF0QDBQULDwwZGUIaEAuVGxgBRAIFEhwHHUQMCxwTHAVrAAwFFRwKFkQZsxseDqBDGXMSHwfFQiAhIiMeJApEBwcOcahDJcLSJCYcGkQKcRAnQhkF0SgmEykHXkObox8q1iEjKN8rENqYD7MmeBCmzwSLFS1I3AqzYIPDESS+sWCxgQMLEgOSJKjozeAKFyskCDigQFwSBhJMjDDhAlyLFyVA+dIzAUUKEi0eaNhAIg8YGiEMenkwASNDDBkLqRQAEEAkup9KDkEFgC4IACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+gohome-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBAQCBCQiJNze3ERCROTi5MzGzLy6vDw6PKyqrKyurBQSFGRiZGxqbGRmZISChEQ+RExKTExOTHRydDQyNOTe5FROVLSurCwqLMTCxPT29Pz6/LSutFxeXLyytLSytPz+/JSWlKympPTq7KSipNzW3BwaHHx6fKx2VJRWNHQmBFweDOzq7Ly+vNTW1JxWNLSajPTe1Ny6pKxWJNTS1IyOjJRmbPTi3OzKrNSSXMSGVHQiBHx+fJSSlPzy9IxOVOzWxOSyjNSCPLxeDJyWnIRGTOTGtMxmDLRWBHwqBIxGTLRSDDQuNNSunKxKBGwyNMSafMxqHMReDKRGDPTu9LxuPLxaDJQ+DIR+hGQqNIQyBGQiBNTO1EQKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4QBAYSIiYQCAwQCiokEhwACBQYHBAiQhAiHlQYJCgkEC5uCkp8MDQ4NDwylmwgQlgQRERIEBBOkmxQVBgQWFwUFFxEEDLyJGAUZtQoFGhsFHLYdyoOVHsEf0SAbIAUex8mwlAUhtSIFG+3uIyTWvAIGJMEkJe76GyXbEeWUBJg4USKaBhQpVKzYoIFFiwYUBBJa8MAFCw0vYMSQMWOhBhoTKCQSUKMEiw02buDIoWOHBg0GeIhEFKAHDR8afgAJImSIioYliMws1MPkhiJGchxBkmTDCBo1hg4KQMTiBiUyhBxZ8pNFiR5MEtU0WqSJVidJNDyNKraHC5xPNKBEkTLlJ5WvUgWNvfikyhArV34+7ZEXQAAsB2iUyHLlihYtW0pwOYAFgyJDmDNr7jIIWiAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+goto-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBBQSDAwODAQCBCwiHDQuJExCNFRCNAwGBDwuJEw+NFxKPBQODEQ6LFxOPEw6NCwmHDQmJBwaFCQaFEQ2LCQeFDwyJBwWFDwyLDQqJAwKBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAWSICCOJBkEQqmWA1EYR4Gsq5Aoy2EYKU0yDcPCkSP4SgShw2FoDI6jQeNxYD6MUBFCEXxAelkRgxCRhEWQiW/wXE2CataAUmiXKo+Fwg6YWxQWfCQEAxckUgoYDRSCR4gKB4ZnFVwUCgUMZ30KCRQUhJpzBRQQjUcSnmyaM32mPgQNmZpRBwmSsxAZBBqzUa4iBiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+help-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBCQuNBwiJAwiLAwaJAwSHAwSFIy+3ERynCw2PCQuPAwmPCxOZCxWdJzG3FSazBwmNAQKDAQGBDRmhBQyTDxujDR2rIy21AwWJDyGxCxmjAwmNDRihAQOFDxmhCxunBQWFAwaLCRahDR6rESGvDQ2PCRWdDRunDSGvCRSdAwWHCwuLDSOzHSmxDyKxBxCZBwqNHSu1DyOzAQSHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAahQIBwCAgIBAPCoGAgOoeBAyKhWCwYDUf0CX1AIhLiJEGpBLiAAaRxdgYsl7Ybk8igBZoN5xmAdDxoanp8HyANISF8EBsiXBMjJBolBEQmGHFoRScbKHIKDykqK5lFAZRCnyknTaROLA8tq61OChgtKqyzQgEYEJi6UC4vI3LAASkbMBPARAEBdszR0sACEaPSMTIQM8W6KzNl3bo0NOJDdEEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+int-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIIAAPwCBIQChAQCBBwaHAQGBAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAANJCLrc/iDAuYKlU0r8NHfXB24iEyrCIAjAynakQLQuDS+vrTcnI1M9HyaIykFOKwUhZ6zEWC5oU9GrRY+kkqdUiXCdWW74SzYkAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+leftjust-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIihI+py+1vgpy0Tohzs1T7z3CiBJbQWJnqg4rre7jwTBtGAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+locationbar_erase-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBPz+/AAAACH5BAEAAAAALAAAAAAWABYAAAJChI+py+0PX5i0VmbzVboHPgmCJVoJJY5haR5VGsCa+6ZqZ2Sy95E2n0OVdi2A8EacIIS+YpC3WUIpi6kygs1qsYYCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+lock-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBHRudFxaXExGTERCRAwGDGxubPz+/Pz2/Ozm7Nza3NTS1KympFRSVHR2dNTO1JSSlKyqrKSipDQyNMTGxDw+PLSutKymrMTCxAQCBHRqLBQODJyanDQuFFxSJFRSJFRGJERCHExCHISChHxyLEQ6HGRaJExKHLSmbLy2fOzitPz23KSiZHxuNHxyNJSOTNTOnMTCjLSudKSaXJSKRJyOTOTetNzWpHxuPOTi5MzKzLS2tFxWXOzq7Ly6vOTe5Ix+RLSqdNzSpLyydKyqbKyiZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4IBAgMEBQKEjI0GBwgJCgsMDY2XjwkOAgQBDxCLl4QNCaGCBBGWooINCAqqrBKgqwATFKaDFRYVtBMXsIMNGBm0GRADjQIJxKIaGxwdHh8gISIhGyMZzIwkGholJiYfJiAfJyEZISDbg90oKCkqKwcHKyooLC0f7IIuLzD2YMSQgW8GDRri+AFoUMOGvRsxUhSsQQPHvmQSchyQtEAHhh0WJHDQcJERjwsKDvRI0BGDjwgicXhQyCOjSgUKPO6AObIkIQESfmxk6REDT4s0bfaYpDNkT4VAha5s+TLmzEYtatwIOHAiDZIKNQAJYk9IjCFEisyoocFEB4UACtBpm0t3LiF4gQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+lsub-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBIQChAAAACH5BAEAAAAALAAAAAAWABYAAAI9hI+pe+EPHTNhgjox04srn4CI2FgkZaaZurGd+5nRfAiCYVuJzfN6jbvdfrshEZE7ApNGXa+nZDaVVIOhAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+lsup-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBIQChAQCBAAAACH5BAEAAAAALAAAAAAWABYAAAI5hI+pF2G9YpszKgcgtgtyuX2I44UcRYkM5qmWAMcyzAn1/eKRnfe7vuD9fEGgQlgkHo2JmRPpStgLACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mail_forward-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIcAAJR6fIxydIxubIRqbIRmZHxeXHRaXHRWVGxSVGROTFxGRFxCRFQ+PEw6PEw2NEQuLPwCBJR2dLyijPTixPz69Pzq3Pzy3Pzu5PTu7Ozi1LyelOzavPz+/DwqLLyafPTmvPz67Pz29Pzy7LSWlPzmzPz6/LyajPTitOTSzMyurPz25PTatPTi3KyOjPzuxAwqVDQiJHxiZPTetKySlPzqvPz27BQ6bAwmTPTexLyinNzGxDRunPzy5KySjCQ+ZNzq9KTO7JzC3Nzq/Ozu/LzW7FSm1BR6vGSWvFyq1AyGxAxytAx6vBSKxAxSjMyujLSunES+5BSi1ByGvAQCBNzCrOTaxNTOvMS6rKyelCx6rBx6tBQKDOTWvPzu1PTq1OzezAQOHAxGdBROhAQGFPzy1NzOvIRqXLyynOzarPz21Jx2XPTWrLSShAw2XKSCbPzuzAwePAQCDPzyzPzqzPTmxOzWtAwGBKyObOTSrNzGrKyGbOzatEQyNKyCZOzWrOTGpNS2lCweHCQaHCQWFBwSFBQODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBhBwgQKFSpY0HgBQwYNGzh0mDhRAAUPHziACEGBpYgRJDiUGEkSwoCQJk6opNASRQoOFETQJDkggwoOJlYApcCihQuVL2DUhBDjhIqjJmRwwDCDhswaNm5MjYHjKggOOU7o0CGTA9gdYknG2KCCBw8VJVL0uBgihAUfP+CSNGCjsI/DiBPbAMJBsEQbQYQM+UG5smUiRYw0jlvYxhEkSYyIHm1EyRLTTH40EZvAyZPOR4pAmU07ipIkUKQ0mQIhAZUqVq5gKXzkSBYtyLVEyd1ki8QFXLp4+WJFQowbYLJnD5NbzJiJCjaQnhnvpYwZM0/OPFlvQ/f3iQvQpBlvQc0aCWy4VKnCpY0Y5yQxgEYXZFjghgwZUOHGCW90YQEccUwloBwGyjAHHXUoSAMZb0xhx1QOoMHDHSfIwSEOdTjhAQ1d4MFbTQ6Q4MYacrzxhhx04JCHHhvQsMeLJPHRBxpr+LHCGnusgccfgKixQR1ATtTBlDDAEIggggxCCCGFbLGFHVFKZEdAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mail_generic-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBDQyNCwqLCQiJBwaHBQSFAwKDAQCBDw6PPz+/Pz69Pz27PTy7PTy5PTu5PTu3PTu1PTq1PTqzOzmzPzuvOzitPTmvOzivAQGBDw+POzevPz67Pz25Pz23Pzy1PzyzPzqvOTavERCRKSilPz21OTevIR+ZExKTOTi3JyanLS2tPz6/Pz65KyihJSKbMS6lExOTNTW1JSWlJSKZMSylNTOrNTKpFRSVPz29MTCxPTmzKymjIyCdOTWxOzexOTWrBQWFFRWVOzu7MzKxJyalOzatLSulMzKtOzmxOTarFxaXKyqnPTmtIyGdIR+bOzetOzixBweHGRiZOzm3NzWzNzSrOTetGRmZOzizOTexOzm1JSKdGxqbHRydJySdHR2dOzapHx6fKyijOTixCwuLHx+fFxeXERGRDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeIiYqLAQECjwORAwSUBZYFBpkHmwgJCgsMDA0OD6UQERITFBMVFhcVGBkangq1ChsLGxwcHQ0dHR4fICEGIiMSCbS3uLq8wCQUJSYGJygpKhQJKyvLLM4Nwi0uLwUwDQsxMtmeuQveHR8UMzQ1NgU3Dgo41jk6ns0cKOzgYaOHjx9AgjTAUUvIECLZNmxoUISHkSM9KiBJQkCJA4kKEoBQoWJJAiYtmjh5AmVCsCJRpHzckKCCySlUUvBYUqUHDysSPnxIEuXKA5pPRiRwxwFLFhRaIEDYUoEChCcDuECoOWKFuwW7nHkg4WELkw8/BHRRwESpt10dU8SSHevlRxIBX6C0WBE27q8GZMkKbTADjIAwYlb4GLMYShYoPTRo6FGiSJEKPyzMIFMmzJcvXbhwkSLFjJkbQW6cOHNGhAgEAdAsmk27tm0ABgIBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mail_get-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQ6bCQ+ZAwePKTC5Ozu/NTi9GSWvAwSJGSu3JS+5CR+rAQOHPTy/AyKzES23AwOHCw+bOTq/BR6xES+5AwmTBw6ZMTW9Ax6tByi1BRGdAw2XAQCBDQuNDRupKzS9FSm1BR2vBym3EzC7CSGxBROhNTW1Pz+/OTm5NTO1AQGFNzW3Ozq7Ozm7IyKjJyWnMzOzNzq9Nze3OTa5Ly6vCQiJGReZISChKyqrAwqVBRWlOTi5MS6xJSWlNza3OTe5Ly2vGxmbKymrIyGjMzGzISGhKSepCQmJDw6PHR2dJSOlPTy9MTGxLy+vLS2tMzKzLSutMTCxLSytKSipJyenKyurJyanCwqLCwmLCwuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4IBhgIBA4SLjAABBAUGBwiNlY4FCQoLDJaNAQ0ODwsQnYwREhMUE5ylFYYRFhcYGRgaGxsDHJUdFR4SHyAhEyIjJCUcuo0cJr0nExihxgwoyYscKSnMHicOIw4lKissLdWDHC4vMCu9McYqMjMyNOUANTY3OPEoOTolDCszdrSgwaMcBxs9TMxYOCMHBx8zfPj48QNINQ5BbMBIIUShDIUoTAhR94PHPEEHbQwZckOGjBQviMxYUWQIDCMmdXE4gqRnkiFETAxR8iKFjJU2evZEdmLJkgJIbqS4wXJIUapImj5FtuSEVyRVV1IVi4RIChhEkLVAgcJHEqVwVJUmYdKkiRNkALMRecKECRG/ff8CEQJFCA5kMKJEoUHDCQ/HkB9LmWKECpUeyKoIMSLEyosen0OD7iH2xg1dV7BkqXGlBpbWNTq4Zn2khu0aAAwEAgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+mail_replyall-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIcAAJR6fIxydIxubIRqbIRmZHxeXHRaXHRWVGxSVGROTFxGRFxCRFQ+PEw6PEw2NEQuLPwCBLyejPTixPz29PTu3Pzu5Pzy7Ozi1LyelPTavPz+/DwqLPz67PTetPz69ERCRLSWlPTmzPz6/OzexLyajPzqvDw+PDQ2NMyurDQiJPz23PTatJyenAQCBPTevPz25LSajOzq7HxiZPTexPz65JyanBQ6bKSmpBwuTOTi5OzaxBRCdHySvGRiZHx6fBQSFERGRNzq9IyOjHx+fGxqbPzu3BwaHFSq3Aw6XAxKfPzy3Gy63ByWzJzO7Mzi9OzavBRytAx6vCSazGRKTPzy1AQKHBRGdBRyrDy63ES+3Cym1CR6rBwWVAQSLAx+xCyCtBRmnPzuzAQWLAwePPzyzKSCbAQOJByGvOTWvPTmxBQODFQ6PPTWrPzqzOzatAwGBKyObLSWfPTivKyCZEQyNKyGZOzWrOzWtOTSrOTGpNS2lJx2XDQmJCweHCQaHCQWFBwSFBQKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBgggoQJFCpkzGjhAoYMGjZMpMghQgcNFjh4mODhA4gQGkSIHAmBwAgNJEpo8KDSxAkUGjhMSEGz5gUVIiKs2PmBRQudHiwQpUnAxYsXImB0aBqjBcuoU0fKmPGChgUNH2qIqGHjg9u3bicWIFs2rYgbNnDkyGFhb8cccQ3ouJqWQo0dPFr0WMy4h48LFj4gsKriB5AeNngEaSGks+chPnwQOXFAh4oXRYxk9nAEyY7XO2wksWHDx5ATCDIoUXEBsYclTJo4cWJhuIjhSXacSPBEiZLMQY4wgRKluvXqUpyIsDElAxUqVaxcwcGCPQuWLOixaNHCZAsXBU+oqKDSxQqULF6ifNmyn/8VMOtxwcAK36kQRhdJQIFFEmKM4eCDYGyhhYAEkqFEGSuYYcUZLaDxXRpqSNRCEu6twYaFZXTQhgRd2NCCG9918AYELTjoXgNuKAFHB2RQEUYHVbQQRwlUpPHGGFwkyQUEDsgxx4lh9BhCBy2U8UQJcrSg5JIQ0FEHG3bc0QGYK+CRhx57PEGlkhM9sAEffKTQhx9+/AEIIIGoEUgLLRRFR0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mail_reply-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIcAAJR6fIxydIxubIRqbIRmZHxeXHRaXHRWVGxSVGROTFxGRFxCRFQ+PEw6PEw2NEQuLPwCBMSihPTixPz69PTq5Pzy1Pzu5PTq1Pzy7Pzu7Ozi1LyelPTavPz+/DwqLLSajPTetPz27LSWlPzmzPz6/PTexPz67Pz29OTSzMyurPz25LyajBRCdPzuvDQmJOzexPTevOzq5BQ6bBwuTDQiJHxiZPz23Pz65LyinPzmvBxCbHySvAQCBOTi3OTq9CweHOzaxFSq3Aw6XGy63ByWzJzO7Mzi9OzavNzq9BRytAx6vBR6tPzy3AwOHDy63Ax+xCSazCym1CR6rBwWVOzizAQSLES+3CyCtBRyrBRmnGRKTPzu1MzGtAxKfAQWLAwePPTizMy6nByGvNzWxOzWrNzOtBQKDJR2ZNS2lPTmvBQODPTatKSCbOTaxLyqlAQKHFQ6PPzyzPzqzPTu1PTivOzWtKyObPzuzOTOtLSWfPzqvAwGBKyCZPTWrPTmxNzKrEQyNOzatOTGpJx2XCQaHCQWFBwSFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBgggoQJFCpYuIDBQgYNGzh08DCR4oQPIDqEmDBhJQYRIzqQIFkSAoESJCKkDGFiwgkUKTpMwECz5IASKjqsSMlSA4sWQjG4qGnzhYoQSmF0iCFjBgmWGWhQrVHCxg2sOHLo2MGjB0sLYmsWQHq1p4wdPtqemGDhB1UDQFSouKHi7oQgQmSwUMyYxcQDZQWz2EFiCJEiRoyQyLzZyGIIB47YKLwDSRAiSZSoXq1kCRHNLBK8YGKjCYskTp4ogeKkt+8oUaBImZKAAxMmVKrctqL7ihTnz7FkAT5FC4cKFbZwadIFdxcvX8KLss8iJcoUBUcq2KgAJoxyMTy4jCFTxoxEHl2GLyCDncmWM2hUIQMPY2CXhhoTfTEcA2tgVwEba7Thxhs88FdBD/ZB8MUUHMJBRhw2sAGCHBKU4UaFc1RAhxnhcdhhHUzYAUIcFdxRAh4R5KGHinu4OIVEDqTBRx81xhGHHzD8wQYQetDRI4cTAcIHGWT0EQgZa1ApCBqDcBAID1Q94IEHLtBAAyGEFGKIIWqYYQYPYNZkQEAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mail_send-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIcAAIR6fIRydHxubHRqbHRmZGxeXGxaXGRWVFxSVFxOTFRGRExCREw+PEQ6PDw2NDwuLPwCBLSijOzixPz69PTq3PTu5PTu3PTu7OTi1KyelOzavPz+/DQqLPz67LSafOzetPz27Pz29KyajPTmzPz6/NzSzLyurCwiJPz25Ozi3JyOjPzuxBRGbAwSHOzexPz23KSSlPzqvBROdISavBxSdAwaLHRiZLSinNTGxMy+vBxGZNzu9BSGrAwWJMSyrKSSjFy61ETO3BRWfPz65PTqzHTK3ByqzBSWxEzW5AQWJOTWxBRCXOTu9BSOvDzO3ByavBRKbOzaxOzizKSWlCQ2TAQCBJza7BRWdNzSxJSCbMzq9BSOtCSKrAwiPOTavPzy3LymlCySrAwmPFRKTPzy1NTGrPzu1JR+bOzatPzyzCy61ByGpOzWtJyCbPTmvPzuzIS+3FymxCSuzBR6nJyCZOTWvKSObMSujOzivAwKDOTSrNzKrJyGbDwyNOzWrMy2lIx2XBwWFBQSFBQODAwGBAQGBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBgggoQJFCpYqMDxAoYMGjZwmEixg4cPGzqA6BBiAggRIzaQGEkSwgAMJCKgnNBhQogSJlKGOFHTpgYUG0TsnJBCxQoSE1i0KErAxYsOJJRuuAAjhkwZM2jUqGnDBQoUHTbciIEjx4YNOmbs4CGjB8kCZlGAALHBx4+YcTcACcJDyFSJBo6iGNIhhQkiG8BOKGLkCBK6SSQisHoWhZIbG5bMYALECI8mTZw8gTL1QJQXZ6VMiUylSpUlVpoYaXLFtm0EGmCjwJLlA2O9MrRsccKlC8kEXr7AdgEmwtkhX2SQ2BIkjBiSYzSQr/nyhUKZLIrJJOcexvlEBV7IvCBjRkmAMzHOaufhxDvJBWiQISAFxUUQQRovJNeEGmu4JxEDbKQhXxsfuFDGGW68IQMcccgxRxUkNRDhC3R8QMQIdZwXQ11JJGFbiB+QYccHaaTxhgt13OFBDGTgkUdRDrhAhx5k2JjGCB/swYcXMXwAYk190OGHHx/4wUaVepTxByAaoPEkSQ5wwMEJZAZipiCDDJIHIYV8OZEdAQEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+matrix-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBIQChCH5BAEAAAAALAAAAAAWABYAAAJHhI+pyw0Bw4sTVmmw1C/3/20ex2VUtJ2Uwx7oBb9eR45ziNfgy6tW2+pZhJicjXbTiZA7X2q4AjqIsajSuDsuty5n9SddGAoAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+message_get-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBFxatHx+/Hx69GRixFRWtHR29FxaxHx6/Gxq9ExKxGRm/FRW9Dw+xFxavFxazFRS1ExO9ERC/DQy5CQmzBwaxBQSpCwqLMS+xBwatExK/DQy9CQm/BQW3AQCjJyavAQCBMzGzAwOtDQ21DQy/Cwq/BQW9AwK5JSStOTi5AwKDKyurMTGxLS2xISGpNTS1IyKjJyanMTCxAQC1MzKzNza3MzOzCQiJGxqbHx6fKyqrLy61NTO1JSSlNTW1NzW3Nze3HRydKSipISChDw6PLy+vFxaXPTy9ISGhPz+/Ly6vLSytJSWlHx+fCQmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4IBAgIDBISLjIWHiY2RggWHBgeSkYYICQqYjQUICwwNnoMFDg8QDBESExQVFpgXGBkQERoSGxwdHh8gkiAhGCIjJCUmJx4oKb+NKissIS0iHcgeLi8pzI0gMDEyLzIiM9c0NTU2zYQ3ODk6L/A7yvDnPBjqgiA5PTYvPvU+fvh4AeQFDXwgggTBwEIIOB8sakB0iO7gIH05hvToIeQFBo4eNwoJEaIZiAtEUgbhWGQjRxk9hhhJSeQXiCM4jxBxyXMjEiI5bR5JQnRnT5dDiNCgIcNmCiBAfAShSZVmECVKltgc+MIGCxlgw4pdskKHEJtMZRTJuqStW7dCImLEYGLTrJC4PeYy0asXxpAhTZpdGHzBSWHDiBPfWCzIQCAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+misc-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFCQiJERGRBwaHFxeXHx+fDw+PGRmZExOTGxubKSipDQyNHx6fIyKjJSSlJyanISGhISChLS2tIyOjHR2dAwKDAQGBJyenAQCBCwqLLy+vKyqrAwODMTGxKyurFRWVLSytLy6vMTCxMzOzGRiZNTW1CwuLMzKzFxaXJSWlOTm5Nze3Ozu7OTi5Ozq7GxqbDw6PHRydAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAb/QIBwSBwGBMVkMjAgFAwHBFJpPB4SiQJCsWAQqEJB4prdNhQNx7QYIFwLD0ikQZdMHgelOPGYULQVDg4QEAVfRAEBBwUTEE0WFwcYhAuNF0QDBQULDwwZGUIaEAuVGxgBRAIFEhwHHUQMCxwTHAVrAAwFFRwKFkQZsxseDqBDGXMSHwfFQiAhIiMeJApEBwcOcahDJcLSJCYcGkQKcRAnQhkF0SgmEykHXkObox8q1iEjKN8rENqYD7MmeBCmzwSLFS1I3AqzYIPDESS+sWCxgQMLEgOSJKjozeAKFyskCDigQFwSBhJMjDDhAlyLFyVA+dIzAUUKEi0eaNhAIg8YGiEMenkwASNDDBkLqRQAEEAkup9KDkEFACUIACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+move-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAI6hI8RyJ26nAQQzlbrdWrP7nHRNh5gwpxmaZxWylJdRtf2fcux2rr7n8LsQrxQzyhE9mhIplKjPE5wBQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+news_subscribe-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAASC/Dw6PAQCBHRydPT29GxqbCQiJPz+9PTy9JwCBKwqLPz6/GRiZERCRPz+/FRSVDQyNBQSFBwaHDQ2NKSipJyanHx+fMzOzNza3FTCFGRmZCwqLAwODLzqpCwuLExOTLzqrFTGFAQGBES+BETCBEzCDDSqBBQ+BLTqnBRCBFRWVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAb0QIBwCAgIiMgkckAoHJVQgEFAOCCc0WThcEgoDgvGMztFJLiJ83Ws3C4ODIY1jUCIlQ0Bd+FwMLZmCXV3Qw8CCAICfW9wBQhddVgAEIcCCwuJDlxWBQx1AhFPjlyJlwISj1ZWBJQTAImIerGqVwgEiAwUR46ysAeJcKoEoYkTVLGPvrWVDBUWEwEXF1aziMGfAhhiAhAVFdKPyMux2YkAEc3fF3WcdQTAGYkQQxAF3uAIGggbCBwCHfEEeEBiIB0+BB8cgHAQogMIKPXurRMxgkQJExjZELT3jUGDEyhMpDhxIouUOB8qqAhZ0iS9CJMStTQQBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+next-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBOze9ORy7Pzy/PSi5LQCvNSG1JQ2nNx21LQCzMRGzNRy3KQCpLwKzAAAACH5BAEAAAAALAAAAAAWABYAAARTEMhJq704axC671WAfR8VCOKUbudApCBHksVgHO+5agFiHwVBAuYZ+RQLBmLHatgMS8mMyREsDI7oRipEeLWsKVG8Fce26EspzeaR2vDQNE7PGCIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+openterm-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIcAAPwCBAQCBPTy9PTu9Ozq7OTi5Nze3OTe5Nza3NzW3NTS1MzOzMzKzMzGzMTCxMTGxOzm7AwGDBQOFBQSFCQeHCwmLCwuLDQyNDw6PERCRFROVEQ+RDQ2NLy+vKSipISChGxqbExKTOzu7OTm5Pz+/GRiZMS+xLy6vBQWFLy2vCwiHFQ+NMSmfNSyhIxmTDwuLJx+bLS2tCwmHMyyhMyqfPTqpPzyvLSWbLSWfPzitIx+ZDw2PAwKDCQiJGxWRPTmrPTerMyuhPzqtPz63PTWnPz6zNy+nIRiVDQuLKyWbOTanPz21NS2jNS6lDQqJHRaTPzmrPTSnPzyxOTClPz2xNSuhPTqxPzuvOzSpAQGDOTKnMy2jOzSrPTu1NzKnOzOnBwWHJRuXLSWdPTatPzqvNzClCwmJOzSnOTOnPTuxOzKlOzerOzarOzitJR6ZNTO1IxmXPTWrNSyjPzOjPTSpLSehHRqZOzirOTCjPS+fPzGhOy6bOzKhGROPMy2lPz+1PzmtKRyRHRiNNTCdPz+zNzCjEQ2NKySdDQmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAj/AAEIHEiwoMGBARIqXMhQIUIBAwYQIFCggIEDCBIoULBgAYMGDgIIDEBAwMSKBRBk3NjxAciQIwdACBBBwgQKFSxcwJBBwwYMHBx0EAmA5EwPH0CEsCChoYgOQ0cSGCHhA4kSS5syJGDiBNEAFVGUKKEBAwWFFM6SNJHi64gDFEKE4FBBggoKK1i0cPECxokYXw0gsECYggQZM2jAqGHjBo4cOtqOxLhDAg8ePXz8ABJEyBAWRIoYOfJipEoMCZEkuaFkSAslS5jUGJKkSRAnRREo0JDwCZQoTKQAmUKlihQrVa5gKZ1lI+oAK7QM2cJlSZMuU4Z4+TJEx0iNOwKAggkjZkyOFmS8kClzpcUQLRRGbjRD4MgZNEzSqKG+ZgobI2248dUbDDDwABzcxSEHEFpgEcUcdMRRhx1fFejAAx0cgcYdSxiBRx566LEHH0d8QFRRNC3Uhx985CHEH0MAEkhCBxWkgiCDFEFIEYUYUmONMhyCRxVH/PgjBYioYJAdAQEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+paintbrush-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBMTC/AQCtAQCdPz+/MzKzOzu7KyqrCwuLAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARZEMhJ6wxiDMsp1lvHfRohWuRAmOeVlUTQSukqz3U8A/nd9rtCAWTbAQoGg0q3OyANCOYPA0UgfCdMJnHFimre72sZ7pBWiTLqRUirK5hV7A0P2O3GvD5PjwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+paren-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBIQChAQCBBQSFCH5BAEAAAAALAAAAAAWABYAAAJThI+pGou9oDuS1hlqnkxu/niVQB6kYHzAiJYoUK7paLrxpr6GMJjWeqlFGirEaQhcDHQJnEQX2/1kMBv08Yu1ttNkFRr1ikHjIiYYjDjSWLIbUAAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+pencil-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAASC/IQCBPwCBPyChMQCBPzCxAQCBPz+/MzKzISChKyqrDQyNEQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARYEMhJ6wxiEMtpIAWxddwXiqRlikSQeiAbuC+wirNR322gv7zcLobzDU+9XypoBBKTR1lz+RTWDgip8nUwZK1XLyIx5XoVicX2RUAo1DVKi7GOBxjxfNwQAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+percent-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIzhI+py+0P4wkU1XfDhBdo/zndF4qh1pkGKYFk2XpTqoJr9G5YfmOz3hixfBZa7IhMJg0FACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+player_eject-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAwKDJSWlFRSVBQSFKymrOzq7HRydERCRPz+/MzGzISGhJyenKSmpGxqbJyWnJSOlKSepLy2vIyOjGRiZPTu9IyGjLSutFxaXExOTHx2fGReZAQCBAQGBBwaHCQiJLSytKyurJSSlFxeXNze3LS2tIyKjFxWXHRudAwGDBQOFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa1QIBwSCwaj8ikcqkMCJjHwIBQgBIDhgMiUbVKFQsGItBdBhpgh4PxIJvRC8cA4oiMy8bvQhJhMAYTFBVOURAWEw0QFxcMERAYCBluVxobDxkVHJocmBwEGgmEQx0dHh0CpKmkH6odVlanBR8FtAIFtiCkSB0LISEiGCIGIxAPDySuRwIOBwrOzwoHJRHJRh0jJgMj2gMnERQUCNVFHQQoCBvo6CkICATjRB0qp7b1K6qv+foyQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+player_end-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNFxeXAQCBMTCxGReZBQSFOzm7AwKDKymrJSSlFRSVCwqLLy6vPTy9OTe5Ozq7CQiJLSytOTi5BwaHPz+/HRydMzKzKSepJSOlKSipJyanIyGjIyKjKyurISGhMzGzJyWnHR2dISChIyOjLSutDw+PERCRHx6fJSWlIR+hJyenGRmZHx2fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa6QIBwSCwaj8ikMBBQKgOCgRMZIBSkxYHWoDVWD9EigpBQLLBERsPxCA8NDUhjgTBGJJNGG02RVBQWdUV3FxgZe0IGfoAGdhoXGxwdiAYef4FGFBoeHB8dGSBRihUhIo1FBhkbIyMkJRYmAwYal4JEBh2RChIWJ1IIGxUZFqdECCgkHR6wWAYpFR2YWSobvL5vFgfDaEMDIivMRBEsD9HcQgMWvecDLB0tZ0btsfJa9vLXU/X6/P3+b0EAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+player_pause-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBAwODMTCxKSmpJSWlFRSVAQGBBwaHLSutOzq7Ly6vCQeJPz+/Hx2fBQWFGxubLSytJSOlBQOFAwKDJSSlJyWnIyOjHRydNze3GRiZAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAWBICCOZGmeaKqubOumQSDEgRjPMSoMRGEcol3vh0IkFAtDDWBEKlGMRKPgEIii0yrqIS1ArADu9KuLNCSOSdCMVp8ohEZFC4DL6SaBpXGh6/l4JX8XZACDhXkYCn1LAoqMUBAZEhBLDJKUSyYBGmhPAJyemiU0NDaloy+qq6ytI8whACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+player_start-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAQCBExOTAwKDAQGBJSSlHx+fBQSFMTCxKymrFRSVOzu7GxqbLSytLy6vJyanPz+/GReZBwaHHRydKSepKSipGRiZJyWnAwODLSutKSmpISChPTu9ISGhFxaXJSWlIyGjJSOlERCRIyKjDw2PIyOjLy2vOzm7Dw6PLS2tCQmJOTe5GxmbDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa7QIBwSCwaj8ik0hgQLJGBgbMoqBIKU2LAcMgOEQmFYeEFbBmNMgDhYDwWBC0k4pCoJ46IgRIXBioRCRYXamwRGBQIfgaBFhiERhkaenxmCoEbBhyQRYaIGVsdghgem4UWegcEBB8UHhsgIaZGBBgRIpUIIxQhChginEQIIBEklWslFyYnBsFfFCi4WQgpFBwqFxNGKxcsxl4IAS0NZEYCF3vlwgEfUuZV8JEuI2pPAARN9kcE9fr+SwaCAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+player_stop-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBAwKDBQSFBwaHCQmJJSSlISChJSOlJSWlGxqbGRiZNTS1PTy9Pz+/Ozm7OTi5FRSVIyKjOTe5MTCxIR+hExOTHR2dLy6vLSytLy2vHRydFxWXIyGjIyOjPz2/FRWVHx6fExKTMzOzJyanKSmpKyqrKSipAQGBLSutHx2fDw6PAwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa1QIBwSCwaj8ikcslsAgKCAWEQjQ4KgSwyYDAcugZEQqFYYJECA6PhaLcfEEUkgJZAGJB8fkKpWOhHAxcOGBQZGBoaGQgbHIBGAhUOGR0SBxISBh4Xf0iCHxQSlRIIXhsgj0UCIaCXmJgHGyKpRJ+hmB5dHQqOaCENIx0epBIkBhdzngoPGCQlJifQJBvJRygRKRcKGxcXGypys1srEREc5SLnICLiR1koLFVUWfRO9vf4+UwyQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+prec_minus-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBKSipPz+/CH5BAEAAAAALAAAAAAWABYAAAJAhI+py62RgnRnGguZ3BlTYIHdl13jh3goFpIleggvTK8ctw76Pswav/MtAkCd8NHj9HLFY6S4JEGdqdumtjAUAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+prec_plus-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBKSipPz+/CH5BAEAAAAALAAAAAAWABYAAAJHhI+py22hgjwSonktxBZU7GnhkyXc6JmmeDpnG2lg1YCOInT3zrvfxwsMhsSBrkYUDo8MpTEZNH6M0SV058xWi1Tsj9ZjGAoAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+previous-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBOzC7PTq9NSG1MxW3LQCzNRi7MRGzLQCvPz2/NRq3ORy7HQCdJwClAAAACH5BAEAAAAALAAAAAAWABYAAARUEMhJq70Yh813rl1HheInBYIwrEJwktxJFEbRmuOBJIXivp5LQLcj+HCnBaPBMBhdMBBjw0w8ccEA0/EzdQHaHywmnIyDyDSIrG4LQ+64OSqvx+kRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+prod-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBIQChCH5BAEAAAAALAAAAAAWABYAAAI7hI+py+1/gpy0hlVRZlP19mmSE0YjeIoXuqpkarYYbJQeDdiJrrs77gvOZDVg7Eb8JXtFSpMJiUoB9AIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+queue-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIIAAPwCBAQCBKSipMTC/Pz+/AAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAANfCLrc/jDKEGQMQlDLKM5aZQXDQIHZ9nhleaLqEhAE1bofKCozXZO3l0bmK9qCQ2LRCDQlAb3lkoTZQaVS6jOKpWmt3O5X2fU6wWXfuBM2mmINCpbKkavho56VI9s7DAkAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+redo-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBCReDJzGjMzivOTu3Pz+/JTWbHy+VHTCTMTivPT69BxGDESuJDyiHESiHEymJIzKZAQCBFS2LFzKNGzWPDRqHCxqDFSqLHy2XESCHAwaBAQOBBQqBDyWJHyqZDyKFGSiVESeJBQ6BAwSBGTGPFyWPFSSLEyOLESGJBQiDAwiBBQmDCRGFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaoQIBwSCwaj8hkMcBkKpcBwYAwEDif0YLhwEUkFItFMkAwMBoOR+PxgHwjRDggamhIJpQ8ZbKGKOQLcgEFdhUWEYgRF3sNfhELBHALAhgZFhobRBwREhQdEAIEHpIKHwsaSJwUDQgQIJINARxKESESDQ0dgCIjSpAkDAwPco+ZSJAlJicnKHIAIrNHidOIQxunT0kpCyrZSCss0d5Fj6jjRonn6uvs2QZBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+reload-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBCRSFCRSHBw+DBxCFCQ6FBwyDBQWBBxGFCxyLGTChMzqzLzmvHzKjDyOTER+RERyNDSqXNzy3LzivFS+fCyCPBQmBCQiBBxKFBQqDOTy3LTitES2dDR+PCxuJOT25KTarCx+PESSTCxKHDSeVCyKRNT21ESWVDSGPBQyDAQCBBQSFDRuLDSyZDySTGzChCRiJKSmpExKTDS2ZGzGhLy+vGxqbISChDSKRMzKzGxubDQ2NIyOjCQiJCwqLBQWFCwuLKSipERCRERGRHR2dAwKDDw6PFRWVIyKjCQmJFRSVBwaHKyurAQGBExOTBweHFxeXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf9gACCg4IBAgMEBQYHhI2ECAkKCwwNDg8QBAOOhAQREhMUFQgWBxcHGBmbggkaGxwPB4yDB6SbBJIKHQaqtY0eHyAhsqrDgx4aCiKpqoQHAyMjJBMKJaSxzAAHIRsmJgonKA0LHSmDKiuOBywRLSQuLyEwwyoxMuiN6iUzNBXy5jU2bsgoJugABBz95uXQsUMGD3vpPPgTpKIGwx4+HMr4kW4YkCA2hAzxAQSIECI+imBTwVIFESNHerRUgc0cEiFHkjiiyYzeDiVLdvLcySSkkKGEWiZVweSGkIHMmvQosoQlkaZOjvhosvKJjIAxoOAsgpRZkQNLnvSoqspAIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+revert-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAAQCBPwCBPz+/BQSFPTy9CQiJNTW1ERCRLSytAQGBISChMzKzFRWVDQyNCwqLMTCxFxeXOTm1KSipPz69BweHHR2dJSWlMya/Mxm/GQCzOzWxGRmZPzOzMzOzMzOnExOTDw6PNze3Ozq7OTi5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAWABYAAAbrQIBwSAwYAwDjUCloOgUDQlJJFCKfzoLAMF0ih9jmASGQfq3IBECgYC8YCsah4Rgc7+Bw2fCY4pNrCg8QboIIEX5HXXoEjWZ3eAIMgxITcRRVmVdOE50TBRV6TkJsD3EWDBUOoRcXGBmwsAJqT44aoKJNtAoVDAwWFRUFGwKxxhkCQhMEyxEcGrfEuWoGBgsdDwseHhQQvt++Hx8HmUQU4OHiICAJkHcDDB8hBCIj1QYfDomQAOIiHwxCPBiYr507JeNGAOQz8IC+g0YKrAtxAMQDBBgPFDB4EACIAwIHDkQAAhNEKuUStDMQBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+rightjust-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIhhI+py+1vgpy0Toizjvbur3WiBJbhSJnqgorri7nwDBoFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+rsub-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBIQChAAAACH5BAEAAAAALAAAAAAWABYAAAI+hI+pFu3f1gmSVUBrlnt19SUhMk5XaWnnqrYc+2rQfNWHIBi4feP+zssBdkJez5gAIodDYbH2+yGBymXCUAAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+rsup-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBIQChAQCBAAAACH5BAEAAAAALAAAAAAWABYAAAI6hI+pyxBhXlOv1omggxon6VFdGG1laFmkyQLCC8fvJNB2U+M3k/P70gP+FEHiMFFEHhFJJk0GXUkNBQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+run-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBOzq5MzOzPTy9KyurNze3PTy7IyOjOTi5MTGxNza3MTCxMzKzHx+fOTm5NTSzNTS1NTW1FxaXAQGBLy+vJSWlGxqbGRmZIyKhDw6PAQGDJyenAwKDLy6vLSytBQSFLy6tKyqrHR2dLS2tJyanJSSlISGhKSmpCQiJISGjCwqLBwaHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbcQIBwSCwaj8RAAMkUBgSDZdMpBQQIharyGDAclsoDYhtIKKrDwMEgUBMWiwSj3HCg0w+DfgGJQAYSDRMUTAELBhJ8fw0KFXdJBwkLEhYXGAUNDBUZj0pXkxYaARsIDRUMHJ5pAgQHkxEYUh0JFR4fHAVZTgMFCAt+sUIgBB4hIggOI1pKCQO8CB0gAgYkJGNbRQEKEYwNCa7VIhOPaRAKCpoV1QUl5E5mDJrFJAW4JuRlCuMnKB+94yVQ2DGi7QSYABcQgACTDF+VFChULJsiZIUCiRS5sMjIsQidIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+showmenu-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBBwaHERCRIyKjBQi/ERO7HR+1Ly+1Pz+/Ozq7MTCxOzu7NTS1AAAAAAAACH5BAEAAAAALAAAAAAWABYAAARkEMhJq7046z2D/2AoDAQVFGiqqsaBmGH8jWWX3Hiu3+YdKglPMIDrDXc+Is92zAmFi5pECWIkjySj0EkUZplb3JP4nV65WCmAqhR3yeo2Emmc0zsyGc3U6Pv/gAAKHISFhoQGEQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+signature-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAISGhISChHx+fHx6fHR2dHRydGxubGxqbGRmZGRiZFxeXFxaXFRWVFRSVExOTPwCBAQCBMzKzMzOzMTCtMS2dJSCTCwqLPz+/PTu1MzCtERCRMSydPTqxPz+9Pz6/MS+rNzKlKSSVOTarPz69ISCtGxurJyaxPT29MS6pOzmvNzSnHRyrPz29OTi5LyqXOzavMy6fFxanHR2rOzq5JyKTOzizPTqzKyWVGxqpPTy7LymZGRipLSy1PTu5KSSZFRKLExKTGRaNPz27PTq3LSiXPTq1GRWNDQ2NMTC3FxSNLymXGxqrPzy7IRyPDQyNCQmJGRinJSCdHxuVBQSDPTy5PTm1IR2RJyOfKSSfBweHGRenFxepNzGrKyejNS+pNTCnNzCpLyedBwaFBQWFNzOrOTOtOTOrBQSFOzStOTKpAwKBMS+tMS6rMS2nMSylMSulLymhLymfAQGBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAA8ALAAAAAAWABYAAAf/gAAAAQIDBAUGBwgJCgsMDQ4OD5MPEAEREpmYmJqaE5IPFBUWAxEXp6ipqJ+TFRgVBaaqsxcZGhUVGxwdBrK0qB4fFSAhIiMYCLIkJSa0JygVKSIhKSoJvhcrqh4sLRUuKR4vITAL2DGpMiMzNBs1FzYiKjcMER6oOKglLDkVOinwRMCAAcKBrx33eMTwkKPHPx8/RGxwEaICkIMXcOBgMaJfCgw/fMCgWCGIhoMlSOQQkmMIkSJGUoysGOTBEVlIZMTg16NHhSJJZCqhOenmqSU5cDDB0JJIzJlNak5yYoqHDBY7hmgN8aPGhhslKU16EgHJDiY9oGz9EcJFkChSaKaIfUC2I5UhMarU+GElyJUrWHzIFZslAtqWVbRs4dIFi5cvYMKImTsmQs8qVVrUePGCDJcyZkCEGUzpTAQMmGts5ozGTJo0XEbPVTNhDRsUbdy82Q0HTpwwwNXMlQOhuPHjyIWLNRAIACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+spellcheck-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAASC/AQCBFxaXBQWFAwKDPzCxPwaHPwiJNQGBOxKTPQ6PNQCBGwCBPQ+POwCBPwqLMwCBHwCBBwCBFQCBLQCBPwCBBQCBCQCBPQCBOQCBDQCBFwCBJQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAWGICCOZGmeaAoErMi+4xuQgQAI8yoKw2rfOZ1LRIgJh0hhDncsyXKypNMIKAKbNGpwFjxukcza7jt8xmCAgkpVMKxRhQOCnTAVFAtGqtBwLEgFDxAREigBExQVFRAibYNdJhaIigmODBdvF4gYDwoZDBpvIhKIGYOFoi4bHBGQogESqKlvBiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+sqrt-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIIAAPwCBIQChAQCBBwaHAQGBAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAANPCLrc/jDCQKutkcqQJeCP5k3g6IjCIAjAynYt0brzUn7gW++i0i8CGcNiuyl0NlyysYKhXgQdUvmcNZtDTo/mmvo+ptMvjDOSzWey+mFIAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+start-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VAQCBCRGZAxCZGyavExmjHyatOTy9CxihISevPz+/KzO3BRylAw+XDRWbPz6/FzC3CSuzDyexJzO5Mzq9CxSdAQOFISmxNzu9HTS5BSmxAyexDSuzJTa7Mzu9Kzi7GS21CRmjAQOHHSWtLze7AyWvHzG3BRihCTO3BS+1AyixBSWvBSOtBSStAQWJDzW5BTC3BSqzBS21CTC1ETW3AQSHEze7BRqlBRmjAQCDBR+pBRefBRSdAQKFAAAACH5BAEAAAAALAAAAAAWABYAAAa0QIBwSCwaj8ikMqBcMpsCQTEwIDQBUWKgYHgqs8LAAZGwQqWAgGLBaDgEj0Fgjh5mxRBERDKhICAQFRYXRVEBGBAZGhscHR4VHyAhIiOFAiQZJRoSGyaNJxQnEyiVRFEoGykqKyYsJiYtLi0mKC+WFygrMDEyMzQ1wDQqKDaWADYoMzcqsjg5DSgoBISmaCOoMG4v29s2OsZCyDs8DldgQtc95WdFPg7rV0Y+XvHt9ff4SXRBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+stop-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAASC/CQKDBwKDCwODNyKjPzq7My+vIxiXAQCBOSOjPz6/OSelNySjNyGhMR+fLRaTGQ2LPz+/Nx+dNR2bNRybMxuZMxeXMxiZLQSFJQaHFwqJNyKhOSCfNyCfNR6dMxmXMxWVMRORLQODOR+fOSSjNR2dMQ2LJQWFMRWTLwWDNSCfMxeVLwaFKQODNR+fNx+fMxiXKQSDOSWlMRSTMxaVMQ6NMxORMQyJOTS1MxqXLwWFLRORMxKPMQaHMxKTLQWFCH5BAEAAAAALAAAAAAWABYAAAb2QIBwSCwajwGBcikIHIsDQmFKNRwQT2EgoVgsGOCG4wHBIgmRhWRCqVQsF0xGYyYGNgoGh9PpeCQfICEic3UAAWgLIxwRJBsbHSUREyYYJ3RDAQULexGejhueESgpl3WaCxsqJKKsChEUKywtmFoFDC4vCayikzCyMbWHt38NCTKiHhUfMyzBdQIFKsodob0VNDWzwppuKxMRrx6iNjcitNA4bh+iEzkwojc66JkOOxcf7G35PBE9KS1MEUGgIQOIFfk++KjRw9wJgUUIZvhRoyLDFCliQDQisUWLGCJOeNx4hKCGkyhPGnqCoKVLl1liypyZxUAQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+sum-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBIQChCH5BAEAAAAALAAAAAAWABYAAAIyhI+py+1/gpyUMrvm1bdhFTgfhIykYZ4pyZ2o5EZwDLSurc7ZFnqZDgLKKsQe7QihFwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_block-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py30Bo5zBWUWzvNzo33GfFl5jVlonlTrr1DbvFi9vjeeNUQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_bold-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIxhI+py+0Powm0VnknjVkH2AEhE45LZ55Wqn6e65TsMc5eYosbksswubJIhsSiccgvAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+text_center-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py30Bo5zBWUbz3Sh7yIWfFHKjVl4nmFrr1Lpr7LwkjeeIUQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBBwaHAwKDBQSFLy+vLS2tJSWlBQWFKyqrFRSVCwqLDQyNNTS1GxqbFxaXJyanIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAVcICCOZGmKQSoMaZsShBsQBdAapHvgaIDUqUPJlRjSbAoT0fRDKgODRbF0PLUYjZO2F2Bst9evNix+dsvDlGKK5jraudQb7qbX6a2HEJ+ycyF+LRE8ZTI+fX5oGCEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_italic-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py+0P4wqUSlQvttrkDnyaOHIdeaGRupplAIauVM3xjeeOUQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_left-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+pyw0Bo5zB2UXz3Sp7yG2fFJajVjonmIor2TJvfL0wjecIXQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_right-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py30Bo5zBWUfz3SZ7yIXdF4kWqZkbCqoMO7kXLC+wVOe6YRQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text_under-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIvhI+py+0PowmUnhpeVVnb1DkbCI1I2JhX+Z0sOr2cTHpwK7a4rUr+hAnufsTirwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+toggle_log-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIYAAAQCBAQ2NPwCBATW1KSWfBweHATS1Pz+/Ozm1GxiTATOzPz6/Pz69ATGxKSahOzaxPzy5HxuVLSmlOTazPz27AS+vPT29NzClPTexHxuXLSmjAyKhPTy9KyehNy+lPTy5Pz29HxyXNzWxAS2tOzexPzy7IR6ZASytPTy7ASurPTu3KSSdIx+bASqrJyOdIyCbASmpJySfPzu3OzizJyKbKyijASipJSGdOTWtPTq1PTq3NS+lJySdOzWtOzi1My6lMS+rOTOrMS2nNTGrNTCpNzKpJSGZKyafLSifIx+ZHx6ZFR6bFR+dAQyNAQuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAAWABYAAAf/gAABAoSFhoeHAAMAiI2IigSMjoQABYkGBAeSjwAICYkKmQublJ0HDJ+GAA0OB66bpq4HCQC1lA2ZrqMCAA8QBwvBERITFIwAFa2yFgAXGL+uDBkaxRu1FQQLshwdHhgfDK4gIRoiFNYAI8quHA4XJCUMCwwMJhLm6Ce5rigEzhAMQICwYKLcuVopWgUDoWLFhQcfKNCjwOLeQQAtCFDYiAKBC28QKITk8MIgOhgxIHyQIWOGi4cfIHAogYJGjWq1bNzAkSOHjgc0dmBAgQKCUR43S1jjVeFGDx8PcNAAKePDjxg1gOCThOxFEBxBgpJQMQGpkCETEIBYSqkpkSJGOYTyOCJkgg4OIDaybXvjh5ELLpAMUYEAgQ7COPbyTWJEiY3HkCOTaruESYVamDPbQtTESedJhOgEAgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+top-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBAw2VHSWtBRihAQOHISmxNzu9BSmxHyatPz6/Lze7CTO3AyixAQSHHTS5BTC3DzW5ByyzPz+/OTy9AyexEze7GyavKzO3FzC3AyWvBSqzBR+pAQKFCRGZExmjCxihBRylCSuzBSWvBS21BSStBRSdAw+XAxCZDyexDSuzCTC1BSOtJzO5JTa7ETW3BRqlAQWJDRWbOT2/Mzq9HzG3BRmjJzS5Kzi7GS21BS+1CxSdCRmjAQOFAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaoQIBwSCwaj8jkMMBsOp3Ip7SpHAoGhELVKDAcENmtNaFYMBoEh1hAPjwgEUlYyZ5QHpIKxALWIgUXFBgZCBUaG3AcBB1HAh4fICEiFRUjJCUhBCYnjEQCAignoikqhissKAKiJwFJAS0uKhovMDFiADIzNDUsLza2Yh4KNDcsEbW3Ago4NSUrBMBbAjQ5KRo60Mk7PATdKH5bAT0xDg4xPa236uvsShRBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+undo-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBCReDJzGjMzivOTu3PT69MTivHy+VJTWbIzKZEymJESmFESiHDyiHESqLAQCBFzKNGzWPFS2LNTmzCxqDDRqHPz+/KTGnBQqBAQOBAwaBESCHHy2XBxGDOzy7HTCTEyyJDSqFHzWTAwSBBQ6BIy+dESKJFySPFSSNAwiBCRGFBQmDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAalQIBwSCwaj8ikMsBkKotMwYAwEDiXgYLhwD0gCFZiQKxNKBYMRqPh+D6G16y5AYnYIxBJAyF4AwITTAUJdBESD4gPFBV6Fn6ABBcJDIYPGEQZGhQbHAIdfx4JHw2VSBodGwWfAR4LDSALfkgYAQurBiAhICKfSSMkvQElGyYnGyi9Rxkdj4nOskUYyU9FpxnURikdGtjRKivdRKfQ2Inh5+jpRwZBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+up-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VAQCBHSWtBRmjAQOHISmxNzu9BSmxBRihHyatPz6/Lze7CTO3BSixHTS5BTC3DzW5ByyzPz+/OTy9AyexEze7ByixGyavKzO3FzC3AyWvBS+1BR+pAQKFCRGZExmjCxihBRylCSuzBSWvBS21BSOtBRSdAw+XAxCZDyexDSyzCTC1JzO5JTa7DSuzETW3BRqlAQWJDRWbOT2/Mzq9HzG3JzS5Kzi7BSStGS21CxSdCRmjAQOFAQSHAAAACH5BAEAAAAALAAAAAAWABYAAAaeQIBwSCwaj8ikcqkMCJjHwIBQgBIDhgMiUbUGFAtGw0GFfheHByQi4S6/E8pDUoFYLm5kAEPJaBAVGxIcER0JHlEfICEiIxUkGyUmIgknKIhXASkonCorgSwmKQGcKE9IAi0uLxUwMTJWMzQ1NiYwBLBQHws1N7avXgs4NjkcCblMATU6KhvGyG87PAnUKV1MAj0+2zIFp1bg4eJJdkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+view_choose-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBFRSVExKTDQyNPz69PTq5Pz+/OzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARTEMhJq70466Cl+AMxBVwnFIVRAmQHCIeBrC1L3tQgJ/SaEbeeC1PLBHE2ybFI9A1HzstHEIK6YCmhDTmBybQaHYJn7QC5zKeytIQe1+pKNE6P2yMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+view_detailed-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBFRSVExKTDQyNPz+/Pz69PTq5AQCBOzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAQ+EMhJq7046817+MLQUQFRGMc4lQaSAkcMx3QltMmrDrSu/sCgEPgJhIiFk89DaL1qPRnlhsgBebWhdstVESIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+view_icon-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBFRSVExKTDQyNPz69PTq5AQCBPz+/OzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARWEMhJq7046z2DF0PlBeAVEERhiKhqHgWyUgEsX0KczFOO7JeBYciTCImc5ITIXDKHyqhU9AnRqq9UEVDTvmLbGhin2/qAliOUot5OLc81IO5+2+8WewQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewmag--22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFJyanKy2tLzCxHyChNTa3Nzq7Nz29Nzy9Mzy9MTu9OTy9Nzi5Oz6/OT29MTi5Kzi7NTy9KTm7JzW3ITO1Lzq7IzW5HzK1LS+vMTq7Jze7ITW3GTCzGS+zLTS1MzOzLzq9Kzm7Jze5ITW5HTS3FS2vLze5EzCzEyyvEyutJTa5NTu9ITa5FTK1ESirLTm7Mzi5FS6xEy2vESerESmtFSutESmrKyqrAz+/Dw+RAzi3ASutHRydAQCBAAAACH5BAEAAAAALAAAAAAWABYAAAbKQIBQGCgWh8jksCgYEAaCozIZKBgOiIRiwSgEpstCw/HYQiKRhBcMCBgQDodkMaFU0t9pQHCIyy0TFxgYEVF6GQ4LCQkaERscHR4RH3lUIAkWCyEiIyQlHiYjEJVIAQQJJ2gjJSUoKSorlHoCLBQcHC0lLikvHjCGejEiHBgeMjM0NRwPpFQFDBHFNjceHAjAYFWoI7cnCVE4OWxtex8QH1EBOjs4zUpGUjw6Pe3j2fP19u/47vrq9P3s/avno2BBf/MCClSob4iBIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewmag-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFJyanKy2tLzCxHyChNTa3Nzq7Nz29Nzy9Mzy9MTu9OTy9Nzi5Oz6/OT29MTi5Kzi7NTy9KTm7JzW3ITO1Lzq7IzW5HzK1LS+vMTq7Jze7ITW3GTCzGS+zLTS1MzOzLzq9Kzm7Jze5ITW5HTS3FS2vLze5EzCzEyyvEyutJTa5NTu9ITa5FTK1ESirLTm7Mzi5FS6xEy2vESerESmtFSutESmrKyqrAz+/Dw+RAzi3ASutHRydAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbIQIBQGCgWh8jksCgYEAaCozIZKBgOiIRiwSgEpstCw/HYQiKRhBcMCBgQDodkMaFU0t9pQHCIyy0TFxgYEVF6GQ4LCQkaERscHR4RH3lUIAkWCyEiIyQlHiYjEJVIAQQJJ2gjJSUoKSorlHoCLBQcHC0lLikvHjCGejEiHBgeMjM0NRwPpFQFDBHFNjceHAjAYFWoI7cnCVE4OWxtex8QH1EBOjs4zUpGUjw6Pe3j2fP19u/47vrq9P3s/cunr9S8gAIRFhTCLAgAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewmag+-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFJyanKy2tLzCxHyChNTa3Nzq7Nz29Nzy9Mzy9MTu9OTy9Nzi5Oz6/OT29MTi5Kzi7NTy9KTm7JzW3ITO1Lzq7IzW5HzK1LS+vMTq7Jze7ITW3GTCzGS+zLTS1MzOzLzq9Kzm7Jze5ITW5HTS3FS2vLze5EzCzEyyvEyutJTa5NTu9ITa5FTK1ESirLTm7Mzi5FS6xEy2vESerESmtFSutESmrKyqrAz+/Dw+RAzi3ASutHRydAQCBAAAACH5BAEAAAAALAAAAAAWABYAAAbQQIBQGCgWh8jksCgYEAaCozIZKBgOiIRiwSgEpstCw/HYQiKRhBcMCBgQDodkMaFU0t9pQHCIyy0TFxgYEVF6GQ4LCQkaERscHR4RH3lUIAkWCyEiIyQlHiYjEJVIAQQJJ2gjJSUoKSorlHoCLBQcHC0lLikvHjCGejEiHBgeMjM0NRwPpFQFDBHFNjceHAjAYFWoI7cnCVE4OWxtex8QH1EBOjs4zUpGUjw6Pe3j2fP19u/4zT766vRI+fvHD4CPgwcJ9qg0UB85JA0dDjEQBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+view_multicolumn-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBFRSVExKTDQyNPz+/Pz69PTq5AQCBOzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARTEMhJq7046813+MJQfUF4BURhHGO6noSBsEcNoDJtS4KcsJQe4ncZ1HYT47HDbDqfUAnJRJmKLIGCCjjJbmE5wBI3EyOFxKCPS1EiJW52dE6vZyIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+view_sidetree-22:actions actions22 22:photo:22 22:R0lGODlhFgAVAIUAAPwCBFRWVFxWXFxaXExKTNTO1NTS1Nze3Hx6fLSutMzGzLy6vMTCxDQyNMzOzPT29Pz6/Pz+/PTu9Ozq7OTi5Pz2/Ozm7MzKzGxmbIyKjAQCBPTy9FROVFRSVPTq5OzOpMS+xPzu5OTKpExOTJSOlOzu7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABUAAAb/QIBwSCwaAQFBcqlsLgcBAnFQqBqqhwIiUVB4F4wGMeB4QMyPSCFQkEwmlMlCPKRC7pCKmjpxTyxzUwVmEBF6FxiDbxZyUnUFdxERhQUZbX4TDBlEAgUVkQ8DogEDAqYBTwEaAw54eQNusRMPs319Gp0PFZ8PAhMRGpLCwxOrFw/IFRuwwMICHAIEkhK4lxK0A7/Bkh0RHtvFAwp9D27MGugRAh4f29TithIW2c2SBOjgqwxv/AIS9cOEvQPBiBEFetsidOhAQFqEcCDgWLBAwR9AARFCuMPFAMwCEAsQpuMQQkS+EQ1SNkBAwuKwe+kiUDuSzU0JPyUm5HSj4Qi+Bp9A8QEIAgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+view_text-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIkhI+py+0Po2ShBlOxzbP7n2yaJoLm+ZTcxqHuC6hXzML2HVEFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+view_tree-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBFRSVExKTDQyNPz+/Pz69Pzu5PTq5OzaxBQOFOzKpFRWVFxWXOzexPTexCH5BAEAAAAALAAAAAAWABYAAARPEMhJq704g6A779kHCORAgNskFMYhakE8FkjyBcoWv+JwJItXaELYCTFHlCSpZKKcoB5jYHpOGgUadLKbIRw3jhEzQDyCSuI4zW673yhDBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+window_fullscreen-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBNTW1NTS1MzOzMTGxLy+vLy6vLS2tKyurKyqrKSmpKSipJyenMzKzMTCxLSytFxaXPz+/Pz+9Pz+7IQCBMzOvMzOtPz+1MzOrPz+5Pz+3MzOpMzOnMzOxAAAACH5BAEAAAAALAAAAAAWABYAAAWxICCOZGmeKBqsbOu+rjAQRFEYxoEkibIwjUZMRnAUHjkEpPcLriLQqHQ6XRUk2Kw2O+lSKIUVoUKubLflikVcPnO75cvKkXZL4HG2pK31lilqc1lmfRNfgBQYGBlidl5fGhobGxqMAQNnXYaQkZOLjVgVmpsUkRoVnpZje2SkphtlGBUcbH+br5NptAF0rYe4G4plHSseaaW4irLDcxYOFtDRFhnU1B3X1zDa2indIwYhACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+window_nofullscreen-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBNTW1NTS1MzOzMTGxLy+vLy6vLS2tKyurKyqrKSmpKSipJyenMzKzMTCxLSytFxaXPz+/Pz+9Pz+7IQCBMzOvMzOtPz+5Pz+3MzOrPz+1Pz+zMzOpPz+xMzOxMzOnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbKQIBwSCwaj0hkYMlsOp9OwYBAKBQMhgMikVAsGI1GVEpwFB5ZBKT7DS8j8Lh8Pl8WJPiJfr/PTygUBUsEEhV4h4h+ExUUFoMVkIWJhxWLkBeDhZCGiXqbFRiYAYSanId7mxihSwOlphJ6gJ8ZGksOiqd/gKoYGRmipIh7gBSqvhkbtaOuw7sYn8mseJuxxcabGxwdmZ/EvL6f2o+Qz869yBUem9sBH4sYf7znG/Qb6h4gSx8fDh8W/wA1CBTYoSCIfFASQknCcIiBIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+wizard-22:actions actions22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBNzaTPz6BAQCBPz+BExKBMzOTPz+rPz+3ISCBPTyhISCLISChPz+xOTiVPz+/MTCxKSipKyqrExOTDw+PDQyNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAV+ICCOZAkEZqoKqoqKAzHAb1sIxhAQwWAQhRaJd0AcdgkhqaBAOBUL5WjAaD6TUqog0DAildqcg+cDtgaPACTCiM0AOhV6sG4DWOAHnf2uyfV1b1lsgVIwEgwTFHaGA2yKFYJgiJCSQo6JFJGGcJSalkKPn5wimZukAJWoIgYhACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
diff --git a/ext/tk/sample/tkextlib/ICONS/tkIcons.kde b/ext/tk/sample/tkextlib/ICONS/tkIcons.kde
new file mode 100644
index 0000000000..0d5b2c8695
--- /dev/null
+++ b/ext/tk/sample/tkextlib/ICONS/tkIcons.kde
@@ -0,0 +1,195 @@
+actattach16:act act16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBPz+/AQCBAAAACH5BAEAAAAALAAAAAAQABAAAAI2hAOCxg2h0nJHyEshi9HpxU1GOCLdZoKpQ15nibUoprKp9lh2oucUxsBRXsJh4Hjs/QTMpr8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actbookmark16:act act16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCwqLLSytLy+vERGRFRWVDQ2NKSmpAQCBKyurMTGxISChJyanHR2dIyKjGxubHRydGRmZIyOjFxeXHx6fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVbICACwWieY1CibCCsrBkMb0zchSEcNYskCtqBBzshFkOGQFk0IRqOxqPBODRHCMhCQKteRc9FI/KQWGOIyFYgkDC+gPR4snCcfRGKOIKIgSMQE31+f4OEYCZ+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actbookmarknew16:act act16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCwqLLSytLy6vERGRFRWVDQyNKSipAQCBMTGxKyurISChJSSlJyanHR2dIyKjPz+xISGhPz+BGxubMTCBHx+fPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVfICACwWieY1CibCCsrBkMb0zchTEcNYsIiYHiwIOdEAvigdFQGE0Ix4NBbSAgsWjk+jBIAlcUYrJASChnSXZSoUDelKfoKpFALJA61ueGI2IAZmhogGFmCGGAgXsifiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actcheck16:act act16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBMT+xATCBASCBARCBAQCBEQCBAAAACH5BAEAAAAALAAAAAAQABAAAAM2CLrc/itAF8RkdVyVye4FpzUgJwijORCGUhDDOZbLG6Nd2xjwibIQ2y80sRGIl4IBuWk6Af4EACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actcross16:act act16 16:photo:16 16:R0lGODlhEAAQAIIAAASC/PwCBMQCBEQCBIQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMuCLrc/hCGFyYLQjQsquLDQ2ScEEJjZkYfyQKlJa2j7AQnMM7NfucLze1FLD78CQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actexit16:act act16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBDQyNHR2dCH5BAEAAAAALAAAAAAQABAAAAI4hI+pFrHb3nEg1iWiDiINCwYDko0V9XUTda6I1TIsUMpGinyzbB6ZeGuoEr+GUDL4CXqSphPhLwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+acthelp16:act act16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQ6XAQCBCyCvARSjAQ+ZGSm1ARCbEyWzESOxIy63ARalAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAQ/EEgQqhUz00GEJx2WFUY3BZw5HYh4cu6mSkEy06B72LHkiYFST0NRLIaa4I0oQyZhTKInSq2eAlaaMAuYEv0RACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actitemadd16:act act16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBARCZPz+/Mzq9BTC3ITC1HSyzGSivAw+XBSStIS6zHy2zAQCDFyatAQOHFSStEyOtAQSJBSq1DR2nCxunCRmlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVbICCOQTmeaCAMRIC+AVu47xkTBl2Ld16XQNYBQTQBVIOkMHFQJBeMI4tAbSSu2IRDSnhAvFfI97sFRM6RwOMacbjLKckVvgvIJ5EdSU7J648VgXQ7Dmd/hyJ+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actitemdelete16:act act16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBARCZPz+/Mzq9BTC3AQCDAQOHFSStAQSJAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAQwEMhJq704681n+GAISoEwnGg6EAUQrEQsz4ThEkeu77kNIAagMEj0dY7IpHI58UcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actlock16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaVAQCBKSipDQyNMTCxISChFxaLFxSJEQ+FExGHCQiDBwaDGxiLHxyNHRuPIR+TIyGZJSSfFxaRFxWJGRiLJyaXNzWpNTOnMzGnLy2hJSKTGReLKyqjPTu1NzarMS+jLSyfKyibJySXIyGVCQeDLSytPT29Ozu7OTi5NTS1KyurJSSjGxqVFxaXLS2tKSebOzuzLSufJSOXExGLGRiTExONAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaTQIBwGCgGhkhkQDBoEpLKQoBACAyOUID1qTVwoQGvMPxNFgVjAxp6QCQUicSCwVgkG44HJCKRRCYUCAxIFRYXhxgZGhYbHINEHR4fGCAhIiMkFSVKJicoKSoFKwMsLZtDLison6GjLA92qCueoAUvpC2xQhWqrLYDErmEMDEXlDIwMxAHukI0NS01EzY2NAmPAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actredo16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBxOHBxSHBRGHKzCtNzu3MTSzBQ2FLzSxIzCjCSKFCyeHDzCLAxGHAwuFDSCNBxKLES+NHSmfBQ6FBxWJAQaDAQWFAw+HDSyLJzOnISyjMTexAQOBAwmDAw+FMzizAQODDymNKzWrAQKDAwaDEy6TFTGTFSyXDyKTAQCBAwiFBQyHAwSFAwmHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ2QIBwSCwaj0hAICBICgcDQsEgaB4PiIRiW0AEiE3sdsFgcK2CBsCheEAcjgYjoigwJRM2pUK0XDAKGRobDRwKHUcegAsfExUdIEcVCgshImojfEUkCiUmJygHACkqHEQpqKkpogAgK5FOQywtprFDKRwptrZ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actreload16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCRaJBxWJBxOHBRGBCxeLLTatCSKFCymJBQ6BAwmBNzu3AQCBAQOBCRSJKzWrGy+ZDy+NBxSHFSmTBxWHLTWtCyaHCSSFCx6PETKNBQ+FBwaHCRKJMTixLy6vExOTKyqrFxaXDQyNDw+PBQSFHx6fCwuLJyenDQ2NISChLSytJSSlFxeXAwODCQmJBweHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaBQIBQGBAMBALCcCksGA4IQkJBUDIDC6gVwGhshY5HlMn9DiCRL1MyYE8iiapaSKlALBdMRiPckDkdeXt9HgxkGhWDXB4fH4ZMGnxcICEiI45kQiQkDCUmJZskmUIiJyiPQgyoQwwpH35LqqgMKiEjq5obqh8rLCMtowAkLqovuH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actrun16:act act16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/ISChKSipMTCxLS2tLy+vMzOzMTGxNTS1AAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARlEMgJQqDYyiDGrR8oWJxnCcQXDMU4GEYqFN4UEHB+FEhtv7EBIYEohkjBkwJBqggEMB+ncHhaBsDUZmbAXq67EecQ02x2CMWzkAs504gCO3qcDZjkl11FMJVIN0cqHSpuGYYSfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actstop16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAASC/Gw6NGQuLHQ6NGQmJFweHFQaFPTm5PTa3PTW1Oy+vOS6tNSinKReVDQWFPz+/Nx6fNyCfNyGhNR+dMxybMRiXLxGRIwWFNx2dNx+fNx2bMxuZLQWFBwWFPTu7Pzy9NRqZNRuZMRSVLwmJGwWFNR2dMQiHPTKxMxmXMQyLMxmZNx6dMxiXMRSRMRaVKxybMxaVEQWFMQuJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaaQIAQEBAMCAWDYcgkHhAJxYLRcDQBggckIplQKpaLdRh4YDIaSWa94Vw6woAHgv6AMKGPaMQhwQMJJRkfhHmEJhdvRCcgGSCEkCgpbnAECiorGYYfLCItlAAFCygQj5AfbYlwBQwVE5AukG6KBi8tMC0fLi0pHxyzcAAxFxwmMny/wEwOxMm/qlcdJCSJ1H5XQh3a28HY3kx+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actundo16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBxSHBxOHMTSzNzu3KzCtBRGHCSKFIzCjLzSxBQ2FAxGHDzCLCyeHBQ+FHSmfAwuFBxKLDSCNMzizISyjJzOnDSyLAw+FAQSDAQeDBxWJAwmDAQOBKzWrDymNAQaDAQODAwaDDyKTFSyXFTGTEy6TAQCBAQKDAwiFBQyHAwSFAwmHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ1QIBwSCwaj0hiQCBICpcDQsFgGAaIguhhi0gohIsrQEDYMhiNrRfgeAQC5fMCAolIDhD2hFI5WC4YRBkaBxsOE2l/RxsHHA4dHmkfRyAbIQ4iIyQlB5NFGCAACiakpSZEJyinTgAcKSesACorgU4mJ6uxR35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actunlock16:act act16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaVAQCBKSipDQyNMTCxISChFxaLFxSJExGHEQ+FCQiDBwaDBweDGxiLHxyNHRuPIR+RIyGZJSSfFxaRGxmLJyaXNzWpNTOnMzGnMS+jJSKTGReLKyqjPTu1NzarLSufKyibJySXIyGVGxiNFxaXLSytPT29Ozu7OTi5NTS1KyurGxqVCQeDJSSjLS2tNTW1KSmpGRiLKSebOzuzJSOXExONExGLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaVQIBwOAwYA8SkMCAYOAnKYiFAIAQGyOgVCggYuEovVxztMpdnwAGRSCgUCwOjIeQ6HpCIZDKRUNYMRBUWF4UYGRoWGxyBRR0eHxgaICEiIyR0QyUmJygpKgUrAxMsLUQlKyieoKIuEAunK52fBS8DLiywQySpnjC1Mbi6QjIzNBeSIBY1EQfDQgosLAEUNjY3Co1DfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appbook16:app app16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBDyKhDSChGSinFSWlEySjCx+fHSqrGSipESOjCR6dKTGxISytIy6vFSalBxydAQeHHyurAxubARmZCR+fBx2dDyKjPz+/MzKzLTS1IyOjAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVkICCOZGmKQXCWqTCoa0oUxnDAZIrsSaEMCxwgwGggHI3E47eA4AKRogQxcy0mFFhgEW3MCoOKBZsdUrhFxSUMyT7P3bAlhcnk4BoHvb4RBuABGHwpJn+BGX1CLAGJKzmKjpF+IQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+appbookopen16:app app16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBExCNGSenHRmVCwqJPTq1GxeTHRqXPz+/DwyJPTq3Ny+lOzexPzy5HRuVFSWlNzClPTexIR2ZOzevPz29AxqbPz6/IR+ZDyKjPTy5IyCZPz27ESOjJySfDSGhPTm1PTizJSKdDSChNzWxMS2nIR6ZKyijNzOrOzWtIx+bLSifNTGrMy6lIx+ZCRWRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaeQEAAQCwWBYJiYEAoGAFIw0E5QCScAIVikUgQqNargtFwdB9KSDhxiEjMiUlgHlB3E48IpdKdLCxzEAQJFxUTblwJGH9zGQgVGhUbbhxdG4wBHQQaCwaTb10emB8EBiAhInp8CSKYIw8kDRSfDiUmJ4xCIxMoKSoRJRMrJyy5uhMtLisTLCQkC8bHGBMj1daARgEjLyN03kPZc09FfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appboxes16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMT+xAT+BASCBATCBMT+/AT+/ASChATCxPz+xPz+BISCBMTCBAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEEgZwrwYBCFqvhs3DNYXjChRlWBRjIRqGN4UuEUczMZxsDeXykdEsDQVVSLhQxhBCkVlmXA+KVHFYhFYOoHbMGN6pTQaW8YYiQmcG+q16a0+Zipw+4e9B/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+appbox16:app app16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBPz+xISCBMTCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANECKoR6ys2IVqokF08yMTA1gwkYX5WQK5ma4VceTYPxXnBWdtY6+0834/Bowgzm6APWRQcH4TiMhPK2WYRiZWW7XK7/gQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appbrowser16:app app16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxONCROfCRKfKx6LNy+bNTOpGSS1DRupAwyXBRSnPTSjPTqvOzqzMzSvHSSlKy6ZDxutAxCpBQ2XBxepLTKvPzqzPzy5OTShLS2dLSqRFR2jBRerBQ+jOTixOzetNS2XHx6XDR2tCRexBwyTDyKzOTavPzq1OzKdCx23BRKtCQ6VCQmHFSa7IyirOzSnGSGpIR+bFSO1DyK7DR+5CRixBw2VDQuHFye7IS27NzGXISuhEyS5DR25BRWxBQ+lBQyXCQqPCxSfGyu7GyerKy2ZFR+rERqfCRmxBROtBQ+fBwuTBwmNDSW9JyabLyqRIx+TExSXBQ6bAQCBBQ6ZBxapDR+zBxq3LyaLJySRHxqPGxeNBxGbCRmrHRyRERONDRKNDQ2JCQuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAeygACCg4SFhgABAQIDh4MBBAUGBwgDCYcKCwwNDg8QERIThRQVFhcNGBkaGxwdoYMDHhcXHxggISIjEiSvJSYXJwsoISkpIyorLIIDLS4WLzAxMjM0NSo2N8o4OS46OzwzPSk+P0BBgkI8Q0NERUZHCEhJSktMgwk4Qy1NTk9QUVJLphCiUsWKlStYsmjZQiJgIS4KuijQ4iXAFxYCDVFJwGUFmDBhMjYSw0KMyEYoBfkJBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+appcalc16:app app16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBISChPz+/AQCBCH5BAEAAAAALAAAAAAQABAAAAI4hI9pwe0Ogpi00hHF2LzzzFlTsIHD45SSx6oCeW4wjK2tl83y7t64pIsJaxrfh2bEAJIlhRPhLwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appclock16:app app16 16:photo:16 16:R0lGODlhEAAQAIIAALy+vAQCBPwCBMQCBIQCBISChPz+/MTCxCH5BAAAAAAALAAAAAAQABAAAANbCLHcrSLKOZcYmDSCsR1aUABAsXDDJwJGa5SBFwgaWxbCG3CWaBwG3C8Y67FawpYiNQscg65fsVkYuoAmJs1pBR522lQB6ILJLqHRwQQOZzYdZnw+dzruDIA/AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+appdate16:app app16 16:photo:16 16:R0lGODlhEAAQAIQAAASC/AQCBPzerPyqXMRaBIQCBISChPz+/KSipMTCxPz+BMTCBPwCBPz+xPzCxMQCBISCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVxICCOQGCeJjkGwkC8RFEEavkax2G8dB0QuRyhhzoBg8MSYsncJXKJZIDZHCoWP1ogGIwGrtnSgUFmHLyNRHhrdpjRamnO/SYkromHdnxwnwkKVxByZW8DgQsQM2JcfwZXO0MBCZSVBgMuLzJaRZ0pfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+apppencil16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAASC/IQCBMQCBPzCxAQCBPz+/MTCxISChDQyNKSipEQCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARDEMhJZRBD1H2z3lMnjKCFjUJQimOgcmcbELCXzjXq0hV785WCQYcDFQjDXeloMByKG6YTAdwIDAlqSZJSVFeKLcUfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+appsheet16:app app16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBAT+/Pz+/KSipPz+BAAAAAAAACH5BAEAAAAALAAAAAAQABAAAANFCBDc7iqIKUW98WkWpx1DAIphR41ouWya+YVpoBAaCKtMoRfsyue8WGC3YxBii5+RtiEWmASFdDVs6GRTKfCa7UK6AH8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+apptool16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBISChGRmZMTCxKSipLS2tHx6fPz+/OTm5FxaXOzu7DQyNMzOzAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAReEMhAq7wYBDECKVSGBcbRfcEYauSZXgFCrEEXgDCSeIEyzKSXZoBYVCoJVIqBGByKu0Cy8QHxmgNngWCkGgqsGWFseu6oMApoXHAWhWnKrv0UqeYDe0YO10/6fhJ+EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+apptools16:app app16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBExKTERCRAQCBOzu7Nze3MzKzLy+vCxqZBQ2NJyanKyqrGRiZDRydKza3FRWVPT29LSytDw6PMTm5EySjCxaXGRaJFSanCRSVGxqbPTmvMSqVJTW1GSurHS6vOzq7KSipISChFRKHJSGNPz23GxKFBQ6PKyurCwqLMyufJx2RAQGBJSWlEwyDIRiLNy+lLSKVDwmDJRuNOTOrLyabGRCFDx2dKSCVOzWtHzCxOTGnNSyhAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAahQIBwCAgIBAOiUiggFAyHASKxDAwUC8Zg0HAglA9IZPGQABoTSqJCFTIOEIsFgHBcEhhHUpKJFCwaGxYYHB0VEx4IEh8gIQwiIyQbJRMcHokmEicfDygAkCkqJQgIGG0rLElCLS4vMCWqQwMCQg0UMTIzNDVLQjaIGDE3ODQlS785CEkxKjowvEOHybG4O6JDCdNKuDUxRAmxRDHeveUAfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appuser16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/MTCxISChMT+/ATCxASChFxaXAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMg5gw00yyDGIAR1YUDggeFWFIZhnSBZrsZxdIOFEGTA2oeBAHeyuGwvzxBlYdUOLROMFzDQntJPrNoqAKUBaqnV+k57ZORruykHDj2LqIzUVKp1u0iuB/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+appusers16:app app16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxISChAT+BMRaBPyqXARCBPz+/FxaXAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARLEIRJa5Ui673nsGAgeKE1Bl9AUEXbiqTlFlZaGUZoszm4BzhDAVf5BYbAXI+TAR6CS2ZGSZSEiIIqYIsSIEaJ7GRrlY7J1lKA7I8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+appwp16:app app16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBKSinJyOfPz27Pzy7AwKDExOTJyWlERCRKSelPz69LyyrKymnPz+/MS2fDQyJAQCBOTazLSiXOzivMS2jKSSVOzmxPz25NzSpPTu5KyebOzixNTGjOTWpMSydMSybCwqFGReVKyaXNzSnGxeNJSCVMS2nPz23MSuZIR+bJyShLyqnOTOtGxiXIR6XOTSvIx6RMSubIyCdKSalMS6pOTWxMzKvKSabJyKTOzezHxuPGRmZKyurMTCvPTq3AAAACH5BAEAAAAALAAAAAAQABAAAAajQIBwCAgIiEhiYEA4FgwHRDKhIBAWz4OhgGQ0FAPHA7qFEBONb0Qy0ULeQ2+aUrFcMI+3GYBOZzQbHB0eHyAhIQByDREiEwMjFRIkJQImAgJ+jScjHigkKSorLC0AKg2NFSMoki4qCy+IQgITKDAxkjIzNDWkQxQoJaskMgk2Eb1DNzgoOCoHDDY5yEIwJToAOzw9ET7TQiREAhkZ3kmy5QB+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+cal1day16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANOCLrMEUDIOUS9AFLLhx8LIRZjKYZmMRCkaChFLHty/AIiS3y6q+QtT49wq8VotRtQJGwRf6Zmrlj7DJLQXsupTJmeEIN4TB5nII20wp8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+cal5days16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANMCLrMEUDIOUS9AFLLhx8LIRZjKYbj55GioRRwoQ5x4QIiIdMmcec7jy53q81qP9OO5VMAj8RXTFWzOZW95HDLdEEM4LA4nIE0zgp/AgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+cal7days16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANPCLrMEUDIOUS9AFLLhx8LIRZjKYbj55GioRRwoQ5x4QIiwcp0fucsj873qvGMv5Jw2FIACUsW4WakGW1O046I05qmGYBhTC6TM5CGWuFPAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+calappointment16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBAQC/AQCjPz+/MTCxPz+BISCBISChKSipAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARbEMhJaQhA6D1E/wDGeeRgDhOhFoTBEi+REgdrIHScSEVvAD9Xr7cDqGSGpFEnQSqTv2NxCFQOiU1VEAiTZmstHFg1vQKuw+LxxfYaV/AuOQRI2O/4ewhT6Uv8EQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+calbell16:cal cal16 16:photo:16 16:R0lGODlhDwAOAIIAAPwCBISCBPz+BIQCBMTCxISChPz+/AQCBCH5BAEAAAAALAAAAAAPAA4AAAM+CLrR+zCIAWsgLVRGRBhOVQiG94WPVAbHaZHYAWqRYLbge88RsbInGuBCEhRYrZYm4xk4nYdoKzKIbiKHawIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+callist16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBAQC/AQCjPz+/KSipPzerMRaBEQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARDEMhJaQhA6D1E/wDGeeRgDhOhruyatjBRSIRxxOsMEAdC0BUZDcfSEYvDo3Bn++2Cxt7RqFxWhZiCdsvdhjCVsMQfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+calmonth16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBAQC/AQCjPz+/MTCxKSipAAAACH5BAEAAAEALAAAAAAQABAAAANSCLrMEUDIOUS9AFLLhx8LIRZjKYbiRxLFIBpK0Q6z7MkwkJIe8b0KEeuWchFysuStVsjtfMbeMQitWpG25YfmNK1WU53XNIUYzug0OgNpuBX+BAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+caltoday16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBPwCBAQC/AQCjPz+/MTCxKSipPyCBMRaBPyqXAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARTEMhJaQhA6D1E/wDGeeRgDhOhFmurpi5LyIQhFfiBIAfuFzaAioBIJBCummRYPCaDPh3vhwsOZdihNfa8Ub/AJXemFZPPNBvGwG672yFMZS7xRwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+caltodo16:cal cal16 16:photo:16 16:R0lGODlhEAAQAIMAAAQCBAT+BAQC/AQCjPz+/MTCxPzCxKSipPwCBMQCBIQCBAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAARaEMhJaQhA6D1E/wDGeeRgDhOhFmurpi5LyMYhFXiuFwZiA6qZYbbqJX5BIw2RAPxwAAWCyWMCCsiXFGEEErKz6LQZfOqiTR1YJiGq1rFyyHmo2+/1EKbCl/gjACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+connecting16:connect connect16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBPz+BMTCBISCBAQCBPz+/MTCxMTGxISChFxaXMzGzKSipAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMhJZbihUiz60FPnfaA0iBpBVGdHEYWxToEoSHBRHHM9AgSEQRcj+AYkYAJxIPKQFUJiOdTJQFIDU6dYzKKFhTCM+E5g4mXaDAyrlogEG+DGTecA7wsP8EcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+connectno16:connect connect16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBPz+BMTCBAQCBERCBPz+/MTCxMTGxISChFxaXMzGzKSipAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARPEMhJq704axBEHoPUEdhQGMNYFuwxkKInDYjBniEnwMCQIIebSzXx/WwsFK+YMABZikWuYlrUCtZpEYv4WRPaHhb064YB41kCfJFSQBh/BAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+connectyes16:connect connect16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/KSipDQyNMTCxMTGxISChFxaXMzGzAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARaEMhJZxCjgsAtDtUlCOA1gJQ4kl/IDatAoF7xxkS6GgEBr6jAobCyBX42SQBxMOx6A8MhiGASR8YDgrYsNEeJ0zaEGZY7uoH2oB6nOUwtbdLaVOeTUwo/8UcAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+devcdmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tOzOvNTqvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/LzKvMTCxDQyNASCBARCBDTSJIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAa0QIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTBqUiuUCVmAeiYzmsKlwOt/AAKFIFAIIFx4WHyAhUwIDIgsZFyMkFxchJSYmiBkSBBoIJJwIGgOhiCYFJSEnFyQjFwNZewABISAfFiYnCAEmCREIrwAIFhwVGwcaBAkPGApsQsAVFA0GBQMRbxBTKM0ODQwTEq192ClDgROkBHvYKuNJUu5CKCorX1RDKCkpUn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+devcdunmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXISChNTS1MzKzMTGxMy+vNSytAQCBOzq7OTi5Nza3Oy6vPy2tOTStPz6/Ozu7Nze3MTKxOS2tNzmvLT2tDw+BPTy9MzOzLS2tPy+tLz+tLz2tLSynLzqvLzavLTOtNTW1KSipPz+/MTCxLy6vDQyNOTm5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAapQIBQGBAYA8Ok0DggFAwHBEIJECQUi8GT0XBMh9YHJDKQTLqUigWsuDwSmMxBQ9lwvoEBQpEoBBAWHRseHyBTAgMhCxgWIiMWFiASJCSHEgQSGQgjmwglGKCHBQUSICYWIyIWAwshIVMBIB8eFSQmCAEFCREIekIIFRsUGgcZEgkPFydrvxUUDg0GBSEREGJfv9AMEySsJxDYQ4DcEhh64UpS6lTs7QB+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+devdiskmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBDQyNIRuVKyCXMSKROzSrOzKpOTGnLSafLySZKxuLMSOVPTWvPzixLSehNyibOzOrGxaVJx+XOzGnFw2FJRuPKx+TPTSrHRWPKyKZPTOpHxOJKyKXFw+HKSipISChMTCxFxaXIRiPNSWXExOTOS2hLR+PLRyLPTWtMyOTASCBARCBPz+/DTSJIyKjIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaTQIBwCAgYA8SkMCAYDARI5ZJQMBwQiWgyoFgwrA3HQ7scQAqFAcEQOUi0zAkFUSFYLghMBloUCDQNGxwdHhwHekcfICEhICIfIxkLJBABJUYCICABIhAOBiYnKJaXmH4CGSkYCCqkSAEfTKenrkOwsrQll0IrS7G5uwArLLaxLbXCLsTFLyDBKy4wZEVHvCwsRn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+devdiskunmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBDQyNIRuVKyCXMSKRPTWtOzKpOTGnLSafLySZKxuLMSOVOzOrPzm1LSehNyibGxaVJx+XOzGnFw2FJRuPKx+TPTSrHRWPKyKZPTWvHxOJKyKXFw+HPTOpKSipISChMTCxFxaXIRiPHxaNLRyLNSWXExOTPzixOS2hLR+PMyOTPz+/IyKjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaIQIBwCAgYA8SkMCAYDARI5ZJQMBwQiWgyoFgwGgiD46FdDiCFwoDQAEe0TMkEQSFULIcLBloUCDIaDRscHRsNHhhHHyAhISAiHyMkJSYQASdGAiAgASIQKA0pKguXmJl+AiQGFwgrpUgBH0yoqK9DsbO1J5hbsrq8SrgstlJFHy0gwMVFR1J+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+devfloppymount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBMTCxARmZPz+/FSWlLSytKSipERCRIyOjISChOTm5HRydNza3GRiZFRSVASCBARCBDTSJIT+bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVrICCOQBCQKBkIw5mqLFG47zoQ+FwbN57TosDhgPD5dMEEIqE04kwlBWKBUEiNVYFpyqAyGEUCgqEtERiNNMLhQKzLQYJg7n7Y4aMAwbCUPvAQeWNgfzQQETAIhSMQEogwgBITQEGGEREmfiEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+devfloppyunmount16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBMTCxARmZPz+/FSWlLSytKSipERCRIyOjISChOTm5HRydNza3GRiZFRSVCH5BAEAAAAALAAAAAAQABAAAARcEMgJQqCYBjFu1hxReN82EOhYGieaklJwHIjrqnGCJLqNWhUFYoFQCG1FgWXIIDIYNQKCoawQGI0swuFAbKsxgmDsfZjBkwDBsNM90Jot9A3DbBD0Dwiur9QnfhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+devnetwork16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBAQCBISChPz+/Nza3ARaZESanCyKlARudARGTLy+vNzq7ARmbMTCxARufAROVMzOzKSipARyfOzq7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVmICAGZFmKQiACweCSBImq41AYB5IodLq2hwWO0ejRWDac48Gb/QKNqNRoqspmrVcAUuIJBANS8sBIFCORUgooPEh4J8B67NgdsVBp9C5XWfl9LRMTCyReX19hARNojWlWLH+AAH4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+devpc16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBISChHx+fPz+/AQCBAQC/AT+/AQCxAQChAT+BLy+vAR+BAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARYEIAgqK1YzsG754QUDERpmkEpkkXrtoK6EcVgHIibhnNx564Yb0TDvQq7FQ34EiqPOhnREqhWSUPsyZSQAbbg7GcMEgwUiYVivTa1R+y4XEGoWO/4AMAfAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+devscanner16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBAQCBPz+/MT+/ASChARCRATCxMTCxFxaXKSipDQyNAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARTEMgJgqWBVivEldkUdKSXhVjZfenommglDERh3Tc4E4ZRHAGgkEPr9X6H5AHBERSMRyWzkug8jQXFEhWoOo8dRYxqLXSmGjIJnVaz29Q3fAP3RwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+devscreen16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXFRSVPz+/PT29OTm5OTi5DQyNDw+PERGRExKTHx+fISChIyKjHRydFxeXDQ2NCQmJBQSFAQCBERCRMTGxHR2dGRiZExOTDw6PCQiJAwODCwuLFRWVOzu7BweHAwKDCwqLHx6fBQWFGxqbGRmZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAanQIBwSCwKAwKkMslEAgSDqDRKqBYKhkNgcDggEorkMrDQchkNhuOhgEQkk0l5S2lUGpYLJqPZTAwMHB0DCmhqAW0Rfh5zAxgOkBcCFAcfIBMECxwBBAEPFw8dChkhcBMDDAcdnQqtFKSWcQMimx4dGRkQBxGxsg6bBQEawx8jl3GnJFoFHRNXVVNRJYIFDAsL1tgiDiQXFx0HABwcXeQH5OjkRutEfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+devspeaker16:dev dev16 16:photo:16 16:R0lGODlhEAAQAIMAAPwCBFxaXAT+/DQyNATCxMTCxPz+/AQCBKSipASChAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAARWEMgJQqCXziDG2JoUEENhZBkmHIWJVptAmqcIW/Js1MiF56TBzkckAAcHoa9nMRKeA4TyJk0knsHhTeK5khBaH2VwLYVh40TJhQ6RzeIQV32Quz8hfwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editcopy16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIUAAFxaXPwCBNze3GxubERCRPz+/Pz29Pzy5OTe3LS2tAQCBPTq3PTizLyulKyqrOzexLymhLy+vPTy9OzWvLyifMTCxHRydOzSrLyihPz6/OTKpLyabOzu7OTm5MS2nMSqjKSipDQyNJyenLSytOTi5NTS1JyanNTW1JSWlLy6vKyurAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAAaUQIBwCAgYj0eAYLkcEJBIZWFaGBie0ICUOnBiowKq4YBIKIbJcGG8YDQUDoHTKGU/HhBFpHrVIiQHbQ8TFAoVBRZeSoEIgxcYhhkSAmZKghcXGht6EhwdDmcRHh4NHxgbmwkcCwIgZwqwsbAhCR0CCiIKWQAOCQkjJAolJrpQShK2wicoxVEJKSMqDiAizLuysiF+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editcut16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIEAAPwCBAQCBPz+/ISChCH5BAEAAAAALAAAAAAQABAAAAIwhI9pwaHrGFRBNDdPlYB3bWHQ1YXPtYln+iCpmqCDp6El7Ylsp6ssR1uYSKuW0V8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+editdelete16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbPT29GxubMzOzDQyNIyKjHRydERCROTi3IyKhPz29Ox6bPzCxPzy7PTm3NS6rIQCBMxCNPTq3PTi1PTezMyynPTm1PTaxOzWvMyulOzGrMymhPTq5OzOtNTKxNTOzNTCtNS+rMSehAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaKQAAgQCwahcihYMkcBAiBpLJApRoOBWgyIKhSEQkFgrBAcr1URiPhKAsDD3QB8RhA3FM0IlLHnyUTVBMSFBUWfl0XGBMTGBcZGodmcQWKjpAbHIgIBY2LHRoempOdjooTGx8giIOPFYofISJ+DyMXI6AfFySyfiUmJSUnKBYcICIpfgELzM3OZX5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+edit16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBFxaVMR+RPzKjNze3AQCBMR6RPzGjPyODPz+/MzOzPyKDPyKBPz29OTWzPyGDPyGBOx6BOza1OR2BKROBNSOXKRKBBwOBOzu7PTWxPzizOySZPyCDFxaXOy2lNRyRMxmJCQOBPTm1OzStPTKrMR+XIRWLFxGNCQSBDQyNIRSNDQuJERGRLyqlNzSvIx6ZKRuVEw6LLSyrLymhKSShBwaFFROTJyWjMS+vNzW1OTazNzKrHRqXOzezOTOpPTq3OzWvOTStLyedMS+rLy2pMSynMSulAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAewgAAAAYSFhoQCA4IBBI2OjgUGBwiLBAmXlpcKkgsMlZcJBA0JDpIPEBGVjwkSBgOnExSfmBIVBxAMExYXswkYGRobHLq8gh2PHhoeHyAWIYKzIiMkJSYnKCnQg5YNHtQqKywtK9qMBC4vMDEBMjIz2dCMDTQ1Njc4OToz5PEEOzw3ZPToMcLHO23HfogQ0QMIkCA+hPBbhAPHECJFjMyYIUQIvEUpUqwQOXKkSEF+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editpaste16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQiFHRqNIx+LFxSBDw6PKSaRPz+/NTOjKyiZDw+POTe3AQCBIR2HPT23Ly2dIR2FMTCxLS2tCQmJKSipExGLHx+fHR2dJyenJyanJSSlERCRGRmZNTW1ERGRNze3GxubBweHMzOzJSWlIyOjHRydPz29MzKzIyKjPTq3Ly2rLy+vISGhPzy5LymhISChPTizOzWvKyurPTexOzSrDQyNHx6fCwuLGxqbOzKpMSabAQGBMS2nLyulMSidAAAACH5BAEAAAAALAAAAAAQABAAAAa7QIBQGBAMCMMkoMAsGA6IBKFZECoWDEbDgXgYIIRIRDJZMigUMKHCrlgul7KCgcloNJu8fsMpFzoZgRoeHx0fHwsgGyEACiIjIxokhAeVByUmG0snkpIbC5YHF4obBREkJCgon5YmKQsqDAUrqiwsrAcmLSkpLrISLC/CrCYOKTAxvgUywhYvGx+6xzM0vjUSNhdvn7zIMdUMNxw4IByKH8fINDk6DABZWTsbYzw9Li4+7UoAHvD+4X6CAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editshred16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbGxubMzOzPz69DQyNIyKjERCRPz29PT29OTi3IyKhPz27PTu5PTy5Pz6/Pzy7PTq3OzexLyqlPTm1PTizOzavLyqjOzWvOzaxLyifOzizOTOpAQCBOzezAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaEQAAgQCwahcihYMkcBAiBpLJApRoOBWgyIKhWEQkFYYHkeqkMxKFBFpq9jgdkEGlPqwrJhCIY2N8FFRYUFxcYGX9dgRKEGhiHiYEOhBcbGBwdiQEOARcBGwEeAZllAgEUnQEfoQEgmp4hrCKtrwEYsrRlTiMBJAG8syN/IyMAxMXHSH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+edittrash16:edit edit16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBAQCBKSipFxaXPz+/MTCxISChDQyNCH5BAEAAAAALAAAAAAQABAAAANQCKrRsZA5EYZ7K5BdugkdlQVCsRHdoGLMRwqw8UWvIKvGwTICQdmGgY7W+92GEJKPdNwBlMYgMlNkSp3QgOxKXAKFWE0UHHlObI3yyFH2JwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+fileclose16:file file16 16:photo:16 16:R0lGODlhEAAQAIQAAPwCBCQiJBwaHAQCBDQyNDw6PFxaXFRSVERGRCwqLAwODGRiZHx6fPz+/GxqbAwKDCQmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAVaICCOZGmeqBgEwjCkRGEcSKK4JrEcBrMgAdeLVDg0GguGsYEbBQyGYyN6FDoPDIf0+LCKBIgetQERDgGDBGIpNY8GioAU0m6KXFw883w3+/l9f4AkfimGIn4hACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+filedocument16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJSWjPz+/Ozq7GxqbJyanPT29HRydMzOzDQyNIyKjERCROTi3Pz69PTy7Pzy7PTu5Ozm3LyqlJyWlJSSjJSOhOzi1LyulPz27PTq3PTm1OzezLyqjIyKhJSKfOzaxPz29OzizLyidIyGdIyCdOTOpLymhOzavOTStMTCtMS+rMS6pMSynMSulLyedAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaQQIAQECgajcNkQMBkDgKEQFK4LFgLhkMBIVUKroWEYlEgMLxbBKLQUBwc52HgAQ4LBo049atWQyIPA3pEdFcQEhMUFYNVagQWFxgZGoxfYRsTHB0eH5UJCJAYICEinUoPIxIcHCQkIiIllQYEGCEhJicoKYwPmiQeKisrKLFKLCwtLi8wHyUlMYwM0tPUDH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+filefind16:file file16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBCQmJDw+PBQSFAQCBMza3NTm5MTW1HyChOT29Ozq7MTq7Kze5Kzm7Oz6/NTy9Iza5GzGzKzS1Nzy9Nz29Kzq9HTGzHTK1Lza3AwKDLzu9JTi7HTW5GTCzITO1Mzq7Hza5FTK1ESyvHzKzKzW3DQyNDyqtDw6PIzW5HzGzAT+/Dw+RKyurNTOzMTGxMS+tJSGdATCxHRydLSqpLymnLSijBweHERCRNze3Pz69PTy9Oze1OTSxOTGrMSqlLy+vPTu5OzSvMymjNTGvNS+tMy2pMyunMSefAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe4gACCAAECA4OIiAIEBQYHBAKJgwIICQoLDA0IkZIECQ4PCxARCwSSAxITFA8VEBYXGBmJAQYLGhUbHB0eH7KIGRIMEBAgISIjJKaIJQQLFxERIialkieUGigpKRoIBCqJKyyLBwvJAioEyoICLS4v6QQwMQQyLuqLli8zNDU2BCf1lN3AkUPHDh49fAQAAEnGD1MCCALZEaSHkIUMBQS8wWMIkSJGhBzBmFEGgRsBUqpMiSgdAD+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+filenew16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFxaXNze3Ly2rJyanPz+/Ozq7GxqbPz6/GxubNTKxDQyNIyKhHRydERCROTi3PT29Pz29Pzy7PTq3My2pPzu5PTi1NS+rPTq5PTezMyynPTm1Pz69OzWvMyqjPTu5PTm3OzOtOzGrMSehNTCtNS+tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ/QAAgQCwWhUhhQMBkDgKEQFIpKFgLhgMiOl1eC4iEYrtIer+MxsFRRgYe3wLkMWC0qXE5/T6sfiMSExR8Z1YRFRMWF4RwYIcYFhkahH6AGBuRk2YCCBwSFZgdHR6UgB8gkR0hpJsSGCAZoiEiI4QKtyQlFBQeHrVmC8HCw21+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fileopen16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBOSmZPzSnPzChPzGhPyuZEwyHExOTFROTFxaVFRSTMSGTPT29Ozu7Nze3NTS1MzKzMTGxLy6vLS2tLSytDQyNOTm5OTi5Ly+vKyqrKSmpIyOjLR+RNTW1MzOzJyenGxqZBweHKSinJSWlExKTMTCxKyurGxubBQSFAwKDJyanERCRERGRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaRQIBwGCgGhkhkEWA8HpNPojFJFU6ryitTiw0IBgRBkxsYFAiGtDodDZwPCERCEV8sEk0CI9FoOB4BEBESExQVFgEEBw8PFxcYEBIZGhscCEwdCxAPGA8eHxkUGyAhIkwHEREQqxEZExUjJCVWCBAZJhEmGRUnoygpQioZGxsnxsQrHByzQiJxz3EsLSwWpkJ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fileprint16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBFRKNAQCBPz+/MTCxExKLPTq5Pz29Pz6/OzezPT29PTu7PTy7NzClOzm1PTu5LSabJyanPTm3FxaXOzCjOTKrOzi1OzaxOTSvJyenGRmZLyyTKSipDQyNERCROTi5Hx+fMzKzJSSlIyOjISChLS2tAT+BDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaYQIBwKAwIBMTkMDAYEApIpVBgOCAOg4RRGlAoEAuGIdGITgWOq4LxcCQgZkEkIHksHgYJOR6ZQCgVFhYJFxgTBVMZihoCfxUYDWUbUBGKGREcjBoQEB2TAB4CAx+Vl5WMhyACHiEhH6IfIiMktCQgE0cZJQStr6O2t6EARxO6vK6iEx4dZsMCxbsmBB4nzUTEutVSSUdmfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filesave16:file file16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBFRSVMTCxKyurPz+/JSWlFRWVJyenKSipJSSlOzu7ISChISGhIyOjHR2dJyanIyKjHx6fMzOzGRiZAQGBFxeXGRmZHRydGxqbAwODOTm5ExOTERGRExKTHx+fGxubNza3Dw+PDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaAQIAQECgOj0jBgFAoBpBHpaFAbRqRh0F1a30ClAhuNZHwZhViqgFhJizSjIZXQCAoHOKHYw5xRBiAElQTFAoVQgINFBYXGBkZFxYHGRqIDBQbmRwdHgKeH2YgHpmkIR0HAhFeTqSZIhwCFIdIrBsjAgcPXlBERZ4Gu7xCRZVDfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+folder16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBwWHMzKzOzq7ERCRExGTCwqLARqnAQ+ZHR2dKyqrNTOzHx2fCQiJMTi9NTu9HzC3AxmnAQ+XPTm7Dy67DymzITC3IzG5AxypHRydKymrMzOzOzu7BweHByy9AyGtFyy1IzG3NTu/ARupFRSVByazBR6rAyGvFyuzJTK3MTm9BR+tAxWhHS61MTi7Pz+/IymvCxulBRelAx2rHS63Pz6/PTy9PTu9Nza3ISitBRupFSixNTS1CxqnDQyNMzGzOTi5MTCxMTGxGxubGxqbLy2vLSutGRiZLy6vLSytKyurDQuNFxaXKSipDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAECg4eIAAMEBQYHCImDBgkKCwwNBQIBBw4Bhw8QERITFJYEFQUFnoIPFhcYoRkaFBscHR4Ggh8gIRciEiMQJBkltCa6JyUoKSkXKhIrLCQYuQAPLS4TEyUhKb0qLzDVAjEFMjMuNBMoNcw21QY3ODkFOjs82RM1PfDzFRU3fOggcM7Fj2pAgggRokOHDx9DhhAZUqQaISBGhjwMEvEIkiIHEgUAkgSJkiNLmFSMJChAEydPGBSBwvJQgAc0/QQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folderhtml16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBERGRBQWFMzKzOzq7CwqLDw6NARqnAQ+XHR2dKyqrOTm5ExKTERCRHRydMTi7NTu9HS+1KSmpBweHDy67DyixHS61ITG3AxypByu7DxinBw+ZERmdIySjITC3ARypExOTDRurIR2RPTSdJyulEyGvBw+bFSyzJTK3LzKvPzivOTixNTChLSybGyCfCRSnBQqRASGtFyuzDw+PCRShPzy5OzerOTShKyaTEx6pCxerGRufBR+rOTezPTShNy6bER+1BxCfBQuRAxelFSixBw2VISq3GySrPTWlHyanIyitFSO3IymtCRujAxWhCRqlCQ6XGyWvNS2bFyGvDxuvCRSpLy+vMS+vGxqbFyO1GSi3EyO1FRaVCQuPLS2tDxyzKyWNFxaNCQyPGxubCxajERSVExKNJyenAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfZgACCAAECg4eIAAMEBQICBomDBwgJCgsEDA0BDg8BhwYQERKUDxOYDAyeghQVFhehGBmVlwwOqxobHB0eH6EfIAkPIYIiIyQlJhsnKBcpvrYiKissLS4vMDEyFjOvNAA1LDY3ODk6Oyc8PTIyFzQ1Jj42P0A6QTtCQ0REIEUORkdIkihZwsSekBhNnDyBciCKiSNSplDRUcWKkRhXCGDJYgiGli1cpuTocsILjytfFmRpACAGRTBhRogZgzHlAjKGWnIoY+bMgRgBDHRBo/LAIZoxuhwKatRPIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+folderlocked16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQSFMzKzOTm5CwuLERCRARqnAQ+XHR2dKSmpOzm5GxqbCQiJMTi7NTu9HS+1HRydOTm1Ozq7Dy67DyixHS61ITC3AxypERGRBweHByu7ASGtFyy1DSOtDRmfExOTBSazBR+rCwqLAxWhAxelByGtDSaxAwODHy+1Dw+PPT29IyqvCxujOzu7NTW1Nza3ExGJJyebKyqfMTCpFRSPOTi5DQqHOTezDw2NMTGxKyqhMTGrGxmXDQ2NMTCxMTGpHx6bHx2bBQWFIyOXDQuDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfDgACCAAECg4eIAAMEBQICBomDBwgJCgsEDAKFDQGHDg8QEZQSlxMUDJ2CDhUWF6AYGZWXFBqCGxwdFh4XGK8fIAohtiIIIx25EZwBDREHgiQjJSYmGScoKSoRKQ8rggIsDC0uJS4oGygoAyjdAAcsLxQUMDEyMzQ1EzapBy8MDDc36tFwgONFjlQ6dgCEEZBHDx8+ctRIRehHAyAwZASZIGRIEBoUBwUwIGMCiwFEaBQJichIjo9FZLBsacRIAB0A/AQCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+foldernew16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAQCBPz+hPz+BOSmZPzSnPzChFxaXMTCBPyuZPz+xPzGhEwyHExOTPz+/MSGTFROTPT29OTm5KyurDQyNNza3Ozq5Nze3LR+RLy+vJyenMzKzNTS1Ly6vJSWlFRSTMzOzMTGxLS2tKSmpGxubBQSFAwKDKSinJyanIyOjCQiJERCRERGRBweHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaNQIBwSCwaj8ikcokMCIqBaEDoBAQG1meAUDAQpIcBQoy1dg2JdBqhECgQ1IWB0WgcBIOBwIHXBwwPEBEREhIBbG4IExR/DBUVFhIXV2NjDVYYDY8SFU4ZVxpVAQwbGxynGxkdTh6XVh8gGSGzGSITIxokJUImGSMTwLcnKCkprgAqDSt1zCssKxQtQ35BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+folderopen16:folder folder16 16:photo:16 16:R0lGODlhEAAQAIYAAPwCBAQCBExKTBQWFOzi1Ozq7ERCRCwqLPz+/PT29Ozu7OTm5FRSVHRydIR+fISCfMTCvAQ6XARqnJSKfIx6XPz6/MzKxJTa9Mzq9JzO5PTy7OzizJSOhIyCdOTi5Dy65FTC7HS2zMzm7OTSvNTCnIRyVNza3Dw+PASq5BSGrFyqzMyyjMzOzAR+zBRejBxqnBx+rHRmTPTy9IyqvDRylFxaXNze3DRujAQ2VLSyrDQ2NNTW1NTS1AQ6VJyenGxqbMTGxLy6vGRiZKyurKyqrKSmpDw6PDw6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAfCgACCAAECg4eIAAMEBQYCB4mHAQgJCgsLDAEGDQGIkw4PBQkJBYwQnRESEREIoRMUE6IVChYGERcYGaoRGhsbHBQdHgu2HyAhGSK6qxsjJCUmJwARKCkpKsjKqislLNIRLS4vLykw2MkRMRAGhDIJMzTiLzDXETUQ0gAGCgU2HjM35N3AkYMdAB0EbCjcwcPCDBguevjIR0jHDwgWLACBECRIBB8GJekQMiRIjhxEIlBMFOBADR9FIhiJ5OnAEQB+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailforward16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRydHxubHxmZGxiXHRmZFxOTFxGPFxKTPwCBLymlMy+pOze3PTq3PTu5Pzy7LSmnOTaxOzm5LyqlNzOtPz69Pz27MzCtLyqrPT27IRubPzuzNTGvNTCxLSelPz25Bw+ZFxKPPzy1Pz65LyupBxKdCxWfPTm1Pz23LyinBxGbGzO5DRafBxWfBxajCymxHTS5BxSdBxKbFTK3EzG1CSGvCyKvCSSxCSavGTO5GRaVPzqzFzK5EzG3BSCtAwiPGxaVPTivPzy3NzKpBxObCRefBxqlPTmzJR2bKyahAwyRPzmvOTOpKyObNS+nPz21AQOFKyOfPzuxAQCBGRORLSadPzyzLymjMy2lOzetDwuJFRCPEw6NEQ6LEQyLEQ6NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAAAQABAAAAfhgAABAgIDBAQFBgcIBwmOCQIKCwwNDg8OEBESjY8CDBMUFRYVFxgZDJyOGhsPChwVHR4fFSAhjwkaIiMOJBQQDRUVJSa3GicoHw4pEA8SGSorLI8tLtQu19gqLzDECTEyMzQ14zY1Njc3ODkqCTo7MjIxNCs5PD03PjctPwlAQUIihhBpQbCIihtG+CUocASFkAhIkogQ8kFJwkcFlogIkoRJEydPnkBR6GiAxiQLgiiIIkXElFQJqESoMsRKkAhXqkhhApNKFSxZggTJ4nHIEJhaDhzYwoVLFy1avHyB6ScQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mailget16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAxKdBRSfCyGvFSm1BxKfCSWzCyWzBRCXCRKfBwuRAQGDDw6PHy23Cym1CSSxByCxBxunBQSFKyurMTCxExihNza3NTW1JSSlMzKzFxaXLS2tNze3KSipCQmJGxmbNTS1KSepLy2vISGhJSWlHx+fERGRPz6/IyKjDw+POzq7JyenMzOzKSmpCwuLDQyNIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaeQIBwGBAIAsOkUjAgFJRQQMHgjC4PBIEVgAh4D4aEYrGAMhINxwPyiCgYSsmEUmk82grLRZJkYCgXaAEKFxYZcEISGhsZFxwFeY0WHR5CDB8dGCAXG5shGxQicBIMpSMUGxgTGSQlpQwSJicnEwwdI7gdKAwTsykpKiobr8QMKxeHDBcsGRvOzxsT0i0uL9HSHdkT2ZkoMJXF4a8AfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mail16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBGxaVOTe1Oze3OTWxOTWvNzStNzKpEQ6LOTezPz+/Pzy7Pz69Pz27Pz25Pz21PzuzPzuxEQyLLyinLSmnPz67Pz23LSafKyObDwuJMzCtLSelPzy1My6nLymjNTCxLyqnPzq1LyihKyOfOzavOzetEQ6NPTq3NzOtLymnNTGxJR2bOTOpPTivNTGvLymlKSShKyahEw+NOTe3PTm1Pzu1Pzy3FRCPPz65LSadFxGPOzm3PzqzPTmzPzmvEw6NCH5BAEAAAAALAAAAAAQABAAAAaqQIBwSCwaj8ikMhloOp/QpmAgqAoIhELBUDgcEIGEYrFgNBoLx+IBiRwkgQnFoWAwKhWLhX3BZAILGhsCDXgODhwdGB5vgAofICBlDiEiIx4kJSYBJ2UoEykqHSMrLC0nLWAnFS4UCycvMAcEMR0RLTIBMwaSahw0NTYtFwclNwEdLws4eoc2DxwQOR06ASk7PBAhIRE9Pj0tLSUY1T8I5gjn6Qgy7D8SfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailreplyall16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRubHxubHxqbHxmZGxeXHRmZGROTFRCPFxKTFxGPPwCBLymlMy6pOTa1PTq3PTu5Pz27Dw+POzi3PTm1OTWvPz25FRSVERCRLympPzuzPTu7NTGvFxaXKSmpPzu1Pz65Hx6fHxqZPzq1Pz23HR2dBw+ZHx+fISChJSWlDQmJHRydCxWfBxGbJyenExKTHRiXPzqzPzy3CQmJDRafGTO5ExOTERKTGxWVCRSfHTS5CymxBxajBxWfPTmvPzy1CyixCSaxCySxDSaxDSWxDSSvDyaxGS21PTmzPz21AwiPBRejCSavByGtCSezEzG3FzK5FzG3GzO5FTK3CQ2bPTixBxqlCRefBxSdBxSfBx2nCQ+dHxmXPzmvLSafAwmRAwyRPzyzDw6POzavNzKpAQOFPzuxBwWTBw2ZGRORLyWdMy2lOzetPTivAQCBKyObOTOpAweNBwWVEQyLEw2LEQ2LDwuJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAQABAAAAf4gAABAgMEBQUGBwgJCguOCwEMDQ4PEBESDA4TjY8DFAwVERYXGBkRm4+QGhsMHB0eGB8bDpyOARogEBceIRgXv8COIiMkGB4lJSYnIcwoKb/DGyoXKywtKS4pHinMLzAxJDIzNDUtNjcv6B0hLzgfMh85OjstPDw99zwd7T4/LTVAgggZQqSIECNHevSAgSSJkiVMmjh5AiWKlClAiFARUeVHFSVWmLS40gNLlh5agGzh0kWDlwZfrIDREKaCAjEqrFA5MMYLmTAxlJTxYoZMozNozqRRs4ZNmy5s3LwhA0dBnDNn5MxBoAABnTp17IitowDrmQV+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailreply16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRubHxubHxqbHxmZGxeXHRmZGROTEw+NFxKTFxGPPwCBLymnMy6pOTa1PTm1Pzy7LymlOzi3HxqZOTWvPz69Pz25My+tLympFRGRHxuZPzu1LymjNTGvNTCxBw+ZPz23PzuzPz65PTu5NzOtCxWfBxKbPzq1DRafGTO5BxGbPzy9HTS5CymxBxajHRiXPzqzCyixCSaxCySxDSaxDSSvGS21GxWVAwmRBRejCSavByGtCSezEzG3FzK5FzG3CQ2bPzuxAwiPBxqlBxKdCRefBxWfBxSdBxSfBx2nCQ+dPzy1CRqlAwyRDQmJPTmvPTixLSafOTOpAQOFPz21BwWTBw2ZPzmvNS6nPTivAQCBAweNBwWVNzKpPzyzLyihGRORLyWdMy2lOzetKyObEQyLEw6NEw2LDwuJEQ2LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAQABAAAAfqgAABAgMEBQUGBwgJCguOCwEMDQ4PEJYRDhKNjxMPDBQVFhAXGBUSGY8LGhsQHB0VHh8gFQ6bjgEhIiMMJCUmFbS2CwMnG6IoKSorI7WpEycWFiUsLSou1yXXji8wFiopMTIzNDUz4zbZNxsbODk6Ozw9Pj8pPzEzQDdB60JDOkRFjBw5giRJDCWdlmxwIIRJExAWKDRyMgTIiydLoESRImQKlSUSF1SxUoXAlSBRsGSJoCVICIlbqlThcoBClC5eYFD4EiVIFwUyqywAE0ZMlqNjpJDpIkUBl0dlFChAYOZMmTJoyqQR5icQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mailsend16:mail mail16 16:photo:16 16:R0lGODlhEAAQAIYAAIx+fIRubHxubHxqbHxmZGxeXHRmZGROTFRCPFxKTFxGPPwCBHxqZLyqlMy6pOze3PTq3PTu5Pz27Pzy7LyinOTaxOzi3Ozq3LymlOTOtPz69Pzy5My+tLympPzqzNTGvLSelPzy3BxGbBQ6VPzuzPz65LyupNzOtPz+/GzO5BRejPzq1Pz23LymjHTS5CyixCSavBxqlPz25LymnGTO5CymxCSaxByGtHRiXPzy1CySxCSezGxWVPzuxKyOhMy6nDSaxEzG3PTivNzKpKyOfPzu1FzK5PTmzJR2ZLyihLSWfKyObOzmzPzmvDyaxOzavLSafGRORMy2lOzetDwuJEw6NEw2LEQyLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAQABAAAAfUgAABAgMEBQUGBwgJCguOCwwNDg8QERITFBUWjY8DFxgZGhsaHB0aD5yODB4TGB+kICEaIiOPCwEkJRcmJyYPKCIpKrWqKywTmC0SIi4vMDHEDCsyMg8zEyI0NTY3z7U4Hhs5Mx+0IyI6OyPrIzw9Gys+PxIy2EBBxAs8Qjk5Q0RFWFxAZySfgSMsilRAkiRECHQ08hHgJ0TJkCU/mECU2ISEkowUlpAQ4QTfowNPoAzJIeRJCyjm8kVRIkWIzSkXhwxJtYAKgp9VrFi5QoWKFZ5+AgEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav1downarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIYhI+py+0PUZi0zmTtypflV0VdRJbm6fgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+nav1leftarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAP///wAAACH5BAEAAAAALAAAAAAQABAAAAIdhI+pyxqdwoNGTmgvy9px/IEWBWRkKZ2oWrKu4hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav1rightarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIdhI+pyxCtwoNHTmpvy3rxnnwQh1mUI52o6rCu6hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav1uparrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIYhI+py+0PWwhxzmetzFpxnnxfRJbmufgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+nav2downarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIfhI+pq+EPXYpxUckoO3AjbF3dJwahllXe6AFgC8d+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav2leftarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+pyxf5VohmSlsxmpjTzAHeN5ak6UHpqKRi2GpwvH3Q3eT64RcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav2rightarrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAImhI+pq5HOAjQyVnqfhHue7oAaKH5kiW0AmnLqaHomkj02g+e6XwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav2uparrow16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIghI+pyxfR0HsRzNnuXVqn3mVQZWFRyIDjp65Ga5Ly4hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+navback16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRSdBRObCQ2TBxObISevAQCBNzu/BRGZPz6/FzC3Pz+/HTS5ByyzJze7Mzq9ITC3AQWLAyWvBSavFyuxAwaLAwSHBRafBSOrDzW5AyixCS61ETW3CzG1AQeLAweLAxefBSStEze7CSWtCyatBSCnBRWfAwmPBRWdByixAQSHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZiQIBwSCwah4HjUTBQFgkFg3MoKBykU0QhoUAIAuAksbpgNByPxQMSGVsVDYlkIqdUiJYLJqORbDgcHRseRR8gISIaEyMkGCVYRBEmeyAnlgaQkSgpmU4RAZ1OKqFOpFNGfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+navdown16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRObCRKZBxCXAwyTKTK3Ozy/NTm9GSivAQWHNzu/FzC3IzO5CySrAQOHAyuzETS3CSWtAyOtETa5Aw2VLze7ByWtBy61BSavAxWdBRCXAwqPAQCBDR+nKTe7FS+1Eze7ByixBRmjPz+/AyexAyixAQKFBRqjAQGDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZeQIBwSCwaj0hAYCkYEJLKguGASEADigWj4bgaHpBINykwSCYRa5HCFFQsF0xGo9lwhpSOwfORYC4gISJ3RAQdIyQYJSAlImNrh4uNJkl5CoKUUBQnjlB4KJ6hokN+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+navforward16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBAwyTBRObAw2VDR+nCRKZOzy/KTe7Pz+/KTK3Nzu/Lze7FS+1AyexAyuzBSavAyOtBSmzOTy/BRqjNTm9IzO5ETS3ETa5By61AyixByixBRmjAQGDBxCXGSivCySrCSWtBTC3AQOHAQWHAxWdEze7AQKFBRCXAwqPAQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZjQIBwSCwahYGjUjBQGgWEpHNYMBCaT4G2UDggos+EwmBYMBpf6VBgYDgeEMgjIpmoAQVKxXLBPDIXGhscRB0eHyAgDSGBGyJFASMiIiMkJYImUwAnmJqbjp4AKCmhAKSlTn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+navhome16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBDw6PBQWFCQiJAQCBFxeXMTCxJyanDwyLDQqLFRSVLSytJSSlISChCQmJERGRFRWVGxubKSmpJyenGRmZLy+vOzq7OTi5Ly6vGRiZPTy9Pz6/OTm5ExOTPT29BwaHNza3NS6tJRqRGQqBNy6pIyKjDwGBPTe1JSWlDQyNOTGrNRiBGwmBIRaLNymdLxWBHxGFNySXCwqLKyqrNR6LKxGBNTS1NTW1Jw+BEweDDQ2NAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaoQIBwCAgIiEjAgAAoGA6I5DBBUBgWjIZDqnwYGgVIoTGQQgyRiGRCgZCR1nTFcsFkHm9hBp2paDYbHAsZHW9eERkYGh4eGx4ag3gfSgMTIBshIiMkGyAlCCZTEpciJyQjGxcoKUQBEhcbIiorLB4XEltDrhcaLS4vtbcJra8bMDHAGrcyrTMXHjA0NSypEsO6EzY3IzU4OdoTzK0BCAkDMgkIOjJlAH5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+navup16:nav nav16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBBRObAwSHBRSdISevBRWfAweLNzu/BSOrAQWLPz6/FzC3DzW5BxObHTS5ByyzAyixEze7BSStBRWdAyWvByixAQSHCQ2TAQCBBRGZJze7CS61BSavAxefMzq9ETW3CSWtAwmPPz+/CzG1ITC3FyuxBSCnAQeLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZfQIBwSCwaj8hhQJAkDggFQxMQIBwQhUSyqlgwsFpjg6BwPCARySSstC4eFAqEURlYhoMLBpPRUDYcHXt7RgUeFB8gIU0BIoiKjAcUIwiLSQUkJRsmGIwJJwmEU6OkfkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+playeject16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+py+0R3IFQUtruXVqn3kkWyIARR4rqKvoFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+playend16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIjhI+py8Eb3ENRggrxjRnrVIWcIoYd91FaenysMU6wTNeLXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+playpause16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIfhI+py+1vgoxzyUCxrZd18ClfmIyVyJ1lqkHuC0N+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+playstart16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIjhI+pyxudwlNyguqkqRZh3h0gl43hpoElqlHt9UKw7NG27BcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+playstop16:play play16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+py+1vgpySUWpvXXqrHmSaeJEYhKYq6hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textblock16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+py40Bo5SOzRvrwlgrfnkJOIkPaaaJXwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textbold16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIihI+py70BowPQ1HZpwNv212Vg9IGHmIjoWa4ey5DSRNd+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+textbottom16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIVhI+py+0Po5y0hYtzrkB7zH0fN/kFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textcenter16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+pm+EPIZsnRkqtDnhu1zHfFSpjaY4PavgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textitalic16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+py+0BgztwUmmjBXX3jE0auHHhM5Yq4xcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textleft16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+pm+EPIZsgRoqr3Vnt102fFSJjUC6nlPoFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textmiddle16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIXhI+py+0PT5i01pisphjt3UmfFZYm5hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textmove16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIbhI+pm+EPIZsg2kfZvblXbwTg10WlA4rjyvgFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textright16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIahI+pm+EPIZstSrqsDhhv1ylfFE5jiYwX6hcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textsortdec16:text text16 16:photo:16 16:R0lGODlhEAAQAIIAAAT+BPwCBAQCBAQC/FxaXAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM5CBDM+uKp8KiMsmaAs82dtnGeCHnNp4TjNQ4jq8CbDNOroIe3ROyEx2A4vOgkOBzgFxQ6Xa0owJ8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+textsortinc16:text text16 16:photo:16 16:R0lGODlhEAAQAIIAAAT+BAQC/AQCBPwCBFxaXAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAM4CAqxLm61CGBs81FMrQxgpnhKJlaXFJHUGg0w7DrDUmvtPQo8qyuEHoHW6hEVv+DQFvuhWtCFPwEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIlhI8Jwe2/AmpTynqPTXSqrnBM+I0kdmpmGmUp+K4nPMvhYx9+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+texttop16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIWhI9pwe2uYnq0yQtqxbz7D4biSIZ+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+textunder16:text text16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIjhI+pu+FxXoOIKpds1oBH7hlYxYxRCaIZ01lhJbHy9tTv7BcAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewchoose16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMzCLrcGlAs6UAYgwLdLtEcI4ygQo7VVp2oupGpG4vmaUVTemX523qlFcw0a4RqNlkx5k8AACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewdetailed16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMmCLrc/i1IAVkYg1Z1iRYUKCqitp1oikqBWV3ZOnhkWNagqu+qnwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewicon16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMwCLrcG1AwGOQbw6qANeCEB3pCSZpO6pgowJZqLKuUGE0dnuEhf8IL1kz1shSHDX8CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewmag-16:view view16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1HyChOTy9Mzq7Kze5Kzm7OT29Oz6/Nzy9Lzu7JTW3GTCzLza3NTy9Nz29Ize7HTGzHzK1AwKDMTq7Kzq9JTi7HTW5HzGzMzu9KzS1IzW5Iza5FTK1ESyvLTa3HTK1GzGzGzG1DyqtIzK1AT+/AQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ+QIAQEBAMhkikgFAwHAiC5FCASCQUCwYiKiU0HA9IRAIhSAcTSuXBsFwwk0wyYNBANpyOxPMxIzMgCyEiHSMkGCV+SAQQJicoJCllUgBUECEeKhAIBCuUSxMKIFArBIpJBCxmLQQuL6eUAFCusJSzr7Kmpl0CtLGLvbW2Zn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewmag16:view view16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1HyChOTy9Mzq7Kze5Kzm7OT29Oz6/Nzy9Lzu7JTW3GTCzLza3NTy9Nz29Ize7HTGzHzK1AwKDMTq7Kzq9JTi7HTW5HzGzMzu9KzS1IzW5Iza5FTK1ESyvLTa3HTK1GzGzGzG1DyqtIzK1AT+/AQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAZ8QIAQEBAMhkikgFAwHAiC5FCASCQUCwYiKiU0HA9IRAIhSAcTSuXBsFwwk0wyYNBANpyOxPMxIzMgCyEiHSMkGCV+SAQQJicoJCllUgBUECEeKhAIBCuUSxMKIFArBIpJBCxmLQQuL6eUAFCusJSzr7GLArS5Q7O1tmZ+QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewmag+16:view view16 16:photo:16 16:R0lGODlhEAAQAIUAAPwCBCQmJDw+PAwODAQCBMza3NTm5MTW1HyChOTy9Mzq7Kze5Kzm7OT29Oz6/Nzy9Lzu7JTW3GTCzLza3NTy9Nz29Ize7HTGzHzK1AwKDMTq7Kzq9JTi7HTW5HzGzMzu9KzS1IzW5Iza5FTK1ESyvLTa3HTK1GzGzGzG1DyqtIzK1AT+/AQGBATCxHRydMTCxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaBQIAQEBAMhkikgFAwHAiC5FCASCQUCwYiKiU0HA9IRAIhSAcTSuXBsFwwk0wyYNBANpyOxPMxIzMgCyEiHSMkGCV+SAQQJicoJCllUgBUECEeKhAIBCuUSxMKIFArBIpJBCxmLQQuL6cAsLECrqeys7WxpqZdtK9Ct8C0fsHAZn5BACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewmulticolumn16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAPwCBDQyNAQCBPz+/PzerAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAMwCLrc/ixI0WSgKoyBl+beQFACpo1AqXbKCr1wLAMWS08hGG3dSZqin4sxnBmPD38CACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewtext16:view view16 16:photo:16 16:R0lGODlhEAAQAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAQABAAAAIchI+py40BTQSwuovp3DXkv1ia1IHmIXLiyWJ+AQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewtree16:view view16 16:photo:16 16:R0lGODlhEAAQAIIAAAQCBPwCBDQyNPz+/PzerAAAAAAAAAAAACH5BAEAAAEALAAAAAAQABAAAAMuCLHcri4yGISlj4kxcANgNRBQCIbL6U1Su7bB62rXvGydG25kqpwfIGxILBr9CQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actattach22:act act22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBMTCxPz+/DQyNKSipAQCBISChFxaXDw6PAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARrEMgJgqA4zzus/gLhFd5HCcZAXqsphYPUdhcYFNRcZnvdtpnDqPTbUWgAJKBYwzBlw+bRo3xmkNWoBgm0OrVLn3GC9RgCk8DhUw7c0rHPr4CDu5SYQNyEt7uSY3p/UAKFhYKDSQOLiwgFdhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actbookmark22:act act22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBCQmJCwqLMTGxAQCBBwaHMTCxLSytERGRFRWVLy+vKyqrKSmpHR2dJSSlJyanISGhGxubIyOjKyurGxqbFxeXGRmZHx+fKSipLy6vGRiZLS2tFRSVHRydJSWlHx6fCH5BAEAAAAALAAAAAAWABYAAAWWICCOZGmewamaQrq+wUC8azHINGocOI38iIRAceDNaISFYklkGHOEhoNBfUAOhuOLEJE8HoPiRKFdESiQBqViuTDIUAsEcyAeGJmyiqC5RCwJGg0YcEh9D0V3Dxt6JwQVDRYVHBUdi40mjw0PTgwQHgeYJQQJfxUXFxAOoTkFpQ0fsRSimQkWEQ0VtI62HLt7vjl7JQYhACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actbookmarknew22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBCwqLCQiJCQmJMTGxAQCBLy+vLSytERGRFRWVKyurKyqrLS2tKSmpHR2dJSWlKSipISGhGxubIyOjGxqbIyKjFxaXGRmZHx+fPz+NGRiZPz+ZPz+HMTCBKSiHPz+jFxeXPz+XPz+tPz+zPz+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAamQIBwSCwaj4Gj0hgQLJ+AAaEAVQoI06pRYDhkoYgwIhEgKBTfZ2FhaBsYDS8VWnA8Go0FJIKeqyUTDw8EDHBpSwUUFQ4UFhcYDQYFfkoFFxEQDG8KEAUZlEeWGBIakw4FG1STiBoYBRwdBR4fHgUdHKBEBSCnIR8iIyIfIblFu6ceIyQjtcXGCbLKzAUKzrq+wMLEVa+xs7W31kOTk6nkWuOf6Ea5QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actexit22:act act22 22:photo:22 22:R0lGODlhFgAWAIEAAPwCBAQCBHR2dDQyNCH5BAEAAAAALAAAAAAWABYAAAJOhI+py90RnIMyRUOxhDfzJkACdoXBuEDDkQFDi5go0MrKx16kns80b7qdELCgBYaEGWwL5nG1ePFiKp9A6kuYRNuho8vxVrrZivmMRtMLACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+acthelp22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBCQuNBwiJAwiLAwaJAwSHAwSFIy+3ERynCw2PCQuPAwmPCxOZCxWdJzG3FSazBwmNAQKDAQGBDRmhBQyTDxujDR2rIy21AwWJDyGxCxmjAwmNDRihAQOFDxmhCxunBQWFAwaLCRahDR6rESGvDQ2PCRWdDRunDSGvCRSdAwWHCwuLDSOzHSmxDyKxBxCZBwqNHSu1DyOzAQSHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAahQIBwCAgIBAPCoGAgOoeBAyKhWCwYDUf0CX1AIhLiJEGpBLiAAaRxdgYsl7Ybk8igBZoN5xmAdDxoanp8HyANISF8EBsiXBMjJBolBEQmGHFoRScbKHIKDykqK5lFAZRCnyknTaROLA8tq61OChgtKqyzQgEYEJi6UC4vI3LAASkbMBPARAEBdszR0sACEaPSMTIQM8W6KzNl3bo0NOJDdEEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actlock22:act act22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBHRudFxaXExGTERCRAwGDGxubPz+/Pz2/Ozm7Nza3NTS1KympFRSVHR2dNTO1JSSlKyqrKSipDQyNMTGxDw+PLSutKymrMTCxAQCBHRqLBQODJyanDQuFFxSJFRSJFRGJERCHExCHISChHxyLEQ6HGRaJExKHLSmbLy2fOzitPz23KSiZHxuNHxyNJSOTNTOnMTCjLSudKSaXJSKRJyOTOTetNzWpHxuPOTi5MzKzLS2tFxWXOzq7Ly6vOTe5Ix+RLSqdNzSpLyydKyqbKyiZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4IBAgMEBQKEjI0GBwgJCgsMDY2XjwkOAgQBDxCLl4QNCaGCBBGWooINCAqqrBKgqwATFKaDFRYVtBMXsIMNGBm0GRADjQIJxKIaGxwdHh8gISIhGyMZzIwkGholJiYfJiAfJyEZISDbg90oKCkqKwcHKyooLC0f7IIuLzD2YMSQgW8GDRri+AFoUMOGvRsxUhSsQQPHvmQSchyQtEAHhh0WJHDQcJERjwsKDvRI0BGDjwgicXhQyCOjSgUKPO6AObIkIQESfmxk6REDT4s0bfaYpDNkT4VAha5s+TLmzEYtatwIOHAiDZIKNQAJYk9IjCFEisyoocFEB4UACtBpm0t3LiF4gQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+actredo22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBCReDJzGjMzivOTu3Pz+/JTWbHy+VHTCTMTivPT69BxGDESuJDyiHESiHEymJIzKZAQCBFS2LFzKNGzWPDRqHCxqDFSqLHy2XESCHAwaBAQOBBQqBDyWJHyqZDyKFGSiVESeJBQ6BAwSBGTGPFyWPFSSLEyOLESGJBQiDAwiBBQmDCRGFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaoQIBwSCwaj8hkMcBkKpcBwYAwEDif0YLhwEUkFItFMkAwMBoOR+PxgHwjRDggamhIJpQ8ZbKGKOQLcgEFdhUWEYgRF3sNfhELBHALAhgZFhobRBwREhQdEAIEHpIKHwsaSJwUDQgQIJINARxKESESDQ0dgCIjSpAkDAwPco+ZSJAlJicnKHIAIrNHidOIQxunT0kpCyrZSCss0d5Fj6jjRonn6uvs2QZBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actreload22:act act22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBCRSFCRSHBw+DBxCFCQ6FBwyDBQWBBxGFCxyLGTChMzqzLzmvHzKjDyOTER+RERyNDSqXNzy3LzivFS+fCyCPBQmBCQiBBxKFBQqDOTy3LTitES2dDR+PCxuJOT25KTarCx+PESSTCxKHDSeVCyKRNT21ESWVDSGPBQyDAQCBBQSFDRuLDSyZDySTGzChCRiJKSmpExKTDS2ZGzGhLy+vGxqbISChDSKRMzKzGxubDQ2NIyOjCQiJCwqLBQWFCwuLKSipERCRERGRHR2dAwKDDw6PFRWVIyKjCQmJFRSVBwaHKyurAQGBExOTBweHFxeXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf9gACCg4IBAgMEBQYHhI2ECAkKCwwNDg8QBAOOhAQREhMUFQgWBxcHGBmbggkaGxwPB4yDB6SbBJIKHQaqtY0eHyAhsqrDgx4aCiKpqoQHAyMjJBMKJaSxzAAHIRsmJgonKA0LHSmDKiuOBywRLSQuLyEwwyoxMuiN6iUzNBXy5jU2bsgoJugABBz95uXQsUMGD3vpPPgTpKIGwx4+HMr4kW4YkCA2hAzxAQSIECI+imBTwVIFESNHerRUgc0cEiFHkjiiyYzeDiVLdvLcySSkkKGEWiZVweSGkIHMmvQosoQlkaZOjvhosvKJjIAxoOAsgpRZkQNLnvSoqspAIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+actrun22:act act22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBAwKDAwKBCQiHNze3AQCBBwWFDw6NPTy9PTy/Dw2NKyytOTi3LS2tMTKzMzOxLy+tLy+vBQODNze5NTS1JyalIyCbIx6VIRyVISGfJyelOTq7EQ+NMTGxKyurGxeRLyKPOSmROSuVOy2XOSiTLzCzNTOzDw+NCwqLHxuVOy6bPzGfOSuXNTW1LSyrMSWRNymTOSmTKSCTPTGjPzSnPzWnMyaVBQSDMTCxPz+/KyahNSeRHxeLJRyTPzmtPzarOy6fJyajNza1Ly6vLyulFRCJPzirPTOlMS2pNTSzMTCvJyenBQWFNzKtPz6vPzyvPzqtOzGlOTe1AwGBFxWTLy6tPTm1PzSpPzutPz2xPTSnOTSxOy2dPzapPzerOzm5IR+dPzu5Pzu1PzqxPzy5Pz+9GRiXGxuZKympHR2bOTm5Pz6/MzSzBwaFJSSjCQmHPz2/AwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeEAQKIjIIDBAQDjYMFBoMHCAkKgwYFhwULDAUKCg0ODxCkBQgRnoUSExMUDxUWFxgZGpAbFIuGHB0eHyAhIiMkIB8lJieIKCUpJCTGIyorLCktKIUDpC4YLzAxIjIyMzQ1NhgdpJI3ODktJTowOyM8Ejc9Pj9AQUIEclAocCMIBQhDiOwgoaKIoCI+jBxBkkSJkCWemIyq0GSHCBVHihRx8gRKFCmpKhGaQqWKFYZXsGR5kkXLFgRUXBUqkCGCFS5AjnTx0sXKlyA6CRVgAAHMAilhxIwhU6ZFkBY5kgKYUoXBAzMKzixZ4AJNGgVm1KxhM0WpmQpUMtooaOPGxAM3Nw60oYLGjNYCbzYJOgAnRzNBJ95oPYQCgpJtkwzFoULlRuRPiy9fNhAIACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actstop22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAASC/CQKDBwKDCwODNyKjPzq7My+vIxiXAQCBOSOjPz6/OSelNySjNyGhMR+fLRaTGQ2LPz+/Nx+dNR2bNRybMxuZMxeXMxiZLQSFJQaHFwqJNyKhOSCfNyCfNR6dMxmXMxWVMRORLQODOR+fOSSjNR2dMQ2LJQWFMRWTLwWDNSCfMxeVLwaFKQODNR+fNx+fMxiXKQSDOSWlMRSTMxaVMQ6NMxORMQyJOTS1MxqXLwWFLRORMxKPMQaHMxKTLQWFCH5BAEAAAAALAAAAAAWABYAAAb2QIBwSCwajwGBcikIHIsDQmFKNRwQT2EgoVgsGOCG4wHBIgmRhWRCqVQsF0xGYyYGNgoGh9PpeCQfICEic3UAAWgLIxwRJBsbHSUREyYYJ3RDAQULexGejhueESgpl3WaCxsqJKKsChEUKywtmFoFDC4vCayikzCyMbWHt38NCTKiHhUfMyzBdQIFKsodob0VNDWzwppuKxMRrx6iNjcitNA4bh+iEzkwojc66JkOOxcf7G35PBE9KS1MEUGgIQOIFfk++KjRw9wJgUUIZvhRoyLDFCliQDQisUWLGCJOeNx4hKCGkyhPGnqCoKVLl1liypyZxUAQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actundo22:act act22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBCReDJzGjMzivOTu3PT69MTivHy+VJTWbIzKZEymJESmFESiHDyiHESqLAQCBFzKNGzWPFS2LNTmzCxqDDRqHPz+/KTGnBQqBAQOBAwaBESCHHy2XBxGDOzy7HTCTEyyJDSqFHzWTAwSBBQ6BIy+dESKJFySPFSSNAwiBCRGFBQmDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAalQIBwSCwaj8ikMsBkKotMwYAwEDiXgYLhwD0gCFZiQKxNKBYMRqPh+D6G16y5AYnYIxBJAyF4AwITTAUJdBESD4gPFBV6Fn6ABBcJDIYPGEQZGhQbHAIdfx4JHw2VSBodGwWfAR4LDSALfkgYAQurBiAhICKfSSMkvQElGyYnGyi9Rxkdj4nOskUYyU9FpxnURikdGtjRKivdRKfQ2Inh5+jpRwZBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+actunlock22:act act22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBGxqbFxaXExOTEQ+RAQCBPz+/PTy9Ozq7Nza3NTS1KSipFRSVOTi5Hx2fJSSlKyqrJyenJyWnDw6PMzKzKyurDQyNFxWXMTCxJyanHRuLHxuLGReJFxSLFROJFxWJExCHERCHBQODISChHxyLHRqNIRyNHRmLLSqbKyiZLy6fOTarPz67Pzy3OzitKymZFxSJJySTNTSnPTy3NzSpMTChLSydKyqbKSaXJySVIyGRGReLPz23NTOnMzCjHxuPLy2vKSmpOTe5LS2tLSutHxuNHRuPMS+xFxWLIR+RDw2HFRKJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SDAQIDBAUChY2EAQYHCAkKCwyOjZANDgIEAQoPjJiDAg2iggQQp5gMBwmrDBESl6MTFKuoFQSjABYRF40CGAW8BRm7hQwNxBobHB0eHx4gISIjBdiEAhYFJBslHOHSHh4hBSHlxIUmJygpKissBiwtLi8pGjDqhBoxMjMuaNSwcSMFjhw6dnjYRyrGCh4ueviw4Q5HDB0/PjAUJCBCAwMIGiiggAEIBFk/FgYLIgRkggQkhxAJkqGExkYMFnxsIGRkSQgLHhRRWUjAggQgG8AsSWRBBiP6VrYMOfKIyaBDNwLo+HHSUplOSyDRqiEHjRkretRQkcLgxayNF0wksQGQxsSKMTIq0QpgCba/gAE7IhMIACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+appbook22:app app22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBDyGhCyCfFSWlESOjDyKjDSGhCx+fGSinGSenFyanEySjHSqpHSqrGympEySlBx2dISytHyyrCR6dKTGxHyurHSurHyytGSipCR6fARmZFSalEyWlBRubAxubBRydDyKhDSChLSytPz+/MzKzIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbFQIBwSCwaj8ikMhBQIpmCQdM5ZBIKhgNiugwkFAsCI7pNMhuOxkNBgBgEiAi3GkBLJpJHYgEpaClyREwVFhcSEhgOGQoMfgMaERtcARQBFRMYExZ6HB0FUYAekkIBHxqWFmlrC1haESAfG6MBGx+VFRgKYH0hInGRklO0ppYXCwwMWQiQHkwjgrWnFRdYZHIBJCTP0LaWGAcDW9jZ2nMAw9IWTOQkJSZMRsOV49nu8E+19PbmR7TY+1TovONH5V7Ag0QMBAEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+appbookopen22:app app22 22:photo:22 22:R0lGODlhFgAWAIYAAAQCBAQ2NPwCBHSurIS2tBx2dBweHPz+/Ozm1GxiTGyqpPz6/Pz69GSqpOzaxPzy5HxuVLSmlOTazPz27PT29NzClPTexHxuXLSmjAxqbFSinPTy9KyehNy+lPTy5Pz29HxyXNzWxKSahOzexPzy7IR2ZOTWtESenPTy7KSWfIyCbKyijAQGBDyalPTu3KSSdDSOjJyOdCSGhPzu3OzizJSGdPTq1PTq3JySdMy6lAyKhOzWtOzi1OTOrJyKbMS2nJySfMS+rAwCBNzOrNTCpNzKpJSGZKyafLSifLyylIx+ZHx6ZDSChAQuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAAWABYAAAf/gAABAoSFhoeHAAMAiI2IAAQFjI6EAAaJkQeTjwAICYkKBQcLm5WdBwyfhgChB66bp64HCQC1lQ2irqQCAA4PowsLEBESE4wAuLIHFAAVFr+uDBcYxRm1GrmuGxwdFh4Mrh8gGCET1gDYyhsiFSMkDAsMDCUYJhvnJ9kHKCnODwwfPlBQsULCPRYAWogK9sHFiwoOPEyQh0JFPXO1YBSYwBEFghjdHkwQOYGgwQwIZRR44GHGDBogabhAsYEEihrUMAIoUMCEDRs3HODIYQHFA6MPcJA7KICFjgw7eIzo4cOfiwc/gKwIUm2SkKdDdlDt4AABDaU/iIRwwbTSUyJFOow4S3Hkx9oNDDZgXPU0h1wcSIgEGUw4ibVET5WoWMKksePHpdxmyKADAEIWly9HJtQkQJMmlAgZCAQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+apppencil22:app app22 22:photo:22 22:R0lGODlhFgAWAIMAAASC/IQCBPwCBPyChMQCBPzCxAQCBPz+/MzKzISChKyqrDQyNEQCBAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARYEMhJ6wxiEMtpIAWxddwXiqRlikSQeiAbuC+wirNR322gv7zcLobzDU+9XypoBBKTR1lz+RTWDgip8nUwZK1XLyIx5XoVicX2RUAo1DVKi7GOBxjxfNwQAQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+apptool22:app app22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBISChFxaXNze3NTS1Ly6vKSipNTO1Ly2vNza3Pz+/MzOzOTe5DQyNOzu7MTCxGRmZMTGxPTy9Ozm7Hx6fPTu9MzGzGxmbAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAW1ICCOZGmeaEoGbBsI6joMRGEcbQwESDIrtVtAF1gwDLNaAmfKiVgLBJKgwB1KxQZrBHU0FAXmavFoQLYiB6TxFXMj5AZBwnJI2I3wcNWALyYEcgoKXxRhOHs7XxEVCwsWFgoUDRYUFwwQB25ZCxiNjo6GkwUXN2NsCxEYqhUHoQ0MEglYRQQXErcHrI55FycuB2YSmoyOBTEtB2sXuhU6XAENC2a6z9AKCwq+1tAN3E2J3ySkIQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+connecting22:connect connect22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBPz+BMTCBISCBAQCBPz+/MTCxOTi5AQGBNze3Ly6vISChNza3FxaXKSipAAAACH5BAEAAAAALAAAAAAWABYAAAR4EMhJqwzY6omD+MNGdR8YilNZnug0qGzrqrL1lnV1fyJBVB6VQEMoGH4ADGwQkxQPBwMiKGA2J8VEAnq0tgiKg5aL/C7C2gTjKCM0zowDQ8tuNQznNL7cKzjOUQsNfER+gguIg19+Pm6ChBZFDmWNi5M5FIyYFHQRACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+connectno22:connect connect22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBPz+BMTCBERCBAQCBPz+/MTCxOTi5Nze3OTm5Ly6vNza3ISChFxaXKSipAAAACH5BAEAAAAALAAAAAAWABYAAARiEMhJq7046827/+AVCKE0Dh9BAGdaGISAToFGFMcBU+11I4hDYseSZQiKwwKoI/QwBIYiuFDCZseGdIlYEjUNg1SpY6w2N4cUIW6cjwW1lsFwo+MqgtZuw0/ydw5vH34lBhEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+connectyes22:connect connect22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBKyirPz+/KymrOTi5KSipMzCzNza3OTe5Ozi7MzGzPTq9OTm5ISChMS+xFxaXNze3GReZIyCjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAWLICCOZGmeaBkAQpoGg7C6JizTQT7CxPwOwFWgYPChYIXkIHC4uQKGAiKRKCyNpxxUUVViVYNFLkqtLo+DAkMMLXQPXwAy2WCTF4544FGtKuwPDhB6DnxuUmyCcXIQhV1uYoMuEAcOBxEKCHg6TzGFCJUSizuejROKOAM9OY2SnUU7nD89NCcDsLUnIQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+devscreen22:dev dev22 22:photo:22 22:R0lGODlhFgAWAIcAAPwCBAQCBPTy9PTu9Ozq7OTi5Nze3OTe5Nza3NzW3NTS1MzOzMzKzMzGzMTCxMTGxOzm7AwGDBQOFBQSFCQeHCwmLCwuLDQyNDw6PERCRFROVEQ+RDQ2NLy+vKSipISChGxqbExKTOzu7OTm5Pz+/GRiZMS+xLy6vBQWFLy2vCwiHFQ+NMSmfNSyhIxmTDwuLJx+bLS2tCwmHMyyhMyqfPTqpPzyvLSWbLSWfPzitIx+ZDw2PAwKDCQiJGxWRPTmrPTerMyuhPzqtPz63PTWnPz6zNy+nIRiVDQuLKyWbOTanPz21NS2jNS6lDQqJHRaTPzmrPTSnPzyxOTClPz2xNSuhPTqxPzuvOzSpAQGDOTKnMy2jOzSrPTu1NzKnOzOnBwWHJRuXLSWdPTatPzqvNzClCwmJOzSnOTOnPTuxOzKlOzerOzarOzitJR6ZNTO1IxmXPTWrNSyjPzOjPTSpLSehHRqZOzirOTCjPS+fPzGhOy6bOzKhGROPMy2lPz+1PzmtKRyRHRiNNTCdPz+zNzCjEQ2NKySdDQmJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAj/AAEIHEiwoMGBARIqXMhQIUIBAwYQIFCggIEDCBIoULBgAYMGDgIIDEBAwMSKBRBk3NjxAciQIwdACBBBwgQKFSxcwJBBwwYMHBx0EAmA5EwPH0CEsCChoYgOQ0cSGCHhA4kSS5syJGDiBNEAFVGUKKEBAwWFFM6SNJHi64gDFEKE4FBBggoKK1i0cPECxokYXw0gsECYggQZM2jAqGHjBo4cOtqOxLhDAg8ePXz8ABJEyBAWRIoYOfJipEoMCZEkuaFkSAslS5jUGJKkSRAnRREo0JDwCZQoTKQAmUKlihQrVa5gKZ1lI+oAK7QM2cJlSZMuU4Z4+TJEx0iNOwKAggkjZkyOFmS8kClzpcUQLRRGbjRD4MgZNEzSqKG+ZgobI2248dUbDDDwABzcxSEHEFpgEcUcdMRRhx1fFejAAx0cgcYdSxiBRx566LEHH0d8QFRRNC3Uhx985CHEH0MAEkhCBxWkgiCDFEFIEYUYUmONMhyCRxVH/PgjBYioYJAdAQEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editcopy22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFPz+/DQyNISChDw6PMzKzMTGxERGRIyKjFxaXMTCvKSmpHR2dPz6/Pz29PTq3MS2rPz69MTCxFxWVHx6dJyWjNzSzPz27Pzy7Pzu5PTm3NTKvIR+fJyGfHxuZHxqXNTCtPTq5PTi1PTezNS+rExOTFRORMyylPTaxOzWxOzSvNze3NTOxMy2nMyulMyqjAQCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbYQIBwSCwahYGkUnk0BgTQ6IAQaBKfUWhBYKhaAU+CgXAQIAyChLeJzSIQhcH6GFaM0QtGY5kstqEODw8QEQELAhJTc08KBBMEFBUWDRcBE1pca20SGBkaEBscAY5maFRIAgoLHRQRHh8gIQFlZnByqA8ZGSIQIyQjJQEmYgJ5p2ACrK4gJx4gKIZZAgdeAQ4ZI9kjKSor0AwEjeAs1S0cHAslLi4vMDDRWeRIfEsxMeET4ATyVoYLC5fizXEiAR84BeMG+pEm8EsAFhAjSlR4hR6fLxiF0AkCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+editcut22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBAwCBPz+/OTi5JyanOzq7DQyNGxqbAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARbEMhJq704gxBE0Bf3cZo4kRJqBQNRfBucyudgvJS6VaxLzyMa6/bLiWA9HOg4VIIkL5vzuRkcpkvRIIAorphJLzBW84WEuRZWp6uaT7J2Sh1Hit3OY/ZO7WvsEQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editdelete22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIYAAASC/FRSVExKTERCRDw6PDQyNCwuLBweHBwaHAwODAwKDAQCBExOTNze3NTW1MTGxLS2tJyanPz+/Ozu7BQSFCwqLDw+POTi5PTu7MzKxIR+fCQmJPz6/Oze1NTGvPz69Pzy7Pz29LyyrPy+vPyupPTm1BQWFIQCBPwCBMS6rPzSzNTOxPTi1NS+rPTezNzOxPTizOzWxMy2pOzaxMy2nPTaxOzOtMyynOzSvMyqjPx+fOzGpMSihPTq3OzKrOTCpNzKxNTCtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf8gACCAQIDBAUGBwgJCgsLgpCRAAwNlZYODxALEY+SkAMNEqKjEw0UD5yegqCjrRMVEqidkgWhraMWF7GptLa3EgEWFRSOnhW+vxgZEBqzkBvItxwdHryRCNGjHyAhHSLOgtgSI60c2yQjJd+eJqEnKK0hJCgnJSngAO0SF+8qEvL0VrBogW+BLX4oVKgIyMIFQU8KfDV4R+8FDBcxZBREthAFiRIsOsygsVEUh4Un3pGoUcPGjZInK65QicPlxg8oX5RwqNJGjo0hdJwQ6EIkjRM6dvDYCKIHSBc1Ztjw4eOH0oIrsgIJEqSFDBo0cuTgsdSTo7No0xYTZCcQACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+edit22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBISGhISChHx+fHx6fHR2dGxqbGxubGRmZGRiZFxeXFxaXFRSVIxSLPyuXMzKzMzKxMTCtExOTPzqrPz+/NTS1MS+tOSaVPyWNPz6/IxeNPzavPyKBNTW1PyCBPyGBJxmNPzOpLx6PNRqBMSCRNySTPyCDPSGBMxiBKROBHRydPSylOyydMxmBJxKBAwODPS2lPTq3OyabJxGBPTy5PTGrOyOXPR+DPz69PzmzPzevNxuPORqLMReFPzy7MyCXKxiNIRKHBQWFNTOxPzixJRaPFxONHRqVPz27PTy7PzStCwqJDQyLJSGdIx6ZPz29PTu5HRmTLSKbMSGZHROPFxKPJSKfJyShKyehMyuhDQmHEQuJJyOfLSijMSynMS6pLSefDQyNHx2bKSahLyqhLymhOzi1FRGNIR+bNzKtOTOtOTKrOTKpLyedAQCBFRWVPTq5NzOvLyunLSmlNTCrOTOrNzGrLyidMS+rLyynKyijLymjLyqjAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gAAAAQECAwQFBQYHBggJCgsLDAwADQ6CAQ8QD5ydEJ+gERKWE4ICDxSpqhWqqhYNFxMYphCtqaytGRoXGxgcggSoth25u70eH8APFR0VzMzNziAXIRjIvwAFwq3EqSLUGB/iI4LathS4JCXVJh8nKCmCKrXDFCss1eIfLS4v8ssdmgWsAGNDDBnt3s3wJ+jAtlUhaNSwccNEi4WCBBl4SAHHihw6ZOzg0QNjRgAG6KXK4CNEjBU/gDQI8kLISQAIADobAoMIzCINjLw4YvNkAno4kCRRUuNHESNLmDRxUjSjAlRPfECJImUKlSpMrFzBIqWqoKtJaWSJomULAy5XXrp4+QKGYcYFoCBEWRImi5gmY7CQyVLGriAGD2jEMHMmCxc0Xb6kUbOGTRs3N988gLM4jpw5Y+iwqcOGjZ07mE8yiGABz5c8c/Ts4cOnDJkybS7fdMO7t+/fvDMaCAQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+editpaste22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQWFDw6FHRuFGRaBFxSBAQCBAQKBCQiBIx6HPz6/NTOfKyiXDQuFOTm5Pz+/Ozu7PTq5Pz63PTyxNTOjKSeRExGLMTGxMzKzNTS1NTW1Dw2NKSmpKyqrKSipJyanNzWlLy6ZLSuVIx6FISChIyKhJSSlCQiJLS2tDw6NDQyNCQiFCQmHBQSDGRiZHRydGxubHx6dGxqbFxeXGRmZFxaXCwuLOzq7KyurHx+fDwmFEQuFCweFCQWDBQODBwaHBweHKSinJSWlOTi5JyepHR2dDw6PBQSFNze3ERGRIyKjIyOjISGhPz29Pzy7MS2rMzOzFRWVHx2dHxybDQiFPz27Pzu5PTq3PTm1NTCtJyGdHxuZHxqXPzq3PTaxNS6pFxWVFRKRNS2nPTi1PTStNSulNzOxNSynMymhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCgwABAgMEBYSLggaOjgcICQoLDA2Pj4MGDg8QEZ4FDxITFBUWFxcYGRobjQ8cHR4fCQ8gCyEiFSMWJCUkJieNEB4dKB4pKissK8wrLS4vMDHBAAYQHx8dFx0fJDIzNDU0M+IyHzaNNyg43Ng5Ojs7Ojw9Pj9AMkCNDiZB/h9CSOx4QLCgihItqBkYgqIDESElitAYWJCgkQcXjjRCgi1Ihw4BB5LAQOLCgyQYHihpUU3DBw5ElpAgAYNixSRJjKjQaECDCRPZPDB5IbIGSQwKLnh4wbInLA4kmJB4oaPiAwVNnER40hRK1BIAaVatUZJEFCkmpmjgCeWDCalFe4q4oFKwSRUrEa5gycLzwq8lUnPQ4PEgSpYcUZ5o2cIlS1O/JHLEDdfjQZMIVrpgweLFy5e+M6WSmBGlxYMYYBRzCaOFi5imHWBIfOEiShLTVjaP6eyFTBmN1TA5OvLDjJksWb58OVMGDRqWjAYdmU79SIvpjqJr104nEAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+editshred22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBFRSVExKTERCRDw6PDQyNCwuLBweHBwaHAwODAwKDAQCBExOTNze3NTW1MTGxLS2tJyanOze1Pz+/Ozu7BQSFCwqLDw+POTi5MzKxPTu7LyyrIR+fCQmJPz6/Pz69Pzy7Pz29OzaxPTu5PTq3PTm3My6pPzu5PTq5NS+rPTm1PTi1PTezOzWxPz27MyynOzSvMyulOzOtOzKrMymhOzGpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbpQIAwIBgMCAXDAZFQLBbCqJTRqFobjgdkEYFKowPJZEyeUBqVR/crHDTKZYplovZKCW84+YKZZNZSBXl6EwEEBhVPXxZihGMaGRscdkIdg4QeEnVfCH2OHyAhIhuUAAiXZSEhIyQlJqWnjiEnKCWupRWoYyEgJK0SKaUKjam0JCorLMFfC6iqx8giLa/MGAsT1wsuCyULKwssC9RSzdkfCyALKuALLQsvpeXYIQso3gsiCzALMfENC+dGcMNHUAY/f+jq3ctncMYCGggFrsvHcEGNh/EyPFmg8cmrJxAVkVO0EUDJklHoBAEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+edittrash22:edit edit22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBERGRExOTDQyNISChBQSFCQiJCwuLPT29Nze3GxqbDw6PGxubHR2dJyanLSytJSWlJSSlOzq7Pz6/Nza3Ly6vFRWVBQWFIyKjMTCxHx6fIyOjLS2tOTi5PTy9OTm5Hx+fNTW1KyurKSmpJyenExKTMzKzKSipFxeXCwqLMzOzKyqrMTGxLy+vHRydBwaHNTS1DQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAb8QIBwSCwaj8KAMoA8LgUDQsFwQByay4RiwWg4GA9IRGk0SCYJSsUCsVwwGQ1EsmESD5xOp+L5gDwhBRIZDhcDdkMGDgEiIxAkJQ8Ok5MmAohDAQ1xJxUlKCUlEg0pKpiZJRoLCxmtCw1eURhOcR4rbQ8cGRwLAwgGtBYTDywtGRKjvQTARgEZLhMcKC0OrQMvAirMRc7CHCTU1g2+20TO0NIn1RwDCya/wdHT1Rnt5LToKOq79trx0tR02YPX7Jm8fRxMOIhSLhOJE/LCJSTlr5kFEBQsWDiR4UGGBgsuHDg1BEYAfTE6oEBR4AIBAiS5yWBAAAGBAyaPGAgCACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+fileclose22:file file22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBERGRERCRDw6PCwqLExOTFRWVHRydGxqbGRiZCQiJISChIyKjHx6fDQyNBwaHJSWlKSipBQWFJyanPz+/JSSlCQmJAwKDCwuLBweHBQSFGxubExKTISGhDQ2NFxeXFRSVDw+PAwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbZQIBwSCwaj8jkMSAYDAgEJbFgOBwQCUOAoJAaFgvGonHIBhyP5BcSgUAYDWxggD4WFmx3e3HQngkSRgYMEBMUFG4MCId0BGlEAQeEhocVDYcUdBYKF0QCB3gRlJgUAQEYBBkaRAMbDZMMpAYcT46rQwMJrgsdC6QcfwoPnUMOBgkIV6SHHg6bw0QEAQYfBpggBZjPGsRD0gEchxwCIR6HChnQRQ8DIU4DTR4Em+ncRw8O+fmoXPXdRg+gQLFgIYM/KRIkoDP4QMKFf0o0aBAh4qGUixgzCrETBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+filefind22:file file22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQSFJyanLS6vLzCxISChNTe3OTu9Oz6/Nzy9Nzy/NTy/OT2/Nzi5Mzu9Lzq9KTe7LTq9PT+/Pz+/Nz2/Mzu/Kzm9Jza5HzK1LTi9PTu9IzW5ITO3FxaXNT2/KTi7Iza7GzC1LzW3FRSVMzO1MTq7HTS3Fy6zFS2vKzm7Lze5MTGzHzS5FTG1Ey2xEyyvJze7JzW3ITa5FTK3EymrGS+zFxWXKymrMzi7ESirEyqvLSyrKze7MzOzMTCxKSepAz+/NzW3MzKzBwWHLzS3ERCRAzi3KyurNze3MzGzLy2vLSutCQiJAyytHRydOTe5MTGxLy6tLyqpKyelJSCdOze3NS+tLyupLSmnKSOhCwuLPzy9Pzu7Oze1OzazOTOvMyihOTi5PTm3Pzi1PTazPTWxOzOtNSunDQyNPzy7Pzu5OzKrNzSzNzGvNS6rMyynMymjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCgwGFhYOIiYQBAgMEAwKHiokBBQYHCAkKCwwFAZOEBQ0IDAsODxARCZ6gAAEGEhMSFBUWFxgZCJ+TjBoMEpkRERscGBGRih0BBAgeFBQOER8gISEfIruIIwEkCCUVwhcgJicoKSrZg9srCRkRGdMsLS4vMNiK2wIKMRsbMiwzXtCocSydIBs3AuCIwIFDiBMucugAoWvSiB2VNPDg0ELHwA0MkCXr4aNSggg8NoDIQOFHgBtAkgURMiDAEAFEVBCJFKCIkSMGOyDRkETJEkOFmABoUsRJQkQdnkzQACWKlBtTplBR6qopxkFRJ0ytYuWKFCxZtBBq+hRA2AlbRrh08fLlCxi1a51g+dQhDFwuYsaQKWPmDBpKXgNETaNGjJgyhNfcVdTTiWI2XpK0cePmzRk4YA5T5otGixY0qFOXbgXAQCAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filenew22:file file22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBExOTERCRDw6PCwuLBwaHAwODAQCBOze1NTW1OTi5Nze3MTGxLS2tJyanPz+/Ozu7OTi3BQSFCwqLDw+PDQyNFRSVPTu7MzKxLyyrIR+fCQmJPz6/NTOxPz69Pzy7PTu5Pz29Pzu5PTq5PTm1My6pBQWFPTq3PTm3NS+rAwKDPTi1PTezOzWxMy2pPz27PTazOzSvMyynOzaxOzOtPTaxOzKrMyqjOzGpMymhPTizOTCpNzSzNTGvMymjMSihCH5BAEAAAAALAAAAAAWABYAAAboQIBwSCwaiYGAYEAgFAqGg/Q4DCASCsTiymgcHAcqQLB4mM+QiIQBppLPcMjkwQ4bB2X4maKgt4sVCHpnFhQTElNFE3mDDxcYGRp2RBuMgxwIHX9EBZZwHh8gCBmTQ52NISEiIyQlpUImng8hHyInKAgprwAqgnC0IKwrLLpGB4wctLYkwy0uuwd9Z8AnJywsLcVFx2YcL7UnJCwwLTEy0GXJoSgrCCwzNDTnxgjeH9UrKzXwNDY36LRGhEOwLx4NHDmgJbh3QoeOgv127EhojEeHDj16pEhRQoZHHzl+QJNCsqTJSXaCAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+fileopen22:file file22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBAQCBCQWDCwaDDwmFPSubPzGhPzCfPy2dOSmZPzKlPzSnPzOlPzKjBQODPzChPzWnPy2bPSmXPyuZOyeXIRSLEQuFEwyHEQqFDQiFCweDKRuPFRSTPT29PTy9Ozq7OTi3Nze3NTW1MzOzMTGxMTCxLy6tLSytKyurDQyNMzKxOTm5OTi5Nza1NTS1MTCvLS2tLSyrKSmpJyenJSWlIyKjHx+fFxeXBwaHKxuPMzKzLy6vIyOjHx6fDw6NPy6dGxubLy+vISChCQmJNza3KyqrBQSFLR2RKSinJyanGxqZAwGBJSSlCwqLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeDAYqKiIeLj4wBjQCMhY+NkoiLk5qbhQIDoJyGBAUGBwgEo4MECQoLDA2pDrS1tKQPEAwHERITE77AvxKqhAQNDA8UFRYXFs8YBAQZGqGPxw0RGxwdHR4eHyAhIiMkJSYnKCgpBAYPEhcqHyssLS4kLzAxMjM0NTY3cBA4UCAHBw8gVnhgEcKFjhc7UPDj0cMHAAI/KFgY4YLFio/jRpTYsW8GDyCSCEQw2DChOHIqgsCQSEPIEEEEJFhAoUNECCJEyOk4d6KIyRtGcB7hIJKjixEjHu4oimSGEIs4d8IIUoKECnNB0ElMwkNJJgBLlJBAcQKGiR07KGAURVGViY0mhIwwSTKjr99+THjUoIg0r48hTRIrRtxkiOMhDgrZCQQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+fileprint22:file file22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBFxaXDQyNFxSTPTizOzi1FxORDw2NExKLPTi1Pzy9Pz6/FRWVPz29Pz2/PTy7PTu9OzezPzu5OzavAQCBPzy7PTm3OzazOzKrPTu5FxSRERCRGReXPTq5Pzu7ExGTMS+xKSmpOTKpPTq3JSCDNzSfHRydLyadOzCjOzOtOzSvLyyTMTCxKSipGRiZFROLPz+/KyurJyenJyWnGxmbLSabOzClOzm7LSutJSWlJSSlJyanGxqbNze3OTm5IyGjNTO1Nza3NzW3OTe5IyKjHx6fMzGzMTGxMzOzNTW1IR+hISGhKymrLy6vLSytERGRGxubKyqrLy2vLS2tDQ2NEQ+RASKBAT+BFxeXHRudAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4QBAgOEiYqEAgQFBgcGi5MICQoLmAQDh5OEDA2YCw4ODxARApKUCaGYEAsSCRMUnQysCwoVEhYXGLOLCBCgDqK5GQUXGooCAhscBB0euBUZEAUJvQgIgx8gIR8iCSPiHuIFEREDJCXaANwhJhsnKCnWERcRKiopFCvsBywhQrRwQWGAPAz5EhpQ9wIABRgKYsiYMTEEDQocatiwkUIEP18fbkCAAcMBjhwzdOyQwYNCgBMfKJSgMItBjxs+btwgCSGGjhw/ZoRgQKGZCRMUPgABEgSIkCE3SZok8qNqkR85NtDUEcPIkaVAkCR5SrJBDCVKlmzQ6pCCiRlMTJo4YUH3K5AeMBYYWctW0BOaUH60cBJFypQmII6wyEpFQBVFMSm4UAI3hJUrOGh8oOJrklYKWIromJGDR99Ogz5j4ZGlM+pEnwmBCwQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+filesave22:file file22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBGxqbAQCBLy+vERCRExKTHRydIyKjMTCxFxaXGRiZFRSVFRWVPz6/Nze3Nzm5Pz+/JyanDw+PExOTHR2dMTGxBQWFLSytHx+fISChOzy9Ly6vAQGBJSWlMzKzAwODJSSlHx6fIyOjOTi5DQ2NISGhGxubCwuLOzq7ERGRFxeXNTW1CwqLPT29Dw6PGRmZKSmpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAb/QIBQGBAMj8ikUDAgFAzKKCBwQCQUCcICKh0SEAhGw5EIZAmBrgCxeDQgcDJWyz0GIggJfL+XGwQJRxNgC3yGDwwUFUZDFhdthnwMGAZNQwEZFwQakXANBBQbHIIdERIBnRAOiR4ERx8gsSEMBBmGCyEGG3YGBwcgIr8UCwQHECOgG4xCtRkEJAvBJRklJgkSFBQeJ68hJiEoESkFKiEZIbkGARsLlwEGExENGhorGSkpFAYm66NDLAECpGiBYsUIFA8wLHBBQMWLVkdUCFCwaYVFBOymkVCgYEMgOykEpICBccMBAhhELFigTEqAAgIIwCiQ4eRKDyS6EAlJIAI0EpaudF4iIKDAAn9CkRT5eMROEAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+foldernew22:folder folder22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBNzaTPT2FISCBCQaDPz+BExKBDwmFPSubPzChPzCfPy2dPz6BMzOTAQCBOSmZPzKlPzSnPzOlPzKjBQODPz+rPz+3PzWnPyuZPSmXNyaXPTyhISCLIRSLEQuFEwyHPy2bKRuPFRSTPT29PTy9Ozq7Pz+xJyanDQyNPzGhMzKzOTi3Nza3OTiVBQWFDwqFKxuPOTi5JSSjISChHR2dGRmZFxeXPS2dNTSzNTS1OTm5KSipLS2tLSytKyqpIyKhGRiZNze3NTW1MTGxMTCvLy6tIyKjCQmJMTCxMzOzMzKxJyenHx6fLR2RLy6vJSSlHx+fDw6NLy+vIyOjAwGBGxqZKyurCwuLBQSFJSWlCwqLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeIiYqLjI2MAY6HAgOHBJYEhJCDBQaDmgcICQoLB4MGDA0OAQUBDg2cAAcPEBESE6QUuQasFRYVq5SxCRcSCggYGRjIGgYbFs8bHIMHExIJGR0eHx7cB83PFhsDDuTUEyAhIiMjJCQluwEmvsAnKAcp1x4qKyUrLLupWrByxcnFiwQIYIggEaNEiRgBZMyYQaNADRs2REA6cCODBxw5+OnQgWMHjx4+BND4MQOIg1gI0gUREkTHiplDhhApEoCGkRlHBL3I8MEHEhz+WAhJogTJySVMfthwIehAExE5jubAkYQpESc8fOx4AiXKNA8+ekhBgqSpzh5hPHcsmVLjpSAqVZBY6VGkiJMiPQKLnTvjCiEsWU4o3nGC8YksMmT8YCmC6iAXKLRc2cz5yGYtR0JjKWQgEAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+mailforward22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIcAAJR6fIxydIxubIRqbIRmZHxeXHRaXHRWVGxSVGROTFxGRFxCRFQ+PEw6PEw2NEQuLPwCBJR2dLyijPTixPz69Pzq3Pzy3Pzu5PTu7Ozi1LyelOzavPz+/DwqLLyafPTmvPz67Pz29Pzy7LSWlPzmzPz6/LyajPTitOTSzMyurPz25PTatPTi3KyOjPzuxAwqVDQiJHxiZPTetKySlPzqvPz27BQ6bAwmTPTexLyinNzGxDRunPzy5KySjCQ+ZNzq9KTO7JzC3Nzq/Ozu/LzW7FSm1BR6vGSWvFyq1AyGxAxytAx6vBSKxAxSjMyujLSunES+5BSi1ByGvAQCBNzCrOTaxNTOvMS6rKyelCx6rBx6tBQKDOTWvPzu1PTq1OzezAQOHAxGdBROhAQGFPzy1NzOvIRqXLyynOzarPz21Jx2XPTWrLSShAw2XKSCbPzuzAwePAQCDPzyzPzqzPTmxOzWtAwGBKyObOTSrNzGrKyGbOzatEQyNKyCZOzWrOTGpNS2lCweHCQaHCQWFBwSFBQODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBhBwgQKFSpY0HgBQwYNGzh0mDhRAAUPHziACEGBpYgRJDiUGEkSwoCQJk6opNASRQoOFETQJDkggwoOJlYApcCihQuVL2DUhBDjhIqjJmRwwDCDhswaNm5MjYHjKggOOU7o0CGTA9gdYknG2KCCBw8VJVL0uBgihAUfP+CSNGCjsI/DiBPbAMJBsEQbQYQM+UG5smUiRYw0jlvYxhEkSYyIHm1EyRLTTH40EZvAyZPOR4pAmU07ipIkUKQ0mQIhAZUqVq5gKXzkSBYtyLVEyd1ki8QFXLp4+WJFQowbYLJnD5NbzJiJCjaQnhnvpYwZM0/OPFlvQ/f3iQvQpBlvQc0aCWy4VKnCpY0Y5yQxgEYXZFjghgwZUOHGCW90YQEccUwloBwGyjAHHXUoSAMZb0xhx1QOoMHDHSfIwSEOdTjhAQ1d4MFbTQ6Q4MYacrzxhhx04JCHHhvQsMeLJPHRBxpr+LHCGnusgccfgKixQR1ATtTBlDDAEIggggxCCCGFbLGFHVFKZEdAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mailget22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBBQ6bCQ+ZAwePKTC5Ozu/NTi9GSWvAwSJGSu3JS+5CR+rAQOHPTy/AyKzES23AwOHCw+bOTq/BR6xES+5AwmTBw6ZMTW9Ax6tByi1BRGdAw2XAQCBDQuNDRupKzS9FSm1BR2vBym3EzC7CSGxBROhNTW1Pz+/OTm5NTO1AQGFNzW3Ozq7Ozm7IyKjJyWnMzOzNzq9Nze3OTa5Ly6vCQiJGReZISChKyqrAwqVBRWlOTi5MS6xJSWlNza3OTe5Ly2vGxmbKymrIyGjMzGzISGhKSepCQmJDw6PHR2dJSOlPTy9MTGxLy+vLS2tMzKzLSutMTCxLSytKSipJyenKyurJyanCwqLCwmLCwuLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4IBhgIBA4SLjAABBAUGBwiNlY4FCQoLDJaNAQ0ODwsQnYwREhMUE5ylFYYRFhcYGRgaGxsDHJUdFR4SHyAhEyIjJCUcuo0cJr0nExihxgwoyYscKSnMHicOIw4lKissLdWDHC4vMCu9McYqMjMyNOUANTY3OPEoOTolDCszdrSgwaMcBxs9TMxYOCMHBx8zfPj48QNINQ5BbMBIIUShDIUoTAhR94PHPEEHbQwZckOGjBQviMxYUWQIDCMmdXE4gqRnkiFETAxR8iKFjJU2evZEdmLJkgJIbqS4wXJIUapImj5FtuSEVyRVV1IVi4RIChhEkLVAgcJHEqVwVJUmYdKkiRNkALMRecKECRG/ff8CEQJFCA5kMKJEoUHDCQ/HkB9LmWKECpUeyKoIMSLEyosen0OD7iH2xg1dV7BkqXGlBpbWNTq4Zn2khu0aAAwEAgAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+mail22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBDQyNCwqLCQiJBwaHBQSFAwKDAQCBDw6PPz+/Pz69Pz27PTy7PTy5PTu5PTu3PTu1PTq1PTqzOzmzPzuvOzitPTmvOzivAQGBDw+POzevPz67Pz25Pz23Pzy1PzyzPzqvOTavERCRKSilPz21OTevIR+ZExKTOTi3JyanLS2tPz6/Pz65KyihJSKbMS6lExOTNTW1JSWlJSKZMSylNTOrNTKpFRSVPz29MTCxPTmzKymjIyCdOTWxOzexOTWrBQWFFRWVOzu7MzKxJyalOzatLSulMzKtOzmxOTarFxaXKyqnPTmtIyGdIR+bOzetOzixBweHGRiZOzm3NzWzNzSrOTetGRmZOzizOTexOzm1JSKdGxqbHRydJySdHR2dOzapHx6fKyijOTixCwuLHx+fFxeXERGRDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4SFhoeIiYqLAQECjwORAwSUBZYFBpkHmwgJCgsMDA0OD6UQERITFBMVFhcVGBkangq1ChsLGxwcHQ0dHR4fICEGIiMSCbS3uLq8wCQUJSYGJygpKhQJKyvLLM4Nwi0uLwUwDQsxMtmeuQveHR8UMzQ1NgU3Dgo41jk6ns0cKOzgYaOHjx9AgjTAUUvIECLZNmxoUISHkSM9KiBJQkCJA4kKEoBQoWJJAiYtmjh5AmVCsCJRpHzckKCCySlUUvBYUqUHDysSPnxIEuXKA5pPRiRwxwFLFhRaIEDYUoEChCcDuECoOWKFuwW7nHkg4WELkw8/BHRRwESpt10dU8SSHevlRxIBX6C0WBE27q8GZMkKbTADjIAwYlb4GLMYShYoPTRo6FGiSJEKPyzMIFMmzJcvXbhwkSLFjJkbQW6cOHNGhAgEAdAsmk27tm0ABgIBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+mailreplyall22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIcAAJR6fIxydIxubIRqbIRmZHxeXHRaXHRWVGxSVGROTFxGRFxCRFQ+PEw6PEw2NEQuLPwCBLyejPTixPz29PTu3Pzu5Pzy7Ozi1LyelPTavPz+/DwqLPz67PTetPz69ERCRLSWlPTmzPz6/OzexLyajPzqvDw+PDQ2NMyurDQiJPz23PTatJyenAQCBPTevPz25LSajOzq7HxiZPTexPz65JyanBQ6bKSmpBwuTOTi5OzaxBRCdHySvGRiZHx6fBQSFERGRNzq9IyOjHx+fGxqbPzu3BwaHFSq3Aw6XAxKfPzy3Gy63ByWzJzO7Mzi9OzavBRytAx6vCSazGRKTPzy1AQKHBRGdBRyrDy63ES+3Cym1CR6rBwWVAQSLAx+xCyCtBRmnPzuzAQWLAwePPzyzKSCbAQOJByGvOTWvPTmxBQODFQ6PPTWrPzqzOzatAwGBKyObLSWfPTivKyCZEQyNKyGZOzWrOzWtOTSrOTGpNS2lJx2XDQmJCweHCQaHCQWFBwSFBQKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBgggoQJFCpkzGjhAoYMGjZMpMghQgcNFjh4mODhA4gQGkSIHAmBwAgNJEpo8KDSxAkUGjhMSEGz5gUVIiKs2PmBRQudHiwQpUnAxYsXImB0aBqjBcuoU0fKmPGChgUNH2qIqGHjg9u3bicWIFs2rYgbNnDkyGFhb8cccQ3ouJqWQo0dPFr0WMy4h48LFj4gsKriB5AeNngEaSGks+chPnwQOXFAh4oXRYxk9nAEyY7XO2wksWHDx5ATCDIoUXEBsYclTJo4cWJhuIjhSXacSPBEiZLMQY4wgRKluvXqUpyIsDElAxUqVaxcwcGCPQuWLOixaNHCZAsXBU+oqKDSxQqULF6ifNmyn/8VMOtxwcAK36kQRhdJQIFFEmKM4eCDYGyhhYAEkqFEGSuYYcUZLaDxXRpqSNRCEu6twYaFZXTQhgRd2NCCG9918AYELTjoXgNuKAFHB2RQEUYHVbQQRwlUpPHGGFwkyQUEDsgxx4lh9BhCBy2U8UQJcrSg5JIQ0FEHG3bc0QGYK+CRhx57PEGlkhM9sAEffKTQhx9+/AEIIIGoEUgLLRRFR0AAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailreply22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIcAAJR6fIxydIxubIRqbIRmZHxeXHRaXHRWVGxSVGROTFxGRFxCRFQ+PEw6PEw2NEQuLPwCBMSihPTixPz69PTq5Pzy1Pzu5PTq1Pzy7Pzu7Ozi1LyelPTavPz+/DwqLLSajPTetPz27LSWlPzmzPz6/PTexPz67Pz29OTSzMyurPz25LyajBRCdPzuvDQmJOzexPTevOzq5BQ6bBwuTDQiJHxiZPz23Pz65LyinPzmvBxCbHySvAQCBOTi3OTq9CweHOzaxFSq3Aw6XGy63ByWzJzO7Mzi9OzavNzq9BRytAx6vBR6tPzy3AwOHDy63Ax+xCSazCym1CR6rBwWVOzizAQSLES+3CyCtBRyrBRmnGRKTPzu1MzGtAxKfAQWLAwePPTizMy6nByGvNzWxOzWrNzOtBQKDJR2ZNS2lPTmvBQODPTatKSCbOTaxLyqlAQKHFQ6PPzyzPzqzPTu1PTivOzWtKyObPzuzOTOtLSWfPzqvAwGBKyCZPTWrPTmxNzKrEQyNOzatOTGpJx2XCQaHCQWFBwSFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBgggoQJFCpYuIDBQgYNGzh08DCR4oQPIDqEmDBhJQYRIzqQIFkSAoESJCKkDGFiwgkUKTpMwECz5IASKjqsSMlSA4sWQjG4qGnzhYoQSmF0iCFjBgmWGWhQrVHCxg2sOHLo2MGjB0sLYmsWQHq1p4wdPtqemGDhB1UDQFSouKHi7oQgQmSwUMyYxcQDZQWz2EFiCJEiRoyQyLzZyGIIB47YKLwDSRAiSZSoXq1kCRHNLBK8YGKjCYskTp4ogeKkt+8oUaBImZKAAxMmVKrctqL7ihTnz7FkAT5FC4cKFbZwadIFdxcvX8KLss8iJcoUBUcq2KgAJoxyMTy4jCFTxoxEHl2GLyCDncmWM2hUIQMPY2CXhhoTfTEcA2tgVwEba7Thxhs88FdBD/ZB8MUUHMJBRhw2sAGCHBKU4UaFc1RAhxnhcdhhHUzYAUIcFdxRAh4R5KGHinu4OIVEDqTBRx81xhGHHzD8wQYQetDRI4cTAcIHGWT0EQgZa1ApCBqDcBAID1Q94IEHLtBAAyGEFGKIIWqYYQYPYNZkQEAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+mailsend22:mail mail22 22:photo:22 22:R0lGODlhFgAWAIcAAIR6fIRydHxubHRqbHRmZGxeXGxaXGRWVFxSVFxOTFRGRExCREw+PEQ6PDw2NDwuLPwCBLSijOzixPz69PTq3PTu5PTu3PTu7OTi1KyelOzavPz+/DQqLPz67LSafOzetPz27Pz29KyajPTmzPz6/NzSzLyurCwiJPz25Ozi3JyOjPzuxBRGbAwSHOzexPz23KSSlPzqvBROdISavBxSdAwaLHRiZLSinNTGxMy+vBxGZNzu9BSGrAwWJMSyrKSSjFy61ETO3BRWfPz65PTqzHTK3ByqzBSWxEzW5AQWJOTWxBRCXOTu9BSOvDzO3ByavBRKbOzaxOzizKSWlCQ2TAQCBJza7BRWdNzSxJSCbMzq9BSOtCSKrAwiPOTavPzy3LymlCySrAwmPFRKTPzy1NTGrPzu1JR+bOzatPzyzCy61ByGpOzWtJyCbPTmvPzuzIS+3FymxCSuzBR6nJyCZOTWvKSObMSujOzivAwKDOTSrNzKrJyGbDwyNOzWrMy2lIx2XBwWFBQSFBQODAwGBAQGBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAWABYAAAj/AAEEEDCAQAEDBxAkULCAQQMHDyBInBgggoQJFCpYqMDxAoYMGjZwmEixg4cPGzqA6BBiAggRIzaQGEkSwgAMJCKgnNBhQogSJlKGOFHTpgYUG0TsnJBCxQoSE1i0KErAxYsOJJRuuAAjhkwZM2jUqGnDBQoUHTbciIEjx4YNOmbs4CGjB8kCZlGAALHBx4+YcTcACcJDyFSJBo6iGNIhhQkiG8BOKGLkCBK6SSQisHoWhZIbG5bMYALECI8mTZw8gTL1QJQXZ6VMiUylSpUlVpoYaXLFtm0EGmCjwJLlA2O9MrRsccKlC8kEXr7AdgEmwtkhX2SQ2BIkjBiSYzSQr/nyhUKZLIrJJOcexvlEBV7IvCBjRkmAMzHOaufhxDvJBWiQISAFxUUQQRovJNeEGmu4JxEDbKQhXxsfuFDGGW68IQMcccgxRxUkNRDhC3R8QMQIdZwXQ11JJGFbiB+QYccHaaTxhgt13OFBDGTgkUdRDrhAhx5k2JjGCB/swYcXMXwAYk190OGHHx/4wUaVepTxByAaoPEkSQ5wwMEJZAZipiCDDJIHIYV8OZEdAQEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+nav1downarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBBQSFAQGBDQyNExKTHx6fGxqbFxeXGRiZFRWVDw+PAwKDJSWlOzu7LSytJyenJSSlISGhISChIyOjFxaXDw6PPz+/MTCxLS2tIyKjKSmpKSipJyanAwODDQ2NHRydERCRFRSVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZzQIBwSCwaj8ikcslsOp/OgHRKlQoCgymRUDAcEIkwYgxWFBYERpHQcDwgEclEQmk8DhWL2kiIXDBwExMNGRoJaUkEEH8bEQ0cGgcWAksEHX8QHBKSHk1sfxMHH5ROBBsOICGkT2wiq1CIULKztLW2t0h2QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav1leftarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAQCBExKTJSSlHx6fAQGBOzu7GxqbJyenPz+/LSytFxaXMTCxGRiZKSmpISGhFxeXISChAwKDFRWVHRydJSWlBQSFERCRIyKjDQ2NIyOjLS2tDw6PBwaHFRSVDw+PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZ5QIBwSCwaj8ikchgQLJGBgfNZDBAKBirRekBMtYGEYsHIgsWNhOO7tCrShDU18Hg/CJAIG0o4wCUQcksTFBUSCRYSEnpUFxgIGQkJGYyNGggbHBaVjR2QCxEeWkITHQ4IH3tPFwEMA2ajAKUgqlQTTbFEE7W5vUgGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav1rightarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNGReZAQCBMTCxGRiZMzGzOTm5LSytPTy9Pz+/CwqLOTi5Ly6vCwmLMzKzJyanJSSlBQWFKymrIyGjCQeJJyWnISChISGhHx2fKyurDw6PAwODHx6fHRydDw2PERCRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZ2QIBwSCwaj8hkMRBQKgOCgRMZIBSk06XhEM0SA4iE4uoVLhCMhqLrdSAekMgYO5VM4BQ521mxIC4UFxBWdEkSERYYFxETGQGFSBKCGBEaGRuQSBwdeZaPXpsQCB6YZQMdEI6ZSgMepKusHh+wrCC0rLdlursGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav1uparrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBFxeXDw+PMTGxHRudPz+/JSSlLSytIyKjHR2dISChIyGjIyOjLSutLy6vKSepJyanISGhJSOlOzm7Ozu7MzGzKyurJyenDQyNGReZKSmpIR+hCwuLCQiJBwaHBQSFAwKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAZtQIBwSCwaj8ikcslsOp9QYyAQFQYEAyr0Sihkn1fDAeHVLsOJNELxVaITC0bDUU6GH5AIQ8KYrNtFVxQVFBYWFxgRCREYdUQZGhYEDwgIGxAHCQocCgWOQhmhGR0epR8gqCFTq1Wtrq+wsUt0QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav2downarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBAQGBBwaHDQyNExKTHx6fGxqbFxeXGRiZFRSVDw+PAwKDJSWlOzu7LSytJyenJSSlISGhISChIyOjFRWVDw6PPz+/MTCxLS2tGRmZDQ2NAwODJyanKSmpKSipIyKjHRydBQSFERCRExOTFxaXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAasQIBwSCwah4FkQKBsDpoBIqFgOCASCYRWm1AUFgRGkdBwPCARiWRCaTwOFYvYSIhcMOiJpJGZaDYcR0IEHXceEQ0fICEWIoJDhHcQHxIHgI9SEHeVG46YUh8OISOen1INCqWmUnOYTUxQAU9NUlRWWFtbCiRgrYNlZ2lriG8lYUd1khETE24gCZeCkRgeFBAQIAeNn9OTlXKrBJoYnKrcoaPmpmSpq3S+7u50QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav2leftarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAQCBExKTJSSlHx6fAQGBOzu7GxqbJyenPz+/LSytFxaXMTCxGRiZKSmpISGhFxeXISChAwKDFRWVHRydJSWlBQSFERCRIyKjDQ2NIyOjLS2tDw6PBwaHFRSVDw+PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAavQIBwSCwaj8gkMiBYNpeDZzEQXRIKBmPgmtUSDgipcAsWjxOKBaN7Tq+n6EbCIQ3E5+KtQk6gjwl7CX11D3sPBBARTQGFDYeJT2R8EhB0koKUfgATFBUSCRYSEoqcnqCiikMXGAgZCQkZqautr7FiFxoIGxwWqQC4ury+qh2tCxEexMbIRhMdDggfYs7Q0kcXAQwDbELY2txEziBmmx3jSRNMR+nk4e2b70ry80QGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+nav2rightarrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNFxeXAQCBMTGxOzm7CwqLLy2vPTy9Pz+/Ly6vCQiJLSytLS2tLSutOTi5MzGzKSepIyKjJSOlKSmpMzKzJyanIyOjBwaHIyGjISGhJSSlISChBQSFJyenIR+hGxubDw+PHRydHR2dEQ+RHx6fERCRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa6QIBwSCwaj8hkIIBcJgEBweAYnTYJUmMAa9USClniFtwlGg6IRFhoUKTXwwWj0FB3F46Hwl6UQyISfAB+EROCQgsUFRYSF3yJEIyBaxgWDBkaGRtclQwSHBIbEGEdGx4fGhcOICEDGBsWHBmqIq1CHRIWGRMMIyRTHRy6Er22tyONq8YdJRe0xkIDwr2/QwMfliMmZQADIxasZd4e4UYDIr7c59rc0eVFA+/m0EQD9PDt0flP/P3+BkEAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+nav2uparrow22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBGReZDQyNMTCxHx6fPz+/JyWnKyurHx2fDw6PJSSlISGhIyKjIyGjISChLy6vJyanOTm5PTy9OTi5MzKzLSytKSepMTGxMzGzLS2tLSutKymrHRydCQiJCwmLBwWHAwODLy2vHx+fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAajQIBwSCwaj8RAAMkUBgSDZdP4JBSi06TAcEAkFNLp07BgLLzY5njRcDzO3zB1C4lEGI83Wj58SiYUFRUWdg0XEXFFAwIYGRoWGxwRZQUFHZdgRAObmx4fHiChISFKpVlKWUdPaalOAlasp1sHG4myZGZ7Yltsbgu1mUhjdRF5egmxfQJ/gYOFdrZDi40iFgiSCw8jBQmYcpydn6Ego6WorUwGQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+navback22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VCRGZAxCZGyavExmjHyatOTy9CxihISevPz+/KzO3BRylAw+XAQCBDRWbPz6/FzC3CSuzDyexJzO5Mzq9CxSdAQOFISmxNzu9HTS5BSmxAyexDSuzJTa7Mzu9Kzi7GS21CRmjAQOHHSWtLze7AyWvHzG3BRihAQKFCTO3BS+1AyixBSWvBSOtBSStAQWJBSixDzW5BTC3BSqzBS21CTC1ETW3AQSHEze7BRqlBRmjAQCDBR+pBRefBRSdCH5BAEAAAAALAAAAAAWABYAAAalQIBwSCwaj8ikMqBcMpvHgGAANQYIhWdVGDAcENQtIJBQLBgNx0MQaDuQXcghIplQDhBIxXKJYiAZGhscHR4VHyAhIiNWJBklGhIbJoQnFCcTKIxFKSgbKissJi0mJi4vLiYoMEcXKDEyMzQ1Nje2NisoOEg4KDU5K6g6OwwoKAN9SCOeMmgwz884PEq9PT4NYkPLP9jZQikN3d4AKVrjKePp3gZBACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+navdown22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VCRKZDRSbBxCXJTC1Mzi7Nzq9NTm9Bx2nAQCBNzu9JzG3Hy+1HzG3IzO5BRmjPz6/LTe7Dy61AyStCTC1FzC1AyGrETS3ETC1ETa5BRulAyuzBRylAw+XMTe7Gy+3CSqzAyexBTC3DR+nIS21KTW5Nzu/KzO3FzC3Pz+/ByixEze7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaRQIBwSCwaj8ikcnkMBAQDgjPAFAYKhsMBkVBUAYEFo+F4QLzVQEQyoVTOX/XBcsHA0+vMRbNBMwkRDhxuHX5GTlIeHh8gISIjFAEeiVRECiQlDAUmgxQjIhwiJHdFlycoKSIUFCEjGiGkRpcqCxYijxorsUezcxYsuoZJsxLAu0qXB7DCTJfHVQrMX9PU1Uh0QQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+navforward22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VAQCBBxCXDR+nIS21Aw+XJTC1Nzu/KzO3Pz+/Nzq9Pz6/MTe7KTW5FzC1Nzu9CRKZMzi7IzK3Lzi7LTe7HzG3Gy+3AyuzAyexFzC3DRSbHy+1Dy61CSqzAySvAyStLze7IzO5AyGrETa5ByixBRmjCTC1ETS3BTC3Bx2nAyWvEze7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAaYQIBwSCwaj8hkMqBsBgTN5IAAjRoDBaq1aDggtMuAWDzoJhTgY+CwYLgZDccDwkgXI5IJZVGxXDAZGnR2QxsLHB0PHRgeHyAZDyFfVUQDCyIgIyCPIB+QJCUmlEMBEiInKCQnKSkeKSQeomoqJrUmKiArKSwZsmoCwMEBGCyxo1EGHr3HUQEEvltCBtDRAAbMW0zV29xDBkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+navhome22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIYAAPwCBAQCBCQiJNze3ERCROTi5MzGzLy6vDw6PKyqrKyurBQSFGRiZGxqbGRmZISChEQ+RExKTExOTHRydDQyNOTe5FROVLSurCwqLMTCxPT29Pz6/LSutFxeXLyytLSytPz+/JSWlKympPTq7KSipNzW3BwaHHx6fKx2VJRWNHQmBFweDOzq7Ly+vNTW1JxWNLSajPTe1Ny6pKxWJNTS1IyOjJRmbPTi3OzKrNSSXMSGVHQiBHx+fJSSlPzy9IxOVOzWxOSyjNSCPLxeDJyWnIRGTOTGtMxmDLRWBHwqBIxGTLRSDDQuNNSunKxKBGwyNMSafMxqHMReDKRGDPTu9LxuPLxaDJQ+DIR+hGQqNIQyBGQiBNTO1EQKBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAf/gACCg4QBAYSIiYQCAwQCiokEhwACBQYHBAiQhAiHlQYJCgkEC5uCkp8MDQ4NDwylmwgQlgQRERIEBBOkmxQVBgQWFwUFFxEEDLyJGAUZtQoFGhsFHLYdyoOVHsEf0SAbIAUex8mwlAUhtSIFG+3uIyTWvAIGJMEkJe76GyXbEeWUBJg4USKaBhQpVKzYoIFFiwYUBBJa8MAFCw0vYMSQMWOhBhoTKCQSUKMEiw02buDIoWOHBg0GeIhEFKAHDR8afgAJImSIioYliMws1MPkhiJGchxBkmTDCBo1hg4KQMTiBiUyhBxZ8pNFiR5MEtU0WqSJVidJNDyNKraHC5xPNKBEkTLlJ5WvUgWNvfikyhArV34+7ZEXQAAsB2iUyHLlihYtW0pwOYAFgyJDmDNr7jIIWiAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+navup22:nav nav22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAw2VAQCBHSWtBRmjAQOHISmxNzu9BSmxBRihHyatPz6/Lze7CTO3BSixHTS5BTC3DzW5ByyzPz+/OTy9AyexEze7ByixGyavKzO3FzC3AyWvBS+1BR+pAQKFCRGZExmjCxihBRylCSuzBSWvBS21BSOtBRSdAw+XAxCZDyexDSyzCTC1JzO5JTa7DSuzETW3BRqlAQWJDRWbOT2/Mzq9HzG3JzS5Kzi7BSStGS21CxSdCRmjAQOFAQSHAAAACH5BAEAAAAALAAAAAAWABYAAAaeQIBwSCwaj8ikcqkMCJjHwIBQgBIDhgMiUbUGFAtGw0GFfheHByQi4S6/E8pDUoFYLm5kAEPJaBAVGxIcER0JHlEfICEiIxUkGyUmIgknKIhXASkonCorgSwmKQGcKE9IAi0uLxUwMTJWMzQ1NiYwBLBQHws1N7avXgs4NjkcCblMATU6KhvGyG87PAnUKV1MAj0+2zIFp1bg4eJJdkEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+playeject22:play play22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAwKDJSWlFRSVBQSFKymrOzq7HRydERCRPz+/MzGzISGhJyenKSmpGxqbJyWnJSOlKSepLy2vIyOjGRiZPTu9IyGjLSutFxaXExOTHx2fGReZAQCBAQGBBwaHCQiJLSytKyurJSSlFxeXNze3LS2tIyKjFxWXHRudAwGDBQOFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa1QIBwSCwaj8ikcqkMCJjHwIBQgBIDhgMiUbVKFQsGItBdBhpgh4PxIJvRC8cA4oiMy8bvQhJhMAYTFBVOURAWEw0QFxcMERAYCBluVxobDxkVHJocmBwEGgmEQx0dHh0CpKmkH6odVlanBR8FtAIFtiCkSB0LISEiGCIGIxAPDySuRwIOBwrOzwoHJRHJRh0jJgMj2gMnERQUCNVFHQQoCBvo6CkICATjRB0qp7b1K6qv+foyQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+playend22:play play22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNFxeXAQCBMTCxGReZBQSFOzm7AwKDKymrJSSlFRSVCwqLLy6vPTy9OTe5Ozq7CQiJLSytOTi5BwaHPz+/HRydMzKzKSepJSOlKSipJyanIyGjIyKjKyurISGhMzGzJyWnHR2dISChIyOjLSutDw+PERCRHx6fJSWlIR+hJyenGRmZHx2fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa6QIBwSCwaj8ikMBBQKgOCgRMZIBSkxYHWoDVWD9EigpBQLLBERsPxCA8NDUhjgTBGJJNGG02RVBQWdUV3FxgZe0IGfoAGdhoXGxwdiAYef4FGFBoeHB8dGSBRihUhIo1FBhkbIyMkJRYmAwYal4JEBh2RChIWJ1IIGxUZFqdECCgkHR6wWAYpFR2YWSobvL5vFgfDaEMDIivMRBEsD9HcQgMWvecDLB0tZ0btsfJa9vLXU/X6/P3+b0EAACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+playpause22:play play22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBAwODMTCxKSmpJSWlFRSVAQGBBwaHLSutOzq7Ly6vCQeJPz+/Hx2fBQWFGxubLSytJSOlBQOFAwKDJSSlJyWnIyOjHRydNze3GRiZAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAWBICCOZGmeaKqubOumQSDEgRjPMSoMRGEcol3vh0IkFAtDDWBEKlGMRKPgEIii0yrqIS1ArADu9KuLNCSOSdCMVp8ohEZFC4DL6SaBpXGh6/l4JX8XZACDhXkYCn1LAoqMUBAZEhBLDJKUSyYBGmhPAJyemiU0NDaloy+qq6ytI8whACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+playstart22:play play22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBDQyNAQCBExOTAwKDAQGBJSSlHx+fBQSFMTCxKymrFRSVOzu7GxqbLSytLy6vJyanPz+/GReZBwaHHRydKSepKSipGRiZJyWnAwODLSutKSmpISChPTu9ISGhFxaXJSWlIyGjJSOlERCRIyKjDw2PIyOjLy2vOzm7Dw6PLS2tCQmJOTe5GxmbDQ2NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa7QIBwSCwaj8ik0hgQLJGBgbMoqBIKU2LAcMgOEQmFYeEFbBmNMgDhYDwWBC0k4pCoJ46IgRIXBioRCRYXamwRGBQIfgaBFhiERhkaenxmCoEbBhyQRYaIGVsdghgem4UWegcEBB8UHhsgIaZGBBgRIpUIIxQhChginEQIIBEklWslFyYnBsFfFCi4WQgpFBwqFxNGKxcsxl4IAS0NZEYCF3vlwgEfUuZV8JEuI2pPAARN9kcE9fr+SwaCAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+playstop22:play play22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBAQCBAwKDBQSFBwaHCQmJJSSlISChJSOlJSWlGxqbGRiZNTS1PTy9Pz+/Ozm7OTi5FRSVIyKjOTe5MTCxIR+hExOTHR2dLy6vLSytLy2vHRydFxWXIyGjIyOjPz2/FRWVHx6fExKTMzOzJyanKSmpKyqrKSipAQGBLSutHx2fDw6PAwODAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAa1QIBwSCwaj8ikcslsAgKCAWEQjQ4KgSwyYDAcugZEQqFYYJECA6PhaLcfEEUkgJZAGJB8fkKpWOhHAxcOGBQZGBoaGQgbHIBGAhUOGR0SBxISBh4Xf0iCHxQSlRIIXhsgj0UCIaCXmJgHGyKpRJ+hmB5dHQqOaCENIx0epBIkBhdzngoPGCQlJifQJBvJRygRKRcKGxcXGypys1srEREc5SLnICLiR1koLFVUWfRO9vf4+UwyQQAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+textblock22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py30Bo5zBWUWzvNzo33GfFl5jVlonlTrr1DbvFi9vjeeNUQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textbold22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIxhI+py+0Powm0VnknjVkH2AEhE45LZ55Wqn6e65TsMc5eYosbksswubJIhsSiccgvAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+textcenter22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py30Bo5zBWUbz3Sh7yIWfFHKjVl4nmFrr1Lpr7LwkjeeIUQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textitalic22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py+0P4wqUSlQvttrkDnyaOHIdeaGRupplAIauVM3xjeeOUQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textleft22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+pyw0Bo5zB2UXz3Sp7yG2fFJajVjonmIor2TJvfL0wjecIXQAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textright22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAImhI+py30Bo5zBWUfz3SZ7yIXdF4kWqZkbCqoMO7kXLC+wVOe6YRQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+text22:text text22 22:photo:22 22:R0lGODlhFgAWAIQAAPwCBAQCBBwaHAwKDBQSFLy+vLS2tJSWlBQWFKyqrFRSVCwqLDQyNNTS1GxqbFxaXJyanIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAVcICCOZGmKQSoMaZsShBsQBdAapHvgaIDUqUPJlRjSbAoT0fRDKgODRbF0PLUYjZO2F2Bst9evNix+dsvDlGKK5jraudQb7qbX6a2HEJ+ycyF+LRE8ZTI+fX5oGCEAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+textunder22:text text22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIvhI+py+0PowmUnhpeVVnb1DkbCI1I2JhX+Z0sOr2cTHpwK7a4rUr+hAnufsTirwAAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewchoose22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBFRSVExKTDQyNPz69PTq5Pz+/OzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARTEMhJq70466Cl+AMxBVwnFIVRAmQHCIeBrC1L3tQgJ/SaEbeeC1PLBHE2ybFI9A1HzstHEIK6YCmhDTmBybQaHYJn7QC5zKeytIQe1+pKNE6P2yMAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewdetailed22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBFRSVExKTDQyNPz+/Pz69PTq5AQCBOzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAQ+EMhJq7046817+MLQUQFRGMc4lQaSAkcMx3QltMmrDrSu/sCgEPgJhIiFk89DaL1qPRnlhsgBebWhdstVESIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewicon22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBFRSVExKTDQyNPz69PTq5AQCBPz+/OzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARWEMhJq7046z2DF0PlBeAVEERhiKhqHgWyUgEsX0KczFOO7JeBYciTCImc5ITIXDKHyqhU9AnRqq9UEVDTvmLbGhin2/qAliOUot5OLc81IO5+2+8WewQAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewmag-22:view view22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFJyanKy2tLzCxHyChNTa3Nzq7Nz29Nzy9Mzy9MTu9OTy9Nzi5Oz6/OT29MTi5Kzi7NTy9KTm7JzW3ITO1Lzq7IzW5HzK1LS+vMTq7Jze7ITW3GTCzGS+zLTS1MzOzLzq9Kzm7Jze5ITW5HTS3FS2vLze5EzCzEyyvEyutJTa5NTu9ITa5FTK1ESirLTm7Mzi5FS6xEy2vESerESmtFSutESmrKyqrAz+/Dw+RAzi3ASutHRydAQCBAAAACH5BAEAAAAALAAAAAAWABYAAAbKQIBQGCgWh8jksCgYEAaCozIZKBgOiIRiwSgEpstCw/HYQiKRhBcMCBgQDodkMaFU0t9pQHCIyy0TFxgYEVF6GQ4LCQkaERscHR4RH3lUIAkWCyEiIyQlHiYjEJVIAQQJJ2gjJSUoKSorlHoCLBQcHC0lLikvHjCGejEiHBgeMjM0NRwPpFQFDBHFNjceHAjAYFWoI7cnCVE4OWxtex8QH1EBOjs4zUpGUjw6Pe3j2fP19u/47vrq9P3s/avno2BBf/MCClSob4iBIAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewmag22:view view22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFJyanKy2tLzCxHyChNTa3Nzq7Nz29Nzy9Mzy9MTu9OTy9Nzi5Oz6/OT29MTi5Kzi7NTy9KTm7JzW3ITO1Lzq7IzW5HzK1LS+vMTq7Jze7ITW3GTCzGS+zLTS1MzOzLzq9Kzm7Jze5ITW5HTS3FS2vLze5EzCzEyyvEyutJTa5NTu9ITa5FTK1ESirLTm7Mzi5FS6xEy2vESerESmtFSutESmrKyqrAz+/Dw+RAzi3ASutHRydAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbIQIBQGCgWh8jksCgYEAaCozIZKBgOiIRiwSgEpstCw/HYQiKRhBcMCBgQDodkMaFU0t9pQHCIyy0TFxgYEVF6GQ4LCQkaERscHR4RH3lUIAkWCyEiIyQlHiYjEJVIAQQJJ2gjJSUoKSorlHoCLBQcHC0lLikvHjCGejEiHBgeMjM0NRwPpFQFDBHFNjceHAjAYFWoI7cnCVE4OWxtex8QH1EBOjs4zUpGUjw6Pe3j2fP19u/47vrq9P3s/cunr9S8gAIRFhTCLAgAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewmag+22:view view22 22:photo:22 22:R0lGODlhFgAWAIUAAPwCBBQSFJyanKy2tLzCxHyChNTa3Nzq7Nz29Nzy9Mzy9MTu9OTy9Nzi5Oz6/OT29MTi5Kzi7NTy9KTm7JzW3ITO1Lzq7IzW5HzK1LS+vMTq7Jze7ITW3GTCzGS+zLTS1MzOzLzq9Kzm7Jze5ITW5HTS3FS2vLze5EzCzEyyvEyutJTa5NTu9ITa5FTK1ESirLTm7Mzi5FS6xEy2vESerESmtFSutESmrKyqrAz+/Dw+RAzi3ASutHRydAQCBAAAACH5BAEAAAAALAAAAAAWABYAAAbQQIBQGCgWh8jksCgYEAaCozIZKBgOiIRiwSgEpstCw/HYQiKRhBcMCBgQDodkMaFU0t9pQHCIyy0TFxgYEVF6GQ4LCQkaERscHR4RH3lUIAkWCyEiIyQlHiYjEJVIAQQJJ2gjJSUoKSorlHoCLBQcHC0lLikvHjCGejEiHBgeMjM0NRwPpFQFDBHFNjceHAjAYFWoI7cnCVE4OWxtex8QH1EBOjs4zUpGUjw6Pe3j2fP19u/4zT766vRI+fvHD4CPgwcJ9qg0UB85JA0dDjEQBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
+viewmulticolumn22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBFRSVExKTDQyNPz+/Pz69PTq5AQCBOzaxOTKpAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARTEMhJq7046813+MJQfUF4BURhHGO6noSBsEcNoDJtS4KcsJQe4ncZ1HYT47HDbDqfUAnJRJmKLIGCCjjJbmE5wBI3EyOFxKCPS1EiJW52dE6vZyIAIf5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3dy5kZXZlbGNvci5jb20AOw==
+viewtext22:view view22 22:photo:22 22:R0lGODlhFgAWAIAAAPwCBAQCBCH5BAEAAAAALAAAAAAWABYAAAIkhI+py+0Po2ShBlOxzbP7n2yaJoLm+ZTcxqHuC6hXzML2HVEFACH+aENyZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2ZWxjb3IuY29tADs=
+viewtree22:view view22 22:photo:22 22:R0lGODlhFgAWAIMAAPwCBAQCBFRSVExKTDQyNPz+/Pz69Pzu5PTq5OzaxBQOFOzKpFRWVFxWXOzexPTexCH5BAEAAAAALAAAAAAWABYAAARPEMhJq704g6A779kHCORAgNskFMYhakE8FkjyBcoWv+JwJItXaELYCTFHlCSpZKKcoB5jYHpOGgUadLKbIRw3jhEzQDyCSuI4zW673yhDBAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7
diff --git a/ext/tk/sample/tkextlib/ICONS/viewIcons.rb b/ext/tk/sample/tkextlib/ICONS/viewIcons.rb
new file mode 100644
index 0000000000..fc88eb5c85
--- /dev/null
+++ b/ext/tk/sample/tkextlib/ICONS/viewIcons.rb
@@ -0,0 +1,329 @@
+#!/usr/bin/env ruby
+#
+# viewIcons.rb
+#
+# -- Display icons from icon library.
+#
+# -- Copy the clicked icon data (command string of creating
+# a TkPhotoImage instance) to the clipboard.
+#
+require 'tk'
+require 'tkextlib/ICONS'
+
+class ViewIcons
+ #####################################
+ private
+ #####################################
+ def _create_controls
+ @controls = base = TkFrame.new
+ columns = TkFrame.new(base)
+ line1 = TkFrame.new(base, :height=>2, :borderwidth=>1, :relief=>:sunken)
+ line2 = TkFrame.new(base, :height=>2, :borderwidth=>1, :relief=>:sunken)
+
+ lbl_library = TkLabel.new(base, :font=>@boldfont, :text=>'Library')
+ lbl_groups = TkLabel.new(base, :font=>@boldfont, :text=>'Groups')
+ lbl_columns = TkLabel.new(base, :font=>@boldfont, :text=>'Columns')
+
+ ent_library = TkEntry.new(base, :width=>50, :textvariable=>@library)
+ ent_groups = TkEntry.new(base, :width=>50, :textvariable=>@groups)
+
+ btn_browse = TkButton.new(base, :text=>'Browse',
+ :command=>method(:select_icons))
+ btn_view = TkButton.new(base, :text=>'View',
+ :command=>method(:display_icons))
+ btn_exit = TkButton.new(base, :text=>'Exit', :command=>proc{exit})
+
+ @column_btns = {}
+ 6.step(20, 2){|i|
+ @column_btns[i] = TkButton.new(columns,
+ :text=>i.to_s, :width=>2,
+ :command=>proc{set_columns(i)}
+ ).pack(:side=>:left)
+ }
+ @column_btns[@columns][:relief] = :sunken
+
+ lbl_library.grid(:row=>0, :column=>0, :padx=>4)
+ ent_library.grid(:row=>0, :column=>1)
+ btn_browse.grid(:row=>0, :column=>2, :padx=>4, :pady=>2, :sticky=>:ew)
+
+ line1.grid(:row=>1, :column=>0, :pady=>2, :columnspan=>3, :sticky=>:ew)
+
+ lbl_groups.grid(:row=>2, :column=>0, :padx=>4)
+ ent_groups.grid(:row=>2, :column=>1)
+ btn_view.grid(:row=>2, :column=>2, :padx=>4, :pady=>2, :sticky=>:ew)
+
+ line1.grid(:row=>3, :column=>0, :pady=>2, :columnspan=>3, :sticky=>:ew)
+
+ lbl_columns.grid(:row=>4, :column=>0, :padx=>4)
+ columns.grid(:row=>4, :column=>1, :padx=>2, :sticky=>:ew)
+ btn_exit.grid(:row=>4, :column=>2, :padx=>4, :pady=>2, :sticky=>:ew)
+
+ base.pack
+
+ ent_library.bind('Return', method(:display_icons), '')
+ ent_groups.bind('Return', method(:display_icons), '')
+ end
+
+ def _create_display
+ base = TkFrame.new(:borderwidth=>2, :relief=>:sunken)
+
+ @icons_window = icons = TkCanvas.new(base)
+ xscr = icons.xscrollbar(TkScrollbar.new(base))
+ yscr = icons.yscrollbar(TkScrollbar.new(base))
+
+ icons.grid(:row=>0, :column=>0, :sticky=>:news)
+ yscr.grid(:row=>0, :column=>1, :sticky=>:ns)
+ xscr.grid(:row=>1, :column=>0, :sticky=>:ew)
+ base.grid_columnconfigure(0, :weight=>1)
+ base.grid_columnconfigure(1, :weight=>0)
+ base.grid_rowconfigure(0, :weight=>1)
+ base.grid_rowconfigure(1, :weight=>0)
+ # yscr.pack(:side=>:right, :fill=>:y)
+ # xscr.pack(:side=>:bottom, :fill=>:x)
+ # icons.pack(:side=>:left, :fill=>:both, :expand=>true)
+
+ @icons_layout = TkFrame.new(icons).pack
+ TkcWindow.create(icons, 0, 0, :anchor=>:nw, :window=>@icons_layout)
+ @icons_layout.bind('Configure', method(:layout_resize), '')
+
+ base.pack(:expand=>true, :fill=>:both)
+ end
+
+ def _create_info_window
+ @info_window = TkToplevel.new(:background=>'lightyellow', :borderwidth=>1,
+ :relief=>:solid){|w|
+ lbl_name = TkLabel.new(w, :text=>'Name', :background=>'lightyellow',
+ :font=>@boldfont, :justify=>:left)
+ lbl_grps = TkLabel.new(w, :text=>'Groups', :background=>'lightyellow',
+ :font=>@boldfont, :justify=>:left)
+ lbl_type = TkLabel.new(w, :text=>'Type', :background=>'lightyellow',
+ :font=>@boldfont, :justify=>:left)
+ lbl_size = TkLabel.new(w, :text=>'Size', :background=>'lightyellow',
+ :font=>@boldfont, :justify=>:left)
+
+ lbl_name.grid(:row=>0, :column=>0, :sticky=>:w)
+ lbl_grps.grid(:row=>1, :column=>0, :sticky=>:w)
+ lbl_type.grid(:row=>2, :column=>0, :sticky=>:w)
+ lbl_size.grid(:row=>3, :column=>0, :sticky=>:w)
+
+ @name = TkLabel.new(w, :background=>'lightyellow', :justify=>:left)
+ @grps = TkLabel.new(w, :background=>'lightyellow', :justify=>:left)
+ @type = TkLabel.new(w, :background=>'lightyellow', :justify=>:left)
+ @size = TkLabel.new(w, :background=>'lightyellow', :justify=>:left)
+
+ @name.grid(:row=>0, :column=>1, :sticky=>:w)
+ @grps.grid(:row=>1, :column=>1, :sticky=>:w)
+ @type.grid(:row=>2, :column=>1, :sticky=>:w)
+ @size.grid(:row=>3, :column=>1, :sticky=>:w)
+
+ def name(txt)
+ @name['text'] = txt
+ end
+ def groups(txt)
+ @grps['text'] = txt
+ end
+ def type(txt)
+ @type['text'] = txt
+ end
+ def size(txt)
+ @size['text'] = txt
+ end
+
+ overrideredirect(true)
+ withdraw
+ }
+ end
+
+ def initialize(init_path = Tk::LIBRARY)
+ init_path = Tk::LIBRARY unless init_path
+ init_path = File.expand_path(init_path)
+ if File.directory?(init_path)
+ @initial_dir = init_path
+ @initial_file = 'tkIcons'
+ else
+ @initial_dir = File.dirname(init_path)
+ @initial_file = File.basename(init_path)
+ end
+
+ if Tk::PLATFORM['platform'] == 'unix'
+ TkOption.add('*HighlightThickness', 0)
+ end
+
+ @columns = 14
+ @command = ""
+
+ @delay_timer = nil
+
+ dummy = TkLabel.new
+ @font = dummy.font
+ @boldfont = TkFont.new(@font, :weight=>:bold)
+ @icons = {}
+ @icon_name = {}
+ @icon_info = {}
+
+ @library = TkVariable.new(File.join(@initial_dir, @initial_file))
+ @groups = TkVariable.new('*')
+
+ _create_controls
+
+ _create_display
+
+ _create_info_window
+
+ Tk.root.title('viewIcons')
+ layout_resize
+ Tk.root.resizable(false, true)
+
+ display_icons
+ end
+
+ def init_info(item, name)
+ @icon_name[item] = name
+
+ item.bind('Button-1', method(:clip_info), '%W')
+ item.bind('Enter', method(:delay_info), '%W')
+ item.bind('Leave', method(:cancel_info), '')
+ end
+
+ def delay_info(item)
+ cancel_info
+ @delay_timer = TkTimer.new(200, 1, proc{ show_info(item) }).start
+ end
+
+ def cancel_info
+ if @delay_timer
+ @delay_timer.cancel
+ @delay_timer = nil
+ end
+ @info_window.withdraw
+ end
+
+ def show_info(item)
+ name, groups, type, size = @icon_info[@icon_name[item]]
+ @info_window.name(name)
+ @info_window.groups(groups)
+ @info_window.type(type)
+ @info_window.size(size)
+
+ info_x = item.winfo_rootx + 10
+ info_y = item.winfo_rooty + item.winfo_height
+
+ @info_window.geometry("+#{info_x}+#{info_y}")
+ @info_window.deiconify
+
+ @info_window.raise
+
+ @delay_timer = nil
+ end
+
+ def primary_transfer(offset, max_chars)
+ @command
+ end
+
+ def lost_selection
+ @command = ""
+ end
+
+ def clip_info(item)
+ name = @icon_name[item]
+ data_width = 60
+
+ cmd = "#{name} = TkPhotoImage.new(:data=><<'EOD')\n"
+
+ icon_data = Tk::ICONS.query(name, :file=>@library.value, :items=>'d')[0][0]
+
+ icon_data.scan(/.{1,#{data_width}}/m){|s| cmd << ' ' << s << "\n"}
+
+ cmd << "EOD\n"
+
+ @command = cmd
+
+ TkClipboard.clear
+ TkClipboard.append(@command)
+
+ if Tk::PLATFORM['platform'] == 'unix'
+ TkSelection.handle(Tk.root, method(:primary_transfer),
+ :selection=>'PRIMARY')
+ TkSelection.set_owner(Tk.root, :selection=>'PRIMARY',
+ :command=>method(:lost_selection))
+ end
+
+ Tk.bell
+ end
+
+ def layout_resize
+ Tk.update
+ bbox = @icons_window.bbox('all')
+ width = @controls.winfo_width - @icons_window.yscrollbar.winfo_width - 8
+
+ @icons_window.configure(:width=>width, :scrollregion=>bbox,
+ :xscrollincrement=>'0.1i',
+ :yscrollincrement=>'0.1i')
+ end
+
+ def select_icons
+ new_lib = Tk.getOpenFile(:initialdir=>@initial_dir,
+ :initialfile=>'tkIcons',
+ :title=>'Select Icon Library',
+ :filetypes=>[
+ ['Icon Libraries', ['tkIcons*']],
+ ['All Files', ['*']]
+ ])
+
+ @library.value = new_lib if new_lib.length != 0
+ display_icons
+ end
+
+ def display_icons
+ column = 0
+ limit = @columns - 1
+ row = 0
+
+ unless File.exist?(@library.value)
+ Tk.messageBox(:icon=>'warning', :message=>'File does not exist',
+ :title=>'viewIcons')
+ return
+ end
+
+ cursor = Tk.root[:cursor]
+ Tk.root[:cursor] = 'watch'
+
+ Tk::ICONS.delete(@icons)
+
+ @icons_frame.destroy if @icons_frame
+ @icons_frame = TkFrame.new(@icons_layout).pack
+
+ @icons = Tk::ICONS.create(:file=>@library.value, :group=>@groups.value)
+
+ Tk::ICONS.query(:file=>@library.value, :group=>@groups.value).each{|inf|
+ name = inf[0]
+ @icon_info[name] = inf
+
+ lbl = TkLabel.new(@icons_frame, :image=>"::icon::#{name}")
+ lbl.grid(:column=>column, :row=>row, :padx=>3, :pady=>3)
+ # lbl.grid_columnconfigure column
+
+ init_info(lbl, name)
+
+ if column == limit
+ column = 0
+ row += 1
+ else
+ column += 1
+ end
+ }
+
+ Tk.root[:cursor] = cursor
+ end
+
+ def set_columns(columns)
+ @columns = columns
+ 6.step(20, 2){|i| @column_btns[i][:relief] = :raised }
+ @column_btns[@columns][:relief] = :sunken
+ display_icons
+ end
+end
+
+ViewIcons.new(ARGV[0])
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/barchart5.rb b/ext/tk/sample/tkextlib/blt/barchart5.rb
new file mode 100644
index 0000000000..db181d10ca
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/barchart5.rb
@@ -0,0 +1,101 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/blt'
+
+load File.join(File.dirname(File.expand_path(__FILE__)),
+ 'scripts', 'stipples.rb')
+
+TkOption.add('*graph.x.Title', 'X Axis Label')
+TkOption.add('*graph.y.Title', 'Y Axis Label')
+TkOption.add('*graph.title', 'A Simple Barchart')
+TkOption.add('*graph.x.Font', 'Times 10')
+TkOption.add('*graph.Element.Relief', :raised)
+
+visual = Tk.root.winfo_screenvisual
+if visual != 'staticgray' && visual != 'grayscale'
+ TkOption.add('*graph.LineMarker.color', 'yellow')
+ TkOption.add('*graph.Element.Background', 'white')
+ TkOption.add('*graph.Legend.activeForeground', 'pink')
+ TkOption.add('*print.background', 'yellow')
+ TkOption.add('*quit.background', 'red')
+ TkOption.add('*graph.background', 'palegreen')
+ TkOption.add('*graph.plotBackground', 'lightblue')
+end
+
+htext = Tk::BLT::Htext.new(:widgetname=>'.htext', :text=><<EOD)
+ This is an example of the barchart widget. The barchart has
+ many components; x and y axis, legend, crosshairs, elements, etc.
+ To create a postscript file "bar.ps", press the %%
+
+ ruby {
+ b = TkButton.new(Tk::BLT::Htext::Htext_Widget.window,
+ :widgetname=>'print', :text=>'Print',
+ :command=>proc{
+ $graph.postsript(:output=>'bar.ps')
+ })
+ Tk::BLT::Htext::Htext_Widget.window.append(b)
+ }
+
+%% button.
+%%
+
+ ruby {
+ $graph = Tk::BLT::Barchart.new(:widgetname=>'.htext.graph',
+ :relief=>:raised, :borderwidth=>2)
+ $graph.xaxis_configure(:rotate=>90, :stepsize=>0)
+ Tk::BLT::Htext::Htext_Widget.window.append($graph,
+ :fill=>:both, :padx=>4)
+ }
+
+%%
+ Hit the %%
+
+ ruby {
+ b = TkButton.new(Tk::BLT::Htext::Htext_Widget.window,
+ :widgetname=>'quit', :text=>'Quit',
+ :command=>proc{ exit })
+ Tk::BLT::Htext::Htext_Widget.window.append(b)
+ }
+
+%% button when you've seen enough.%%
+
+ ruby {
+ l = TkLabel.new(Tk::BLT::Htext::Htext_Widget.window, :bitmap=>'BLT')
+ Tk::BLT::Htext::Htext_Widget.window.append(l, :padx=>20)
+ }
+
+%%
+EOD
+
+names = %w(One Two Three Four Five Six Seven Eight)
+if visual == 'staticgray' || visual == 'grayscale'
+ fgcolors = %w(white white white white white white white white)
+ bgcolors = %w(black black black black black black black black)
+else
+ fgcolors = %w(yellow orange red magenta purple blue cyan green)
+ bgcolors = %w(yellow4 orange4 red4 magenta4 purple4 blue4 cyan4 green4)
+end
+
+numColors = names.length
+
+Tk::TCL_PRECISION.value = 15
+
+x = Tk::BLT::Vector.new
+y = Tk::BLT::Vector.new
+x.seq(-5.0, 5.0, 0.2)
+y.expr("sin(#{x})")
+barWidth = 0.19
+
+$graph.element_create('sin', :relief=>:raised, :borderwidth=>1,
+ :x=>x, :y=>y, :barwidth=>barWidth)
+
+Tk::BLT::Table.add(Tk.root, htext, :fill=>:both)
+
+Tk.root.minsize(0, 0)
+
+Tk::BLT.zoom_stack($graph)
+Tk::BLT.crosshairs($graph)
+Tk::BLT.active_legend($graph)
+Tk::BLT.closest_point($graph)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/calendar.rb b/ext/tk/sample/tkextlib/blt/calendar.rb
new file mode 100644
index 0000000000..4fc6d64d9e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/calendar.rb
@@ -0,0 +1,117 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/blt'
+
+require 'date'
+
+dir = File.join(File.dirname(File.expand_path(__FILE__)), 'images')
+file = File.join(dir, 'chalk.gif')
+active = File.join(dir, 'rain.gif')
+
+texture1 = TkPhotoImage.new(:file=>file)
+texture2 = TkPhotoImage.new(:file=>active)
+
+TkOption.add('*Tile', texture1)
+
+TkOption.add('*HighlightThickness', 0)
+TkOption.add('*calendar.weekframe*Tile', texture2)
+TkOption.add('*Calendar.Label.borderWidth', 0)
+TkOption.add('*Calendar.Label.relief', :sunken)
+TkOption.add('*Calendar.Frame.borderWidth', 2)
+TkOption.add('*Calendar.Frame.relief', :raised)
+TkOption.add('*Calendar.Label.font', 'Helvetica 11')
+TkOption.add('*Calendar.Label.foreground', 'navyblue')
+TkOption.add('*button.foreground', 'navyblue')
+TkOption.add('*background', 'grey85')
+TkOption.add('*Label.ipadX', 200)
+
+TkOption.add('*tile', texture2)
+
+class BLT_Calendar_sample
+ @@monthInfo = [
+ nil, # dummy
+ ['January', 31],
+ ['February', 28],
+ ['March', 31],
+ ['April', 30],
+ ['May', 31],
+ ['June', 30],
+ ['July', 31],
+ ['August', 31],
+ ['Septembar', 30],
+ ['October', 31],
+ ['November', 30],
+ ['December', 31]
+ ]
+
+ @@abbrDays = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
+
+ def initialize()
+ today = Date.today
+
+ if TkComm.bool(Tk.info(:commands, '.calendar'))
+ Tk.destroy('.calendar')
+ end
+ cal = Tk::BLT::Tile::Frame.new(:widgetname=>'.calendar',
+ :classname=>'Calendar',
+ :width=>'3i', :height=>'3i')
+
+ mon = Tk::BLT::Tile::Label.new(cal, :font=>'Courier 14 bold',
+ :text=>"#{@@monthInfo[today.month][0]} " +
+ "#{today.year}")
+ Tk::BLT::Table.add(cal, mon, [1, 0], :cspan=>7, :pady=>10)
+
+ week_f = Tk::BLT::Tile::Frame.new(cal, :widgetname=>'weekframe',
+ :relief=>:sunken, :borderwidth=>1)
+ Tk::BLT::Table.add(cal, week_f, [2, 0], :columnspan=>7, :fill=>:both)
+
+ @@abbrDays.each_with_index{|dayName, idx|
+ Tk::BLT::Table.add(cal,
+ Tk::BLT::Tile::Label.new(cal, :text=>dayName,
+ :font=>'Helvetica 12'),
+ [2, idx], :pady=>2, :padx=>2)
+ }
+
+ Tk::BLT::Table.itemconfigure(cal, 'c*', 'r2', :pad=>4)
+
+ numDays = @@monthInfo[today.month][1]
+ week = 0
+ cnt = 1
+
+ wkday = today.wday - ((today.day - 1) % 7)
+ wkday += 7 if wkday < 0
+
+ while cnt <= numDays
+ Tk::BLT::Table.add(cal,
+ Tk::BLT::Tile::Label.new(cal, :text=>cnt){
+ self.configure(:borderwidth=>1,
+ :relief=>:sunken) if cnt == today.day
+ },
+ [week+3, wkday], :fill=>:both, :ipadx=>10, :ipady=>4)
+ cnt += 1
+ wkday += 1
+ if wkday == 7
+ week += 1
+ wkday = 0
+ end
+ end
+
+ Tk::BLT::Tile::Frame.new(cal, :borderwidth=>1, :relief=>:sunken){|f|
+ Tk::BLT::Table.add(f,
+ Tk::BLT::Tile::Button.new(f, :widgetname=>'button',
+ :command=>proc{exit},
+ :borderwidth=>2,
+ :text=>'Quit'),
+ :padx=>4, :pady=>4)
+ Tk::BLT::Table.add(cal, f, [week+4, 5], :cspan=>2, :pady=>4)
+ }
+
+ Tk::BLT::Table.add(Tk.root, cal, :fill=>:both)
+ Tk::BLT::Table.itemconfigure(cal, 'r0', :resize=>:none)
+ end
+end
+
+BLT_Calendar_sample.new
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/graph6.rb b/ext/tk/sample/tkextlib/blt/graph6.rb
new file mode 100644
index 0000000000..f899b44115
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/graph6.rb
@@ -0,0 +1,2222 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/blt'
+
+Tk::TCL_PRECISION.value = 15
+
+[
+ ['*Graph.Width', '10i'],
+ ['*Graph.leftMargin', '.75i'],
+ ['*Graph.Height', '6i'],
+ ['*Graph.plotBackground', 'black'],
+ ['*LineMarker.color', 'white'],
+ ['*LineMarker.Dashes', 5],
+ ['*TextMarker.foreground', 'white'],
+ ['*TextMarker.Background', ''],
+
+ ['*Graph.x.hide', true],
+ ['*Graph.x.title', ''],
+ ['*Graph.y.rotate', 90],
+ # ['*Graph.y.stepSize', 2.0],
+ ['*Graph.title', ''],
+ ['*graph.Title', 'Example s27'],
+ ['*graph.x.hide', false],
+ ['*graph.topMargin', 0],
+ ['*graph.bottomMargin', 0],
+ ['*x.Title', 'Time'],
+ ['*y.Title', 'Signals'],
+ ['*Pixels', 1],
+
+ ['*Reduce', 0.5],
+ ['*bufferElements', false],
+
+ ['*Element.color', 'green4'],
+ ['*Element.ScaleSymbols', true],
+ ['*Element.Color', 'grey70'],
+ ['*Element.Symbol', :none],
+ ['*Element.LineWidth', 1],
+ # ['*Element.Smooth', :natural],
+ ['*Element.Smooth', :catrom],
+
+ ['*activeLine.LineWidth', 2],
+ ['*activeLine.Color', 'white'],
+ ['*activeLine.Color', 'green1'],
+
+ # ['*Legend.Hide', true],
+ ['*Legend.Position', :right],
+ ['*Legend.Relief', :flat],
+ ['*Legend.activeRelief', :sunken],
+ ['*Legend.borderWidth', 2],
+ #['*Legend.Font', '-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*'],
+ ['*Legend.Font', 'Helvetica -10'],
+ ['*Grid.hide', false],
+ ['*Grid.dashes', [1, 5]],
+
+ # ['*foreground', 'white'],
+ ['*zoomOutline.outline', 'yellow'],
+].each{|k, v| TkOption.add(k, v)}
+
+##############################
+
+class BLT_Graph_Demo
+ def initialize
+ @graph = Tk::BLT::Graph.new(:widgetname=>'graph')
+
+ @root = Tk.root
+ @root.minsize(0, 0)
+
+ _set_vectors()
+ (1..39).each{|i| @graph.element_create("V#{i}", :x=>@x, :y=>@v[i])}
+
+ @top = Tk::BLT::Tile::Toplevel.new
+=begin
+ legend = Tk::BLT::Graph.new(@top, :widgetname=>'legend',
+ :without_creating=>true)
+ @graph.legend_configure(:position=>legend)
+=end
+ # legend = @graph.legend_window_create(@top, :widgetname=>'legend')
+ legend = @graph.legend_window_create(@top)
+ legend.pack(:fill=>:both, :expand=>true)
+
+ Tk::BLT::Table.add(@root, @graph, [0,0], :fill=>:both)
+
+ @quit_btn = Tk::BLT::Tile::Button.new(:text=>' quit ', :background=>'red',
+ :command=>proc{exit})
+ Tk::BLT::Table.add(@root, @quit_btn, [1,0], :anchor=>:e, :padx=>10)
+
+ @graph.zoom_stack
+ @graph.crosshairs
+ @graph.closest_point
+ @graph.print_key
+
+ @graph.legend_bind(:all, 'ButtonRelease-1',
+ proc{|w| highlightTrace(w)}, '%W')
+ @graph.legend_bind(:all, 'ButtonRelease-3',
+ proc{|w|
+ w.legend_deactivate('*')
+ active = w.element_activate
+ w.element_deactivate(*active)
+ }, '%W')
+ end
+
+ private
+
+ def _set_vectors
+ @x = Tk::BLT::Vector.new(:variable=>'')
+ @v = []
+ (1..39).each{|i| @v[i] = Tk::BLT::Vector.new(:variable=>'')}
+
+ @x.set(<<-'EOD')
+ 0 1e-10 2e-10 3e-10 4e-10 5e-10 6e-10 7e-10 8e-10 9e-10
+ 1e-09 1.1e-09 1.2e-09 1.3e-09 1.4e-09 1.5e-09 1.6e-09 1.7e-09
+ 1.8e-09 1.9e-09 2e-09 2.1e-09 2.2e-09 2.3e-09 2.4e-09 2.5e-09
+ 2.6e-09 2.7e-09 2.8e-09 2.9e-09 3e-09 3.1e-09 3.2e-09 3.3e-09
+ 3.4e-09 3.5e-09 3.6e-09 3.7e-09 3.8e-09 3.9e-09 4e-09 4.1e-09
+ 4.2e-09 4.3e-09 4.4e-09 4.5e-09 4.6e-09 4.7e-09 4.8e-09
+ 4.9e-09 5e-09 5.1e-09 5.2e-09 5.3e-09 5.4e-09 5.5e-09 5.6e-09
+ 5.7e-09 5.8e-09 5.9e-09 6e-09 6.1e-09 6.2e-09 6.3e-09 6.4e-09
+ 6.5e-09 6.6e-09 6.7e-09 6.8e-09 6.9e-09 7e-09 7.1e-09 7.2e-09
+ 7.3e-09 7.4e-09 7.5e-09 7.6e-09 7.7e-09 7.8e-09 7.9e-09
+ 8e-09 8.1e-09 8.2e-09 8.3e-09 8.4e-09 8.5e-09 8.6e-09 8.7e-09
+ 8.8e-09 8.9e-09 9e-09 9.1e-09 9.2e-09 9.3e-09 9.4e-09 9.5e-09
+ 9.6e-09 9.7e-09 9.8e-09 9.9e-09 1e-08 1.01e-08 1.02e-08
+ 1.03e-08 1.04e-08 1.05e-08 1.06e-08 1.07e-08 1.08e-08 1.09e-08
+ 1.1e-08 1.11e-08 1.12e-08 1.13e-08 1.14e-08 1.15e-08 1.16e-08
+ 1.17e-08 1.18e-08 1.19e-08 1.2e-08 1.21e-08 1.22e-08 1.23e-08
+ 1.24e-08 1.25e-08 1.26e-08 1.27e-08 1.28e-08 1.29e-08 1.3e-08
+ 1.31e-08 1.32e-08 1.33e-08 1.34e-08 1.35e-08 1.36e-08 1.37e-08
+ 1.38e-08 1.39e-08 1.4e-08 1.41e-08 1.42e-08 1.43e-08 1.44e-08
+ 1.45e-08 1.46e-08 1.47e-08 1.48e-08 1.49e-08 1.5e-08 1.51e-08
+ 1.52e-08 1.53e-08 1.54e-08 1.55e-08 1.56e-08 1.57e-08 1.58e-08
+ 1.59e-08 1.6e-08 1.61e-08 1.62e-08 1.63e-08 1.64e-08 1.65e-08
+ 1.66e-08 1.67e-08 1.68e-08 1.69e-08 1.7e-08 1.71e-08 1.72e-08
+ 1.73e-08 1.74e-08 1.75e-08 1.76e-08 1.77e-08 1.78e-08 1.79e-08
+ 1.8e-08 1.81e-08 1.82e-08 1.83e-08 1.84e-08 1.85e-08 1.86e-08
+ 1.87e-08 1.88e-08 1.89e-08 1.9e-08 1.91e-08 1.92e-08 1.93e-08
+ 1.94e-08 1.95e-08 1.96e-08 1.97e-08 1.98e-08 1.99e-08 2e-08
+ 2.01e-08 2.02e-08 2.03e-08 2.04e-08 2.05e-08 2.06e-08 2.07e-08
+ 2.08e-08 2.09e-08 2.1e-08 2.11e-08 2.12e-08 2.13e-08 2.14e-08
+ 2.15e-08 2.16e-08 2.17e-08 2.18e-08 2.19e-08 2.2e-08 2.21e-08
+ 2.22e-08 2.23e-08 2.24e-08 2.25e-08 2.26e-08 2.27e-08 2.28e-08
+ 2.29e-08 2.3e-08 2.31e-08 2.32e-08 2.33e-08 2.34e-08 2.35e-08
+ 2.36e-08 2.37e-08 2.38e-08 2.39e-08 2.4e-08 2.41e-08 2.42e-08
+ 2.43e-08 2.44e-08 2.45e-08 2.46e-08 2.47e-08 2.48e-08 2.49e-08
+ 2.5e-08 2.51e-08 2.52e-08 2.53e-08 2.54e-08 2.55e-08 2.56e-08
+ 2.57e-08 2.58e-08 2.59e-08 2.6e-08 2.61e-08 2.62e-08 2.63e-08
+ 2.64e-08 2.65e-08 2.66e-08 2.67e-08 2.68e-08 2.69e-08 2.7e-08
+ 2.71e-08 2.72e-08 2.73e-08 2.74e-08 2.75e-08 2.76e-08 2.77e-08
+ 2.78e-08 2.79e-08 2.8e-08 2.81e-08 2.82e-08 2.83e-08 2.84e-08
+ 2.85e-08 2.86e-08 2.87e-08 2.88e-08 2.89e-08 2.9e-08 2.91e-08
+ 2.92e-08 2.93e-08 2.94e-08 2.95e-08 2.96e-08 2.97e-08 2.98e-08
+ 2.99e-08 3e-08 3.01e-08 3.02e-08 3.03e-08 3.04e-08 3.05e-08
+ 3.06e-08 3.07e-08 3.08e-08 3.09e-08 3.1e-08 3.11e-08 3.12e-08
+ 3.13e-08 3.14e-08 3.15e-08 3.16e-08 3.17e-08 3.18e-08 3.19e-08
+ 3.2e-08 3.21e-08 3.22e-08 3.23e-08 3.24e-08 3.25e-08 3.26e-08
+ 3.27e-08 3.28e-08 3.29e-08 3.3e-08 3.31e-08 3.32e-08 3.33e-08
+ 3.34e-08 3.35e-08 3.36e-08 3.37e-08 3.38e-08 3.39e-08 3.4e-08
+ 3.41e-08 3.42e-08 3.43e-08 3.44e-08 3.45e-08 3.46e-08 3.47e-08
+ 3.48e-08 3.49e-08 3.5e-08 3.51e-08 3.52e-08 3.53e-08 3.54e-08
+ 3.55e-08 3.56e-08 3.57e-08 3.58e-08 3.59e-08 3.6e-08
+ EOD
+
+ @v[1].set(<<-'EOD')
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ EOD
+
+ @v[2].set(<<-'EOD')
+ 0 1 2 3 4 5 5 5 5 5 5 5 5 5 5 5 4 3 2 1 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 1 2 3 4 5 5 5 5 5 5 5 5 5 5 5 4 3 2 1
+ 5.32907e-15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 5
+ 5 5 5 5 5 5 5 5 5 4 3 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0
+ EOD
+
+ @v[3].set(<<-'EOD')
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 4 3 2 1 8.88178e-16
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 1 2 3 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 4 3 2 1 2.13718e-14 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0
+ EOD
+
+ @v[4].set(<<-'EOD')
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 4 3 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 1 2 3 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ EOD
+
+ @v[5].set(<<-'EOD')
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 4 3 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 1 2 3 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ EOD
+
+ @v[6].set(<<-'EOD')
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 4 3 2 1 8.88178e-16
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 1 2 3 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 4 3 2 1 2.13718e-14 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0
+ EOD
+
+ @v[7].set(<<-'EOD')
+ 5 5.16904 4.84159 3.34542 0.317102 0.103304 0.0275721 0.0221534
+ 0.017689 0.0142639 0.0113974 0.00918238 0.00742541 0.00616602
+ 0.00481195 0.00397049 -0.0659889 -0.025671 0.165495 0.986891
+ 3.05229 4.55511 4.91611 4.98192 4.99428 4.99833 4.99095
+ 4.97295 4.95493 4.93428 4.90723 4.94799 4.98584 4.99566
+ 4.99813 4.99907 4.99947 4.99965 4.99976 4.99984 4.99989
+ 4.99992 4.99994 4.99996 4.99998 5.00002 5.00006 5.00002
+ 4.99996 4.99994 4.99999 5.00003 5.00002 5 4.99997 4.99997
+ 4.99997 4.99997 4.99997 4.99996 4.99997 4.99997 4.99998
+ 4.99998 4.99999 5 5 5 5 5 5 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5 5 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99998 4.99998 4.99998 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 5 5 5 5 5 5 5 5.16575
+ 4.69986 2.43862 0.0230224 0.035229 -0.0210607 -0.0292766
+ -0.0172693 -0.00271479 -0.000912251 -0.000349106 -0.000116866
+ -4.24733e-05 -1.39536e-05 -3.01179e-05 -0.0657192 -0.0204835
+ 0.183378 1.07181 3.118 4.46472 4.84158 4.94795 4.98173 4.99236
+ 4.99762 5.01939 5.0433 5.05332 5.04959 5.03955 5.02851 5.02052
+ 5.01422 5.00965 5.00631 5.00405 5.00248 5.00083 5.00012
+ 5.00209 5.00387 5.00347 4.99917 4.99213 4.98411 4.97521
+ 4.96332 4.94601 4.9304 4.94633 4.97936 4.99264 4.99685 4.99857
+ 4.99925 4.99954 4.9997 4.99973 4.9997 4.99973 4.99979 4.99983
+ 4.99986 4.99988 4.9999 4.9999 4.99992 4.99993 4.99994 4.99995
+ 4.99996 4.99996 4.99997 4.99997 4.99998 4.99998 4.99998
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 5 5 5 5.00001 5.00001 5.00001 5.00001 5.00002 5.00002 5.00002
+ 5.00002 5.00001 5.00001 5.00001 5 5 5 5 5 5 5 5 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 5 5 5.14242 4.76101 3.16003 0.299374
+ 0.0645506 -0.000498424 -2.45108e-05 -2.27986e-05 -5.24401e-05
+ -4.9884e-05 -4.92491e-05 -2.93354e-05 -3.21402e-05 -2.11851e-05
+ -3.37925e-05 -0.0657892 -0.020563 0.182582 1.06058 3.12484
+ 4.46552 4.84146 4.95102 4.98556 4.99472 4.99806 4.99909
+ 4.99955 4.99976 4.99994 4.99992 5.00029 4.99967 4.99849
+ 4.99736 4.99884 5.00099 5.00377 5.00215 4.99994 4.99893
+ 4.99788 4.99862 5.00055 5.00134 5.00127 5.00073 5.00039
+ 5.00018 5.00006 5.00001 4.99985 5.00026 5.00018 5.00003
+ 4.99981 4.99985 4.99987 4.99985 4.99982 4.99982 4.99982
+ 4.99983 4.99985 4.99987 4.99989 4.99991 4.99992 4.99994
+ 4.99995 4.99995 4.99994 4.99994 4.99996 4.99999 5.00002
+ 5.00008 5.00009 5.00006 5.00001 5 4.99999 4.99998 4.99997
+ 4.99996 4.99997 4.99997 4.99998 4.99998 4.99999 4.99999
+ 4.99999 5 5 5 5 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999 4.99998 4.99998
+ 4.99998
+ EOD
+
+ @v[8].set(<<-'EOD')
+ 5 5.03758 5.04711 4.96911 4.20882 3.96295 4.01117 4.15521
+ 4.2967 4.42274 4.5295 4.6176 4.69014 4.74831 4.7966 4.83537
+ 4.80526 4.787 4.79295 4.88588 5.08978 5.15615 5.10778 5.07718
+ 5.06652 5.08225 4.9744 4.52977 3.77452 2.69426 1.15294 0.245509
+ 0.0981544 0.0567527 0.0367487 0.0252578 0.0180599 0.0133837
+ 0.0101497 0.0078616 0.00620186 0.00499056 0.0041027 0.00344223
+ 0.00295808 0.00260089 0.00229887 0.00200817 0.00176397 0.00160116
+ 0.00147381 0.00134645 0.00125029 0.00116043 0.00107371 0.00101981
+ 0.000965921 0.000912028 0.000858135 0.000804242 0.000761669
+ 0.00072672 0.000691771 0.000656823 0.000621874 0.000588722
+ 0.00057041 0.000552098 0.000533785 0.000515473 0.000497162
+ 0.00047885 0.000460537 0.000442226 0.000423914 0.000405601
+ 0.000388399 0.000378694 0.000368989 0.000359284 0.00034958
+ 0.000339875 0.00033017 0.000320465 0.00031076 0.000301055
+ 0.00029135 0.000282207 0.000276247 0.000270287 0.000264327
+ 0.000258367 0.000252407 0.000246447 0.000240487 0.000234527
+ 0.000228567 0.000222607 0.000217086 0.000213696 0.000210307
+ 0.000206918 0.000203528 0.000200139 0.00019675 0.00019336
+ 0.000189971 0.000186582 0.000183192 0.000179803 0.000176414
+ 0.000173025 0.000169635 0.000166246 0.000162857 0.000159467
+ 0.000156078 0.000152689 0.000149299 0.00014591 0.00014255
+ 0.0316021 0.163272 0.348732 0.603651 0.35745 0.135965 0.0707354
+ 0.0314595 0.0201047 0.00994945 0.00389601 0.00138839 0.00060778
+ 0.000329648 0.000492396 -0.0732035 -0.0844077 -0.0789062
+ -0.0390837 0.0197559 0.0183094 -0.00180099 -0.0189565 -0.0424144
+ -0.0735904 -0.0892423 0.285039 1.13702 2.10809 2.95826 3.60164
+ 4.0435 4.35771 4.57254 4.71769 4.81329 4.87534 4.91487 4.94264
+ 4.97375 5.01526 5.06517 5.10154 5.06259 4.89005 4.5787 4.12226
+ 3.46151 2.49023 1.2586 0.32725 0.116753 0.0701865 0.0455509
+ 0.0286914 0.0178176 0.0117599 0.00902715 0.00760583 0.00637745
+ 0.00543811 0.00439377 0.00352448 0.0030151 0.00285771 0.002465
+ 0.00203114 0.00173004 0.0014839 0.00125177 0.00105327 0.000894905
+ 0.000766372 0.000658894 0.000569105 0.000492114 0.000427938
+ 0.000370217 0.000314758 0.000266569 0.000233726 0.000209048
+ 0.000191957 0.000177169 0.000166604 0.000161 0.000157314
+ 0.000143828 0.000130342 0.000116857 0.000103371 8.98855e-05
+ 7.63998e-05 6.29141e-05 5.76583e-05 5.30027e-05 4.8347e-05
+ 4.36913e-05 3.90357e-05 3.438e-05 2.97243e-05 2.72507e-05
+ 2.59083e-05 2.45659e-05 2.32235e-05 2.18811e-05 2.05387e-05
+ 1.91963e-05 1.78539e-05 1.65115e-05 1.51691e-05 1.38267e-05
+ 1.24843e-05 1.11419e-05 9.79954e-06 8.51574e-06 7.69807e-06
+ 6.8804e-06 6.06273e-06 5.24506e-06 0.0287318 0.0317111 -0.0320087
+ -0.103609 0.0369639 0.0121128 0.00961197 0.00934971 0.00820853
+ 0.00699769 0.00607002 0.00535541 0.00476552 0.00427601 0.00376357
+ -0.073012 -0.0866964 -0.0809538 -0.038005 0.0277001 0.0188906
+ 0.00614597 0.00373629 0.00489787 0.0146573 0.0191052 0.0151708
+ 0.0124224 0.0105859 0.00879272 0.00729464 0.0070047 0.00449575
+ -0.00626652 -0.0252417 -0.0147287 0.022538 0.0822905 0.0947372
+ 0.0657516 0.0445506 0.0316753 0.0220971 0.0158101 0.0140971
+ 0.0161498 0.0139876 0.0122447 0.0106994 0.009397 0.00822236
+ 0.00686509 0.00797431 0.00751269 0.00671173 0.00595243 0.00524633
+ 0.00459528 0.00401688 0.00350109 0.00303954 0.00260569 0.00222792
+ 0.00191033 0.00163917 0.00140949 0.00121464 0.0010471 0.000900638
+ 0.000768847 0.000645236 0.000524807 0.000460275 0.000442237
+ 0.000446775 0.000397026 0.000301585 0.000228994 0.000190894
+ 0.000166569 0.000152261 0.000137953 0.000123644 0.000109336
+ 9.50281e-05 8.56557e-05 7.78437e-05 7.00318e-05 6.22198e-05
+ 5.44079e-05 4.87539e-05 4.57761e-05 4.27982e-05 3.98203e-05
+ 3.68425e-05 3.38646e-05 3.08868e-05 2.79089e-05 2.4931e-05
+ 2.19532e-05 1.89753e-05 1.75244e-05 1.64095e-05 1.52946e-05
+ 1.41797e-05 1.30648e-05 1.19499e-05 1.0835e-05 9.72011e-06
+ 8.60521e-06 7.4903e-06 6.5117e-06 6.10334e-06 5.69497e-06
+ 5.2866e-06 4.87824e-06 4.46987e-06 4.06151e-06 3.65314e-06
+ 3.24477e-06
+ EOD
+
+ @v[9].set(<<-'EOD')
+ 1.86175 1.99708 2.07867 2.01211 2.43309 3.27194 3.63896
+ 3.90426 4.11074 4.27932 4.41496 4.52543 4.61491 4.68862
+ 4.7479 4.79666 4.72895 4.68886 4.70354 4.81353 5.01568 5.14184
+ 5.10482 5.07362 5.05143 5.03638 5.02323 5.01465 5.00853
+ 5.00383 4.99985 5.00454 5.00652 5.00546 5.00411 5.003 5.00214
+ 5.00151 5.00106 5.00073 5.0005 5.00034 5.00023 5.00015 5.0001
+ 5.00005 5 5.00001 5.00005 5.00005 5.00003 5 4.99998 4.99996
+ 4.99994 4.99995 4.99997 4.99998 5 5.00001 5.00002 5.00002
+ 5.00003 5.00003 5.00003 5.00003 5.00003 5.00003 5.00002
+ 5.00002 5.00001 5.00001 5.00001 5 5 5 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99998
+ 4.99998 4.99998 4.99999 4.99999 4.99999 4.99999 5 5 5 5
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.17392 4.94828 3.78491
+ 1.52079 0.608874 0.244031 0.127087 0.0552995 0.0361032 0.0169025
+ 0.006364 0.00217624 0.000921391 0.000457305 0.000786754
+ -0.120016 -0.148054 -0.15898 -0.0801463 0.16463 0.174017
+ 0.0799249 0.0318788 0.0129696 0.00483397 0.0025677 0.0042079
+ 0.00350003 0.00178404 -8.72902e-05 -0.00128497 -0.00142213
+ -0.00130018 -0.00106874 -0.000789207 -0.000824335 -0.00104518
+ -0.00136799 -0.004366 -0.0102621 -0.0109254 -0.00649259
+ -0.00194842 0.00029793 0.00148673 0.00221085 0.00228291
+ 0.00185261 0.00139687 0.00148183 0.00562266 0.00844119 0.00754627
+ 0.00657396 0.00591212 0.00539269 0.0049282 0.00448417 0.0040572
+ 0.00363719 0.00320392 0.00279607 0.00243938 0.00211505 0.00182302
+ 0.00156254 0.0013341 0.00113834 0.000971865 0.00082776 0.000706193
+ 0.000602499 0.000515059 0.000441401 0.00037897 0.000325459
+ 0.00028083 0.000242096 0.000207274 0.000176444 0.000150372
+ 0.000126407 0.000103373 9.05522e-05 8.53555e-05 8.63685e-05
+ 9.02593e-05 8.37346e-05 7.72099e-05 7.06852e-05 6.41605e-05
+ 5.76358e-05 5.11112e-05 4.45865e-05 4.08176e-05 3.72497e-05
+ 3.36818e-05 3.01138e-05 2.65459e-05 2.2978e-05 1.94101e-05
+ 1.76154e-05 1.67399e-05 1.58645e-05 1.4989e-05 1.41136e-05
+ 1.32381e-05 1.23626e-05 1.14872e-05 1.06117e-05 9.73629e-06
+ 8.86083e-06 7.98538e-06 7.10993e-06 6.23447e-06 5.44363e-06
+ 5.32578e-06 5.20792e-06 5.09007e-06 4.97222e-06 0.0784323
+ 0.0474527 -0.0764232 -0.151146 0.0615785 0.0144489 0.00974161
+ 0.00947176 0.00849005 0.00728201 0.00630581 0.00554032 0.00487809
+ 0.00441504 0.00384139 -0.118943 -0.149894 -0.161173 -0.0825299
+ 0.171686 0.176912 0.0816085 0.0335236 0.013791 0.0056976
+ 0.00238833 0.00105348 0.000526199 0.00025969 0.000396026
+ 0.000837835 0.00170131 0.00196699 -0.000553314 -0.0061621
+ -0.0111895 -0.0142698 -0.0124608 -0.00795847 -0.00467822
+ -0.0043058 -0.00874449 -0.0118584 -0.00871386 -0.00377892
+ 1.95244e-05 0.00218952 0.00325486 0.00386497 0.00422837
+ 0.00446883 0.00447065 0.00486647 0.00547838 0.00565398 0.00559092
+ 0.00538752 0.00507015 0.00466305 0.00420756 0.00373465 0.00328404
+ 0.00287059 0.00250057 0.00216124 0.00184861 0.00156815 0.00134624
+ 0.00117857 0.00103412 0.0008948 0.000761012 0.000619853
+ 0.000462614 0.000319965 0.000287666 0.000356415 0.000379946
+ 0.000339183 0.00027972 0.000252982 0.000226244 0.000199507
+ 0.000172769 0.000146031 0.000130097 0.000117578 0.000105059
+ 9.25401e-05 8.00213e-05 7.11204e-05 6.67061e-05 6.22918e-05
+ 5.78775e-05 5.34632e-05 4.90489e-05 4.46346e-05 4.02203e-05
+ 3.5806e-05 3.13916e-05 2.69773e-05 2.4827e-05 2.31747e-05
+ 2.15225e-05 1.98702e-05 1.8218e-05 1.65658e-05 1.49135e-05
+ 1.32613e-05 1.1609e-05 9.95678e-06 8.50108e-06 7.86765e-06
+ 7.23422e-06 6.60079e-06 5.96736e-06 5.33393e-06 4.7005e-06
+ 4.06707e-06 3.43363e-06
+ EOD
+
+ @v[10].set(<<-'EOD')
+ 1.86175 1.99308 2.16619 2.46661 3.09359 3.76864 4.31299
+ 4.65564 4.83425 4.92153 4.96157 4.98063 4.98649 4.99039
+ 4.9945 4.9972 4.96206 4.89882 4.83865 4.83202 4.91016 5.04479
+ 5.06078 5.04827 5.03474 5.0246 5.01639 5.00996 5.00569 5.00239
+ 5.00043 5.00296 5.00437 5.00382 5.00287 5.00208 5.00148
+ 5.00104 5.00073 5.0005 5.00034 5.00023 5.00016 5.00011 5.00008
+ 5.00007 5.00007 5.00004 5 4.99998 4.99998 4.99997 4.99998
+ 4.99999 5 5 5.00001 5.00001 5.00001 5.00002 5.00002 5.00001
+ 5.00001 5.00001 5.00001 5 5 5 5 5 5 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 5 5 5 5 5 5 5 5 5 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5 5 5 5 5 5 5 5 5.10081
+ 5.10949 4.98359 5.00733 5.15145 4.37298 2.36126 0.470759
+ 0.0577238 0.0115884 0.00262611 0.000671499 0.000389038 0.000291291
+ 0.000317347 -0.0167823 -0.0158344 -0.0140559 0.0104849 0.0865874
+ 0.107813 0.0524688 0.0214369 0.00876443 0.00341595 0.00170778
+ 0.00259042 0.0022241 0.00118519 1.10217e-06 -0.000784506
+ -0.000948169 -0.000856256 -0.000696719 -0.000485987 -0.000724787
+ -0.000981491 -0.001454 -0.00552498 -0.0114992 -0.0105266
+ -0.00543527 -0.000982798 0.00127356 0.00224212 0.00275439
+ 0.00281098 0.0025471 0.00230368 0.00222576 0.00485522 0.00729453
+ 0.00691796 0.0062615 0.00573987 0.0052688 0.00481185 0.00436934
+ 0.00394326 0.00352712 0.00309978 0.00270038 0.00235335 0.00203742
+ 0.00175256 0.00150067 0.00128126 0.00109323 0.000933619
+ 0.000795113 0.000678182 0.00057843 0.000494345 0.000423609
+ 0.000363821 0.000312766 0.000269856 0.000232389 0.000198382
+ 0.000168126 0.00014267 0.000119293 9.69034e-05 8.5669e-05
+ 8.26828e-05 8.64066e-05 9.26665e-05 8.5454e-05 7.82416e-05
+ 7.10291e-05 6.38167e-05 5.66043e-05 4.93918e-05 4.21794e-05
+ 3.86073e-05 3.53007e-05 3.19941e-05 2.86876e-05 2.5381e-05
+ 2.20744e-05 1.87678e-05 1.70933e-05 1.62648e-05 1.54363e-05
+ 1.46079e-05 1.37794e-05 1.2951e-05 1.21225e-05 1.12941e-05
+ 1.04656e-05 9.63716e-06 8.80871e-06 7.98026e-06 7.1518e-06
+ 6.32335e-06 5.5374e-06 5.08959e-06 4.64178e-06 4.19397e-06
+ 3.74616e-06 0.0438026 0.0242078 -0.0602019 -0.0840866 0.00148461
+ -0.00292489 0.000442098 0.00219489 0.00281478 0.00290756
+ 0.00277945 0.00263896 0.00240099 0.00223283 0.001947 -0.0153629
+ -0.0148815 -0.0128673 0.0126017 0.0905161 0.11051 0.0538958
+ 0.022562 0.00935726 0.00397422 0.00172534 0.000790207 0.000416322
+ 0.000191632 0.000469721 0.0009779 0.00192566 0.00200688
+ -0.0016502 -0.00733932 -0.0128113 -0.0147608 -0.0115456
+ -0.00668995 -0.00401368 -0.00463908 -0.0101197 -0.0118993
+ -0.0076276 -0.00262656 0.000813059 0.00264455 0.00350796
+ 0.00399494 0.0043049 0.00451658 0.00444739 0.00503842 0.00559516
+ 0.00568213 0.00556459 0.0053176 0.00496654 0.00454337 0.00408592
+ 0.00362171 0.00317793 0.00277001 0.00240394 0.00207009 0.00176575
+ 0.00149725 0.00129045 0.00114257 0.00101135 0.000871672
+ 0.000723764 0.000580438 0.000427507 0.000296956 0.000281834
+ 0.000376628 0.000412266 0.000367547 0.000295305 0.000264513
+ 0.000233721 0.000202929 0.000172137 0.000141345 0.000124721
+ 0.000112577 0.000100433 8.82893e-05 7.61453e-05 6.75517e-05
+ 6.33609e-05 5.91701e-05 5.49792e-05 5.07884e-05 4.65976e-05
+ 4.24067e-05 3.82159e-05 3.40251e-05 2.98342e-05 2.56434e-05
+ 2.36401e-05 2.21181e-05 2.05961e-05 1.90741e-05 1.75521e-05
+ 1.60301e-05 1.45081e-05 1.29861e-05 1.14641e-05 9.94208e-06
+ 8.59252e-06 7.96439e-06 7.33626e-06 6.70813e-06 6.07999e-06
+ 5.45186e-06 4.82373e-06 4.1956e-06 3.56747e-06
+ EOD
+
+ @v[11].set(<<-'EOD')
+ 1.86175 1.73419 1.42874 1.04055 0.943004 0.268275 0.0826455
+ 0.0388346 0.0214104 0.0135431 0.00961322 0.00712846 0.00588262
+ 0.00432397 0.00377774 0.00270134 -0.00393731 -0.00542187
+ -0.00126596 0.0113777 0.0134522 0.00477056 -0.00211067 -0.00229253
+ -0.00173355 -0.00122404 -0.00113426 -0.000744931 -0.000520112
+ -0.000410048 -0.000220439 0.000508104 5.15856e-05 -0.000112593
+ -0.000118917 -9.57394e-05 -7.15727e-05 -5.11847e-05 -3.58275e-05
+ -2.47166e-05 -1.68866e-05 -1.14082e-05 -7.66646e-06 -5.12139e-06
+ -3.63426e-06 -3.01815e-06 -2.64862e-06 -1.4947e-06 -1.91403e-07
+ -2.5763e-08 -7.73699e-07 -1.52164e-06 -1.07268e-06 -3.81696e-07
+ 2.6727e-07 4.75489e-07 6.83708e-07 8.91926e-07 1.10014e-06
+ 1.30836e-06 1.2482e-06 1.00726e-06 7.66311e-07 5.25364e-07
+ 2.84417e-07 6.27857e-08 7.43904e-10 -6.12979e-08 -1.2334e-07
+ -1.85382e-07 -2.47423e-07 -3.09465e-07 -3.71507e-07 -4.33549e-07
+ -4.95591e-07 -5.57633e-07 -6.04571e-07 -5.4944e-07 -4.9431e-07
+ -4.3918e-07 -3.84049e-07 -3.28919e-07 -2.73789e-07 -2.18659e-07
+ -1.63528e-07 -1.08398e-07 -5.32678e-08 1.062e-09 5.08502e-08
+ 1.00638e-07 1.50427e-07 2.00215e-07 2.50003e-07 2.99791e-07
+ 3.4958e-07 3.99368e-07 4.49156e-07 4.98944e-07 5.34512e-07
+ 5.01032e-07 4.67553e-07 4.34073e-07 4.00593e-07 3.67113e-07
+ 3.33633e-07 3.00153e-07 2.66674e-07 2.33194e-07 1.99714e-07
+ 1.66234e-07 1.32754e-07 9.92744e-08 6.57945e-08 3.23147e-08
+ -1.16513e-09 -3.4645e-08 -6.81248e-08 -1.01605e-07 -1.35084e-07
+ -1.68564e-07 -2.18729e-07 0.0114926 -0.0245378 -0.111828
+ 0.0964775 1.61491 3.22668 4.22041 4.54492 4.82845 4.94868
+ 4.98588 4.99609 4.9981 4.99908 4.99788 4.98395 4.99294 4.99724
+ 5.01939 5.0471 5.00902 4.98194 4.98496 4.99188 4.99623 4.99862
+ 5.00025 4.99974 4.99953 4.99946 4.99958 5.00012 4.99997
+ 4.99992 4.99988 4.99985 4.9998 4.9997 4.9988 4.99806 4.99982
+ 5.00143 5.00159 5.00098 5.00053 5.00028 5.00007 4.99977
+ 4.99992 5.00005 5.00133 5.0009 4.99993 4.99972 4.99975 4.9998
+ 4.99982 4.99983 4.99983 4.99983 4.99983 4.99984 4.99986
+ 4.99987 4.99989 4.9999 4.99991 4.99992 4.99994 4.99995 4.99995
+ 4.99996 4.99997 4.99997 4.99998 4.99998 4.99998 4.99998
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 5 5 5 5.00001 5.00001 5.00001 5.00002 5.00002 5.00002 5.00002
+ 5.00002 5.00001 5.00001 5.00001 5 5 5 5 5 5 5 5 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 5 5 5.01457 4.99482 4.96561 4.99326
+ 5.03452 5.00424 5.00101 5.00045 5.00004 4.99965 4.99997
+ 4.99994 4.99958 4.99999 4.99936 4.9839 4.99248 4.99717 5.01976
+ 5.04869 5.0087 4.98143 4.98488 4.99199 4.99622 4.9983 4.99928
+ 4.99971 4.99986 5.00031 5.00022 5.00035 5.0001 4.99884 4.99811
+ 4.99803 4.99887 5.00078 5.00151 5.00116 5.00007 4.99843
+ 4.99915 5.00107 5.00168 5.00141 5.00092 5.00055 5.0003 5.00016
+ 5.0001 5.00001 5.00016 5.0002 5.00009 4.99993 4.99975 4.99984
+ 4.99991 4.99991 4.99982 4.99974 4.99974 4.99985 4.99995
+ 4.99999 4.99998 5.00004 5.00013 5.00015 5.00007 4.99988
+ 4.99982 4.99985 4.99995 5.00006 5.0002 5.00025 5.0002 5.00009
+ 5.00006 5.00004 5.00002 5 4.99998 4.99997 4.99998 4.99998
+ 4.99999 4.99999 4.99999 5 5 5 5 5 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999
+ 4.99998 4.99998 4.99998
+ EOD
+
+ @v[12].set(<<-'EOD')
+ 5 5.16975 4.78685 2.94241 0.126698 0.0487004 -0.00422591
+ -0.00130689 -0.000486756 -0.000195875 -0.000108988 -6.66736e-05
+ -7.26005e-05 -5.63608e-05 -3.81859e-05 -2.123e-05 -0.0646846
+ -0.0184474 0.182248 1.06731 3.10988 4.46133 4.84133 4.95113
+ 4.98364 4.99455 4.99694 4.99727 4.9994 4.99975 5.0001 5.00132
+ 5.00089 5.00039 5.00019 5.00011 5.00006 5.00005 5.00004
+ 5.00001 4.99992 4.99992 5.00002 5.00013 5.00017 5.00009
+ 4.99992 4.99991 4.99994 4.99996 4.99998 4.99999 5.00001
+ 5.00004 5.00006 5.00005 5.00004 5.00003 5.00002 5.00001
+ 5 4.99999 4.99999 4.99998 4.99998 4.99997 4.99997 4.99998
+ 4.99998 4.99998 4.99998 4.99999 4.99999 4.99999 4.99999
+ 5 5 5 5 5 5 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00002 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 5 5.14699 4.78074
+ 3.19424 0.305663 0.0611255 -0.00179951 -0.0012032 0.000405978
+ 0.000989399 0.000445194 0.000191447 8.30476e-05 3.96236e-05
+ 1.91866e-05 1.70665e-05 -0.0655239 -0.0210234 0.1827 1.06848
+ 3.11554 4.46518 4.84212 4.94853 4.98244 4.99434 4.9997 5.00081
+ 5.00009 4.99972 4.99985 4.99974 4.9995 4.99949 4.99958 4.99973
+ 4.99948 4.99914 4.99874 4.99946 5.00309 5.0091 5.01576 5.01835
+ 5.01852 5.0176 5.01625 5.01479 5.01345 5.01264 5.011 5.01092
+ 5.01344 5.01363 5.01289 5.01184 5.01071 5.00956 5.00848
+ 5.00751 5.00663 5.00577 5.00497 5.00427 5.00365 5.0031 5.00264
+ 5.00224 5.00191 5.00163 5.00138 5.00117 5.00099 5.00083
+ 5.00071 5.00061 5.00053 5.00045 5.00037 5.00029 5.00022
+ 5.00019 5.0002 5.00023 5.00024 5.00023 5.00023 5.00022 5.0002
+ 5.00018 5.00016 5.00014 5.00011 5.00009 5.00007 5.00006
+ 5.00005 5.00005 5.00004 5.00003 5.00002 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00002 5.00002 5.00002 5.00002 5.00002 5.00002 5.00002
+ 5.00002 5.00001 5.00001 5.00001 5.14298 4.79809 3.32704
+ 0.498385 0.105773 0.0160646 0.0319912 0.0299434 0.0240102
+ 0.0185844 0.0130411 0.0106532 0.00864871 0.00744519 0.00660887
+ -0.0612913 -0.0203719 0.174998 0.991787 3.06292 4.60005
+ 4.93058 4.98917 5.00033 4.9999 4.99909 4.9966 4.9955 4.99488
+ 4.99374 4.9943 5.00131 5.00506 4.99311 4.96288 4.93567 4.92439
+ 4.94236 4.9732 4.98864 4.99458 5.00031 5.00694 5.01525 5.01945
+ 5.01998 5.01953 5.01874 5.01766 5.0164 5.01509 5.01326 5.01423
+ 5.01455 5.01361 5.01245 5.01122 5.01002 5.00888 5.00783
+ 5.00687 5.00596 5.00514 5.00442 5.00379 5.00325 5.00279
+ 5.0024 5.00208 5.0018 5.00153 5.00126 5.00107 5.00094 5.00085
+ 5.00078 5.00072 5.00063 5.00053 5.00042 5.00038 5.00034
+ 5.0003 5.00027 5.00023 5.00021 5.00019 5.00017 5.00015 5.00013
+ 5.00012 5.00011 5.0001 5.0001 5.00009 5.00008 5.00007 5.00007
+ 5.00006 5.00005 5.00005 5.00004 5.00004 5.00003 5.00003
+ 5.00002 5.00002 5.00002 5.00001 5.00001 5 5 5 5.00001 5.00001
+ 5.00001 5.00002 5.00002 5.00002 5.00002
+ EOD
+
+ @v[13].set(<<-'EOD')
+ 9.73784e-10 0.0189926 0.0926769 0.206309 0.111533 0.0953491
+ 0.0426966 0.0214177 0.0117943 0.00741442 0.00528816 0.00398417
+ 0.0032967 0.00266499 0.00206647 0.00158788 -0.0371391 -0.0439528
+ -0.0408653 -0.0188706 0.0150241 0.0126852 0.00209817 -0.000239206
+ -5.31488e-05 0.000876324 -0.00451221 -0.0165223 -0.0284127
+ -0.0427584 -0.0502453 -0.0257366 -0.00903938 -0.00376456
+ -0.00233385 -0.00169922 -0.00130397 -0.00102542 -0.000811435
+ -0.000648115 -0.000529266 -0.00043795 -0.00036574 -0.00030716
+ -0.00026221 -0.000229662 -0.000205112 -0.000181038 -0.000162045
+ -0.000148988 -0.000137633 -0.000126278 -0.000115562 -0.000104976
+ -9.49324e-05 -9.0585e-05 -8.62375e-05 -8.18901e-05 -7.75426e-05
+ -7.31952e-05 -6.93752e-05 -6.59106e-05 -6.24461e-05 -5.89815e-05
+ -5.55169e-05 -5.22412e-05 -5.05263e-05 -4.88114e-05 -4.70966e-05
+ -4.53817e-05 -4.36668e-05 -4.19519e-05 -4.0237e-05 -3.85222e-05
+ -3.68073e-05 -3.50924e-05 -3.34782e-05 -3.25442e-05 -3.16102e-05
+ -3.06763e-05 -2.97423e-05 -2.88083e-05 -2.78744e-05 -2.69404e-05
+ -2.60064e-05 -2.50725e-05 -2.41385e-05 -2.32635e-05 -2.27232e-05
+ -2.21829e-05 -2.16426e-05 -2.11023e-05 -2.0562e-05 -2.00217e-05
+ -1.94814e-05 -1.89411e-05 -1.84007e-05 -1.78604e-05 -1.73647e-05
+ -1.70853e-05 -1.68059e-05 -1.65265e-05 -1.62471e-05 -1.59677e-05
+ -1.56883e-05 -1.54089e-05 -1.51295e-05 -1.48501e-05 -1.45707e-05
+ -1.42913e-05 -1.40119e-05 -1.37325e-05 -1.34531e-05 -1.31737e-05
+ -1.28943e-05 -1.26149e-05 -1.23355e-05 -1.20561e-05 -1.17767e-05
+ -1.14973e-05 -1.10954e-05 0.0152675 0.0228237 -0.00460678
+ -0.0341525 0.0232109 -0.0138039 -0.0416538 -0.0458764 -0.0201967
+ -0.00878316 -0.00379173 -0.00164621 -0.000785131 -0.00037575
+ -0.000352375 -0.0545586 -0.0746881 -0.0771865 -0.05386 -0.0022199
+ 0.0136703 0.00633526 0.00138826 -0.00108934 0.0038886 0.0298077
+ 0.0475776 0.0481003 0.0464167 0.047818 0.042789 0.035207
+ 0.0264423 0.0193959 0.0151614 0.00624257 -0.00913057 -0.0310696
+ -0.0430238 0.016426 0.189762 0.49025 0.820116 1.13919 1.43549
+ 1.70658 1.95183 2.17414 2.38506 2.5657 2.73958 2.97905 3.21403
+ 3.43025 3.62645 3.8028 3.96002 4.09996 4.22443 4.33427 4.42886
+ 4.51097 4.5817 4.64326 4.6957 4.74132 4.7797 4.81298 4.84102
+ 4.86512 4.88523 4.90224 4.91649 4.92846 4.93868 4.94755
+ 4.95483 4.96114 4.96682 4.97161 4.97502 4.9776 4.97944 4.98141
+ 4.98319 4.98467 4.98585 4.9869 4.98796 4.98902 4.99008 4.99114
+ 4.9922 4.99326 4.9938 4.99429 4.99479 4.99528 4.99578 4.99628
+ 4.99677 4.99704 4.99718 4.99733 4.99747 4.99762 4.99777
+ 4.99791 4.99806 4.9982 4.99835 4.9985 4.99864 4.99879 4.99893
+ 4.99907 4.99916 4.99925 4.99934 4.99943 5.01473 4.92293
+ 4.61974 4.0316 3.7835 3.74195 3.78344 3.87272 3.97386 4.07319
+ 4.16686 4.25256 4.33126 4.40264 4.46697 4.49249 4.51807
+ 4.55803 4.64055 4.78574 4.86074 4.88334 4.8999 4.91455 4.92814
+ 4.93926 4.94761 4.95433 4.95907 4.9654 4.98317 5.0208 5.05134
+ 4.85852 4.16041 3.00077 1.68376 0.672707 0.240838 0.0794725
+ -0.0106347 -0.00879443 0.107196 0.368163 0.701424 1.03581
+ 1.3601 1.6678 1.95731 2.22701 2.47544 2.69099 2.92327 3.16648
+ 3.3877 3.59067 3.77344 3.93584 4.08066 4.20863 4.32065 4.41791
+ 4.50211 4.57423 4.63614 4.68888 4.73377 4.7721 4.80519 4.83338
+ 4.85732 4.87815 4.89514 4.90927 4.92108 4.93122 4.94014
+ 4.94845 4.95601 4.96251 4.96576 4.969 4.97225 4.9755 4.97874
+ 4.98087 4.98265 4.98442 4.9862 4.98797 4.98924 4.9899 4.99055
+ 4.9912 4.99186 4.99251 4.99316 4.99381 4.99447 4.99512 4.99577
+ 4.99609 4.99634 4.99659 4.99683 4.99708 4.99732 4.99757
+ 4.99782 4.99806 4.99831 4.99853 4.99863 4.99873 4.99883
+ 4.99893 4.99903 4.99913 4.99923 4.99933
+ EOD
+
+ @v[14].set(<<-'EOD')
+ 1.86175 2.00147 1.85141 1.0654 0.275481 0.205547 0.0712627
+ 0.0313387 0.0151431 0.00864531 0.00593861 0.00438111 0.0037479
+ 0.00305857 0.00221221 0.0017081 -0.0896128 -0.109079 -0.121356
+ -0.0542001 0.175821 0.177442 0.0814591 0.0333042 0.0134909
+ 0.00625777 0.00100092 -0.00552776 -0.00411139 -0.00150395
+ -0.000564784 3.48169e-05 -0.000287014 -0.000538515 -0.000456537
+ -0.000325677 -0.000275468 -0.000166452 -8.27481e-05 -8.28704e-05
+ -7.47644e-05 -4.60552e-05 -2.61481e-06 2.26359e-05 2.53852e-05
+ -1.39853e-06 -4.23456e-05 -4.0907e-05 -2.8501e-05 -1.5945e-05
+ -9.01122e-06 -2.07747e-06 1.49328e-06 4.38398e-06 6.84248e-06
+ 4.76711e-06 2.69173e-06 6.16362e-07 -1.45901e-06 -3.53438e-06
+ -4.14256e-06 -3.76238e-06 -3.3822e-06 -3.00202e-06 -2.62184e-06
+ -2.24878e-06 -1.93456e-06 -1.62033e-06 -1.3061e-06 -9.91867e-07
+ -6.77638e-07 -3.63409e-07 -4.91792e-08 2.6505e-07 5.7928e-07
+ 8.93509e-07 1.16076e-06 1.11055e-06 1.06034e-06 1.01014e-06
+ 9.59927e-07 9.09719e-07 8.59511e-07 8.09302e-07 7.59094e-07
+ 7.08886e-07 6.58678e-07 5.99251e-07 4.87523e-07 3.75795e-07
+ 2.64068e-07 1.5234e-07 4.06119e-08 -7.1116e-08 -1.82844e-07
+ -2.94572e-07 -4.063e-07 -5.18027e-07 -6.08517e-07 -5.95879e-07
+ -5.83241e-07 -5.70604e-07 -5.57966e-07 -5.45328e-07 -5.3269e-07
+ -5.20053e-07 -5.07415e-07 -4.94777e-07 -4.8214e-07 -4.69502e-07
+ -4.56864e-07 -4.44226e-07 -4.31589e-07 -4.18951e-07 -4.06313e-07
+ -3.93676e-07 -3.81038e-07 -3.684e-07 -3.55762e-07 -3.43125e-07
+ 1.06736e-05 0.0797407 0.0437947 -0.0645098 -0.0877312 0.0653203
+ -0.00621184 -0.0353188 -0.0491378 -0.0251957 -0.0110996
+ -0.00481123 -0.0020941 -0.000998038 -0.000478747 -0.000445332
+ -0.102046 -0.135753 -0.154351 -0.0827509 0.163348 0.174012
+ 0.0794822 0.0310624 0.0112213 0.00249061 0.00130764 0.00181315
+ 0.00163875 0.00101454 0.000497435 0.000195258 5.31901e-05
+ 2.4607e-05 6.62736e-05 7.90718e-05 4.0372e-05 -0.000141184
+ -0.000280623 5.5608e-05 0.000799565 0.000920189 0.000931616
+ 0.000494527 0.000162303 -8.24884e-05 -0.000183938 -0.000203899
+ -0.000144788 -9.87063e-05 -0.000227929 2.93932e-05 0.000208563
+ 1.88958e-06 -7.6335e-05 -0.000172472 -0.000165656 -0.000145889
+ -0.000177311 -0.000191058 -0.000168287 -0.00015755 -0.00013142
+ -8.10488e-05 -6.36115e-05 -7.8699e-05 -8.11282e-05 -7.98625e-05
+ -5.98807e-05 -3.40879e-05 -1.95464e-05 -1.79247e-05 -4.45514e-05
+ -7.47995e-05 -8.7682e-05 -7.50806e-05 -3.25561e-05 -4.34114e-05
+ -7.69099e-05 -0.000141101 -0.00018743 -0.000148471 -5.06546e-05
+ 0.000120195 0.000177635 0.000177052 0.000146344 9.75126e-05
+ 8.31233e-05 6.8734e-05 5.43447e-05 3.99554e-05 2.55661e-05
+ 1.11768e-05 -3.21253e-06 -3.88937e-06 -3.56628e-06 -3.24318e-06
+ -2.92008e-06 -2.59699e-06 -2.27389e-06 -1.9508e-06 -1.73227e-06
+ -1.56796e-06 -1.40365e-06 -1.23934e-06 -1.07503e-06 -9.10722e-07
+ -7.46412e-07 -5.82101e-07 -4.1779e-07 -2.5348e-07 -8.91694e-08
+ 7.51412e-08 2.39452e-07 4.03762e-07 5.95733e-07 1.00771e-06
+ 1.41969e-06 1.83167e-06 2.24365e-06 0.0828257 0.231038 0.465438
+ 1.54516 2.8461 3.19221 3.40395 3.6382 3.80758 3.93848 4.04882
+ 4.15428 4.247 4.32917 4.40235 4.36941 4.397 4.48862 4.64552
+ 4.86595 5.03475 5.0348 5.02627 5.01967 5.01542 5.00925 4.98613
+ 4.9519 4.91581 4.87357 4.82302 4.80403 4.82565 4.86102 4.89483
+ 4.92253 4.94428 4.96257 4.97608 4.98373 4.98823 4.99182
+ 4.99437 4.99635 4.99745 4.99802 4.99843 4.99873 4.99895
+ 4.99912 4.99925 4.99931 4.99962 4.99973 4.99972 4.99971
+ 4.9997 4.99969 4.9997 4.99971 4.99973 4.99974 4.99976 4.99978
+ 4.9998 4.99982 4.99985 4.99987 4.99989 4.9999 4.99991 4.99991
+ 4.99993 4.99994 4.99997 5.00001 5.00006 5.00008 5.00006
+ 5.00002 5 4.99999 4.99998 4.99997 4.99995 4.99995 4.99995
+ 4.99995 4.99995 4.99995 4.99995 4.99996 4.99997 4.99997
+ 4.99998 4.99999 5 5 5.00001 5.00002 5.00002 5.00002 5.00002
+ 5.00002 5.00002 5.00002 5.00002 5.00002 5.00002 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5 5 5 4.99999 4.99999 4.99999
+ EOD
+
+ @v[15].set(<<-'EOD')
+ 1.86175 2.00199 2.08919 1.84314 1.08254 0.214737 0.0377351
+ 0.00952455 0.00232763 0.000563614 0.000263477 0.000148642
+ 0.000285086 0.000242592 7.34699e-05 -1.53467e-05 -0.0161874
+ -0.0157876 -0.0141194 0.0132576 0.0903272 0.109938 0.0535295
+ 0.0224216 0.00940945 0.00466825 -0.000649972 -0.00654752
+ -0.00333248 -0.00103671 -0.000508276 -5.8896e-05 -0.00043938
+ -0.000544704 -0.00044444 -0.000307093 -0.00024517 -0.000154538
+ -8.78602e-05 -7.10461e-05 -6.06485e-05 -3.91039e-05 -8.45988e-06
+ 9.43442e-06 1.28351e-05 -2.16734e-06 -2.6142e-05 -2.54768e-05
+ -1.88997e-05 -1.17906e-05 -7.3808e-06 -2.97101e-06 1.19146e-07
+ 2.94246e-06 5.38942e-06 3.88851e-06 2.38761e-06 8.86704e-07
+ -6.14201e-07 -2.11511e-06 -2.59565e-06 -2.38885e-06 -2.18205e-06
+ -1.97525e-06 -1.76845e-06 -1.56241e-06 -1.36258e-06 -1.16276e-06
+ -9.62939e-07 -7.63116e-07 -5.63293e-07 -3.6347e-07 -1.63647e-07
+ 3.61756e-08 2.35999e-07 4.35822e-07 6.07653e-07 5.90323e-07
+ 5.72994e-07 5.55665e-07 5.38336e-07 5.21007e-07 5.03678e-07
+ 4.86349e-07 4.6902e-07 4.51691e-07 4.34361e-07 4.11899e-07
+ 3.60315e-07 3.08731e-07 2.57146e-07 2.05562e-07 1.53977e-07
+ 1.02393e-07 5.08082e-08 -7.76222e-10 -5.23607e-08 -1.03945e-07
+ -1.47815e-07 -1.54225e-07 -1.60635e-07 -1.67045e-07 -1.73455e-07
+ -1.79864e-07 -1.86274e-07 -1.92684e-07 -1.99094e-07 -2.05504e-07
+ -2.11914e-07 -2.18324e-07 -2.24734e-07 -2.31144e-07 -2.37554e-07
+ -2.43964e-07 -2.50373e-07 -2.56783e-07 -2.63193e-07 -2.69603e-07
+ -2.76013e-07 -2.82423e-07 2.92534e-06 0.0446777 0.024278
+ -0.0518987 -0.0636547 0.00983929 -0.000518204 -0.000265194
+ 0.000154772 0.000299538 3.12715e-05 -3.18225e-05 -2.48268e-05
+ -1.16701e-05 -6.05117e-06 7.61116e-06 -0.0163668 -0.0158244
+ -0.0141177 0.0100085 0.0857144 0.107784 0.051862 0.0204448
+ 0.00629858 0.000967736 0.00121674 0.00190276 0.00154009
+ 0.000860922 0.000410386 0.000164585 3.99493e-05 1.93797e-05
+ 5.67594e-05 0.000110126 2.49925e-05 -7.17815e-05 -0.000142299
+ -1.63109e-05 0.000439529 0.000562489 0.000594599 0.000326164
+ 0.000126423 -4.26063e-05 -0.000122927 -0.000114152 -6.72706e-05
+ -6.41242e-05 -0.000135588 2.61507e-05 0.000134036 6.43734e-06
+ -4.6223e-05 -0.000112047 -0.000101388 -8.67847e-05 -0.000117664
+ -0.000133957 -0.000116558 -0.000100873 -7.65448e-05 -4.44964e-05
+ -3.6677e-05 -5.26632e-05 -5.45172e-05 -5.13545e-05 -3.73869e-05
+ -1.99732e-05 -1.0907e-05 -1.10081e-05 -3.02609e-05 -5.18517e-05
+ -6.13597e-05 -5.30706e-05 -2.39572e-05 -3.24146e-05 -5.70062e-05
+ -0.000103448 -0.000135376 -0.0001024 -2.39007e-05 0.000110929
+ 0.000151226 0.000142044 0.000105922 5.62834e-05 4.78476e-05
+ 3.94117e-05 3.09759e-05 2.25401e-05 1.41042e-05 5.66837e-06
+ -2.76747e-06 -3.08639e-06 -2.81341e-06 -2.54043e-06 -2.26745e-06
+ -1.99447e-06 -1.72149e-06 -1.44851e-06 -1.26226e-06 -1.12096e-06
+ -9.79661e-07 -8.38363e-07 -6.97065e-07 -5.55768e-07 -4.1447e-07
+ -2.73173e-07 -1.31875e-07 9.42259e-09 1.5072e-07 2.92018e-07
+ 4.33315e-07 5.74613e-07 7.10363e-07 8.01984e-07 8.93604e-07
+ 9.85225e-07 1.07685e-06 0.04474 0.0928765 0.141327 0.0176048
+ -0.071675 -0.0124613 0.989022 2.28104 3.40619 4.21417 4.67173
+ 4.87438 4.96044 4.98996 4.99858 4.96672 4.89502 4.79391
+ 4.76433 4.8387 4.98612 5.0161 5.01722 5.01437 5.01256 4.99827
+ 4.95807 4.9209 4.88217 4.83006 4.78461 4.80759 4.85548 4.89604
+ 4.9254 4.94617 4.96126 4.97374 4.98255 4.98792 4.99126 4.99361
+ 4.99554 4.99699 4.99792 4.99846 4.99881 4.99905 4.99924
+ 4.99938 4.99949 4.99955 4.9997 4.9998 4.99982 4.99982 4.99982
+ 4.99982 4.99982 4.99983 4.99984 4.99985 4.99986 4.99987
+ 4.99988 4.99989 4.9999 4.99992 4.99993 4.99994 4.99995 4.99995
+ 4.99996 4.99996 4.99998 4.99999 5.00001 5.00002 5.00002
+ 5.00001 5.00001 5 4.99999 4.99999 4.99998 4.99998 4.99998
+ 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998
+ 4.99999 4.99999 4.99999 4.99999 5 5 5 5 5 5 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ EOD
+
+ @v[16].set(<<-'EOD')
+ 1.86175 1.73073 1.50572 1.89001 3.39004 4.36034 4.79012
+ 4.93798 4.98305 4.99539 4.9979 4.99904 4.99772 4.9983 4.99935
+ 4.99975 4.98837 4.99456 4.99728 5.01838 5.04568 5.00759
+ 4.98112 4.98479 4.99197 4.99641 4.99747 4.99775 5.00043
+ 5.0007 5.00035 5.00023 4.99976 5.00002 5.00007 5.0002 4.99993
+ 5.00003 5.00021 5.00006 4.99993 4.99992 5.00002 5.00013
+ 5.00017 5.00009 4.99992 4.99991 4.99993 4.99996 4.99998
+ 4.99999 5.00001 5.00003 5.00005 5.00004 5.00004 5.00003
+ 5.00002 5.00001 5 4.99999 4.99999 4.99998 4.99998 4.99997
+ 4.99997 4.99998 4.99998 4.99998 4.99998 4.99999 4.99999
+ 4.99999 4.99999 5 5 5 5 5 5 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00002 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 5 5.01498 4.99342 4.96899 5.00301 5.02627 4.9977
+ 4.99548 4.99757 5.00277 5.00245 5.0014 5.00069 5.00032 5.00014
+ 5.00009 4.9867 4.99262 4.99607 5.01805 5.04713 5.00927 4.98184
+ 4.98483 4.9914 4.99616 4.99902 4.9999 4.99987 4.99979 4.99981
+ 4.99989 4.99994 4.99998 5.0002 5.00001 5.00008 5.00008 5.0001
+ 5.00021 5.00032 5.00025 5.00019 5.00006 5.00007 4.99994
+ 4.99997 4.99999 5.00023 5.00008 4.99993 4.99998 4.99986
+ 4.99982 5.00003 4.99985 4.99996 5.00014 5 4.99984 4.99979
+ 4.99982 4.99993 5.00008 5.00011 5.00002 4.99996 4.9999 4.99994
+ 5.00001 5.00007 5.00009 4.99995 4.99978 4.99971 4.99976
+ 4.99997 4.99996 4.99989 4.99972 4.99955 4.99953 4.99959
+ 4.99976 4.9999 5.00005 5.00023 5.00039 5.00034 5.00029 5.00024
+ 5.00019 5.00014 5.00009 5.00004 5.00003 5.00002 5.00001
+ 5 5 4.99999 4.99998 4.99998 4.99998 4.99998 4.99998 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 5 5 5 5
+ 5.00001 5.00002 5.00003 5.00004 5.01564 5.03395 5.04932
+ 5.11868 3.92502 1.31888 0.163888 0.0946876 0.0789578 0.0565084
+ 0.0260333 0.0156986 0.00907667 0.00613629 0.00468417 -0.00174008
+ -0.0021422 0.000586962 0.0124937 0.0147977 0.00838454 0.00039383
+ -0.000522021 -0.000426598 -0.000290214 -0.00173713 -0.00384132
+ -0.00382945 -0.00429219 -0.00580193 -0.00393246 0.0017543
+ 0.00423045 0.00408931 0.0031976 0.00245457 0.00187293 0.00159068
+ 0.00105697 0.000609902 0.000358825 0.000334125 0.000212708
+ 0.000168116 8.97349e-05 5.21578e-05 3.84527e-05 2.93033e-05
+ 2.10067e-05 1.59954e-05 1.13917e-05 5.49738e-06 2.77217e-05
+ 6.51259e-06 -6.65468e-06 2.09837e-06 -6.617e-06 -4.80187e-06
+ 1.55031e-06 4.26536e-06 7.69457e-07 -1.46213e-06 -7.25202e-07
+ 3.26501e-06 6.55807e-06 7.524e-06 6.07209e-06 6.00701e-06
+ 5.41166e-06 3.86573e-06 1.10651e-06 -2.74603e-06 -2.18566e-06
+ 2.3658e-06 8.59956e-06 8.35046e-06 2.90621e-06 -8.75982e-07
+ -1.87189e-06 -2.1528e-06 -1.94875e-06 -1.74471e-06 -1.54067e-06
+ -1.33662e-06 -1.13258e-06 -8.40567e-07 -5.20743e-07 -2.00918e-07
+ 1.18906e-07 4.38731e-07 6.11382e-07 6.01529e-07 5.91675e-07
+ 5.81822e-07 5.71968e-07 5.62115e-07 5.52261e-07 5.42407e-07
+ 5.32554e-07 5.227e-07 5.12847e-07 4.72812e-07 4.26137e-07
+ 3.79462e-07 3.32786e-07 2.86111e-07 2.39436e-07 1.92761e-07
+ 1.46086e-07 9.94107e-08 5.27356e-08 -2.77779e-10 -7.98079e-08
+ -1.59338e-07 -2.38868e-07 -3.18398e-07 -3.97928e-07 -4.77458e-07
+ -5.56988e-07 -6.36519e-07
+ EOD
+
+ @v[17].set(<<-'EOD')
+ 5 5.16963 4.84136 3.33754 0.316206 0.103113 0.0273341 0.0221102
+ 0.0177008 0.0143758 0.0115203 0.00929231 0.00752716 0.00625439
+ 0.00489872 0.00403656 -0.0657317 -0.0256467 0.165394 0.985963
+ 3.05067 4.55799 4.89728 4.92464 4.8882 4.90592 4.97315 4.99241
+ 4.99694 4.99845 4.99905 4.99939 4.99959 4.99971 4.9998 4.99986
+ 4.9999 4.99993 4.99995 4.99996 4.99997 4.99998 4.99998 4.99999
+ 4.99999 4.99999 4.99999 4.99999 5 5.00001 5.00003 5.00005
+ 5.00004 5.00002 5 4.99999 4.99999 4.99998 4.99998 4.99997
+ 4.99997 4.99998 4.99998 4.99999 4.99999 5 5 5 5 5 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00002 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5 5 5 5
+ 5 5 5 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99998
+ 4.99998 4.99998 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 5 5 5 5 5 5 5.00025 5.1657 4.69981 2.43895
+ 0.0229743 0.0351406 -0.0211974 -0.0312063 -0.0160331 -0.0021718
+ -0.000766597 -0.000251052 -5.49363e-05 -3.36364e-06 -2.01983e-06
+ -9.70575e-06 -0.0657007 -0.0205247 0.183332 1.07163 3.11839
+ 4.46213 4.84163 4.95195 4.99159 5.02084 5.04029 5.04138
+ 5.0271 5.00445 4.97957 4.95702 4.95231 4.97819 4.99191 4.9963
+ 4.99822 4.99878 4.99903 4.99925 4.99942 4.9995 4.99954 4.99957
+ 4.99961 4.99966 4.9997 4.99974 4.99977 4.99981 4.99983 4.99986
+ 4.99988 4.9999 4.99991 4.99992 4.99994 4.99995 4.99995 4.99996
+ 4.99997 4.99997 4.99998 4.99998 4.99998 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5.00001 5.00001 5.00001
+ 5.00002 5.00002 5.00002 5.00002 5.00002 5.00002 5.00002
+ 5.00002 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5 5 5 4.99999 4.99998 4.99997 4.99996 5.14239 4.76219
+ 3.16574 0.299969 0.0631609 -0.00118611 -0.00026052 -5.96333e-05
+ -1.44904e-05 -4.3859e-06 -2.99454e-06 1.10547e-06 4.84662e-06
+ 1.30971e-05 2.23082e-05 -0.0655844 -0.0204818 0.182507 1.05954
+ 3.12277 4.46735 4.83915 4.94512 4.97679 4.98654 4.9966 5.00833
+ 5.00776 5.00432 5.00199 5.00086 5.00033 5.00008 5 5.00001
+ 5 5.00005 5.00002 4.99981 4.99991 4.99998 4.99979 4.99979
+ 4.99984 4.9998 4.9998 5.00006 5.00002 5.00001 5 5 4.99992
+ 4.99998 4.99999 5.00002 5.00014 4.99999 4.99987 4.99993
+ 5.00003 5.00011 5.00005 4.99996 4.99987 4.99985 4.99994
+ 5.00009 5.0001 5 4.99993 4.99997 5.00008 5.00015 5.00021
+ 5.00021 5.00007 4.99978 4.99965 4.99973 4.9999 4.99992 4.99995
+ 4.99997 4.99999 5.00001 5.00002 5.00001 5.00001 5.00001
+ 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99998 4.99998 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 5 5 5 5 5 5.00001 5.00001 5.00001 5.00002
+ 5.00002 5.00002
+ EOD
+
+ @v[18].set(<<-'EOD')
+ 5 5.0333 5.02472 4.92559 4.18383 3.93923 3.9961 4.14293
+ 4.28591 4.41336 4.52157 4.61101 4.68472 4.7439 4.79294 4.83239
+ 4.80697 4.78808 4.79322 4.8838 5.08529 5.21863 4.88852 3.90198
+ 2.14586 0.383977 0.101103 0.0525711 0.0318287 0.020895 0.0146908
+ 0.010831 0.00830272 0.00656377 0.00532066 0.00440078 0.00369956
+ 0.00315713 0.00272614 0.00237965 0.00209659 0.00186339 0.00167014
+ 0.0015081 0.00137172 0.00125607 0.00115393 0.00106076 0.000980166
+ 0.000918015 0.000862837 0.00080766 0.000763488 0.000721541
+ 0.000680825 0.000653026 0.000625226 0.000597426 0.000569627
+ 0.000541827 0.000519087 0.000499756 0.000480424 0.000461093
+ 0.000441761 0.000423291 0.000411941 0.00040059 0.00038924
+ 0.000377889 0.000366539 0.000355188 0.000343838 0.000332487
+ 0.000321137 0.000309786 0.000299055 0.000292509 0.000285963
+ 0.000279417 0.000272871 0.000266325 0.000259779 0.000253233
+ 0.000246686 0.00024014 0.000233594 0.000227387 0.0002231
+ 0.000218813 0.000214526 0.00021024 0.000205953 0.000201666
+ 0.000197379 0.000193092 0.000188805 0.000184519 0.000180526
+ 0.000177963 0.0001754 0.000172837 0.000170274 0.000167711
+ 0.000165148 0.000162585 0.000160022 0.000157459 0.000154895
+ 0.000152332 0.000149769 0.000147206 0.000144643 0.00014208
+ 0.000139517 0.000136954 0.000134391 0.000131828 0.000129265
+ 0.000126702 0.000132838 0.0311184 0.163151 0.34986 0.604501
+ 0.357125 0.136137 0.0711304 0.0346959 0.0212674 0.00872193
+ 0.00252206 0.000455269 7.59332e-05 2.91532e-05 0.000320562
+ -0.0720911 -0.0840491 -0.0791345 -0.0404143 0.0182035 -0.0235871
+ -0.0426072 -0.0597501 0.00824773 0.481404 1.32496 2.11949
+ 2.57317 2.58202 2.15054 1.33786 0.45702 0.153772 0.0913584
+ 0.0604989 0.0421591 0.0271456 0.0170021 0.0115815 0.00907886
+ 0.00742466 0.00626096 0.00531127 0.00450501 0.00381927 0.00323718
+ 0.00274374 0.00232494 0.00196885 0.00166686 0.00141134 0.00119437
+ 0.0010109 0.000855534 0.000723378 0.000611408 0.000516704
+ 0.000436769 0.000369523 0.000313026 0.00026526 0.000223976
+ 0.000188972 0.000159042 0.000134148 0.000112688 9.49738e-05
+ 7.97877e-05 6.721e-05 5.65115e-05 4.77194e-05 4.03591e-05
+ 3.42848e-05 2.92627e-05 2.50435e-05 2.1412e-05 1.84532e-05
+ 1.58624e-05 1.34673e-05 1.14461e-05 1.00935e-05 9.12375e-06
+ 8.50202e-06 7.81431e-06 7.20729e-06 6.73936e-06 6.3702e-06
+ 5.90049e-06 5.43077e-06 4.96105e-06 4.49133e-06 4.02162e-06
+ 3.5519e-06 3.08218e-06 2.79099e-06 2.51281e-06 2.23463e-06
+ 1.95645e-06 1.67827e-06 1.40009e-06 1.12191e-06 1.01376e-06
+ 9.9375e-07 9.73741e-07 9.53733e-07 9.33724e-07 9.13715e-07
+ 8.93707e-07 8.73698e-07 8.5369e-07 8.33681e-07 8.13673e-07
+ 7.93664e-07 7.73655e-07 7.53647e-07 7.21781e-07 5.956e-07
+ 4.69419e-07 3.43239e-07 2.17058e-07 0.0284032 0.0374438
+ -0.0157543 -0.0680497 0.0504768 0.0100294 0.00222261 0.000528697
+ 0.000132929 3.99489e-05 2.46066e-05 4.56327e-06 -6.54853e-06
+ 1.33783e-05 -3.68221e-05 -0.0724498 -0.0843663 -0.0792935
+ -0.0406426 0.0200019 0.0426259 0.0220753 0.00668555 -0.000968483
+ 0.024662 0.0383437 0.0911513 0.087848 0.0602076 0.0390559
+ 0.0260573 0.0180444 0.012974 0.00985409 0.00788132 0.0064228
+ 0.005545 0.00453571 0.00364245 0.00310278 0.00270523 0.00236439
+ 0.0020945 0.00186808 0.00167493 0.00151731 0.00138594 0.00126945
+ 0.00116695 0.0010762 0.000996366 0.000928387 0.000864414
+ 0.000808258 0.000759574 0.000713865 0.000666712 0.000632716
+ 0.000601262 0.000572163 0.000543986 0.000515253 0.0004897
+ 0.000468112 0.000449313 0.000432981 0.000417911 0.000401307
+ 0.000382712 0.000366678 0.000355736 0.000349171 0.000335727
+ 0.000317091 0.000296086 0.000283543 0.000277366 0.000272233
+ 0.000267001 0.000263147 0.000256699 0.000250251 0.000243803
+ 0.000237355 0.000230907 0.000225424 0.000220247 0.000215069
+ 0.000209892 0.000204714 0.000200213 0.000196548 0.000192884
+ 0.00018922 0.000185556 0.000181892 0.000178228 0.000174564
+ 0.0001709 0.000167236 0.000163572 0.000160824 0.000158279
+ 0.000155733 0.000153187 0.000150641 0.000148095 0.000145549
+ 0.000143003 0.000140457 0.000137911 0.000135457 0.000133386
+ 0.000131315 0.000129245 0.000127174 0.000125103 0.000123032
+ 0.000120961 0.000118891
+ EOD
+
+ @v[19].set(<<-'EOD')
+ 1.86175 1.99994 2.0833 2.01627 2.42503 3.25769 3.62134 3.88827
+ 4.09688 4.26773 4.40529 4.51734 4.60827 4.68313 4.74346
+ 4.79302 4.72815 4.68959 4.70421 4.81316 5.01375 5.14493
+ 5.10305 5.0699 5.04484 5.03751 5.03348 5.02504 5.01799 5.01271
+ 5.00895 5.00628 5.0044 5.00309 5.00216 5.00151 5.00105 5.00073
+ 5.00051 5.00034 5.00023 5.00015 5.0001 5.00007 5.00003 4.99998
+ 4.99993 4.99993 4.99995 4.99999 5.00001 5.00003 5.00002
+ 5.00001 5 5 5 5 4.99999 4.99999 4.99999 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5.00017 5.17398
+ 4.94779 3.78508 1.52302 0.608808 0.244311 0.126053 0.0597175
+ 0.038422 0.0158174 0.00481338 0.00107847 0.000301256 0.000114861
+ 0.00059489 -0.118904 -0.147478 -0.158986 -0.080544 0.165361
+ 0.171378 0.0776087 0.0435738 0.0428235 0.0423755 0.0347695
+ 0.0225061 0.0155539 0.0121357 0.0107997 0.0103976 0.0124406
+ 0.016814 0.0167556 0.0149852 0.01459 0.0141182 0.0131934
+ 0.0120286 0.0108692 0.0097184 0.00855881 0.00744912 0.00643877
+ 0.00554044 0.00475165 0.00406535 0.00347158 0.00295981 0.00251995
+ 0.00214318 0.00182101 0.00154613 0.00131196 0.0011119 0.000941587
+ 0.000796999 0.000674582 0.000571283 0.000484276 0.000410649
+ 0.000347005 0.000292984 0.000246715 0.000208143 0.00017489
+ 0.000147412 0.000123854 0.000104332 8.77229e-05 7.40686e-05
+ 6.2637e-05 5.32e-05 4.53946e-05 3.88343e-05 3.31864e-05
+ 2.85905e-05 2.45725e-05 2.08671e-05 1.77301e-05 1.55911e-05
+ 1.40153e-05 1.29421e-05 1.18693e-05 1.09815e-05 1.03484e-05
+ 9.87664e-06 9.14446e-06 8.41228e-06 7.68011e-06 6.94793e-06
+ 6.21575e-06 5.48357e-06 4.7514e-06 4.38454e-06 4.04432e-06
+ 3.7041e-06 3.36388e-06 3.02366e-06 2.68344e-06 2.34322e-06
+ 2.15196e-06 2.03791e-06 1.92386e-06 1.80982e-06 1.69577e-06
+ 1.58173e-06 1.46768e-06 1.35363e-06 1.23959e-06 1.12554e-06
+ 1.0115e-06 8.9745e-07 7.83404e-07 6.69358e-07 4.76113e-07
+ -3.47071e-07 -1.17025e-06 -1.99344e-06 -2.81662e-06 0.0783754
+ 0.0500262 -0.0659563 -0.120914 0.0815957 0.0154255 0.00347177
+ 0.000840357 0.000214582 6.54655e-05 3.91709e-05 8.07396e-06
+ -4.44265e-07 1.74384e-05 -4.52725e-05 -0.119379 -0.147984
+ -0.159247 -0.0824604 0.169014 0.177628 0.0758742 0.010558
+ -0.0346506 -0.0710288 -0.0838952 -0.0599521 -0.034568 -0.0181615
+ -0.00968034 -0.00547115 -0.00333511 -0.00232468 -0.00181159
+ -0.00143841 -0.00116601 -0.000839755 -0.000569764 -0.000578683
+ -0.000490551 -0.000411712 -0.000437859 -0.000408185 -0.000356644
+ -0.000311332 -0.000269006 -0.000221396 -0.000210054 -0.0001923
+ -0.000175122 -0.000161039 -0.0001428 -0.000126123 -0.000127893
+ -8.14516e-05 -0.000120166 -0.000154909 -0.000112733 -8.40377e-05
+ -7.11342e-05 -8.09538e-05 -9.77789e-05 -9.82402e-05 -7.73531e-05
+ -5.28255e-05 -3.1096e-05 -1.87967e-05 -1.96552e-05 -4.16655e-05
+ -5.77185e-05 -5.24142e-05 -2.83153e-05 -1.90012e-05 -1.54415e-05
+ -2.52569e-05 -6.23747e-05 -0.000130543 -0.000149394 -0.000110886
+ -4.35517e-05 -4.17084e-05 -3.98651e-05 -3.80218e-05 -3.61785e-05
+ -3.43352e-05 -3.36249e-05 -3.32729e-05 -3.29208e-05 -3.25687e-05
+ -3.22166e-05 -3.17143e-05 -3.10258e-05 -3.03372e-05 -2.96486e-05
+ -2.89601e-05 -2.82715e-05 -2.75829e-05 -2.68944e-05 -2.62058e-05
+ -2.55173e-05 -2.48287e-05 -2.43043e-05 -2.38159e-05 -2.33276e-05
+ -2.28393e-05 -2.2351e-05 -2.18626e-05 -2.13743e-05 -2.0886e-05
+ -2.03977e-05 -1.99093e-05 -1.945e-05 -1.91122e-05 -1.87744e-05
+ -1.84366e-05 -1.80987e-05 -1.77609e-05 -1.74231e-05 -1.70853e-05
+ -1.67474e-05
+ EOD
+
+ @v[20].set(<<-'EOD')
+ 1.86175 1.99724 2.17266 2.48439 3.15933 3.85231 4.38091
+ 4.69033 4.85034 4.92851 4.96453 4.98188 4.98736 4.991 4.99482
+ 4.9973 4.96422 4.89989 4.83907 4.83151 4.90868 5.04854 5.06104
+ 5.04571 5.03219 5.03025 5.02273 5.01707 5.0123 5.0087 5.00611
+ 5.00429 5.00301 5.00211 5.00148 5.00103 5.00072 5.0005 5.00035
+ 5.00024 5.00016 5.00011 5.00007 5.00005 5.00003 5.00001
+ 4.99999 4.99998 4.99998 4.99998 4.99998 4.99998 4.99999
+ 5 5 5.00001 5.00001 5.00002 5.00002 5.00002 5.00002 5.00002
+ 5.00002 5.00001 5.00001 5 5 5 5 5 5 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 5 5 5 5 5 5 5 5 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5 5 5 5
+ 5 5 4.99981 5.10081 5.10903 4.98404 5.00999 5.14946 4.36501
+ 2.23938 0.325144 0.00660272 -0.0102186 -0.0082401 -0.00556785
+ -0.00374178 -0.00264763 -0.00202823 -0.0182241 -0.0169551
+ -0.0150395 0.0103736 0.0877592 0.104382 0.0515938 0.0373818
+ 0.0411547 0.0397009 0.0308946 0.0205793 0.0154037 0.0129191
+ 0.0119327 0.011527 0.0124295 0.0161152 0.0161076 0.0145391
+ 0.0144541 0.0139287 0.0129215 0.0117239 0.0105795 0.00942983
+ 0.00827423 0.00718354 0.00619954 0.00532868 0.00456631 0.00390448
+ 0.00333254 0.00284003 0.00241714 0.00205524 0.0017458 0.00148202
+ 0.00125739 0.0010655 0.000902213 0.000763611 0.000646279
+ 0.000547291 0.000463934 0.000393401 0.000332424 0.000280655
+ 0.000236328 0.000199386 0.000167536 0.000141218 0.000118654
+ 9.99559e-05 8.40479e-05 7.09694e-05 6.00188e-05 5.09786e-05
+ 4.3502e-05 3.72191e-05 3.18114e-05 2.74071e-05 2.35539e-05
+ 1.99967e-05 1.69871e-05 1.49449e-05 1.3451e-05 1.24492e-05
+ 1.14256e-05 1.05669e-05 9.94487e-06 9.47514e-06 8.77318e-06
+ 8.07123e-06 7.36927e-06 6.66731e-06 5.96536e-06 5.2634e-06
+ 4.56144e-06 4.23044e-06 3.92649e-06 3.62254e-06 3.31858e-06
+ 3.01463e-06 2.71068e-06 2.40673e-06 2.23063e-06 2.12082e-06
+ 2.01102e-06 1.90121e-06 1.7914e-06 1.68159e-06 1.57178e-06
+ 1.46197e-06 1.35216e-06 1.24235e-06 1.13255e-06 1.02274e-06
+ 9.12929e-07 8.0312e-07 6.33171e-07 -1.51288e-08 -6.63428e-07
+ -1.31173e-06 -1.96003e-06 0.0437517 0.0265689 -0.0515377
+ -0.0658688 0.010727 -0.000511921 -8.36924e-05 2.13278e-05
+ 1.45207e-05 4.54862e-06 -6.14726e-06 2.0062e-06 1.02709e-06
+ 1.4152e-05 -3.08225e-05 -0.0166501 -0.0157139 -0.013957
+ 0.0107537 0.0873717 0.111302 0.0454129 -0.00530142 -0.0468336
+ -0.0790063 -0.0826944 -0.0534753 -0.0288705 -0.0149009 -0.00801592
+ -0.0046342 -0.00291835 -0.00213019 -0.00170055 -0.001352
+ -0.00110593 -0.000742655 -0.000532042 -0.000544742 -0.000479206
+ -0.000407307 -0.000403575 -0.000366209 -0.000324161 -0.000286183
+ -0.000247579 -0.000214281 -0.000203435 -0.000186896 -0.000171033
+ -0.00015779 -0.000145259 -0.000128069 -0.000122647 -9.89398e-05
+ -0.000114926 -0.000132195 -0.000107872 -8.91015e-05 -7.87996e-05
+ -8.14061e-05 -8.9098e-05 -8.83368e-05 -7.6122e-05 -6.14668e-05
+ -4.75402e-05 -3.81855e-05 -3.69696e-05 -4.78656e-05 -5.61346e-05
+ -5.35007e-05 -4.1459e-05 -3.35411e-05 -2.52374e-05 -2.37479e-05
+ -4.6406e-05 -9.41884e-05 -0.000109222 -8.52676e-05 -4.25166e-05
+ -4.10125e-05 -3.95085e-05 -3.80045e-05 -3.65004e-05 -3.49964e-05
+ -3.41627e-05 -3.3541e-05 -3.29193e-05 -3.22976e-05 -3.16758e-05
+ -3.10334e-05 -3.03653e-05 -2.96971e-05 -2.9029e-05 -2.83609e-05
+ -2.76928e-05 -2.70246e-05 -2.63565e-05 -2.56884e-05 -2.50203e-05
+ -2.43521e-05 -2.38716e-05 -2.34324e-05 -2.29932e-05 -2.25539e-05
+ -2.21147e-05 -2.16755e-05 -2.12362e-05 -2.0797e-05 -2.03578e-05
+ -1.99186e-05 -1.95079e-05 -1.9217e-05 -1.8926e-05 -1.8635e-05
+ -1.8344e-05 -1.8053e-05 -1.7762e-05 -1.74711e-05 -1.71801e-05
+ EOD
+
+ @v[21].set(<<-'EOD')
+ 1.86175 1.73273 1.42016 1.02483 0.944013 0.274107 0.0823742
+ 0.0379366 0.020816 0.0132952 0.00955525 0.00717008 0.00592286
+ 0.00437379 0.00383557 0.00273694 -0.0037467 -0.0054191 -0.00131454
+ 0.0112179 0.0133918 0.00519747 -0.00260113 -0.00252847 -0.00181292
+ 0.000183398 -0.000667607 -0.000750747 -0.000594314 -0.000433904
+ -0.000308985 -0.000217858 -0.000152926 -0.000107454 -7.54076e-05
+ -5.2675e-05 -3.66299e-05 -2.54341e-05 -1.75095e-05 -1.18848e-05
+ -7.97289e-06 -5.30239e-06 -3.53615e-06 -2.38504e-06 -2.40158e-06
+ -3.84485e-06 -5.29435e-06 -2.57099e-06 1.95189e-06 3.55083e-06
+ 2.06179e-06 5.72753e-07 3.30469e-07 3.40296e-07 3.60221e-07
+ 4.86081e-07 6.1194e-07 7.37799e-07 8.63659e-07 9.89518e-07
+ 9.21274e-07 7.22275e-07 5.23276e-07 3.24277e-07 1.25278e-07
+ -5.59467e-08 -9.03265e-08 -1.24706e-07 -1.59086e-07 -1.93466e-07
+ -2.27846e-07 -2.62226e-07 -2.96605e-07 -3.30985e-07 -3.65365e-07
+ -3.99745e-07 -4.24266e-07 -3.82163e-07 -3.40061e-07 -2.97959e-07
+ -2.55857e-07 -2.13755e-07 -1.71652e-07 -1.2955e-07 -8.7448e-08
+ -4.53457e-08 -3.24353e-09 3.76901e-08 7.19937e-08 1.06297e-07
+ 1.40601e-07 1.74904e-07 2.09208e-07 2.43512e-07 2.77815e-07
+ 3.12119e-07 3.46422e-07 3.80726e-07 4.04507e-07 3.77191e-07
+ 3.49876e-07 3.22561e-07 2.95246e-07 2.67931e-07 2.40616e-07
+ 2.13301e-07 1.85986e-07 1.58671e-07 1.31356e-07 1.04041e-07
+ 7.67256e-08 4.94105e-08 2.20955e-08 -5.21962e-09 -3.25347e-08
+ -5.98498e-08 -8.71649e-08 -1.1448e-07 -1.41795e-07 -1.6911e-07
+ 7.87893e-06 0.0114592 -0.0245712 -0.111637 0.0961324 1.61168
+ 3.22343 4.20442 4.53535 4.83834 4.95464 4.98874 4.99746
+ 4.99883 4.99948 4.99815 4.98431 4.99298 4.99718 5.01948
+ 5.04749 5.008 4.98243 4.98985 4.99781 4.99887 4.99679 4.99616
+ 4.99743 4.99859 4.99936 4.99972 5.00058 5.00123 5.0002 4.99945
+ 4.99983 4.9998 4.99966 4.99958 4.99956 4.99956 4.99956 4.99958
+ 4.99961 4.99965 4.99969 4.99973 4.99977 4.9998 4.99983 4.99985
+ 4.99987 4.99989 4.99991 4.99992 4.99993 4.99994 4.99995
+ 4.99996 4.99997 4.99997 4.99998 4.99998 4.99998 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5.00001 5.00001
+ 5.00001 5.00002 5.00002 5.00002 5.00002 5.00002 5.00002
+ 5.00002 5.00002 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5 5 5 4.99999 4.99998 4.99997 4.99996 5.01454
+ 4.99566 4.96796 4.99819 5.03232 5.00034 4.99867 4.99937
+ 4.99977 4.99992 4.99997 4.99999 5.00001 5.00021 4.99974
+ 4.98462 4.99301 4.99723 5.01936 5.04807 5.00929 4.9789 4.97876
+ 4.98244 4.9863 4.99575 5.0069 5.00863 5.00624 5.00357 5.0019
+ 5.00098 5.00048 5.00025 5.00016 5.00011 5.00013 5.00009
+ 4.99982 4.99994 5.00005 4.99994 4.99988 4.99989 4.99997
+ 5.00003 5.00005 5.00002 5.00001 5.00001 5.00001 4.99993
+ 4.99999 5 5.00021 4.99997 4.99981 5 5.00009 5.0001 5.00001
+ 4.99991 4.9999 5 5.00011 5.00017 5.00018 5.00018 5.00014
+ 5.00007 4.99999 4.9999 4.9999 5.00001 5.00016 5.00014 4.99999
+ 4.99993 4.99999 5.00009 5.00007 5.00006 5.00004 5.00003
+ 5.00001 5.00001 5 4.99999 4.99998 4.99997 4.99997 4.99997
+ 4.99998 4.99998 4.99998 4.99998 4.99999 4.99999 4.99999
+ 5 5 5 5 5 5 5.00001 5.00001 5.00001 5.00001 5.00001 5.00002
+ 5.00002 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5 5
+ EOD
+
+ @v[22].set(<<-'EOD')
+ 7.10441e-10 0.00107105 0.000637109 -0.00236346 -0.018079
+ -0.0120077 -0.00217059 0.00266679 0.00403383 0.00403836
+ 0.00356705 0.00303303 0.00244716 0.00198586 0.0016855 0.00136497
+ -3.96022e-05 -0.000367409 -3.77079e-05 0.00194085 0.00506964
+ -0.0400214 -0.0402572 0.0524434 0.286234 0.803011 1.44795
+ 2.02473 2.54768 3.02748 3.4415 3.78287 4.09667 4.35152 4.53987
+ 4.67614 4.77407 4.84319 4.89227 4.92702 4.95119 4.96764
+ 4.97846 4.98557 4.98982 4.99209 4.99371 4.99569 4.99727
+ 4.99802 4.99834 4.99867 4.99892 4.99915 4.99936 4.99939
+ 4.99943 4.99946 4.9995 4.99953 4.99957 4.9996 4.99963 4.99967
+ 4.9997 4.99973 4.99974 4.99975 4.99976 4.99977 4.99978 4.9998
+ 4.99981 4.99982 4.99983 4.99984 4.99985 4.99986 4.99986
+ 4.99986 4.99987 4.99987 4.99988 4.99988 4.99989 4.99989
+ 4.9999 4.9999 4.9999 4.9999 4.99991 4.99991 4.99991 4.99991
+ 4.99992 4.99992 4.99992 4.99992 4.99993 4.99993 4.99993
+ 4.99993 4.99993 4.99993 4.99993 4.99993 4.99994 4.99994
+ 4.99994 4.99994 4.99994 4.99994 4.99994 4.99994 4.99995
+ 4.99995 4.99995 4.99995 4.99995 4.99995 4.99995 5.00145
+ 5.00659 5.01209 5.01931 5.00279 4.99273 4.99217 4.99295
+ 4.99471 4.99594 4.99696 4.9978 4.99844 4.99891 4.99924 4.99635
+ 4.99699 4.99813 5.00068 5.00307 5.0588 4.96365 4.54012 3.6307
+ 2.35176 1.0322 0.354379 0.115986 0.0435668 0.0245112 0.020786
+ 0.0164656 0.0118409 0.00849698 0.00597078 0.0040105 0.0026076
+ 0.0016597 0.00118185 0.00121067 0.00153587 0.00174836 0.00136519
+ -0.000189116 -0.00315555 -0.00646603 -0.00898042 -0.010203
+ -0.0110896 -0.0123764 -0.00953841 -0.00225795 0.000818314
+ 0.00152252 0.00150269 0.00119025 0.000767068 0.000308852
+ -3.79272e-05 -0.00019691 -0.000186642 -9.73653e-05 -8.49784e-06
+ 2.04147e-05 -9.91086e-06 -1.55959e-05 -1.80499e-05 -1.77097e-05
+ -1.51548e-05 -1.1978e-05 -9.84916e-06 -1.29728e-05 -1.67235e-05
+ -1.74153e-05 -1.39958e-05 -5.92272e-06 -8.08216e-06 -1.53077e-05
+ -2.92531e-05 -3.91049e-05 -2.98935e-05 -7.32122e-06 3.18534e-05
+ 4.39134e-05 4.18753e-05 3.22759e-05 1.86766e-05 1.58432e-05
+ 1.30098e-05 1.01765e-05 7.34312e-06 4.50975e-06 1.67639e-06
+ -1.15697e-06 -1.23877e-06 -1.11991e-06 -1.00106e-06 -8.82208e-07
+ -7.63355e-07 -6.44502e-07 -5.2565e-07 -4.29318e-07 -3.44661e-07
+ -2.60004e-07 -1.75347e-07 -9.06904e-08 -6.03349e-09 7.86234e-08
+ 1.6328e-07 2.47937e-07 3.32594e-07 4.17251e-07 5.01908e-07
+ 5.86565e-07 6.71222e-07 7.36123e-07 6.43886e-07 5.5165e-07
+ 4.59414e-07 3.67178e-07 0.000334759 -4.60833e-05 -0.00106139
+ -0.00166624 0.000859563 0.00102606 0.00410037 0.00419931
+ 0.00518997 0.00459791 0.00503125 0.00523877 0.00452158 0.00339924
+ 0.00233399 0.000876915 0.000546439 0.000444299 0.000983968
+ 0.00119304 -0.0429422 -0.0403983 0.0534896 0.288013 0.807345
+ 1.44247 2.03448 2.57021 3.05049 3.47332 3.8131 4.1009 4.34677
+ 4.53512 4.67127 4.76531 4.82526 4.86593 4.89586 4.91904
+ 4.93806 4.95348 4.96597 4.97629 4.9843 4.98983 4.99335 4.9957
+ 4.99741 4.99864 4.99946 4.99994 5.00047 5.00073 5.00086
+ 5.00092 5.00094 5.00091 5.00087 5.00081 5.00074 5.00067
+ 5.00059 5.00052 5.00046 5.0004 5.00034 5.0003 5.00026 5.00022
+ 5.00019 5.00016 5.00014 5.00012 5.0001 5.00009 5.00007 5.00006
+ 5.00006 5.00005 5.00004 5.00004 5.00004 5.00003 5.00003
+ 5.00003 5.00002 5.00002 5.00002 5.00002 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5 5 5 5 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 5 5 5 5 5 5 5 5 5 5.00001 5.00001
+ 5.00001 5.00001 5.00002 5.00002
+ EOD
+
+ @v[23].set(<<-'EOD')
+ 5 5.00284 5.01266 5.01895 4.98936 4.99575 4.99217 4.99545
+ 4.99775 4.99894 4.99946 4.99968 4.99975 4.99977 4.99986
+ 4.9999 4.99528 4.99808 5.00039 5.00392 5.00512 4.99985 4.99863
+ 4.99942 4.99992 5.00017 4.99897 4.99803 4.99784 4.99739
+ 4.99883 5.00365 5.00298 5.00133 5.00048 5.00019 5.00008
+ 5.00005 5.00004 5.00003 5.00002 5.00002 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5 5 4.99999 4.99997 4.99995 4.99996
+ 4.99998 5 5.00001 5.00001 5.00002 5.00002 5.00003 5.00003
+ 5.00002 5.00002 5.00001 5.00001 5 5 5 5 5 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99998 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 5 5 5 5 5 5 5 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00002
+ 5.00002 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5 5 5 5 5 5 5 5.00217 5.00108 4.99547 4.99658 5.00667
+ 4.99641 4.99532 4.99938 5.00328 5.00222 5.00114 5.00052
+ 5.00024 5.00011 5.00009 4.99285 4.99591 4.99897 5.00403
+ 5.00786 5.00318 4.99942 4.9992 4.99949 5.001 5.00408 5.00319
+ 5.00063 4.99995 5.00014 4.99982 4.99832 4.99838 4.99865
+ 4.99912 4.99836 4.99735 4.99606 4.99814 5.00958 5.02973
+ 5.05293 5.06103 4.99342 4.80726 4.50744 4.07509 3.41358
+ 2.37924 1.03194 0.261552 0.142392 0.0904482 0.0555071 0.0322869
+ 0.018289 0.0113802 0.00875182 0.00757055 0.00629906 0.00523
+ 0.00403349 0.0031953 0.00280864 0.00286119 0.00250389 0.00202815
+ 0.001723 0.00147312 0.0012411 0.00104401 0.000886204 0.000758277
+ 0.000651915 0.00056348 0.000487966 0.000424048 0.000365613
+ 0.000308178 0.000258725 0.000228061 0.000207976 0.000198491
+ 0.00018518 0.000172716 0.000163197 0.000155007 0.000141734
+ 0.000128461 0.000115188 0.000101915 8.86417e-05 7.53686e-05
+ 6.20956e-05 5.69164e-05 5.23275e-05 4.77385e-05 4.31495e-05
+ 3.85605e-05 3.39716e-05 2.93826e-05 2.69449e-05 2.56224e-05
+ 2.42999e-05 2.29774e-05 2.16549e-05 2.03324e-05 1.90099e-05
+ 1.76873e-05 1.63648e-05 1.50423e-05 1.37198e-05 1.23973e-05
+ 1.10748e-05 9.75232e-06 8.48447e-06 7.65129e-06 6.81811e-06
+ 5.98494e-06 5.15176e-06 0.00056893 -0.00787906 -0.0217381
+ -0.0370066 -0.00770505 0.00659312 0.00975477 0.00949456
+ 0.00777552 0.00655645 0.00568776 0.00508782 0.00458121 0.00410187
+ 0.00365665 0.0015121 0.00160863 0.00263181 0.00638941 0.00772607
+ 0.00225583 0.0010843 0.000882939 0.000801563 0.00075632
+ 0.000554992 0.000435131 0.0003474 0.000217667 0.000491602
+ 0.0012267 0.00250446 0.000212058 -0.0174972 -0.0527527 -0.0479071
+ 0.194908 1.45838 3.40677 4.49242 4.86894 4.97215 5.01218
+ 5.04342 5.06228 5.03069 4.87169 4.57056 4.11523 3.38264
+ 2.19691 0.715839 0.172818 0.102162 0.0627162 0.0363388 0.020289
+ 0.0119414 0.00826608 0.0066417 0.00549092 0.00492505 0.00439443
+ 0.0037156 0.00306471 0.00247451 0.00195965 0.0014822 0.0010815
+ 0.000904464 0.0010514 0.00152308 0.00120752 0.000228447
+ -0.00102833 -0.00116644 -0.00042067 4.78758e-05 5.09599e-05
+ -4.45756e-05 -3.22966e-06 3.81163e-05 7.94622e-05 0.000120808
+ 0.000162154 0.000161895 0.000148481 0.000135068 0.000121654
+ 0.000108241 9.81453e-05 9.2164e-05 8.61827e-05 8.02014e-05
+ 7.42201e-05 6.82388e-05 6.22576e-05 5.62763e-05 5.0295e-05
+ 4.43137e-05 3.83324e-05 3.54323e-05 3.321e-05 3.09877e-05
+ 2.87654e-05 2.65431e-05 2.43209e-05 2.20986e-05 1.98763e-05
+ 1.7654e-05 1.54317e-05 1.34612e-05 1.25441e-05 1.1627e-05
+ 1.07099e-05 9.79276e-06 8.87564e-06 7.95851e-06 7.04139e-06
+ 6.12427e-06
+ EOD
+
+ @v[24].set(<<-'EOD')
+ 5 5.01099 5.00866 4.97845 4.92369 4.9273 4.97413 4.9929
+ 4.99826 4.99958 4.99978 5.00005 4.99968 4.99959 5.00014
+ 4.99979 4.99914 4.99982 5.00023 5.00295 5.00664 4.99854
+ 4.99647 5.00438 5.01722 5.03681 5.04766 5.04799 5.04867
+ 5.04873 5.04685 5.04413 5.0367 5.02505 5.01726 5.01183 5.00806
+ 5.00549 5.00371 5.00246 5.00162 5.00105 5.00069 5.00045
+ 5.00031 5.00024 5.00019 5.00012 5.00007 5.00004 5.00001
+ 4.99998 4.99999 4.99999 5 5.00001 5.00001 5.00002 5.00002
+ 5.00003 5.00003 5.00003 5.00002 5.00002 5.00001 5.00001
+ 5.00001 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 5 5 5 5 5 5 5 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00002 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5 5 5 5 5 5 5 5.00418 4.99953 4.99152
+ 4.99807 5.00497 5.00112 5.00055 5.00038 5.00018 5.00006
+ 5.00006 5.00007 5.00006 5.00004 5.00004 4.99853 4.99945
+ 4.99998 5.00304 5.00935 5.00742 4.99181 4.97421 4.93603
+ 4.8853 4.8927 4.93984 4.97458 4.99039 4.99614 4.99801 4.99851
+ 4.99869 4.99924 5.00108 5.00181 5.00119 5.00059 5.00031
+ 5.00022 5.00018 5.00011 5.00001 5.00006 4.99981 4.99977
+ 4.99982 5.00012 4.99993 5.00008 5.00043 5.00048 5.00024
+ 5.00008 4.99984 4.99993 5.00011 4.99996 4.9998 4.99977 4.9998
+ 4.99993 5.00008 5.00011 5.00002 4.99995 4.99989 4.99993
+ 5 5.00007 5.00009 4.99994 4.99977 4.9997 4.99975 4.99996
+ 4.99996 4.99988 4.9997 4.99952 4.9995 4.99956 4.99973 4.99988
+ 5.00005 5.00025 5.00042 5.00036 5.00031 5.00025 5.0002 5.00014
+ 5.00009 5.00003 5.00002 5.00001 5.00001 5 4.99999 4.99998
+ 4.99998 4.99997 4.99998 4.99998 4.99998 4.99998 4.99998
+ 4.99998 4.99998 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 5.00284
+ 5.00442 5.00381 4.98997 4.99092 5.00733 5.07791 4.98237
+ 4.86434 4.76835 4.74067 4.79278 4.85094 4.90068 4.93603
+ 4.95698 4.96984 4.97856 4.98869 4.99904 5.0005 4.99524 5.00181
+ 5.01878 5.05177 5.07986 4.98917 4.56217 3.68 2.3539 1.18541
+ 0.505772 0.221044 0.115287 0.0760938 0.0589194 0.0476784
+ 0.0457213 0.0412911 0.033889 0.0259741 0.0191452 0.0139018
+ 0.0100235 0.00711788 0.00497657 0.00349368 0.00250021 0.00176179
+ 0.00121843 0.000838368 0.000582711 0.000423458 0.000294608
+ 0.000201251 0.000133748 8.6227e-05 5.44252e-05 3.30514e-05
+ 1.93926e-05 1.09814e-05 5.29857e-06 1.92247e-06 3.08708e-07
+ -3.74311e-07 -6.11121e-07 -7.27807e-07 -4.87604e-07 -4.80493e-07
+ -9.15925e-07 -2.03774e-06 -4.01128e-06 -2.46644e-06 2.10626e-06
+ 8.22422e-06 1.04922e-05 9.83047e-06 7.27106e-06 3.29654e-06
+ -2.06736e-06 -2.18019e-06 -2.29303e-06 -2.40586e-06 -2.51869e-06
+ -2.63153e-06 -2.24615e-06 -1.70325e-06 -1.16036e-06 -6.17468e-07
+ -7.45754e-08 2.45198e-07 2.88285e-07 3.31373e-07 3.7446e-07
+ 4.17548e-07 4.60635e-07 5.03723e-07 5.4681e-07 5.89898e-07
+ 6.32985e-07 6.76073e-07 6.19054e-07 5.4001e-07 4.60967e-07
+ 3.81923e-07 3.02879e-07 2.23836e-07 1.44792e-07 6.57488e-08
+ -1.32948e-08 -9.23383e-08 -1.6698e-07 -2.23206e-07 -2.79432e-07
+ -3.35658e-07 -3.91884e-07 -4.48109e-07 -5.04335e-07 -5.60561e-07
+ -6.16787e-07
+ EOD
+
+ @v[25].set(<<-'EOD')
+ 1.34824 1.35838 1.36465 1.34675 1.29167 1.23161 1.2201 1.2185
+ 1.2181 1.21798 1.21793 1.21788 1.21785 1.21782 1.21779 1.21776
+ 1.21655 1.21656 1.21669 1.21871 1.22421 1.22247 1.21858
+ 1.2228 1.23803 1.27737 1.10647 0.395248 0.0600669 0.027687
+ 0.0192374 0.015425 0.0130881 0.00977445 0.00696598 0.00491122
+ 0.00341952 0.00237078 0.00162339 0.00109178 0.000726647
+ 0.000478886 0.00031568 0.000207902 0.000143494 0.000109768
+ 8.62987e-05 5.69775e-05 3.36547e-05 2.30356e-05 1.86108e-05
+ 1.41861e-05 1.08293e-05 7.68835e-06 4.79593e-06 4.51019e-06
+ 4.22444e-06 3.9387e-06 3.65295e-06 3.36721e-06 3.04559e-06
+ 2.69981e-06 2.35403e-06 2.00825e-06 1.66247e-06 1.34508e-06
+ 1.26225e-06 1.17941e-06 1.09657e-06 1.01373e-06 9.30893e-07
+ 8.48054e-07 7.65216e-07 6.82378e-07 5.9954e-07 5.16702e-07
+ 4.37489e-07 3.82774e-07 3.2806e-07 2.73346e-07 2.18632e-07
+ 1.63917e-07 1.09203e-07 5.4489e-08 -2.2523e-10 -5.49395e-08
+ -1.09654e-07 -1.52862e-07 -1.3079e-07 -1.08718e-07 -8.6646e-08
+ -6.45739e-08 -4.25019e-08 -2.04298e-08 1.64229e-09 2.37144e-08
+ 4.57864e-08 6.78585e-08 8.71693e-08 9.30725e-08 9.89758e-08
+ 1.04879e-07 1.10782e-07 1.16685e-07 1.22589e-07 1.28492e-07
+ 1.34395e-07 1.40298e-07 1.46201e-07 1.52105e-07 1.58008e-07
+ 1.63911e-07 1.69814e-07 1.75718e-07 1.81621e-07 1.87524e-07
+ 1.93427e-07 1.9933e-07 2.05234e-07 2.11137e-07 2.19788e-07
+ 0.000393944 -0.000218983 -0.00105784 0.00172403 -0.00027134
+ -0.000204147 8.79968e-06 5.93762e-05 5.83554e-05 4.13815e-05
+ 3.71369e-05 3.03372e-05 2.25336e-05 1.5986e-05 1.07284e-05
+ -7.5239e-05 5.60593e-05 6.97571e-05 0.000667617 0.000960856
+ 0.00131749 -0.00759564 -0.0217897 -0.0450321 -0.076646 -0.128569
+ -0.186391 -0.202175 -0.206953 -0.2082 -0.208416 -0.208669
+ -0.208934 -0.209111 -0.209234 -0.209329 -0.209389 -0.209416
+ -0.2094 -0.209329 -0.20926 -0.209204 -0.209208 -0.209285
+ -0.209454 -0.209641 -0.20977 -0.209811 -0.209833 -0.209887
+ -0.209653 -0.209127 -0.208893 -0.208811 -0.208777 -0.208758
+ -0.208747 -0.20874 -0.208726 -0.208697 -0.208657 -0.208611
+ -0.208565 -0.208524 -0.208488 -0.208451 -0.208412 -0.208373
+ -0.208333 -0.208294 -0.208256 -0.208219 -0.208183 -0.208145
+ -0.208107 -0.208066 -0.208029 -0.207993 -0.207959 -0.207923
+ -0.207883 -0.207838 -0.207789 -0.207747 -0.20771 -0.207675
+ -0.207642 -0.207605 -0.207568 -0.207531 -0.207494 -0.207457
+ -0.20742 -0.207383 -0.207346 -0.207308 -0.207271 -0.207233
+ -0.207196 -0.207158 -0.207121 -0.207084 -0.207046 -0.207009
+ -0.206972 -0.206935 -0.206898 -0.206861 -0.206823 -0.206786
+ -0.206749 -0.206712 -0.206675 -0.206638 -0.2066 -0.206563
+ -0.206526 -0.206489 -0.206452 -0.206415 -0.203384 -0.20015
+ -0.196872 -0.205024 -0.210727 -0.206779 -0.0685263 0.586138
+ 1.4665 2.22945 2.77554 3.076 3.24926 3.34515 3.40164 3.43006
+ 3.43713 3.43075 3.42886 3.4384 3.46567 3.49025 3.51287 3.53821
+ 3.57841 3.39846 2.80753 2.22947 1.7549 1.30429 0.707786
+ 0.303206 0.131352 0.0671706 0.0429955 0.032461 0.0257161
+ 0.0239521 0.0217397 0.0179705 0.0138745 0.0102813 0.00749643
+ 0.0054328 0.00386817 0.0027004 0.00189442 0.00135552 0.000954715
+ 0.000659981 0.000453435 0.000313993 0.000231347 0.000159665
+ 0.000108122 7.10528e-05 4.50233e-05 2.77892e-05 1.62765e-05
+ 8.9893e-06 4.5471e-06 1.54614e-06 -1.6542e-07 -8.68508e-07
+ -1.04369e-06 -9.63086e-07 -8.44294e-07 -6.57339e-07 -7.35885e-07
+ -9.80056e-07 -1.39772e-06 -2.10199e-06 -1.37474e-06 6.13269e-07
+ 3.3028e-06 4.60941e-06 4.91053e-06 4.14186e-06 2.45258e-06
+ -8.7388e-09 -3.59647e-07 -7.10554e-07 -1.06146e-06 -1.41237e-06
+ -1.76328e-06 -1.63073e-06 -1.34534e-06 -1.05995e-06 -7.74561e-07
+ -4.8917e-07 -2.95733e-07 -2.16326e-07 -1.3692e-07 -5.75135e-08
+ 2.18929e-08 1.01299e-07 1.80706e-07 2.60112e-07 3.39519e-07
+ 4.18925e-07 4.98332e-07 4.83984e-07 4.4901e-07 4.14035e-07
+ 3.79061e-07 3.44087e-07 3.09112e-07 2.74138e-07 2.39163e-07
+ 2.04189e-07 1.69215e-07 1.26002e-07 4.83213e-08 -2.9359e-08
+ -1.07039e-07 -1.8472e-07 -2.624e-07 -3.4008e-07 -4.1776e-07
+ -4.95441e-07
+ EOD
+
+ @v[26].set(<<-'EOD')
+ 7.10441e-10 0.000309731 -0.000308186 -0.001694 -0.00360784
+ 8.40909e-05 0.00203175 0.0012896 0.000596548 0.000277191
+ 0.000161134 0.000120439 8.4915e-05 9.49929e-05 6.18812e-05
+ 1.65433e-05 1.89682e-05 3.97578e-05 4.95446e-05 0.000225325
+ 0.000214579 -0.00230134 -0.000451102 0.00997237 0.0341443
+ 0.0449314 0.0424411 0.0341996 0.0315315 0.0308892 0.0291614
+ 0.024365 0.0190282 0.0188976 0.017238 0.0138526 0.0105645
+ 0.00778548 0.00561753 0.0039871 0.00279554 0.00194075 0.0013468
+ 0.000934775 0.000664723 0.000498911 0.000377384 0.000254183
+ 0.000163421 0.000120773 9.65058e-05 7.22384e-05 5.60316e-05
+ 4.14549e-05 2.79516e-05 2.57096e-05 2.34677e-05 2.12257e-05
+ 1.89837e-05 1.67417e-05 1.46737e-05 1.27228e-05 1.07719e-05
+ 8.82099e-06 6.87009e-06 5.0896e-06 4.71705e-06 4.34451e-06
+ 3.97196e-06 3.59941e-06 3.22686e-06 2.85431e-06 2.48176e-06
+ 2.10921e-06 1.73666e-06 1.36411e-06 1.02855e-06 9.42931e-07
+ 8.57316e-07 7.71701e-07 6.86086e-07 6.00471e-07 5.14856e-07
+ 4.29241e-07 3.43626e-07 2.58011e-07 1.72396e-07 9.85409e-08
+ 9.14091e-08 8.42773e-08 7.71456e-08 7.00138e-08 6.2882e-08
+ 5.57503e-08 4.86185e-08 4.14867e-08 3.4355e-08 2.72232e-08
+ 2.05821e-08 1.63235e-08 1.2065e-08 7.80643e-09 3.54786e-09
+ -7.10696e-10 -4.96926e-09 -9.22782e-09 -1.34864e-08 -1.77449e-08
+ -2.20035e-08 -2.62621e-08 -3.05206e-08 -3.47792e-08 -3.90378e-08
+ -4.32963e-08 -4.75549e-08 -5.18134e-08 -5.6072e-08 -6.03306e-08
+ -6.45891e-08 -6.88477e-08 -8.76373e-06 0.000131607 -0.00021685
+ -0.000433027 0.00047234 0.000211593 -0.000189601 3.2492e-05
+ 0.000575955 7.72235e-05 -0.000285172 -0.000242061 -0.000135112
+ -3.50117e-05 -2.75868e-05 5.48974e-05 1.80604e-07 5.48911e-05
+ 3.97478e-05 0.000192909 0.000297932 0.00402253 -0.0122366
+ -0.047853 -0.0963082 -0.108071 -0.0567275 -0.0239271 -0.0178628
+ -0.0233027 -0.031853 -0.0400843 -0.0482725 -0.0576154 -0.0627218
+ -0.0511236 -0.0279524 -0.0150986 -0.00931091 -0.00652876
+ -0.00479286 -0.00344346 -0.00249578 -0.0019532 -0.00157977
+ -0.00131848 -0.00111251 -0.000939229 -0.000797445 -0.000708384
+ -0.000630452 -0.000539722 -0.000508862 -0.000480596 -0.000439484
+ -0.000407217 -0.000363866 -0.000329506 -0.000318642 -0.000307362
+ -0.000286511 -0.000266253 -0.000242943 -0.000218107 -0.000204661
+ -0.00020241 -0.000194435 -0.000185062 -0.000173042 -0.000160549
+ -0.000151407 -0.000145626 -0.000145976 -0.000147342 -0.000145288
+ -0.000137979 -0.000124481 -0.000123218 -0.000127453 -0.000139006
+ -0.000145486 -0.000129764 -9.82749e-05 -4.72596e-05 -3.08671e-05
+ -3.28834e-05 -4.52254e-05 -6.25389e-05 -6.32516e-05 -6.39643e-05
+ -6.4677e-05 -6.53897e-05 -6.61023e-05 -6.6815e-05 -6.75277e-05
+ -6.61005e-05 -6.45173e-05 -6.29341e-05 -6.13509e-05 -5.97676e-05
+ -5.81844e-05 -5.66012e-05 -5.54231e-05 -5.4455e-05 -5.3487e-05
+ -5.25189e-05 -5.15508e-05 -5.05828e-05 -4.96147e-05 -4.86466e-05
+ -4.76785e-05 -4.67105e-05 -4.57424e-05 -4.47743e-05 -4.38063e-05
+ -4.28382e-05 -4.18821e-05 -4.10211e-05 -4.016e-05 -3.9299e-05
+ -3.8438e-05 4.29885e-05 5.14113e-05 -0.000127986 -0.000611463
+ -0.000149428 0.000882394 0.00297059 -0.00405825 -0.00591067
+ -0.00546997 -0.00158744 0.00190677 0.00298403 0.00268595
+ 0.00196161 0.00130289 0.000783347 0.000520683 0.000565306
+ 0.00053419 -0.00224696 -0.000920818 0.0132755 0.0322504
+ 0.0442808 0.0638615 0.0701007 0.0539356 0.0247771 0.056244
+ 0.294266 0.831368 1.45424 2.02898 2.54559 2.9937 3.35333
+ 3.72609 4.06363 4.32789 4.52413 4.66504 4.7652 4.83637 4.88631
+ 4.92109 4.94464 4.96046 4.97218 4.98079 4.98679 4.99076
+ 4.99361 4.99555 4.99686 4.99783 4.99853 4.99902 4.99936
+ 4.99959 4.99973 4.99983 4.9999 4.99993 4.99996 4.99998 5
+ 5.00001 5 4.99999 4.99997 4.99994 4.99993 4.99994 4.99996
+ 4.99999 5.00004 5.00006 5.00005 5.00003 5.00002 5.00001
+ 5 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 5 5 5 5 5 5 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999 4.99999 4.99998
+ EOD
+
+ @v[27].set(<<-'EOD')
+ 5 4.99984 4.99796 4.99478 4.9889 4.98738 4.98896 4.99087
+ 4.99262 4.99419 4.99552 4.99659 4.99743 4.99807 4.99855
+ 4.9989 4.99894 4.99908 4.99935 5.00001 5.0007 5.00132 5.00032
+ 4.99976 5.00134 5.00339 5.00315 5.00157 5.00091 5.00058
+ 5.00012 4.99944 4.99886 4.9994 4.99934 4.99899 4.99876 4.99868
+ 4.99872 4.99883 4.99898 4.99914 4.9993 4.99944 4.99956 4.99967
+ 4.99976 4.99982 4.99986 4.9999 4.99993 4.99997 4.99997 4.99998
+ 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998
+ 4.99999 4.99999 4.99999 4.99999 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5.00009 5.00028 5.00015 4.99983
+ 5.00036 4.99996 4.99834 4.99783 5.00383 5.00734 5.00387
+ 5.00058 4.99893 4.99836 4.99832 4.99854 4.99873 4.99905
+ 4.99927 4.99952 4.99969 4.99834 4.99536 4.99163 4.99073
+ 5.0053 5.03631 5.03103 4.9008 4.62503 4.21887 3.70902 3.09967
+ 2.35791 1.41912 0.519675 0.210458 0.131362 0.0980819 0.0708209
+ 0.0471701 0.0323272 0.0253535 0.0199144 0.0152615 0.0117228
+ 0.00917696 0.00738117 0.00609292 0.00512664 0.00436184 0.0037961
+ 0.00331639 0.00289006 0.0025477 0.00226529 0.00202925 0.00182793
+ 0.00165474 0.00150531 0.00137529 0.00125983 0.00115603 0.00106455
+ 0.000982977 0.000911255 0.000846819 0.000790092 0.000738698
+ 0.000692816 0.00065107 0.000613595 0.000579642 0.000548935
+ 0.00052106 0.000495598 0.000472174 0.000450849 0.000431118
+ 0.000412667 0.000395868 0.000381319 0.000368487 0.000357327
+ 0.000344212 0.000330334 0.00031622 0.000303298 0.000295809
+ 0.00028832 0.000280831 0.000273342 0.000265853 0.000258364
+ 0.000250875 0.000245118 0.000239488 0.000233857 0.000228227
+ 0.000222596 0.000216966 0.000211336 0.000207047 0.000203455
+ 0.000199863 0.00019627 0.000192678 0.000189085 0.000185493
+ 0.0001819 0.000178308 0.000174716 0.000171123 0.000167531
+ 0.000163938 0.000160346 0.000156835 0.000153973 0.00015111
+ 0.000148248 0.000145385 0.000296579 -3.96718e-05 -0.000449085
+ 0.000323433 0.000750086 0.000268264 0.000149028 -0.000100249
+ 7.00956e-05 0.00012605 0.00022592 0.000193036 0.000120453
+ 8.07865e-05 7.65771e-05 -3.27828e-05 0.000116759 0.000169498
+ 0.000409804 0.000414965 0.00092323 -0.00590633 -0.0175477
+ -0.032433 -0.0559842 -0.0820373 0.0688484 0.626629 1.32929
+ 2.01657 2.60925 3.12329 3.38952 3.14128 2.38463 1.23802
+ 0.316019 0.107832 0.0694707 0.051837 0.035247 0.0209999
+ 0.0116618 0.00967674 0.00789182 0.00574566 0.00386872 0.00258612
+ 0.00167126 0.00104169 0.000641093 0.000401246 0.000277928
+ 0.000171775 0.000102266 5.89376e-05 3.29258e-05 1.80463e-05
+ 1.0057e-05 6.4571e-06 5.10093e-06 4.06791e-06 3.62716e-06
+ 3.63321e-06 3.99625e-06 4.64368e-06 5.20886e-06 4.77728e-06
+ 3.23919e-06 1.14113e-06 -1.29416e-06 -4.15607e-06 -1.88532e-06
+ 5.24411e-06 1.38678e-05 1.28823e-05 3.6758e-06 -2.52285e-06
+ -3.97133e-06 -4.03071e-06 -3.37154e-06 -2.71238e-06 -2.05321e-06
+ -1.39404e-06 -7.34872e-07 -3.73325e-07 -1.05873e-07 1.61578e-07
+ 4.2903e-07 6.96482e-07 8.18468e-07 7.60065e-07 7.01662e-07
+ 6.43258e-07 5.84855e-07 5.26452e-07 4.68049e-07 4.09646e-07
+ 3.51243e-07 2.9284e-07 2.34437e-07 1.71213e-07 1.06928e-07
+ 4.2644e-08 -2.16403e-08 -8.59247e-08 -1.50209e-07 -2.14493e-07
+ -2.78778e-07 -3.43062e-07 -4.07346e-07 -4.55065e-07 -4.3348e-07
+ -4.11896e-07 -3.90311e-07 -3.68726e-07 -3.47141e-07 -3.25556e-07
+ -3.03971e-07 -2.82386e-07
+ EOD
+
+ @v[28].set(<<-'EOD')
+ 0.368163 0.361756 0.327463 0.269513 0.149476 0.0805716 0.0501146
+ 0.03403 0.0230886 0.0160474 0.0116071 0.00870013 0.00679614
+ 0.00542384 0.00432512 0.00340653 -0.00129719 -0.00399429
+ -0.00318719 0.00443085 0.0150156 0.0334147 0.0132288 -0.0189751
+ -0.0508377 -0.0252174 -0.0142489 -0.00675908 -0.0038653
+ -0.00243423 -0.00168891 -0.00120901 -0.000900426 -0.000685575
+ -0.000557595 -0.000457268 -0.000377427 -0.000315269 -0.000266613
+ -0.000228397 -0.000198283 -0.000174248 -0.000154886 -0.00013892
+ -0.000125864 -0.000115189 -0.000105841 -9.66611e-05 -8.84262e-05
+ -8.23872e-05 -7.74668e-05 -7.25463e-05 -6.79992e-05 -6.35276e-05
+ -5.92413e-05 -5.68994e-05 -5.45574e-05 -5.22154e-05 -4.98735e-05
+ -4.75315e-05 -4.54981e-05 -4.36726e-05 -4.18471e-05 -4.00216e-05
+ -3.81961e-05 -3.64559e-05 -3.54209e-05 -3.43858e-05 -3.33508e-05
+ -3.23157e-05 -3.12807e-05 -3.02456e-05 -2.92105e-05 -2.81755e-05
+ -2.71404e-05 -2.61054e-05 -2.51232e-05 -2.44984e-05 -2.38736e-05
+ -2.32487e-05 -2.26239e-05 -2.19991e-05 -2.13742e-05 -2.07494e-05
+ -2.01246e-05 -1.94998e-05 -1.88749e-05 -1.82865e-05 -1.79044e-05
+ -1.75224e-05 -1.71403e-05 -1.67582e-05 -1.63762e-05 -1.59941e-05
+ -1.56121e-05 -1.523e-05 -1.4848e-05 -1.44659e-05 -1.41138e-05
+ -1.39075e-05 -1.37011e-05 -1.34947e-05 -1.32883e-05 -1.30819e-05
+ -1.28755e-05 -1.26691e-05 -1.24627e-05 -1.22563e-05 -1.205e-05
+ -1.18436e-05 -1.16372e-05 -1.14308e-05 -1.12244e-05 -1.1018e-05
+ -1.08116e-05 -1.06052e-05 -1.03988e-05 -1.01924e-05 -9.98605e-06
+ -9.77966e-06 -2.85319e-05 0.00281092 0.00180106 -0.000981083
+ 0.00551926 -0.00119763 -0.0295069 -0.0367677 0.064749 0.119022
+ 0.0882007 0.0552062 0.03418 0.0223243 0.015545 0.011949
+ 0.00757134 0.00667655 0.00583243 0.00644443 0.00650959 -0.0302575
+ -0.0437806 -0.0355466 0.0381776 0.282109 0.674178 1.07582
+ 1.45189 1.789 2.08649 2.34663 2.57245 2.81211 3.04778 3.2523
+ 3.45877 3.65593 3.83396 3.9923 4.13368 4.25864 4.36719 4.46064
+ 4.54086 4.60962 4.66835 4.71838 4.76094 4.79716 4.82796
+ 4.85413 4.87634 4.89518 4.91116 4.92476 4.93631 4.94608
+ 4.95434 4.9613 4.96715 4.97211 4.97638 4.98001 4.98312 4.98571
+ 4.98795 4.98979 4.99138 4.99269 4.99381 4.99474 4.99551
+ 4.99615 4.99668 4.99713 4.99752 4.99783 4.99811 4.99836
+ 4.99858 4.99873 4.99884 4.99892 4.999 4.99907 4.99912 4.99916
+ 4.99921 4.99926 4.99932 4.99937 4.99942 4.99948 4.99953
+ 4.99956 4.99958 4.99961 4.99963 4.99966 4.99968 4.99971
+ 4.99972 4.99973 4.99974 4.99975 4.99976 4.99977 4.99978
+ 4.99979 4.9998 4.9998 4.99981 4.99982 4.99983 4.99984 4.99985
+ 4.99986 4.99986 4.99987 4.99987 5.00498 5.00354 4.99359
+ 4.98981 5.00498 5.00099 5.00041 5.00022 5.00015 5.00012
+ 5.0001 5.00008 5.00005 5.00003 5 4.99431 4.99459 4.99591
+ 5.00087 5.01029 5.03935 4.92784 4.51643 3.78356 2.68745
+ 1.43417 0.583128 0.205094 0.0777337 0.0391566 0.02723 0.023883
+ 0.018808 0.010165 0.00254623 -0.00377463 -0.0038097 0.00144145
+ 0.00267231 0.00193045 0.00144538 0.00121758 0.00112893 0.00109424
+ 0.0010226 0.000948072 0.000882573 0.000826996 0.000776391
+ 0.000729719 0.000686499 0.000647333 0.000610108 0.000575631
+ 0.000545069 0.000515485 0.000488514 0.000465316 0.000443215
+ 0.000422454 0.00040292 0.00038488 0.000368472 0.000353628
+ 0.000339643 0.000326197 0.000313483 0.000302884 0.000294038
+ 0.000284003 0.000270941 0.000254925 0.000246511 0.000244089
+ 0.000245538 0.000242099 0.000235728 0.000227482 0.000218001
+ 0.000207257 0.000202127 0.000196997 0.000191868 0.000186738
+ 0.000181608 0.00017758 0.000173899 0.000170219 0.000166538
+ 0.000162857 0.000159576 0.00015679 0.000154005 0.000151219
+ 0.000148433 0.000145647 0.000142861 0.000140076 0.00013729
+ 0.000134504 0.000131718 0.000129603 0.000127635 0.000125668
+ 0.0001237 0.000121732 0.000119765 0.000117797 0.000115829
+ 0.000113862 0.000111894 0.000109993 0.000108372 0.000106751
+ 0.00010513 0.000103509 0.000101887 0.000100266 9.86449e-05
+ 9.70237e-05
+ EOD
+
+ @v[29].set(<<-'EOD')
+ 5 4.99899 4.99654 4.99327 4.9863 4.98954 4.99212 4.99378
+ 4.9951 4.99624 4.99715 4.99786 4.99839 4.99879 4.99909 4.99931
+ 4.99922 4.99933 4.99971 5.00064 5.00084 5.00123 4.99865
+ 4.99853 4.99983 5.00457 5.00242 5.00105 5.00062 5.00042
+ 4.99971 4.9994 4.9992 4.9996 4.99955 4.99932 4.99918 4.99915
+ 4.99919 4.99927 4.99937 4.99948 4.99957 4.99966 4.99974
+ 4.9998 4.99985 4.99989 4.99992 4.99993 4.99994 4.99994 4.99996
+ 4.99998 5 5 5.00001 5.00001 5.00001 5.00002 5.00002 5.00001
+ 5.00001 5.00001 5 5 5 5 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99998 4.99998 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 5 5 5 5
+ 5 5 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00002 5.00002 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5 5 5 5 5 5 4.9997 4.99998 4.99954 4.99963
+ 5.00059 4.99945 4.99732 4.99957 5.00919 5.00558 5.00033
+ 4.99851 4.9983 4.99854 4.99871 4.99928 4.99914 4.99939 4.99952
+ 4.9998 4.99976 4.99744 4.99598 4.99478 4.99806 5.01911 5.04602
+ 5.05469 5.01317 4.89484 4.69655 4.42036 4.06069 3.60793
+ 3.12531 2.72975 2.45187 2.25081 2.09841 1.98509 1.90211
+ 1.84084 1.79411 1.7574 1.72763 1.70283 1.68188 1.66389 1.64823
+ 1.63438 1.62201 1.61088 1.60081 1.59163 1.58323 1.57549
+ 1.56835 1.56173 1.55558 1.54985 1.54451 1.53951 1.53479
+ 1.53035 1.52615 1.5222 1.51845 1.5149 1.51153 1.50834 1.50529
+ 1.5024 1.49964 1.497 1.49449 1.49208 1.48977 1.48755 1.48542
+ 1.48336 1.48138 1.47948 1.47765 1.4759 1.47419 1.47255 1.47096
+ 1.46949 1.46823 1.46696 1.4657 1.46444 1.46317 1.46191 1.46065
+ 1.45956 1.4585 1.45743 1.45636 1.45529 1.45422 1.45315 1.45226
+ 1.45145 1.45064 1.44983 1.44902 1.44821 1.4474 1.44659 1.44579
+ 1.44498 1.44417 1.44336 1.44255 1.44174 1.44094 1.44019
+ 1.43944 1.43868 1.43793 1.43765 1.43679 1.43515 1.43405
+ 1.43478 1.43387 1.43345 1.43184 1.43086 1.43021 1.43003
+ 1.42988 1.42944 1.42883 1.42818 1.42702 1.42642 1.42595
+ 1.42586 1.42616 1.42783 1.41733 1.38106 1.30738 1.3877 2.09819
+ 3.05285 3.58059 3.77601 3.87609 4.02557 4.24887 4.4608 4.60411
+ 4.72109 4.8255 4.90465 4.97379 5.01253 5.01532 5.01239 5.0092
+ 5.00665 5.00474 5.00333 5.00232 5.00163 5.00117 5.00082
+ 5.00057 5.00039 5.00027 5.00019 5.00013 5.00009 5.00006
+ 5.00004 5.00003 5.00002 5.00001 5.00001 5 5 5 4.99998 4.99995
+ 4.99992 4.99996 5.00005 5.00012 5.00008 4.99996 4.9999 4.99985
+ 4.99986 4.99997 5.00021 5.0003 5.00024 5.00009 5.00007 5.00005
+ 5.00003 5.00001 4.99998 4.99998 4.99998 4.99999 4.99999
+ 5 5 5 5 5 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00002 5.00002 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999 4.99998
+ 4.99998 4.99998
+ EOD
+
+ @v[30].set(<<-'EOD')
+ 7.10441e-10 5.70385e-05 0.000226143 0.000131916 -0.000887764
+ -8.01837e-05 -3.49653e-05 9.40039e-05 0.000118663 0.000108025
+ 8.6059e-05 6.33268e-05 4.99295e-05 3.16843e-05 3.60692e-05
+ 2.07572e-05 -8.6375e-05 3.44583e-05 8.07397e-05 0.000196296
+ 0.000115615 -7.12768e-05 -0.000129812 -4.18679e-05 7.94364e-05
+ 0.000182034 -5.41226e-05 -0.000451819 -0.000713937 -0.00129863
+ -0.00262186 -0.00213417 -0.00133767 0.000775698 0.000969902
+ 0.000549281 0.000280946 0.000140321 8.6919e-05 7.22446e-05
+ 6.5631e-05 6.45263e-05 6.63087e-05 7.17391e-05 7.59042e-05
+ 7.59172e-05 7.03353e-05 6.33558e-05 5.31136e-05 4.64278e-05
+ 4.40594e-05 4.16909e-05 4.05674e-05 3.96957e-05 3.87875e-05
+ 3.74977e-05 3.62079e-05 3.49181e-05 3.36283e-05 3.23385e-05
+ 3.12427e-05 3.02775e-05 2.93124e-05 2.83472e-05 2.7382e-05
+ 2.64613e-05 2.59077e-05 2.5354e-05 2.48004e-05 2.42468e-05
+ 2.36931e-05 2.31395e-05 2.25859e-05 2.20322e-05 2.14786e-05
+ 2.0925e-05 2.03916e-05 1.9995e-05 1.95984e-05 1.92019e-05
+ 1.88053e-05 1.84087e-05 1.80122e-05 1.76156e-05 1.7219e-05
+ 1.68225e-05 1.64259e-05 1.6051e-05 1.57991e-05 1.55471e-05
+ 1.52952e-05 1.50433e-05 1.47913e-05 1.45394e-05 1.42875e-05
+ 1.40356e-05 1.37836e-05 1.35317e-05 1.32978e-05 1.31513e-05
+ 1.30048e-05 1.28583e-05 1.27118e-05 1.25653e-05 1.24188e-05
+ 1.22724e-05 1.21259e-05 1.19794e-05 1.18329e-05 1.16864e-05
+ 1.15399e-05 1.13934e-05 1.12469e-05 1.11005e-05 1.0954e-05
+ 1.08075e-05 1.0661e-05 1.05145e-05 1.0368e-05 1.02215e-05
+ 1.76447e-05 7.21516e-05 -3.59786e-05 -0.000159618 0.000156236
+ 0.000135106 -0.000336402 -0.000302283 0.000699323 0.000473866
+ -0.000156146 -0.000225625 -0.000123592 -3.78116e-05 8.47472e-06
+ 2.43387e-06 -7.44762e-05 7.80111e-05 9.43608e-05 0.000170159
+ 8.83919e-05 -0.00018802 -0.000373512 -0.000390597 0.000156875
+ 0.0032343 0.00776304 -0.000566905 -0.00760695 -0.0159226
+ -0.0245989 -0.0331402 -0.0100902 0.067837 0.266702 0.910818
+ 1.82282 2.69714 3.43247 3.98325 4.32893 4.51529 4.67087
+ 4.79288 4.87574 4.92797 4.95902 4.97655 4.98622 4.99195
+ 4.99526 4.99735 4.9991 4.99974 4.99982 4.99974 4.99961 4.9995
+ 4.99943 4.9994 4.9994 4.99942 4.99944 4.99948 4.99952 4.99956
+ 4.99961 4.99965 4.9997 4.99974 4.99977 4.99981 4.99983 4.99986
+ 4.99988 4.9999 4.99991 4.99992 4.99993 4.99994 4.99995 4.99995
+ 4.99996 4.99997 4.99997 4.99998 4.99998 4.99999 4.99999
+ 4.99999 5 5 5 5.00001 5.00001 5.00001 5.00001 5.00001 5
+ 5 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 5 5.00019 4.99888 4.99663 4.99457 4.99902
+ 5.00229 5.00323 5.00302 5.0023 5.0015 5.00085 5.00041 5.00013
+ 4.99993 4.99979 4.99948 4.99954 4.99983 5.00055 5.00109
+ 5.00009 4.9987 4.998 4.99755 4.99676 4.99618 5.01091 5.05272
+ 5.04156 4.80112 4.27692 3.42343 2.23953 0.967179 0.429813
+ 0.540757 1.32991 2.32147 3.14903 3.78143 4.22325 4.47978
+ 4.59448 4.69875 4.79798 4.87419 4.92339 4.95249 4.97174
+ 4.98408 4.99124 4.99478 4.99729 4.99868 4.9992 4.99941 4.99947
+ 4.99946 4.99943 4.9994 4.99939 4.9994 4.99942 4.99946 4.99951
+ 4.99956 4.99961 4.99967 4.99973 4.99977 4.9998 4.99981 4.99983
+ 4.99984 4.99987 4.99992 5.00001 5.00005 5.00001 4.99994
+ 4.99995 4.99995 4.99996 4.99996 4.99996 4.99997 4.99997
+ 4.99997 4.99998 4.99998 4.99998 4.99998 4.99999 4.99999
+ 4.99999 4.99999 5 5 5 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5 5 5 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999
+ 4.99998 4.99998 4.99998
+ EOD
+
+ @v[31].set(<<-'EOD')
+ 1.8179e-09 -5.28841e-06 -1.44913e-05 -3.62932e-05 -9.75719e-05
+ 0.000141781 3.73396e-05 -1.65603e-05 -1.5271e-05 -6.73884e-06
+ 4.40157e-06 -4.85345e-06 -1.02964e-05 2.03126e-05 -1.89457e-05
+ -8.75564e-06 7.67422e-06 4.71103e-06 1.29798e-05 6.13469e-06
+ -1.14363e-05 -0.0394563 -0.0477298 -0.0622012 -0.0519225
+ 0.262499 0.943611 1.67052 2.31017 2.84028 3.28467 3.61582
+ 3.85887 4.13011 4.36511 4.54063 4.67013 4.76408 4.83263
+ 4.8825 4.91837 4.94373 4.96117 4.97318 4.98093 4.98562 4.98906
+ 4.99267 4.99539 4.99666 4.99731 4.99797 4.99844 4.99887
+ 4.99927 4.99933 4.99938 4.99944 4.99949 4.99955 4.9996 4.99965
+ 4.9997 4.99975 4.9998 4.99985 4.99986 4.99987 4.99989 4.9999
+ 4.99991 4.99992 4.99993 4.99995 4.99996 4.99997 4.99998
+ 4.99998 4.99999 4.99999 4.99999 4.99999 5 5 5 5 5.00001
+ 5.00001 5.00001 5 5 5 5 5 5 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99997 5.00002 5.00004 5.0001 5.0001 4.99987 5.00009
+ 5.00021 5.00002 5.00004 4.99988 5.00013 4.99993 5.00026
+ 4.99973 5 5.00006 5.00009 5.00004 5.00004 5.04854 4.82711
+ 4.04208 2.64155 0.838902 0.19014 0.0982549 0.0723197 0.0576863
+ 0.0427644 0.0301979 0.020146 0.0135728 0.00980358 0.00774482
+ 0.00586604 0.0036687 0.00211511 0.00121906 0.000647581 0.000828436
+ 0.00190938 0.00224254 0.00199956 0.00165488 0.00135612 0.00113715
+ 0.000984181 0.000877175 0.000789973 0.000741139 0.000689338
+ 0.000625676 0.000586082 0.000550152 0.000529573 0.000505606
+ 0.000482117 0.000460574 0.000441649 0.000424674 0.000408398
+ 0.000391914 0.000376272 0.000361487 0.000348181 0.000336045
+ 0.000324466 0.000313545 0.000303046 0.000293056 0.00028356
+ 0.000274586 0.000266155 0.000258279 0.000250938 0.000243789
+ 0.000236912 0.000230244 0.000224186 0.000219291 0.000215346
+ 0.000212468 0.000207291 0.000200862 0.00019368 0.000186767
+ 0.000183515 0.000180263 0.00017701 0.000173758 0.000170506
+ 0.000167253 0.000164001 0.000161164 0.000158357 0.00015555
+ 0.000152743 0.000149936 0.000147129 0.000144322 0.000142066
+ 0.000140096 0.000138127 0.000136157 0.000134187 0.000132218
+ 0.000130248 0.000128278 0.000126308 0.000124339 0.000122369
+ 0.000120399 0.000118429 0.00011646 0.000114527 0.000112892
+ 0.000111258 0.000109623 0.000107988 0.000103598 6.86052e-05
+ 3.337e-05 7.00783e-05 0.000218764 0.000221318 0.000118593
+ -0.000113962 5.78552e-05 9.42068e-05 0.000237037 0.000171302
+ 0.0001033 6.16066e-05 5.52908e-05 6.30233e-05 7.01897e-05
+ 8.48573e-05 0.000106859 8.37213e-05 -0.0391541 -0.047722
+ -0.0618454 -0.0169804 0.345725 1.03426 1.74825 2.37152 2.88737
+ 3.32173 3.66761 3.9707 4.17762 3.98832 3.30483 2.09737 0.710892
+ 0.148159 0.0707463 0.0555808 0.045618 0.0319116 0.0199589
+ 0.0133357 0.00898528 0.00586075 0.00375478 0.00245443 0.00156038
+ 0.000962344 0.000590953 0.000375107 0.000250243 0.00015882
+ 0.000100203 6.18122e-05 3.7372e-05 2.23009e-05 1.32569e-05
+ 8.29437e-06 5.72457e-06 3.96832e-06 2.98935e-06 2.59699e-06
+ 2.75024e-06 3.38689e-06 4.0453e-06 3.50095e-06 1.64988e-06
+ -3.84371e-07 -2.03828e-06 -3.46401e-06 -1.24301e-06 4.63458e-06
+ 1.14104e-05 1.02619e-05 2.15487e-06 -2.98487e-06 -3.67221e-06
+ -2.94279e-06 -2.58649e-06 -2.23019e-06 -1.87389e-06 -1.5176e-06
+ -1.1613e-06 -7.92127e-07 -4.18889e-07 -4.56502e-08 3.27588e-07
+ 7.00827e-07 8.79539e-07 8.17025e-07 7.5451e-07 6.91996e-07
+ 6.29481e-07 5.66966e-07 5.04452e-07 4.41937e-07 3.79422e-07
+ 3.16908e-07 2.54393e-07 1.90078e-07 1.25366e-07 6.0654e-08
+ -4.05776e-09 -6.87696e-08 -1.33481e-07 -1.98193e-07 -2.62905e-07
+ -3.27617e-07 -3.92329e-07 -4.40392e-07 -4.18802e-07 -3.97213e-07
+ -3.75624e-07 -3.54035e-07 -3.32446e-07 -3.10856e-07 -2.89267e-07
+ -2.67678e-07
+ EOD
+
+ @v[32].set(<<-'EOD')
+ 1.10294 1.10297 1.10291 1.10277 1.10259 1.10294 1.10313
+ 1.10306 1.10299 1.10296 1.10295 1.10295 1.10294 1.10294
+ 1.10294 1.10294 1.10294 1.10294 1.10294 1.10296 1.10296
+ 1.00547 0.998599 1.5201 2.49297 3.31258 3.73162 3.84757
+ 3.92505 4.02965 4.16599 4.30294 4.41541 4.52886 4.64414
+ 4.73865 4.81065 4.86391 4.90315 4.93188 4.95258 4.96726
+ 4.97738 4.98436 4.98888 4.99162 4.99363 4.99573 4.99731
+ 4.99804 4.99843 4.99881 4.99909 4.99934 4.99957 4.9996 4.99964
+ 4.99967 4.9997 4.99973 4.99977 4.9998 4.99983 4.99986 4.99988
+ 4.99991 4.99992 4.99992 4.99993 4.99994 4.99994 4.99995
+ 4.99996 4.99996 4.99997 4.99997 4.99998 4.99998 4.99999
+ 4.99999 4.99999 4.99999 5 5 5 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 5.00028 4.99988 4.99968
+ 5.00019 4.99987 5.00021 4.99973 4.99977 4.99996 4.99997
+ 5.0002 4.99957 5.00026 4.99947 5.00074 5.00003 4.99987 4.99979
+ 5.00008 4.99997 5.08794 5.05993 4.76875 3.99197 3.10174
+ 2.5197 2.21771 2.04 1.92235 1.83874 1.77592 1.72665 1.686
+ 1.65276 1.6286 1.61299 1.60039 1.58934 1.57954 1.57083 1.56306
+ 1.55604 1.54963 1.54375 1.53832 1.53331 1.52865 1.52432
+ 1.52026 1.51645 1.51287 1.50949 1.50629 1.50327 1.50039
+ 1.49766 1.49505 1.49257 1.49019 1.48792 1.48574 1.48365
+ 1.48164 1.47971 1.47784 1.47604 1.47431 1.47264 1.47102
+ 1.46945 1.46794 1.46647 1.46505 1.46367 1.46233 1.46103
+ 1.45976 1.45853 1.45733 1.45616 1.45502 1.45392 1.45284
+ 1.45179 1.45076 1.44975 1.4488 1.44795 1.44711 1.44626 1.44541
+ 1.44457 1.44372 1.44287 1.44212 1.44138 1.44063 1.43989
+ 1.43914 1.4384 1.43766 1.43701 1.43641 1.43581 1.43522 1.43462
+ 1.43402 1.43342 1.43282 1.43223 1.43163 1.43103 1.43043
+ 1.42984 1.42924 1.42865 1.42808 1.42752 1.42695 1.42639
+ 1.42584 1.42529 1.42472 1.42412 1.42365 1.42326 1.42304
+ 1.42162 1.42082 1.42032 1.42029 1.42026 1.41995 1.41947
+ 1.41894 1.41841 1.4179 1.41742 1.41699 1.41656 1.32097 1.30963
+ 1.78765 2.64656 3.35764 3.747 3.86589 3.94217 4.04185 4.18453
+ 4.3561 4.53439 4.68621 4.74905 4.77848 4.84629 4.91261 4.97541
+ 5.01284 5.01548 5.01248 5.00924 5.00666 5.00475 5.00334
+ 5.00234 5.00164 5.00118 5.00083 5.00058 5.0004 5.00028 5.00019
+ 5.00013 5.00009 5.00007 5.00004 5.00003 5.00002 5.00001
+ 5.00001 5.00001 5 5 4.99999 4.99995 4.99992 4.99996 5.00006
+ 5.00012 5.00009 4.99997 4.9999 4.99985 4.99986 4.99997 5.00021
+ 5.00031 5.00024 5.0001 5.00007 5.00005 5.00003 5.00001 4.99998
+ 4.99998 4.99999 4.99999 4.99999 5 5 5 5 5 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00002 5.00002 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5 5 5 5
+ 5 4.99999 4.99999 4.99999 4.99998 4.99998 4.99998
+ EOD
+
+ @v[33].set(<<-'EOD')
+ 5 5.00012 5.00023 5.0003 4.99972 4.99988 4.99984 4.99991
+ 4.99996 4.99999 5.00008 5.00009 4.99986 5.00003 5.00007
+ 4.99995 4.9999 4.99997 5.00013 5.00014 5.00013 4.99701 4.99763
+ 4.99742 4.99998 5.02836 5.07262 4.96856 4.57267 3.85637
+ 2.79544 1.45942 0.408016 0.084885 0.0271375 0.0119294 0.00707546
+ 0.0051087 0.00373035 0.00264737 0.00186477 0.00130379 0.000915857
+ 0.000653121 0.000483893 0.000380852 0.000302362 0.000219498
+ 0.000154435 0.000121928 0.000104026 8.61242e-05 7.48526e-05
+ 6.49216e-05 5.56238e-05 5.29689e-05 5.03139e-05 4.7659e-05
+ 4.5004e-05 4.23491e-05 4.00356e-05 3.79522e-05 3.58687e-05
+ 3.37852e-05 3.17018e-05 2.97592e-05 2.89804e-05 2.82016e-05
+ 2.74228e-05 2.66441e-05 2.58653e-05 2.50865e-05 2.43077e-05
+ 2.35289e-05 2.27501e-05 2.19714e-05 2.12346e-05 2.07821e-05
+ 2.03295e-05 1.98769e-05 1.94244e-05 1.89718e-05 1.85192e-05
+ 1.80667e-05 1.76141e-05 1.71615e-05 1.6709e-05 1.62828e-05
+ 1.60061e-05 1.57294e-05 1.54527e-05 1.5176e-05 1.48993e-05
+ 1.46226e-05 1.43459e-05 1.40692e-05 1.37925e-05 1.35158e-05
+ 1.3262e-05 1.31191e-05 1.29761e-05 1.28332e-05 1.26903e-05
+ 1.25474e-05 1.24045e-05 1.22615e-05 1.21186e-05 1.19757e-05
+ 1.18328e-05 1.16898e-05 1.15469e-05 1.1404e-05 1.12611e-05
+ 1.11182e-05 1.09752e-05 1.08323e-05 1.06894e-05 1.05465e-05
+ 1.04036e-05 1.02606e-05 1.00185e-05 3.8343e-05 -3.06781e-05
+ -0.000111758 0.000111673 0.000130815 -0.000210491 -0.000231304
+ 0.000310226 0.000265303 3.0878e-05 -4.48405e-05 -1.2852e-05
+ -7.84469e-06 3.29986e-05 -1.23286e-05 -6.07871e-05 5.35082e-05
+ 7.69194e-05 0.000126221 6.57178e-05 0.00223349 -0.0148854
+ -0.0476636 -0.0491447 0.220125 1.11174 2.03988 2.90209 3.61069
+ 4.13554 4.50679 4.71501 4.83916 4.91027 4.95284 4.98086
+ 4.99151 4.98651 4.97113 4.95075 4.93102 4.93683 4.95457
+ 4.97071 4.98212 4.98948 4.99386 4.99636 4.99785 4.9987 4.99927
+ 4.99989 5.00014 5.00007 4.99988 4.99982 4.99976 4.99973
+ 4.99972 4.99972 4.99973 4.99974 4.99975 4.99977 4.99979
+ 4.99981 4.99984 4.99986 4.99988 4.99989 4.99991 4.99992
+ 4.99993 4.99994 4.99995 4.99996 4.99996 4.99997 4.99997
+ 4.99998 4.99998 4.99998 4.99998 4.99999 4.99999 4.99999
+ 4.99999 5 5 5 5.00001 5.00001 5.00001 5.00002 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5 5 5 5 5 5 5 5 4.99999 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999 4.99999
+ 4.99999 4.99999 4.99999 5 5.00012 4.99946 4.99839 4.99733
+ 4.99948 5.00114 5.00158 5.00147 5.00113 5.00073 5.00043
+ 5.0002 5.00006 4.99995 4.99986 4.99973 4.99976 4.9999 5.00029
+ 5.00055 4.99704 4.99734 4.9972 5.00278 5.03354 5.07184 4.94057
+ 4.51936 3.75638 2.60982 1.23803 0.315016 0.0796102 0.0252894
+ 0.0165723 0.0827785 0.491298 1.40686 2.33436 3.1251 3.7691
+ 4.22201 4.49976 4.68115 4.80513 4.88509 4.93208 4.95861
+ 4.97579 4.98655 4.99268 4.99571 4.99771 4.99881 4.99929
+ 4.99954 4.99965 4.9997 4.99971 4.99971 4.99971 4.99971 4.99972
+ 4.99974 4.99976 4.99978 4.99981 4.99984 4.99987 4.99989
+ 4.99991 4.99991 4.99992 4.99992 4.99993 4.99997 5.00003
+ 5.00006 5.00004 5.00001 5 4.99999 4.99998 4.99998 4.99997
+ 4.99997 4.99997 4.99998 4.99998 4.99998 4.99999 4.99999
+ 4.99999 4.99999 5 5 5 5 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5 5 5 5 5 5 5 4.99999
+ 4.99999 4.99999 4.99999 4.99998 4.99998
+ EOD
+
+ @v[34].set(<<-'EOD')
+ 5 5.00207 5.00813 5.01486 5.00156 5.0018 4.99861 4.99844
+ 4.99888 4.9993 4.99956 4.99971 4.99979 4.99983 4.99987 4.99989
+ 4.99671 4.9974 4.99864 5.00131 5.00377 5.0021 5.00039 4.99993
+ 5.00004 5.0009 5.00109 4.99636 4.98617 4.96778 4.92047 4.89528
+ 4.91112 4.9559 4.98286 4.99369 4.99812 4.99951 4.99994 5.00014
+ 5.00008 4.99994 4.99984 4.99989 4.99998 5.00004 5.00004
+ 5.00006 5.00005 5.00001 4.99997 4.99992 4.99993 4.99994
+ 4.99996 4.99996 4.99996 4.99996 4.99996 4.99996 4.99996
+ 4.99996 4.99996 4.99996 4.99996 4.99996 4.99996 4.99996
+ 4.99997 4.99997 4.99997 4.99997 4.99997 4.99997 4.99997
+ 4.99997 4.99997 4.99997 4.99997 4.99997 4.99997 4.99997
+ 4.99997 4.99997 4.99997 4.99997 4.99997 4.99997 4.99997
+ 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998
+ 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998
+ 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998
+ 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998
+ 4.99998 4.99998 4.99998 4.99998 5.00131 5.00072 4.9977 4.99811
+ 5.00325 4.99647 4.98948 4.99459 5.00262 5.00276 5.00156
+ 5.00072 5.0003 5.00013 4.99995 4.99668 4.99775 4.99917 5.00173
+ 5.00386 5.00188 4.99888 4.99757 4.99951 5.01712 5.0557 5.07088
+ 5.07704 5.07758 5.06958 5.04223 5.03331 5.0279 5.03408 5.07611
+ 5.01911 4.68594 3.99152 2.92195 1.69878 0.809 0.344091 0.154663
+ 0.0788717 0.0467212 0.0336168 0.0280514 0.0254947 0.024173
+ 0.0223567 0.0220555 0.0271514 0.0295872 0.0296052 0.0283971
+ 0.0264726 0.0241813 0.0218244 0.0195349 0.017368 0.0152495
+ 0.013295 0.0115444 0.00996982 0.00857091 0.00733891 0.00627261
+ 0.0053494 0.00456316 0.00388373 0.00331073 0.00282181 0.00240991
+ 0.00206389 0.00177187 0.00152283 0.00131167 0.00112558 0.000954373
+ 0.000805726 0.00069326 0.000600991 0.000525743 0.00047355
+ 0.00044359 0.000434815 0.000436053 0.000402511 0.000368969
+ 0.000335427 0.000301886 0.000268344 0.000234802 0.00020126
+ 0.000184967 0.000169932 0.000154896 0.000139861 0.000124825
+ 0.00010979 9.47546e-05 8.67896e-05 8.24901e-05 7.81906e-05
+ 7.38911e-05 6.95915e-05 6.5292e-05 6.09925e-05 5.66929e-05
+ 5.23934e-05 4.80939e-05 4.37943e-05 3.94948e-05 3.51953e-05
+ 3.08957e-05 2.67968e-05 2.42936e-05 2.17904e-05 1.92872e-05
+ 1.6784e-05 0.00125927 -0.00794344 -0.0305499 -0.0621697
+ -0.0463796 -0.0224608 -0.00538381 0.00546086 0.0108675 0.012883
+ 0.0131787 0.0127271 0.0119702 0.0110398 0.0100635 0.00649617
+ 0.00489388 0.00545863 0.0098351 0.0167428 0.0126563 0.00697542
+ 0.00427027 0.00330002 0.00390774 0.00408999 -0.00259143
+ -0.0160578 -0.0451849 -0.0409651 0.1301 0.597429 1.3848
+ 2.63426 3.81272 4.51373 4.8412 4.98731 4.88165 4.37165 3.40034
+ 2.17681 1.12217 0.505129 0.219703 0.104992 0.0622333 0.0448317
+ 0.0355782 0.0311867 0.0293529 0.0274615 0.0288739 0.0307845
+ 0.0304909 0.029245 0.0273602 0.0251006 0.022697 0.0202765
+ 0.0179357 0.0157106 0.0136562 0.0117951 0.0101273 0.00865784
+ 0.00739394 0.00634364 0.00551356 0.00480538 0.00415747 0.00356084
+ 0.00297585 0.00236711 0.00181853 0.00160713 0.00169822 0.00166542
+ 0.00145504 0.00120252 0.00109259 0.000982658 0.00087273
+ 0.000762802 0.000652874 0.000584068 0.000528263 0.000472458
+ 0.000416653 0.000360848 0.000321155 0.000301442 0.000281729
+ 0.000262016 0.000242303 0.00022259 0.000202877 0.000183164
+ 0.000163451 0.000143738 0.000124025 0.000114582 0.000107399
+ 0.000100216 9.30332e-05 8.58502e-05 7.86672e-05 7.14841e-05
+ 6.43011e-05 5.7118e-05 4.9935e-05 4.35378e-05 4.04281e-05
+ 3.73184e-05 3.42088e-05 3.10991e-05 2.79894e-05 2.48798e-05
+ 2.17701e-05 1.86604e-05
+ EOD
+
+ @v[35].set(<<-'EOD')
+ 7.24585e-12 2.21843e-05 3.20014e-05 1.25076e-05 -2.44947e-05
+ 1.8425e-05 5.50546e-06 3.53025e-05 -1.07551e-05 -3.94383e-06
+ -2.27848e-06 -9.04789e-05 7.44215e-05 -2.7662e-05 0.000200038
+ -2.11998e-05 -2.09011e-05 2.37098e-05 2.18751e-05 -2.28422e-05
+ -6.23659e-05 3.58241e-05 1.76386e-05 -4.28311e-05 0.000355626
+ 0.00156903 0.00100999 -0.0085304 -0.02067 -0.0389485 -0.0651568
+ -0.128475 -0.314362 -0.406837 -0.421558 -0.421277 -0.418176
+ -0.414481 -0.410845 -0.407348 -0.403971 -0.400716 -0.397582
+ -0.394563 -0.391658 -0.388866 -0.386178 -0.383585 -0.381094
+ -0.378789 -0.376569 -0.37435 -0.372256 -0.370188 -0.36815
+ -0.366422 -0.364694 -0.362967 -0.361239 -0.359511 -0.357888
+ -0.356334 -0.354781 -0.353227 -0.351674 -0.350152 -0.348888
+ -0.347625 -0.346361 -0.345098 -0.343834 -0.342571 -0.341307
+ -0.340044 -0.33878 -0.337517 -0.336279 -0.335215 -0.334152
+ -0.333088 -0.332024 -0.330961 -0.329897 -0.328833 -0.32777
+ -0.326706 -0.325642 -0.324601 -0.323683 -0.322766 -0.321849
+ -0.320932 -0.320014 -0.319097 -0.31818 -0.317263 -0.316345
+ -0.315428 -0.314545 -0.313825 -0.313106 -0.312387 -0.311667
+ -0.310948 -0.310228 -0.309509 -0.308789 -0.30807 -0.307351
+ -0.306631 -0.305912 -0.305192 -0.304473 -0.303754 -0.303034
+ -0.302315 -0.301595 -0.300876 -0.300157 -0.299437 -0.298716
+ -0.29798 -0.297329 -0.296691 -0.295837 -0.29516 -0.294725
+ -0.294044 -0.292917 -0.292351 -0.291965 -0.291365 -0.290687
+ -0.290027 -0.289376 -0.288772 -0.288193 -0.287505 -0.286892
+ -0.28626 -0.285714 -0.284545 -0.289246 -0.298717 -0.298492
+ -0.214163 0.181451 0.0749974 0.0454707 0.0292987 0.0196837
+ 0.0124119 0.00884715 0.00527181 0.00585821 0.0296361 0.169856
+ 0.361207 0.538856 0.67469 0.685933 0.392802 0.17772 0.0813085
+ 0.0424601 0.0246654 0.0175258 0.0144256 0.0129859 0.012205
+ 0.0112846 0.010933 0.0134813 0.0147254 0.0147981 0.0142156
+ 0.0132732 0.0121355 0.0109587 0.00981238 0.00872731 0.00767007
+ 0.00669346 0.00581341 0.00502167 0.00431819 0.00369842 0.00316168
+ 0.00269663 0.00230035 0.00195801 0.00166928 0.00142286 0.00121522
+ 0.00104072 0.000893384 0.000767675 0.000661268 0.000567659
+ 0.000481766 0.000407101 0.000350044 0.000302721 0.000263424
+ 0.000236813 0.00022199 0.000218182 0.000219548 0.0002027
+ 0.000185853 0.000169006 0.000152158 0.000135311 0.000118463
+ 0.000101616 9.33782e-05 8.57685e-05 7.81588e-05 7.0549e-05
+ 6.29393e-05 5.53296e-05 4.77199e-05 4.36954e-05 4.15296e-05
+ 3.93637e-05 3.71978e-05 3.50319e-05 3.28661e-05 3.07002e-05
+ 2.85343e-05 2.63685e-05 2.42026e-05 2.20367e-05 1.98709e-05
+ 1.7705e-05 1.55391e-05 1.34772e-05 1.22416e-05 1.10061e-05
+ 9.77055e-06 8.535e-06 0.000631271 -0.00362586 -0.0146235
+ -0.0308486 -0.0237466 -0.0117522 -0.00304171 0.00251033
+ 0.00531986 0.0063897 0.00657351 0.00636494 0.00599705 0.00553442
+ 0.00505994 0.00330925 0.00246671 0.0027006 0.00473161 0.00830333
+ 0.00649147 0.00356815 0.00217448 0.00187579 0.00270447 0.00219543
+ -0.00546118 -0.0179576 -0.0445306 -0.0649309 0.0197935 0.473629
+ 0.87268 0.269542 0.0086094 0.0844602 0.606456 1.04929 0.906014
+ 0.916205 0.919425 0.872867 0.556244 0.262457 0.11838 0.0571226
+ 0.0333451 0.0237133 0.0185096 0.0159617 0.0148663 0.0138683
+ 0.0144081 0.0153797 0.0152551 0.0146487 0.0137192 0.0125973
+ 0.0113996 0.0101903 0.00901851 0.00790495 0.00687502 0.00593994
+ 0.00510092 0.00436111 0.00372439 0.0031945 0.00277537 0.00241888
+ 0.002095 0.00179943 0.00150419 0.00119264 0.00090934 0.000802394
+ 0.000852816 0.000838368 0.000730842 0.000601028 0.000546616
+ 0.000492205 0.000437793 0.000383381 0.000328969 0.00029454
+ 0.000266428 0.000238317 0.000210205 0.000182093 0.000162091
+ 0.000152145 0.000142198 0.000132252 0.000122306 0.000112359
+ 0.000102413 9.24665e-05 8.25201e-05 7.25738e-05 6.26274e-05
+ 5.78553e-05 5.42216e-05 5.05878e-05 4.69541e-05 4.33204e-05
+ 3.96867e-05 3.60529e-05 3.24192e-05 2.87855e-05 2.51518e-05
+ 2.19153e-05 2.03406e-05 1.8766e-05 1.71913e-05 1.56167e-05
+ 1.4042e-05 1.24674e-05 1.08927e-05 9.31806e-06
+ EOD
+
+ @v[36].set(<<-'EOD')
+ 5 5.01426 5.02852 5.01923 4.77685 4.56471 4.52338 4.56813
+ 4.63122 4.693 4.74776 4.79385 4.83258 4.86358 4.88918 4.91021
+ 4.90553 4.89733 4.89554 4.91953 5.00757 5.07101 5.06318
+ 5.05241 5.05535 5.08042 5.07251 4.90973 4.56136 3.98637
+ 3.237 2.67216 2.33678 2.13529 2.00544 1.91429 1.84638 1.79461
+ 1.75338 1.71958 1.69175 1.6686 1.64918 1.63258 1.61836 1.60607
+ 1.59506 1.58483 1.57575 1.56847 1.56193 1.55538 1.54968
+ 1.54416 1.5388 1.53523 1.53165 1.52807 1.52449 1.52091 1.51771
+ 1.51477 1.51182 1.50888 1.50593 1.50309 1.50113 1.49917
+ 1.4972 1.49524 1.49328 1.49132 1.48935 1.48739 1.48543 1.48346
+ 1.48157 1.48012 1.47868 1.47724 1.47579 1.47435 1.47291
+ 1.47146 1.47002 1.46857 1.46713 1.46574 1.46462 1.4635 1.46238
+ 1.46126 1.46014 1.45902 1.4579 1.45678 1.45567 1.45455 1.45349
+ 1.45275 1.45201 1.45127 1.45053 1.44979 1.44905 1.44831
+ 1.44757 1.44683 1.44609 1.44535 1.44461 1.44387 1.44313
+ 1.44239 1.44165 1.44091 1.44017 1.43943 1.43869 1.43795
+ 1.43721 1.43874 1.43976 1.43619 1.43182 1.43726 1.43084
+ 1.42587 1.42383 1.42642 1.42728 1.42736 1.4271 1.42669 1.42621
+ 1.42569 1.41703 1.41244 1.41019 1.41199 1.41833 1.42502
+ 1.41504 1.37535 1.28381 1.44779 2.33713 3.25835 3.67554
+ 3.84975 4.01125 4.2253 4.45433 4.62215 4.74478 4.82998 4.8868
+ 4.92396 4.94768 4.96498 4.98537 5.0128 5.04467 5.06722 5.06535
+ 5.01475 4.91956 4.80647 4.7242 4.7059 4.73552 4.76379 4.81684
+ 4.87376 4.92276 4.96112 4.9884 5.0045 5.00999 5.00933 5.00619
+ 5.00384 5.00342 5.00373 5.00362 5.00309 5.00272 5.00239
+ 5.00204 5.00172 5.00146 5.00124 5.00105 5.00089 5.00076
+ 5.00065 5.00057 5.00048 5.00041 5.00034 5.00028 5.00023
+ 5.00019 5.00015 5.00015 5.00016 5.0002 5.00023 5.00021 5.00019
+ 5.00017 5.00015 5.00012 5.0001 5.00008 5.00007 5.00006 5.00005
+ 5.00004 5.00003 5.00002 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00002 5.00002 5.00002 5.00002
+ 5.00002 5.00002 5.00002 5.00002 5.00002 5.00002 5.00001
+ 5.00001 5.00001 5.00062 4.99506 4.9835 4.96726 4.9728 4.97877
+ 4.98675 4.9966 5.00406 5.00679 5.00629 5.00561 5.00487 5.00429
+ 5.00384 5.002 5.00164 5.00229 5.00484 5.00769 5.00019 5.00242
+ 5.01319 5.0335 5.07265 5.10129 5.11485 5.12551 5.13953 5.16048
+ 5.18862 5.22811 5.25656 5.25627 5.19975 4.9139 4.24745 3.43732
+ 2.8202 2.43224 2.17409 2.01333 1.93951 1.94622 1.98861 2.02217
+ 2.05383 2.08376 2.11184 2.13793 2.16191 2.18267 2.20502
+ 2.22837 2.24958 2.26901 2.28648 2.302 2.31582 2.32802 2.33869
+ 2.34795 2.35596 2.36282 2.3687 2.37371 2.37797 2.38161 2.38476
+ 2.38743 2.3897 2.39168 2.39329 2.39463 2.39575 2.39671 2.39756
+ 2.39835 2.39907 2.39968 2.39999 2.4003 2.40061 2.40091 2.40122
+ 2.40142 2.40159 2.40176 2.40193 2.4021 2.40222 2.40228 2.40234
+ 2.4024 2.40247 2.40253 2.40259 2.40265 2.40271 2.40277 2.40284
+ 2.40287 2.40289 2.40291 2.40294 2.40296 2.40298 2.40301
+ 2.40303 2.40305 2.40308 2.4031 2.40311 2.40312 2.40313 2.40314
+ 2.40315 2.40316 2.40317 2.40318
+ EOD
+
+ @v[37].set(<<-'EOD')
+ 5 5.01732 5.03181 5.05944 5.12686 5.20725 5.28103 5.31254
+ 5.32901 5.33709 5.3408 5.34257 5.34311 5.34347 5.34386 5.34411
+ 5.3406 5.33484 5.32942 5.32904 5.33644 5.34869 5.35001 5.34882
+ 5.34758 5.34672 5.34599 5.34496 5.34364 5.34165 5.33712
+ 5.33502 5.3366 5.34067 5.34306 5.34398 5.34434 5.34442 5.34443
+ 5.34443 5.34441 5.34439 5.34437 5.34437 5.34438 5.34438
+ 5.34438 5.34438 5.34438 5.34437 5.34437 5.34436 5.34436
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437 5.34437
+ 5.34437 5.34437 5.34437 5.34437 5.34437 5.35377 5.35451
+ 5.34265 5.34488 5.35861 5.28622 4.90033 4.75027 4.89731
+ 4.97098 4.99293 4.99832 4.99909 4.99956 4.99858 4.99829
+ 4.9998 5.00035 5.0038 5.00989 5.00251 4.99438 4.9953 4.99761
+ 4.99985 5.00152 5.0011 5.00046 4.99996 4.99925 4.99862 4.99919
+ 4.99961 5.00048 5.00234 4.99654 4.98235 4.95936 4.83738
+ 4.53021 4.21004 4.00593 3.91207 3.88059 3.87822 3.89117
+ 3.91278 3.94044 3.97376 4.01152 4.05052 4.10679 4.17908
+ 4.25673 4.33414 4.40875 4.47879 4.54342 4.60258 4.65595
+ 4.70291 4.74414 4.78018 4.81185 4.83915 4.86291 4.88301
+ 4.90048 4.91528 4.92802 4.9387 4.94777 4.95539 4.9618 4.96725
+ 4.97195 4.97588 4.97932 4.98247 4.98512 4.98697 4.98831
+ 4.98919 4.99015 4.99101 4.99169 4.99222 4.99282 4.99341
+ 4.994 4.9946 4.99519 4.99578 4.99638 4.99667 4.99693 4.9972
+ 4.99747 4.99773 4.998 4.99827 4.99841 4.99849 4.99856 4.99864
+ 4.99872 4.9988 4.99888 4.99896 4.99904 4.99911 4.99919 4.99927
+ 4.99935 4.99943 4.9995 4.99955 4.9996 4.99965 4.9997 5.00736
+ 4.98252 4.87516 4.66727 4.49142 4.43103 4.4301 4.4571 4.49729
+ 4.5407 4.5835 4.62363 4.66114 4.69577 4.72738 4.74632 4.75971
+ 4.77576 4.80671 4.87073 4.91665 4.93252 4.94418 4.95331
+ 4.96094 4.96727 4.97148 4.97471 4.97612 4.98276 5.00247
+ 5.04086 5.08628 5.10673 5.08887 5.0564 5.02767 5.01336 4.99685
+ 4.97422 4.90866 4.67035 4.33117 4.07888 3.94432 3.89105
+ 3.88174 3.89292 3.91442 3.94564 3.98708 4.0355 4.09134 4.16315
+ 4.24088 4.31918 4.39527 4.46693 4.53337 4.59405 4.6486 4.69693
+ 4.73938 4.77617 4.80809 4.83551 4.85895 4.87894 4.89596
+ 4.91081 4.92417 4.93651 4.94552 4.95198 4.9565 4.96096 4.96523
+ 4.96972 4.97428 4.97868 4.98064 4.9826 4.98455 4.98651 4.98847
+ 4.98967 4.99064 4.9916 4.99257 4.99353 4.99422 4.99457 4.99493
+ 4.99528 4.99563 4.99598 4.99633 4.99668 4.99703 4.99738
+ 4.99773 4.9979 4.99804 4.99817 4.9983 4.99843 4.99856 4.99869
+ 4.99883 4.99896 4.99909 4.99921 4.99926 4.99931 4.99937
+ 4.99942 4.99948 4.99953 4.99959 4.99964
+ EOD
+
+ @v[38].set(<<-'EOD')
+ 4.49849 4.53282 4.58329 4.66625 4.83345 4.97823 5.0207 5.01816
+ 5.01116 5.00595 5.00296 5.00148 5.00073 5.00062 5.00033
+ 5.0003 4.99864 4.99661 4.99652 4.99928 5.00361 5.12573 5.17251
+ 5.22612 5.33479 5.44503 5.44432 5.44379 5.44334 5.443 5.44276
+ 5.44258 5.44246 5.44238 5.44232 5.44228 5.44225 5.44223
+ 5.44221 5.4422 5.44219 5.44219 5.44218 5.44218 5.44218 5.44218
+ 5.44217 5.44217 5.44217 5.44217 5.44217 5.44217 5.44217
+ 5.44217 5.44217 5.44217 5.44217 5.44217 5.44217 5.44217
+ 5.44217 5.44217 5.44217 5.44217 5.44217 5.44217 5.44216
+ 5.44216 5.44216 5.44216 5.44216 5.44216 5.44216 5.44216
+ 5.44216 5.44216 5.44216 5.44216 5.44216 5.44216 5.44216
+ 5.44216 5.44216 5.44216 5.44216 5.44215 5.44215 5.44215
+ 5.44215 5.44215 5.44215 5.44215 5.44215 5.44215 5.44215
+ 5.44215 5.44215 5.44215 5.44215 5.44215 5.44215 5.44215
+ 5.44215 5.44215 5.44215 5.44215 5.44215 5.44215 5.44215
+ 5.44214 5.44214 5.44214 5.44214 5.44214 5.44214 5.44214
+ 5.44214 5.44214 5.44214 5.44214 5.44212 5.45159 5.45236
+ 5.44064 5.44307 5.45616 5.38122 4.77163 3.53297 2.74466
+ 2.34448 2.11802 1.9783 1.88656 1.82001 1.77389 1.72955 1.69632
+ 1.66971 1.6526 1.65236 1.56034 1.53764 1.97139 2.75096 3.39212
+ 3.74042 3.82345 3.85696 3.88547 3.91862 3.9585 4.00467 4.05903
+ 4.1254 4.19533 4.26791 4.34517 4.42112 4.49238 4.55807 4.6179
+ 4.6713 4.71815 4.75889 4.79418 4.82456 4.85062 4.87291 4.89196
+ 4.90823 4.92209 4.93388 4.9439 4.95242 4.95968 4.96585 4.97108
+ 4.9755 4.97923 4.98237 4.98503 4.98732 4.98927 4.99094 4.99233
+ 4.99353 4.99452 4.99538 4.99608 4.99668 4.99718 4.9976 4.99794
+ 4.99822 4.99847 4.99867 4.99884 4.99899 4.99913 4.99924
+ 4.99932 4.99938 4.99943 4.99947 4.99951 4.99953 4.99955
+ 4.99958 4.99961 4.99964 4.99967 4.99969 4.99972 4.99975
+ 4.99977 4.99978 4.99979 4.99981 4.99982 4.99983 4.99985
+ 4.99986 4.99986 4.99987 4.99987 4.99988 4.99988 4.99988
+ 4.99989 4.99989 4.9999 4.9999 4.99991 4.99991 4.99992 4.99992
+ 4.99993 4.99993 4.99993 4.99994 5.00381 5.00064 4.99246
+ 4.99823 5.00349 5.00076 5.00033 5.00015 5.00009 5.00007
+ 5.00005 5.00004 5.00003 5.00002 4.99988 4.99732 4.99728
+ 4.9978 5.00187 5.00927 5.08712 5.07654 4.92855 4.4863 3.76162
+ 3.00049 2.49834 2.20883 2.03492 1.92384 1.84676 1.79021
+ 1.74716 1.7132 1.68576 1.66309 1.64406 1.62785 1.61383 1.60162
+ 1.59081 1.58117 1.57253 1.56473 1.55765 1.55117 1.54527
+ 1.53988 1.53485 1.53012 1.5257 1.5216 1.51773 1.51411 1.51071
+ 1.50746 1.50438 1.50146 1.49868 1.49603 1.4935 1.49109 1.48878
+ 1.48657 1.48445 1.48242 1.48046 1.47858 1.47677 1.47502
+ 1.47333 1.4717 1.47012 1.46859 1.46711 1.46568 1.46428 1.46292
+ 1.4616 1.46034 1.45923 1.45812 1.45701 1.4559 1.45479 1.45378
+ 1.45279 1.45181 1.45082 1.44983 1.44893 1.44813 1.44732
+ 1.44652 1.44571 1.44491 1.4441 1.4433 1.44249 1.44169 1.44089
+ 1.44019 1.43951 1.43883 1.43815 1.43747 1.4368 1.43612 1.43544
+ 1.43476 1.43408 1.43342 1.43283 1.43223 1.43163 1.43104
+ 1.43044 1.42984 1.42924 1.42865
+ EOD
+
+ @v[39].set(<<-'EOD')
+ 5 5.01048 5.01221 4.98887 4.76261 4.54943 4.51564 4.56249
+ 4.62621 4.68843 4.74374 4.79044 4.82972 4.86127 4.88724
+ 4.90862 4.90791 4.89858 4.89589 4.91767 5.00405 5.16956
+ 5.12391 4.7557 3.87953 3.01124 2.48482 2.20424 2.03812 1.92679
+ 1.84956 1.79256 1.74907 1.71487 1.68724 1.6644 1.64513 1.6287
+ 1.61446 1.60197 1.59095 1.58117 1.57245 1.5646 1.55752 1.55109
+ 1.54516 1.53958 1.53444 1.53008 1.52606 1.52205 1.51843
+ 1.5149 1.51146 1.50893 1.50639 1.50387 1.50133 1.4988 1.49651
+ 1.49436 1.49222 1.49007 1.48793 1.48585 1.48433 1.4828 1.48128
+ 1.47975 1.47823 1.4767 1.47518 1.47365 1.47213 1.4706 1.46912
+ 1.46795 1.46678 1.46561 1.46444 1.46327 1.4621 1.46093 1.45976
+ 1.45859 1.45741 1.45628 1.45534 1.45441 1.45347 1.45254
+ 1.4516 1.45067 1.44973 1.4488 1.44786 1.44693 1.44604 1.44539
+ 1.44475 1.4441 1.44345 1.44281 1.44216 1.44151 1.44086 1.44022
+ 1.43957 1.43892 1.43828 1.43763 1.43698 1.43633 1.43569
+ 1.43504 1.43439 1.43375 1.4331 1.43245 1.4318 1.43157 1.43089
+ 1.43001 1.43042 1.42899 1.42439 1.42216 1.43447 1.44048
+ 1.43705 1.43314 1.43039 1.42861 1.42739 1.42651 1.42548
+ 1.42488 1.4243 1.42392 1.4235 1.32443 1.31149 1.78169 2.64844
+ 3.43211 3.95252 4.20231 4.3746 4.49948 4.58929 4.65742 4.71183
+ 4.77057 4.83196 4.88354 4.92894 4.96625 4.99235 5.00651
+ 5.00941 5.00813 5.00689 5.00588 5.00504 5.00431 5.00368
+ 5.00314 5.00268 5.00228 5.00194 5.00165 5.0014 5.00118 5.001
+ 5.00085 5.00072 5.00061 5.00052 5.00044 5.00037 5.00031
+ 5.00027 5.00022 5.00019 5.00016 5.00013 5.00011 5.00009
+ 5.00008 5.00007 5.00006 5.00005 5.00004 5.00003 5.00003
+ 5.00003 5.00002 5.00002 5.00002 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001 5.00001
+ 5.00001 5.00001 5 5 5 5 5 4.99999 4.99999 4.99999 4.99998
+ 4.99998 4.99998 4.99998 4.99998 4.99998 4.99998 4.99999
+ 4.99999 4.99999 4.99999 4.99999 4.99999 5 5 5 5 5.00001
+ 5.00002 5.00003 5.00004 5.00022 4.99974 4.99942 4.99997
+ 5.00063 5.00002 5.00003 4.99994 4.99998 4.99999 5 5 5 5
+ 5 4.99981 4.99998 5.00004 5.00036 5.00049 5.12012 5.16315
+ 5.19712 5.21835 4.87874 4.10151 3.31555 2.74207 2.38075
+ 2.15872 2.01614 1.91886 1.84852 1.79401 1.75052 1.71508
+ 1.68672 1.66467 1.64602 1.62985 1.61576 1.60343 1.59256
+ 1.58287 1.57418 1.56632 1.55922 1.55282 1.54687 1.54132
+ 1.53618 1.53143 1.52698 1.52282 1.51895 1.51527 1.5118 1.50851
+ 1.5054 1.50244 1.49963 1.49695 1.4944 1.49196 1.48963 1.4874
+ 1.48527 1.48322 1.48124 1.47934 1.47751 1.47574 1.47403
+ 1.47239 1.4708 1.46926 1.46777 1.46632 1.46491 1.46355 1.46237
+ 1.4612 1.46002 1.45884 1.45766 1.45659 1.45555 1.45451 1.45346
+ 1.45242 1.45147 1.45062 1.44978 1.44894 1.44809 1.44725
+ 1.4464 1.44556 1.44472 1.44387 1.44303 1.4423 1.44159 1.44088
+ 1.44017 1.43947 1.43876 1.43805 1.43734 1.43664 1.43593
+ 1.43524 1.43462 1.434 1.43338 1.43276 1.43213 1.43151 1.43089
+ 1.43027
+ EOD
+ end
+
+ def highlightTrace(graph)
+ entry = graph.legend_get(:current)
+ active_list = graph.legend_activate
+ if active_list.include?(entry)
+ graph.legend_deactivate(entry)
+ graph.element_deactivate(entry)
+ else
+ graph.legend_activate(entry)
+ graph.element_activate(entry)
+ end
+ end
+
+end
+
+BLT_Graph_Demo.new
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/graph7.rb b/ext/tk/sample/tkextlib/blt/graph7.rb
new file mode 100644
index 0000000000..27fbe53d97
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/graph7.rb
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/blt'
+
+length = 250000
+graph = Tk::BLT::Graph.new(:title=>"Scatter Plot\n#{length} points")
+graph.xaxis_configure(:loose=>false, :title=>'X Axis Label')
+graph.yaxis_configure(:title=>'Y Axis Label')
+graph.legend_configure(:activerelief=>:sunken, :background=>'')
+
+Tk::BLT::Table.add(Tk.root, graph, [0,0], :fill=>:both)
+
+v_x = Tk::BLT::Vector.new(length)
+v_y = Tk::BLT::Vector.new(length)
+v_x.expr("random(#{v_x})")
+v_y.expr("random(#{v_y})")
+v_x.sort(v_y)
+
+plot = Tk::BLT::PlotComponent::Element.new(graph, :symbol=>:square,
+ :color=>'green4', :fill=>'green2',
+ :linewidth=>0, :outlinewidth=>1,
+ :pixels=>4, :label=>'plot',
+ :xdata=>v_x, :ydata=>v_y)
+
+Tk.root.minsize(0, 0)
+
+#graph.zoom_stack
+#graph.crosshairs
+#graph.active_legend
+#graph.closest_point
+Tk::BLT.zoom_stack(graph)
+Tk::BLT.crosshairs(graph)
+Tk::BLT.active_legend(graph)
+Tk::BLT.closest_point(graph)
+
+Tk::BLT::Busy.hold(graph)
+Tk.update
+Tk::BLT::Busy.release(graph)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/graph7a.rb b/ext/tk/sample/tkextlib/blt/graph7a.rb
new file mode 100644
index 0000000000..a014f72fc7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/graph7a.rb
@@ -0,0 +1,63 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/blt'
+
+file = File.join(File.dirname(File.expand_path(__FILE__)),
+ 'images', 'buckskin.gif')
+bgTexture = TkPhotoImage.new(:file=>file)
+
+TkOption.add('*Graph.Tile', bgTexture)
+TkOption.add('*Label.Tile', bgTexture)
+TkOption.add('*Frame.Tile', bgTexture)
+TkOption.add('*Htext.Tile', bgTexture)
+TkOption.add('*TileOffset', 0)
+TkOption.add('*HighlightThickness', 0)
+TkOption.add('*Element.ScaleSybols', false)
+TkOption.add('*Element.Smooth', :linear)
+TkOption.add('*activeLine.Color', 'yellow4')
+TkOption.add('*activeLine.Fill', 'yellow')
+TkOption.add('*activeLine.LineWidth', 0)
+TkOption.add('*Element.Pixels', 3)
+TkOption.add('*Graph.halo', '7i')
+
+if Tk.root.winfo_screenvisual != 'staticgray'
+ TkOption.add('*print.background', 'yellow')
+ TkOption.add('*quit.background', 'red')
+end
+
+length = 250000
+graph = Tk::BLT::Graph.new(:title=>"Scatter Plot\n#{length} points")
+graph.xaxis_configure(:loose=>false, :title=>'X Axis Label')
+graph.yaxis_configure(:title=>'Y Axis Label')
+graph.legend_configure(:activerelief=>:sunken, :background=>'')
+
+Tk::BLT::Table.add(Tk.root, graph, [0,0], :fill=>:both)
+
+v_x = Tk::BLT::Vector.new(length)
+v_y = Tk::BLT::Vector.new(length)
+v_x.expr("random(#{v_x})")
+v_y.expr("random(#{v_y})")
+v_x.sort(v_y)
+
+plot = Tk::BLT::PlotComponent::Element.new(graph, :symbol=>:square,
+ :color=>'green4', :fill=>'green2',
+ :linewidth=>0, :outlinewidth=>1,
+ :pixels=>4, :label=>'plot',
+ :xdata=>v_x, :ydata=>v_y)
+
+Tk.root.minsize(0, 0)
+
+#graph.zoom_stack
+#graph.crosshairs
+#graph.active_legend
+#graph.closest_point
+Tk::BLT.zoom_stack(graph)
+Tk::BLT.crosshairs(graph)
+Tk::BLT.active_legend(graph)
+Tk::BLT.closest_point(graph)
+
+Tk::BLT::Busy.hold(graph)
+Tk.update
+Tk::BLT::Busy.release(graph)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/graph7b.rb b/ext/tk/sample/tkextlib/blt/graph7b.rb
new file mode 100644
index 0000000000..c589f18d86
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/graph7b.rb
@@ -0,0 +1,41 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/blt'
+
+length = 250000
+graph = Tk::BLT::Graph.new(:title=>"Scatter Plot\n#{length} points")
+graph.xaxis_configure(:loose=>false, :title=>'X Axis Label')
+graph.yaxis_configure(:title=>'Y Axis Label')
+graph.legend_configure(:activerelief=>:sunken, :background=>'')
+
+Tk::BLT::Table.add(Tk.root, graph, [0,0], :fill=>:both)
+
+x = Array.new(length)
+y = Array.new(length)
+(0...length).each{|i|
+ x[i] = rand
+ y[i] = rand
+}
+
+plot = Tk::BLT::PlotComponent::Element.new(graph, :symbol=>:square,
+ :color=>'green4', :fill=>'green2',
+ :linewidth=>0, :outlinewidth=>1,
+ :pixels=>4, :label=>'plot',
+ :xdata=>x, :ydata=>y)
+
+Tk.root.minsize(0, 0)
+
+#graph.zoom_stack
+#graph.crosshairs
+#graph.active_legend
+#graph.closest_point
+Tk::BLT.zoom_stack(graph)
+Tk::BLT.crosshairs(graph)
+Tk::BLT.active_legend(graph)
+Tk::BLT.closest_point(graph)
+
+Tk::BLT::Busy.hold(graph)
+Tk.update
+Tk::BLT::Busy.release(graph)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/graph7c.rb b/ext/tk/sample/tkextlib/blt/graph7c.rb
new file mode 100644
index 0000000000..495b66f4af
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/graph7c.rb
@@ -0,0 +1,45 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/blt'
+
+length = 250000
+graph = Tk::BLT::Graph.new(:title=>"Scatter Plot\n#{length} points")
+graph.xaxis_configure(:loose=>false, :title=>'X Axis Label')
+graph.yaxis_configure(:title=>'Y Axis Label')
+graph.legend_configure(:activerelief=>:sunken, :background=>'')
+
+Tk::BLT::Table.add(Tk.root, graph, [0,0], :fill=>:both)
+
+v_x = Tk::BLT::Vector.new(length)
+v_y = Tk::BLT::Vector.new(length)
+x = Array.new(length)
+y = Array.new(length)
+(0...length).each{|i|
+ x[i] = rand
+ y[i] = rand
+}
+v_x.set(x)
+v_y.set(y)
+
+plot = Tk::BLT::PlotComponent::Element.new(graph, :symbol=>:square,
+ :color=>'green4', :fill=>'green2',
+ :linewidth=>0, :outlinewidth=>1,
+ :pixels=>4, :label=>'plot',
+ :xdata=>v_x, :ydata=>v_y)
+
+Tk.root.minsize(0, 0)
+
+#graph.zoom_stack
+#graph.crosshairs
+#graph.active_legend
+#graph.closest_point
+Tk::BLT.zoom_stack(graph)
+Tk::BLT.crosshairs(graph)
+Tk::BLT.active_legend(graph)
+Tk::BLT.closest_point(graph)
+
+Tk::BLT::Busy.hold(graph)
+Tk.update
+Tk::BLT::Busy.release(graph)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/images/buckskin.gif b/ext/tk/sample/tkextlib/blt/images/buckskin.gif
new file mode 100644
index 0000000000..e2d7be9d62
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/images/buckskin.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/blt/images/chalk.gif b/ext/tk/sample/tkextlib/blt/images/chalk.gif
new file mode 100644
index 0000000000..30d29a7221
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/images/chalk.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/blt/images/qv100.t.gif b/ext/tk/sample/tkextlib/blt/images/qv100.t.gif
new file mode 100644
index 0000000000..1e738ee86b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/images/qv100.t.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/blt/images/rain.gif b/ext/tk/sample/tkextlib/blt/images/rain.gif
new file mode 100644
index 0000000000..d7bb417939
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/images/rain.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/blt/images/sample.gif b/ext/tk/sample/tkextlib/blt/images/sample.gif
new file mode 100644
index 0000000000..1d8a4010c3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/images/sample.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/blt/pareto.rb b/ext/tk/sample/tkextlib/blt/pareto.rb
new file mode 100644
index 0000000000..94d5f3f97f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/pareto.rb
@@ -0,0 +1,90 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/blt'
+
+# Example of a pareto chart.
+#
+# The pareto chart mixes line and bar elements in the same graph.
+# Each processing operating is represented by a bar element. The
+# total accumulated defects is displayed with a single line element.
+b = Tk::BLT::Barchart.new(:title=>'Defects Found During Inspection',
+ :font=>'Helvetica 12', :plotpady=>[12, 4],
+ :width=>'6i', :height=>'5i')
+Tk::BLT::Table.add(Tk.root, b, :fill=>:both)
+
+data = [
+ ["Spot Weld", 82, 'yellow'],
+ ["Lathe", 49, 'orange'],
+ ["Gear Cut", 38, 'green'],
+ ["Drill", 24, 'blue'],
+ ["Grind", 17, 'red'],
+ ["Lapping", 12, 'brown'],
+ ["Press", 8, 'purple'],
+ ["De-burr", 4, 'pink'],
+ ["Packaging", 3, 'cyan'],
+ ["Other", 12, 'magenta']
+]
+
+# Create an X-Y graph line element to trace the accumulated defects.
+b.line_create('accum', :label=>'', :symbol=>:none, :color=>'red')
+
+# Define a bitmap to be used to stipple the background of each bar.
+pattern1 = Tk::BLT::Bitmap.define([ [4, 4], [1, 2, 4, 8] ])
+
+# For each process, create a bar element to display the magnitude.
+count = 0
+sum = 0
+ydata = [0]
+xdata = [0]
+labels = []
+
+data.each{|label, value, color|
+ count += 1
+ b.element_create(label, :xdata=>count, :ydata=>value, :foreground=>color,
+ :relief=>:solid, :borderwidth=>1, :stipple=>pattern1,
+ :background=>'lightblue')
+ labels[count] = label
+ # Get the total number of defects.
+ sum += value
+ ydata << sum
+ xdata << count
+}
+
+# Configure the coordinates of the accumulated defects,
+# now that we know what they are.
+b.element_configure('accum', :xdata=>xdata, :ydata=>ydata)
+
+# Add text markers to label the percentage of total at each point.
+xdata.zip(ydata){|x, y|
+ percent = (y * 100.0) / sum
+ if x == 0
+ text = ' 0%'
+ else
+ text = '%.1f' % percent
+ end
+ b.marker_create(:text, :coords=>[x, y], :text=>text, :font=>'Helvetica 10',
+ :foreground=>'red4', :anchor=>:center, :yoffset=>-5)
+}
+
+# Display an auxillary y-axis for percentages.
+b.axis_configure('y2', :hide=>false, :min=>0.0, :max=>100.0,
+ :title=>'Percentage')
+
+# Title the y-axis
+b.axis_configure('y', :title=>'Defects')
+
+# Configure the x-axis to display the process names, instead of numbers.
+b.axis_configure('x', :title=>'Process', :rotate=>90, :subdivisions=>0,
+ :command=>proc{|w, val|
+ val = val.round
+ labels[val]? labels[val]: val
+ })
+
+# No legend needed.
+b.legend_configure(:hide=>true)
+
+# Configure the grid lines.
+b.gridline_configure(:mapx=>:x, :color=>'lightblue')
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/plot1.rb b/ext/tk/sample/tkextlib/blt/plot1.rb
new file mode 100644
index 0000000000..07dff48292
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/plot1.rb
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/blt'
+
+graph = Tk::BLT::Graph.new.pack
+plot = Tk::BLT::PlotComponent::Element.new(graph, :linewidth=>0, :label=>'foo')
+plot.data([[1.0, 3.4], [1.1, 2.8], [1.2, 3.1], [1.4, 2.9]].flatten)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/plot1b.rb b/ext/tk/sample/tkextlib/blt/plot1b.rb
new file mode 100644
index 0000000000..eb41e361f9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/plot1b.rb
@@ -0,0 +1,10 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/blt'
+
+graph = Tk::BLT::Graph.new.pack
+plot = graph.element_create
+plot.configure(:linewidth=>0, :label=>'foo',
+ :data=>[[1.0, 3.4], [1.1, 2.8], [1.2, 3.1], [1.4, 2.9]].flatten)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/readme.txt b/ext/tk/sample/tkextlib/blt/readme.txt
new file mode 100644
index 0000000000..fe12dd88a3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/readme.txt
@@ -0,0 +1,2 @@
+The scripts and image files in this directory are based on demo files
+of Tcl/Tk's BLT extention.
diff --git a/ext/tk/sample/tkextlib/blt/scripts/stipples.rb b/ext/tk/sample/tkextlib/blt/scripts/stipples.rb
new file mode 100644
index 0000000000..47f3c4d063
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/scripts/stipples.rb
@@ -0,0 +1,156 @@
+$stipples = {} unless $stipples
+
+$stipples['bdiagonal1'] = Tk::BLT::Bitmap.new(<<EOD)
+#define bdiagonal1_width 8
+#define bdiagonal1_height 8
+static unsigned char bdiagonal1_bits[] = {
+ 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11};
+EOD
+
+$stipples['bdiagonal2'] = Tk::BLT::Bitmap.new(<<EOD)
+#define bdiagonal2_width 8
+#define bdiagonal2_height 8
+static unsigned char bdiagonal2_bits[] = {
+ 0x08, 0x04, 0x02, 0x01, 0x80, 0x40, 0x20, 0x10};
+EOD
+
+$stipples['checker2'] = Tk::BLT::Bitmap.new(<<EOD)
+#define checker2_width 8
+#define checker2_height 8
+static unsigned char checker2_bits[] = {
+ 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc};
+EOD
+
+
+$stipples['checker3'] = Tk::BLT::Bitmap.new(<<EOD)
+#define checker3_width 8
+#define checker3_height 8
+static unsigned char checker3_bits[] = {
+ 0x0f, 0x0f, 0x0f, 0x0f, 0xf0, 0xf0, 0xf0, 0xf0};
+EOD
+
+$stipples['cross1'] = Tk::BLT::Bitmap.new(<<EOD)
+#define cross1_width 8
+#define cross1_height 8
+static unsigned char cross_bits[] = {
+ 0xff, 0xaa, 0xff, 0xaa, 0xff, 0xaa, 0xff, 0xaa};
+EOD
+
+$stipples['cross2'] = Tk::BLT::Bitmap.new(<<EOD)
+#define cross2_width 8
+#define cross2_height 8
+static unsigned char cross2_bits[] = {
+ 0xff, 0x88, 0x88, 0x88, 0xff, 0x88, 0x88, 0x88};
+EOD
+
+$stipples['cross3'] = Tk::BLT::Bitmap.new(<<EOD)
+#define cross3_width 8
+#define cross3_height 8
+static unsigned char cross3_bits[] = {
+ 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+EOD
+
+$stipples['crossdiag'] = Tk::BLT::Bitmap.new(<<EOD)
+#define crossdiag_width 8
+#define crossdiag_height 8
+static unsigned char crossdiag2_bits[] = {
+ 0x18, 0x24, 0x42, 0x81, 0x81, 0x42, 0x24, 0x18};
+EOD
+
+$stipples['dot1'] = Tk::BLT::Bitmap.new(<<EOD)
+#define dot1_width 8
+#define dot1_height 8
+static unsigned char dot1_bits[] = {
+ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa};
+EOD
+
+$stipples['dot2'] = Tk::BLT::Bitmap.new(<<EOD)
+#define dot2_width 8
+#define dot2_height 8
+static unsigned char dot2_bits[] = {
+ 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00};
+EOD
+
+$stipples['dot3'] = Tk::BLT::Bitmap.new(<<EOD)
+#define dot3_width 8
+#define dot3_height 8
+static unsigned char dot3_bits[] = {
+ 0x11, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00};
+EOD
+
+$stipples['dot4'] = Tk::BLT::Bitmap.new(<<EOD)
+#define dot4_width 8
+#define dot4_height 8
+static unsigned char dot4_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+EOD
+
+$stipples['fdiagonal1'] = Tk::BLT::Bitmap.new(<<EOD)
+#define fdiagonal1_width 8
+#define fdiagonal1_height 8
+static unsigned char fdiagonal1_bits[] = {
+ 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88};
+EOD
+
+$stipples['fdiagonal2'] = Tk::BLT::Bitmap.new(<<EOD)
+#define fdiagonal2_width 8
+#define fdiagonal2_height 8
+static unsigned char fdiagonal2_bits[] = {
+ 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08};
+EOD
+
+$stipples['hline1'] = Tk::BLT::Bitmap.new(<<EOD)
+#define hline1_width 8
+#define hline1_height 8
+static unsigned char hline1_bits[] = {
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00};
+EOD
+
+$stipples['hline2'] = Tk::BLT::Bitmap.new(<<EOD)
+#define hline2_width 8
+#define hline2_height 8
+static unsigned char hline2_bits[] = {
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00};
+EOD
+
+$stipples['lbottom'] = Tk::BLT::Bitmap.new(<<EOD)
+#define lbottom_width 8
+#define lbottom_height 8
+static unsigned char lbottom_bits[] = {
+ 0x00, 0x11, 0x11, 0x77, 0x00, 0x11, 0x11, 0x77};
+EOD
+
+$stipples['ltop'] = Tk::BLT::Bitmap.new(<<EOD)
+#define ltop_width 8
+#define ltop_height 8
+static unsigned char ltop_bits[] = {
+ 0xee, 0x88, 0x88, 0x00, 0xee, 0x88, 0x88, 0x00};
+EOD
+
+$stipples['rbottom'] = Tk::BLT::Bitmap.new(<<EOD)
+#define rbottom_width 8
+#define rbottom_height 8
+static unsigned char rbottom_bits[] = {
+ 0x00, 0x88, 0x88, 0xee, 0x00, 0x88, 0x88, 0xee};
+EOD
+
+$stipples['rtop'] = Tk::BLT::Bitmap.new(<<EOD)
+#define rtop_width 8
+#define rtop_height 8
+static unsigned char rtop_bits[] = {
+ 0x77, 0x11, 0x11, 0x00, 0x77, 0x11, 0x11, 0x00};
+EOD
+
+$stipples['vline1'] = Tk::BLT::Bitmap.new(<<EOD)
+#define vline1_width 8
+#define vline1_height 8
+static unsigned char vline1_bits[] = {
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
+EOD
+
+$stipples['vline2'] = Tk::BLT::Bitmap.new(<<EOD)
+#define vline2_width 8
+#define vline2_height 8
+static unsigned char vline2_bits[] = {
+ 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33};
+EOD
diff --git a/ext/tk/sample/tkextlib/blt/winop1.rb b/ext/tk/sample/tkextlib/blt/winop1.rb
new file mode 100644
index 0000000000..e94138cd94
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/winop1.rb
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/blt'
+
+file = File.join(File.dirname(File.expand_path(__FILE__)),
+ 'images', 'sample.gif')
+if File.exist?(file)
+ src = TkPhotoImage.new(:file=>file)
+else
+ fail RuntimeError, 'no image file'
+end
+
+width = src.width
+height = src.height
+
+TkOption.add('*Label.font', '*helvetica*10*')
+TkOption.add('*Label.background', 'white')
+
+l_img0 = TkLabel.new(:image=>src)
+l_hdr0 = TkLabel.new(:text=>"#{width} x #{height}")
+l_ftr0 = TkLabel.new(:text=>'100%')
+Tk.root.background('white')
+
+(2..10).each{|i|
+ iw = width/i
+ ih = height/i
+ r = '%6g'%(100.0/i)
+ dst = TkPhotoImage.new(:width=>iw, :height=>ih)
+ Tk::BLT::Winop.image_resample(src, dst, :sinc)
+ l_hdr = TkLabel.new(:text=>"#{iw} x #{ih}")
+ l_ftr = TkLabel.new(:text=>"#{r}%")
+ l_img = TkLabel.new(:image=>dst)
+ Tk::BLT::Table.add(Tk.root,
+ [0,i], l_hdr,
+ [1,i], l_img,
+ [2,i], l_ftr)
+ Tk.update
+}
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/blt/winop2.rb b/ext/tk/sample/tkextlib/blt/winop2.rb
new file mode 100644
index 0000000000..1f674ee893
--- /dev/null
+++ b/ext/tk/sample/tkextlib/blt/winop2.rb
@@ -0,0 +1,28 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/blt'
+
+file = File.join(File.dirname(File.expand_path(__FILE__)),
+ 'images', 'qv100.t.gif')
+if File.exist?(file)
+ src = TkPhotoImage.new(:file=>file)
+else
+ fail RuntimeError, 'no image file'
+end
+
+width = src.width
+height = src.height
+
+TkOption.add('*Label.font', '*helvetica*10*')
+TkOption.add('*Label.background', 'white')
+
+[0, 90, 180, 270, 360, 45].each_with_index{|r, i|
+ dest = TkPhotoImage.new
+ Tk::BLT::Winop.image_rotate(src, dest, r)
+ l_txt = TkLabel.new(:text=>"#{r} degrees")
+ l_img = TkLabel.new(:image=>dest)
+ Tk::BLT::Table.add(Tk.root, [0,i], l_img, [1,i], l_txt)
+ Tk.update
+}
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/bwidget/Orig_LICENSE.txt b/ext/tk/sample/tkextlib/bwidget/Orig_LICENSE.txt
new file mode 100644
index 0000000000..0c4c16fe47
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/Orig_LICENSE.txt
@@ -0,0 +1,53 @@
+
+ ######################################################################
+ ### The following text is the original 'LICENSE.txt' of BWidget ###
+ ### extension. ###
+ ### Original Tcl source files are not include in this directry, ###
+ ### because of all of them are rewrited to Ruby files. ###
+ ### However, the bitmap data files ('bwidgtet.xbm' and 'x1.xbm') ###
+ ### included in this directory are quoted from BWidget source ###
+ ### archive. So, those bitmaps are under the following license. ###
+ ######################################################################
+
+
+BWidget ToolKit
+Copyright (c) 1998-1999 UNIFIX.
+Copyright (c) 2001-2002 ActiveState Corp.
+
+The following terms apply to all files associated with the software
+unless explicitly disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
diff --git a/ext/tk/sample/tkextlib/bwidget/basic.rb b/ext/tk/sample/tkextlib/bwidget/basic.rb
new file mode 100644
index 0000000000..c1521651fd
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/basic.rb
@@ -0,0 +1,198 @@
+#
+# basic demo --- called from demo.rb
+#
+unless Object.const_defined?('DemoVar')
+ fail RuntimeError, "This is NOT a stand alone script. This script is called from 'demo.rb'. "
+end
+
+module DemoBasic
+ @@var = TkVariable.new_hash
+ @@after = nil
+ @@count = 0
+
+ def self.create(nb)
+ frame = nb.insert('end', 'demoBasic', :text=>'Basic')
+ topf = TkFrame.new(frame)
+
+ titf1 = Tk::BWidget::TitleFrame.new(topf, :text=>'Label')
+ titf2 = Tk::BWidget::TitleFrame.new(topf, :text=>'Entry')
+
+ titf3 = Tk::BWidget::TitleFrame.new(frame, :text=>'Button and ArrowButton')
+
+ _label(titf1.get_frame)
+ _entry(titf2.get_frame)
+ _button(titf3.get_frame)
+
+ Tk.pack(titf1, titf2, :side=>:left, :fill=>:both, :padx=>4, :expand=>true)
+ topf.pack(:pady=>2, :fill=>:x)
+ titf3.pack(:pady=>2, :padx=>4, :fill=>:x)
+ end
+
+ def self._label(parent)
+ lab = Tk::BWidget::Label.new(parent, :text=>'This is a Label widget',
+ :helptext=>'Label widget')
+ chk = TkCheckbutton.new(parent, :text=>'Disabled',
+ :variable=>@@var.ref(lab, 'state'),
+ :onvalue=>'disabled', :offvalue=>'normal',
+ :command=>proc{lab[:state] = @@var[lab, 'state']})
+ lab.pack(:anchor=>:w, :pady=>4)
+ chk.pack(:anchor=>:w)
+ end
+
+ def self._entry(parent)
+ ent = Tk::BWidget::Entry.new(parent, :text=>'Press enter',
+ :helptext=>'Entry widtet',
+ :command=>proc{
+ @@var['entcmd'] = 'command called'
+ Tk.after(500, proc{@@var['entcmd'] = ''})
+ })
+
+ chk1 = TkCheckbutton.new(parent, :text=>'Disabled',
+ :variable=>@@var.ref(ent, 'state'),
+ :onvalue=>'disabled', :offvalue=>'normal',
+ :command=>proc{ent.state = @@var[ent, 'state']})
+
+ chk2 = TkCheckbutton.new(parent, :text=>'Non editable',
+ :variable=>@@var.ref(ent, 'editable'),
+ :onvalue=>false, :offvalue=>true,
+ :command=>proc{
+ ent.editable = @@var[ent, 'editable']
+ })
+
+ lab = TkLabel.new(parent, :textvariable=>@@var.ref('entcmd'),
+ :foreground=>'red')
+
+ ent.pack(:pady=>4, :anchor=>:w)
+ Tk.pack(chk1, chk2, :anchor=>:w)
+ lab.pack(:pady=>4)
+ end
+
+ def self._button(parent)
+ frame = TkFrame.new(parent)
+ but = Tk::BWidget::Button.new(frame, :text=>'Press me!',
+ :repeatdelay=>300,
+ :command=>proc{_butcmd('command')},
+ :helptext=>'This is a Button widget')
+
+ sep1 = Tk::BWidget::Separator.new(frame, :orient=>:vertical)
+ arr1 = Tk::BWidget::ArrowButton.new(frame, :type=>:button,
+ :width=>25, :height=>25, :repeatdelay=>300,
+ :command=>proc{_butcmd('command')},
+ :helptext=>"This is an ArrowButton widget\nof type button")
+
+ sep2 = Tk::BWidget::Separator.new(frame, :orient=>:vertical)
+ arr2 = Tk::BWidget::ArrowButton.new(frame, :type=>:arrow,
+ :width=>25, :height=>25, :relief=>:sunken,
+ :ipadx=>0, :ipady=>0, :repeatdelay=>300,
+ :command=>proc{_butcmd('command')},
+ :helptext=>"This is an ArrowButton widget\nof type arrow")
+
+ but.pack(:side=>:left, :padx=>4)
+ sep1.pack(:side=>:left, :padx=>4, :fill=>:y)
+ arr1.pack(:side=>:left, :padx=>4)
+ sep2.pack(:side=>:left, :padx=>4, :fill=>:y)
+ arr2.pack(:side=>:left, :padx=>4)
+ frame.pack
+
+ Tk::BWidget::Separator.new(parent,
+ :orient=>:horizontal).pack(:fill=>:x, :pady=>10)
+
+ labf1 = Tk::BWidget::LabelFrame.new(parent, :text=>'Command',
+ :side=>:top, :anchor=>:w,
+ :relief=>:sunken, :borderwidth=>1)
+ subf = labf1.get_frame
+ chk1 = TkCheckbutton.new(subf, :text=>'Disabled',
+ :variable=>@@var.ref('bstate'),
+ :onvalue=>'disabled', :offvalue=>'normal',
+ :command=>proc{_bstate(@@var['bstate'],
+ but, arr1, arr2)})
+ chk2 = TkCheckbutton.new(subf, :text=>"Use armcommand/\ndisarmcommand",
+ :variable=>@@var.ref('barmcmd'),
+ :command=>proc{_barmcmd(@@var['barmcmd'],
+ but, arr1, arr2)})
+ Tk.pack(chk1, chk2, :anchor=>:w)
+
+ label = TkLabel.new(parent, :textvariable=>@@var.ref('butcmd'),
+ :foreground=>'red').pack(:side=>:bottom, :pady=>4)
+
+ labf2 = Tk::BWidget::LabelFrame.new(parent, :text=>'Direction',
+ :side=>:top, :anchor=>:w,
+ :relief=>:sunken, :borderwidth=>1)
+ subf = labf2.get_frame
+ @@var['bside'] = :top
+ [:top, :left, :bottom, :right].each{|dir|
+ TkRadiobutton.new(subf, :text=>"#{dir} arrow",
+ :variable=>@@var.ref('bside'), :value=>dir,
+ :command=>proc{_bside(@@var['bside'], arr1, arr2)}
+ ).pack(:anchor=>:w)
+ }
+
+ labf3 = Tk::BWidget::LabelFrame.new(parent, :text=>'Relief',
+ :side=>:top, :anchor=>:w,
+ :relief=>:sunken, :borderwidth=>1)
+ subf = labf3.get_frame
+ @@var['brelief'] = :raised
+ [ %w(raised sunken ridge groove), %w(flat solid link)].each{|lrelief|
+ f = TkFrame.new(subf)
+ lrelief.each{|relief|
+ TkRadiobutton.new(f, :text=>relief,
+ :variable=>@@var.ref('brelief'), :value=>relief,
+ :command=>proc{
+ _brelief(@@var['brelief'], but, arr1, arr2)
+ }).pack(:anchor=>:w)
+ }
+ f.pack(:side=>:left, :padx=>2, :anchor=>:n)
+ }
+ Tk.pack(labf1, labf2, labf3, :side=>:left, :fill=>:y, :padx=>4)
+ end
+
+ def self._bstate(state, but, arr1, arr2)
+ [but, arr1, arr2].each{|b| b[:state] = state}
+ end
+
+ def self._brelief(relief, but, arr1, arr2)
+ but[:relief] = relief
+ if relief.to_s != 'link'
+ [arr1, arr2].each{|arr| arr[:relief] = relief}
+ end
+ end
+
+ def self._bside(side, *args)
+ args.each{|arr| arr[:dir] = side}
+ end
+
+ def self._barmcmd(value, but, arr1, arr2)
+ if TkComm.bool(value)
+ but.configure(:armcommand=>proc{_butcmd('arm')},
+ :disarmcommand=>proc{_butcmd('disarm')},
+ :command=>'')
+ [arr1, arr2].each{|arr|
+ arr.configure(:armcommand=>proc{_butcmd('arm')},
+ :disarmcommand=>proc{_butcmd('disarm')},
+ :command=>'')
+ }
+ else
+ but.configure(:armcommand=>'', :disarmcommand=>'',
+ :command=>proc{_butcmd('command')})
+ [arr1, arr2].each{|arr|
+ arr.configure(:armcommand=>'', :disarmcommand=>'',
+ :command=>proc{_butcmd('command')})
+ }
+ end
+ end
+
+ def self._butcmd(reason)
+ unless @@after
+ @@after = TkTimer.new(500, 1, proc{@@var['butcmd'] = ''})
+ end
+ @@after.stop
+ if (reason == 'arm')
+ @@count += 1
+ @@var['butcmd'] = "#{reason} command called (#{@@count})"
+ else
+ @@count = 0
+ @@var['butcmd'] = "#{reason} command called"
+ end
+ @@after.start
+ end
+end
diff --git a/ext/tk/sample/tkextlib/bwidget/bwidget.xbm b/ext/tk/sample/tkextlib/bwidget/bwidget.xbm
new file mode 100644
index 0000000000..5451ebb9c0
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/bwidget.xbm
@@ -0,0 +1,46 @@
+#define bwidget_width 76
+#define bwidget_height 64
+static char bwidget_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0x00,0xb6,0x6d,0xdb,0x16,0x00,0x00,0x00,0x00,0xf0,
+ 0x00,0xdb,0xb6,0x6d,0xab,0x00,0x00,0x00,0x00,0xf0,0x00,0x55,0x55,0x55,0x75,
+ 0x01,0x00,0x00,0x00,0xf0,0x00,0x6d,0xdb,0xb6,0xad,0x02,0x00,0x00,0x00,0xf0,
+ 0x00,0xb6,0x6d,0xdb,0xb6,0x05,0x00,0x00,0x00,0xf0,0x00,0x55,0x55,0x55,0x55,
+ 0x05,0x00,0x00,0x00,0xf0,0x00,0xda,0xb6,0xad,0x6d,0x0b,0x00,0x00,0x00,0xf0,
+ 0x00,0x6b,0x03,0xc0,0xb6,0x05,0x00,0x00,0x00,0xf0,0x00,0x56,0x05,0x00,0x55,
+ 0x0d,0x00,0x00,0x00,0xf0,0x00,0xbb,0x05,0x80,0xdb,0x06,0x00,0x00,0x00,0xf0,
+ 0x00,0xca,0x06,0x00,0x6c,0x0b,0x00,0x00,0x00,0xf0,0x00,0xb6,0x02,0x00,0xaa,
+ 0x0a,0x00,0x00,0x00,0xf0,0x00,0xab,0x05,0x00,0x6c,0x0b,0x00,0x00,0x00,0xf0,
+ 0x00,0xdd,0x06,0x00,0xb6,0x05,0x00,0x00,0x00,0xf0,0x00,0xaa,0x02,0x00,0x55,
+ 0x05,0x00,0x00,0x00,0xf0,0x00,0xb7,0x05,0xc0,0xda,0x02,0x00,0x00,0x00,0xf0,
+ 0x00,0xd9,0x06,0x50,0x6b,0x01,0x00,0x00,0x00,0xf0,0x00,0x56,0xb5,0xad,0xad,
+ 0x00,0x00,0x00,0x00,0xf0,0x00,0xdb,0xd6,0x76,0x15,0x00,0x00,0x00,0x00,0xf0,
+ 0x00,0x6a,0xab,0xaa,0x2d,0x00,0x00,0x00,0x00,0xf0,0x00,0x56,0x75,0xad,0xb6,
+ 0x02,0x00,0x00,0x00,0xf0,0x00,0xbb,0xad,0xd6,0xaa,0x05,0x00,0x00,0x00,0xf0,
+ 0x00,0xca,0xb6,0x6b,0xdb,0x2a,0x00,0x00,0x00,0xf0,0x00,0x77,0xd5,0x5c,0x6d,
+ 0x2d,0x00,0x00,0x00,0xf0,0x00,0x99,0x05,0x00,0xaa,0x56,0x00,0x00,0x00,0xf0,
+ 0x00,0xee,0x06,0x00,0x6c,0xbb,0x00,0x00,0x00,0xf0,0x00,0xaa,0x02,0x00,0xb0,
+ 0x55,0x00,0x00,0x00,0xf0,0x00,0x55,0x05,0x00,0xa8,0xd6,0x00,0x00,0x00,0xf0,
+ 0x00,0xee,0x06,0x00,0xd0,0x6a,0x00,0x00,0x00,0xf0,0x00,0x55,0x03,0x00,0x68,
+ 0xb7,0xfc,0x00,0x7e,0xf0,0x00,0x6d,0x05,0x00,0xa8,0xaa,0xfc,0x80,0x7e,0xf0,
+ 0x00,0xb6,0x05,0x00,0x50,0xbb,0xfe,0x01,0x7e,0xf0,0x00,0x55,0x05,0x00,0x78,
+ 0xad,0xfe,0x81,0x1f,0xf0,0x00,0xb6,0x05,0x00,0xa4,0xb5,0xfe,0x81,0x1f,0xf0,
+ 0x00,0x5b,0x05,0x80,0xba,0x56,0xfe,0x83,0x1f,0xf0,0x00,0xaa,0x6b,0x5b,0xd5,
+ 0x5a,0xff,0x85,0x1f,0xf0,0x00,0xdb,0x5a,0xad,0x57,0x2b,0xff,0xc7,0x0f,0xf0,
+ 0x00,0x6d,0xad,0xd5,0x6a,0x0d,0xff,0xc7,0x0f,0xf0,0x00,0xaa,0xd6,0xb6,0xba,
+ 0x05,0xdf,0xc7,0x0f,0xf0,0x00,0xb7,0xb5,0x5a,0xab,0x8a,0xdf,0xcf,0x0f,0xf0,
+ 0x00,0xd9,0x5a,0xab,0x6d,0x8f,0xcf,0xef,0x07,0xf0,0x00,0x56,0xad,0x75,0xb5,
+ 0xaf,0x8f,0xef,0x07,0xf0,0x00,0xb5,0xeb,0x5a,0x00,0x9f,0xcf,0xef,0x07,0xf0,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0x8f,0xff,0x07,0xf0,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0x87,0xff,0x03,0xf0,0x00,0x00,0x00,0x00,0x00,0xff,0x03,0xff,0x03,0xf0,
+ 0x00,0x00,0x00,0x00,0x00,0xfe,0x03,0xff,0x03,0xf0,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0x03,0xff,0x01,0xf0,0x00,0x00,0x00,0x00,0x00,0xfc,0x01,0xff,0x03,0xf0,
+ 0x00,0x00,0x00,0x00,0x00,0xfe,0x01,0xfe,0x01,0xf0,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x01,0xfe,0x01,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0};
diff --git a/ext/tk/sample/tkextlib/bwidget/demo.rb b/ext/tk/sample/tkextlib/bwidget/demo.rb
new file mode 100644
index 0000000000..785d2681a8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/demo.rb
@@ -0,0 +1,243 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/bwidget'
+
+module DemoVar
+ @_wfont = nil
+ @notebook = nil
+ @mainframe = nil
+ @status = TkVariable.new
+ @prgtext = TkVariable.new
+ @prgindic = TkVariable.new
+ @font = nil
+ @font_name = nil
+ @toolbar1 = TkVariable.new(true)
+ @toolbar2 = TkVariable.new(true)
+end
+class << DemoVar
+ attr_accessor :_wfont, :notebook, :mainframe, :font, :font_name
+ attr_reader :status, :prgtext, :prgindic, :toolbar1, :toolbar2
+end
+
+class BWidget_Demo
+ DEMODIR = File.dirname(File.expand_path(__FILE__))
+
+ %w(manager basic select dnd tree tmpldlg).each{|f|
+ require File.join(DEMODIR, f << '.rb')
+ }
+
+ def initialize
+ TkOption.add('*TitleFrame.l.font', 'helvetica 11 bold italic')
+
+ root = TkRoot.new(:title=>'BWidget demo')
+ root.withdraw
+
+ _create
+
+ Tk::BWidget.place(root, 0, 0, :center)
+ root.deiconify
+ root.raise
+ root.focus(true)
+
+ root.geometry(root.geometry)
+ end
+
+ def _create
+ DemoVar.prgtext.value = 'Please wait while loading font...'
+ DemoVar.prgindic.value = -1
+
+ intro = _create_intro
+
+ Tk.update
+
+ Tk::BWidget::SelectFont.load_font
+
+ descmenu = [
+ '&File', 'all', 'file', 0, [
+ ['command', 'E&xit', [], 'Exit BWidget demo', [],
+ {:command=>proc{exit}}]
+ ],
+ '&Options', 'all', 'options', 0, [
+ ['checkbutton', 'Toolbar &1', ['all', 'option'],
+ 'Show/hide toolbar 1', [],
+ { :variable=>DemoVar.toolbar1,
+ :command=>proc{
+ DemoVar.mainframe.show_toolbar(0, DemoVar.toolbar1.value)
+ }
+ }
+ ],
+ ['checkbutton', 'Toolbar &2', ['all', 'option'],
+ 'Show/hide toolbar 2', [],
+ { :variable=>DemoVar.toolbar2,
+ :command=>proc{
+ DemoVar.mainframe.show_toolbar(1, DemoVar.toolbar2.value)
+ }
+ }
+ ]
+ ]
+ ]
+
+ DemoVar.prgtext.value = 'Creating MainFrame...'
+ DemoVar.prgindic.value = 0
+
+ DemoVar.mainframe = Tk::BWidget::MainFrame.new(
+ :menu=>descmenu,
+ :textvariable=>DemoVar.status,
+ :progressvar=>DemoVar.prgindic
+ )
+
+ # toobar 1 creation
+ DemoVar.prgindic.numeric += 1
+
+ DemoVar.mainframe.add_toolbar{|tb1|
+ Tk::BWidget::ButtonBox.new(tb1, :spacing=>0, :padx=>1, :pady=>1){|bbox|
+ add(:image=>Tk::BWidget::Bitmap.new('new'),
+ :highlightthickness=>0, :takefocus=>0, :relief=>:link,
+ :borderwidth=>1, :padx=>1, :pady=>1,
+ :command=>proc{puts 'select "Create a new file" icon'},
+ :helptext=>"Create a new file")
+
+ add(:image=>Tk::BWidget::Bitmap.new('open'),
+ :highlightthickness=>0, :takefocus=>0, :relief=>:link,
+ :borderwidth=>1, :padx=>1, :pady=>1,
+ :command=>proc{puts 'select "Open an existing file" icon'},
+ :helptext=>"Open an existing file")
+
+ add(:image=>Tk::BWidget::Bitmap.new('save'),
+ :highlightthickness=>0, :takefocus=>0, :relief=>:link,
+ :borderwidth=>1, :padx=>1, :pady=>1,
+ :command=>proc{puts 'select "Save file" icon'},
+ :helptext=>"Save file")
+
+ pack(:side=>:left, :anchor=>:w)
+ }
+
+ Tk::BWidget::Separator.new(tb1, :orient=>:vertical){
+ pack(:side=>:left, :fill=>:y, :padx=>4, :anchor=>:w)
+ }
+
+ DemoVar.prgindic.numeric += 1
+
+ Tk::BWidget::ButtonBox.new(tb1, :spacing=>0, :padx=>1, :pady=>1){|bbox|
+ add(:image=>Tk::BWidget::Bitmap.new('cut'),
+ :highlightthickness=>0, :takefocus=>0, :relief=>:link,
+ :borderwidth=>1, :padx=>1, :pady=>1,
+ :command=>proc{puts 'select "Cut selection" icon'},
+ :helptext=>"Cut selection")
+
+ add(:image=>Tk::BWidget::Bitmap.new('copy'),
+ :highlightthickness=>0, :takefocus=>0, :relief=>:link,
+ :borderwidth=>1, :padx=>1, :pady=>1,
+ :command=>proc{puts 'select "Copy selection" icon'},
+ :helptext=>"Copy selection")
+
+ add(:image=>Tk::BWidget::Bitmap.new('paste'),
+ :highlightthickness=>0, :takefocus=>0, :relief=>:link,
+ :borderwidth=>1, :padx=>1, :pady=>1,
+ :command=>proc{puts 'select "Paste selection" icon'},
+ :helptext=>"Paste selection")
+
+ pack(:side=>:left, :anchor=>:w)
+ }
+ }
+
+ # toolbar 2 creation
+ DemoVar.prgindic.numeric += 1
+
+ tb2 = DemoVar.mainframe.add_toolbar
+ DemoVar._wfont = Tk::BWidget::SelectFont::Toolbar.new(tb2,
+ :command=>proc{update_font(DemoVar._wfont[:font])}
+ )
+ DemoVar.font = DemoVar._wfont[:font]
+ DemoVar._wfont.pack(:side=>:left, :anchor=>:w)
+
+ DemoVar.mainframe.add_indicator(
+ :text=>"BWidget #{Tk::BWidget.package_version}"
+ )
+ DemoVar.mainframe.add_indicator(:textvariable=>'tk_patchLevel')
+
+ # NoteBook creation
+ DemoVar.notebook = Tk::BWidget::NoteBook.new(DemoVar.mainframe.get_frame)
+
+ DemoVar.prgtext.value = "Creating Manager..."
+ DemoVar.prgindic.numeric += 1
+ DemoManager.create(DemoVar.notebook)
+
+ DemoVar.prgtext.value = "Creating Basic..."
+ DemoVar.prgindic.numeric += 1
+ DemoBasic.create(DemoVar.notebook)
+
+ DemoVar.prgtext.value = "Creating Select..."
+ DemoVar.prgindic.numeric += 1
+ DemoSelect.create(DemoVar.notebook)
+
+ DemoVar.prgtext.value = "Creating Dialog..."
+ DemoVar.prgindic.numeric += 1
+ DemoDialog.create(DemoVar.notebook)
+
+ DemoVar.prgtext.value = "Creating Drag and Drop..."
+ DemoVar.prgindic.numeric += 1
+ DemoDnD.create(DemoVar.notebook)
+
+ DemoVar.prgtext.value = "Creating Tree..."
+ DemoVar.prgindic.numeric += 1
+ DemoTree.create(DemoVar.notebook)
+
+ DemoVar.prgtext.value = "Done"
+ DemoVar.prgindic.numeric += 1
+
+ DemoVar.notebook.compute_size
+ DemoVar.notebook.pack(:fill=>:both, :expand=>true, :padx=>4, :pady=>4)
+ DemoVar.notebook.raise(DemoVar.notebook.get_page(0))
+
+ DemoVar.mainframe.pack(:fill=>:both, :expand=>true)
+
+ Tk.update_idletasks
+
+ intro.destroy
+ end
+
+ def update_font(newfont)
+ root = Tk.root
+ root[:cursor] = 'watch'
+ if newfont != '' && DemoVar.font != newfont
+ DemoVar._wfont[:font] = newfont
+ DemoVar.notebook[:font] = newfont
+ DemoVar.font = newfont
+ end
+ root[:cursor] = ''
+ end
+
+ def _create_intro
+ top = TkToplevel.new(:relief=>:raised, :borderwidth=>2)
+ top.withdraw
+ top.overrideredirect(true)
+
+ ximg = TkLabel.new(top, :bitmap=>"@#{File.join(DEMODIR,'x1.xbm')}",
+ :foreground=>'grey90', :background=>'white')
+ bwimg = TkLabel.new(ximg, :bitmap=>"@#{File.join(DEMODIR,'bwidget.xbm')}",
+ :foreground=>'grey90', :background=>'white')
+ frame = TkFrame.new(ximg, :background=>'white')
+ TkLabel.new(frame, :text=>'Loading demo',
+ :background=>'white', :font=>'times 8').pack
+ TkLabel.new(frame, :textvariable=>DemoVar.prgtext,
+ :background=>'white', :font=>'times 8', :width=>35).pack
+ Tk::BWidget::ProgressBar.new(frame, :width=>50, :height=>10,
+ :background=>'white',
+ :variable=>DemoVar.prgindic,
+ :maximum=>10).pack
+ frame.place(:x=>0, :y=>0, :anchor=>:nw)
+ bwimg.place(:relx=>1, :rely=>1, :anchor=>:se)
+ ximg.pack
+ Tk::BWidget.place(top, 0, 0, :center)
+ top.deiconify
+
+ top
+ end
+end
+
+module DemoVar
+ Demo = BWidget_Demo.new
+end
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/bwidget/dnd.rb b/ext/tk/sample/tkextlib/bwidget/dnd.rb
new file mode 100644
index 0000000000..1c8b036530
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/dnd.rb
@@ -0,0 +1,46 @@
+#
+# dnd demo --- called from demo.rb
+#
+unless Object.const_defined?('DemoVar')
+ fail RuntimeError, "This is NOT a stand alone script. This script is called from 'demo.rb'. "
+end
+
+module DemoDnD
+ def self.create(nb)
+ frame = nb.insert('end', 'demoDnD', :text=>'Drag and Drop')
+
+ titf1 = Tk::BWidget::TitleFrame.new(frame, :text=>'Drag source')
+ subf = titf1.get_frame
+
+ ent1 = Tk::BWidget::LabelEntry.new(subf, :label=>'Entry',
+ :labelwidth=>14, :dragenabled=>true,
+ :dragevent=>3)
+ labf1 = Tk::BWidget::LabelFrame.new(subf, :text=>'Label (text)',
+ :width=>14)
+ f = labf1.get_frame
+ lab = Tk::BWidget::Label.new(f, :text=>'Drag this text',
+ :dragenabled=>true, :dragevent=>3).pack
+
+ labf2 = Tk::BWidget::LabelFrame.new(subf, :text=>'Label (bitmap)',
+ :width=>14)
+ f = labf2.get_frame
+ lab = Tk::BWidget::Label.new(f, :bitmap=>'info',
+ :dragenabled=>true, :dragevent=>3).pack
+
+ Tk.pack(ent1, labf1, labf2, :side=>:top, :fill=>:x, :pady=>4)
+
+ titf2 = Tk::BWidget::TitleFrame.new(frame, :text=>'Drop targets')
+ subf = titf2.get_frame
+
+ ent1 = Tk::BWidget::LabelEntry.new(subf, :label=>'Entry',
+ :labelwidth=>14, :dropenabled=>true)
+ labf1 = Tk::BWidget::LabelFrame.new(subf, :text=>'Label', :width=>14)
+ f = labf1.get_frame
+ lab = Tk::BWidget::Label.new(f, :dropenabled=>true,
+ :highlightthickness=>1).pack(:fill=>:x)
+ Tk.pack(ent1, labf1, :side=>:top, :fill=>:x, :pady=>4)
+ Tk.pack(titf1, titf2, :pady=>4)
+
+ frame
+ end
+end
diff --git a/ext/tk/sample/tkextlib/bwidget/manager.rb b/ext/tk/sample/tkextlib/bwidget/manager.rb
new file mode 100644
index 0000000000..776cb3065b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/manager.rb
@@ -0,0 +1,150 @@
+#
+# manager demo --- called from demo.rb
+#
+unless Object.const_defined?('DemoVar')
+ fail RuntimeError, "This is NOT a stand alone script. This script is called from 'demo.rb'. "
+end
+
+module DemoManager
+ @@progress = TkVariable.new(false)
+ @@status = TkVariable.new('Compute in progress...')
+ @@homogeneous = TkVariable.new(false)
+ @@constw = TkVariable.new
+ @@afterobj = nil
+
+ def self.create(nb)
+ frame = nb.insert('end', 'demoManager', :text=>'Manager')
+
+ topf = TkFrame.new(frame)
+ titf1 = Tk::BWidget::TitleFrame.new(topf, :text=>"MainFrame")
+ titf2 = Tk::BWidget::TitleFrame.new(topf, :text=>"NoteBook")
+ titf3 = Tk::BWidget::TitleFrame.new(frame, :text=>"Paned & ScrolledWindow")
+
+ _mainframe(titf1.get_frame)
+ _notebook(titf2.get_frame)
+ _paned(titf3.get_frame)
+
+ Tk.pack(titf1, titf2, :padx=>4, :side=>:left, :fill=>:both, :expand=>true)
+ Tk.pack(topf, :fill=>:x, :pady=>2)
+ Tk.pack(titf3, :pady=>2, :padx=>4, :fill=>:both, :expand=>true)
+
+ frame
+ end
+
+ def self._mainframe(parent)
+ labf1 = Tk::BWidget::LabelFrame.new(parent, :text=>'Toolbar',
+ :side=>:top, :anchor=>:w,
+ :relief=>:sunken, :borderwidth=>2)
+ subf = labf1.get_frame
+ chk1 = TkCheckbutton.new(subf, :text=>'View toolbar 1',
+ :variable=>DemoVar.toolbar1,
+ :command=>proc{
+ DemoVar.mainframe.show_toolbar(
+ 0, DemoVar.toolbar1.value
+ )
+ })
+ chk2 = TkCheckbutton.new(subf, :text=>'View toolbar 2',
+ :variable=>DemoVar.toolbar2,
+ :command=>proc{
+ DemoVar.mainframe.show_toolbar(
+ 1, DemoVar.toolbar2.value
+ )
+ })
+
+ Tk.pack(chk1, chk2, :anchor=>:w, :fill=>:x)
+ labf1.pack(:fill=>:both)
+
+ labf2 = Tk::BWidget::LabelFrame.new(parent, :text=>'Status bar',
+ :side=>:top, :anchor=>:w,
+ :relief=>:sunken, :borderwidth=>2)
+ subf = labf2.get_frame
+ chk1 = TkCheckbutton.new(subf, :text=>"Show Progress\nindicator",
+ :justify=>:left, :variable=>@@progress,
+ :command=>proc{ _show_progress })
+ chk1.pack(:anchor=>:w, :fill=>:x)
+
+ Tk.pack(labf1, labf2, :side=>:left, :padx=>4, :fill=>:both)
+ end
+
+ def self._notebook(parent)
+ TkCheckbutton.new(parent, :text=>'Homogeneous label',
+ :variable=>@@homogeneous,
+ :command=>proc{
+ DemoVar.notebook[:homogeneous] = @@homogeneous.value
+ }).pack(:side=>:left, :anchor=>:n, :fill=>:x)
+ end
+
+ def self._paned(parent)
+ pw1 = Tk::BWidget::PanedWindow.new(parent, :side=>:top)
+ pane = pw1.add(:minsize=>100)
+
+ pw2 = Tk::BWidget::PanedWindow.new(pane, :side=>:left)
+ pane1 = pw2.add(:minsize=>100)
+ pane2 = pw2.add(:minsize=>100)
+
+ pane3 = pw1.add(:minsize=>100)
+
+ [pane1, pane2].each{|pane|
+ sw = Tk::BWidget::ScrolledWindow.new(pane)
+ lb = TkListbox.new(sw, :height=>8, :width=>20, :highlightthickness=>0)
+ (1..8).each{|i| lb.insert('end', "Valur #{i}") }
+ sw.set_widget(lb)
+ sw.pack(:fill=>:both, :expand=>true)
+ }
+
+ sw = Tk::BWidget::ScrolledWindow.new(pane3, :relief=>:sunken,
+ :borderwidth=>2)
+ sf = Tk::BWidget::ScrollableFrame.new(sw)
+ sw.set_widget(sf)
+ subf = sf.get_frame
+ lab = TkLabel.new(subf, :text=>'This is a ScrollableFrame')
+ chk = TkCheckbutton.new(subf, :text=>'Constrained with',
+ :variable=>@@constw, :command=>proc{
+ sf['constrainedwidth'] = @@constw.value
+ })
+ lab.pack
+ chk.pack(:anchor=>:w)
+ chk.bind('FocusIn', proc{sf.see(chk)})
+ (0..20).each{|i|
+ ent = TkEntry.new(subf, :width=>50).pack(:fill=>:x, :pady=>4)
+ ent.bind('FocusIn', proc{sf.see(ent)})
+ ent.insert('end', "Text field #{i}")
+ }
+
+ Tk.pack(sw, pw2, pw1, :fill=>:both, :expand=>true)
+ end
+
+ def self._show_progress
+ unless @@afterobj
+ @@afterobj = TkTimer.new(30, -1, proc{_update_progress})
+ end
+ if @@progress.bool
+ DemoVar.status.value = 'Compute in progress...'
+ DemoVar.prgindic.value = 0
+ DemoVar.mainframe.show_statusbar(:progression)
+ @@afterobj.start unless @@afterobj.running?
+ else
+ DemoVar.status.value = ''
+ DemoVar.mainframe.show_statusbar(:status)
+ @@afterobj.stop
+ end
+ end
+
+ def self._update_progress
+ if @@progress.bool
+ if DemoVar.prgindic.numeric < 100
+ DemoVar.prgindic.numeric += 5
+ else
+ @@progress.value = false
+ DemoVar.mainframe.show_statusbar(:status)
+ DemoVar.status.value = 'Done'
+ @@afterobj.stop
+ Tk.after(500, proc{ DemoVar.status.value = '' })
+ end
+ else
+ @@afterobj.stop
+ end
+ end
+
+end
+
diff --git a/ext/tk/sample/tkextlib/bwidget/select.rb b/ext/tk/sample/tkextlib/bwidget/select.rb
new file mode 100644
index 0000000000..ea24b47e2e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/select.rb
@@ -0,0 +1,82 @@
+#
+# select demo --- called from demo.rb
+#
+unless Object.const_defined?('DemoVar')
+ fail RuntimeError, "This is NOT a stand alone script. This script is called from 'demo.rb'. "
+end
+
+module DemoSelect
+ @@var = TkVariable.new_hash
+
+ def self.create(nb)
+ frame = nb.insert('end', 'demoSelect', :text=>'Spin & Combo')
+
+ titf1 = Tk::BWidget::TitleFrame.new(frame, :text=>'SpinBox')
+ subf = titf1.get_frame
+ spin = Tk::BWidget::SpinBox.new(subf, :range=>[1, 100, 1],
+ :textvariable=>@@var.ref('spin', 'var'),
+ :helptext=>'This is the SpinBox')
+ ent = Tk::BWidget::LabelEntry.new(subf, :label=>'Linked var',
+ :labelwidth=>10, :labelanchor=>:w,
+ :textvariable=>@@var.ref('spin', 'var'),
+ :editable=>0,
+ :helptext=>"This is an Entry reflecting\nthe linked var of SpinBox")
+ labf = Tk::BWidget::LabelFrame.new(subf, :text=>'Options',
+ :side=>:top, :anchor=>:w,
+ :relief=>:sunken, :borderwidth=>1,
+ :helptext=>'Modify some options of SpinBox')
+ subf = labf.get_frame
+ chk1 = TkCheckbutton.new(subf, :text=>'Non editable',
+ :variable=>@@var.ref('spin', 'editable'),
+ :onvalue=>false, :offvalue=>true,
+ :command=>proc{
+ spin.editable(@@var['spin', 'editable'])
+ })
+ chk2 = TkCheckbutton.new(subf, :text=>'Disabled',
+ :variable=>@@var.ref('spin', 'state'),
+ :onvalue=>'disabled', :offvalue=>'normal',
+ :command=>proc{
+ spin.state(@@var['spin', 'state'])
+ })
+ Tk.pack(chk1, chk2, :side=>:left, :anchor=>:w)
+ Tk.pack(spin, ent, labf, :pady=>4, :fill=>:x)
+ titf1.pack
+
+ titf2 = Tk::BWidget::TitleFrame.new(frame, :text=>'ComboBox')
+ subf = titf2.get_frame
+ combo = Tk::BWidget::ComboBox.new(subf,
+ :textvariable=>@@var.ref('combo', 'var'),
+ :values=>[
+ 'first value', 'second value',
+ 'third value', 'fourth value',
+ 'fifth value'
+ ],
+ :helptext=>'This is the ComboBox')
+ ent = Tk::BWidget::LabelEntry.new(subf, :label=>'Linked var',
+ :labelwidth=>10, :labelanchor=>:w,
+ :textvariable=>@@var.ref('combo', 'var'),
+ :editable=>0, :helptext=>"This is an Entry reflecting\nthe linked var of ComboBox")
+ labf = Tk::BWidget::LabelFrame.new(subf, :text=>'Options', :side=>:top,
+ :anchor=>:w, :relief=>:sunken,
+ :borderwidth=>1, :helptext=>'Modify some options of ComboBox')
+ subf = labf.get_frame
+ chk1 = TkCheckbutton.new(subf, :text=>'Non editable',
+ :variable=>@@var.ref('combo', 'editable'),
+ :onvalue=>false, :offvalue=>true,
+ :command=>proc{
+ combo.editable(@@var['combo', 'editable'])
+ })
+ chk2 = TkCheckbutton.new(subf, :text=>'Disabled',
+ :variable=>@@var.ref('combo', 'state'),
+ :onvalue=>'disabled', :offvalue=>'normal',
+ :command=>proc{
+ combo.state(@@var['combo', 'state'])
+ })
+
+ Tk.pack(chk1, chk2, :side=>:left, :anchor=>:w)
+ Tk.pack(combo, ent, labf, :pady=>4, :fill=>:x)
+ Tk.pack(titf1, titf2, :pady=>4)
+
+ frame
+ end
+end
diff --git a/ext/tk/sample/tkextlib/bwidget/tmpldlg.rb b/ext/tk/sample/tkextlib/bwidget/tmpldlg.rb
new file mode 100644
index 0000000000..3d19c8d092
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/tmpldlg.rb
@@ -0,0 +1,221 @@
+#
+# templdlg demo --- called from demo.rb
+#
+unless Object.const_defined?('DemoVar')
+ fail RuntimeError, "This is NOT a stand alone script. This script is called from 'demo.rb'. "
+end
+
+module DemoDialog
+ @@tmpl = TkVariable.new_hash
+ @@msg = TkVariable.new_hash
+ @@msgdlg = nil
+ @@progmsg = TkVariable.new
+ @@progval = TkVariable.new
+ @@progdlg = nil
+ @@resources = TkVariable.new('en')
+
+ def self.create(nb)
+ frame = nb.insert('end', 'demoDlg', :text=>'Dialog')
+
+ titf1 = Tk::BWidget::TitleFrame.new(frame, :text=>'Resources')
+ titf2 = Tk::BWidget::TitleFrame.new(frame, :text=>'Template Dialog')
+ titf3 = Tk::BWidget::TitleFrame.new(frame, :text=>'Message Dialog')
+ titf4 = Tk::BWidget::TitleFrame.new(frame, :text=>'Other dialog')
+
+ subf = titf1.get_frame
+ cmd = proc{ TkOption.read_file(File.join(Tk::BWidget::LIBRARY, 'lang',
+ @@resources.value + '.rc')) }
+ Tk.pack(TkRadiobutton.new(subf, :text=>'English', :value=>'en',
+ :variable=>@@resources, :command=>cmd),
+ TkRadiobutton.new(subf, :text=>'French', :value=>'fr',
+ :variable=>@@resources, :command=>cmd),
+ TkRadiobutton.new(subf, :text=>'German', :value=>'de',
+ :variable=>@@resources, :command=>cmd),
+ :side=>:left)
+
+ _tmpldlg(titf2.get_frame)
+ _msgdlg(titf3.get_frame)
+ _stddlg(titf4.get_frame)
+
+ titf1.pack(:fill=>:x, :pady=>2, :padx=>2)
+ titf4.pack(:side=>:bottom, :fill=>:x, :pady=>2, :padx=>2)
+ Tk.pack(titf2, titf3, :side=>:left, :padx=>2, :fill=>:both, :expand=>true)
+ end
+
+ def self._tmpldlg(parent)
+ @@tmpl['side'] = :bottom
+ @@tmpl['anchor'] = :c
+
+ labf1 = Tk::BWidget::LabelFrame.new(parent, :text=>'Button side',
+ :side=>:top, :anchor=>:w,
+ :relief=>:sunken, :borderwidth=>1)
+ subf = labf1.get_frame
+ Tk.pack(TkRadiobutton.new(subf, :text=>'Bottom', :value=>:bottom,
+ :variable=>@@tmpl.ref('side'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Left', :value=>:left,
+ :variable=>@@tmpl.ref('side'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Right', :value=>:right,
+ :variable=>@@tmpl.ref('side'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Top', :value=>:top,
+ :variable=>@@tmpl.ref('side'), :anchor=>:w),
+ :fill=>:x, :anchor=>:w)
+
+ labf2 = Tk::BWidget::LabelFrame.new(parent, :text=>'Button anchor',
+ :side=>:top, :anchor=>:w,
+ :relief=>:sunken, :borderwidth=>1)
+ subf = labf2.get_frame
+ Tk.pack(TkRadiobutton.new(subf, :text=>'North', :value=>:n,
+ :variable=>@@tmpl.ref('anchor'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'West', :value=>:w,
+ :variable=>@@tmpl.ref('anchor'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'East', :value=>:e,
+ :variable=>@@tmpl.ref('anchor'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'South', :value=>:s,
+ :variable=>@@tmpl.ref('anchor'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Center', :value=>:c,
+ :variable=>@@tmpl.ref('anchor'), :anchor=>:w),
+ :fill=>:x, :anchor=>:w)
+
+ sep = Tk::BWidget::Separator.new(parent, :orient=>:horizontal)
+ button = TkButton.new(parent, :text=>'Show', :command=>proc{_show_tmpldlg})
+
+ button.pack(:side=>:bottom)
+ sep.pack(:side=>:bottom, :fill=>:x, :pady=>10)
+ Tk.pack(labf1, labf2, :side=>:left, :padx=>4, :anchor=>:n)
+ end
+
+ def self._msgdlg(parent)
+ @@msg['type'] = 'ok'
+ @@msg['icon'] = 'info'
+
+ labf1 = Tk::BWidget::LabelFrame.new(parent, :text=>'Type', :side=>:top,
+ :anchor=>:w, :relief=>:sunken,
+ :borderwidth=>1)
+ subf = labf1.get_frame
+ Tk.pack(TkRadiobutton.new(subf, :text=>'Ok', :value=>'ok',
+ :variable=>@@msg.ref('type'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Ok, Cancel', :value=>'okcancel',
+ :variable=>@@msg.ref('type'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Retry, Cancel',
+ :value=>'retrycancel',
+ :variable=>@@msg.ref('type'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Yes, No', :value=>'yesno',
+ :variable=>@@msg.ref('type'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Yes, No, Cancel',
+ :value=>'yesnocancel',
+ :variable=>@@msg.ref('type'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Abort, Retry, Ignore',
+ :value=>'abortretryignore',
+ :variable=>@@msg.ref('type'), :anchor=>:w),
+ :fill=>:x, :anchor=>:w)
+
+ Tk.pack(TkRadiobutton.new(subf, :text=>'User', :value=>'user',
+ :variable=>@@msg.ref('type'), :anchor=>:w),
+ Tk::BWidget::Entry.new(subf, :textvariable=>@@msg.ref('buttons')),
+ :side=>:left)
+
+ labf2 = Tk::BWidget::LabelFrame.new(parent, :text=>'Icon', :side=>:top,
+ :anchor=>:w, :relief=>:sunken,
+ :borderwidth=>1)
+ subf = labf2.get_frame
+ Tk.pack(TkRadiobutton.new(subf, :text=>'Information', :value=>'info',
+ :variable=>@@msg.ref('icon'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Question', :value=>'question',
+ :variable=>@@msg.ref('icon'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Warning', :value=>'warning',
+ :variable=>@@msg.ref('icon'), :anchor=>:w),
+ TkRadiobutton.new(subf, :text=>'Error', :value=>'error',
+ :variable=>@@msg.ref('icon'), :anchor=>:w),
+ :fill=>:x, :anchor=>:w)
+
+ sep = Tk::BWidget::Separator.new(parent, :orient=>:horizontal)
+ button = TkButton.new(parent, :text=>'Show', :command=>proc{_show_msgdlg})
+
+ button.pack(:side=>:bottom)
+ sep.pack(:side=>:bottom, :fill=>:x, :pady=>10)
+ Tk.pack(labf1, labf2, :side=>:left, :padx=>4, :anchor=>:n)
+ end
+
+ def self._stddlg(parent)
+ Tk.pack(TkButton.new(parent, :text=>'Select a color '){|w|
+ command(proc{DemoDialog._show_color(w)})
+ },
+ TkButton.new(parent, :text=>'Font selector dialog',
+ :command=>proc{_show_fontdlg}),
+ TkButton.new(parent, :text=>'Progression dialog',
+ :command=>proc{_show_progdlg}),
+ TkButton.new(parent, :text=>'Password dialog',
+ :command=>proc{_show_passdlg}),
+ :side=>:left, :padx=>5, :anchor=>:w)
+ end
+
+ def self._show_color(w)
+ dlg = Tk::BWidget::SelectColor.new(w, :color=>w.background)
+ color = dlg.menu([:below, w])
+ unless color.empty?
+ w.background(color)
+ end
+ end
+
+ def self._show_tmpldlg
+ dlg = Tk::BWidget::Dialog.new(:relative=>Tk.root, :modal=>:local,
+ :separator=>true, :title=>'Template dialog',
+ :side=>@@tmpl['side'],
+ :anchor=>@@tmpl['anchor'],
+ :default=>0, :cancel=>1)
+ dlg.add('name'=>'ok')
+ dlg.add('name'=>'cancel')
+ TkMessage.new(dlg.get_frame, :text=>"Template\nDialog", :justify=>:center,
+ :anchor=>:c, :width=>80).pack(:fill=>:both, :expand=>true,
+ :padx=>100, :pady=>100)
+ dlg.draw
+ dlg.destroy
+ end
+
+ def self._show_msgdlg
+ @@msgdlg.destroy if @@msgdlg
+ @@msgdlg = Tk::BWidget::MessageDlg.new(:relative=>Tk.root,
+ :message=>'Message for MessageBox',
+ :type=>@@msg['type'],
+ :icon=>@@msg['icon'],
+ :buttons=>@@msg['buttons'])
+ @@msgdlg.create
+ end
+
+ def self._show_fontdlg
+ font = Tk::BWidget::SelectFont.new(:relative=>Tk.root,
+ :font=>DemoVar.font).create
+ DemoVar::Demo.update_font(font)
+ end
+
+ def self._show_progdlg
+ @@progmsg.value = "Compute in progress..."
+ @@progval.value = 0
+
+ @@progdlg = Tk::BWidget::ProgressDlg.new(:relative=>Tk.root,
+ :title=>'Wait...',
+ :type=>'infinite', :width=>20,
+ :textvariable=>@@progmsg,
+ :variable=>@@progval,
+ :stop=>'Stop') {
+ command(proc{self.destroy})
+ create
+ }
+ _update_progdlg
+ end
+
+ def self._update_progdlg
+ TkTimer.new(20, -1, proc{
+ if @@progdlg && @@progdlg.winfo_exist?
+ @@progval.value = 2
+ else
+ stop
+ end
+ }).start
+ end
+
+ def self._show_passdlg
+ Tk::BWidget::PasswdDlg.new(:relative=>Tk.root).create
+ end
+end
+
diff --git a/ext/tk/sample/tkextlib/bwidget/tree.rb b/ext/tk/sample/tkextlib/bwidget/tree.rb
new file mode 100644
index 0000000000..e1fcaa774f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/tree.rb
@@ -0,0 +1,289 @@
+#
+# templdlg demo --- called from demo.rb
+#
+unless Object.const_defined?('DemoVar')
+ fail RuntimeError, "This is NOT a stand alone script. This script is called from 'demo.rb'. "
+end
+
+module DemoTree
+ @@count = 0
+ @@dblclick = false
+ @@top = nil
+
+ def self.create(nb)
+ frame = nb.insert('end', 'demoTree', :text=>'Tree')
+ pw = Tk::BWidget::PanedWindow.new(frame, :side=>:top)
+
+ pane = pw.add(:weight=>1)
+ title = Tk::BWidget::TitleFrame.new(pane, :text=>'Directory tree')
+ sw = Tk::BWidget::ScrolledWindow.new(title.get_frame,
+ :relief=>:sunken, :borderwidth=>2)
+ tree = Tk::BWidget::Tree.new(sw, :relief=>:flat, :borderwidth=>0,
+ :width=>15, :highlightthickness=>0,
+ :redraw=>false, :dropenabled=>true,
+ :dragenabled=>true, :dragevent=>3,
+ :droptypes=>[
+ 'TREE_NODE', [
+ :copy, [],
+ :move, [],
+ :link, []
+ ],
+ 'LISTBOX_ITEM', [
+ :copy, [],
+ :move, [],
+ :link, []
+ ]
+ ],
+ :opencmd=>proc{|node|
+ moddir(1, tree, node)
+ },
+ :closecmd=>proc{|node|
+ moddir(0, tree, node)
+ })
+ sw.set_widget(tree)
+
+ sw.pack(:side=>:top, :expand=>true, :fill=>:both)
+ title.pack(:fill=>:both, :expand=>true)
+
+ pane = pw.add(:weight=>2)
+ lf = Tk::BWidget::TitleFrame.new(pane, :text=>'Content')
+ sw = Tk::BWidget::ScrolledWindow.new(lf.get_frame,
+ :scrollbar=>:horizontal,
+ :auto=>:none, :relief=>:sunken,
+ :borderwidth=>2)
+
+ list = Tk::BWidget::ListBox.new(sw, :relief=>:flat, :borderwidth=>0,
+ :highlightthickness=>0, :width=>20,
+ :multicolumn=>true, :redraw=>false,
+ :dragevent=>3, :dropenabled=>true,
+ :dragenabled=>true,
+ :droptypes=>[
+ 'TREE_NODE', [
+ :copy, [],
+ :move, [],
+ :link, []
+ ],
+ 'LISTBOX_ITEM', [
+ :copy, [],
+ :move, [],
+ :link, []
+ ]
+ ])
+ sw.set_widget(list)
+
+ Tk.pack(sw, lf, :fill=>:both, :expand=>true)
+
+ pw.pack(:fill=>:both, :expand=>true)
+
+ tree.textbind('ButtonPress-1',
+ proc{|node, ev| select('tree', 1, tree, list, node)})
+ tree.textbind('Double-ButtonPress-1',
+ proc{|node, ev| select('tree', 2, tree, list, node)})
+
+ list.textbind('ButtonPress-1',
+ proc{|node, ev| select('list', 1, tree, list, node)})
+ list.textbind('Double-ButtonPress-1',
+ proc{|node, ev| select('list', 2, tree, list, node)})
+
+ list.imagebind('Double-ButtonPress-1',
+ proc{|node, ev| select('list', 2, tree, list, node)})
+
+ nb.itemconfigure('demoTree',
+ :createcmd=>proc{|*args| init(tree, list, *args)},
+ :raisecmd=>proc{
+ Tk.root.geometry =~
+ /\d+x\d+([+-]{1,2}\d+)([+-]{1,2}\d+)/
+ global_w = ($1 || 0).to_i
+ global_h = ($2 || 0).to_i
+ if @@top
+ Tk::BWidget.place(@@top, 0, 0, :at,
+ global_w - Tk.root.winfo_screenwidth, global_h)
+ @@top.deiconify
+ Tk.root.bind('Unmap', proc{@@top.withdraw})
+ Tk.root.bind('Map', proc{@@top.deiconify})
+ Tk.root.bind('Configure', proc{|w|
+ if w == Tk.root
+ Tk.root.geometry =~
+ /\d+x\d+([+-]{1,2}\d+)([+-]{1,2}\d+)/
+ global_w = ($1 || 0).to_i
+ global_h = ($2 || 0).to_i
+ Tk::BWidget.place(@@top, 0, 0, :at,
+ global_w - Tk.root.winfo_screenwidth,
+ global_h)
+ end
+ }, '%W')
+ end
+ },
+ :leavecmd=>proc{
+ @@top.withdraw if @@top
+ Tk.root.bind_remove('Unmap')
+ Tk.root.bind_remove('Map')
+ Tk.root.bind_remove('Configure')
+ true
+ })
+ end
+
+ def self.init(tree, list, *args)
+ @@count = 0
+ if Tk::PLATFORM['platform'] == 'unix'
+ rootdir = File.expand_path('~')
+ else
+ rootdir = 'c:'
+ end
+
+ tree.insert('end', 'root', 'home',
+ :text=>rootdir, :data=>rootdir, :open=>true,
+ :image=>Tk::BWidget::Bitmap.new('openfold'))
+ getdir(tree, 'home', rootdir)
+ select('tree', 1, tree, list, 'home')
+ tree.redraw(true)
+ list.redraw(true)
+
+ @@top = TkToplevel.new
+ @@top.withdraw
+ @@top.protocol('WM_DELETE_WINDOW'){
+ # don't kill me
+ }
+ @@top.resizable(false, false)
+ @@top.title('Drag rectangle to scroll directory tree')
+ @@top.transient(Tk.root)
+ Tk::BWidget::ScrollView.new(@@top, :window=>tree, :fill=>'white',
+ :width=>300, :height=>300, :relief=>:sunken,
+ :bd=>1).pack(:fill=>:both, :expand=>true)
+ end
+
+ def self.getdir(tree, node, path)
+ lentries = Dir.glob(File.join(path, '*')).sort
+ lfiles = []
+ lentries.each{|f|
+ basename = File.basename(f)
+ if File.directory?(f)
+ Tk::BWidget::Tree::Node.new(tree, node,
+ :index=>'end', :text=>basename,
+ :image=>Tk::BWidget::Bitmap.new('folder'),
+ :drawcross=>:allways, :data=>f)
+ @@count += 1
+ else
+ lfiles << basename
+ end
+ }
+ tree.itemconfigure(node, :drawcross=>:auto, :data=>lfiles)
+ end
+
+ def self.moddir(idx, tree, node)
+ if (idx != 0 && tree.itemcget(node, :drawcross).to_s == 'allways')
+ getdir(tree, node, tree.itemcget(node, :data))
+ if tree.nodes(node).empty?
+ tree.itemconfigure(node, :image=>Tk::BWidget::Bitmap.new('folder'))
+ else
+ tree.itemconfigure(node, :image=>Tk::BWidget::Bitmap.new('openfold'))
+ end
+ else
+ img = %w(folder openfold)[idx] || 'openfold'
+ tree.itemconfigure(node, :image=>Tk::BWidget::Bitmap.new(img))
+ end
+ end
+
+ def self.select(where, num, tree, list, node)
+ @@dblclick = true
+ if num == 1
+ if (where == 'tree' &&
+ tree.selection_get.find{|x|
+ TkUtil._get_eval_string(x) == TkUtil._get_eval_string(node)
+ })
+ @@dblclick = false
+ Tk.after(500, proc{edit('tree', tree, list, node)})
+ return
+ end
+ if (where == 'list' &&
+ list.selection_get.find{|x|
+ TkUtil._get_eval_string(x) == TkUtil._get_eval_string(node)
+ })
+ @@dblclick = false
+ Tk.after(500, proc{edit('list', tree, list, node)})
+ return
+ end
+ if where == 'tree'
+ select_node(tree, list, node)
+ else
+ list.selection_set(node)
+ end
+ elsif (where == 'list' && tree.exist?(node))
+ parent = tree.parent(node)
+ while TkUtil._get_eval_string(parent) != 'root'
+ tree.itemconfigure(parent, :open=>true)
+ parent = tree.parent(parent)
+ end
+ select_node(tree, list, node)
+ end
+ end
+
+ def self.select_node(tree, list, node)
+ tree.selection_set(node)
+ Tk.update
+ list.delete(*(list.items(0, 'end')))
+
+ dir = tree.itemcget(node, :data)
+ if tree.itemcget(node, :drawcross).to_s == 'allways'
+ getdir(tree, node, dir)
+ dir = tree.itemcget(node, :data)
+ end
+
+ tree.nodes(node).each{|subnode|
+ list.insert('end', subnode,
+ :text=>tree.itemcget(subnode, :text),
+ :image=>Tk::BWidget::Bitmap.new('folder'))
+ }
+
+ TkComm.simplelist(dir).each{|f|
+ Tk::BWidget::ListBox::Item.new(list, 'end', :text=>f,
+ :image=>Tk::BWidget::Bitmap.new('file'))
+ }
+ end
+
+ def self.edit(where, tree, list, node)
+ return if @@dblclick
+
+ if (where == 'tree' &&
+ tree.selection_get.find{|x|
+ TkUtil._get_eval_string(x) == TkUtil._get_eval_string(node)
+ })
+ res = tree.edit(node, tree.itemcget(node, :text))
+ if res != ''
+ tree.itemconfigure(node, :text=>res)
+ if list.exist?(node)
+ list.itemconfigure(node, :text=>res)
+ end
+ tree.selection_set(node)
+ end
+ return
+ end
+
+ if (where == 'list')
+ res = list.edit(node, list.igemcget(node, :text))
+ if res != ''
+ list.itemconfigure(node, :text=>res)
+ if tree.exist?(node)
+ tree.itemconfigure(node, :text=>res)
+ else
+ cursel = tree.selection_get[0]
+ index = list.index(node) - tree.nodes(cursel).size
+ data = TkComm.simplelist(tree.itemcget(cursel, :data))
+ data[index] = res
+ tree.itemconfigure(cursel, :date=>data)
+ end
+ list.selection_set(node)
+ end
+ end
+ end
+
+ def self.expand(tree, but)
+ unless (cur = tree.selection_get).empty?
+ if TkComm.bool(but)
+ tree.opentree(cur)
+ else
+ tree.closetree(cur)
+ end
+ end
+ end
+end
diff --git a/ext/tk/sample/tkextlib/bwidget/x1.xbm b/ext/tk/sample/tkextlib/bwidget/x1.xbm
new file mode 100644
index 0000000000..6137a118f8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/bwidget/x1.xbm
@@ -0,0 +1,2258 @@
+#define x1_width 626
+#define x1_height 428
+static char x1_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x03,0x80,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xe0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x80,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x03,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x3f,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x1f,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xc0,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x07,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x1f,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x3f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x0f,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0xf8,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,
+ 0x7f,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0x3f,0x00,0x00,0x00,0xc0,0xff,0xff,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x3f,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xe0,0xff,0xff,
+ 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0xfc,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xfe,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0x07,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x01,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x03,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xe0,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,
+ 0xf8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x03,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,
+ 0x00,0x00,0x00,0x00,0xfe,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,
+ 0xff,0xff,0xff,0x01,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x80,0xff,0x07,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x07,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xc0,0xff,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x07,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xf8,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,
+ 0x00,0x00,0x00,0x00,0xf8,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0xfc,0xff,0x0f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,
+ 0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0x7f,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x07,0x00,0x00,0x00,0x80,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xc0,0xff,0xff,0x1f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xe0,0xff,0xff,
+ 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0x3f,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x1f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0x00,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1f,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0x1f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xe0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0xe0,0xff,
+ 0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0x07,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x0f,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xf0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x07,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xfd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,
+ 0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x80,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x80,
+ 0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x07,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xfd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xf8,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0xf8,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0x01,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x01,0x00,0x00,0x00,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+ 0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,
+ 0x7f,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0xff,0x7f,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x3f,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x1f,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,
+ 0xff,0x1f,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf0,0xff,0x0f,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,
+ 0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x07,0x00,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x03,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x07,0x00,
+ 0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0x03,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0x01,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x01,0x00,0x00,0x00,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x07,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x00,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0x7f,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0x7f,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
+ 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0xe0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x0f,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,
+ 0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x80,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x07,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x80,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x1f,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,
+ 0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x06,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xfd,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xfd,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0x00,
+ 0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xfc,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfc,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0xfc,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfc,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfc,0x00,0x00,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0xfc,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0xfc,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0x00,0x00,0x00,0x00,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xfc,0x00,0x00,
+ 0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0xfc,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x0f,0xfc,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0xfc,0x00,0x00,0x00,0xe0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0xfc,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x07,0xfc,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x07,0xfc,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0xfc,0x00,0x00,0x00,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0xfc,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x03,0xfc,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xfc,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xfc,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0xfc,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0xfc,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xfc,0x00,0x00,0x80,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0xfc,0x00,0x00,
+ 0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x00,0xfc,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x00,0xfc,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xfc,0x00,0x00,0xe0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xfc,0x00,
+ 0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x1f,0x00,0xfc,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0xfc,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0xfc,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0xfc,
+ 0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x0f,0x00,0xfc,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x07,0x00,0xfc,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0xfc,0x00,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,
+ 0xfc,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0xfc,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0xfc,0x00,0x80,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0xfc,0x00,0x80,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0xfc,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0xfc,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0xfc,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0xfc,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,
+ 0x00,0x00,0xfc,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0xfc,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0xfc,0x00,0xf0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0xfc,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0xfc,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xfc,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xfc,0x00,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,
+ 0xfc,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x03,0x00,0x00,0xfc,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xfc,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xfc,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0xfc,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0x00,0x00,0x00,0xfc,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0xfc,0x00,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xfc,0x80,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,
+ 0x00,0x00,0xfc,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1f,0x00,0x00,0x00,0xfc,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xfc,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xfc,
+ 0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0xfc,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xfc,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xfc,0xe0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0xfc,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x01,0x00,0x00,0x00,0xfc,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xfc,0xf0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xfc,0xf0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,
+ 0x00,0xfc,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0xfc,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0xfc,0xf8,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0xfc,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0xfc,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x07,0x00,0x00,0x00,0x00,0xfc,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0xfc,0xf8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0xfc,
+ 0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,
+ 0x00,0x00,0x00,0xfc,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0xfc,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0xfc,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0xfc,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x0f,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x01,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x00,0x00,0x00,0xc0,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,
+ 0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xc0,0x0f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x01,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0xe0,
+ 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x80,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x80,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xf8,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0xfc,0x3f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,
+ 0xfc,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x80,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x01,0x00,0x00,0x00,0xfe,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x80,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x80,0xff,0x7f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x80,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0xc0,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0xe0,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xf0,0xff,0xff,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0xf8,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x07,0x00,0x00,0x00,0xf8,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xfc,0xff,0xff,0x03,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0xc0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xc0,0xff,
+ 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xe0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x0f,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
+ 0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xf8,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x01,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0x07,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,
+ 0xff,0x07,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xf0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0x03,0x00,
+ 0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,
+ 0xff,0xff,0x03,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xf8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x3f,0x00,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x3f,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf8,0xff,0xff,0x1f,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xf0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x0f,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0x07,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0x01,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0x01,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xe0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfe,0x7f,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xc0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x80,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x80,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x80,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0x03,0x00,
+ 0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0xf0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,
+ 0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x1f,0x00,
+ 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,
+ 0xff,0xff,0x07,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x7f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x7f,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xf8,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
+ 0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xf0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x01,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x7f,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0x1f,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xc0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0x7f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xf8,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfe,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x07,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,
+ 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xc0,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0xc0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,
+ 0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf8,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x1f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x3f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x80,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf8,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,
+ 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,
+ 0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x80,0x0f,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0xc0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x80,
+ 0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xfc};
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/Orig_LICENSE.txt b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/Orig_LICENSE.txt
new file mode 100644
index 0000000000..22f787609d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/Orig_LICENSE.txt
@@ -0,0 +1,42 @@
+
+ #######################################################################
+ ### The following text is the original 'license.terms' of iwidges ###
+ ### extension. ###
+ ### Original Tcl source files are not include in this directry, ###
+ ### because of all of them are rewrited to Ruby files. ###
+ ### However, the image data files in the 'images' directory are ###
+ ### quoted from iwidgets source archive. ###
+ #######################################################################
+
+
+This software is copyrighted by DSC Technologies and private individual
+contributors. The copyright holder is specifically listed in the header
+of each file. The following terms apply to all files associated with the
+software unless explicitly disclaimed in individual files by private
+contributors.
+
+Copyright 1997 DSC Technologies Corporation
+
+Permission to use, copy, modify, distribute and license this software and
+its documentation for any purpose, and without fee or written agreement
+with DSC, is hereby granted, provided that the above copyright notice
+appears in all copies and that both the copyright notice and warranty
+disclaimer below appear in supporting documentation, and that the names of
+DSC Technologies Corporation or DSC Communications Corporation not be used
+in advertising or publicity pertaining to the software without specific,
+written prior permission.
+
+DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-INFRINGEMENT.
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND
+DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL DSC BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+RESTRICTED RIGHTS: Use, duplication or disclosure by the government
+is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
+of the Rights in Technical Data and Computer Software Clause as DFARS
+252.227-7013 and FAR 52.227-19.
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/box.xbm b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/box.xbm
new file mode 100644
index 0000000000..7498e15de2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/box.xbm
@@ -0,0 +1,14 @@
+#define Tool_32_box_width 32
+#define Tool_32_box_height 32
+static unsigned char Tool_32_box_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x0f, 0x20, 0x00, 0x00, 0x08,
+ 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08,
+ 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08,
+ 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08,
+ 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08,
+ 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08,
+ 0xe0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/clear.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/clear.gif
new file mode 100644
index 0000000000..bd45628aa7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/clear.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/close.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/close.gif
new file mode 100644
index 0000000000..f91b9e9d1e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/close.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/copy.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/copy.gif
new file mode 100644
index 0000000000..7319f1dcb0
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/copy.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/cut.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/cut.gif
new file mode 100644
index 0000000000..4258b17591
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/cut.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/exit.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/exit.gif
new file mode 100644
index 0000000000..e462be033f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/exit.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/find.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/find.gif
new file mode 100644
index 0000000000..dddcb8044b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/find.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/help.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/help.gif
new file mode 100644
index 0000000000..bc8f18c00d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/help.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/line.xbm b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/line.xbm
new file mode 100644
index 0000000000..4622ae978b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/line.xbm
@@ -0,0 +1,14 @@
+#define lineOp_width 32
+#define lineOp_height 32
+static unsigned char lineOp_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+ 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00,
+ 0x80, 0x07, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
+ 0x00, 0xe0, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x07, 0x00,
+ 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x01,
+ 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x0f,
+ 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/mag.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/mag.gif
new file mode 100644
index 0000000000..4a5be66e76
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/mag.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/new.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/new.gif
new file mode 100644
index 0000000000..9c68ad35f5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/new.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/open.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/open.gif
new file mode 100644
index 0000000000..bed862c8c4
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/open.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/oval.xbm b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/oval.xbm
new file mode 100644
index 0000000000..856bd43785
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/oval.xbm
@@ -0,0 +1,14 @@
+#define ovalOp_width 32
+#define ovalOp_height 32
+static unsigned char ovalOp_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00,
+ 0x00, 0x1c, 0x70, 0x00, 0x00, 0x03, 0x80, 0x01, 0x80, 0x00, 0x00, 0x02,
+ 0x40, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x10,
+ 0x10, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x20,
+ 0x08, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x10,
+ 0x10, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x04,
+ 0x80, 0x00, 0x00, 0x02, 0x00, 0x03, 0x80, 0x01, 0x00, 0x1c, 0x70, 0x00,
+ 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/paste.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/paste.gif
new file mode 100644
index 0000000000..9974f23bf5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/paste.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/points.xbm b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/points.xbm
new file mode 100644
index 0000000000..c50aa4c5f3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/points.xbm
@@ -0,0 +1,14 @@
+#define dotPencilOp_width 32
+#define dotPencilOp_height 32
+static unsigned char dotPencilOp_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x12, 0x00,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x80, 0x04, 0x00,
+ 0x00, 0x80, 0x04, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00,
+ 0x00, 0x90, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00,
+ 0x00, 0x24, 0x00, 0x18, 0x00, 0x24, 0x00, 0x18, 0x00, 0x12, 0x00, 0x00,
+ 0x00, 0x12, 0x00, 0x30, 0x00, 0x0e, 0x00, 0x30, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x06, 0x0c, 0x30, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x30, 0xa0, 0x01,
+ 0x00, 0x60, 0xb0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/poly.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/poly.gif
new file mode 100644
index 0000000000..2b595bb9b7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/poly.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/print.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/print.gif
new file mode 100644
index 0000000000..d321f17457
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/print.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/ruler.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/ruler.gif
new file mode 100644
index 0000000000..00d26febf6
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/ruler.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/save.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/save.gif
new file mode 100644
index 0000000000..d1ceb1a5c4
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/save.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/select.gif b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/select.gif
new file mode 100644
index 0000000000..f885c9ca5f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/select.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/text.xbm b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/text.xbm
new file mode 100644
index 0000000000..ffb0686303
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/catalog_demo/images/text.xbm
@@ -0,0 +1,14 @@
+#define font_edit_width 32
+#define font_edit_height 32
+static unsigned char font_edit_bits[] = {
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x1c,
+ 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x80, 0x7b,
+ 0x00, 0x00, 0x80, 0x7e, 0x00, 0x00, 0xc0, 0xfd, 0x00, 0x00, 0x60, 0xfb,
+ 0x00, 0x00, 0xb0, 0xf7, 0x00, 0x00, 0xd0, 0xef, 0x00, 0x00, 0xf8, 0xdf,
+ 0x00, 0x00, 0xd4, 0x7f, 0x00, 0x00, 0xaa, 0x1f, 0x00, 0x00, 0x15, 0x0f,
+ 0x00, 0x80, 0x82, 0x06, 0x03, 0x40, 0x01, 0x01, 0x07, 0xa0, 0x80, 0x00,
+ 0x0f, 0x10, 0x40, 0x00, 0x1f, 0x08, 0x20, 0x00, 0x3b, 0xe4, 0x1f, 0x00,
+ 0x73, 0x1a, 0x00, 0x00, 0xe3, 0x07, 0x00, 0x00, 0xc3, 0x01, 0x00, 0x00,
+ 0xe3, 0x03, 0x00, 0x00, 0x7b, 0x07, 0x00, 0x00, 0x1f, 0x06, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/buttonbox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/buttonbox.rb
new file mode 100644
index 0000000000..2b7cd45205
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/buttonbox.rb
@@ -0,0 +1,22 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+# sample 1
+p bb1 = Tk::Iwidgets::Buttonbox.new
+p bb1.add('Yes', :text=>'Yes', :command=>proc{puts 'Yes'})
+p bb1.add('No', :text=>'No', :command=>proc{puts 'No'})
+p bb1.add('Maybe', :text=>'Maybe', :command=>proc{puts 'Maybe'})
+bb1.default('Yes')
+bb1.pack(:expand=>true, :fill=>:both, :pady=>5)
+print "\n"
+
+# sample 2
+p bb2 = Tk::Iwidgets::Buttonbox.new
+p btn1 = bb2.add(:text=>'Yes', :command=>proc{puts 'Yes'})
+p btn2 = bb2.add(:text=>'No', :command=>proc{puts 'No'})
+p btn3 = bb2.add(:text=>'Maybe', :command=>proc{puts 'Maybe'})
+bb2.default(btn1)
+bb2.pack(:expand=>true, :fill=>:both, :pady=>5)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/calendar.rb b/ext/tk/sample/tkextlib/iwidgets/sample/calendar.rb
new file mode 100644
index 0000000000..4dd929c035
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/calendar.rb
@@ -0,0 +1,10 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Calendar.new(:command=>proc{|arg| puts(arg.date)},
+ :weekendbackground=>'mistyrose',
+ :weekdaybackground=>'ghostwhite',
+ :outline=>'black', :startday=>'wednesday',
+ :days=>%w(We Th Fr Sa Su Mo Tu)).pack
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/canvasprintbox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/canvasprintbox.rb
new file mode 100644
index 0000000000..c7c043000a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/canvasprintbox.rb
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Canvasprintbox.new(:orient=>:landscape, :stretch=>1) \
+ .pack(:padx=>10, :pady=>10, :fill=>:both, :expand=>true)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/canvasprintdialog.rb b/ext/tk/sample/tkextlib/iwidgets/sample/canvasprintdialog.rb
new file mode 100644
index 0000000000..ea8d63e6eb
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/canvasprintdialog.rb
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Canvasprintdialog.new.activate
+
+Tk.mainloop
+
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/checkbox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/checkbox.rb
new file mode 100644
index 0000000000..bae0eba73a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/checkbox.rb
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+cb = Tk::Iwidgets::Checkbox.new
+cb.add('bold', :text=>'Bold')
+cb.add('italic', :text=>'Italic')
+cb.add('underline', :text=>'Underline')
+cb.select('underline')
+cb.pack(:expand=>true, :fill=>:both, :padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/combobox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/combobox.rb
new file mode 100644
index 0000000000..ec9c7a1df3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/combobox.rb
@@ -0,0 +1,32 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+#
+# Non-editable Dropdown Combobox
+#
+cb1 = Tk::Iwidgets::Combobox.new(:labeltext=>'Month:',
+ :selectioncommand=>proc{
+ puts(cb1.get_curselection)
+ },
+ :editable=>false, :listheight=>185,
+ :popupcursor=>'hand1')
+
+cb1.insert_list('end', *%w(Jan Feb Mar Apr May June Jul Aug Sept Oct Nov Dec))
+
+
+#
+# Editable Dropdown Combobox
+#
+cb2 = Tk::Iwidgets::Combobox.new(:labeltext=>'Operating System:',
+ :selectioncommand=>proc{
+ puts(cb2.get_curselection)
+ })
+
+cb2.insert_list('end', *%w(Linux HP-UX SunOS Solaris Irix))
+cb2.insert_entry('end', 'L')
+
+cb1.pack(:padx=>10, :pady=>10, :fill=>:x)
+cb2.pack(:padx=>10, :pady=>10, :fill=>:x)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/dateentry.rb b/ext/tk/sample/tkextlib/iwidgets/sample/dateentry.rb
new file mode 100644
index 0000000000..5727879217
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/dateentry.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Dateentry.new.pack
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/datefield.rb b/ext/tk/sample/tkextlib/iwidgets/sample/datefield.rb
new file mode 100644
index 0000000000..12d498245d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/datefield.rb
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+df = Tk::Iwidgets::Datefield.new(:command=>proc{puts(df.get)})
+df.pack(:fill=>:x, :expand=>true, :padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/dialog.rb b/ext/tk/sample/tkextlib/iwidgets/sample/dialog.rb
new file mode 100644
index 0000000000..3449cd4b3d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/dialog.rb
@@ -0,0 +1,20 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Thread.new{Tk.mainloop}
+
+d = Tk::Iwidgets::Dialog.new(:modality=>:application)
+
+d.buttonconfigure('OK', :command=>proc{puts 'OK'; d.deactivate true})
+d.buttonconfigure('Apply', :command=>proc{puts 'Apply'})
+d.buttonconfigure('Cancel', :command=>proc{puts 'Cancel'; d.deactivate false})
+d.buttonconfigure('Help', :command=>proc{puts 'Help'})
+
+TkListbox.new(d.child_site, :relief=>:sunken).pack(:expand=>true, :fill=>:both)
+
+if TkComm.bool(d.activate)
+ puts "Exit via OK button"
+else
+ puts "Exit via Cancel button"
+end
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/dialogshell.rb b/ext/tk/sample/tkextlib/iwidgets/sample/dialogshell.rb
new file mode 100644
index 0000000000..197521e0a4
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/dialogshell.rb
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+ds = Tk::Iwidgets::Dialogshell.new(:modality=>:none)
+
+ds.add('OK', :text=>'OK', :command=>proc{puts 'OK'; ds.deactivate})
+ds.add('Cancel', :text=>'Cancel', :command=>proc{puts 'Cancel'; ds.deactivate})
+ds.default('OK')
+
+TkButton.new(:text=>'ACTIVATE', :padx=>7, :pady=>7,
+ :command=>proc{puts ds.activate}).pack(:padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/disjointlistbox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/disjointlistbox.rb
new file mode 100644
index 0000000000..85c5d03d17
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/disjointlistbox.rb
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+djl = Tk::Iwidgets::Disjointlistbox.new.pack(:fill=>:both, :expand=>true,
+ :padx=>10, :pady=>10)
+djl.set_lhs(*[0,2,4,5])
+djl.set_rhs(3,6)
+
+djl.insert_lhs(1,7,8)
+djl.insert_rhs(9)
+
+p djl.get_lhs
+p djl.get_rhs
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/entryfield-1.rb b/ext/tk/sample/tkextlib/iwidgets/sample/entryfield-1.rb
new file mode 100644
index 0000000000..856d883a92
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/entryfield-1.rb
@@ -0,0 +1,39 @@
+#!/usr/bin/env ruby
+#########################################################
+#
+# use Tk::UTF8_String() for a utf8 charecter
+#
+#########################################################
+require 'tk'
+require 'tkextlib/iwidgets'
+
+TkOption.add('*textBackground', 'white')
+
+ef = Tk::Iwidgets::Entryfield.new(:command=>proc{puts "Return Pressed"})
+
+fef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Fixed:',
+ :fixed=>10, :width=>12)
+
+nef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Numeric:',
+ :validate=>:numeric, :width=>12)
+
+aef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Alphabetic:',
+ :validate=>:alphabetic, :width=>12,
+ :invalid=>proc{
+ puts "Alphabetic contents invalid"
+ })
+
+pef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Password:', :width=>12,
+ :show=>Tk::UTF8_String("\267"),
+ ## <=== utf8 character
+ :command=>proc{puts "Return Pressed"})
+
+Tk::Iwidgets::Labeledwidget.alignlabels(ef, fef, nef, aef, pef)
+
+ef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+fef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+nef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+aef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+pef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/entryfield-2.rb b/ext/tk/sample/tkextlib/iwidgets/sample/entryfield-2.rb
new file mode 100644
index 0000000000..4a4c2e7eb7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/entryfield-2.rb
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+#########################################################
+#
+# set $KCODE to 'utf' for a utf8 charecter
+#
+#########################################################
+$KCODE='utf'
+
+require 'tk'
+require 'tkextlib/iwidgets'
+
+TkOption.add('*textBackground', 'white')
+
+ef = Tk::Iwidgets::Entryfield.new(:command=>proc{puts "Return Pressed"})
+
+fef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Fixed:',
+ :fixed=>10, :width=>12)
+
+nef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Numeric:',
+ :validate=>:numeric, :width=>12)
+
+aef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Alphabetic:',
+ :validate=>:alphabetic, :width=>12,
+ :invalid=>proc{
+ puts "Alphabetic contents invalid"
+ })
+
+pef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Password:', :width=>12,
+ :show=>"\267", ## <=== utf8 character
+ :command=>proc{puts "Return Pressed"})
+
+Tk::Iwidgets::Labeledwidget.alignlabels(ef, fef, nef, aef, pef)
+
+ef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+fef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+nef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+aef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+pef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/entryfield-3.rb b/ext/tk/sample/tkextlib/iwidgets/sample/entryfield-3.rb
new file mode 100644
index 0000000000..bddd542f64
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/entryfield-3.rb
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+#########################################################
+#
+# set Tk.encoding = 'utf-8' for a utf8 charecter
+#
+#########################################################
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk.encoding = 'utf-8'
+
+TkOption.add('*textBackground', 'white')
+
+ef = Tk::Iwidgets::Entryfield.new(:command=>proc{puts "Return Pressed"})
+
+fef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Fixed:',
+ :fixed=>10, :width=>12)
+
+nef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Numeric:',
+ :validate=>:numeric, :width=>12)
+
+aef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Alphabetic:',
+ :validate=>:alphabetic, :width=>12,
+ :invalid=>proc{
+ puts "Alphabetic contents invalid"
+ })
+
+pef = Tk::Iwidgets::Entryfield.new(:labeltext=>'Password:', :width=>12,
+ :show=>"\267", ## <=== utf8 character
+ :command=>proc{puts "Return Pressed"})
+
+Tk::Iwidgets::Labeledwidget.alignlabels(ef, fef, nef, aef, pef)
+
+ef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+fef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+nef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+aef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+pef.pack(:fil=>:x, :expand=>true, :padx=>10, :pady=>5)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/extbutton.rb b/ext/tk/sample/tkextlib/iwidgets/sample/extbutton.rb
new file mode 100644
index 0000000000..6971052b60
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/extbutton.rb
@@ -0,0 +1,20 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Extbutton.new(:text=>'Bitmap example', :bitmap=>'info',
+ :background=>'bisque', :activeforeground=>'red',
+ :bitmapforeground=>'blue', :defaultring=>true,
+ :command=>proc{
+ puts "Bisque is beautiful"
+ }).pack(:expand=>true)
+
+#img = TkPhotoImage.new(:file=>File.join(File.dirname(File.expand_path(__FILE__)), '../../../images/earthris.gif'))
+img = TkPhotoImage.new(:file=>File.join(File.dirname(File.expand_path(__FILE__)), '../catalog_demo/images/clear.gif'))
+
+Tk::Iwidgets::Extbutton.new(:text=>'Image example', :relief=>:ridge,
+ :image=>img, :imagepos=>:e, :font=>'9x15bold',
+ :activebackground=>'lightyellow',
+ :background=>'lightgreen').pack(:expand=>true)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/extfileselectionbox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/extfileselectionbox.rb
new file mode 100644
index 0000000000..4738084d9d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/extfileselectionbox.rb
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Extfileselectionbox.new.pack(:padx=>10, :pady=>10,
+ :fill=>:both, :expand=>true)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/extfileselectiondialog.rb b/ext/tk/sample/tkextlib/iwidgets/sample/extfileselectiondialog.rb
new file mode 100644
index 0000000000..c1a9b3defd
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/extfileselectiondialog.rb
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mainloop = Thread.new{Tk.mainloop}
+
+#
+# Non-modal example
+#
+nmfsd = Tk::Iwidgets::Extfileselectiondialog.new(:title=>'Non-Modal')
+nmfsd.buttonconfigure('OK', :command=>proc{
+ puts "You selected #{nmfsd.get}"
+ nmfsd.deactivate
+ })
+nmfsd.activate
+
+#
+# Modal example
+#
+mfsd = Tk::Iwidgets::Extfileselectiondialog.new(:modality=>:application)
+mfsd.center
+if TkComm.bool(mfsd.activate)
+ puts "You selected #{mfsd.get}"
+else
+ puts "You cancelled the dialog"
+end
+
+
+mainloop.join
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/feedback.rb b/ext/tk/sample/tkextlib/iwidgets/sample/feedback.rb
new file mode 100644
index 0000000000..7b87a029ed
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/feedback.rb
@@ -0,0 +1,10 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Feedback.new(:labeltext=>'Status', :steps=>20){|fb|
+ pack(:padx=>10, :pady=>10, :fill=>:both, :expand=>true)
+ TkTimer.new(500, 20, proc{fb.step}).start(2500)
+}
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/fileselectionbox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/fileselectionbox.rb
new file mode 100644
index 0000000000..2ad3adb974
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/fileselectionbox.rb
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Fileselectionbox.new.pack(:padx=>10, :pady=>10,
+ :fill=>:both, :expand=>true)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/fileselectiondialog.rb b/ext/tk/sample/tkextlib/iwidgets/sample/fileselectiondialog.rb
new file mode 100644
index 0000000000..ff22b2f643
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/fileselectiondialog.rb
@@ -0,0 +1,28 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mainloop = Thread.new{Tk.mainloop}
+
+#
+# Non-modal example
+#
+nmfsd = Tk::Iwidgets::Fileselectiondialog.new(:title=>'Non-Modal')
+nmfsd.buttonconfigure('OK', :command=>proc{
+ puts "You selected #{nmfsd.get}"
+ nmfsd.deactivate
+ })
+nmfsd.activate
+
+#
+# Modal example
+#
+mfsd = Tk::Iwidgets::Fileselectiondialog.new(:modality=>:application)
+mfsd.center
+if TkComm.bool(mfsd.activate)
+ puts "You selected #{mfsd.get}"
+else
+ puts "You cancelled the dialog"
+end
+
+mainloop.join
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/finddialog.rb b/ext/tk/sample/tkextlib/iwidgets/sample/finddialog.rb
new file mode 100644
index 0000000000..110efb9b96
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/finddialog.rb
@@ -0,0 +1,15 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mainloop = Thread.new{Tk.mainloop}
+
+st = Tk::Iwidgets::Scrolledtext.new.pack
+st.insert('end', "Now is the time for all good men\n")
+st.insert('end', "to come to the aid of their country")
+
+fd = Tk::Iwidgets::Finddialog.new(:textwidget=>st)
+fd.center(st)
+fd.activate
+
+mainloop.join
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/hierarchy.rb b/ext/tk/sample/tkextlib/iwidgets/sample/hierarchy.rb
new file mode 100644
index 0000000000..ddb08d8b78
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/hierarchy.rb
@@ -0,0 +1,25 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+def get_files(file)
+ dir = (file.empty?)? ENV['HOME'] : TkComm._fromUTF8(file)
+ Dir.chdir(dir) rescue return ''
+ Dir['*'].sort.collect{|f|
+ [TkComm._toUTF8(File.join(dir, f)), TkComm._toUTF8(f)]
+ }
+end
+
+Tk::Iwidgets::Hierarchy.new(:querycommand=>proc{|arg| get_files(arg.node)},
+ :visibleitems=>'30x15',
+ :labeltext=>ENV['HOME']).pack(:side=>:left,
+ :expand=>true,
+ :fill=>:both)
+
+# Tk::Iwidgets::Hierarchy.new(:querycommand=>[proc{|n| get_files(n)}, '%n'],
+# :visibleitems=>'30x15',
+# :labeltext=>ENV['HOME']).pack(:side=>:left,
+# :expand=>true,
+# :fill=>:both)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/hyperhelp.rb b/ext/tk/sample/tkextlib/iwidgets/sample/hyperhelp.rb
new file mode 100644
index 0000000000..f9c92bf6dc
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/hyperhelp.rb
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mainloop = Thread.new{Tk.mainloop}
+
+dir = '/usr/local/ActiveTcl/demos/IWidgets/html/'
+href = [ 'hyperhelp.n', 'buttonbox.n', 'calendar.n' ]
+
+hh = Tk::Iwidgets::Hyperhelp.new(:topics=>href, :helpdir=>dir)
+hh.show_topic('hyperhelp.n')
+hh.activate
+
+mainloop.join
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/labeledframe.rb b/ext/tk/sample/tkextlib/iwidgets/sample/labeledframe.rb
new file mode 100644
index 0000000000..4e2e21e727
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/labeledframe.rb
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+lf = Tk::Iwidgets::Labeledframe.new(:labeltext=>'Entry Frame', :labelpos=>:n)
+lf.pack(:fill=>:both, :expand=>true, :padx=>10, :pady=>10)
+
+cs = lf.child_site
+
+Tk::Iwidgets::Entryfield.new(cs, :labeltext=>'Name:').pack(:side=>:top, :fill=>:x)
+Tk::Iwidgets::Spinint.new(cs, :labeltext=>'Number:').pack(:side=>:top, :fill=>:x)
+Tk::Iwidgets::Pushbutton.new(cs, :text=>'Details:').pack(:side=>:top, :fill=>:x)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/labeledwidget.rb b/ext/tk/sample/tkextlib/iwidgets/sample/labeledwidget.rb
new file mode 100644
index 0000000000..1d2e0a98a3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/labeledwidget.rb
@@ -0,0 +1,13 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+lw = Tk::Iwidgets::Labeledwidget.new(:labeltext=>'Canvas Widget',
+ :labelpos=>:s)
+lw.pack(:fill=>:both, :expand=>true, :padx=>10, :pady=>10)
+
+cw = TkCanvas.new(lw.child_site, :relief=>:raised, :width=>200, :height=>200,
+ :borderwidth=>3, :background=>:white)
+cw.pack(:padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/mainwindow.rb b/ext/tk/sample/tkextlib/iwidgets/sample/mainwindow.rb
new file mode 100644
index 0000000000..b87a6d27f9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/mainwindow.rb
@@ -0,0 +1,64 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mw = Tk::Iwidgets::Mainwindow.new
+
+mw.menubar.add(:menubutton, 'file', :text=>'File', :underline=>0,
+ :padx=>8, :pady=>2, :menu=>[
+ [:options, {:tearoff=>false}],
+
+ [:command, 'new', {
+ :label=>'New', :underline=>0,
+ :helpstr=>'Create a new file'
+ }
+ ],
+
+ [:command, 'open', {
+ :label=>'Open ...', :underline=>0,
+ :helpstr=>'Open an existing file'
+ }
+ ],
+
+ [:command, 'save', {
+ :label=>'Save', :underline=>0,
+ :helpstr=>'Save the current file'
+ }
+ ],
+
+ [:command, 'saveas', {
+ :label=>'Save As', :underline=>5,
+ :helpstr=>'Save the file as a different name'
+ }
+ ],
+
+ [:command, 'print', {
+ :label=>'Print', :underline=>0,
+ :helpstr=>'Print the file'
+ }
+ ],
+
+ [:separator, 'sep1'],
+
+ [:command, 'close', {
+ :label=>'Close', :underline=>0,
+ :helpstr=>'Close the file'
+ }
+ ],
+
+ [:separator, 'sep2'],
+
+ [:command, 'exit', {
+ :label=>'Exit', :underline=>1,
+ :helpstr=>'Exit this application'
+ }
+ ],
+
+ nil
+ ])
+
+Tk::Iwidgets::Scrolledtext.new(mw.child_site).pack(:fill=>:both, :expand=>true)
+
+mw.activate
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/menubar.rb b/ext/tk/sample/tkextlib/iwidgets/sample/menubar.rb
new file mode 100644
index 0000000000..891761adc1
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/menubar.rb
@@ -0,0 +1,124 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+helpvar = TkVariable.new
+viewmode = TkVariable.new
+
+menu_spec = [
+ [:menubutton, 'file', {
+ :text=>'File', :menu=>[
+ [:options, {:tearoff=>false}],
+
+ [:command, 'new', {
+ :label=>'New', :helpstr=>'Open new document',
+ :command=>proc{puts 'NEW'}
+ }
+ ],
+
+ [:command, 'close', {
+ :label=>'Close', :helpstr=>'Close current document',
+ :command=>proc{puts 'CLOSE'}
+ }
+ ],
+
+ [:separator, 'sep1'],
+
+ [:command, 'exit', {
+ :label=>'Exit', :helpstr=>'Exit application',
+ :command=>proc{exit}
+ }
+ ]
+ ]
+ }
+ ],
+
+ [:menubutton, 'edit', {
+ :text=>'Edit', :menu=>[
+ [:options, {:tearoff=>false}],
+
+ [:command, 'undo', {
+ :label=>'Undo', :underline=>0,
+ :helpstr=>'Undo last command',
+ :command=>proc{puts 'UNDO'}
+ }
+ ],
+
+ [:separator, 'sep2'],
+
+ [:command, 'cut', {
+ :label=>'Cut', :underline=>1,
+ :helpstr=>'Cut selection to clipboard',
+ :command=>proc{puts 'CUT'}
+ }
+ ],
+
+ [:command, 'copy', {
+ :label=>'Copy', :underline=>1,
+ :helpstr=>'Copy selection to clipboard',
+ :command=>proc{puts 'COPY'}
+ }
+ ],
+
+ [:command, 'paste', {
+ :label=>'Paste', :underline=>0,
+ :helpstr=>'Paste clipboard contents',
+ :command=>proc{puts 'PASTE'}
+ }
+ ]
+ ]
+ }
+ ],
+
+ [:menubutton, 'options', {
+ :text=>'Options', :menu=>[
+ [:options, {:tearoff=>false, :selectcolor=>'blue'}],
+
+ [:radiobutton, 'byName', {
+ :variable=>viewmode, :value=>'NAME',
+ :label=>'by Name', :helpstr=>'View files by name order',
+ :command=>proc{puts 'NAME'}
+ }
+ ],
+
+ [:radiobutton, 'byDate', {
+ :variable=>viewmode, :value=>'DATE',
+ :label=>'by Date', :helpstr=>'View files by date order',
+ :command=>proc{puts 'DATE'}
+ }
+ ],
+
+ [:cascade, 'prefs', {
+ :label=>'Preferences', :menu=>[
+ [:command, 'colors', {
+ :label=>'Colors...', :helpstr=>'Change text colors',
+ :command=>proc{puts 'COLORS'}
+ }
+ ],
+
+ [:command, 'fonts', {
+ :label=>'Fonts...', :helpstr=>'Change text font',
+ :command=>proc{puts 'COLORS'}
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+]
+
+#mb = Tk::Iwidgets::Menubar.new(:helpvariable=>helpvar,
+# :menubuttons=>menu_spec)
+mb = Tk::Iwidgets::Menubar.new(:helpvariable=>helpvar)
+mb.configure(:menubuttons=>menu_spec)
+
+fr = TkFrame.new(:width=>300, :height=>300)
+ef = TkEntry.new(:textvariable=>helpvar)
+
+mb.pack(:anchor=>:nw, :fill=>:x, :expand=>true)
+fr.pack(:fill=>:both, :expand=>true)
+ef.pack(:anchor=>:sw, :fill=>:x, :expand=>true)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/menubar2.rb b/ext/tk/sample/tkextlib/iwidgets/sample/menubar2.rb
new file mode 100644
index 0000000000..d6f2292650
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/menubar2.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+helpvar = TkVariable.new
+viewmode = TkVariable.new
+
+mb = Tk::Iwidgets::Menubar.new
+mb.menubuttons = [
+ [:menubutton, 'file', {
+ :text=>'File', :menu=>[
+ [:command, 'new', {:label=>'New'}],
+ [:command, 'close', {:label=>'Close'}],
+ [:separator, 'sep1'],
+ [:command, 'quit', {:label=>'Quit'}]
+ ]
+ }
+ ],
+ [:menubutton, 'edit', {:text=>'Edit'}]
+]
+
+mb.add(:command, '.edit.undo', :label=>'Undo', :underline=>0)
+mb.add(:separator, '.edit.sep2')
+mb.add(:command, '.edit.cut', :label=>'Cut', :underline=>1)
+mb.add(:command, '.edit.copy', :label=>'Copy', :underline=>1)
+mb.add(:command, '.edit.paste', :label=>'Paste', :underline=>0)
+
+mb.add(:menubutton, '.options', :text=>'Options', :menu=>[
+ [:radiobutton, 'byName', {
+ :variable=>viewmode, :value=>'NAME', :label=>'by Name'}
+ ],
+ [:radiobutton, 'byDate', {
+ :variable=>viewmode, :value=>'DATE', :label=>'by Date'}
+ ]
+ ])
+
+mb.add(:cascade, '.options.prefs', :label=>'Preferences', :menu=>[
+ [:command, 'colors', {:label=>'Colors...'}],
+ [:command, 'fonts', {:label=>'Fonts...'}]
+ ])
+
+mb.pack(:side=>:left, :anchor=>:nw, :fill=>:x, :expand=>true)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/messagebox1.rb b/ext/tk/sample/tkextlib/iwidgets/sample/messagebox1.rb
new file mode 100644
index 0000000000..3221dbc30c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/messagebox1.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mb = Tk::Iwidgets::Messagebox.new(:hscrollmode=>:dynamic,
+ :labeltext=>'Messages', :labelpos=>:n,
+ :height=>120, :width=>550,
+ :savedir=>'/tmp', :textbackground=>'#d9d9d9')
+mb.pack(:padx=>5, :pady=>5, :fill=>:both, :expand=>true)
+
+mb.type_add('ERROR', :background=>'red', :foreground=>'white', :bell=>true)
+mb.type_add('WARNING', :background=>'yellow', :foreground=>'black')
+mb.type_add('INFO', :background=>'white', :foreground=>'black')
+
+mb.issue('This is an error message in red with a beep', 'ERROR')
+mb.issue('This warning message in yellow', 'WARNING')
+mb.issue('This is an informational message', 'INFO')
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/messagebox2.rb b/ext/tk/sample/tkextlib/iwidgets/sample/messagebox2.rb
new file mode 100644
index 0000000000..2f0e3648a6
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/messagebox2.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mb = Tk::Iwidgets::Messagebox.new(:hscrollmode=>:dynamic,
+ :labeltext=>'Messages', :labelpos=>:n,
+ :height=>120, :width=>550,
+ :savedir=>'/tmp', :textbackground=>'#d9d9d9')
+mb.pack(:padx=>5, :pady=>5, :fill=>:both, :expand=>true)
+
+error = mb.type_add(:background=>'red', :foreground=>'white', :bell=>true)
+warning = mb.type_add(:background=>'yellow', :foreground=>'black')
+info = mb.type_add(:background=>'white', :foreground=>'black')
+
+mb.issue('This is an error message in red with a beep', error)
+mb.issue('This warning message in yellow', warning)
+mb.issue('This is an informational message', info)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/messagedialog.rb b/ext/tk/sample/tkextlib/iwidgets/sample/messagedialog.rb
new file mode 100644
index 0000000000..6c6bfbca3f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/messagedialog.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mainloop = Thread.new{Tk.mainloop}
+
+#
+# Standard question message dialog used for confirmation.
+#
+md = Tk::Iwidgets::Messagedialog.new(:title=>'Message Dialog',
+ :text=>'Are you sure ? ',
+ :bitmap=>'questhead', :modality=>:global)
+
+md.buttonconfigure('OK', :text=>'Yes')
+md.buttonconfigure('Cancel', :text=>'No')
+
+if TkComm.bool(md.activate)
+ md.text('Are you really sure ? ')
+ if TkComm.bool(md.activate)
+ puts 'Yes'
+ else
+ puts 'No'
+ end
+else
+ puts 'No'
+end
+
+md.destroy
+
+#
+# Copyright notice with automatic deactivation.
+#
+bmp = '@' + File.join(File.dirname(File.expand_path(__FILE__)), '../catalog_demo/images/text.xbm')
+
+cr = Tk::Iwidgets::Messagedialog.new(:title=>'Copyright',
+ :bitmap=>bmp, :imagepos=>:n,
+ :text=>"Copyright 200x XXX Corporation\nAll rights reserved")
+
+cr.hide('Cancel')
+
+cr.activate
+Tk.after(7000, proc{cr.deactivate; Tk.root.destroy})
+
+mainloop.join
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/notebook.rb b/ext/tk/sample/tkextlib/iwidgets/sample/notebook.rb
new file mode 100644
index 0000000000..e33b81eb6f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/notebook.rb
@@ -0,0 +1,30 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+# Create the tabnotebook widget and pack it.
+nb = Tk::Iwidgets::Notebook.new(:width=>100, :height=>100)
+nb.pack(:anchor=>:nw, :fill=>:both, :expand=>true,
+ :side=>:left, :padx=>10, :pady=>10)
+
+# Add two pages to the tabnotebook,
+# labelled "Page One" and "Page Two"
+nb.add(:label=>'Page One')
+nb.add(:label=>'Page Two')
+
+# Get the child site frames of these two pages.
+page1CS = nb.child_site(0)
+page2CS = nb.child_site('Page Two')
+
+# Create buttons on each page of the tabnotebook.
+TkButton.new(page1CS, :text=>'Button One').pack
+TkButton.new(page2CS, :text=>'Button Two').pack
+
+# Select the first page of the tabnotebook.
+nb.select(0)
+
+# Create the scrollbar and associate teh scrollbar
+# and the notebook together, then pack the scrollbar
+nb.scrollbar(TkScrollbar.new).pack(:fill=>:y, :expand=>true, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/notebook2.rb b/ext/tk/sample/tkextlib/iwidgets/sample/notebook2.rb
new file mode 100644
index 0000000000..649de4f024
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/notebook2.rb
@@ -0,0 +1,30 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+# Create the tabnotebook widget and pack it.
+nb = Tk::Iwidgets::Notebook.new(:width=>100, :height=>100)
+nb.pack(:anchor=>:nw, :fill=>:both, :expand=>true,
+ :side=>:top, :padx=>10, :pady=>0)
+
+# Add two pages to the tabnotebook,
+# labelled "Page One" and "Page Two"
+nb.add(:label=>'Page One')
+nb.add(:label=>'Page Two')
+
+# Get the child site frames of these two pages.
+page1CS = nb.child_site(0)
+page2CS = nb.child_site('Page Two')
+
+# Create buttons on each page of the tabnotebook.
+TkButton.new(page1CS, :text=>'Button One').pack
+TkButton.new(page2CS, :text=>'Button Two').pack
+
+# Select the first page of the tabnotebook.
+nb.select(0)
+
+# Create the scrollbar and associate teh scrollbar
+# and the notebook together, then pack the scrollbar
+nb.xscrollbar(TkScrollbar.new).pack(:fill=>:x, :expand=>true, :padx=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/optionmenu.rb b/ext/tk/sample/tkextlib/iwidgets/sample/optionmenu.rb
new file mode 100644
index 0000000000..1fd7a5bc05
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/optionmenu.rb
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+om = Tk::Iwidgets::Optionmenu.new(:labelmargin=>5, :labelpos=>:w,
+ :labeltext=>"Operating System :")
+
+om.insert('end', 'Unix', 'VMS', 'Linux', 'OS/2', 'Windows NT', 'DOS')
+om.sort_ascending
+om.select('Linux')
+
+om.pack(:padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/panedwindow.rb b/ext/tk/sample/tkextlib/iwidgets/sample/panedwindow.rb
new file mode 100644
index 0000000000..6e4458e508
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/panedwindow.rb
@@ -0,0 +1,22 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+pw = Tk::Iwidgets::Panedwindow.new(:width=>300, :height=>300)
+
+pw.add('top')
+pw.add('middle', :margin=>10)
+pw.add('bottom', :margin=>10, :minimum=>10)
+
+pw.pack(:fill=>:both, :expand=>true)
+
+pw.child_site_list.each{|pane|
+ TkButton.new(pane, :text=>pane.path, :relief=>:raised,
+ :borderwidth=>2).pack(:fill=>:both, :expand=>true)
+}
+
+pw.fraction(50,30,20)
+pw.paneconfigure(0, :minimum=>20)
+pw.paneconfigure('bottom', :margin=>15)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/panedwindow2.rb b/ext/tk/sample/tkextlib/iwidgets/sample/panedwindow2.rb
new file mode 100644
index 0000000000..6779cb57db
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/panedwindow2.rb
@@ -0,0 +1,22 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+pw = Tk::Iwidgets::Panedwindow.new(:width=>300, :height=>300)
+
+top = pw.add
+middle = pw.add(:margin=>10)
+bottom = pw.add(:margin=>10, :minimum=>10)
+
+pw.pack(:fill=>:both, :expand=>true)
+
+pw.child_site_list.each{|pane|
+ TkButton.new(pane, :text=>pane.path, :relief=>:raised,
+ :borderwidth=>2).pack(:fill=>:both, :expand=>true)
+}
+
+pw.fraction(50,30,20)
+pw.paneconfigure(0, :minimum=>20) # 0 == pw.index(top)
+pw.paneconfigure(bottom, :margin=>15)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/promptdialog.rb b/ext/tk/sample/tkextlib/iwidgets/sample/promptdialog.rb
new file mode 100644
index 0000000000..2c643e56f7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/promptdialog.rb
@@ -0,0 +1,17 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mainloop = Thread.new{Tk.mainloop}
+
+TkOption.add('*textBackground', 'white')
+
+pd = Tk::Iwidgets::Promptdialog.new(:modality=>:global, :title=>'Password',
+ :labeltext=>'Password:', :show=>'*')
+pd.hide('Apply')
+
+if TkComm.bool(pd.activate)
+ puts "Password entered: #{pd.get}"
+else
+ puts "Password prompt cancelled"
+end
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/pushbutton.rb b/ext/tk/sample/tkextlib/iwidgets/sample/pushbutton.rb
new file mode 100644
index 0000000000..6e1c3fffe3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/pushbutton.rb
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Pushbutton.new(:text=>'Hello',
+ :command=>proc{puts 'Hello World'},
+ :defaultring=>true).pack(:padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/radiobox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/radiobox.rb
new file mode 100644
index 0000000000..9cd6a002b0
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/radiobox.rb
@@ -0,0 +1,13 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+rb = Tk::Iwidgets::Radiobox.new(:labeltext=>'Fonts')
+rb.add('times', :text=>'Times')
+rb.add('helvetica', :text=>'Helvetica')
+rb.add('courier', :text=>'Courier')
+rb.add('symbol', :text=>'Symbol')
+rb.select('courier')
+rb.pack(:expand=>true, :fill=>:both, :padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/scrolledcanvas.rb b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledcanvas.rb
new file mode 100644
index 0000000000..92c94b96bb
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledcanvas.rb
@@ -0,0 +1,13 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+sc = Tk::Iwidgets::Scrolledcanvas.new
+
+sc.create(TkcRectangle, 100, 100, 400, 400, :fill=>'red')
+TkcRectangle.new(sc, 300, 300, 600, 600, :fill=>'green')
+TkcRectangle.new(sc, [[200, 200], [500, 500]], :fill=>'blue')
+
+sc.pack(:expand=>true, :fill=>:both, :padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/scrolledframe.rb b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledframe.rb
new file mode 100644
index 0000000000..5219847c9c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledframe.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+sf = Tk::Iwidgets::Scrolledframe.new(:width=>150, :height=>180,
+ :labeltext=>'scrolledframe')
+cs = sf.child_site
+
+TkButton.new(cs, :text=>'Hello').pack(:pady=>10)
+TkButton.new(cs, :text=>'World').pack(:pady=>10)
+TkButton.new(cs, :text=>'This is a test').pack(:pady=>10)
+TkButton.new(cs, :text=>'This is a really big button').pack(:pady=>10)
+TkButton.new(cs, :text=>'This is another really big button').pack(:pady=>10)
+TkButton.new(cs, :text=>'This is the last really big button').pack(:pady=>10)
+
+sf.pack(:expand=>true, :fill=>:both, :padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/scrolledhtml.rb b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledhtml.rb
new file mode 100644
index 0000000000..04334b8da8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledhtml.rb
@@ -0,0 +1,15 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+TkOption.add('*textBackground', 'white')
+
+sh = Tk::Iwidgets::Scrolledhtml.new(:fontname=>'helvetica',
+ :linkcommand=>proc{|href|
+ sh.import_link(href)
+ })
+sh.pack(:expand=>true, :fill=>:both, :padx=>10, :pady=>10)
+
+sh.import(Tk.getOpenFile(:title=>'select HTML document'))
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/scrolledlistbox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledlistbox.rb
new file mode 100644
index 0000000000..0b69751911
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledlistbox.rb
@@ -0,0 +1,22 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+TkOption.add('*textBackground', 'white')
+
+slb = Tk::Iwidgets::Scrolledlistbox.new(:selectmode=>:single,
+ :vscrollmode=>:static,
+ :hscrollmode=>:dynamic,
+ :labeltext=>'List',
+ :selectioncommand=>proc{
+ puts(slb.get_curselection)
+ },
+ :dblclickcommand=>proc{
+ puts('Double Click')
+ puts(slb.get_curselection)
+ })
+slb.pack(:expand=>true, :fill=>:both, :padx=>10, :pady=>10)
+
+slb.insert('end', *['Hello', 'Out There', 'World'])
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/scrolledtext.rb b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledtext.rb
new file mode 100644
index 0000000000..dd1a99a829
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/scrolledtext.rb
@@ -0,0 +1,11 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+st = Tk::Iwidgets::Scrolledtext.new(:hscrollmode=>:dynamic, :wrap=>:none,
+ :labeltext=>'Password File')
+st.pack(:expand=>true, :fill=>:both, :padx=>10, :pady=>10)
+
+st.import('/etc/passwd')
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/selectionbox.rb b/ext/tk/sample/tkextlib/iwidgets/sample/selectionbox.rb
new file mode 100644
index 0000000000..a5d623ae80
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/selectionbox.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+TkOption.add('*textBackground', 'white')
+
+sb = Tk::Iwidgets::Selectionbox.new.pack(:padx=>10, :pady=>10,
+ :fill=>:both, :expand=>true)
+
+sb.insert_items('end', *['Hello', 'Out There', 'World'])
+
+TkLabel.new(sb.child_site,
+ :text=>'Child Site is Here').pack(:fill=>:x, :padx=>10, :pady=>10)
+
+sb.insert_items(2, 'Cruel Cruel')
+
+sb.selection_set(1)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/selectiondialog.rb b/ext/tk/sample/tkextlib/iwidgets/sample/selectiondialog.rb
new file mode 100644
index 0000000000..f40b419180
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/selectiondialog.rb
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+mainloop = Thread.new{Tk.mainloop}
+
+TkButton.new(:text=>'QUIT',
+ :command=>proc{Tk.root.destroy}).pack(:padx=>10, :pady=>10)
+
+Tk::Iwidgets::Selectiondialog.new.activate
+
+mainloop.join
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/shell.rb b/ext/tk/sample/tkextlib/iwidgets/sample/shell.rb
new file mode 100644
index 0000000000..c44b5554a6
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/shell.rb
@@ -0,0 +1,17 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+sh = Tk::Iwidgets::Shell.new(:modality=>:application,
+ :padx=>20, :pady=>20, :title=>'Shell')
+
+TkButton.new(:text=>'ACTIVATE', :padx=>7, :pady=>7,
+ :command=>proc{puts sh.activate}).pack(:padx=>10, :pady=>10)
+
+TkLabel.new(sh.child_site, :text=>'SHELL').pack
+TkButton.new(sh.child_site, :text=>'YES',
+ :command=>proc{sh.deactivate 'press YES'}).pack(:fill=>:x)
+TkButton.new(sh.child_site, :text=>'NO',
+ :command=>proc{sh.deactivate 'press NO'}).pack(:fill=>:x)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/spindate.rb b/ext/tk/sample/tkextlib/iwidgets/sample/spindate.rb
new file mode 100644
index 0000000000..17197a66b7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/spindate.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Spindate.new.pack(:padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/spinint.rb b/ext/tk/sample/tkextlib/iwidgets/sample/spinint.rb
new file mode 100644
index 0000000000..0bcdefb763
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/spinint.rb
@@ -0,0 +1,10 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+TkOption.add('*textBackground', 'white')
+
+Tk::Iwidgets::Spinint.new(:labeltext=>'Temperature', :labelpos=>:w, :width=>5,
+ :fixed=>true, :range=>[32, 212]).pack(:pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/spinner.rb b/ext/tk/sample/tkextlib/iwidgets/sample/spinner.rb
new file mode 100644
index 0000000000..295d38ee96
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/spinner.rb
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+class Spinner_demo < TkWindow
+ Months = %w(January February March April May June July August September October November December)
+
+ def block_input(c)
+ false
+ end
+
+ def spin_month(step)
+ index = Months.index(@spinner.get) + step
+ index = 11 if index < 0
+ index = 0 if index > 11
+
+ @spinner.value = Months[index]
+ end
+
+ def initialize(parent=nil)
+ @spinner = Tk::Iwidgets::Spinner.new(parent, :labeltext=>'Month : ',
+ :width=>10, :fixed=>10,
+ :validate=>proc{|c| block_input},
+ :decrement=>proc{spin_month -1},
+ :increment=>proc{spin_month 1})
+ @path = @spinner
+ @spinner.insert(0, Months[0])
+ end
+end
+
+Spinner_demo.new.pack(:padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/spintime.rb b/ext/tk/sample/tkextlib/iwidgets/sample/spintime.rb
new file mode 100644
index 0000000000..2c13884b94
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/spintime.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Spintime.new.pack(:padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook.rb b/ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook.rb
new file mode 100644
index 0000000000..6f1ecc4fa4
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook.rb
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+# Create the tabnotebook widget and pack it.
+tn = Tk::Iwidgets::Tabnotebook.new(:width=>300, :height=>100)
+tn.pack(:anchor=>:nw, :fill=>:both, :expand=>true,
+ :side=>:left, :padx=>10, :pady=>10)
+
+# Add two pages to the tabnotebook,
+# labelled "Page One" and "Page Two"
+tn.add(:label=>'Page One')
+tn.add(:label=>'Page Two')
+
+# Get the child site frames of these two pages.
+page1CS = tn.child_site(0)
+page2CS = tn.child_site('Page Two')
+
+# Create buttons on each page of the tabnotebook.
+TkButton.new(page1CS, :text=>'Button One').pack
+TkButton.new(page2CS, :text=>'Button Two').pack
+
+# Select the first page of the tabnotebook.
+tn.select(0)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook2.rb b/ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook2.rb
new file mode 100644
index 0000000000..4a5eef5a8f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/tabnotebook2.rb
@@ -0,0 +1,30 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+# Create the tabnotebook widget and pack it.
+tn = Tk::Iwidgets::Tabnotebook.new(:width=>300, :height=>100)
+tn.pack(:anchor=>:nw, :fill=>:both, :expand=>true,
+ :side=>:top, :padx=>10, :pady=>0)
+
+# Add two pages to the tabnotebook,
+# labelled "Page One" and "Page Two"
+tn.add(:label=>'Page One')
+tn.add(:label=>'Page Two')
+
+# Get the child site frames of these two pages.
+page1CS = tn.child_site(0)
+page2CS = tn.child_site('Page Two')
+
+# Create buttons on each page of the tabnotebook.
+TkButton.new(page1CS, :text=>'Button One').pack
+TkButton.new(page2CS, :text=>'Button Two').pack
+
+# Select the first page of the tabnotebook.
+tn.select(0)
+
+# Create the scrollbar
+# and the notebook together, then pack the scrollbar
+tn.xscrollbar(TkScrollbar.new).pack(:fill=>:x, :expand=>true, :padx=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/tabset.rb b/ext/tk/sample/tkextlib/iwidgets/sample/tabset.rb
new file mode 100644
index 0000000000..90be46b40b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/tabset.rb
@@ -0,0 +1,34 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+# Create a listbox with two items (one and two)
+l = TkListbox.new(:selectmode=>:single, :exportselection=>false).pack
+l.insert('end', 'one')
+l.insert('end', 'two')
+l.selection_set(0)
+
+# Define a proc that knows how to select an item
+# from a list given an index from the tabset -command callback.
+selectItem = proc{|item|
+ l.selection_clear(l.curselection)
+ l.selection_set(item)
+ l.see(item)
+}
+
+# Create a tabset, set its -command to call selectItem
+# Add two labels to the tabset (one and two).
+ts = Tk::Iwidgets::Tabset.new(:command=>selectItem)
+ts.add(:label=>1)
+ts.add(:label=>2)
+ts.select(0)
+ts.pack(:fill=>:x, :expand=>true)
+
+# Define a proc that knows how to select a tab
+# given a y pixel coordinate from the list..
+selectTab = proc{|y| ts.select(l.nearest(y)) }
+
+# bind button 1 press to the selectTab procedure.
+l.bind('ButtonPress-1', proc{|y| selectTab.call(y) }, '%y')
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/timeentry.rb b/ext/tk/sample/tkextlib/iwidgets/sample/timeentry.rb
new file mode 100644
index 0000000000..465939947b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/timeentry.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Tk::Iwidgets::Timeentry.new.pack
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/timefield.rb b/ext/tk/sample/tkextlib/iwidgets/sample/timefield.rb
new file mode 100644
index 0000000000..bb5945048d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/timefield.rb
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+tf = Tk::Iwidgets::Timefield.new(:command=>proc{puts(tf.get)})
+tf.pack(:fill=>:x, :expand=>true, :padx=>10, :pady=>10)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/toolbar.rb b/ext/tk/sample/tkextlib/iwidgets/sample/toolbar.rb
new file mode 100644
index 0000000000..355466eb1a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/toolbar.rb
@@ -0,0 +1,152 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+##########################################
+# icon images
+editcopy22 = TkPhotoImage.new(:data=><<'EOD')
+ R0lGODlhFgAWAIUAAPwCBBQSFPz+/DQyNISChDw6PMzKzMTGxERGRIyKjFxa
+ XMTCvKSmpHR2dPz6/Pz29PTq3MS2rPz69MTCxFxWVHx6dJyWjNzSzPz27Pzy
+ 7Pzu5PTm3NTKvIR+fJyGfHxuZHxqXNTCtPTq5PTi1PTezNS+rExOTFRORMyy
+ lPTaxOzWxOzSvNze3NTOxMy2nMyulMyqjAQCBAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAbY
+ QIBwSCwahYGkUnk0BgTQ6IAQaBKfUWhBYKhaAU+CgXAQIAyChLeJzSIQhcH6
+ GFaM0QtGY5kstqEODw8QEQELAhJTc08KBBMEFBUWDRcBE1pca20SGBkaEBsc
+ AY5maFRIAgoLHRQRHh8gIQFlZnByqA8ZGSIQIyQjJQEmYgJ5p2ACrK4gJx4g
+ KIZZAgdeAQ4ZI9kjKSor0AwEjeAs1S0cHAslLi4vMDDRWeRIfEsxMeET4ATy
+ VoYLC5fizXEiAR84BeMG+pEm8EsAFhAjSlR4hR6fLxiF0AkCACH+aENyZWF0
+ ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29yIDE5
+ OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cuZGV2
+ ZWxjb3IuY29tADs=
+EOD
+
+editcut22 = TkPhotoImage.new(:data=><<'EOD')
+ R0lGODlhFgAWAIMAAPwCBAQCBAwCBPz+/OTi5JyanOzq7DQyNGxqbAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAARbEMhJq704gxBE
+ 0Bf3cZo4kRJqBQNRfBucyudgvJS6VaxLzyMa6/bLiWA9HOg4VIIkL5vzuRkc
+ pkvRIIAorphJLzBW84WEuRZWp6uaT7J2Sh1Hit3OY/ZO7WvsEQAh/mhDcmVh
+ dGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAx
+ OTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRl
+ dmVsY29yLmNvbQA7
+EOD
+
+editpaste22 = TkPhotoImage.new(:data=><<'EOD')
+ R0lGODlhFgAWAIYAAPwCBBQWFDw6FHRuFGRaBFxSBAQCBAQKBCQiBIx6HPz6
+ /NTOfKyiXDQuFOTm5Pz+/Ozu7PTq5Pz63PTyxNTOjKSeRExGLMTGxMzKzNTS
+ 1NTW1Dw2NKSmpKyqrKSipJyanNzWlLy6ZLSuVIx6FISChIyKhJSSlCQiJLS2
+ tDw6NDQyNCQiFCQmHBQSDGRiZHRydGxubHx6dGxqbFxeXGRmZFxaXCwuLOzq
+ 7KyurHx+fDwmFEQuFCweFCQWDBQODBwaHBweHKSinJSWlOTi5JyepHR2dDw6
+ PBQSFNze3ERGRIyKjIyOjISGhPz29Pzy7MS2rMzOzFRWVHx2dHxybDQiFPz2
+ 7Pzu5PTq3PTm1NTCtJyGdHxuZHxqXPzq3PTaxNS6pFxWVFRKRNS2nPTi1PTS
+ tNSulNzOxNSynMymhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAA
+ LAAAAAAWABYAAAf/gACCgwABAgMEBYSLggaOjgcICQoLDA2Pj4MGDg8QEZ4F
+ DxITFBUWFxcYGRobjQ8cHR4fCQ8gCyEiFSMWJCUkJieNEB4dKB4pKissK8wr
+ LS4vMDHBAAYQHx8dFx0fJDIzNDU0M+IyHzaNNyg43Ng5Ojs7Ojw9Pj9AMkCN
+ DiZB/h9CSOx4QLCgihItqBkYgqIDESElitAYWJCgkQcXjjRCgi1Ihw4BB5LA
+ QOLCgyQYHihpUU3DBw5ElpAgAYNixSRJjKjQaECDCRPZPDB5IbIGSQwKLnh4
+ wbInLA4kmJB4oaPiAwVNnER40hRK1BIAaVatUZJEFCkmpmjgCeWDCalFe4q4
+ oFKwSRUrEa5gycLzwq8lUnPQ4PEgSpYcUZ5o2cIlS1O/JHLEDdfjQZMIVrpg
+ weLFy5e+M6WSmBGlxYMYYBRzCaOFi5imHWBIfOEiShLTVjaP6eyFTBmN1TA5
+ OvLDjJksWb58OVMGDRqWjAYdmU79SIvpjqJr104nEAAh/mhDcmVhdGVkIGJ5
+ IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5
+ OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29y
+ LmNvbQA7
+EOD
+
+editdelete22 = TkPhotoImage.new(:data=><<'EOD')
+ R0lGODlhFgAWAIYAAASC/FRSVExKTERCRDw6PDQyNCwuLBweHBwaHAwODAwK
+ DAQCBExOTNze3NTW1MTGxLS2tJyanPz+/Ozu7BQSFCwqLDw+POTi5PTu7MzK
+ xIR+fCQmJPz6/Oze1NTGvPz69Pzy7Pz29LyyrPy+vPyupPTm1BQWFIQCBPwC
+ BMS6rPzSzNTOxPTi1NS+rPTezNzOxPTizOzWxMy2pOzaxMy2nPTaxOzOtMyy
+ nOzSvMyqjPx+fOzGpMSihPTq3OzKrOTCpNzKxNTCtAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAA
+ LAAAAAAWABYAAAf8gACCAQIDBAUGBwgJCgsLgpCRAAwNlZYODxALEY+SkAMN
+ EqKjEw0UD5yegqCjrRMVEqidkgWhraMWF7GptLa3EgEWFRSOnhW+vxgZEBqz
+ kBvItxwdHryRCNGjHyAhHSLOgtgSI60c2yQjJd+eJqEnKK0hJCgnJSngAO0S
+ F+8qEvL0VrBogW+BLX4oVKgIyMIFQU8KfDV4R+8FDBcxZBREthAFiRIsOsyg
+ sVEUh4Un3pGoUcPGjZInK65QicPlxg8oX5RwqNJGjo0hdJwQ6EIkjRM6dvDY
+ CKIHSBc1Ztjw4eOH0oIrsgIJEqSFDBo0cuTgsdSTo7No0xYTZCcQACH+aENy
+ ZWF0ZWQgYnkgQk1QVG9HSUYgUHJvIHZlcnNpb24gMi41DQqpIERldmVsQ29y
+ IDE5OTcsMTk5OC4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCmh0dHA6Ly93d3cu
+ ZGV2ZWxjb3IuY29tADs=
+EOD
+
+text22 = TkPhotoImage.new(:data=><<'EOD')
+ R0lGODlhFgAWAIQAAPwCBAQCBBwaHAwKDBQSFLy+vLS2tJSWlBQWFKyqrFRS
+ VCwqLDQyNNTS1GxqbFxaXJyanIyOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAWABYAAAVcICCOZGmK
+ QSoMaZsShBsQBdAapHvgaIDUqUPJlRjSbAoT0fRDKgODRbF0PLUYjZO2F2Bs
+ t9evNix+dsvDlGKK5jraudQb7qbX6a2HEJ+ycyF+LRE8ZTI+fX5oGCEAIf5o
+ Q3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2ZWxD
+ b3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDovL3d3
+ dy5kZXZlbGNvci5jb20AOw==
+EOD
+
+##########################################
+
+bmp_dir = File.join(File.dirname(File.expand_path(__FILE__)),
+ '../catalog_demo/images')
+
+##########################################
+
+status_var = TkVariable.new
+radio_var = TkVariable.new
+check_var1 = TkVariable.new
+check_var2 = TkVariable.new
+
+tb = Tk::Iwidgets::Toolbar.new(:helpvariable=>status_var)
+
+##########################################
+
+tb.add(:button, :helpstr=>'Copy It', :image=>editcopy22,
+ :balloonstr=>'Copy', :command=>proc{puts 'Copy It'})
+
+tb.add(:button, :helpstr=>'Cut It', :image=>editcut22,
+ :balloonstr=>'Cut', :command=>proc{puts 'Cut It'})
+
+tb.add(:button, :helpstr=>'Paste It', :image=>editpaste22,
+ :balloonstr=>'Paste', :command=>proc{puts 'Paste It'})
+
+tb.add(:button, :helpstr=>'Delete It', :image=>editdelete22,
+ :balloonstr=>'Delete', :command=>proc{puts 'Delete It'})
+
+#--------------------------------
+
+tb.add(:frame, :borderwidth=>1, :width=>10, :height=>10)
+
+#--------------------------------
+
+tb.add(:radiobutton, :variable=>radio_var, :value=>'Box',
+ :bitmap=>"@#{bmp_dir}/box.xbm",
+ :helpstr=>'Radio Button #1', :balloonstr=>'Radio',
+ :command=>proc{puts 'Radio Button "Box"'})
+
+tb.add(:radiobutton, :variable=>radio_var, :value=>'Line',
+ :bitmap=>"@#{bmp_dir}/line.xbm",
+ :helpstr=>'Radio Button #2', :balloonstr=>'Radio',
+ :command=>proc{puts 'Radio Button "Line"'})
+
+tb.add(:radiobutton, :variable=>radio_var, :value=>'Oval',
+ :bitmap=>"@#{bmp_dir}/oval.xbm",
+ :helpstr=>'Radio Button #3', :balloonstr=>'Radio',
+ :command=>proc{puts 'Radio Button "Oval"'})
+
+#--------------------------------
+
+tb.add(:frame, :borderwidth=>1, :width=>10, :height=>10)
+
+#--------------------------------
+
+tb.add(:checkbutton, :variable=>check_var1, :onvalue=>'yes', :offvalue=>'no',
+ :image=>text22, :command=>proc{puts 'Checkbutton 1'})
+
+tb.add(:checkbutton, :variable=>check_var2, :onvalue=>'yes', :offvalue=>'no',
+ :bitmap=>"@#{bmp_dir}/points.xbm", :command=>proc{puts 'Checkbutton 2'})
+
+tb.pack(:side=>:top, :anchor=>:nw)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/iwidgets/sample/watch.rb b/ext/tk/sample/tkextlib/iwidgets/sample/watch.rb
new file mode 100644
index 0000000000..808c798aec
--- /dev/null
+++ b/ext/tk/sample/tkextlib/iwidgets/sample/watch.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+require 'tk'
+require 'tkextlib/iwidgets'
+
+Thread.new{
+ trap('INT') {puts 'catch SIGINT'}
+ sleep 5
+ trap('INT', 'DEFAULT')
+}
+
+Tk::Iwidgets::Watch.new(:state=>:disabled, :showampm=>:no,
+ :width=>155, :height=>155){|w|
+ w.pack(:padx=>10, :pady=>10, :fill=>:both, :expand=>true)
+ # TkTimer.new(1000, -1, proc{w.show; Tk.update}).start
+ TkTimer.new(25, -1, proc{w.show; Tk.update}).start
+}
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tcllib/Orig_LICENSE.txt b/ext/tk/sample/tkextlib/tcllib/Orig_LICENSE.txt
new file mode 100644
index 0000000000..272853870c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tcllib/Orig_LICENSE.txt
@@ -0,0 +1,46 @@
+
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ >>> The following text is the original 'license.term' of tklib <<<
+ >>> extension. <<<
+ >>> Original Tcl files are not include in this directry, because <<<
+ >>> of all of them are rewrited to Ruby files. <<<
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+This software is copyrighted by Ajuba Solutions and other parties.
+The following terms apply to all files associated with the software unless
+explicitly disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
diff --git a/ext/tk/sample/tkextlib/tcllib/datefield.rb b/ext/tk/sample/tkextlib/tcllib/datefield.rb
new file mode 100644
index 0000000000..cfeca0c6de
--- /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..053b0de085
--- /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..33a6f29940
--- /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..2b5c7642bb
--- /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..8f8c3eb880
--- /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/tile/Orig_LICENSE.txt b/ext/tk/sample/tkextlib/tile/Orig_LICENSE.txt
new file mode 100644
index 0000000000..2326ef21fa
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/Orig_LICENSE.txt
@@ -0,0 +1,30 @@
+
+ ######################################################################
+ ### The following text is the original 'license.terms' of tile ###
+ ### extension. ###
+ ######################################################################
+
+
+LICENSE ("MIT-style")
+
+This software is Copyright (C) 2003 Joe English and other parties.
+
+The following terms apply to all files associated with this software
+unless explicitly disclaimed in individual files.
+
+The author(s) hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS for a PARTICULAR PURPOSE. IN NO EVENT
+shall the AUTHORS of THIS SOFTWARE be LIABLE to ANY PARTY for
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, or CONSEQUENTIAL DAMAGES
+arising out of the USE of THIS SOFTWARE and its DOCUMENTATION.
diff --git a/ext/tk/sample/tkextlib/tile/demo.rb b/ext/tk/sample/tkextlib/tile/demo.rb
new file mode 100644
index 0000000000..633a072460
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/demo.rb
@@ -0,0 +1,983 @@
+#!/usr/bin/env ruby
+#
+# Demo for 'tile' package.
+#
+require 'tk'
+
+demodir = File.dirname($0)
+themesdir = File.join(demodir, 'themes')
+Tk::AUTO_PATH.lappend('.', demodir, themesdir)
+
+Dir.foreach(themesdir){|name|
+ next if name == '.' || name == '..'
+ dir = File.join(themesdir, name)
+ Tk::AUTO_PATH.lappend(dir) if File.directory?(dir)
+}
+
+require 'tkextlib/tile'
+
+def version?(ver)
+ TkPackage.vcompare(Tk::Tile.package_version, ver) >= 0
+end
+
+# define Tcl/Tk procedures for compatibility
+Tk::Tile.__define_LoadImages_proc_for_compatibility__!
+Tk::Tile::Style.__define_wrapper_proc_for_compatibility__!
+
+unless Tk::Tile::Style.theme_names.include?('step')
+ Tk::Tile::Style.theme_create('step')
+end
+
+Tk.load_tclscript(File.join(demodir, 'toolbutton.tcl'))
+Tk.load_tclscript(File.join(demodir, 'repeater.tcl'))
+
+# This forces an update of the available packages list. It's required
+# for package names to find the themes in demos/themes/*.tcl
+## Tk.tk_call(TkPackage.unknown_proc, 'Tcl', TkPackage.provide('Tcl'))
+## --> This doesn't work.
+## Because, unknown_proc may be "command + some arguments".
+Tk.ip_eval("#{TkPackage.unknown_proc} Tcl #{TkPackage.provide('Tcl')}")
+
+TkRoot.new{
+ title 'Tile demo'
+ iconname 'Tile demo'
+}
+
+# The descriptive names of the builtin themes.
+$THEMELIST = [
+ ['default', 'Default'],
+ ['classic', 'Classic'],
+ ['alt', 'Revitalized'],
+ ['winnative', 'Windows native'],
+ ['xpnative', 'XP Native'],
+ ['aqua', 'Aqua'],
+]
+
+$V = TkVariable.new_hash(:THEME => 'default',
+ :COMPOUND => 'top',
+ :CONSOLE => false,
+ :MENURADIO1 => 'One',
+ :MENUCHECK1 => true,
+ :PBMODE => 'determinate',
+ :SELECTED => true,
+ :CHOICE => 2)
+
+# Add in any available loadable themes.
+TkPackage.names.find_all{|n| n =~ /^(tile|ttk)::theme::/}.each{|pkg|
+ name = pkg.split('::')[-1]
+ unless $THEMELIST.assoc(name)
+ $THEMELIST << [name, Tk.tk_call('string', 'totitle', name)]
+ end
+}
+
+# Add theme definition written by ruby
+$RUBY_THEMELIST = []
+begin
+ load(File.join(demodir, 'themes', 'kroc.rb'), true)
+rescue => e
+raise e
+ $RUBY_THEMELIST << ['kroc-rb', 'Kroc (by Ruby)', false]
+else
+ $RUBY_THEMELIST << ['kroc-rb', 'Kroc (by Ruby)', true]
+end
+
+def makeThemeControl(parent)
+ c = Tk::Tile::Labelframe.new(parent, :text=>'Theme')
+ $THEMELIST.each{|theme, name|
+ b = Tk::Tile::Radiobutton.new(c, :text=>name, :value=>theme,
+ :variable=>$V.ref(:THEME),
+ :command=>proc{setTheme(theme)})
+ b.grid(:sticky=>:ew)
+ unless (TkPackage.names.find{|n| n =~ /(tile|ttk)::theme::#{theme}/})
+ b.ttk_state(:disabled)
+ end
+ }
+ $RUBY_THEMELIST.each{|theme, name, available|
+ b = Tk::Tile::Radiobutton.new(c, :text=>name, :value=>theme,
+ :variable=>$V.ref(:THEME),
+ :command=>proc{setTheme(theme)})
+ b.grid(:sticky=>:ew)
+ b.ttk_state(:disabled) unless available
+ }
+ c
+end
+
+def makeThemeMenu(parent)
+ m = TkMenu.new(parent)
+ $THEMELIST.each{|theme, name|
+ m.add(:radiobutton, :label=>name, :variable=>$V.ref(:THEME),
+ :value=>theme, :command=>proc{setTheme(theme)})
+ unless (TkPackage.names.find{|n| n =~ /(tile|ttk)::theme::#{theme}/})
+ m.entryconfigure(:end, :state=>:disabled)
+ end
+ }
+ $RUBY_THEMELIST.each{|theme, name, available|
+ m.add(:radiobutton, :label=>name, :variable=>$V.ref(:THEME),
+ :value=>theme, :command=>proc{setTheme(theme)})
+ m.entryconfigure(:end, :state=>:disabled) unless available
+ }
+ m
+end
+
+def setTheme(theme)
+ if (pkg = TkPackage.names.find{|n| n =~ /(tile|ttk)::theme::#{theme}/})
+ unless Tk::Tile::Style.theme_names.find{|n| n == theme}
+ TkPackage.require(pkg)
+ end
+ end
+ Tk::Tile::Style.theme_use(theme)
+end
+
+#
+# Load icons...
+#
+$BUTTONS = ['open', 'new', 'save']
+$CHECKBOXES = ['bold', 'italic']
+$ICON = {}
+
+def loadIcons(file)
+ Tk.load_tclscript(file)
+ img_data = TkVarAccess.new('ImgData')
+ img_data.keys.each{|icon|
+ $ICON[icon] = TkPhotoImage.new(:data=>img_data[icon])
+ }
+end
+
+loadIcons(File.join(demodir, 'iconlib.tcl'))
+
+#
+# Utilities:
+#
+def foreachWidget(wins, cmd)
+ wins.each{|w|
+ cmd.call(w)
+ foreachWidget(w.winfo_children, cmd)
+ }
+end
+
+# sbstub
+# Used as the :command option for a scrollbar,
+# updates the scrollbar's position.
+#
+def sbstub(sb, cmd, num, units = 'units')
+ num = TkComm.number(num)
+ case cmd.to_s
+ when 'moveto'
+ sb.set(num, num+0.5)
+
+ when 'scroll'
+ if units.to_s == 'pages'
+ delta = 0.2
+ else
+ delta = 0.05
+ end
+ current = sb.get
+ sb.set(current[0] + delta * num, current[1] + delta * num)
+ end
+end
+
+# ... for debugging:
+TkBindTag::ALL.bind('ButtonPress-3', proc{|w| $W = w}, '%W')
+TkBindTag::ALL.bind('Control-ButtonPress-3', proc{|w| w.set_focus}, '%W')
+
+def showHelp()
+ Tk.messageBox(:message=>'No help yet...')
+end
+
+#
+# See toolbutton.tcl.
+TkOption.add('*Toolbar.relief', :groove)
+TkOption.add('*Toolbar.borderWidth', 2)
+
+TkOption.add('*Toolbar.Button.Pad', 2)
+
+$ROOT = Tk.root
+$BASE = $ROOT
+Tk.destroy(*($ROOT.winfo_children))
+
+$TOOLBARS = []
+
+#
+# Toolbar button standard vs. tile comparison:
+#
+def makeToolbars
+ #
+ # Tile toolbar:
+ #
+ tb = Tk::Tile::Frame.new($BASE, :class=>'Toolbar')
+ $TOOLBARS << tb
+ i = 0
+ $BUTTONS.each{|icon|
+ i += 1
+ Tk::Tile::Button.new(tb, :text=>icon, :image=>$ICON[icon],
+ :compound=>$V[:COMPOUND],
+ :style=>:Toolbutton).grid(:row=>0, :column=>i,
+ :sticky=>:news)
+ }
+ $CHECKBOXES.each{|icon|
+ i += 1
+ Tk::Tile::Checkbutton.new(tb, :text=>icon, :image=>$ICON[icon],
+ :variable=>$V.ref(icon),
+ :compound=>$V[:COMPOUND],
+ :style=>:Toolbutton).grid(:row=>0, :column=>i,
+ :sticky=>:news)
+ }
+
+ mb = Tk::Tile::Menubutton.new(tb, :text=>'toolbar', :image=>$ICON['file'],
+ :compound=>$V[:COMPOUND])
+ mb.configure(:menu=>makeCompoundMenu(mb))
+ i += 1
+ mb.grid(:row=>0, :column=>i, :sticky=>:news)
+
+ i += 1
+ tb.grid_columnconfigure(i, :weight=>1)
+
+ #
+ # Standard toolbar:
+ #
+ tb = TkFrame.new($BASE, :class=>'Toolbar')
+ $TOOLBARS << tb
+ i = 0
+ $BUTTONS.each{|icon|
+ i += 1
+ TkButton.new(tb, :text=>icon, :image=>$ICON[icon],
+ :compound=>$V[:COMPOUND], :relief=>:flat,
+ :overrelief=>:raised).grid(:row=>0, :column=>i,
+ :sticky=>:news)
+ }
+ $CHECKBOXES.each{|icon|
+ i += 1
+ TkCheckbutton.new(tb, :text=>icon, :image=>$ICON[icon],
+ :variable=>$V.ref(icon), :compound=>$V[:COMPOUND],
+ :indicatoron=>false, :selectcolor=>'', :relief=>:flat,
+ :overrelief=>:raised).grid(:row=>0, :column=>i,
+ :sticky=>:news)
+ }
+
+ mb = TkMenubutton.new(tb, :text=>'toolbar', :image=>$ICON['file'],
+ :compound=>$V[:COMPOUND])
+ mb.configure(:menu=>makeCompoundMenu(mb))
+ i += 1
+ mb.grid(:row=>0, :column=>i, :sticky=>:news)
+
+ i += 1
+ tb.grid_columnconfigure(i, :weight=>1)
+end
+
+#
+# Toolbar :compound control:
+#
+def makeCompoundMenu(mb)
+ menu = TkMenu.new(mb)
+ %w(text image none top bottom left right center).each{|str|
+ menu.add(:radiobutton, :label=>Tk.tk_call('string', 'totitle', str),
+ :variable=>$V.ref(:COMPOUND), :value=>str,
+ :command=>proc{ changeToolbars() })
+ }
+ menu
+end
+
+makeToolbars()
+
+## CONTROLS
+control = Tk::Tile::Frame.new($BASE)
+
+#
+# Overall theme control:
+#
+makeThemeControl(control).grid(:sticky=>:news, :padx=>6, :ipadx=>6)
+control.grid_rowconfigure(99, :weight=>1)
+
+def changeToolbars
+ foreachWidget($TOOLBARS,
+ proc{|w|
+ begin
+ w.compound($V[:COMPOUND])
+ rescue
+ end
+ })
+end
+
+def scrolledWidget(parent, klass, themed, *args)
+ if themed
+ f = Tk::Tile::Frame.new(parent)
+ t = klass.new(f, *args)
+ vs = Tk::Tile::Scrollbar.new(f)
+ hs = Tk::Tile::Scrollbar.new(f)
+ else
+ f = TkFrame.new(parent)
+ t = klass.new(f, *args)
+ vs = TkScrollbar.new(f)
+ hs = TkScrollbar.new(f)
+ end
+ t.yscrollbar(vs)
+ t.xscrollbar(hs)
+
+ TkGrid.configure(t, vs, :sticky=>:news)
+ TkGrid.configure(hs, 'x', :sticky=>:news)
+ TkGrid.rowconfigure(f, 0, :weight=>1)
+ TkGrid.columnconfigure(f, 0, :weight=>1)
+
+ [f, t]
+end
+
+#
+# Notebook demonstration:
+#
+def makeNotebook
+ nb = Tk::Tile::Notebook.new($BASE, :padding=>6)
+ nb.enable_traversal
+ client = Tk::Tile::Frame.new(nb)
+ nb.add(client, :text=>'Demo', :underline=>0)
+ nb.select(client)
+
+ scales = Tk::Tile::Frame.new(nb)
+ nb.add(scales, :text=>'Scales')
+ combo = Tk::Tile::Frame.new(nb)
+ nb.add(combo, :text=>'Combobox', :underline=>7)
+ tree = Tk::Tile::Frame.new(nb)
+ nb.add(tree, :text=>'Tree')
+ others = Tk::Tile::Frame.new(nb)
+ nb.add(others, :text=>'Others', :underline=>4)
+
+ [nb, client, scales, combo, tree, others]
+end
+
+nb, client, scales, combo, tree, others = makeNotebook()
+
+#
+# Side-by side check, radio, and menu button comparison:
+#
+def fillMenu(menu)
+ %w(above below left right flush).each{|dir|
+ menu.add(:command, :label=>Tk.tk_call('string', 'totitle', dir),
+ :command=>proc{ menu.winfo_parent.direction(dir) })
+ }
+ menu.add(:cascade, :label=>'Submenu', :menu=>(submenu = TkMenu.new(menu)))
+ submenu.add(:command, :label=>'Subcommand 1')
+ submenu.add(:command, :label=>'Subcommand 2')
+ submenu.add(:command, :label=>'Subcommand 3')
+
+ menu.add(:separator)
+ menu.add(:command, :label=>'Quit', :command=>proc{Tk.root.destroy})
+end
+
+l = Tk::Tile::Labelframe.new(client, :text=>'Themed', :padding=>6)
+r = TkLabelframe.new(client, :text=>'Standard', :padx=>6, :pady=>6)
+
+## Styled frame
+cb = Tk::Tile::Checkbutton.new(l, :text=>'Checkbutton',
+ :variable=>$V.ref(:SELECTED), :underline=>2)
+rb1 = Tk::Tile::Radiobutton.new(l, :text=>'One', :variable=>$V.ref(:CHOICE),
+ :value=>1, :underline=>0)
+rb2 = Tk::Tile::Radiobutton.new(l, :text=>'Two', :variable=>$V.ref(:CHOICE),
+ :value=>2)
+rb3 = Tk::Tile::Radiobutton.new(l, :text=>'Three',
+ :variable=>$V.ref(:CHOICE),
+ :value=>3, :underline=>0)
+btn = Tk::Tile::Button.new(l, :text=>'Button', :underline=>0)
+
+mb = Tk::Tile::Menubutton.new(l, :text=>'Menubutton', :underline=>2)
+m = TkMenu.new(mb)
+mb.menu(m)
+fillMenu(m)
+
+$entryText = TkVariable.new('Entry widget')
+e = Tk::Tile::Entry.new(l, :textvariable=>$entryText)
+e.selection_range(6, :end)
+
+ltext_f, ltext = scrolledWidget(l, TkText, true,
+ :width=>12, :height=>5, :wrap=>:none)
+# NOTE TO MAINTAINERS:
+# The checkbuttons are -sticky ew / -expand x on purpose:
+# it demonstrates one of the differences between TCheckbuttons
+# and standard checkbuttons.
+#
+Tk.grid(cb, :sticky=>:ew)
+Tk.grid(rb1, :sticky=>:ew)
+Tk.grid(rb2, :sticky=>:ew)
+Tk.grid(rb3, :sticky=>:ew)
+Tk.grid(btn, :sticky=>:ew, :padx=>2, :pady=>2)
+Tk.grid(mb, :sticky=>:ew, :padx=>2, :pady=>2)
+Tk.grid(e, :sticky=>:ew, :padx=>2, :pady=>2)
+Tk.grid(ltext_f, :sticky=>:news)
+
+TkGrid.columnconfigure(l, 0, :weight=>1)
+TkGrid.rowconfigure(l, 7, :weight=>1) # text widget (grid is a PITA)
+
+## Orig frame
+cb = TkCheckbutton.new(r, :text=>'Checkbutton', :variable=>$V.ref(:SELECTED))
+rb1 = TkRadiobutton.new(r, :text=>'One',
+ :variable=>$V.ref(:CHOICE), :value=>1)
+rb2 = TkRadiobutton.new(r, :text=>'Two', :variable=>$V.ref(:CHOICE),
+ :value=>2, :underline=>1)
+rb3 = TkRadiobutton.new(r, :text=>'Three',
+ :variable=>$V.ref(:CHOICE), :value=>3)
+btn = TkButton.new(r, :text=>'Button')
+
+mb = TkMenubutton.new(r, :text=>'Menubutton', :underline=>3, :takefocus=>true)
+m = TkMenu.new(mb)
+mb.menu(m)
+$V[:rmbIndicatoron] = mb.indicatoron
+m.add(:checkbutton, :label=>'Indicator?', #'
+ :variable=>$V.ref(:rmbIndicatoron),
+ :command=>proc{mb.indicatoron($V[:rmbIndicatoron])})
+m.add(:separator)
+fillMenu(m)
+
+e = TkEntry.new(r, :textvariable=>$entryText)
+
+rtext_f, rtext = scrolledWidget(r, TkText, false,
+ :width=>12, :height=>5, :wrap=>:none)
+
+Tk.grid(cb, :sticky=>:ew)
+Tk.grid(rb1, :sticky=>:ew)
+Tk.grid(rb2, :sticky=>:ew)
+Tk.grid(rb3, :sticky=>:ew)
+Tk.grid(btn, :sticky=>:ew, :padx=>2, :pady=>2)
+Tk.grid(mb, :sticky=>:ew, :padx=>2, :pady=>2)
+Tk.grid(e, :sticky=>:ew, :padx=>2, :pady=>2)
+Tk.grid(rtext_f, :sticky=>:news)
+
+TkGrid.columnconfigure(l, 0, :weight=>1)
+TkGrid.rowconfigure(l, 7, :weight=>1) # text widget (grid is a PITA)
+
+Tk.grid(l, r, :sticky=>:news, :padx=>6, :pady=>6)
+TkGrid.rowconfigure(client, 0, :weight=>1)
+TkGrid.columnconfigure(client, [0, 1], :weight=>1)
+
+#
+# Add some text to the text boxes:
+#
+msgs = [
+"The cat crept into the crypt, crapped and crept out again",
+"Peter Piper picked a peck of pickled peppers",
+"How much wood would a woodchuck chuck if a woodchuck could chuck wood",
+"He thrusts his fists against the posts and still insists he sees the ghosts",
+"Who put the bomb in the bom-b-bom-b-bom,",
+"Is this your sister's sixth zither, sir?",
+"Who put the ram in the ramalamadingdong?",
+"I am not the pheasant plucker, I'm the pheasant plucker's mate."
+]
+
+nmsgs = msgs.size
+(0...50).each{|n|
+ msg = msgs[n % nmsgs]
+ ltext.insert(:end, "#{n}: #{msg}\n")
+ rtext.insert(:end, "#{n}: #{msg}\n")
+}
+#
+# Scales and sliders pane:
+#
+l = Tk::Tile::Labelframe.new(scales, :text=>'Themed', :padding=>6)
+r = TkLabelframe.new(scales, :text=>'Standard', :padx=>6, :pady=>6)
+
+if version?('0.6')
+
+ # thremed frame
+ scale = Tk::Tile::Scale.new(l, :orient=>:horizontal, :from=>0, :to=>100,
+ :variable=>$V.ref(:SCALE))
+ vscale = Tk::Tile::Scale.new(l, :orient=>:vertical, :from=>0, :to=>100,
+ :variable=>$V.ref(:VSCALE))
+ progress = Tk::Tile::Progressbar.new(l, :orient=>:horizontal, :maximum=>100)
+ vprogress = Tk::Tile::Progressbar.new(l, :orient=>:vertical, :maximum=>100)
+
+ if true
+ def progress.inverted(w, value)
+ if w.mode == 'indeterminate'
+ w.value(value)
+ else
+ w.value(w.maximum - value)
+ end
+ end
+ scale.command {|value| progress.value(value)}
+ vscale.command {|value| progress.inverted(vprogress, value) }
+ else
+ # This would also work, but the Tk scale widgets
+ # in the right hand pane cause some interference when
+ # in autoincrement/indeterminate mode.
+ #
+ progress.variable $V.ref(:SCALE)
+ vprogress.variable $V.ref(:VSCALE)
+ end
+
+ scale.set(50)
+ vscale.set(50)
+
+ lmode = Tk::Tile::Label.new(l, :text=>'Progress bar mode')
+ pbmode0 = Tk::Tile::Radiobutton.new(l, :variable=>$V.ref(:PBMODE),
+ :text=>'determinate', :value=>'determinate',
+ :command=>proc{pbMode(progress, vprogress)})
+ pbmode1 = Tk::Tile::Radiobutton.new(l, :variable=>$V.ref(:PBMODE),
+ :text=>'indeterminate', :value=>'indeterminate',
+ :command=>proc{pbMode(progress, vprogress)})
+ def pbMode(progress, vprogress)
+ if vprogress.mode != $V[:PBMODE]
+ vprogress.value(vprogress.maximum - vprogress.value)
+ end
+
+ progress.mode $V[:PBMODE]
+ vprogress.mode $V[:PBMODE]
+ end
+
+ start = Tk::Tile::Button.new(l, :text=>"Start",
+ :command=>proc{pbStart(progress, vprogress)})
+ def pbStart(progress, vprogress)
+ # $V[:PBMODE] = 'indeterminate'
+ pbMode(progress, vprogress)
+ progress.start 10
+ vprogress.start
+ end
+
+ stop = Tk::Tile::Button.new(l, :text=>'Stop',
+ :command=>proc{pbStop(progress, vprogress)})
+ def pbStop(progress, vprogress)
+ progress.stop
+ vprogress.stop
+ end
+
+ Tk.grid(scale, :columnspan=>2, :sticky=>'ew')
+ Tk.grid(progress, :columnspan=>2, :sticky=>'ew')
+ Tk.grid(vscale, vprogress, :sticky=>'nws')
+
+ Tk.grid(lmode, :sticky=>'we', :columnspan=>2)
+ Tk.grid(pbmode0, :sticky=>'we', :columnspan=>2)
+ Tk.grid(pbmode1, :sticky=>'we', :columnspan=>2)
+ Tk.grid(start, :sticky=>'we', :columnspan=>2)
+ Tk.grid(stop, :sticky=>'we', :columnspan=>2)
+
+ l.grid_columnconfigure(0, :weight=>1)
+ l.grid_columnconfigure(1, :weight=>1)
+ l.grid_rowconfigure(99, :weight=>1)
+
+ # standard frame
+ TkScale.new(r, :orient=>:horizontal, :from=>0, :to=>100,
+ :variable=>$V.ref(:SCALE)).grid(:sticky=>'news')
+ TkScale.new(r, :orient=>:vertical, :from=>0, :to=>100,
+ :variable=>$V.ref(:VSCALE)).grid(:sticky=>'nws')
+
+ r.grid_columnconfigure(0, :weight=>1)
+ r.grid_columnconfigure(1, :weight=>1)
+ r.grid_rowconfigure(99, :weight=>1)
+
+else # tile 0.5 or earlier
+
+ # themed frame
+ scale = Tk::Tile::Scale.new(l, :variable=>$V.ref(:SCALE),
+ :orient=>:horizontal, :from=>0, :to=>100)
+ vscale = Tk::Tile::Scale.new(l, :variable=>$V.ref(:VSCALE),
+ :orient=>:vertical, :from=>-25, :to=>25)
+
+ progress = Tk::Tile::Progress.new(l,
+ :orient=>:horizontal, :from=>0, :to=>100)
+ vprogress = Tk::Tile::Progress.new(l,
+ :orient=>:vertical, :from=>-25, :to=>25)
+
+ if true
+ scale.command{|value| progress.set(value)}
+ vscale.command{|value| vprogress.set(value)}
+ else # this would also work. (via TkVariable#trace)
+ v1 = scale.variable
+ v2 = vscale.variable
+ v1.trace('w', proc{ progress.set(v1.value) })
+ v2.trace('w', proc{ vprogress.set(v2.value) })
+ end
+
+ Tk.grid(scale, :columnspan=>2, :sticky=>:ew)
+ Tk.grid(progress, :columnspan=>2, :sticky=>:ew)
+ Tk.grid(vscale, vprogress, :sticky=>:nws)
+ TkGrid.columnconfigure(l, 0, :weight=>1)
+ TkGrid.columnconfigure(l, 1, :weight=>1)
+
+ # standard frame
+ TkScale.new(r, :variable=>$V.ref(:SCALE),
+ :orient=>:horizontal, :from=>0, :to=>100).grid(:sticky=>'news')
+ TkScale.new(r, :variable=>$V.ref(:VSCALE),
+ :orient=>:vertical, :from=>-25, :to=>25).grid(:sticky=>'nws')
+
+ TkGrid.columnconfigure(r, 0, :weight=>1)
+ TkGrid.columnconfigure(r, 1, :weight=>1)
+end
+
+# layout frames
+Tk.grid(l, r, :sticky=>'nwes', :padx=>6, :pady=>6)
+scales.grid_columnconfigure(0, :weight=>1)
+scales.grid_columnconfigure(1, :weight=>1)
+scales.grid_rowconfigure(0, :weight=>1)
+
+#
+# Command box:
+#
+cmd = Tk::Tile::Frame.new($BASE)
+b_close = Tk::Tile::Button.new(cmd, :text=>'Close',
+ :underline=>0, :default=>:normal,
+ :command=>proc{Tk.root.destroy})
+b_help = Tk::Tile::Button.new(cmd, :text=>'Help', :underline=>0,
+ :default=>:normal, :command=>proc{showHelp()})
+Tk.grid('x', b_close, b_help, :pady=>[6, 4], :padx=>4)
+TkGrid.columnconfigure(cmd, 0, :weight=>1)
+
+#
+# Set up accelerators:
+#
+$ROOT.bind('KeyPress-Escape', proc{Tk.event_generate(b_close, '<Invoke>')})
+$ROOT.bind('<Help>', proc{Tk.event_generate(b_help, '<Invoke>')})
+Tk::Tile::KeyNav.enableMnemonics($ROOT)
+Tk::Tile::KeyNav.defaultButton(b_help)
+
+Tk.grid($TOOLBARS[0], '-', :sticky=>:ew)
+Tk.grid($TOOLBARS[1], '-', :sticky=>:ew)
+Tk.grid(control, nb, :sticky=>:news)
+Tk.grid(cmd, '-', :sticky=>:ew)
+TkGrid.columnconfigure($ROOT, 1, :weight=>1)
+TkGrid.rowconfigure($ROOT, 2, :weight=>1)
+
+#
+# Add a menu
+#
+menu = TkMenu.new($BASE)
+$ROOT.menu(menu)
+m_file = TkMenu.new(menu, :tearoff=>0)
+menu.add(:cascade, :label=>'File', :underline=>0, :menu=>m_file)
+m_file.add(:command, :label=>'Open', :underline=>0,
+ :compound=>:left, :image=>$ICON['open'])
+m_file.add(:command, :label=>'Save', :underline=>0,
+ :compound=>:left, :image=>$ICON['save'])
+m_file.add(:separator)
+m_f_test = TkMenu.new(menu, :tearoff=>0)
+m_file.add(:cascade, :label=>'Test submenu', :underline=>0, :menu=>m_f_test)
+m_file.add(:checkbutton, :label=>'Text check', :underline=>5,
+ :variable=>$V.ref(:MENUCHECK1))
+m_file.insert(:end, :separator)
+
+if Tk.windowingsystem != 'x11'
+ TkConsole.create
+ m_file.insert(:end, :checkbutton, :label=>'Console', :underline=>5,
+ :variable=>$V.ref(:CONSOLE), :command=>proc{toggle_console()})
+ def toggle_console
+ if TkComm.bool($V[:CONSOLE])
+ TkConsole.show
+ else
+ TkConsole.hide
+ end
+ end
+end
+
+m_file.add(:command, :label=>'Exit', :underline=>1,
+ :command=>proc{Tk.event_generate(b_close, '<Invoke>')})
+
+%w(One Two Three Four).each{|lbl|
+ m_f_test.add(:radiobutton, :label=>lbl, :variable=>$V.ref(:MENURADIO1))
+}
+
+# Add Theme menu.
+#
+menu.add(:cascade, :label=>'Theme', :underline=>3,
+ :menu=>makeThemeMenu(menu))
+
+setTheme($V[:THEME])
+
+#
+# Combobox demo pane:
+#
+values = %w(list abc def ghi jkl mno pqr stu vwx yz)
+2.times {|i|
+ cb = Tk::Tile::Combobox.new(
+ combo, :values=>values, :textvariable=>$V.ref(:COMBO))
+ cb.pack(:side=>:top, :padx=>2, :pady=>2, :expand=>false, :fill=>:x)
+ if i == 1
+ cb.ttk_state :readonly
+ begin
+ cb.current = 3 # ignore if unsupported (tile0.4)
+ rescue
+ end
+ end
+}
+
+#
+# Treeview widget demo pane:
+#
+if version?('0.5')
+
+ treeview = nil # avoid 'undefined' error
+ scrollbar = Tk::Tile::Scrollbar.new(tree,
+ :command=>proc{|*args| treeview.yview(*args)})
+ treeview = Tk::Tile::Treeview.new(tree, :columns=>%w(Class), :padding=>4,
+ :yscrollcommand=>proc{|*args| scrollbar.set(*args)})
+
+ Tk.grid(treeview, scrollbar, :sticky=>'news')
+ tree.grid_columnconfigure(0, :weight=>1)
+ tree.grid_rowconfigure(0, :weight=>1)
+ tree.grid_propagate(0)
+
+ # Add initial tree node:
+ # Later nodes will be added in <<TreeviewOpen>> binding.
+ treeview.insert('', 0, :id=>'.', :text=>'Main Window', :open=>false,
+ :values=>[TkWinfo.classname('.')])
+ treeview.headingconfigure('#0', :text=>'Widget')
+ treeview.headingconfigure('Class', :text=>'Class')
+ treeview.bind('<TreeviewOpen>', proc{fillTree(treeview)})
+
+ def fillTree(treeview)
+ id = treeview.focus_item
+ unless TkWinfo.exist?(id)
+ treeview.delete(id)
+ end
+ # Replace tree item children with current list of child windows.
+ treeview.delete(treeview.children(id))
+ for child in TkWinfo.children(id)
+ treeview.insert(id, :end, :id=>child, :text=>TkWinfo.appname(child),
+ :open=>false, :values=>[TkWinfo.classname(child)])
+ unless TkWinfo.children(child).empty?
+ # insert dummy child to show [+] indicator
+ treeview.insert(child, :end)
+ end
+ end
+ end
+
+else
+ Tk::Tile::Label.new(tree,
+ :text=>'Treeview is supported on tile 0.5 or later...').pack
+end
+
+#
+# Other demos:
+#
+$Timers = {:StateMonitor=>nil, :FocusMonitor=>nil}
+
+begin
+ msg = Tk::Tile::Label.new(others, :justify=>:left, :wraplength=>300)
+rescue
+ msg = TkMessage.new(others, :aspect=>200)
+end
+
+$Desc = {}
+
+showDescription = TkBindTag.new
+showDescription.bind('Enter', proc{|w| msg.text($Desc[w.path])}, '%W')
+showDescription.bind('Leave', proc{|w| msg.text('')}, '%W')
+
+[
+ [ :trackStates, "Widget states...",
+ "Display/modify widget state bits" ],
+
+ [ :scrollbarResizeDemo, "Scrollbar resize behavior...",
+ "Shows how Tile and standard scrollbars differ when they're sized too large" ],
+
+ [ :trackFocus, "Track keyboard focus..." ,
+ "Display the name of the widget that currently has focus" ],
+
+ [ :repeatDemo, "Repeating buttons...",
+ "Demonstrates custom classes (see demos/repeater.tcl)" ]
+
+].each{|demo_cmd, label, description|
+ b = Tk::Tile::Button.new(others, :text=>label,
+ :command=>proc{ self.__send__(demo_cmd) })
+ $Desc[b.path] = description
+ b.bindtags <<= showDescription
+
+ b.pack(:side=>:top, :expand=>false, :fill=>:x, :padx=>6, :pady=>6)
+}
+
+msg.pack(:side=>:bottom, :expand=>true, :fill=>:both)
+
+
+#
+# Scrollbar resize demo:
+#
+$scrollbars = nil
+
+def scrollbarResizeDemo
+ if $scrollbars
+ begin
+ $scrollbars.destroy
+ rescue
+ end
+ end
+ $scrollbars = TkToplevel.new(:title=>'Scrollbars', :geometry=>'200x200')
+ f = TkFrame.new($scrollbars, :height=>200)
+ tsb = Tk::Tile::Scrollbar.new(f, :command=>proc{|*args| sbstub(tsb, *args)})
+ sb = TkScrollbar.new(f, :command=>proc{|*args| sbstub(sb, *args)})
+ Tk.grid(tsb, sb, :sticky=>:news)
+
+ sb.set(0, 0.5) # prevent backwards-compatibility mode for old SB
+
+ f.grid_columnconfigure(0, :weight=>1)
+ f.grid_columnconfigure(1, :weight=>1)
+ f.grid_rowconfigure(0, :weight=>1)
+
+ f.pack(:expand=>true, :fill=>:both)
+end
+
+#
+# Track focus demo:
+#
+$FocusInf = TkVariable.new_hash
+$focus = nil
+
+def trackFocus
+ if $focus
+ begin
+ $focus.destroy
+ rescue
+ end
+ end
+ $focus = TkToplevel.new(:title=>'Keyboard focus')
+ i = 0
+ [
+ ["Focus widget:", :Widget],
+ ["Class:", :WidgetClass],
+ ["Next:", :WidgetNext],
+ ["Grab:", :Grab],
+ ["Status:", :GrabStatus]
+ ].each{|label, var_index|
+ Tk.grid(Tk::Tile::Label.new($focus, :text=>label, :anchor=>:e),
+ Tk::Tile::Label.new($focus,
+ :textvariable=>$FocusInf.ref(var_index),
+ :width=>40, :anchor=>:w, :relief=>:groove),
+ :sticky=>:ew)
+ i += 1
+ }
+ $focus.grid_columnconfigure(1, :weight=>1)
+ $focus.grid_rowconfigure(i, :weight=>1)
+
+ $focus.bind('Destroy', proc{Tk.after_cancel($Timers[:FocusMonitor])})
+ focusMonitor
+end
+
+def focusMonitor
+ $FocusInf[:Widget] = focus_win = Tk.focus
+ if focus_win
+ $FocusInf[:WidgetClass] = focus_win.winfo_classname
+ $FocusInf[:WidgetNext] = Tk.focus_next(focus_win)
+ else
+ $FocusInf[:WidgetClass] = $FocusInf[:WidgetNext] = ''
+ end
+
+ $FocusInf[:Grab] = grab_wins = Tk.current_grabs
+ unless grab_wins.empty?
+ $FocusInf[:GrabStatus] = grab_wins[0].grab_status
+ else
+ $FocusInf[:GrabStatus] = ''
+ end
+
+ $Timers[:FocusMonitor] = Tk.after(200, proc{ focusMonitor() })
+end
+
+#
+# Widget state demo:
+#
+$Widget = TkVariable.new
+
+TkBindTag::ALL.bind('Control-Shift-ButtonPress-1',
+ proc{|w|
+ $Widget.value = w
+ updateStates()
+ Tk.callback_break
+ }, '%W')
+$states_list = %w(active disabled focus pressed selected
+ background indeterminate invalid default)
+$states_btns = {}
+$states = nil
+
+$State = TkVariable.new_hash
+
+def trackStates
+ if $states
+ begin
+ $state.destroy
+ rescue
+ end
+ end
+ $states = TkToplevel.new(:title=>'Widget states')
+
+ l_inf = Tk::Tile::Label.new($states, :text=>"Press Control-Shift-Button-1 on any widget")
+
+ l_lw = Tk::Tile::Label.new($states, :text=>'Widget:',
+ :anchor=>:e, :relief=>:groove)
+ l_w = Tk::Tile::Label.new($states, :textvariable=>$Widget,
+ :anchor=>:w, :relief=>:groove)
+
+ Tk.grid(l_inf, '-', :sticky=>:ew, :padx=>6, :pady=>6)
+ Tk.grid(l_lw, l_w, :sticky=>:ew)
+
+ $states_list.each{|st|
+ cb = Tk::Tile::Checkbutton.new($states, :text=>st,
+ :variable=>$State.ref(st),
+ :command=>proc{ changeState(st) })
+ $states_btns[st] = cb
+ Tk.grid('x', cb, :sticky=>:nsew)
+ }
+
+ $states.grid_columnconfigure(1, :weight=>1)
+
+ f_cmd = Tk::Tile::Frame.new($states)
+ Tk.grid('x', f_cmd, :sticky=>:nse)
+
+ b_close = Tk::Tile::Button.new(f_cmd, :text=>'Close',
+ :command=>proc{ $states.destroy })
+ Tk.grid('x', b_close, :padx=>4, :pady=>[6,4])
+ f_cmd.grid_columnconfigure(0, :weight=>1)
+
+ $states.bind('KeyPress-Escape', proc{Tk.event_generate(b_close, '<Invoke>')})
+
+ $states.bind('Destroy', proc{Tk.after_cancel($Timers[:StateMonitor])})
+ stateMonitor()
+end
+
+def stateMonitor
+ updateStates() if $Widget.value != ''
+ $Timers[:StateMonitor] = Tk.after(200, proc{ stateMonitor() })
+end
+
+def updateStates
+ $states_list.each{|st|
+ begin
+ $State[st] = $Widget.window.ttk_instate(st)
+ rescue
+ $states_btns[st].ttk_state('disabled')
+ else
+ $states_btns[st].ttk_state('!disabled')
+ end
+ }
+end
+
+def changeState(st)
+ if $Widget.value != ''
+ if $State.bool_element(st)
+ $Widget.window.ttk_state(st)
+ else
+ $Widget.window.ttk_state("!#{st}")
+ end
+ end
+end
+
+#
+# Repeating buttons demo:
+#
+def repeatDemo
+ if defined?($repeatDemo) && $repeatDemo.exist?
+ $repeatDemo.deiconify; return
+ end
+ $repeatDemo = TkToplevel.new(:title=>'Repeating button')
+
+ f = Tk::Tile::Frame.new($repeatDemo)
+ b = Tk::Tile::Button.new(f, :class=>'Repeater', :text=>'Press and hold')
+ if version?('0.6')
+ p = Tk::Tile::Progressbar.new(f, :orient=>:horizontal, :maximum=>10)
+ else # progressbar is not supported
+ p = Tk::Tile::Progress.new(f, :orient=>:horizontal, :from=>0, :to=>10)
+ def p.step
+ i = self.get + 1
+ i = self.from if i > self.to
+ self.set(i)
+ end
+ end
+ b.command {p.step}
+
+ b.pack(:side=>:left, :expand=>false, :fill=>:none, :padx=>6, :pady=>6)
+ p.pack(:side=>:right, :expand=>true, :fill=>:x, :padx=>6, :pady=>6)
+ f.pack(:expand=>true, :fill=>:both)
+end
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tile/iconlib.tcl b/ext/tk/sample/tkextlib/tile/iconlib.tcl
new file mode 100644
index 0000000000..9a93ece504
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/iconlib.tcl
@@ -0,0 +1,110 @@
+array set ImgData {
+bold {R0lGODlhEAAQAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAQABAAAAI6hI+py60U3wj+
+RYQFJYRvEWFBCeFbRFhQQvhG8YPgX0RYUEL4FhEWlBC+RYQFJYQPFN8IPqYut/8hBQA7}
+copy {R0lGODlhEAAQAJEAANnZ2QAAAP///wAAhCH5BAEAAAAALAAAAAAQABAAAAJUhI8JFJ/gY4iI
+UEL4FyIiFIXgW0iEUDgfACBI9pzMAAGRiIghWSMDECR7JEKGtkFIRFBG+TIQKDQxtgzcDcmX
+IfgwQrFlCD4MyZch+EDzj+Bj6mYBADs=}
+cut {R0lGODlhEAAQAJEAANnZ2QAAAAAAhP///yH5BAEAAAAALAAAAAAQABAAAAJFhI+pcUHwEeIi
+E0gACIKPEAFBIXy0gMg8EhM+YmQiKSL4eAIiJMI/EQEhQGYGYiQIQAg+iAkIATIzECMBIgT/
+RBARERlSADs=}
+dragfile {R0lGODlhGAAYAKIAANnZ2TMzM////wAAAJmZmf///////////yH5BAEAAAAALAAAAAAYABgA
+AAPACBi63IqgC4GiyxwogaAbKLrMgSKBoBoousyBogEACIGiyxwoKgGAECI4uiyCExMTOACB
+osuNpDoAGCI4uiyCIkREOACBosutSDoAgSI4usyCIjQAGCi63Iw0ACEoOLrMgiI0ABgoutyM
+NAAhKDi6zIIiNAAYKLrcjDQAISg4usyCIjQAGCi63Iw0AIGiiqPLIyhCA4CBosvNSAMQKKo4
+ujyCIjQAGCi63Iw0AIGiy81IAxCBpMu9GAMAgKPL3QgJADs=}
+dragicon {R0lGODlhGAAYALMAANnZ2TMzM/////8zM8zMzGYAAAAAAJmZmQCZMwAzZgCZzGZmZv//////
+/////////yH5BAEAAAAALAAAAAAYABgAAAT/EMAgJ60SAjlBgEJOSoMIEMgZoJCT0iADBFIG
+KOSkNMwAAABhwiHnIEKIIIQQAQIZhBBwyDmKEMIEE0yABoAghIBDzlGEENDIaQAIQgg45BwF
+CinPOccAECYcUiKEEBFCiHPgMQAEIcQYYyABBUGIQCHlMQCEScZAAhKEEApCECGOARAEIQQp
+BRGIpAyCJCGOASBAISdEcqJAVBLiGABggELOAJGUKyiVhDgGABigkJMEhNAKSqkEhTgGgCCl
+FCQEGIJSSiUhjgEgQCEnJVBJmYQ4BoAAhZyTQCVnEuIYAAIUckoCk5xSiGMACFDISSs9BoBg
+rRXQMQAEKOSklR4DEUAI8MhJ6wwGAACgkZNWCkAEADs=}
+error {R0lGODlhIAAgAKIAANnZ2YQAAP8AAISEhP///////////////yH5BAEAAAAALAAAAAAgACAA
+AAP/CLoMGLqKoMvtGIqiqxEYCLrcioGiyxwIusyBgaLLLRiBoMsQKLrcjYGgu4Giy+2CAkFX
+A0WX2wXFIOgGii7trkCEohsDCACBoktEKLpKhISiGwAIECiqSKooukiqKKoxgACBooukKiIo
+SKooujGDECi6iqQqsopEV2MQAkV3kXQZRXdjEAJFl5F0FUWXY3ACRZcFSRdFlyVwJlB0WZB0
+UXRZAmcCRZeRdBVFl2NwAkV3kXQZRXdjcAJFV5FURVaR6GoMDgSKLpKqiKAgqaLoxgwOBIoq
+kiqKLpIqimrM4ECg6BIRiq4SIaHoxgyCBoou7a5AhKIbMzgAAIGiy+2CTWJmBhAAAkWX2wXF
+zCDoBooud2PMDIKuRqDocgtGzMwg6O4Eii5z4Kgi6DIMhqLoagQGjiqCLvPgYOgqji6CLrfi
+6DIj6HI7jq4i6DIkADs=}
+file {R0lGODlhCwANAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAALAA0AAAIyhI9G8Q0AguSH
+AMQdxQgxEyEFQfItICQokYgEBMm3gBCKLRIQJN8CQii2SECQfAug+FgAOw==}
+folder {R0lGODlhEAANAKIAANnZ2YSEhMbGxv//AP///wAAAP///////yH5BAEAAAAALAAAAAAQAA0A
+AANjCIqhiqDLITgyEgi6GoIjIyMYugCBpMsaWBA0giMjIzgyUYBBMjIoIyODEgVBODIygiMj
+E1gQJIMyMjIoI1GAQSMjODIyghMFQSgjI4MyMhJYEDSCIyMjODJRgKHLXAiApcucADs=}
+hourglass {R0lGODlhIAAgAKIAANnZ2YAAAAAAAP8AAP///8DAwICAgP///yH5BAEAAAAALAAAAAAgACAA
+AAPZCLrc/jDKSau9OGcUuqyCoMvNGENVhaMrCLrcjaLLgqDL7WhFVIVVZoKgy+1oRUSFVWaC
+oMvtaEVEhVVmgqDL7WhFRIVVZoKgy+1oVVaCJWaCoMvtgKxISrBMEHS5fZEVSRkKgi63NzIq
+EwRdbndkVCYIutzeyIqqDAVBl9sXWRFJYZkg6HI7ICsiKqwyEwRdbkcrIhKsMhMEXW5HKyIp
+lDITBF1uRysyEiwxEwRdbkcrIyuUEhMEXW5H0WVB0OVujKGqwtEVBF1uRtHlRdDl9odRTlrt
+xRmjBAA7}
+info {R0lGODlhIAAgAKIAANnZ2YSEhMbGxv///wAA/wAAAP///////yH5BAEAAAAALAAAAAAgACAA
+AAP/CLoMGLqKoMvtGCo4uhKBgaDLDRghOLqsghEIuryBgqPLPSiBoMsQOLojhEQkOLpTCLob
+OLqKpIujq4WgC4Gju0i6OLpbCKohOLorhEQkOLorhaAQOLrc3qgCIARHl9sbSQUEji4j6RKO
+Lk9hQODosiKp4ujyFIbi6LIiqeLo8hSG4uiyIqni6PIUhuLosiKp4ujyFIYKji4PkiqOLkth
+BASOLg+SKo4uV2AEhODoMpIqju5KYShA4Ogqku7i6E4FRgAAYOHocvugiohAUC0cXe7GiohA
+0IUSHF3uQamICATdrULB0WUVrIqIQNBlCCwVHF2pwsJQRdDlDYyoKsHRPMLQDQRdbsDQqBmc
+wlBF0OV2jJqZwggEXW5vVDMVgaDL7Y5qKgJBl9sfVUUg6HL7AxSKoMvtr1AEgi5DAgA7}
+italic {R0lGODlhEAAQAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAQABAAAAIrhI+py+1A4hN8
+hIjINBITPlpEZBqJCR8tIjKNxISPFhGZQOITfExdbv9FCgA7}
+new {R0lGODlhEAAQAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAQABAAAAJFhI95FN8IvgXJ
+jyD4ECQ/JAh+kPyICIIdJP+CYAfJvyDYQfIvCHaQ/AuCHST/gmAHyb8g2EHyLwh2kPwLgk3x
+MQg+pu4WADs=}
+open {R0lGODlhEAAQAKIAANnZ2QAAAP//AP///4SEAP///////////yH5BAEAAAAALAAAAAAQABAA
+AANZCLrczigUQZc1EDQgEHSZAwMgIhB0NQIDQkYwdANBNUZwZGQEJxBUQwZlZGRQAkE1RnAE
+Q5dVcCSQdDcAYySQdDcAISSQdDcAASKQdDcAAQBDlwNBl9sfApQAOw==}
+openfold {R0lGODlhEAANAKIAANnZ2YSEhP///8bGxv//AAAAAP///////yH5BAEAAAAALAAAAAAQAA0A
+AANgCIqhiqDLgaIaCLoagkNDIxi6AIFCQ0M4KKpRgCFDQzg0NIQThaHLSxgVKLochRMVMkhD
+Q4M0VBFYEDKEQ0NDOFFRgCE0NEhDQ4MVBRAoNDSEQ0NRWAAYuqyFBQBYurwJADs=}
+overstrike {R0lGODlhEAAQAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAQABAAAAI3hI+py80Uh+Aj
+RFhQCP8iMILgWwRGEHyLwAiCbxEYQfCB4iPBhwiMIPgXYREEHyEiguBj6nI7FQA7}
+palette {R0lGODlhEAAQAKIAANnZ2QAAAP//AP////8A/4QAhP8AAAD//yH5BAEAAAAALAAAAAAQABAA
+AANtCLrcjqGBoMsRKCMTgaALMSgDAYMSCKoxgAFBITgSAIAQEhUIARCAEgAQOBAwghMQEwga
+MoIjIxAIEgCAEBEyKBAgg4GgGxAIYTGCgaALcRgQIIGgCwEYICODgaALITgyEoGguxiqCLrc
+/lChBAA7}
+passwd {R0lGODlhIAAgAMQAANnZ2QAAAICAgICAAP///7CwsMDAwMjIAPjIAOjo6Pj4AODg4HBwcMj4
+ANjY2JiYANDQ0MjIyPj4yKCgoMiYAMjImDAwAMjIMJiYmJCQkP//////////////////////
+/yH5BAEAAAAALAAAAAAgACAAAAX/ICCOIhiIIgiII1maZSCMQnCeJyAIQiAIAiAMwxCcJwkk
+EAQRCIUwGMSBDEEAAuJIlgKRJEEgGAMRBIGiDENQlqNAJAsYCEwgEEEgBAHSIEMAAuJIAgKR
+LEsgGEMgCEJgBMqhHENQlgJILMsSCMRABEFgGAESHMcRgIA4kgKxOIsTBAOhKAITKEGDHMhD
+kqIAEqAjisJAgIooBkpwNMcTgIA4jgLhOBAkEAOhKIoSKEGDIMcTkKQICgQEQQIxEIqiBEpw
+IMdxPAEIiCMJCEQUMUQ0EIqiHIfSIM3xBGUpCiABCUQyEMqhHMiBHMjxBCAgjuQoEAKxRANB
+HMqhHM1x/zxDUJajQIACsUTDQBAEIR3IcQRDAALiSIoCYQiEE03gII7HQR3BEICAOJICYRSC
+QDjRNE1CAAzVQR3WE5AkAAqEUQiFQEARBAUAAAzHQR3BEICAOI4CUQhFIBAREwXjUFUHdQRD
+QJJAABbCFAhEJBgBAADAMAwXdQRDAALiCAhEIRQCYRiCEZDjUFFHMAQkIBAFOAmTQBiFUAQg
+II7AUFXUEQwBCQjEJExBkBRCEZCjMIBD9RxDAALiGEzCFBBYIRTBOI7AQB1DMIoCMQkYGAjL
+JEwBCIgjOVDDEJCAQGACJiTTJEwBSY5BEJAiSCCwTAiCZBKmAATEkSzNQBCCYCDBJgELTNMk
+g0AMEgwTAhAQR7I0zYARgvM8TyAIznMMAQA7}
+paste {R0lGODlhEAAQAKIAANnZ2QAAAP//AISEAISEhP///wAAhP///yH5BAEAAAAALAAAAAAQABAA
+AANwCLrcjqGBoKsYqiKrCDSGBkMiJJCGAgCDKBB0gwYDIKYwdJUIAyBokIaGBmloAhBiaAgH
+TdcCEIKGBsmwVM0AIYaGcAxL1coQgoYGySoisMzMAoeGxrB01QJpaMiwMHTLAEPVsHTVEHTR
+dBlBlxswAQA7}
+print {R0lGODlhEAAQAKIAANnZ2QAAAP///4SEhP//AP///////////yH5BAEAAAAALAAAAAAQABAA
+AANZCLrcjqG7CLqBoquBoBuCoSqBoBsouhoIuiEYqrKBoIGiqwEYEIChyxAIEYGgywEYgKHL
+DAgRCLozgwABARgIukSEABEBGLq8gAEQCLobgAEAgKHLgaDLzZgAOw==}
+question {R0lGODlhIAAgAKIAANnZ2YSEhMbGxv///wAAAAAA/////////yH5BAEAAAAALAAAAAAgACAA
+AAP/CLoMGLqKoMvtGCo4uhKBgaDLDRghOLqsghEIuryBgqPLPSiBoMsQOLrcjYSgu4GjO4Kl
+Kzi6Qwi6EDi6I4UyU1VYgqM7hKAagqM7VTg6VYWFoztCCAqBo6tVWDVThVU4ukqBACE4ulqF
+VSNVWIWjq0IYEDi6K4UlU1VYOLpMgRA4uryCpTi6PIShOLq8hVU4uqyEoTi6vIUlOLqshKE4
+uryFhaPLSxgqOLrc3kgoAgJHl0ewSnB0eQhDIQRHl6uwCkeXhTAUIHB0uQqrcHSZAiMAAJBw
+dFcKS3B0lwIjAkGVcHS5GykiAkEXSHB0uQeFIiIQdJcIBUeXVZAoIgJBT5chkFRwdIUICUMV
+QZc3MIKIBEcJQzcQdLkBQ4NmcAhDFUGX2zFoZggjEHS5vRHNUASCLrc7oqEIBF1uf0QUgaDL
+7Q9QKIIut79CEQi6DAkAOw==}
+redo {R0lGODlhEAAQAJEAANnZ2QAAhP///////yH5BAEAAAAALAAAAAAQABAAAAIvhI+py+1vSByC
+jxAYQXDMwsyAggQAQBB8iwgMgg8REQgUwqbYBDsIPqYutz+MgBQAOw==}
+save {R0lGODlhEAAQAJEAANnZ2QAAAISEAP///yH5BAEAAAAALAAAAAAQABAAAAJWhI9pFB8RIIRC
++BYQFqQQvkWEBSmEbyFhQQrhW0hYkEL4FhIWpBC+hYQFSYxvIgFAoXy0AAiSGP8kAIIkxgcI
+CSBEQvEBQgIIkVB8gJAAAhgfj+BjWgEAOw==}
+underline {R0lGODlhEAAQAJEAANnZ2QAAAP///////yH5BAEAAAAALAAAAAAQABAAAAI3hI+py60UBy4I
+vkVcBMG/iIsg+BdxEQT/Ii6C4F/ERRD8i7gIgn8RF0HwkWITfExFin8EH1OXCwA7}
+undo {R0lGODlhEAAQAJEAANnZ2QAAhP///////yH5BAEAAAAALAAAAAAQABAAAAIuhI+py+2vSByC
+HxdxQCHsCIg7oAAAEUHwLTAiKIQPgRSbYMfd3VEIH1OX2x8mUgA7}
+warning {R0lGODlhIAAgAKIAANnZ2YSEAP//AMbGxgAAAISEhP///////yH5BAEAAAAALAAAAAAgACAA
+AAP/CLq8gREIutz+KESGEHS5vVGIiAxSIehy+6JAUaUqBF1uBxQoukOFhaDL7RgoukKFhaDL
+3RgoujqEVQi63IyBortUWAi63IuBostDWIWgy60YIjKERCMiSFUIutyAISKCpCoiOFSFoMsd
+KCpIqiKCQlUIusyBooqkKiIoQ1UIuryBooqkiqJKVQi6rIGii6SKojpUWAi6DIGiG0RIgaJL
+VQi6HCi6MoREg6I7VFgIuhsoukqEhKKrVFgIuhoouhuEgaKrQ1iFoAuBortDOCi6S4WFoBso
+uiyEostDWIWgGii63K6IqgAAIVB0WQaJBkV3h7AKAAJFl4WQiFB0mQoLRyBQdFkJiQhFl4ew
+CgJFl3WQaFB0WQirIFB0ud0RVVWg6HJ7o6GqAgwUXW5fNFRVhQCBpMvti0oVABCwdLndEehi
+6XI7I4AEADs=}
+}
diff --git a/ext/tk/sample/tkextlib/tile/readme.txt b/ext/tk/sample/tkextlib/tile/readme.txt
new file mode 100644
index 0000000000..a76b3338f7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/readme.txt
@@ -0,0 +1,2 @@
+All of *.tcl and under themes/ directory (except kroc.rb) are
+quoted from Tcl/Tk's Tile extension. Please read Orig_LICENSE.txt.
diff --git a/ext/tk/sample/tkextlib/tile/repeater.tcl b/ext/tk/sample/tkextlib/tile/repeater.tcl
new file mode 100644
index 0000000000..652ba8ab17
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/repeater.tcl
@@ -0,0 +1,117 @@
+#
+# $Id$
+#
+# Demonstration of custom classes.
+#
+# The Tile button doesn't have built-in support for autorepeat.
+# Instead of adding -repeatdelay and -repeatinterval options,
+# and all the extra binding scripts required to deal with them,
+# we create a custom widget class for autorepeating buttons.
+#
+# Usage:
+# ttk::button .b -class Repeater [... other options ...]
+#
+# TODO:
+# Use system settings for repeat interval and initial delay.
+#
+# Notes:
+# Repeater buttons work more like scrollbar arrows than
+# Tk repeating buttons: they fire once immediately when
+# first pressed, and $State(delay) specifies the initial
+# interval before the button starts autorepeating.
+#
+
+namespace eval tile::Repeater {
+ variable State
+ set State(timer) {} ;# [after] id of repeat script
+ set State(interval) 100 ;# interval between repetitions
+ set State(delay) 300 ;# delay after initial invocation
+}
+
+### Class bindings.
+#
+
+bind Repeater <Enter> { %W state active }
+bind Repeater <Leave> { %W state !active }
+
+bind Repeater <Key-space> { tile::Repeater::Activate %W }
+bind Repeater <<Invoke>> { tile::Repeater::Activate %W }
+
+bind Repeater <ButtonPress-1> { tile::Repeater::Press %W }
+bind Repeater <ButtonRelease-1> { tile::Repeater::Release %W }
+bind Repeater <B1-Leave> { tile::Repeater::Pause %W }
+bind Repeater <B1-Enter> { tile::Repeater::Resume %W } ;# @@@ see below
+
+# @@@ Workaround for metacity-induced bug:
+bind Repeater <B1-Enter> \
+ { if {"%d" ne "NotifyUngrab"} { tile::Repeater::Resume %W } }
+
+### Binding procedures.
+#
+
+## Activate -- Keyboard activation binding.
+# Simulate clicking the button, and invoke the command once.
+#
+proc tile::Repeater::Activate {w} {
+ $w instate disabled { return }
+ set oldState [$w state pressed]
+ update idletasks; after 100
+ $w state $oldState
+ after idle [list $w invoke]
+}
+
+## Press -- ButtonPress-1 binding.
+# Invoke the command once and start autorepeating after
+# $State(delay) milliseconds.
+#
+proc tile::Repeater::Press {w} {
+ variable State
+ $w instate disabled { return }
+ $w state pressed
+ $w invoke
+ after cancel $State(timer)
+ set State(timer) [after $State(delay) [list tile::Repeater::Repeat $w]]
+}
+
+## Release -- ButtonRelease binding.
+# Stop repeating.
+#
+proc tile::Repeater::Release {w} {
+ variable State
+ $w state !pressed
+ after cancel $State(timer)
+}
+
+## Pause -- B1-Leave binding
+# Temporarily suspend autorepeat.
+#
+proc tile::Repeater::Pause {w} {
+ variable State
+ $w state !pressed
+ after cancel $State(timer)
+}
+
+## Resume -- B1-Enter binding
+# Resume autorepeat.
+#
+proc tile::Repeater::Resume {w} {
+ variable State
+ $w instate disabled { return }
+ $w state pressed
+ $w invoke
+ after cancel $State(timer)
+ set State(timer) [after $State(interval) [list tile::Repeater::Repeat $w]]
+}
+
+## Repeat -- Timer script
+# Invoke the command and reschedule another repetition
+# after $State(interval) milliseconds.
+#
+proc tile::Repeater::Repeat {w} {
+ variable State
+ $w instate disabled { return }
+ $w invoke
+ set State(timer) [after $State(interval) [list tile::Repeater::Repeat $w]]
+}
+
+#*EOF*
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue.tcl b/ext/tk/sample/tkextlib/tile/themes/blue/blue.tcl
new file mode 100644
index 0000000000..37e3d07ff7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue.tcl
@@ -0,0 +1,149 @@
+# blue.tcl - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
+#
+# blue.tcl,v 1.27 2005/10/08 14:56:57 jenglish Exp
+#
+#
+
+namespace eval tile::theme::blue {
+
+ package provide tile::theme::blue 0.7
+
+ set imgdir [file join [file dirname [info script]] blue]
+ array set I [tile::LoadImages $imgdir *.gif]
+
+ array set colors {
+ -frame "#6699cc"
+ -lighter "#bcd2e8"
+ -window "#e6f3ff"
+ -selectbg "#ffff33"
+ -selectfg "#000000"
+ -disabledfg "#666666"
+ }
+
+ style theme create blue -settings {
+
+ style default . \
+ -borderwidth 1 \
+ -background $colors(-frame) \
+ -fieldbackground $colors(-window) \
+ -troughcolor $colors(-lighter) \
+ -selectbackground $colors(-selectbg) \
+ -selectforeground $colors(-selectfg) \
+ ;
+ style map . -foreground [list disabled $colors(-disabledfg)]
+
+ ## Buttons.
+ #
+ style default TButton -padding "10 0"
+ style layout TButton {
+ Button.button -children {
+ Button.focus -children {
+ Button.padding -children {
+ Button.label
+ }
+ }
+ }
+ }
+
+ style element create button image $I(button-n) \
+ -map [list pressed $I(button-p) active $I(button-h)] \
+ -border 4 -sticky ew
+
+ style element create Checkbutton.indicator image $I(check-nu) \
+ -width 24 -sticky w -map [list \
+ {!disabled active selected} $I(check-hc) \
+ {!disabled active} $I(check-hu) \
+ {!disabled selected} $I(check-nc) ]
+
+ style element create Radiobutton.indicator image $I(radio-nu) \
+ -width 24 -sticky w -map [list \
+ {!disabled active selected} $I(radio-hc) \
+ {!disabled active} $I(radio-hu) \
+ selected $I(radio-nc) ]
+
+ style default TMenubutton -relief raised -padding {10 2}
+
+ ## Toolbar buttons.
+ #
+ style default Toolbutton \
+ -width 0 -relief flat -borderwidth 2 -padding 4 \
+ -background $colors(-frame) -foreground #000000 ;
+ style map Toolbutton -background [list active $colors(-selectbg)]
+ style map Toolbutton -foreground [list active $colors(-selectfg)]
+ style map Toolbutton -relief {
+ disabled flat
+ selected sunken
+ pressed sunken
+ active raised
+ }
+
+ ## Entry widgets.
+ #
+ style default TEntry \
+ -selectborderwidth 1 -padding 2 -insertwidth 2 -font TkTextFont
+ style default TCombobox \
+ -selectborderwidth 1 -padding 2 -insertwidth 2 -font TkTextFont
+
+ ## Notebooks.
+ #
+ style default TNotebook.Tab -padding {4 2 4 2}
+ style map TNotebook.Tab \
+ -background \
+ [list selected $colors(-frame) active $colors(-lighter)] \
+ -padding [list selected {4 4 4 2}]
+
+ ## Labelframes.
+ #
+ style default TLabelframe -borderwidth 2 -relief groove
+
+ ## Scrollbars.
+ #
+ style layout Vertical.TScrollbar {
+ Scrollbar.trough -children {
+ Scrollbar.uparrow -side top
+ Scrollbar.downarrow -side bottom
+ Scrollbar.uparrow -side bottom
+ Vertical.Scrollbar.thumb -side top -expand true -sticky ns
+ }
+ }
+
+ style layout Horizontal.TScrollbar {
+ Scrollbar.trough -children {
+ Scrollbar.leftarrow -side left
+ Scrollbar.rightarrow -side right
+ Scrollbar.leftarrow -side right
+ Horizontal.Scrollbar.thumb -side left -expand true -sticky we
+ }
+ }
+
+ style element create Horizontal.Scrollbar.thumb image $I(sb-thumb) \
+ -map [list {pressed !disabled} $I(sb-thumb-p)] -border 3
+
+ style element create Vertical.Scrollbar.thumb image $I(sb-vthumb) \
+ -map [list {pressed !disabled} $I(sb-vthumb-p)] -border 3
+
+ foreach dir {up down left right} {
+ style element create ${dir}arrow image $I(arrow${dir}) \
+ -map [list \
+ disabled $I(arrow${dir}) \
+ pressed $I(arrow${dir}-p) \
+ active $I(arrow${dir}-h)] \
+ -border 1 -sticky {}
+ }
+
+ ## Scales.
+ #
+ style element create Scale.slider \
+ image $I(slider) -map [list {pressed !disabled} $I(slider-p)]
+
+ style element create Vertical.Scale.slider \
+ image $I(vslider) -map [list {pressed !disabled} $I(vslider-p)]
+
+ style element create Horizontal.Progress.bar \
+ image $I(sb-thumb) -border 2
+ style element create Vertical.Progress.bar \
+ image $I(sb-vthumb) -border 2
+
+ }
+}
+
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-h.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-h.gif
new file mode 100644
index 0000000000..3c1be9d880
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-h.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-p.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-p.gif
new file mode 100644
index 0000000000..1cb36ec554
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown.gif
new file mode 100644
index 0000000000..e363c362ed
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowdown.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-h.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-h.gif
new file mode 100644
index 0000000000..cbc3db2756
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-h.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-p.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-p.gif
new file mode 100644
index 0000000000..14d541b03e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft.gif
new file mode 100644
index 0000000000..32584a34b2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowleft.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-h.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-h.gif
new file mode 100644
index 0000000000..913e9da94b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-h.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-p.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-p.gif
new file mode 100644
index 0000000000..d02208fcf7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright.gif
new file mode 100644
index 0000000000..2b0f1fd07b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowright.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-h.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-h.gif
new file mode 100644
index 0000000000..6059bae094
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-h.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-p.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-p.gif
new file mode 100644
index 0000000000..20b6a824f4
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup.gif
new file mode 100644
index 0000000000..5857616228
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/arrowup.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-h.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-h.gif
new file mode 100644
index 0000000000..0947f43b90
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-h.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.gif
new file mode 100644
index 0000000000..d9845283a5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.xcf b/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.xcf
new file mode 100644
index 0000000000..e38ed19e61
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-n.xcf
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-p.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-p.gif
new file mode 100644
index 0000000000..e819b1b951
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/button-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hc.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hc.gif
new file mode 100644
index 0000000000..b753aead97
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hu.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hu.gif
new file mode 100644
index 0000000000..74dbb799a2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-hu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nc.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nc.gif
new file mode 100644
index 0000000000..8f3d9114a3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nu.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nu.gif
new file mode 100644
index 0000000000..6f360ffd62
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/check-nu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hc.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hc.gif
new file mode 100644
index 0000000000..f7c21fb0c3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hu.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hu.gif
new file mode 100644
index 0000000000..a006630388
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-hu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nc.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nc.gif
new file mode 100644
index 0000000000..0281de37d8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nu.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nu.gif
new file mode 100644
index 0000000000..58ec60c1db
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/radio-nu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb-p.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb-p.gif
new file mode 100644
index 0000000000..6cfaa416d1
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb.gif
new file mode 100644
index 0000000000..d9bfc0a7be
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-thumb.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb-p.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb-p.gif
new file mode 100644
index 0000000000..930d7fd9ff
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb.gif
new file mode 100644
index 0000000000..060be5dd41
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/sb-vthumb.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/slider-p.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/slider-p.gif
new file mode 100644
index 0000000000..c1c089de3e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/slider-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/slider.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/slider.gif
new file mode 100644
index 0000000000..1805c2dc7c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/slider.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider-p.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider-p.gif
new file mode 100644
index 0000000000..bc37b31c3d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider.gif b/ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider.gif
new file mode 100644
index 0000000000..d3745c7f62
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/blue/vslider.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl b/ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl
new file mode 100644
index 0000000000..4facac70d8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl
@@ -0,0 +1,6 @@
+# Package index for tile demo pixmap themes.
+
+if {[file isdirectory [file join $dir blue]]} {
+ package ifneeded tile::theme::blue 0.7 \
+ [list source [file join $dir blue.tcl]]
+}
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik.tcl b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik.tcl
new file mode 100644
index 0000000000..79fcd7c04e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik.tcl
@@ -0,0 +1,194 @@
+# keramik.tcl -
+#
+# A sample pixmap theme for the tile package.
+#
+# Copyright (c) 2004 Googie
+# Copyright (c) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
+#
+# $Id$
+
+package require Tk 8.4; # minimum version for Tile
+package require tile 0.5; # depends upon tile 0.5
+
+namespace eval tile {
+ namespace eval theme {
+ namespace eval keramik {
+ variable version 0.3.2
+ }
+ }
+}
+
+namespace eval tile::theme::keramik {
+
+ variable imgdir [file join [file dirname [info script]] keramik]
+ variable I
+ array set I [tile::LoadImages $imgdir *.gif]
+
+ variable colors
+ array set colors {
+ -frame "#cccccc"
+ -lighter "#cccccc"
+ -window "#ffffff"
+ -selectbg "#eeeeee"
+ -selectfg "#000000"
+ -disabledfg "#aaaaaa"
+ }
+
+ style theme create keramik -parent alt -settings {
+
+
+ # -----------------------------------------------------------------
+ # Theme defaults
+ #
+ style default . \
+ -borderwidth 1 \
+ -background $colors(-frame) \
+ -troughcolor $colors(-lighter) \
+ -font TkDefaultFont \
+ ;
+
+ style map . -foreground [list disabled $colors(-disabledfg)]
+
+ # -----------------------------------------------------------------
+ # Button elements
+ # - the button has a large rounded border and needs a bit of
+ # horizontal padding.
+ # - the checkbutton and radiobutton have the focus drawn around
+ # the whole widget - hence the new layouts.
+ #
+ style layout TButton {
+ Button.background
+ Button.button -children {
+ Button.focus -children {
+ Button.label
+ }
+ }
+ }
+ style layout Toolbutton {
+ Toolbutton.background
+ Toolbutton.button -children {
+ Toolbutton.focus -children {
+ Toolbutton.label
+ }
+ }
+ }
+ style element create button image $I(button-n) \
+ -border {8 6 8 16} -padding {6 6} -sticky news \
+ -map [list {pressed !disabled} $I(button-p) \
+ {active !selected} $I(button-h) \
+ selected $I(button-s) \
+ disabled $I(button-d)]
+ style default TButton -padding {10 6}
+
+ style element create Toolbutton.button image $I(tbar-n) \
+ -border {2 8 2 16} -padding {2 2} -sticky news \
+ -map [list {pressed !disabled} $I(tbar-p) \
+ {active !selected} $I(tbar-a) \
+ selected $I(tbar-p)]
+
+ style element create Checkbutton.indicator image $I(check-u) \
+ -width 20 -sticky w \
+ -map [list selected $I(check-c)]
+
+ style element create Radiobutton.indicator image $I(radio-u) \
+ -width 20 -sticky w \
+ -map [list selected $I(radio-c)]
+
+ # The layout for the menubutton is modified to have a button element
+ # drawn on top of the background. This means we can have transparent
+ # pixels in the button element. Also, the pixmap has a special
+ # region on the right for the arrow. So we draw the indicator as a
+ # sibling element to the button, and draw it after (ie on top of) the
+ # button image.
+ style layout TMenubutton {
+ Menubutton.background
+ Menubutton.button -children {
+ Menubutton.focus -children {
+ Menubutton.padding -children {
+ Menubutton.label -side left -expand true
+ }
+ }
+ }
+ Menubutton.indicator -side right
+ }
+ style element create Menubutton.button image $I(mbut-n) \
+ -map [list {active !disabled} $I(mbut-a) \
+ {pressed !disabled} $I(mbut-a) \
+ {disabled} $I(mbut-d)] \
+ -border {7 10 29 15} -padding {7 4 29 4} -sticky news
+ style element create Menubutton.indicator image $I(mbut-arrow-n) \
+ -width 11 -sticky w -padding {0 0 18 0}
+
+ # -----------------------------------------------------------------
+ # Scrollbars, scale and progress elements
+ # - the scrollbar has three arrow buttons, two at the bottom and
+ # one at the top.
+ #
+ style layout Vertical.TScrollbar {
+ Scrollbar.background
+ Scrollbar.trough -children {
+ Scrollbar.uparrow -side top
+ Scrollbar.downarrow -side bottom
+ Scrollbar.uparrow -side bottom
+ Vertical.Scrollbar.thumb -side top -expand true -sticky ns
+ }
+ }
+
+ style layout Horizontal.TScrollbar {
+ Scrollbar.background
+ Scrollbar.trough -children {
+ Scrollbar.leftarrow -side left
+ Scrollbar.rightarrow -side right
+ Scrollbar.leftarrow -side right
+ Horizontal.Scrollbar.thumb -side left -expand true -sticky we
+ }
+ }
+
+ style default TScrollbar -width 16
+
+ style element create Horizontal.Scrollbar.thumb image $I(hsb-n) \
+ -border {6 4} -width 15 -height 16 -sticky news \
+ -map [list {pressed !disabled} $I(hsb-p)]
+
+ style element create Vertical.Scrollbar.thumb image $I(vsb-n) \
+ -border {4 6} -width 16 -height 15 -sticky news \
+ -map [list {pressed !disabled} $I(vsb-p)]
+
+ style element create Scale.slider image $I(hslider-n) \
+ -border 3
+
+ style element create Vertical.Scale.slider image $I(vslider-n) \
+ -border 3
+
+ style element create Horizontal.Progress.bar image $I(hsb-n) \
+ -border {6 4}
+
+ style element create Vertical.Progress.bar image $I(vsb-n) \
+ -border {4 6}
+
+ style element create uparrow image $I(arrowup-n) \
+ -map [list {pressed !disabled} $I(arrowup-p)]
+
+ style element create downarrow image $I(arrowdown-n) \
+ -map [list {pressed !disabled} $I(arrowdown-p)]
+
+ style element create rightarrow image $I(arrowright-n) \
+ -map [list {pressed !disabled} $I(arrowright-p)]
+
+ style element create leftarrow image $I(arrowleft-n) \
+ -map [list {pressed !disabled} $I(arrowleft-p)]
+
+ # -----------------------------------------------------------------
+ # Notebook elements
+ #
+ style element create tab image $I(tab-n) \
+ -map [list selected $I(tab-p) active $I(tab-p)] \
+ -border {6 6 6 2} -height 12
+
+ ## Labelframes.
+ #
+ style default TLabelframe -borderwidth 2 -relief groove
+ }
+}
+
+package provide tile::theme::keramik $::tile::theme::keramik::version
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-n.gif
new file mode 100644
index 0000000000..2d84f29c60
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-p.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-p.gif
new file mode 100644
index 0000000000..52ee752641
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowdown-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-n.gif
new file mode 100644
index 0000000000..ff309c56f2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-p.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-p.gif
new file mode 100644
index 0000000000..2159f274a5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowleft-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-n.gif
new file mode 100644
index 0000000000..905fa7ed1d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-p.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-p.gif
new file mode 100644
index 0000000000..0323332f30
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowright-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-n.gif
new file mode 100644
index 0000000000..20dcadb30e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-p.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-p.gif
new file mode 100644
index 0000000000..129169e4c4
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/arrowup-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-d.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-d.gif
new file mode 100644
index 0000000000..fe9bf98f81
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-d.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-h.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-h.gif
new file mode 100644
index 0000000000..210734d1ae
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-h.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-n.gif
new file mode 100644
index 0000000000..5e1eafa854
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-p.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-p.gif
new file mode 100644
index 0000000000..bfd74889f8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-s.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-s.gif
new file mode 100644
index 0000000000..1095ed7583
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/button-s.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-c.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-c.gif
new file mode 100644
index 0000000000..06e8795df8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-c.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-u.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-u.gif
new file mode 100644
index 0000000000..3c02fcbe81
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/check-u.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-n.gif
new file mode 100644
index 0000000000..1d93973c75
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-p.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-p.gif
new file mode 100644
index 0000000000..18fbae08ab
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hsb-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hslider-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hslider-n.gif
new file mode 100644
index 0000000000..334e8e4a40
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/hslider-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-a.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-a.gif
new file mode 100644
index 0000000000..2e2f1c2f10
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-a.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-arrow-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-arrow-n.gif
new file mode 100644
index 0000000000..48197cbfc9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-arrow-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-d.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-d.gif
new file mode 100644
index 0000000000..4a294b4984
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-d.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-n.gif
new file mode 100644
index 0000000000..65c0e4efa2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/mbut-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-c.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-c.gif
new file mode 100644
index 0000000000..c8257c9336
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-c.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-u.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-u.gif
new file mode 100644
index 0000000000..215a73821c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/radio-u.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-n.gif
new file mode 100644
index 0000000000..03099a95be
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-p.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-p.gif
new file mode 100644
index 0000000000..abec6aba40
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tab-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-a.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-a.gif
new file mode 100644
index 0000000000..2c223ba2c5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-a.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-n.gif
new file mode 100644
index 0000000000..77ef8a26cf
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-p.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-p.gif
new file mode 100644
index 0000000000..3179b87ad9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/tbar-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-n.gif
new file mode 100644
index 0000000000..be01e4a72a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-p.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-p.gif
new file mode 100644
index 0000000000..0bb39e91ff
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vsb-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vslider-n.gif b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vslider-n.gif
new file mode 100644
index 0000000000..cf03d7f325
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/keramik/vslider-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/keramik/pkgIndex.tcl b/ext/tk/sample/tkextlib/tile/themes/keramik/pkgIndex.tcl
new file mode 100644
index 0000000000..4bb89aa8a5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/keramik/pkgIndex.tcl
@@ -0,0 +1,15 @@
+# pkgIndex.tcl for additional tile pixmap themes.
+#
+# We don't provide the package is the image subdirectory isn't present,
+# or we don't have the right version of Tcl/Tk
+#
+# To use this automatically within tile, the tile-using application should
+# use tile::availableThemes and tile::setTheme
+#
+# $Id$
+
+if {![file isdirectory [file join $dir keramik]]} { return }
+if {![package vsatisfies [package provide Tcl] 8.4]} { return }
+
+package ifneeded tile::theme::keramik 0.3.2 \
+ [list source [file join $dir keramik.tcl]]
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc.rb b/ext/tk/sample/tkextlib/tile/themes/kroc.rb
new file mode 100644
index 0000000000..27006d847f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc.rb
@@ -0,0 +1,226 @@
+#
+# kroc.rb
+#
+# based on:
+# >> kroc.tcl - Copyright (C) 2004 David Zolli <kroc@kroc.tk>
+#
+
+imgdir = File.join(File.dirname(__FILE__), 'kroc', 'kroc')
+$images = Tk::Tile.load_images(imgdir, '*.gif')
+
+if TkPackage.vcompare(Tk::Tile.package_version, '0.5') >= 0
+ $TNotebook_Tab = Tk::Tile::TNotebook.style('Tab')
+else
+ $TNotebook_Tab = 'Tab.TNotebook'
+end
+
+def kroc_rb_settings
+ # Tk::Tile::Style.default(TkRoot, :background=>'#FCB64F',
+ # :troughcolor=>'#F8C278', :borderwidth=>1)
+ # or
+ # Tk::Tile::Style.default(Tk.root, :background=>'#FCB64F',
+ # :troughcolor=>'#F8C278', :borderwidth=>1)
+ # or
+ # Tk::Tile::Style.default('.', :background=>'#FCB64F',
+ # :troughcolor=>'#F8C278', :borderwidth=>1)
+ # or
+ # Tk::Tile::Style.default(nil, :background=>'#FCB64F',
+ # :troughcolor=>'#F8C278', :borderwidth=>1)
+ # or
+ Tk::Tile::Style.default(:background=>'#FCB64F', :troughcolor=>'#F8C278',
+ :borderwidth=>1)
+ # Tk::Tile::Style.default(TkRoot, :font=>Tk::Tile::Font::Default,
+ # :borderwidth=>1)
+ # or
+ # Tk::Tile::Style.default(Tk.root, :font=>Tk::Tile::Font::Default,
+ # :borderwidth=>1)
+ # or
+ # Tk::Tile::Style.default('.', :font=>Tk::Tile::Font::Default,
+ # :borderwidth=>1)
+ # or
+ # Tk::Tile::Style.default(nil, :font=>Tk::Tile::Font::Default,
+ # :borderwidth=>1)
+ # or
+ Tk::Tile::Style.default(:font=>Tk::Tile::Font::Default, :borderwidth=>1)
+
+ # Tk::Tile::Style.map(TkRoot, :background=>[:active, '#694418'])
+ # or
+ # Tk::Tile::Style.map(Tk.root, :background=>[:active, '#694418'])
+ # or
+ # Tk::Tile::Style.map('.', :background=>[:active, '#694418'])
+ # or
+ # Tk::Tile::Style.map(nil, :background=>[:active, '#694418'])
+ # or
+ Tk::Tile::Style.map(:background=>[:active, '#694418'])
+ Tk::Tile::Style.map(:foreground=>[:disabled, '#B2B2B2', :active, '#FFE7CB'])
+
+ # Tk::Tile::Style.default('TButton', :padding=>[10,4])
+ Tk::Tile::Style.default(Tk::Tile::TButton, :padding=>[10,4])
+
+ # Tk::Tile::Style.default('TNotebook.Tab',
+ Tk::Tile::Style.default($TNotebook_Tab,
+ :padding=>[10, 3], :font=>Tk::Tile::Font::Default)
+ # Tk::Tile::Style.map('TNotebook.Tab',
+ Tk::Tile::Style.map($TNotebook_Tab,
+ :background=>[:selected, '#FCB64F', '', '#FFE6BA'],
+ :foreground=>['', 'black'],
+ :padding=>[:selected, [10, 6, 10, 3]])
+
+ # Tk::Tile::Style.map('TScrollbar',
+ Tk::Tile::Style.map(Tk::Tile::TScrollbar,
+ :background=>[:pressed, '#694418'],
+ :arrowcolor=>[:pressed, '#FEF7CB'],
+ :relief=>[:pressed, :sunken])
+
+ # Tk::Tile::Style.layout('Vertical.TScrollbar',
+ Tk::Tile::Style.layout(Tk::Tile.style('Vertical', Tk::Tile::TScrollbar),
+ ['Scrollbar.trough', {:children=>[
+ 'Scrollbar.uparrow', {:side=>:top},
+ 'Scrollbar.downarrow', {:side=>:bottom},
+ 'Scrollbar.uparrow', {:side=>:bottom},
+ 'Scrollbar.thumb', {:side=>:top, :expand=>true}
+ ]}
+ ])
+
+ # Tk::Tile::Style.layout('Horizontal.TScrollbar',
+ Tk::Tile::Style.layout(Tk::Tile.style('Horizontal', Tk::Tile::TScrollbar),
+ ['Scrollbar.trough', {:children=>[
+ 'Scrollbar.leftarrow', {:side=>:left},
+ 'Scrollbar.rightarrow', {:side=>:right},
+ 'Scrollbar.leftarrow', {:side=>:right},
+ 'Scrollbar.thumb', {:side=>:left, :expand=>true}
+ ]}
+ ])
+
+ #
+ # Elements:
+ #
+ if Tk::Tile::TILE_SPEC_VERSION_ID >= 8
+ Tk::Tile::Style.element_create('Button.button',
+ :image,
+ [ $images['button-n'],
+ :pressed, $images['button-p'],
+ :active, $images['button-h'],
+ ], :border=>3, :sticky=>:ew)
+
+ Tk::Tile::Style.element_create('Checkbutton.indicator',
+ :image,
+ [ $images['check-nu'],
+ [:pressed, :selected],$images['check-nc'],
+ :pressed, $images['check-nu'],
+ [:active, :selected], $images['check-hc'],
+ :active, $images['check-hu'],
+ :selected, $images['check-nc'],
+ ], :sticky=>:w)
+
+ Tk::Tile::Style.element_create('Radiobutton.indicator',
+ :image,
+ [ $images['radio-nu'],
+ [:pressed,:selected],$images['radio-nc'],
+ :pressed, $images['radio-nu'],
+ [:active,:selected], $images['radio-hc'],
+ :active, $images['radio-hu'],
+ :selected, $images['radio-nc'],
+ ], :sticky=>:w)
+
+ elsif TkPackage.vcompare(Tk::Tile.package_version, '0.5') >= 0
+ Tk::Tile::Style.element_create('Button.button',
+ :image, $images['button-n'],
+ :map=>[
+ :pressed, $images['button-p'],
+ :active, $images['button-h'],
+ ], :border=>3, :sticky=>:ew)
+
+ Tk::Tile::Style.element_create('Checkbutton.indicator',
+ :image, $images['check-nu'],
+ :map=>[
+ [:pressed, :selected],$images['check-nc'],
+ :pressed, $images['check-nu'],
+ [:active, :selected], $images['check-hc'],
+ :active, $images['check-hu'],
+ :selected, $images['check-nc'],
+ ], :sticky=>:w)
+
+ Tk::Tile::Style.element_create('Radiobutton.indicator',
+ :image, $images['radio-nu'],
+ :map=>[
+ [:pressed, :selected],$images['radio-nc'],
+ :pressed, $images['radio-nu'],
+ [:active, :selected], $images['radio-hc'],
+ :active, $images['radio-hu'],
+ :selected, $images['radio-nc'],
+ ], :sticky=>:w)
+
+ else # tile 0.4 or earlier
+ Tk::Tile::Style.element_create('Button.button', :pixmap,
+ :images=>[
+ :pressed, $images['button-p'],
+ :active, $images['button-h'],
+ '', $images['button-n']
+ ], :border=>3, :tiling=>:tile)
+
+ Tk::Tile::Style.element_create('Checkbutton.indicator', :pixmap,
+ :images=>[
+ [:pressed, :selected],$images['check-nc'],
+ :pressed, $images['check-nu'],
+ [:active, :selected], $images['check-hc'],
+ :active, $images['check-hu'],
+ :selected, $images['check-nc'],
+ '', $images['check-nu'],
+ ], :tiling=>:fixed)
+
+ Tk::Tile::Style.element_create('Radiobutton.indicator', :pixmap,
+ :images=>[
+ [:pressed, :selected],$images['radio-nc'],
+ :pressed, $images['radio-nu'],
+ [:active, :selected], $images['radio-hc'],
+ :active, $images['radio-hu'],
+ :selected, $images['radio-nc'],
+ '', $images['radio-nu'],
+ ], :tiling=>:fixed)
+
+ end
+
+ #
+ # Settings:
+ #
+ # Tk::Tile::Style.layout(Tk::Tile::TButton,
+ Tk::Tile::Style.layout('TButton', [
+ 'Button.button', {:children=>[
+ 'Button.focus', {:children=>[
+ 'Button.padding', {:children=>[
+ 'Button.label', {:expand=>true, :sticky=>''}
+ ]}
+ ]}
+ ]}
+ ])
+
+ # Tk::Tile::Style.layout(Tk::Tile::TCheckbutton,
+ Tk::Tile::Style.layout('TCheckbutton', [
+ 'Checkbutton.background', # this is not needed in tile 0.5 or later
+ 'Checkbutton.border', {:children=>[
+ 'Checkbutton.padding', {:children=>[
+ 'Checkbutton.indicator', {:side=>:left},
+ 'Checkbutton.focus', {:side=>:left, :children=>[
+ 'Checkbutton.label'
+ ]}
+ ]}
+ ]}
+ ])
+
+ # Tk::Tile::Style.layout(Tk::Tile::TRadiobutton,
+ Tk::Tile::Style.layout('TRadiobutton', [
+ 'Radiobutton.background', # this is not needed in tile 0.5 or later
+ 'Radiobutton.border', {:children=>[
+ 'Radiobutton.padding', {:children=>[
+ 'Radiobutton.indicator', {:side=>:left},
+ 'Radiobutton.focus', {:expand=>true, :sticky=>:w, :children=>[
+ 'Radiobutton.label', {:side=>:right, :expand=>true}
+ ]}
+ ]}
+ ]}
+ ])
+end
+
+Tk::Tile::Style.theme_create('kroc-rb', :parent=>'alt',
+ :settings=>proc{ kroc_rb_settings() })
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc.tcl b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc.tcl
new file mode 100644
index 0000000000..73548acef2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc.tcl
@@ -0,0 +1,163 @@
+# kroc.tcl - Copyright (C) 2004 David Zolli <kroc@kroc.tk>
+#
+# A sample pixmap theme for the tile package.
+
+#package require tile::pixmap
+
+namespace eval tile {
+ namespace eval kroc {
+ variable version 0.0.1
+ }
+}
+
+namespace eval tile::kroc {
+
+ set imgdir [file join [file dirname [info script]] kroc]
+ array set Images [tile::LoadImages $imgdir *.gif]
+
+ if {[package vsatisfies [package provide tile] 0.5]} {
+ set TNoteBook_Tab TNotebook.Tab
+ } else {
+ set TNoteBook_Tab Tab.TNotebook
+ }
+
+ style theme create kroc -parent alt -settings {
+
+ style default . -background #FCB64F -troughcolor #F8C278 -borderwidth 1
+ style default . -font TkDefaultFont -borderwidth 1
+ style map . -background [list active #694418]
+ style map . -foreground [list disabled #B2B2B2 active #FFE7CB]
+
+ style default TButton -padding "10 4"
+
+ style default $TNoteBook_Tab -padding {10 3} -font TkDefaultFont
+ style map $TNoteBook_Tab \
+ -background [list selected #FCB64F {} #FFE6BA] \
+ -foreground [list {} black] \
+ -padding [list selected {10 6 10 3}]
+
+ style map TScrollbar \
+ -background { pressed #694418} \
+ -arrowcolor { pressed #FFE7CB } \
+ -relief { pressed sunken } \
+ ;
+
+ style layout Vertical.TScrollbar {
+ Scrollbar.trough -children {
+ Scrollbar.uparrow -side top
+ Scrollbar.downarrow -side bottom
+ Scrollbar.uparrow -side bottom
+ Scrollbar.thumb -side top -expand true
+ }
+ }
+
+ style layout Horizontal.TScrollbar {
+ Scrollbar.trough -children {
+ Scrollbar.leftarrow -side left
+ Scrollbar.rightarrow -side right
+ Scrollbar.leftarrow -side right
+ Scrollbar.thumb -side left -expand true
+ }
+ }
+
+ #
+ # Elements:
+ #
+ if {[package vsatisfies [package provide tile] 0.5]} {
+
+ style element create Button.button image $Images(button-n) \
+ -map [list \
+ pressed $Images(button-p) \
+ active $Images(button-h) \
+ ] -border 3 -sticky ew
+
+ style element create Checkbutton.indicator image $Images(check-nu) \
+ -map [list \
+ {pressed selected} $Images(check-nc) \
+ pressed $Images(check-nu) \
+ {active selected} $Images(check-hc) \
+ active $Images(check-hu) \
+ selected $Images(check-nc) \
+ ] -sticky w
+
+ style element create Radiobutton.indicator image $Images(radio-nu) \
+ -map [list \
+ {pressed selected} $Images(radio-nc) \
+ pressed $Images(radio-nu) \
+ {active selected} $Images(radio-hc) \
+ active $Images(radio-hu) \
+ selected $Images(radio-nc) \
+ ] -sticky w
+
+ } else {
+
+ style element create Button.button pixmap -images [list \
+ pressed $Images(button-p) \
+ active $Images(button-h) \
+ {} $Images(button-n) \
+ ] -border 3 -tiling tile
+
+ style element create Checkbutton.indicator pixmap -images [list \
+ {pressed selected} $Images(check-nc) \
+ pressed $Images(check-nu) \
+ {active selected} $Images(check-hc) \
+ active $Images(check-hu) \
+ selected $Images(check-nc) \
+ {} $Images(check-nu) \
+ ] -tiling fixed
+
+ style element create Radiobutton.indicator pixmap -images [list \
+ {pressed selected} $Images(radio-nc) \
+ pressed $Images(radio-nu) \
+ {active selected} $Images(radio-hc) \
+ active $Images(radio-hu) \
+ selected $Images(radio-nc) \
+ {} $Images(radio-nu) \
+ ] -tiling fixed
+
+ }
+
+ #
+ # Settings: (*button.background is not needed in tile 0.5 or above)
+ #
+ style layout TButton {
+ Button.button -children {
+ Button.focus -children {
+ Button.padding -children {
+ Button.label -expand true -sticky {}
+ }
+ }
+ }
+ }
+
+ style layout TCheckbutton {
+ Checkbutton.border -children {
+ Checkbutton.background
+ Checkbutton.padding -children {
+ Checkbutton.indicator -side left
+ Checkbutton.focus -side left -children {
+ Checkbutton.label
+ }
+ }
+ }
+ }
+
+ style layout TRadiobutton {
+ Radiobutton.border -children {
+ Radiobutton.background
+ Radiobutton.padding -children {
+ Radiobutton.indicator -side left
+ Radiobutton.focus -expand true -sticky w -children {
+ Radiobutton.label -side right -expand true
+ }
+ }
+ }
+ }
+
+ } }
+
+# -------------------------------------------------------------------------
+
+package provide tile::theme::kroc $::tile::kroc::version
+
+# -------------------------------------------------------------------------
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-h.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-h.gif
new file mode 100644
index 0000000000..e7a140dede
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-h.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-n.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-n.gif
new file mode 100644
index 0000000000..78b506ddeb
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-p.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-p.gif
new file mode 100644
index 0000000000..a5a4e90be1
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/button-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hc.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hc.gif
new file mode 100644
index 0000000000..41503c5ebd
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hu.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hu.gif
new file mode 100644
index 0000000000..b3e512ca67
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-hu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nc.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nc.gif
new file mode 100644
index 0000000000..a28c288fce
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nu.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nu.gif
new file mode 100644
index 0000000000..5c23931bbc
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/check-nu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hc.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hc.gif
new file mode 100644
index 0000000000..359fe1cc8b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hu.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hu.gif
new file mode 100644
index 0000000000..9f46b37926
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-hu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nc.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nc.gif
new file mode 100644
index 0000000000..6437f33a7a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nu.gif b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nu.gif
new file mode 100644
index 0000000000..2d2aac8597
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/kroc/radio-nu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc/pkgIndex.tcl b/ext/tk/sample/tkextlib/tile/themes/kroc/pkgIndex.tcl
new file mode 100644
index 0000000000..179077917c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc/pkgIndex.tcl
@@ -0,0 +1,15 @@
+# pkgIndex.tcl for additional tile pixmap themes.
+#
+# We don't provide the package is the image subdirectory isn't present,
+# or we don't have the right version of Tcl/Tk
+#
+# To use this automatically within tile, the tile-using application should
+# use tile::availableThemes and tile::setTheme
+#
+# $Id$
+
+if {![file isdirectory [file join $dir kroc]]} { return }
+if {![package vsatisfies [package provide Tcl] 8.4]} { return }
+
+package ifneeded tile::theme::kroc 0.0.1 \
+ [list source [file join $dir kroc.tcl]]
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/pkgIndex.tcl b/ext/tk/sample/tkextlib/tile/themes/plastik/pkgIndex.tcl
new file mode 100644
index 0000000000..e39aff6f44
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/pkgIndex.tcl
@@ -0,0 +1,16 @@
+# pkgIndex.tcl for additional tile pixmap themes.
+#
+# We don't provide the package is the image subdirectory isn't present,
+# or we don't have the right version of Tcl/Tk
+#
+# To use this automatically within tile, the tile-using application should
+# use tile::availableThemes and tile::setTheme
+#
+# $Id$
+
+if {![file isdirectory [file join $dir plastik]]} { return }
+if {![package vsatisfies [package provide Tcl] 8.4]} { return }
+
+package ifneeded tile::theme::plastik 0.3.1 \
+ [list source [file join $dir plastik.tcl]]
+
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik.tcl b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik.tcl
new file mode 100644
index 0000000000..ea6ed74162
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik.tcl
@@ -0,0 +1,125 @@
+# plastik.tcl - Copyright (C) 2004 Googie
+#
+# A sample pixmap theme for the tile package.
+#
+# Copyright (c) 2004 Googie
+# Copyright (c) 2005 Pat Thoyts <patthoyts@users.sourceforge.net>
+#
+# $Id$
+
+package require Tk 8.4
+package require tile 0.5
+
+namespace eval tile::theme::plastik {
+
+ variable version 0.3.1
+ package provide tile::theme::plastik $version
+
+ variable imgdir [file join [file dirname [info script]] plastik]
+ variable Images;
+ array set Images [tile::LoadImages $imgdir *.gif]
+
+ variable colors
+ array set colors {
+ -frame "#cccccc"
+ -disabledfg "#aaaaaa"
+ -selectbg "#657a9e"
+ -selectfg "#ffffff"
+ }
+
+style theme create plastik -parent default -settings {
+ style default . \
+ -background $colors(-frame) \
+ -troughcolor $colors(-frame) \
+ -selectbackground $colors(-selectbg) \
+ -selectforeground $colors(-selectfg) \
+ -font TkDefaultFont \
+ -borderwidth 1 \
+ ;
+
+ style map . -foreground [list disabled $colors(-disabledfg)]
+
+ #
+ # Layouts:
+ #
+ style layout Vertical.TScrollbar {
+ Scrollbar.background
+ Scrollbar.trough -children {
+ Scrollbar.uparrow -side top
+ Scrollbar.downarrow -side bottom
+ Scrollbar.uparrow -side bottom
+ Vertical.Scrollbar.thumb -side top -expand true -sticky ns
+ }
+ }
+
+ style layout Horizontal.TScrollbar {
+ Scrollbar.background
+ Scrollbar.trough -children {
+ Scrollbar.leftarrow -side left
+ Scrollbar.rightarrow -side right
+ Scrollbar.leftarrow -side right
+ Horizontal.Scrollbar.thumb -side left -expand true -sticky we
+ }
+ }
+
+ style layout TButton {
+ Button.button -children {
+ Button.focus -children {
+ Button.padding -children {
+ Button.label -side left -expand true
+ }
+ }
+ }
+ }
+
+ #
+ # Elements:
+ #
+ style element create Button.button image $Images(button-n) \
+ -border 4 -sticky ew \
+ -map [list pressed $Images(button-p) active $Images(button-h)]
+
+ style element create Checkbutton.indicator image $Images(check-nu) \
+ -sticky {} -map [list \
+ {active selected} $Images(check-hc) \
+ {pressed selected} $Images(check-pc) \
+ active $Images(check-hu) \
+ selected $Images(check-nc) \
+ ]
+
+ style element create Radiobutton.indicator image $Images(radio-nu) \
+ -sticky {} -map [list \
+ {active selected} $Images(radio-hc) \
+ {pressed selected} $Images(radio-pc) \
+ active $Images(radio-hu) \
+ selected $Images(radio-nc) \
+ ]
+
+ style element create Horizontal.Scrollbar.thumb \
+ image $Images(hsb-n) -border 3 -sticky ew
+ style element create Vertical.Scrollbar.thumb \
+ image $Images(vsb-n) -border 3 -sticky ns
+
+ style element create Scale.slider \
+ image $Images(hslider-n) -sticky {}
+ style element create Vertical.Scale.slider \
+ image $Images(vslider-n) -sticky {}
+
+ style element create Scrollbar.uparrow image $Images(arrowup-n) \
+ -map [list pressed $Images(arrowup-p)] -sticky {}
+ style element create Scrollbar.downarrow image $Images(arrowdown-n) \
+ -map [list pressed $Images(arrowdown-p)] -sticky {}
+ style element create Scrollbar.leftarrow image $Images(arrowleft-n) \
+ -map [list pressed $Images(arrowleft-p)] -sticky {}
+ style element create Scrollbar.rightarrow image $Images(arrowright-n) \
+ -map [list pressed $Images(arrowright-p)] -sticky {}
+
+ #
+ # Settings:
+ #
+ style default TButton -width -10
+ style default TNotebook.Tab -padding {6 2 6 2}
+ style default TLabelframe -borderwidth 2 -relief groove
+
+} }
+
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-n.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-n.gif
new file mode 100644
index 0000000000..d914e7a3d3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-p.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-p.gif
new file mode 100644
index 0000000000..abffaa49f6
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowdown-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-n.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-n.gif
new file mode 100644
index 0000000000..9939ae1d50
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-p.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-p.gif
new file mode 100644
index 0000000000..1a45ef2e4b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowleft-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-n.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-n.gif
new file mode 100644
index 0000000000..f4b563fed2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-p.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-p.gif
new file mode 100644
index 0000000000..5459d5e615
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowright-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-n.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-n.gif
new file mode 100644
index 0000000000..118290cd95
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-p.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-p.gif
new file mode 100644
index 0000000000..89f9b38c73
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/arrowup-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-h.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-h.gif
new file mode 100644
index 0000000000..548f3769df
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-h.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-n.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-n.gif
new file mode 100644
index 0000000000..49a25909f3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-p.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-p.gif
new file mode 100644
index 0000000000..e83f7ed985
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/button-p.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hc.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hc.gif
new file mode 100644
index 0000000000..b279fa50d8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hu.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hu.gif
new file mode 100644
index 0000000000..5b4fb4f037
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-hu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nc.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nc.gif
new file mode 100644
index 0000000000..b139e02a09
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nu.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nu.gif
new file mode 100644
index 0000000000..fbe391f9d8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-nu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-pc.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-pc.gif
new file mode 100644
index 0000000000..75a3bd635c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/check-pc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hsb-n.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hsb-n.gif
new file mode 100644
index 0000000000..b8ea07ea92
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hsb-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hslider-n.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hslider-n.gif
new file mode 100644
index 0000000000..ce8f28404f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/hslider-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hc.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hc.gif
new file mode 100644
index 0000000000..33917715b0
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hu.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hu.gif
new file mode 100644
index 0000000000..88925d0e1d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-hu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nc.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nc.gif
new file mode 100644
index 0000000000..f8723d367a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nu.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nu.gif
new file mode 100644
index 0000000000..fb5140e6a1
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-nu.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-pc.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-pc.gif
new file mode 100644
index 0000000000..176225d9e1
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/radio-pc.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vsb-n.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vsb-n.gif
new file mode 100644
index 0000000000..85bac4579e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vsb-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vslider-n.gif b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vslider-n.gif
new file mode 100644
index 0000000000..cf887f9855
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/themes/plastik/plastik/vslider-n.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tile/toolbutton.tcl b/ext/tk/sample/tkextlib/tile/toolbutton.tcl
new file mode 100644
index 0000000000..4e08034e31
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tile/toolbutton.tcl
@@ -0,0 +1,152 @@
+#
+# $Id$
+#
+# Demonstration of custom widget styles.
+#
+
+#
+# ~ BACKGROUND
+#
+# Checkbuttons in toolbars have a very different appearance
+# than regular checkbuttons: there's no indicator, they
+# "pop up" when the mouse is over them, and they appear sunken
+# when selected.
+#
+# Tk added partial support for toolbar-style buttons in 8.4
+# with the "-overrelief" option, and TIP #82 added further
+# support with the "-offrelief" option. So to get a toolbar-style
+# checkbutton, you can configure it with:
+#
+# checkbutton .cb \
+# -indicatoron false -selectcolor {} -relief flat -overrelief raised
+#
+# Behind the scenes, Tk has a lot of rather complicated logic
+# to implement this checkbutton style; see library/button.tcl,
+# generic/tkButton.c, and the platform-specific files unix/tkUnixButton.c
+# et al. for the full details.
+#
+# The tile widget set has a better way: custom styles.
+# Since the appearance is completely controlled by the theme engine,
+# we can define a new "Toolbutton" style and just use:
+#
+# checkbutton .cb -style Toolbutton
+#
+#
+# ~ DEMONSTRATION
+#
+# The tile built-in themes (default, "alt", windows, and XP)
+# already include Toolbutton styles. This script will add
+# them to the "step" and "blue" themes as a demonstration.
+#
+# (Note: Pushbuttons and radiobuttons can also use the "Toolbutton"
+# style; see demo.tcl.)
+#
+
+style theme settings "step" {
+
+#
+# First, we use [style layout] to define what elements to
+# use and how they're arranged. Toolbuttons are pretty
+# simple, consisting of a border, some internal padding,
+# and a label. (See also the TScrollbar layout definition
+# in demos/blue.tcl for a more complicated layout spec.)
+#
+ style layout Toolbutton {
+ Toolbutton.background
+ Toolbutton.border -children {
+ Toolbutton.padding -children {
+ Toolbutton.label
+ }
+ }
+ }
+
+# (Actually the above isn't strictly necessary, since the same layout
+# is defined in the default theme; we could have inherited it
+# instead.)
+#
+# Next, specify default values for element options.
+# For many options (like -background), the defaults
+# inherited from the parent style are sufficient.
+#
+ style default Toolbutton -width 0 -padding 1 -relief flat -borderwidth 2
+
+#
+# Finally, use [style map] to specify state-specific
+# resource values. We want a flat relief if the widget is
+# disabled, sunken if it's selected (on) or pressed,
+# and raised when it's active (the mouse pointer is
+# over the widget). Each state-value pair is checked
+# in order, and the first matching state takes precedence.
+#
+ style map Toolbutton -relief {
+ disabled flat
+ selected sunken
+ pressed sunken
+ active raised
+ }
+}
+
+#
+# Now for the "blue" theme. (Since the purpose of this
+# theme is to show what *can* be done, not necessarily what
+# *should* be done, the following makes some questionable
+# design decisions from an aesthetic standpoint.)
+#
+if {![catch {package require tile::theme::blue}]} {
+style theme settings "blue" {
+
+ #
+ # Default values:
+ #
+ style default Toolbutton \
+ -width 0 -relief flat -borderwidth 2 \
+ -background #6699CC -foreground #000000 ;
+
+ #
+ # Configure state-specific values for -relief, as before:
+ #
+ style map Toolbutton -relief {
+ disabled flat
+ selected sunken
+ pressed sunken
+ active raised
+ }
+
+ #
+ # Adjust the -padding at the same time, to enhance
+ # the raised/sunken illusion:
+ #
+ style default Toolbutton -padding 4
+ style map Toolbutton -padding {
+ disabled {4}
+ selected {6 6 2 2}
+ pressed {6 6 2 2}
+ active {2 2 6 6}
+ }
+
+ #
+ # ... and change the foreground and background colors
+ # when the mouse cursor is over the widget:
+ #
+ style map Toolbutton -background {
+ active #008800
+ } -foreground {
+ active #FFFFFF
+ }
+}
+
+}
+
+#
+# ~ A final note:
+#
+# TIP #82 also says: "When -indicatoron is off and the button itself
+# is on, the relief continues to be hard-coded to sunken. For symmetry,
+# we might consider adding another -onrelief option to cover this
+# case. But it is difficult to imagine ever wanting to change the
+# value of -onrelief so it has been omitted from this TIP.
+# If there as strong desire to have -onrelief, it can be added later."
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# The Tile project aims to make sure that this never needs to happen.
+#
diff --git a/ext/tk/sample/tkextlib/tkHTML/Orig_COPYRIGHT.txt b/ext/tk/sample/tkextlib/tkHTML/Orig_COPYRIGHT.txt
new file mode 100644
index 0000000000..2b3757bb23
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/Orig_COPYRIGHT.txt
@@ -0,0 +1,12 @@
+
+The following text is the original 'COPYRIGHT' file of tkHTML.
+
+-----------------------------------------------------------------------
+Most of the source code for the Tk Html widget has been place in the
+public domain. You can do with it whatever you want. However, some
+files have been copied from other sources and contain copyrights.
+A copyright notice appears separately at the top of each source file.
+-----------------------------------------------------------------------
+
+In this sample, HTML documents are quoted in the 'tests' directory of
+tkHTML source tree. There were no copyright notice in the directory.
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..a4d78ea5b1
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/hv.rb
@@ -0,0 +1,313 @@
+#!/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 <IMG> markup
+#
+images = {}
+old_imgs = {}
+big_imgs = {}
+
+hotkey = {}
+
+move_big_image = proc{|b|
+ if big_imgs.key?(b)
+ b.copy(big_imgs[b])
+ big_imgs[b].delete
+ big_imgs.delete(b)
+ Tk.update
+ end
+}
+
+image_cmd = proc{|*args|
+ if show_img.bool
+ smgray
+ else
+ fn = args[0]
+
+ if old_imgs.key?(fn)
+ images[fn] = old_imgs[fn]
+ old_imgs.delete(fn)
+ images[fn]
+
+ else
+ begin
+ img = TkPhotoImage.new(:file=>fn)
+ rescue
+ smgray
+ else
+ 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
+ end
+ end
+ end
+}
+
+#
+# This routine is called for every <SCRIPT> markup
+#
+script_cmd = proc{|*args|
+ # puts "ScriptCmd: #{args.inspect}"
+}
+
+# This routine is called for every <APPLET> markup
+#
+applet_cmd = proc{|w, arglist|
+ # puts "AppletCmd: w=#{w} arglist=#{arglist}"
+ TkLabel.new(w, :text=>"The Applet #{w}", :bd=>2, :relief=>raised)
+}
+
+#
+# Construct the main HTML viewer
+#
+html = Tk::HTML_Widget.new(:padx=>5, :pady=>9,
+ :formcommand=>form_cmd,
+ :imagecommand=>image_cmd,
+ :scriptcommand=>script_cmd,
+ :appletcommand=>applet_cmd,
+ :underlinehyperlinks=>0,
+ :bg=>'white', :tablerelief=>:raised)
+vscr = html.yscrollbar(TkScrollbar.new)
+hscr = html.xscrollbar(TkScrollbar.new)
+
+Tk.grid(html, vscr, :sticky=>:news)
+Tk.grid(hscr, :sticky=>:ew)
+Tk.root.grid_columnconfigure(0, :weight=>1)
+Tk.root.grid_columnconfigure(1, :weight=>0)
+Tk.root.grid_rowconfigure(0, :weight=>1)
+Tk.root.grid_rowconfigure(1, :weight=>0)
+
+#
+# This procedure is called when the user clicks on a hyperlink.
+#
+priv = {}
+last_file = ''
+
+# Read a file
+#
+read_file = proc{|name|
+ begin
+ fp = open(name, 'r')
+ ret = fp.read(File.size(name))
+ rescue
+ ret = nil
+ fp = nil
+ Tk.messageBox(:icon=>'error', :message=>"fail to open '#{name}'",
+ :type=>:ok)
+ ensure
+ fp.close if fp
+ end
+ ret
+}
+
+# Clear the screen.
+#
+clear_screen = proc{
+ html.clear
+ old_imgs.clear
+ big_imgs.clear
+ hotkey.clear
+ images.each{|k, v| old_imgs[k] = v }
+ images.clear
+}
+
+# Load a file into the HTML widget
+#
+load_file = proc{|name|
+ if (doc = read_file.call(name))
+ clear_screen.call
+ last_file = name
+ html.configure(:base=>name)
+ html.parse(doc)
+ old_imgs.clear
+ end
+}
+
+href_binding = proc{|x, y|
+ # koba & dg marking text
+ html.selection_clear
+ priv['mark'] = "@#{x},#{y}"
+ lst = html.href(x, y)
+
+ unless lst.size.zero?
+ lnk, target = lst
+
+ if lnk != ""
+ if lnk =~ /^#{last_file}#(.*)$/
+ html.yview($1)
+ else
+ load_file.call(lnk)
+ end
+ end
+ end
+}
+html.clipping_window.bind('1', href_binding, '%x %y')
+
+# marking text with the mouse and copying to the clipboard just with tkhtml2.0 working
+html.clipping_window.bind('B1-Motion', proc{|w, x, y|
+ w.selection_set(priv['mark'], "@#{x},#{y}")
+ TkClipboard.clear
+ # avoid tkhtml0.0 errors
+ # anyone can fix this for tkhtml0.0
+ begin
+ TkClipboard.append(TkSelection.get)
+ rescue
+ end
+ }, '%W %x %y')
+
+# This procedure is called when the user selects the File/Open
+# menu option.
+#
+last_dir = Dir.pwd
+sel_load = proc{
+ filetypes = [
+ ['Html Files', ['.html', '.htm']],
+ ['All Files', '*']
+ ]
+
+ f = Tk.getOpenFile(:initialdir=>last_dir, :filetypes=>filetypes)
+ if f != ''
+ load_file.call(f)
+ last_dir = File.dirname(f)
+ end
+}
+
+# Refresh the current file.
+#
+refresh = proc{|*args|
+ load_file.call(last_file)
+}
+
+# This binding changes the cursor when the mouse move over
+# top of a hyperlink.
+#
+Tk::HTML_Widget::ClippingWindow.bind('Motion', proc{|w, x, y|
+ parent = w.winfo_parent
+ url = parent.href(x, y)
+ unless url.empty?
+ parent[:cursor] = 'hand2'
+ else
+ parent[:cursor] = ''
+ end
+ }, '%W %x %y')
+#
+# Setup menu
+#
+menu_spec = [
+ [['File', 0],
+ ['Open', sel_load, 0],
+ ['Refresh', refresh, 0],
+ '---',
+ ['Exit', proc{exit}, 1]],
+
+ [['View', 0],
+ ['Underline Hyperlinks', ul_hyper],
+ ['Show Table Structure', show_tbl],
+ ['Show Images', show_img]]
+]
+
+mbar = Tk.root.add_menubar(menu_spec)
+
+#
+# Setup trace
+#
+ul_hyper.trace('w', proc{
+ html[:underlinehyperlinks] = ul_hyper.value
+ refresh.call
+ })
+
+show_tbl.trace('w', proc{
+ if show_tbl.bool
+ html[:tablerelief] = :flat
+ else
+ html[:tablerelief] = :raised
+ end
+ refresh.call
+ })
+
+show_img.trace('w', refresh)
+
+# If an arguent was specified, read it into the HTML widget.
+#
+Tk.update
+if file && file != ""
+ load_file.call(file)
+end
+
+#####################################
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image1 b/ext/tk/sample/tkextlib/tkHTML/page1/image1
new file mode 100644
index 0000000000..31e96b6797
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image1
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image10 b/ext/tk/sample/tkextlib/tkHTML/page1/image10
new file mode 100644
index 0000000000..80a8f81686
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image10
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image11 b/ext/tk/sample/tkextlib/tkHTML/page1/image11
new file mode 100644
index 0000000000..e8cb01d450
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image11
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image12 b/ext/tk/sample/tkextlib/tkHTML/page1/image12
new file mode 100644
index 0000000000..c317bbd5cc
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image12
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image13 b/ext/tk/sample/tkextlib/tkHTML/page1/image13
new file mode 100644
index 0000000000..ac4b3cd594
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image13
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image14 b/ext/tk/sample/tkextlib/tkHTML/page1/image14
new file mode 100644
index 0000000000..c3b02558e3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image14
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image2 b/ext/tk/sample/tkextlib/tkHTML/page1/image2
new file mode 100644
index 0000000000..da26d7092e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image2
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image3 b/ext/tk/sample/tkextlib/tkHTML/page1/image3
new file mode 100644
index 0000000000..d91cdfafab
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image3
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image4 b/ext/tk/sample/tkextlib/tkHTML/page1/image4
new file mode 100644
index 0000000000..5fdf70c0e5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image4
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image5 b/ext/tk/sample/tkextlib/tkHTML/page1/image5
new file mode 100644
index 0000000000..67cd14d78d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image5
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image6 b/ext/tk/sample/tkextlib/tkHTML/page1/image6
new file mode 100644
index 0000000000..9e05aa0f36
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image6
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image7 b/ext/tk/sample/tkextlib/tkHTML/page1/image7
new file mode 100644
index 0000000000..879656d45c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image7
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image8 b/ext/tk/sample/tkextlib/tkHTML/page1/image8
new file mode 100644
index 0000000000..8c647c4f00
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image8
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/image9 b/ext/tk/sample/tkextlib/tkHTML/page1/image9
new file mode 100644
index 0000000000..3a7707589b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/image9
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page1/index.html b/ext/tk/sample/tkextlib/tkHTML/page1/index.html
new file mode 100644
index 0000000000..9efac7f7af
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page1/index.html
@@ -0,0 +1,115 @@
+<HTML><HEAD><TITLE>Slashdot:News for Nerds. Stuff that Matters.</TITLE> </HEAD>
+<BODY bgcolor="#000000" text="#000000" link="#006666" vlink="#000000">
+<center><a href="http://209.207.224.220/redir.pl?1463" target="_top"><img src="image1" alt="Click Here to enter the Sweepstakes" border="2" width="468" height="60"></a></center> <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0"><TR><TD WIDTH="1"><SCRIPT LANGUAGE="JAVASCRIPT">
+<!-- now="now" ="" new="new" Date();="Date();" tail="tail" ="" now.getTime();="now.getTime();" document.write("<IMG="document.write("<IMG" SRC="http://209.207.224.245/Slashdot/pc.gif?/slashhead.inc,"+" tail="tail" +="+" "=""" WIDTH="1" HEIGHT="1><BR>");" -->
+</SCRIPT>
+<NOSCRIPT>
+<IMG SRC="image2" WIDTH="1" HEIGHT="1">
+</NOSCRIPT></TD></TR></TABLE><P>
+<TABLE bgcolor="#FFFFFF" cellpadding="0" cellspacing="0" border="0" width="99%" align="center">
+ <TR>
+ <TD valign="top" align="left" valign="top"><A href="http://slashdot.org/"><IMG src="image3" width="275" height="72" border="0" alt="Welcome to Slashdot"></A></TD>
+ <TD><A href="http://slashdot.org/search.pl?topic=linux"><IMG SRC="image4" width="60" height="70" border="0" alt="Linux"></A></TD>
+<TD><A href="http://slashdot.org/search.pl?topic=news"><IMG SRC="image5" width="34" height="44" border="0" alt="News"></A></TD>
+<TD><A href="http://slashdot.org/search.pl?topic=usa"><IMG SRC="image6" width="80" height="61" border="0" alt="United States"></A></TD>
+<TD><A href="http://slashdot.org/search.pl?topic=ed"><IMG SRC="image7" width="87" height="64" border="0" alt="Education"></A></TD>
+<TD><A href="http://slashdot.org/search.pl?topic=space"><IMG SRC="image8" width="73" height="59" border="0" alt="Space"></A></TD>
+
+</TR></TABLE>
+<TABLE width="99%" align="center" cellpadding="0" cellspacing="0" border="0" bgcolor="#FFFFFF"><TR>
+<TD valign="top" rowspan="5"><NOBR><FONT size="2"><B>
+&nbsp;<A href="/faq.shtml">faq</A> <BR>
+&nbsp;<A href="/code.shtml">code</A> <BR>
+&nbsp;<A href="/awards.shtml">awards</A> <BR>
+&nbsp;<A href="http://Andover.Net/privacy.html">privacy</A> <BR>
+&nbsp;<A href="http://slashnet.org">slashNET</A> <BR>
+&nbsp;<A href="/search.pl">older stuff</A> <BR>
+&nbsp;<A href="http://cmdrtaco.net">rob's page</A> <BR>
+&nbsp;<A href="/users.pl?op=preferences">preferences</A> <BR>
+&nbsp;<A href="http://Andover.Net">andover.net</A> <BR>
+&nbsp;<A href="/submit.pl">submit story</A> <BR>
+&nbsp;<A href="/advertising.shtml">advertising</A> <BR>
+&nbsp;<A href="/supporters.shtml">supporters</A> <BR>
+&nbsp;<A href="/pollBooth.pl">past polls</A> <BR>
+&nbsp;<A href="/topics.shtml">topics</A> <BR>
+&nbsp;<A href="/about.shtml">about</A> <BR>
+&nbsp;<A href="/jobs.shtml">jobs</A> <BR>
+&nbsp;<A href="/hof.shtml">hof</A>
+
+</B></FONT></NOBR>
+ <P><TABLE border="0" cellpadding="1" cellspacing="0" align="center" bgcolor="#CCCCCC"><TR>
+ <TD><FONT size="2" color="#000000"><B> Sections</B></FONT></TD></TR>
+ <TR><TD><TABLE border="0" cellspacing="1" cellpadding="1" bgcolor="#FFFFFF" width="100%"><TR><TD><FONT color="#000000" size="2"><NOBR>
+1/23<BR>
+<B><A href="http://slashdot.org/index.pl?section=apache">apache</A></B><BR>
+1/29 (3)<BR>
+<B><A href="http://slashdot.org/index.pl?section=askslashdot">askslashdot</A></B><BR>
+1/27<BR>
+<B><A href="http://slashdot.org/index.pl?section=awards">awards</A></B><BR>
+1/29 (2)<BR>
+<B><A href="http://slashdot.org/index.pl?section=books">books</A></B><BR>
+1/27<BR>
+<B><A href="http://slashdot.org/index.pl?section=bsd">bsd</A></B><BR>
+1/28 (2)<BR>
+<B><A href="http://slashdot.org/index.pl?section=features">features</A></B><BR>
+1/28 (2)<BR>
+<B><A href="http://slashdot.org/index.pl?section=interviews">interviews</A></B><BR>
+1/19<BR>
+<B><A href="http://slashdot.org/index.pl?section=radio">radio</A></B><BR>
+1/27 (2)<BR>
+<B><A href="http://slashdot.org/index.pl?section=science">science</A></B><BR>
+1/28 (3)<BR>
+<B><A href="http://slashdot.org/index.pl?section=yro">yro</A></B><BR> </NOBR></FONT></TD></TR></TABLE><TR>
+ <TD><A href="http://andover.net"><FONT size="2" color="#000000"><B>Andover.Net</B></FONT></A></TD></TR>
+ <TR><TD><TABLE border="0" cellspacing="1" cellpadding="1" bgcolor="#FFFFFF"><TR><TD>
+<FONT color="#000000" size="2"><NOBR><A href="http://www.andovernews.com">AndoverNews</A><BR><A href="http://www.askreggie.com">Ask Reggie</A><BR><A href="http://www.davecentral.com">DaveCentral</A><BR><A href="http://www.freecode.com">FreeCode</A><BR><A href="http://www.mediabuilder.com">MediaBuilder</A><BR> </NOBR></FONT></TD></TR></TABLE></TD></TR></TABLE></P>
+ <P></P>
+</TD><TD valign="top" align="left"><FONT color="#000000"> <TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Who Bought Linux.Net?</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=linux"><IMG src="image4" width="60" height="70" border="0" align="right" hspace="20" vspace="10" alt="Linux"></A> <B>Posted by <A href="http://CmdrTaco.net">CmdrTaco</A> on Saturday January 29, @10:52AM</B><BR> <FONT size="2"><B>from the this-game-again dept.</B></FONT><BR> 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 <A href="http://www.linux.com">Linux.com</A> to <A href="http://www.valinux.com">VA Linux</A>. Hopefully he'll take me for a ride in his yacht. ;) <P><B>( </B><A href="http://slashdot.org/articles/00/01/29/0837235.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/29/0837235&mode=thread&threshold=0">58</A> of <A href="http://slashdot.org/article.pl?sid=00/01/29/0837235&mode=thread&threshold=-1">62</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Book Reviews: E-Mails from (Over?) The Edge</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=news"><IMG src="image5" width="34" height="44" border="0" align="right" hspace="20" vspace="10" alt="News"></A> <B>Posted by <A href="http://hemos.net">Hemos</A> on Saturday January 29, @10:43AM</B><BR> <FONT size="2"><B>from the touching-story dept.</B></FONT><BR> 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 <a href="http://www.thevenue.org">TheVenue</a>. I'll warn you - it's not a tech text. But it's still worth reading. Click below to read more. <P><B>( </B><A href="http://slashdot.org/books/00/01/24/1146250.shtml"><B>Read More...</B></A> | <A href="http://slashdot.org/article.pl?sid=00/01/24/1146250&mode=nocomment">6197 bytes in body</A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/24/1146250&mode=thread&threshold=0">6</A> of <A href="http://slashdot.org/article.pl?sid=00/01/24/1146250&mode=thread&threshold=-1">22</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Linux Kernel 2.3.41</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=linux"><IMG src="image4" width="60" height="70" border="0" align="right" hspace="20" vspace="10" alt="Linux"></A> <B>Posted by <A href="http://CmdrTaco.net">CmdrTaco</A> on Saturday January 29, @10:21AM</B><BR> <FONT size="2"><B>from the download-compile-reboot-repeat dept.</B></FONT><BR> <A href="mailto:bwhitehead@nospam.acm.org">sdriver</A> writes <I>"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! ;) "</I> 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! <P><B>( </B><A href="http://slashdot.org/articles/00/01/29/0834223.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/29/0834223&mode=thread&threshold=0">52</A> of <A href="http://slashdot.org/article.pl?sid=00/01/29/0834223&mode=thread&threshold=-1">57</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Congress Still Figuring Out E-Mail</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=usa"><IMG src="image6" width="80" height="61" border="0" align="right" hspace="20" vspace="10" alt="United States"></A> <B>Posted by <A href="mailto:roblimo@slashdot.org">Roblimo</A> on Saturday January 29, @07:28AM</B><BR> <FONT size="2"><B>from the voice-of-the-people-can-get-awfully-loud dept.</B></FONT><BR> Jett writes <I>" <A href="http://www.vote.com/">Vote.com</A> has <A href="http://www.vote.com/magazine/editorials/editorial1843752.phtml">an interesting article</A> 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.'"</I> <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/2311232.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/2311232&mode=thread&threshold=0">66</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/2311232&mode=thread&threshold=-1">66</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Ask Slashdot: Sci Fi Literature 101?</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=ed"><IMG src="image7" width="87" height="64" border="0" align="right" hspace="20" vspace="10" alt="Education"></A> <B>Posted by <A href="http://exit118.com/">Cliff</A> on Saturday January 29, @06:56AM</B><BR> <FONT size="2"><B>from the recommendations-wanted dept.</B></FONT><BR> ohlaadee asks: <I>"My niece (she's 13) wants to start reading science fiction. I do too. I gave us both Asimov's </I>_The Foundation_<I>&nbsp; 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?"</I> <P><B>( </B><A href="http://slashdot.org/askslashdot/00/01/22/1946244.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/22/1946244&mode=thread&threshold=0">345</A> of <A href="http://slashdot.org/article.pl?sid=00/01/22/1946244&mode=thread&threshold=-1">345</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Could Distributed.Net Help the Mars Polar Lander?</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=space"><IMG src="image8" width="73" height="59" border="0" align="right" hspace="20" vspace="10" alt="Space"></A> <B>Posted by <A href="mailto:roblimo@slashdot.org">Roblimo</A> on Saturday January 29, @03:35AM</B><BR> <FONT size="2"><B>from the food-for-thought dept.</B></FONT><BR> Anonymous Coward writes <I>"This official JPL <A href="http://mpfwww.jpl.nasa.gov/msp98/news/mpl000127.html">press release</A> 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 <A href="http://www.distributed.net"> distributed.net</A>."</I> Interesting thought. Is anyone at distributed.net or JPL interested in pursuing it? <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/2318246.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/2318246&mode=thread&threshold=0">99</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/2318246&mode=thread&threshold=-1">102</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>iCrave TV Loses Battle against U.S. Broadcasters</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=tv"><IMG src="image10" width="50" height="50" border="0" align="right" hspace="20" vspace="10" alt="Television"></A> <B>Posted by <A href="mailto:roblimo@slashdot.org">Roblimo</A> on Saturday January 29, @12:21AM</B><BR> <FONT size="2"><B>from the shut-down-just-before-the-super-bowl dept.</B></FONT><BR> <A href="mailto:doran@brandx.net">Doran</A> writes <I>"C|Net has <a href="http://news.cnet.com/news/0-1004-200-1535528.html">this story</a> about how the Canadian company <a href="http://www.icravetv.com">iCraveTV.com</a> 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. "</I> <P><B>( </B><A href="http://slashdot.org/articles/00/01/29/0010203.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/29/0010203&mode=thread&threshold=0">152</A> of <A href="http://slashdot.org/article.pl?sid=00/01/29/0010203&mode=thread&threshold=-1">170</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Win2k Security holes found</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=microsoft"><IMG src="image11" width="75" height="55" border="0" align="right" hspace="20" vspace="10" alt="Microsoft"></A> <B>Posted by <A href="mailto:heunique@slashdot.org">HeUnique</A> on Friday January 28, @04:58PM</B><BR> <FONT size="2"><B>from the and-it's-not-even-out-yet dept.</B></FONT><BR> According to a story posted by <a href="http://www.zdnn.com">ZDNN</a>, <a href="http://www.zdnet.com/zdnn/stories/news/0,4586,2429334,00.html?chkpt=zdnntop">two security holes</a> 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. <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/1653228.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/1653228&mode=thread&threshold=0">510</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/1653228&mode=thread&threshold=-1">534</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Encryption Debate at Mitnick Trial</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=encryption"><IMG src="image12" width="80" height="70" border="0" align="right" hspace="20" vspace="10" alt="Encryption"></A> <B>Posted by <A href="http://hemos.net">Hemos</A> on Friday January 28, @03:33PM</B><BR> <FONT size="2"><B>from the gimmie-the-data dept.</B></FONT><BR> A number of people have written about <A HREF="http://nytimes.com/library/tech/00/01/cyber/cyberlaw/28law.html">the latest twist</a> 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. <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/1320253.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/1320253&mode=thread&threshold=0">504</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/1320253&mode=thread&threshold=-1">521</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Forum: Future Ports of Games to Linux</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=games"><IMG src="image13" width="80" height="56" border="0" align="right" hspace="20" vspace="10" alt="Games"></A> <B>Posted by <A href="http://CmdrTaco.net">CmdrTaco</A> on Friday January 28, @02:26PM</B><BR> <FONT size="2"><B>from the it's-been-awhile dept.</B></FONT><BR> 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. ;) <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/1257211.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/1257211&mode=thread&threshold=0">648</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/1257211&mode=thread&threshold=-1">652</A> </B>comments <B>)</B> <P></TD><TD width="210" align="center" valign="top"><TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="/index.pl?section=features"><FONT COLOR="#FFFFFF">Features</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><A href="/vote.pl">Voting has begun</A> for the $100k <A href="/index.pl?section=awards">Slashdot Beanie Awards</A>. Talk amongst yourselves and choose who deserves the cash. <P>The latest installment of <A href="http://www.thesync.com/geeks">Geeks in Space</A> is up at <A href="http://www.thesync.com">The Sync</A>. Listen to CmdrTaco, Hemos, and Nate talk about the latest events to happen - or not happen in the computer world. <P>Perhaps you are seeking Jon Katz's series of articles related to recent events in Colorado. These articles include <A href="/article.pl?sid=99/04/25/1438249">Voices from the Hellmouth</A>, <A href="/article.pl?sid=99/04/27/0310247">More Stories from the Hellmouth</A> or <A href="/article.pl?sid=99/04/29/0124247">The Price of Being Different</A>, <P>For something different, try reading a little essay <A href="/article.pl?sid=99/03/31/0137221">Thoughts from the Furnace</A> about the internet, and flame. <p> And for a bit of an amusing take on the Open Source world, check out <a href="/article.pl?sid=99/08/24/1327256&mode=thread">Open Source as an Ant Farm</a> <P><B>Update: 01/03 03:10</B> by <B><A href="http://cowboyneal.org">CowboyNeal</a></B>: <P align="right"><B><A href="/features/">Past Features</A></B> <!-- end="end" features="features" block="block" --></FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="http://slashdot.org/index.pl?section=askslashdot"><FONT COLOR="#FFFFFF">Ask Slashdot</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1946244">Sci Fi Literature 101?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/192226">Linux and Satellite Internet Services</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1843258">Open Defensive Patents?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1825252">Technologies That Shaped the Last Century?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1958212">Disk Repair Tools for Linux?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1955215">Why Can't the Command-Line be More Standardized?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1928235">Packet Radio Networking with PalmOS?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1817211">Cheap Rackmount Enclosures/Systems?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1950249">Open Source Software and Tax Breaks?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1917207">Building an Upgradable Dual Processor System</A> <P> if you have a question for Ask Slashdot, send it to <A href="mailto:askslashdot@slashdot.org">askslashdot@slashdot.org</A></FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="/users.pl"><FONT COLOR="#FFFFFF">Slashdot Login</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><FORM action="/users.pl" METHOD="POST"> <B>Nickname:</B><BR> <INPUT type="text" name="unickname" size="20" value=""><BR> <B>Password:</B><BR> <INPUT type="hidden" name="returnto" value="index.pl"> <INPUT type="password" name="upasswd" size="20"><BR> <INPUT type="submit" name="op" value="userlogin"> </FORM> Don't have an account yet? <A href="/users.pl">Go Create One</A>. A user account will allow you to customize all these <A href="/cheesyportal.shtml">nutty little boxes</A>, tailor the stories you see, as well as remember your comment viewing preferences.</FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Slashdot Poll</B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><FORM action="http://slashdot.org/pollBooth.pl"> <INPUT type="hidden" name="qid" value="techadvance"> <B>The Tech Advance I Most Want Is:</B><BR><INPUT type="radio" name="aid" value="1">Nanotechnology<BR><INPUT type="radio" name="aid" value="2">Cold Fusion<BR><INPUT type="radio" name="aid" value="3">Powerful Fuel Cells<BR><INPUT type="radio" name="aid" value="4">Hard Wiring my Body<BR><INPUT type="radio" name="aid" value="5">Universal Strong Crypto<BR><INPUT type="radio" name="aid" value="6">Interstellar Travel<BR><INPUT type="radio" name="aid" value="7">Cybernetic Body Armor<BR><INPUT type="radio" name="aid" value="8">ColecoVision<BR><INPUT type="submit" value="Vote"> [ <A href="http://slashdot.org/pollBooth.pl?qid=techadvance&aid=-1"><B>Results</B></A> | <A href="http://slashdot.org/pollBooth.pl?"><B>Polls</B></A> ] <BR>Comments:<B>656</B> | Votes:<B>29121</B></FORM> </FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Older Stuff</B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><P><B><A href="http://slashdot.org/index.pl?section=&issue=730512&mode=thread"><FONT size="4">Friday</FONT></A> January 28</B> <LI><A href="http://slashdot.org/articles/00/01/28/1110258.shtml">Abstract Programming and GPL Enforcement</A> (235) <LI><A href="http://slashdot.org/interviews/00/01/28/1225206.shtml">Interview: FreeDOS Leader Jim Hall Answers</A> (86) <LI><A href="http://slashdot.org/articles/00/01/28/116240.shtml">Open Source's Achilles Heel</A> (466) <LI><A href="http://slashdot.org/features/00/01/26/1915230.shtml">The Virtue of Communal Instincts</A> (237) <LI><A href="http://slashdot.org/articles/00/01/28/0723223.shtml">Gartner Group Debunking Open Source Myths</A> (165) <LI><A href="http://slashdot.org/yro/00/01/28/0917229.shtml">DoubleClick Taken to Court</A> (310) <LI><A href="http://slashdot.org/articles/00/01/28/0718209.shtml">Updated Slash & Server 51</A> (81) <LI><A href="http://slashdot.org/articles/00/01/28/089230.shtml">XMMS 1.0.0 Released</A> (128) <LI><A href="http://slashdot.org/askslashdot/00/01/22/192226.shtml">Linux and Satellite Internet Services</A> (138) <LI><A href="http://slashdot.org/articles/00/01/27/1811221.shtml">UN Wants to Combat Online Racism</A> (531) <P><B><A href="http://slashdot.org/index.pl?section=&issue=730511&mode=thread"><FONT size="4">Thursday</FONT></A> January 27</B> <LI><A href="http://slashdot.org/yro/00/01/27/2330205.shtml">Crackdowns, Fools and the MPAA</A> (351) <LI><A href="http://slashdot.org/articles/00/01/27/0832215.shtml">Heroes of Might and Magic III Demo Released</A> (157) <LI><A href="http://slashdot.org/science/00/01/27/1345241.shtml">Sandia Labs Venture Into Nanotechnology</A> (117) <LI><A href="http://slashdot.org/articles/00/01/27/0931237.shtml">CA Announces Program Ports to Linux</A> (195) <LI><A href="http://slashdot.org/interviews/00/01/27/1118251.shtml">Interview: Larry Augustin Finally Answers</A> (210) <LI><A href="http://slashdot.org/awards/00/01/27/0855252.shtml">Final Call for Voting in Slashdot's Beanie Awards</A> (178) <LI><A href="http://slashdot.org/features/00/01/26/197211.shtml">Transmeta Code Morphing != Just In Time</A> (449) <LI><A href="http://slashdot.org/books/00/01/24/1150256.shtml">Intrusion Detection</A> (65) <LI><A href="http://slashdot.org/science/00/01/27/0824239.shtml">Using Enzymes to Help Fight CO2 Build-Up</A> (165) <LI><A href="http://slashdot.org/articles/00/01/27/0712217.shtml">Jon Johansen on ABC World News Tonight</A> (415) <P align="right"><BR><A href="http://slashdot.org/search.pl?section=&min=30"><B>Older Articles</B></A><BR><A href="http://slashdot.org/index.pl?section=&mode=thread&issue=730512"><B>Yesterday's Edition</B></A> </FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="/index.pl?section=books"><FONT COLOR="#FFFFFF">Book Reviews</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><p>Jon Katz, Resident Gasbag, has a new, very appropriate book coming out soon, <a href="http://www.thinkgeek.com">Geeks</a>. Preorder now and receive the book early. <p>For probably the best fiction read around, check out Neal Stephenson's <cite><a href="/article.pl?sid=99/06/23/139229&mode=thread">Cryptonomicon</a></cite>, an engaging read about WWII, cryptography and buried treasure. And data vaults. <p>If you've been doing a lot of work in Perl, you've probably figured out you really need <cite><a href="/article.pl?sid=99/05/10/2238254&mode=thread">Perl in a Nutshell</a></cite> or <cite><a href="/article.pl?sid=99/01/29/1035246&mode=thread">The Perl Cookbook</a></cite>. If you're still learning, grab <cite><a href="/books/older/980526096229.shtml">Programming Perl</a></cite>. <p>And if you want to learn more about how to become a better coder, grab <cite><a href="/article.pl?sid=99/06/28/1417229&mode=thread">The Unified Software Development Process</a></cite> or <cite><a href="/article.pl?sid=99/04/08/1512209&mode=thread">The Practice of Programming</cite></a> Additionally, check out <cite><a href="http://slashdot.org/article.pl?sid=99/09/16/1333202&mode=thread">Refactoring: Improving the Design of Existing Code</a></cite> . <p>Developing a large application? Grab Eric Greenberg's excellent <cite><a href="/article.pl?sid=99/07/13/1943258&mode=thread">Network Application Frameworks</cite></a>. <P>Visit <A href="/index.pl?section=books">Our Book Reviews Section</A> for more. <br> <B>Update: 11/12 05:19</B> by <B><A href="mailto:hemos@slashdot.org">H</A></B>:</FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Quick Links</B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><B>Cool Sites:</B> <LI><A href="http://www.linux.com">Linux.com</A> (What <B>is</B> Linux?) <LI><A href="http://everything.blockstackers.com">Everything</A> (Blow your Mind) <LI><A href="http://www.geekculture.com/geekycomics/Aftery2k/aftery2kmain.html">After Y2k</A> (<I>This</I> is Post-Apocalyptic?) <LI><A href="http://www.userfriendly.org">User Friendly</A> (Laugh) <LI><A href="http://themes.org">Themes.org</A> (Make X Perty) <P><B>Support Slashdot:</B> <LI><A href="http://www.thinkgeek.com">ThinkGeek</A> (Clothe Yourself in Slashdot) <LI><A href="http://cdnow.com/from=sr-302791">CDnow</A> (Support <A href="http://www.cdnow.com/gift/malda@slashdot.org">Rob's Who Habit</A>) <LI><A href="http://adfu.slashdot.org">Slashdot Advertiser Index</A></FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="http://freshmeat.net"><FONT COLOR="#FFFFFF">Freshmeat</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><P><FONT size="4" color="#006666"><B>January</B></FONT><BR> <LI><A href="http://freshmeat.net/news/2000/01/29/949208399.html">We should get this out of the door now</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949159642.html">Is Linux for Crazies?</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949156343.html">SQN Linux 1.6</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949156277.html">Limo 0.3.2</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949156237.html">Fusion GS 1.3</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949145887.html">MMR 1.5.4</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949142835.html">KUPS 0.3.4</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949142815.html">3DSE patch for XMMS 4</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949139763.html">Linux 2.3.41</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949139751.html">Free Code for Linux S/390</A> <FORM METHOD="post" ACTION="http://core.freshmeat.net/search.php3"> <FONT size="3" color="#006666"><B>Search Freshmeat:</B></FONT><BR> <INPUT TYPE="hidden" NAME="link" VALUE="freshmeat.net"> <INPUT TYPE="text" NAME="query"> </FORM> <P align="right"><A href="http://freshmeat.net"><B>More Meat...</B></A></FONT></TD> </TR> </TABLE><P> </FONT></TD>
+ </TR>
+ </TABLE><TABLE cellpadding="0" cellspacing="0" border="0" width="99%" align="center" bgcolor="ffffff">
+ <TR>
+ <TD colspan="4" align="center"><IMG src="image14" alt="" width="80%" height="1" hspace="10" vspace="30"></TD>
+ </TR><TR>
+ <TD align="center"><FONT size="2" face="arial,helvetica">
+ <FORM method="GET" action="http://slashdot.org/search.pl">
+ <INPUT type="name" name="query" value="" width="20" size="20" length="20">
+ <INPUT type="submit" value="Search">
+ </FORM>
+ </FONT>
+ </TD>
+ <TD bgcolor="#ffffff" width="25"> &nbsp; </TD>
+ <TD align="center">
+ <FONT size="2" face="arial,helvetica"><I>Wasn't there something about a PASCAL programmer knowing the value of
+everything and the Wirth of nothing?
+<TD>&nbsp;</TD></I></FONT>
+ </FONT>
+ </TD></TR>
+ <TR><TD colspan="4" align="center">
+ <FONT size="1" color="#006666" face="arial,helvetica">
+
+ All trademarks and copyrights on this
+ page are owned by their respective owners. Comments
+ are owned by the Poster.
+ The Rest © 1997-2000 <A href="http://Andover.Net">Andover.Net</A>.
+</FONT></CENTER>
+ </TD>
+ </TR>
+ </TABLE>
+ <CENTER>
+ <FONT size="2" color="#006666">
+
+ [ <A href="http://slashdot.org/"><Font color="#ffffff">home</FONT></A> |
+ <A href="http://slashdot.org/awards.shtml"><Font color="#ffffff">awards</FONT></A> |
+ <A href="http://slashdot.org/supporters.shtml"><FONT color="#ffffff">supporters</FONT></A> |
+ <A href="http://CmdrTaco.net"><FONT color="#ffffff">rob's homepage</FONT></A> |
+ <A href="http://slashdot.org/submit.pl"><FONT color="#ffffff">contribute story</FONT></A> |
+ <A href="http://slashdot.org/search.pl"><FONT color="#ffffff">older articles</FONT></A> |
+ <A href="http://Andover.Net"><FONT color="#ffffff">Andover.Net</FONT></A> |
+ <A href="http://slashdot.org/advertising.shtml"><FONT color="#ffffff">advertising</FONT></A> |
+ <A href="http://slashdot.org/pollBooth.pl"><FONT color="#ffffff">past polls</FONT></A> |
+ <A href="http://slashdot.org/about.shtml"><FONT color="#ffffff">about</FONT></A> |
+ <A href="http://slashdot.org/faq.shtml"><FONT color="#ffffff">faq</FONT></A> ]
+ </FONT>
+ </CENTER>
+</BODY>
+</HTML>
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image1 b/ext/tk/sample/tkextlib/tkHTML/page2/image1
new file mode 100644
index 0000000000..2ed6ddcfe1
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image1
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image10 b/ext/tk/sample/tkextlib/tkHTML/page2/image10
new file mode 100644
index 0000000000..3021b68990
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image10
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image11 b/ext/tk/sample/tkextlib/tkHTML/page2/image11
new file mode 100644
index 0000000000..41d1fe3666
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image11
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image12 b/ext/tk/sample/tkextlib/tkHTML/page2/image12
new file mode 100644
index 0000000000..655a686541
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image12
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image13 b/ext/tk/sample/tkextlib/tkHTML/page2/image13
new file mode 100644
index 0000000000..97d5950e8c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image13
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image14 b/ext/tk/sample/tkextlib/tkHTML/page2/image14
new file mode 100644
index 0000000000..6d73ad833c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image14
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image15 b/ext/tk/sample/tkextlib/tkHTML/page2/image15
new file mode 100644
index 0000000000..90cc3b2b16
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image15
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image16 b/ext/tk/sample/tkextlib/tkHTML/page2/image16
new file mode 100644
index 0000000000..93aa853cf1
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image16
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image17 b/ext/tk/sample/tkextlib/tkHTML/page2/image17
new file mode 100644
index 0000000000..f46f0308cd
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image17
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image18 b/ext/tk/sample/tkextlib/tkHTML/page2/image18
new file mode 100644
index 0000000000..3badd5e909
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image18
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image19 b/ext/tk/sample/tkextlib/tkHTML/page2/image19
new file mode 100644
index 0000000000..bd4f6d9677
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image19
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image2 b/ext/tk/sample/tkextlib/tkHTML/page2/image2
new file mode 100644
index 0000000000..7566dda25d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image2
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image20 b/ext/tk/sample/tkextlib/tkHTML/page2/image20
new file mode 100644
index 0000000000..358fa95f63
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image20
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image21 b/ext/tk/sample/tkextlib/tkHTML/page2/image21
new file mode 100644
index 0000000000..c81aa52588
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image21
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image22 b/ext/tk/sample/tkextlib/tkHTML/page2/image22
new file mode 100644
index 0000000000..6cbd63022a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image22
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image23 b/ext/tk/sample/tkextlib/tkHTML/page2/image23
new file mode 100644
index 0000000000..e8173a7456
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image23
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image24 b/ext/tk/sample/tkextlib/tkHTML/page2/image24
new file mode 100644
index 0000000000..bffd4b4956
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image24
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image25 b/ext/tk/sample/tkextlib/tkHTML/page2/image25
new file mode 100644
index 0000000000..c656fa4f30
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image25
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image26 b/ext/tk/sample/tkextlib/tkHTML/page2/image26
new file mode 100644
index 0000000000..bc93fdb259
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image26
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image27 b/ext/tk/sample/tkextlib/tkHTML/page2/image27
new file mode 100644
index 0000000000..6ad0eff1e7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image27
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image28 b/ext/tk/sample/tkextlib/tkHTML/page2/image28
new file mode 100644
index 0000000000..88f0d7cea6
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image28
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image29 b/ext/tk/sample/tkextlib/tkHTML/page2/image29
new file mode 100644
index 0000000000..e0704183b3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image29
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image3 b/ext/tk/sample/tkextlib/tkHTML/page2/image3
new file mode 100644
index 0000000000..ac3fa33e6f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image3
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image30 b/ext/tk/sample/tkextlib/tkHTML/page2/image30
new file mode 100644
index 0000000000..4a41950434
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image30
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image31 b/ext/tk/sample/tkextlib/tkHTML/page2/image31
new file mode 100644
index 0000000000..60f13ed564
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image31
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image32 b/ext/tk/sample/tkextlib/tkHTML/page2/image32
new file mode 100644
index 0000000000..04ddc4e8d7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image32
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image33 b/ext/tk/sample/tkextlib/tkHTML/page2/image33
new file mode 100644
index 0000000000..c1ecfff6c4
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image33
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image34 b/ext/tk/sample/tkextlib/tkHTML/page2/image34
new file mode 100644
index 0000000000..3dfd5d76e2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image34
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image35 b/ext/tk/sample/tkextlib/tkHTML/page2/image35
new file mode 100644
index 0000000000..aea44f3017
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image35
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image36 b/ext/tk/sample/tkextlib/tkHTML/page2/image36
new file mode 100644
index 0000000000..baef0e0380
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image36
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image37 b/ext/tk/sample/tkextlib/tkHTML/page2/image37
new file mode 100644
index 0000000000..6c6ba52b45
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image37
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image38 b/ext/tk/sample/tkextlib/tkHTML/page2/image38
new file mode 100644
index 0000000000..e298e04b29
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image38
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image39 b/ext/tk/sample/tkextlib/tkHTML/page2/image39
new file mode 100644
index 0000000000..e16e2f10d5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image39
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image4 b/ext/tk/sample/tkextlib/tkHTML/page2/image4
new file mode 100644
index 0000000000..9e5e46b7e5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image4
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image5 b/ext/tk/sample/tkextlib/tkHTML/page2/image5
new file mode 100644
index 0000000000..646a6d9a51
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image5
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image6 b/ext/tk/sample/tkextlib/tkHTML/page2/image6
new file mode 100644
index 0000000000..7df417c710
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image6
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image7 b/ext/tk/sample/tkextlib/tkHTML/page2/image7
new file mode 100644
index 0000000000..0e6ac10aff
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image7
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image8 b/ext/tk/sample/tkextlib/tkHTML/page2/image8
new file mode 100644
index 0000000000..ba7fb476b9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image8
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image9 b/ext/tk/sample/tkextlib/tkHTML/page2/image9
new file mode 100644
index 0000000000..b1cad73ae9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page2/image9
Binary files differ
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 @@
+<html>
+<head>
+ <title>Tcl Resource Center</title>
+</head>
+
+<body bgcolor="white" text="black">
+
+ <!-- MenuTopLevel Resource Software Extensions -->
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="120" valign="TOP"><a href="/"><img src="image1" width="120" height="79" alt="Scriptics" border="0"></a></td>
+ <td valign="top" width="548">
+
+ <!-- Table to hold tabs -->
+ <table cellpadding="0" cellspacing="0" border="0" width="548">
+ <tr>
+ <td valign="top" align="right" colspan="15" width="548"><a name="TOP"><img src="image2" width="548" height="9" alt="Tcl/Tk" border="0"></a></td>
+ </tr>
+ <tr>
+ <td valign="top" align="right" colspan="15" width="548"><img src="image3" width="482" height="34" alt="Scripting Solutions for eBusiness Integration" border="0"></td>
+ </tr>
+ <tr>
+ <td width="18" valign="TOP"><img src="image4" width="18" height="36" alt="" border="0"></td>
+ <td width="58"><a href="/products/" onMouseOver="msover(4, 'http://images.scriptics.com/images/ProductsMouseOff.gif') ; return true ;" onMouseOut="msover(4, 'http://images.scriptics.com/images/ProductsOff.gif') ; return true ;"><img src="image5" width="58" height="36" alt="Products" border="0"></a></td>
+ <td width="14" valign="TOP"><img src="image6" width="14" height="36" alt="" border="0"></td>
+ <td width="69"><a href="/customers/" onMouseOver="msover(6, 'http://images.scriptics.com/images/CustomersMouseOff.gif') ; return true ;" onMouseOut="msover(6, 'http://images.scriptics.com/images/CustomersOff.gif') ; return true ;"><img src="image7" width="69" height="36" alt="Customers" border="0"></a></td>
+ <td width="14" valign="TOP"><img src="image6" width="14" height="36" alt="" border="0"></td>
+ <td width="60"><a href="/partners/" onMouseOver="msover(8, 'http://images.scriptics.com/images/PartnersMouseOff.gif') ; return true ;" onMouseOut="msover(8, 'http://images.scriptics.com/images/PartnersOff.gif') ; return true ;"><img src="image8" width="60" height="36" alt="Partners" border="0"></a></td>
+ <td width="14" valign="TOP"><img src="image6" width="14" height="36" alt="" border="0"></td>
+ <td width="56"><a href="/services/" onMouseOver="msover(10, 'http://images.scriptics.com/images/ServicesMouseOff.gif') ; return true ;" onMouseOut="msover(10, 'http://images.scriptics.com/images/ServicesOff.gif') ; return true ;"><img src="image9" width="56" height="36" alt="Services" border="0"></a></td>
+ <td width="14" valign="TOP"><img src="image10" width="14" height="36" alt="" border="0"></td>
+ <td width="88"><a href="/resource/" onMouseOver="msover(12, 'http://images.scriptics.com/images/ResourceMouseOn.gif') ; return true ;" onMouseOut="msover(12, 'http://images.scriptics.com/images/ResourceOn.gif') ; return true ;"><img src="image11" width="88" height="36" alt="Tcl Resources" border="0"></a></td>
+ <td width="14" valign="TOP"><img src="image12" width="14" height="36" alt="" border="0"></td>
+ <td width="57"><a href="/company/" onMouseOver="msover(14, 'http://images.scriptics.com/images/CompanyMouseOff.gif') ; return true ;" onMouseOut="msover(14, 'http://images.scriptics.com/images/CompanyOff.gif') ; return true ;"><img src="image13" width="57" height="36" alt="Company" border="0"></a></td>
+ <td width="8" valign="TOP"><img src="image14" width="8" height="36" alt="" border="0"></td>
+ <td width="50" valign="TOP"><img src="image15" width="50" height="36" alt="" border="0"></td>
+ <td width="14" valign="TOP"><img src="image16" width="14" height="36" alt="" border="0"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table> <script language="Javascript">
+ <!--
+ function msover(num, file )
+ {
+ old = (((navigator.appName=='Netscape') &&
+ (parseInt(navigator.appVersion)<=3.0 )))
+ if ( !old ) {
+ document.images[num].src=file
+ }
+ }
+ //-->
+ </SCRIPT>
+
+<!-- MenuSubLevel Resource Software Extensions Tk -->
+
+<table cellpadding="0" cellspacing="0" border="0">
+
+<!-- Left Hand Column-->
+
+<tr><td valign="top" width="120"><table cellpadding="0" cellspacing="0" border="0" width="120">
+ <tr>
+ <td width="120" valign="TOP"><img src="image17" width="120" height="4" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/software/"><img src="image18" width="120" height="11" alt="Software" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/software/tcltk/"><img src="image20" width="120" height="11" alt="Tcl/Tk Core" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/software/applications/"><img src="image21" width="120" height="11" alt="Applications" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image22" width="120" height="4" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/software/extensions/"><img src="image23" width="120" height="11" alt="Extensions" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image24" width="120" height="6" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/software/patches/"><img src="image25" width="120" height="11" alt="Patches" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/software/java/"><img src="image26" width="120" height="11" alt="Tcl &amp; Java" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/software/ports/"><img src="image27" width="120" height="11" alt="Tcl/Tk Ports" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/software/tools/"><img src="image28" width="120" height="11" alt="Tools" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image29" width="120" height="6" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/doc/"><img src="image30" width="120" height="11" alt="Documentation" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/resource/community/"><img src="image32" width="120" height="11" alt="Community" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/live/bydate"><img src="image33" width="120" height="11" alt="What's New" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/forms/urlnote.html"><img src="image34" width="120" height="11" alt="Add URL" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/live/keyword"><img src="image35" width="120" height="11" alt="Keyword Search" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><a href="/live/sitemap"><img src="image36" width="120" height="11" alt="Index" border="0"></a></td>
+ </tr>
+ <tr>
+ <td width="120" valign="TOP"><img src="image37" width="120" height="6" alt="" border="0"></td>
+ </tr>
+</table><!-- End Left Column --></td><!-- Right Hand Column --><td valign="top" width="548" align="left"><table cellpadding="0" cellspacing="0" border="0" width="548">
+ <tr>
+ <td width="295" valign="TOP"><img src="image38" width="295" height="42" alt="Resource" border="0"></td>
+ <td width="187" valign="bottom" align="right"><FORM action="/live/keyword"><img src="image39" width="46" height="24" alt="" border="0"><INPUT TYPE="TEXT" SIZE="10" MAXLENGTH="35" NAME="keywords"><INPUT type="IMAGE" border="0" img="img" src="http://images.scriptics.com/images/Go.gif" value="submit" width="33" height="24"></FORM>
+ </tr>
+ </table>
+ <!-- 2 Columns for spacer -->
+ <table cellpadding="0" cellspacing="0" border="0" width="548">
+ <tr>
+ <!-- Spacer Column -->
+ <td valign="top" width="10">
+ &nbsp;
+ </td>
+
+
+ <td valign="top" width="548"><font face="Geneva, Helvetica, Arial" size="2"><h1>Tcl Resource Center</h1>
+<font size="+1"><a href="/resource/">Top</a>&gt;<a href="/resource/software/" ="">Software Central</a>&gt;<a href="/resource/software/extensions/" ="">Extensions</a>&gt;Tk Widgets</font><font size="-1"><br>Viewed by name (<a href="/resource/software/extensions/tk/?sortby=date">By date</a>)</font><br>
+<p>Tk is a toolkit for building graphical user interfaces with Tcl.
+ Your Tcl/Tk scripts run on UNIX, Windows, and Macintosh.<p>
+<font face="Geneva, Helvetica, Arial"><ul></ul></font><dl>
+<dt><b><a href="http://marge.phys.washington.edu/%7Ezager/blt80-unoff-exe.zip" ="">BLT 8.0 Unofficial zip and DLL</a></b>
+<dd>This is a compiled version of BLT 8.0 "unofficial" for
+the Windows platform. <a href="/live/annotate?url=http%3a%2f%2fmarge%2ephys%2ewashington%2eedu%2f%257Ezager%2fblt80%2dunoff%2dexe%2ezip">Edit</a>
+ <i><font size="-1">(September 24, 1999 06:31)</font></i><dt><b><a href="ftp://ftp.neosoft.com/languages/tcl/sorted/unknown/blt8.0p2-unoff.tgz" ="">BLT 8.0p2 Unofficial tar file</a><a name="bltunoff"></a></b>
+<dd>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 <a href="ftp://ftp.neosoft.com/languages/sorted/devel/blt2.3-8.1.tar.gz">2.3-8.1 version</a> that has been patched to work with 8.1.
+ <a href="ftp://ftp.neosoft.com/languages/tcl/sorted/unknown/blt8.0p2-unoff.README">README file</a>. <a href="/live/annotate?url=ftp%3a%2f%2fftp%2eneosoft%2ecom%2flanguages%2ftcl%2fsorted%2funknown%2fblt8%2e0p2%2dunoff%2etgz">Edit</a>
+ <i><font size="-1">(August 30, 1999 06:38)</font></i><dt><b><a href="http://www.tcltk.com/blt/" ="">BLT Home Page</a></b>
+<dd>
+ Author <b>George Howlett</b>, Version <b>2.3</b>,
+ Works with <b>Tk 4.1 through Tk 8.1</b>
+<br><a href="ftp://ftp.tcltk.com/pub/blt/">Download</a>, <a href="ftp://ftp.tcltk.com/pub/blt/BLT2.3.tar.gz">BLT2.3.tar.gz</a>, <a href="ftp://ftp.tcltk.com/pub/blt/BLT2.4h.tar.gz">BLT2.4h.tar.gz</a>, <a href="ftp://ftp.tcltk.com/pub/blt/BLT2.4i.tar.gz">BLT2.4i.tar.gz</a>, <a href="ftp://ftp.tcltk.com/pub/blt/blt2.4i-for-8.0.exe">blt2.4i-for-8.0.exe</a>, <a href="ftp://ftp.tcltk.com/pub/blt/blt2.4i-for-8.1.exe">blt2.4i-for-8.1.exe</a><br>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 "<a href="#bltunoff">unofficial</a>" release for 8.0p2
+and 8.1a2 that were not done by the author. <a href="/live/annotate?url=http%3a%2f%2fwww%2etcltk%2ecom%2fblt%2f">Edit</a>
+ <i><font size="-1">(October 26, 1999 09:43)</font></i><dt><b><a href="http://www.unifix-online.com/BWidget/index.html" ="">BWidget</a></b>
+<dd>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 ... <a href="/live/annotate?url=http%3a%2f%2fwww%2eunifix%2donline%2ecom%2fBWidget%2findex%2ehtml">Edit</a>
+ <i><font size="-1">(September 06, 1999 09:58)</font></i><dt><b><a href="http://purl.oclc.org/net/nijtmans/dash.html" ="">Dash Patch for Tk</a></b>
+<dd>This patch has many enhancements to the Tk and its canvas
+widget, including dashed lines, smoothed polygons,
+and performance enhancements. <a href="/live/annotate?url=http%3a%2f%2fpurl%2eoclc%2eorg%2fnet%2fnijtmans%2fdash%2ehtml">Edit</a>
+ <i><font size="-1">(November 21, 1999 06:33)</font></i><dt><b><a href="http://www.hwaci.com/sw/et" ="">Embedded Tk (et)</a></b>
+<dd>
+ Author <b><a href="mailto:drh@acm.org" ="">Richard Hipp</a></b>, Version <b>8.0b5</b>,
+ Works with <b>Tk 4.0, 4.1, 4.2, 8.0</b>
+<br>Download: <a href="http://www.hwaci.com/sw/et/et80b5.tar.gz">et80b5.tar.gz</a><br>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. <a href="/live/annotate?url=http%3a%2f%2fwww%2ehwaci%2ecom%2fsw%2fet">Edit</a>
+ <i><font size="-1">(August 19, 1999 15:35)</font></i><dt><b><a href="http://www.purl.org/net/hobbs/tcl/script/tkcon/" ="">Enhanced Tk Console (TkCon)</a></b>
+<dd>
+ Author <b><a href="mailto:jeffrey.hobbs@oen.siemens.de" ="">Jeff Hobbs</a></b>, Version <b>1.3</b>,
+ Works with <b>Tk 4.1 through Tk 8.1</b>
+<br>Download: <a href="http://www.purl.org/net/hobbs/tcl/script/tkcon/tkcon.tar.gz">tkcon.tar.gz</a><br>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. <a href="/live/annotate?url=http%3a%2f%2fwww%2epurl%2eorg%2fnet%2fhobbs%2ftcl%2fscript%2ftkcon%2f">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:06)</font></i><dt><b><a href="http://www.scriptmeridian.org/projects/tk/" ="">Frontier-Tk ScriptMeridian project</a></b>
+<dd>This project seeks to integrate the Tk toolkit
+with the Frontier scripting language. <a href="/live/annotate?url=http%3a%2f%2fwww%2escriptmeridian%2eorg%2fprojects%2ftk%2f">Edit</a>
+ <i><font size="-1">(August 19, 1999 15:36)</font></i><dt><b><a href="http://purl.oclc.org/net/nijtmans/img.html" ="">Img image format extension</a></b>
+<dd>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.
+ <a href="/live/annotate?url=http%3a%2f%2fpurl%2eoclc%2eorg%2fnet%2fnijtmans%2fimg%2ehtml">Edit</a>
+ <i><font size="-1">(November 21, 1999 06:35)</font></i><dt><b><a href="http://purl.oclc.org/net/oakley/tcl/mclistbox/index.html" ="">mclistbox - a multi-column listbox widget</a></b>
+<dd>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. <a href="/live/annotate?url=http%3a%2f%2fpurl%2eoclc%2eorg%2fnet%2foakley%2ftcl%2fmclistbox%2findex%2ehtml">Edit</a>
+ <i><font size="-1">(August 19, 1999 15:37)</font></i><dt><b><a href="http://home.t-online.de/home/dshepherd/tkview.htm" ="">MFC views C++ class for embedding Tk</a></b>
+<dd>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. <a href="/live/annotate?url=http%3a%2f%2fhome%2et%2donline%2ede%2fhome%2fdshepherd%2ftkview%2ehtm">Edit</a>
+ <i><font size="-1">(August 19, 1999 15:38)</font></i><dt><b><a href="http://www.cs.umd.edu/hcil/pad++" ="">Pad++</a></b>
+<dd>
+ Author <b><a href="mailto:pad-info@cs.umd.edu" ="">Ben Bederson et al</a></b>, Version <b>0.9p1</b>,
+ Works with <b>8.0</b>
+<br>Download: <a href="http://www.cs.umd.edu/hcil/pad++/download.html">download.html</a><br>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. <a href="/live/annotate?url=http%3a%2f%2fwww%2ecs%2eumd%2eedu%2fhcil%2fpad%2b%2b">Edit</a>
+ <i><font size="-1">(August 19, 1999 15:39)</font></i><dt><b><a href="http://home.t-online.de/home/sesam.com/freeware.htm" ="">Progressbar</a></b>
+<dd>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. <a href="/live/annotate?url=http%3a%2f%2fhome%2et%2donline%2ede%2fhome%2fsesam%2ecom%2ffreeware%2ehtm">Edit</a>
+ <i><font size="-1">(January 24, 2000 09:19)</font></i><dt><b><a href="http://jfontain.free.fr/" ="">scwoop (Simple Composite Widget Object Oriented Package)</a></b>
+<dd>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. <a href="/live/annotate?url=http%3a%2f%2fjfontain%2efree%2efr%2f">Edit</a>
+ <i><font size="-1">(January 09, 2000 02:10)</font></i><dt><b><a href="http://www2.clearlight.com/~oakley/tcl/supertext.html" ="">Supertext - tk text widget with unlimited undo</a></b>
+<dd>
+ Author <b><a href="mailto:oakley@channelpoint.com" ="">Bryan Oakley</a></b>, Version <b>1.0b1</b>,
+ Works with <b>Tcl 8.0</b>
+<br>Download: <a href="http://www2.clearlight.com/~oakley/tcl/supertext.tcl">supertext.tcl</a><br>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. <a href="/live/annotate?url=http%3a%2f%2fwww2%2eclearlight%2ecom%2f%7eoakley%2ftcl%2fsupertext%2ehtml">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:06)</font></i><dt><b><a href="http://www.hwaci.com/sw/tk/nbpi.html" ="">Tabbed Notebook Widget</a></b>
+<dd>
+ Author <b><a href="mailto:drh@acm.org" ="">Richard Hipp</a></b>, Version <b>1.0</b>,
+ Works with <b>Tk 4.1 or later.</b>
+<br>Download: <a href="http://www.hwaci.com/sw/tk/notebook.tcl">notebook.tcl</a><br>This implements a tabbed notebook using
+a canvas widget and embedded frames.
+This is pure Tcl
+code - not a C extension. <a href="/live/annotate?url=http%3a%2f%2fwww%2ehwaci%2ecom%2fsw%2ftk%2fnbpi%2ehtml">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:08)</font></i><dt><b><a href="http://www.tcltk.com/ellson/ftp/Gdtclft2.0.README" ="">Tcl GD - graphics</a></b>
+<dd>
+ Author <b>John Ellson and Spencer Thomas</b>, Version <b>2.0</b>,
+ Works with <b>8.0 and higher</b>
+<br>Download: <a href="http://www.tcltk.com/ellson/ftp/Gdtclft2.0.tar.gz">Gdtclft2.0.tar.gz</a><br>
+ 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. <a href="/live/annotate?url=http%3a%2f%2fwww%2etcltk%2ecom%2fellson%2fftp%2fGdtclft2%2e0%2eREADME">Edit</a>
+ <i><font size="-1">(August 19, 1999 14:52)</font></i><dt><b><a href="http://www.stratasys.com/software/metagui" ="">The Meta-GUI Tools</a></b>
+<dd>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. <a href="/live/annotate?url=http%3a%2f%2fwww%2estratasys%2ecom%2fsoftware%2fmetagui">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:10)</font></i><dt><b><a href="http://jfontain.free.fr/" ="">Tkpiechart Home Page</a></b>
+<dd>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. <a href="/live/annotate?url=http%3a%2f%2fjfontain%2efree%2efr%2f">Edit</a>
+ <i><font size="-1">(January 09, 2000 02:12)</font></i><dt><b><a href="http://www.cygnus.com/~irox/tkprint/" ="">TkPrint</a></b>
+<dd>TkPrint is an extension that allows you to print from a
+ Tk widget. <a href="/live/annotate?url=http%3a%2f%2fwww%2ecygnus%2ecom%2f%7eirox%2ftkprint%2f">Edit</a>
+ <i><font size="-1">(October 11, 1999 09:58)</font></i><dt><b><a href="http://www.purl.org/net/hobbs/tcl/capp/" ="">TkTable Home Page</a></b>
+<dd>The TkTable widget. The <code>table</code> command creates a
+2-dimensional grid of cells. The table can use a Tcl array variable or Tcl
+
+command for data storage and retrieval. <a href="/live/annotate?url=http%3a%2f%2fwww%2epurl%2eorg%2fnet%2fhobbs%2ftcl%2fcapp%2f">Edit</a>
+ <i><font size="-1">(November 18, 1999 09:25)</font></i><dt><b><a href="http://ftp.austintx.net/users/jatucker/TkTextmatrix/default.htm" ="">TkTextMatrix (spreadsheet)</a></b>
+<dd>
+ Author <b><a href="mailto:jatucker@austin.dsccc.com" ="">John Arthur Tucker</a></b>, Version <b>4.1</b>,
+ Works with <b>Tk 4.1</b>
+<br>Download: <a href="http://ftp.austintx.net/users/jatucker/TkTextmatrix/download.htm">download.htm</a>, <a href="http://ftp.austintx.net/users/jatucker/TkTextmatrix/textmatrix4.1.tar.gz">textmatrix4.1.tar.gz</a><br>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. <a href="/live/annotate?url=http%3a%2f%2fftp%2eaustintx%2enet%2fusers%2fjatucker%2fTkTextmatrix%2fdefault%2ehtm">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:14)</font></i><dt><b><a href="http://www.cs.umd.edu/~bederson/Togl.html" ="">ToGL - a Tk Open GL widget</a></b>
+<dd>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:
+<ul>
+<li> color-index mode support including color allocation functions
+<li> support for requesting stencil, accumulation, alpha buffers, etc
+<li> multiple OpenGL drawing widgets
+<li> OpenGL extension testing from Tcl
+<li> simple, portable font support
+<li> overlay plane support
+</ul>
+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. <a href="/live/annotate?url=http%3a%2f%2fwww%2ecs%2eumd%2eedu%2f%7ebederson%2fTogl%2ehtml">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:14)</font></i><dt><b><a href="http://www.hwaci.com/sw/tk/treepi.html" ="">Tree Widget</a></b>
+<dd>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. <a href="/live/annotate?url=http%3a%2f%2fwww%2ehwaci%2ecom%2fsw%2ftk%2ftreepi%2ehtml">Edit</a>
+ <i><font size="-1">(September 29, 1999 14:37)</font></i><dt><b><a href="http://www.du.edu/~mschwart/tcl-tk.htm" ="">Windows Extensions for Tcl/Tk (Michael Schwartz)</a></b>
+<dd>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. <a href="/live/annotate?url=http%3a%2f%2fwww%2edu%2eedu%2f%7emschwart%2ftcl%2dtk%2ehtm">Edit</a>
+ <i><font size="-1">(October 07, 1999 10:50)</font></i><dt><b><a href="http://www.tcltk.com/iwidgets/" ="">[incr Widgets] Home Page</a></b>
+<dd>[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
+<a href="http://www.tcltk.com/itcl/">[incr Tcl]</a> distributions. <a href="/live/annotate?url=http%3a%2f%2fwww%2etcltk%2ecom%2fiwidgets%2f">Edit</a>
+ <i><font size="-1">(September 05, 1999 16:08)</font></i><dt><b><a href="http://www1.clearlight.com/~oakley/tcl/combobox/index.html" ="">combobox</a></b>
+<dd>
+ Author <b><a href="mailto:oakley@channelpoint.com" ="">Bryan Oakley</a></b>, Version <b>1.03</b>,
+ Works with <b>8.x</b>
+<br>Download: <a href="http://www1.clearlight.com/~oakley/tcl/combobox/combobox.tcl">combobox.tcl</a><br>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. <a href="/live/annotate?url=http%3a%2f%2fwww1%2eclearlight%2ecom%2f%7eoakley%2ftcl%2fcombobox%2findex%2ehtml">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:15)</font></i><dt><b><a href="http://www.multimania.com/droche/rnotebook/index.html" ="">Rnotebook</a></b>
+<dd>
+ Author <b><a href="mailto:dan@lectra.com" ="">Daniel Roche</a></b>, Version <b>1.0</b>,
+ Works with <b>8.0 or higher</b>
+<br>Download: <a href="http://www.multimania.com/droche/rnotebook/index.html">index.html</a><br>This implements a resizeable notebook
+widget in pure tcl/tk <a href="/live/annotate?url=http%3a%2f%2fwww%2emultimania%2ecom%2fdroche%2frnotebook%2findex%2ehtml">Edit</a>
+ <i><font size="-1">(August 19, 1999 15:39)</font></i><dt><b><a href="http://www.tregar.com/samdi.html" ="">saMDI v1.0a1 Multi-Document Interface Extension</a></b>
+<dd>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. <a href="/live/annotate?url=http%3a%2f%2fwww%2etregar%2ecom%2fsamdi%2ehtml">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:07)</font></i><dt><b><a href="http://tix.mne.com/htdocs/tix/index.html" ="">Tix Support Site</a></b>
+<dd>
+ Author <b><a href="mailto:tix@mne.com" ="">Ioi Lam, (adopted by Gregg Squires)</a></b>, Version <b>4.1</b>,
+ Works with <b>Tcl 7.4 through Tcl 8.0</b>
+<br><a href="ftp://ftp.tix.mne.com/pub/tix/">Download</a>, <a href="ftp://ftp.tix.mne.com/pub/tix/Tix4.1.0.006.tar.gz">Tix4.1.0.006.tar.gz</a>, <a href="ftp://ftp.tix.mne.com/pub/tix/Tix41p6.zip">Tix41p6.zip</a>, <a href="ftp://ftp.tix.mne.com/pub/tix/win41p6bin.zip">win41p6bin.zip</a><br><b>Tix has found a new home!</b>
+ <br>
+ Tix provides over 40 new Tk including the
+combo box, file selection dialogs, paned widget,
+notebook, hierarchical list, directory tree, and more.
+ <a href="/live/annotate?url=http%3a%2f%2ftix%2emne%2ecom%2fhtdocs%2ftix%2findex%2ehtml">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:11)</font></i><dt><b><a href="ftp://ftp.archive.eso.org/pub/tree" ="">Tk Tree Widget (C++)</a></b>
+<dd>Tk Tree widget for Tcl8.0.3.
+
+This version contains (optional) support for \[incr Tcl\] and \[incr Tk\]
+version 3.0.
+<br>
+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.
+ <a href="/live/annotate?url=ftp%3a%2f%2fftp%2earchive%2eeso%2eorg%2fpub%2ftree">Edit</a>
+ <i><font size="-1">(August 25, 1999 03:14)</font></i><dt><b><a href="http://www.purl.org/net/hobbs/tcl/script/widget/" ="">widget, simple megawidget package</a></b>
+<dd>
+ Author <b><a href="mailto:jeffrey.hobbs@oen.siemens.de" ="">Jeffrey Hobbs</a></b>, Version <b>0.9</b>,
+ Works with <b>Tcl/Tk 8.0 or higher</b>
+<br>Download: <a href="http://www.purl.org/net/hobbs/tcl/script/widget/widget-0.9.tar.gz">widget-0.9.tar.gz</a><br>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. <a href="/live/annotate?url=http%3a%2f%2fwww%2epurl%2eorg%2fnet%2fhobbs%2ftcl%2fscript%2fwidget%2f">Edit</a>
+ <i><font size="-1">(August 23, 1999 12:16)</font></i></dl>
+<hr><p><center><font size="-1" face="Geneva, Helvetica, Arial"><br><a href="#TOP"><b>Top</b></a><br><!-- key ResourceSoftwareExtensions --><a href="/">Home</a>
+ | <a href="/products/">Products</a>
+ | <a href="/customers/">Customers</a>
+ | <a href="/partners/">Partners</a>
+ | <a href="/services/">Services</a>
+ | <a href="/resource/">Tcl Resources</a>
+ | <a href="/company/">Company</a>
+<br><a href="/live/keyword">Search</a>
+ | <a href="/live/map">Site Map</a>
+ | <a href="/company/feedback.html?url=%2fresource%2fsoftware%2fextensions%2ftk%2f">Feedback</a>
+ | <a href="/company/contact.html">Contact Us</a>
+ | <a href="mailto:info@scriptics.com">info@scriptics.com</a>
+
+ <SCRIPT LANGUAGE="Javascript">
+<!--
+ browser = (((navigator.appName == "Netscape") &&(parseInt(navigator.appVersion) >= 3 )) || ((navigator.appName =="Microsoft Internet Explorer") && (parseInt(navigator.appVersion) >= 4 )))
+
+ if ( browser )
+ {
+ over = new MakeImageArray(10)
+ over[0].src = "http://images.scriptics.com/images/ProductsMouseOff.gif"
+ over[1].src = "http://images.scriptics.com/images/CustomersMouseOff.gif"
+ over[2].src = "http://images.scriptics.com/images/PartnersMouseOff.gif"
+ over[3].src = "http://images.scriptics.com/images/ServicesMouseOff.gif"
+ over[4].src = "http://images.scriptics.com/images/ResourceMouseOff.gif"
+ over[5].src = "http://images.scriptics.com/images/CompanyMouseOff.gif"
+ over[6].src = "http://images.scriptics.com/images/homeMainRollover1.gif"
+ over[7].src = "http://images.scriptics.com/images/homeMainRollover2.gif"
+ over[8].src = "http://images.scriptics.com/images/homeMainRollover3.gif"
+ over[9].src = "http://images.scriptics.com/images/homeMainRollover3.gif"
+
+ }
+
+ function MakeImageArray(n) {
+ this.length = n
+ for (var i = 0; i<=n; i++)="i++)" {="{" this[i]="this[i]" ="" new="new" Image()="Image()" }="}" return="return" this="this" }="}" //="//" --="--">
+ </SCRIPT><br>
+ <font size="2">
+ &copy; 1998-2000 Scriptics Corporation. All rights reserved.
+ <a href="/legal_notice.html">Legal Notice</a> | <A href="" /privacy.html="/privacy.html">
+ Privacy Statement</a>
+ </td></tr></table></td></tr></table>
+</Body>
+</Html> \ 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 0000000000..814d1e8f08
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image1
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image10 b/ext/tk/sample/tkextlib/tkHTML/page3/image10
new file mode 100644
index 0000000000..45001faf05
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image10
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image11 b/ext/tk/sample/tkextlib/tkHTML/page3/image11
new file mode 100644
index 0000000000..7c4c170f21
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image11
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image12 b/ext/tk/sample/tkextlib/tkHTML/page3/image12
new file mode 100644
index 0000000000..903e7344a6
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image12
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image13 b/ext/tk/sample/tkextlib/tkHTML/page3/image13
new file mode 100644
index 0000000000..226d4f68c2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image13
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image14 b/ext/tk/sample/tkextlib/tkHTML/page3/image14
new file mode 100644
index 0000000000..8e8c71814c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image14
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image2 b/ext/tk/sample/tkextlib/tkHTML/page3/image2
new file mode 100644
index 0000000000..2ddeb3258c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image2
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image3 b/ext/tk/sample/tkextlib/tkHTML/page3/image3
new file mode 100644
index 0000000000..1651ba7e41
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image3
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image4 b/ext/tk/sample/tkextlib/tkHTML/page3/image4
new file mode 100644
index 0000000000..b565c8dd0e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image4
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image5 b/ext/tk/sample/tkextlib/tkHTML/page3/image5
new file mode 100644
index 0000000000..e1268b81c0
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image5
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image6 b/ext/tk/sample/tkextlib/tkHTML/page3/image6
new file mode 100644
index 0000000000..1a6b260b40
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image6
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image7 b/ext/tk/sample/tkextlib/tkHTML/page3/image7
new file mode 100644
index 0000000000..cec7aa04d8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image7
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image8 b/ext/tk/sample/tkextlib/tkHTML/page3/image8
new file mode 100644
index 0000000000..ad0d748d65
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image8
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image9 b/ext/tk/sample/tkextlib/tkHTML/page3/image9
new file mode 100644
index 0000000000..46ade3018b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/image9
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/index.html b/ext/tk/sample/tkextlib/tkHTML/page3/index.html
new file mode 100644
index 0000000000..ce92e8a22e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page3/index.html
@@ -0,0 +1,2787 @@
+<html><body bgcolor="white">
+<hr>
+<h1 align="center">Embedding Tcl in C/C++ Applications</h1>
+
+ <table width="100%">
+ <tr><td valign="top" align="left" width="46%">
+ <b>Presented At:</b>
+ <blockquote>
+ The&nbsp;Tcl2K&nbsp;Conference<br>
+ Austin, Texas<br>
+ <nobr>9:00am, February 15, 2000</nobr><br>
+ </blockquote>
+ </td>
+ <td width="5%">&nbsp;</td>
+ <td valign="top" align="left" width="46%">
+ <b>Instructor:</b>
+ <blockquote>
+ D. Richard Hipp<br>
+ drh@hwaci.com<br>
+ http://www.hwaci.com/drh/<br>
+ 704.948.4565
+ </blockquote>
+ </td></tr>
+ </table><p>
+ <center><table border="2">
+ <tr><td>
+ <p align="center">
+ Copies of these notes, example source code,<br>and other
+ resources related to this tutorial<br>are available online at
+ <a href="http://www.hwaci.com/tcl2k/">
+ http://www.hwaci.com/tcl2k/</a></p>
+ <p align="center"><small>$Id$</small></p></td></tr>
+ </table>
+ </center>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Tutorial Outline</h2>
+<p><ul><li>Introduction</li>
+<li>Building It Yourself</li>
+<ul><li>"Hello, World!" using Tcl</li>
+<li>Tcl scripts as C strings</li>
+<li>Adding new Tcl commands</li>
+<li>A tour of the Tcl API</li>
+<li>Tcl initialization scripts</li>
+<li>Adding Tk</li>
+</ul><li>Tools Survey</li>
+<li>Mktclapp</li>
+<ul><li>"Hello World" using mktclapp</li>
+<li>Adding C code</li>
+<li>Other Features</li>
+<li>Invoking Tcl from C</li>
+<li>Running mktclapp directly</li>
+<li>Real-world examples</li>
+</ul><li>Summary</li>
+</ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Embedding Tcl in C/C++ Applications</h2>
+<p><ul><li>You know how to program in Tcl/Tk</li></ul><ul><li>You know how to program in C/C++</li></ul><ul><li>This tutorial is about how to do both at the same time.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Why Mix C With Tcl/Tk?</h2>
+<p><ul><li>Use C for the things C is good at and Tcl for the things
+ Tcl is good at.</li></ul><ul><li>Generate standalone executables.
+ <ul><li>Eliminate the need to install Tcl/Tk.</li>
+ <li>Prevent problems when the wrong version of Tcl/Tk is installed.</li>
+ </ul></li></ul><ul><li>Prevent end users from changing the source code.
+ <ul><li>Keeps users from creating new bugs.</li>
+ <li>Protects proprietary code.</li>
+ </ul></li></ul><ul><li>Office politics</li></ul><ul><li>Use Tcl/Tk as a portability layer for a large C program</li></ul><ul><li>Use Tcl as a testing interface</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Why Mix C With Tcl/Tk?</h2>
+<p><blockquote><big><b>
+ "Use C for the things C is good at and use Tcl/Tk for the things
+ Tcl/Tk is good at."
+ </b></blockquote></p><p>
+
+ <table width="100%">
+ <tr><td valign="top" align="left" width="46%">
+ <b>C is good at:</b>
+ <ul>
+ <li>Speed</li>
+ <li>Complex data structures</li>
+ <li>Computation</li>
+ <li>Interacting with hardware</li>
+ <li>Byte-by-byte data analysis</li>
+ </ul>
+ </td>
+ <td width="5%">&nbsp;</td>
+ <td valign="top" align="left" width="46%">
+ <b>Tcl/Tk is good at:</b>
+ <ul>
+ <li>Building a user interface</li>
+ <li>Manipulation of strings</li>
+ <li>Portability</li>
+ <li>Opening sockets</li>
+ <li>Handling events</li>
+ </ul>
+ </td></tr>
+ </table>
+<br clear="both"><p><hr></p>
+<h2 align="center">Programming Models</h2>
+<table width="100%">
+<tr><td valign="top" width="49%">
+
+ <p><b>Mainstream Tcl Programming Model:</b></p>
+</td>
+<td width="2%">&nbsp;</td>
+<td valign="top" width="49%">
+
+ <p><b>Embedded Tcl Programming Model:&nbsp;&nbsp;</b></p>
+</td></tr>
+<tr><td valign="top" width="49%">
+
+ <ul><li>Add bits of C code to a large Tcl program</li></ul>
+</td>
+<td width="2%">&nbsp;</td>
+<td valign="top" width="49%">
+
+ <ul><li>Add bits of Tcl code to a large C program</li></ul>
+</td></tr>
+<tr><td valign="top" width="49%">
+
+ <ul><li>Main Tcl script loads extensions written in C</li></ul>
+</td>
+<td width="2%">&nbsp;</td>
+<td valign="top" width="49%">
+
+ <ul><li>Main C procedure invokes the Tcl interpreter</li></ul>
+</td></tr>
+<tr><td valign="top" width="49%">
+
+ <ul><li>Tcl/Tk is a programming language</li></ul>
+</td>
+<td width="2%">&nbsp;</td>
+<td valign="top" width="49%">
+
+ <ul><li>Tcl/Tk is a C library</li></ul>
+</td></tr>
+<tr><td valign="top" width="49%">
+
+ <center><img src="image1"><br>
+ Most of the Tcl2K conference is about</center>
+</td>
+<td width="2%">&nbsp;</td>
+<td valign="top" width="49%">
+
+ <center><img src="image1"><br>
+ This tutorial is about</center>
+</td></tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">"Hello, World!" Using The Tcl Library</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h></tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Always include &lt;tcl.h></td>
+</tr>
+<tr><td valign="center">
+<small><tt>int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Create a new Tcl interpreter</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;"puts&nbsp;{Hello,&nbsp;World!}");</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Execute a Tcl command.</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Compiling "Hello, World!"</h2>
+<p><p><b>Unix:</b></p>
+ <blockquote><tt>
+ $ gcc hello.c -ltcl -lm -ldl<br>
+ $ ./a.out<br>
+ Hello, World!</tt></blockquote>
+
+ <p><b>Windows using Cygwin:</b></p>
+ <blockquote><tt>
+ C:> gcc hello.c -ltcl80 -lm<br>
+ C:> a.exe<br>
+ Hello, World!</tt></blockquote>
+
+ <p><b>Windows using Mingw32:</b></p>
+ <blockquote><tt>
+ C:> gcc -mno-cygwin hello.c -ltcl82 -lm<br>
+ </tt></blockquote>
+<table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>Also works with VC++</b></td></tr></table></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Where Does <tt>-ltcl</tt> Come From On Unix?</h2>
+<p><p>Build it yourself using these steps:</p></p><p>
+<p><ul><li>Get tcl8.2.2.tar.gz from Scriptics</li></ul><ul><li><tt>zcat tcl8.2.2.tar.gz | tar vx </tt></li></ul><ul><li><tt>cd tcl8.2.2/unix</tt></li></ul><ul><li><tt>./configure --disable-shared</tt></li></ul><ul><li><tt>make</tt></li></ul><ul><li>Move <b>libtcl8.2.a</b> to your lib directory.</li></ul><ul><li>Copy <b>../generic/tcl.h</b> into /usr/include.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">What Other Libraries Are Required For Unix?</h2>
+<p><ul><li>The sequence of <b>-l</b> options after <b>-ltcl</b>
+ varies from system to system</li></ul><ul><li>Observe what libraries the TCL makefile inserts when
+ it is building <b>tclsh</b></li></ul><ul><li>Examples in this talk are for RedHat Linux 6.0 for Intel</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">How To Compile Under Unix Without Installing Tcl</h2>
+<p><p>Specify the *.a file directly:</p>
+ <blockquote><pre>
+ $ gcc -I../tcl8.2.2/generic hello.c \
+ ../tcl8.2.2/unix/libtcl8.2.a -lm -ldl
+ $ strip a.out
+ $ ./a.out
+ Hello, World!</pre></blockquote>
+
+ <p>Or, tell the C compiler where to look for *.a files:</p>
+ <blockquote><pre>
+ $ gcc -I../tcl8.2.2/generic hello.c \
+ -L../tcl8.2.2/unix -ltcl -lm -ldl
+ $ strip a.out
+ $ ./a.out
+ Hello, World!</pre></blockquote>
+<table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>The <tt>-I../tcl8.2.2</tt> argument
+ tells the compiler where to
+ find <tt>&lt;tcl.h&gt;</tt>.</p></b></td></tr></table></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">What's "Cygwin"?</h2>
+<p><ul><li>An implementation of GCC/G++ and all development tools
+ for Windows95/98/NT/2000</li></ul><ul><li>Available for free download at
+ <blockquote>
+ <tt>http://sourceware.cygnus.com/cygwin/</tt>
+ </blockquote></li></ul><ul><li>Also available shrink-wrapped at your local software retailer or
+ online at
+ <blockquote>
+ <tt>http://www.cygnus.com/cygwin/index.html</tt>
+ </blockquote></li></ul><ul><li>Programs compiled using Cygwin require a special
+ DLL (<b>cygwin1.dll</b>) that provides a POSIX system API</li></ul><ul><li>Cygwin1.dll cannot be shipped with proprietary programs
+ without purchasing a license from Cygnus.</li></ul><ul><li>Mingw32 is the same compiler as Cygwin, but generates
+ binaries that do not use cygwin1.dll</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Where Does <tt>-ltcl82</tt> Come From On Windows?</h2>
+<p><p>Build it like this:</p></p><p>
+<p><ul><li>Get <b>tcl82.lib</b> and <b>tcl82.dll</b> from Scriptics.</li></ul><ul><li><tt>echo EXPORTS >tcl82.def</tt></li></ul><ul><li><tt>nm tcl82.lib | grep 'T _' | sed 's/.* T _//' >>tcl82.def</tt></li></ul><ul><li><tt>dlltool --def tcl82.def --dllname tcl82.dll --output-lib libtcl82.a</tt></li></ul><ul><li>Move <b>libtcl82.a</b> to the lib directory and <b>tcl82.dll</b>
+ to the bin directory.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Where Does Your Code Go?</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*&nbsp;Your&nbsp;application&nbsp;code&nbsp;goes&nbsp;here&nbsp;*/</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Insert C code here to do whatever it is your program is
+ suppose to do</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Building A Simple TCLSH</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;char&nbsp;*z;<br>
+&nbsp;&nbsp;char&nbsp;zLine[2000];<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;while(&nbsp;fgets(zLine,sizeof(zLine),stdin)&nbsp;){</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Get one line of input</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zLine);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Execute the input as Tcl.</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;z&nbsp;=&nbsp;Tcl_GetStringResult(interp);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;z[0]&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("¸üÿ¿PX¶\n",&nbsp;z);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Print result if not empty</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>What if user types more than 2000 characters?</b></td></tr></table>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Building A Simple TCLSH</h2>
+<p>Use TCL to handle input. Allows input lines of unlimited length.</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+/*&nbsp;Tcl&nbsp;code&nbsp;to&nbsp;implement&nbsp;the<br>
+**&nbsp;input&nbsp;loop&nbsp;*/<br>
+static&nbsp;char&nbsp;zLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;"while&nbsp;{![eof&nbsp;stdin]}&nbsp;{\n"</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;"&nbsp;&nbsp;set&nbsp;line&nbsp;[gets&nbsp;stdin]\n"</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Get one line of input</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;"&nbsp;&nbsp;set&nbsp;result&nbsp;[eval&nbsp;$line]\n"</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Execute input as Tcl</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;"&nbsp;&nbsp;if&nbsp;{$result!=\"\"}&nbsp;{puts&nbsp;$result}\n"</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Print result</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;"}\n"<br>
+;<br>
+&nbsp;<br>
+<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zLoop);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Run the Tcl input loop</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>But what about commands that span multiple lines of input?</b></td></tr></table>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Better Handling Of Command-Line Input</h2>
+<p>The file "input.tcl"</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>set&nbsp;line&nbsp;{}<br>
+while&nbsp;{![eof&nbsp;stdin]}&nbsp;{</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if&nbsp;{$line!=""}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;">&nbsp;"<br>
+&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;"%&nbsp;"<br>
+&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;flush&nbsp;stdout</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Prompt for user input. The prompt is normally &quot;%&quot;
+ but changes to &quot;&gt;&quot; if the current line is a continuation.</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;append&nbsp;line&nbsp;[gets&nbsp;stdin]<br>
+&nbsp;&nbsp;if&nbsp;{[info&nbsp;complete&nbsp;$line]}&nbsp;{</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;{[catch&nbsp;{uplevel&nbsp;#0&nbsp;$line}&nbsp;result]}&nbsp;{</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">If the command is complete, execute it.</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;stderr&nbsp;"Error:&nbsp;$result"<br>
+&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;elseif&nbsp;{$result!=""}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;$result<br>
+&nbsp;&nbsp;&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;line&nbsp;{}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;append&nbsp;line&nbsp;\n<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">If the command is incomplete, append a newline and get
+ another line of text.</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Better Handling Of Command-Line Input</h2>
+<p>The file "input.c"</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;"source&nbsp;input.tcl");</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Read and execute the input loop</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>But now the program is not standalone!</b></td></tr></table>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Converting Scripts Into C Strings</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;"set&nbsp;line&nbsp;{}\n"<br>
+&nbsp;&nbsp;"while&nbsp;{![eof&nbsp;stdin]}&nbsp;{\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;if&nbsp;{$line!=\"\"}&nbsp;{\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;\">&nbsp;\"\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;}&nbsp;else&nbsp;{\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;\"%&nbsp;\"\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;}\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;flush&nbsp;stdout\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;append&nbsp;line&nbsp;[gets&nbsp;stdin]\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;if&nbsp;{[info&nbsp;complete&nbsp;$line]}&nbsp;{\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;{[catch&nbsp;{uplevel&nbsp;#0&nbsp;$line}&nbsp;result]}&nbsp;{\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;stderr&nbsp;\"Error:&nbsp;$result\"\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;elseif&nbsp;{$result!=\"\"}&nbsp;{\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;$result\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;}\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;line&nbsp;{}\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;}&nbsp;else&nbsp;{\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;append&nbsp;line&nbsp;\\n\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;}\n"<br>
+&nbsp;&nbsp;"}\n"<br>
+;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Compile Tcl Scripts Into C Programs</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;/*&nbsp;Actual&nbsp;code&nbsp;omitted&nbsp;*/<br>
+;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Copy and paste the converted Tcl script here</td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Execute the Tcl code</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Converting Scripts To Strings<br>Using SED Or TCLSH</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>sed&nbsp;-e&nbsp;'s/\\/\\\\/g'&nbsp;\&nbsp;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Convert <b>\</b> into <b>\\</b></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;-e&nbsp;'s/"/\\"/g'&nbsp;\&nbsp;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Convert <b>"</b> into <b>\"</b></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;-e&nbsp;'s/^/&nbsp;&nbsp;"/'&nbsp;\&nbsp;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Add <b>"</b> to start of each line</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;-e&nbsp;'s/$/\\n"/'&nbsp;input.tcl</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Add <b>\n"</b> to end of each line</td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+&nbsp;<br>
+<br>
+&nbsp;<br>
+<br>
+while&nbsp;{![eof&nbsp;stdin]}&nbsp;{<br>
+&nbsp;&nbsp;set&nbsp;line&nbsp;[gets&nbsp;stdin]</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;regsub&nbsp;-all&nbsp;{\}&nbsp;$line&nbsp;{&amp;&amp;}&nbsp;line</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Convert <b>\</b> into <b>\\</b></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;regsub&nbsp;-all&nbsp;{"}&nbsp;$line&nbsp;{\"}&nbsp;line</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Convert <b>"</b> into <b>\"</b></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;puts&nbsp;"\"$line\\n\""</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Add <b>"</b> in front and <b>\n"</b> at the end</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Converting Scripts Into C Strings</h2>
+<p>You may want to save space by removing comments and extra whitespace
+ from scripts.</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;"set&nbsp;line&nbsp;{}\n"<br>
+&nbsp;&nbsp;"while&nbsp;{![eof&nbsp;stdin]}&nbsp;{\n"<br>
+&nbsp;&nbsp;"if&nbsp;{$line!=\"\"}&nbsp;{\n"<br>
+&nbsp;&nbsp;"puts&nbsp;-nonewline&nbsp;\">&nbsp;\"\n"<br>
+&nbsp;&nbsp;"}&nbsp;else&nbsp;{\n"<br>
+&nbsp;&nbsp;"puts&nbsp;-nonewline&nbsp;\"%&nbsp;\"\n"<br>
+&nbsp;&nbsp;"}\n"<br>
+&nbsp;&nbsp;"flush&nbsp;stdout\n"<br>
+&nbsp;&nbsp;"append&nbsp;line&nbsp;[gets&nbsp;stdin]\n"<br>
+&nbsp;&nbsp;"if&nbsp;{[info&nbsp;complete&nbsp;$line]}&nbsp;{\n"<br>
+&nbsp;&nbsp;"if&nbsp;{[catch&nbsp;{uplevel&nbsp;#0&nbsp;$line}&nbsp;result]}&nbsp;{\n"<br>
+&nbsp;&nbsp;"puts&nbsp;stderr&nbsp;\"Error:&nbsp;$result\"\n"<br>
+&nbsp;&nbsp;"}&nbsp;elseif&nbsp;{$result!=\"\"}&nbsp;{\n"<br>
+&nbsp;&nbsp;"puts&nbsp;$result\n"<br>
+&nbsp;&nbsp;"}\n"<br>
+&nbsp;&nbsp;"set&nbsp;line&nbsp;{}\n"<br>
+&nbsp;&nbsp;"}&nbsp;else&nbsp;{\n"<br>
+&nbsp;&nbsp;"append&nbsp;line&nbsp;\\n\n"<br>
+&nbsp;&nbsp;"}\n"<br>
+&nbsp;&nbsp;"}\n"<br>
+;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Converting Scripts To Strings</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>sed&nbsp;-e&nbsp;'s/\\/\\\\/g'&nbsp;\&nbsp;<br>
+&nbsp;&nbsp;-e&nbsp;'s/"/\\"/g'&nbsp;\&nbsp;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;-e&nbsp;'/^&nbsp;*#/d'&nbsp;\&nbsp;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Delete lines that begin with #</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;-e&nbsp;'/^&nbsp;*$/d'&nbsp;\&nbsp;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Delete blank lines</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;-e&nbsp;'s/^&nbsp;*/&nbsp;&nbsp;"/'&nbsp;\&nbsp;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Delete leading spaces</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;-e&nbsp;'s/$/\\n"/'&nbsp;input.tcl<br>
+&nbsp;<br>
+<br>
+&nbsp;<br>
+<br>
+&nbsp;<br>
+while&nbsp;{![eof&nbsp;stdin]}&nbsp;{<br>
+&nbsp;&nbsp;set&nbsp;line&nbsp;[gets&nbsp;stdin]</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;set&nbsp;line&nbsp;[string&nbsp;trimleft&nbsp;$line]</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Remove leading space</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if&nbsp;{$line==""}&nbsp;continue</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Delete blank lines</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if&nbsp;{[string&nbsp;index&nbsp;$line&nbsp;0]=="#"}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;continue<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Delete lines starting with #</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;regsub&nbsp;-all&nbsp;{\}&nbsp;$line&nbsp;{&amp;&amp;}&nbsp;line<br>
+&nbsp;&nbsp;regsub&nbsp;-all&nbsp;{"}&nbsp;$line&nbsp;{\"}&nbsp;line<br>
+&nbsp;&nbsp;puts&nbsp;"\"$line\\n\""<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Removing Comments Or Leading Space<br>Will Break Some Tcl Scripts!</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>image&nbsp;create&nbsp;bitmap&nbsp;smiley&nbsp;-data&nbsp;{</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>#define&nbsp;smile_width&nbsp;15<br>
+#define&nbsp;smile_height&nbsp;15</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">These lines begin with # but are not comment</td>
+</tr>
+<tr><td valign="center">
+<small><tt>static&nbsp;unsigned&nbsp;char&nbsp;smile_bits[]&nbsp;=&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;0xc0,&nbsp;0x01,&nbsp;0x30,&nbsp;0x06,&nbsp;0x0c,&nbsp;0x18,<br>
+&nbsp;&nbsp;&nbsp;0x04,&nbsp;0x10,&nbsp;0x22,&nbsp;0x22,&nbsp;0x52,&nbsp;0x25,<br>
+&nbsp;&nbsp;&nbsp;0x01,&nbsp;0x40,&nbsp;0x01,&nbsp;0x40,&nbsp;0x01,&nbsp;0x40,<br>
+&nbsp;&nbsp;&nbsp;0x12,&nbsp;0x24,&nbsp;0xe2,&nbsp;0x23,&nbsp;0x04,&nbsp;0x10,<br>
+&nbsp;&nbsp;&nbsp;0x0c,&nbsp;0x18,&nbsp;0x30,&nbsp;0x06,&nbsp;0xc0,&nbsp;0x01};<br>
+}<br>
+&nbsp;<br>
+<br>
+&nbsp;<br>
+text&nbsp;.t<br>
+pack&nbsp;.t<br>
+.t&nbsp;insert&nbsp;end&nbsp;[string&nbsp;trim&nbsp;{</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>She&nbsp;walks&nbsp;in&nbsp;beauty,&nbsp;like&nbsp;the&nbsp;night<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Of&nbsp;cloudless&nbsp;climes&nbsp;and&nbsp;starry&nbsp;skies;<br>
+And&nbsp;all&nbsp;that's&nbsp;best&nbsp;of&nbsp;dark&nbsp;and&nbsp;bright<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Meet&nbsp;in&nbsp;her&nbsp;aspect&nbsp;and&nbsp;her&nbsp;eyes;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Indentation is deleted on lines 2
+ and 4</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}]&nbsp;<br>
+&nbsp;<br>
+</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>Problems like these are rare</b></td></tr></table>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Adding A "continue" Command</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>set&nbsp;line&nbsp;{}<br>
+while&nbsp;{![eof&nbsp;stdin]}&nbsp;{<br>
+&nbsp;&nbsp;if&nbsp;{$line!=""}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;">&nbsp;"<br>
+&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;"%&nbsp;"<br>
+&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;flush&nbsp;stdout<br>
+&nbsp;&nbsp;append&nbsp;line&nbsp;[gets&nbsp;stdin]<br>
+&nbsp;&nbsp;if&nbsp;{[info&nbsp;complete&nbsp;$line]}&nbsp;{</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;{[lindex&nbsp;$line&nbsp;0]=="continue"}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Break out of the loop if the command
+ is "continue"</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;elseif&nbsp;{[catch&nbsp;{uplevel&nbsp;#0&nbsp;$line}&nbsp;result]}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;stderr&nbsp;"Error:&nbsp;$result"<br>
+&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;elseif&nbsp;{$result!=""}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;$result<br>
+&nbsp;&nbsp;&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;line&nbsp;{}<br>
+&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;append&nbsp;line&nbsp;\n<br>
+&nbsp;&nbsp;}<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Stop For Tcl Input At Various Points<br>In A C Program</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;Input&nbsp;loop&nbsp;as&nbsp;a&nbsp;C&nbsp;string&nbsp;*/<br>
+;<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*&nbsp;Application&nbsp;C&nbsp;code&nbsp;*/</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Do some computation</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Stop for some Tcl input</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*&nbsp;More&nbsp;application&nbsp;C&nbsp;code&nbsp;*/</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Do more computation</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Stop for more Tcl input</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*&nbsp;Finish&nbsp;up&nbsp;the&nbsp;application&nbsp;*/</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Finish the computation</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Using Tcl For Testing</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;Input&nbsp;loop&nbsp;as&nbsp;a&nbsp;C&nbsp;string&nbsp;*/<br>
+;<br>
+&nbsp;<br>
+</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+#ifdef&nbsp;TESTING<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Create interpreter only if TESTING
+ is defined</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();<br>
+#endif<br>
+&nbsp;&nbsp;/*&nbsp;Application&nbsp;C&nbsp;code&nbsp;*/</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>#ifdef&nbsp;TESTING<br>
+&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
+#endif</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Accept command-line input only if TESTING
+ is defined</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*&nbsp;More&nbsp;application&nbsp;C&nbsp;code&nbsp;*/<br>
+#ifdef&nbsp;TESTING<br>
+&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
+#endif<br>
+&nbsp;&nbsp;/*&nbsp;Finish&nbsp;up&nbsp;the&nbsp;application&nbsp;*/<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Creating A New Tcl Command In C</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+int&nbsp;NewCmd(</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;void&nbsp;*clientData,<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp,<br>
+&nbsp;&nbsp;int&nbsp;argc,<br>
+&nbsp;&nbsp;char&nbsp;**argv</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">The Tcl command is implemented as
+ a C function with four arguments.</td>
+</tr>
+<tr><td valign="center">
+<small><tt>){<br>
+&nbsp;&nbsp;printf("Hello,&nbsp;World!\n");</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Returns TCL_OK or TCL_ERROR</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}<br>
+&nbsp;<br>
+static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;code&nbsp;omitted...&nbsp;*/<br>
+;<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_CreateCommand(interp,&nbsp;"helloworld",<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NewCmd,&nbsp;0,&nbsp;0);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Tell the interpreter which C function to call when the
+ "helloworld" Tcl command is executed</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Linkage From Tcl To C</h2>
+<p><p align="center"><img src="image4"></p></p><p><ul><li>3rd parameter of Tcl_CreateCommand() is a pointer to the C subroutine
+ that implements the command.</li></ul><ul><li>4th parameter to Tcl_CreateCommand() becomes the 1st parameter to
+ the C routine whenever the Tcl command is executed.</li></ul><ul><li>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.</li></ul></p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Linkage From Tcl To C</h2>
+<p><p align="center"><img src="image5"></p></p><p><ul><li>5th parameter of Tcl_CreateCommand() is a pointer to the C subroutine
+ that is called when the Tcl command is deleted.</li></ul><ul><li>4th parameter to Tcl_CreateCommand() becomes the 1st parameter to
+ the C routine.</li></ul></p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">When To Use A Delete Proc</h2>
+<p>Examples of where the delete proc is used in standard Tcl/Tk:</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>button&nbsp;.b&nbsp;-text&nbsp;Hello<br>
+pack&nbsp;.b</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>rename&nbsp;.b&nbsp;{}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Deleting the <b>.b</b> command causes the button to be destroyed</td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+&nbsp;<br>
+</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>image&nbsp;create&nbsp;photo&nbsp;smiley&nbsp;\&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;-file&nbsp;smiley.gif</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>rename&nbsp;smiley&nbsp;{}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Deleting the <b>smiley</b> command destroys the image and reclaims the
+ memory used to hold the image</td>
+</tr>
+</table>
+<p><ul><li>Always use a delete proc if the clientData is a pointer to
+ malloced memory or some other resource that needs freeing</li></ul><ul><li>Delete procs are never used in the Tcl core but are used
+ extensively in Tk</li></ul></p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Linkage From Tcl To C</h2>
+<p>The <tt>argc</tt> and <tt>argv</tt> parameters work just like in
+ <tt>main()</tt></p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>helloworld&nbsp;one&nbsp;{two&nbsp;three}&nbsp;four</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><tt>argc = 4<br>
+ argv[0] = "helloworld"<br>
+ argv[1] = "one"<br>
+ argv[2] = "two three"<br>
+ argv[3] = "four"<br>
+ argv[4] = NULL</tt></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">A Short-Cut</h2>
+<p>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.</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#define&nbsp;TCLARGS&nbsp;\&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;*clientData,&nbsp;\&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;Tcl_Interp&nbsp;*interp,&nbsp;\&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;argc,&nbsp;\&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*argv</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Define TCLARGS once in a header file</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;<br>
+&nbsp;<br>
+&nbsp;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>int&nbsp;NewCmd(TCLARGS){</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Use the TCLARGS macro to define new C functions
+ that implement Tcl commands.</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;&nbsp;/*&nbsp;implementation...&nbsp;*/<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>For brevity, we will use the TCLARGS macro during the
+ rest of this talk.</b></td></tr></table>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Returning A Value From C Back To Tcl</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>int&nbsp;NewCmd(TCLARGS){</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Note that the C function returns an "int"</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Return value is TCL_OK or TCL_ERROR</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><ul><li>TCL_OK and TCL_ERROR are defined in &lt;tcl.h&gt;</li></ul><ul><li>Other valid return values TCL_RETURN, TCL_BREAK and TCL_CONTINUE
+ are rarely used</li></ul><ul><li>Common mistake: forgetting to return TCL_OK</li></ul></p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Returning A Value From C Back To Tcl</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>int&nbsp;NewCmd(TCLARGS){</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_SetResult(interp,"Hello!",TCL_STATIC);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Set the result to "Hello!"</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><ul><li>Result should be the text of an error message if you
+ return TCL_ERROR.</li></ul><ul><li>3rd argument to Tcl_SetResult() can be TCL_STATIC,
+ TCL_DYNAMIC, TCL_VOLATILE, or a function pointer.</li></ul><ul><li>Also consider using Tcl_AppendResult().</li></ul><ul><li>Direct access to <tt>interp->result</tt> is deprecated.</li></ul><ul><li>See the man pages for details.</li></ul></p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">The Tcl_Obj Interface</h2>
+<p><ul><li>A new way to write Tcl commands in C code</li></ul><ul><li>First introduced in Tcl8.0</li></ul><ul><li>Can be much faster, especially for lists or numeric values.</li></ul><ul><li>Able to handle arbitrary binary data.</li></ul><ul><li>More difficult to program.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">The Tcl_Obj Interface</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>int&nbsp;NewObjCmd(<br>
+&nbsp;&nbsp;void&nbsp;*clientData,<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp,<br>
+&nbsp;&nbsp;int&nbsp;objc,</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Obj&nbsp;*const*&nbsp;objv</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">4th parameter is an array Tcl_Objs, not an array of strings</td>
+</tr>
+<tr><td valign="center">
+<small><tt>){<br>
+&nbsp;&nbsp;/*&nbsp;Implementation...&nbsp;*/<br>
+&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
+}<br>
+&nbsp;<br>
+static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;code&nbsp;omitted...&nbsp;*/<br>
+;<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_CreateObjCommand(interp,&nbsp;"newcmd",<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NewObjCmd,&nbsp;0,&nbsp;0);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Use a different function to register the command</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">The Tcl_Obj Interface</h2>
+<p><ul><li>There are countless access methods for reading information from and
+ placing information in Tcl_Objs. Always use the access methods.</li></ul><ul><li>Details provided at Lee Bernhard's talk this afternoon.</li></ul><ul><li>Definitely use Tcl_Objs if you are writing a new Tcl extension.</li></ul><ul><li>Tcl_Objs address some of the weaknesses of Tcl relative to C/C++.
+ <ul>
+ <li> Tcl_Objs are faster </li>
+ <li> Tcl_Objs work with binary data </li>
+ </ul>
+ But C/C++ is faster still and better for working with binary data.</li></ul><ul><li>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.</li></ul><ul><li>This talk will focus on the string interface.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Nickel Tour Of The Tcl API</h2>
+<p><p><b>Memory allocation functions</b></p>
+<center><table width="90%"><tr>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Alloc<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Free<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Realloc<br>
+</tt></small></td>
+</table></center><p><b>Functions useful in the implementation of new Tcl commands</b></p>
+<center><table width="90%"><tr>
+<td width="32%" valign="top"><small><tt>
+ Tcl_AppendElement<br>
+ Tcl_AppendResult<br>
+ Tcl_GetBoolean<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_GetDouble<br>
+ Tcl_GetInt<br>
+ Tcl_GetStringResult<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_ResetResult<br>
+ Tcl_SetResult<br>
+</tt></small></td>
+</table></center><p><b>Functions for controlling the Tcl interpreter</b></p>
+<center><table width="90%"><tr>
+<td width="32%" valign="top"><small><tt>
+ Tcl_CreateCommand<br>
+ Tcl_CreateInterp<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_CreateObjCommand<br>
+ Tcl_DeleteCommand<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_DeleteInterp<br>
+ Tcl_Exit<br>
+</tt></small></td>
+</table></center></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Nickel Tour Of The Tcl API</h2>
+<p><p><b>I/O functions</b></p>
+<center><table width="90%"><tr>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Close<br>
+ Tcl_Eof<br>
+ Tcl_Flush<br>
+ Tcl_GetChannel<br>
+ Tcl_GetChannelMode<br>
+ Tcl_GetChannelName<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Gets<br>
+ Tcl_OpenCommandChannel<br>
+ Tcl_OpenFileChannel<br>
+ Tcl_OpenTcpClient<br>
+ Tcl_OpenTcpServer<br>
+ Tcl_Read<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Seek<br>
+ Tcl_Tell<br>
+ Tcl_Ungets<br>
+ Tcl_Write<br>
+ Tcl_WriteChars<br>
+</tt></small></td>
+</table></center><p><b>Names and meanings of system error codes</b></p>
+<center><table width="90%"><tr>
+<td width="32%" valign="top"><small><tt>
+ Tcl_ErrnoId<br>
+ Tcl_ErrnoMsg<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_GetErrno<br>
+ Tcl_SetErrno<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_SignalId<br>
+ Tcl_SignalMsg<br>
+</tt></small></td>
+</table></center></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Nickel Tour Of The Tcl API</h2>
+<p><p><b>General Operating System Calls</b></p>
+<center><table width="90%"><tr>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Access<br>
+ Tcl_Chdir<br>
+ Tcl_GetCwd<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_GetHostName<br>
+ Tcl_GetNameOfExecutable<br>
+ Tcl_Sleep<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Stat<br>
+</tt></small></td>
+</table></center><p><b>String Manipulation And Comparison</b></p>
+<center><table width="90%"><tr>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Concat<br>
+ Tcl_Merge<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_SplitList<br>
+ Tcl_StringCaseMatch<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_StringMatch<br>
+</tt></small></td>
+</table></center><p><b>Dynamically Resizable Strings</b></p>
+<center><table width="90%"><tr>
+<td width="49%" valign="top"><small><tt>
+ Tcl_DStringAppend<br>
+ Tcl_DStringAppendElement<br>
+ Tcl_DStringEndSublist<br>
+ Tcl_DStringInit<br>
+ Tcl_DStringLength<br>
+</tt></small></td>
+<td width="49%" valign="top"><small><tt>
+ Tcl_DStringResult<br>
+ Tcl_DStringSetLength<br>
+ Tcl_DStringStartSublist<br>
+ Tcl_DStringValue<br>
+</tt></small></td>
+</table></center></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Nickel Tour Of The Tcl API</h2>
+<p><p><b>Event Handlers</b></p>
+<center><table width="90%"><tr>
+<td width="49%" valign="top"><small><tt>
+ Tcl_CancelIdleCall<br>
+ Tcl_CreateChannelHandler<br>
+ Tcl_CreateTimerHandler<br>
+ Tcl_DeleteChannelHandler<br>
+</tt></small></td>
+<td width="49%" valign="top"><small><tt>
+ Tcl_DeleteTimerHandler<br>
+ Tcl_DoOneEvent<br>
+ Tcl_DoWhenIdle<br>
+</tt></small></td>
+</table></center><p><b>Functions For Reading And Writing Tcl Variables</b></p>
+<center><table width="90%"><tr>
+<td width="32%" valign="top"><small><tt>
+ Tcl_GetVar<br>
+ Tcl_GetVar2<br>
+ Tcl_LinkVar<br>
+ Tcl_SetVar<br>
+ Tcl_SetVar2<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_TraceVar<br>
+ Tcl_TraceVar2<br>
+ Tcl_UnlinkVar<br>
+ Tcl_UnsetVar<br>
+ Tcl_UnsetVar2<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_UntraceVar<br>
+ Tcl_UntraceVar2<br>
+ Tcl_UpdateLinkedVar<br>
+</tt></small></td>
+</table></center><p><b>Functions For Executing Tcl Code</b></p>
+<center><table width="90%"><tr>
+<td width="32%" valign="top"><small><tt>
+ Tcl_Eval<br>
+ Tcl_EvalFile<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_EvalObj<br>
+ Tcl_GlobalEval<br>
+</tt></small></td>
+<td width="32%" valign="top"><small><tt>
+ Tcl_GlobalEvalObj<br>
+ Tcl_VarEval<br>
+</tt></small></td>
+</table></center></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Nickel Tour Of The Tcl API</h2>
+<p><p><b>Functions For Dealing With Unicode</b></p>
+<center><table width="90%"><tr>
+<td width="49%" valign="top"><small><tt>
+ Tcl_NumUtfChars<br>
+ Tcl_UniCharAtIndex<br>
+ Tcl_UniCharIsAlnum<br>
+ Tcl_UniCharIsAlpha<br>
+ Tcl_UniCharIsControl<br>
+ Tcl_UniCharIsDigit<br>
+ Tcl_UniCharIsGraph<br>
+ Tcl_UniCharIsLower<br>
+ Tcl_UniCharIsPrint<br>
+ Tcl_UniCharIsPunct<br>
+ Tcl_UniCharIsSpace<br>
+ Tcl_UniCharIsUpper<br>
+ Tcl_UniCharIsWordChar<br>
+ Tcl_UniCharLen<br>
+ Tcl_UniCharNcmp<br>
+ Tcl_UniCharToLower<br>
+ Tcl_UniCharToTitle<br>
+</tt></small></td>
+<td width="49%" valign="top"><small><tt>
+ Tcl_UniCharToUpper<br>
+ Tcl_UniCharToUtf<br>
+ Tcl_UniCharToUtfDString<br>
+ Tcl_UtfAtIndex<br>
+ Tcl_UtfBackslash<br>
+ Tcl_UtfCharComplete<br>
+ Tcl_UtfFindFirst<br>
+ Tcl_UtfFindLast<br>
+ Tcl_UtfNcasecmp<br>
+ Tcl_UtfNcmp<br>
+ Tcl_UtfNext<br>
+ Tcl_UtfPrev<br>
+ Tcl_UtfToLower<br>
+ Tcl_UtfToTitle<br>
+ Tcl_UtfToUniChar<br>
+ Tcl_UtfToUniCharDString<br>
+ Tcl_UtfToUpper<br>
+</tt></small></td>
+</table></center>
+ <p><b>Functions For Dealing With Tcl_Objs</b></p>
+ <blockquote><i>Too numerous to list...</i></blockquote></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Documentation Of The Tcl API</h2>
+<p><ul><li>Tcl comes with excellent man pages</li></ul><ul><li>"Use the source, Luke"</li></ul><ul><li>See <tt>tclDecl.h</tt> for a list of API functions</li></ul><ul><li>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.</li></ul><ul><li>Most API functions are used within Tcl and Tk. Use grep to locate
+ examples.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Initialization Scripts</h2>
+<p><ul><li>Run the mini TCLSH implemented above and execute the <tt>parray</tt> command</li></ul><ul><li>It doesn't work! What's wrong? </p></li></li></ul><ul><li><tt>parray</tt> is really a Tcl proc that is read in when the
+ interpreter is initialized. </p></li></li></ul><ul><li><tt>parray</tt> (and several other commands) are stored in a
+ handful of &quot;Initialization Scripts&quot; </p></li></li></ul><ul><li>All the initialization scripts are stored in the
+ &quot;Tcl Library&quot; - a directory on the host
+ computer. </p></li></li></ul><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>Invoke the Tcl_Init() function to locate and read the
+ Tcl initialization scripts.</b></td></tr></table></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">The <tt>Tcl_Init()</tt> Function</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;code&nbsp;omitted...&nbsp;*/<br>
+;<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Init(interp);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Locate and read the initialization scripts</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*&nbsp;Call&nbsp;Tcl_CreateCommand()?&nbsp;*/<br>
+&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>But Tcl_Init() can fail. We need to check its return value...</b></td></tr></table>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">The <tt>Tcl_Init()</tt> Function</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
+&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;code&nbsp;omitted...&nbsp;*/<br>
+;<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;Tcl_Init(interp)!=TCL_OK&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Tcl_Init()&nbsp;failed:&nbsp;¸üÿ¿PX¶",<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tcl_GetStringResult(interp));<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Print error message if Tcl_Init() fails</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*&nbsp;Call&nbsp;Tcl_CreateCommand()?&nbsp;*/<br>
+&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>But now the program is not standalone.</b></td></tr></table>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">How <tt>Tcl_Init()</tt> Works</h2>
+<p><ul><li>Computes the value of variable <tt>tcl_libPath</tt>.</li></ul><ul><li>Invokes the procedure named &quot;<tt>tclInit</tt>&quot;</li></ul><ul><li>A default <tt>tclInit</tt> procedure is built into Tcl.
+ You can define an alternative <tt>tclInit</tt> procedure
+ prior to calling <tt>Tcl_Init()</tt>.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">The Default <tt>initTcl</tt> Procedure</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>set&nbsp;errors&nbsp;{}<br>
+set&nbsp;dirs&nbsp;{}<br>
+if&nbsp;{[info&nbsp;exists&nbsp;tcl_library]}&nbsp;{<br>
+&nbsp;&nbsp;lappend&nbsp;dirs&nbsp;$tcl_library<br>
+}&nbsp;else&nbsp;{<br>
+&nbsp;&nbsp;if&nbsp;{[info&nbsp;exists&nbsp;env(TCL_LIBRARY)]}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;lappend&nbsp;dirs&nbsp;$env(TCL_LIBRARY)<br>
+&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;lappend&nbsp;dirs&nbsp;$tclDefaultLibrary<br>
+&nbsp;&nbsp;unset&nbsp;tclDefaultLibrary<br>
+&nbsp;&nbsp;set&nbsp;dirs&nbsp;[concat&nbsp;$dirs&nbsp;$tcl_libPath]<br>
+}<br>
+foreach&nbsp;i&nbsp;$dirs&nbsp;{<br>
+&nbsp;&nbsp;set&nbsp;tcl_library&nbsp;$i<br>
+&nbsp;&nbsp;set&nbsp;tclfile&nbsp;[file&nbsp;join&nbsp;$i&nbsp;init.tcl]<br>
+&nbsp;&nbsp;if&nbsp;{[file&nbsp;exists&nbsp;$tclfile]}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;{![catch&nbsp;{uplevel&nbsp;#0&nbsp;[list&nbsp;source&nbsp;$tclfile]}&nbsp;msg]}&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br>
+&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;append&nbsp;errors&nbsp;"$tclfile:&nbsp;$msg\n$errorInfo\n"<br>
+&nbsp;&nbsp;&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;}<br>
+}<br>
+error&nbsp;"Can't&nbsp;find&nbsp;a&nbsp;usable&nbsp;init.tcl&nbsp;..."</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">The Default Initialization Sequence</h2>
+<p><ul><li>The <tt>tclInit</tt> procedure locates and sources the <tt>init.tcl</tt>
+ script. The directory that contains <tt>init.tcl</tt> is stored in
+ the <tt>tcl_library</tt> variable.</li></ul><ul><li>The <tt>init.tcl</tt> script creates an <tt>unknown</tt> procedure.
+ The <tt>unknown</tt> procedure will run whenever Tcl encounters an
+ unknown command.</li></ul><ul><li>The <tt>unknown</tt> procedure consults the file <tt>tclIndex</tt> in the
+ <tt>tcl_library</tt> directory to see if the command is defined by one of
+ the initialization scripts.</li></ul><ul><li>The <tt>unknown</tt> procedure sources any needed initialization scripts
+ and retries the command.</li></ul><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>Commands defined in the initialization scripts are loaded
+ on demand.</b></td></tr></table></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Standalone Initialization Techniques</h2>
+<p><p><b>Manually execute all initialization scripts</b></p>
+<ul><li>Convert all initialization scripts into C strings and
+ put them in the executable.</li></ul><ul><li>Call <tt>Tcl_Eval()</tt> on each initialization script and omit the
+ call to <tt>Tcl_Init()</tt></li></ul><ul><li>Or, redefine <tt>tclInit</tt> so that it does not attempt to source
+ <tt>init.tcl</tt> then call <tt>Tcl_Eval()</tt> on each initialization
+ script after <tt>Tcl_Init()</tt> returns.</li></ul><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>This approach is not recommended</b></td></tr></table></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Standalone Initialization Techniques</h2>
+<p><p><b>Redefining the builtin <tt>source</tt> command</b></p>
+<ul><li>Convert all initialization scripts into C strings and
+ put them in the executable.</li></ul><ul><li>Create a new <tt>source</tt> command that
+ calls <tt>Tcl_Eval()</tt> on the appropriate built-in string
+ instead of reading from the disk.</li></ul><ul><li>Read from disk if the named file is not one that is built in.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Redefining <tt>source</tt></h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>static&nbsp;char&nbsp;zInitTcl[]&nbsp;=&nbsp;"...";<br>
+static&nbsp;char&nbsp;zParrayTcl[]&nbsp;=&nbsp;"...";</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Scripts <tt>init.tcl</tt> and <tt>parray.tcl</tt></td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+int&nbsp;NewSourceCmd(TCLARGS){</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;!strcmp(argv[1],"/builtin/init.tcl")&nbsp;)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Tcl_Eval(interp,&nbsp;zInitTcl);<br>
+&nbsp;&nbsp;if(&nbsp;!strcmp(argv[1],"/builtin/parray.tcl")&nbsp;)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Tcl_Eval(interp,&nbsp;zParrayTcl);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Call <tt>Tcl_Eval()</tt> on builtin strings if the names match</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;Tcl_EvalFile(interp,&nbsp;argv[1]);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Call <tt>Tcl_EvalFile()</tt> if no match</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;setenv("TCL_LIBRARY","/builtin");</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Causes <tt>tclInit</tt> to look for <tt>init.tcl</tt> in <tt>/builtin</tt></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_CreateCommand(interp,&nbsp;"source",<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NewSourceCmd,&nbsp;0,&nbsp;0);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Redefine <tt>source</tt></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Init(interp);<br>
+&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Redefining <tt>source</tt></h2>
+<p><ul><li>This approach works for all versions of Tcl and Tk.</li></ul><ul><li>Also need to redefine the "<tt>file exists</tt>" Tcl command since it
+ too is used by <tt>tclInit</tt>.</li></ul><ul><li>To verify that the program is really standalone, remove the call
+ to <tt>Tcl_EvalFile()</tt>.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Standalone Initialization Techniques</h2>
+<p><p><b>Use the <tt>Tcl</tt>*<tt>InsertProc()</tt> functions</b></p>
+<ul><li>Three routines that overload basic file I/O operations:
+ <ul>
+ <li> <tt>TclStatInsertProc()</tt> </li>
+ <li> <tt>TclAccessInsertProc()</tt> </li>
+ <li> <tt>TclOpenFileChannelInsertProc()</tt> </li>
+ </ul></li></ul><ul><li>Allows us to implement a virtual filesystem that overlays the
+ real filesystem.</li></ul><ul><li>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.</li></ul><ul><li>These functions first appeared in Tcl8.0.3.
+ Presumably to support TclPro Wrapper.</li></ul><ul><li>The only documentation is comments on the code.
+ See the Tcl source file <tt>generic/tclIOUtil.c</tt></li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">The <tt>TclStatInsertProc()</tt> Function</h2>
+<p><ul><li>Sole argument is a pointer to a function whose interface is the
+ same as <tt>stat()</tt></li></ul><ul><li>Functions are stacked. Tcl tries each <tt>stat</tt> function on the
+ list, beginning with the most recently inserted, until one succeeds.</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">The <tt>TclStatInsertProc()</tt> Function</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tclInt.h></tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Rather than <tt>&lt;tcl.h&gt;</tt>!</td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+static&nbsp;int<br>
+BltinFileStat(char&nbsp;*path,struct&nbsp;stat&nbsp;*buf){<br>
+&nbsp;&nbsp;char&nbsp;*zData;<br>
+&nbsp;&nbsp;int&nbsp;nData;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;zData&nbsp;=&nbsp;FindBuiltinFile(path,&nbsp;0,&nbsp;&amp;nData);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Check if <tt>path</tt> is a builtin</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;zData==0&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;-1;<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Fail if <tt>path</tt> is not a builtin</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;memset(buf,&nbsp;0,&nbsp;sizeof(*buf));<br>
+&nbsp;&nbsp;buf->st_mode&nbsp;=&nbsp;0400;<br>
+&nbsp;&nbsp;buf->st_size&nbsp;=&nbsp;nData;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;0;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Success if it is builtin</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;TclStatInsertProc(BltinFileStat);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Register new <tt>stat</tt> function</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();<br>
+&nbsp;&nbsp;Tcl_Init(interp);<br>
+&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">The <tt>TclAccessInsertProc()</tt> Function</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tclInt.h></tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Rather than <tt>&lt;tcl.h&gt;</tt>!</td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+/*&nbsp;BltinFileStat()&nbsp;not&nbsp;shown...&nbsp;*/<br>
+&nbsp;<br>
+static&nbsp;int<br>
+BltinFileAccess(char&nbsp;*path,&nbsp;int&nbsp;mode){<br>
+&nbsp;&nbsp;char&nbsp;*zData;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;mode&nbsp;&amp;&nbsp;3&nbsp;)&nbsp;return&nbsp;-1;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">All builtins are read-only</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;zData&nbsp;=&nbsp;FindBuiltinFile(path,&nbsp;0,&nbsp;&amp;nData);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Check if <tt>path</tt> is a builtin</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;zData==0&nbsp;)&nbsp;return&nbsp;-1;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Fail if <tt>path</tt> is not a builtin</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;0;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Success if it is builtin</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;TclStatInsertProc(BltinFileStat);<br>
+&nbsp;&nbsp;TclAccessInsertProc(BltinFileAccess);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Register new <tt>stat</tt> and <tt>access</tt> functions</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();<br>
+&nbsp;&nbsp;Tcl_Init(interp);<br>
+&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">The <tt>TclOpenFileChannelInsertProc()</tt> Function</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>static&nbsp;Tcl_Channel&nbsp;BuiltinFileOpen(<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp,&nbsp;&nbsp;&nbsp;/*&nbsp;The&nbsp;TCL&nbsp;interpreter&nbsp;doing&nbsp;the&nbsp;open&nbsp;*/<br>
+&nbsp;&nbsp;char&nbsp;*zFilename,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Name&nbsp;of&nbsp;the&nbsp;file&nbsp;to&nbsp;open&nbsp;*/<br>
+&nbsp;&nbsp;char&nbsp;*modeString,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Mode&nbsp;string&nbsp;for&nbsp;the&nbsp;open&nbsp;(ignored)&nbsp;*/<br>
+&nbsp;&nbsp;int&nbsp;permissions&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Permissions&nbsp;for&nbsp;a&nbsp;newly&nbsp;created&nbsp;file&nbsp;(ignored)&nbsp;*/<br>
+){<br>
+&nbsp;&nbsp;char&nbsp;*zData;<br>
+&nbsp;&nbsp;BuiltinFileStruct&nbsp;*p;<br>
+&nbsp;&nbsp;int&nbsp;nData;<br>
+&nbsp;&nbsp;char&nbsp;zName[50];<br>
+&nbsp;&nbsp;Tcl_Channel&nbsp;chan;<br>
+&nbsp;&nbsp;static&nbsp;int&nbsp;count&nbsp;=&nbsp;1;<br>
+&nbsp;<br>
+&nbsp;&nbsp;zData&nbsp;=&nbsp;FindBuiltinFile(zFilename,&nbsp;1,&nbsp;&amp;nData);<br>
+&nbsp;&nbsp;if(&nbsp;zData==0&nbsp;)&nbsp;return&nbsp;NULL;<br>
+&nbsp;&nbsp;p&nbsp;=&nbsp;(BuiltinFileStruct*)Tcl_Alloc(&nbsp;sizeof(BuiltinFileStruct)&nbsp;);<br>
+&nbsp;&nbsp;if(&nbsp;p==0&nbsp;)&nbsp;return&nbsp;NULL;<br>
+&nbsp;&nbsp;p->zData&nbsp;=&nbsp;zData;<br>
+&nbsp;&nbsp;p->nData&nbsp;=&nbsp;nData;<br>
+&nbsp;&nbsp;p->cursor&nbsp;=&nbsp;0;<br>
+&nbsp;&nbsp;sprintf(zName,"etbi_bffffc7c_8049b04",((int)BuiltinFileOpen)>>12,count++);<br>
+&nbsp;&nbsp;chan&nbsp;=&nbsp;Tcl_CreateChannel(&amp;builtinChannelType,&nbsp;zName,&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ClientData)p,&nbsp;TCL_READABLE);<br>
+&nbsp;&nbsp;return&nbsp;chan;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">The <tt>TclOpenFileChannelInsertProc()</tt> Function</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>static&nbsp;Tcl_ChannelType&nbsp;builtinChannelType&nbsp;=&nbsp;{<br>
+&nbsp;&nbsp;"builtin",&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Type&nbsp;name.&nbsp;*/<br>
+&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Always&nbsp;non-blocking.*/<br>
+&nbsp;&nbsp;BuiltinFileClose,&nbsp;&nbsp;&nbsp;/*&nbsp;Close&nbsp;proc.&nbsp;*/<br>
+&nbsp;&nbsp;BuiltinFileInput,&nbsp;&nbsp;&nbsp;/*&nbsp;Input&nbsp;proc.&nbsp;*/<br>
+&nbsp;&nbsp;BuiltinFileOutput,&nbsp;&nbsp;/*&nbsp;Output&nbsp;proc.&nbsp;*/<br>
+&nbsp;&nbsp;BuiltinFileSeek,&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Seek&nbsp;proc.&nbsp;*/<br>
+&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Set&nbsp;option&nbsp;proc.&nbsp;*/<br>
+&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Get&nbsp;option&nbsp;proc.&nbsp;*/<br>
+&nbsp;&nbsp;BuiltinFileWatch,&nbsp;&nbsp;&nbsp;/*&nbsp;Watch&nbsp;for&nbsp;events&nbsp;on&nbsp;console.&nbsp;*/<br>
+&nbsp;&nbsp;BuiltinFileHandle,&nbsp;&nbsp;/*&nbsp;Get&nbsp;a&nbsp;handle&nbsp;from&nbsp;the&nbsp;device.&nbsp;*/<br>
+};</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p>
+ <p>For additional information see:</p>
+ <ul>
+ <li>The man page for <tt>Tcl_CreateChannel()</tt></li>
+ <li>Tk source code file <tt>generic/tkConsole.c</tt></li>
+ </ul>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Initializing Tk</h2>
+<p><ul><li>All the same initialization script issues as Tcl</li></ul><ul><li>Tk initialization scripts are in a different directory
+ than the Tcl initialization scripts - the "Tk Library"</li></ul><ul><li>Call <tt>Tk_Init()</tt> after <tt>Tcl_Init()</tt></li></ul><ul><li>Must have an event loop or Tk will not work!</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Implementing An Event Loop</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>button&nbsp;.b&nbsp;-text&nbsp;Hello&nbsp;-command&nbsp;exit<br>
+pack&nbsp;.b</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Create a Tk interface</td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>bind&nbsp;.&nbsp;&lt;Destroy>&nbsp;{<br>
+&nbsp;&nbsp;if&nbsp;{![winfo&nbsp;exists&nbsp;.]}&nbsp;exit<br>
+}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Close the application when the main window
+ is destroyed</td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>while&nbsp;1&nbsp;{vwait&nbsp;forever}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">The event loop</td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">"Hello, World!" Using Tk</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tk.h><br>
+&nbsp;<br>
+</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>static&nbsp;char&nbsp;zHello[]&nbsp;=&nbsp;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">The application code</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;"button&nbsp;.b&nbsp;"<br>
+&nbsp;&nbsp;&nbsp;&nbsp;"-text&nbsp;{Hello,&nbsp;World}&nbsp;"<br>
+&nbsp;&nbsp;&nbsp;&nbsp;"-command&nbsp;exit\n"<br>
+&nbsp;&nbsp;"pack&nbsp;.b\n";<br>
+&nbsp;<br>
+</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>static&nbsp;char&nbsp;zEventLoop[]&nbsp;=</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">The event loop</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;"bind&nbsp;.&nbsp;&lt;Destroy>&nbsp;{\n"<br>
+&nbsp;&nbsp;"&nbsp;&nbsp;if&nbsp;{![winfo&nbsp;exists&nbsp;.]}&nbsp;exit\n"<br>
+&nbsp;&nbsp;"}\n"<br>
+&nbsp;&nbsp;"while&nbsp;1&nbsp;{vwait&nbsp;forever}\n";<br>
+&nbsp;<br>
+<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
+&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Init(interp);<br>
+&nbsp;&nbsp;Tk_Init(interp);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">We really should check the return values of the init functions...</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zHello);</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zEventLoop);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">The event loop never returns</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*NOTREACHED*/<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Compiling "Hello, World!" For Tk</h2>
+<p><p><b>Unix:</b></p>
+ <blockquote><pre>
+ $ gcc hello.c -ltk -L/usr/X11R6/lib \
+ -lX11 -ltcl -lm -ldl
+ $ ./a.out</pre></blockquote>
+
+ <p><b>Windows using Cygwin:</b></p>
+ <blockquote><pre>
+ C:> gcc hello.c -mwindows -ltk80 -ltcl80 -lm
+ C:> a.exe</pre></blockquote>
+
+ <p><b>Windows using Mingw32:</b></p>
+ <blockquote><pre>
+ C:> gcc -mno-cygwin hello.c -mwindows \
+ -ltk82 -ltcl82 -lm
+ C:> a.exe</pre></blockquote></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Making The Program Standalone</h2>
+<p><p>To make a Tcl application standalone you have to convert the following
+ initialization scripts to C strings and compile them into the
+ executable:</p>
+ <table><tr>
+ <td valign="top"><tt>
+ &nbsp;&nbsp;auto.tcl<br>
+ &nbsp;&nbsp;history.tcl<br>
+ &nbsp;&nbsp;init.tcl
+ </tt></td>
+ <td valign="top"><tt>
+ &nbsp;&nbsp;ldAout.tcl<br>
+ &nbsp;&nbsp;package.tcl
+ </tt></td>
+ <td valign="top"><tt>
+ &nbsp;&nbsp;parray.tcl<br>
+ &nbsp;&nbsp;safe.tcl
+ </tt></td>
+ <td valign="top"><tt>
+ &nbsp;&nbsp;tclIndex<br>
+ &nbsp;&nbsp;word.tcl
+ </tt></td>
+ </tr></table>
+
+ <p>To make a Tk application standalone requires these additional
+ initialization scripts from the Tk Library:</p>
+ <table><tr>
+ <td valign="top"><tt>
+ &nbsp;&nbsp;bgerror.tcl<br>
+ &nbsp;&nbsp;button.tcl<br>
+ &nbsp;&nbsp;clrpick.tcl<br>
+ &nbsp;&nbsp;comdlg.tcl<br>
+ &nbsp;&nbsp;console.tcl<br>
+ &nbsp;&nbsp;dialog.tcl
+ </tt></td>
+ <td valign="top"><tt>
+ &nbsp;&nbsp;entry.tcl<br>
+ &nbsp;&nbsp;focus.tcl<br>
+ &nbsp;&nbsp;listbox.tcl<br>
+ &nbsp;&nbsp;menu.tcl<br>
+ &nbsp;&nbsp;msgbox.tcl<br>
+ &nbsp;&nbsp;optMenu.tcl
+ </tt></td>
+ <td valign="top"><tt>
+ &nbsp;&nbsp;palette.tcl<br>
+ &nbsp;&nbsp;safetk.tcl<br>
+ &nbsp;&nbsp;scale.tcl<br>
+ &nbsp;&nbsp;scrlbar.tcl<br>
+ &nbsp;&nbsp;tclIndex<br>
+ &nbsp;&nbsp;tearoff.tcl
+ </tt></td>
+ <td valign="top"><tt>
+ &nbsp;&nbsp;text.tcl<br>
+ &nbsp;&nbsp;tk.tcl<br>
+ &nbsp;&nbsp;tkfbox.tcl<br>
+ &nbsp;&nbsp;xmfbox.tcl
+ </tt></td>
+ </tr></table>
+
+ <p>Total of about 13K lines and 400K bytes of text or 9K lines and
+ 250K bytes if you strip comments and leading spaces</p></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">A Review Of The Features We Want</h2>
+<p><ol type="A">
+ <li value="1">
+ Combine C/C++ with Tcl/Tk into a single executable.</dd>
+ </li></ol>
+
+ <ol type="A">
+ <li value="2">
+ The executable should be standalone. It must not depend
+ on files not normally found on the system.
+ </li></ol>
+
+ <ol type="A">
+ <li value="3">
+ It should be difficult for end users to alter the program
+ (and introduce bugs).
+ </li></ol></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Available Programming Aids</h2>
+<p><p>Several tools are available. The chart below shows which tools
+ help achieve which objectives.</p>
+
+ <center><table border="2">
+ <tr>
+ <td></td>
+ <td colspan="3" align="center">
+ <b>Features The Tool Helps To Achieve</b></td>
+ </tr>
+ <tr>
+ <td align="center"><b>Tool Name</b></td>
+ <td align="center">Mix C and Tcl</td>
+ <td align="center">Standalone</td>
+ <td align="center">Hide Source</td>
+ </tr>
+ <tr>
+ <td>SWIG</td>
+ <td align="center"><img src="image6"></td>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td>TclPro Wrapper</td>
+ <td>&nbsp;</td>
+ <td align="center"><img src="image6"></td>
+ <td align="center"><img src="image6"></td>
+ </tr>
+ <tr>
+ <td>FreeWrap</td>
+ <td>&nbsp;</td>
+ <td align="center"><img src="image6"></td>
+ <td align="center"><img src="image6"></td>
+ </tr>
+ <tr>
+ <td>Wrap</td>
+ <td>&nbsp;</td>
+ <td align="center"><img src="image6"></td>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td>mktclapp</td>
+ <td align="center"><img src="image6"></td>
+ <td align="center"><img src="image6"></td>
+ <td align="center"><img src="image6"></td>
+ </tr>
+ </table></center></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">SWIG</h2>
+<table><tr><td valign="top"><img src="image7"></td>
+<td valign="top"><p><ul><li>Creates an interface between an existing C/C++ library and a high-level
+ programming language. Support for:
+ <ul>
+ <li> Tcl/Tk </li>
+ <li> Perl </li>
+ <li> Python </li>
+ <li> Java </li>
+ <li> Eiffel </li>
+ <li> Guile </li>
+ </ul></li></ul><ul><li>No changes required to C/C++ code. Can be used with legacy libraries.</li></ul><ul><li>Generates an extension, not a standalone binary</li></ul><ul><li>The tutorial on SWIG was yesterday afternoon.</li></ul><ul><li>http://www.swig.org/</li></ul></p></td></tr></table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Wrapper Programs</h2>
+<table><tr><td valign="top"><img src="image8"></td>
+<td valign="top"><p><ul><li>Convert a pure Tcl/Tk program into a standalone binary</li></ul><ul><li>Several wrapper programs are available:
+ <ul>
+ <li> TclPro Wrapper - http://www.scriptics.com/ </li>
+ <li> FreeWrap - http://www.albany.net/~dlabelle/freewrap/freewrap.html </li>
+ <li> Wrap - http://members1.chello.nl/~j.nijtmans/wrap.html </li>
+ </ul></li></ul><ul><li>No C compiler required!</li></ul><ul><li>TclPro will convert Tcl script into bytecode so that it cannot be
+ easily read by the end user. FreeWrap encrypts the scripts.</li></ul><ul><li>FreeWrap uses compression on its executable.
+ Wrap uses compression on both the executable and on the bundled script files.</li></ul><ul><li>Usually include extensions like winico and/or BLT</li></ul></p></td></tr></table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">mktclapp</h2>
+<table><tr><td valign="top"><img src="image9"></td>
+<td valign="top"><p><ul><li>Mix C/C++ with Tcl/Tk into a standalone binary</li></ul>
+<ul><li><tt>mktclapp</tt> generates an application initialization file
+ that contains Tcl scripts as strings and makes all necessary calls
+ to <tt>Tcl_Init</tt>, <tt>Tcl_CreateCommand</tt>,
+ <tt>Tcl</tt>*<tt>InsertProc</tt>, etc.</li></ul><ul><li>Features to make it easier to write new Tcl command in C</li></ul><ul><li><tt>xmktclapp.tcl</tt> provides a GUI interface to <tt>mktclapp</tt></li></ul><ul><li>http://www.hwaci.com/sw/mktclapp/</li></ul></p></td></tr></table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">"Hello, World!" Using Mktclapp</h2>
+<p><ul><li>Download <tt>mktclapp.c</tt> and <tt>xmktclapp.tcl</tt> from
+ http://www.hwaci.com/sw/mktclapp/</li></ul><ul><li>Compile <tt>mktclapp</tt>:
+ <blockquote><pre>
+ cc -o mktclapp mktclapp.c
+ </pre></blockquote></li></ul><ul><li>Create "Hello, World!" as a Tcl script in file <tt>hw.tcl</tt>:
+ <blockquote><pre>
+ button .b -text {Hello, World!} -command exit
+ pack .b
+ </pre></blockquote></li></ul><ul><li>Launch xmktclapp:
+ <blockquote><pre>
+ wish xmktclapp.tcl
+ </pre></blockquote></li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">"Hello, World!" Using Mktclapp</h2>
+<table width="100%"><tr><td valign="top"><p><ul><li>Set "Command Line Input?" to "None"</li></ul><ul><li>Set "Standalone?" to "Yes"</li></ul><ul><li>Enter "<tt>hw.mta</tt>" for the Configuration File</li></ul><ul><li>Enter "<tt>hw.c</tt>" for the Output C File</li></ul></p></td>
+<td valign="top" align="right"><img src="image10"></td></tr></table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">"Hello, World!" Using Mktclapp</h2>
+<table width="100%"><tr><td valign="top"><p><ul><li>Go to the "Tcl Scripts" page</li></ul><ul><li>Press "Insert" and add <tt>hw.tcl</tt> to the list of
+ Tcl scripts</li></ul><ul><li>Change the "Startup Script" to be <tt>hw.tcl</tt>.</li></ul><ul><li>Select File/Build and File/Exit</li></ul></p></td>
+<td valign="top" align="right"><img src="image11"></td></tr></table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">"Hello, World!" Using Mktclapp</h2>
+<p><ul><li>Mktclapp generates <tt>hw.c</tt>.
+ Compile it something like this:
+ <pre>
+ cc hw.c -ltk -L/usr/X11R6/lib -lX11 -ltcl -lm -ldl
+ </pre></li></ul><ul><li>Or, if using Cygwin:
+ <pre>
+ gcc hw.c -mwindows -ltk80 -ltcl80 -lm
+ </pre></li></ul><ul><li>Or, if using Mingw32:
+ <pre>
+ gcc -mno-cygwin hw.c -mwindows -ltk82 -ltcl82 -lm
+ </pre></li></ul><ul><li>And you're done!</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Adding C Code To Your Program</h2>
+<p>Put the new C code in a new source file named "<tt>add.c</tt>"</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;"hw.h"</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Generated by mktclapp</td>
+</tr>
+<tr><td valign="center">
+<small><tt></tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>int&nbsp;ET_COMMAND_add(ET_TCLARGS){</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><tt>ET_TCLARGS</tt> is a macro defined in <tt>hw.h</tt></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;int&nbsp;a,&nbsp;b;<br>
+&nbsp;&nbsp;char&nbsp;zResult[30];<br>
+&nbsp;&nbsp;a&nbsp;=&nbsp;atoi(argv[1]);<br>
+&nbsp;&nbsp;b&nbsp;=&nbsp;atoi(argv[2]);<br>
+&nbsp;&nbsp;sprintf(zResult,&nbsp;"-1073742724",&nbsp;a+b);<br>
+&nbsp;&nbsp;Tcl_SetResult(interp,&nbsp;zResult,&nbsp;TCL_VOLATILE);<br>
+&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Adding C Code To Your Program</h2>
+<table width="100%"><tr><td valign="top"><p><ul><li>Go to the "C/C++ Modules" page of xmktclapp.tcl</li></ul>
+<ul><li>Press "Insert" and add <tt>add.c</tt> to the list of
+ C/C++ modules</p></li></ul></li></ul><ul><li>Select File/Build and File/Exit</li></ul></p></td>
+<td valign="top" align="right"><img src="image12"></td></tr></table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Adding C Code To Your Program</h2>
+<p><ul><li>Compile as follows:
+ <pre>
+ cc add.c hw.c -ltk -L/usr/X11R6/lib -ltcl -lm -ldl
+ </pre></li></ul><ul><li>Or construct a Makefile that compiles <tt>add.c</tt> into <tt>add.o</tt>
+ and <tt>hw.c</tt> into <tt>hw.o</tt> and then links them.</li></ul><ul><li>Compile the same way for Windows except use the usual Windows
+ libraries and options...</li></ul><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>Don't have to worry with <tt>Tcl_CreateCommand()</tt> - Mktclapp takes
+ care of that automatically.</b></td></tr></table></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Checking Parameters In The <tt>add</tt> Command</h2>
+<p>Modify <tt>add.c</tt> to insure the <tt>add</tt> command
+ is called with exactly two integer arguments</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;"hw.h"<br>
+&nbsp;<br>
+int&nbsp;ET_COMMAND_add(ET_TCLARGS){<br>
+&nbsp;&nbsp;int&nbsp;a,&nbsp;b;<br>
+&nbsp;&nbsp;char&nbsp;zResult[30];</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;argc!=3&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;Tcl_AppendResult(interp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"wrong&nbsp;#&nbsp;args:&nbsp;should&nbsp;be:&nbsp;\"",<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argv[0],&nbsp;"&nbsp;VALUE&nbsp;VALUE\"",&nbsp;0);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Report an error if there are not exactly
+ 2 arguments</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;Tcl_GetInt(interp,&nbsp;argv[1],&nbsp;&amp;a)!=TCL_OK&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Report an error if the first argument is
+ not an integer</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;Tcl_GetInt(interp,&nbsp;argv[2],&nbsp;&amp;b)!=TCL_OK&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Do the same for the second argument</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;sprintf(zResult,&nbsp;"-1073742724",&nbsp;a+b);<br>
+&nbsp;&nbsp;Tcl_SetResult(interp,&nbsp;zResult,&nbsp;TCL_VOLATILE);<br>
+&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Using The Tcl_Obj Interface</h2>
+<p>In the file <tt>objadd.c</tt> put this code:</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;"hw.h"</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+int&nbsp;ET_OBJCOMMAND_add2(ET_OBJARGS){<br>
+&nbsp;&nbsp;int&nbsp;a,&nbsp;b;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Use "<tt>ET_OBJCOMMAND</tt>" instead of "<tt>ET_COMMAND</tt>" and
+ "<tt>ET_OBJARGS</tt>" instead of "<tt>ET_TCLARGS</tt>"</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;objc!=3&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;Tcl_WrongNumArgs(interp,&nbsp;1,&nbsp;objv,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"number&nbsp;number");<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">A special routine for "wrong # args" error</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;Tcl_GetIntFromObj(interp,&nbsp;objv[1],&nbsp;&amp;a)&nbsp;){</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Instead of <tt>Tcl_GetInt</tt></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;if(&nbsp;Tcl_GetIntFromObj(interp,&nbsp;objv[2],&nbsp;&amp;b)&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_SetIntObj(Tcl_GetObjResult(interp),&nbsp;a+b);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Result stored as integer, not a string</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Speed Of Tcl_Obj Versus "char*" Interfaces</h2>
+<p><ul><li>Compile both <tt>add</tt> and <tt>add2</tt> into the same executable.</li></ul><ul><li>Compare their speeds:
+ <pre>
+ time {add 123456 654321} 10000
+ <font color="blue">26 microseconds per iteration</font>
+ time {add2 123456 654321} 10000
+ <font color="blue">4 microseconds per iteration</font>
+ </pre></li></ul><ul><li>The Tcl_Obj version is 650 faster!</li></ul><ul><li>Replace the addition with a "real" computation that takes
+ 10 milliseconds.</li></ul><ul><li>Now the Tcl_Obj version is only 0.2 faster!</li></ul><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>In many real-world problems, the Tcl_Obj interface has no noticeable
+ speed advantage over the string interface.</b></td></tr></table></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">More About Built-in Tcl Scripts</h2>
+<table><tr><td valign="top"><img src="image11"></td>
+<td valign="top"><p><ul><li>Comments and leading white-space are removed from the
+ script by default. Use the "Don't Strip Comments"
+ button to change this.</li></ul><ul><li>The file name must exactly match the name that is
+ used by the <tt>source</tt> command.</li></ul></p></td></tr></table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Locations Of Libraries</h2>
+<table><tr><td valign="top"><img src="image13"></td>
+<td valign="top"><p><ul><li>Tells mktclapp where to look for script libraries.</li></ul><ul><li>All Tcl scripts in the indicated directories are
+ compiled into the <tt>appinit.c</tt> file.</li></ul><ul><li>Comments and extra white-space are removed.
+ There is no way to turn this off.</li></ul></p></td></tr></table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Built-in Binary Data Files</h2>
+<table><tr><td valign="top"><img src="image14"></td>
+<td valign="top"><p><ul><li>Arbitrary files become part of the virtual filesystem</li></ul><ul><li>No comment or white-space removal is attempted</li></ul><ul><li>Useful for images or other binary data</li></ul></p></td></tr></table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">New Commands In Namespaces</h2>
+<p>Two underscores (__) are replaced by two colons (::) in
+ command names, thus giving the ability to define new commands
+ in a namespace</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;hw.h></tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt><br>
+int&nbsp;ET_COMMAND_adder__add(ET_TCLARGS){<br>
+&nbsp;&nbsp;int&nbsp;a,&nbsp;b;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Creates the Tcl command called "<tt>adder::add</tt>"</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;char&nbsp;*zResult[30];<br>
+&nbsp;&nbsp;if(&nbsp;argc!=3&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;Tcl_AppendResult(interp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"wrong&nbsp;#&nbsp;args:&nbsp;should&nbsp;be:&nbsp;\"",<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argv[0],&nbsp;"&nbsp;VALUE&nbsp;VALUE\"",&nbsp;0);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;if(&nbsp;Tcl_GetInt(interp,&nbsp;argv[1],&nbsp;&amp;a)!=TCL_OK&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;if(&nbsp;Tcl_GetInt(interp,&nbsp;argv[1],&nbsp;&amp;b)!=TCL_OK&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}<br>
+&nbsp;&nbsp;sprintf(zResult,&nbsp;"-1073742724",&nbsp;a+b);<br>
+&nbsp;&nbsp;Tcl_SetResult(interp,&nbsp;zResult,&nbsp;TCL_VOLATILE);<br>
+&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Adding Your Own <tt>main()</tt></h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;/*&nbsp;Application&nbsp;specific&nbsp;initialization&nbsp;*/</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Et_Init(argc,&nbsp;argv);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Never returns!</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*NOTREACHED*/<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><table><tr><td valign="top"><img src="image3"></td>
+<td valign="top"><b>The "Autofork" feature is disabled if you supply your own <tt>main()</tt></b></td></tr></table>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Initializing The Tcl Interpreter</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+int&nbsp;counter&nbsp;=&nbsp;0;<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
+&nbsp;&nbsp;&nbsp;Et_Init(argc,&nbsp;argv);<br>
+&nbsp;&nbsp;&nbsp;/*NOTREACHED*/<br>
+&nbsp;&nbsp;&nbsp;return&nbsp;0;<br>
+}<br>
+&nbsp;<br>
+int&nbsp;Et_AppInit(Tcl_Interp&nbsp;*interp){</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;if(&nbsp;Blt_Init(Interp)&nbsp;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Example: Initialize an extension</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Tcl_LinkVar(interp,&nbsp;"counter",&nbsp;&amp;counter,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TCL_LINK_INT);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Or link a C variable to a Tcl variable</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Return TCL_OK if successful</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Writing Your Own Event Loop</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>void&nbsp;Et_CustomMainLoop(Tcl_Interp&nbsp;*interp){</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Replaces the default event loop</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;return;</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Ex: Return without handling any events.</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Et_Init(argc,&nbsp;argv);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">This now returns after initializing Tcl</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*&nbsp;Application&nbsp;code&nbsp;here&nbsp;*/<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Writing Your Own Event Loop</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;&lt;tcl.h><br>
+&nbsp;<br>
+void&nbsp;Et_CustomMainLoop(Tcl_Interp&nbsp;*interp){</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;for(;;){<br>
+&nbsp;&nbsp;&nbsp;&nbsp;Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);<br>
+&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Other&nbsp;processing...&nbsp;*/<br>
+&nbsp;&nbsp;}</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Intermix processing and event handling</td>
+</tr>
+<tr><td valign="center">
+<small><tt>}<br>
+&nbsp;<br>
+int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;Et_Init(argc,&nbsp;argv);</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Never returns</td>
+</tr>
+<tr><td valign="center">
+<small><tt>&nbsp;&nbsp;/*NOTREACHED*/<br>
+&nbsp;&nbsp;return&nbsp;0;<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Mktclapp Initialization Sequence</h2>
+<p><ul><li>Initialization starts when the <tt>Et_Init()</tt>
+ function is called either by client code or by
+ the <tt>main()</tt> that mktclapp generates</li></ul><ul><li>Create the main Tcl interpreter</li></ul><ul><li>Construct the virtual filesystem overlay by redefining
+ the <tt>source</tt> command and by using the
+ <tt>Tcl</tt>*<tt>InsertProc()</tt> functions</li></ul><ul><li>Call <tt>Et_PreInit()</tt> if the client defines it</li></ul><ul><li>Call <tt>Tcl_Init()</tt> and <tt>Tk_Init()</tt></li></ul><ul><li>Call <tt>Tcl_CreateCommand()</tt> and <tt>Tcl_CreateObjCommand()</tt>
+ for every <tt>ET_COMMAND_</tt>* and <tt>ET_OBJCOMMAND_</tt>* function
+ in the client code</li></ul><ul><li>Call <tt>Et_AppInit()</tt> if the client defines it</li></ul><ul><li>Run the main Tcl script if there is one</li></ul><ul><li>Call <tt>Et_CustomMainLoop()</tt> if defined by client code or
+ else run the built-in event loop</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Invoking Tcl From C</h2>
+<p><ul><li>Use one of the built-in evaluation functions:
+ <center><table width="80%">
+ <tr><td valign="top" width="50%"><ul>
+ <li> Tcl_Eval() </li>
+ <li> Tcl_VarEval() </li>
+ <li> Tcl_EvalFile() </li>
+ <li> Tcl_GlobalEval() </li>
+ </ul></td>
+ <td valign="top" width="50%"><ul>
+ <li> Tcl_EvalObj() </li>
+ <li> Tcl_GlobalEvalObj() </li>
+ </ul></td></tr>
+ </table></center></li></ul><ul><li>Mktclapp provides evaluation functions with variable argument
+ lists as in <tt>printf()</tt>:
+ <ul>
+ <li> Et_EvalF() </li>
+ <li> Et_GlobalEvalF() </li>
+ </ul></li></ul><ul><li>Mktclapp provides a global variable <tt>Et_Interp</tt> which is
+ a pointer to the main interpreter</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Invoking Tcl From C</h2>
+<p>Example: A C function that pops up an error message dialog box</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;"appinit.h"<br>
+&nbsp;<br>
+void&nbsp;ErrMsg(char&nbsp;*zMsg){<br>
+&nbsp;&nbsp;Tcl_SetVar(Et_Interp,&nbsp;"zMsg",&nbsp;zMsg,&nbsp;TCL_GLOBAL_ONLY);<br>
+&nbsp;&nbsp;Tcl_GlobalEval(Et_Interp,&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;"tk_messageBox&nbsp;-icon&nbsp;error&nbsp;-msg&nbsp;$zMsg&nbsp;-type&nbsp;ok");<br>
+&nbsp;&nbsp;Tcl_UnsetVar(Et_Interp,&nbsp;"zMsg",&nbsp;TCL_GLOBAL_ONLY);<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Invoking Tcl From C</h2>
+<p>The same C function implemented using <tt>Et_EvalF()</tt> instead
+ of <tt>Tcl_GlobalEval()</tt></p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;"appinit.h"<br>
+&nbsp;<br>
+void&nbsp;ErrMsg(char&nbsp;*zMsg){<br>
+&nbsp;&nbsp;Et_EvalF(Et_Interp,&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;"tk_messageBox&nbsp;-icon&nbsp;error&nbsp;-msg&nbsp;{¸üÿ¿PX¶}&nbsp;-type&nbsp;ok",<br>
+&nbsp;&nbsp;&nbsp;&nbsp;zMsg);<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p>
+ <ul><li>
+ Suppose the function is called as follows:
+ <blockquote>
+ <tt>ErrMsg("Syntax error near \"}\"");</tt>
+ </blockquote>
+ </li></ul>
+
+ <ul><li>
+ The command that gets executed is:
+ <pre>
+ tk_messageBox -icon error -msg \
+ {Syntax error near "}"} -type ok
+ </pre>
+ </li></ul>
+
+ <ul><li>
+ But this is an ill-formed Tcl command!
+ </li></ul>
+</p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Invoking Tcl From C</h2>
+<p>Use the "<tt></tt>" format to generate a quoted string</p><p>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#include&nbsp;"appinit.h"<br>
+&nbsp;<br>
+void&nbsp;ErrMsg(char&nbsp;*zMsg){<br>
+&nbsp;&nbsp;Et_EvalF(Et_Interp,&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;"tk_messageBox&nbsp;-icon&nbsp;error&nbsp;-msg&nbsp;\"%\"&nbsp;-type&nbsp;ok",<br>
+&nbsp;&nbsp;&nbsp;&nbsp;zMsg);<br>
+}</tt></small></td>
+<td></td><td></td><td></td><td></td>
+</tr>
+</table>
+<p><ul><li>The <tt></tt> puts a backslash before all characters that
+ are special to Tcl</li></ul><ul><li>The Tcl command becomes:
+ <pre>
+ tk_messageBox -icon error -msg \
+ "Syntax error near \"\}\"" -type ok
+ </pre></li></ul></p>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Other Functions Provided By Mktclapp</h2>
+<p><ul><li><tt>void Et_ResultF(Tcl_Interp*, ...);</tt></li></ul><ul><li><tt>char *Et_DStringAppendF(Tcl_DString*, ...);</tt></li></ul><ul><li><tt>int Et_AppendObjF(Tcl_Obj*, ...);</tt></li></ul><ul><li><tt>char *mprintf(const char *format, ...);<br>
+ char *vmprintf(const char *format, va_list);</tt></li></ul><ul><li><tt>void Et_NewBuiltinFile(char *filename, char *data, int amt);</tt></li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Operating Mktclapp From The Command Line</h2>
+<p><ul><li>Generate the <tt>appinit.h</tt> header file like this:
+ <blockquote>
+ <tt>mktclapp -header &gt;appinit.h</tt>
+ </blockquote></li></ul><ul><li>Generate the <tt>appinit.c</tt> file like this:
+ <blockquote>
+ <tt>mktclapp -f appinit.mta >appinit.c</tt>
+ </blockquote></li></ul><ul><li>The <tt>*.mta</tt> file is just a list of command-line options</li></ul><ul><li>Enter
+ <blockquote>
+ <tt>mktclapp -help</tt>
+ </blockquote>
+ to get a list of available options</li></ul><ul><li>Look at MTA files generated by xmktclapp.tcl for examples</li></ul></p>
+<br clear="both"><p><hr></p>
+<h2 align="center">Format Of An MTA File</h2>
+<table cellspacing="0" cellpadding="0" border="0">
+<tr><td valign="center">
+<small><tt>#&nbsp;Configuration&nbsp;file&nbsp;generated&nbsp;by&nbsp;xmktclapp<br>
+#&nbsp;Hand&nbsp;editing&nbsp;is&nbsp;not&nbsp;recommended<br>
+#</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Comments begin with one #</td>
+</tr>
+<tr><td valign="center">
+<small><tt>##&nbsp;Autofork&nbsp;No<br>
+##&nbsp;CFile:add.c&nbsp;1<br>
+##&nbsp;CFile:objadd.c&nbsp;1<br>
+##&nbsp;CmdLine&nbsp;Console<br>
+##&nbsp;ConfigFile&nbsp;hw.mta<br>
+##&nbsp;Data:check.gif&nbsp;1<br>
+##&nbsp;MainScript&nbsp;hw.tcl<br>
+##&nbsp;Mode&nbsp;Tcl/Tk<br>
+##&nbsp;NoSource&nbsp;No<br>
+##&nbsp;OutputFile&nbsp;hw.c<br>
+##&nbsp;Shroud&nbsp;No<br>
+##&nbsp;Standalone&nbsp;Yes<br>
+##&nbsp;TclFile:hw.tcl&nbsp;1<br>
+##&nbsp;TclLib&nbsp;/usr/lib/tcl8.0<br>
+##&nbsp;TkLib&nbsp;/usr/lib/tk8.0</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">Lines beginning with two #s are used
+ by xmktclapp.tcl and ignored by mktclapp</td>
+</tr>
+<tr><td valign="center">
+<small><tt>-console<br>
+-main-script&nbsp;"hw.tcl"<br>
+-tcl-library&nbsp;"/usr/lib/tcl8.0"<br>
+-tk-library&nbsp;"/usr/lib/tk8.0"<br>
+"add.c"<br>
+"objadd.c"<br>
+-i&nbsp;"check.gif"<br>
+-strip-tcl&nbsp;"hw.tcl"</tt></small></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center"><img src="image2"></td>
+<td>&nbsp;&nbsp;</td>
+<td valign="center">All other lines are read by mktclapp and
+ ignored by xmktclapp.tcl</td>
+</tr>
+</table>
+
+<br clear="both"><p><hr></p>
+<h2 align="center">Summary</h2>
+<p><ul><li>Use Tcl for the things Tcl is good at and use C/C++ for the things that
+ C/C++ is good at</li></ul><ul><li>Use wrapper programs to make pure Tcl programs standalone</li></ul><ul><li>Use mktclapp to combine Tcl/Tk with C/C++ into a standalone</li></ul></p>
+<br clear="both"><p><hr></p>
diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image1 b/ext/tk/sample/tkextlib/tkHTML/page4/image1
new file mode 100644
index 0000000000..da26d7092e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page4/image1
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image2 b/ext/tk/sample/tkextlib/tkHTML/page4/image2
new file mode 100644
index 0000000000..e176a96a55
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page4/image2
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image3 b/ext/tk/sample/tkextlib/tkHTML/page4/image3
new file mode 100644
index 0000000000..e829d3712c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page4/image3
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image4 b/ext/tk/sample/tkextlib/tkHTML/page4/image4
new file mode 100644
index 0000000000..f14ea13547
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page4/image4
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image5 b/ext/tk/sample/tkextlib/tkHTML/page4/image5
new file mode 100644
index 0000000000..4ef6277226
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page4/image5
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image6 b/ext/tk/sample/tkextlib/tkHTML/page4/image6
new file mode 100644
index 0000000000..1adb261b40
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page4/image6
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image7 b/ext/tk/sample/tkextlib/tkHTML/page4/image7
new file mode 100644
index 0000000000..ba0d26ec18
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page4/image7
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image8 b/ext/tk/sample/tkextlib/tkHTML/page4/image8
new file mode 100644
index 0000000000..8b81d58e27
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page4/image8
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image9 b/ext/tk/sample/tkextlib/tkHTML/page4/image9
new file mode 100644
index 0000000000..f0a352f9d0
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/page4/image9
Binary files differ
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 @@
+<!DOCTYPE HTML="HTML" PUBLIC="PUBLIC" "-//W3C//DTD=""-//W3C//DTD" HTML="HTML" 4.0="4.0" Transitional//EN"="Transitional//EN"">
+<HTML>
+<HEAD>
+<TITLE>[fm] welcome to freshmeat.net</TITLE>
+<STYLE TYPE="text/css"><!-- A:link {text-decoration: none}A:visited{text-decoration:none}A:active{text-decoration:none}--></STYLE>
+</HEAD>
+<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699">
+<BR><CENTER><TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0"><TR><TD WIDTH="1"><SCRIPT LANGUAGE="JAVASCRIPT">
+<!--
+now = new Date();
+tail = now.getTime();
+document.write("<IMG SRC='http://209.207.224.246/FreshMeat/Core/pc.gif?/index.php3," + tail + "' WIDTH=1 HEIGHT=1><BR>");
+//-->
+</SCRIPT>
+<NOSCRIPT>
+<IMG SRC="image1" WIDTH="1" HEIGHT="1"><BR>
+</NOSCRIPT></TD></TR></TABLE>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0"><TR><TD WIDTH="468"><SCRIPT LANGUAGE="JAVASCRIPT">
+<!--
+now = new Date();
+tail = now.getTime();
+AltText = "\"Please click here.\"";
+document.write("<A HREF='http://ads.freshmeat.net/cgi-bin/ad_click.pl?index,tsof0001en'>")
+document.write("<IMG SRC='http://ads.freshmeat.net/tsof0001en.gif?" + tail + "' WIDTH=468 HEIGHT=60 ALT=" + AltText + "></A><BR>");
+//-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="http://ads.freshmeat.net/cgi-bin/ad_click.pl?index,tsof0001en"><IMG SRC="image2" WIDTH="468" HEIGHT="60" ALT="Please click here."></A><BR>
+</NOSCRIPT></TD></TR></TABLE>
+
+<TABLE CELLSPACING="0" CELLPADDING="2" BORDER="0" WIDTH="97%"><TR>
+<TD ALIGN="left" VALIGN="bottom"><A HREF="/"><IMG SRC="image3" BORDER="0" ALT="freshmeat.net" WIDTH="300" HEIGHT="65"></A></TD>
+<TD VALIGN="bottom" ALIGN="left" ROWSPAN="2"><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<FORM METHOD="get" ACTION="/search.php3">
+<SMALL>find: <INPUT TYPE="text" SIZE="15" NAME="query"></SMALL></FORM></FONT></TD>
+<TD ALIGN="right" VALIGN="bottom"><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<A HREF="http://www.linux.com"><FONT COLOR="#000000"><B><SMALL>linux.com partner</SMALL></B></FONT></A><BR>
+<TABLE CELLSPACING="0" CELLPADDING="1" BORDER="0" WIDTH="100%"><TR>
+<TD ALIGN="right"><SMALL><NOBR><FONT FACE="Lucida,Verdana,Helvetica,Arial"><B><A HREF="/">news</A> |<BR>
+<A HREF="/appindex/">appindex</A> |<BR>
+<A HREF="/editorials/">editorials</A> |</B></FONT></NOBR></SMALL></TD>
+<TD ALIGN="right"><SMALL><NOBR><FONT FACE="Lucida,Verdana,Helvetica,Arial"><B><A HREF="/lounge/">lounge</A> |<BR>
+<A HREF="/contrib.php3">contribute</A> |<BR>
+<A HREF="/feedback.php3">feedback</A> |</B></FONT></NOBR></SMALL></TD>
+<TD ALIGN="right"><SMALL><NOBR><FONT FACE="Lucida,Verdana,Helvetica,Arial"><B><A HREF="/about.php3">about</A> |<BR>
+<A HREF="/awards.php3">awards</A> |<BR>
+<A HREF="/faq.php3">FAQ</A> |</B></FONT></NOBR></SMALL></TD>
+</TR></TABLE></TD>
+</TR></TABLE>
+<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0">
+<TR BGCOLOR="#000000"><TD><IMG SRC="image4" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
+<TABLE CELLSPACING="0" CELLPADDING="3" BORDER="0" WIDTH="100%" BGCOLOR="#BBDDFF">
+<TR><TD ALIGN="center" VALIGN="top">
+<BR>
+<FONT FACE="Lucida,Verdana,Helvetica,Arial">
+
+
+<SMALL><B>sort by: [ <A HREF="/news/2000/01/29/">date</A> | <A HREF="/news/list.php3?day=/2000/01/29/&orderby=name">name</A> | <A HREF="/news/list.php3?day=/2000/01/29/&orderby=urgency">urgency</A> ]</B></SMALL><BR></TD><TD>&nbsp;</TD></TR><TR><TD VALIGN="top" ALIGN="center"><FONT FACE="Lucida,Verdana,Helvetica,Arial"><TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">We should get this out of the door now</FONT></B><BR>
+<SMALL><B><A HREF="mailto:scoop@freshmeat.net">scoop</A> - January 29th 2000, 23:59 EST</B></SMALL>
+<P>Everyone else is talking about it, so we should announce it ourselves
+before you start to think it's a government hoax. <A HREF="http://server51.freshmeat.net/">Server 51</A> 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.
+
+
+
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949208399.html">comments (8)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>Category: freshmeat
+</SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+ <A HREF="http://server51.freshmeat.net"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">Is Linux for Crazies?</FONT></B><BR>
+<SMALL><B><A HREF="mailto:jeff.covey@pobox.com">jeff covey</A> - January 29th 2000, 23:59 EST</B></SMALL>
+<P>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."
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949208340.html">comments (2), 2065 words in body</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>Category: Editorial
+</SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+ &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">RabbIT 2.0.2</FONT></B><BR>
+<SMALL><B><A HREF="mailto:d94-rol@nada.kth.se">Ernimril</A> - January 29th 2000, 18:29 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> 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).
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949188564.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: freely distributable</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/daemons/proxy.html"><FONT COLOR="#FFFFFF">Daemons/Proxy</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/902659138/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/902659138/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/1998/08/09/902659138.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">nmpg 1.1.3</FONT></B><BR>
+<SMALL><B><A HREF="mailto:narkos@linuxmail.org">Joel Lindau</A> - January 29th 2000, 18:18 EST</B></SMALL>
+<DIV ALIGN="justify"><P>nmpg is a small command-driven frontend and network-jukebox for mpg123.</DIV>
+<P><B>Changes:</B> Bugfixes, better memory managment, a new .nmpgrc parser, and new options.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949187896.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: OpenSource</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/console/sound.html"><FONT COLOR="#FFFFFF">Console/Sound</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/935430877/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/935430877/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/935430877/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/08/23/935430877.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">mod_dtcl 0.7.3</FONT></B><BR>
+<SMALL><B><A HREF="mailto:davidw@prosa.it">David Welton</A> - January 29th 2000, 18:11 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> A major overhaul of header handling and internal buffering, and the addition of the ability to handle binary data.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949187471.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/web/development.html"><FONT COLOR="#FFFFFF">Web/Development</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/917925309/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/917925309/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/917925309/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/02/01/917925309.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">CoreLinux++ 0.4.6</FONT></B><BR>
+<SMALL><B><A HREF="mailto:frankc@users.sourceforge.net">Frank V. Castellucci</A> - January 29th 2000, 18:07 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> 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.
+<P><B>Urgency:</B> medium
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949187233.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: LGPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/development/libraries.html"><FONT COLOR="#FFFFFF">Development/Libraries</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/944077775/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/944077775/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/944077775/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/12/01/944077775.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">scribe 0.2</FONT></B><BR>
+<SMALL><B><A HREF="mailto:kahlage@logoncafe.net">ChromeBob</A> - January 29th 2000, 12:12 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> A fix for an fflush() bug and better documentation.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949165962.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/development/tools.html"><FONT COLOR="#FFFFFF">Development/Tools</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/946661656/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/946661656/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/1999/12/31/946661656.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">E theme updater 0.1</FONT></B><BR>
+<SMALL><B><A HREF="mailto:hallvar@ii.uib.no">Hallvar Helleseth</A> - January 29th 2000, 12:04 EST</B></SMALL>
+<DIV ALIGN="justify"><P>E theme Updater is a bash script to automatically update all of your Enlightenment themes from e.themes.org.</DIV>
+<P><B>Changes:</B> Initial release.
+
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949165472.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/console/misc.html"><FONT COLOR="#FFFFFF">Console/Misc</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/949164501/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/949164501/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/2000/01/29/949164501.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">Powertweak-Linux 0.1.7</FONT></B><BR>
+<SMALL><B><A HREF="mailto:dave@denial.force9.co.uk">Dave Jones</A> - January 29th 2000, 12:03 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> 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.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949165416.html">comments (2)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/console/system.html"><FONT COLOR="#FFFFFF">Console/System</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/930836224/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/930836224/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/930836224/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/07/01/930836224.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">Pexeso Beta</FONT></B><BR>
+<SMALL><B><A HREF="mailto:pavolkrigler@pobox.sk">Pavol Krigler</A> - January 29th 2000, 11:55 EST</B></SMALL>
+<DIV ALIGN="justify"><P>pexeso is a simple graphic card game for one or two players.</DIV>
+<P><B>Changes:</B> Initial public release.
+
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164956.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: Freeware</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/console/games.html"><FONT COLOR="#FFFFFF">Console/Games</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/949141436/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/949141436/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/2000/01/29/949141436.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">XZX 2.9.2</FONT></B><BR>
+<SMALL><B><A HREF="mailto:Erik.Kunze@fantasy.muc.de">E. Kunze</A> - January 29th 2000, 11:54 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> Lots of feature improvement and bug fixes. Most parts of the audio support has been rewritten for different UNICES.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164896.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: Shareware</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/x11/emulators.html"><FONT COLOR="#FFFFFF">X11/Emulators</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/936956384/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/936956384/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/936956384/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/09/10/936956384.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">DistroLib 0.4</FONT></B><BR>
+<SMALL><B><A HREF="mailto:phir@gcu-squad.org">PhiR</A> - January 29th 2000, 11:54 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> Important bug fixes and command history support.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164869.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/development/libraries.html"><FONT COLOR="#FFFFFF">Development/Libraries</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/942588431/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/942588431/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/942588431/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/11/14/942588431.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">ToutDoux 1.1.7</FONT></B><BR>
+<SMALL><B><A HREF="mailto:yeupou@altern.org">yeupou</A> - January 29th 2000, 11:54 EST</B></SMALL>
+<DIV ALIGN="justify"><P>ToutDoux is a project manager which lets you design a plan of action using a tree structure, with translations in French and English.</DIV>
+<P><B>Changes:</B> A new menu and XML standard for save files.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164843.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/gnome/tools.html"><FONT COLOR="#FFFFFF">GNOME/Tools</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/944433411/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/944433411/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/1999/12/05/944433411.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">goMP 1.0.3</FONT></B><BR>
+<SMALL><B><A HREF="mailto:dioxine@poulet.org">Gautier</A> - January 29th 2000, 11:52 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> 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.
+<P><B>Urgency:</B> medium
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164772.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: Artistic</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/web/tools.html"><FONT COLOR="#FFFFFF">Web/Tools</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/948492962/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/948492962/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/948492962/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/2000/01/21/948492962.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">APSEND 1.40</FONT></B><BR>
+<SMALL><B><A HREF="mailto:sventek@gmx.net">M.K.</A> - January 29th 2000, 11:50 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> The stream attack, bugfixes, and rewrites for parts of the code.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164633.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/console/networking.html"><FONT COLOR="#FFFFFF">Console/Networking</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/941654429/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/941654429/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/941654429/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/11/03/941654429.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">ecasound 1.6.12r10</FONT></B><BR>
+<SMALL><B><A HREF="mailto:kaiv@wakkanet.fi">Kai Vehmanen</A> - January 29th 2000, 11:48 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> 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.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164529.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/console/sound.html"><FONT COLOR="#FFFFFF">Console/Sound</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/931819147/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/931819147/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/931819147/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/07/12/931819147.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">SCEZ 20000129</FONT></B><BR>
+<SMALL><B><A HREF="mailto:m032@mbsks.franken.de">endergone Zwiebeltuete</A> - January 29th 2000, 11:46 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> More card and reader drivers, and an application to read out GSM SIM card (phone book and SMS) and write it to the card.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164394.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: BSD type</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/development/libraries.html"><FONT COLOR="#FFFFFF">Development/Libraries</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/939677525/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/939677525/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/1999/10/11/939677525.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">Comicq 0.2.0</FONT></B><BR>
+<SMALL><B><A HREF="mailto:terminal6@submail.net">Terminal6</A> - January 29th 2000, 11:45 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> Several bugfixes, icq99a compliance, and a new option --ip that allows you to get any user's IP by their UIN.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164350.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/console/communication.html"><FONT COLOR="#FFFFFF">Console/Communication</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/948389309/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/948389309/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/2000/01/20/948389309.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">senv 0.2</FONT></B><BR>
+<SMALL><B><A HREF="mailto:kojak@ids.pl">Zbyszek Sobiecki</A> - January 29th 2000, 11:44 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> Login shell limits and environment setting for users, permanent resource limits for specified groups of users and environment variables, and other minor bugfixes.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164259.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/console/administration.html"><FONT COLOR="#FFFFFF">Console/Administration</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/944953892/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/changelog/944953892/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/12/11/944953892.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2">
+<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF">
+<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B><FONT SIZE="+2">XZX 2.9.2</FONT></B><BR>
+<SMALL><B><A HREF="mailto:Erik.Kunze@fantasy.muc.de">E. Kunze</A> - January 29th 2000, 10:55 EST</B></SMALL>
+<DIV ALIGN="justify"><P>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.</DIV>
+<P><B>Changes:</B> Lots of feature improvement and bug fixes. Most parts of the audio support has been rewritten for different UNICES.
+<P><B>Urgency:</B> low
+<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949161354.html">comments (0)</A> ]</B>
+</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle">
+&nbsp;<FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: Shareware</SMALL></B><BR>
+<B><SMALL>&nbsp;Category: <A HREF="/appindex/x11/emulators.html"><FONT COLOR="#FFFFFF">X11/Emulators</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right">
+<A HREF="http://apps.freshmeat.net/download/936956384/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/936956384/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/936956384/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/09/10/936956384.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> &nbsp;
+</TD></TR></TABLE>
+<HR WIDTH="0" SIZE="0">
+
+
+<P><SMALL><CENTER><B>[ <A HREF="/news/2000/01/29/">full page for today</A> | <A HREF="/news/2000/01/28/">yesterday's edition</A> ]</SMALL></B></CENTER></FONT></TD><TD WIDTH="27%" VALIGN="top" ALIGN="center"><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">navigator</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="/news/2000/01/29/"><FONT COLOR="#000000">full page for today</FONT></A><BR>
+- <A HREF="/news/2000/01/28/"><FONT COLOR="#000000">yesterday's edition</FONT></A><BR>
+- <A HREF="news://news.freshmeat.net/"><FONT COLOR="#000000"><B>new:</B> fm news via NNTP</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">eye catcher</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<B>Free Shirts</B><BR>We give away a free freshmeat t-shirt every week for the best comment added to an application announcement or story posted on freshmeat.
+<P><B>#freshmeat</B><BR>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 <A HREF="http://openprojects.nu/">The Open Projects Network</A>.
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">site notes</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="/news/2000/01/29/949208399.html"><FONT COLOR="#000000">We should get this out of the door now (Jan 29th)</FONT></A><BR>
+- <A HREF="/news/2000/01/01/946704535.html"><FONT COLOR="#000000">freshmeat Y2K report (Jan 01st)</FONT></A><BR>
+- <A HREF="/news/1999/08/16/934862340.html"><FONT COLOR="#000000">Assorted freshmeat notes (Aug 16th)</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">recent editorials</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="/news/2000/01/29/949208340.html"><FONT COLOR="#000000">Is Linux for Crazies? (Jan 29th)</FONT></A><BR>
+- <A HREF="/news/2000/01/22/948603540.html"><FONT COLOR="#000000">A New Business Plan for Free Software (Jan 22nd)</FONT></A><BR>
+- <A HREF="/news/2000/01/15/947998740.html"><FONT COLOR="#000000">Is Linux Going to Reunite the UNIX Market? (Jan 15th)</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">andover.net</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+<BR><CENTER><A HREF="http://andover.net"><IMG SRC="image9" BORDER="0" WIDTH="150" HEIGHT="43" ALT="Mirror Logo"></A></CENTER><P>
+- <A HREF="http://www.animfactory.com/"><FONT COLOR="#000000">Animation Factory</FONT></A><BR>
+- <A HREF="http://www.davecentral.com/"><FONT COLOR="#000000">DaveCentral</FONT></A><BR>
+- <A HREF="http://www.freecode.com/"><FONT COLOR="#000000">FreeCode</FONT></A><BR>
+- <A HREF="http://www.InternetTrafficReport.com/"><FONT COLOR="#000000">Internet Traffic Report</FONT></A><BR>
+- <A HREF="http://www.ITManagersJournal.com/"><FONT COLOR="#000000">IT Manager's Journal</FONT></A><BR>
+- <A HREF="http://www.mediabuilder.com/"><FONT COLOR="#000000">MediaBuilder</FONT></A><BR>
+- <A HREF="http://slashdot.org/"><FONT COLOR="#000000">Slashdot</FONT></A><BR>
+- <A HREF="http://www.slaughterhouse.com/"><FONT COLOR="#000000">Slaughterhouse</FONT></A><BR>
+- <A HREF="http://www.techmailings.com/"><FONT COLOR="#000000">TechMailings</FONT></A><BR>
+- <A HREF="http://www.techsightings.com/"><FONT COLOR="#000000">TechSightings</FONT></A><BR>
+<BR><CENTER><B>E-Commerce</B></CENTER><P>
+- <A HREF="http://www.thinkgeek.com"><FONT COLOR="#000000">ThinkGeek (Stuff for smart masses)</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">supported sites</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="http://www.userfriendly.org"><FONT COLOR="#000000">Userfriendly.org</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com"><FONT COLOR="#000000">SecurityFocus</FONT></A><BR>
+- <A HREF="http://copyleft.net"><FONT COLOR="#000000">copyleft</FONT></A><BR>
+- <A HREF="http://filewatcher.org"><FONT COLOR="#000000">Filewatcher</FONT></A><BR>
+- <A HREF="http://www.linux.com"><FONT COLOR="#000000">Linux.com</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org"><FONT COLOR="#000000">LinuxTelephony</FONT></A><BR>
+- <A HREF="http://www.linuxtoday.com"><FONT COLOR="#000000">LinuxToday</FONT></A><BR>
+- <A HREF="http://openprojects.nu/services/irc.html"><FONT COLOR="#000000">Openprojects</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com"><FONT COLOR="#000000">32bitsonline</FONT></A><BR>
+- <A HREF="http://www.gnu.org"><FONT COLOR="#000000">The GNU Project</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="/news/2000/01/29/"><font color="#000000">saturday</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="/news/2000/01/29/949208399.html"><FONT COLOR="#000000">We should get this out of the door now</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949208340.html"><FONT COLOR="#000000">Is Linux for Crazies?</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949188564.html"><FONT COLOR="#000000">RabbIT 2.0.2</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949187896.html"><FONT COLOR="#000000">nmpg 1.1.3</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949187471.html"><FONT COLOR="#000000">mod_dtcl 0.7.3</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949187233.html"><FONT COLOR="#000000">CoreLinux++ 0.4.6</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949165962.html"><FONT COLOR="#000000">scribe 0.2</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949165472.html"><FONT COLOR="#000000">E theme updater 0.1</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949165416.html"><FONT COLOR="#000000">Powertweak-Linux 0.1.7</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164956.html"><FONT COLOR="#000000">Pexeso Beta</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164896.html"><FONT COLOR="#000000">XZX 2.9.2</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164869.html"><FONT COLOR="#000000">DistroLib 0.4</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164843.html"><FONT COLOR="#000000">ToutDoux 1.1.7</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164772.html"><FONT COLOR="#000000">goMP 1.0.3</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164633.html"><FONT COLOR="#000000">APSEND 1.40</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164529.html"><FONT COLOR="#000000">ecasound 1.6.12r10</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164394.html"><FONT COLOR="#000000">SCEZ 20000129</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164350.html"><FONT COLOR="#000000">Comicq 0.2.0</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949164259.html"><FONT COLOR="#000000">senv 0.2</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949161354.html"><FONT COLOR="#000000">XZX 2.9.2</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949161036.html"><FONT COLOR="#000000">log4j 0.7.5</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949156343.html"><FONT COLOR="#000000">SQN Linux 1.6</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949156277.html"><FONT COLOR="#000000">Limo 0.3.2</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949156237.html"><FONT COLOR="#000000">Fusion GS 1.3</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949145887.html"><FONT COLOR="#000000">MMR 1.5.4</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949142835.html"><FONT COLOR="#000000">KUPS 0.3.4</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949142815.html"><FONT COLOR="#000000">3DSE patch for XMMS 4</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949139763.html"><FONT COLOR="#000000">Linux 2.3.41</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949139751.html"><FONT COLOR="#000000">Free Code for Linux S/390</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135979.html"><FONT COLOR="#000000">CircleMUD 3.0 beta patchlevel 17</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135938.html"><FONT COLOR="#000000">NiL Isn't Liero 000128</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135913.html"><FONT COLOR="#000000">OpenSSH Unix Port 1.2.2</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135889.html"><FONT COLOR="#000000">KBoxes! 1.3</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135867.html"><FONT COLOR="#000000">phpLanParty 0.23</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135509.html"><FONT COLOR="#000000">DGen/SDL 1.20</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135482.html"><FONT COLOR="#000000">EdcomLib 1.0 alpha 5</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135309.html"><FONT COLOR="#000000">Etherboot 4.4.2</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135205.html"><FONT COLOR="#000000">BLADE 0.18.0</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135115.html"><FONT COLOR="#000000">Sapphire 0.13.7</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949135070.html"><FONT COLOR="#000000">ippl 1.99.3</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134977.html"><FONT COLOR="#000000">Saint 1.5patch1</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134943.html"><FONT COLOR="#000000">Zircon 1.18.232</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134927.html"><FONT COLOR="#000000">nmap 2.3BETA14</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134901.html"><FONT COLOR="#000000">xterm patch #124</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134817.html"><FONT COLOR="#000000">MyThreads-Links v0.5.2</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134633.html"><FONT COLOR="#000000">sudo 1.6.2p1</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134552.html"><FONT COLOR="#000000">MIT Photonic-Bands 0.10</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134246.html"><FONT COLOR="#000000">Launcher 0.86</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134179.html"><FONT COLOR="#000000">nano 0.8.1</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134103.html"><FONT COLOR="#000000">Gtk-- 1.1.8</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949134049.html"><FONT COLOR="#000000">tkchooser 0.65</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949133420.html"><FONT COLOR="#000000">XShipWars 1.33a</FONT></A><BR>
+- <A HREF="/news/2000/01/29/949133280.html"><FONT COLOR="#000000">Lamerpad 0.1</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="/news/2000/01/28/"><font color="#000000">friday</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="/news/2000/01/28/949117833.html"><FONT COLOR="#000000">fsv 0.9</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949117711.html"><FONT COLOR="#000000">popsneaker 0.1.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949114716.html"><FONT COLOR="#000000">eyep-updater.sh 1.0</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949113240.html"><FONT COLOR="#000000">W3Mail 0.5.0</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949113214.html"><FONT COLOR="#000000">The Urgent Decision 0.9.9</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949112269.html"><FONT COLOR="#000000">LTSP 1.02</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949112198.html"><FONT COLOR="#000000">Production BASIC 0.2.12</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949112123.html"><FONT COLOR="#000000">Postfix 19991231-pl03</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949109732.html"><FONT COLOR="#000000">Mp3 Commander 0.7</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949109324.html"><FONT COLOR="#000000">iManager 1.0.1b</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949108399.html"><FONT COLOR="#000000">Eterm 0.9</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949108308.html"><FONT COLOR="#000000">dqd_dirindex 1.0</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949108087.html"><FONT COLOR="#000000">Tidings 1.0.4</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949108026.html"><FONT COLOR="#000000">localscan 2.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949107922.html"><FONT COLOR="#000000">WMKeyboard 0.3</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949107834.html"><FONT COLOR="#000000">fcmp 1.0.2</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949107767.html"><FONT COLOR="#000000">Akkord 0.3.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949107649.html"><FONT COLOR="#000000">HiM 0.1.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949106305.html"><FONT COLOR="#000000">cdrecord 1.8</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949103400.html"><FONT COLOR="#000000">eMixer 0.05.5</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949103187.html"><FONT COLOR="#000000">FreeVSD 1.4.0</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949103096.html"><FONT COLOR="#000000">Common C++ Libraries 0.0</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949095155.html"><FONT COLOR="#000000">Moonshine 1.0beta2</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949095112.html"><FONT COLOR="#000000">swim 0.3.5</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949095009.html"><FONT COLOR="#000000">Xmame/xmess 0.36b15.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949094448.html"><FONT COLOR="#000000">pcmcia-cs 3.1.9</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949091509.html"><FONT COLOR="#000000">gPS 0.5.2</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949091415.html"><FONT COLOR="#000000">Snort 1.5.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949090436.html"><FONT COLOR="#000000">Pygmy Linux 0.7 beta</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949090237.html"><FONT COLOR="#000000">Intro to Bash Programming HOWTO 0.3</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949084379.html"><FONT COLOR="#000000">GNU Pth 1.3b2</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949084356.html"><FONT COLOR="#000000">Laonux 0.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949084304.html"><FONT COLOR="#000000">x-wvdial 0.12</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949084188.html"><FONT COLOR="#000000">Intro to Bash Programming HOWTO 0.3</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949084106.html"><FONT COLOR="#000000">Catalog 1.02</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949084062.html"><FONT COLOR="#000000">harvest 1.5.20-kj-0.9</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949068306.html"><FONT COLOR="#000000">wmseti 0.3.0a</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949057272.html"><FONT COLOR="#000000">RIG 1.02</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949057019.html"><FONT COLOR="#000000">FreeAddr 0.2</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949056939.html"><FONT COLOR="#000000">GtkAda 1.2.5</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949056664.html"><FONT COLOR="#000000">dot.conf 0.6.0</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949055099.html"><FONT COLOR="#000000">dep.pl 1.28.0</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949054980.html"><FONT COLOR="#000000">Prae's Scripts 1.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949044301.html"><FONT COLOR="#000000">Project Clock 0.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949044285.html"><FONT COLOR="#000000">Xtheater 0.2.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949040013.html"><FONT COLOR="#000000">i-no Chart 0.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949039945.html"><FONT COLOR="#000000">spliff 0.8.1</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949038953.html"><FONT COLOR="#000000">Regexx 0.95</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949038316.html"><FONT COLOR="#000000">RBook 0.5.0</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949036742.html"><FONT COLOR="#000000">RIG 1.01</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949036714.html"><FONT COLOR="#000000">wchat 1.2.0</FONT></A><BR>
+- <A HREF="/news/2000/01/28/949036428.html"><FONT COLOR="#000000">PCCS MySQLDatabase Admin Tool 1.2.2</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="/news/2000/01/27/"><font color="#000000">thursday</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="/news/2000/01/27/949033332.html"><FONT COLOR="#000000">CADUBI 1.1b1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949032987.html"><FONT COLOR="#000000">Angus' Chess Clock 0.8.1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949032555.html"><FONT COLOR="#000000">MP3 Report Generator 1.0.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949032518.html"><FONT COLOR="#000000">4DOM 0.9.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949032386.html"><FONT COLOR="#000000">4XSLT 0.8.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949031346.html"><FONT COLOR="#000000">OpenNaken 1.10</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949025747.html"><FONT COLOR="#000000">iManager 1.0b</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949025168.html"><FONT COLOR="#000000">QuakeForge 0.1.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949023271.html"><FONT COLOR="#000000">pylice 0.7.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949023250.html"><FONT COLOR="#000000">Solfege 0.6.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949023151.html"><FONT COLOR="#000000">xinetd 2.1.8.7p1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949022849.html"><FONT COLOR="#000000">jac 0.13</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949022803.html"><FONT COLOR="#000000">Xmms 1.0.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949022319.html"><FONT COLOR="#000000">KSrnd 0.97</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949021877.html"><FONT COLOR="#000000">getpg / UW-IMAP 0.54</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949021849.html"><FONT COLOR="#000000">getpg 0.53</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949021824.html"><FONT COLOR="#000000">setserial 2.17</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949021250.html"><FONT COLOR="#000000">Pan 0.7.3</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949021216.html"><FONT COLOR="#000000">jwhois 2.4.1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949021126.html"><FONT COLOR="#000000">Kmp3 1.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949020964.html"><FONT COLOR="#000000">xPine 0.0.12</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949019905.html"><FONT COLOR="#000000">Avenger's News System 2.1 Alpha</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949019709.html"><FONT COLOR="#000000">RIG 1.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949019321.html"><FONT COLOR="#000000">scroller 1.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949018347.html"><FONT COLOR="#000000">Perl EyeP Client 0.1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949017796.html"><FONT COLOR="#000000">sfront 0.54</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949017631.html"><FONT COLOR="#000000">XFrisk 1.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949016202.html"><FONT COLOR="#000000">Moffy 0.0.1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949015348.html"><FONT COLOR="#000000">Solid POP3 0.14</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949014200.html"><FONT COLOR="#000000">php3guest 1.5</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949013630.html"><FONT COLOR="#000000">crUD 01.27.2000</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949013380.html"><FONT COLOR="#000000">crUD 01.27.2000</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949012979.html"><FONT COLOR="#000000">Free Pascal Compiler 0.99.14</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949012771.html"><FONT COLOR="#000000">gtk-font-hack 0.2-gtk-1.2.6</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949009233.html"><FONT COLOR="#000000">Linux 2.2.15pre5</FONT></A><BR>
+- <A HREF="/news/2000/01/27/949005620.html"><FONT COLOR="#000000">krunseti 0.2.1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948996446.html"><FONT COLOR="#000000">CompuPic 5.0.1036</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948995905.html"><FONT COLOR="#000000">gfontview 0.3.3</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948995819.html"><FONT COLOR="#000000">authlocal 1.0.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948995600.html"><FONT COLOR="#000000">bigwig 1.1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948995501.html"><FONT COLOR="#000000">CAFire 0.0.11</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948995429.html"><FONT COLOR="#000000">ANVLOGIN 2.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948994944.html"><FONT COLOR="#000000">sawmill.el 1.9</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948994810.html"><FONT COLOR="#000000">Perlsh 20000127</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948994776.html"><FONT COLOR="#000000">sitescooper 2.1.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948994691.html"><FONT COLOR="#000000">MHDns 1.4</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948994419.html"><FONT COLOR="#000000">JChemPaint 0.5</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948994364.html"><FONT COLOR="#000000">Filesystems HOWTO 0.7.3</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948994343.html"><FONT COLOR="#000000">KSnes9x 1.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948993513.html"><FONT COLOR="#000000">Mozilla M13</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948993439.html"><FONT COLOR="#000000">edna 0.3</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948993409.html"><FONT COLOR="#000000">GMasqdialer 0.99.8</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948993341.html"><FONT COLOR="#000000">spliff 0.8</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948992808.html"><FONT COLOR="#000000">MultiSeti 0.3</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970667.html"><FONT COLOR="#000000">rude 0.50</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970605.html"><FONT COLOR="#000000">cgi-util++ 0.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970479.html"><FONT COLOR="#000000">Cricket 0.72</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970458.html"><FONT COLOR="#000000">nuni 0.04</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970379.html"><FONT COLOR="#000000">Ksetiwatch 0.3.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970358.html"><FONT COLOR="#000000">SiteMgrYAP 0.1.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970322.html"><FONT COLOR="#000000">phpLanParty 0.21</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970285.html"><FONT COLOR="#000000">Glitter Newsreader 0.1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970263.html"><FONT COLOR="#000000">Fastresolve 2.4</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970164.html"><FONT COLOR="#000000">ColdSync 1.1.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970080.html"><FONT COLOR="#000000">DDD 3.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948970032.html"><FONT COLOR="#000000">X Northern Captain 4.2.1</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948969919.html"><FONT COLOR="#000000">abcde 1.0.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948969659.html"><FONT COLOR="#000000">Gnapster 1.3.2</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948969551.html"><FONT COLOR="#000000">xmix 1.0 Alpha</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948969488.html"><FONT COLOR="#000000">gtktetcolor 0.3</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948969412.html"><FONT COLOR="#000000">muttzilla 0.40</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948969395.html"><FONT COLOR="#000000">muttzilla 0.40</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948969337.html"><FONT COLOR="#000000">asp2php 0.73.6</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948969217.html"><FONT COLOR="#000000">mod_ticket 1.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948969078.html"><FONT COLOR="#000000">MegaHAL for Eggdrop .01</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948968456.html"><FONT COLOR="#000000">Jetty 2.3.5</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948968386.html"><FONT COLOR="#000000">xlpotdb 1.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948968341.html"><FONT COLOR="#000000">Koala Complete MUD Server 0.1.1a</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948968255.html"><FONT COLOR="#000000">mcountd 0.4</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948967933.html"><FONT COLOR="#000000">cdbackup 0.5.0</FONT></A><BR>
+- <A HREF="/news/2000/01/27/948967908.html"><FONT COLOR="#000000">The Java SSH/Telnet Application/Applet 2.0 RC1</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://slashdot.org"><font color="#000000">slashdot</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/1534255"><FONT COLOR="#000000">Petition Apple for Linux QuickTime</FONT></A><BR>
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/1223249"><FONT COLOR="#000000">GNUstep 0.6.5 freeze</FONT></A><BR>
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/28/2324203"><FONT COLOR="#000000">YETI@Home</FONT></A><BR>
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/1024215"><FONT COLOR="#000000">Documents Unsealed in Microsoft/Caldera Case</FONT></A><BR>
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/0837235"><FONT COLOR="#000000">Who Bought Linux.Net?</FONT></A><BR>
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/24/1146250"><FONT COLOR="#000000">E-Mails from (Over?) The Edge</FONT></A><BR>
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/0834223"><FONT COLOR="#000000">Linux Kernel 2.3.41</FONT></A><BR>
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/28/2311232"><FONT COLOR="#000000">Congress Still Figuring Out E-Mail</FONT></A><BR>
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/22/1946244"><FONT COLOR="#000000">Sci Fi Literature 101?</FONT></A><BR>
+- <A HREF="http://slashdot.org/article.pl?sid=00/01/28/2318246"><FONT COLOR="#000000">Could Distributed.Net Help the Mars Polar Lander?</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://www.securityfocus.com"><font color="#000000">securityfocus</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.zdnet.com/zdnn/stories/news/0,4586,2429334,00.html?chkpt=zdnntop"><FONT COLOR="#000000">Win2000 security hole a 'major threat'</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.computerworld.com/home/print.nsf/all/000128e45a"><FONT COLOR="#000000">Visa acknowledges cracker break-ins</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.zdnet.com/sr/stories/column/0,4712,2429536,00.html"><FONT COLOR="#000000">What's Wrong With Microsoft Security?</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.zdnet.com/pcweek/stories/news/0,4153,2429334,00.html"><FONT COLOR="#000000">Microsoft posts first Win2K security patch</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com/level2/?go=tools&id=1018"><FONT COLOR="#000000">Libnids 1.12</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.theregister.co.uk/000127-000005.html"><FONT COLOR="#000000">New hack attack is greater threat than imagined</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.mercurycenter.com/svtech/news/indepth/docs/hacker012700.htm"><FONT COLOR="#000000">Student charged with hacking</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com/level2/?go=library&id=63"><FONT COLOR="#000000">Building and Managing Virtual Private Networks (book)</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com/level2/?go=library&id=111"><FONT COLOR="#000000">Threats, Vulnerabilities and Real-Worl Responses: The Foundations of the TruSecure Process</FONT></A><BR>
+- <A HREF="http://www.securityfocus.com/level2/?go=library&id=1701"><FONT COLOR="#000000">The Hundredth Window : Protecting Your Privacy and Security in the Age of the Internet (boo</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://www.bebits.com"><font color="#000000">bebits</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="http://www.bebits.com/app/706/"><FONT COLOR="#000000">Pe 3.0a3</FONT></A><BR>
+- <A HREF="http://www.bebits.com/app/757/"><FONT COLOR="#000000">Rarscript 1.5</FONT></A><BR>
+- <A HREF="http://www.bebits.com/app/736/"><FONT COLOR="#000000">CD Manager 0.66a beta</FONT></A><BR>
+- <A HREF="http://www.bebits.com/app/174/"><FONT COLOR="#000000">TraX 1.1</FONT></A><BR>
+- <A HREF="http://www.bebits.com/app/785/"><FONT COLOR="#000000">BeMath 1.2.2</FONT></A><BR>
+- <A HREF="http://www.bebits.com/app/784/"><FONT COLOR="#000000">simple blackjack 1</FONT></A><BR>
+- <A HREF="http://www.bebits.com/app/758/"><FONT COLOR="#000000">HtmlTree 0.5.3</FONT></A><BR>
+- <A HREF="http://www.bebits.com/app/783/"><FONT COLOR="#000000">Yacp 0.1</FONT></A><BR>
+- <A HREF="http://www.bebits.com/app/222/"><FONT COLOR="#000000">TicTacToe 1.5</FONT></A><BR>
+- <A HREF="http://www.bebits.com/app/706/"><FONT COLOR="#000000">Pe 3.0a2</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://linuxtoday.com"><font color="#000000">linuxtoday</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="http://linuxtoday.com/story.php3?sn=15878"><FONT COLOR="#000000">Linux Journal: KDE--The Next Generation</FONT></A><BR>
+- <A HREF="http://linuxtoday.com/story.php3?sn=15876"><FONT COLOR="#000000">Kernel Cousin gimp-devel #11 Is Out</FONT></A><BR>
+- <A HREF="http://linuxtoday.com/story.php3?sn=15875"><FONT COLOR="#000000">Infoworld: Corel Linux OS ideal for the desktop</FONT></A><BR>
+- <A HREF="http://linuxtoday.com/story.php3?sn=15874"><FONT COLOR="#000000">Technology Evaluation: IBM Jumps on the Linux Bandwagon with Both Feet, Sort Of</FONT></A><BR>
+- <A HREF="http://linuxtoday.com/story.php3?sn=15873"><FONT COLOR="#000000">Tobias Hövekamp: European Union acknowledges</FONT></A><BR>
+- <A HREF=""><FONT COLOR="#000000">&</FONT></A><BR>
+- <A HREF=""><FONT COLOR="#000000">#34;Open Source Software</FONT></A><BR>
+- <A HREF=""><FONT COLOR="#000000">&</FONT></A><BR>
+- <A HREF=""><FONT COLOR="#000000">#34;</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://www.linuxtelephony.org"><font color="#000000">linuxtelephony</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=208&r=0"><FONT COLOR="#000000">Traverse Technologies releases NETspider-U in US</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=207&r=0"><FONT COLOR="#000000">Quicknet releases new GPL'd Linux Drivers!</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=206&r=0"><FONT COLOR="#000000">Natural Microsystems Delivers Carrier-Class Linux</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=205&r=0"><FONT COLOR="#000000">Quicknet is hiring programmers of all kinds!</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=204&r=0"><FONT COLOR="#000000">Babylon MLPPP Software Released under GPL</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=202&r=0"><FONT COLOR="#000000">Linux Telephony Server Project?</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=203&r=0"><FONT COLOR="#000000">Vovida Networks to Hire Telephony Software Engineers</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=200&r=0"><FONT COLOR="#000000">SPIRO-Linux Introduces Web-Enabled Phone Administration</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=199&r=0"><FONT COLOR="#000000">LinuxTelephony sponsors area at LinuxFest 2000</FONT></A><BR>
+- <A HREF="http://www.linuxtelephony.org/article.cgi?i=198&r=0"><FONT COLOR="#000000">GSM-Mobile Switching Center (MSC) with Linux-PC</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD>
+<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3">
+<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://www.32bitsonline.com"><font color="#000000">32bitsonline</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial">
+- <A HREF="http://www.32bitsonline.com/article.php3?file=issues/200001/homeworld&page=1
+"><FONT COLOR="#000000">Game: Homeworld</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001271a&page=1
+"><FONT COLOR="#000000">DVD Lawsuit Spreads Its Own 'Trade Secrets'</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001272&page=1
+"><FONT COLOR="#000000">Register.com Adds 'One-step' Domain Registration</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com/article.php3?file=issues/200001/webevent&page=1
+"><FONT COLOR="#000000">WebEvent: Keeping you organized</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001273a&page=1
+"><FONT COLOR="#000000">Y2K Officers Defend $100 Bil Investment</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com/article.php3?file=issues/200001/jan2000_john_berger&page=1
+"><FONT COLOR="#000000">DON'T BE FOOLED</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001274&page=1
+"><FONT COLOR="#000000">Microsoft Scorns Think-Tank's Breakup Idea</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001275a&page=1
+"><FONT COLOR="#000000">Yahoo Accused Of Stalking Internet Users</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001276a&page=1
+"><FONT COLOR="#000000">eToys.com Settles Spat With Swiss Artist Group</FONT></A><BR>
+- <A HREF="http://www.32bitsonline.com/
+"><FONT COLOR="#000000">[more articles/news]</FONT></A><BR>
+&nbsp;</FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P>
+<BR><BR></FONT>
+</TD></TR></TABLE>
+<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0">
+<TR BGCOLOR="#000000"><TD><IMG SRC="image4" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
+</CENTER>
+<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="100%" BORDER="0"><TR>
+<TD VALIGN="top" ALIGN="center"><FONT FACE="Lucida,Verdana,Helvetica,Arial"><SMALL>copyright © 1997-2000 <A HREF="http://andover.net">Andover.Net</A> -
+icons courtesy of <A HREF="mailto:tigert@gimp.org">tigert@gimp.org</A> -
+code revision <A HREF="http://freshmeat.net/ChangeLog">20000101</A> -
+our <A HREF="http://www.andover.net/privacy.html">privacy policy</A></SMALL></FONT></TD>
+</TR></TABLE>
+</BODY>
+</HTML>
+
+
diff --git a/ext/tk/sample/tkextlib/tkHTML/ss.rb b/ext/tk/sample/tkextlib/tkHTML/ss.rb
new file mode 100644
index 0000000000..1c13d7ac34
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkHTML/ss.rb
@@ -0,0 +1,436 @@
+#!/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'
+
+file = ARGV[0]
+
+class TkHTML_File_Viewer
+ include TkComm
+
+# These are images to use with the actual image specified in a
+# "<img>" 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
+
+ def initialize(file = nil)
+ @root = TkRoot.new(:title=>'HTML File Viewer', :iconname=>'HV')
+ @fswin = nil
+
+ @html = nil
+ @html_fs = nil
+
+ @hotkey = {}
+
+ @applet_arg = TkVarAccess.new_hash('AppletArg')
+
+ @images = {}
+ @old_imgs = {}
+ @big_imgs = {}
+
+ @last_dir = Dir.pwd
+
+ @last_file = ''
+
+ @key_block = false
+
+ Tk::HTML_Widget::ClippingWindow.bind('1',
+ proc{|w, ksym| key_press(w, ksym)},
+ '%W Down')
+ Tk::HTML_Widget::ClippingWindow.bind('3',
+ proc{|w, ksym| key_press(w, ksym)},
+ '%W Up')
+ Tk::HTML_Widget::ClippingWindow.bind('2',
+ proc{|w, ksym| key_press(w, ksym)},
+ '%W Down')
+
+ Tk::HTML_Widget::ClippingWindow.bind('KeyPress',
+ proc{|w, ksym| key_press(w, ksym)},
+ '%W %K')
+
+ ############################################
+ #
+ # Build the half-size view of the page
+ #
+ menu_spec = [
+ [['File', 0],
+ ['Open', proc{sel_load()}, 0],
+ ['Full Screen', proc{fullscreen()}, 0],
+ ['Refresh', proc{refresh()}, 0],
+ '---',
+ ['Exit', proc{exit}, 1]]
+ ]
+
+ mbar = @root.add_menubar(menu_spec)
+
+ @html = Tk::HTML_Widget.new(:width=>512, :height=>384,
+ :padx=>5, :pady=>9,
+ :formcommand=>proc{|*args| form_cmd(*args)},
+ :imagecommand=>proc{|*args|
+ image_cmd(1, *args)
+ },
+ :scriptcommand=>proc{|*args|
+ script_cmd(*args)
+ },
+ :appletcommand=>proc{|*args|
+ applet_cmd(*args)
+ },
+ :hyperlinkcommand=>proc{|*args|
+ hyper_cmd(*args)
+ },
+ :fontcommand=>proc{|*args|
+ pick_font(*args)
+ },
+ :appletcommand=>proc{|*args|
+ run_applet('small', *args)
+ },
+ :bg=>'white', :tablerelief=>:raised)
+
+ @html.token_handler('meta', proc{|*args| meta(@html, *args)})
+
+ vscr = @html.yscrollbar(TkScrollbar.new)
+ hscr = @html.xscrollbar(TkScrollbar.new)
+
+ Tk.grid(@html, vscr, :sticky=>:news)
+ Tk.grid(hscr, :sticky=>:ew)
+ @root.grid_columnconfigure(0, :weight=>1)
+ @root.grid_columnconfigure(1, :weight=>0)
+ @root.grid_rowconfigure(0, :weight=>1)
+ @root.grid_rowconfigure(1, :weight=>0)
+
+ ############################################
+
+ @html.clipwin.focus
+
+ # If an arguent was specified, read it into the HTML widget.
+ #
+ Tk.update
+ if file && file != ""
+ load_file(file)
+ end
+ end
+
+ #
+ # A font chooser routine.
+ #
+ # html[:fontcommand] = pick_font
+ def pick_font(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(' ')
+ end
+
+ # This routine is called to pick fonts for the fullscreen view.
+ #
+ def pick_font_fs(size, attrs)
+ baseFontSize = 24
+
+ # 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(' ')
+ end
+
+ #
+ #
+ def hyper_cmd(*args)
+ puts "HyperlinkCommand: #{args.inspect}"
+ end
+
+ # This routine is called to run an applet
+ #
+ def run_applet(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
+ end
+
+ #
+ #
+ def form_cmd(n, cmd, *args)
+ # p [n, cmd, *args]
+ end
+
+ #
+ #
+ def move_big_image(b)
+ return unless @big_imgs.key?(b)
+ b.copy(@big_imgs[b])
+ @big_imgs[b].delete
+ @big_imgs.delete(b)
+ end
+
+ def image_cmd(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(b) })
+ end
+
+ @images[fn] = img
+
+ img
+ end
+
+ #
+ # This routine is called for every <SCRIPT> markup
+ #
+ def script_cmd(*args)
+ # puts "ScriptCmd: #{args.inspect}"
+ end
+
+ # This routine is called for every <APPLET> markup
+ #
+ def applet_cmd(w, arglist)
+ # puts "AppletCmd: w=#{w} arglist=#{arglist}"
+ #TkLabel.new(w, :text=>"The Applet #{w}", :bd=>2, :relief=>raised)
+ end
+
+ # This binding fires when there is a click on a hyperlink
+ #
+ def href_binding(w, x, y)
+ lst = w.href(x, y)
+ unless lst.empty?
+ process_url(lst)
+ end
+ end
+
+ #
+ #
+ def sel_load
+ filetypes = [
+ ['Html Files', ['.html', '.htm']],
+ ['All Files', '*']
+ ]
+
+ f = Tk.getOpenFile(:initialdir=>@last_dir, :filetypes=>filetypes)
+ if f != ''
+ load_file(f)
+ @last_dir = File.dirname(f)
+ end
+ end
+
+ # Clear the screen.
+ #
+ def clear_screen
+ if @html_fs && @html_fs.exist?
+ w = @html_fs
+ else
+ w = @html
+ end
+ w.clear
+ @old_imgs.clear
+ @big_imgs.clear
+ @hotkey.clear
+ @images.each{|k, v| @old_imgs[k] = v }
+ @images.clear
+ end
+
+ # Read a file
+ #
+ def read_file(name)
+ begin
+ fp = open(name, 'r')
+ ret = fp.read(File.size(name))
+ rescue
+ ret = nil
+ fp = nil
+ Tk.messageBox(:icon=>'error', :message=>"fail to open '#{name}'",
+ :type=>:ok)
+ ensure
+ fp.close if fp
+ end
+ ret
+ end
+
+ # Process the given URL
+ #
+ def process_url(url)
+ case url[0]
+ when /^file:/
+ load_file(url[0][5..-1])
+ when /^exec:/
+ Tk.ip_eval(url[0][5..-1].tr('\\', ' '))
+ else
+ load_file(url[0])
+ end
+ end
+
+ # Load a file into the HTML widget
+ #
+ def load_file(name)
+ return unless (doc = read_file(name))
+ clear_screen()
+ @last_file = name
+ if @html_fs && @html_fs.exist?
+ w = @html_fs
+ else
+ w = @html
+ end
+ w.configure(:base=>name)
+ w.parse(doc)
+ w.configure(:cursor=>'top_left_arrow')
+ @old_imgs.clear
+ end
+
+ # Refresh the current file.
+ #
+ def refresh(*args)
+ load_file(@last_file) if @last_file
+ end
+
+ # This routine is called whenever a "<meta>" markup is seen.
+ #
+ def meta(w, tag, alist)
+ v = Hash[*simplelist(alist)]
+
+ if v.key?('key') && v.key?('href')
+ @hotkey[v['key']] = w.resolve(v['href'])
+ end
+
+ if v.key?('next')
+ @hotkey['Down'] =v['next']
+ end
+
+ if v.key?('prev')
+ @hotkey['Up'] =v['prev']
+ end
+
+ if v.key?('other')
+ @hotkey['o'] =v['other']
+ end
+ end
+
+ # Go from full-screen mode back to window mode.
+ #
+ def fullscreen_off
+ @fswin.destroy
+ @root.deiconify
+ Tk.update
+ @root.raise
+ @html.clipwin.focus
+ clear_screen()
+ @old_imgs.clear
+ refresh()
+ end
+
+ # Go from window mode to full-screen mode.
+ #
+ def fullscreen
+ if @fswin && @fswin.exist?
+ @fswin.deiconify
+ Tk.update
+ @fswin.raise
+ return
+ end
+
+ width = @root.winfo_screenwidth
+ height = @root.winfo_screenheight
+ @fswin = TkToplevel.new(:overrideredirect=>true,
+ :geometry=>"#{width}x#{height}+0+0")
+
+ @html_fs = Tk::HTML_Widget.new(@fswin, :padx=>5, :pady=>9,
+ :formcommand=>proc{|*args|
+ form_cmd(*args)
+ },
+ :imagecommand=>proc{|*args|
+ image_cmd(0, *args)
+ },
+ :scriptcommand=>proc{|*args|
+ script_cmd(*args)
+ },
+ :appletcommand=>proc{|*args|
+ applet_cmd(*args)
+ },
+ :hyperlinkcommand=>proc{|*args|
+ hyper_cmd(*args)
+ },
+ :appletcommand=>proc{|*args|
+ run_applet('big', *args)
+ },
+ :fontcommand=>proc{|*args|
+ pick_font_fs(*args)
+ },
+ :bg=>'white', :tablerelief=>:raised,
+ :cursor=>:tcross) {
+ pack(:fill=>:both, :expand=>true)
+ token_handler('meta', proc{|*args| meta(self, *args)})
+ }
+
+ clear_screen()
+ @old_imgs.clear
+ refresh()
+ Tk.update
+ @html_fs.clipwin.focus
+ end
+
+ #
+ #
+ def key_press(w, keysym)
+ return if @key_block
+ @key_block = true
+ Tk.after(250, proc{@key_block = false})
+
+ if @hotkey.key?(keysym)
+ process_url(@hotkey[keysym])
+ end
+ case keysym
+ when 'Escape'
+ if @fswin && @fswin.exist?
+ fullscreen_off()
+ else
+ fullscreen()
+ end
+ end
+ end
+end
+############################################
+
+TkHTML_File_Viewer.new(file)
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tkimg/demo.rb b/ext/tk/sample/tkextlib/tkimg/demo.rb
new file mode 100644
index 0000000000..a0c4d1b64f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkimg/demo.rb
@@ -0,0 +1,1478 @@
+#!/usr/bin/env ruby
+#
+# Tk::Img demo
+#
+# -- This script is based on demo.tcl of Tcl/Tk's 'Img' extention.
+# Image data in this script is those of demo.tcl.
+# Please read 'license_terms_of_Img_extension' file.
+#
+require 'tk'
+require 'tkextlib/tkimg'
+
+#
+# Make the Image format available.
+#
+class TkImg_demo
+ def initialize
+ img_version = Tk::Img.package_version
+
+ @typeFrame = Hash.new
+ @imgPriv = Hash.new
+
+ root = TkRoot.new(:title=>'Tests for available image formats')
+
+ root.winfo_children.each{|w| w.destroy}
+ TkImage.names{|img| img.delete}
+
+ f = TkFrame.new
+ TkButton.new(f, :text=>'Dismiss', :command=>proc{exit}).pack(:side=>:left)
+ f.pack(:side=>:top, :expand=>:y, :fill=>:both)
+
+ TkMessage.new(:aspect=>900, :text=>format('This page shows the available image formats of the Img extension (Img version %s, using Tcl/Tk %s)', img_version, Tk::TK_PATCHLEVEL)).pack(:side=>:top, :expand=>:y, :fill=>:both)
+ end
+
+##############################
+
+ def update_animated_gif(w, method, num)
+ return unless @imgPriv[w]
+
+ if @imgPriv[w][:args]
+ im = TkPhotoImage.new
+ im.copy(@imgPriv[w][num])
+ num += 1
+ begin
+ im.configure(@imgPriv[w][:args].merge(:format=>[:gif, {:index=>num}]))
+ im.configure(:data=>'', :file=>'') #free storage
+ @imgPriv[w][num] = im
+ rescue
+ @imgPriv[w].delete(:args)
+ if num > 1
+ num = 0
+ im = @imgPriv[w][num]
+ else
+ # this is not an animated GIF; just stop
+ @imgPriv[w].delete(0)
+ return
+ end
+ end
+ else
+ num += 1
+ num = 0 unless @imgPriv[w][num]
+ im = @imgPriv[w][num]
+ end
+ begin
+ w.__send__(method, im)
+ Tk.update_idletasks
+ Tk.after(20, proc{update_animated_gif(w, method, num)})
+ rescue
+ @imgPriv[w].delete(:args)
+ @imgPriv[w].each{|im|
+ @im.delete
+ @imgPriv.delete(im)
+ }
+ end
+ end
+
+ def show_animated_gif(keys)
+ w = TkLabel.new
+ begin
+ im = TkPhotoImage.new(keys.merge(:format=>[:gif, {:index=>0}]))
+ im.configure(:data=>'', :file=>'', :format=>'') #free storage
+ w.image(im)
+ @imgPriv[w] ||= Hash.new
+ @imgPriv[w][0] = im
+ @imgPriv[w][:args] = keys
+ Tk.update_idletasks
+ Tk.after(20, proc{update_animated_gif(w, :image, 0)})
+ rescue => e
+ w.configure(:text=>"error displaying animated gif:\n#{e.message}",
+ :image=>'', :relief=>:ridge)
+ end
+ w.pack
+ end
+
+ def show_image(fmt, type, data)
+ fmt = fmt.to_s.capitalize
+ unless @typeFrame[fmt]
+ @typeFrame[fmt] = TkFrame.new.pack(:side=>:top, :expand=>true, :fill=>:x)
+ TkLabel.new(@typeFrame[fmt], :text=>"#{fmt} : ").pack(:side=>:left)
+ end
+ begin
+ f = TkFrame.new(@typeFrame[fmt],
+ :borderwidth=>2, :relief=>:ridge).pack(:side=>:left)
+ im = TkPhotoImage.new(:data=>data)
+ im['data'] = ''
+ TkLabel.new(f, :image=>im).pack
+ TkLabel.new(f, :text=>type, :borderwidth=>0, :pady=>0, :padx=>2,
+ :font=>'Helvetica 8').pack
+ rescue => e
+ TkMessage.new(f, :text=>"error displaying #{type} image: #{e.message}",
+ :aspect=>250).pack
+ end
+ Tk.update
+ end
+
+end
+
+##############
+
+demo = TkImg_demo.new
+
+##############
+
+demo.show_animated_gif(:data=><<'ENDofIMG')
+R0lGODlhYgIEAIIAAQAAACQAJEkASW0AbZIAkrYAttsA2/8A/yH/C05FVFNDQVBFMi4wAwEA
+AAAh+QQABgD/ACwAAAAAYgIEAAIDuUg63CMwwiCCvQAHwLv/YCiOZGmeaKqubOu+pZXNV03d
+kuAwysLoucjNlpFtYMikcslsOp+ijbRow1EiD12jtyA4INnJZGg8HmfQtHrNbrPP6KqlEgRq
+B17vzi6ukKVmHXBuhIWGh4RTcXJ0QQ8OeVx6XzlWVTRoiJqbnJ0tGmUXdDhgd1uTP2FCo5dT
+g56wsbKaoYBzVlimPJJ7QX9EirPCw8RttTZ1ul29Er81mMXR0tMvxzXJO1wAACH5BAAGAP8A
+LAAAAABiAgQAAgPdCLrc/jDKSau9OOuNAwjgB46kEJjnKazr0A5wTBDDbBc4buz74f/AoHBI
+LBqPSCGPh7M5abQYTOBysVYprAlFCo0+YI9CzCmbz+i0es1uu9/wOFrsqYtE3S73yq9SpTBP
+BDk5PEmHiImKRQYHTISDNjWTMX9UfFuZIFwkY3RhcqGio6SlpqeoqRt2dXmuWyqZV1Z/UjM1
+ToQFS46Lvr/AQUu6BYK4gJe0V7Eprl+sXqrS09TV1tfYbKxhziqxmFOAgYKDOrs9wenqSY07
+uznklFKXmCzN3aB22fv81AAAIfkEAAYA/wAspgAAABgBBAACA+YIEQrNS61Jg1hX6C2GHiBI
+DERpFkShFkZrHHAsz3Rt06/Lrqk5jqFQ58PheI5B0s+HWrFch9dtSp26dDyULwnqeIoay+Qi
+rkAcZ4YDrVY/IOaxGGz0IkPLknN3rfr/MToGTilaJSRcR3RgikF5JyuDfYCUVFeDKj0mSkle
+Q4sYcXFvaA1rDxIScKIZYUVfiUA+PU6Tlbc4US07PJs/nYqLQ4kieZkqki24yzJXe5qziEHD
+dHNloqqpbqfcbquiGK2MH0mzkJG2zLfOhObSQsHC1OVKTLVQUurrWL1biZ9grIFLs2YbNwAh
++QQABgD/ACyHAAAAVwEEAAID/ggQy94uyCloFTgPsYf/AyGOYmGaRnoYR+u+cCzPcZqeJyl6
+xMdhm4zwUgkUJ8iFkqFgKptQCQRJMRqJwqAPtCMVCDhDwcaimc9mslhs0vXeoJ9caL1Q748n
+tMl89PFURURXQx4cH11eYChjKmiPkC5kOGCVIyCYWkN2VoB8fXtOS34RgJybGkCZbosnZJGw
+aCw3bF9tXSFxhqhXnb5JSUt6CsKlxneDqHIdqyEjOI0qZbHUMGq1bs6Yh3NDdb93U1Ki41Hi
+poSEqYZcuYphr9XykjbQrLnbHbwYEkd4xQ2GERvoZxQ6LIUOrWLlKtq8h5Ps6ci0SxknQOVE
+Ddy4HvGPQVMIC1Hk4QZavIfUZq3J8YUEPl0WL3qaIIwjMQAh+QQABgD/ACxlAAAAmwEEAAID
+/ggRCr1qSSlWDVXorYfwQxgSxECSBVGsheEaB3zMdG3feF7DbsumJ5JJJPpwjhnLZMloPp4M
+h3RKrVqv2KxW2nRGmBQlBnP0dD7EYfDne8l08DjcbfgFhaW0cX8ciy9LD05RUREOhQ2GYEoa
+ZGQbIGlDJmsqPy9ymZo0PD11Kyp3anogfX5igamGh1utrq+uhFBQYBm2j5CSIncnLHWYm8Fx
+bj52QZOSSBeNp2BfEIVeU4PUi0mOSJFoaXcpvnTC4TnExiejRdrK2IsSgrKIsPHyr4OJ7GHL
+thxmkSN4vZdauIghriCnF2yAmBOCzoiZPkkAOav3JEs0d+z0ZdPFMgvFJWAGCxL7pPBYHiJ8
+TElcNGuey5cwW97Dp6yDpBK82LgJaXAki47IGqq7xm4WPCoAACH5BAAGAP8ALEYAAADZAQQA
+AgP+GKC7yiHKGYSo1Wo9xPgfMYhEWRZoYaiGcbxwLM90Tbf4ihKFSYqgjnBDjFwuGMoD0Fgy
+n9CodEqtWq/YrHa7hTgaTSXySCZ6PMFQyJdC5Vy2uFz+VqV8pFH6czYfM0pKYF4MYE0OD4ET
+Y4BEfHt6eDt2OAdwc5iZLzhtO3iQIBYdGhgWpYoTYUxOXK2ur7CxrV5fqBR/GWZDaT9sPG4s
+l5rDNi4tdpOfQGlno6SmSEkUiISDT4mJtYpkubq7Qb0mbSuVwsTnmzltPJ96oY9+uNGKiLWy
+9/j5+l3YqrZl3UT12YPnxLg36BLCULdOmbt38bjNC3TISSEqSyRQE1M8yo8QXiMk/XJTSaFC
+hg19gIp4auI0Vhf3yZxJUx8EbP/K6EIDLqSvgy1MJlSno0cPlcsg+gEkTZBGVlMAACH5BAAG
+AP8ALCYAAAAXAgQAAgP+CAHaHQtKKGioV+itRx/gQIBESRTnWRRGexhHLM90bd9127Jrao7A
+kMfDKVommMnisYwwHM+odEqtWq/YrHbL7Xq/YIaTCVEoj5YiZ8gmiX6l1UrnguHu+DvdIEeh
+4EJsAkRqGBoXZxJmEU2NYo9mYoyJFRwZG22Bbz99LHR5oKEydDxyPiUimiCDrIeViK9ni4wP
+kGG3uLm6u7y9tmO1iRKuGZeYmUDJJn18OqLPoKQ9fyZuga2Er4fCioqRTVFlZWTcxJVFQx9u
+yioqPM7Q8TbSptRBI0KthRvF3OLitnwJHEiwoMErk5jMOmMIVqFMIdjFmeMJhh15GF/o6HRK
+qhq+VayyWYLlr5GTcVjAlTS0DyIJOBPlfMqI0WKzeoA+htCnph+3SFAOCh1KtGivk/+EnWs5
+KJDEFMzg0ZS3BydMVSL5aStJ6woAIfkEAAYA/wAsBwAAAFUCBAACA/4ICqEd8MUJRQ0i65GH
+F55HEMM4FkShFgZrHHAsz3Rt10aer6s5lqEQqKPRYI6WI+XBYDYYi+diSq1ar9isdsvter/g
+sHhMLkebUEhziUkai8ROMOQ78Vy6m37Pf+1aPXUlJEJCcG9ubGpOaWlPUowSSxYZbW1FHCBz
+g3V3eC98oaIwfi07KCkmQIQfH4eUsBdLa4tnUma4ubq7vL2+v1mPUGiKE7GVh4V0Pz53pjmj
+0X06LD2oqqxBG4dKiRS0TrdTkcURlBWwmJqaIqsmqDw6oNL0NPKeddnaHJlwl0qKGgkTB6yg
+wYMIEyq8Qm5RsXOW4PCbGIREp3jy5tXbWE4KUCBsm4aI5HYuSUBJDoZZgQTu4aVkm5ZdVCFv
+o01SB/589AFkzshXAE8KXEi0qNGjSMlEajnpJcxN+exUy3OTIzUeUXvue4WsXC0mWAAAIfkE
+AAYA/wAsAAAAAGICBAACA/4YotIuA8JBKxkk60KKN6BxiEdpnmiqrmhoeF6naVXdRI/DBAq/
+8MAAQDgsEgHIpHLJbDqf0Kh0Sq1ar9isdsvterdEIW8IJAfPv0XOEalZZjJYwcWq2++i0Fwu
+m2HcbWs5PWoMgm01F4obci90d5CRJS5yHBw0GX8UEpw6D4RnY0FGYUVfp6ipqqusra6vXKVk
+pqFBhYM5gYkYcJWOIZLBdnovMH2YbjcSOLc+hA2GyoB/cBmWe8DC2ivExpdw05vMn4W1o2Wi
+sOrr7O3u7/BVoujz5mrQhxNuF7zWHTCPtgmcNALEHmPg+NnohOvHs3yILPRjBBAYiYHaXBRD
+6CtnmiBP5mqZGhmvpMmTKFOqbBJGTEgg+D5GlFjt2pyAGIVR4lNNU7JxnhwCACH5BAAGAP8A
+LAAAAABiAgQAAgPtWLZ7/jDKSaU5rOhCuu9DKA5CKJRnGgjB6rJt3AIxDdzBbet87//AoHBI
+LBqPyKRyyWw6n9CodOrL8ay5rFa2YsG8qRNJXAoRRB8CZ6NgYCrweJxhUNjd8rz+QWevPwMg
+ImUoYWEtX1wzNFg2jVSQkZKTlJWWl5iZTo+OW4qIMYZhJKQjgWlqbHQXe61wFwt2bQ2utROw
+sX6oZqYoY4YvLp81WY47msjJysvMzc7PxjPEw2DVKWOmvKceaxurtuB8GLl1Dazhtn0bqGdn
+vb/AXsPE0dD29/j5+vvLVtHzJ7qIKpSNXSpVtNCly1AAACH5BAAGAP8ALAAAAABiAgQAAgPV
+eLq8diYWUwqxJJOx9/iDEIpCaZpBmQZs6wYAC8QwPd94ru987//AoHBILBqPyKRyyWw6n9Ao
+Elaj0l4tlYC1PZVCoHBnnLFUJpF0Y81uOyCTc0Wj4YRBJO9qu8LKqjaAUoOEhYaHiImKi4yN
+TzUxN1STflxZXiZgInccdGZyaQ9uo24PoXFmdHacJCOYKXx8lZRXM5COuLm6u7y9vr+KtJSz
+e1perpwZnRqfaGqk0GunZxd0yh54mq8qxFaRwODh4uPk5eaEVVbdxpibm3fWZXLOotEAADs=
+ENDofIMG
+
+demo.show_image('bmp', '1-bit', <<'ENDofIMG')
+Qk3OAQAAAAAAAD4AAAAoAAAAIgAAADIAAAABAAEAAAAAAJABAABtCwAAbQsAAAIAAAACAAAA
+MzPMAMwzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAZmTKAAAAAABIRIwAAAAAAEZAigAAAAAAQECIAAAAAAAAAAgAAAAAAAAEAA
+AAAAAAABQAAAAAAAAAPAAAAAAAAAB+AAAAAAAAAC4AAAAAAAAALgAAAAAAAAAsAAAAAAAAAC
+wAAAAAAAAALgAAAAAAAABuAAAAAAAAAG4AAAAAAAAAbgAAAAAAAABuAAAAAAAAAG4AAAAAAA
+AAfgAAAAAAAAA+AAAAAAAAADcAAAAAAAAAPwAAAAAAAAA/AAAAAAAAAD+AAAAAAAAAP4AAAA
+AAAAA/gAAAAAAAAD4AAAAAAAAAHgAAAAAAAAAfAAAAAAAAAA+AAAAAAAAAB8AAAAAAAAADgA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ENDofIMG
+
+demo.show_image('bmp', '4-bit', <<'ENDofIMG')
+Qk1aBAAAAAAAAHIAAAAoAAAAIgAAADIAAAABAAQAAAAAAOgDAABtCwAAbQsAAA8AAAAPAAAA
+////AAD//wDMzP8AmZn/AGaZ/wAzM8wAmZnMAGaZzAAzZswAzMyZAJmZmQDMZjMAZjNmADMz
+ZgBmMzMABWMgAAAAAAAAAAAAAAAAAAAAAAAFVVVVVVVVVVVVVVVVVVVVUAAAAAVVVVVVVVVV
+VVVVVVVVVVVQAAAABVVVVVVVVVVVVVVVVVVVVVAAAAAFVVVVVVVVVVVVVVVVVVVVUAAAAAVV
+VVVVVVVVVVVVVVVVVVWAAAAABVVVVVVVVVVVVVVVVVVVVVAAAAAFVVBVU3VSVVNVB1UFBVVV
+UAAAAAVVUFU1VVNVVVUFVQBVVVVgAAAABVVQVVUFU1VVVQVVBVVVVTAAAAAIVVBVVVVTVXVV
+BVUFVVVVMAAAAAVVVVVVVVFVFVVVVQVVVVUgAAAABVVVVVVVVVUFVVVVVVVVVSAAAAAHVVVV
+VVVVW5tVVVVVVVVVAAAAAAZVVVVVVVW8u2VVVVVVVVUAAAAAA1VVVVVVW7W7tVVVVVVVVQAA
+AAADVVVVVVWCtbuzVVVVVVVVAAAAAANVVVVVVVW1vrJVVVVVVVUAAAAAAlVVVVVVWLW7UFVV
+VVVVVQAAAAACVVVVVVVatbtVVVVVVVVVAAAAAABVVVVVVVq3u8NVVVVVVVUAAAAAAFVVVVVV
+XrS74VVVVVVVVQAAAAAAVVVVVVWLtbuyVVVVVVVVAAAAAABVVVVVVUu1u7BVVVVVVVUAAAAA
+AFVVVVVVO7W7sFVVVVVVVQAAAAAAVVVVVVUbtbu6VVVVVVVVAAAAAABVVVVVVSu9u1VVVVVV
+VVUAAAAAAFVVVVVVJb67tVVVVVVVVQAAAAAAVVVVVVVVu6u7VVVVVVVVAAAAAABVVVVVVVW7
+u7slVVVVVVUAAAAAAFVVVVVVVbu7u1VVVVVVVQAAAAACVVVVVVVVu7u7wlRVVVVVAAAAAAJV
+VVVVVVW7u7uwV1VVVVUAAAAAA1VVVVVVVbu7u7BVhVVVVSAAAAADVVVVVYVVu7vFAFUVVVVV
+MAAAAAZVVVVVhVUbu7VVVRVXVVVgAAAAB1VVVVVVVVu7u1VVFVFVVVAAAAAFVVVVVVhVVLu7
+xVVVVVVVgAAAAAVVVVVVUVVVK7u1VVVVVVVQAAAACFVVVVhRVVVQq7VVVVVVVVAAAAAFVVVV
+VFV1VVUgBVVVVVVVUAAAAAVVVVVUVRVVVVVVVVVVVVVQAAAABVVVVViFUVVVVVVVVVVVVVAA
+AAAFVVVVVRVUFVVVVVVVVVVVUAAAAAVVVVVVVVVVVVVVVVVVVVVQAAAABVVVVVVVVVVVVVVV
+VVVVVVIAAAAFVVVVVVVVVVVVVVVVVVVVUQAAAAVVVVVVVVVVVVVVVTdVVVVWAAAAAAAhNnWF
+VVVVVVcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==}
+ENDofIMG
+
+if false
+demo.show_image('bmp', '4-bit-RLE', <<'ENDofIMG')
+Qk1sAwAAAAAAAHYAAAAoAAAAIgAAADIAAAABAAQAAgAAAPYCAAAAAAAAAAAAABAAAAAQAAAA
+////AMzM/wAA//8AmZn/AJmZzABmmcwAMzPMADNmzABmmf8AmZmZAMxmMwBmM2YAZjMzADMz
+ZgDMzJkAAAAAAAAGBkMQABwAAAACBh5mAmAAAAIGHmYCYAAAAgYeZgJgAAACBh5mAmAAAAIG
+HmYCcAAAAgYeZgJgAAAAIgZmYGZjVmFmY2YFZgYGZmZgAAAAACIGZmBmNmZjZmZmBmYAZmZm
+QAAAAAAiBmZgZmYGY2ZmZgZmBmZmZjAAAAAAIgdmYGZmZmNmVmYGZgZmZmYwAAAAAgYKZgAW
+YmYmZmZmBmZmZhAAAAACBg5mAgYOZgIQAAACBQxmAARq6g5mAgAAAAIEDGYABquqRgAMZgIA
+AAACAwpmAAhqpqqmDGYCAAAAAgMKZgAIcaaqowxmAgAAAAIDDGYABqasoQAMZgIAAAACAQpm
+AAhnpqpgDGYCAAAAAgEKZgAGaaaqAA5mAgAAAAIACmYACGmlqrMMZgIAAAACAApmAAhsqKrC
+DGYCAAAAAgAKZgAIeqaqoQxmAgAAAAIACmYACIqmqqAMZgIAAAACAApmAAg6pqqgDGYCAAAA
+AgAKZgAIKqaqqQxmAgAAAAIACmYABhqtqgAOZgIAAAACAApmAAgWrKqmDGYCAAAAAgAMZgAG
+qpqqAAxmAgAAAAIADGYACKqqqhYKZgIAAAACAAxmAAaqqqoADGYCAAAAAgEMZgAKqqqqsWgA
+CGYCAAAAAgEMZgAKqqqqoGUACGYCAAAAAgMMZgAUqqqqoGZ2ZmZmEAAAAgMIZgAYdmaqqrYA
+ZiZmZmYwAAACBAhmABh2ZiqqpmZmJmVmZkAAAAIFDGYAFGqqqmZmJmJmZmAAAAIGCGYADGdm
+aKqqtgpmAnAAAAIGCGYADGJmZhqqpgpmAmAAAAAWB2ZmZmdiZmZgmqYACmYCYAAAABYGZmZm
+aGZWZmYQBgAKZgJgAAAADgZmZmZoZiYAEmYCYAAAAA4GZmZmZ3ZiABJmAmAAAAIGCGYABiZo
+JgAQZgJgAAACBh5mAmAAAAIGHmYCYQAAAgYeZgJiAAACBhZmAAo1ZmZmZAAAAAAMAAASNFZ2
+CGYCZQwAAAAiAAAB
+ENDofIMG
+end
+
+demo.show_image('bmp', '8-bit', <<'ENDofIMG')
+Qk0CCAAAAAAAAPoAAAAoAAAAIgAAADIAAAABAAgAAAAAAAgHAABtCwAAbQsAADEAAAAxAAAA
+////AMz//wAA//8AzMz/AJnM/wAAzP8AmZn/AGaZ/wAAmf8AZmb/ADNm/wAzM/8A/8zMAMzM
+zACZmcwAZpnMAACZzABmZswAM2bMAABmzAAzM8wAADPMAAAAzAD/zJkAzMyZAMyZmQCZmZkA
+ZmaZAGYzmQAzM5kAzJlmAJlmZgBmZmYAZjNmADMzZgDMmTMAmWYzAJkzMwBmMzMAmWYAAJkz
+AAAAAN0A7u7uAN3d3QC7u7sAqqqqAIiIiAB3d3cAVVVVAAARDgYDKgAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAVFRUVFRUVFRUVFBQUFBQUFRUVFRUVFRUVFRUVFRUVFQAAAAAV
+FRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFQAAAAAVFRUVFRUVFRUVFRUVFRUVFRUV
+FRUVFRUVFRUVFRUVFAAAAAAVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFAAAAAAV
+FRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVEgAAAAAVFRUVFhUVFRYVFRUWFRUVERUV
+FhUVFRYVFhUVFRUVEQAAAAAUFRUWABEVFQYPFhUDERUWBhUVKg8VFAAUABQVFRUVEQAAAAAU
+FRUWABYVBhQWFRUGFBUWERUWABYVFgAAFRUVFRUVDgAAAAAUFRUVABUVFBEAFhUGFBUUFRUV
+ABUVFgARFRUVFRUVBgAAAAASFRUWABUVFRUVFRUGFBUPFhUWABYVFgAVFBUVFRUVBgAAAAAR
+FRUVFhUVFRUVFRUEFBUEFhUVFhUVFQAWFRUVFRUVAwAAAAARFRUVFRUVFRUVFRUVFRUrHRUV
+FRUVFRUVFRUVFRUVAwAAAAAPFRUVFRUVFRUVFRUVFCQYKBUVFRUVFRUVFRUVFRUVKgAAAAAO
+FRUVFRUVFRUVFRUUJyEeKA4VFRUVFRUVFRUVFRUVAAAAAAAGFRUVFRUVFRUVFRYeKB0kKCQU
+FRUVFRUVFRUVFRUVAAAAAAAGFRUVFRUVFRUVFRIDKBQnKCgGFRUVFRUVFRUVFRUVAAAAAAAG
+FRUVFRUVFRUVFRUVJxEnJigDFRUVFRUVFRUVFRUVAAAAAAADFRUVFRUVFRUVFRUSKBEnKAkq
+FRUVFRUVFRUVFRUVAAAAAAADFRUVFRUVFRUVFRUuJxEoKBEWFRUVFRUVFRUVFRUVAAAAAAAr
+FRUVFRUVFRUVFRYvKA8oKCEGFRUVFRUVFRUVFRUVAAAAAAAqFRUVFRUVFRUVFRQmKAcoKCYE
+FRUVFRUVFRUVFRUVAAAAAAAAFRUVFRUVFRUVFRIoJwkoKCgDFRUVFRUVFRUVFRUVAAAAAAAA
+FRUVFRUVFRUVFQcoJxEnKCgBFRUVFRUVFRUVFRUUAAAAAAAAFRUVFRUVFRUVFQYoKBQnKCgq
+FhUVFRUVFRUVFRUUAAAAAAAAFRUVFRUVFRUVFQQoKBQkKCgsFhUVFRUVFRUVFRUUAAAAAAAA
+FRUVFRUVFRUVFQMkKCIjKB0RFRUVFRUVFRUVFRUUAAAAAAAAFRUVFRUVFRUVFQMUKCYeKCgV
+FRUVFRUVFRUVFRUVAAAAAAAAFRUVFRUVFRUVFRUVKCgaKCgnFRUVFRUVFRUVFRUVAAAAAAAA
+FRUVFRUVFRUVFRUUKCgkKCgoAxYVFRUVFRUVFRUVAAAAAAArFRUVFRUVFRUVFRURKCgoKCgo
+ERQVFRUVFRUVFRUVAAAAAAADFRUVFRUVFRUVFRURKCgoKCgoIQMWCBUVFRUVFRUVAAAAAAAD
+FRUVFRUVFRUVFRURKCgoKCgoKAAWEBYVFRUVFRUVKgAAAAAGFRUVFRUVFRUVFRUUJygoKCgo
+KAAWFRMVFRUVFRUVAwAAAAAGFRUVFRUVFRUTFhUWHigoKCEUKgAWFgIVFRUVFRUVBgAAAAAO
+FRUVFRUVFRUTFRUVBCgoKCgUFRYVFgIWFRAWFRUVDgAAAAAPFRUVFRUVFRUVFRUVFR4oKCgo
+FRUVFQIVFQUVFRUVEQAAAAARFRUVFRUVFRUVExUVFQckKCgoIRUVFRYVFRUVFRUVEgAAAAAR
+FRUVFRUVFRUWAhYVFRYDJygoKB0VFRUVFRUVFRUVFAAAAAASFRUVFRUVFRMVBRUVFRUWKhko
+KBQVFRUVFRUVFRUVFQAAAAAUFRUVFRUVFQgWFRAVFRUVFgMAKxYVFRUVFRUVFRUVFQAAAAAU
+FRUVFRUVFQgWFQIWFRUVFRUWFhUVFRUVFRUVFRUVFQAAAAAUFRUVFRUVFRMTFRUFFhUVFRUV
+FRUVFRUVFRUVFRUVFQAAAAAVFRUVFRUVFRYFFhUIAhYVFRUVFRUVFRUVFRUVFRUVFQAAAAAV
+FRUVFRUVFRUVFRUVFhUVFRUVFRUVFRUVFRUVFRUVFQAAAAAVFRUVFRUVFRUVFRUVFRUVFRUV
+FRUVFRUVFRUVFRUVFQMAAAAVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFQQAAAAV
+FRUVFRUVFRUVFRUVFRUVFRUVFRUVFAYPEREUFBQVFQ4AAAAAACoDBAYODxESFBQVFRUVFRUV
+FQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
+ENDofIMG
+
+if false
+demo.show_image('bmp', '8-bit-RLE', <<'ENDofIMG')
+Qk22CAAAAAAAADYEAAAoAAAAIgAAADIAAAABAAgAAQAAAIAEAAAAAAAAAAAAAAABAAAAAQAA
+////AO7u7gDMzP8Amcz/AJmZ/wCZmcwAZpnMAGZmzAAzZswAMzPMAAAzzAAAAMwAAMz/AACZ
+/wAA//8AAGbMAACZzADd3d0AzJmZAJkzAACZZgAAMzOZAGaZ/wCZZjMAZjNmAMyZZgCZmZkA
+ZjMzADMzZgDMmTMAu7u7AMz//wBmZv8Ad3d3AIiIiADMzJkAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG
+AAcFBAIBHAAAAAEACgoGCRAKAQAAAAEAIAoBAAAAAQAfCgEJAQAAAAEAHwoBCQEAAAABAB8K
+AQgBAAAAAQAECgAWCwoKCgsKCgoLCgoKBwoKCwoKCgsKCwUKAQcBAAAAABwACQoKCwAHCgoE
+BgsKAgcKCwQKCgEGCgkACQAJBAoBBwEAAAAAGgAJCgoLAAsKBAkLCgoECQoLBwoLAAsKCwAA
+BgoBBQEAAAAAGgAJCgoKAAoKCQcACwoECQoJCgoKAAoKCwAHBgoBBAEAAAAABgAICgoLAAcK
+AA4ECQoGCwoLAAsKCwAKCQUKAQQBAAAAAAYABwoKCgsHCgANAwkKAwsKCgsKCgoACwAGCgEC
+AQAAAAEAAQcOCgERARUOCgECAQAAAAEAAQYMCgAECRcjEw4KAQEBAAAAAQABBQsKAAYJFBgZ
+EwUNCgEAAQAAAAEAAQQKCgAICxkTFRcTFwkMCgEAAQAAAAEAAQQKCgAICAITCRQTEwQMCgEA
+AQAAAAEAAQQMCgAGFAcUGxMCDAoBAAEAAAABAAECCwoABwgTBxQTIAEADAoBAAEAAAABAAEC
+CwoAByIUBxMTBwsADAoBAAEAAAABAAERCgoACAshEwYTExgEDAoBAAEAAAABAAEBCgoACAkb
+ExYTExsDDAoBAAEAAAABAAEACgoACAgTFCATExMCDAoBAAEAAAABAAEACgoACBYTFAcUExMf
+CwoAAwkAAAAAAAEAAQAKCgAJBBMTCRQTEwELAAoKAAMJAAAAAAABAAEACgoACQMTEwkXExMe
+CwAKCgADCQAAAAAAAQABAAoKAAgCFxMcHRMVBwsKAAMJAAAAAAABAAEACgoABwIJExsZExMA
+DQoBAAEAAAABAAEADAoABhMTGhMTFAwKAQABAAAAAQABAAsKAAkJExMXExMTAgsACgoBAAEA
+AAABAAERCwoBBwYTAQcBCQoKAQABAAAAAQABAgsKAQcGEwAEGAILDQgKAQABAAAAAQABAgsK
+AQcHEwAEAAsQCwcKAQEBAAAAAQABBAsKAQkBFAYTAAQACwoPBwoBAgEAAAABAAEECAoADw8L
+CgsZExMTGAkBAAsLDgAHCgEEAQAAAAEAAQUICgAFDwoKCgMABBMADwkKCwoLDgsKEAsKCgoF
+AAAAAAEAAQYNCgEZBBMECgAEDgoKDAQKAQcBAAAAAQABBwkKAA4PCgoKFhcTExMYCgoKCwcK
+AQgBAAAAAQABBwgKAAwLDgsKCgsCFBMTExUKCgEJAQAAAAEAAQgHCgADDwoMAAQKAAYLARIT
+EwkLCgEAAAABAAEJBwoABA0LChAECgAFCwIAEQsACwoBAAAAAQABCQcKAAUNCwoOCwAFCgEL
+AQsMCgEAAAABAAEJBwoABg8PCgoMCxIKAQAAAAEACAoABwsMCwoNDgsAEQoBAAAAAQANCgEL
+EgoBAAAAAQAgCgECAAABACAKAQMAAAEAFgoACwkEBgcHCQkJCgoFAAAAAA0AAAABAgMEBQYH
+CAkJAAgKAQYMAAAAIgAAAQ==
+ENDofIMG
+end
+
+demo.show_image('bmp', '32-bit', <<'ENDofIMG')
+Qk2GFAAAAAAAADYAAAAoAAAAIgAAADIAAAABABgAAAAAAFAUAABtCwAAbQsAAAAAAAAAAAAA
+////ZmbMmZnMmZn/zMz/7u7u////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////AAD///8A
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wzM8wzM8wzM8wzM8wzM8wzM8wAM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8z///8AAP///wAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzP///wAA////ADPMADPMADPM
+ADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPM
+ADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMMzPM////AAD///8AM8wAM8wAM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wzM8z///8AAP///wAzzAAzzAAzzAAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzDNmzP///wAA////ADPMADPMADPMADPMAADMADPMADPM
+ADPMAADMADPMADPMADPMAADMADPMADPMADPMZmbMADPMADPMAADMADPMADPMADPMAADMADPM
+AADMADPMADPMADPMADPMADPMZmbM////AAD///8zM8wAM8wAM8wAAMz///9mZswAM8wAM8yZ
+mf9mmcwAAMwAM8zMzP9mZswAM8wAAMyZmf8AM8wAM8zu7u5mmcwAM8wzM8z///8zM8z///8z
+M8wAM8wAM8wAM8wAM8xmZsz///8AAP///zMzzAAzzAAzzAAAzP///wAAzAAzzJmZ/zMzzAAA
+zAAzzAAzzJmZ/zMzzAAzzAAAzGZmzAAzzAAAzP///wAAzAAzzAAAzP///////wAzzAAzzAAz
+zAAzzAAzzAAzzJmZzP///wAA////MzPMADPMADPMADPM////ADPMADPMMzPMZmbM////AADM
+ADPMmZn/MzPMADPMMzPMADPMADPMADPM////ADPMADPMAADM////ZmbMADPMADPMADPMADPM
+ADPMADPMmZn/////AAD///8zZswAM8wAM8wAAMz///8AM8wAM8wAM8wAM8wAM8wAM8wAM8yZ
+mf8zM8wAM8xmmcwAAMwAM8wAAMz///8AAMwAM8wAAMz///8AM8wzM8wAM8wAM8wAM8wAM8wA
+M8yZmf////8AAP///2ZmzAAzzAAzzAAzzAAAzAAzzAAzzAAzzAAzzAAzzAAzzAAzzJnM/zMz
+zAAzzJnM/wAAzAAzzAAzzAAAzAAzzAAzzAAzzP///wAAzAAzzAAzzAAzzAAzzAAzzAAzzMzM
+/////wAA////ZmbMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPM
+3d3dMzOZADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMzMz/////
+AAD///9mmcwAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wzM8yZZjPMzJmZ
+MwAAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8zu7u7///8AAP//
+/5mZzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzDMzzJlmAGYzZsyZZpkzAJmZ
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzP///////wAA////mZn/
+ADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMAADMzJlmmTMAMzOZmWYzmTMAmWYzMzPM
+ADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPM////////AAD///+Zmf8AM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wzZszMzP+ZMwAzM8yZZgCZMwCZMwCZmf8AM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8z///////8AAP///5mZ/wAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzJlmAGZmzJlmAGYzM5kzAMzM/wAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzP///////wAA////zMz/ADPMADPMADPMADPM
+ADPMADPMADPMADPMADPMADPMADPMM2bMmTMAZmbMmWYAmTMAZmb/7u7uADPMADPMADPMADPM
+ADPMADPMADPMADPMADPMADPMADPMADPM////////AAD////MzP8AM8wAM8wAM8wAM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8yIiIiZZgBmZsyZMwCZMwBmZswAAMwAM8wAM8wAM8wAM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8z///////8AAP///93d3QAzzAAzzAAzzAAzzAAzzAAzzAAz
+zAAzzAAzzAAzzAAAzHd3d5kzAGaZzJkzAJkzAGYzZpmZ/wAzzAAzzAAzzAAzzAAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzP///////wAA////7u7uADPMADPMADPMADPMADPMADPMADPMADPM
+ADPMADPMMzPMZjMzmTMAZpn/mTMAmTMAZjMzmcz/ADPMADPMADPMADPMADPMADPMADPMADPM
+ADPMADPMADPMADPM////////AAD///////8AM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wA
+M8wzZsyZMwCZZgBmZv+ZMwCZMwCZMwDMzP8AM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wA
+M8wAM8wAM8z///////8AAP///////wAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzGaZ
+/5kzAJlmAGZmzJlmAJkzAJkzAMz//wAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAz
+zDMzzP///////wAA////////ADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMmZn/mTMA
+mTMAMzPMmWYAmTMAmTMA7u7uAADMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMMzPM
+////////AAD///////8AM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8yZzP+ZMwCZMwAz
+M8yZZjOZMwCZMwC7u7sAAMwAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wzM8z/////
+//8AAP///////wAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzMzM/5lmM5kzADMzZsyZ
+M5kzADMzmWZmzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzDMzzP///////wAA
+////////ADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMzMz/MzPMmTMAZjMzzJlmmTMA
+mTMAADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPM////////AAD/////
+//8AM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8yZMwCZMwCZmZmZMwCZMwCZ
+ZgAAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8z///////8AAP///////wAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzDMzzJkzAJkzAJlmM5kzAJkzAJkzAMzM
+/wAAzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzP///////wAA////3d3dADPMADPM
+ADPMADPMADPMADPMADPMADPMADPMADPMADPMZmbMmTMAmTMAmTMAmTMAmTMAmTMAZmbMMzPM
+ADPMADPMADPMADPMADPMADPMADPMADPMADPMADPM////////AAD////MzP8AM8wAM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8xmZsyZMwCZMwCZMwCZMwCZMwCZMwBmM2bMzP8AAMwA
+mf8AM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8z///////8AAP///8zM/wAzzAAzzAAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzGZmzJkzAJkzAJkzAJkzAJkzAJkzAJkzAP///wAAzACZzAAA
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzO7u7v///wAA////mZn/ADPMADPMADPMADPMADPMADPM
+ADPMADPMADPMADPMADPMMzPMmWYAmTMAmTMAmTMAmTMAmTMAmTMA////AADMADPMAGbMADPM
+ADPMADPMADPMADPMADPMADPMzMz/////AAD///+Zmf8AM8wAM8wAM8wAM8wAM8wAM8wAM8wA
+M8wAZswAAMwAM8wAAMzMmWaZMwCZMwCZMwBmM2YzM8zu7u7///8AAMwAAMwA//8AM8wAM8wA
+M8wAM8wAM8wAM8wAM8yZmf////8AAP///5mZzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzABm
+zAAzzAAzzAAzzJnM/5kzAJkzAJkzAJkzADMzzAAzzAAAzAAzzAAAzAD//wAAzAAzzACZzAAA
+zAAzzAAzzAAzzJmZzP///wAA////ZpnMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPM
+ADPMADPMADPMzJlmmTMAmTMAmTMAmTMAADPMADPMADPMADPMAP//ADPMADPMAMz/ADPMADPM
+ADPMADPMZmbM////AAD///9mZswAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAZswAM8wA
+M8wAM8xmmf+ZZjOZMwCZMwCZMwBmM2YAM8wAM8wAM8wAAMwAM8wAM8wAM8wAM8wAM8wAM8wA
+M8wzZsz///8AAP///2ZmzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAAzAD//wAAzAAzzAAz
+zAAAzMzM/5lmAJkzAJkzAJkzADMzmQAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzDMz
+zP///wAA////M2bMADPMADPMADPMADPMADPMADPMADPMAGbMADPMAMz/ADPMADPMADPMADPM
+AADM7u7uzJmZmTMAmTMAMzPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPM////
+AAD///8zM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAmf8AAMwAM8wAmcwAM8wAM8wAM8wAM8wA
+AMzMzP/////d3d0AAMwAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8z///8AAP//
+/zMzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzACZ/wAAzAAzzAD//wAAzAAzzAAzzAAzzAAzzAAz
+zAAAzAAAzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzP///wAA////MzPM
+ADPMADPMADPMADPMADPMADPMADPMAGbMAGbMADPMADPMAMz/AADMADPMADPMADPMADPMADPM
+ADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPM////AAD///8AM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAAMwAzP8AAMwAM8wAmf8A//8AAMwAM8wAM8wAM8wAM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8z///8AAP///wAzzAAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAAzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzP///wAA////ADPMADPMADPMADPMADPM
+ADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPM
+ADPMADPMADPMADPMADPMADPMADPMADPMADPMzMz/AAD///8AM8wAM8wAM8wAM8wAM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wAM8wA
+M8wAM8wAM8wAM8wAM8wAM8wAM8wAM8yZzP8AAP///wAzzAAzzAAzzAAzzAAzzAAzzAAzzAAz
+zAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzAAzzDMzzJmZ/2aZzGZm
+zGZmzDMzzDMzzDMzzAAzzAAzzJmZzAAA////////////7u7uzMz/mcz/mZn/mZnMZpnMZmbM
+M2bMMzPMMzPMADPMADPMADPMADPMADPMADPMADPMADPMZpnM////////////////////////
+////////////////////////AAD/////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+//////////////////8AAA==
+ENDofIMG
+
+demo.show_image('gif', 'gif87a', <<'ENDofIMG')
+R0lGODdhQAAoAPcAAAAAADgoOHBgYJiIkIB4iJCAiIB4gGBIUGhggKiYmLCYoLiooHBocMCA
+eJBocLCYmMCooKiQkKCAgGBASIiAiGhYeLiQiIhoaJhwcJh4gMCYkMCgoMCoqKiQiEBAWEg4
+QMiwoMioqMComLCIiFhAWIBgaJhweHBgcLiQkIiAgDg4UIhwgHhgYJh4cMiooFBQcGBYeJiA
+iIBwgIh4iKCAiKB4eHhYYGhIWKiIiEhAWFBIYEhAaEhIaHBYcHBgeFBQeHBogHBQYHBQWGBA
+UFhQaGBYaFhYeKCIkLCQmHhYaGBIWLCYiFBAYEhAYFhQYFBIaFhYcKCIiKCQkKiIkLCIgHBQ
+aIhwcJiAeIBgcJBwcLCQiKiAeKB4gHhwgNCwqMiwqIBoeHBYaJh4eMCYmJBweGhYYNC4qEg4
+UEA4WGBQWEBAYFBQaHBoeFhQcGhgeGhYcMiwsJB4cGBIYNjIwEAwSMCgmHhocFBAWNDAuNDI
+uIBweGBYcHhoeDgwQGhgaKCIgNjQuKiAgNjIuKiIgKCAeKCQiEhIWFBIUGBQaNC4sGBQcGBY
+YMi4sGhYWFhIYFhIaFhQWHhoaLCQkDg4SHBgaJB4gJB4eLiYmLiomGhYaEhIYFhYaIh4gHho
+gGhgcIBoaGBIaHhgcNDAsFBAUGhQYLigoLioqJiIgGhQaFA4SFhIWHhweFBIWJiAgIh4eFhI
+UHBYYIhweEg4WLiYkDg4WGBQYEA4SEA4UMCwqIhocHhgaJB4iJCAgFhASEBAUEhAUIBocFhA
+UKCQmHhgeEgwSNjQwEg4SLCgmDgwUGhQWLCgoEAwUFBASLigmEAwQGhIUFg4SIhoeEgwQKiY
+kFA4UDgwSJiIiIBwcKiQmLCooLCYkDgoQP//////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+/////////////////////////////////ywAAAAAQAAoAAAI/gABCBxIsKDBggEEDBhAoICB
+AwcjSpxIMSKCBAoWIGDQoIGDBxAURJBAoKLJkwcnUKgQoYEFlxcwdOyYoYGGDRw6eEDJc+IH
+CSBCiHg5YiaJEjM7mjgBAkUKAip6Sh24YqYGmUkbYGDRwoWGlxocvIABI4aMGVN70qiRNSkL
+Gzda4BhhIoeOHTx6+PjxwwcCIGlPouiI4WUDFkFYCLlhYwiLBkU73iBShAgRAkaMHCGAIDBF
+JBpmXkiiZMiQCagzLEFRgi0GDUyaONHx5MkLKFFCSOns+eCUBlRKVIErxIYVG1ewsMiixYSW
+LVxQkIDRpDqRJF1gVPDyhQDg3gSB/mQAwyKMmBJjpoAhU6bKCjMgMGxZAuIMmjRq0KhpsmbN
+EjZtuHEEAgQ4Ad5ACLxRQhkZwBHHGHKMAcccdFxhBgpU1FGDHUzc0QESduDhxRx56DEHHnvs
+4R0ffRzYhREwYOHHH4BUEQgZYYlgoSBfjCHIBh0MAoEdAxBSiCGHIJLIHHCYwEEFQHRhx4Ew
+LLCHIm4sIggjc9RhgQhzgEAIIGSEAAIgjShhwhwN4MGEI4/sAIkjSEQiCRJYuAHEJL0RwMge
+ejzBBiV6VGKJFpcMskUcFyQygoiEbAABJn9kogkaa+RgwCZEMEEEBlNw4gMbiPQ2QyeefAKK
+GpT0cAIk/jjEgQIKggAiiAMgUAFZIkiEIkokozyigyakLFLBGzb8IcUDPXjSGxArlGJKKKcg
+sQAqdojAlQMaCDLGHIlk8EkqiFhQBxJL5BAGE0yo4gQaTBTAQAYc2NGDZ4UAYcoOhfBxwiql
+nFGGDQ3UwMIFGsyBAgs19MBKDg0IQUoroqCRgweO5OCKJjo4osEYBXjySmAE/JBCDHBMUUkT
+T6AxiktgvXTDDbDEUoEsF8ySQxl8LJEGLTugUUQtllBQyyqW8DFyWggY8UYoHPBxxh1O0PDA
+GA0g1ZEQQphQwhus2GJDEGh4cAstbjSBBhF7aEJEEzwYQUQnaQSWHQ+o4BIG/i5gPFIKHl8k
+ZYENGOSiixysqHHGLYbE4IQTt1TQhA6o8KDJGjy8YJkiJPOlCAw7OPKEB7LccYsQoUFWxwSq
+2EFJETo8ogoaThSRwy2y4KEGBaDwUIQfu1DiwyOBNc3DGrzI0cYdnNyRQx+vuCRIAyD0wokS
+aehgSw60+GIILbSoYMstpvwywxM88PAEETwQQTIMCOwBBjAdfMFIFBcEQ4IIDdTaAjAJgMQd
+UnGGJJTtdpMI3yRUAAEP4AUIT9DECRxhN2EoIAZ7IAUkAhECDgwDDLYgxgREgQk8FMNWcxAF
+BwjRhztEQRWtoIQdbHGGHOCBFmqAgRr2kIm6pWUC/p3wwRFAMYM/6IIUR0gAE+Rwh2DIwRgo
+wEMe5jAHQQhCFHFoBAAycYxXxMER27MBMtTACtkU4QyeUYACStGEO8QADA/wRAAEIoMsiOEK
+NxACCEAgiDwIAg+l+EQyAnCKDljAFLbghTHKp4Yi9IBznlEGBxLhiGUsgQOM+EQWAPABKkBC
+DBEIRC/iIApbCQICgxhCMERAiBZYwRLMmIAxFgAK7r3gCb1hAwXwYIUogKIMQSBEHprhDCVc
+4BNVnAMgABEm+hTgGYcoAzQWIAIsTOABaSBEFNIAiSfIAjwIYEQIZIGFMIAhDW/IAy6igYNE
+fEEUiWDEJcRgjBsEgRTM/pDDH5jRAUbgwhQJcIUkaAAEWvziQAjgQCnukIBW6KEWVsDDLFhA
+hQuEwAUjAMEsZnGBPwhBAtI4AAMaEYEOfAIAyjjGNOKgByLM8UADUAYnEmCJLwQBB3jAhRYG
+gTAN4CALWajDEWBxAV1MIBIMcIItjCEQSEShEqoYBTUOJBBbFACAqWjGBl5BhS+gQAs4mEYH
+COHPXmCBEBMYxjQC0IhbVEMglEgDKX5xBgpSVSAEqAAnTtGMB4CBEApAAS6yMIhmlMISlmjG
+IKxxjFnc4AgCsIMqXMEJXujhF7eABFPvKhAEsMENqliAFHpBCRvUAQKm4IAVxBCFBSijFA8Y
+2MQAjDENUrjCClaohB2KAAlWcJYgCLjGABKAjVYsIBsJuEQEmoGJbJjiuNpIQDY4UYAC8EEP
+kegEA9zwBk38tiAIMEB0swGBbGDjGM2QhDIeMItsONe9MrWGMKxhXU8Q4aDfLcgkCpCCCCRA
+G0hQQAKU4d4FGDgbyiBuBAZQAArIAAZ7yEF+IwIER8wAGxherwKOcQllTGMaSJBCBGLAi1Os
+gBJ2nbBEoFCAAUQhCtiIQASEIeMB0IAG1rAsH5ywDRWbJACdmEFDdlGAGMyAxF1gAwzuQNWA
+AAA7
+ENDofIMG
+
+demo.show_image('gif', 'gif89a', <<'ENDofIMG')
+R0lGODlhQAAoAPcAAMnJyTgoOHBgYJiIkIB4iJCAiIB4gGBIUGhggKiYmLCYoLiooHBocMCA
+eJBocLCYmMCooKiQkKCAgGBASIiAiGhYeLiQiIhoaJhwcJh4gMCYkMCgoMCoqKiQiEBAWEg4
+QMiwoMioqMComLCIiFhAWIBgaJhweHBgcLiQkIiAgDg4UIhwgHhgYJh4cMiooFBQcGBYeJiA
+iIBwgIh4iKCAiKB4eHhYYGhIWKiIiEhAWFBIYEhAaEhIaHBYcHBgeFBQeHBogHBQYHBQWGBA
+UFhQaGBYaFhYeKCIkLCQmHhYaGBIWLCYiFBAYEhAYFhQYFBIaFhYcKCIiKCQkKiIkLCIgHBQ
+aIhwcJiAeIBgcJBwcLCQiKiAeKB4gHhwgNCwqMiwqIBoeHBYaJh4eMCYmJBweGhYYNC4qEg4
+UEA4WGBQWEBAYFBQaHBoeFhQcGhgeGhYcMiwsJB4cGBIYNjIwEAwSMCgmHhocFBAWNDAuNDI
+uIBweGBYcHhoeDgwQGhgaKCIgNjQuKiAgNjIuKiIgKCAeKCQiEhIWFBIUGBQaNC4sGBQcGBY
+YMi4sGhYWFhIYFhIaFhQWHhoaLCQkDg4SHBgaJB4gJB4eLiYmLiomGhYaEhIYFhYaIh4gHho
+gGhgcIBoaGBIaHhgcNDAsFBAUGhQYLigoLioqJiIgGhQaFA4SFhIWHhweFBIWJiAgIh4eFhI
+UHBYYIhweEg4WLiYkDg4WGBQYEA4SEA4UMCwqIhocHhgaJB4iJCAgFhASEBAUEhAUIBocFhA
+UKCQmHhgeEgwSNjQwEg4SLCgmDgwUGhQWLCgoEAwUFBASLigmEAwQGhIUFg4SIhoeEgwQKiY
+kFA4UDgwSJiIiIBwcKiQmLCooLCYkDgoQP//////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+/////////////////////////////////yH5BAEAAAAALAAAAABAACgAAAj+AAEIHEiwoMGC
+AQQMGECggIEDByNKnEgxIoIEChYgYNCggYMHEBREkECgosmTBydQqBChgQWXFzB07JihgYYN
+HDp4QMlz4gcJIEKIeDliJokSMzuaOAECRQoCKnpKHbhipgaZSRtgYNHChYaXGhy8gAEjhowZ
+U3vSqJE1KQsbN1rgGGEih44dPHr4+PHDBwIgaU+i6IjhZQMWQVgIuWFjCIsGRTveIFKECBEC
+RowcIYAgMEUkGmZeSKJkyJAJqDMsQVGCLQYNTJo40fHkyQsoUUJI6ez54JQGVEpUgSvEhhUb
+V7CwyKLFhJYtXFCQgNGkOpEkXWBU8PKFAODeBIH+ZADDIoyYEmOmgCFTpsoKMyAwbFkC4gya
+NGrQqGmyZs0SNm24cQQCBDgB3kAIvFFCGRnAEccYcowBxxx0XGEGClTUUYMdTNzRARJ24OHF
+HHnoMQcee+zhHR99HNiFETBg4ccfgFQRCBlhiWChIF+MIcgGHQwCgR0DEFKIIYcgksgccJjA
+QQVAdGHHgTAssIcibiwiCCNz1GGBCHOAQAggZIQAAiCNKGHCHA3gwYQjj+wAiSNIRCIJEli4
+AcQkvRHAyB56PMEGJXpUYokWlwyyRRwXJDKCiIRsAAEmf2SiCRpr5GDAJkQwQQQGU3DiAxuI
+9DZDJ558AooalPRwAiT+OMSBAgqCACKIAyBQAVkiSIQiSiSjPKKDJqQsUsEbNvwhxQM9eNIb
+ECuUYkoopyCxACp2iMCVAxoIMsYciWTwSSqIWFAHEkvkEAYTTKjiBBpMFMBABhzY0YNnhQBh
+yg6F8HHCKqWcUYYNDdTAwgUazIECCzX0wEoODQhBSiuioJGDB47k4IomOjiiwRgFePJKYAT8
+kEIMcExRSRNPoDGKS2C9dMMNsMRSgSwXzJJDGXwskQYtO6BRRC2WUFDLKpbwMXJaCBjxRigc
+8HHGHU7Q8MAYDSDVkRBCmFDCG6zYYkMQaHhwCy1uNIEGEXtoQkQTPBhBRCdpBJYdD6jgEgb+
+LmA8UgoeXyRlgQ0Y5KKLHKyoccYthsTghBO3VNCEDqjwoMkaPLxgmSIk86UIDDs48oQHstxx
+ixChQVbHBKrYQUkROjyiChpOFJHDLbLgoQYFoPBQhB+7UOLDI4E1zcMavMjRxh2c3JFDH6+4
+JEgDIPTCiRJp6GBLDrT4YggttKhgyy2m/DLDEzzw8AQRPBBBMgwI7AEGMB18wUgUFwRDgggN
+1NoCMAmAxB1ScYYklO12kwjfJFQAAQ/gBQhP0MQJHGE3YSggBnsgBSQCEQIODAMMtiDGBESB
+CTwUw1ZzEAUHCNGHO0RBFa2ghB1scYYc4IEWaoCBGvaQibqlZQL+nfDBEUAxgz/oghRHSAAT
+5HCHYMjBGCjAQx7mMAdBCEIUcWgEADJxjFfEwRHbswEy1MAK2RThDJ5RgAJK0YQ7xAAMD/BE
+AAQigyyI4Qo3EAIIQCCIPAgCD6X4RDICcIoOWMAUtuCFMcqnhiL0gHOeUQYHEuGIZSyBA4z4
+RBYA8AEqQEIMEQhEL+IgClsJAgKDGEIwRECIFljBEsyYgDEWAAruveAJvWEDBfBghSiAogxB
+IEQemuEMJVzgE1WcAyAAESb6FOAZhygDNBYgAixM4AFpIEQU0gCJJ8gCPAhgRAhkgYUwgCEN
+b8gDLqKBg0R8QRSJYMQlxGCMGwSBFMz+kMMfmNEBRuDCFAlwhSRoAARa/OJACOBAKe6QgFbo
+oRZWwMMsWECFC4TABSMAwSxmcYE/CEEC0jgAAxoRgQ58AgDKOMY04qAHIszxQANQBicSYIkv
+BAEHeMCFFgaBMA3gIAtZqMMRYHEBXUwgEgxwgi2MIRBIRKESqhgFNQ4kEFsUAICpaMYGXkGF
+L6BACziYRgcI4c9eYIEQExjGNALQiFtUQyCUSAMpfnEGClJVIASoACdO0YwHgIEQCkABLrIw
+iGaUwhKWaMYgrHGMWdzgCAKwgypcwQle6OEXt4AEU+8qEASwwQ2qWIAUekEJG9QBAqbggBXE
+EIUFKKMUDxjYxACMMQ1SuMIKVqiEHYoACVZwliAIuMYAEoCNViwgGwm4RASagYlsmOK42khA
+NjhRgALwQQ+R6AQD3PAGTfy2IAgwQHSzAYFsYOMYzZCEMh4wi2w4170ytYYwrGFdTxDhoN8t
+yCQKkIIIJEAbSFBAApTh3gUYOBvKIG4EBlAACsgABnvIQX4jAgRHzAAbGF6vAo5xCWVMYxpI
+kEIEYsCLU6yAEnadsESgUIABRCEK2IhABIQh4wHQgAbWsCwfnLANFZskAJ2YQUN2UYAYzIDE
+XWADDO5A1YAAADs=
+ENDofIMG
+
+teapot = <<'ENDofIMG'
+",
+".. c #998074",
+"#. c #84aadc",
+"a. c #c47e55",
+"b. c #4c6ea0",
+"c. c #d48a64",
+"d. c #ecccbc",
+"e. c #8c6252",
+"f. c #b1a094",
+"g. c #714628",
+"h. c #af8a76",
+"i. c #2c5284",
+"j. c #98745f",
+"k. c #8f5124",
+"l. c #844614",
+"m. c #5074a6",
+"n. c #aeb2b9",
+"o. c #3e291c",
+"p. c #44689b",
+"q. c #4c2705",
+"r. c #1b2b43",
+"s. c #e1c8bb",
+"t. c #dd782d",
+"u. c #9c5824",
+"v. c #547aac",
+"w. c #906e5a",
+"x. c #545253",
+"y. c #e07e33",
+"z. c #bcaeac",
+"A. c #aeb6bc",
+"B. c #6f737b",
+"C. c #7e5942",
+"D. c #b55e1a",
+"E. c #7c5134",
+"F. c #8c7a70",
+"G. c #62524d",
+"H. c #bc8a6c",
+"I. c #936754",
+"J. c #6e6d75",
+"K. c #8cb0e2",
+"L. c #d4beb4",
+"M. c #2a201a",
+"N. c #c48664",
+"O. c #412105",
+"P. c #a95a19",
+"Q. c #747a7c",
+"R. c #2a2e33",
+"S. c #484c53",
+"T. c #8690a1",
+"U. c #6c524c",
+"V. c #505967",
+"W. c #040204",
+"X. c #8cb6e4",
+"Y. c #8f4912",
+"Z. c #846e5c",
+"0. c #244a7c",
+"1. c #dcc2b6",
+"2. c #33261b",
+"3. c #81736c",
+"4. c #3c3b46",
+"5. c #735f53",
+"6. c #545e69",
+"7. c #bc7c58",
+"8. c #4c2f1d",
+"9. c #a4806b",
+".# c #604c4c",
+"## c #d4916b",
+"a# c #5c80b2",
+"b# c #e3d3cd",
+"c# c #c8ad9a",
+"d# c #bf6c2e",
+"e# c #08121c",
+"f# c #9c5e34",
+"g# c #9298a1",
+"h# c #8b7f7c",
+"i# c #835f44",
+"j# c #a46e54",
+"k# c #474649",
+"l# c #a65d26",
+"m# c #be6420",
+"n# c #7c9ed2",
+"o# c #ac622c",
+"p# c #726e6c",
+"q# c #e1a684",
+"r# c #a48676",
+"s# c #54464c",
+"t# c #a0a4ac",
+"u# c #b37b5a",
+"v# c #947a70",
+"w# c #543d31",
+"x# c #743e12",
+"y# c #98bcee",
+"z# c #d49e7c",
+"A# c #64320c",
+"B# c #d4cac6",
+"C# c #2c3642",
+"D# c #6e686b",
+"E# c #5c463e",
+"F# c #7f7575",
+"G# c #bcb2b0",
+"H# c #979dac",
+"I# c #a47a61",
+"J# c #8c9094",
+"K# c #1c262c",
+"L# c #d3c3bc",
+"M# c #9cc2f4",
+"N# c #af7455",
+"O# c #fcad5f",
+"P# c #6486b8",
+"Q# c #d4742d",
+"R# c #6d4e3d",
+"S# c #242224",
+"T# c #3b444c",
+"U# c #181515",
+"V# c #6e4024",
+"W# c #749bcc",
+"X# c #afabac",
+"Y# c #7e6a64",
+"Z# c #343634",
+"0# c #e8ac8a",
+"1# c #343a44",
+"2# c #b18f7a",
+"3# c #dda07f",
+"4# c #6f380d",
+"5# c #2f5684",
+"6# c #a08d86",
+"7# c #5f6068",
+"8# c #625751",
+"9# c #16253b",
+".a c #94b6e9",
+"#a c #dfcec8",
+"aa c #3c6194",
+"ba c #ecdad3",
+"ca c #948a89",
+"da c #a4c8fa",
+"ea c #bcb6b8",
+"fa c #604432",
+"ga c #cc6d29",
+"ha c #949ea4",
+"ia c #413024",
+"ja c #a48a7a",
+"ka c #9a867d",
+"la c #1c1a1c",
+"ma c #342116",
+"na c #bc8364",
+"oa c #9c8674",
+"pa c #844e25",
+"qa c #3c4a5c",
+"ra c #582c0d",
+"sa c #c7835a",
+"ta c #613c24",
+"ua c #614b41",
+"va c #adaeb5",
+"wa c #805c4c",
+"xa c #0a0b0f",
+"ya c #c4b2ac",
+"za c #648abc",
+"Aa c #af846a",
+"Ba c #c68a69",
+"Ca c #483c39",
+"Da c #7f400d",
+"Ea c #646e74",
+"Fa c #a85515",
+"Ga c #042244",
+"Ha c #816759",
+"Ia c #95817c",
+"Ja c #9c9aa1",
+"Ka c #9c6b54",
+"La c #7e4924",
+"Ma c #0c1a2c",
+"Na c #5f595f",
+"Oa c #6f615e",
+"Pa c #474149",
+"Qa c #8c9aac",
+"Ra c #cbbeb8",
+"Sa c #806e68",
+"Ta c #82624e",
+"Ua c #949294",
+"Va c #b4652c",
+"Wa c #9c9ea4",
+"Xa c #72574c",
+"Ya c #2a303e",
+"Za c #bc9175",
+"0a c #9c7a64",
+"1a c #261a13",
+"2a c #aca6ac",
+"3a c #341a04",
+"4a c #593520",
+"5a c #d49878",
+"6a c #26282c",
+"7a c #475261",
+"8a c #3f3535",
+"9a c #63676f",
+".b c #a47255",
+"#b c #bc967c",
+"ab c #52433a",
+"bb c #80a4d6",
+"cb c #544c4c",
+"db c #bc723c",
+"eb c #645e54",
+"fb c #a4abb4",
+"gb c #c89070",
+"hb c #8c7469",
+"ib c #c7b8b3",
+" ",
+" ",
+" ",
+" wawae.e.wa ",
+" .#j#N#7.a.db.# ",
+" 8.g.x#C.o. ",
+" N#DaA#raY.Xa4aV#4aPas#q.W.W.6a ",
+" i#O.l.4.4.4.4.4.s#wa7.N#wawaXawawawaA#q.C. ",
+" 3a3a4#wawawae.e.e.I.j#m#d#VaN#KaI.e.e.e.e.waDaO..#j#j#N#N#j#fa ",
+" O.A#wae.e.I.e.I.I.Kal#m#m#D.u.KaKaKaKaI.e.I.e.Da3aXaE#C#W.o.C. ",
+" w#e.k.I.I.Kaf#KaKaKaKal#m#m#D.l#j#Kaj#KaKaKaKaKaFai#u. GaDaI. ",
+" .#waKaI.KaKaj#j#j#j#j#VaD.m#FaVaj#j#j#j#j#j#j#KaKae.U. 9#o.Ka ",
+" .#Xae.Kaj#j#N#N#N#N#N#j#N#j#N#N#N#N#N#dbdbN#N#N#I.waU. e#M.taPa ",
+" .#U.Xawae.Kaj#N#7.dbj#a.a.a.a.a.a.a.j#7.sa##naj#I.e.waXaU.Yama.# ",
+" .#U.Xawae.I.Ka.bna3#0#3###sasaa.sac.##Ba7.u#N#Kaf#f#waXaU.4.s#Pa ",
+" j#N#5aW.Y.u#j#R# 8a.#XaXae.e.I.KaN#naz#0#q#gb7.7.N#N#N#u#nau#N#N#Kaf#f#e.waU.LaU. ",
+" 4.Hahb.bI.j#KaY. s#U.XaXawae.KaKaN#na3#0#3#gbna7.N#u#u#N#7.u#N#.bj#KaI.e.waXa.# ",
+" G.2#e.KaI.E# .#U.Xawae.P.Kaj#N#H.z#q#3#gb7.7.7.7.N#N#u#u#N#.bj#KaI.e.TaXaU.0. ",
+" Ca.#e.j#Va 5#aa0.MaU.Xawak.d#I.j#I#N.5a3#5aBa7.dbN#N#dbN#N#u#I#j#KaKaI.e.waXaU.0.i.p. ",
+" abU.I.KapaaaaaxaGaU.C.wau.VaKaj#I#na5a5agbN.u#N#7.N#N#N#N#N#.bj#KaKaI.e.waXa.#R#m.m.m.p. ",
+" zaW#0.0.s#waKam#0.0.e#GaU.C.k.l#I.KaKa.bnagbgbBa7.u#7.N#N#N#N#N#.bj#j#KaKaI.e.waXa.#.#b.m.m.i.i.0. ",
+" 5#aaW#W#n#aaaa0.U..#e.Kau.ta4aLak.k.u.o#e.KaKa.bu#H.H.nau#N#N#N#N#N#N#j#N#j#KaKaI.I.e.waXa.#fab.m.i.i.i.i.i.0. ",
+"p.p.p.aan#W#0.0.0.0.p.uaU.KaKal#o#d#gal#o#o#e.I.Kaj#N#Aau#u#N#N#N#.bN#N#j#.bj#j#KaKaI.I.e.waXa.#E#m.m.v.m.i.i.m.n#bbn# ",
+"p.p.n#n#n#p.0.0.0.0.0.xa.#waKaKagaQ#t.y.d#dbi#e.I.Ka.bN#I#N#N#N#N#.bN#N#j#N#j#KaKaI.f#e.waXaU.U.w#5#m.m.i.i.i.m.bbbbbbbbaa ",
+"n#n#n#n#n#n#0.aaaap.aaaas#s#waKaj#na##O#dbl#wae.I.I.j.j#j#j#j#j#j#j#.bj#j#j#KaKaKaI.e.e.waXaE.Hai.m.m.i.i.i.i.p.p.bbb.b.p.p.aa ",
+"p.bbn#bbp.p.p.p.p.p.aaaaaaua..#be.Kaj#j#u.XawaTae.I.KaKaKaKaj#j#j#j#j#KaKaKaKaKaI.I.i#waXawaR#uav.m.m.v.v.i.b.bbbbbbbbp.p.b.p.p.",
+"bbp.p.p.p.p.p.n#p.0.0.0.0.p.8#Oa2#ZaZaZak.XaXawae.e.e.I.KaKaKaj#KaKaKaKaI.w.I.I.I.e.waXa0aXa5.5#i.m.m.v.v.p.p.#.#.#.#.#.#.b.bb#.",
+"bbW#p.p.p.n#bbbbp.0.0.0.0.0.0.0.x.D#3.3.w.waU.wawae.e.e.e.f#I.I.I.I.I.I.I.f#e.e.wawaXae.w.ua4.5#5#i.7ai.b.b.b.p.b.#.#.#.p.b.b.#.",
+"p.bbp.bbbbp.p.p.p.0.0.6.p.p.p.0.0.0.0.9#R#wae.9.j.wawae.Tae.e.e.e.I.e.Tai#e.wawaw.Aaw.hbOa6aC#5#m.v.v.#.p.p.b.b.p.#.#.b.b.p.p.b.",
+"0.0.0.p.p.p.p.aa0.0.p.p.p.p.p.p.0.0.p.qaT#s#Z.0a..h.I#I#ZaZaI#gbI#.bH..b.bH.h.j.r#HaU.PaV.V.Na1#v.m.K.K.K.#.b.#.#.#.#.K.p.b.m.p.",
+"0.0.0.0.p.0.0.0.0.0.0.p.p.p.p.0.0.p.p.qaqaqa2.iaR#HaY#ja2#2#I#Za2#0a2#2#h.jaoaF.8#V.6aC#C#C#CaNab.bbbbK.#.b.b.b.#.K.K.#.#.#.X.#.",
+"b.b.p.p.p.0.i.0.0.0.0.p.0.0.0.i.0.0.qaqak#6aR.6a3aiawaY#OaOaOaD#Iah#D#OaF#cbPa6a6aW.V.6.1#C#7ap#b.b.b.b.b.b.b.b.b.K.K.#.b.b.b.b.",
+"bb#.#.#.#.b.b.i.0.p.p.p.0.b.b.0.0.0.qar.YaYaYaR.K#Z#E.xa1a2.S#.#x.x.S.R.laU#1#W.W.9a6.J#J#T.7av#K.K.K.K.b.b.m.m.b.m.K.b.p.m.b.b.",
+"#.#.#.#.#.#.K.#.#.#.#.#.#.b.b.b.#.p.qaqaYaR.YaR.Pa6ak#S#lalaW.W.xaW.W.W.W.U#U#ebT.hag#g#haT.7ac#K.K.K.K.K.K.b.b.#.K.K.K.K.m.b.b.",
+"#.#.#.b.b.b.b.#.#.bb#.#.#.b.K.bbK.#.T.T.J#R.YaS.S.x.ebebR.2.S#S#S#T#S#S#S.9a7aEaEafbhag#6.7aV.m.K.K.K.K.X.K.m.X.K.K..a.aX.K.b.m.",
+"b.b.p.b.p.b.p.K.K.K.b.b.b.b.#.#.#.#.T.T.J#UaJ#J#g#g#haWaWa7#9a2at#fbA.t#9a6.9aJ.EaEafbV.6.V.Nam.b.m..a.am.b.m.m.m.K.X.K..a.a.am.",
+" p.b.p.p.b.p.K.b.b.p.b.b.b.b.K.#.K.7a7aV.9aWat#X#WahaH#ha6.t#n.n.n.n.fbfb9a9an.t#t#fbfb7aV.7#m.m.m..am.m.m.m.m.m.m..a.a.am.m.m.",
+" b.p.b.#.#.#.#.#.b.b.b.b.b.b.K.Pax.V.7aNa7#7#t#vafbB.B.B.B.B.n.A.A.A.fbfb9aA.t#t#fbfbQaH#7#D#m.X..a.a.aX.v.v.v.v.m.m..am.v.m.m.",
+" #.K.K.K.K.K.#.b.b.b.b.K.K.K.T.S.V.9aB.ebNaV.p#9a9aB.D#9a9aB.A.A.A.9aB.B.Eafbn.t#g#hat#X#m..ay#y#y#y#.ay#v.v.v..aX.y#.av.v.v.",
+" #.K.K.#.K.K.K.K.K.K.K.K.K.QaT.V.7#Ea9af.f.2at#OaD#F#Q.J.9aEaB.Ea9a6.Ea9aEaV.H#H#t#2aD#J.v.m.y#y#y#y#X..ay#y#y#y#y#y#.ay#.av.",
+" K.K.K.K.b.b.b.b.K.K.K.K.g#g#t#D#fbWag#c#X#2a2aeb7#D#Q.vaA.2at#p#9a6.V.7#7#9avaSaSaSav.m.v.v.y#.ay#X.v.v.v.v.y#y#y#y#y#y#y#",
+" K.K.b.m.b.b.b.b.K.K.K.K.Ja7#7#6.2az.#ac#z.G#eaG#p#2a2a2at#t#t#t#7#9aD#J.SaL#RaRaF#v.v.v.v.v.v.y#m.v.v.a#a#v.v.M#M#M#y#y# ",
+" b.b.m.b.m.b.b.b.K.X.7#7#7#7#D#3.1.z.yac#yaibh#caB#L#eaz.z.z.z.z.F#h##ab##aL#ibibv.a#m.m.v.y#M#y#a#v.v.v.a#a#a#a#M# ",
+" p.b.m.b.b.m.b.b.m.b.7#9a9aSahb..m..ayayahbhbF.h#Ias.RaRaibibL.L#kab#bab#1.L.L.y#y#a#v.v.M#y#y#M#y#v.a#a#a#v.a#a# ",
+" b.m.b.b.X.K..aK.b.7#D#F#hbv#m.b.m.m.F.F.F.v#v#F.v#L.L.L.L#..ka6#h.s.1.L#1.y#M#y#daM#M#day#y#M#M#M#a#a#a#a# ",
+" p.b.X.X.X.X.X.X.X.9aD#6#..m..aX.y#m.m.F.v#v#v#....1.Ia....kakar#r#r#1.s.M#M#y#a#a#a#M#M#y#y#daM#dadada ",
+" .a.aX..aX..aX..aD#SaF..ay#y#.aX..am.m.........s.s.9.9.r#r#r#r#kakar#M#M#a#a#a#a#a#a#M#M#M#M#dadada ",
+" K.X..a.a.a.a.aH#vab#1.y#X.X.y#y#y#y#v.v...s.d.d.d.s.r#r#h.jajajar#a#M#v.a#a#a#a#a#a#P#dadadaM# "};
+ENDofIMG
+
+demo.show_image('xpm', 'color', "/* XPM */
+static char * teapot[] = {
+\"64 48 204 2\",
+\" c #145ec4#{teapot}")
+
+demo.show_image('xpm', 'transparent', "/* XPM */
+static char * teapot[] = {
+\"64 48 204 2\",
+\" s None c None#{teapot}")
+
+demo.show_image('xbm', 'bitmap', <<'ENDofIMG')
+#define flagup_width 48
+#define flagup_height 48
+static char flagup_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xef, 0x6a, 0x00,
+ 0x00, 0x00, 0xc0, 0x7b, 0x75, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x6a, 0x00,
+ 0x00, 0x00, 0x30, 0x60, 0x75, 0x00, 0x00, 0x00, 0x18, 0xe0, 0x7f, 0x00,
+ 0x00, 0x00, 0x0c, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x06, 0xe0, 0x04, 0x00,
+ 0x00, 0x00, 0x03, 0xe0, 0x04, 0x00, 0x00, 0x80, 0x01, 0xe0, 0x06, 0x00,
+ 0x00, 0xc0, 0x1f, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x7f, 0xe0, 0x07, 0x00,
+ 0x00, 0x70, 0xe0, 0xe0, 0x05, 0x00, 0x00, 0x38, 0x80, 0xe1, 0x04, 0x00,
+ 0x00, 0x18, 0x80, 0xf1, 0x04, 0x00, 0x00, 0x0c, 0x00, 0xfb, 0x04, 0x00,
+ 0x00, 0x0c, 0x00, 0xff, 0x04, 0x00, 0x00, 0x86, 0x1f, 0xee, 0x04, 0x00,
+ 0x00, 0x06, 0x06, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00,
+ 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x66, 0x04, 0x00,
+ 0x7f, 0x56, 0x52, 0x06, 0xe4, 0xff, 0x00, 0x76, 0x55, 0x06, 0x04, 0x00,
+ 0x00, 0x56, 0x57, 0x06, 0x04, 0x00, 0x00, 0x56, 0x55, 0x06, 0x06, 0x00,
+ 0x00, 0x56, 0xd5, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,
+ 0x54, 0x06, 0x00, 0xc6, 0x54, 0x55, 0xaa, 0x06, 0x00, 0x66, 0xaa, 0x2a,
+ 0x54, 0x06, 0x00, 0x36, 0x55, 0x55, 0xaa, 0x06, 0x00, 0xbe, 0xaa, 0x2a,
+ 0x54, 0xfe, 0xff, 0x6f, 0x55, 0x55, 0xaa, 0xfc, 0xff, 0xa7, 0xaa, 0x2a,
+ 0x54, 0x01, 0x88, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
+ 0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
+ 0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,
+ 0x54, 0x55, 0x8d, 0x50, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa8, 0xaa, 0x2a,
+ 0x54, 0x55, 0x95, 0x54, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
+ 0x54, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ENDofIMG
+
+demo.show_image('png', 'color', <<'ENDofIMG')
+iVBORw0KGgoAAAANSUhEUgAAAC4AAAAjCAIAAAETQp8oAAAIVklEQVR4nNVXPYgbSRb+xm7B
+K5CgC07QtaCDOvBCDeyAFAxIwQYdbKCBDeTgQBMqtOGCcTYOvXDBODjwHBzsBHcwExzMBAtW
+4GN7YQ1ScKAOBNPBLFcLHugGC7pgBf0WeuGC1vz6h7XZ4O5DIJp69dX3qr969Rp4A3erv69H
+YQn8aasDxh0Aw66JTtPU5ZIIhLsAvIZXw9rLJItfvd74vVzNepPx3Rh2DQAPwPFO3zqenaaO
+GcAdAAdRkuf50TQxyv8Q0gqh0ZWYNQDD0GRpHrbVJHFRYvtGE9H9nr7/dAwg8OkugLldmFaz
+1fDLtXKj1eytt76fv9JKKkkmaE5/yFbMD0IzDA2A3UEbQFsHH6bs7rsGvt0dnC9yu1heRTwZ
+dKPkHMDhTj9OXp0tXpelCBp0F8DXo/DLjp5ni+3uxou5fXT/c5Tl/HwxPcvO3dIDkOXFxGYA
+0tz+5/neNJooRSqVqi1DE3iXqyhJp2n+1dODooBjVpKKAm2t7gAIpCACgHUlD6IkXFfj2HaN
+YnBs3Ur2oK0BHO/030zqDgBmVpIAVPv924AI7cDvt3X16L0/usKzUcjAo4MIwKjftjb1SRAR
+g6/UVjje6T8bhXvDlZ/3Rt3Di/QOJ6fa9wEMu6arJJFwXGSOT6b2NsvEppPTNMnSZ6Owa4I0
+5Ulsn+8OAIABIh34WvuCKIotAN/Hg377293BDRZFBCDNmQABxNbN0vwwig93BrHNJnHS1TLL
+nE/U7xqfJBhp6m5rAdDTSkkaz6xWUitSvhCCRk9Pjnf6StHR1BYFGGwUSYLRgZKUZO4Gi1Ey
+shYAEQE4iJJwPSgKMLD1dEwQAI6myf2n469O4rZWSorxzD48iFAdxcsXEZ1aJfyJtbF1/bYO
+TaCV/ACD+PRrI//3MOzeOC+/yrvX4RM96Lcz50ah8Wm1EXfePwdAaIKvR/1RaKrHve0wSTMA
+RYHMrU7A26vTs2HY39Tj2AJAWdYEDqOkBPaGYbJ4XTKWS14syyRdnF33S1v7Twbdb3cHO/02
+gJP4FMVFCpKIiIFh15Agm7rM5Qykeb5a5pJlFJrT1B1ESdjWD/pmkmRK0ZNRtxpNUzfsmszl
+He0nNo2SbBzbyrWhCa4yapuWcywEqFZblmXLl2se/JpQ0h/HPypJZ855pbeh1d++m5vA37yn
+7in55+3eX17EZXmhRQkBIM/ZprkkAlAwj2d2Z9ADUDBCo9e1ZObK0NUsAno6uMpIXnhX+jSz
+WeZYK+kTJok9ffZA+qKtVV5wASYSBBARAbHNK8YVi80LBjsUbSUlyCcIwDEe7o/jxFa+cK5w
+edEzgZJUERWMauiCJXMdHez2e0+jxLq8ykJJGvXbjw8nWx2tCFGSHU+tUTItWCuSAiDW/jUt
+xxNLwMOjKCDSSkpJWVEUBZjZOpfmeWWvqc2Ysd0zVU49rR4eRVcsjpkgKmICigJ7J7GSlOYM
+4NHR1KZ5Fbm9P54kqSTR0XLromhcnSMGtCQGADqaxv22BiG68FXljgpPx/Etr1+dI1+AiHyi
+/SgGsN0zkogvRg+iBL8Gxzv9qlP4eFye8f8/mOBG87b2rrjfHMc7/cTlKKClJEJi87ZRW1+d
+XAZ8cNV9P9o6eDzojGN73RfPdwdpxvvjWeBLZrbSFQU62mfm63N/GymBTx2tQqOVpP1xEiUr
+u/fbOuxom7loZisjEVFeMDPGcWayj5XSb+vtnk7zQiv55GSyagcBAFW7l2SpL3Wlwye639OD
+rnHMB9GMIHySjlcbQQQi2NT5hIub6EJKtbG54ywviJAzJ9Z1dNA1KrZpynwysePYjmM7Co0v
+5eNBL0rS/atzTbkrtPI7WgEYdo0QSHN2jnPmwgFUZAygmNjs5mu5wg3b+oRHg24BuEoqMwP9
+ts6ZT2ZWCwJB+X7qeNDWmXM508ODVYnqmkAAu6P7+4djx4VPomeCtlbMvPVG79PVwVZXE4TR
+FCf545Mpbl3QXKL/WWtdSbtY4sJULSkWeWE+qb9IUikEL1n9rv7P6Q+b91SNsB1+/v08WXLZ
+8LyG8DbX1XfJebEsG1RrNuvlz7UFMzNMS36mpJLStOQ9JQXVXi+WX2xq55YP//GyWv12r/Dl
+5qcN8uz5AkAJnKZ506/XBVyBl/GP1bfd5sYn38/Ts9R58DqfNj/f3PhjGB6+mJIg5zhc18uC
+Pc9rCmop0fLrLxNb92oM1D14WP0AqIZYlgBwdqtBvY604CRnm7MAfCGUL2c26xrdM0oH0qVF
+1fjHNus9OuA8VUgPdwZEAFj7xMwMntnMpnnmOPBldR0QkZQkJVXI8sIE/uVX6u1dMcpvNRtl
+WTYEbbb8L3t/yF6X4/mZzYqax3WvweBwo5XY5e/qxMuyLPngu6Srm8uyXFcytouWlH+fzL1f
+vB/yZVPWWlK2pHDlUklyy7LRIM/zxFq5VoNjbjUbZVl7MbdvkcI/8eanzWWJhVvOX7lv/n02
+P89Vs9HAWp0aUlKNUfcECSzc8l7L9+u1+bn7JrZfbLSIoJpkAvnXf83P3dItueF5Rknlk1cT
+S8bPv/BPZck/lbJBql43SjouyxKVlLcU/mejkFEcRtYEghlEJASKAlIgL+CYcy62jE7ZEcgx
+XxZWE/ijsFP1G9cJCXgy7PpCAOACKedaSkEAsL1/Ffm2ElfAKGkCJyWBwcWqDhDRUbQqJI/6
+nTRxDEQzezkvydzjk2hvO7xeuAAw8Oho+paFbuItUqQkgACkqVOSSICIolliL+hHoUkd5znW
+FVl3o2Ax4+FB5BMB7yhkHyQFgGPurfs2ZRCc42tVFcPQnNr8/V2Qe1dBfS9ue2Vv2CUhiGia
+2Oczm7mPIf04/BfyDD1tMD0WfgAAAABJRU5ErkJggg==
+ENDofIMG
+
+demo.show_image('png', 'grayscale', <<'ENDofIMG')
+iVBORw0KGgoAAAANSUhEUgAAAC4AAAAjCAAAAAG5S1ejAAAEJElEQVR4nKWTXUwcZRiFH2YG
+ZpiBLsx2wW6ZpU1YC+3axWClf7ZKY5NVozHRxIYaL0xq1YuGeOFVRW40TXthk4aLxsT/xJjG
++tdiGkUl1nQV6rYokuy2IFugy8/irp3dHXYGvFiwBdQ08Vx9+d73Oznfe84LAIjQNv+ELdBy
+aVqTRBSh/8p6aGMZWpDomBwwETg7020sL0NjG0XsTTT9GmlSdreji1xZ555bvzmyVvcNAI/s
+pRX/8lfi4uHoREIEnrnEKwNjcxUibdt+39PX6gwNTEkkB0l+3VPtdgclQI8fs0zd8gvoMkZX
+MBywY3B0Ox0FKoGcTvtKhQuQa5tBuvXmkHOCx4Y1xS7o6Qg29vFi6DvMe79paRjP5sIgAL/1
+jxwKJC4ewS72+kp7WfX4UQRgFUlBjA1/2R7t25DQdpbZiQJPU5V1xVMuqW+9ykc+X37WKJLC
+AmD8gkJX0HIOS3S3f+B3h48jAVNI0Viztbub4wCdC+rUf/3J7eEBOgr6l0Dbr4TUpffBl0Jw
+cARr5qYvL2wPM1d8bv65a3kzPTKKBHU7AuFT53eAS3FaSsdyynQcRGiNxXaVff9wfa+Of/rB
+T66OpgkmRNiYkkssj6CuDusJ6s4YDTUHTjsCuEiNauQu7MNqXJ8LekGoRwAVXNGkV+1/33Wn
+mVdERYx5EWDCttbJqpQ5NqCRSgV0UbE0BBjzP/XpBDn90Te3ll3q8aXXqGIVAvSInau8rrSV
+m5iaY9DaU6TUdyKAKVUhWh/qSU6Owmv9mv9wIQ+OxynqbpZ6IQ6cAgrzURXtc/ZoDnQtGWFH
+6z/OW/t/dhkARbfR2DGer5avbnyZZWleCv/+C13AkYmP3bkxqy73X+y6v9F9NgLNW8Sf7DJs
+yzI+X8ne3DK99r0YoDNSEUHbdb95RiozLWR5TM2ABP79fyRlc8gfiKZ7wuFQ5dOR01CU8vpp
+kZMp05St+UFrga4IQN3npMg7W2/8UCm5k9uT2TcgID7/rqkF/LnDANTvkNYNvlMIZn6L73re
+YfWMEdEynm8bSkIXs3Lppki21G3fsGpr3bU1yvS21InFHO8sjTMfryzNXIxbmyPXhPrm0Bkl
+fXdGKr/DfVl2ZEEQqJhl9O91SF+fFMtWR+8KeKdsogdSxe3ynCdnR0dn3IqmuFyKkqwxFtmN
+alutu2/qx3FRsZuGXFm7a8OsL+r5ikSFx53Vb5RJomBWO30L7WaDNTN8fthTrLrmZHnGVz58
+4Z4ST81nU3/Khl6SnbWy5ZVGxu5btOmQfa7GUmRLzZhmU0oyu8B4SOwEEJ/VsFJVCq/ftCm/
+xnDZOVC+gCd/dnqB+NsH1QzgnLzFxoX2CoGELiu9kxBKpo1JAOv4ygwvhsDcNC6lTgF7h25u
+g7mivaD9QKlyOZxcUVyJvwDv65E2xA9RYAAAAABJRU5ErkJggg==
+ENDofIMG
+
+demo.show_image('png', 'transparent color', <<'ENDofIMG')
+iVBORw0KGgoAAAANSUhEUgAAAC4AAAAjCAYAAAGcIAh/AAAIl0lEQVR4nOWYIXDjyNLHf7p6
+oMU0TIIDtcxhNhT0Mi9LoD+2y7JsF+6xhG3YBSYsYWt2gg6zWcS+gSM2w9RsPiDbiS/Z/e7u
+3b33ql5Xqcoujbp7unv+/+6B70i2//HLskn3G8f8xLJaO34COJ3WqX30+BgwIiCML7oYiKps
+Xcw+362pjDyp+Z6t/19Op3UC+AfA3fk8uahsHj1RFdgZv247QgjcPnRZXRV/3txBmtqmvecZ
+wGlTp94HmknFuou0nWNeW0SEdzPLu8tVBlAWkg4hnE9smtkSFyMAE1tx0z5y1rxh6zzDALcP
+3WE975s6nTbjlj8tJmn8qPwnAvh75NdPi9TUo5Wfnr/4spgeTN+cz5MtJF2u1kDO1JbpH/CU
+4AfnuTht0sfbNrNVxWJW03aOresz2KWwDwNr1wPgg+N/v12kh3ZNVQmVN1QTk5q6HBfvpTLC
+ow/8fHnNMEBUpTLCMIwh/QmgNDmyq7k3leG67bLmTcVq67JpXaEoWxefdryY2ARjVX0vMj8B
+6M4ccEjz3yoipElZpPnOQ+A4IL9Hvi6bpMDH6zYDWM4nyTlPITkigqKHtUdJvzufp6/LJl2c
+Ph3ci+U03TyL0836EVuMB+10WqdpZRDJiTrQR+X+wWWvKl87z/rR0/Wer8smTesyea+st45v
+nxajAR1jYMsiWVuQi9BuHQBFAe/nk/Trbu2R8mqXfx8UAXJg6yIbH7hpt9ycL9LW9ay3HVNr
+6PtIIcJ8WlOIAQXv4+thAZjZisoIq43DVgZbCVWRk+fC8vKeu/M5VSXcPrhsGEBR6kowArUt
+qYzQ9fGl8roytG7coux2MRZwyaiI7O3lKhNyYASNd5er7Of7bTaxFZXJWW0cH3bJPqrRr8sm
+tY+OKi9YO8fWxWw+sampS2xl/nxNF8LfjEz/qXI6fYkdf/iE/lYKkfR+PqGPkWVTp2IPZ7xS
+ij+Spi7TL8t5Wu6YBODirKHzI/AOA/Tx6fj/MPtfT5tEzqG0bCGpObHctB0K2cVpk1wMhKCo
+KlFBBFbbEQIOnk9skb4spunXT4t0Ph+57X77CMOzEBjZgRPZ6bROkgvOR/oYUMCHcFB8pHzZ
+1Dz6yHXb0Uws7+d1Wnc9VSV8WT6xmPeR02md+hg4sQWd87Rdn622Luv6mO3DB88S6nce5jm4
+PiIiLKY1nQ8Uec6ymaTrdpuZWpKPgQLBB8VFzeqySLYyByfPrlbHnlf5eKRDUJzfdVXAoMpq
+4zhfzHb/oaktb6xBVWnq8qAYQICZLY+Vm6cKwhTCxvX0UbGVoRBYd47Hr++TKXImtiIMyoAi
+kiOMWCTA1gX2xg7KXRhQlMjApDIYhEJG2I0KH65WbDvHvo5jHIhhYFaPSLg3MCiHNU/K+8iJ
+Lfk0n3HZdrgYDmGojLCcT/h8s+btiaUSaLs+u3tw1JXBD4qtBJMDotjiN57frR0CfLhtKUWw
+lcEYoR+GEW5VcTFmPoQDSz64PlOFs1kNjGU6sxUfbtvjOo+qmZAfrArjibu431KZsTIAPt4+
+ZM6HQ37OrlbZuvMYyTmxhrfPYPkIWxSwRnaeCbcP22w+sQnhwJPAgWn2crnavnrSj7ClyMek
+FCJcteMHZ7MaszuV+3XXbffHSePufJ72be1fKoXIfycT1WXxYuP/NBH9lXJ3Pk9dDDCANQYR
+6FxgUle8/fn+aO2/zPGJLdPnxQmrrXtRyN8+LZLvlavVhrIYsdaZyDDAiS1Q1Rf6/lbHy0LS
+ia1oaktlhKtVR9u5oyGzObG4PtJu3GEIEhHCoKjCattT93+h4/OJTWcziw8DtjJ8uV+zdfEo
+kvuZqes9hbEHpwuR9G5mWUxroirX7QYhpxBD1NHhcQPj43ykEFJUXgLiPpUhKn0YEIGgSudG
+/pjWFVvn8arcrx2rrctWWzc2WMbweTGj7Xy6OgJHIcQBWxWc2AoYp5w8H2eLGJWgyhABGRgD
+Ow62qj9up168LIT0cTFlAOK+KdNxOptPLEGV+43D5uNtS1UU+KgsJpY+RoIKH66fqGJalykH
+Pi3fcXWzIupAITmzumRiK1T1iFqey9SW6e3UIuTUVth2gc/3D8f8tpeoZAKc7JsQfRopVZUY
+BuZvSjY+oAq+j1SFcLnaIiKYAu4+LVNZjNgdd7yoGoiMTA8j3blecVFpapvmE5sWE5v2v+cT
+m0yRs+l6alsQox6cftVxANl1XTw7zY8+4MKA5BAH6H3k28axcYHC5Pg4cN12PLpAZeDq4xl3
+X86Tj0pQuG87Fic1tjTjEKdgCqjLAhiQ3WaKMZGHB8bgBB3P1Q8d34sflC4oLig5UOQ5VWHY
+uJ5pbZnVFbY0RD8cRv2t65l9vM40eCo8N+eLHVoothBUFUXZuB7nA31UysIc+gERwZjxkd3/
+PgzUZcHza7dXHd+3OnU1Lp7XJeeLE3SAm3WH6weiBoTxbqK2hkrM2BnqOHecXa6yR9fjY+Rs
+9gYfFB+VtfP4fmDrw+GurXlTYQzYaozx3mGT7xr5GMeLpOKph37V8XbjUFVyGSPUdj2fb9fc
+PDwiuWCLEbqMEQyC98pkRxS1LZjWI4L8z3WbqSoi0JyU2FLoo2YPrs9cH7POBQZVqkKoqwoQ
+8nxEsxAUEcEWBVNb4eMxln8XcsZboIGb1lGXOapjJPJ8bEpNDmF3pRZ04G1t8RoRZIfNT+xY
+l0VaNif7zvmFTYH05XRKsTtbOoDXgDWGfFfoZ1fH332fgIbxVqQuI8aMJaDD065FhNv2CbM/
+zk+S7yK6y9hz6fqYfb5v08VZ84JIYLxd+Xj78F1XXpPvOm7M07n2Po6Tzq6pbjcdLurB+LKp
+R/QI8KaSo3cH55Tsw3W7a3FfUvgflR9SflRl9qbAeQUZCenqN2PDaVOnRxd+9wQQ9eWm/oy8
+quTidJokH280HzrHt42jfyWK/075P4AQnUfVTZNLAAAAAElFTkSuQmCC
+ENDofIMG
+
+demo.show_image('png', 'transparent grayscale', <<'ENDofIMG')
+iVBORw0KGgoAAAANSUhEUgAAAC4AAAAjCAQAAAE2KcD0AAAFPElEQVR4nMXWXYicZxUH8N+z
+M3HezCy76axJzJrtR8jWVVc29IMtTTG6hUqqqL1QWlrxQmirXpTihRdSY4pUSws1IIEWBesH
+CAZFapNaSISgpUurJra2i7u2IWs+dpNMnbWzndfM9Hixs5tNmrYJCv7vHvi///ec85z/OQ/L
+kODeeMZ1fq+LsTjolIqixAejx3jqj5EFknfEWFBke5zwkga62O01+9LAO38INsW9QeKmmHG1
+vzrgapkttiWqkWA0hsziSr/1CX+T25fAp+Km4PZg8F2CfCseipGga+HwxYBvxur4hWQoigtp
+T7grHk3rbXHAVKJIzQRq9sZ+a/XpixHFBZGqaQ/LNVTlBnVRVcKAPWnEeBrWMrXw7+uD7WfF
+3EVTFdvSxaaiFJfFaGAxlLfinmj7fuIzcUhFpmUZfXvUND2a+Gr0uT+x1+cxFhsc1zDvQOrE
+CC97wWH3xHDM+JMHg5YV+uNSKz2PHrfEQ2eK24OaLgVTDnnKtpj0Rx8wo+IG3VpmLFNnSNW4
+futUZb7tW9b6Xcq1rFe2QdU/ztAHvIgMe9KIXDvdl4rYl7aln6VBfcbtSEupnkTRpKk0Grkt
+9mHHUsV3nl378kV31f8SH1/qkbe91UVU4hanbI0ylhXybIzE12JrwN0OI/caOqPgDL4SK+xI
+rI5rPK2d7opZdU3zSsYXC7kxNhs2blf6g82gV6adxmKlo5oyp0yf6Zmtpu1xrc/Gi9a6O2DG
+WJyy0SsOpvE0nRiJjvq/UHJUZovDun0ynkyVOKak5kQaiH7c7IFF9V7UHVFB07NuQ26TKzSN
+RH+nJkOL9HIn3kk1/cpe8NPodaWG0zIFmYIp/Yv0WS25y5WUFc172EsqqKsbVlWQyVUW6UcN
+utWvzVow9Kf9wHW6HUz7XWrOOmUFaxbp+xXs1KNfrzm5ptl00puYSLkbJZkhO1OH3khFa1CQ
++7mqGh5LR8AD6QUVg+5Ly3qmbbW2ZF8ajaLnwXTnpnctu/lOz5RlKp5I3KiinWDP2w+k7XH7
+hVuk8v9008DSz9/VTBeG7XHMaWuVvOJDvv7fiA/GHZ5dKvODMeuX+jQdlduoucS7yMVQjUGb
+9Nndmd6jca2C57R0oyWXG/BEuoDIR2PMKe/3E1MdehWHrXIgUYmP+piGJxV1a8hRUnJUOebP
+NONg3OGfakoaXjVo2KQ5+42ncVvjEl9wIH6VFhKt6zeIsSipqWtoKMmFCfk5dVg6luM2bXWc
+1nad1z3jEkV9aq5X84bvJRiOgi/7sYaKYYOaHcssYCg2K7rchMfTslk6nwqu6EjTVHeVQ3Iz
+qnbJ9PhuVIM65v1bjrbjTtoUo3F9bIrRGI1eL9tgzuPL9ymsxGkwbVbJvBnjpqxSs9srqr7h
+kaiZt9cN+mVaeqwXCtrKCgoKOG7ewlPgnC0w57gTCrq916SPGNbvpBYm3ZnqVtim5E2rNbVM
+OuI1fTIVmV69Mpma9RYedcvEj2DAgKvcqmmvY15X1LJBr4qW1XF/+rtTblRTM2HWIbMY0WMd
+Mpmyklnz+s4Vf05TpumgH9ons1q3XiUzNmq6wjAeSU3vcY33qaWJdDS96g1Vl0lKGuoyawyp
+ndstcE+0PG29XKYkVzavoeFqdUWNjicH4maFZW+DQnxJBbm6NTJ853wmOm2dAb1aHQtnfpPg
+c/Fn7c4oZjr9KO5eMgrt9Jjz4yzxVbowo6ok87wTCbZGzZyBzgnytOOCBu859m/4sGOK6ktL
+4qZ49byboHEBU2kZ5c5YKfMX42oX/849L/4D4jD0vGNZ6YMAAAAASUVORK5CYII=
+ENDofIMG
+
+demo.show_image('jpeg', 'color', <<'ENDofIMG')
+/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRof
+Hh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwh
+MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAAR
+CAAmADkDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAA
+AgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkK
+FhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWG
+h4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl
+5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREA
+AgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYk
+NOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE
+hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk
+5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDzLyJSuV5FIsUm4DAzW1Ywpb3sbPhoQ4LA
+jPGea6jWdH0W6EdxYLJA78gICUb169KIq8JTutDWnSnUmqcFds4y2e5jkzGrOVGTt7Ct2aae
+ZFzGSR6cmni1t4RiFWCseRknJHf+f51MsZG4JHwP4hXmVaqctEfVYDLqsKbTla+43S7NZLkr
+dHamMEgg9R6isDVtDu7KdjFGZoOodOcD3rowWIVRkbDuUHI3DFbWnOs1n9pIIMZwwIzyBxwe
+v/16ujWs9iK+VQqfFN3W3Yo6Pp/n6LbXFx9rWeCNifLbjac9T6YxXN+a/wDzy/SvedC13S5/
+DtnZ3ckZmMQSVVTK8cYJ6HI96tfZvC3/AD42/wD35NdfM5dT5Pdtp3PBtEji1CVTtyR1U9vc
+11WpXOnRW9rYwWxB6O+/n2OOgrm40EZyg2n2rTm8M6xp+lrrk1q76bIu4hcMwB74zkD3/TFV
+KcXRcFHXudWGm6deM+axUmCQytGjrIi8Kyg81NFKrxqogVsMWk5OH78j8/YfnQ1hKlrbXU8F
+xCk43ws67d4/L3H5j1rLurqVLhhno2RXlKErn2f1qEIKV7xL77QN21VxwMdqdLdvBpbpDveS
+5cJGiHBzyMj8/wBB61i3OoySJjhR3C0+71FYYfIjncSgbSUOMj0J/mBW1OlJSuzz8fmsY0nG
+kvQ6qO4ubaLyt8fnR/Idh3AEdfyNQeVrH/QQuf8Avv8A+tWd4fu0j0dePnEjIM+vU/zqz/aq
+f8/J/wC/h/xotNSaifEO6bsVo1yy8DmvetkF3HbaW0INuYFMiYwpXA4wKKK7Y7HWtzSvNPs7
+ywezurdJLYrjyyOgx29D6EcivGviF4EtfDlnFqVpeSvFLMsPkSKCVJVjncO3y9MfjRRRUirX
+NKdWcfdi9DhbW3YRS3a7cW+GOepycDA+vWsaS3AcqScjvRRUU9zOcnLVlqx8+Elll43qoH1r
+K2L70UVaerMluf/Z
+ENDofIMG
+
+demo.show_image('jpeg', 'grayscale', <<'ENDofIMG')
+/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRof
+Hh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAAmADkBAREA/8QAHwAA
+AQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQR
+BRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RF
+RkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ip
+qrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9oACAEB
+AAA/APMvIlK5XkUixSbgMDNX7Z7mOTMas5UZO3sK3Zpp5kXMZJHpyan0uzWS5K3R2pjBIIPU
+eorA1bQ7uynYxRmaDqHTnA966/R9P8/Rba4uPtazwRsT5bcbTnqfTGK5vzX/AOeX6VFYwpb3
+sbPhoQ4LAjPGea6jWdH0W6EdxYLJA78gICUb169KzBa28IxCrBWPIyTkjv8Az/OpljI3BI+B
+/EKcCxCqMjYdyg5G4Yra051ms/tJBBjOGBGeQOOD1/8Ar16PoWu6XP4ds7O7kjMxiCSqqZXj
+jBPQ5HvVr7N4W/58bf8A78mvBtEji1CVTtyR1U9vc11WpXOnRW9rYwWxB6O+/n2OOgrDmCQy
+tGjrIi8Kyg81NFKrxqogVsMWk5OH78j8/YfnUT7QN21VxwMdqdLdvBpbpDveS5cJGiHBzyMj
+8/0HrWnHcXNtF5W+Pzo/kOw7gCOv5GoPK1j/AKCFz/33/wDWrIjQRnKDafatObwzrGn6WuuT
+Wrvpsi7iFwzAHvjOQPf9MVE1hKlrbXU8FxCk43ws67d4/L3H5j1rLurqVLhhno2RVa51GSRM
+cKO4Wn3eorDD5Ec7iUDaShxkehP8wK0vD92kejrx84kZBn16n+dWf7VT/n5P/fw/41WjXLLw
+Oa962QXcdtpbQg25gUyJjClcDjArSvNPs7ywezurdJLYrjyyOgx29D6EcivGviF4EtfDlnFq
+VpeSvFLMsPkSKCVJVjncO3y9MfjXC2tuwilu124t8Mc9Tk4GB9etY0luA5Uk5HerVj58JLLL
+xvVQPrWVsX3r/9k=
+ENDofIMG
+
+demo.show_image('jpeg', 'progressive color', <<'ENDofIMG')
+/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRof
+Hh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwh
+MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgAR
+CAAmADkDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAQDBQYBAv/EABkBAAIDAQAA
+AAAAAAAAAAAAAAECAAMFBP/aAAwDAQACEAMQAAABzA7aRqV/vvl1eIWLrCCt3stuTgrWtaNs
+PsV5dljqXX57XwtLMSLehdazjQjUSQBZVQK//8QAHhAAAgIDAQEBAQAAAAAAAAAAAQIAAwQR
+EiEQBRP/2gAIAQEAAQUC0ZoxegSSZUm2toZDTXuncQcvdTS05UTXyv1KL6jj84spAsNjVhT4
+QfIW1UGZRq6DyHGurq4PLMemsJjWaGO2qf6wTxg9aOn6GCuOir4VibHz/8QAHxEAAgEEAgMA
+AAAAAAAAAAAAAQIAAwQQERIxEyFB/9oACAEDAQE/AVUseIlC3YL3HtQ3ZxTPFwdzygDfyV7o
+BdLlWI9CE7x//8QAGxEAAwEBAAMAAAAAAAAAAAAAAAECESEQEjH/2gAIAQIBAT8BXxsqukWb
+o2vTMMZMvTu8EUifH//EACgQAAEDAwIDCQAAAAAAAAAAAAIAAREQITESUQMiMhMjM0FScYGR
+of/aAAgBAQAGPwKllhcys0shItUs3ksJtkxBLKyxTVsgAnaYuugfqggwqMrHvS2SwotLLxCp
+27j3boSdiacVhnuvldX7QeFHLF1oIZHZNxBN4d4h05emmaf/xAAgEAEAAwACAgIDAAAAAAAA
+AAABABEhMUFRcWGBEJHx/9oACAEBAAE/IcshZFgLXiHkBRkjX2ZMMXcupaDQ7fZRlXxwzq2m
+HKvtNw8afMR+4nAyQDPwUhn1PcOblWCA4SAgq7fyjXNBFYupQJoHCzZ/Qg6ZDC0rzWJF3bSr
+hl7gHj1CvvTIIebEpAaSnHFp1UQioh8wNbjHv6jUa7TSpzzsEon/2gAMAwEAAgADAAAAEIb7
+MuvRaP43Yv/EABoRAQADAQEBAAAAAAAAAAAAAAEAETEhUXH/2gAIAQMBAT8QGjax8NL2bzZn
+k1Ubj8VKe1w5H5Gxahs6xyN0w2f/xAAaEQEBAQEBAQEAAAAAAAAAAAABABEhMUFR/9oACAEC
+AQE/EBu05G8Fg+WvqUj1+xtC02FE8QZt6h63/8QAJBABAAICAgIBBAMAAAAAAAAAAQARITFB
+UWGRcaGx0fCB4fH/2gAIAQEAAT8QvtkSkKLl8RFvQllJTrLEKYaUR2dkTm2mejzMlLHRa9vV
+VP3kopAoS8XmEZJwK929QBQEyWtpz9/cQpiOEFAWXobKVLxEVQS8hjDv+46IjecMUumzzP8A
+cRqyTa48sXGOt/w1ogxTIDmGiosjXPJ78HuVGgwVxK9tt03ks9/Q7nZ8b0E36Z+z/EFWbeJY
+AwKAPNXYefpUHWepPryezuBl6sSs4HJFYsll1Z0v3CYYxDfe37zz/b8yzAZldCmppUMURDFp
+Y0Vx09JklKrxFSl046V/MBjlFe22ij53AGls5lpwah8z5p//2Q==
+ENDofIMG
+
+demo.show_image('jpeg', 'progressive grayscale', <<'ENDofIMG')
+/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRof
+Hh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wgALCAAmADkBAREA/8QAGgAA
+AgMBAQAAAAAAAAAAAAAAAgQDBQYBAP/aAAgBAQAAAAHMenfNC3rRtFT67pJcFaomPWQTaBWP
+rMsW9ZxtElKr/8QAHhAAAgIDAQEBAQAAAAAAAAAAAQIAAwQREiEQBRP/2gAIAQEAAQUC0Zox
+egSSZUm2toZDTXuncQcvdTS05UTXyv1KL6jj84spAsNjVhT4QfIW1UGZRq6DyHGurq4PLMem
+sJjWaGO2qf6wTxg9aOn6GCuOir4VibHz/8QAKBAAAQMDAgMJAAAAAAAAAAAAAgABERAhMRJR
+AyIyEyMzQVJxgZGh/9oACAEBAAY/AqWWFzKzSyEi1SzeSwm2TEEsrLFNWyACdpi66B+qCDCo
+yse9LZLCi0svEKnbuPduhJ2JpxWGe6+V1ftB4UcsXWghkdk3EE3h3iHTl6aZp//EACAQAQAD
+AAICAgMAAAAAAAAAAAEAESExQVFxYYEQkfH/2gAIAQEAAT8hyyFkWAteIeQFGSNfZkwxdy6l
+oNDt9lGVfHDOraYcq+03Dxp8xH7icDJAM/BSGfU9w5uVYIDhICCrt/KNc0EVi6lAmgcLNn9C
+DpkMLSvNYkXdtKuGXuAePUK+9Mgh5sSkBpKccWnVRCKiHzA1uMe/qNRrtNKnPOwSif/aAAgB
+AQAAABCrPPK25v/EACQQAQACAgICAQQDAAAAAAAAAAEAESExQVFhkXGhsdHwgeHx/9oACAEB
+AAE/EL7ZEpCi5fERb0JZSU6yxCmGlEdnZE5tpno8zJSx0Wvb1VT95KKQKEvF5hGScCvdvUAU
+BMlrac/f3EKYjhBQFl6GylS8RFUEvIYw7/uOiI3nDFLps8z/AHEask2uPLFxjrf8NaIMUyA5
+hoqLI1zye/B7lRoMFcSvbbdN5LPf0O52fG9BN+mfs/xBVm3iWAMCgDzV2Hn6VB1nqT68ns7g
+ZerErOByRWLJZdWdL9wmGMQ33t+88/2/MswGZXQpqaVDFEQxaWNFcdPSZJSq8RUpdOOlfzAY
+5RXttoo+dwBpbOZacGofM+af/9k=
+ENDofIMG
+
+demo.show_image('tiff', 'uncompressed', <<'ENDofIMG')
+TU0AKgAAHggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAADb///bttu2tv+Sttu2ttvb2/8AJEkAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////b//+229u2
+29vb2/+2ttttttu2ttu22//b//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAJAC229skbZLb//+2tv8AJEkkbZJtkrbb///b//9tktvb//8A
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSttu2
+29u2ttvb2/8AAAC229skbZIAACSSttu229uSttsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAJCQAJCSSttsAAACS
+ttvb//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAASUkAAABJbZIAACQkAACStrYASQDb2/8AAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////29v//9v/29v///8AAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AABtJACSbSS2bUnbkm22km3btm22kkn/25L//9ttJAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSSSSSSSTbkm2SSSSSSSSSJACSSSS2
+bUm2bUm2bUn/27b//9v/////////////27b/tm3btm3//9v/27b//////////////9skAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAkAABJAAAAAACSSSRJAABtJABtJACSbSSSSSTbtm22km3btm3btm3btm22km3/
+km22bUn/25L/27b/25Lbtm3btpLbkm3/27bbtpLbtm22km3/25L/27b//7b/27b//////9v/
+/////9v/////tpL/km1tJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtAABJAABJAABJAACSJCRJ
+AABtJABtAACSSSRtJACSbSSSSSTbkm222222km22bUm2kknbtpLb25K2km22kknbtpLbtm3b
+tpLbtm22km3btpK2km3btpLb25L//9v/25L/25Lb29v//7b/27b//7b/27b/25Lb29v/27bb
+tpL//9v//////7b///////////////+2bUkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAABJAABJAABJAABJAABJJACSSSSSJABtSQCSSSSSSSSSSSSSJCSSSSS2
+bUmSSSSSJABtJABtAACSSSS2kkm2bUnbkkm2kkn/25K2kknbtm22km3bkm22km3/tm3btm3b
+tm3btpLbkm22km22kkm2kknbtm3bkpL/25L/27b//7b/27b//7b/////tm3btpL/27b/tm3b
+tpLbtm3//7b/25L//9v/////////////////////2/8AAAAAAAAAAAAAAACSSSQkAABtJABJ
+AABtJABJAABJAABJAACSSSRtSQBtJABtSSS2kkmSJCSSJCSSSSSSSSSSSSSSSSSSSSSSSSRt
+JACSSSSSSSS2bUm2km3//9u2bUm2bUm2bUm2SSS2bUm2bUm2km2SSSSSSSTbtm3btpL/25K2
+km3btkm2km3btm22km3bkm3btpL/25K2tm3bkm22km3btm22bUm2bUm2bUm2kkm2bUnbtm22
+tm3bkm3b25L//9v///////////8ADgEAAAMAAAABAEAAAAEBAAMAAAABACgAAAECAAMAAAAD
+AAAetgEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAESAAMAAAABAAEAAAEV
+AAMAAAABAAMAAAEWAAMAAAABACgAAAEXAAQAAAABAAAeAAEaAAUAAAABAAAevAEbAAUAAAAB
+AAAexAEcAAMAAAABAAEAAAEoAAMAAAABAAIAAAAAAAAACAAIAAgSwAAAAAQAABLAAAAABAAA
+ENDofIMG
+
+demo.show_image('tiff', 'packbits compressed', <<'ENDofIMG')
+TU0AKgAABAqBAMEAgQDBAIEAwQCBAMEAgQDBAIEAwQCBAMEAgQDBAIEAwQCBAMEAgQDBAIEA
+wQCBAMEAgQDBAIEAwQCbAAvb///bttu2tv+Sttv/tv7bA/8AJEm8AKEA/v8G2///ttvbtv3b
+Df+2ttttttu2ttu22//b//+/AKMACCQAttvbJG2S2////7YR/wAkSSRtkm2Sttv//9v//22S
+/9v//8IAoQADkrbbtv/b/7b+2wD//gARttvbJG2SAAAkkrbbttvbkrbbwgCcAAAk9wD/JAUA
+JCSSttv+AAGStv/b///CAJcA/0n+AAJJbZL/AP8k/wAIkra2AEkA29v/wgCBAMEAgQDBAIEA
+wQCBAMEAgQDBAIEAwQCBAMEAgQDBAIEAwQCBAMEAgQDBAIEAwQD9///b//8B2///2/7/gQDQ
+AB5tJACSbSS2bUnbkm22km3btm22kkn/25L//9ttJAAkgQDgACOSSSSSSSTbkm2SSSSSSSSS
+JACSSSS2bUm2bUm2bUn/27b//9v3/w3btv+2bdu2bf//2//btvb/AdskigADJAAASfwAU5JJ
+JEkAAG0kAG0kAJJtJJJJJNu2bbaSbdu2bdu2bdu2bbaSbf+SbbZtSf/bkv/btv/bktu2bdu2
+ktuSbf/bttu2ktu2bbaSbf/bkv/btv//tv/btvz/ANv8/wDb/f8GtpL/km1tJLUAYm0AAEkA
+AEkAAEkAAJIkJEkAAG0kAG0AAJJJJG0kAJJtJJJJJNuSbbbbbbaSbbZtSbaSSdu2ktvbkraS
+bbaSSdu2ktu2bdu2ktu2bbaSbdu2kraSbdu2ktvbkv//2//bkv/bkv7b//8Mtv/btv//tv/b
+tv/bkv7bCP/bttu2kv//2/z/ALb1/wK2bUnXAH9JAABJAABJAABJAABJJACSSSSSJABtSQCS
+SSSSSSSSSSSSJCSSSSS2bUmSSSSSJABtJABtAACSSSS2kkm2bUnbkkm2kkn/25K2kknbtm22
+km3bkm22km3/tm3btm3btm3btpLbkm22km22kkm2kknbtm3bkpL/25L/27b//7b/2wO2//+2
+/f8Ztm3btpL/27b/tm3btpLbtm3//7b/25L//9vx/wHb//UAAZJJ/yT/AH9tJABJAABtJABJ
+AABJAABJAACSSSRtSQBtJABtSSS2kkmSJCSSJCSSSSSSSSSSSSSSSSSSSSSSSSRtJACSSSSS
+SSS2bUm2km3//9u2bUm2bUm2bUm2SSS2bUm2bUm2km2SSSSSSSTbtm3btpL/25K2km3btkm2
+km3btm22km3bkjBt27aS/9uStrZt25JttpJt27Zttm1Jtm1Jtm1JtpJJtm1J27ZttrZt25Jt
+29uS///b+P8ADgEAAAMAAAABAEAAAAEBAAMAAAABACgAAAECAAMAAAADAAAEuAEDAAMAAAAB
+gAUAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAESAAMAAAABAAEAAAEVAAMAAAABAAMAAAEW
+AAMAAAABACgAAAEXAAQAAAABAAAEAgEaAAUAAAABAAAEvgEbAAUAAAABAAAExgEcAAMAAAAB
+AAEAAAEoAAMAAAABAAIAAAAAAAAACAAIAAgSwAAAAAQAABLAAAAABAAA
+ENDofIMG
+
+if false
+demo.show_image('tiff', 'pixarlog compressed', <<'ENDofIMG')
+TU0AKgAAA3Z4nO2aIWzbUBCGz7HjYyVTNDAp0CgKDRorCauiSGFjRmWRxs0rlQ2FlUWKrLKQ
+sIDK1BoyjFRUjZSF7f13eYnjpZOmdeuU3Wc1se+dn17uf/ee5SuRYRiGYRiGYRiGYRiGYRiG
+YRg/YxVt3EG04IpLJkqocJ8VD6S1746ELsOP8UNMxO1J9MbDPQs2EvOKcV66uOsZoo34lwxb
+JraMfEsif+S06Lrj74/5XNi2iG6jdbCKruMRz3gdfKUbF/OFi/c0vHbzfNvqBDl1giENKHdt
+492dI/7sdIElMRV+i0l0G62igcx3ZMBhnUFc0ebV4fZzeBfDfx2ofyGr1DycOt+3/RXnALIB
+63rTqnYo9SVYBxptVS11+WDz//WZh/MQ8Z5E8/AiwjdmPnTg9qfg1sV+Hn7gabiK3gWbSDPl
+rcdsGIZhGIZhGIZhGIZhnCebXc1IKxeJ2LSGkbija+8G/zAXEd4LDqkTbFuo091T312l8iYd
+79JhK7ngGY+dNSfoklKP38eX4VOMt73NN77Gr4B3tP4NOeLbCWY84qfYt18x4ntPUCd133XG
+zv+RSOp5RD57DlRSiSo5Y59RY1HQV2fH1KRyunbDy/D/0VRjr3HVirQqMuJJxO2UvDY+R4hm
+DKUe3RXywudIHbVrdBe8lNzJJfK08y2kQr5k7RfXS0ZeZaJNIfYl+35S8dF7j1fI8dHV8fmC
+P7P23OO7+Dl8/idVvZCYz7hpz6VyNHKz/6ACxj8kqLNk5MWxIrkoktKhP0Re49uX+qtWxUtn
+1cjP2Nvhi8/h7vyg7FDUXLKe+7o6tEKs/bgrGUEiFfdTeqji6qN1evSaiLYH34X4/piVaOnx
+Qzx1Gr72f03MX9xdEdlcVh5dhZaMLBkS1XJCuZJxo1XXKOwWsOld6nPQbiC9asT70l+5+93Q
+cMFY//rSk1eBaj7IgaoxW3wGlXu710X7QetwpxnRqTxSEHlEupJZk+x3v2xnIRk1VMvk3oJp
+32tz7a2Du7svVNl0tUFdmtt+NiNWOuf1vE6+m/8aUR/5bSuTqBYu06/2UTjeLU7h8+h+r6nf
+ZfAMMKYbUaTH3+Lj+1Tf+n4E/6K2c+kKqS26Py0k7xDTmcz+tPZ04VUmyTLvX4p/wdR4Gsm4
+uV54beCT1Z5edCVNpc/TSn0HoOsh4gAOAQAAAwAAAAEAQAAAAQEAAwAAAAEAKAAAAQIAAwAA
+AAMAAAQkAQMAAwAAAAGAjQAAAQYAAwAAAAEAAgAAAREABAAAAAEAAAAIARIAAwAAAAEAAQAA
+ARUAAwAAAAEAAwAAARYAAwAAAAEAKAAAARcABAAAAAEAAANuARoABQAAAAEAAAQqARsABQAA
+AAEAAAQyARwAAwAAAAEAAQAAASgAAwAAAAEAAgAAAAAAAAAIAAgACBLAAAAABAAAEsAAAAAE
+AAA=
+ENDofIMG
+end
+
+if false
+demo.show_image('tiff', 'logluv compressed', <<'ENDofIMG')
+TU0AKgAAAAgADgEAAAMAAAABAEAAAAEBAAMAAAABACgAAAECAAMAAAADAAAAtgEDAAMAAAAB
+h3QAAAEGAAMAAAABAAIAAAERAAQAAAABAAAAAAESAAMAAAABAAEAAAEVAAMAAAABAAMAAAEW
+AAMAAAABACgAAAEXAAQAAAABAAAAAAEaAAUAAAABAAAAvAEbAAUAAAABAAAAxAEcAAMAAAAB
+AAEAAAEoAAMAAAABAAIAAAAAAAAAEAAQABASwAAAAAQAABLAAAAABAAA
+ENDofIMG
+end
+
+demo.show_image('tiff', 'jpeg compressed', <<'ENDofIMG')
+TU0AKgAABID/2P/AABEIACgAQAMAEQABEQACEQD/2gAMAwAAAQACAAA/APn+vn+vn+iiiiii
+iiiiiiiiiiiiiiiiiiiiiiiiiiitK28O63e28VxaaNqE8ExIilitXZXIODtIGDyCOPStO18O
+a5e28VxaaNqNxBLny5IrV3V8Eg4IGDyCPqDWtZ+FvEOo2kd3Y6Dql1bS/wCrmgs5HR+SOCBg
+8gj6g1m1mkEEgggjqDWUysjFWUqwOCCMEGikpKKKKKKKKKKKKKKUHBB449RRXdXHxU16+nt5
+Ll1j8li5MDOTIxdWJYOzKSMMF3KwG4jHTHo83xl8QXs8U92Y1aJWASAMAxZkO472ZSQA4G5W
+A3YwRjb6mfjj4guZ4pblYYhEr/u7VWHmMzIcszuwyAHC5Vgu7G054x/GPiGDxNqtvqEcLRz/
+AGcR3LFAvmSB3wwwTxsKcEnbjaCQorA8e+J7bxbrdvqcEDRzfZViunaNU82QM3zgAnjaUGCT
+jG0HAFcx8QfFlt4z1221aK18i4+yrFdt5ap50iu+HwCTymzgkkY25IUE87XLVydFFFFFFFFF
+FFFFFFFFFFFFFFFFFFe2vceH9WtktdR8KaRGsEu53hjW2Z8ZH3o1jP8AeG32B6/d7l/E9hqU
+ENvqHhjSkWKUNKUt47Z2IJHDRiM+oK5xx7Db0t34mjvrWK3u9F0vEcoeUxWkdvI2MjAaJUOO
+eV6d/TFlfhp4BvnlmZtYtCHG6G3uUKJk9F3Izce7ZP542IfDXgG5trm4uv7YtJlOfJhnURAs
+TiNMxuxwM43NkgZ61p2lh4Lube5muodVhmDMdlvdII0JJwqgxuxA46tkj8cT23wi+HtwIsat
+raF/veZcQx4PoN0QJ+vA4zV+x8C/Dm6it92rauJJOH33McIVs8gb4cnjvwDjOfS5p+geAZoo
+BcXuqmWRQGYXEcKo2eRhoiTgc54HB554zofgFayMfM8XeSp+ZC2nggr0/wCeo7+38jitB8H9
+OLAXfi9bVXXfG72PyuucZB8z1BH4fXEUHw70/wDdte+IzaxyLvjZrLO5ckZA3jnIx6Z79cNm
++AEUkFwNO8YQXF3EuRFLYtGh/wB5w7bRjnODS3HwYtJYpF0fxfbXlzHgvHNZvEqg9CWVnwMc
+5x0/HEt18NNPc+VpPimG7uVAaRJ7NokQHHJZWf37c44zms4fs++JyCf7Y8P/AC5zi5lOB68R
+9ODVdfgZr7KP+J54fDEkbBcysw9yBGePft3qOH4S6lLGr/2/oCgnH/HxK2PQnbGeD69B3xkZ
+w7z4N+MrW8lgjs7O5RGwJor+FUf3AdlbGeOQOlYM/wAL/E0V08McdhOik7ZV1CGNZAP4gJGV
+sfUDofSsV/Aeti9kt4jYShSdsxvookcDuPNZTjnuAfbg1n6h8MPGumiMy+HbybzM4+x7brGM
+Z3eUW29e+M846GoL34aeMrHZu8P3dxuyM2O26C4x97yi23qOuM0tz8PPFlvs2aLNeb8/8g90
+vNuMfe8ktt68ZxnnHQ1//9kAAA8BAAADAAAAAQBAAAABAQADAAAAAQAoAAABAgADAAAAAwAA
+BToBAwADAAAAAQAHAAABBgADAAAAAQACAAABEQAEAAAAAQAAAAgBEgADAAAAAQABAAABFQAD
+AAAAAQADAAABFgADAAAAAQAoAAABFwAEAAAAAQAABHcBGgAFAAAAAQAABUABGwAFAAAAAQAA
+BUgBHAADAAAAAQABAAABKAADAAAAAQACAAABWwAHAAABIQAABVAAAAAAAAgACAAIEsAAAAAE
+AAASwAAAAAQAAP/Y/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQu
+JyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQF
+BgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0Kx
+wRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlq
+c3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT
+1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9k=
+ENDofIMG
+
+demo.show_image('tiff', 'deflate compressed', <<'ENDofIMG')
+TU0AKgAAAah4nO2Y643EMAiEXQzNUIyboRiaoRh2ADuP+7N70knZkxhZlmNH2fkMRPGO0Wq1
+Wq1Wq9Vqtb5L5m5qqi7Rm5kP4qdNfSSHc3dYDtfmMD8TQS3mn3b3TjRgm6YEgsaeYzwRg4TC
+9PcjRMLYzpmxcABW8+ifNviJ6DIktLKN/vv3/xRHwXJuPoV5HTwqKK1Wq9VqtVqtz+VxwMjv
+8ej/39fUpCGTdLLJVJmm6NlNQIQlev+AhyVMaDBfA6GYAU41nFrzqLSFSw3GjJf6ZeEpUvwu
+bxDOcFREAkpXRKph7IjRzOjAvEnOC9jzcC7rnlp13YB29ip4wvxT1Jn+qwlthMQ5QWDbwlsE
+RTis4uQX+cZl+zCPQfWWGZgsEkfHhaML3KyQN901lIjwL/6a4GvL5EEK4QErneKSKqPW0qaD
++awarnpJlkTIOnI9Aic1o1LsuEHuMdIyHTgrPyVTVKsM/YfuRzY4odxz3v2KBfaf021aDQqi
+E2q3SYs0QxN1cdSOHnW0i8uWyYoR79dFIK95nedr5HhObRRmctXuUC9uNR31AAAOAQAAAwAA
+AAEAQAAAAQEAAwAAAAEAKAAAAQIAAwAAAAMAAAJWAQMAAwAAAAGAsgAAAQYAAwAAAAEAAgAA
+AREABAAAAAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEAAwAAARYAAwAAAAEAKAAAARcABAAA
+AAEAAAGfARoABQAAAAEAAAJcARsABQAAAAEAAAJkARwAAwAAAAEAAQAAASgAAwAAAAEAAgAA
+AAAAAAAIAAgACBLAAAAABAAAEsAAAAAEAAA=
+ENDofIMG
+
+if Tk::PLATFORM['platform'] != 'windows'
+demo.show_image('other', 'postscript', <<'ENDofIMG')
+%!PS-Adobe-3
+%%Title: postscript.ps
+%%BoundingBox: 66 648 146 720
+%%Pages: 1
+%%DocumentProcSets: Adobe_distill 0.96
+%%EndComments
+%%BeginProcSet: Adobe_distill 0.96
+/PROLOGUE 30 40 add dict def
+ % 30 procedure entries + room for 40 cached font dictionaries
+ PROLOGUE begin
+ /clip { } def % causes problems. remove if "clip" is needed
+ /bdef { bind def } bind def /ldef { load def } bdef
+ /T { moveto show } bdef /A { moveto ashow } bdef
+ /W { moveto widthshow } bdef /AW { moveto awidthshow } bdef
+ /f /fill ldef /R { { rlineto } repeat } bdef
+ /r /rlineto ldef /L { { lineto } repeat } bdef
+ /m /moveto ldef /l { moveto lineto stroke } bdef
+ /x { 0 rlineto } bdef /y { 0 exch rlineto } bdef
+ /c /curveto ldef /cp /closepath ldef
+ /s /stroke ldef /w /setlinewidth ldef
+ /g /setgray ldef /j /setlinejoin ldef
+ /d /setdash ldef /F /setfont ldef
+ /C /setcmykcolor where { /setcmykcolor get }{ %ifelse
+ { %def
+ 1 sub 3 { 3 index add neg dup 0 lt { pop 0 } if 3 1 roll } repeat
+ setrgbcolor
+ } bind
+ } ifelse def
+ /selectfont where { pop }{ %ifelse
+ /selectfont { exch findfont exch scalefont setfont } bdef
+ } ifelse
+ /MF { exch findfont exch makefont setfont } bdef
+ /FF /selectfont ldef
+ /DF { selectfont currentfont def } bdef
+ /BEGINPAGE { pop /pagesave save def } bdef
+ /ENDPAGE { pop pagesave restore showpage } def
+ /REMAP { %def
+ FontDirectory 2 index known { pop pop pop } { %ifelse
+ findfont dup length dict begin
+ { 1 index /FID ne {def}{pop pop} ifelse } forall
+ exch dup length 0 gt { /Encoding exch def }{ pop } ifelse
+ currentdict end definefont pop
+ } ifelse
+ } bdef
+ /RECODE { %def
+ 3 -1 roll 1 index findfont /Encoding get 256 array copy exch
+ 0 exch { %forall
+ dup type/nametype eq
+ { 3 {2 index} repeat put pop 1 add }{ exch pop }ifelse
+ } forall pop 3 1 roll REMAP
+ } bdef
+ end %PROLOGUE
+%%EndProcSet: Adobe_distill 0.96
+%%EndProlog
+%%BeginSetup
+PROLOGUE begin
+%%EndSetup
+%%Page: 1 1
+1 BEGINPAGE
+1 g
+2 setlinecap
+144 53 m
+390 x
+-19 y
+-390 x
+eofill
+0 g
+1.268 w
+0 setlinecap
+4 setmiterlimit
+[] 0 d
+109.698 714.182 m
+111.525 713.672 112.472 713.234 113.624 712.431 c
+-22.3128 -25.8381 r
+97.4019 682.652 103.794 672.84 100.329 664.844 c
+102.034 675.687 90.7436 683.82 84.1099 684.842 c
+25.588 29.3407 r
+f
+1.0361 w
+f
+f
+91.8805 654.468 m
+96.0255 654.285 100.155 654.188 104.481 654.188 c
+113.804 654.188 122.752 654.636 131.141 655.44 c
+134.222 655.737 136.724 658.133 137.108 661.279 c
+137.79 666.855 138.107 672.696 138.107 678.705 c
+138.107 684.714 137.79 690.555 137.108 696.131 c
+136.724 699.277 134.222 701.674 131.141 701.97 c
+127.476 702.321 123.704 702.604 119.84 702.813 c
+119.84 702.813 103.842 668.373 102.231 664.827 c
+99.8549 659.595 96.601 655.765 91.8805 654.468 c
+f
+0.7851 w
+77.8202 655.44 m
+74.7171 655.948 72.2887 657.716 71.8525 661.279 c
+71.1725 666.855 70.8549 672.696 70.8549 678.705 c
+70.8549 684.714 71.1725 690.555 71.8525 696.131 c
+72.2381 699.277 74.7417 701.674 77.8202 701.97 c
+82.1335 702.383 86.5932 702.702 91.1764 702.916 c
+8.16241 9.07727 r
+99.2863 711.98 101.266 712.345 102.996 711.921 c
+-28.4564 -32.9334 r
+80.6983 681.906 98.7446 677.354 98.7446 666.708 c
+98.7446 655.332 86.3243 654.054 77.8202 655.44 c
+f
+0.0843 w
+139.67 644.154 m
+140.194 644.154 140.619 644.576 140.619 645.098 c
+140.619 645.619 140.194 646.042 139.67 646.042 c
+139.146 646.042 138.721 645.619 138.721 645.098 c
+138.721 644.576 139.146 644.154 139.67 644.154 c
+1 ENDPAGE
+%%Trailer
+end %PROLOGUE
+%%Pages: 1
+%%EOF
+ENDofIMG
+end
+
+if false
+demo.show_image('other', 'pdf', <<'ENDofIMG')
+JVBERi0xLjIKJcfsj6IKNCAwIG9iago8PC9MZW5ndGggNSAwIFIvRmlsdGVyIC9GbGF0ZURl
+Y29kZT4+CnN0cmVhbQp4nF1TSY7cQAy7+xX1AkFbaXlG3jBAgAAzh/z/Esp2uyeDPhhUayEp
+FZMsnt/9/fg6/h6y/hzCHdS1UlyodH0dIrJJNyIWlLpE1OcLrGQOjLg6MOIm6+NoMULWiopN
+bevz6HRiaUQ0aKMHW1L7itQitGA2UvwdDuhoIaw8zSN3UOVqTnILNLAiXQVy3NNvCvQs+M57
+Zv4Gj6LivWK7UxS0dDCknBGl2jNY6MKoKmBkljwYfQUD2d8ZqjkKgINASEyEfCq208nc0Fon
+YSdZIiFy7IldQmbACe4FraKUfVYkzEAgarhgIBJyvIGi+IYrCWqm4I6UJ4mvV4PmfTW4J3TI
+tZCHQzdmDqeLY7Jgpf6IAG7KKVAsLAMBxWIEqrEvuAAc8xXp2Rtgkdhp038B7PfcCyQZ5WDV
+oXIuWGdCI387SO/GjezVgcZyuRaAP1b3gXVmopb1ZfXXkSM/z6Imx+4xpHAsseGHgD2abFzu
+2+qEzjwjl9fJN4vb6zd+ef1Ebq+fDrfZz4zH7GFhc0O32cPSJR+zXzIes0vnMPZlNk73ejWT
+gFNDYs/IOM3tkTXmGUbMsaPF9cAwq8KuyNwxFMc4gJY+d47S0Td/68nSNxkiUNpz159H8Twg
+g1LkcKyGBe6TkQYL3jhwTDwreSJ7gw9eZeBY3GZpPBU/FjY7/HX8A9+h3WJlbmRzdHJlYW0K
+ZW5kb2JqCjUgMCBvYmoKNTE2CmVuZG9iagozIDAgb2JqCjw8Ci9UeXBlIC9QYWdlCi9NZWRp
+YUJveCBbMCAwIDYxMiA3OTJdCi9QYXJlbnQgMiAwIFIKL1Jlc291cmNlcyA8PCAvUHJvY1Nl
+dCBbL1BERl0KPj4KL0NvbnRlbnRzIDQgMCBSCj4+CmVuZG9iagoyIDAgb2JqCjw8IC9UeXBl
+IC9QYWdlcyAvS2lkcyBbCjMgMCBSCl0gL0NvdW50IDEKPj4KZW5kb2JqCjEgMCBvYmoKPDwg
+L1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSCj4+CmVuZG9iago2IDAgb2JqCjw8IC9DcmVh
+dGlvbkRhdGUgKEQ6MTk5NzEyMDUyMjU2MzcpCi9Qcm9kdWNlciAoQWxhZGRpbiBHaG9zdHNj
+cmlwdCA1LjEwKQo+PgplbmRvYmoKeHJlZgowIDcKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAw
+MDAwNzk5IDAwMDAwIG4gCjAwMDAwMDA3NDAgMDAwMDAgbiAKMDAwMDAwMDYyMCAwMDAwMCBu
+IAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDA2MDEgMDAwMDAgbiAKMDAwMDAwMDg0OCAw
+MDAwMCBuIAp0cmFpbGVyCjw8IC9TaXplIDcgL1Jvb3QgMSAwIFIgL0luZm8gNiAwIFIKPj4K
+c3RhcnR4cmVmCjkzOQolJUVPRgo=
+ENDofIMG
+end
+
+#######################
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tkimg/license_terms_of_Img_extension b/ext/tk/sample/tkextlib/tkimg/license_terms_of_Img_extension
new file mode 100644
index 0000000000..7f515feee8
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkimg/license_terms_of_Img_extension
@@ -0,0 +1,41 @@
+This software is copyrighted by Jan Nijtmans (the maintainer)
+and a lot of other people who contributed code (most notably
+Andreas Kupries, Thomas G. Lane, Ioi K. Lam, Mario Weilguni
+and Roger E Critchlow Jr).
+The following terms apply to all files associated with the
+software unless explicitly disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
diff --git a/ext/tk/sample/tkextlib/tkimg/readme.txt b/ext/tk/sample/tkextlib/tkimg/readme.txt
new file mode 100644
index 0000000000..4d9774492c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tkimg/readme.txt
@@ -0,0 +1,3 @@
+The script 'demo.rb' is based on 'demo.tcl' of Tcl/Tk's 'Img' extention.
+Image data in 'demo.rb' is those of 'demo.tcl'.
+Please read 'license_terms_of_Img_extension' file.
diff --git a/ext/tk/sample/tkextlib/tktable/Orig_LICENSE.txt b/ext/tk/sample/tkextlib/tktable/Orig_LICENSE.txt
new file mode 100644
index 0000000000..dd176a7ccf
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/Orig_LICENSE.txt
@@ -0,0 +1,52 @@
+
+ #######################################################################
+ ### The following text is the original 'license.txt' of tktable ###
+ ### extension. ###
+ ### Original Tcl source files are not include in this directry, ###
+ ### because of all of them are rewrited to Ruby files. ###
+ ### However, the image data file is quoted from iwidgets source ###
+ ### archive. ###
+ #######################################################################
+
+
+ * COPYRIGHT AND LICENSE TERMS *
+
+(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
+it falls under similar license terms).
+
+This software is copyrighted by Jeffrey Hobbs <jeff.hobbs@acm.org>. The
+following terms apply to all files associated with the software unless
+explicitly disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute, and
+license this software and its documentation for any purpose, provided that
+existing copyright notices are retained in all copies and that this notice
+is included verbatim in any distributions. No written agreement, license,
+or royalty fee is required for any of the authorized uses.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
+EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS
+PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
+OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
+is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
+of the Rights in Technical Data and Computer Software Clause as DFARS
+252.227-7013 and FAR 52.227-19.
+
+SPECIAL NOTES:
+
+This software also falls under the bourbon_ware clause:
+
+ Should you find this software useful in your daily work, you should
+ feel obliged to take the author out for a drink if the opportunity
+ presents itself. The user may feel exempt from this clause if they
+ are under 21 or think the author has already partaken of too many
+ drinks.
diff --git a/ext/tk/sample/tkextlib/tktable/basic.rb b/ext/tk/sample/tkextlib/tktable/basic.rb
new file mode 100644
index 0000000000..0d2d48893a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/basic.rb
@@ -0,0 +1,60 @@
+#!/usr/bin/env ruby
+##
+## basic.rb
+##
+## This demo shows the basic use of the table widget
+##
+## ( based on 'basic.tcl' included source archive of tktable extension )
+##
+require 'tk'
+require 'tkextlib/tktable'
+
+ary = TkVariable.new_hash
+rows = 8
+cols = 8
+
+# fill table variable
+((-(rows))..rows).each{|x|
+ ((-(cols))..cols).each{|y|
+ ary[x,y] = "r#{x},c#{y}"
+ }
+}
+
+lbl = TkLabel.new(:text=>"TkTable v1 Example")
+
+table = Tk::TkTable.new(:rows=>rows, :cols=>cols, :variable=>ary,
+ :width=>6, :height=>6,
+ :titlerows=>1, :titlecols=>2,
+ :roworigin=>-1, :colorigin=>-2,
+ :rowstretchmode=>:last, :colstretchmode=>:last,
+ :rowtagcommand=>proc{|row|
+ row = Integer(row)
+ (row>0 && row%2 == 1)? 'OddRow': ''
+ },
+ :coltagcommand=>proc{|col|
+ col = Integer(col)
+ (col>0 && col%2 == 1)? 'OddCol': ''
+ },
+ :selectmode=>:extended, :sparsearray=>false)
+
+sx = table.xscrollbar(TkScrollbar.new)
+sy = table.yscrollbar(TkScrollbar.new)
+
+btn = TkButton.new(:text=>'Exit', :command=>proc{exit})
+
+Tk.grid(lbl, '-', :sticky=>:ew)
+Tk.grid(table, sy, :sticky=>:news)
+Tk.grid(sx, :sticky=>:ew)
+Tk.grid(btn, :sticky=>:ew, :columnspan=>2)
+
+Tk.root.grid_columnconfig(0, :weight=>1)
+Tk.root.grid_rowconfig(1, :weight=>1)
+
+table.tag_configure('OddRow', :bg=>'orange', :fg=>'purple')
+table.tag_configure('OddCol', :bg=>'brown', :fg=>'pink')
+
+table.set_width([-2, 7], [-1, 7], [1, 5], [2, 8], [4, 14])
+
+puts "Table is #{table.path} with array #{(table['variable'])}"
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tktable/buttons.rb b/ext/tk/sample/tkextlib/tktable/buttons.rb
new file mode 100644
index 0000000000..b21e8673c2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/buttons.rb
@@ -0,0 +1,76 @@
+#!/usr/bin/env ruby
+##
+## buttons.rb
+##
+## demonstrates the simulation of a button array
+##
+## ( based on 'buttons.tcl' included source archive of tktable extension )
+##
+require 'tk'
+require 'tkextlib/tktable'
+
+# create the table
+tab = TkVariable.new_hash
+rows = 20
+cols = 20
+
+table = Tk::TkTable.new(:rows=>rows + 1, :cols=>cols + 1,
+ :variable=>tab, :titlerows=>1, :titlecols=>1,
+ :roworigin=>-1, :colorigin=>-1,
+ :colwidth=>4, :width=>8, :height=>8,
+ :cursor=>'top_left_arrow', :borderwidth=>2,
+ :flashmode=>false, :state=>:disabled)
+
+sx = table.xscrollbar(TkScrollbar.new)
+sy = table.yscrollbar(TkScrollbar.new)
+
+Tk.grid(table, sy, :sticky=>:news)
+Tk.grid(sx, :sticky=>:ew)
+
+Tk.root.grid_columnconfig(0, :weight=>1)
+Tk.root.grid_rowconfig(0, :weight=>1)
+
+# set up tags for the various states of the buttons
+table.tag_configure('OFF', :bg=>'red', :relief=>:raised)
+table.tag_configure('ON', :bg=>'green', :relief=>:sunken)
+table.tag_configure('sel', :bg=>'gray75', :relief=>:flat)
+
+# clean up if mouse leaves the widget
+table.bind('Leave', proc{|w| w.selection_clear_all}, '%W')
+
+# highlight the cell under the mouse
+table.bind('Motion', proc{|w, x, y|
+ Tk.callback_break if w.selection_include?(TkComm._at(x,y))
+ w.selection_clear_all
+ w.selection_set(TkComm._at(x,y))
+ Tk.callback_break
+ ## "break" prevents the call to tkTableCheckBorder
+ }, '%W %x %y')
+
+# mousebutton 1 toggles the value of the cell
+# use of "selection includes" would work here
+table.bind('1', proc{|w, x, y|
+ #rc = w.curselection[0]
+ rc = w.index(TkComm._at(x,y))
+ if tab[rc] == 'ON'
+ tab[rc] = 'OFF'
+ w.tag_cell('OFF', rc)
+ else
+ tab[rc] = 'ON'
+ w.tag_cell('ON', rc)
+ end}, '%W %x %y')
+
+
+# inititialize the array, titles, and celltags
+0.step(rows){|i|
+ tab[i,-1] = i
+ 0.step(cols){|j|
+ if i == 0
+ tab[-1,j] = j
+ end
+ tab[i,j] = "OFF"
+ table.tag_cell('OFF', "#{i},#{j}")
+ }
+}
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tktable/command.rb b/ext/tk/sample/tkextlib/tktable/command.rb
new file mode 100644
index 0000000000..bf36159ccc
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/command.rb
@@ -0,0 +1,89 @@
+#!/usr/bin/env ruby
+##
+## command.rb
+##
+## This demo shows the use of the table widget's -command options
+##
+## ( based on 'command.tcl' included source archive of tktable extension )
+##
+require 'tk'
+require 'tkextlib/tktable'
+
+# create the table
+data = TkVariable.new_hash
+rows = 10
+cols = 10
+
+# fill table variable
+((-(rows))..rows).each{|x|
+ ((-(cols))..cols).each{|y|
+ data[x,y] = "#{x} x #{y}"
+ }
+}
+
+lbl = TkLabel.new(:text=>"TkTable :command Example")
+cur_var = TkVariable.new
+current = TkLabel.new(:textvariable=>cur_var, :width=>5)
+ent_var = TkVariable.new
+entry = TkEntry.new(:textvariable=>ent_var)
+
+table = Tk::TkTable.new(:rows=>rows, :cols=>cols,
+ :command=>[proc{|mode, cell, val|
+ if (mode == :w)
+ data[cell] = val
+ else
+ begin
+ data[cell] # exist
+ rescue
+ '' # not exist
+ end
+ end
+ }, '%i %C %s'],
+ :width=>6, :height=>6,
+ :titlerows=>1, :titlecols=>1,
+ :roworigin=>-1, :colorigin=>-1,
+ :rowstretchmode=>:last, :colstretchmode=>:last,
+ :rowtagcommand=>proc{|row|
+ row = Integer(row)
+ (row>0 && row%2 == 1)? 'OddRow': ''
+ },
+ :coltagcommand=>proc{|col|
+ col = Integer(col)
+ (col>0 && col%2 == 1)? 'OddCol': ''
+ },
+ :selectmode=>:extended, :flashmode=>true,
+ :rowstretch=>:unset, :colstretch=>:unset,
+ :browsecommand=>[proc{|w, s|
+ cur_var.value = s
+ ent_var.value = w.get(s)
+ }, '%W %S'],
+ :validate=>true,
+ :validatecommand=>proc{|e|
+ ent_var.value = e.new_value; true
+ })
+=begin
+ :validatecommand=>[
+ proc{|s|
+ ent_var.value = s; true
+ }, '%S'])
+=end
+
+sx = table.xscrollbar(TkScrollbar.new)
+sy = table.yscrollbar(TkScrollbar.new)
+
+entry.bind('Return', proc{|w| table.curvalue = w.value}, '%W')
+
+Tk.grid(lbl, '-', '-', :sticky=>:ew)
+Tk.grid(current, entry, '-', :sticky=>:ew)
+Tk.grid(table, '-', sy, :sticky=>:news)
+Tk.grid(sx, '-', :sticky=>:ew)
+
+Tk.root.grid_columnconfig(1, :weight=>1)
+Tk.root.grid_rowconfig(2, :weight=>1)
+
+table.tag_configure('OddRow', :bg=>'orange', :fg=>'purple')
+table.tag_configure('OddCol', :bg=>'brown', :fg=>'pink')
+
+puts "Table is #{table.path}"
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tktable/debug.rb b/ext/tk/sample/tkextlib/tktable/debug.rb
new file mode 100644
index 0000000000..d5cd5e49ba
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/debug.rb
@@ -0,0 +1,101 @@
+#!/usr/bin/env ruby
+##
+## debug.rb
+##
+## This demo uses most features of the table widget
+##
+## ( based on 'debug.tcl' included source archive of tktable extension )
+##
+require 'tk'
+require 'tkextlib/tktable'
+
+# create the table
+ary = TkVariable.new_hash
+rows = 25
+cols = 20
+
+# fill table variable
+((-(rows))..rows).each{|x|
+ ((-(cols))..cols).each{|y|
+ ary[x,y] = "r#{x},c#{y}"
+ }
+}
+
+lbl = TkLabel.new(:text=>"TkTable v2 Example")
+
+table = Tk::TkTable.new(:rows=>rows, :cols=>cols, :variable=>ary,
+ :width=>6, :height=>6,
+ :titlerows=>1, :titlecols=>2,
+ :roworigin=>-5, :colorigin=>-2,
+ :coltagcommand=>proc{|col|
+ col = Integer(col)
+ (col>0 && col%2 == 1)? 'OddCol': ''
+ },
+ :selectmode=>:extended, :flashmode=>true,
+ :rowstretch=>:unset, :colstretch=>:unset,
+ :selecttitles=>false, :drawmode=>:single)
+
+sx = table.xscrollbar(TkScrollbar.new)
+sy = table.yscrollbar(TkScrollbar.new)
+
+btn = TkButton.new(:text=>'Exit', :command=>proc{exit})
+
+Tk.grid(lbl, '-', :sticky=>:ew)
+Tk.grid(table, sy, :sticky=>:news)
+Tk.grid(sx, :sticky=>:ew)
+Tk.grid(btn, :sticky=>:ew, :columnspan=>2)
+
+Tk.root.grid_columnconfig(0, :weight=>1)
+Tk.root.grid_rowconfig(1, :weight=>1)
+
+table.tag_configure('OddCol', :bg=>'brown', :fg=>'pink')
+table.tag_configure('title', :bg=>'red', :fg=>'green', :relief=>:sunken)
+table.tag_configure('dis', :state=>:disabled)
+
+first = table[:colorigin]
+%w(n s e w nw ne sw se c).each_with_index{|anchor, idx|
+ table.tag_configure(anchor, :anchor=>anchor)
+ table.tag_row(anchor, idx)
+ table.set([idx,first], anchor)
+}
+courier = TkFont.new(:family=>'Courier', :size=>10)
+table.tag_configure('s', :font=>courier, :justify=>:center)
+
+logo = TkPhotoImage.new(:file=>File.join(File.dirname(File.expand_path(__FILE__)), 'tcllogo.gif'))
+table.tag_configure('logo', :image=>logo, :showtext=>true)
+table.tag_cell('logo', [1,2], [2,3], [4,1])
+table.tag_cell('dis', [2,1], [1,-1], [3,0])
+table.set_width([-2,8], [-1,9], [0, 12], [4, 14])
+
+table.set([1,1], "multi-line\ntext\nmight be\ninteresting",
+ [3,2], "more\nmulti-line\nplaying\n",
+ [2,2], "null\0byte")
+
+# This is in the row span
+l = TkLabel.new(table, :text=>'Window s', :bg=>'yellow')
+table.window_configure([6,0], :sticky=>:s, :window=>l)
+
+# This is in the row titles
+l = TkLabel.new(table, :text=>'Window ne', :bg=>'yellow')
+table.window_configure([4,-1], :sticky=>:ne, :window=>l)
+
+# This will get swallowed by a span
+l = TkLabel.new(table, :text=>'Window ew', :bg=>'yellow')
+table.window_configure([5,3], :sticky=>:ew, :window=>l)
+
+# This is in the col titles
+l = TkLabel.new(table, :text=>'Window news', :bg=>'yellow')
+table.window_configure([-5,1], :sticky=>:news, :window=>l)
+
+l = TkLabel.new(table.winfo_parent, :text=>'Sibling l', :bg=>'orange')
+table.window_configure([5,1], :sticky=>:news, :window=>l)
+
+if table.span_list.empty?
+ table.set_spans([-1,-2], [0,3], [1,2], [0,5], [3,2], [2,2], [6,0], [4,0])
+end
+
+puts "Table is #{table.path} with array #{(table['variable'])}"
+
+# table.postscript(:file=>'out.ps', :first=>:origin, :last=>[2,2])
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tktable/dynarows.rb b/ext/tk/sample/tkextlib/tktable/dynarows.rb
new file mode 100644
index 0000000000..d083e26559
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/dynarows.rb
@@ -0,0 +1,99 @@
+#!/usr/bin/env ruby
+##
+## dynarows.rb
+##
+## This demos shows the use of the validation mechanism of the table
+## and uses the table's cache (no -command or -variable) with a cute
+## dynamic row routine.
+##
+## ( based on 'dynarows.tcl' included source archive of tktable extension )
+##
+require 'tk'
+require 'tkextlib/tktable'
+
+def table_validate(w, idx)
+ return unless idx =~ /^(\d+),(\d+)$/
+ row = Integer($1)
+ col = Integer($2)
+ val = w.get(idx)
+
+ [w, idx]
+ nrows = w[:rows]
+ return if row == nrows - 1 && val == ''
+
+ begin
+ time = Tk.tk_call('clock', 'scan', val)
+ date = []
+ Tk.tk_call('clock', 'format', time,
+ :format=>'%m %d %Y').split(' ').each{|item|
+ date << item.sub(/^\s*0*/,'')
+ }
+ w.set(idx, date.join('/'))
+ if row == nrows - 1
+ if w.get([row,1]) != '' && w.get([row,2]) != ''
+ w.tag_row_reset(row)
+ w.set([row,0], row)
+ nrows += 1
+ row += 1
+ w.configure(:rows=>nrows)
+ w.tag_row('unset', row)
+ w.set([row,0], '*')
+ w.see([row,1])
+ w.activate([row,1])
+ end
+ end
+ rescue
+ Tk.bell
+ w.activate(idx)
+ w.selection_clear_all
+ w.selection_set(:active)
+ w.see(:active)
+ end
+end
+
+
+lbl = TkLabel.new(:text=>"Dynamic Date Validated Rows")
+
+table = Tk::TkTable.new(:rows=>2, :cols=>3, :cache=>1, :selecttype=>:row,
+ :titlerows=>1, :titlecols=>1, :height=>5,
+ :colstretch=>:unset, :rowstretch=>:unset,
+ :autoclear=>true,
+ :browsecommand=>[
+ proc{|w,s| table_validate(w, s)},
+ '%W %s'
+ ])
+table.set([0,1], 'Begin', [0,2], 'End', [1,0], '*')
+table.tag_configure('unset', :fg=>'#008811')
+table.tag_configure('title', :fg=>'red')
+table.tag_row('unset', 1)
+table.set_width(0,3)
+
+sx = table.xscrollbar(TkScrollbar.new)
+sy = table.yscrollbar(TkScrollbar.new)
+
+Tk.grid(lbl, '-', :sticky=>:ew)
+Tk.grid(table, sy, :sticky=>:news)
+Tk.grid(sx, :sticky=>:ew)
+
+Tk.root.grid_columnconfig(0, :weight=>1)
+Tk.root.grid_rowconfig(1, :weight=>1)
+
+rtn_proc = proc{|w|
+ r = w.row_index(:active)
+ c = w.col_index(:active)
+
+ if c == 2
+ r += 1
+ w.activate([r,1])
+ else
+ c += 1
+ w.activate([r,c])
+ end
+ w.see(:active)
+ Tk.callback_break
+}
+
+table.bind('Return', rtn_proc, '%W')
+table.bind('KP_Enter', rtn_proc, '%W')
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tktable/maxsize.rb b/ext/tk/sample/tkextlib/tktable/maxsize.rb
new file mode 100644
index 0000000000..aff68ff377
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/maxsize.rb
@@ -0,0 +1,67 @@
+#!/usr/bin/env ruby
+##
+## maxsize.rb
+##
+## This demo uses a really big table. The big startup time is in
+## filling the table's Tcl array var.
+##
+## ( based on 'maxsize.tcl' included source archive of tktable extension )
+##
+require 'tk'
+require 'tkextlib/tktable'
+
+ary = TkVariable.new_hash
+rows = 40000
+cols = 10
+
+# fill table variable
+((-(rows))..rows).each{|x|
+ ((-(cols))..cols).each{|y|
+ ary[x,y] = "#{x},#{y}"
+ }
+}
+
+lbl = TkLabel.new(:text=>"TkTable v2 Example")
+
+table = Tk::TkTable.new(:rows=>rows, :cols=>cols, :variable=>ary,
+ :width=>6, :height=>8,
+ :titlerows=>1, :titlecols=>1,
+ :coltagcommand=>proc{|col|
+ col = Integer(col)
+ (col>0 && col%2 == 1)? 'OddCol': ''
+ },
+ :selectmode=>:extended,
+ :colstretch=>:unset, :rowstretch=>:unset,
+ :selecttitles=>false, :drawmode=>:slow)
+
+sx = table.xscrollbar(TkScrollbar.new)
+sy = table.yscrollbar(TkScrollbar.new)
+
+btn = TkButton.new(:text=>'Exit', :command=>proc{exit})
+
+Tk.grid(lbl, '-', :sticky=>:ew)
+Tk.grid(table, sy, :sticky=>:news)
+Tk.grid(sx, :sticky=>:ew)
+Tk.grid(btn, :sticky=>:ew, :columnspan=>2)
+
+Tk.root.grid_columnconfig(0, :weight=>1)
+Tk.root.grid_rowconfig(1, :weight=>1)
+
+table.tag_configure('OddCol', :bg=>'brown', :fg=>'pink')
+table.tag_configure('title', :bg=>'red', :fg=>'blue', :relief=>:sunken)
+table.tag_configure('dis', :state=>:disabled)
+
+first = table[:colorigin]
+%w(n s e w nw ne sw se c).each_with_index{|anchor, idx|
+ table.tag_configure(anchor, :anchor=>anchor)
+ table.tag_row(anchor, idx)
+ table.set([idx,first], anchor)
+}
+courier = TkFont.new(:family=>'Courier', :size=>10)
+table.tag_configure('s', :font=>courier, :justify=>:center)
+
+table.set_width([-2, 8], [-1, 9], [0, 12], [4, 14])
+
+puts "Table is #{table.path} with array #{(table['variable'])}"
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tktable/spreadsheet.rb b/ext/tk/sample/tkextlib/tktable/spreadsheet.rb
new file mode 100644
index 0000000000..9da896f5a7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/spreadsheet.rb
@@ -0,0 +1,137 @@
+#!/usr/bin/env ruby
+##
+## spreadsheet.rb
+##
+## This demos shows how you can simulate a 3D table
+## and has other basic features to begin a basic spreadsheet
+##
+## ( based on 'spreadsheet.tcl' included source archive of tktable extension )
+##
+require 'tk'
+require 'tkextlib/tktable'
+
+rows = 10
+cols = 10
+cur_var = TkVariable.new
+table_list = Hash.new{|hash, key| hash[key] = TkVariable.new_hash}
+page = TkVariable.new('AA')
+color = Hash.new('pink')
+color['AA'] = 'orange'
+color['BB'] = 'blue'
+color['CC'] = 'green'
+
+def colorize(num)
+ num = Integer(num)
+ return 'colored' if (num > 0 && num % 2 == 1)
+end
+
+def fill_table(tbl_list, page, r=10, c=10)
+ ary = tbl_list[page]
+
+ (0...r).each{|i|
+ (0...c).each{|j|
+ if i!=0 && j!=0
+ ary[i,j] = "#{page} #{i},#{j}"
+ elsif i!=0
+ ary[i,j] = i.to_s
+ else
+ ary[i,j] = (64+j).chr
+ end
+ }
+ }
+end
+
+def changepage(tbl_list, tbl, ent, col, var, elem, op)
+ if elem != ''
+ page = var[elem]
+ else
+ page = var.value
+ end
+ if tbl[:variable] != tbl_list[page].id
+ tbl.selection_clear_all
+ tbl.variable(tbl_list[page])
+ ent.textvariable(tbl_list[page].ref('active'))
+ tbl.activate('origin')
+ tbl.tag_configure('colored', :bg=>col[page])
+ tbl.see('active')
+ end
+end
+
+lbl = TkLabel.new(:text=>"TkTable v1 Spreadsheet Example")
+
+current = TkLabel.new(:textvariable=>cur_var, :width=>5)
+entry = TkEntry.new(:textvariable=>table_list[page.value].ref('active'))
+lpage = TkLabel.new(:text=>'PAGE:', :width=>6, :anchor=>:e)
+optmenu = TkOptionMenubutton.new(page, *(%w(AA BB CC DD)))
+
+fill_table(table_list, page.value)
+fill_table(table_list, 'BB', Integer(rows/2), Integer(cols/2))
+
+table = Tk::TkTable.new(:rows=>rows, :cols=>cols, :width=>5, :height=>5,
+ :variable=>table_list[page.value],
+ :titlerows=>1, :titlecols=>1,
+ :coltagcommand=>proc{|n| colorize(n)},
+ :flashmode=>true, :selectmode=>:extended,
+ :colstretch=>:unset, :rowstretch=>:unset,
+ :browsecommand=>proc{|e| cur_var.value = e.new_index})
+
+page.trace(:w, proc{|var, elem, op|
+ changepage(table_list, table, entry, color, var, elem, op)
+ })
+
+table.tag_configure('colored', :bg=>color[page.value])
+table.tag_configure('title', :fg=>'red', :relief=>:groove)
+table.tag_configure('blue', :bg=>'blue')
+table.tag_configure('green', :bg=>'green')
+
+table.tag_cell('green', [6,3], [5,7], [4,9])
+table.tag_cell('blue', [8,8])
+table.tag_row('blue', 7)
+table.tag_col('blue', 6, 8)
+table.set_width([0, 3], [2, 7])
+
+sx = table.xscrollbar(TkScrollbar.new)
+sy = table.yscrollbar(TkScrollbar.new)
+
+btn = TkButton.new(:text=>'Exit', :command=>proc{exit})
+
+Tk.grid(lbl, '-', '-', '-', '-', :sticky=>:ew)
+Tk.grid(current, entry, lpage, optmenu, '-', :sticky=>:ew)
+Tk.grid(table, '-', '-', '-', sy, :sticky=>:ns)
+Tk.grid(sx, '-', '-', '-', :sticky=>:ew)
+Tk.grid(btn, '-', '-', '-', '-', :sticky=>:ew)
+
+Tk.root.grid_columnconfig(1, :weight=>1)
+Tk.root.grid_rowconfig(2, :weight=>1)
+
+table.grid_configure(:sticky=>:news)
+
+entry.bind('Return', proc{
+ r = table.row_index(:active)
+ c = table.col_index(:active)
+ rmax = table[:rows]
+ cmax = table[:cols]
+
+ c += 1
+ if c == cmax
+ c = table[:titlecols]
+ r += 1
+ if r == rmax
+ r = table[:titlerows]
+ end
+ end
+ table.activate([r, c])
+ table.see('active')
+ })
+
+menu = TkMenu.new
+m_file = TkMenu.new(menu)
+Tk.root.menu(menu)
+menu.add(:cascade, :label=>'File', :underline=>0, :menu=>m_file)
+m_file.add(:command, :label=>'Fill Array',
+ :command=>proc{ fill_table(table_list, page.value) })
+m_file.add(:command, :label=>'Quit', :command=>proc{exit})
+
+puts "Table is #{table.path} with array #{(table['variable'])}"
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/tktable/tcllogo.gif b/ext/tk/sample/tkextlib/tktable/tcllogo.gif
new file mode 100755
index 0000000000..4603d4ff41
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/tcllogo.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/tktable/valid.rb b/ext/tk/sample/tkextlib/tktable/valid.rb
new file mode 100644
index 0000000000..e5d3f11d84
--- /dev/null
+++ b/ext/tk/sample/tkextlib/tktable/valid.rb
@@ -0,0 +1,88 @@
+#!/usr/bin/env ruby
+##
+## valid.rb
+##
+## This demos shows the use of the validation mechanism of the table
+## and uses the table's cache (no -command or -variable)
+##
+## ( based on 'valid.tcl' included source archive of tktable extension )
+##
+require 'tk'
+require 'tkextlib/tktable'
+
+rows = 10
+cols = 10
+
+def colorize(num)
+ num = Integer(num)
+ return 'colored' if (num > 0 && num % 2 == 1)
+end
+
+def fill_headers(w, r=10, c=10)
+ (1..(r-1)).each{|i| w.set([i,0], i.to_s)}
+
+ (1..(c-1)).each{|j|
+ if j % 3 == 1
+ w.set([0,j], 'AlphaNum')
+ elsif j % 2 == 1
+ w.set([0,j], 'Alpha')
+ elsif j != 0
+ w.set([0,j], 'Real')
+ end
+ }
+end
+
+def validate_proc(c, val)
+ if c % 3 == 1
+ # AlphaNum
+ regexp = /^[A-Za-z0-9 ]*$/
+ elsif c % 2 == 1
+ # Alpha
+ regexp = /^[A-Za-z ]*$/
+ elsif c != 0
+ # 'Real'
+ regexp = /^[-+]?[0-9]*\.?[0-9]*([0-9]\.?e[-+]?[0-9]*)?$/
+ end
+ if val =~ regexp
+ return true
+ else
+ Tk.bell
+ return false
+ end
+end
+
+lbl = TkLabel.new(:text=>"TkTable v1 Validated Table Example")
+
+table = Tk::TkTable.new(:rows=>rows, :cols=>cols, :cache=>1,
+ :width=>5, :height=>5, :titlerows=>1, :titlecols=>1,
+ :coltagcommand=>proc{|n| colorize(n)},
+ :flashmode=>true, :selectmode=>:extended,
+ :colstretch=>:unset, :rowstretch=>:unset,
+ :validate=>true,
+ :validatecommand=>proc{|e|
+ unless e.widget.tag_include?('title', e.index)
+ validate_proc(e.column, e.new_value)
+ end } )
+
+fill_headers(table)
+
+table.tag_configure('colored', :bg=>'lightblue')
+table.tag_configure('title', :fg=>'red')
+table.set_width(0,3)
+
+sx = table.xscrollbar(TkScrollbar.new)
+sy = table.yscrollbar(TkScrollbar.new)
+
+btn = TkButton.new(:text=>'Exit', :command=>proc{exit})
+
+Tk.grid(lbl, '-', :sticky=>:ew)
+Tk.grid(table, sy, :sticky=>:news)
+Tk.grid(sx, :sticky=>:ew)
+Tk.grid(btn, '-', :sticky=>:ew)
+
+Tk.root.grid_columnconfig(0, :weight=>1)
+Tk.root.grid_rowconfig(1, :weight=>1)
+
+puts "Table is #{table.path}"
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/treectrl/bitmaps.rb b/ext/tk/sample/tkextlib/treectrl/bitmaps.rb
new file mode 100644
index 0000000000..745e6a2e5b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/bitmaps.rb
@@ -0,0 +1,76 @@
+#
+# Demo: Bitmaps
+#
+def demoBitmaps(t)
+ #if $Version_1_1_OrLater
+ if @has_bgimg
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :selectmode=>:browse, :orient=>:horizontal, :wrap=>'5 items',
+ :showheader=>false, :backgroundimage=>@images['sky'])
+ else
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :selectmode=>:browse, :orient=>:horizontal, :wrap=>'5 items',
+ :showheader=>false)
+ end
+
+ if $HasColumnCreate
+ t.column_create(:itembackground=>['gray90', []])
+ else
+ t.column_configure(0, :itembackground=>['gray90', []])
+ end
+
+ t.element_create('elemTxt', :text,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('elemSelTxt', :rect, :showfocus=>true,
+ :fill=>[@SystemHighlight, ['selected', 'focus']])
+ t.element_create('elemSelBmp', :rect, :outlinewidth=>4,
+ :outline=>[@SystemHighlight, ['selected', 'focus']])
+ t.element_create('elemBmp', :bitmap,
+ :foreground=>[@SystemHighlight, ['selected', 'focus']],
+ :background=>'linen',
+ :bitmap=>['question' ['selected']])
+
+ s = t.style_create('STYLE', :orient=>:vertical)
+ t.style_elements(s, ['elemSelBmp', 'elemBmp', 'elemSelTxt', 'elemTxt'])
+ t.style_layout(s, 'elemSelBmp', :union=>'elemBmp', :ipadx=>6, :ipady=>6)
+ t.style_layout(s, 'elemBmp', :pady=>[0, 6], :expand=>:we)
+ t.style_layout(s, 'elemSelTxt', :union=>'elemTxt', :ipadx=>2)
+ t.style_layout(s, 'elemTxt', :expand=>:we)
+
+ # Set default item style
+ if $Version_1_1_OrLater
+ t.defaultstyle = [s]
+ end
+
+ bitmap_names = %w(error gray75 gray50 gray25 gray12
+ hourglass info questhead question warning)
+
+ bitmap_names.each{|name|
+ i = t.item_create
+ unless $Version_1_1_OrLater
+ t.item_style_set(i, 0, s)
+ end
+ t.item_text(i, 0, name)
+ t.item_element_configure(i, 0, 'elemBmp', :bitmap=>name)
+ t.item_lastchild(:root, i)
+ }
+
+ bitmap_names.each{|name|
+ i = t.item_create
+ t.item_style_set(i, 0, s)
+ t.item_text(i, 0, name)
+ if true
+ t.item_element_configure(i, 0, 'elemBmp', :bitmap=>name,
+ :foreground=>['brown', ''],
+ :background=>['', ''])
+ else
+ t.item_element_configure(i, 0, 'elemBmp', :bitmap=>name,
+ :foreground=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'brown', []
+ ],
+ :background=>['', []])
+ end
+ t.item_lastchild(:root, i)
+ }
+end
diff --git a/ext/tk/sample/tkextlib/treectrl/demo.rb b/ext/tk/sample/tkextlib/treectrl/demo.rb
new file mode 100644
index 0000000000..eed95d0e1c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/demo.rb
@@ -0,0 +1,1311 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/treectrl'
+
+$ScriptDir = File.dirname(File.expand_path(__FILE__))
+
+$HasColumnCreate = Tk::TreeCtrl::HasColumnCreateCommand
+
+$Version_1_1_OrLater = (TkPackage.vcompare(Tk::TreeCtrl.package_version, '1.1') >= 0)
+
+#if Hash.instance_methods.include?(:key)
+if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ # ruby 1.9.x --> use Hash#key
+ # Because Hash#index show warning "Hash#index is deprecated; use Hash#key".
+else
+ # ruby 1.8.x --> use Hash#index
+ class Hash
+ alias key index
+ end
+end
+
+class TkTreeCtrl_demo
+ def initialize(dir)
+ @ScriptDir = dir || '.'
+
+ @thisPlatform = Tk::PLATFORM['platform']
+ if @thisPlatform == 'unix' && Tk.windowingsystem == 'aqua'
+ @thisPlatform = 'macosx'
+ end
+
+ @RandomN = [500]
+
+ @images = Hash.new
+ @sel_images = Hash.new
+
+ @popup = Hash.new
+ @mTree = Hash.new
+ @mHeader = Hash.new
+
+ @non_clear_list = []
+
+ @demoCmd = Hash.new
+ @demoFile = Hash.new
+
+ # Get default colors
+ w = TkListbox.new
+ @SystemButtonFace = w[:highlightbackground]
+ @SystemHighlight = w[:selectbackground]
+ @SystemHighlightText = w[:selectforeground]
+ w.destroy
+
+ ####################
+
+ make_source_window()
+ make_menubar()
+ make_main_window()
+
+ if $Version_1_1_OrLater
+ begin
+ @tree2[:backgroundimage]
+ @has_bgimg = true
+ rescue
+ @has_bgimg = false
+ end
+ else
+ @has_bgimg = false
+ end
+
+ ####################
+
+ make_list_popup()
+ make_header_popup()
+
+ init_pics('sky')
+
+ ####################
+
+ @tree2.bind('ButtonPress-3',
+ proc{|w, x, y, rootx, rooty|
+ show_list_popup(w, x, y, rootx, rooty)
+ }, '%W %x %y %X %Y')
+
+ # Allow "scan" bindings
+ if @thisPlatform == 'windows'
+ @tree2.bind_remove('Control-ButtonPress-3')
+ end
+
+ ####################
+
+ init_demo_scripts_module()
+ load_demo_scripts()
+ init_demo_list()
+
+ ####################
+
+ @tree1.notify_bind(@tree1, 'Selection',
+ proc{|c, t|
+ if c == 1
+ item = t.selection_get[0]
+ demo_set(@demoCmd[item], @demoFile[item])
+ end
+ }, '%c %T')
+
+ # When one item is selected in the demo list, display the styles in
+ # that item.
+ # See DemoClear for why the tag "DontDelete" is used
+ @tree2.notify_bind('DontDelete', 'Selection',
+ proc{|c, t|
+ display_styles_in_item(t.selection_get[0]) if c == 1
+ }, '%c %T')
+ end
+
+ ##########################
+
+ def init_pics(*args)
+ args.each{|pat|
+ unless TkImage.names.find{|img| (name = @images.key(img)) && File.fnmatch(pat, name)}
+ Dir.glob(File.join(@ScriptDir, 'pics', "#{pat}.gif")).each{|file|
+ name = File.basename(file, '.gif')
+ img = TkPhotoImage.new(:file=>file)
+ @images[name] = img
+ @sel_images[name] = TkPhotoImage.new
+ @sel_images[name].copy(img)
+ Tk::TreeCtrl.image_tint(@sel_images[name], @SystemHighlight, 128)
+ }
+ end
+ }
+ end
+
+ ##########################
+
+ private
+
+ def make_menubar
+ menuspec = [
+ [['File']]
+ ]
+ if Tk::PLATFORM['platform'] != 'unix'
+ TkConsole.create
+ TkConsole.eval('.console conf -height 8')
+ menuspec[0] << ['Console', proc{
+ if TkComm.bool(TkConsole.eval('winfo ismapped .'))
+ TkConsole.hide
+ else
+ TkConsole.show
+ end
+ }]
+ end
+ menuspec[0] << ['View Source', proc{toggle_source_window()}]
+ menuspec[0] << ['Quit', proc{exit}]
+ Tk.root.add_menubar(menuspec)
+ end
+
+ def make_source_window
+ @src_top = TkToplevel.new
+ f = TkFrame.new(@src_top, :borderwidth=>0)
+ case @thisPlatform
+ when 'macintosh', 'macos'
+ font = TkFont.new(['Geneva', 9])
+ when 'unix'
+ font = TkFont.new(['Courier', -12])
+ else
+ font = TkFont.new(['Courier', 9])
+ end
+
+ @src_txt = TkText.new(f, :font=>font, :tabs=>font.measure('1234'),
+ :wrap=>:none)
+ xscr = @src_txt.xscrollbar(TkScrollbar.new(f))
+ yscr = @src_txt.yscrollbar(TkScrollbar.new(f))
+
+ f.pack(:expand=>true, :fill=>:both)
+ f.grid_columnconfigure(0, :weight=>1)
+ f.grid_rowconfigure(0, :weight=>1)
+ @src_txt.grid(:row=>0, :column=>0, :sticky=>:news)
+ xscr.grid(:row=>1, :column=>0, :sticky=>:we)
+ yscr.grid(:row=>0, :column=>1, :sticky=>:ns)
+
+ @src_top.protocol('WM_DELETE_WINDOW', proc{@src_top.withdraw})
+ @src_top.geometry('-0+0')
+ @src_top.withdraw
+ end
+
+ def show_source(file)
+ @src_top.title("Demo Source: #{file}")
+ @src_txt.value = IO.read(File.join(@ScriptDir, file))
+ @src_txt.set_insert('1.0')
+ end
+
+ def toggle_source_window
+ if @src_top.winfo_mapped?
+ @src_top.withdraw
+ else
+ @src_top.deiconify
+ end
+ end
+
+ def tree_plus_scrollbars_in_a_frame(parent, h, v)
+ f = TkFrame.new(parent, :borderwidth=>1, :relief=>:sunken)
+ case @thisPlatform
+ when 'macintosh'
+ font = TkFont.new(['Geneva', 9])
+ when 'macos'
+ font = TkFont.new(['Lucida Grande', 11])
+ when 'unix'
+ font = TkFont.new(['Helvetica', -12])
+ else
+ # There is a bug on my Win98 box with Tk_MeasureChars() and
+ # MS Sans Serif 8.
+ font = TkFont.new(['MS Sans', 8])
+ end
+
+ tree = Tk::TreeCtrl.new(f, :highlightthickness=>0,
+ :borderwidth=>0, :font=>font)
+ tree[:xscrollincrement] = 20
+ tree.debug_configure(:enable=>false, :display=>false)
+
+ if h
+ h_scr = TkScrollbar.new(f, :orient=>:horizontal,
+ :command=>proc{|*args| tree.xview(*args)})
+ tree.notify_bind(h_scr, 'Scroll-x',
+ proc{|w, l, u| w.set(l, u)}, '%W %l %u')
+ h_scr.bind('ButtonPress-1', proc{tree.set_focus})
+ end
+
+ if v
+ v_scr = TkScrollbar.new(f, :orient=>:vertical,
+ :command=>proc{|*args| tree.yview(*args)})
+ tree.notify_bind(v_scr, 'Scroll-y',
+ proc{|w, l, u| w.set(l, u)}, '%W %l %u')
+ v_scr.bind('ButtonPress-1', proc{tree.set_focus})
+ end
+
+ f.grid_columnconfigure(0, :weight=>1)
+ f.grid_rowconfigure(0, :weight=>1)
+ tree.grid(:row=>0, :column=>0, :sticky=>:news)
+ h_scr.grid(:row=>1, :column=>0, :sticky=>:we) if h
+ v_scr.grid(:row=>0, :column=>1, :sticky=>:ns) if v
+
+ [f, tree]
+ end
+
+ def make_main_window
+ Tk.root.title('Tk::TreeCtrl Demo')
+
+ case @thisPlatform
+ when 'macintosh', 'macosx'
+ Tk.root.geometry('+40+40')
+ else
+ Tk.root.geometry('+0+30')
+ end
+
+ pane1 = TkPanedWindow.new(:orient=>:vertical, :borderwidth=>0)
+ pane2 = TkPanedWindow.new(:orient=>:horizontal, :borderwidth=>0)
+
+ # Tree + scrollbar: demos
+ f1, @tree1 = tree_plus_scrollbars_in_a_frame(nil, false, true)
+ @tree1.configure(:showbuttons=>false, :showlines=>:false,
+ :showroot=>false, :height=>100)
+ if $HasColumnCreate
+ @tree1.column_create(:text=>'List of Demos',
+ :expand=>true, :button=>false)
+ else
+ @tree1.column_configure(0, :text=>'List of Demos',
+ :expand=>true, :button=>false)
+ end
+
+ # Tree + scrollbar: styles + elements in list
+ f4, @tree4 = tree_plus_scrollbars_in_a_frame(nil, false, true)
+ @tree4.configure(:showroot=>false, :height=>140)
+ if $HasColumnCreate
+ @tree4.column_create(:text=>'Elements and Styles',
+ :expand=>true, :button=>false)
+ else
+ @tree4.column_configure(0, :text=>'Elements and Styles',
+ :expand=>true, :button=>false)
+ end
+
+ # Tree + scrollbar: styles + elements in selected item
+ f3, @tree3 = tree_plus_scrollbars_in_a_frame(nil, false, true)
+ @tree3.configure(:showroot=>false)
+ if $HasColumnCreate
+ @tree3.column_create(:text=>'Styles in Item',
+ :expand=>true, :button=>false)
+ else
+ @tree3.column_configure(0, :text=>'Styles in Item',
+ :expand=>true, :button=>false)
+ end
+
+ pane1.add(f1, f4, f3, :height=>150)
+ pane1.pack(:expand=>true, :fill=>:both)
+
+ # Frame on right
+ f2_base = TkFrame.new
+
+ # Tree + scrollbars
+ f2, @tree2 = tree_plus_scrollbars_in_a_frame(f2_base, true, true)
+ @tree2.configure(:indent=>19)
+ @tree2.debug_configure(:enable=>false, :display=>true,
+ :erasecolor=>'pink', :displaydelay=>30)
+
+ # Give it a big border to debug drawing
+ @tree2.configure(:borderwidth=>6, :relief=>:ridge, :highlightthickness=>3)
+
+ f2_base.grid_columnconfigure(0, :weight=>1)
+ f2_base.grid_rowconfigure(0, :weight=>1)
+ f2.grid(:row=>0, :column=>0, :sticky=>:news, :pady=>0)
+
+ pane2.add(pane1, :width=>200)
+ pane2.add(f2_base, :width=>450)
+
+ pane2.pack(:expand=>true, :fill=>:both)
+
+ ###
+ # A treectrl widget can generate the following built-in events:
+ # <ActiveItem> called when the active item changes
+ # <Collapse-before> called before an item is closed
+ # <Collapse-after> called after an item is closed
+ # <Expand-before> called before an item is opened
+ # <Expand-after> called after an item is opened
+ # <Selection> called when items are added to or removed from the selection
+ # <Scroll-x> called when horizontal scroll position changes
+ # <Scroll-y> called when vertical scroll position changes
+ #
+ # The application programmer can define custom events to be
+ # generated by the "T notify generate" command. The following events
+ # are generated by the example bindings.
+
+ @tree2.notify_install_event('Header')
+ @tree2.notify_install_detail('Header', 'invoke')
+
+ @tree2.notify_install_event('Drag')
+ @tree2.notify_install_detail('Drag', 'begin')
+ @tree2.notify_install_detail('Drag', 'end')
+ @tree2.notify_install_detail('Drag', 'receive')
+
+ @tree2.notify_install_event('Edit')
+ @tree2.notify_install_detail('Edit', 'accept')
+ end
+
+ def make_list_popup
+ @popup[:bgimg] = TkVariable.new
+ @popup[:bgmode] = TkVariable.new
+ @popup[:debug] = Hash.new{|h, k| h[k] = TkVariable.new}
+ @popup[:doublebuffer] = TkVariable.new
+ @popup[:linestyle] = TkVariable.new
+ @popup[:orient] = TkVariable.new
+ @popup[:selectmode] = TkVariable.new
+ @popup[:show] = Hash.new{|h, k| h[k] = TkVariable.new}
+
+ menuspec = [
+ [ 'Collapse', [], nil, '', {:menu_config=>{:tearoff=>false}} ],
+
+ [ 'Expand', [], nil, '', {:menu_config=>{:tearoff=>false}} ]
+ ]
+
+ # if $Version_1_1_OrLater
+ if @has_bgimg
+ menuspec << \
+ [ 'Background Image',
+ [
+ [ 'none', [@popup[:bgimg], 'none'], nil, '',
+ {:command=>proc{@tree2.backgroundimage = ''}} ],
+ [ 'sky', [@popup[:bgimg], 'sky'], nil, '',
+ {:command=>proc{
+ @tree2.backgroundimage = @images[@popup[:bgimg].value]}} ]
+ ],
+ nil, '', {:menu_config=>{:tearoff=>false}}
+ ]
+ end
+
+ menuspec.concat([
+ [ 'Background Mode',
+ %w(column index row visindex).collect{|val|
+ [ val, [@popup[:bgmode], val] , nil, '',
+ {:command=>proc{@tree2.backgroundmode = @popup[:bgmode].value}} ]
+ },
+ nil, '', {:menu_config=>{:tearoff=>false}}
+ ],
+
+ [ 'Debug',
+ [
+ [ 'Data', @popup[:debug][:data], nil, '',
+ {:command=>proc{
+ @tree2.debug_configure(:data=>@popup[:debug][:data].value)
+ }
+ } ],
+ [ 'Display', @popup[:debug][:display], nil, '',
+ {:command=>proc{
+ @tree2.debug_configure(:display=>@popup[:debug][:display].value)
+ }
+ } ],
+ [ 'Enable', @popup[:debug][:enable], nil, '',
+ {:command=>proc{
+ @tree2.debug_configure(:enable=>@popup[:debug][:enable].value)
+ }
+ } ]
+ ],
+ nil, '', {:menu_config=>{:tearoff=>false}}
+ ],
+
+ [ 'Buffering',
+ [
+ [ 'none', [@popup[:doublebuffer], 'none'], nil, '',
+ {:command=>proc{
+ @tree2.doublebuffer = @popup[:doublebuffer].value
+ }
+ } ],
+ [ 'item', [@popup[:doublebuffer], 'item'], nil, '',
+ {:command=>proc{
+ @tree2.doublebuffer = @popup[:doublebuffer].value
+ }
+ } ],
+ [ 'window', [@popup[:doublebuffer], 'window'], nil, '',
+ {:command=>proc{
+ @tree2.doublebuffer = @popup[:doublebuffer].value
+ }
+ } ]
+ ],
+ nil, '', {:menu_config=>{:tearoff=>false}}
+ ],
+
+ [ 'Line style',
+ [
+ [ 'dot', [@popup[:linestyle], 'dot'], nil, '',
+ {:command=>proc{@tree2.linestyle = @popup[:linestyle].value}} ],
+ [ 'solid', [@popup[:linestyle], 'solid'], nil, '',
+ {:command=>proc{@tree2.linestyle = @popup[:linestyle].value}} ]
+ ],
+ nil, '', {:menu_config=>{:tearoff=>false}}
+ ],
+
+ [ 'Orient',
+ [
+ [ 'Horizontal', [@popup[:orient], 'horizontal'], nil, '',
+ {:command=>proc{@tree2.orient = @popup[:orient].value}} ],
+ [ 'Vertical', [@popup[:orient], 'vertical'], nil, '',
+ {:command=>proc{@tree2.orient = @popup[:orient].value}} ]
+ ],
+ nil, '', {:menu_config=>{:tearoff=>false}}
+ ],
+
+ [ 'Selectmode',
+ %w(list browse extended multiple single).collect{|val|
+ [ val, [@popup[:selectmode], val] , nil, '',
+ {:command=>proc{@tree2.selectmode = @popup[:selectmode].value}} ]
+ },
+ nil, '', {:menu_config=>{:tearoff=>false}}
+ ],
+
+ [ 'Show',
+ [
+ [ 'Buttons', @popup[:show][:buttons], nil, '',
+ {:command=>proc{
+ @tree2.showbuttons = @popup[:show][:buttons].value
+ }
+ } ],
+ [ 'Header', @popup[:show][:header], nil, '',
+ {:command=>proc{
+ @tree2.showheader = @popup[:show][:header].value
+ }
+ } ],
+ [ 'Lines', @popup[:show][:lines], nil, '',
+ {:command=>proc{
+ @tree2.showlines = @popup[:show][:lines].value
+ }
+ } ],
+ [ 'Root', @popup[:show][:root], nil, '',
+ {:command=>proc{
+ @tree2.showroot = @popup[:show][:root].value
+ }
+ } ],
+ [ 'Root Button', @popup[:show][:rootbutton], nil, '',
+ {:command=>proc{
+ @tree2.showrootbutton = @popup[:show][:rootbutton].value
+ }
+ } ]
+ ],
+ nil, '', {:menu_config=>{:tearoff=>false}}
+ ],
+
+ [ 'Visible', [], nil, '', {:menu_config=>{:tearoff=>false}} ]
+ ])
+
+ m = TkMenu.new_menuspec(menuspec, @tree2, false)
+ @non_clear_list << m
+ @mTree[@tree2] = m
+ end
+
+ def show_list_popup(w, x, y, rootx, rooty)
+ id = w.identify(x, y)
+ unless id.empty?
+ if id[0] == 'header'
+ col = id[1]
+ @popup[:column].value = col
+ @popup[:arrow].value = w.column_cget(col, :arrow)
+ @popup[:arrowside].value = w.column_cget(col, :arrowside)
+ @popup[:arrowgravity].value = w.column_cget(col, :arrowgravity)
+ @popup[:expand].value = w.column_cget(col, :expand)
+ @popup[:squeeze].value = w.column_cget(col, :squeeze)
+ @popup[:justify].value = w.column_cget(col, :justify)
+ @mHeader[w].popup(rootx, rooty)
+ return
+ end
+ end
+
+ m = @mTree[w].entrycget('Collapse', :menu)
+ m.delete(0, :end)
+ if $Version_1_1_OrLater
+ m.add_command(:label=>'All', :command=>proc{w.item_collapse(:all)})
+ else
+ m.add_command(:label=>'All', :command=>proc{w.collapse(:all)})
+ end
+ unless id.empty?
+ if id[0] == 'item'
+ item = id[1]
+ if $Version_1_1_OrLater
+ m.add_command(:label=>"Item #{item}",
+ :command=>proc{w.item_collapse(item)})
+ m.add_command(:label=>"Item #{item} (recurse)",
+ :command=>proc{w.item_collapse_recurse(item)})
+ else
+ m.add_command(:label=>"Item #{item}",
+ :command=>proc{w.collapse(item)})
+ m.add_command(:label=>"Item #{item} (recurse)",
+ :command=>proc{w.collapse_recurse(item)})
+ end
+ end
+ end
+
+ m = @mTree[w].entrycget('Expand', :menu)
+ m.delete(0, :end)
+ if $Version_1_1_OrLater
+ m.add_command(:label=>'All', :command=>proc{w.item_expand(:all)})
+ else
+ m.add_command(:label=>'All', :command=>proc{w.expand(:all)})
+ end
+ unless id.empty?
+ if id[0] == 'item'
+ item = id[1]
+ if $Version_1_1_OrLater
+ m.add_command(:label=>"Item #{item}",
+ :command=>proc{w.item_expand(item)})
+ m.add_command(:label=>"Item #{item} (recurse)",
+ :command=>proc{w.item_expand_recurse(item)})
+ else
+ m.add_command(:label=>"Item #{item}",
+ :command=>proc{w.expand(item)})
+ m.add_command(:label=>"Item #{item} (recurse)",
+ :command=>proc{w.expand_recurse(item)})
+ end
+ end
+ end
+
+ [:data, :display, :enable].each{|k|
+ @popup[:debug][k].value = w.debug_cget(k)
+ }
+ # if $Version_1_1_OrLater
+ if @has_bgimg
+ @popup[:bgimg].value = @images.key(w[:backgroundimage])
+ end
+ @popup[:bgmode].value = w[:backgroundmode]
+ @popup[:doublebuffer].value = w[:doublebuffer]
+ @popup[:linestyle].value = w[:linestyle]
+ @popup[:orient].value = w[:orient]
+ @popup[:selectmode].value = w[:selectmode]
+ @popup[:show][:buttons].value = w[:showbuttons]
+ @popup[:show][:header].value = w[:showheader]
+ @popup[:show][:lines].value = w[:showlines]
+ @popup[:show][:root].value = w[:showroot]
+ @popup[:show][:rootbutton].value = w[:showrootbutton]
+
+ m = @mTree[w].entrycget('Visible', :menu)
+ m.delete(0, :end)
+ @popup[:visible] = []
+ (0...(w.numcolumns)).each{|i|
+ @popup[:visible][i] = TkVariable.new(w.column_cget(i, :visible))
+ txt = w.column_cget(i, :text)
+ img_name = w.column_cget(i, :image)
+ img_name = @images.key(img_name) if img_name.kind_of?(TkImage)
+ m.add_checkbutton(:variable=>@popup[:visible][i],
+ :label=>"Column #{i} \"#{txt}\" [#{img_name}]",
+ :command=>proc{w.column_configure(i, :visible=>@popup[:visible][i].value)})
+ }
+
+ @mTree[w].popup(rootx, rooty)
+ end
+
+ def make_header_popup
+ @popup[:column] = TkVariable.new unless @popup[:column]
+ @popup[:arrow] = TkVariable.new
+ @popup[:arrowside] = TkVariable.new
+ @popup[:arrowgravity] = TkVariable.new
+ @popup[:expand] = TkVariable.new
+ @popup[:squeeze] = TkVariable.new
+ @popup[:justify] = TkVariable.new
+
+ menuspec = [
+ [ 'Arrow',
+ [
+ [ 'None', [@popup[:arrow], 'none'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value, :arrow=>:none)
+ }
+ } ],
+ [ 'Up', [@popup[:arrow], 'up'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value, :arrow=>:up)
+ }
+ } ],
+ [ 'Down', [@popup[:arrow], 'down'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value, :arrow=>:down)
+ }
+ } ],
+
+ '---',
+
+ [ 'Side Left', [@popup[:arrowside], 'left'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value,
+ :arrowside=>:left)
+ }
+ } ],
+ [ 'Side Right', [@popup[:arrowside], 'right'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value,
+ :arrowside=>:right)
+ }
+ } ],
+
+ '---',
+
+ [ 'Gravity Left', [@popup[:arrowgravity], 'left'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value,
+ :arrowgravity=>:left)
+ }
+ } ],
+ [ 'Gravity Right', [@popup[:arrowgravity], 'right'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value,
+ :arrowgravity=>:right)
+ }
+ } ],
+ ],
+ nil, '', {:menu_config=>{:tearoff=>false}} ],
+
+ [ 'Expand', @popup[:expand], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value,
+ :expand=>@popup[:expand].value)
+ }
+ } ],
+
+ [ 'Squeeze', @popup[:squeeze], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value,
+ :squeeze=>@popup[:squeeze].value)
+ }
+ } ],
+
+ [ 'Justify',
+ [
+ [ 'Left', [@popup[:justify], 'left'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value, :justify=>:left)
+ }
+ } ],
+ [ 'Center', [@popup[:justify], 'center'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value,
+ :justify=>:center)
+ }
+ } ],
+ [ 'Right', [@popup[:justify], 'right'], nil, '',
+ {:command=>proc{
+ @tree2.column_configure(@popup[:column].value,
+ :justify=>:right)
+ }
+ } ]
+ ],
+ nil, '', {:menu_config=>{:tearoff=>false}} ]
+ ]
+
+ m = TkMenu.new_menuspec(menuspec, @tree2, false)
+ @non_clear_list << m
+ @mHeader[@tree2] = m
+ end
+
+ ###########################
+
+ def init_demo_scripts_module
+ @demo_scripts = Module.new
+
+ master = self
+
+ has_bgimg = @has_bgimg
+
+ scriptDir = @ScriptDir
+
+ thisPlatform = @thisPlatform
+
+ randomN = @RandomN
+
+ images = @images
+ sel_images = @sel_images
+
+ systemButtonFace = @SystemButtonFace
+ systemHighlight = @SystemHighlight
+ systemHighlightText = @SystemHighlightText
+
+ def master._pub_display_styles_in_item(item)
+ display_styles_in_item(item)
+ end
+ proc_disp_styles_in_item = proc{|item|
+ master._pub_display_styles_in_item(item)
+ }
+
+ @demo_scripts.instance_eval{
+ @master = master
+
+ @has_bgimg = has_bgimg
+
+ @display_styles_in_item = proc_disp_styles_in_item
+
+ @Priv = TkVarAccess.new('::TreeCtrl::Priv')
+
+ @ScriptDir = scriptDir
+
+ @thisPlatform = thisPlatform
+
+ @RandomN = randomN
+
+ @images = images
+ @sel_images = sel_images
+
+ @SystemButtonFace = systemButtonFace
+ @SystemHighlight = systemHighlight
+ @SystemHighlightText = systemHighlightText
+ }
+
+ class << @demo_scripts
+ def _get_binding
+ binding
+ end
+ private :_get_binding
+
+ def load_demo(file)
+ puts "load \"#{file}\"" if $DEBUG
+ begin
+ eval(IO.readlines(file).join, _get_binding())
+ rescue Exception => e
+ bt = e.backtrace
+
+ if bt[0] =~ /^([^:]+):(\d+):/
+ errline = $2.to_i
+ else
+ raise e
+ end
+
+ if bt[1] =~ /^([^:]+):(\d+):/
+ bt.unshift("#{file}:#{errline - $2.to_i + 1}")
+ raise e
+ else
+ raise e
+ end
+ end
+ end
+
+ def init_pics(*args)
+ @master.init_pics(*args)
+ end
+ end
+ end
+
+ def load_demo_scripts
+ # demo sources
+ [
+ 'bitmaps',
+ 'explorer',
+ 'help',
+ 'imovie',
+ 'layout',
+ 'mailwasher',
+ 'outlook-folders',
+ 'outlook-newgroup',
+ 'random',
+ 'www-options'
+ ].each{|f|
+ @demo_scripts.load_demo(File.join(@ScriptDir, "#{f}.rb"))
+ }
+ end
+
+ ###########################
+
+ def init_demo_list
+ @tree1.element_create('e1', :text,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ @tree1.element_create('e2', :rect, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus'],
+ ])
+ @tree1.style_create('s1')
+ @tree1.style_elements('s1', ['e2', 'e1'])
+
+ # Tk listbox has linespace + 1 height
+ @tree1.style_layout('s1', 'e2', :union=>['e1'],
+ :ipadx=>2, :ipady=>[0, 1], :iexpand=>:e)
+
+ if $Version_1_1_OrLater
+ @tree1.defaultstyle = 's1'
+ end
+
+ ###
+ [
+ ["Random #{@RandomN[0]} Items", :demoRandom, 'random.rb'],
+ ["Random #{@RandomN[0]} Items, Button Images", :demoRandom2, 'random.rb'],
+ ["Outlook Express (Folders)", :demoOutlookFolders, 'outlook-folders.rb'],
+ ["Outlook Express (Newsgroup)", :demoOutlookNewsgroup, 'outlook-newgroup.rb'],
+ ["Explorer (Details)", :demoExplorerDetails, 'explorer.rb'],
+ ["Explorer (List)", :demoExplorerList, 'explorer.rb'],
+ ["Explorer (Large icons)", :demoExplorerLargeIcons, 'explorer.rb'],
+ ["Explorer (Small icons)", :demoExplorerSmallIcons, 'explorer.rb'],
+ ["Internet Options", :demoInternetOptions, 'www-options.rb'],
+ ["Help Contents", :demoHelpContents, 'help.rb'],
+ ["Layout", :demoLayout, 'layout.rb'],
+ ["MailWasher", :demoMailWasher, 'mailwasher.rb'],
+ ["Bitmaps", :demoBitmaps, 'bitmaps.rb'],
+ ["iMovie", :demoIMovie, 'imovie.rb']
+ ].each{|label, cmd, file|
+ item = @tree1.item_create
+ @tree1.item_lastchild(:root, item)
+ unless $Version_1_1_OrLater
+ @tree1.item_style_set(item, 0, 's1')
+ end
+ @tree1.item_text(item, 0, label)
+ @demoCmd[item] = cmd
+ @demoFile[item] = file
+ }
+
+ @tree1.yview_moveto(0.0)
+ end
+
+ def demo_set(cmd, file)
+ demo_clear()
+ clicks = Tk::Clock.clicks
+ @demo_scripts.__send__(cmd, @tree2)
+ clicks = Tk::Clock.clicks - clicks
+ puts "set list in #{'%.2g'%(clicks/1000000.0)} seconds (#{clicks} clicks)"
+ @tree2.xview_moveto(0)
+ @tree2.yview_moveto(0)
+ Tk.update
+ display_styles_in_list()
+ show_source(file)
+ end
+
+ def display_styles_in_list
+ # Create elements and styles the first time this is called
+ if @tree4.style_names.empty?
+ @tree4.element_create('e1', :text,
+ :fill=>[@SystemHighlightText,['selected','focus']])
+ @tree4.element_create('e2', :text,
+ :fill=>[
+ @SystemHighlightText, ['selected','focus'],
+ '', ['selected','!focus'],
+ 'blue', []
+ ])
+ @tree4.element_create('e3', :rect, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected','focus'],
+ 'gray', ['selected', '!focus']
+ ])
+
+ @tree4.style_create('s1')
+ @tree4.style_elements('s1', ['e3', 'e1'])
+ @tree4.style_layout('s1', 'e3', :union=>['e1'], :ipadx=>1, :ipady=>[0,1])
+
+ @tree4.style_create('s2')
+ @tree4.style_elements('s2', ['e3', 'e1', 'e2'])
+ @tree4.style_layout('s2', 'e1', :padx=>[0,4])
+ @tree4.style_layout('s2', 'e3', :union=>['e1', 'e2'],
+ :ipadx=>1, :ipady=>[0,1])
+ end
+
+ # Clear the list
+ @tree4.item_delete(:all)
+
+ # One item for each element in the demo list
+ @tree2.element_names.sort.each{|elem|
+ if $Version_1_1_OrLater
+ item = @tree4.item_create(:button=>true)
+ @tree4.item_collapse(item)
+ else
+ item = @tree4.item_create
+ @tree4.item_hasbutton(item, true)
+ @tree4.collapse(item)
+ end
+ @tree4.item_style_set(item, 0, 's1')
+ @tree4.item_text(item, 0,
+ "Element #{elem} (#{@tree2.element_type(elem)})")
+
+ # One item for each configuration option for this element
+ @tree2.element_configinfo(elem).each{|name, x, y, default, current|
+ item2 = @tree4.item_create
+
+ if default == current
+ @tree4.item_style_set(item2, 0, 's1')
+ @tree4.item_complex(item2, [
+ ['e1', {:text=>"#{name} #{current.inspect}"}]
+ ])
+ else
+ @tree4.item_style_set(item2, 0, 's2')
+ @tree4.item_complex(item2, [
+ ['e1', {:text=>name}],
+ ['e2', {:text=>current.inspect}]
+ ])
+ end
+
+ @tree4.item_lastchild(item, item2)
+ }
+
+ @tree4.item_lastchild(:root, item)
+ }
+
+ # One item for each style in the demo list
+ @tree2.style_names.sort.each{|sty|
+ if $Version_1_1_OrLater
+ item = @tree4.item_create(:button=>true)
+ @tree4.item_collapse(item)
+ else
+ item = @tree4.item_create
+ @tree4.item_hasbutton(item, true)
+ @tree4.collapse(item)
+ end
+ @tree4.item_style_set(item, 0, 's1')
+ @tree4.item_text(item, 0, "Style #{sty}")
+
+ # One item for each element in the style
+ @tree2.style_elements(sty).each{|elem|
+ if $Version_1_1_OrLater
+ item2 = @tree4.item_create(:button=>true)
+ @tree4.item_collapse(item2)
+ else
+ item2 = @tree4.item_create
+ @tree4.item_hasbutton(item2, true)
+ @tree4.collapse(item2)
+ end
+ @tree4.item_style_set(item2, 0, 's1')
+ @tree4.item_text(item2, 0,
+ "Element #{elem} (#{@tree2.element_type(elem)})")
+
+ # One item for each layout option for this element in this style
+ @tree2.style_layout(sty, elem).each{|k, v|
+ item3 = @tree4.item_create
+ unless $Version_1_1_OrLater
+ @tree4.item_hasbutton(item3, false)
+ end
+ @tree4.item_style_set(item3, 0, 's1')
+ @tree4.item_text(item3, 0, "#{k} #{v.inspect}")
+ @tree4.item_lastchild(item2, item3)
+ }
+
+ @tree4.item_lastchild(item, item2)
+ }
+
+ @tree4.item_lastchild(:root, item)
+ }
+
+ @tree4.xview_moveto(0)
+ @tree4.yview_moveto(0)
+ end
+
+ def display_styles_in_item(item)
+ @tree3.column_configure(0, :text=>"Styles in item #{@tree2.index(item)}")
+
+ # Create elements and styles the first time this is called
+ if @tree3.style_names.empty?
+ @tree3.element_create('e1', :text,
+ :fill=>[@SystemHighlightText,['selected','focus']])
+ @tree3.element_create('e2', :text,
+ :fill=>[
+ @SystemHighlightText, ['selected','focus'],
+ '', ['selected','!focus'],
+ 'blue', []
+ ])
+ @tree3.element_create('e3', :rect, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected','focus'],
+ 'gray', ['selected', '!focus']
+ ])
+
+ @tree3.style_create('s1')
+ @tree3.style_elements('s1', ['e3', 'e1'])
+ @tree3.style_layout('s1', 'e3', :union=>['e1'], :ipadx=>1, :ipady=>[0,1])
+
+ @tree3.style_create('s2')
+ @tree3.style_elements('s2', ['e3', 'e1', 'e2'])
+ @tree3.style_layout('s2', 'e1', :padx=>[0,4])
+ @tree3.style_layout('s2', 'e3', :union=>['e1', 'e2'],
+ :ipadx=>1, :ipady=>[0,1])
+ end
+ # Clear the list
+ @tree3.item_delete(:all)
+
+ # One item for each item-column
+ column = 0
+ @tree2.item_style_set(item).each{|sty|
+ item2 = @tree3.item_create
+ if $Version_1_1_OrLater
+ @tree3.item_collapse(item2)
+ else
+ @tree3.collapse(item2)
+ end
+ @tree3.item_style_set(item2, 0, 's1')
+ @tree3.item_element_configure(item2, 0, 'e1',
+ :text=>"Column #{column}: Style #{sty}")
+
+ button = false
+
+ # One item for each element in this style
+ unless sty.to_s.empty?
+ @tree2.item_style_elements(item, column).each{|elem|
+ button = true
+ if $Version_1_1_OrLater
+ item3 = @tree3.item_create(:button=>true)
+ else
+ item3 = @tree3.item_create
+ @tree3.item_hasbutton(item3, true)
+ end
+ if $Version_1_1_OrLater
+ @tree3.item_collapse(item3)
+ else
+ @tree3.collapse(item3)
+ end
+ @tree3.item_style_set(item3, 0, 's1')
+ @tree3.item_element_configure(item3, 0, 'e1',
+ :text=>"Element #{elem} (#{@tree2.element_type(elem)})")
+
+ # One item for each configuration option in this element
+ @tree2.item_element_configinfo(item, column, elem) \
+ .each{|name, x, y, default, current|
+ item4 = @tree3.item_create
+ masterDefault = @tree2.element_cget(elem, name)
+ sameAsMaster = (masterDefault == current)
+ if !sameAsMaster && current == ''
+ sameAsMaster = true
+ current = masterDefault
+ end
+
+ if sameAsMaster
+ @tree3.item_style_set(item4, 0, 's1')
+ @tree3.item_complex(item4, [
+ ['e1',
+ {:text=>"#{name} #{current.inspect}"}]
+ ])
+ else
+ @tree3.item_style_set(item4, 0, 's2')
+ @tree3.item_complex(item4, [
+ ['e1', {:text=>name}],
+ ['e2', {:text=>current.inspect}]
+ ])
+ end
+ @tree3.item_lastchild(item3, item4)
+ }
+ @tree3.item_lastchild(item2, item3)
+ }
+ if $Version_1_1_OrLater
+ @tree3.item_configure(item2, :button=>true) if button
+ else
+ @tree3.item_hasbutton(item2, true) if button
+ end
+ end
+ @tree3.item_lastchild(:root, item2)
+ column += 1
+ }
+
+ @tree3.xview_moveto(0)
+ @tree3.yview_moveto(0)
+ end
+
+ def demo_clear
+ # Clear the demo list
+ @tree2.item_delete(:all)
+
+ # Clear all bindings on the demo list added by the previous demo.
+ # This is why DontDelete is used for the <Selection> binding.
+ @tree2.notify_bindinfo(@tree2).each{|ev|
+ @tree2.notify_bind_remove(@tree2, ev)
+ }
+
+ # Clear all run-time states
+ @tree2.state_names.each{|st| @tree2.state_undefine(st) }
+
+ # Clear the styles-in-item list
+ @tree3.item_delete(:all)
+
+ # Delete columns in demo list
+ while (@tree2.numcolumns > 0)
+ @tree2.column_delete(0)
+ end
+
+ # Delete all styles in demo list
+ @tree2.style_delete(*(@tree2.style_names))
+
+ # Delete all elements in demo list
+ @tree2.element_delete(*(@tree2.element_names))
+
+ if $Version_1_1_OrLater
+ @tree2.item_configure(:root, :button=>false)
+ @tree2.item_expand(:root)
+ else
+ @tree2.item_hasbutton(:root, false)
+ @tree2.expand(:root)
+ end
+
+ # Restore some happy defaults to the demo list
+ # if $Version_1_1_OrLater
+ if @has_bgimg
+ @tree2.configure(:orient=>:vertical, :wrap=>'',
+ :xscrollincrement=>0, :yscrollincrement=>0,
+ :itemheight=>0, :showheader=>true,
+ :background=>'white', :scrollmargin=>0,
+ :xscrolldelay=>50, :yscrolldelay=>50,
+ :openbuttonimage=>'', :closedbuttonimage=>'',
+ :backgroundmode=>:row, :treecolumn=>0, :indent=>19,
+ :defaultstyle=>'', :backgroundimage=>'')
+ else
+ @tree2.configure(:orient=>:vertical, :wrap=>'',
+ :xscrollincrement=>0, :yscrollincrement=>0,
+ :itemheight=>0, :showheader=>true,
+ :background=>'white', :scrollmargin=>0,
+ :xscrolldelay=>50, :yscrolldelay=>50,
+ :openbuttonimage=>'', :closedbuttonimage=>'',
+ :backgroundmode=>:row, :treecolumn=>0, :indent=>19)
+ end
+
+ # Restore default bindings to the demo list
+ @tree2.bindtags = [ @tree2, Tk::TreeCtrl, @tree2.winfo_toplevel, :all ]
+
+ @tree2.winfo_children.each{|w|
+ w.destroy unless @non_clear_list.include?(w)
+ }
+ end
+end
+
+TkTreeCtrl_demo.new($ScriptDir)
+
+##############################################
+
+def cursor_window(top = nil)
+ top.destroy if top.kind_of?(TkWindow) && top.winfo_exist?
+ top = TkToplevel.new(:title=>'Cursor Window')
+
+ c = TkCanvas.new(top, :background=>'white',
+ :width=>50*10, :highlightthickness=>0,
+ :borderwidth=>0).pack(:expand=>true, :fill=>:both)
+ cursors = %w(
+ X_cursor
+ arrow
+ based_arrow_down
+ based_arrow_up
+ boat
+ bogosity
+ bottom_left_corner
+ bottom_right_corner
+ bottom_side
+ bottom_tee
+ box_spiral
+ center_ptr
+ circle
+ clock
+ coffee_mug
+ cross
+ cross_reverse
+ crosshair
+ diamond_cross
+ dot
+ dotbox
+ double_arrow
+ draft_large
+ draft_small
+ draped_box
+ exchange
+ fleur
+ gobbler
+ gumby
+ hand1
+ hand2
+ heart
+ icon
+ iron_cross
+ left_ptr
+ left_side
+ left_tee
+ leftbutton
+ ll_angle
+ lr_angle
+ man
+ middlebutton
+ mouse
+ pencil
+ pirate
+ plus
+ question_arrow
+ right_ptr
+ right_side
+ right_tee
+ rightbutton
+ rtl_logo
+ sailboat
+ sb_down_arrow
+ sb_h_double_arrow
+ sb_left_arrow
+ sb_right_arrow
+ sb_up_arrow
+ sb_v_double_arrow
+ shuttle
+ sizing
+ spider
+ spraycan
+ star
+ target
+ tcross
+ top_left_arrow
+ top_left_corner
+ top_right_corner
+ top_side
+ top_tee
+ trek
+ ul_angle
+ umbrella
+ ur_angle
+ watch
+ xterm
+ )
+
+ orig_cursor = c.cursor
+ col = 0
+ row = 0
+
+ cursors.each{|cur|
+ x = col * 50
+ y = row * 40
+
+ begin
+ c.cursor = cur
+
+ r = TkcRectangle.new(c, x, y, x+50, y+40,
+ :fill=>'gray90', :outline=>'black', :width=>2)
+ t = TkcText.new(c, x+50/2, y+4, :text=>cur, :anchor=>:n, :width=>42)
+
+ col += 1
+ if col >= 10
+ col = 0
+ row += 1
+ end
+
+ r.bind('Enter', proc{c.cursor = cur; r.fill = 'linen'})
+ r.bind('Leave', proc{c.cursor = ''; r.fill = 'gray90'})
+
+ t.bind('Enter', proc{c.cursor = cur})
+ t.bind('Leave', proc{c.cursor = ''})
+ rescue
+ c.cursor = orig_cursor
+ end
+ }
+
+ c.cursor = orig_cursor
+ c.height = (row + 1) * 40
+end
+
+cursor_window()
+
+##############################################
+
+# A little screen magnifier for X11
+if Tk::PLATFORM['platform'] == 'unix' && Tk.windowingsystem != 'aqua'
+ def show_loupe(setting=nil)
+ loupe = (setting.kind_of?(Hash))? setting: {}
+ loupe[:zoom] = 3 unless loupe[:zoom]
+ loupe[:x] = 0 unless loupe[:x]
+ loupe[:y] = 0 unless loupe[:y]
+ loupe[:auto] = true unless loupe[:auto]
+ loupe[:delay] = 500 unless loupe[:delay]
+ loupe[:image] =
+ TkPhotoImage.new(:width=>150, :height=>150) unless loupe[:image]
+
+ top = TkToplevel.new(:geometry=>'-0+30',
+ :title=>'A little screen magnifier for X11')
+ TkLabel.new(top, :image=>loupe[:image]).pack
+
+ TkTimer.new(proc{loupe[:delay]}, -1, proc{
+ x, y = TkWinfo.pointerxy(Tk.root)
+ if loupe[:auto] || loupe[:x] != x || loupe[:y] != y
+ w = loupe[:image].width
+ h = loupe[:image].height
+ Tk::TreeCtrl.loupe(loupe[:image], x, y, w, h, loupe[:zoom])
+ loupe[:x] = x
+ loupe[:y] = y
+ end
+ }).start
+ end
+
+ show_loupe()
+end
+
+##############################################
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/treectrl/explorer.rb b/ext/tk/sample/tkextlib/treectrl/explorer.rb
new file mode 100644
index 0000000000..242777cbce
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/explorer.rb
@@ -0,0 +1,430 @@
+
+def demoExplorerAux(t, dir_proc, file_proc)
+ base_dir = File.dirname(File.dirname(@ScriptDir))
+
+ clicks = Tk::Clock.clicks
+ globDirs = Dir.glob(File.join(base_dir, '*')).find_all{|file|
+ FileTest.directory?(file)
+ }
+ clickGlobDirs = Tk::Clock.clicks - clicks
+
+ clicks = Tk::Clock.clicks
+ list = globDirs.sort
+ clickSortDirs = Tk::Clock.clicks - clicks
+
+ clicks = Tk::Clock.clicks
+ list.each{|file| dir_proc.call(file)}
+ clickAddDirs = Tk::Clock.clicks - clicks
+
+ clicks = Tk::Clock.clicks
+ globFiles = Dir.glob(File.join(base_dir, '*')).find_all{|file|
+ FileTest.file?(file)
+ }
+ clickGlobFiles = Tk::Clock.clicks - clicks
+
+ clicks = Tk::Clock.clicks
+ list = globFiles.sort
+ clickSortFiles = Tk::Clock.clicks - clicks
+
+ clicks = Tk::Clock.clicks
+ list.each{|file| file_proc.call(file)}
+ clickAddFiles = Tk::Clock.clicks - clicks
+
+ gd = '%.2g' % (clickGlobDirs / 1000000.0)
+ sd = '%.2g' % (clickSortDirs / 1000000.0)
+ ad = '%.2g' % (clickAddDirs / 1000000.0)
+ gf = '%.2g' % (clickGlobFiles / 1000000.0)
+ sf = '%.2g' % (clickSortFiles / 1000000.0)
+ af = '%.2g' % (clickAddFiles / 1000000.0)
+
+ puts "dirs(#{globDirs.length}) glob/sort/add #{gd}/#{sd}/#{ad} files(#{globFiles.length}) glob/sort/add #{gf}/#{sf}/#{af}"
+
+ @Priv[:DirCnt, t] = globDirs.length
+end
+
+#
+# Demo: explorer files
+#
+def demoExplorerDetails(t)
+ height = t.font.metrics(:linespace)
+ height = 18 if height < 18
+
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :itemheight=>height, :selectmode=>:extended,
+ :xscrollincrement=>20, :scrollmargin=>16,
+ :xscrolldelay=>[500, 50], :yscrolldelay=>[500, 50])
+
+ init_pics('small-*')
+
+ if $HasColumnCreate
+ t.column_create(:text=>'Name', :tag=>'name',
+ :width=>200, :arrow=>:up, :arrowpad=>6)
+ t.column_create(:text=>'Size', :tag=>'size', :justify=>:right,
+ :width=>60, :arrowside=>:left, :arrowgravity=>:right)
+ t.column_create(:text=>'Type', :tag=>'type', :width=>120)
+ t.column_create(:text=>'Modified', :tag=>'modified', :width=>130)
+ else
+ t.column_configure(0, :text=>'Name', :tag=>'name',
+ :width=>200, :arrow=>:up, :arrowpad=>6)
+ t.column_configure(1, :text=>'Size', :tag=>'size', :justify=>:right,
+ :width=>60, :arrowside=>:left, :arrowgravity=>:right)
+ t.column_configure(2, :text=>'Type', :tag=>'type', :width=>120)
+ t.column_configure(3, :text=>'Modified', :tag=>'modified', :width=>130)
+ end
+
+ t.element_create('e1', :image,
+ :image=>[
+ @sel_images['small-folder'], ['selected'],
+ @images['small-folder'], []
+ ])
+ t.element_create('e2', :text, :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('txtType', :text, :lines=>1)
+ t.element_create('txtSize', :text, :lines=>1,
+ :datatype=>:integer, :format=>'%dKB')
+ t.element_create('txtDate', :text, :lines=>1,
+ :datatype=>:time, :format=>'%d/%m/%y %I:%M %p')
+ t.element_create('e4', :rect, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+
+ # image + text
+ s = t.style_create('styName', :orient=>:horizontal)
+ t.style_elements(s, ['e4', 'e1', 'e2'])
+ t.style_layout(s, 'e1', :expand=>:ns)
+ t.style_layout(s, 'e2', :padx=>[2,0], :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'e4', :union=>['e2'], :iexpand=>:ns, :ipadx=>2)
+
+ # column 1: text
+ s = t.style_create('stySize')
+ t.style_elements(s, ['txtSize'])
+ t.style_layout(s, 'txtSize', :padx=>6, :squeeze=>:x, :expand=>:ns)
+
+ # column 2: text
+ s = t.style_create('styType')
+ t.style_elements(s, ['txtType'])
+ t.style_layout(s, 'txtType', :padx=>6, :squeeze=>:x, :expand=>:ns)
+
+ # column 3: text
+ s = t.style_create('styDate')
+ t.style_elements(s, ['txtDate'])
+ t.style_layout(s, 'txtDate', :padx=>6, :squeeze=>:x, :expand=>:ns)
+
+ @Priv[:edit, t] = ['e2']
+ @Priv[:sensitive, t] = [ ['name', 'styName', 'e1', 'e2'] ]
+ @Priv[:dragimage, t] = [ ['name', 'styName', 'e1', 'e2'] ]
+
+ t.notify_bind(t, 'Edit-accept',
+ proc{|w, i, tt| w.item_text(i, 0, tt)}, '%T %I %t')
+
+ dir_proc = proc{|file|
+ item = t.item_create
+ t.item_style_set(item, 0, 'styName', 2, 'styType', 3, 'styDate')
+ t.item_complex(item,
+ [['e2', {:text=>File.basename(file)}]],
+ [],
+ [['txtType', {:text=>'Folder'}]],
+ [['txtDate', {:data=>File.mtime(file).tv_sec}]])
+ t.item_lastchild(:root, item)
+ }
+
+ file_proc = proc{|file|
+ item = t.item_create
+ t.item_style_set(item, 0, 'styName', 1, 'stySize',
+ 2, 'styType', 3, 'styDate')
+
+ ext = File.extname(file)
+ case ext
+ when '.dll'
+ img = 'small-dll'
+ when '.exe'
+ img = 'small-exe'
+ when '.txt'
+ img = 'small-txt'
+ else
+ img = 'small-file'
+ end
+
+ type = ext.upcase
+ type = type[1..-1] << ' ' unless type.empty?
+ type << 'File'
+
+ t.item_complex(item,
+ [
+ ['e1', {:image=>[@sel_images[img], ['selected'],
+ @images[img], []]}],
+ ['e2', {:text=>File.basename(file)}]
+ ],
+ [ ['txtSize', {:data=>File.size(file)/1024 + 1}] ],
+ [ ['txtType', {:text=>type}] ],
+ [ ['txtDate', {:data=>File.mtime(file).tv_sec}] ]
+ )
+ t.item_lastchild(:root, item)
+ }
+
+ demoExplorerAux(t, dir_proc, file_proc)
+
+ @SortColumn = 0
+ t.notify_bind(t, 'Header-invoke',
+ proc{|w, c| explorerHeaderInvoke(t, w, c)}, '%T %C')
+
+ t.bindtags = [ t, 'TreeCtrlFileList', Tk::TreeCtrl, t.winfo_toplevel, :all ]
+end
+
+def explorerHeaderInvoke(t, w, c)
+ if (c == @SortColumn)
+ if t.column_cget(@SortColumn, :arrow) == 'down'
+ order = :increasing
+ arrow = :up
+ else
+ order = :decreasing
+ arrow = :down
+ end
+ else
+ if t.column_cget(@SortColumn, :arrow) == 'down'
+ order = :decreasing
+ arrow = :down
+ else
+ order = :increasing
+ arrow = :up
+ end
+ t.column_configure(@SortColumn, :arrow=>:none)
+ @SortColumn = c
+ end
+
+ t.column_configure(c, :arrow=>arrow)
+ dirCount = TkComm.number(@Priv[:DirCnt, t])
+ lastDir = dirCount - 1
+ case t.column_cget(c, :tag)
+ when 'name'
+ if dirCount > 0
+ t.item_sort(:root, order, {:last=>"root child #{lastDir}"},
+ {:column=>c, :dictionary=>true})
+ end
+ if dirCount < t.numitems - 1
+ t.item_sort(:root, order, {:first=>"root child #{dirCount}"},
+ {:column=>c, :dictionary=>true})
+ end
+
+ when 'size'
+ if dirCount < t.numitems - 1
+ t.item_sort(:root, order, {:first=>"root child #{dirCount}"},
+ {:column=>c, :integer=>true},
+ {:column=>'name', :dictionary=>true})
+ end
+
+ when 'type'
+ if dirCount < t.numitems - 1
+ t.item_sort(:root, order, {:first=>"root child #{dirCount}"},
+ {:column=>c, :dictionary=>true},
+ {:column=>'name', :dictionary=>true})
+ end
+
+ when 'modified'
+ if dirCount > 0
+ t.item_sort(:root, order, {:last=>"root child #{lastDir}"},
+ {:column=>c, :integer=>true},
+ {:column=>'name', :dictionary=>true})
+ end
+ if dirCount < t.numitems - 1
+ t.item_sort(:root, order, {:first=>"root child #{dirCount}"},
+ {:column=>c, :integer=>true},
+ {:column=>'name', :dictionary=>true})
+ end
+
+ end
+end
+
+def demoExplorerLargeIcons(t)
+ # Item height is 32 for icon, 4 padding, 3 lines of text
+ itemHeight = 32 + 4 + t.font.metrics(:linespace) * 3
+
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :selectmode=>:extended, :wrap=>:window, :orient=>:horizontal,
+ :itemheight=>itemHeight, :showheader=>false, :scrollmargin=>16,
+ :xscrolldelay=>[500, 50], :yscrolldelay=>[500, 50])
+
+ init_pics('big-*')
+
+ if $HasColumnCreate
+ t.column_create(:width=>75)
+ else
+ t.column_configure(0, :width=>75)
+ end
+
+ t.element_create('elemImg', :image,
+ :image=>[
+ @sel_images['big-folder'], ['selected'],
+ @images['big-folder'], []
+ ])
+ t.element_create('elemTxt', :text, :justify=>:center,
+ :lines=>1, :width=>71, :wrap=>:word,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('elemSel', :rect, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected']
+ ])
+
+ # image + text
+ s = t.style_create('STYLE', :orient=>:vertical)
+ t.style_elements(s, ['elemSel', 'elemImg', 'elemTxt'])
+ t.style_layout(s, 'elemImg', :expand=>:we)
+ t.style_layout(s, 'elemTxt',
+ :pady=>[4,0], :padx=>2, :squeeze=>:x, :expand=>:we)
+ t.style_layout(s, 'elemSel', :union=>['elemTxt'])
+
+ @Priv[:edit, t] = ['elemTxt']
+ @Priv[:sensitive, t] = [ [0, 'STYLE', 'elemImg', 'elemTxt'] ]
+ @Priv[:dragimage, t] = [ [0, 'STYLE', 'elemImg', 'elemTxt'] ]
+
+ t.notify_bind(t, 'Edit-accept',
+ proc{|w, i, tt| w.item_text(i, 0, tt)}, '%T %I %t')
+
+ dir_proc = proc{|file|
+ item = t.item_create
+ t.item_style_set(item, 0, 'STYLE')
+ t.item_text(item, 0, File.basename(file))
+ t.item_lastchild(:root, item)
+ }
+
+ file_proc = proc{|file|
+ item = t.item_create
+ t.item_style_set(item, 0, 'STYLE')
+
+ ext = File.extname(file)
+ case ext
+ when '.dll'
+ img = 'big-dll'
+ when '.exe'
+ img = 'big-exe'
+ when '.txt'
+ img = 'big-txt'
+ else
+ img = 'big-file'
+ end
+
+ type = ext.upcase
+ type = type[1..-1] << ' ' unless type.empty?
+ type << 'File'
+
+ t.item_complex(item,
+ [
+ ['elemImg', {:image=>[@sel_images[img], ['selected'],
+ @images[img], []]}],
+ ['elemTxt', {:text=>File.basename(file)}]
+ ])
+ t.item_lastchild(:root, item)
+ }
+
+ demoExplorerAux(t, dir_proc, file_proc)
+
+ t.activate(t.index('root firstchild'))
+
+ t.notify_bind(t, 'ActiveItem',
+ proc{|w, a, c|
+ w.item_element_configure(a, 0, 'elemTxt', :lines=>'')
+ w.item_element_configure(c, 0, 'elemTxt', :lines=>3)
+ }, '%T %p %c')
+
+ t.bindtags = [ t, 'TreeCtrlFileList', Tk::TreeCtrl, t.winfo_toplevel, :all ]
+end
+
+# Tree is horizontal, wrapping occurs at right edge of window, each item
+# is as wide as the smallest needed multiple of 110 pixels
+def demoExplorerSmallIcons(t)
+ demoExplorerList(t)
+ t.configure(:orient=>:horizontal, :xscrollincrement=>0)
+ t.column_configure(0, :width=>'', :stepwidth=>110, :widthhack=>false)
+end
+
+# Tree is vertical, wrapping occurs at bottom of window, each range has the
+# same width (as wide as the longest item), xscrollincrement is by range
+def demoExplorerList(t)
+ height = t.font.metrics(:linespace) + 2
+ height = 18 if height < 18
+
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :itemheight=>height, :selectmode=>:extended, :wrap=>:window,
+ :showheader=>false, :scrollmargin=>16,
+ :xscrolldelay=>[500, 50], :yscrolldelay=>[500, 50])
+
+ init_pics('small-*')
+
+ if $HasColumnCreate
+ t.column_create(:widthhack=>true)
+ else
+ t.column_configure(0, :widthhack=>true)
+ end
+
+ t.element_create('elemImg', :image,
+ :image=>[
+ @sel_images['small-folder'], ['selected'],
+ @images['small-folder'], []
+ ])
+ t.element_create('elemTxt', :text, :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('elemSel', :rect, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+
+ # image + text
+ s = t.style_create('STYLE')
+ t.style_elements(s, ['elemSel', 'elemImg', 'elemTxt'])
+ t.style_layout(s, 'elemImg', :expand=>:ns)
+ t.style_layout(s, 'elemTxt', :squeeze=>:x, :expand=>:ns, :padx=>[2,0])
+ t.style_layout(s, 'elemSel', :union=>['elemTxt'], :iexpand=>:ns, :ipadx=>2)
+
+ @Priv[:edit, t] = ['elemTxt']
+ @Priv[:sensitive, t] = [ [0, 'STYLE', 'elemImg', 'elemTxt'] ]
+ @Priv[:dragimage, t] = [ [0, 'STYLE', 'elemImg', 'elemTxt'] ]
+
+ t.notify_bind(t, 'Edit-accept',
+ proc{|w, i, tt| w.item_text(i, 0, tt)}, '%T %I %t')
+
+ dir_proc = proc{|file|
+ item = t.item_create
+ t.item_style_set(item, 0, 'STYLE')
+ t.item_text(item, 0, File.basename(file))
+ t.item_lastchild(:root, item)
+ }
+
+ file_proc = proc{|file|
+ item = t.item_create
+ t.item_style_set(item, 0, 'STYLE')
+
+ ext = File.extname(file)
+ case ext
+ when '.dll'
+ img = 'small-dll'
+ when '.exe'
+ img = 'small-exe'
+ when '.txt'
+ img = 'small-txt'
+ else
+ img = 'small-file'
+ end
+
+ type = ext.upcase
+ type = type[1..-1] << ' ' unless type.empty?
+ type << 'File'
+
+ t.item_complex(item,
+ [
+ ['elemImg', {:image=>[@sel_images[img], ['selected'],
+ @images[img], []]}],
+ ['elemTxt', {:text=>File.basename(file)}]
+ ])
+ t.item_lastchild(:root, item)
+ }
+
+ demoExplorerAux(t, dir_proc, file_proc)
+
+ t.activate(t.item_firstchild(:root))
+
+ t.bindtags = [ t, 'TreeCtrlFileList', Tk::TreeCtrl, t.winfo_toplevel, :all ]
+end
diff --git a/ext/tk/sample/tkextlib/treectrl/help.rb b/ext/tk/sample/tkextlib/treectrl/help.rb
new file mode 100644
index 0000000000..af026fc006
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/help.rb
@@ -0,0 +1,404 @@
+#
+# Demo: Help contents
+#
+def demoHelpContents(t)
+ height = t.font.metrics(:linespace)
+ height = 18 if height < 18
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :itemheight=>height, :selectmode=>:browse)
+
+ init_pics('help-*')
+
+ if $Version_1_1_OrLater
+ t.column_create(:text=>'Help Contents')
+ else # TreeCtrl 1.0
+ t.column_configure(0, :text=>'Help Contents')
+ end
+
+ # Define a new item state
+ t.state_define('mouseover')
+
+ t.element_create('e1', :image, :image=>@images['help-page'])
+ t.element_create('e2', :image, :image=>[
+ @images['help-book-open'], ['open'],
+ @images['help-book-closed'], [],
+ ])
+ t.element_create('e3', :text,
+ :font=>[t.font.dup.underline(true), ['mouseover']],
+ :fill=>[
+ @SystemHighlightText, ['selected', 'focus'],
+ 'blue', ['mouseover']
+ ])
+ t.element_create('e4', :rect, :showfocus=>true,
+ :fill=>[@SystemHighlight, ['selected', 'focus']])
+
+ # book
+ s = t.style_create('s1')
+ t.style_elements(s, ['e4', 'e1', 'e3'])
+ t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e3', :expand=>:ns)
+ t.style_layout(s, 'e4', :union=>['e3'], :iexpand=>:ns, :ipadx=>2)
+
+ # page
+ s = t.style_create('s2')
+ t.style_elements(s, ['e4', 'e2', 'e3'])
+ t.style_layout(s, 'e2', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e3', :expand=>:ns)
+ t.style_layout(s, 'e4', :union=>['e3'], :iexpand=>:ns, :ipadx=>2)
+
+ parentList = [:root, '', '', '', '', '', '']
+ parent = :root
+ [
+ [0, 's1', "Welcome to Help"],
+ [0, 's2', "Introducing Windows 98"],
+ [1, 's2', "How to Use Help"],
+ [2, 's1', "Find a topic"],
+ [2, 's1', "Get more out of help"],
+ [1, 's2', "Register Your Software"],
+ [2, 's1', "Registering Windows 98 online"],
+ [1, 's2', "What's New in Windows 98"],
+ [2, 's1', "Innovative, easy-to-use features"],
+ [2, 's1', "Improved reliability"],
+ [2, 's1', "A faster operating system"],
+ [2, 's1', "True Web integration"],
+ [2, 's1', "More entertaining and fun"],
+ [1, 's2', "If You're New to Windows 98"],
+ [2, 's2', "Tips for Macintosh Users"],
+ [3, 's1', "Why does the mouse have two buttons?"]
+ ].each{|depth, style, text|
+ item = t.item_create
+ t.item_style_set(item, 0, style)
+ t.item_element_configure(item, 0, 'e3', :text=>text)
+ if $Version_1_1_OrLater
+ t.item_collapse(item)
+ else # TreeCtrl 1.0
+ t.collapse(item)
+ end
+ t.item_lastchild(parentList[depth], item)
+ depth += 1
+ parentList[depth] = item
+ }
+
+ treeCtrlHelp = TkBindTag.new
+
+ treeCtrlHelp.bind('Double-ButtonPress-1',
+ proc{|w, x, y|
+ if w.identify(x, y)[0] == 'header'
+ Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y)
+ else
+ helpButton1(w, x, y)
+ end
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('ButtonPress-1',
+ proc{|w, x, y|
+ helpButton1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('Button1-Motion',
+ proc{|w, x, y|
+ helpMotion1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('Button1-Leave',
+ proc{|w, x, y|
+ helpLeave1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('ButtonRelease-1',
+ proc{|w, x, y|
+ helpRelease1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('Motion', proc{|w, x, y| helpMotion(w, x, y) }, '%W %x %y')
+
+ treeCtrlHelp.bind('Leave', proc{|w, x, y| helpMotion(w, x, y) }, '%W %x %y')
+
+ treeCtrlHelp.bind('KeyPress-Return',
+ proc{|w, x, y|
+ if w.selection_get.length == 1
+ if $Version_1_1_OrLater
+ w.item_toggle(w.selection_get[0])
+ else # TreeCtrl 1.0
+ w.toggle(w.selection_get[0])
+ end
+ end
+ Tk.callback_break
+ }, '%W %x %y')
+
+ @Priv[:help, :prev] = ''
+
+ t.bindtags = [ t, treeCtrlHelp, Tk::TreeCtrl, t.winfo_toplevel, :all ]
+end
+
+# This is an alternate implementation that does not define a new item state
+# to change the appearance of the item under the cursor.
+def demoHelpContents2(t)
+ height = t.font.metrics(:linespace)
+ height = 18 if height < 18
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :itemheight=>height, :selectmode=>:browse)
+
+ init_pics('help-*')
+
+ if $Version_1_1_OrLater
+ t.column_create(:text=>'Help Contents')
+ else # TreeCtrl 1.0
+ t.column_configure(0, :text=>'Help Contents')
+ end
+
+ t.element_create('e1', :image, :image=>@images['help-page'])
+ t.element_create('e2', :image, :image=>[
+ @images['help-book-open'], ['open'],
+ @images['help-book-closed'], [],
+ ])
+ t.element_create('e3', :text,
+ :fill=>[
+ @SystemHighlightText, ['selected', 'focus'],
+ 'blue', []
+ ])
+ t.element_create('e4', :rect, :showfocus=>true,
+ :fill=>[@SystemHighligh, ['selected', 'focus']])
+ t.element_create('e5', :text, :font=>t.font.dup.underline(true),
+ :fill=>[
+ @SystemHighlightText, ['selected', 'focus'],
+ 'blue', []
+ ])
+
+ # book
+ s = t.style_create('s1')
+ t.style_elements(s, ['e4', 'e1', 'e3'])
+ t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e3', :expand=>:ns)
+ t.style_layout(s, 'e4', :union=>['e3'], :iexpand=>:ns, :ipadx=>2)
+
+ # page
+ s = t.style_create('s2')
+ t.style_elements(s, ['e4', 'e2', 'e3'])
+ t.style_layout(s, 'e2', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e3', :expand=>:ns)
+ t.style_layout(s, 'e4', :union=>['e3'], :iexpand=>:ns, :ipadx=>2)
+
+ # book (focus)
+ s = t.style_create('s1.f')
+ t.style_elements(s, ['e4', 'e1', 'e5'])
+ t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e5', :expand=>:ns)
+ t.style_layout(s, 'e4', :union=>['e5'], :iexpand=>:ns, :ipadx=>2)
+
+ # page (focus)
+ s = t.style_create('s2')
+ t.style_elements(s, ['e4', 'e2', 'e5'])
+ t.style_layout(s, 'e2', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e5', :expand=>:ns)
+ t.style_layout(s, 'e4', :union=>['e5'], :iexpand=>:ns, :ipadx=>2)
+
+ parentList = [:root, '', '', '', '', '', '']
+ parent = :root
+ [
+ [0, 's1', "Welcome to Help"],
+ [0, 's2', "Introducing Windows 98"],
+ [1, 's2', "How to Use Help"],
+ [2, 's1' "Find a topic"],
+ [2, 's1', "Get more out of help"],
+ [1, 's2', "Register Your Software"],
+ [2, 's1', "Registering Windows 98 online"],
+ [1, 's2', "What's New in Windows 98"],
+ [2, 's1', "Innovative, easy-to-use features"],
+ [2, 's1', "Improved reliability"],
+ [2, 's1', "A faster operating system"],
+ [2, 's1', "True Web integration"],
+ [2, 's1', "More entertaining and fun"],
+ [1, 's2', "If You're New to Windows 98"],
+ [2, 's2', "Tips for Macintosh Users"],
+ [3, 's1', "Why does the mouse have two buttons?"]
+ ].each{|depth, style, text|
+ item = t.item_create
+ t.item_style_set(item, 0, style)
+ t.item_element_configure(item, 0, 'e3', :text=>text)
+ if $Version_1_1_OrLater
+ t.item_collapse(item)
+ else # TreeCtrl 1.0
+ t.collapse(item)
+ end
+ t.item_lastchild(parentList[depth], item)
+ depth += 1
+ parentList[depth] = item
+ }
+
+ treeCtrlHelp = TkBindTag.new
+
+ treeCtrlHelp.bind('Double-ButtonPress-1',
+ proc{|w, x, y|
+ if w.identify(x, y)[0] == 'header'
+ Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y)
+ else
+ helpButton1(w, x, y)
+ end
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('ButtonPress-1',
+ proc{|w, x, y|
+ helpButton1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('Button1-Motion',
+ proc{|w, x, y|
+ helpMotion1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('Button1-Leave',
+ proc{|w, x, y|
+ helpLeave1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('ButtonRelease-1',
+ proc{|w, x, y|
+ helpRelease1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlHelp.bind('Motion', proc{|w, x, y| helpMotion(w, x, y) }, '%W %x %y')
+
+ treeCtrlHelp.bind('Leave', proc{|w, x, y| helpMotion(w, x, y) }, '%W %x %y')
+
+ treeCtrlHelp.bind('KeyPress-Return',
+ proc{|w, x, y|
+ if w.selection_get.length == 1
+ w.item_toggle(w.selection_get[0])
+ end
+ Tk.callback_break
+ }, '%W %x %y')
+
+ @Priv[:help, :prev] = ''
+
+ t.bindtags = [ t, treeCtrlHelp, Tk::TreeCtrl, t.winfo_toplevel, :all ]
+end
+
+def helpButton1(w, x, y)
+ w.set_focus
+ id = w.identify(x, y)
+ @Priv['buttonMode'] = ''
+ if id[0] == 'header'
+ Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y)
+ elsif id[0] == 'item'
+ item = id[1]
+ # didn't click an element
+ return if id.length != 6
+ if w.selection_includes(item)
+ w.toggle(item)
+ return
+ end
+ if w.selection_get.length > 0
+ item2 = w.selection_get[0]
+ if $Version_1_1_OrLater
+ w.item_collapse(item2)
+ else # TreeCtrl 1.0
+ w.collapse(item2)
+ end
+ w.item_ancestors(item2).each{|i|
+ if $Version_1_1_OrLater
+ w.item_collapse(i) if w.compare(item, '!=', i)
+ else # TreeCtrl 1.0
+ w.collapse(i) if w.compare(item, '!=', i)
+ end
+ }
+ end
+ w.activate(item)
+ if $Version_1_1_OrLater
+ w.item_ancestors(item).each{|i|
+ w.item_expand(i)
+ }
+ w.item_toggle(item)
+ else # TreeCtrl 1.0
+ w.expand(*(w.item_ancestors(item)))
+ w.toggle(item)
+ end
+ w.selection_modify(item, :all)
+ end
+end
+
+def helpMotion1(w, x, y)
+ case @Priv['buttonMode']
+ when 'resize', 'header'
+ Tk::TreeCtrl::BindCallback.motion1(w, x, y)
+ end
+end
+
+def helpLeave1(w, x, y)
+ # This is called when I do ButtonPress-1 on Unix for some reason,
+ # and buttonMode is undefined.
+ return unless @Priv.exist?('buttonMode')
+ case @Priv['buttonMode']
+ when 'header'
+ w.column_configure(@Priv['column'], :sunken=>false)
+ end
+end
+
+def helpRelease1(w, x, y)
+ case @Priv['buttonMode']
+ when 'resize', 'header'
+ Tk::TreeCtrl::BindCallback.release1(w, x, y)
+ end
+ @Priv['buttonMode'] = ''
+end
+
+def helpMotion(w, x, y)
+ id = w.identify(x, y)
+ if id.empty?
+ elsif id[0] == 'header'
+ elsif id[0] == 'item'
+ item = id[1]
+ if id.length == 6
+ if @Priv[:help, :prev] != TkComm._get_eval_string(item)
+ if @Priv[:help, :prev] != ''
+ w.item_state_set(@Priv[:help, :prev], '!mouseover')
+ end
+ w.item_state_set(item, 'mouseover')
+ @Priv[:help, :prev] = item
+ end
+ return
+ end
+ end
+ if @Priv[:help, :prev] != ''
+ w.item_state_set(@Priv[:help, :prev], '!mouseover')
+ @Priv[:help, :prev] = ''
+ end
+end
+
+# Alternate implementation doesn't rely on mouseover state
+def helpMotion2(w, x, y)
+ id = w.identify(x, y)
+ if id[0] == 'header'
+ elsif !id.empty?
+ item = id[1]
+ if id.kength == 6
+ if @Priv[:help, :prev] != TkComm._get_eval_string(item)
+ if @Priv[:help, :prev] != ''
+ style = w.item_style_set(@Priv[:help, :prev], 0)
+ style.sub!(/\.f$/, '')
+ w.item_style_map(@Priv[:help, :prev], 0, style, ['e5', 'e3'])
+ end
+ style = w.item_style_set(item, 0)
+ w.item_style_map(item, 0, style + '.f', ['e3', 'e5'])
+ @Priv[:help, :prev] = item
+ end
+ return
+ end
+ end
+ if @Priv[:help, :prev] != ''
+ style = w.item_style_set(@Priv[:help, :prev], 0)
+ style.sub!(/\.f$/, '')
+ w.item_style_map(@Priv[:help, :prev], 0, style, ['e5', 'e3'])
+ @Priv[:help, :prev] = ''
+ end
+end
diff --git a/ext/tk/sample/tkextlib/treectrl/imovie.rb b/ext/tk/sample/tkextlib/treectrl/imovie.rb
new file mode 100644
index 0000000000..d61bf9a7c3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/imovie.rb
@@ -0,0 +1,130 @@
+#
+# Demo: iMovie
+#
+def demoIMovie(t)
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :selectmode=>:browse, :orient=>:horizontal, :wrap=>:window,
+ :showheader=>false, :background=>'#dcdcdc')
+
+ if $HasColumnCreate
+ t.column_create
+ end
+
+ init_pics('imovie-*')
+
+ case @thisPlatform
+ when 'macintosh', 'macosx'
+ font1 = TkFont.new(['Geneva', 9])
+ font2 = TkFont.new(['Geneva', 10])
+ when 'unix'
+ font1 = TkFont.new(['Helvetica', -12])
+ font2 = TkFont.new(['Helvetica', -14])
+ else
+ font1 = TkFont.new(['Helvetica', 8])
+ font2 = TkFont.new(['Helvetica', 10])
+ end
+
+ t.element_create('elemTime', :text, :font=>font1)
+ t.element_create('elemName', :text, :font=>font2, :lines=>1, :width=>80)
+ t.element_create('elemRect', :rect, :outline=>'#827878', :outlinewidth=>1,
+ :fill=>['#ffdc5a', ['selected'], 'white', []])
+ t.element_create('elemImg', :image)
+ t.element_create('elemShadow', :rect, :outline=>'gray', :outlinewidth=>1,
+ :open=>:wn)
+
+ s = t.style_create('STYLE', :orient=>:vertical)
+ t.style_elements(s, [
+ 'elemShadow', 'elemRect', 'elemTime',
+ 'elemImg', 'elemName'
+ ])
+ t.style_layout(s, 'elemShadow', :detach=>true,
+ :padx=>[1,2], :pady=>[1,2], :iexpand=>:es)
+ t.style_layout(s, 'elemTime', :padx=>[2,0])
+ t.style_layout(s, 'elemImg', :pady=>[0,1])
+ t.style_layout(s, 'elemName', :expand=>:we, :ipady=>[0,2], :padx=>[0,3],
+ :squeeze=>:x)
+ t.style_layout(s, 'elemRect', :union=>['elemTime', 'elemImg', 'elemName'],
+ :ipadx=>6, :padx=>[0,3], :pady=>[0,3])
+
+ # Set default item style
+ if $Version_1_1_OrLater
+ t.defaultstyle([s])
+ end
+
+ (0..4).each{|i|
+ [
+ ['15:20', 'Clip 1', @images['imovie-01']],
+ ['19:18', 'Clip 2', @images['imovie-02']],
+ ['07:20', 'Clip 3', @images['imovie-03']],
+ ['07:20', 'Clip 4', @images['imovie-04']],
+ ['07:20', 'Clip 5', @images['imovie-05']],
+ ['07:20', 'Clip 6', @images['imovie-06']],
+ ['07:20', 'Clip 7', @images['imovie-07']]
+ ].each{|time, name, image|
+ item = t.item_create
+ unless $Version_1_1_OrLater
+ t.item_style_set(item, 0, s)
+ end
+ t.item_element_configure(item, 0, 'elemTime', :text=>time)
+ t.item_element_configure(item, 0, 'elemName', :text=>name)
+ t.item_element_configure(item, 0, 'elemImg', :image=>image)
+ t.item_lastchild(:root, item)
+ }
+ }
+
+ t.notify_bind(t, 'Edit-accept', proc{|w, i, c, e, tt|
+ w.item_element_configure(i, c, e, :text=>tt)
+ }, '%T %I %C %E %t')
+
+ iMovie = TkBindTag.new
+ iMovie.bind('ButtonPress-1', proc{|w, x, y|
+ iMovieButton1(w, x, y)
+ }, '%W %x %y')
+
+ t.bindtags = [t, iMovie, Tk::TreeCtrl, t.winfo_toplevel, TkBindTag::ALL]
+end
+
+def iMovieButton1(w, x, y)
+ w.set_focus
+ id = w.identify(x,y)
+
+ if id.empty?
+ # Click outside any item
+
+ elsif id[0] == 'header'
+ # Click in header
+ Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y)
+
+ elsif id[0] == 'item'
+ # Click in item
+ Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y)
+ Tk.update
+ where, item, arg1, arg2, arg3, arg4 = id
+ case arg1
+ when 'column'
+ i = id[1]
+ if id.length == 6
+ e = id[-1]
+ if e == 'elemName'
+ exists = TkWinfo.exist?(w.path + '.entry')
+ Tk::TreeCtrl::BindCallback.entryOpen(w, i, 0, e)
+ ent = TkComm.window(w.path + '.entry')
+ unless exists
+ ent.configure(:borderwidth=>0, :justify=>:center,
+ :background=>'#ffdc5a')
+ x1, y1, x2, y2 = w.item_bbox(i, 0, e)
+ ent.place(:y=>y1 - 1)
+ end
+ ent.selection_clear
+ x1, y1, x2, y2 = w.item_bbox(i)
+ ent.place(:x=>x1 + 1, :width=>x2 - x1 - 5)
+ puts "@#{x - (x1 + 1)}"
+ # ent.icursor = ent.index("@#{x - (x1 + 1)}")
+ ent.icursor = ent.index(TkComm._at(x - (x1 + 1)))
+ end
+ end
+ end
+ end
+
+ Tk.callback_break
+end
diff --git a/ext/tk/sample/tkextlib/treectrl/layout.rb b/ext/tk/sample/tkextlib/treectrl/layout.rb
new file mode 100644
index 0000000000..745ac86f36
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/layout.rb
@@ -0,0 +1,159 @@
+#
+# Demo: Layout
+#
+def demoLayout(t)
+ t.configure(:showroot=>false, :showrootbutton=>true, :showbuttons=>true,
+ :showlines=>true, :itemheight=>0, :selectmode=>:browse)
+
+ if $HasColumnCreate
+ t.column_create(:text=>'Layout')
+ else
+ t.column_configure(0, :text=>'Layout')
+ end
+
+ t.element_create('e1', :rect, :width=>30, :height=>30, :fill=>'gray20')
+ t.element_create('e2', :rect, :width=>30, :height=>30, :fill=>'gray40',
+ :outline=>'blue', :outlinewidth=>3)
+ t.element_create('e3', :rect, :fill=>'gray60')
+ t.element_create('e4', :rect, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'], 'gray80', []
+ ])
+ t.element_create('e5', :rect, :fill=>'{sky blue}', :width=>20, :height=>20)
+ t.element_create('e6', :rect, :fill=>'{sea green}', :width=>30, :height=>16)
+ t.element_create('e7', :rect, :fill=>'{sky blue}', :width=>30, :height=>16)
+ t.element_create('e8', :rect, :fill=>'gray70', :height=>1)
+
+ s = t.style_create('s1')
+ t.style_elements(s, ['e4', 'e3', 'e1', 'e2', 'e5', 'e6', 'e7'])
+ t.style_layout(s, 'e1', :padx=>[28, 4], :pady=>4)
+ t.style_layout(s, 'e2', :expand=>:es, :padx=>[0, 38])
+ t.style_layout(s, 'e3', :union=>['e1', 'e2'], :ipadx=>4, :ipady=>4, :pady=>2)
+ t.style_layout(s, 'e4', :detach=>true, :iexpand=>:es)
+ t.style_layout(s, 'e5', :detach=>true, :padx=>[2,0], :pady=>2, :iexpand=>:s)
+ t.style_layout(s, 'e6', :detach=>true, :expand=>:ws,
+ :padx=>[0,2], :pady=>[2,0])
+ t.style_layout(s, 'e7', :detach=>true, :expand=>:wn,
+ :padx=>[0,2], :pady=>[0,2])
+
+ if $Version_1_1_OrLater
+ i = t.item_create(:button=>true)
+ else
+ i = t.item_create
+ t.item_hasbutton(i, true)
+ end
+ t.item_style_set(i, 0, s)
+ t.item_lastchild(:root, i)
+ parent = i
+
+ i = t.item_create()
+ unless $Version_1_1_OrLater
+ t.item_hasbutton(i, false)
+ end
+ t.item_style_set(i, 0, s)
+ t.item_lastchild(parent, i)
+
+ ###
+
+ s = t.style_create('s2')
+ t.style_elements(s, ['e4', 'e3', 'e1'])
+ t.style_layout(s, 'e1', :padx=>8, :pady=>8, :iexpand=>:e)
+ t.style_layout(s, 'e3', :union=>['e1'], :ipadx=>[20,4], :ipady=>[4,12])
+ t.style_layout(s, 'e4', :detach=>true, :iexpand=>:es)
+
+ if $Version_1_1_OrLater
+ i = t.item_create(:button=>true)
+ else
+ i = t.item_create
+ t.item_hasbutton(i, true)
+ end
+ t.item_style_set(i, 0, s)
+ t.item_lastchild(:root, i)
+
+ i2 = t.item_create()
+ unless $Version_1_1_OrLater
+ t.item_hasbutton(i2, false)
+ end
+ t.item_style_set(i2, 0, s)
+ t.item_lastchild(i, i2)
+
+ ###
+
+ s = t.style_create('s3')
+ t.style_elements(s, ['e4', 'e3', 'e1', 'e5', 'e6'])
+ t.style_layout(s, 'e4', :union=>['e1', 'e6'], :ipadx=>8, :ipady=>[8,0])
+ t.style_layout(s, 'e3', :union=>['e1', 'e5'], :ipadx=>4, :ipady=>4)
+ t.style_layout(s, 'e5', :ipady=>[0,20])
+
+ if $Version_1_1_OrLater
+ i = t.item_create(:button=>true)
+ else
+ i = t.item_create
+ t.item_hasbutton(i, true)
+ end
+ t.item_style_set(i, 0, s)
+ t.item_lastchild(:root, i)
+
+ i2 = t.item_create()
+ unless $Version_1_1_OrLater
+ t.item_hasbutton(i2, false)
+ end
+ t.item_style_set(i2, 0, s)
+ t.item_lastchild(i, i2)
+
+ ###
+
+ t.element_create('eb', :border, :background=>@SystemButtonFace,
+ :relief=>[:sunken, ['selected'], :raised, []],
+ :thickness=>2, :filled=>true)
+ t.element_create('et', :text)
+
+ text = "Here is a text element surrounded by a border element.\nResize the column to watch me wrap."
+
+ s = t.style_create('e4')
+ t.style_elements(s, ['eb', 'et'])
+ t.style_layout(s, 'eb', :union=>['et'], :ipadx=>2, :ipady=>2)
+ t.style_layout(s, 'et', :squeeze=>:x)
+
+ if $Version_1_1_OrLater
+ i = t.item_create(:button=>true)
+ else
+ i = t.item_create
+ t.item_hasbutton(i, true)
+ end
+ t.item_style_set(i, 0, s)
+ t.item_text(i, 0, text)
+ t.item_lastchild(:root, i)
+ parent = i
+
+ i = t.item_create()
+ unless $Version_1_1_OrLater
+ t.item_hasbutton(i, false)
+ end
+ t.item_style_set(i, 0, s)
+ t.item_text(i, 0, text)
+ t.item_lastchild(parent, i)
+
+ ###
+
+ styleNum = 5
+ [
+ [:horizontal, [:s, :ns, :n]],
+ [:vertical, [:e, :we, :w]]
+ ].each{|orient, expandList|
+ expandList.each{|expand|
+ s = t.style_create("s#{styleNum}", :orient=>orient)
+ t.style_elements(s, ['e4', 'e8', 'e2', 'e5', 'e6'])
+ t.style_layout(s, 'e4', :detach=>true, :iexpand=>:es)
+ t.style_layout(s, 'e8', :detach=>true, :expand=>:n, :iexpand=>:e)
+ t.style_layout(s, 'e2', :expand=>expand)
+ t.style_layout(s, 'e5', :expand=>expand)
+ t.style_layout(s, 'e6', :expand=>expand)
+ styleNum += 1
+
+ i = t.item_create()
+ t.item_style_set(i, 0, s)
+ t.item_lastchild(:root, i)
+ }
+ }
+end
diff --git a/ext/tk/sample/tkextlib/treectrl/mailwasher.rb b/ext/tk/sample/tkextlib/treectrl/mailwasher.rb
new file mode 100644
index 0000000000..836e1e87de
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/mailwasher.rb
@@ -0,0 +1,269 @@
+#
+# Demo: MailWasher
+#
+def demoMailWasher(t)
+ init_pics('*checked')
+
+ height = t.font.metrics(:linespace) + 2
+ height = 18 if height < 18
+
+ t.configure(:showroot=>false, :showrootbutton=>false, :showbuttons=>false,
+ :showlines=>false, :itemheight=>height, :selectmode=>:browse,
+ :xscrollincrement=>1)
+
+ pad = 4
+
+ if $Version_1_1_OrLater
+ t.column_create(:text=>'Delete', :textpadx=>pad, :tag=>'delete')
+ t.column_create(:text=>'Bounce', :textpadx=>pad, :tag=>'bounce')
+ t.column_create(:text=>'Status', :width=>80, :textpadx=>pad,
+ :tag=>'status')
+ t.column_create(:text=>'Size', :width=>40, :textpadx=>pad,
+ :justify=>:right, :tag=>'size')
+ t.column_create(:text=>'From', :width=>140, :textpadx=>pad, :tag=>'from')
+ t.column_create(:text=>'Subject', :width=>240, :textpadx=>pad,
+ :tag=>'subject')
+ t.column_create(:text=>'Received', :textpadx=>pad, :arrow=>:up,
+ :arrowpad=>[4,0], :tag=>'received')
+ t.column_create(:text=>'Attachments', :textpadx=>pad, :tag=>'attachments')
+
+ t.state_define('CHECK')
+
+ t.element_create('imgCheck', :image, :image=>[
+ @images['checked'], ['CHECK'], @images['unchecked'], []
+ ])
+
+ else # TreeCtrl 1.0
+ t.column_configure(0, :text=>'Delete', :textpadx=>pad, :tag=>'delete')
+ t.column_configure(1, :text=>'Bounce', :textpadx=>pad, :tag=>'bounce')
+ t.column_configure(2, :text=>'Status', :width=>80, :textpadx=>pad,
+ :tag=>'status')
+ t.column_configure(3, :text=>'Size', :width=>40, :textpadx=>pad,
+ :justify=>:right, :tag=>'size')
+ t.column_configure(4, :text=>'From', :width=>140, :textpadx=>pad,
+ :tag=>'from')
+ t.column_configure(5, :text=>'Subject', :width=>240, :textpadx=>pad,
+ :tag=>'subject')
+ t.column_configure(6, :text=>'Received', :textpadx=>pad, :arrow=>:up,
+ :arrowpad=>[4,0], :tag=>'received')
+ t.column_configure(7, :text=>'Attachments', :textpadx=>pad,
+ :tag=>'attachments')
+
+ t.element_create('imgOff', :image, :image=>@images['unchecked'])
+ t.element_create('imgOn', :image, :image=>@images['checked'])
+ end
+
+ t.element_create('border', :rect, :open=>:nw, :outline=>'gray',
+ :outlinewidth=>1, :fill=>[@SystemHighlight, ['selected']])
+ t.element_create('txtAny', :text, :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected']])
+ t.element_create('txtNone', :text, :text=>'none', :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected']])
+ t.element_create('txtYes', :text, :text=>'yes', :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected']])
+ t.element_create('txtNormal', :text, :text=>'Normal', :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected'], '#006800', []])
+ t.element_create('txtPossSpam', :text, :text=>'Possible Spam', :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected'], '#787800', []])
+ t.element_create('txtProbSpam', :text, :text=>'Probably Spam', :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected'], '#FF9000', []])
+ t.element_create('txtBlacklist', :text, :text=>'Blacklisted', :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected'], '#FF5800', []])
+
+ if $Version_1_1_OrLater
+ s = t.style_create('styCheck')
+ t.style_elements(s, ['border', 'imgCheck'])
+ t.style_layout(s, 'border', :detach=>true, :iexpand=>:es)
+ t.style_layout(s, 'imgCheck', :expand=>:news)
+ else
+ ['Off', 'On'].each{|name|
+ s = t.style_create('sty' << name)
+ i = 'img' << name
+ t.style_elements(s, ['border', i])
+ t.style_layout(s, 'border', :detach=>true, :iexpand=>:es)
+ t.style_layout(s, i, :expand=>:news)
+ }
+ end
+
+ pad = 4
+
+ %w(Any None Yes Normal PossSpam ProbSpam Blacklist).each{|name|
+ s = t.style_create('sty' << name)
+ e = 'txt' << name
+ t.style_elements(s, ['border', e])
+ t.style_layout(s, 'border', :detach=>true, :iexpand=>:es)
+ t.style_layout(s, e, :padx=>pad, :squeeze=>:x, :expand=>:ns)
+ }
+
+ [
+ ['baldy@spammer.com', "Your hair is thinning"],
+ ['flat@spammer.com', "Your breasts are too small"],
+ ['tiny@spammer.com', "Your penis is too small"],
+ ['dumbass@spammer.com', "You are not very smart"],
+ ['bankrobber@spammer.com', "You need more money"],
+ ['loser@spammer.com', "You need better friends"],
+ ['gossip@spammer.com', "Find out what your coworkers think about you"],
+ ['whoami@spammer.com', "Find out what you think about yourself"],
+ ['downsized@spammer.com', "You need a better job"],
+ ['poorhouse@spammer.com', "Your mortgage is a joke"],
+ ['spam4ever@spammer.com', "You need more spam"]
+ ].each{|frm, subj|
+ item = t.item_create
+ status = ['styNormal','styPossSpam','styProbSpam','styBlacklist'][rand(4)]
+ attachments = ['styNone','styYes'][rand(2)]
+
+ if $Version_1_1_OrLater
+ delete = [false, true][rand(2)]
+ bounce = [false, true][rand(2)]
+ t.item_style_set(item,
+ 0, 'styCheck', 1, 'styCheck', 2, status, 3, 'styAny',
+ 4, 'styAny', 5, 'styAny', 6, 'styAny', 7, attachments)
+ t.item_state_forcolumn(item, 'delete', 'CHECK') if delete
+ t.item_state_forcolumn(item, 'bounce', 'CHECK') if bounce
+
+ else # TreeCtrl 1.0
+ delete = ['styOn', 'styOff'][rand(2)]
+ bounce = ['styOn', 'styOff'][rand(2)]
+ t.item_style_set(item,
+ 0, delete, 1, bounce, 2, status, 3, 'styAny',
+ 4, 'styAny', 5, 'styAny', 6, 'styAny', 7, attachments)
+ end
+
+ bytes = 512 + rand(1024 * 12)
+ size = "#{bytes / 1024 + 1}KB"
+ seconds = Tk::Clock.seconds - rand(100000)
+ received = Tk::Clock.format(seconds, '%d/%m/%y %I:%M %p')
+ t.item_text(item, 3, size, 4, frm, 5, subj, 6, received)
+ t.item_lastchild(:root, item)
+ }
+
+ sortColumn = 6
+ t.notify_bind(t, 'Header-invoke',
+ proc{|c, w|
+ if c == sortColumn
+ if w.column_cget(sortColumn, :arrow) == 'down'
+ order = :increasing
+ arrow = :up
+ else
+ order = :decreasing
+ arrow = :down
+ end
+ else
+ if w.column_cget(sortColumn, :arrow) == 'down'
+ order = :decreasing
+ arrow = :down
+ else
+ order = :increasing
+ arrow = :up
+ end
+ w.column_configure(sortColumn, :arrow=>:none)
+ sortColumn = c
+ end
+ w.column_configure(c, :arrow=>arrow)
+ case w.column_cget(c, :tag)
+ when 'bounce', 'delete'
+ w.item_sort(:root, order,
+ {
+ :column=>c,
+ :command=>proc{|item1, item2|
+ compareOnOff(w, c, item1, item2)
+ }
+ },
+ { :column=>'subject', :dictionary=>true })
+ when 'status'
+ w.item_sort(:root, order,
+ { :column=>c, :dictionary=>true })
+ when 'from'
+ w.item_sort(:root, order,
+ { :column=>c, :dictionary=>true },
+ { :column=>'subject', :dictionary=>true })
+ when 'subject'
+ w.item_sort(:root, order,
+ { :column=>c, :dictionary=>true })
+ when 'size'
+ w.item_sort(:root, order,
+ { :column=>c, :dictionary=>true },
+ { :column=>'subject', :dictionary=>true })
+ when 'received'
+ w.item_sort(:root, order,
+ { :column=>c, :dictionary=>true },
+ { :column=>'subject', :dictionary=>true })
+ when 'attachments'
+ w.item_sort(:root, order,
+ { :column=>c, :dictionary=>true },
+ { :column=>'subject', :dictionary=>true })
+ end
+ }, '%C %T')
+
+ mailWasher = TkBindTag.new
+
+ if $Version_1_1_OrLater
+ mailWasher.bind('ButtonPress-1',
+ proc{|w, x, y|
+ id = w.identify(x, y)
+ if id.empty?
+ elsif id[0] == 'header'
+ else
+ what, item, where, arg1, arg2, arg3 = id
+ if where == 'column'
+ tag = w.column_cget(arg1, :tag)
+ if tag == 'delete' || tag == 'bounce'
+ w.item_state_forcolumn(item, arg1, '~CHECK')
+ end
+ end
+ end
+ }, '%W %x %y')
+ else # TreeCtrl 1.0
+ mailWasher.bind('ButtonPress-1',
+ proc{|w, x, y|
+ id = w.identify(x, y)
+ if id.empty?
+ elsif id[0] == 'header'
+ else
+ what, item, where, arg1, arg2, arg3 = id
+ if where == 'column'
+ tag = w.column_cget(arg1, :tag)
+ if tag == 'delete' || tag == 'bounce'
+ style = w.item_style_set(item, arg1)
+ if style == 'styOn'
+ style = 'styOff'
+ else
+ style = 'styOn'
+ end
+ w.item_style_set(item, arg1, style)
+ @display_styles_in_item.call(item)
+ end
+ end
+ end
+ }, '%W %x %y')
+ end
+
+ t.bindtags = [t, mailWasher, Tk::TreeCtrl, t.winfo_toplevel, TkBindTag::ALL]
+end
+
+if $Version_1_1_OrLater
+ def compareOnOff(w, c, item1, item2)
+ s1 = w.item_state_forcolumn(item1, c)
+ s2 = w.item_state_forcolumn(item2, c)
+ if (s1 == s2)
+ 0
+ elsif (s1 == 'CHECK')
+ -1
+ else
+ 1
+ end
+ end
+
+else # TreeCtrl 1.0
+ def compareOnOff(w, c, item1, item2)
+ s1 = w.item_style_set(item1, c)
+ s2 = w.item_style_set(item2, c)
+ if (s1 == s2)
+ 0
+ elsif (s1 == 'styOff')
+ -1
+ else
+ 1
+ end
+ end
+end
diff --git a/ext/tk/sample/tkextlib/treectrl/outlook-folders.rb b/ext/tk/sample/tkextlib/treectrl/outlook-folders.rb
new file mode 100644
index 0000000000..c3af86868e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/outlook-folders.rb
@@ -0,0 +1,124 @@
+#
+# Demo: Outlook Express folder list
+#
+def demoOutlookFolders(t)
+ init_pics('outlook-*')
+
+ height = t.font.metrics(:linespace) + 2
+ height = 18 if height < 18
+
+ t.configure(:itemheight=>height, :selectmode=>:browse, :showlines=>true,
+ :showroot=>true, :showrootbutton=>false, :showbuttons=>true)
+
+ if $HasColumnCreate
+ t.column_create(:text=>'Folders')
+ else
+ t.column_configure(0, :text=>'Folders')
+ end
+
+ t.element_create('e1', :image)
+ t.element_create('e2', :text, :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('e3', :text, :lines=>1, :font=>t.font.dup.weight(:bold),
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('e4', :text, :fill=>'blue')
+ t.element_create('e5', :image, :image=>@images['outlook-folder'])
+ t.element_create('e6', :rect, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+
+ # image + text
+ s = t.style_create('s1')
+ t.style_elements(s, ['e6', 'e1', 'e2'])
+ t.style_layout(s, 'e1', :expand=>:ns)
+ t.style_layout(s, 'e2', :padx=>[4,0], :expand=>:ns, :squeeze=>:x)
+ t.style_layout(s, 'e6', :union=>['e2'], :iexpand=>:ns, :ipadx=>2)
+
+ # image + text + text
+ s = t.style_create('s2')
+ t.style_elements(s, ['e6', 'e1', 'e3', 'e4'])
+ t.style_layout(s, 'e1', :expand=>:ns)
+ t.style_layout(s, 'e3', :padx=>4, :expand=>:ns, :squeeze=>:x)
+ t.style_layout(s, 'e4', :expand=>:ns)
+ t.style_layout(s, 'e6', :union=>['e3'], :iexpand=>:ns, :ipadx=>2)
+
+ # folder + text
+ s = t.style_create('s3')
+ t.style_elements(s, ['e6', 'e5', 'e2'])
+ t.style_layout(s, 'e5', :expand=>:ns)
+ t.style_layout(s, 'e2', :padx=>[4,0], :expand=>:ns, :squeeze=>:x)
+ t.style_layout(s, 'e6', :union=>['e2'], :iexpand=>:ns, :ipadx=>2)
+
+ # folder + text + text
+ s = t.style_create('s4')
+ t.style_elements(s, ['e6', 'e5', 'e3', 'e4'])
+ t.style_layout(s, 'e5', :expand=>:ns)
+ t.style_layout(s, 'e3', :padx=>4, :expand=>:ns, :squeeze=>:x)
+ t.style_layout(s, 'e4', :expand=>:ns)
+ t.style_layout(s, 'e6', :union=>['e3'], :iexpand=>:ns, :ipadx=>2)
+
+ t.item_style_set(:root, 0, 's1')
+ t.item_complex(:root,
+ [
+ ['e1', {:image=>@images['outlook-main']}],
+ ['e2', {:text=>'Outlook Express'}]
+ ])
+
+ parentList = [:root, '', '', '', '', '', '']
+ parent = :root
+ [
+ [0, :local, "Local Folders", true, 0],
+ [1, :inbox, 'Inbox', false, 5],
+ [1, :outbox, 'Outbox', false, 0],
+ [1, :sent, "Sent Items", false, 0],
+ [1, :deleted, "Deleted Items", false, 50],
+ [1, :draft, 'Drafts', false, 0],
+ [1, :folder, "Messages to Dad", false, 0],
+ [1, :folder, "Messages to Sis", false, 0],
+ [1, :folder, "Messages to Me", false, 0],
+ [2, :folder, "2001", false, 0],
+ [2, :folder, "2000", false, 0],
+ [2, :folder, "1999", false, 0],
+ [0, :server, "news.gmane.org", true, 0],
+ [1, :group, "gmane.comp.lang.lua.general", false, 498]
+ ].each{|depth, img, text, button, unread|
+ if $Version_1_1_OrLater
+ item = t.item_create(:button=>button)
+ else
+ item = t.item_create
+ t.item_hasbutton(item, button)
+ end
+ if img == :folder
+ if unread != 0
+ t.item_style_set(item, 0, 's4')
+ t.item_complex(item,
+ [['e3', {:text=>text}], ['e4', {:text=>"(#{unread})"}]])
+ else
+ t.item_style_set(item, 0, 's3')
+ t.item_complex(item, [['e2', {:text=>text}]])
+ end
+ else
+ if unread != 0
+ t.item_style_set(item, 0, 's2')
+ t.item_complex(item,
+ [
+ ['e1', {:image=>@images["outlook-#{img}"]}],
+ ['e3', {:text=>text}],
+ ['e4', {:text=>"(#{unread})"}]
+ ])
+ else
+ t.item_style_set(item, 0, 's1')
+ t.item_complex(item,
+ [
+ ['e1', {:image=>@images["outlook-#{img}"]}],
+ ['e2', {:text=>text}]
+ ])
+ end
+ end
+ t.item_lastchild(parentList[depth], item)
+ depth += 1
+ parentList[depth] = item
+ }
+end
diff --git a/ext/tk/sample/tkextlib/treectrl/outlook-newgroup.rb b/ext/tk/sample/tkextlib/treectrl/outlook-newgroup.rb
new file mode 100644
index 0000000000..d7e7f7e004
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/outlook-newgroup.rb
@@ -0,0 +1,448 @@
+#
+# Demo: Outlook Express newsgroup messages
+#
+def demoOutlookNewsgroup(t)
+ init_pics('outlook-*')
+
+ height = t.font.metrics(:linespace)
+ height = 18 if height < 18
+ t.configure(:itemheight=>height, :selectmode=>:browse, :showlines=>false,
+ :showroot=>false, :showrootbutton=>false, :showbuttons=>true)
+
+ if $Version_1_1_OrLater
+ t.column_create(:image=>@images['outlook-clip'], :tag=>'clip')
+ t.column_create(:image=>@images['outlook-arrow'], :tag=>'arrow')
+ t.column_create(:image=>@images['outlook-watch'], :tag=>'watch')
+ t.column_create(:text=>'Subject', :width=>250, :tag=>'subject')
+ t.column_create(:text=>'From', :width=>150, :tag=>'from')
+ t.column_create(:text=>'Sent', :width=>150, :tag=>'sent')
+ t.column_create(:text=>'Size', :width=>60, :justify=>:right, :tag=>'size')
+ else # TreeCtrl 1.0
+ t.column_configure(0, :image=>@images['outlook-clip'], :tag=>'clip')
+ t.column_configure(1, :image=>@images['outlook-arrow'], :tag=>'arrow')
+ t.column_configure(2, :image=>@images['outlook-watch'], :tag=>'watch')
+ t.column_configure(3, :text=>'Subject', :width=>250, :tag=>'subject')
+ t.column_configure(4, :text=>'From', :width=>150, :tag=>'from')
+ t.column_configure(5, :text=>'Sent', :width=>150, :tag=>'sent')
+ t.column_configure(6, :text=>'Size', :width=>60, :justify=>:right,
+ :tag=>'size')
+ end
+
+ # Would be nice if I could specify a column -tag too
+ t.treecolumn = 3
+
+ # State for a read message
+ t.state_define('read')
+
+ # State for a message with unread descendants
+ t.state_define('unread')
+
+ t.element_create('elemImg', :image,
+ :image=>[
+ @sel_images['outlook-read-2'],
+ ['selected', 'read', 'unread', '!open'],
+ @images['outlook-read-2'], ['read', 'unread', '!open'],
+ @sel_images['outlook-read'], ['selected', 'read'],
+ @images['outlook-read'], ['read'],
+ @sel_images['outlook-unread'], ['selected'],
+ @images['outlook-unread'], []
+ ])
+ t.element_create('elemTxt', :text, :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']],
+ :font=>[
+ t.font.dup.weight(:bold), ['read', 'unread', '!open'],
+ t.font.dup.weight(:bold), ['!read']
+ ])
+ t.element_create('sel.e', :rect, :open=>:e, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+ t.element_create('sel.w', :rect, :open=>:w, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+ t.element_create('sel.we', :rect, :open=>:we, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+
+ # Image + text
+ s = t.style_create('s1')
+ t.style_elements(s, ['sel.e', 'elemImg', 'elemTxt'])
+ t.style_layout(s, 'elemImg', :expand=>:ns)
+ t.style_layout(s, 'elemTxt', :padx=>[2,6], :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.e', :union=>['elemTxt'],
+ :iexpand=>:nes, :ipadx=>[2,0])
+
+ # Text
+ s = t.style_create('s2.we')
+ t.style_elements(s, ['sel.we', 'elemTxt'])
+ t.style_layout(s, 'elemTxt', :padx=>6, :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.we', :detach=>true, :iexpand=>:es)
+
+ # Text
+ s = t.style_create('s2.w')
+ t.style_elements(s, ['sel.w', 'elemTxt'])
+ t.style_layout(s, 'elemTxt', :padx=>6, :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.w', :detach=>true, :iexpand=>:es)
+
+ # Set default item style
+ if $Version_1_1_OrLater
+ t.defaultstyle = ['', '', '', 's1', 's2.we', 's2.we', 's2.w']
+ end
+
+ msgCnt = 100
+ thread = 0
+
+ @Message = Hash.new{|k, v| k[v] = Hash.new}
+ @Message[:count][0] = 0
+
+ items = [t.index(:root)]
+
+ (1...(msgCnt)).each{|i|
+ item_i = t.item_create
+ item_j = nil
+ j = nil
+ loop {
+ j = rand(i)
+ item_j = items[j]
+ break if j == 0
+ next if t.depth(item_j) == 5
+ next if @Message[:count][@Message[:thread][item_j]] == 15
+ break
+ }
+ t.item_lastchild(item_j, item_i)
+
+ @Message[:read][item_i] = (rand(2) == 0)
+ if j == 0
+ thread += 1
+ @Message[:thread][item_i] = thread
+ @Message[:seconds][item_i] = (Tk::Clock.seconds - rand(500000))
+ @Message[:seconds2][item_i] = @Message[:seconds][item_i]
+ @Message[:count][thread] = 1
+ else
+ @Message[:thread][item_i] = @Message[:thread][item_j]
+ @Message[:seconds][item_i] = (@Message[:seconds2][item_j] + rand(10000))
+ @Message[:seconds2][item_i] = @Message[:seconds][item_i]
+ @Message[:seconds2][item_j] = @Message[:seconds][item_i]
+ @Message[:count][@Message[:thread][item_j]] += 1
+ end
+ items << item_i
+ }
+
+ (1...(msgCnt)).each{|i|
+ item_i = items[i]
+ subject = "This is thread number #{@Message[:thread][item_i]}"
+ from = 'somebody@somewhere.net'
+ sent = Tk::Clock.format(@Message[:seconds][item_i], "%d/%m/%y %I:%M %p")
+ size = "#{1 + rand(10)}KB"
+
+ # This message has been read
+ t.item_state_set(item_i, 'read') if @Message[:read][item_i]
+
+ # This message has unread descendants
+ t.item_state_set(item_i, 'unread') if anyUnreadDescendants(t, item_i)
+
+ if t.item_numchildren(item_i) > 0
+ if $Version_1_1_OrLater
+ t.item_configure(item_i, :button=>true)
+ else # TreeCtrl 1.0
+ t.item_hasbutton(item_i, true)
+ end
+
+ # Collapse some messages
+ if $Version_1_1_OrLater
+ t.item_collapse(item_i) if rand(2) == 0
+ else # TreeCtrl 1.0
+ t.collapse(item_i) if rand(2) == 0
+ end
+ end
+
+ unless $Version_1_1_OrLater
+ t.item_style_set(item_i, 3, 's1', 4, 's2.we', 5, 's2.we', 6, 's2.w')
+ end
+ t.item_text(item_i, 3, subject, 4, from, 5, sent, 6, size)
+ }
+
+ # Do something when the selection changes
+ t.notify_bind(t, 'Selection',
+ proc{|w|
+ if w.selection_count == 1
+ # One item is selected
+ if @Message[:afterId][:id]
+ Tk.after_cancel(@Message[:afterId][:id])
+ end
+ @Message[:afterId][:item] = w.selection_get[0]
+ @Message[:afterId][:id] = Tk.after(500, proc{
+ messageReadDelayed(w)
+ })
+ end
+ }, '%T')
+end
+
+def messageReadDelayed(t)
+ @Message[:afterId].delete(:id)
+ i = @Message[:afterId][:item]
+ return unless t.selection_includes(i)
+
+ # This message is not read
+ unless @Message[:read][i]
+ # Read the message
+ t.item_state_set(i, 'read')
+ @Message[:read][i] = true
+
+ # Check ancestors (except root)
+ t.item_ancestors(i)[0..-2].each{|i2|
+ # This ancestor has no more unread descendants
+ t.item_state_set(i2, '!unread') unless anyUnreadDescendants(t, i2)
+ }
+ end
+end
+
+# Alternate implementation which does not rely on run-time states
+def demoOutlookNewsgroup2(t)
+ init_pics('outlook-*')
+
+ height = t.font.metrics(:linespace)
+ height = 18 if height < 18
+ t.configure(:itemheight=>height, :selectmode=>:browse, :showlines=>false,
+ :showroot=>false, :showrootbutton=>false, :showbuttons=>true)
+
+ if $Version_1_1_OrLater
+ t.column_create(:image=>@images['outlook-clip'], :tag=>'clip')
+ t.column_create(:image=>@images['outlook-arrow'], :tag=>'arrow')
+ t.column_create(:image=>@images['outlook-watch'], :tag=>'watch')
+ t.column_create(:text=>'Subject', :width=>250, :tag=>'subject')
+ t.column_create(:text=>'From', :width=>150, :tag=>'from')
+ t.column_create(:text=>'Sent', :width=>150, :tag=>'sent')
+ t.column_create(:text=>'Size', :width=>60, :justify=>:right, :tag=>'size')
+ else # TreeCtrl 1.0
+ t.column_configure(0, :image=>@images['outlook-clip'], :tag=>'clip')
+ t.column_configure(1, :image=>@images['outlook-arrow'], :tag=>'arrow')
+ t.column_configure(2, :image=>@images['outlook-watch'], :tag=>'watch')
+ t.column_configure(3, :text=>'Subject', :width=>250, :tag=>'subject')
+ t.column_configure(4, :text=>'From', :width=>150, :tag=>'from')
+ t.column_configure(5, :text=>'Sent', :width=>150, :tag=>'sent')
+ t.column_configure(6, :text=>'Size', :width=>60, :justify=>:right,
+ :tag=>'size')
+ end
+
+ t.treecolumn = 3
+
+ t.element_create('image.unread', :image, :image=>@images['outlook-unread'])
+ t.element_create('image.read', :image, :image=>@images['outlook-read'])
+ t.element_create('image.read2', :image, :image=>@images['outlook-read-2'])
+ t.element_create('text.read', :text, :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('text.unread', :text, :lines=>1,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']],
+ :font=>t.font.dup.weight(:bold))
+ t.element_create('sel.e', :rect, :open=>:e, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+ t.element_create('sel.w', :rect, :open=>:w, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+ t.element_create('sel.we', :rect, :open=>:we, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+
+ # Image + text
+ s = t.style_create('unread')
+ t.style_elements(s, ['sel.e', 'image.unread', 'text.unread'])
+ t.style_layout(s, 'image.unread', :expand=>:ns)
+ t.style_layout(s, 'text.unread', :padx=>[2,6], :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.e', :union=>['text.unread'],
+ :iexpand=>:nes, :ipadx=>[2,0])
+
+ # Image + text
+ s = t.style_create('read')
+ t.style_elements(s, ['sel.e', 'image.read', 'text.read'])
+ t.style_layout(s, 'image.read', :expand=>:ns)
+ t.style_layout(s, 'text.read', :padx=>[2,6], :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.e', :union=>['text.read'],
+ :iexpand=>:nes, :ipadx=>[2,0])
+
+ # Image + text
+ s = t.style_create('read2')
+ t.style_elements(s, ['sel.e', 'image.read2', 'text.unread'])
+ t.style_layout(s, 'image.read2', :expand=>:ns)
+ t.style_layout(s, 'text.unread', :padx=>[2,6], :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.e', :union=>['text.unread'],
+ :iexpand=>:nes, :ipadx=>[2,0])
+
+ # Text
+ s = t.style_create('unread.we')
+ t.style_elements(s, ['sel.we', 'text.unread'])
+ t.style_layout(s, 'text.unread', :padx=>6, :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.we', :detach=>true, :iexpand=>:es)
+
+ # Text
+ s = t.style_create('read.we')
+ t.style_elements(s, ['sel.we', 'text.read'])
+ t.style_layout(s, 'text.read', :padx=>6, :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.we', :detach=>true, :iexpand=>:es)
+
+ # Text
+ s = t.style_create('unread.w')
+ t.style_elements(s, ['sel.w', 'text.unread'])
+ t.style_layout(s, 'text.unread', :padx=>6, :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.w', :detach=>true, :iexpand=>:es)
+
+ # Text
+ s = t.style_create('read.w')
+ t.style_elements(s, ['sel.w', 'text.read'])
+ t.style_layout(s, 'text.read', :padx=>6, :squeeze=>:x, :expand=>:ns)
+ t.style_layout(s, 'sel.w', :detach=>true, :iexpand=>:es)
+
+ msgCnt = 100
+ thread = 0
+
+ @Message = Hash.new{|k, v| k[v] = Hash.new}
+ @Message[:count][0] = 0
+
+ (1...(msgCnt)).each{|i|
+ t.item_create
+ j = nil
+ loop {
+ j = rand(i)
+ break if j == 0
+ next if t.depth(j) == 5
+ next if @Message[:count][@Message[:thread][j]] == 15
+ break
+ }
+ t.item_lastchild(j, i)
+
+ @Message[:read][i] = (rand(2) == 0)
+ if j == 0
+ thread += 1
+ @Message[:thread][i] = thread
+ @Message[:seconds][i] = (Tk::Clock.seconds - rand(500000))
+ @Message[:seconds2][i] = @Message[:seconds][i]
+ @Message[:count][thread] = 1
+ else
+ @Message[:thread][i] = @Message[:thread][j]
+ @Message[:seconds][i] = (@Message[:seconds2][j] + rand(10000))
+ @Message[:seconds2][i] = @Message[:seconds][i]
+ @Message[:seconds2][j] = @Message[:seconds][i]
+ @Message[:count][@Message[:thread][j]] += 1
+ end
+ }
+
+ (1...(msgCnt)).each{|i|
+ subject = "This is thread number #{@Message[:thread][i]}"
+ from = 'somebody@somewhere.net'
+ sent = Tk::Clock.format(@Message[:seconds][i], "%d/%m/%y %I:%M %p")
+ size = "#{1 + rand(10)}KB"
+ if @Message[:read][i]
+ style = 'read'
+ style2 = 'read2'
+ else
+ style = 'unread'
+ style2 = 'unread2'
+ end
+ t.item_style_set(i, 3, style, 4, "#{style2}.we", 5, "#{style2}.we",
+ 6, "#{style2}.w")
+ t.item_text(i, 3, subject, 4, from, 5, sent, 6, size)
+ if t.item_numchildren(i) > 0
+ t.item_configure(item_i, :button=>true)
+ end
+ }
+
+ # Do something when the selection changes
+ t.notify_bind(t, 'Selection',
+ proc{|w|
+ if w.selection_count == 1
+ i = t.selection_get[0]
+ unless @Message[:read][i]
+ if t.item_isopen(i) || !anyUnreadDescendants(t, i)
+ # unread -> read
+ t.item_style_map(i, 'subject', 'read',
+ ['text.unread', 'text.read'])
+ t.item_style_map(i, 'from', 'read.we',
+ ['text.unread', 'text.read'])
+ t.item_style_map(i, 'sent', 'read.we',
+ ['text.unread', 'text.read'])
+ t.item_style_map(i, 'size', 'read.w',
+ ['text.unread', 'text.read'])
+ else
+ # unread -> read2
+ t.item_style_map(i, 'subject', 'read2',
+ ['text.unread', 'text.unread'])
+ end
+
+ @Message[:read][i] = true
+ @display_styles_in_item.call(i)
+ end
+ end
+ }, '%T')
+
+ t.notify_bind(t, 'Expand-after',
+ proc{|w, i|
+ if @Messge[:read][i] && anyUnreadDescendants(t, i)
+ # read2 -> read
+ t.item_style_map(i, 'subject', 'read',
+ ['text.unread', 'text.read'])
+ # unread -> read
+ t.item_style_map(i, 'from', 'read.we',
+ ['text.unread', 'text.read'])
+ t.item_style_map(i, 'sent', 'read.we',
+ ['text.unread', 'text.read'])
+ t.item_style_map(i, 'size', 'read.w',
+ ['text.unread', 'text.read'])
+ end
+ }, '%T %I')
+
+ t.notify_bind(t, 'Collapse-after',
+ proc{|w, i|
+ if @Messge[:read][i] && anyUnreadDescendants(t, i)
+ # read -> read2
+ t.item_style_map(i, 'subject', 'read2',
+ ['text.read', 'text.unread'])
+ # read -> unread
+ t.item_style_map(i, 'from', 'unread.we',
+ ['text.read', 'text.unread'])
+ t.item_style_map(i, 'sent', 'unread.we',
+ ['text.read', 'text.unread'])
+ t.item_style_map(i, 'size', 'unread.w',
+ ['text.read', 'text.unread'])
+ end
+ }, '%T %I')
+
+ (1...(msgCnt)).each{|i|
+ if rand(2) == 0
+ if t.item_numchildren(i) > 0
+ if $Version_1_1_OrLater
+ t.item_collapse(i)
+ else # TreeCtrl 1.0
+ t.collapse(i)
+ end
+ end
+ end
+ }
+end
+
+def anyUnreadDescendants(t, i)
+ itemList = []
+ item = t.item_firstchild(i)
+ itemList.push(item) if item != ''
+
+ while item = itemList.pop
+ return true unless @Message[:read][item]
+
+ item2 = t.item_nextsibling(item)
+ itemList.push(item2) if item2 != ''
+ item2 = t.item_firstchild(item)
+ itemList.push(item2) if item2 != ''
+ end
+ false
+end
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-dll.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-dll.gif
new file mode 100644
index 0000000000..09170c0e26
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/big-dll.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-exe.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-exe.gif
new file mode 100644
index 0000000000..e19aac1a2d
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/big-exe.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-file.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-file.gif
new file mode 100644
index 0000000000..6c752312a3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/big-file.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-folder.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-folder.gif
new file mode 100644
index 0000000000..186c9749fd
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/big-folder.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/big-txt.gif b/ext/tk/sample/tkextlib/treectrl/pics/big-txt.gif
new file mode 100644
index 0000000000..a93492586e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/big-txt.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/checked.gif b/ext/tk/sample/tkextlib/treectrl/pics/checked.gif
new file mode 100644
index 0000000000..3b9b176ab3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/checked.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/file.gif b/ext/tk/sample/tkextlib/treectrl/pics/file.gif
new file mode 100644
index 0000000000..a64c2a06bd
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/file.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/folder-closed.gif b/ext/tk/sample/tkextlib/treectrl/pics/folder-closed.gif
new file mode 100644
index 0000000000..0a064376c9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/folder-closed.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/folder-open.gif b/ext/tk/sample/tkextlib/treectrl/pics/folder-open.gif
new file mode 100644
index 0000000000..3fac27ffd9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/folder-open.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/help-book-closed.gif b/ext/tk/sample/tkextlib/treectrl/pics/help-book-closed.gif
new file mode 100644
index 0000000000..0a0497bfa3
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/help-book-closed.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/help-book-open.gif b/ext/tk/sample/tkextlib/treectrl/pics/help-book-open.gif
new file mode 100644
index 0000000000..40656c5194
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/help-book-open.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/help-page.gif b/ext/tk/sample/tkextlib/treectrl/pics/help-page.gif
new file mode 100644
index 0000000000..e1ce1d72f5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/help-page.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-01.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-01.gif
new file mode 100644
index 0000000000..5fd9215551
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-01.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-02.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-02.gif
new file mode 100644
index 0000000000..3d2d1c17c2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-02.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-03.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-03.gif
new file mode 100644
index 0000000000..9fccf12b51
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-03.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-04.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-04.gif
new file mode 100644
index 0000000000..eff851c9bb
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-04.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-05.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-05.gif
new file mode 100644
index 0000000000..ad00c827f6
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-05.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-06.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-06.gif
new file mode 100644
index 0000000000..238bf162ac
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-06.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/imovie-07.gif b/ext/tk/sample/tkextlib/treectrl/pics/imovie-07.gif
new file mode 100644
index 0000000000..a9287e1b1c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/imovie-07.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-check-off.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-check-off.gif
new file mode 100644
index 0000000000..e64866a394
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-check-off.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-check-on.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-check-on.gif
new file mode 100644
index 0000000000..cf652beff2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-check-on.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-print.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-print.gif
new file mode 100644
index 0000000000..7ac25b10e9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-print.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-off.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-off.gif
new file mode 100644
index 0000000000..90ef62971f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-off.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-on.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-on.gif
new file mode 100644
index 0000000000..9de742c198
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-radio-on.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-search.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-search.gif
new file mode 100644
index 0000000000..1f9a047701
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-search.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/internet-security.gif b/ext/tk/sample/tkextlib/treectrl/pics/internet-security.gif
new file mode 100644
index 0000000000..86d3943786
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/internet-security.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/mac-collapse.gif b/ext/tk/sample/tkextlib/treectrl/pics/mac-collapse.gif
new file mode 100644
index 0000000000..81302c80c1
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/mac-collapse.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/mac-expand.gif b/ext/tk/sample/tkextlib/treectrl/pics/mac-expand.gif
new file mode 100644
index 0000000000..0a2cd80040
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/mac-expand.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-arrow.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-arrow.gif
new file mode 100644
index 0000000000..b1c2afd426
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-arrow.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-clip.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-clip.gif
new file mode 100644
index 0000000000..8578132702
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-clip.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-deleted.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-deleted.gif
new file mode 100644
index 0000000000..7cc8369b4b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-deleted.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-draft.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-draft.gif
new file mode 100644
index 0000000000..f19585050f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-draft.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-folder.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-folder.gif
new file mode 100644
index 0000000000..b3f733563b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-folder.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-group.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-group.gif
new file mode 100644
index 0000000000..29ad9b466e
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-group.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-inbox.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-inbox.gif
new file mode 100644
index 0000000000..f41d804444
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-inbox.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-local.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-local.gif
new file mode 100644
index 0000000000..0c74970d32
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-local.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-main.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-main.gif
new file mode 100644
index 0000000000..92325fa85f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-main.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-outbox.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-outbox.gif
new file mode 100644
index 0000000000..c7e80527a0
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-outbox.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-read-2.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-read-2.gif
new file mode 100644
index 0000000000..2f15a3af05
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-read-2.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-read.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-read.gif
new file mode 100644
index 0000000000..a6f956207a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-read.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-sent.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-sent.gif
new file mode 100644
index 0000000000..963b56c4c9
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-sent.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-server.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-server.gif
new file mode 100644
index 0000000000..c950845d62
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-server.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-unread.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-unread.gif
new file mode 100644
index 0000000000..3df4b99439
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-unread.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/outlook-watch.gif b/ext/tk/sample/tkextlib/treectrl/pics/outlook-watch.gif
new file mode 100644
index 0000000000..87ec861312
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/outlook-watch.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/sky.gif b/ext/tk/sample/tkextlib/treectrl/pics/sky.gif
new file mode 100644
index 0000000000..b7fbf14a0a
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/sky.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-dll.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-dll.gif
new file mode 100644
index 0000000000..d8875ec23f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/small-dll.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-exe.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-exe.gif
new file mode 100644
index 0000000000..69d30beacd
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/small-exe.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-file.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-file.gif
new file mode 100644
index 0000000000..f340662879
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/small-file.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-folder.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-folder.gif
new file mode 100644
index 0000000000..ad1b24da84
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/small-folder.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/small-txt.gif b/ext/tk/sample/tkextlib/treectrl/pics/small-txt.gif
new file mode 100644
index 0000000000..cdc7cbfe99
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/small-txt.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/pics/unchecked.gif b/ext/tk/sample/tkextlib/treectrl/pics/unchecked.gif
new file mode 100644
index 0000000000..833e48268b
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/pics/unchecked.gif
Binary files differ
diff --git a/ext/tk/sample/tkextlib/treectrl/random.rb b/ext/tk/sample/tkextlib/treectrl/random.rb
new file mode 100644
index 0000000000..2c9e614aa5
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/random.rb
@@ -0,0 +1,508 @@
+#
+def random_N
+ @RandomN[0] || 500
+end
+
+#
+# Demo: random N items
+#
+def demoRandom(t)
+ init_pics('folder-*', 'small-*')
+
+ height = t.font.metrics(:linespace)
+ height = 18 if height < 18
+ t.configure(:itemheight=>height, :selectmode=>:extended,
+ :showroot=>true, :showrootbutton=>true, :showbuttons=>true,
+ :showlines=>true, :scrollmargin=>16,
+ :xscrolldelay=>[500, 50], :yscrolldelay=>[500, 50])
+
+ if $Version_1_1_OrLater
+ t.column_create(:expand=>true, :text=>'Item',
+ :itembackground=>['#e0e8f0', []], :tag=>'item')
+ t.column_create(:text=>'Parent', :justify=>:center,
+ :itembackground=>['gray90', []], :tag=>'parent')
+ t.column_create(:text=>'Depth', :justify=>:center,
+ :itembackground=>['linen', []], :tag=>'depth')
+ else # TreeCtrl 1.0
+ t.column_configure(0, :expand=>true, :text=>'Item',
+ :itembackground=>['#e0e8f0', []], :tag=>'item')
+ t.column_configure(1, :text=>'Parent', :justify=>:center,
+ :itembackground=>['gray90', []], :tag=>'parent')
+ t.column_configure(2, :text=>'Depth', :justify=>:center,
+ :itembackground=>['linen', []], :tag=>'depth')
+ end
+
+ t.element_create('e1', :image, :image=>[
+ @images['folder-open'], ['open'],
+ @images['folder-closed'], []
+ ])
+ t.element_create('e2', :image, :image=>@images['small-file'])
+ t.element_create('e3', :text,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('e4', :text, :fill=>'blue')
+ t.element_create('e6', :text)
+ t.element_create('e5', :rect, :showfocus=>true,
+ :fill=>[
+ @SystemHighlight, ['selected', 'focus'],
+ 'gray', ['selected', '!focus']
+ ])
+
+ s = t.style_create('s1')
+ t.style_elements(s, ['e5', 'e1', 'e3', 'e4'])
+ t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e3', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e4', :padx=>[0,6], :expand=>:ns)
+ t.style_layout(s, 'e5', :union=>['e3'], :iexpand=>:ns, :ipadx=>2)
+
+ s = t.style_create('s2')
+ t.style_elements(s, ['e5', 'e2', 'e3'])
+ t.style_layout(s, 'e2', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e3', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e5', :union=>['e3'], :iexpand=>:ns, :ipadx=>2)
+
+ s = t.style_create('s3')
+ t.style_elements(s, ['e6'])
+ t.style_layout(s, 'e6', :padx=>6, :expand=>:ns)
+
+ @Priv[:sensitive, t] = [
+ [:item, 's1', 'e5', 'e1', 'e3'],
+ [:item, 's2', 'e5', 'e2', 'e3']
+ ]
+ @Priv[:dragimage, t] = [
+ [:item, 's1', 'e1', 'e3'],
+ [:item, 's2', 'e2', 'e3']
+ ]
+
+ clicks = Tk::Clock.clicks
+ items = [ t.index(:root) ]
+ (1...(random_N())).each{|i|
+ item_i = t.item_create
+ item_j = nil
+ loop {
+ j = rand(i)
+ item_j = items[j]
+ break if t.depth(item_j) < 5
+ }
+ if $Version_1_1_OrLater
+ t.item_collapse(item_i) if rand(2) == 0
+ else # TreeCtrl 1.0
+ t.collapse(item_i) if rand(2) == 0
+ end
+ if rand(2) == 0
+ t.item_lastchild(item_j, item_i)
+ else
+ t.item_firstchild(item_j, item_i)
+ end
+ items << item_i
+ }
+ puts "created #{random_N() - 1} items in #{Tk::Clock.clicks - clicks} clicks"
+
+ clicks = Tk::Clock.clicks
+ (0...(random_N())).each{|i|
+ item_i = items[i]
+ numChildren = t.item_numchildren(item_i)
+ if numChildren > 0
+ if $Version_1_1_OrLater
+ t.item_configure(item_i, :button=>true)
+ else # TreeCtrl 1.0
+ t.item_hasbutton(item_i, true)
+ end
+ t.item_style_set(item_i, 0, 's1', 1, 's3', 2, 's3')
+ t.item_complex(item_i,
+ [ ['e3', {:text=>"Item #{i}"}],
+ ['e4', {:text=>"(#{numChildren})"}] ],
+ [ ['e6', {:text=>"#{t.item_parent(item_i)}"}] ],
+ [ ['e6', {:text=>"#{t.depth(item_i)}"}] ])
+ else
+ t.item_style_set(item_i, 1, 's3', 2, 's3', 0, 's2')
+ t.item_complex(item_i,
+ [ ['e3', {:text=>"Item #{i}"}] ],
+ [ ['e6', {:text=>"#{t.item_parent(item_i)}"}] ],
+ [ ['e6', {:text=>"#{t.depth(item_i)}"}] ])
+ end
+ }
+ puts "configured #{random_N()} items in #{Tk::Clock.clicks - clicks} clicks"
+
+ treeCtrlRandom = TkBindTag.new
+
+ treeCtrlRandom.bind('Double-ButtonPress-1',
+ proc{|w, x, y|
+ Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlRandom.bind('Control-ButtonPress-1',
+ proc{|w, x, y|
+ @Priv['selectMode'] = :toggle
+ randomButton1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlRandom.bind('Shift-ButtonPress-1',
+ proc{|w, x, y|
+ @Priv['selectMode'] = :add
+ randomButton1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlRandom.bind('ButtonPress-1',
+ proc{|w, x, y|
+ @Priv['selectMode'] = :set
+ randomButton1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlRandom.bind('Button1-Motion',
+ proc{|w, x, y|
+ randomMotion1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlRandom.bind('Button1-Leave',
+ proc{|w, x, y|
+ randomLeave1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ treeCtrlRandom.bind('ButtonRelease-1',
+ proc{|w, x, y|
+ randomRelease1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ t.bindtags = [ t, treeCtrlRandom, Tk::TreeCtrl, t.winfo_toplevel, :all ]
+end
+
+def randomButton1(t, x, y)
+ t.set_focus
+ id = t.identify(x, y)
+ puts id.inspect
+ @Priv['buttonMode'] = ''
+
+ # Click outside any item
+ if id.empty?
+ t.selection_clear
+
+ # Click in header
+ elsif id[0] == 'header'
+ Tk::TreeCtrl::BindCallback.buttonPress1(t, x, y)
+
+ # Click in item
+ else
+ where, item, arg1, arg2, arg3, arg4 = id
+ case arg1
+ when 'button'
+ if $Version_1_1_OrLater
+ t.item_toggle(item)
+ else # TreeCtrl 1.0
+ t.toggle(item)
+ end
+
+ when 'line'
+ if $Version_1_1_OrLater
+ t.item_toggle(arg2)
+ else # TreeCtrl 1.0
+ t.toggle(arg2)
+ end
+
+ when 'column'
+ ok = false
+ # Clicked an element
+ if id.length == 6
+ column = id[3]
+ e = id[5]
+ @Priv.list_element(:sensitive, t).each{|lst|
+ c, s, *eList = TkComm.simplelist(lst)
+ next if column != t.column_index(c)
+ next if t.item_style_set(item, c) != s
+ next if eList.find{|le| le == e} == nil
+ ok = true
+ break
+ }
+ end
+ unless ok
+ t.selection_clear
+ return
+ end
+
+ @Priv[:drag, :motion] = 0
+ @Priv[:drag, :x] = t.canvasx(x)
+ @Priv[:drag, :y] = t.canvasy(y)
+ @Priv[:drop] = ''
+
+ if @Priv['selectMode'] == 'add'
+ Tk::TreeCtrl::BindCallback.beginExtend(t, item)
+ elsif @Priv['selectMode'] == 'toggle'
+ Tk::TreeCtrl::BindCallback.beginToggle(t, item)
+ elsif ! t.selection_includes(item)
+ Tk::TreeCtrl::BindCallback.beginSelect(t, item)
+ end
+ t.activate(item)
+
+ if t.selection_includes(item)
+ @Priv['buttonMode'] = 'drag'
+ end
+ end
+ end
+end
+
+def randomMotion1(t, x, y)
+ case @Priv['buttonMode']
+ when 'resize', 'header'
+ Tk::TreeCtrl::BindCallback.motion1(t, x, y)
+ when 'drag'
+ randomAutoScanCheck(t, x, y)
+ randomMotion(t, x, y)
+ end
+end
+
+def randomMotion(t, x, y)
+ case @Priv['buttonMode']
+ when 'resize', 'header'
+ Tk::TreeCtrl::BindCallback.motion1(t, x, y)
+
+ when 'drag'
+ # Detect initial mouse movement
+ unless @Priv.bool_element(:drag, :motion)
+ @Priv[:selection] = t.selection_get
+ @Priv[:drop] = ''
+ t.dragimage_clear
+ # For each selected item, add 2nd and 3rd elements of
+ # column "item" to the dragimage
+ @Priv.list_element(:selection).each{|i|
+ @Priv.list_element(:dragimage,t).each{|lst|
+ c, s, *eList = TkComm.simplelist(lst)
+ if t.item_style_set(i, c) == s
+ t.dragimage_add(i, c, *eList)
+ end
+ }
+ }
+ @Priv[:drag,:motion] = true
+ end
+
+ # Find the item under the cursor
+ cursor = 'X_cursor'
+ drop = ''
+ id = t.identify(x, y)
+ ok = false
+ if !id.empty? && id[0] == 'item' && id.length == 6
+ item = id[1]
+ column = id[3]
+ e = id[5]
+ @Priv.list_element(:sensitive,t).each{|lst|
+ c, s, *eList = TkComm.simplelist(lst)
+ next if column != t.column_index(c)
+ next if t.item_style_set(item, c) != s
+ next unless eList.find{|val| val.to_s == e.to_s}
+ ok = true
+ break
+ }
+ ok = true if @Priv.list_element(:sensitive,t).find{|val| TkComm.simplelist(val).index(e)}
+ end
+
+ if ok
+ # If the item is not in the pre-drag selection
+ # (i.e. not being dragged) see if we can drop on it
+ unless @Priv.list_element(:selection).find{|val| val.to_s == item.to_s}
+ drop = item
+ # We can drop if dragged item isn't an ancestor
+ @Priv.list_element(:selection).each{|item2|
+ if t.item_isancestor(item2, item)
+ drop = ''
+ break
+ end
+ }
+ if drop != ''
+ x1, y1, x2, y2 = t.item_bbox(drop)
+ if y < y1 + 3
+ cursor = 'top_side'
+ @Priv[:drop,:pos] = 'prevsibling'
+ elsif y >= y2 - 3
+ cursor = 'bottom_side'
+ @Priv[:drop,:pos] = 'nextsibling'
+ else
+ cursor = ''
+ @Priv[:drop,:pos] = 'lastchild'
+ end
+ end
+ end
+ end
+
+ t[:cursor] = cursor if t[:cursor] != cursor
+
+ # Select the item under the cursor (if any) and deselect
+ # the previous drop-item (if any)
+ t.selection_modify(drop, @Priv[:drop])
+ @Priv[:drop] = drop
+
+ # Show the dragimage in its new position
+ x = t.canvasx(x) - @Priv.numeric_element(:drag,:x)
+ y = t.canvasx(y) - @Priv.numeric_element(:drag,:y)
+ t.dragimage_offset(x, y)
+ t.dragimage_configure(:visible=>true)
+ end
+end
+
+def randomLeave1(t, x, y)
+ # This is called when I do ButtonPress-1 on Unix for some reason,
+ # and buttonMode is undefined.
+ return unless @Priv.exist?('buttonMode')
+ case @Priv['buttonMode']
+ when 'header'
+ Tk::TreeCtrl::BindCallback.leave1(t, x, y)
+ end
+end
+
+def randomRelease1(t, x, y)
+ case @Priv['buttonMode']
+ when 'resize', 'header'
+ Tk::TreeCtrl::BindCallback.release1(t, x, y)
+ when 'drag'
+ Tk::TreeCtrl::BindCallback.autoScanCancel(t)
+ t.dragimage_configure(:visible=>false)
+ t.selection_modify('', @Priv[:drop])
+ t[:cursor] = ''
+ if @Priv[:drop] != ''
+ randomDrop(t, @Priv[:drop], @Priv.list_element(:selection),
+ @Priv[:drop, :pos])
+ end
+ end
+ @Priv['buttonMode'] = ''
+end
+
+def randomDrop(t, target, src, pos)
+ parentList = []
+ case pos
+ when 'lastchild'
+ parent = target
+ when 'prevsibling'
+ parent = t.item_parent(target)
+ when 'nextsibling'
+ parent = t.item_parent(target)
+ end
+ src.each{|item|
+ # Ignore any item whose ancestor is also selected
+ ignore = false
+ t.item_ancestors(item).each{|ancestor|
+ if src.find{|val| val.to_s == ancestor.to_s}
+ ignore = true
+ break
+ end
+ }
+ next if ignore
+
+ # Update the old parent of this moved item later
+ unless parentList.find{|val| val.to_s == item.to_s}
+ parentList << t.item_parent(item)
+ end
+
+ # Add to target
+ t.__send__("item_#{pos}", target, item)
+
+ # Update text: parent
+ t.item_element_configure(item, 'parent', 'e6', :text=>parent)
+
+ # Update text: depth
+ t.item_element_configure(item, 'depth', 'e6', :text=>t.depth(item))
+
+ # Recursively update text: depth
+ itemList = []
+ item = t.item_firstchild(item)
+ itemList << item if item != ''
+
+ while item = itemList.pop
+ t.item_element_configure(item, 'depth', 'e6', :text=>t.depth(item))
+
+ item2 = t.item_nextsibling(item)
+ itemList << item2 if item2 != ''
+
+ item2 = t.item_firstchild(item)
+ itemList << item2 if item2 != ''
+ end
+ }
+
+ # Update items that lost some children
+ parentList.each{|item|
+ numChildren = t.item_numchildren(item)
+ if numChildren == 0
+ if $Version_1_1_OrLater
+ t.item_configure(item, :button=>false)
+ else # TreeCtrl 1.0
+ t.item_hasbutton(item, false)
+ end
+ t.item_style_map(item, 'item', 's2', ['e3', 'e3'])
+ else
+ t.item_element_configure(item, 'item', 'e4', :text=>"(#{numChildren})")
+ end
+ }
+
+ # Update the target that gained some children
+ if t.item_style_set(parent, 0) != 's1'
+ if $Version_1_1_OrLater
+ t.item_configure(parent, :button=>true)
+ else # TreeCtrl 1.0
+ t.item_hasbutton(parent, true)
+ end
+ t.item_style_map(parent, 'item', 's1', ['e3', 'e3'])
+ end
+ numChildren = t.item_numchildren(parent)
+ t.item_element_configure(parent, 'item', 'e4', :text=>"(#{numChildren})")
+end
+
+# Same as TreeCtrl::AutoScanCheck, but calls RandomMotion and
+# RandomAutoScanCheckAux
+def randomAutoScanCheck(t, x, y)
+ x1, y1, x2, y2 = t.contentbox
+ margin = t.winfo_pixels(t.scrollmargin)
+ if x < x1 + margin || x >= x2 - margin || y < y1 + margin || y >= y2 - margin
+ if ! @Priv.exist?(:autoscan, :afterId, t)
+ if y >= y2 - margin
+ t.yview(:scroll, 1, :units)
+ delay = t.yscrolldelay
+ elsif y < y1 + margin
+ t.yview(:scroll, -1, :units)
+ delay = t.yscrolldelay
+ elsif x >= x2 - margin
+ t.xview(:scroll, 1, :units)
+ delay = t.xscrolldelay
+ elsif x < x1 + margin
+ t.xview(:scroll, -1, :units)
+ delay = t.xscrolldelay
+ end
+ if @Priv.exist?(:autoscan, :scanning, t)
+ delay = delay[1] if delay.kind_of?(Array)
+ else
+ delay = delay[0] if delay.kind_of?(Array)
+ @Priv[:autoscan, :scanning, t] = true
+ end
+ case @Priv['buttonMode']
+ when 'drag', 'marquee'
+ randomMotion(t, x, y)
+ end
+ @Priv[:autoscan, :afterId, t] =
+ Tk.after(delay, proc{ randomAutoScanCheckAux(t) })
+ end
+ return
+ end
+ Tk::TreeCtrl::BindCallback.autoScanCancel(t)
+end
+
+def randomAutoScanCheckAux(t)
+ @Priv.unset(:autoscan, :afterId, t)
+ x = t.winfo_pointerx - t.winfo_rootx
+ y = t.winfo_pointery - t.winfo_rooty
+ randomAutoScanCheck(t, x, y)
+end
+
+#
+# Demo: random N items, button images
+#
+def demoRandom2(t)
+ demoRandom(t)
+
+ init_pics('mac-*')
+
+ t.configure(:openbuttonimage=>@images['mac-collapse'],
+ :closedbuttonimage=>@images['mac-expand'],
+ :showlines=>false)
+end
diff --git a/ext/tk/sample/tkextlib/treectrl/readme.txt b/ext/tk/sample/tkextlib/treectrl/readme.txt
new file mode 100644
index 0000000000..9f26ac069c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/readme.txt
@@ -0,0 +1,2 @@
+The scripts and image files in this directory are based on demo files
+of Tcl/Tk's TreeCtrl extention.
diff --git a/ext/tk/sample/tkextlib/treectrl/www-options.rb b/ext/tk/sample/tkextlib/treectrl/www-options.rb
new file mode 100644
index 0000000000..efa55ca06c
--- /dev/null
+++ b/ext/tk/sample/tkextlib/treectrl/www-options.rb
@@ -0,0 +1,303 @@
+def demoInternetOptions (t)
+ @Option = TkVarAccess.new_hash('::Option')
+
+ height = t.font.metrics(:linespace) + 2
+ height = 18 if height < 18
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :itemheight=>height, :selectmode=>:browse)
+
+ init_pics('internet-*')
+
+ if $HasColumnCreate
+ t.column_create(:text=>'Internet Options')
+ else
+ t.column_configure(0, :text=>'Internet Options')
+ end
+
+ t.state_define('check')
+ t.state_define('radio')
+ t.state_define('on')
+
+ t.element_create('e1', :image, :image=>[
+ @images['internet-check-on'], ['check', 'on'],
+ @images['internet-check-off'], ['check'],
+ @images['internet-radio-on'], ['radio', 'on'],
+ @images['internet-radio-off'], ['radio']
+ ])
+ t.element_create('e2', :text,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('e3', :rect, :showfocus=>true,
+ :fill=>[@SystemHighlight, ['selected', 'focus']])
+
+ s = t.style_create('s1')
+ t.style_elements(s, ['e3', 'e1', 'e2'])
+ t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e2', :expand=>:ns)
+ t.style_layout(s, 'e3', :union=>['e2'], :iexpand=>:ns, :ipadx=>2)
+
+ parentList = [:root, '', '', '', '', '', '']
+ parent = :root
+ [
+ [0, :print, "Printing", "", ""],
+ [1, :off, "Print background colors and images", "o1", ""],
+ [0, :search, "Search from Address bar", "", ""],
+ [1, :search, "When searching", "", ""],
+ [2, :off, "Display results, and go to the most likely sites",
+ "o2", "r1"],
+ [2, :off, "Do not search from the Address bar", "o3", "r1"],
+ [2, :off, "Just display the results in the main window",
+ "o4", "r1"],
+ [2, :on, "Just go to the most likely site", "o5", "r1"],
+ [0, :security, "Security", "", ""],
+ [1, :on, "Check for publisher's certificate revocation", "o5", ""],
+ [1, :off, "Check for server certificate revocation (requires restart)",
+ "o6", ""]
+ ].each{|depth, setting, text, option, group|
+ item = t.item_create()
+ t.item_style_set(item, 0, 's1')
+ t.item_element_configure(item, 0, 'e2', :text=>text)
+ @Option[:option, item] = option
+ @Option[:group, item] = group
+ if setting == :on || setting == :off
+ @Option[:setting, item] = setting
+ if group == ''
+ t.item_state_set(item, 'check')
+ if setting == :on
+ t.item_state_set(item, 'on')
+ end
+ else
+ if setting == :on
+ @Option[:current, group] = item
+ t.item_state_set(item, 'on')
+ end
+ t.item_state_set(item, 'radio')
+ end
+ else
+ t.item_element_configure(item, 0, 'e1',
+ :image=>@images["internet-#{setting}"])
+ end
+ t.item_lastchild(parentList[depth], item)
+ depth += 1
+ parentList[depth] = item
+ }
+
+ treeCtrlOption = TkBindTag.new
+ treeCtrlOption.bind('Double-ButtonPress-1', proc{|w, x, y|
+ Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y)
+ }, '%W %x %y')
+ treeCtrlOption.bind('ButtonPress-1', proc{|w, x, y|
+ optionButton1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+ treeCtrlOption.bind('Button1-Motion', proc{|w, x, y|
+ optionMotion1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+ treeCtrlOption.bind('Button1-Leave', proc{|w, x, y|
+ optionLeave1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+ treeCtrlOption.bind('ButtonRelease-1', proc{|w, x, y|
+ optionRelease1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ t.bindtags = [
+ t, treeCtrlOption, Tk::TreeCtrl, t.winfo_toplevel, TkBindTag::ALL
+ ]
+end
+
+def optionButton1(w, x, y)
+ w.set_focus
+ id = w.identify(x, y)
+ if id[0] == 'header'
+ Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y)
+ elsif id.empty?
+ @Priv['buttonMode'] = ''
+ else
+ @Priv['buttonMode'] = ''
+ item = id[1]
+ w.selection_modify(item, :all)
+ w.activate(item)
+ return if @Option[:option, item] == ''
+ group = @Option[:group, item]
+ if group == ''
+ # a checkbutton
+ w.item_state_set(item, '~on')
+ if @Option[:setting, item] == 'on'
+ setting = :off
+ else
+ setting = :on
+ end
+ @Option[:setting, item] = setting
+ else
+ # a radiobutton
+ current = @Option[:current, group]
+ return if current == item.to_s
+ w.item_state_set(current, '!on')
+ w.item_state_set(item, 'on')
+ @Option[:setting, item] = :on
+ @Option[:current, group] = item
+ end
+ end
+end
+
+# Alternate implementation that doesn't rely on run-time styles
+def demoInternetOptions_2(t)
+ height = t.font.metrics(:linespace) + 2
+ height = 18 if height < 18
+ t.configure(:showroot=>false, :showbuttons=>false, :showlines=>false,
+ :itemheight=>height, :selectmode=>:browse)
+
+ init_pics('internet-*')
+
+ t.column_configure(0, :text=>'Internet Options')
+
+ t.element_create('e1', :image)
+ t.element_create('e2', :text,
+ :fill=>[@SystemHighlightText, ['selected', 'focus']])
+ t.element_create('e3', :rect, :showfocus=>true,
+ :fill=>[@SystemHighlight, ['selected', 'focus']])
+
+ s = t.style_create('s1')
+ t.style_elements('s1', ['e3', 'e1', 'e2'])
+ t.style_layout(s, 'e1', :padx=>[0,4], :expand=>:ns)
+ t.style_layout(s, 'e2', :expand=>:ns)
+ t.style_layout(s, 'e3', :union=>['e2'], :iexpand=>:ns, :ipadx=>2)
+
+ parentList = [:root, '', '', '', '', '', '']
+ parent = :root
+ [
+ [0, :print, "Printing", "", ""],
+ [1, :off, "Print background colors and images", "o1", ""],
+ [0, :search, "Search from Address bar", "", ""],
+ [1, :search, "When searching", "", ""],
+ [2, :off, "Display results, and go to the most likely sites",
+ "o2", "r1"],
+ [2, :off, "Do not search from the Address bar", "o3", "r1"],
+ [2, :off, "Just display the results in the main window",
+ "o4", "r1"],
+ [2, :on, "Just go to the most likely site", "o5", "r1"],
+ [0, :security, "Security", "", ""],
+ [1, :on, "Check for publisher's certificate revocation", "o5", ""],
+ [1, :off, "Check for server certificate revocation (requires restart)",
+ "o6", ""]
+ ].each{|depth, setting, text, option, group|
+ item = t.item_create()
+ t.item_style_set(item, 0, 's1')
+ t.item_element_configure(item, 0, 'e2', :text=>text)
+ @Option[:option, item] = option
+ @Option[:group, item] = group
+ if setting == :on || setting == :off
+ @Option[:setting, item] = setting
+ if group == ''
+ img = @images["internet-check-#{setting}"]
+ t.item_element_configure(item, 0, 'e1', :image=>img)
+ else
+ if setting == :on
+ @Option[:current, group] = item
+ end
+ img = @images["internet-radio-#{setting}"]
+ t.item_element_configure(item, 0, 'e1', :image=>img)
+ end
+ else
+ t.item_element_configure(item, 0, 'e1',
+ :image=>@images["internet-#{setting}"])
+ end
+ t.item_lastchild(parentList[depth], item)
+ depth += 1
+ parentList[depth] = item
+ }
+
+ treeCtrlOption = TkBindTag.new
+ treeCtrlOption.bind('Double-ButtonPress-1', proc{|w, x, y|
+ Tk::TreeCtrl::BindCallback.doubleButton1(w, x, y)
+ }, '%W %x %y')
+ treeCtrlOption.bind('ButtonPress-1', proc{|w, x, y|
+ optionButton1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+ treeCtrlOption.bind('Button1-Motion', proc{|w, x, y|
+ optionMotion1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+ treeCtrlOption.bind('Button1-Leave', proc{|w, x, y|
+ optionLeave1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+ treeCtrlOption.bind('ButtonRelease-1', proc{|w, x, y|
+ optionRelease1(w, x, y)
+ Tk.callback_break
+ }, '%W %x %y')
+
+ t.bindtags = [
+ t, treeCtrlOption, Tk::TreeCtrl, t.winfo_toplevel, TkBindTag::ALL
+ ]
+end
+
+def optionButton1_2(w, x, y)
+ w.set_focus
+ id = w.identify(x, y)
+ if id[0] == 'header'
+ Tk::TreeCtrl::BindCallback.buttonPress1(w, x, y)
+ elsif id.empty?
+ @Priv['buttonMode'] = ''
+ else
+ @Priv['buttonMode'] = ''
+ item = id[1]
+ w.selection_modify(item, :all)
+ w.activate(item)
+ return if @Option[:option, item] == ''
+ group = @Option[:group, item]
+ if group == ''
+ # a checkbutton
+ if @Option[:setting, item] == 'on'
+ setting = :off
+ else
+ setting = :on
+ end
+ w.item_element_configure(item, 0, 'e1',
+ :image=>@images["internet-check-#{setting}"])
+ @Option[:setting, item] = setting
+ else
+ # a radiobutton
+ current = @Option[:current, group]
+ return if current == item.to_s
+ w.item_element_configure(current, 0, 'e1',
+ :image=>@images["internet-radio-off"])
+ w.item_element_configure(item, 0, 'e1',
+ :image=>@images["internet-radio-on"])
+ @Option[:setting, item] = :on
+ @Option[:current, group] = item
+ end
+ end
+end
+
+def optionMotion1(w, x, y)
+ case @Priv['buttonMode']
+ when 'resize', 'header'
+ Tk::TreeCtrl::BindCallback.motion1(w, x, y)
+ end
+end
+
+def optionLeave1(w, x, y)
+ # This is called when I do ButtonPress-1 on Unix for some reason,
+ # and buttonMode is undefined.
+ begin
+ mode = @Priv['buttonMode']
+ rescue
+ else
+ case mode
+ when 'header'
+ t.column_configure(@Priv['column'], :sunken=>false)
+ end
+ end
+end
+
+def optionRelease1(w, x, y)
+ case @Priv['buttonMode']
+ when 'resize', 'header'
+ Tk::TreeCtrl::BindCallback.release1(w, x, y)
+ end
+ @Priv['buttonMode'] = ''
+end
diff --git a/ext/tk/sample/tkextlib/vu/Orig_LICENSE.txt b/ext/tk/sample/tkextlib/vu/Orig_LICENSE.txt
new file mode 100644
index 0000000000..f5f2f770cf
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/Orig_LICENSE.txt
@@ -0,0 +1,51 @@
+
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ >>> The following text is the original 'license.txt' of vu extension. <<<
+ >>> Original Tcl source files are not include in this directry, <<<
+ >>> because of all of them are rewrited to Ruby files. <<<
+ >>> However, the bitmap data file included in this directory is the <<<
+ >>> same file of vu extension. So, the bitmap data file is under the <<<
+ >>> following license. <<<
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ * COPYRIGHT AND LICENSE TERMS *
+
+(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
+it falls under similar license terms).
+
+This software is copyrighted by Jeffrey Hobbs <jeff.hobbs@acm.org> and
+others. The following terms apply to all files associated with the
+software unless explicitly disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute, and
+license this software and its documentation for any purpose, provided that
+existing copyright notices are retained in all copies and that this notice
+is included verbatim in any distributions. No written agreement, license,
+or royalty fee is required for any of the authorized uses.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
+EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS
+PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
+OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
+is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
+of the Rights in Technical Data and Computer Software Clause as DFARS
+252.227-7013 and FAR 52.227-19.
+
+SPECIAL NOTES:
+
+This software also falls under the bourbon_ware clause:
+
+ Should you find this software useful in your daily work, you should
+ feel obliged to take the author out for a drink if the opportunity
+ presents itself. The user may feel exempt from this clause if they
+ are under 21 or think the author has already partaken of too many
+ drinks.
diff --git a/ext/tk/sample/tkextlib/vu/README.txt b/ext/tk/sample/tkextlib/vu/README.txt
new file mode 100644
index 0000000000..ce5f371fac
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/README.txt
@@ -0,0 +1,50 @@
+
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ >>> The following text is the original 'README.txt' of <<<
+ >>> vu extension demos. <<<
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+##
+## DESCRIPTION OF DEMOS
+##
+
+canvItems.tcl
+ old demo of all canvas chart items, useful to find memory leaks.
+ <1> prints out the additional memory usage (charts.so + script)
+
+canvSticker.tcl
+ Heribert Dahms original "demo.tcl"
+ <p> creates DEMO.ps
+
+canvSticker2.tcl
+ compares "sticker" and "text"; press <1>, <2> or <1> ...
+ <p> creates DEMO.ps
+
+dial.tcl
+ demo of variations of the dial widget.
+
+load.tcl
+ Just a utility file, not a real demo.
+
+m128_000.xbm
+ XBM pic used by sticker and canvItems demos
+
+oscilloscope.tcl
+ the heart of a Realtime Oscilloscope,where the PC´s joystick
+ port gives 4 digtal inputs and 4 analog 8 bit values with an
+ resolution of ~1 millisecond (!!!) running Realtime Linux.
+ <p> creates DEMO.ps
+
+pie.tcl
+ The magic 3D spinning pie chart!
+
+vu.tcl
+ demo fo Vu widgets
+
+canvLabel.tcl
+ 'label' is a canvas item just like 'text', but with -angle
+ rotation of the string. This is not built in by default, as
+ it requires the internal Tk headers.
+ press <1>, <2> or <1> ...
+ <p> creates DEMO.ps
+
diff --git a/ext/tk/sample/tkextlib/vu/canvItems.rb b/ext/tk/sample/tkextlib/vu/canvItems.rb
new file mode 100644
index 0000000000..33acf4f7e7
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/canvItems.rb
@@ -0,0 +1,90 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/vu/charts'
+
+#######################################
+
+xbm = File.join(File.dirname(File.expand_path(__FILE__)), 'm128_000.xbm')
+
+sval = [ 11, 22, 33, 44, 55, 66, 77, 88, 99 ]
+
+l0 = TkLabel.new(:width=>128, :height=>128,
+ :bitmap=>"@#{xbm}", :relief=>:groove).pack(:side=>:left)
+
+c0 = TkCanvas.new(:width=>80, :height=>80,
+ :insertwidth=>0, :highlightthickness=>0,
+ :selectborderwidth=>0, :borderwidth=>2,
+ :relief=>:ridge).place(:in=>l0, :relx=>0.5, :rely=>0.5,
+ :anchor=>:c)
+
+st = Tk::Vu::TkcStripchart.new(c0, 3, 3, 80, 80,
+ :background=>"#b7c0d7", :fill=>'slategray3',
+ :jumpscroll=>1, :outline=>'black',
+ :scaleline=>'blue', :stripline=>'red',
+ :selected=>1, :values=>sval)
+
+TkcText.create(c0, 40, 40,
+ :text=>Tk::TCL_PATCHLEVEL, :fill=>'cyan', :tags=>'text')
+
+
+l1 = TkLabel.new(:width=>128, :height=>128,
+ :bitmap=>"@#{xbm}", :relief=>:groove).pack(:side=>:left)
+
+c1 = TkCanvas.new(:width=>80, :height=>80,
+ :insertwidth=>0, :highlightthickness=>0,
+ :selectborderwidth=>0, :borderwidth=>2,
+ :relief=>:ridge).place(:in=>l1, :relx=>0.5, :rely=>0.5,
+ :anchor=>:c)
+
+bar1 = Tk::Vu::TkcBarchart.new(c1, 3, 3, 80, 80,
+ :background=>"#b7c0d7", :scalevalue=>10.0,
+ :autocolor=>true, :selected=>1,
+ :outline=>'black', :barline=>'yellow',
+ :scalelinestyle=>0)
+
+bar2 = Tk::Vu::TkcBarchart.new(c1, 53, 3, 80, 80,
+ :background=>"#b7c0d7", :scalevalue=>10.0,
+ :autocolor=>true, :selected=>1,
+ :outline=>'black', :fill=>"#b7c0d7",
+ :barline=>'red', :scalelinestyle=>22)
+
+
+l2 = TkLabel.new(:width=>128, :height=>128,
+ :bitmap=>"@#{xbm}", :relief=>:groove).pack(:side=>:left)
+
+c2 = TkCanvas.new(:width=>80, :height=>80,
+ :insertwidth=>0, :highlightthickness=>0,
+ :selectborderwidth=>0, :borderwidth=>2,
+ :relief=>:ridge).place(:in=>l2, :relx=>0.5, :rely=>0.5,
+ :anchor=>:c)
+
+begin
+ stick = Tk::Vu::TkcSticker.new(c2, 3, 3, 80, 80,
+ :text=>"Tcl/Tk", :space=>0, :color=>'red',
+ :outline=>'red', :font=>'Helvetica 14 bold',
+ :fill=>'', :stipple=>'', :bar=>'blue',
+ :orient=>:vertical, :anchor=>:s,
+ :relheight=>1.0, :relwidth=>0.15,
+ :relx=>0.1, :rely=>0.0)
+rescue
+ stick = nil
+ TkcText.new(c2, 40, 10, :text=>"No Sticker Item")
+end
+
+c_do = proc{
+ st[:values] = rand() * 100
+
+ bar1[:values] = rand() * 10
+ bar2[:values] = rand() * 10
+
+ stick[:rely] = rand() * 100 * 0.01 if stick
+}
+
+c0.bind('1', c_do)
+
+TkTimer.new(100, -1, c_do).start
+
+Tk.root.bind('q', proc{exit})
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/vu/canvSticker.rb b/ext/tk/sample/tkextlib/vu/canvSticker.rb
new file mode 100644
index 0000000000..e2cd604975
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/canvSticker.rb
@@ -0,0 +1,82 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/vu/charts'
+
+#######################################
+
+Tk.root.geometry('+30+30')
+
+delay = 2000
+
+c = TkCanvas.new.pack
+
+begin
+ st = Tk::Vu::TkcSticker.new(c, 0, 0, 10, 10)
+rescue
+ Tk.messageBox(:type=>'ok', :title=>"No sticker Item",
+ :message=>"This build of vu does not include the sticker item")
+ exit
+end
+#st.delete
+
+steps = []
+
+steps << proc{
+ # I used a 75dpi screen for testing, but others should make no difference!
+ puts 'You\'ll see a small upright rectangle with "He" inside.'
+ st = Tk::Vu::TkcSticker.new(c, '6m', '10m', '13m', '27m', :text=>'Hello')
+}
+
+steps << proc{
+ puts 'You\'ll see the whole "Hello" drawn rotated 90 degrees.'
+ st[:orient] = :vertical
+}
+
+steps << proc{
+ puts 'The rectangle shrinks and the text is clipped to "Hell"'
+ #st.coords('6m', '10m', '13m', '20m')
+ st.coords('6m', '10m', '13m', '17m')
+}
+
+steps << proc{
+ puts 'Now you\'ll read "ello"'
+ st[:lefttrunc] = true
+}
+
+steps << proc{
+ puts 'Enlarging the rectangle shows the complete "Hello" again'
+ st.scale(0, 0, 3, 3)
+}
+
+steps << proc{
+ puts 'This time the text is repeated: "Hello", approx. 5mm space, "Hello"'
+ st[:space] = '5m'
+}
+
+steps << proc{
+ puts 'A vertical bar appears in the lower right region and text jumps to the left.'
+ st.configure(:anchor=>:n, :relw=>0.3, :relh=>0.7,
+ :relx=>0.6, :rely=>0.3, :bar=>'red')
+}
+
+steps << proc{
+ puts 'Paint the backgound.'
+ st[:fill] = 'yellow'
+}
+
+steps << proc{
+ puts "Let's test stippling."
+ st[:stipple] = 'gray25'
+}
+
+steps << proc{
+ puts 'Finally a large outline forces a single "Hello" and shrinks the bar.'
+ st[:width] = '6m'
+}
+
+Tk.root.bind('q', proc{exit})
+
+TkTimer.new(delay, 1, *steps).start
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/vu/canvSticker2.rb b/ext/tk/sample/tkextlib/vu/canvSticker2.rb
new file mode 100644
index 0000000000..548a72c2cb
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/canvSticker2.rb
@@ -0,0 +1,101 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/vu/charts'
+
+#######################################
+
+c = TkCanvas.new.pack
+
+begin
+ st = Tk::Vu::TkcSticker.new(c, 0, 0, 10, 10)
+rescue
+ Tk.messageBox(:type=>'ok', :title=>"No sticker Item",
+ :message=>"This build of vu does not include the sticker item")
+ exit
+end
+
+c.destroy
+
+#---
+#--- set STRING {{x0 y0 x1 y1} {...text...} {resize point: center}
+
+#sti_conf = [ [10, 10, 180, 180], "Sticker äöüß@²³¼½¾", :center ]
+#txt_conf = [ [210, 210], "Text äöüß@²³¼½¾", :center ]
+sti_conf = [ [10, 10, 350, 350],
+ Tk::UTF8_String('Sticker \u00E4\u00F6\u00FC\u00DF\u0040\u00B2\u00B3\u00BC\u00BD\u00BE'),
+ :center ]
+txt_conf = [ [250, 250],
+ Tk::UTF8_String('Text \u00E4\u00F6\u00FC\u00DF\u0040\u00B2\u00B3\u00BC\u00BD\u00BE'),
+ :center ]
+
+#p sti_conf
+
+fnt = TkFont.new('Helvetica 24 bold')
+
+#---GUI
+c = TkCanvas.new(:width=>500, :height=>500, :bg=>'aquamarine3').pack
+
+#---CRRW Use the technique of eval the coord ...
+sti = Tk::Vu::TkcSticker.new(c, sti_conf[0]){
+ anchor sti_conf[2]
+ bar 'black'
+ color 'red'
+ fill ''
+ font fnt
+ lefttrunc 0
+ outline ''
+ relheight 0.0
+ relwidth 0.0
+ relx 0.0
+ rely 0.0
+ space 0
+ stipple ''
+ tags 'sti'
+ text sti_conf[1]
+ width 0
+ orient :vertical
+ minwidth 0
+ minheight 0
+ maxwidth 32767
+ maxheight 32767
+}
+
+txt = TkcText.new(c, txt_conf[0]){
+ activefill ''
+ activestipple ''
+ anchor txt_conf[2]
+ disabledfill ''
+ disabledstipple ''
+ fill 'blue'
+ font fnt
+ justify :left
+ offset '0,0'
+ state ''
+ stipple ''
+ tags ['tex']
+ text txt_conf[1]
+ width 0
+}
+
+#---BINDINGS
+c.bind('2', proc{
+ sti[:orient] = :horizontal
+ txt[:width] = 0 # horizontal
+ })
+
+c.bind('3', proc{
+ sti[:orient] = :vertical
+ txt[:width] = 1 # top down
+ })
+
+Tk.root.bind('p', proc{
+ c.postscript(:file=>'DEMO.ps')
+ puts "DEMO.ps printed"
+ })
+
+Tk.root.bind('q', proc{exit})
+
+#####################
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/vu/dial_demo.rb b/ext/tk/sample/tkextlib/vu/dial_demo.rb
new file mode 100644
index 0000000000..09bd3e9186
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/dial_demo.rb
@@ -0,0 +1,113 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/vu/dial'
+
+#######################################
+
+v_volume = TkVariable.new
+v_speed = TkVariable.new
+v_dir = TkVariable.new
+v_rot = TkVariable.new
+v_linked = TkVariable.new
+v_needle = TkVariable.new
+
+volume = Tk::Vu::Dial.new(:label=>"Volume", :from=>-0.1, :to=>0.1,
+ :resolution=>0.001, :minortickinterval=>0.01,
+ :tickinterval=>0.1, :beginangle=>-20,
+ :endangle=>260, :variable=>v_volume)
+
+speed = Tk::Vu::Dial.new(:label=>"Speed", :from=>2000, :to=>100,
+ :resolution=>10, :tickinterval=>100,
+ :minortickinterval=>0, :variable=>v_speed,
+ :showtags=>:label, :showvalue=>false)
+
+speed.set_tag_constrain(100, 'Fast', 2000, 'Slow')
+
+fwd = Tk::Vu::Dial.new(:from=>-10.0, :to=>-20.0, :resolution=>0.1,
+ :tickinterval=>5.0, :minortickinterval=>1.0,
+ :variable=>v_dir)
+
+rev = Tk::Vu::Dial.new(:from=>-20.0, :to=>-10.0, :resolution=>0.1,
+ :tickinterval=>5.0, :minortickinterval=>1.0,
+ :variable=>v_dir)
+
+small = Tk::Vu::Dial.new(:font=>"Helvetica -10", :from=>0, :to=>10,
+ :resolution=>0.05, :tickinterval=>2,
+ :minortickinterval=>0.5, :radius=>20,
+ :dialcolor=>'red2', :activebackground=>'red',
+ :variable=>v_rot)
+
+large = Tk::Vu::Dial.new(:font=>"Helvetica -8", :from=>0, :to=>10,
+ :resolution=>0.05, :tickinterval=>1,
+ :minortickinterval=>0.25, :radius=>40,
+ :dialcolor=>'red2', :activebackground=>'red',
+ :variable=>v_rot)
+
+turn = Tk::Vu::Dial.new(:needlecolor=>'red', :label=>"Linked",
+ :variable=>v_linked)
+
+scale = TkScale.new(:label=>"Linked", :variable=>v_linked)
+
+d1 = Tk::Vu::Dial.new(:resolution=>0.0001, :from=>-0.1, :to=>0.1,
+ :showvalue=>true, :minortickinterval=>0.01,
+ :tickinterval=>0.1, :radius=>30, :label=>"Dial",
+ :beginangle=>-20, :endangle=>260, :variable=>v_needle,
+ :relief=>:raised)
+
+d2 = Tk::Vu::Dial.new(:resolution=>0.01, :from=>-0.1, :to=>0.1,
+ :showvalue=>true, :minortickinterval=>0.01,
+ :tickinterval=>0.1, :radius=>30, :label=>"Dial 2",
+ :beginangle=>-20, :endangle=>260, :variable=>v_needle,
+ :dialrelief=>:flat, :needlecolor=>'red',
+ :needletype=>:triangle, :relief=>:sunken)
+
+d3 = Tk::Vu::Dial.new(:resolution=>0.001, :from=>-0.1, :to=>0.1,
+ :showvalue=>true, :minortickinterval=>0.01,
+ :tickinterval=>0.1, :radius=>30, :label=>"Dial 3",
+ :beginangle=>-20, :endangle=>260, :variable=>v_needle,
+ :dialrelief=>:flat, :needlecolor=>'blue',
+ :needletype=>:arc, :relief=>:ridge)
+
+f_btns = TkFrame.new
+f_sep = TkFrame.new(:height=>2, :relief=>:sunken, :bd=>1)
+
+
+v_volume.value = -0.1
+v_speed.value = 500
+
+update = TkTimer.new(proc{v_speed.numeric}, -1, proc{
+ if v_volume == volume[:to]
+ v_volume.numeric = volume[:from]
+ else
+ v_volume.numeric += volume[:resolution]
+ end
+ })
+
+b_start = TkButton.new(:text=>"Start", :command=>proc{update.start})
+b_stop = TkButton.new(:text=>"Stop", :command=>proc{update.stop})
+b_exit = TkButton.new(:text=>"Exit", :command=>proc{exit})
+
+Tk.grid(b_start, :in=>f_btns, :sticky=>:ew, :padx=>4, :pady=>4)
+Tk.grid(b_stop, :in=>f_btns, :sticky=>:ew, :padx=>4, :pady=>4)
+f_btns.grid_columnconfigure(0, :weight=>1)
+
+Tk.grid(f_btns, speed, volume, :sticky=>:news)
+Tk.grid(f_sep, '-', '-', :sticky=>:news)
+Tk.grid(fwd, rev, d1, :sticky=>:news)
+Tk.grid(small, large, d2, :sticky=>:news)
+Tk.grid(turn, scale, d3, :sticky=>:news)
+
+Tk.grid(b_exit, '-', '-', :sticky=>:ew, :padx=>4, :pady=>4)
+
+Tk.root.grid_columnconfigure(0, :weight=>1)
+Tk.root.grid_columnconfigure(1, :weight=>1)
+Tk.root.grid_columnconfigure(2, :weight=>1)
+
+Tk.root.grid_rowconfigure(0, :weight=>1)
+Tk.root.grid_rowconfigure(2, :weight=>1)
+Tk.root.grid_rowconfigure(3, :weight=>1)
+Tk.root.grid_rowconfigure(4, :weight=>1)
+
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/vu/m128_000.xbm b/ext/tk/sample/tkextlib/vu/m128_000.xbm
new file mode 100644
index 0000000000..455e3c5e0f
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/m128_000.xbm
@@ -0,0 +1,174 @@
+#define m128_000_width 128
+#define m128_000_height 128
+static unsigned char m128_000_bits[] = {
+ 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
+ 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x03, 0xfc, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x0f, 0xfc, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x0f,
+ 0xbf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3f, 0x7f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3f, 0xaf, 0xfa, 0xab, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xab, 0x3e,
+ 0x5f, 0xf5, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0xf5, 0x57, 0x3d, 0xaf, 0x0e, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0e, 0xac, 0x3e, 0x5f, 0x0d, 0x5c, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x0d, 0x5c, 0x3d,
+ 0xaf, 0x03, 0xb0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x03, 0xb0, 0x3e, 0x5f, 0x03, 0x70, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x03, 0x70, 0x3d, 0xaf, 0x03, 0xb0, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x03, 0xb0, 0x3e,
+ 0x5f, 0x03, 0x70, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x03, 0x70, 0x3d, 0xaf, 0x03, 0xb0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x03, 0xb0, 0x3e, 0x5f, 0x03, 0x70, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x03, 0x70, 0x3d,
+ 0xaf, 0x0e, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x0e, 0xac, 0x3e, 0x5f, 0x0d, 0x5c, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x0d, 0x5c, 0x3d, 0xaf, 0xfa, 0xab, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xab, 0x3e,
+ 0x5f, 0xf5, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0xf5, 0x57, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e,
+ 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d,
+ 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0x3e, 0x5f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3d, 0xaf, 0xfa, 0xab, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xab, 0x3e,
+ 0x5f, 0xf5, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0xf5, 0x57, 0x3d, 0xaf, 0x0e, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0e, 0xac, 0x3e, 0x5f, 0x0d, 0x5c, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x0d, 0x5c, 0x3d,
+ 0xaf, 0x03, 0xb0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x03, 0xb0, 0x3e, 0x5f, 0x03, 0x70, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x03, 0x70, 0x3d, 0xaf, 0x03, 0xb0, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x03, 0xb0, 0x3e,
+ 0x5f, 0x03, 0x70, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x03, 0x70, 0x3d, 0xaf, 0x03, 0xb0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x03, 0xb0, 0x3e, 0x5f, 0x03, 0x70, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x03, 0x70, 0x3d,
+ 0xaf, 0x0e, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0x0e, 0xac, 0x3e, 0x5f, 0x0d, 0x5c, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x0d, 0x5c, 0x3d, 0xaf, 0xfa, 0xab, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfa, 0xab, 0x3e,
+ 0x5f, 0xf5, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0xf5, 0x57, 0x3d, 0xbf, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x3f, 0x7f, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3f,
+ 0xfc, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xea, 0x0f, 0xfc, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x0f, 0xf0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
+ 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
diff --git a/ext/tk/sample/tkextlib/vu/oscilloscope.rb b/ext/tk/sample/tkextlib/vu/oscilloscope.rb
new file mode 100644
index 0000000000..2015e46645
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/oscilloscope.rb
@@ -0,0 +1,68 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/vu/charts'
+
+#---USAGE
+info = "...the heart of a Realtime Oscilloscope, where the PCIs
+joystick port gives 4 digtal inputs and 4 analog 8 bit
+values with an resolution of ~1 millisecond (!!!)
+running Realtime Linux.
+<p> creates DEMO.ps
+<B1-Motion> see what happens"
+puts info
+
+#---GEOMETRY
+geo_fr = [10, 10, 210, 180]
+geo_ch0 = [10, 10, 210, 90]
+geo_ch1 = [10, 90, 210, 180]
+geo_t1 = [15, 88]
+
+#---GUI
+c = TkCanvas.new(:width=>220, :height=>190).pack(:fill=>:both, :expand=>true)
+
+#---background
+TkcRectangle.new(c, geo_fr, :width=>4, :fill=>'aquamarine3',
+ :tags=>['osc', 'frbg'])
+
+#---channel 0
+ch0 = Tk::Vu::TkcStripchart.new(c, geo_ch0,
+ :fill=>'', :jumpscroll=>false,
+ :outline=>'', :scaleline=>'',
+ :stripline=>'cyan', :tags=>['osc', 'ch0'])
+
+#---channel 1
+ch1 = Tk::Vu::TkcStripchart.new(c, geo_ch1,
+ :fill=>'', :jumpscroll=>0,
+ :outline=>'', :scaleline=>'',
+ :stripline=>'red', :tags=>['osc', 'ch1'])
+
+#---frame
+TkcRectangle.new(c, geo_fr, :width=>4, :tags=>['osc', 'frfg'])
+
+#---position
+txt1 = TkcText.new(c, geo_t1, :text=>"B1-Motion: X:%X\tY:%Y",
+ :anchor=>:nw, :tags=>['osc', 'txt1'])
+
+#---BINDINGS
+c.bind('B1-Motion', proc{|x, y, xx, yy|
+ ch0[:values] = x
+ ch1[:values] = y
+ txt1[:text] = "B1-Motion: X:#{xx}\tY:#{yy}"
+ }, '%x %y %X %Y')
+
+Tk.root.bind('v', proc{
+ puts ch0[:values].join(' ')
+ puts ch0[:values].size
+ })
+
+Tk.root.bind('p', proc{
+ c.postscript(:file=>'DEMO.ps')
+ puts "DEMO.ps printed"
+ })
+
+Tk.root.bind('q', proc{exit})
+
+#####################
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/vu/pie.rb b/ext/tk/sample/tkextlib/vu/pie.rb
new file mode 100644
index 0000000000..ed598d6233
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/pie.rb
@@ -0,0 +1,56 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/vu/pie'
+
+pie = Tk::Vu::Pie.new(:label=>"My Revolving Budget"){
+ itemconfigure('Welfare', :value=>3.004)
+ itemconfigure('Military', :value=>7.006)
+ itemconfigure('Transport', :value=>1.6, :explode=>15)
+ itemconfigure('Parks', :value=>0.9)
+ itemconfigure('Schools', :value=>2)
+ itemconfigure('Debt', :value=>4, :explode=>10)
+
+ configure(:angle=>10, :origin=>90, :shadow=>10)
+}
+
+spin = TkTimer.new(60, -1, proc{|obj|
+ pie.configure(:origin=>pie[:origin] + 1)
+})
+
+f = TkFrame.new
+fast_btn = TkButton.new(f, :text=>"Spin Faster", :command=>proc{spin.start})
+slow_btn = TkButton.new(f, :text=>"Spin Slower", :command=>proc{spin.stop})
+quit_btn = TkButton.new(f, :text=>"Exit", :command=>proc{exit})
+
+Tk.grid(pie, :sticky=>:news)
+Tk.grid(f, :sticky=>:ew)
+
+Tk.pack(fast_btn, slow_btn, quit_btn,
+ :in=>f, :side=>:left, :fill=>:both, :expand=>true, :padx=>6, :pady=>4)
+
+Tk.root.grid_columnconfigure(0, :weight=>1)
+Tk.root.grid_rowconfigure(0, :weight=>1)
+
+priv = {
+ :x=>0, :y=>0, :pie_in=>false, :angle=>pie[:angle], :origin=>pie[:origin]
+}
+
+pie.bind('ButtonPress-1', proc{|w, x, y|
+ priv[:x] = x
+ priv[:y] = y
+ priv[:pie_in] = (w.winfo_width/1.8 > x)
+ priv[:angle] = w[:angle]
+ priv[:origin] = w[:origin]
+ }, '%W %x %y')
+
+pie.bind('B1-Motion', proc{|w, x, y|
+ if priv[:pie_in]
+ w.configure(:angle=>priv[:angle] + (priv[:y] - y)/3,
+ :origin=>(priv[:origin] +
+ ((w.winfo_height/2.2 > y)? -1: 1) *
+ (priv[:x] - x)/3) % 360)
+ end
+ }, '%W %x %y')
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkextlib/vu/vu_demo.rb b/ext/tk/sample/tkextlib/vu/vu_demo.rb
new file mode 100644
index 0000000000..d078ae16f2
--- /dev/null
+++ b/ext/tk/sample/tkextlib/vu/vu_demo.rb
@@ -0,0 +1,67 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+require 'tkextlib/vu'
+
+#######################################
+
+puts "Show off barchart and dial widgets"
+
+speed = TkVariable.new(0)
+
+dial = Tk::Vu::Dial.new(:resolution=>0.001, :from=>-0.1, :to=>0.1,
+ :showvalue=>true, :minortickinterval=>0.01,
+ :tickinterval=>0.1, :radius=>50, :label=>"Dial",
+ :beginangle=>-20, :endangle=>260, :dialcolor=>'red3',
+ :active=>'red2', :variable=>speed)
+
+bar = Tk::Vu::Bargraph.new(:from=>0, :to=>100, :relief=>:groove,
+ :border=>2, :label=>"Bar Chart")
+
+#######################################
+
+green = 25
+blue = 50
+purple = 75
+current = 50
+
+def rand_bool
+
+end
+
+update = TkTimer.new(200, -1, proc{
+ if (rand() - 0.5 + speed.numeric * 3) > 0
+ current += 1
+ else
+ current -= 1
+ end
+ bar.set(current)
+ if current < green
+ current = 100 if current <= 0
+ bar[:barcolor] = 'green'
+ elsif current < blue
+ bar[:barcolor] = 'blue'
+ elsif current < purple
+ bar[:barcolor] = 'purple'
+ else
+ bar[:barcolor] = 'red'
+ current = 0 if current >= 100
+ end
+ })
+
+#######################################
+
+gobar = TkButton.new(:text=>"Start", :command=>proc{update.start})
+nobar = TkButton.new(:text=>"Stop", :command=>proc{update.stop})
+quit = TkButton.new(:text=>"Exit", :command=>proc{exit})
+
+Tk.grid('x', gobar, :sticky=>:ew, :padx=>4, :pady=>4)
+Tk.grid(dial, bar, :sticky=>:news)
+Tk.grid('x', nobar, :sticky=>:ew, :padx=>4, :pady=>4)
+Tk.grid(quit, '-', '-', :sticky=>:ew, :padx=>4, :pady=>4)
+Tk.root.grid_columnconfigure(2, :weight=>1)
+Tk.root.grid_rowconfigure(1, :weight=>1)
+
+#######################################
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkfrom.rb b/ext/tk/sample/tkfrom.rb
index 25f1d7c429..2cece7337e 100644
--- a/ext/tk/sample/tkfrom.rb
+++ b/ext/tk/sample/tkfrom.rb
@@ -22,13 +22,13 @@ class Mail
@body = []
while line = f.gets()
$_.chop!
- next if /^From / =~ line # skip From-line
- break if /^$/ =~ line # end of header
+ next if /^From / =~ line # skip From-line
+ break if /^$/ =~ line # end of header
if /^(\S+):\s*(.*)/ =~ line
- @header[attr = $1.capitalize] = $2
+ @header[attr = $1.capitalize] = $2
elsif attr
- sub(/^\s*/, '')
- @header[attr] += "\n" + $_
+ sub(/^\s*/, '')
+ @header[attr] += "\n" + $_
end
end
@@ -65,7 +65,7 @@ list = scroll = nil
TkFrame.new{|f|
list = TkListbox.new(f) {
yscroll proc{|*idx|
- scroll.set *idx
+ scroll.set *idx
}
relief 'raised'
# geometry "80x5"
diff --git a/ext/tk/sample/tkhello.rb b/ext/tk/sample/tkhello.rb
index ab236963e8..3b505f4983 100644
--- a/ext/tk/sample/tkhello.rb
+++ b/ext/tk/sample/tkhello.rb
@@ -1,10 +1,10 @@
require "tk"
TkButton.new(nil,
- 'text' => 'hello',
- 'command' => proc{print "hello\n"}).pack('fill'=>'x')
+ :text => 'hello',
+ :command => proc{print "hello\n"}).pack(:fill=>'x')
TkButton.new(nil,
- 'text' => 'quit',
- 'command' => proc{exit}).pack('fill'=>'x')
+ :text => 'quit',
+ :command => proc{exit}).pack(:fill=>'x')
Tk.mainloop
diff --git a/ext/tk/sample/tkline.rb b/ext/tk/sample/tkline.rb
index 2406b0749f..3124c2fe0c 100644
--- a/ext/tk/sample/tkline.rb
+++ b/ext/tk/sample/tkline.rb
@@ -8,13 +8,15 @@ def start_random
if defined? Thread
Thread.start do
loop do
- sleep 2
- Line.new($c, rand(400), rand(200), rand(400), rand(200))
+ sleep 2
+ Line.new($c, rand(400), rand(200), rand(400), rand(200))
end
end
end
end
+Label.new('text'=>'Please press or drag button-1').pack
+
$c = Canvas.new
$c.pack
$start_x = start_y = 0
diff --git a/ext/tk/sample/tkmenubutton.rb b/ext/tk/sample/tkmenubutton.rb
index 1c7f51000b..37f6128fd9 100644
--- a/ext/tk/sample/tkmenubutton.rb
+++ b/ext/tk/sample/tkmenubutton.rb
@@ -11,7 +11,7 @@ TkFrame.new{|f|
TkMenubutton.new(:parent=>f, :text=>'Right', :underline=>0,
- :direction=>:right, :relief=>:raised){|mb|
+ :direction=>:right, :relief=>:raised){|mb|
menu TkMenu.new(:parent=>mb, :tearoff=>0){
add(:command, :label=>'Right menu: first item',
:command=>proc{print 'You have selected the first item' +
@@ -24,7 +24,7 @@ TkFrame.new{|f|
}
TkMenubutton.new(:parent=>f, :text=>'Below', :underline=>0,
- :direction=>:below, :relief=>:raised){|mb|
+ :direction=>:below, :relief=>:raised){|mb|
menu(TkMenu.new(:parent=>mb, :tearoff=>0){
add(:command, :label=>'Below menu: first item',
:command=>proc{print 'You have selected the first item' +
@@ -37,7 +37,7 @@ TkFrame.new{|f|
}
TkMenubutton.new(:parent=>f, :text=>'Above', :underline=>0,
- :direction=>:above, :relief=>:raised){|mb|
+ :direction=>:above, :relief=>:raised){|mb|
menu TkMenu.new(:parent=>mb, :tearoff=>0){
add(:command, :label=>'Above menu: first item',
:command=>proc{print 'You have selected the first item' +
@@ -50,7 +50,7 @@ TkFrame.new{|f|
}
TkMenubutton.new(:parent=>f, :text=>'Left', :underline=>0,
- :direction=>:left, :relief=>:raised){|mb|
+ :direction=>:left, :relief=>:raised){|mb|
menu(TkMenu.new(:parent=>mb, :tearoff=>0){
add(:command, :label=>'Left menu: first item',
:command=>proc{print 'You have selected the first item' +
@@ -65,7 +65,7 @@ TkFrame.new{|f|
############################
TkFrame.new(:borderwidth=>2, :relief=>:sunken,
- :height=>5).pack(:side=>:top, :fill=>:x, :padx=>20)
+ :height=>5).pack(:side=>:top, :fill=>:x, :padx=>20)
############################
TkLabel.new(:text=>'Sample of TkOptionMenu').pack(:side=>:top)
@@ -83,21 +83,21 @@ TkFrame.new{|f|
b2 = TkOptionMenubutton.new(:parent=>f, :values=>colors) {|optMB|
colors.each{|color|
no_sel = TkPhotoImage.new(:height=>16, :width=>16){
- put 'gray50', *[ 0, 0, 16, 1]
- put 'gray50', *[ 0, 1, 1, 16]
- put 'gray75', *[ 0, 15, 16, 16]
- put 'gray75', *[15, 1, 16, 16]
- put color, *[ 1, 1, 15, 15]
+ put 'gray50', *[ 0, 0, 16, 1]
+ put 'gray50', *[ 0, 1, 1, 16]
+ put 'gray75', *[ 0, 15, 16, 16]
+ put 'gray75', *[15, 1, 16, 16]
+ put color, *[ 1, 1, 15, 15]
}
sel = TkPhotoImage.new(:height=>16, :width=>16){
- put 'Black', *[ 0, 0, 16, 2]
- put 'Black', *[ 0, 2, 2, 16]
- put 'Black', *[ 2, 14, 16, 16]
- put 'Black', *[14, 2, 16, 14]
- put color, *[ 2, 2, 14, 14]
+ put 'Black', *[ 0, 0, 16, 2]
+ put 'Black', *[ 0, 2, 2, 16]
+ put 'Black', *[ 2, 14, 16, 16]
+ put 'Black', *[14, 2, 16, 14]
+ put color, *[ 2, 2, 14, 14]
}
optMB.entryconfigure(color, :hidemargin=>1,
- :image=>no_sel, :selectimage=>sel)
+ :image=>no_sel, :selectimage=>sel)
}
optMB.menuconfigure(:tearoff, 1)
%w(Black gray75 gray50 White).each{|color|
@@ -115,7 +115,7 @@ TkFrame.new{|f|
############################
TkFrame.new(:borderwidth=>2, :relief=>:sunken,
- :height=>5).pack(:side=>:top, :fill=>:x, :padx=>20)
+ :height=>5).pack(:side=>:top, :fill=>:x, :padx=>20)
############################
root = TkRoot.new(:title=>'menubutton samples')
@@ -127,8 +127,8 @@ TkButton.new(root, :text=>'exit', :command=>proc{exit}){
# VirtualEvent <<MenuSelect>> on Tcl/Tk ==> '<MenuSelect>' on Ruby/Tk
# ( remove the most external <, > for Ruby/Tk notation )
TkMenu.bind('<MenuSelect>', proc{|widget|
- p widget.entrycget('active', :label)
- }, '%W')
+ p widget.entrycget('active', :label)
+ }, '%W')
############################
diff --git a/ext/tk/sample/tkmsgcat-load_rb.rb b/ext/tk/sample/tkmsgcat-load_rb.rb
new file mode 100644
index 0000000000..5373e0086f
--- /dev/null
+++ b/ext/tk/sample/tkmsgcat-load_rb.rb
@@ -0,0 +1,102 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+
+demo_dir = File.dirname($0)
+msgcat_dir = [demo_dir, 'msgs_rb'].join(File::Separator)
+top_win = nil
+#msgcat = TkMsgCatalog.new('::tk')
+msgcat = TkMsgCatalog.new('::tkmsgcat_demo')
+default_locale = msgcat.locale
+#msgcat.load_rb(msgcat_dir)
+msgcat.load(msgcat_dir)
+
+col_proc = TkComm.install_bind(proc{|w, color, frame, label|
+ TkComm.window(frame).background(color)
+ Tk.update
+ TkComm.window(label).text(
+ msgcat["%1$s:: %2$s", 'Color',
+ color.capitalize])
+ w.flash; w.flash
+ Tk.callback_break;
+ }, "%W")
+
+del_proc = TkComm.install_cmd(proc{top_win.destroy; top_win = nil})
+
+err_proc = TkComm.install_cmd(proc{fail(RuntimeError,
+ msgcat['Application Error'])})
+
+show_sample = proc{|loc|
+ top_win = TkToplevel.new(:title=>loc)
+
+ msgcat.locale = loc
+ #msgcat.load_rb(msgcat_dir)
+ msgcat.load(msgcat_dir)
+
+ TkLabel.new(top_win){
+ text "preferences:: #{msgcat.preferences.join(' ')}"
+ pack(:pady=>10, :padx=>10)
+ }
+
+ lbl = TkLabel.new(top_win, :text=>msgcat["%1$s:: %2$s",
+ 'Color', '']).pack(:anchor=>'w')
+
+ bg = TkFrame.new(top_win).pack(:ipadx=>20, :ipady=>10,
+ :expand=>true, :fill=>:both)
+
+ TkFrame.new(bg){|f|
+ ['blue', 'green', 'red'].each{|col|
+ TkButton.new(f, :text=>msgcat[col]){
+ bind('ButtonRelease-1', col_proc, "#{col} #{bg.path} #{lbl.path}")
+ }.pack(:fill=>:x)
+ }
+ }.pack(:anchor=>'center', :pady=>15)
+
+ TkFrame.new(top_win){|f|
+ TkButton.new(f, :text=>msgcat['Delete'],
+ :command=>del_proc).pack(:side=>:right, :padx=>5)
+ TkButton.new(f, :text=>msgcat['Error'],
+ :command=>err_proc).pack(:side=>:left, :padx=>5)
+ }.pack(:side=>:bottom, :fill=>:x)
+
+ top_win
+}
+
+
+# listbox for locale list
+TkLabel.new(:text=>"Please click a locale.").pack(:padx=>5, :pady=>3)
+
+TkFrame.new{|f|
+ TkButton.new(f, :text=>msgcat['Exit'],
+ :command=>proc{exit}).pack(:side=>:right, :padx=>5)
+}.pack(:side=>:bottom, :fill=>:x)
+
+f = TkFrame.new.pack(:side=>:top, :fill=>:both, :expand=>true)
+lbox = TkListbox.new(f).pack(:side=>:left, :fill=>:both, :expand=>true)
+lbox.yscrollbar(TkScrollbar.new(f, :width=>12).pack(:side=>:right, :fill=>:y))
+
+lbox.bind('ButtonRelease-1'){|ev|
+ idx = lbox.index("@#{ev.x},#{ev.y}")
+ if idx == 0
+ loc = default_locale
+ else
+ loc = lbox.get(idx)
+ end
+ if top_win != nil && top_win.exist?
+ top_win.destroy
+ end
+ top_win = show_sample.call(loc)
+}
+
+lbox.insert('end', 'default')
+
+Dir.entries(msgcat_dir).sort.each{|f|
+ if f =~ /^(.*).msg$/
+ lbox.insert('end', $1)
+ end
+}
+
+top_win = show_sample.call(default_locale)
+
+# start eventloop
+Tk.mainloop
diff --git a/ext/tk/sample/tkmsgcat-load_rb2.rb b/ext/tk/sample/tkmsgcat-load_rb2.rb
new file mode 100644
index 0000000000..55246545c8
--- /dev/null
+++ b/ext/tk/sample/tkmsgcat-load_rb2.rb
@@ -0,0 +1,102 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+
+demo_dir = File.dirname($0)
+msgcat_dir = [demo_dir, 'msgs_rb2'].join(File::Separator)
+top_win = nil
+#msgcat = TkMsgCatalog.new('::tk')
+msgcat = TkMsgCatalog.new('::tkmsgcat_demo')
+default_locale = msgcat.locale
+#msgcat.load_rb(msgcat_dir)
+msgcat.load(msgcat_dir)
+
+col_proc = TkComm.install_bind(proc{|w, color, frame, label|
+ TkComm.window(frame).background(color)
+ Tk.update
+ TkComm.window(label).text(
+ msgcat["%1$s:: %2$s", 'Color',
+ color.capitalize])
+ w.flash; w.flash
+ Tk.callback_break;
+ }, "%W")
+
+del_proc = TkComm.install_cmd(proc{top_win.destroy; top_win = nil})
+
+err_proc = TkComm.install_cmd(proc{fail(RuntimeError,
+ msgcat['Application Error'])})
+
+show_sample = proc{|loc|
+ top_win = TkToplevel.new(:title=>loc)
+
+ msgcat.locale = loc
+ #msgcat.load_rb(msgcat_dir)
+ msgcat.load(msgcat_dir)
+
+ TkLabel.new(top_win){
+ text "preferences:: #{msgcat.preferences.join(' ')}"
+ pack(:pady=>10, :padx=>10)
+ }
+
+ lbl = TkLabel.new(top_win, :text=>msgcat["%1$s:: %2$s",
+ 'Color', '']).pack(:anchor=>'w')
+
+ bg = TkFrame.new(top_win).pack(:ipadx=>20, :ipady=>10,
+ :expand=>true, :fill=>:both)
+
+ TkFrame.new(bg){|f|
+ ['blue', 'green', 'red'].each{|col|
+ TkButton.new(f, :text=>msgcat[col]){
+ bind('ButtonRelease-1', col_proc, "#{col} #{bg.path} #{lbl.path}")
+ }.pack(:fill=>:x)
+ }
+ }.pack(:anchor=>'center', :pady=>15)
+
+ TkFrame.new(top_win){|f|
+ TkButton.new(f, :text=>msgcat['Delete'],
+ :command=>del_proc).pack(:side=>:right, :padx=>5)
+ TkButton.new(f, :text=>msgcat['Error'],
+ :command=>err_proc).pack(:side=>:left, :padx=>5)
+ }.pack(:side=>:bottom, :fill=>:x)
+
+ top_win
+}
+
+
+# listbox for locale list
+TkLabel.new(:text=>"Please click a locale.").pack(:padx=>5, :pady=>3)
+
+TkFrame.new{|f|
+ TkButton.new(f, :text=>msgcat['Exit'],
+ :command=>proc{exit}).pack(:side=>:right, :padx=>5)
+}.pack(:side=>:bottom, :fill=>:x)
+
+f = TkFrame.new.pack(:side=>:top, :fill=>:both, :expand=>true)
+lbox = TkListbox.new(f).pack(:side=>:left, :fill=>:both, :expand=>true)
+lbox.yscrollbar(TkScrollbar.new(f, :width=>12).pack(:side=>:right, :fill=>:y))
+
+lbox.bind('ButtonRelease-1'){|ev|
+ idx = lbox.index("@#{ev.x},#{ev.y}")
+ if idx == 0
+ loc = default_locale
+ else
+ loc = lbox.get(idx)
+ end
+ if top_win != nil && top_win.exist?
+ top_win.destroy
+ end
+ top_win = show_sample.call(loc)
+}
+
+lbox.insert('end', 'default')
+
+Dir.entries(msgcat_dir).sort.each{|f|
+ if f =~ /^(.*).msg$/
+ lbox.insert('end', $1)
+ end
+}
+
+top_win = show_sample.call(default_locale)
+
+# start eventloop
+Tk.mainloop
diff --git a/ext/tk/sample/tkmsgcat-load_tk.rb b/ext/tk/sample/tkmsgcat-load_tk.rb
new file mode 100644
index 0000000000..45d68e4e0b
--- /dev/null
+++ b/ext/tk/sample/tkmsgcat-load_tk.rb
@@ -0,0 +1,118 @@
+#!/usr/bin/env ruby
+
+require 'tk'
+
+demo_dir = File.dirname($0)
+msgcat_dir = [demo_dir, 'msgs_tk'].join(File::Separator)
+top_win = nil
+#msgcat = TkMsgCatalog.new('::tk')
+msgcat = TkMsgCatalog.new('::tkmsgcat_demo')
+default_locale = msgcat.locale
+msgcat.load_tk(msgcat_dir)
+
+col_proc = TkComm.install_bind(proc{|w, color, frame, label|
+ TkComm.window(frame).background(color)
+ Tk.update
+ TkComm.window(label).text(
+ msgcat.mc("%1$s:: %2$s", 'Color',
+ color.capitalize))
+ w.flash; w.flash
+ Tk.callback_break;
+ }, "%W")
+
+del_proc = TkComm.install_cmd(proc{top_win.destroy; top_win = nil})
+
+err_proc = TkComm.install_cmd(proc{fail(RuntimeError,
+ msgcat.mc('Application Error'))})
+
+show_sample = proc{|loc|
+ top_win = TkToplevel.new(:title=>loc)
+
+ msgcat.locale = loc
+ msgcat.load_tk(msgcat_dir)
+
+ TkLabel.new(top_win){
+ text "preferences:: #{msgcat.preferences.join(' ')}"
+ pack(:pady=>10, :padx=>10)
+ }
+
+ lbl = TkLabel.new(top_win, :text=>msgcat.mc("%1$s:: %2$s",
+ 'Color', '')).pack(:anchor=>'w')
+
+ bg = TkFrame.new(top_win).pack(:ipadx=>20, :ipady=>10,
+ :expand=>true, :fill=>:both)
+
+ TkFrame.new(bg){|f|
+ ['blue', 'green', 'red'].each{|col|
+ TkButton.new(f, :text=>msgcat.mc(col)){
+ bind('ButtonRelease-1', col_proc, "#{col} #{bg.path} #{lbl.path}")
+ }.pack(:fill=>:x)
+=begin
+ TkButton.new(f, :text=>msgcat.mc(col),
+ :command=>proc{
+ bg.background col
+ lbl.text msgcat.mc("%1$s:: %2$s", 'Color', col.capitalize)
+ }).pack(:fill=>:x)
+=end
+ }
+ }.pack(:anchor=>'center', :pady=>15)
+
+ TkFrame.new(top_win){|f|
+ TkButton.new(f, :text=>msgcat.mc('Delete'),
+ :command=>del_proc).pack(:side=>:right, :padx=>5)
+ TkButton.new(f, :text=>msgcat.mc('Error'),
+ :command=>err_proc).pack(:side=>:left, :padx=>5)
+=begin
+ TkButton.new(f, :text=>msgcat.mc('Delete'),
+ :command=>proc{
+ top_win.destroy
+ top_win = nil
+ }).pack(:side=>:right, :padx=>5)
+ TkButton.new(f, :text=>msgcat.mc('Error'),
+ :command=>proc{
+ fail RuntimeError, msgcat.mc('Application Error')
+ }).pack(:side=>:left, :padx=>5)
+=end
+ }.pack(:side=>:bottom, :fill=>:x)
+
+ top_win
+}
+
+
+# listbox for locale list
+TkLabel.new(:text=>"Please click a locale.").pack(:padx=>5, :pady=>3)
+
+TkFrame.new{|f|
+ TkButton.new(f, :text=>msgcat.mc('Exit'),
+ :command=>proc{exit}).pack(:side=>:right, :padx=>5)
+}.pack(:side=>:bottom, :fill=>:x)
+
+f = TkFrame.new.pack(:side=>:top, :fill=>:both, :expand=>true)
+lbox = TkListbox.new(f).pack(:side=>:left, :fill=>:both, :expand=>true)
+lbox.yscrollbar(TkScrollbar.new(f, :width=>12).pack(:side=>:right, :fill=>:y))
+
+lbox.bind('ButtonRelease-1'){|ev|
+ idx = lbox.index("@#{ev.x},#{ev.y}")
+ if idx == 0
+ loc = default_locale
+ else
+ loc = lbox.get(idx)
+ end
+ if top_win != nil && top_win.exist?
+ top_win.destroy
+ end
+ top_win = show_sample.call(loc)
+}
+
+lbox.insert('end', 'default')
+
+Dir.entries(msgcat_dir).sort.each{|f|
+ if f =~ /^(.*).msg$/
+ lbox.insert('end', $1)
+ end
+}
+
+top_win = show_sample.call(default_locale)
+
+# start eventloop
+Tk.mainloop
diff --git a/ext/tk/sample/tkmulticolumnlist.rb b/ext/tk/sample/tkmulticolumnlist.rb
new file mode 100644
index 0000000000..255eb691e5
--- /dev/null
+++ b/ext/tk/sample/tkmulticolumnlist.rb
@@ -0,0 +1,743 @@
+#
+# tkmulticolumnlist.rb : multiple column list widget on scrollable frame
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+
+class TkMultiColumnList < TkText
+ include TkComposite
+
+ # lbox_height : height of listboxes (pixel)
+ # title_info : array [ [<title_string>,<init_width>], ... ]
+ # keys : hash {<option>=><value>, ... }
+ def initialize_composite(lbox_height, title_info, keys={})
+ # argument check
+ if (! title_info.kind_of? Array) or (title_info.size < 2)
+ raise
+ end
+
+ # mode
+ @keep_minsize = true
+ @show_each_hscr = true
+ @show_win_hscr = true
+
+ # init arrays
+ @base_list = []
+ @rel_list = []
+ @title_list = []
+ @title_cmd = []
+ @lbox_list = []
+ @hscr_list = []
+
+ # decide total width
+ @lbox_total = title_info.size
+ @width_total = 0
+ title_info.each{|title, width, cmd|
+ @width_total += width.to_f
+ @title_cmd << cmd
+ }
+
+ # rel-table of label=>index
+ @name_index = {}
+
+ # size definition
+ @window_width = @width_total
+ @sash = 5
+ @scrbar_width = 15
+ @scrbar_border = 3
+ @lbox_border = 1
+ @title_border = 3
+ @h_l_thick = 0
+
+ # init status
+ @mode = :title
+ @command = nil
+
+ # virtical scrollbar
+ @v_scroll = TkYScrollbar.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'borderwidth'=>@scrbar_border,
+ 'width'=>@scrbar_width)
+
+ # horizontal scrollbar
+ @h_scroll = TkXScrollbar.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'borderwidth'=>@scrbar_border,
+ 'width'=>@scrbar_width)
+
+ # create base flames
+ @c_title = TkCanvas.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'width'=>@window_width)
+ @f_title = TkFrame.new(@c_title, 'width'=>@width_total)
+ @w_title = TkcWindow.new(@c_title, 0, 0,
+ 'window'=>@f_title, 'anchor'=>'nw')
+
+ @c_lbox = TkCanvas.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'width'=>@window_width)
+ @f_lbox = TkFrame.new(@c_lbox, 'width'=>@width_total)
+ @w_lbox = TkcWindow.new(@c_lbox, 0, 0, 'window'=>@f_lbox, 'anchor'=>'nw')
+
+ @c_hscr = TkCanvas.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'width'=>@window_width)
+ @f_hscr = TkFrame.new(@c_hscr, 'width'=>@width_total)
+ @w_hscr = TkcWindow.new(@c_hscr, 0, 0, 'window'=>@f_hscr, 'anchor'=>'nw')
+
+ # create each listbox
+ sum = 0.0
+ @rel_list << sum/@width_total
+ title_info.each_with_index{|(label, width), idx|
+ # set relation between label and index
+ if @name_index.include?(label)
+ @name_index[label] << idx
+ else
+ @name_index[label] = [idx]
+ end
+
+ # calculate relative positioning
+ sum += width
+ @rel_list << sum/@width_total
+
+ # title field
+ f = TkFrame.new(@f_title, 'width'=>width)
+ base = [f]
+
+ title = TkLabel.new(f, 'text'=>label, 'borderwidth'=>@title_border,
+ 'relief'=>'raised', 'highlightthickness'=>@h_l_thick)
+ title_binding(title, idx)
+ title.pack('fill'=>'x')
+
+ @title_list << title
+
+ f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>1,
+ 'relheight'=>1.0,
+ 'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+
+ # listbox field
+ f = TkFrame.new(@f_lbox, 'width'=>width)
+ base << f
+ @lbox_list << TkText.new(f, 'highlightthickness'=>@h_l_thick,
+ 'borderwidth'=>@lbox_border,
+ 'takefocus'=>false,
+ 'wrap'=>'none') {
+
+ bindtags(bindtags - [TkText])
+
+ @seltag = TkTextTag.new(self, 'background'=>'#b3b3b3',
+ 'borderwidth'=>1, 'relief'=>'raised')
+ def self.nearest(y)
+ self.index("@1,#{y}").split('.')[0].to_i
+ end
+
+ def self.select_clear(first, last=nil)
+ first = "#{first}.0" if first.kind_of?(Integer)
+ first = self.index(first.to_s + ' linestart')
+ last = first unless last
+ last = "#{last}.0" if first.kind_of?(Integer)
+ last = self.index(last.to_s + ' + 1 lines linestart')
+ @seltag.remove(first, last)
+ end
+
+ def self.select_set(first, last=nil)
+ first = "#{first}.0" if first.kind_of?(Integer)
+ first = self.index(first.to_s + ' linestart')
+ last = first unless last
+ last = "#{last}.0" if first.kind_of?(Integer)
+ last = self.index(last.to_s + ' + 1 lines linestart')
+ @seltag.add(first, last)
+ end
+
+ def self.select_index
+ self.index(@seltag.first).split('.')[0].to_i
+ end
+
+ pack('fill'=>'both', 'expand'=>true)
+ }
+
+ f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>1,
+ 'relwidth'=>@rel_list[idx+1] - @rel_list[idx], 'relheight'=>1.0)
+
+ # scrollbar field
+ f = TkFrame.new(@f_hscr, 'width'=>width)
+ base << f
+ @hscr_list << TkXScrollbar.new(f, 'width'=>@scrbar_width,
+ 'borderwidth'=>@scrbar_border,
+ 'highlightthickness'=>@h_l_thick
+ ).pack('fill'=>'x', 'anchor'=>'w')
+ f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>1,
+ 'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+
+ @lbox_list[idx].xscrollbar(@hscr_list[idx])
+
+ # add new base
+ @base_list << base
+ }
+
+ # pad
+ @f_title_pad = TkFrame.new(@frame, 'relief'=>'raised',
+ 'borderwidth'=>@title_border,
+ 'highlightthickness'=>@h_l_thick)
+
+ @f_scr_pad = TkFrame.new(@frame, 'relief'=>'sunken',
+ 'borderwidth'=>1,
+ 'highlightthickness'=>@h_l_thick)
+
+ # height check
+ title_height = 0
+ @title_list.each{|w|
+ h = w.winfo_reqheight
+ title_height = h if title_height < h
+ }
+
+ hscr_height = 0
+ @hscr_list.each{|w|
+ h = w.winfo_reqheight
+ hscr_height = h if hscr_height < h
+ }
+
+ @f_title.height title_height
+ @f_lbox.height lbox_height
+ @f_hscr.height hscr_height
+
+ # set control procedure for virtical scroll
+ @v_scroll.assign(*@lbox_list)
+
+ # set control procedure for horizoncal scroll
+ @h_scroll.assign(@c_title, @c_lbox, @c_hscr)
+
+ # binding for listboxes
+ @lbox_list.each_with_index{|l, idx|
+ l.bind('Button-1', proc{|w, y|
+ @frame.focus
+ select_line(w, w.nearest(y))
+ }, '%W %y')
+ l.bind('B1-Motion', proc{|w, y|
+ select_line(w, w.nearest(y))
+ }, '%W %y')
+ l.bind('Double-Button-1', proc{
+ @command.call(get_select) if @command
+ })
+
+ l.bind('Control-Home', proc{|w| select_line(w, 0)}, '%W')
+ l.bind('Control-End', proc{|w| select_line(w, 'end')}, '%W')
+
+ l.bind('Button-2', proc{|x, y|
+ @lbox_mark_x = x
+ @lbox_list.each{|lbox| lbox.scan_mark(x, y)}
+ }, '%x %y')
+ l.bind('B2-Motion', proc{|x, y|
+ @lbox_list.each{|lbox| lbox.scan_dragto(@lbox_mark_x, y)}
+ l.scan_dragto(x, y)
+ }, '%x %y')
+ }
+
+ bbox = @w_title.bbox
+ @c_title.height(bbox[3])
+ @c_title.scrollregion(bbox)
+
+ bbox = @w_lbox.bbox
+ @c_lbox.height(bbox[3])
+ @c_lbox.scrollregion(bbox)
+
+ if @show_each_hscr
+ bbox = @w_hscr.bbox
+ @c_hscr.height(bbox[3])
+ @c_hscr.scrollregion(bbox)
+ end
+
+ # binding
+ @frame.takefocus(true)
+ @frame.bind('Key-Up', proc{select_shift(@lbox_list[0], -1)})
+ @frame.bind('Key-Down', proc{select_shift(@lbox_list[0], 1)})
+ @frame.bind('Return', proc{@command.call(get_select) if @command})
+
+ # alignment
+ TkGrid.rowconfigure(@frame, 0, 'weight'=>0)
+ TkGrid.rowconfigure(@frame, 1, 'weight'=>1)
+ TkGrid.rowconfigure(@frame, 2, 'weight'=>0)
+ TkGrid.rowconfigure(@frame, 3, 'weight'=>0)
+ TkGrid.columnconfigure(@frame, 0, 'weight'=>1)
+ TkGrid.columnconfigure(@frame, 1, 'weight'=>0)
+ TkGrid.columnconfigure(@frame, 2, 'weight'=>0)
+ @v_scroll.grid('row'=>1, 'column'=>2, 'sticky'=>'ns')
+ @c_title.grid('row'=>0, 'column'=>0, 'sticky'=>'news')
+ @f_title_pad.grid('row'=>0, 'column'=>2, 'sticky'=>'news')
+ @c_lbox.grid('row'=>1, 'column'=>0, 'sticky'=>'news')
+ @c_hscr.grid('row'=>2, 'column'=>0, 'sticky'=>'ew') if @show_each_hscr
+ @h_scroll.grid('row'=>3, 'column'=>0, 'sticky'=>'ew') if @show_win_hscr
+ @f_scr_pad.grid('row'=>2, 'rowspan'=>2, 'column'=>2, 'sticky'=>'news')
+
+ # binding for 'Configure' event
+ @c_lbox.bind('Configure',
+ proc{|height, width| reconstruct(height, width)},
+ '%h %w')
+
+ # set default receiver of method calls
+ @path = @frame.path
+
+ # configure options
+ keys = {} unless keys
+ keys = _symbolkey2str(keys)
+
+ # command
+ cmd = keys.delete('command')
+ command(cmd) if cmd
+
+ # 'scrollbarwidth' option == 'width' option of scrollbars
+ width = keys.delete('scrollbarwidth')
+ scrollbarwidth(width) if width
+
+ # options for listbox titles
+ title_font = keys.delete('titlefont')
+ titlefont(title_font) if title_font
+
+ title_fg = keys.delete('titleforeground')
+ titleforeground(title_fg) if title_fg
+
+ title_bg = keys.delete('titlebackground')
+ titlebackground(title_bg) if title_bg
+
+ # set receivers for configure methods
+ delegate('DEFAULT', *@lbox_list)
+ delegate('activebackground', @v_scroll, @h_scroll, *@hscr_list)
+ delegate('troughcolor', @v_scroll, @h_scroll, *@hscr_list)
+ delegate('repeatdelay', @v_scroll, @h_scroll, *@hscr_list)
+ delegate('repeatinterval', @v_scroll, @h_scroll, *@hscr_list)
+ delegate('borderwidth', @frame)
+ delegate('width', @c_lbox, @c_title, @c_hscr)
+ delegate('relief', @frame)
+
+ # configure
+ configure(keys) if keys.size > 0
+ end
+ private :initialize_composite
+
+ # keep_minsize?
+ def keep_minsize?
+ @keep_minsize
+ end
+ def keep_minsize(bool)
+ @keep_minsize = bool
+ end
+
+ # each hscr
+ def show_each_hscr
+ @show_each_hscr = true
+ @c_hscr.grid('row'=>2, 'column'=>0, 'sticky'=>'ew')
+ end
+ def hide_each_hscr
+ @show_each_hscr = false
+ @c_hscr.ungrid
+ end
+
+ # window hscroll
+ def show_win_hscr
+ @show_win_hscr = true
+ @h_scroll.grid('row'=>3, 'column'=>0, 'sticky'=>'ew')
+ end
+ def hide_win_hscr
+ @show_each_hscr = false
+ @h_scroll.ungrid
+ end
+
+ # set command
+ def command(cmd)
+ @command = cmd
+ self
+ end
+
+ # set scrollbar width
+ def scrollbarwidth(width)
+ @scrbar_width = width
+ @v_scroll['width'] = @scrbar_width
+ @h_scroll['width'] = @scrbar_width
+ @hscr_list.each{|hscr| hscr['width'] = @scrbar_width}
+ self
+ end
+
+ # set scrollbar border
+ def scrollbarborder(width)
+ @scrbar_border = width
+ @v_scroll['border'] = @scrbar_border
+ @h_scroll['border'] = @scrbar_border
+ @hscr_list.each{|hscr| hscr['border'] = @scrbar_border}
+ self
+ end
+
+ # set listbox borders
+ def listboxborder(width)
+ @lbox_border = width
+ @lbox_list.each{|w| w['border'] = @lbox_border}
+ self
+ end
+
+ # set listbox relief
+ def listboxrelief(relief)
+ @lbox_list.each{|w| w['relief'] = relief}
+ self
+ end
+
+ # set title borders
+ def titleborder(width)
+ @title_border = width
+ @f_title_pad['border'] = @title_border
+ @title_list.each{|label| label['border'] = @title_border}
+ self
+ end
+
+ # set title font
+ def titlefont(font)
+ @title_list.each{|label| label['font'] = font}
+ title_height = 0
+ @title_list.each{|w|
+ h = w.winfo_reqheight
+ title_height = h if title_height < h
+ }
+ @f_title.height title_height
+ bbox = @w_title.bbox
+ @c_title.height(bbox[3])
+ @c_title.scrollregion(bbox)
+ self
+ end
+
+ # set title foreground color
+ def titleforeground(fg)
+ @title_list.each{|label| label['foreground'] = fg}
+ self
+ end
+
+ # set title background color
+ def titlebackground(bg)
+ @f_title_pad['background'] = bg
+ @title_list.each{|label| label['background'] = bg}
+ self
+ end
+
+ # set title cmds
+ def titlecommand(idx, cmd=Proc.new)
+ @title_cmd[idx] = cmd
+ end
+
+ # call title cmds
+ def titleinvoke(idx)
+ @title_cmd[idx].call if @title_cmd[idx]
+ end
+
+ # get label widgets of listbox titles
+ def titlelabels(*indices)
+ @title_list[*indices]
+ end
+
+ # get listbox widgets
+ def columns(*indices)
+ @lbox_list[*indices]
+ end
+
+ def delete(*idx)
+ idx = idx.collect{|i|
+ if i.kind_of?(Integer)
+ "#{i}.0"
+ else
+ i.to_s
+ end
+ }
+ @lbox_list.collect{|lbox| lbox.delete(*idx)}
+ end
+
+ def get(idx_s, idx_e=nil)
+ unless idx_e
+ if idx_s.kind_of?(Integer)
+ idx_s = "#{idx_s}.0"
+ idx_e = "#{idx_s} lineend"
+ else
+ idx_s = idx_s.to_s
+ idx_e = "#{idx_s} lineend"
+ end
+ @lbox_list.collect{|lbox|
+ lbox.get(idx_s, idx_e)
+ }
+ else
+ if idx_s.kind_of?(Integer)
+ idx_s = "#{idx_s}.0"
+ else
+ idx_s = idx_s.to_s
+ end
+ if idx_e.kind_of?(Integer)
+ idx_e = "#{idx_e}.end"
+ else
+ idx_e = "#{idx_e} lineend"
+ end
+ list = @lbox_list.collect{|lbox| lbox.get(idx_s, idx_e).split(/\n/)}
+ result = []
+ list[0].each_with_index{|line, index|
+ result << list.collect{|lines| lines[index]}
+ }
+ result
+ end
+ end
+
+ def get_select
+ get(@lbox_list[0].select_index)
+ end
+
+ def _line_array_to_hash(line)
+ result = {}
+ @name_index.each_pair{|label, indices|
+ if indices.size == 1
+ result[label] = line[indices[0]]
+ else
+ result[label] = indices.collect{|index| line[index]}
+ end
+ }
+ result
+ end
+ private :_line_array_to_hash
+
+ def get_by_hash(*idx)
+ get_result = get(*idx)
+ if idx.size == 1
+ _line_array_to_hash(get_result)
+ else
+ get_result.collect{|line| _line_array_to_hash(line)}
+ end
+ end
+
+ def insert(idx, *lines)
+ lbox_ins = []
+ (0..@lbox_list.size).each{lbox_ins << []}
+
+ if idx.kind_of?(Integer)
+ idx = "#{idx}.0"
+ else
+ idx = idx.to_s
+ end
+
+ if @lbox_list[0].index('1.0 + 1 char') == @lbox_list[0].index('end')
+ cr = ""
+ else
+ cr = "\n"
+ end
+
+ lines.each{|line|
+ if line.kind_of? Hash
+ array = []
+ @name_index.each_pair{|label, indices|
+ if indices.size == 1
+ array[indices[0]] = line[label]
+ else
+ if line[label].kind_of? Array
+ indices.each_with_index{|index, num|
+ array[index] = line[label][num]
+ }
+ else
+ array[indices[0]] = line[label]
+ end
+ end
+ }
+ line = array
+ end
+
+ @name_index.each_pair{|label, indices|
+ if indices.size == 1
+ lbox_ins[indices[0]] << line[indices[0]]
+ else
+ indices.each{|index| lbox_ins[index] << line[index]}
+ end
+ }
+ }
+
+ @lbox_list.each_with_index{|lbox, index|
+ lbox.insert(idx, cr + lbox_ins[index].join("\n")) if lbox_ins[index]
+ }
+ end
+
+ def select_clear(first, last=None)
+ @lbox_list.each{|lbox| lbox.sel_clear(first, last=None)}
+ end
+
+ def select_set(first, last=None)
+ @lbox_list.each{|lbox| lbox.sel_set(first, last=None)}
+ end
+
+ ###########################################
+ private
+
+ def reconstruct(height, width)
+ if @keep_minsize && width <= @width_total
+ @f_title.width(@width_total)
+ @f_lbox.width(@width_total)
+ @f_hscr.width(@width_total) if @show_each_hscr
+ @window_width = @width_total
+ else
+ @f_title.width(width)
+ @f_lbox.width(width)
+ @f_hscr.width(width) if @show_each_hscr
+ @window_width = width
+ end
+
+ @f_lbox.height(height)
+
+ @c_title.scrollregion(@w_title.bbox)
+ @c_lbox.scrollregion(@w_lbox.bbox)
+ @c_hscr.scrollregion(@w_hscr.bbox) if @show_each_hscr
+
+ (0..(@rel_list.size - 2)).each{|idx|
+ title, lbox, hscr = @base_list[idx]
+ title.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+ lbox.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
+ 'relheight'=>1.0)
+ hscr.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+ }
+ end
+
+ def resize(x)
+ idx = @sel_sash
+ return if idx == 0
+
+ # adjustment of relative positioning
+ delta = (x - @x) / @frame_width
+ if delta < @rel_list[idx-1] - @rel_list[idx] + (2*@sash/@frame_width)
+ delta = @rel_list[idx-1] - @rel_list[idx] + (2*@sash/@frame_width)
+ elsif delta > @rel_list[idx+1] - @rel_list[idx] - (2*@sash/@frame_width)
+ delta = @rel_list[idx+1] - @rel_list[idx] - (2*@sash/@frame_width)
+ end
+ @rel_list[idx] += delta
+
+ # adjustment of leftside widget of the sash
+ title, lbox, hscr = @base_list[idx - 1]
+ title.place('relwidth'=>@rel_list[idx] - @rel_list[idx-1])
+ lbox.place('relwidth'=>@rel_list[idx] - @rel_list[idx-1], 'relheight'=>1.0)
+ hscr.place('relwidth'=>@rel_list[idx] - @rel_list[idx-1])
+
+ # adjustment of rightside widget of the sash
+ title, lbox, hscr = @base_list[idx]
+ title.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
+ 'relx'=>@rel_list[idx])
+ lbox.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
+ 'relx'=>@rel_list[idx], 'relheight'=>1.0)
+ hscr.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
+ 'relx'=>@rel_list[idx])
+
+ # update reference position
+ @x = x
+ end
+
+ def motion_cb(w, x, idx)
+ if x <= @sash && idx > 0
+ w.cursor 'sb_h_double_arrow'
+ @mode = :sash
+ @sel_sash = idx
+ elsif x >= w.winfo_width - @sash && idx < @lbox_total - 1
+ w.cursor 'sb_h_double_arrow'
+ @mode = :sash
+ @sel_sash = idx + 1
+ else
+ w.cursor ""
+ @mode = :title
+ @sel_sash = 0
+ end
+ end
+
+ def title_binding(title, index)
+ title.bind('Motion', proc{|w, x, idx| motion_cb(w, x, idx.to_i)},
+ "%W %x #{index}")
+
+ title.bind('Enter', proc{|w, x, idx| motion_cb(w, x, idx.to_i)},
+ "%W %x #{index}")
+
+ title.bind('Leave', proc{|w| w.cursor ""}, "%W")
+
+ title.bind('Button-1',
+ proc{|w, x|
+ if @mode == :sash
+ @x = x
+ @frame_width = TkWinfo.width(@f_title).to_f
+ else
+ title.relief 'sunken'
+ end
+ },
+ '%W %X')
+
+ title.bind('ButtonRelease-1',
+ proc{|w, x, idx|
+ i = idx.to_i
+ if @mode == :title && @title_cmd[i].kind_of?(Proc)
+ @title_cmd[i].call
+ end
+ title.relief 'raised'
+ motion_cb(w,x,i)
+ },
+ "%W %x #{index}")
+
+ title.bind('B1-Motion', proc{|x| resize(x) if @mode == :sash}, "%X")
+ end
+
+ ########################
+ def select_line(w, idx)
+ @lbox_list.each{|l|
+ l.select_clear(1, 'end')
+ l.select_set(idx)
+ }
+ w.select_set(idx)
+ end
+
+ def select_shift(w, dir)
+ head = w.index('@1,1').split('.')[0].to_i
+ tail = w.index("@1,#{w.winfo_height - 1}").split('.')[0].to_i - 1
+ idx = w.select_index + dir
+ last = w.index('end - 1 char').split('.')[0].to_i
+ if idx < 1
+ idx = 1
+ elsif idx > last
+ idx = last
+ end
+ @lbox_list.each{|l|
+ l.select_clear(1, 'end')
+ l.select_set(idx)
+ }
+ if head > idx
+ @lbox_list.each{|l| l.yview('scroll', -1, 'units')}
+ elsif tail < idx
+ @lbox_list.each{|l| l.yview('scroll', 1, 'units')}
+ end
+ end
+ ########################
+end
+
+################################################
+# test
+################################################
+if __FILE__ == $0
+ l = TkMultiColumnList.new(nil, 200,
+ [ ['L1', 200, proc{p 'click L1'}],
+ ['L2', 100],
+ ['L3', 200] ],
+ 'width'=>350,
+ #'titleforeground'=>'yellow',
+ 'titleforeground'=>'white',
+ #'titlebackground'=>'navy',
+ 'titlebackground'=>'blue',
+ 'titlefont'=>'courier'
+ ).pack('fill'=>'both', 'expand'=>true)
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6])
+ l.insert('end', [4,5,6], [4,5,6])
+ l.insert('end', ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+ 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
+ 'cccccccccccccccccccccccccccccccccccccccccccccccccccc'])
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6], [4,5,6])
+ l.insert('end', ['aaaaaaaaaaaaaaa','bbbbbbbbbbbbbb','ccccccccccccccccc'])
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6], [4,5,6])
+ l.insert('end', ['aaaaaaaaaaaaaaa','bbbbbbbbbbbbbb','ccccccccccccccccc'])
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6], [4,5,6])
+ l.insert('end', ['aaaaaaaaaaaaaaa','bbbbbbbbbbbbbb','ccccccccccccccccc'])
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6], [4,5,6])
+ p l.columns(1)
+ p l.columns(1..3)
+ p l.columns(1,2)
+
+ l.command proc{|line_info| p line_info}
+
+ Tk.mainloop
+end
diff --git a/ext/tk/sample/tkmultilistbox.rb b/ext/tk/sample/tkmultilistbox.rb
index 9b66d401b9..6f956d0edb 100644
--- a/ext/tk/sample/tkmultilistbox.rb
+++ b/ext/tk/sample/tkmultilistbox.rb
@@ -36,10 +36,10 @@ class TkMultiListbox < TkListbox
# create base flames
@f_title = TkFrame.new(@frame, 'width'=>@width_total)
@f_lbox = TkFrame.new(@frame,
- 'width'=>@width_total, 'height'=>lbox_height)
+ 'width'=>@width_total, 'height'=>lbox_height)
@f_hscr = TkFrame.new(@frame, 'width'=>@width_total,
- 'height'=>@v_scroll.cget('width') +
- 2 * @v_scroll.cget('borderwidth'))
+ 'height'=>@v_scroll.cget('width') +
+ 2 * @v_scroll.cget('borderwidth'))
# dummy label to keep the hight of title space
TkLabel.new(@f_title, 'text'=>' ').pack
@@ -50,9 +50,9 @@ class TkMultiListbox < TkListbox
title_info.each_with_index{|(label, width), idx|
# set relation between label and index
if @name_index.include?(label)
- @name_index[label] << idx
+ @name_index[label] << idx
else
- @name_index[label] = [idx]
+ @name_index[label] = [idx]
end
# calculate relative positioning
@@ -64,25 +64,25 @@ class TkMultiListbox < TkListbox
base = [f]
@title_list << TkLabel.new(f, 'text'=>label).pack('fill'=>'x')
f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>-6,
- 'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+ 'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
# listbox field
f = TkFrame.new(@f_lbox, 'width'=>width)
base << f
@lbox_list << TkListbox.new(f).pack('fill'=>'both', 'expand'=>true)
f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>-4,
- 'relwidth'=>@rel_list[idx+1] - @rel_list[idx], 'relheight'=>1.0)
+ 'relwidth'=>@rel_list[idx+1] - @rel_list[idx], 'relheight'=>1.0)
# scrollbar field
f = TkFrame.new(@f_hscr, 'width'=>width)
base << f
@hscr_list << TkScrollbar.new(f, 'orient'=>'horizontal') .
- pack('fill'=>'x', 'anchor'=>'w')
+ pack('fill'=>'x', 'anchor'=>'w')
f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>-4,
- 'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+ 'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
@lbox_list[idx].xscrollcommand proc{|first, last|
- @hscr_list[idx].set first, last
+ @hscr_list[idx].set first, last
}
@hscr_list[idx].command proc{|*args| @lbox_list[idx].xview *args}
@@ -94,21 +94,19 @@ class TkMultiListbox < TkListbox
@tab_list = [nil]
(1..(@rel_list.size - 2)).each{|idx|
tab = TkFrame.new(@f_title, 'cursor'=>'sb_h_double_arrow',
- 'width'=>6, 'borderwidth'=>2, 'relief'=>'raised')
+ 'width'=>6, 'borderwidth'=>2, 'relief'=>'raised')
@tab_list << tab
tab.place('relx'=>@rel_list[idx], 'anchor'=>'ne', 'relheight'=>0.95)
tab.bind('Button-1',
- proc{|x| @x = x; @frame_width = TkWinfo.width(@f_title).to_f},
- '%X')
+ proc{|x| @x = x; @frame_width = TkWinfo.width(@f_title).to_f},
+ '%X')
tab.bind('B1-Motion', proc{|x, idx| resize(x, idx.to_i)}, "%X #{idx}")
}
# set control procedure for virtical scroll
@lbox_list.each{|lbox|
lbox.yscrollcommand proc{|first, last|
- @v_scroll.set first, last
- idx = lbox.nearest(0)
- @lbox_list.each{|l| l.yview(idx)}
+ @v_scroll.set first, last
}
}
@v_scroll.command proc{|*args| @lbox_list.each{|lbox| lbox.yview *args} }
@@ -122,16 +120,18 @@ class TkMultiListbox < TkListbox
@current_mode = 'browse'
@lbox_list.each{|l|
l.bind('Shift-Key-Left',
- proc{|w| focus_shift(w, -1); Tk.callback_break}, '%W')
+ proc{|w| focus_shift(w, -1); Tk.callback_break}, '%W')
l.bind('Shift-Key-Right',
- proc{|w| focus_shift(w, 1); Tk.callback_break}, '%W')
+ proc{|w| focus_shift(w, 1); Tk.callback_break}, '%W')
l.bind('Button-2', proc{|x, y|
- @lbox_list.each{|lbox| lbox.scan_mark(x, y)}
- }, '%x %y')
+ @lbox_mark_x = x
+ @lbox_list.each{|lbox| lbox.scan_mark(x, y)}
+ }, '%x %y')
l.bind('B2-Motion', proc{|x, y|
- @lbox_list.each{|lbox| lbox.scan_dragto(x, y)}
- }, '%x %y')
+ @lbox_list.each{|lbox| lbox.scan_dragto(@lbox_mark_x, y)}
+ l.scan_dragto(x, y)
+ }, '%x %y')
l.bindtags(l.bindtags.unshift(@mode[@current_mode]))
}
@@ -174,14 +174,18 @@ class TkMultiListbox < TkListbox
end
# set receivers for configure methods
- delegate('DELETE', *@lbox_list)
+ delegate('DEFAULT', *@lbox_list)
delegate('activebackground', @v_scroll, *@hscr_list)
delegate('troughcolor', @v_scroll, *@hscr_list)
delegate('repeatdelay', @v_scroll, *@hscr_list)
delegate('repeatinterval', @v_scroll, *@hscr_list)
delegate('borderwidth', @frame)
delegate('relief', @frame)
+
+ # configure
+ configure(keys) if keys.size > 0
end
+ private :initialize_composite
# set 'mode' option of listboxes
def mode(sel_mode)
@@ -238,7 +242,7 @@ class TkMultiListbox < TkListbox
list = @lbox_list.collect{|lbox| lbox.get(*idx)}
result = []
list[0].each_with_index{|line, index|
- result << list.collect{|lines| lines[index]}
+ result << list.collect{|lines| lines[index]}
}
result
end
@@ -248,9 +252,9 @@ class TkMultiListbox < TkListbox
result = {}
@name_index.each_pair{|label, indices|
if indices.size == 1
- result[label] = line[indices[0]]
+ result[label] = line[indices[0]]
else
- result[label] = indices.collect{|index| line[index]}
+ result[label] = indices.collect{|index| line[index]}
end
}
result
@@ -272,31 +276,31 @@ class TkMultiListbox < TkListbox
lines.each{|line|
if line.kind_of? Hash
- array = []
- @name_index.each_pair{|label, indices|
- if indices.size == 1
- array[indices[0]] = line[label]
- else
- if line[label].kind_of? Array
- indices.each_with_index{|index, num|
- array[index] = line[label][num]
- }
- else
- array[indices[0]] = line[label]
- end
- end
- }
- line = array
+ array = []
+ @name_index.each_pair{|label, indices|
+ if indices.size == 1
+ array[indices[0]] = line[label]
+ else
+ if line[label].kind_of? Array
+ indices.each_with_index{|index, num|
+ array[index] = line[label][num]
+ }
+ else
+ array[indices[0]] = line[label]
+ end
+ end
+ }
+ line = array
end
@name_index.each_pair{|label, indices|
- if indices.size == 1
- lbox_ins[indices[0]] << line[indices[0]]
- else
- indices.each{|index| lbox_ins[index] << line[index]}
- end
+ if indices.size == 1
+ lbox_ins[indices[0]] << line[indices[0]]
+ else
+ indices.each{|index| lbox_ins[index] << line[index]}
+ end
}
- }
+ }
@lbox_list.each_with_index{|lbox, index|
lbox.insert(idx, *lbox_ins[index]) if lbox_ins[index]
@@ -323,7 +327,7 @@ class TkMultiListbox < TkListbox
title, lbox, hscr = @base_list[idx]
title.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx])
lbox.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
- 'relheight'=>1.0)
+ 'relheight'=>1.0)
hscr.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx])
tab = @tab_list[idx]
@@ -353,11 +357,11 @@ class TkMultiListbox < TkListbox
# adjustment of rightside widget of the tab
title, lbox, hscr = @base_list[idx]
title.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
- 'relx'=>@rel_list[idx])
+ 'relx'=>@rel_list[idx])
lbox.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
- 'relx'=>@rel_list[idx], 'relheight'=>1.0)
+ 'relx'=>@rel_list[idx], 'relheight'=>1.0)
hscr.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
- 'relx'=>@rel_list[idx])
+ 'relx'=>@rel_list[idx])
# update reference position
@x = x
@@ -367,11 +371,11 @@ class TkMultiListbox < TkListbox
def browse_mode_bindtag
t = TkBindTag.new
t.bind('Button-1',
- proc{|w, y| w.focus; select_line(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| w.focus; select_line(w, w.nearest(y))}, '%W %y')
t.bind('B1-Motion', proc{|w, y| select_line(w, w.nearest(y))}, '%W %y')
t.bind('Shift-Button-1',
- proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
t.bind('Key-Up', proc{|w| select_shift(w, -1)}, '%W')
t.bind('Key-Down', proc{|w| select_shift(w, 1)}, '%W')
@@ -382,7 +386,7 @@ class TkMultiListbox < TkListbox
t.bind('space', proc{|w| select_line(w, w.index('active').to_i)}, '%W')
t.bind('Select', proc{|w| select_line(w, w.index('active').to_i)}, '%W')
t.bind('Control-slash',
- proc{|w| select_line(w, w.index('active').to_i)}, '%W')
+ proc{|w| select_line(w, w.index('active').to_i)}, '%W')
t
end
@@ -391,12 +395,12 @@ class TkMultiListbox < TkListbox
def single_mode_bindtag
t = TkBindTag.new
t.bind('Button-1',
- proc{|w, y| w.focus; select_only(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| w.focus; select_only(w, w.nearest(y))}, '%W %y')
t.bind('ButtonRelease-1',
- proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
t.bind('Shift-Button-1',
- proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
t.bind('Key-Up', proc{|w| select_shift(w, -1)}, '%W')
t.bind('Key-Down', proc{|w| select_shift(w, 1)}, '%W')
@@ -407,9 +411,9 @@ class TkMultiListbox < TkListbox
t.bind('space', proc{|w| select_line(w, w.index('active').to_i)}, '%W')
t.bind('Select', proc{|w| select_line(w, w.index('active').to_i)}, '%W')
t.bind('Control-slash',
- proc{|w| select_line(w, w.index('active').to_i)}, '%W')
+ proc{|w| select_line(w, w.index('active').to_i)}, '%W')
t.bind('Control-backslash',
- proc{@lbox_list.each{|l| l.selection_clear(0, 'end')}})
+ proc{@lbox_list.each{|l| l.selection_clear(0, 'end')}})
t
end
@@ -418,22 +422,22 @@ class TkMultiListbox < TkListbox
def extended_mode_bindtag
t = TkBindTag.new
t.bind('Button-1',
- proc{|w, y| w.focus; select_only(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| w.focus; select_only(w, w.nearest(y))}, '%W %y')
t.bind('B1-Motion', proc{|w, y| select_range(w, w.nearest(y))}, '%W %y')
t.bind('ButtonRelease-1',
- proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
t.bind('Shift-Button-1',
- proc{|w, y| select_range(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| select_range(w, w.nearest(y))}, '%W %y')
t.bind('Shift-B1-Motion',
- proc{|w, y| select_range(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| select_range(w, w.nearest(y))}, '%W %y')
t.bind('Control-Button-1',
- proc{|w, y| select_toggle(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| select_toggle(w, w.nearest(y))}, '%W %y')
t.bind('Control-B1-Motion',
- proc{|w, y| select_drag(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| select_drag(w, w.nearest(y))}, '%W %y')
t.bind('Key-Up', proc{|w| active_shift(w, -1)}, '%W')
t.bind('Key-Down', proc{|w| active_shift(w, 1)}, '%W')
@@ -459,9 +463,9 @@ class TkMultiListbox < TkListbox
def multiple_mode_bindtag
t = TkBindTag.new
t.bind('Button-1',
- proc{|w, y| w.focus; select_line3(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| w.focus; select_line3(w, w.nearest(y))}, '%W %y')
t.bind('ButtonRelease-1',
- proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
t.bind('Key-Up', proc{|w| active_shift(w, -1)}, '%W')
t.bind('Key-Down', proc{|w| active_shift(w, 1)}, '%W')
@@ -505,9 +509,9 @@ class TkMultiListbox < TkListbox
@lbox_list.each{|l|
l.selection_anchor(idx)
if st == 1
- l.selection_clear(idx)
+ l.selection_clear(idx)
else
- l.selection_set(idx)
+ l.selection_set(idx)
end
}
end
@@ -516,9 +520,9 @@ class TkMultiListbox < TkListbox
st = w.selection_includes('anchor')
@lbox_list.each{|l|
if st == 1
- l.selection_set('anchor', idx)
+ l.selection_set('anchor', idx)
else
- l.selection_clear('anchor', idx)
+ l.selection_clear('anchor', idx)
end
}
end
@@ -621,16 +625,16 @@ end
################################################
if __FILE__ == $0
f = TkFrame.new(nil, 'width'=>300,
- 'height'=>200).pack('fill'=>'both', 'expand'=>'true')
+ 'height'=>200).pack('fill'=>'both', 'expand'=>'true')
#f = TkFrame.new.pack('fill'=>'both', 'expand'=>'true')
l = TkMultiListbox.new(f, 150,
- [ ['L1', 100],
- ['L2', 200],
- ['L3', 50] ],
- 'titlefont'=>'courier',
- 'titleforeground'=>'yellow',
- 'titlebackground'=>'navy'
- ).pack('fill'=>'both', 'expand'=>true)
+ [ ['L1', 100],
+ ['L2', 200],
+ ['L3', 50] ],
+ 'titlefont'=>'courier',
+ 'titleforeground'=>'yellow',
+ 'titlebackground'=>'navy'
+ ).pack('fill'=>'both', 'expand'=>true)
l.insert('end', [1,2,3])
l.insert('end', [4,5,6])
l.insert('end', [4,5,6], [4,5,6])
diff --git a/ext/tk/sample/tkmultilistframe.rb b/ext/tk/sample/tkmultilistframe.rb
new file mode 100644
index 0000000000..ef1a0a824d
--- /dev/null
+++ b/ext/tk/sample/tkmultilistframe.rb
@@ -0,0 +1,940 @@
+#
+# tkmultilistframe.rb : multiple listbox widget on scrollable frame
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+
+class TkMultiListFrame < TkListbox
+ include TkComposite
+
+ # lbox_height : height of listboxes (pixel)
+ # title_info : array [ [<title_string>,<init_width>], ... ]
+ # keys : hash {<option>=><value>, ... }
+ def initialize_composite(lbox_height, title_info, keys={})
+ # argument check
+ if (! title_info.kind_of? Array) or (title_info.size < 2)
+ raise
+ end
+
+ # mode
+ @keep_minsize = true
+ @show_each_hscr = true
+ @show_win_hscr = true
+
+ # init arrays
+ @base_list = []
+ @rel_list = []
+ @title_list = []
+ @title_cmd = []
+ @lbox_list = []
+ @hscr_list = []
+
+ # decide total width
+ @lbox_total = title_info.size
+ @width_total = 0
+ title_info.each{|title, width, cmd|
+ @width_total += width.to_f
+ @title_cmd << cmd
+ }
+
+ # rel-table of label=>index
+ @name_index = {}
+
+ # size definition
+ @window_width = @width_total
+ @sash = 5
+ @scrbar_width = 15
+ @scrbar_border = 3
+ @lbox_border = 1
+ @title_border = 3
+ @h_l_thick = 0
+
+ # init status
+ @mode = :title
+
+ # virtical scrollbar
+=begin
+ @v_scroll = TkScrollbar.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'borderwidth'=>@scrbar_border,
+ 'orient'=>'vertical', 'width'=>@scrbar_width)
+=end
+ @v_scroll = TkYScrollbar.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'borderwidth'=>@scrbar_border,
+ 'width'=>@scrbar_width)
+
+ # horizontal scrollbar
+=begin
+ @h_scroll = TkScrollbar.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'borderwidth'=>@scrbar_border,
+ 'orient'=>'horizontal', 'width'=>@scrbar_width)
+=end
+ @h_scroll = TkXScrollbar.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'borderwidth'=>@scrbar_border,
+ 'width'=>@scrbar_width)
+
+ # create base flames
+ @c_title = TkCanvas.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'width'=>@window_width)
+ @f_title = TkFrame.new(@c_title, 'width'=>@width_total)
+ @w_title = TkcWindow.new(@c_title, 0, 0,
+ 'window'=>@f_title, 'anchor'=>'nw')
+
+ @c_lbox = TkCanvas.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'width'=>@window_width)
+ @f_lbox = TkFrame.new(@c_lbox, 'width'=>@width_total)
+ @w_lbox = TkcWindow.new(@c_lbox, 0, 0, 'window'=>@f_lbox, 'anchor'=>'nw')
+
+ @c_hscr = TkCanvas.new(@frame, 'highlightthickness'=>@h_l_thick,
+ 'width'=>@window_width)
+ @f_hscr = TkFrame.new(@c_hscr, 'width'=>@width_total)
+ @w_hscr = TkcWindow.new(@c_hscr, 0, 0, 'window'=>@f_hscr, 'anchor'=>'nw')
+
+ # create each listbox
+ sum = 0.0
+ @rel_list << sum/@width_total
+ title_info.each_with_index{|(label, width), idx|
+ # set relation between label and index
+ if @name_index.include?(label)
+ @name_index[label] << idx
+ else
+ @name_index[label] = [idx]
+ end
+
+ # calculate relative positioning
+ sum += width
+ @rel_list << sum/@width_total
+
+ # title field
+ f = TkFrame.new(@f_title, 'width'=>width)
+ base = [f]
+
+ title = TkLabel.new(f, 'text'=>label, 'borderwidth'=>@title_border,
+ 'relief'=>'raised', 'highlightthickness'=>@h_l_thick)
+ title_binding(title, idx)
+ title.pack('fill'=>'x')
+
+ @title_list << title
+
+ f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>1,
+ 'relheight'=>1.0,
+ 'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+
+ # listbox field
+ f = TkFrame.new(@f_lbox, 'width'=>width)
+ base << f
+ @lbox_list << TkListbox.new(f, 'highlightthickness'=>@h_l_thick,
+ 'borderwidth'=>@lbox_border
+ ).pack('fill'=>'both', 'expand'=>true)
+ f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>1,
+ 'relwidth'=>@rel_list[idx+1] - @rel_list[idx], 'relheight'=>1.0)
+
+ # scrollbar field
+ f = TkFrame.new(@f_hscr, 'width'=>width)
+ base << f
+=begin
+ @hscr_list << TkScrollbar.new(f, 'orient'=>'horizontal',
+ 'width'=>@scrbar_width,
+ 'borderwidth'=>@scrbar_border,
+ 'highlightthickness'=>@h_l_thick
+ ).pack('fill'=>'x', 'anchor'=>'w')
+=end
+ @hscr_list << TkXScrollbar.new(f, 'width'=>@scrbar_width,
+ 'borderwidth'=>@scrbar_border,
+ 'highlightthickness'=>@h_l_thick
+ ).pack('fill'=>'x', 'anchor'=>'w')
+ f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>1,
+ 'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+
+=begin
+ @lbox_list[idx].xscrollcommand proc{|first, last|
+ @hscr_list[idx].set first, last
+ }
+ @hscr_list[idx].command proc{|*args| @lbox_list[idx].xview *args}
+=end
+ @lbox_list[idx].xscrollbar(@hscr_list[idx])
+
+ # add new base
+ @base_list << base
+ }
+
+ # pad
+ # @f_title_pad = TkFrame.new(@frame)
+ @f_title_pad = TkFrame.new(@frame, 'relief'=>'raised',
+ 'borderwidth'=>@title_border,
+ 'highlightthickness'=>@h_l_thick)
+
+ @f_scr_pad = TkFrame.new(@frame, 'relief'=>'sunken',
+ 'borderwidth'=>1,
+ 'highlightthickness'=>@h_l_thick)
+
+ # height check
+ title_height = 0
+ @title_list.each{|w|
+ h = w.winfo_reqheight
+ title_height = h if title_height < h
+ }
+
+ hscr_height = 0
+ @hscr_list.each{|w|
+ h = w.winfo_reqheight
+ hscr_height = h if hscr_height < h
+ }
+
+ @f_title.height title_height
+ @f_lbox.height lbox_height
+ @f_hscr.height hscr_height
+
+ # set control procedure for virtical scroll
+=begin
+ @lbox_list.each{|lbox|
+ lbox.yscrollcommand proc{|first, last|
+ @v_scroll.set first, last
+ }
+ }
+ @v_scroll.command proc{|*args| @lbox_list.each{|lbox| lbox.yview *args} }
+=end
+ @v_scroll.assign(*@lbox_list)
+
+ # set control procedure for horizoncal scroll
+=begin
+ @c_title.xscrollcommand proc{|first, last|
+ @h_scroll.set first, last
+ }
+ @c_lbox.xscrollcommand proc{|first, last|
+ @h_scroll.set first, last
+ }
+ @c_hscr.xscrollcommand proc{|first, last|
+ @h_scroll.set first, last
+ }
+ @h_scroll.command proc{|*args|
+ @c_title.xview *args
+ @c_lbox.xview *args
+ @c_hscr.xview *args if @show_each_hscr
+ }
+=end
+ @h_scroll.assign(@c_title, @c_lbox, @c_hscr)
+
+ # binding for listboxes
+ @lbox_mode = {}
+ @lbox_mode['browse'] = browse_mode_bindtag
+ @lbox_mode['single'] = single_mode_bindtag
+ @lbox_mode['extended'] = extended_mode_bindtag
+ @lbox_mode['multiple'] = multiple_mode_bindtag
+ @current_mode = 'browse'
+ @lbox_list.each_with_index{|l, idx|
+ l.bind('Shift-Key-Left',
+ proc{|w| focus_shift(w, -1); Tk.callback_break}, '%W')
+ l.bind('Shift-Key-Right',
+ proc{|w| focus_shift(w, 1); Tk.callback_break}, '%W')
+
+ l.bind('Button-2', proc{|x, y|
+ @lbox_mark_x = x
+ @lbox_list.each{|lbox| lbox.scan_mark(x, y)}
+ }, '%x %y')
+ l.bind('B2-Motion', proc{|x, y|
+ @lbox_list.each{|lbox| lbox.scan_dragto(@lbox_mark_x, y)}
+ l.scan_dragto(x, y)
+ }, '%x %y')
+
+ l.bindtags(l.bindtags.unshift(@lbox_mode[@current_mode]))
+ }
+
+ bbox = @w_title.bbox
+ @c_title.height(bbox[3])
+ @c_title.scrollregion(bbox)
+
+ bbox = @w_lbox.bbox
+ @c_lbox.height(bbox[3])
+ @c_lbox.scrollregion(bbox)
+
+ if @show_each_hscr
+ bbox = @w_hscr.bbox
+ @c_hscr.height(bbox[3])
+ @c_hscr.scrollregion(bbox)
+ end
+
+ # alignment
+ TkGrid.rowconfigure(@frame, 0, 'weight'=>0)
+ TkGrid.rowconfigure(@frame, 1, 'weight'=>1)
+ TkGrid.rowconfigure(@frame, 2, 'weight'=>0)
+ TkGrid.rowconfigure(@frame, 3, 'weight'=>0)
+ TkGrid.columnconfigure(@frame, 0, 'weight'=>1)
+ TkGrid.columnconfigure(@frame, 1, 'weight'=>0)
+ TkGrid.columnconfigure(@frame, 2, 'weight'=>0)
+ @v_scroll.grid('row'=>1, 'column'=>2, 'sticky'=>'ns')
+ @c_title.grid('row'=>0, 'column'=>0, 'sticky'=>'news')
+ @f_title_pad.grid('row'=>0, 'column'=>2, 'sticky'=>'news')
+ @c_lbox.grid('row'=>1, 'column'=>0, 'sticky'=>'news')
+ @c_hscr.grid('row'=>2, 'column'=>0, 'sticky'=>'ew') if @show_each_hscr
+ @h_scroll.grid('row'=>3, 'column'=>0, 'sticky'=>'ew') if @show_win_hscr
+ @f_scr_pad.grid('row'=>2, 'rowspan'=>2, 'column'=>2, 'sticky'=>'news')
+
+ # binding for 'Configure' event
+ @c_lbox.bind('Configure',
+ proc{|height, width| reconstruct(height, width)},
+ '%h %w')
+
+ # set default receiver of method calls
+ @path = @lbox_list[0].path
+
+ # configure options
+ keys = {} unless keys
+ keys = _symbolkey2str(keys)
+
+ # 'mode' option of listboxes
+ sel_mode = keys.delete('mode')
+ mode(sel_mode) if sel_mode
+
+ # 'scrollbarwidth' option == 'width' option of scrollbars
+ width = keys.delete('scrollbarwidth')
+ scrollbarwidth(width) if width
+
+ # options for listbox titles
+ title_font = keys.delete('titlefont')
+ titlefont(title_font) if title_font
+
+ title_fg = keys.delete('titleforeground')
+ titleforeground(title_fg) if title_fg
+
+ title_bg = keys.delete('titlebackground')
+ titlebackground(title_bg) if title_bg
+
+ # set receivers for configure methods
+ delegate('DEFAULT', *@lbox_list)
+ delegate('activebackground', @v_scroll, @h_scroll, *@hscr_list)
+ delegate('troughcolor', @v_scroll, @h_scroll, *@hscr_list)
+ delegate('repeatdelay', @v_scroll, @h_scroll, *@hscr_list)
+ delegate('repeatinterval', @v_scroll, @h_scroll, *@hscr_list)
+ delegate('borderwidth', @frame)
+ delegate('width', @c_lbox, @c_title, @c_hscr)
+ delegate('relief', @frame)
+
+ # configure
+ configure(keys) if keys.size > 0
+ end
+ private :initialize_composite
+
+ # set 'mode' option of listboxes
+ def mode(sel_mode)
+ @lbox_list.each{|l|
+ tags = l.bindtags
+ tags = tags - [ @lbox_mode[@current_mode] ]
+ l.bindtags(tags.unshift(@lbox_mode[sel_mode]))
+ @current_mode = sel_mode
+ }
+ end
+
+ # keep_minsize?
+ def keep_minsize?
+ @keep_minsize
+ end
+ def keep_minsize(bool)
+ @keep_minsize = bool
+ end
+
+ # each hscr
+ def show_each_hscr
+ @show_each_hscr = true
+ @c_hscr.grid('row'=>2, 'column'=>0, 'sticky'=>'ew')
+ end
+ def hide_each_hscr
+ @show_each_hscr = false
+ @c_hscr.ungrid
+ end
+
+ # window hscroll
+ def show_win_hscr
+ @show_win_hscr = true
+ @h_scroll.grid('row'=>3, 'column'=>0, 'sticky'=>'ew')
+ end
+ def hide_win_hscr
+ @show_each_hscr = false
+ @h_scroll.ungrid
+ end
+
+ # set scrollbar width
+ def scrollbarwidth(width)
+ @scrbar_width = width
+ @v_scroll['width'] = @scrbar_width
+ @h_scroll['width'] = @scrbar_width
+ @hscr_list.each{|hscr| hscr['width'] = @scrbar_width}
+ self
+ end
+
+ # set scrollbar border
+ def scrollbarborder(width)
+ @scrbar_border = width
+ @v_scroll['border'] = @scrbar_border
+ @h_scroll['border'] = @scrbar_border
+ @hscr_list.each{|hscr| hscr['border'] = @scrbar_border}
+ self
+ end
+
+ # set listbox borders
+ def listboxborder(width)
+ @lbox_border = width
+ @lbox_list.each{|w| w['border'] = @lbox_border}
+ self
+ end
+
+ # set listbox relief
+ def listboxrelief(relief)
+ @lbox_list.each{|w| w['relief'] = relief}
+ self
+ end
+
+ # set title borders
+ def titleborder(width)
+ @title_border = width
+ @f_title_pad['border'] = @title_border
+ @title_list.each{|label| label['border'] = @title_border}
+ self
+ end
+
+ # set title font
+ def titlefont(font)
+ @title_list.each{|label| label['font'] = font}
+ title_height = 0
+ @title_list.each{|w|
+ h = w.winfo_reqheight
+ title_height = h if title_height < h
+ }
+ @f_title.height title_height
+ bbox = @w_title.bbox
+ @c_title.height(bbox[3])
+ @c_title.scrollregion(bbox)
+ self
+ end
+
+ # set title foreground color
+ def titleforeground(fg)
+ @title_list.each{|label| label['foreground'] = fg}
+ self
+ end
+
+ # set title background color
+ def titlebackground(bg)
+ @f_title_pad['background'] = bg
+ @title_list.each{|label| label['background'] = bg}
+ self
+ end
+
+ # set title cmds
+ def titlecommand(idx, cmd=Proc.new)
+ @title_cmd[idx] = cmd
+ end
+
+ # call title cmds
+ def titleinvoke(idx)
+ @title_cmd[idx].call if @title_cmd[idx]
+ end
+
+ # get label widgets of listbox titles
+ def titlelabels(*indices)
+ @title_list[*indices]
+ end
+
+ # get listbox widgets
+ def columns(*indices)
+ @lbox_list[*indices]
+ end
+
+ def activate(idx)
+ @lbox_list.each{|lbox| lbox.activate(idx)}
+ end
+
+ def bbox(idx)
+ @lbox_list.collect{|lbox| lbox.bbox(idx)}
+ end
+
+ def delete(*idx)
+ @lbox_list.collect{|lbox| lbox.delete(*idx)}
+ end
+
+ def get(*idx)
+ if idx.size == 1
+ @lbox_list.collect{|lbox| lbox.get(*idx)}
+ else
+ list = @lbox_list.collect{|lbox| lbox.get(*idx)}
+ result = []
+ list[0].each_with_index{|line, index|
+ result << list.collect{|lines| lines[index]}
+ }
+ result
+ end
+ end
+
+ def _line_array_to_hash(line)
+ result = {}
+ @name_index.each_pair{|label, indices|
+ if indices.size == 1
+ result[label] = line[indices[0]]
+ else
+ result[label] = indices.collect{|index| line[index]}
+ end
+ }
+ result
+ end
+ private :_line_array_to_hash
+
+ def get_by_hash(*idx)
+ get_result = get(*idx)
+ if idx.size == 1
+ _line_array_to_hash(get_result)
+ else
+ get_result.collect{|line| _line_array_to_hash(line)}
+ end
+ end
+
+ def insert(idx, *lines)
+ lbox_ins = []
+ (0..@lbox_list.size).each{lbox_ins << []}
+
+ lines.each{|line|
+ if line.kind_of? Hash
+ array = []
+ @name_index.each_pair{|label, indices|
+ if indices.size == 1
+ array[indices[0]] = line[label]
+ else
+ if line[label].kind_of? Array
+ indices.each_with_index{|index, num|
+ array[index] = line[label][num]
+ }
+ else
+ array[indices[0]] = line[label]
+ end
+ end
+ }
+ line = array
+ end
+
+ @name_index.each_pair{|label, indices|
+ if indices.size == 1
+ lbox_ins[indices[0]] << line[indices[0]]
+ else
+ indices.each{|index| lbox_ins[index] << line[index]}
+ end
+ }
+ }
+
+ @lbox_list.each_with_index{|lbox, index|
+ lbox.insert(idx, *lbox_ins[index]) if lbox_ins[index]
+ }
+ end
+
+ def selection_anchor(index)
+ @lbox_list.each{|lbox| lbox.selection_anchor(index)}
+ end
+
+ def selection_clear(first, last=None)
+ @lbox_list.each{|lbox| lbox.selection_clear(first, last=None)}
+ end
+
+ def selection_set(first, last=None)
+ @lbox_list.each{|lbox| lbox.selection_set(first, last=None)}
+ end
+
+ ###########################################
+ private
+
+ def reconstruct(height, width)
+ if @keep_minsize && width <= @width_total
+ @f_title.width(@width_total)
+ @f_lbox.width(@width_total)
+ @f_hscr.width(@width_total) if @show_each_hscr
+ @window_width = @width_total
+ else
+ @f_title.width(width)
+ @f_lbox.width(width)
+ @f_hscr.width(width) if @show_each_hscr
+ @window_width = width
+ end
+
+ @f_lbox.height(height)
+
+ @c_title.scrollregion(@w_title.bbox)
+ @c_lbox.scrollregion(@w_lbox.bbox)
+ @c_hscr.scrollregion(@w_hscr.bbox) if @show_each_hscr
+
+ (0..(@rel_list.size - 2)).each{|idx|
+ title, lbox, hscr = @base_list[idx]
+ title.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+ lbox.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
+ 'relheight'=>1.0)
+ hscr.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx])
+ }
+ end
+
+ def resize(x)
+ idx = @sel_sash
+ return if idx == 0
+
+ # adjustment of relative positioning
+ delta = (x - @x) / @frame_width
+ if delta < @rel_list[idx-1] - @rel_list[idx] + (2*@sash/@frame_width)
+ delta = @rel_list[idx-1] - @rel_list[idx] + (2*@sash/@frame_width)
+ elsif delta > @rel_list[idx+1] - @rel_list[idx] - (2*@sash/@frame_width)
+ delta = @rel_list[idx+1] - @rel_list[idx] - (2*@sash/@frame_width)
+ end
+ @rel_list[idx] += delta
+
+ # adjustment of leftside widget of the sash
+ title, lbox, hscr = @base_list[idx - 1]
+ title.place('relwidth'=>@rel_list[idx] - @rel_list[idx-1])
+ lbox.place('relwidth'=>@rel_list[idx] - @rel_list[idx-1], 'relheight'=>1.0)
+ hscr.place('relwidth'=>@rel_list[idx] - @rel_list[idx-1])
+
+ # adjustment of rightside widget of the sash
+ title, lbox, hscr = @base_list[idx]
+ title.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
+ 'relx'=>@rel_list[idx])
+ lbox.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
+ 'relx'=>@rel_list[idx], 'relheight'=>1.0)
+ hscr.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx],
+ 'relx'=>@rel_list[idx])
+
+ # update reference position
+ @x = x
+ end
+
+ def motion_cb(w, x, idx)
+ if x <= @sash && idx > 0
+ w.cursor 'sb_h_double_arrow'
+ @mode = :sash
+ @sel_sash = idx
+ elsif x >= w.winfo_width - @sash && idx < @lbox_total - 1
+ w.cursor 'sb_h_double_arrow'
+ @mode = :sash
+ @sel_sash = idx + 1
+ else
+ w.cursor ""
+ @mode = :title
+ @sel_sash = 0
+ end
+ end
+
+ def title_binding(title, index)
+ title.bind('Motion', proc{|w, x, idx| motion_cb(w, x, idx.to_i)},
+ "%W %x #{index}")
+
+ title.bind('Enter', proc{|w, x, idx| motion_cb(w, x, idx.to_i)},
+ "%W %x #{index}")
+
+ title.bind('Leave', proc{|w| w.cursor ""}, "%W")
+
+ title.bind('Button-1',
+ proc{|w, x|
+ if @mode == :sash
+ @x = x
+ @frame_width = TkWinfo.width(@f_title).to_f
+ else
+ title.relief 'sunken'
+ end
+ },
+ '%W %X')
+
+ title.bind('ButtonRelease-1',
+ proc{|w, x, idx|
+ i = idx.to_i
+ if @mode == :title && @title_cmd[i].kind_of?(Proc)
+ @title_cmd[i].call
+ end
+ title.relief 'raised'
+ motion_cb(w,x,i)
+ },
+ "%W %x #{index}")
+
+ title.bind('B1-Motion', proc{|x| resize(x) if @mode == :sash}, "%X")
+ end
+
+ #################################
+ def browse_mode_bindtag
+ t = TkBindTag.new
+ t.bind('Button-1',
+ proc{|w, y| w.focus; select_line(w, w.nearest(y))}, '%W %y')
+ t.bind('B1-Motion', proc{|w, y| select_line(w, w.nearest(y))}, '%W %y')
+
+ t.bind('Shift-Button-1',
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+
+ t.bind('Key-Up', proc{|w| select_shift(w, -1)}, '%W')
+ t.bind('Key-Down', proc{|w| select_shift(w, 1)}, '%W')
+
+ t.bind('Control-Home', proc{|w| select_line(w, 0)}, '%W')
+ t.bind('Control-End', proc{|w| select_line(w, 'end')}, '%W')
+
+ t.bind('space', proc{|w| select_line(w, w.index('active').to_i)}, '%W')
+ t.bind('Select', proc{|w| select_line(w, w.index('active').to_i)}, '%W')
+ t.bind('Control-slash',
+ proc{|w| select_line(w, w.index('active').to_i)}, '%W')
+
+ t
+ end
+
+ ########################
+ def single_mode_bindtag
+ t = TkBindTag.new
+ t.bind('Button-1',
+ proc{|w, y| w.focus; select_only(w, w.nearest(y))}, '%W %y')
+ t.bind('ButtonRelease-1',
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+
+ t.bind('Shift-Button-1',
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+
+ t.bind('Key-Up', proc{|w| select_shift(w, -1)}, '%W')
+ t.bind('Key-Down', proc{|w| select_shift(w, 1)}, '%W')
+
+ t.bind('Control-Home', proc{|w| select_line(w, 0)}, '%W')
+ t.bind('Control-End', proc{|w| select_line(w, 'end')}, '%W')
+
+ t.bind('space', proc{|w| select_line(w, w.index('active').to_i)}, '%W')
+ t.bind('Select', proc{|w| select_line(w, w.index('active').to_i)}, '%W')
+ t.bind('Control-slash',
+ proc{|w| select_line(w, w.index('active').to_i)}, '%W')
+ t.bind('Control-backslash',
+ proc{@lbox_list.each{|l| l.selection_clear(0, 'end')}})
+
+ t
+ end
+
+ ########################
+ def extended_mode_bindtag
+ t = TkBindTag.new
+ t.bind('Button-1',
+ proc{|w, y| w.focus; select_only(w, w.nearest(y))}, '%W %y')
+ t.bind('B1-Motion', proc{|w, y| select_range(w, w.nearest(y))}, '%W %y')
+
+ t.bind('ButtonRelease-1',
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+
+ t.bind('Shift-Button-1',
+ proc{|w, y| select_range(w, w.nearest(y))}, '%W %y')
+ t.bind('Shift-B1-Motion',
+ proc{|w, y| select_range(w, w.nearest(y))}, '%W %y')
+
+ t.bind('Control-Button-1',
+ proc{|w, y| select_toggle(w, w.nearest(y))}, '%W %y')
+
+ t.bind('Control-B1-Motion',
+ proc{|w, y| select_drag(w, w.nearest(y))}, '%W %y')
+
+ t.bind('Key-Up', proc{|w| active_shift(w, -1)}, '%W')
+ t.bind('Key-Down', proc{|w| active_shift(w, 1)}, '%W')
+
+ t.bind('Shift-Up', proc{|w| select_expand(w, -1)}, '%W')
+ t.bind('Shift-Down', proc{|w| select_expand(w, 1)}, '%W')
+
+ t.bind('Control-Home', proc{|w| select_line2(w, 0)}, '%W')
+ t.bind('Control-End', proc{|w| select_line2(w, 'end')}, '%W')
+
+ t.bind('Control-Shift-Home', proc{|w| select_range(w, 0)}, '%W')
+ t.bind('Control-Shift-End', proc{|w| select_range(w, 'end')}, '%W')
+
+ t.bind('space', proc{|w| select_active(w)}, '%W')
+ t.bind('Select', proc{|w| select_active(w)}, '%W')
+ t.bind('Control-slash', proc{|w| select_all}, '%W')
+ t.bind('Control-backslash', proc{|w| clear_all}, '%W')
+
+ t
+ end
+
+ ########################
+ def multiple_mode_bindtag
+ t = TkBindTag.new
+ t.bind('Button-1',
+ proc{|w, y| w.focus; select_line3(w, w.nearest(y))}, '%W %y')
+ t.bind('ButtonRelease-1',
+ proc{|w, y| active_line(w, w.nearest(y))}, '%W %y')
+
+ t.bind('Key-Up', proc{|w| active_shift(w, -1)}, '%W')
+ t.bind('Key-Down', proc{|w| active_shift(w, 1)}, '%W')
+
+ t.bind('Control-Home', proc{|w| select_line2(w, 0)}, '%W')
+ t.bind('Control-End', proc{|w| select_line2(w, 'end')}, '%W')
+
+ t.bind('Control-Shift-Home', proc{|w| active_line(w, 0)}, '%W')
+ t.bind('Control-Shift-End', proc{|w| active_line(w, 'end')}, '%W')
+
+ t.bind('space', proc{|w| select_active(w)}, '%W')
+ t.bind('Select', proc{|w| select_active(w)}, '%W')
+ t.bind('Control-slash', proc{|w| select_all}, '%W')
+ t.bind('Control-backslash', proc{|w| clear_all}, '%W')
+
+ t
+ end
+
+ ########################
+ def active_line(w, idx)
+ @lbox_list.each{|l| l.activate(idx)}
+ end
+
+ def select_only(w, idx)
+ @lbox_list.each{|l|
+ l.selection_clear(0, 'end')
+ l.selection_anchor(idx)
+ l.selection_set('anchor')
+ }
+ end
+
+ def select_range(w, idx)
+ @lbox_list.each{|l|
+ l.selection_clear(0, 'end')
+ l.selection_set('anchor', idx)
+ }
+ end
+
+ def select_toggle(w, idx)
+ st = w.selection_includes(idx)
+ @lbox_list.each{|l|
+ l.selection_anchor(idx)
+ if st == 1
+ l.selection_clear(idx)
+ else
+ l.selection_set(idx)
+ end
+ }
+ end
+
+ def select_drag(w, idx)
+ st = w.selection_includes('anchor')
+ @lbox_list.each{|l|
+ if st == 1
+ l.selection_set('anchor', idx)
+ else
+ l.selection_clear('anchor', idx)
+ end
+ }
+ end
+
+ def select_line(w, idx)
+ @lbox_list.each{|l|
+ l.selection_clear(0, 'end')
+ l.activate(idx)
+ l.selection_anchor(idx)
+ l.selection_set('anchor')
+ }
+ w.selection_set('anchor')
+ end
+
+ def select_line2(w, idx)
+ @lbox_list.each{|l|
+ l.activate(idx)
+ l.selection_anchor(idx)
+ l.selection_set('anchor')
+ }
+ end
+
+ def select_line3(w, idx)
+ @lbox_list.each{|l|
+ l.selection_set(idx)
+ }
+ end
+
+ def select_active(w)
+ idx = l.activate(idx)
+ @lbox_list.each{|l|
+ l.selection_set(idx)
+ }
+ end
+
+ def select_expand(w, dir)
+ idx = w.index('active').to_i + dir
+ if idx < 0
+ idx = 0
+ elsif idx >= w.size
+ idx = w.size - 1
+ end
+ @lbox_list.each{|l|
+ l.activate(idx)
+ l.selection_set(idx)
+ }
+ end
+
+ def active_shift(w, dir)
+ idx = w.index('active').to_i + dir
+ if idx < 0
+ idx = 0
+ elsif idx >= w.size
+ idx = w.size - 1
+ end
+ @lbox_list.each{|l|
+ l.activate(idx)
+ l.selection_anchor(idx)
+ }
+ end
+
+ def select_shift(w, dir)
+ idx = w.index('anchor').to_i + dir
+ if idx < 0
+ idx = 0
+ elsif idx >= w.size
+ idx = w.size - 1
+ end
+ @lbox_list.each{|l|
+ l.selection_clear(0, 'end')
+ l.activate(idx)
+ l.selection_anchor(idx)
+ l.selection_set('anchor')
+ }
+ end
+
+ def select_all
+ @lbox_list.each{|l|
+ l.selection_set(0, 'end')
+ }
+ end
+
+ def clear_all
+ @lbox_list.each{|l|
+ l.selection_clear(0, 'end')
+ }
+ end
+
+ def focus_shift(w, dir)
+ idx = @lbox_list.index(w) + dir
+ return if idx < 0
+ return if idx >= @lbox_list.size
+ @lbox_list[idx].focus
+ end
+ ########################
+end
+
+################################################
+# test
+################################################
+if __FILE__ == $0
+ l = TkMultiListFrame.new(nil, 200,
+ [ ['L1', 200, proc{p 'click L1'}],
+ ['L2', 100],
+ ['L3', 200] ],
+ 'width'=>350,
+ #'titleforeground'=>'yellow',
+ 'titleforeground'=>'white',
+ #'titlebackground'=>'navy',
+ 'titlebackground'=>'blue',
+ 'titlefont'=>'courier'
+ ).pack('fill'=>'both', 'expand'=>true)
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6])
+ l.insert('end', [4,5,6], [4,5,6])
+ l.insert('end', ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+ 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
+ 'cccccccccccccccccccccccccccccccccccccccccccccccccccc'])
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6], [4,5,6])
+ l.insert('end', ['aaaaaaaaaaaaaaa','bbbbbbbbbbbbbb','ccccccccccccccccc'])
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6], [4,5,6])
+ l.insert('end', ['aaaaaaaaaaaaaaa','bbbbbbbbbbbbbb','ccccccccccccccccc'])
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6], [4,5,6])
+ l.insert('end', ['aaaaaaaaaaaaaaa','bbbbbbbbbbbbbb','ccccccccccccccccc'])
+ l.insert('end', [1,2,3])
+ l.insert('end', [4,5,6], [4,5,6])
+ p l.columns(1)
+ p l.columns(1..3)
+ p l.columns(1,2)
+ Tk.mainloop
+end
diff --git a/ext/tk/sample/tkoptdb-safeTk.rb b/ext/tk/sample/tkoptdb-safeTk.rb
index a5e394b230..a06098323f 100644
--- a/ext/tk/sample/tkoptdb-safeTk.rb
+++ b/ext/tk/sample/tkoptdb-safeTk.rb
@@ -4,32 +4,70 @@ require 'multi-tk'
TkMessage.new(:text => <<EOM).pack
This is a sample of the safe-Tk slave interpreter. \
-On the slave interpreter, 'tkoptdb.rb' demo is running.
-( Attention:: a safe-Tk interpreter can't read options \
+On the slave interpreter, 'tkoptdb.rb' demo is running.
+( NOTE:: a safe-Tk interpreter can't read options \
from a file. Options are given by the master interpreter \
in this script. )
The window shown this message is a root widget of \
the default master interpreter. The other window \
is a toplevel widget of the master interpreter, and it \
-has a container frame of the safe-Tk slave interpreter. \
-You can delete the slave by the button on the toplevel widget.
+has a container frame of the safe-Tk slave interpreter.
+'exit' on the slave interpreter exits the slave only. \
+You can also delete the slave by the button on the toplevel widget.
EOM
if ENV['LANG'] =~ /^ja/
# read Japanese resource
ent = TkOptionDB.read_entries(File.expand_path('resource.ja',
- File.dirname(__FILE__)),
- 'euc-jp')
+ File.dirname(__FILE__)),
+ 'euc-jp')
else
# read English resource
ent = TkOptionDB.read_entries(File.expand_path('resource.en',
- File.dirname(__FILE__)))
+ File.dirname(__FILE__)))
end
+
file = File.expand_path('tkoptdb.rb', File.dirname(__FILE__))
-MultiTkIp.new_safeTk{
- ent.each{|pat, val| TkOptionDB.add(pat, val)}
+
+ip = MultiTkIp.new_safeTk{
+ # When a block is given to 'new_safeTk' method,
+ # the block is evaluated on $SAFE==4.
+ ent.each{|pat, val| Tk.tk_call('option', 'add', pat, val)}
+}
+
+print "ip.eval_proc{$SAFE} ==> ", ip.eval_proc{$SAFE}, "\n"
+
+print "\ncall 'ip.wait_on_mainloop = false'\n"
+print "If 'ip.wait_on_mainloop? == true', ",
+ "when 'mainloop' is called on 'ip.eval_proc', ",
+ "'ip.eval_proc' does't return while the root window exists.\n",
+ "If you want to avoid that, set wait_on_mainloop to false. ",
+ "Then the mainloop in the eval_proc returns soon ",
+ "and the following steps are evaluated. \n",
+ "If you hate the both of them, use 'ip.bg_eval_proc' or ",
+ "wrap 'ip.eval_proc' by a thread.\n"
+
+ip.wait_on_mainloop = false
+
+ret = ip.eval_proc{
+ # When a block is given to 'eval_proc' method,
+ # the block is evaluated on the IP's current safe level.
+ # So, the followings raises an exception.
+ # An Exception object of the exception is returned as a
+ # return value of this method.
+
load file
}
-# Tk.mainloop is ignored on the slave-IP
+print "\nip.eval_proc{}, which includes insecure operiation in the given block, returns an exception object: ", ret.inspect, "\n"
+print "If a proc object is given, the proc is evaluated on the safe-level which is kept on the proc :: ip.eval_proc( proc{$SAFE} ) ==> ", ip.eval_proc(proc{$SAFE}), "\n"
+
+safe0_cmd = Proc.new{
+ print 'safe0_cmd safe-level == ', $SAFE, "\n"
+ # This proc object keeps current safe-level ($SAFE==0).
+ load file
+}
+ip.eval_proc{safe0_cmd.call}
+
+# Tk.mainloop is ignored on the slave-IP
Tk.mainloop
diff --git a/ext/tk/sample/tkoptdb.rb b/ext/tk/sample/tkoptdb.rb
index ab8515ac16..47784ea238 100644
--- a/ext/tk/sample/tkoptdb.rb
+++ b/ext/tk/sample/tkoptdb.rb
@@ -12,12 +12,12 @@ if __FILE__ == $0 || !TkCore::INTERP.safe?
if ENV['LANG'] =~ /^ja/
# read Japanese resource
TkOptionDB.read_with_encoding(File.expand_path('resource.ja',
- File.dirname(__FILE__)),
- 'euc-jp')
+ File.dirname(__FILE__)),
+ 'euc-jp')
else
# read English resource
TkOptionDB.readfile(File.expand_path('resource.en',
- File.dirname(__FILE__)))
+ File.dirname(__FILE__)))
end
end
@@ -33,6 +33,7 @@ cmd = TkOptionDB.new_proc_class(:BTN_CMD, [:show_msg, :bye_msg], 3) {
print "==>#{str.tainted?} (<<< $SAFE=#{$SAFE}): "
str
end
+ private :__check_proc_string__
end
}
@@ -48,12 +49,12 @@ TkFrame.new(:class=>'BtnFrame'){|f|
pack(:fill=>:x, :padx=>10, :pady=>10)
}
TkButton.new(:command=>proc{
- print "($SAFE=#{$SAFE} >>>) : "
- cmd.bye_msg
- print "(<<< $SAFE=#{$SAFE} ) : "
- exit
- },
- :parent=>f, :widgetname=>'quit'){
+ print "($SAFE=#{$SAFE} >>>) : "
+ cmd.bye_msg
+ print "(<<< $SAFE=#{$SAFE} ) : "
+ exit
+ },
+ :parent=>f, :widgetname=>'quit'){
pack(:fill=>:x, :padx=>10, :pady=>10)
}
}
@@ -70,12 +71,12 @@ BtnFrame.new{|f|
pack(:fill=>:x, :padx=>10, :pady=>10)
}
TkButton.new(:command=>proc{
- print "($SAFE=#{$SAFE} >>>) : "
- cmd.bye_msg
- print "(<<< $SAFE=#{$SAFE})"
- exit
- },
- :parent=>f, :widgetname=>'quit'){
+ print "($SAFE=#{$SAFE} >>>) : "
+ cmd.bye_msg
+ print "(<<< $SAFE=#{$SAFE})"
+ exit
+ },
+ :parent=>f, :widgetname=>'quit'){
pack(:fill=>:x, :padx=>10, :pady=>10)
}
}
@@ -92,12 +93,12 @@ TkFrame.new(:class=>'BtnFrame2'){|f|
pack(:fill=>:x, :padx=>10, :pady=>10)
}
TkButton.new(:command=>proc{
- print "($SAFE=#{$SAFE} >>>) : "
- cmd.bye_msg
- print "(<<< $SAFE=#{$SAFE})"
- exit
- },
- :parent=>f, :widgetname=>'quit'){
+ print "($SAFE=#{$SAFE} >>>) : "
+ cmd.bye_msg
+ print "(<<< $SAFE=#{$SAFE})"
+ exit
+ },
+ :parent=>f, :widgetname=>'quit'){
pack(:fill=>:x, :padx=>10, :pady=>10)
}
}
diff --git a/ext/tk/sample/tkrttimer.rb b/ext/tk/sample/tkrttimer.rb
new file mode 100644
index 0000000000..0abd4ecbd2
--- /dev/null
+++ b/ext/tk/sample/tkrttimer.rb
@@ -0,0 +1,77 @@
+#!/usr/bin/env ruby
+# This script is a re-implementation of tktimer.rb with TkTimer(TkAfter) class.
+
+require "tk"
+
+root = TkRoot.new(:title=>'realtime timer sample')
+
+f1 = TkFrame.new(:borderwidth=>2, :relief=>:ridge)
+f1.pack(:side=>:bottom, :fill=>:both)
+TkLabel.new(f1, :text=>'use TkTimer (TkAfter) class').pack(:anchor=>:center)
+label1 = TkLabel.new(:parent=>f1, :relief=>:raised,
+ :width=>10).pack(:fill=>:both)
+
+f2 = TkFrame.new(:borderwidth=>2, :relief=>:ridge)
+f2.pack(:side=>:bottom, :fill=>:both)
+TkLabel.new(f2, :text=>'use TkRTTimer class').pack
+label2 = TkLabel.new(:parent=>f2, :relief=>:raised,
+ :width=>10).pack(:fill=>:both)
+
+TkLabel.new(:padx=>10, :pady=>5, :justify=>'left', :text=><<EOT).pack
+Interval setting of each timer object is 10 ms.
+Each timer object counts up the value on each callback
+(the value is not the clock data).
+The count of the TkTimer object is delayed by execution
+time of callbacks and inaccuracy of interval.
+On the other hand, the count of the TkRTTimer object is
+not delayed. Its callback interval is not accurate too.
+But it can compute error correction about the time when
+a callback should start.
+EOT
+
+# define the procedure repeated by the TkTimer object
+tick = proc{|aobj| #<== TkTimer object
+ cnt = aobj.return_value + 1 # return_value keeps a result of the last proc
+ label = aobj.current_args[0]
+ label.text format("%d.%02d", *(cnt.divmod(100)))
+ cnt #==> return value is kept by TkTimer object
+ # (so, can be send to the next repeat-proc)
+}
+
+timer1 = TkTimer.new(10, -1, [tick, label1]) # 10 ms interval
+timer2 = TkRTTimer.new(10, -1, [tick, label2]) # 10 ms interval
+
+timer1.start(0, proc{ label1.text('0.00'); 0 })
+timer2.start(0, proc{ label2.text('0.00'); 0 })
+
+b_start = TkButton.new(:text=>'Start', :state=>:disabled) {
+ pack(:side=>:left, :fill=>:both, :expand=>true)
+}
+
+b_stop = TkButton.new(:text=>'Stop', :state=>:normal) {
+ pack('side'=>'left', 'fill'=>'both', 'expand'=>'yes')
+}
+
+b_start.command {
+ timer1.continue
+ timer2.continue
+ b_stop.state(:normal)
+ b_start.state(:disabled)
+}
+
+b_stop.command {
+ timer1.stop
+ timer2.stop
+ b_start.state(:normal)
+ b_stop.state(:disabled)
+}
+
+TkButton.new(:text=>'Reset', :state=>:normal) {
+ command { timer1.reset; timer2.reset }
+ pack(:side=>:right, :fill=>:both, :expand=>:yes)
+}
+
+ev_quit = TkVirtualEvent.new('Control-c', 'Control-q')
+Tk.root.bind(ev_quit, proc{Tk.exit}).focus
+
+Tk.mainloop
diff --git a/ext/tk/sample/tksleep_sample.rb b/ext/tk/sample/tksleep_sample.rb
new file mode 100644
index 0000000000..23f6eca54e
--- /dev/null
+++ b/ext/tk/sample/tksleep_sample.rb
@@ -0,0 +1,29 @@
+require 'tk'
+
+v = TkVariable.new(0)
+l = TkLabel.new(:textvariable=>v).pack(:pady=>[1, 10])
+
+a = TkButton.new(:text=>"button A :: proc{p ['AAA', v.value]}").pack(:fill=>:x, :pady=>[1, 15], :padx=>15)
+a.command{p ['AAA', v.value]}
+
+TkLabel.new(:text=>'Callback of the button B returns LIFO order').pack
+b = TkButton.new(:text=>"button B :: proc{n = v.value; p ['B:start', n]; Tk.sleep(10000); p ['B:end', n]}").pack(:fill=>:x, :pady=>[1, 15], :padx=>15)
+b.command{n = v.value; p ['B:start', n]; Tk.sleep(10000); p ['B:end', n]}
+
+TkLabel.new(:text=>'Callback of the button C returns FIFO order').pack
+c = TkButton.new(:text=>"button C :: proc{n = v.value; Thread.new{p ['C:start', n]; Tk.sleep(10000); p ['C:end', n]}}").pack(:fill=>:x, :pady=>[1, 15], :padx=>15)
+c.command{n = v.value; Thread.new{p ['C:start', n]; Tk.sleep(10000); p ['C:end', n]}}
+
+TkLabel.new(:text=>'Callback of the button D blocks eventloop (no respond to event)').pack
+d = TkButton.new(:text=>"button D :: proc{n = v.value; p ['D:start', n]; sleep(10); p ['D:end', n]}").pack(:fill=>:x, :pady=>[1,15], :padx=>15)
+d.command{n = v.value; p ['D:start', n]; sleep(10); p ['D:end', n]}
+
+TkLabel.new(:text=>'Callback of the button E is another way to avoid eventloop blocking').pack
+e = TkButton.new(:text=>"button E :: proc{n = v.value; Thread.new{p ['D:start', n]; sleep(10); p ['D:end', n]}}").pack(:fill=>:x, :pady=>[1,15], :padx=>15)
+e.command{n = v.value; Thread.new{p ['D:start', n]; sleep(10); p ['D:end', n]}}
+
+TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
+
+TkTimer.new(500, -1){v.numeric += 1}.start
+
+Tk.mainloop
diff --git a/ext/tk/sample/tktextframe.rb b/ext/tk/sample/tktextframe.rb
index d1076c5b72..bdab057d34 100644
--- a/ext/tk/sample/tktextframe.rb
+++ b/ext/tk/sample/tktextframe.rb
@@ -35,8 +35,20 @@ class TkTextFrame < TkText
hscroll(keys.delete('hscroll'){true})
# set background of the text widget
+=begin
color = keys.delete('textbackground')
textbackground(color) if color
+=end
+ # please check the differences of the following definitions
+ option_methods(
+ [:scrollbarwidth, :get_scrollbarwidth],
+ [:textbackground, nil, :textbg_info],
+ :textborderwidth,
+ :textrelief
+ )
+
+ # set receiver widgets for configure methods (with alias)
+ delegate_alias('scrollbarrelief', 'relief', @h_scroll, @v_scroll)
# set receiver widgets for configure methods
delegate('DEFAULT', @text)
@@ -51,6 +63,7 @@ class TkTextFrame < TkText
# do configure
configure keys unless keys.empty?
end
+ private :initialize_composite
# set background color of text widget
def textbackground(color = nil)
@@ -61,12 +74,52 @@ class TkTextFrame < TkText
end
end
+ def textbg_info
+ info = @text.configinfo(:background)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ info[0] = 'textbackground'
+ info
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ {'textbackground' => info['background']}
+ end
+ end
+
+ # get/set borderwidth of text widget
+ def set_textborderwidth(width)
+ @text.borderwidth(width)
+ end
+ def get_textborderwidth
+ @text.borderwidth
+ end
+ def textborderwidth(width = nil)
+ if width
+ set_textborderwidth(width)
+ else
+ get_textborderwidth
+ end
+ end
+
+ # set relief of text widget
+ def textrelief(type)
+ @text.relief(type)
+ end
+
+ # get/set width of scrollbar
+ def get_scrollbarwidth
+ @v_scroll.width
+ end
+ def set_scrollbarwidth(width)
+ @v_scroll.width(width)
+ @h_scroll.width(width)
+ end
+ alias :scrollbarwidth :set_scrollbarwidth
+
# vertical scrollbar : ON/OFF
def vscroll(mode)
st = TkGrid.info(@v_scroll)
- if mode && st == [] then
+ if mode && st.size == 0 then
@v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns')
- elsif !mode && st != [] then
+ elsif !mode && st.size != 0 then
@v_scroll.ungrid
end
self
@@ -75,10 +128,10 @@ class TkTextFrame < TkText
# horizontal scrollbar : ON/OFF
def hscroll(mode, wrap_mode="char")
st = TkGrid.info(@h_scroll)
- if mode && st == [] then
+ if mode && st.size == 0 then
@h_scroll.grid('row'=>1, 'column'=>0, 'sticky'=>'ew')
wrap 'none' # => self.wrap('none')
- elsif !mode && st != [] then
+ elsif !mode && st.size != 0 then
@h_scroll.ungrid
wrap wrap_mode # => self.wrap(wrap_mode)
end
@@ -92,14 +145,18 @@ end
################################################
if __FILE__ == $0
f = TkFrame.new.pack('fill'=>'x')
- t = TkTextFrame.new.pack
+ #t = TkTextFrame.new.pack
+ t = TkTextFrame.new(:textborderwidth=>3,
+ :textrelief=>:ridge,
+ :scrollbarrelief=>:ridge).pack
+ p t.configinfo
TkButton.new(f, 'text'=>'vscr OFF',
- 'command'=>proc{t.vscroll(false)}).pack('side'=>'right')
+ 'command'=>proc{t.vscroll(false)}).pack('side'=>'right')
TkButton.new(f, 'text'=>'vscr ON',
- 'command'=>proc{t.vscroll(true)}).pack('side'=>'right')
+ 'command'=>proc{t.vscroll(true)}).pack('side'=>'right')
TkButton.new(f, 'text'=>'hscr ON',
- 'command'=>proc{t.hscroll(true)}).pack('side'=>'left')
+ 'command'=>proc{t.hscroll(true)}).pack('side'=>'left')
TkButton.new(f, 'text'=>'hscr OFF',
- 'command'=>proc{t.hscroll(false)}).pack('side'=>'left')
+ 'command'=>proc{t.hscroll(false)}).pack('side'=>'left')
Tk.mainloop
end
diff --git a/ext/tk/sample/tktextio.rb b/ext/tk/sample/tktextio.rb
new file mode 100644
index 0000000000..9f012feada
--- /dev/null
+++ b/ext/tk/sample/tktextio.rb
@@ -0,0 +1,1060 @@
+#!/usr/bin/env ruby
+#
+# TkTextIO class :: handling I/O stream on a TkText widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+# NOTE: TkTextIO supports 'character' (not 'byte') access only.
+# So, for example, TkTextIO#getc returns a character, TkTextIO#pos
+# means the character position, TkTextIO#read(size) counts by
+# characters, and so on.
+# Of course, it is available to make TkTextIO class to suuport
+# 'byte' access. However, it may break multi-byte characters.
+# and then, displayed string on the text widget may be garbled.
+# I think that it is not good on the supposed situation of using
+# TkTextIO.
+#
+require 'tk'
+require 'tk/text'
+require 'tk/textmark'
+require 'thread'
+
+class TkTextIO < TkText
+ # keep safe level
+ @@create_queues = proc{ [Queue.new, Mutex.new, Queue.new, Mutex.new] }
+
+ OPT_DEFAULTS = {
+ 'mode' => nil,
+ 'overwrite' => false,
+ 'text' => nil,
+ 'show' => :pos,
+ 'wrap' => 'char',
+ 'sync' => true,
+ 'prompt' => nil,
+ 'prompt_cmd' => nil,
+ 'hist_size' => 1000,
+ }
+
+ def create_self(keys)
+ opts = _get_io_params((keys.kind_of?(Hash))? keys: {})
+
+ super(keys)
+
+ @count_var = TkVariable.new
+
+ @write_buffer = ''
+ @read_buffer = ''
+ @buf_size = 0
+ @buf_max = 1024
+
+ @write_buf_queue, @write_buf_mutex,
+ @read_buf_queue, @read_buf_mutex = @@create_queues.call
+
+ @idle_flush = TkTimer.new(:idle, 1, proc{ @flusher.run rescue nil })
+ @timer_flush = TkTimer.new(250, -1, proc{ @flusher.run rescue nil })
+
+ @flusher = Thread.new{ loop { Thread.stop; flush() } }
+
+ @receiver = Thread.new{
+ begin
+ loop {
+ str = @write_buf_queue.deq
+ @write_buf_mutex.synchronize { @write_buffer << str }
+ @idle_flush.start
+ }
+ ensure
+ @flusher.kill
+ end
+ }
+
+ @timer_flush.start
+
+ _setup_io(opts)
+ end
+ private :create_self
+
+ def destroy
+ @flusher.kill rescue nil
+
+ @idle_flush.stop rescue nil
+ @timer_flush.stop rescue nil
+
+ @receiver.kill rescue nil
+
+ super()
+ end
+
+ ####################################
+
+ def _get_io_params(keys)
+ opts = {}
+ self.class.const_get(:OPT_DEFAULTS).each{|k, v|
+ if keys.has_key?(k)
+ opts[k] = keys.delete(k)
+ else
+ opts[k] = v
+ end
+ }
+ opts
+ end
+
+ def _setup_io(opts)
+ unless defined? @txtpos
+ @txtpos = TkTextMark.new(self, '1.0')
+ else
+ @txtpos.set('1.0')
+ end
+ @txtpos.gravity = :left
+
+ @lineno = 0
+ @line_offset = 0
+
+ @hist_max = opts['hist_size'].to_i
+ @hist_index = 0
+ @history = Array.new(@hist_max)
+ @history[0] = ''
+
+ self['wrap'] = wrap
+
+ self.show_mode = opts['show']
+
+ self.value = opts['text'] if opts['text']
+
+ @overwrite = (opts['overwrite'])? true: false
+
+ @sync = opts['sync']
+
+ @prompt = opts['prompt']
+ @prompt_cmd = opts['prompt_cmd']
+
+ @open = {:r => true, :w => true} # default is 'r+'
+
+ @console_mode = false
+ @end_of_stream = false
+ @console_buffer = nil
+
+ case opts['mode']
+ when nil
+ # do nothing
+
+ when :console, 'console'
+ @console_mode = true
+ # @console_buffer = TkTextIO.new(:mode=>'r')
+ @console_buffer = self.class.new(:mode=>'r')
+ self.show_mode = :insert
+
+ when 'r', 'rb'
+ @open[:r] = true; @open[:w] = nil
+
+ when 'r+', 'rb+', 'r+b'
+ @open[:r] = true; @open[:w] = true
+
+ when 'w', 'wb'
+ @open[:r] = nil; @open[:w] = true
+ self.value=''
+
+ when 'w+', 'wb+', 'w+b'
+ @open[:r] = true; @open[:w] = true
+ self.value=''
+
+ when 'a', 'ab'
+ @open[:r] = nil; @open[:w] = true
+ @txtpos.set('end - 1 char')
+ @txtpos.gravity = :right
+
+ when 'a+', 'ab+', 'a+b'
+ @open[:r] = true; @open[:w] = true
+ @txtpos.set('end - 1 char')
+ @txtpos.gravity = :right
+
+ else
+ fail ArgumentError, "unknown mode `#{opts['mode']}'"
+ end
+
+ unless defined? @ins_head
+ @ins_head = TkTextMark.new(self, 'insert')
+ @ins_head.gravity = :left
+ end
+
+ unless defined? @ins_tail
+ @ins_tail = TkTextMark.new(self, 'insert')
+ @ins_tail.gravity = :right
+ end
+
+ unless defined? @tmp_mark
+ @tmp_mark = TkTextMark.new(self, 'insert')
+ @tmp_mark.gravity = :left
+ end
+
+ if @console_mode
+ _set_console_line
+ _setup_console_bindings
+ end
+ end
+ private :_get_io_params, :_setup_io
+
+ def _set_console_line
+ @tmp_mark.set(@ins_tail)
+
+ mark_set('insert', 'end')
+
+ prompt = ''
+ prompt << @prompt_cmd.call if @prompt_cmd
+ prompt << @prompt if @prompt
+ insert(@tmp_mark, prompt)
+
+ @ins_head.set(@ins_tail)
+ @ins_tail.set('insert')
+
+ @txtpos.set(@tmp_mark)
+
+ _see_pos
+ end
+
+ def _replace_console_line(str)
+ self.delete(@ins_head, @ins_tail)
+ self.insert(@ins_head, str)
+ end
+
+ def _get_console_line
+ @tmp_mark.set(@ins_tail)
+ s = self.get(@ins_head, @tmp_mark)
+ _set_console_line
+ s
+ end
+ private :_set_console_line, :_replace_console_line, :_get_console_line
+
+ def _cb_up
+ @history[@hist_index].replace(self.get(@ins_head, @ins_tail))
+ @hist_index += 1
+ @hist_index -= 1 if @hist_index >= @hist_max || !@history[@hist_index]
+ _replace_console_line(@history[@hist_index]) if @history[@hist_index]
+ Tk.callback_break
+ end
+ def _cb_down
+ @history[@hist_index].replace(self.get(@ins_head, @ins_tail))
+ @hist_index -= 1
+ @hist_index = 0 if @hist_index < 0
+ _replace_console_line(@history[@hist_index]) if @history[@hist_index]
+ Tk.callback_break
+ end
+ def _cb_left
+ if @console_mode && compare('insert', '<=', @ins_head)
+ mark_set('insert', @ins_head)
+ Tk.callback_break
+ end
+ end
+ def _cb_backspace
+ if @console_mode && compare('insert', '<=', @ins_head)
+ Tk.callback_break
+ end
+ end
+ def _cb_ctrl_a
+ if @console_mode
+ mark_set('insert', @ins_head)
+ Tk.callback_break
+ end
+ end
+ def _cb_ctrl_u
+ if @console_mode
+ mark_set('insert', @ins_head)
+ delete('insert', 'insert lineend')
+ Tk.callback_break
+ end
+ end
+ private :_cb_up, :_cb_down, :_cb_left, :_cb_backspace,
+ :_cb_ctrl_a, :_cb_ctrl_u
+
+ def _setup_console_bindings
+ @bindtag = TkBindTag.new
+
+ tags = self.bindtags
+ tags[tags.index(self)+1, 0] = @bindtag
+ self.bindtags = tags
+
+ @bindtag.bind('Return'){
+ insert('end - 1 char', "\n")
+ if (str = _get_console_line)
+ @read_buf_queue.push(str)
+
+ @history[0].replace(str.chomp)
+ @history.pop
+ @history.unshift('')
+ @hist_index = 0
+ end
+
+ Tk.update
+ Tk.callback_break
+ }
+ @bindtag.bind('Alt-Return'){
+ Tk.callback_continue
+ }
+
+ @bindtag.bind('FocusIn'){
+ if @console_mode
+ mark_set('insert', @ins_tail)
+ Tk.callback_break
+ end
+ }
+
+ ins_mark = TkTextMark.new(self, 'insert')
+
+ @bindtag.bind('ButtonPress'){
+ if @console_mode
+ ins_mark.set('insert')
+ end
+ }
+
+ @bindtag.bind('ButtonRelease-1'){
+ if @console_mode && compare('insert', '<=', @ins_head)
+ mark_set('insert', ins_mark)
+ Tk.callback_break
+ end
+ }
+
+ @bindtag.bind('ButtonRelease-2', '%x %y'){|x, y|
+ if @console_mode
+ # paste a text at 'insert' only
+ x1, y1, x2, y2 = bbox(ins_mark)
+ unless x == x1 && y == y1
+ Tk.event_generate(self, 'ButtonRelease-2', :x=>x1, :y=>y1)
+ Tk.callback_break
+ end
+ end
+ }
+
+ @bindtag.bind('Up'){ _cb_up }
+ @bindtag.bind('Control-p'){ _cb_up }
+
+ @bindtag.bind('Down'){ _cb_down }
+ @bindtag.bind('Control-n'){ _cb_down }
+
+ @bindtag.bind('Left'){ _cb_left }
+ @bindtag.bind('Control-b'){ _cb_left }
+
+ @bindtag.bind('BackSpace'){ _cb_backspace }
+ @bindtag.bind('Control-h'){ _cb_backspace }
+
+ @bindtag.bind('Home'){ _cb_ctrl_a }
+ @bindtag.bind('Control-a'){ _cb_ctrl_a }
+
+ @bindtag.bind('Control-u'){ _cb_ctrl_u }
+ end
+ private :_setup_console_bindings
+
+ def _block_read(size = nil, ret = '', block_mode = true)
+ return '' if size == 0
+ return nil if ! @read_buf_queue && @read_buffer.empty?
+ ret = '' unless ret.kind_of?(String)
+ ret.replace('') unless ret.empty?
+
+ if block_mode == nil # partial
+ if @read_buffer.empty?
+ ret << @read_buffer.slice!(0..-1)
+ return ret
+ end
+ end
+
+ if size.kind_of?(Numeric)
+ loop{
+ @read_buf_mutex.synchronize {
+ buf_len = @read_buffer.length
+ if buf_len >= size
+ ret << @read_buffer.slice!(0, size)
+ return ret
+ else
+ ret << @read_buffer.slice!(0..-1)
+ size -= buf_len
+ return ret unless @read_buf_queue
+ end
+ }
+ @read_buffer << @read_buf_queue.pop
+ }
+ else # readline
+ rs = (size)? size: $/
+ rs = rs.to_s if rs.kind_of?(Regexp)
+ loop{
+ @read_buf_mutex.synchronize {
+ if (str = @read_buffer.slice!(/\A(.*)(#{rs})/m))
+ ret << str
+ return ret
+ else
+ ret << @read_buffer.slice!(0..-1)
+ return ret unless @read_buf_queue
+ end
+ }
+ @read_buffer << @read_buf_queue.pop
+ }
+ end
+ end
+
+ def _block_write
+ ###### currently, not support
+ end
+ private :_block_read, :_block_write
+
+ ####################################
+
+ def <<(obj)
+ _write(obj)
+ self
+ end
+
+ def binmode
+ self
+ end
+
+ def clone
+ fail NotImplementedError, 'cannot clone TkTextIO'
+ end
+ def dup
+ fail NotImplementedError, 'cannot duplicate TkTextIO'
+ end
+
+ def close
+ close_read
+ close_write
+ nil
+ end
+ def close_read
+ @open[:r] = false if @open[:r]
+ nil
+ end
+ def close_write
+ @open[:w] = false if @opne[:w]
+ nil
+ end
+
+ def closed?(dir=nil)
+ case dir
+ when :r, 'r'
+ !@open[:r]
+ when :w, 'w'
+ !@open[:w]
+ else
+ !@open[:r] && !@open[:w]
+ end
+ end
+
+ def _check_readable
+ fail IOError, "not opened for reading" if @open[:r].nil?
+ fail IOError, "closed stream" if !@open[:r]
+ end
+ def _check_writable
+ fail IOError, "not opened for writing" if @open[:w].nil?
+ fail IOError, "closed stream" if !@open[:w]
+ end
+ private :_check_readable, :_check_writable
+
+ def each_line(rs = $/)
+ _check_readable
+ while(s = self.gets(rs))
+ yield(s)
+ end
+ self
+ end
+ alias each each_line
+
+ def each_char
+ _check_readable
+ while(c = self.getc)
+ yield(c)
+ end
+ self
+ end
+ alias each_byte each_char
+
+ def eof?
+ compare(@txtpos, '==', 'end - 1 char')
+ end
+ alias eof eof?
+
+ def fcntl(*args)
+ fail NotImplementedError, "fcntl is not implemented on #{self.class}"
+ end
+
+ def fsync
+ 0
+ end
+
+ def fileno
+ nil
+ end
+
+ def flush
+ Thread.pass
+ if @open[:w] || ! @write_buffer.empty?
+ @write_buf_mutex.synchronize {
+ _sync_write_buf(@write_buffer)
+ @write_buffer[0..-1] = ''
+ }
+ end
+ self
+ end
+
+ def getc
+ return _block_read(1) if @console_mode
+
+ _check_readable
+ return nil if eof?
+ c = get(@txtpos)
+ @txtpos.set(@txtpos + '1 char')
+ _see_pos
+ c
+ end
+
+ def gets(rs = $/)
+ return _block_read(rs) if @console_mode
+
+ _check_readable
+ return nil if eof?
+ _readline(rs)
+ end
+
+ def ioctrl(*args)
+ fail NotImplementedError, 'iocntl is not implemented on TkTextIO'
+ end
+
+ def isatty
+ false
+ end
+ def tty?
+ false
+ end
+
+ def lineno
+ @lineno + @line_offset
+ end
+
+ def lineno=(num)
+ @line_offset = num - @lineno
+ num
+ end
+
+ def overwrite?
+ @overwrite
+ end
+
+ def overwrite=(ovwt)
+ @overwrite = (ovwt)? true: false
+ end
+
+ def pid
+ nil
+ end
+
+ def index_pos
+ index(@txtpos)
+ end
+ alias tell_index index_pos
+
+ def index_pos=(idx)
+ @txtpos.set(idx)
+ @txtpos.set('end - 1 char') if compare(@txtpos, '>=', :end)
+ _see_pos
+ idx
+ end
+
+ def pos
+ s = get('1.0', @txtpos)
+ number(tk_call('string', 'length', s))
+ end
+ alias tell pos
+
+ def pos=(idx)
+ seek(idx, IO::SEEK_SET)
+ idx
+ end
+
+ def pos_gravity
+ @txtpos.gravity
+ end
+
+ def pos_gravity=(side)
+ @txtpos.gravity = side
+ side
+ end
+
+ def print(arg=$_, *args)
+ _check_writable
+ args.unshift(arg)
+ args.map!{|val| (val == nil)? 'nil': val.to_s }
+ str = args.join($,)
+ str << $\ if $\
+ _write(str)
+ nil
+ end
+ def printf(*args)
+ _check_writable
+ _write(sprintf(*args))
+ nil
+ end
+
+ def putc(c)
+ _check_writable
+ c = c.chr if c.kind_of?(Fixnum)
+ _write(c)
+ c
+ end
+
+ def puts(*args)
+ _check_writable
+ if args.empty?
+ _write("\n")
+ return nil
+ end
+ args.each{|arg|
+ if arg == nil
+ _write("nil\n")
+ elsif arg.kind_of?(Array)
+ puts(*arg)
+ elsif arg.kind_of?(String)
+ _write(arg.chomp)
+ _write("\n")
+ else
+ begin
+ arg = arg.to_ary
+ puts(*arg)
+ rescue
+ puts(arg.to_s)
+ end
+ end
+ }
+ nil
+ end
+
+ def _read(len)
+ epos = @txtpos + "#{len} char"
+ s = get(@txtpos, epos)
+ @txtpos.set(epos)
+ @txtpos.set('end - 1 char') if compare(@txtpos, '>=', :end)
+ _see_pos
+ s
+ end
+ private :_read
+
+ def read(len=nil, buf=nil)
+ return _block_read(len, buf) if @console_mode
+
+ _check_readable
+ if len
+ return "" if len == 0
+ return nil if eof?
+ s = _read(len)
+ else
+ s = get(@txtpos, 'end - 1 char')
+ @txtpos.set('end - 1 char')
+ _see_pos
+ end
+ buf.replace(s) if buf.kind_of?(String)
+ s
+ end
+
+ def readchar
+ return _block_read(1) if @console_mode
+
+ _check_readable
+ fail EOFError if eof?
+ c = get(@txtpos)
+ @txtpos.set(@txtpos + '1 char')
+ _see_pos
+ c
+ end
+
+ def _readline(rs = $/)
+ if rs == nil
+ s = get(@txtpos, 'end - 1 char')
+ @txtpos.set('end - 1 char')
+ elsif rs == ''
+ @count_var.value # make it global
+ idx = tksearch_with_count([:regexp], @count_var,
+ "\n(\n)+", @txtpos, 'end - 1 char')
+ if idx
+ s = get(@txtpos, idx) << "\n"
+ @txtpos.set("#{idx} + #{@count_var.value} char")
+ @txtpos.set('end - 1 char') if compare(@txtpos, '>=', :end)
+ else
+ s = get(@txtpos, 'end - 1 char')
+ @txtpos.set('end - 1 char')
+ end
+ else
+ @count_var.value # make it global
+ idx = tksearch_with_count(@count_var, rs, @txtpos, 'end - 1 char')
+ if idx
+ s = get(@txtpos, "#{idx} + #{@count_var.value} char")
+ @txtpos.set("#{idx} + #{@count_var.value} char")
+ @txtpos.set('end - 1 char') if compare(@txtpos, '>=', :end)
+ else
+ s = get(@txtpos, 'end - 1 char')
+ @txtpos.set('end - 1 char')
+ end
+ end
+
+ _see_pos
+ @lineno += 1
+ $_ = s
+ end
+ private :_readline
+
+ def readline(rs = $/)
+ return _block_readline(rs) if @console_mode
+
+ _check_readable
+ fail EOFError if eof?
+ _readline(rs)
+ end
+
+ def readlines(rs = $/)
+ if @console_mode
+ lines = []
+ while (line = _block_readline(rs))
+ lines << line
+ end
+ return lines
+ end
+
+ _check_readable
+ lines = []
+ until(eof?)
+ lines << _readline(rs)
+ end
+ $_ = nil
+ lines
+ end
+
+ def readpartial(maxlen, buf=nil)
+ #return @console_buffer.readpartial(maxlen, buf) if @console_mode
+ return _block_read(maxlen, buf, nil) if @console_mode
+
+ _check_readable
+ fail EOFError if eof?
+ s = _read(maxlen)
+ buf.replace(s) if buf.kind_of?(String)
+ s
+ end
+
+ def reopen(*args)
+ fail NotImplementedError, 'reopen is not implemented on TkTextIO'
+ end
+
+ def rewind
+ @txtpos.set('1.0')
+ _see_pos
+ @lineno = 0
+ @line_offset = 0
+ self
+ end
+
+ def seek(offset, whence=IO::SEEK_SET)
+ case whence
+ when IO::SEEK_SET
+ offset = "1.0 + #{offset} char" if offset.kind_of?(Numeric)
+ @txtpos.set(offset)
+
+ when IO::SEEK_CUR
+ offset = "#{offset} char" if offset.kind_of?(Numeric)
+ @txtpos.set(@txtpos + offset)
+
+ when IO::SEEK_END
+ offset = "#{offset} char" if offset.kind_of?(Numeric)
+ @txtpos.set("end - 1 char + #{offset}")
+
+ else
+ fail Errno::EINVAL, 'invalid whence argument'
+ end
+
+ @txtpos.set('end - 1 char') if compare(@txtpos, '>=', :end)
+ _see_pos
+
+ 0
+ end
+ alias sysseek seek
+
+ def _see_pos
+ see(@show) if @show
+ end
+ private :_see_pos
+
+ def show_mode
+ (@show == @txtpos)? :pos : @show
+ end
+
+ def show_mode=(mode)
+ # define show mode when file position is changed.
+ # mode == :pos or "pos" or true :: see current file position.
+ # mode == :insert or "insert" :: see insert cursor position.
+ # mode == nil or false :: do nothing
+ # else see 'mode' position ('mode' should be text index or mark)
+ case mode
+ when :pos, 'pos', true
+ @show = @txtpos
+ when :insert, 'insert'
+ @show = :insert
+ when nil, false
+ @show = false
+ else
+ begin
+ index(mode)
+ rescue
+ fail ArgumentError, 'invalid show-position'
+ end
+ @show = mode
+ end
+
+ _see_pos
+
+ mode
+ end
+
+ def stat
+ fail NotImplementedError, 'stat is not implemented on TkTextIO'
+ end
+
+ def sync
+ @sync
+ end
+
+ def sync=(mode)
+ @sync = mode
+ end
+
+ def sysread(len, buf=nil)
+ return _block_read(len, buf) if @console_mode
+
+ _check_readable
+ fail EOFError if eof?
+ s = _read(len)
+ buf.replace(s) if buf.kind_of?(String)
+ s
+ end
+
+ def syswrite(obj)
+ _write(obj)
+ end
+
+ def to_io
+ self
+ end
+
+ def trancate(len)
+ delete("1.0 + #{len} char", :end)
+ 0
+ end
+
+ def ungetc(c)
+ if @console_mode
+ @read_buf_mutex.synchronize {
+ @read_buffer[0,0] = c.chr
+ }
+ return nil
+ end
+
+ _check_readable
+ c = c.chr if c.kind_of?(Fixnum)
+ if compare(@txtpos, '>', '1.0')
+ @txtpos.set(@txtpos - '1 char')
+ delete(@txtpos)
+ insert(@txtpos, tk_call('string', 'range', c, 0, 1))
+ @txtpos.set(@txtpos - '1 char') if @txtpos.gravity == 'right'
+ _see_pos
+ else
+ fail IOError, 'cannot ungetc at head of stream'
+ end
+ nil
+ end
+
+=begin
+ def _write(obj)
+ #s = _get_eval_string(obj)
+ s = (obj.kind_of?(String))? obj: obj.to_s
+ n = number(tk_call('string', 'length', s))
+ delete(@txtpos, @txtpos + "#{n} char") if @overwrite
+ self.insert(@txtpos, s)
+ @txtpos.set(@txtpos + "#{n} char")
+ @txtpos.set('end - 1 char') if compare(@txtpos, '>=', :end)
+ _see_pos
+ Tk.update if @sync
+ n
+ end
+ private :_write
+=end
+#=begin
+ def _sync_write_buf(s)
+ if (n = number(tk_call('string', 'length', s))) > 0
+ delete(@txtpos, @txtpos + "#{n} char") if @overwrite
+ self.insert(@txtpos, s)
+ #Tk.update
+
+ @txtpos.set(@txtpos + "#{n} char")
+ @txtpos.set('end - 1 char') if compare(@txtpos, '>=', :end)
+
+ @ins_head.set(@txtpos) if compare(@txtpos, '>', @ins_head)
+
+ _see_pos
+ end
+ self
+ end
+ private :_sync_write_buf
+
+ def _write(obj)
+ s = (obj.kind_of?(String))? obj: obj.to_s
+ n = number(tk_call('string', 'length', s))
+ @write_buf_queue.enq(s)
+ if @sync
+ Thread.pass
+ Tk.update
+ end
+ n
+ end
+ private :_write
+#=end
+
+ def write(obj)
+ _check_writable
+ _write(obj)
+ end
+end
+
+####################
+# TEST
+####################
+if __FILE__ == $0
+ ev_loop = Thread.new{Tk.mainloop}
+
+ f = TkFrame.new.pack
+ #tio = TkTextIO.new(f, :show=>:nil,
+ #tio = TkTextIO.new(f, :show=>:pos,
+ tio = TkTextIO.new(f, :show=>:insert,
+ :text=>">>> This is an initial text line. <<<\n\n"){
+# yscrollbar(TkScrollbar.new(f).pack(:side=>:right, :fill=>:y))
+ pack(:side=>:left, :fill=>:both, :expand=>true)
+ }
+
+ Tk.update
+
+ $stdin = tio
+ $stdout = tio
+ $stderr = tio
+
+ STDOUT.print("\n========= TkTextIO#gets for inital text ========\n\n")
+
+ while(s = gets)
+ STDOUT.print(s)
+ end
+
+ STDOUT.print("\n============ put strings to TkTextIO ===========\n\n")
+
+ puts "On this sample, a text widget works as if it is a I/O stream."
+ puts "Please see the code."
+ puts
+ printf("printf message: %d %X\n", 123456, 255)
+ puts
+ printf("(output by 'p' method) This TkTextIO object is ...\n")
+ p tio
+ print(" [ Current wrap mode of this object is 'char'. ]\n")
+ puts
+ warn("This is a warning message generated by 'warn' method.")
+ puts
+ puts "current show_mode is #{tio.show_mode}."
+ if tio.show_mode == :pos
+ puts "So, you can see the current file position on this text widget."
+ else
+ puts "So, you can see the position '#{tio.show_mode}' on this text widget."
+ end
+ print("Please scroll up this text widget to see the head of lines.\n")
+ print("---------------------------------------------------------\n")
+
+ STDOUT.print("\n=============== TkTextIO#readlines =============\n\n")
+
+ tio.seek(0)
+ lines = readlines
+ STDOUT.puts(lines.inspect)
+
+ STDOUT.print("\n================== TkTextIO#each ===============\n\n")
+
+ tio.rewind
+ tio.each{|line| STDOUT.printf("%2d: %s\n", tio.lineno, line.chomp)}
+
+ STDOUT.print("\n================================================\n\n")
+
+ STDOUT.print("\n========= reverse order (seek by lines) ========\n\n")
+
+ tio.seek(-1, IO::SEEK_END)
+ begin
+ begin
+ tio.seek(:linestart, IO::SEEK_CUR)
+ rescue
+ # maybe use old version of tk/textmark.rb
+ tio.seek('0 char linestart', IO::SEEK_CUR)
+ end
+ STDOUT.print(gets)
+ tio.seek('-1 char linestart -1 char', IO::SEEK_CUR)
+ end while(tio.pos > 0)
+
+ STDOUT.print("\n================================================\n\n")
+
+ tio.seek(0, IO::SEEK_END)
+
+ STDOUT.print("tio.sync == #{tio.sync}\n")
+# tio.sync = false
+# STDOUT.print("tio.sync == #{tio.sync}\n")
+
+ (0..10).each{|i|
+ STDOUT.print("#{i}\n")
+ s = ''
+ (0..1000).each{ s << '*' }
+ print(s)
+ }
+ print("\n")
+ print("\n=========================================================\n\n")
+
+ s = ''
+ timer = TkTimer.new(:idle, -1, proc{
+ #STDOUT.print("idle call\n")
+ unless s.empty?
+ print(s)
+ s = ''
+ end
+ }).start
+ (0..10).each{|i|
+ STDOUT.print("#{i}\n")
+ (0..1000).each{ s << '*' }
+ }
+# timer.stop
+ until s.empty?
+ sleep 0.1
+ end
+ timer.stop
+
+=begin
+ tio.sync = false
+ print("\n")
+ #(0..10000).each{ putc('*') }
+ (0..10).each{|i|
+ STDOUT.print("#{i}\n")
+ (0..1000).each{ putc('*') }
+ }
+
+ (0..10).each{|i|
+ STDOUT.print("#{i}\n")
+ s = ''
+ (0..1000).each{ s << '*' }
+ print(s)
+ }
+=end
+
+ num = 0
+# io = TkTextIO.new(:mode=>:console, :prompt=>'').pack
+#=begin
+ io = TkTextIO.new(:mode=>:console,
+ :prompt_cmd=>proc{
+ s = "[#{num}]"
+ num += 1
+ s
+ },
+ :prompt=>'-> ').pack
+#=end
+ Thread.new{loop{sleep 2; io.puts 'hoge'}}
+ Thread.new{loop{p io.gets}}
+
+ ev_loop.join
+end
diff --git a/ext/tk/sample/tktree.rb b/ext/tk/sample/tktree.rb
new file mode 100644
index 0000000000..56b7211c88
--- /dev/null
+++ b/ext/tk/sample/tktree.rb
@@ -0,0 +1,103 @@
+##########################################################################
+# TkTree widget class
+#
+# see <http://wiki.tcl.tk/10615>
+#
+# Note: optional argument '-font' of the Tcl library is changed to
+# 'itemfont' on this Ruby library, because of avoiding font
+# operation trouble in 'initialize' method ( see the following
+# test script ).
+#
+##########################################################################
+require 'tk'
+
+class TkTree < TkCanvas
+ TCL_SCRIPT_PATH = File.join(File.dirname(__FILE__), 'tktree.tcl')
+
+ def create_self(keys)
+ args = [@path]
+ if keys.kind_of?(Hash)
+ font = keys.delete('itemfont')
+# font = hash_kv(font) if font.kind_of?(Hash)
+ keys['font'] = font if font
+# args.concat(hash_kv(keys))
+ args << keys
+ end
+ begin
+ tk_call('::tktree::treecreate', *args)
+ rescue NameError, RuntimeError
+ Tk.load_tclscript(TkTree::TCL_SCRIPT_PATH)
+ tk_call('::tktree::treecreate', *args)
+ end
+ end
+
+ def newitem(itempath, keys = nil)
+ if keys.kind_of?(Hash)
+ keys = _symbolkey2str(keys)
+ font = keys.delete('itemfont')
+# font = hash_kv(font) if font.kind_of?(Hash)
+ keys['font'] = font if font
+# tk_call('::tktree::newitem', @path, itempath, *hash_kv(keys))
+ tk_call('::tktree::newitem', @path, itempath, keys)
+ else
+ tk_call('::tktree::newitem', @path, itempath)
+ end
+ end
+
+ def delitem(itempath)
+ tk_call('::tktree::delitem', @path, itempath)
+ end
+
+ def labelat(xpos, ypos)
+ tk_call('::tktree::delitem', @path, xpos, ypos)
+ end
+
+ def getselection
+ tk_call('::tktree::getselection', @path)
+ end
+
+ def setselection(itempath)
+ tk_call('::tktree::getselection', @path, itempath)
+ end
+end
+
+
+##########################################################################
+# test script
+##########################################################################
+if __FILE__ == $0
+ TkLabel.new(:text=><<EOL, :relief=>:ridge, :justify=>:left).pack
+
+ This is a sample to use a Tcl library script on Ruby/Tk.
+ This sample loads tktree.tcl (see <http://wiki.tcl.tk/10615>)
+ and calls functions of the Tcl script.
+EOL
+
+ items = %w(/group1/item1 /group1/item2 /group1/subgroup/item1 /group2/item1 /item1)
+
+ tr1 = TkTree.new.pack(:expand=>true, :fill=>:both)
+ tr1.focus
+
+ items.each{|item|
+ tr1.newitem(item,
+ :command=>proc{Tk.messageBox(:message=>"#{item} executed")})
+ }
+
+ f = TkFrame.new.pack(:expand=>true, :fill=>:both)
+ tr2 = TkTree.new(f, :bg=>'black', #:itemfont=>{:family=>'Times', :size=>14},
+ :textcolor=>'red', :bd=>4, :relief=>:ridge,
+ :selectbackground=>'darkBlue', :selectforeground=>'yellow',
+ :selectborderwidth=>3, :linecolor=>'yellow') {
+ yscrollbar(TkScrollbar.new(f, :width=>10).pack(:side=>:right, :fill=>:y))
+ xscrollbar(TkScrollbar.new(f, :width=>10).pack(:side=>:bottom, :fill=>:x))
+ pack(:expand=>true, :fill=>:both)
+ }
+
+ items.each{|item|
+ tr2.newitem(item, :textcolor=>'green', :image=>'',
+ :itemfont=>{:family=>'Times', :size=>10},
+ :command=>proc{Tk.messageBox(:message=>"#{item} executed")})
+ }
+
+ Tk.mainloop
+end
diff --git a/ext/tk/sample/tktree.tcl b/ext/tk/sample/tktree.tcl
new file mode 100644
index 0000000000..a5e47eb776
--- /dev/null
+++ b/ext/tk/sample/tktree.tcl
@@ -0,0 +1,305 @@
+#
+# This Tcl/Tk script is quoted from <http://wiki.tcl.tk/10615>.
+#
+ package require Tk
+ namespace eval ::tktree {
+
+ # Images used for open and close state of subgroups
+ set ::tktree::imgcollapse [image create photo .tktreeopenbm -data {
+ R0lGODdhCQAJAIAAAAEBAf///ywAAAAACQAJAAACEISPoRvG614D80x5ZXyogwIAOw==}]
+ set ::tktree::imgexpand [image create photo .tktreeclosebm -data {
+ R0lGODdhCQAJAIAAAAEBAf///ywAAAAACQAJAAACEYSPoRu28KCSDSJLc44s3lMAADs=}]
+ ###Default images for groups and children
+ set ::tktree::imgsubgroups [image create photo .tktreeimgfolder -data {
+ R0lGODlhEAANAKIAANnZ2Xh4eLi4uPj4APj4+AAAAP///////yH5BAEAAAAA
+ LAAAAAAQAA0AAANkCIChiqDLITgyEgi6GoIjIyMYugCBpMsaWBA0giMjIzgy
+ UYBBMjIoIyODEgVBODIygiMjE1gQJIMyMjIoI1GAQSMjODIyghMFQSgjI4My
+ MhJYEDSCIyMjODJRgKHLXAiApcsMmAA7}]
+ set ::tktree::imgchildren [image create photo .tktreeimgfile -data {
+ R0lGODlhDQAQAKIAANnZ2Xh4ePj4+Li4uAAAAP///////////yH5BAEAAAAA
+ LAAAAAANABAAAANSGLoLgACBoqsRCBAoujqCASGDojtESCEihCREIjgUKLo8
+ hCGCpCsySIGiy0MYIki6IoMUKLo8hCGCpCsySIGiy0MYKLo8hIGiy0MYOLo8
+ SLrMCQA7}]
+
+ #### Swtich all subgroups of a layer to open or close
+ proc ::tktree::switchlayer {win opn {layer /}} {
+ variable cfg
+ foreach child $cfg($win,$layer:subgroups) {
+ set cfg($win,$child:open) $opn
+ switchlayer $win $opn $child
+ }
+ buildwhenidle $win
+ }
+
+ #### will open or close the item given
+ proc ::tktree::switchstate {win item} {
+ set ::tktree::cfg($win,$item:open) [expr ! $::tktree::cfg($win,$item:open)]
+ buildwhenidle $win
+ }
+
+ #### Select the next item up or down
+ proc ::tktree::updown {win down} {
+ variable cfg
+ set index [lsearch -exact $cfg($win,sortlist) $cfg($win,selection)]
+ if {$down} {incr index} {incr index -1}
+ if {$index < 0} {set index end} elseif {$index >= [llength $cfg($win,sortlist)]} {set index 0}
+ setselection $win [lindex $cfg($win,sortlist) $index]
+ }
+
+ #### left-right button binding commands
+ proc ::tktree::leftright {win right} {
+ variable cfg
+ set item $cfg($win,selection)
+ set index [lsearch -exact $cfg($win,sortlist) $item]
+ set parentindex [lsearch -exact $cfg($win,sortlist) [file dirname $item]]
+ if {$parentindex == -1} {set parentindex [expr $index - 1]}
+ if {$cfg($win,$item:group)} {
+ if {$right} {
+ if {$cfg($win,$item:open)} {incr index} {set cfg($win,$item:open) 1}
+ } else {
+ if {$cfg($win,$item:open)} {set cfg($win,$item:open) 0} {set index $parentindex}
+ }
+ } else {
+ if {$right} {incr index} {set index $parentindex}
+ }
+ if {$index < 0} {set index end} elseif {$index >= [llength $cfg($win,sortlist)]} {set index 0}
+ setselection $win [lindex $cfg($win,sortlist) $index]
+ buildwhenidle $win
+ }
+
+ #### will return the pathname of the item at x and y cooridinates
+ proc ::tktree::labelat {win x y} {
+ set x [$win canvasx $x]; set y [$win canvasy $y]
+ foreach m [$win find overlapping $x $y $x $y] {
+ if {[info exists ::tktree::cfg($win,tag:$m)]} {return $::tktree::cfg($win,tag:$m)}
+ }
+ return ""
+ }
+
+ #### will return the path of the current selection in the given tree widget
+ proc ::tktree::getselection {win} {
+ return $::tktree::cfg($win,selection)
+ }
+
+ #### adjust the scrollview to show the selected item as needed
+ proc ::tktree::scrolladjust {win tag} {
+ update
+ set item [$win bbox $tag]
+ set region [$win cget -scrollregion]
+ foreach {axis idx1 idx2} {yview 1 3 xview 0 2} {
+ set range [expr abs([lindex $region $idx2]) - abs([lindex $region $idx1])]
+ set itemtop [lindex $item $idx1]; set itembot [lindex $item $idx2]
+ set viewtop [expr $range * [lindex [$win $axis] 0]]
+ set viewbot [expr $range * [lindex [$win $axis] 1]]
+ if {$itembot > $viewbot} {$win $axis moveto [expr ($itembot. - $viewbot + $viewtop) / $range]}
+ if {$itemtop < $viewtop} {$win $axis moveto [expr $itemtop. / $range]}
+ }
+ }
+
+ #### will set the current selection to the given item on the given tree
+ proc ::tktree::setselection {win item} {
+ variable cfg
+ if {![llength $cfg($win,sortlist)]} {return}
+ if {$item eq ""} {set item [lindex $cfg($win,sortlist) 0]}
+ if {![info exists cfg($win,$item:tag)]} {set item [lindex $cfg($win,sortlist) 0]}
+ if {[$win gettags $cfg($win,$item:tag)] ne ""} {
+ $win select from $cfg($win,$item:tag) 0
+ $win select to $cfg($win,$item:tag) end
+ set cfg($win,selection) $item
+ scrolladjust $win $cfg($win,$item:tag)
+ } {
+ setselection $win "/[lindex $cfg($win,/:sortlist) 0]"
+ }
+ }
+
+ #### will delete the item given from the tree given
+ proc ::tktree::delitem {win item} {
+ variable cfg
+ if {$item eq "/"} {
+ array unset cfg $win,* ; catch {destroy $win}
+ } {
+ set group [file dirname $item]
+ if {$cfg($win,$item:group)} {set type subgroups} {set type children}
+ set index [lsearch -exact $cfg($win,$group:$type) $item]
+ set cfg($win,$group:$type) [lreplace $cfg($win,$group:$type) $index $index]
+ array unset cfg $win,$item*
+ buildwhenidle $win
+ }
+ }
+
+ #### create a new item in the tree and rebuild the widget
+ proc ::tktree::newitem {win item args} {
+ variable cfg
+ if {[string index $item 0] ne "/"} {set item /$item}
+ if {[string index $item end] eq "/"} {
+ set subgroup 1
+ set type subgroups
+ set item [string range $item 0 end-1]
+ set cfg($win,$item:command) [list ::tktree::switchstate $win $item]
+ } {
+ set subgroup 0
+ set type children
+ set cfg($win,$item:command) {}
+ }
+ #Build parent group if needed
+ set group [file dirname $item]
+ if {![info exists cfg($win,$group:open)]} {newitem $win "$group\/"}
+ lappend cfg($win,$group:$type) $item
+ #Configure the new item
+ set cfg($win,$item:group) $subgroup
+ set cfg($win,$item:subgroups) {}
+ set cfg($win,$item:children) {}
+ set cfg($win,$item:sortlist) {}
+ set cfg($win,$item:tags) {}
+ set cfg($win,$item:open) 0
+ set cfg($win,$item:image) {}
+ set cfg($win,$item:textcolor) $cfg($win,textcolor)
+ set cfg($win,$item:font) $cfg($win,font)
+ if {$cfg($win,images)} {set cfg($win,$item:image) [eval list \$::tktree::img$type]}
+ foreach {confitem confval} $args {
+ switch -exact -- $confitem {
+ -textcolor {set cfg($win,$item:textcolor) $confval}
+ -command {set cfg($win,$item:command) $confval}
+ -image {set cfg($win,$item:image) $confval}
+ -font {set cfg($win,$item:font) $confval}
+ }
+ }
+ buildwhenidle $win
+ }
+
+ #### Draw the given layer of the tree on the canvas starting at xposition
+ proc ::tktree::buildlayer {win layer xpos} {
+ variable cfg
+ #Record y positions for vertical line later on
+ set ystart $cfg($win,y); set yend $cfg($win,y)
+ if {$layer eq "/"} {set cfg($win,sortlist) ""}
+ foreach child $cfg($win,$layer:sortlist) {
+ lappend cfg($win,sortlist) $child
+ #Check spacing required for images
+ set imgwidth 0; set imgheight 0
+ if {[string length $cfg($win,$child:image)]} {
+ set imgwidth [expr ([image width $cfg($win,$child:image)] + 2) / 2]
+ set imgheight [expr ([image height $cfg($win,$child:image)] + 2) / 2]
+ }
+ #find X-axis points for image, horiz line, and text
+ if {$imgwidth} {
+ set centerX [expr $imgwidth + $xpos + 7]
+ set rightX [expr $xpos + 7]
+ set textX [expr ($imgwidth * 2) + $xpos + 10]
+ } {
+ set centerX [expr $xpos + 10]
+ set rightX [expr $centerX + 4]
+ set textX [expr $rightX + 1]
+ }
+ #Find the proper amount to increment the y axis
+ set fontheight [lindex [font metrics $cfg($win,$child:font)] 5]
+ set yincr [expr ($fontheight + 1) / 2]
+ if {$imgheight > $yincr} {set yincr $imgheight}
+ incr cfg($win,y) $yincr
+ #Draw the horizonal line
+ $win create line $xpos $cfg($win,y) $rightX $cfg($win,y) -fill $cfg($win,linecolor)
+ set yend $cfg($win,y)
+ #Draw the image, if it exists
+ if {$imgwidth} {
+ set it [$win create image $centerX $cfg($win,y) -image $cfg($win,$child:image)]
+ $win bind $it <1> [list ::tktree::setselection $win $child]
+ }
+ #Draw text and store tags for reference
+ set cfg($win,$child:tag) [$win create text $textX $cfg($win,y) \
+ -text [file tail $child] -font $cfg($win,$child:font) -anchor w -tags x -fill $cfg($win,$child:textcolor)]
+ set cfg($win,tag:$cfg($win,$child:tag)) $child
+ #Command binding
+ $win bind $cfg($win,$child:tag) <1> [list ::tktree::setselection $win $child]
+ $win bind $cfg($win,$child:tag) <Double-1> $cfg($win,$child:command)
+ #next step up on the y axis
+ incr cfg($win,y) $yincr
+ #If its a group, add open-close functionality
+ if {$cfg($win,$child:group)} {
+ if {$cfg($win,$child:open)} {set img collapse} {set img expand}
+ set ocimg [$win create image $xpos [expr $cfg($win,y) - $yincr] -image [eval list \$::tktree::img$img]]
+ $win bind $ocimg <1> [list ::tktree::switchstate $win $child]
+ if {$cfg($win,$child:open)} {buildlayer $win $child $centerX}
+ }
+ }
+ #Vertical line
+ $win lower [$win create line $xpos [expr $ystart - 7] $xpos $yend -fill $cfg($win,linecolor)]
+ }
+
+ #### sort the layer by subgroups then children
+ proc ::tktree::sortlayer {win {layer /}} {
+ variable cfg
+ set cfg($win,$layer:subgroups) [lsort -dictionary $cfg($win,$layer:subgroups)]
+ set cfg($win,$layer:children) [lsort -dictionary $cfg($win,$layer:children)]
+ set cfg($win,$layer:sortlist) [join [list $cfg($win,$layer:subgroups) $cfg($win,$layer:children)]]
+ foreach group $cfg($win,$layer:subgroups) {sortlayer $win $group}
+ }
+
+ #### build the tree at the given path
+ proc ::tktree::buildtree {win} {
+ variable cfg
+ $win delete all
+ sortlayer $win
+ set xpos 5
+ set cfg($win,y) 5
+ #Draw global expand/contract button, if needed
+ if {[string length $cfg($win,/:subgroups)] && $cfg($win,expandall)} {
+ set exp 0
+ foreach subgroup $cfg($win,/:subgroups) {incr exp $cfg($win,$subgroup:open)}
+ if {$exp} {set type collapse} {set type expand}
+ set ocimg [$win create image 1 1 -image [eval list \$::tktree::img$type] -anchor w]
+ $win bind $ocimg <1> [list ::tktree::switchlayer $win [expr ! $exp]]
+ }
+ #Build the layers and set initial selection
+ buildlayer $win / $xpos
+ $win config -scrollregion [$win bbox all]
+ setselection $win $cfg($win,selection)
+ }
+
+ #### internal use - set up a handle to build the tree when everything is idle
+ proc ::tktree::buildwhenidle {win} {
+ catch {after cancel $::tktree::cfg($win,buildHandle)}
+ set ::tktree::cfg($win,buildHandle) [after idle [list ::tktree::buildtree $win]]
+ }
+
+ #### will create a new tree widget at the given path
+ proc ::tktree::treecreate {win args} {
+ variable cfg
+ #Default configuration for new tree
+ set cfg($win,selection) {}
+ set cfg($win,selidx) {}
+ set cfg($win,/:subgroups) {}
+ set cfg($win,/:children) {}
+ set cfg($win,/:open) 1
+ set cfg($win,images) 1
+ set cfg($win,expandall) 1
+ set cfg($win,linecolor) black
+ set cfg($win,textcolor) black
+ set cfg($win,font) {-family Helvetica -size 10}
+ #Parse and setup custom configuration options
+ set canvascfg ""
+ foreach {item val} $args {
+ switch -- $item {
+ -linecolor {set cfg($win,linecolor) $val}
+ -textcolor {set cfg($win,textcolor) $val}
+ -font {set cfg($win,font) $val}
+ -images {set cfg($win,images) $val}
+ -expandall {set cfg($win,expandall) $val}
+ default {lappend canvascfg $item $val}
+ }
+ }
+ #Build the canvas
+ eval {canvas $win -takefocus 1} $canvascfg
+ bind $win <Destroy> [list ::tktree::delitem $win /]
+ bind $win <1> [list focus $win]
+ bind $win <Return> {eval $::tktree::cfg(%W,[::tktree::getselection %W]:command)}
+ bind $win <space> {eval $::tktree::cfg(%W,[::tktree::getselection %W]:command)}
+ bind $win <Up> [list ::tktree::updown $win 0]
+ bind $win <Down> [list ::tktree::updown $win 1]
+ bind $win <Left> [list ::tktree::leftright $win 0]
+ bind $win <Right> [list ::tktree::leftright $win 1]
+
+ #Build the tree when idle
+ buildwhenidle $win
+ }
+ }
+
diff --git a/ext/tk/sample/ttk_wrapper.rb b/ext/tk/sample/ttk_wrapper.rb
new file mode 100644
index 0000000000..1580668994
--- /dev/null
+++ b/ext/tk/sample/ttk_wrapper.rb
@@ -0,0 +1,154 @@
+#!/usr/bin/env ruby
+#
+# ttk_wrapper.rb -- use Ttk widgets as default on old Ruby/Tk scripts
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+version = '0.1.3'
+#
+##########################################################################
+# parse commandline arguments
+##########################################################################
+require 'optparse'
+opt = OptionParser.new("Usage: #{$0} [options] rubytk_script" << "\n " <<
+ "Ruby/Tk script wrapper. Use Ttk widgets as default.")
+opt.version = version
+
+OPTS = {}
+OPTS[:themedir] = []
+OPTS[:rb_theme] = []
+OPTS[:theme] = 'default'
+
+opt.on('-l', '--list', 'list available theme names'){|v| OPTS[:list] = true}
+opt.on('-t', '--theme theme', 'theme name'){|v| OPTS[:theme] = v}
+opt.on('-d', '--themedir themes_dir', 'directory of theme definitions'){|v|
+ OPTS[:themedir] << v
+}
+opt.on('-r', '--rubytheme rb_theme', 'theme definition file (ruby script)'){|v|
+ OPTS[:rb_theme] << v
+}
+opt.on('-v', '--verbose', 'print verbose messages'){|v| OPTS[:verbose] = true}
+
+opt.parse!(ARGV)
+
+
+##########################################################################
+# load Ttk (Tile) extension
+##########################################################################
+require 'tk'
+
+begin
+ require 'tkextlib/tile'
+ Tk.default_widget_set = :Ttk
+rescue LoadError
+ if OPTS[:verbose]
+ print "warning: fail to load 'Ttk' extension. use standard widgets.\n"
+ end
+end
+
+if OPTS[:verbose]
+ print "current default widget set is '#{Tk.default_widget_set}'\n"
+end
+
+
+##########################################################################
+# define Tcl/Tk procedures for compatibility.
+# those are required when want to use themes included
+# in "sample/tkextlib/tile/demo.rb".
+##########################################################################
+Tk::Tile.__define_LoadImages_proc_for_compatibility__!
+Tk::Tile::Style.__define_wrapper_proc_for_compatibility__!
+
+
+##########################################################################
+# use themes defined on the demo of Ttk (Tile) extension
+##########################################################################
+demodir = File.dirname(__FILE__)
+demo_themesdir = File.expand_path(File.join(demodir, 'tkextlib', 'tile', 'themes'))
+
+Tk::AUTO_PATH.lappend(*OPTS[:themedir]) unless OPTS[:themedir].empty?
+Tk::AUTO_PATH.lappend('.', demodir, demo_themesdir)
+
+OPTS[:themedir] << demo_themesdir
+print "theme-dirs: #{OPTS[:themedir].inspect}\n" if OPTS[:verbose]
+
+OPTS[:themedir].each{|themesdir|
+ if File.directory?(themesdir)
+ Dir.foreach(themesdir){|name|
+ next if name == '.' || name == '..'
+ path = File.join(themesdir, name)
+ Tk::AUTO_PATH.lappend(path) if File.directory?(path)
+ }
+ end
+}
+
+# This forces an update of the available packages list. It's required
+# for package names to find the themes in demos/themes/*.tcl
+Tk.ip_eval("#{TkPackage.unknown_proc} Tcl #{TkPackage.provide('Tcl')}")
+
+# load themes written in Ruby.
+themes_by_ruby = [File.join(demo_themesdir, 'kroc.rb')]
+themes_by_ruby.concat OPTS[:rb_theme]
+print "ruby-themes: #{themes_by_ruby.inspect}\n" if OPTS[:verbose]
+
+themes_by_ruby.each{|f|
+ begin
+ load(f, true)
+ rescue LoadError
+ print "fail to load \"#{f}\"\n" if OPTS[:verbose]
+ end
+}
+
+
+##########################################################################
+# ignore unsupported options of Ttk widgets
+##########################################################################
+TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__! true
+TkItemConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__! true
+
+
+##########################################################################
+# set theme of widget style
+##########################################################################
+if OPTS[:list] || OPTS[:verbose]
+ print "supported theme names: #{Tk::Tile.themes.inspect}\n"
+ exit if OPTS[:list] && ARGV.empty?
+end
+print "use theme: \"#{OPTS[:theme]}\"\n" if OPTS[:theme] && OPTS[:verbose]
+#setTheme(OPTS[:theme]) if OPTS[:theme]
+Tk::Tile.set_theme(OPTS[:theme]) if OPTS[:theme]
+
+
+##########################################################################
+# replace $0 and $RPAGRAM_NAME
+##########################################################################
+# When the expand_path of the target script is long, ruby sometimes
+# fails to set the path to $0 (the path string is trimmed).
+# The following replaces $0 and $PROGNAME to avoid such trouble.
+progname_obj = $0.dup
+$program_name = progname_obj
+
+alias $REAL_PROGRAM_NAME $0
+alias $PROGRAM_NAME $program_name
+alias $0 $program_name
+
+trace_var(:$program_name){|val|
+ unless progname_obj.object_id == val.object_id
+ progname_obj.replace(val.to_s)
+ $program_name = progname_obj
+ end
+}
+
+
+##########################################################################
+# load script
+##########################################################################
+if (path = ARGV.shift) && (script = File.expand_path(path))
+ print "load script \"#{script}\"\n" if OPTS[:verbose]
+ $0 = script
+ load(script)
+else
+ print "Error: no script is given.\n"
+ print opt.help
+ exit(1)
+end
diff --git a/ext/tk/stubs.c b/ext/tk/stubs.c
new file mode 100644
index 0000000000..6d3b330f0e
--- /dev/null
+++ b/ext/tk/stubs.c
@@ -0,0 +1,564 @@
+/************************************************
+
+ stubs.c - Tcl/Tk stubs support
+
+************************************************/
+
+#include "ruby.h"
+#include "stubs.h"
+#include <tcl.h>
+#include <tk.h>
+
+/*------------------------------*/
+
+#ifdef __MACOS__
+# include <tkMac.h>
+# include <Quickdraw.h>
+
+static int call_macinit = 0;
+
+static void
+_macinit()
+{
+ if (!call_macinit) {
+ tcl_macQdPtr = &qd; /* setup QuickDraw globals */
+ Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
+ call_macinit = 1;
+ }
+}
+#endif
+
+/*------------------------------*/
+
+static int nativethread_checked = 0;
+
+static void
+_nativethread_consistency_check(ip)
+ Tcl_Interp *ip;
+{
+ if (nativethread_checked || ip == (Tcl_Interp *)NULL) {
+ return;
+ }
+
+ /* If the variable "tcl_platform(threaded)" exists,
+ then the Tcl interpreter was compiled with threads enabled. */
+ if (Tcl_GetVar2(ip, "tcl_platform", "threaded", TCL_GLOBAL_ONLY) != (char*)NULL) {
+#ifdef HAVE_NATIVETHREAD
+ /* consistent */
+#else
+ rb_warn("Inconsistency. Loaded Tcl/Tk libraries are enabled nativethread-support. But `tcltklib' is not. The inconsistency causes SEGV or other troubles frequently.");
+#endif
+ } else {
+#ifdef HAVE_NATIVETHREAD
+ rb_warning("Inconsistency.`tcltklib' is enabled nativethread-support. But loaded Tcl/Tk libraries are not. (Probably, the inconsistency doesn't cause any troubles.)");
+#else
+ /* consistent */
+#endif
+ }
+
+ Tcl_ResetResult(ip);
+
+ nativethread_checked = 1;
+}
+
+/*------------------------------*/
+
+#if defined USE_TCL_STUBS && defined USE_TK_STUBS
+
+#if defined _WIN32 || defined __CYGWIN__
+# include "util.h"
+# include <windows.h>
+ typedef HINSTANCE DL_HANDLE;
+# define DL_OPEN LoadLibrary
+# define DL_SYM GetProcAddress
+# define TCL_INDEX 4
+# define TK_INDEX 3
+# define TCL_NAME "tcl89%s"
+# define TK_NAME "tk89%s"
+# undef DLEXT
+# define DLEXT ".dll"
+#elif defined HAVE_DLOPEN
+# include <dlfcn.h>
+ typedef void *DL_HANDLE;
+# define DL_OPEN(file) dlopen(file, RTLD_LAZY|RTLD_GLOBAL)
+# define DL_SYM dlsym
+# define TCL_INDEX 8
+# define TK_INDEX 7
+# define TCL_NAME "libtcl8.9%s"
+# define TK_NAME "libtk8.9%s"
+#endif
+
+static DL_HANDLE tcl_dll = (DL_HANDLE)0;
+static DL_HANDLE tk_dll = (DL_HANDLE)0;
+
+int
+#ifdef RUBY_VM
+ruby_open_tcl_dll(char *appname)
+#else
+ruby_open_tcl_dll(appname)
+ char *appname;
+#endif
+{
+ void (*p_Tcl_FindExecutable)(const char *);
+ int n;
+ char *ruby_tcl_dll = 0;
+ char tcl_name[20];
+
+ if (tcl_dll) return TCLTK_STUBS_OK;
+
+ ruby_tcl_dll = getenv("RUBY_TCL_DLL");
+#if defined _WIN32
+ if (ruby_tcl_dll) ruby_tcl_dll = ruby_strdup(ruby_tcl_dll);
+#endif
+ if (ruby_tcl_dll) {
+ tcl_dll = (DL_HANDLE)DL_OPEN(ruby_tcl_dll);
+ } else {
+ snprintf(tcl_name, sizeof tcl_name, TCL_NAME, DLEXT);
+ /* examine from 8.9 to 8.1 */
+ for (n = '9'; n > '0'; n--) {
+ tcl_name[TCL_INDEX] = n;
+ tcl_dll = (DL_HANDLE)DL_OPEN(tcl_name);
+ if (tcl_dll)
+ break;
+ }
+ }
+
+#if defined _WIN32
+ if (ruby_tcl_dll) ruby_xfree(ruby_tcl_dll);
+#endif
+
+ if (!tcl_dll)
+ return NO_TCL_DLL;
+
+ p_Tcl_FindExecutable = (void (*)(const char *))DL_SYM(tcl_dll, "Tcl_FindExecutable");
+ if (!p_Tcl_FindExecutable)
+ return NO_FindExecutable;
+
+ if (appname) {
+ p_Tcl_FindExecutable(appname);
+ } else {
+ p_Tcl_FindExecutable("ruby");
+ }
+
+ return TCLTK_STUBS_OK;
+}
+
+int
+ruby_open_tk_dll()
+{
+ int n;
+ char *ruby_tk_dll = 0;
+ char tk_name[20];
+
+ if (!tcl_dll) {
+ /* int ret = ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */
+ int ret = ruby_open_tcl_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0);
+ if (ret != TCLTK_STUBS_OK) return ret;
+ }
+
+ if (tk_dll) return TCLTK_STUBS_OK;
+
+ ruby_tk_dll = getenv("RUBY_TK_DLL");
+ if (ruby_tk_dll) {
+ tk_dll = (DL_HANDLE)DL_OPEN(ruby_tk_dll);
+ } else {
+ snprintf(tk_name, sizeof tk_name, TK_NAME, DLEXT);
+ /* examine from 8.9 to 8.1 */
+ for (n = '9'; n > '0'; n--) {
+ tk_name[TK_INDEX] = n;
+ tk_dll = (DL_HANDLE)DL_OPEN(tk_name);
+ if (tk_dll)
+ break;
+ }
+ }
+
+ if (!tk_dll)
+ return NO_TK_DLL;
+
+ return TCLTK_STUBS_OK;
+}
+
+int
+#ifdef RUBY_VM
+ruby_open_tcltk_dll(char *appname)
+#else
+ruby_open_tcltk_dll(appname)
+ char *appname;
+#endif
+{
+ return( ruby_open_tcl_dll(appname) || ruby_open_tk_dll() );
+}
+
+int
+tcl_stubs_init_p()
+{
+ return(tclStubsPtr != (TclStubs*)NULL);
+}
+
+int
+tk_stubs_init_p()
+{
+ return(tkStubsPtr != (TkStubs*)NULL);
+}
+
+
+Tcl_Interp *
+#ifdef RUBY_VM
+ruby_tcl_create_ip_and_stubs_init(int *st)
+#else
+ruby_tcl_create_ip_and_stubs_init(st)
+ int *st;
+#endif
+{
+ Tcl_Interp *tcl_ip;
+
+ if (st) *st = 0;
+
+ if (tcl_stubs_init_p()) {
+ tcl_ip = Tcl_CreateInterp();
+
+ if (!tcl_ip) {
+ if (st) *st = FAIL_CreateInterp;
+ return (Tcl_Interp*)NULL;
+ }
+
+ _nativethread_consistency_check(tcl_ip);
+
+ return tcl_ip;
+
+ } else {
+ Tcl_Interp *(*p_Tcl_CreateInterp)();
+ Tcl_Interp *(*p_Tcl_DeleteInterp)();
+
+ if (!tcl_dll) {
+ /* int ret = ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */
+ int ret = ruby_open_tcl_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0);
+
+ if (ret != TCLTK_STUBS_OK) {
+ if (st) *st = ret;
+ return (Tcl_Interp*)NULL;
+ }
+ }
+
+ p_Tcl_CreateInterp
+ = (Tcl_Interp *(*)())DL_SYM(tcl_dll, "Tcl_CreateInterp");
+ if (!p_Tcl_CreateInterp) {
+ if (st) *st = NO_CreateInterp;
+ return (Tcl_Interp*)NULL;
+ }
+
+ p_Tcl_DeleteInterp
+ = (Tcl_Interp *(*)())DL_SYM(tcl_dll, "Tcl_DeleteInterp");
+ if (!p_Tcl_DeleteInterp) {
+ if (st) *st = NO_DeleteInterp;
+ return (Tcl_Interp*)NULL;
+ }
+
+ tcl_ip = (*p_Tcl_CreateInterp)();
+ if (!tcl_ip) {
+ if (st) *st = FAIL_CreateInterp;
+ return (Tcl_Interp*)NULL;
+ }
+
+ if (!Tcl_InitStubs(tcl_ip, "8.1", 0)) {
+ if (st) *st = FAIL_Tcl_InitStubs;
+ (*p_Tcl_DeleteInterp)(tcl_ip);
+ return (Tcl_Interp*)NULL;
+ }
+
+ _nativethread_consistency_check(tcl_ip);
+
+ return tcl_ip;
+ }
+}
+
+int
+ruby_tcl_stubs_init()
+{
+ int st;
+ Tcl_Interp *tcl_ip;
+
+ if (!tcl_stubs_init_p()) {
+ tcl_ip = ruby_tcl_create_ip_and_stubs_init(&st);
+
+ if (!tcl_ip) return st;
+
+ Tcl_DeleteInterp(tcl_ip);
+ }
+
+ return TCLTK_STUBS_OK;
+}
+
+int
+#ifdef RUBY_VM
+ruby_tk_stubs_init(Tcl_Interp *tcl_ip)
+#else
+ruby_tk_stubs_init(tcl_ip)
+ Tcl_Interp *tcl_ip;
+#endif
+{
+ Tcl_ResetResult(tcl_ip);
+
+ if (tk_stubs_init_p()) {
+ if (Tk_Init(tcl_ip) == TCL_ERROR) {
+ return FAIL_Tk_Init;
+ }
+ } else {
+ int (*p_Tk_Init)(Tcl_Interp *);
+
+ if (!tk_dll) {
+ int ret = ruby_open_tk_dll();
+ if (ret != TCLTK_STUBS_OK) return ret;
+ }
+
+ p_Tk_Init = (int (*)(Tcl_Interp *))DL_SYM(tk_dll, "Tk_Init");
+ if (!p_Tk_Init)
+ return NO_Tk_Init;
+
+ if ((*p_Tk_Init)(tcl_ip) == TCL_ERROR)
+ return FAIL_Tk_Init;
+
+ if (!Tk_InitStubs(tcl_ip, "8.1", 0))
+ return FAIL_Tk_InitStubs;
+
+#ifdef __MACOS__
+ _macinit();
+#endif
+ }
+
+ return TCLTK_STUBS_OK;
+}
+
+int
+#ifdef RUBY_VM
+ruby_tk_stubs_safeinit(Tcl_Interp *tcl_ip)
+#else
+ruby_tk_stubs_safeinit(tcl_ip)
+ Tcl_Interp *tcl_ip;
+#endif
+{
+ Tcl_ResetResult(tcl_ip);
+
+ if (tk_stubs_init_p()) {
+ if (Tk_SafeInit(tcl_ip) == TCL_ERROR)
+ return FAIL_Tk_Init;
+ } else {
+ int (*p_Tk_SafeInit)(Tcl_Interp *);
+
+ if (!tk_dll) {
+ int ret = ruby_open_tk_dll();
+ if (ret != TCLTK_STUBS_OK) return ret;
+ }
+
+ p_Tk_SafeInit = (int (*)(Tcl_Interp *))DL_SYM(tk_dll, "Tk_SafeInit");
+ if (!p_Tk_SafeInit)
+ return NO_Tk_Init;
+
+ if ((*p_Tk_SafeInit)(tcl_ip) == TCL_ERROR)
+ return FAIL_Tk_Init;
+
+ if (!Tk_InitStubs(tcl_ip, "8.1", 0))
+ return FAIL_Tk_InitStubs;
+
+#ifdef __MACOS__
+ _macinit();
+#endif
+ }
+
+ return TCLTK_STUBS_OK;
+}
+
+int
+ruby_tcltk_stubs()
+{
+ int st;
+ Tcl_Interp *tcl_ip;
+
+ /* st = ruby_open_tcltk_dll(RSTRING_PTR(rb_argv0)); */
+ st = ruby_open_tcltk_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0);
+ switch(st) {
+ case NO_FindExecutable:
+ return -7;
+ case NO_TCL_DLL:
+ case NO_TK_DLL:
+ return -1;
+ }
+
+ tcl_ip = ruby_tcl_create_ip_and_stubs_init(&st);
+ if (!tcl_ip) {
+ switch(st) {
+ case NO_CreateInterp:
+ case NO_DeleteInterp:
+ return -2;
+ case FAIL_CreateInterp:
+ return -3;
+ case FAIL_Tcl_InitStubs:
+ return -5;
+ }
+ }
+
+ st = ruby_tk_stubs_init(tcl_ip);
+ switch(st) {
+ case NO_Tk_Init:
+ Tcl_DeleteInterp(tcl_ip);
+ return -4;
+ case FAIL_Tk_Init:
+ case FAIL_Tk_InitStubs:
+ Tcl_DeleteInterp(tcl_ip);
+ return -6;
+ }
+
+ Tcl_DeleteInterp(tcl_ip);
+
+ return 0;
+}
+
+/*###################################################*/
+#else /* ! USE_TCL_STUBS || ! USE_TK_STUBS) */
+/*###################################################*/
+
+static int open_tcl_dll = 0;
+static int call_tk_stubs_init = 0;
+
+int
+#ifdef RUBY_VM
+ruby_open_tcl_dll(char *appname)
+#else
+ruby_open_tcl_dll(appname)
+ char *appname;
+#endif
+{
+ if (appname) {
+ Tcl_FindExecutable(appname);
+ } else {
+ Tcl_FindExecutable("ruby");
+ }
+ open_tcl_dll = 1;
+
+ return TCLTK_STUBS_OK;
+}
+
+int
+ruby_open_tk_dll()
+{
+ if (!open_tcl_dll) {
+ /* ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */
+ ruby_open_tcl_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0);
+ }
+
+ return TCLTK_STUBS_OK;
+}
+
+int
+#ifdef RUBY_VM
+ruby_open_tcltk_dll(char *appname)
+#else
+ruby_open_tcltk_dll(appname)
+ char *appname;
+#endif
+{
+ return( ruby_open_tcl_dll(appname) || ruby_open_tk_dll() );
+}
+
+int
+tcl_stubs_init_p()
+{
+ return 1;
+}
+
+int
+tk_stubs_init_p()
+{
+ return call_tk_stubs_init;
+}
+
+Tcl_Interp *
+#ifdef RUBY_VM
+ruby_tcl_create_ip_and_stubs_init(int *st)
+#else
+ruby_tcl_create_ip_and_stubs_init(st)
+ int *st;
+#endif
+{
+ Tcl_Interp *tcl_ip;
+
+ if (!open_tcl_dll) {
+ /* ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */
+ ruby_open_tcl_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0);
+ }
+
+ if (st) *st = 0;
+ tcl_ip = Tcl_CreateInterp();
+ if (!tcl_ip) {
+ if (st) *st = FAIL_CreateInterp;
+ return (Tcl_Interp*)NULL;
+ }
+
+ _nativethread_consistency_check(tcl_ip);
+
+ return tcl_ip;
+}
+
+int
+ruby_tcl_stubs_init()
+{
+ return TCLTK_STUBS_OK;
+}
+
+int
+#ifdef RUBY_VM
+ruby_tk_stubs_init(Tcl_Interp *tcl_ip)
+#else
+ruby_tk_stubs_init(tcl_ip)
+ Tcl_Interp *tcl_ip;
+#endif
+{
+ if (Tk_Init(tcl_ip) == TCL_ERROR)
+ return FAIL_Tk_Init;
+
+ if (!call_tk_stubs_init) {
+#ifdef __MACOS__
+ _macinit();
+#endif
+ call_tk_stubs_init = 1;
+ }
+
+ return TCLTK_STUBS_OK;
+}
+
+int
+#ifdef RUBY_VM
+ruby_tk_stubs_safeinit(Tcl_Interp *tcl_ip)
+#else
+ruby_tk_stubs_safeinit(tcl_ip)
+ Tcl_Interp *tcl_ip;
+#endif
+{
+#if TCL_MAJOR_VERSION >= 8
+ if (Tk_SafeInit(tcl_ip) == TCL_ERROR)
+ return FAIL_Tk_Init;
+
+ if (!call_tk_stubs_init) {
+#ifdef __MACOS__
+ _macinit();
+#endif
+ call_tk_stubs_init = 1;
+ }
+
+ return TCLTK_STUBS_OK;
+
+#else /* TCL_MAJOR_VERSION < 8 */
+
+ return FAIL_Tk_Init;
+#endif
+}
+
+int
+ruby_tcltk_stubs()
+{
+ /* Tcl_FindExecutable(RSTRING_PTR(rb_argv0)); */
+ Tcl_FindExecutable(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0);
+ return 0;
+}
+
+#endif
diff --git a/ext/tk/stubs.h b/ext/tk/stubs.h
new file mode 100644
index 0000000000..7c913fb393
--- /dev/null
+++ b/ext/tk/stubs.h
@@ -0,0 +1,33 @@
+#include <tcl.h>
+
+extern int ruby_open_tcl_dll(char *);
+extern int ruby_open_tk_dll();
+extern int ruby_open_tcltk_dll(char *);
+extern int tcl_stubs_init_p();
+extern int tk_stubs_init_p();
+extern Tcl_Interp *ruby_tcl_create_ip_and_stubs_init(int*);
+extern int ruby_tcl_stubs_init();
+extern int ruby_tk_stubs_init(Tcl_Interp*);
+extern int ruby_tk_stubs_safeinit(Tcl_Interp*);
+extern int ruby_tcltk_stubs();
+
+/* no error */
+#define TCLTK_STUBS_OK (0)
+
+/* return value of ruby_open_tcl_dll() */
+#define NO_TCL_DLL (1)
+#define NO_FindExecutable (2)
+
+/* return value of ruby_open_tk_dll() */
+#define NO_TK_DLL (-1)
+
+/* status value of ruby_tcl_create_ip_and_stubs_init(st) */
+#define NO_CreateInterp (3)
+#define NO_DeleteInterp (4)
+#define FAIL_CreateInterp (5)
+#define FAIL_Tcl_InitStubs (6)
+
+/* return value of ruby_tk_stubs_init() */
+#define NO_Tk_Init (7)
+#define FAIL_Tk_Init (8)
+#define FAIL_Tk_InitStubs (9)
diff --git a/ext/tk/tcltklib.c b/ext/tk/tcltklib.c
new file mode 100644
index 0000000000..8701cfef27
--- /dev/null
+++ b/ext/tk/tcltklib.c
@@ -0,0 +1,10258 @@
+/*
+ * tcltklib.c
+ * Aug. 27, 1997 Y. Shigehiro
+ * Oct. 24, 1997 Y. Matsumoto
+ */
+
+#define TCLTKLIB_RELEASE_DATE "2008-05-23"
+
+#include "ruby.h"
+
+#ifdef RUBY_VM
+/* #include "ruby/ruby.h" */
+#include "ruby/signal.h"
+#include "ruby/encoding.h"
+#else
+/* #include "ruby.h" */
+#include "rubysig.h"
+#include "version.h"
+#endif
+
+#undef EXTERN /* avoid conflict with tcl.h of tcl8.2 or before */
+#include <stdio.h>
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
+#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
+#include <string.h>
+#include <tcl.h>
+#include <tk.h>
+
+#include "stubs.h"
+
+#ifndef TCL_ALPHA_RELEASE
+#define TCL_ALPHA_RELEASE 0
+#define TCL_BETA_RELEASE 1
+#define TCL_FINAL_RELEASE 2
+#endif
+
+static struct {
+ int major;
+ int minor;
+ int patchlevel;
+ int type;
+} tcltk_version = {0, 0, 0, 0};
+
+static void
+set_tcltk_version()
+{
+ if (tcltk_version.major) return;
+
+ Tcl_GetVersion(&(tcltk_version.major),
+ &(tcltk_version.minor),
+ &(tcltk_version.patchlevel),
+ &(tcltk_version.type));
+}
+
+#if TCL_MAJOR_VERSION >= 8
+# ifndef CONST84
+# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 4 /* Tcl8.0.x -- 8.4b1 */
+# define CONST84
+# else /* unknown (maybe TCL_VERSION >= 8.5) */
+# ifdef CONST
+# define CONST84 CONST
+# else
+# define CONST84
+# endif
+# endif
+# endif
+#else /* TCL_MAJOR_VERSION < 8 */
+# ifdef CONST
+# define CONST84 CONST
+# else
+# define CONST
+# define CONST84
+# endif
+#endif
+
+/* copied from eval.c */
+#define TAG_RETURN 0x1
+#define TAG_BREAK 0x2
+#define TAG_NEXT 0x3
+#define TAG_RETRY 0x4
+#define TAG_REDO 0x5
+#define TAG_RAISE 0x6
+#define TAG_THROW 0x7
+#define TAG_FATAL 0x8
+
+/* for ruby_debug */
+#define DUMP1(ARG1) if (ruby_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1); fflush(stderr); }
+#define DUMP2(ARG1, ARG2) if (ruby_debug) { fprintf(stderr, "tcltklib: ");\
+fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); fflush(stderr); }
+#define DUMP3(ARG1, ARG2, ARG3) if (ruby_debug) { fprintf(stderr, "tcltklib: ");\
+fprintf(stderr, ARG1, ARG2, ARG3); fprintf(stderr, "\n"); fflush(stderr); }
+/*
+#define DUMP1(ARG1)
+#define DUMP2(ARG1, ARG2)
+#define DUMP3(ARG1, ARG2, ARG3)
+*/
+
+/* release date */
+const char tcltklib_release_date[] = TCLTKLIB_RELEASE_DATE;
+
+/* finalize_proc_name */
+static char *finalize_hook_name = "INTERP_FINALIZE_HOOK";
+
+static void ip_finalize _((Tcl_Interp*));
+
+static int at_exit = 0;
+
+#ifdef RUBY_VM
+static VALUE cRubyEncoding;
+
+/* encoding */
+static int ENCODING_INDEX_UTF8;
+static int ENCODING_INDEX_BINARY;
+#endif
+static VALUE ENCODING_NAME_UTF8;
+static VALUE ENCODING_NAME_BINARY;
+
+static VALUE create_dummy_encoding_for_tk_core _((VALUE, VALUE, VALUE));
+static VALUE create_dummy_encoding_for_tk _((VALUE, VALUE));
+static int update_encoding_table _((VALUE, VALUE, VALUE));
+static VALUE encoding_table_get_name_core _((VALUE, VALUE, VALUE));
+static VALUE encoding_table_get_obj_core _((VALUE, VALUE, VALUE));
+static VALUE encoding_table_get_name _((VALUE, VALUE));
+static VALUE encoding_table_get_obj _((VALUE, VALUE));
+static VALUE create_encoding_table _((VALUE));
+static VALUE ip_get_encoding_table _((VALUE));
+
+
+/* for callback break & continue */
+static VALUE eTkCallbackReturn;
+static VALUE eTkCallbackBreak;
+static VALUE eTkCallbackContinue;
+
+static VALUE eLocalJumpError;
+
+static VALUE eTkLocalJumpError;
+static VALUE eTkCallbackRetry;
+static VALUE eTkCallbackRedo;
+static VALUE eTkCallbackThrow;
+
+static VALUE tcltkip_class;
+
+static ID ID_at_enc;
+static ID ID_at_interp;
+
+static ID ID_encoding_name;
+static ID ID_encoding_table;
+
+static ID ID_stop_p;
+static ID ID_alive_p;
+static ID ID_kill;
+static ID ID_join;
+static ID ID_value;
+
+static ID ID_call;
+static ID ID_backtrace;
+static ID ID_message;
+
+static ID ID_at_reason;
+static ID ID_return;
+static ID ID_break;
+static ID ID_next;
+
+static ID ID_to_s;
+static ID ID_inspect;
+
+static VALUE ip_invoke_real _((int, VALUE*, VALUE));
+static VALUE ip_invoke _((int, VALUE*, VALUE));
+static VALUE ip_invoke_with_position _((int, VALUE*, VALUE, Tcl_QueuePosition));
+static VALUE tk_funcall _((VALUE(), int, VALUE*, VALUE));
+
+/* Tcl's object type */
+#if TCL_MAJOR_VERSION >= 8
+static char *Tcl_ObjTypeName_ByteArray = "bytearray";
+static Tcl_ObjType *Tcl_ObjType_ByteArray;
+
+static char *Tcl_ObjTypeName_String = "string";
+static Tcl_ObjType *Tcl_ObjType_String;
+
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1)
+#define IS_TCL_BYTEARRAY(obj) ((obj)->typePtr == Tcl_ObjType_ByteArray)
+#define IS_TCL_STRING(obj) ((obj)->typePtr == Tcl_ObjType_String)
+#define IS_TCL_VALID_STRING(obj) ((obj)->bytes != (char*)NULL)
+#endif
+#endif
+
+#ifndef HAVE_RB_HASH_LOOKUP
+#define rb_hash_lookup rb_hash_aref
+#endif
+
+/* safe Tcl_Eval and Tcl_GlobalEval */
+static int
+#ifdef RUBY_VM
+tcl_eval(Tcl_Interp *interp, const char *cmd)
+#else
+tcl_eval(interp, cmd)
+ Tcl_Interp *interp;
+ const char *cmd; /* don't have to be writable */
+#endif
+{
+ char *buf = strdup(cmd);
+ int ret;
+
+ Tcl_AllowExceptions(interp);
+ ret = Tcl_Eval(interp, buf);
+ free(buf);
+ return ret;
+}
+
+#undef Tcl_Eval
+#define Tcl_Eval tcl_eval
+
+static int
+#ifdef RUBY_VM
+tcl_global_eval(Tcl_Interp *interp, const char *cmd)
+#else
+tcl_global_eval(interp, cmd)
+ Tcl_Interp *interp;
+ const char *cmd; /* don't have to be writable */
+#endif
+{
+ char *buf = strdup(cmd);
+ int ret;
+
+ Tcl_AllowExceptions(interp);
+ ret = Tcl_GlobalEval(interp, buf);
+ free(buf);
+ return ret;
+}
+
+#undef Tcl_GlobalEval
+#define Tcl_GlobalEval tcl_global_eval
+
+/* Tcl_{Incr|Decr}RefCount for tcl7.x or earlier */
+#if TCL_MAJOR_VERSION < 8
+#define Tcl_IncrRefCount(obj) (1)
+#define Tcl_DecrRefCount(obj) (1)
+#endif
+
+/* Tcl_GetStringResult for tcl7.x or earlier */
+#if TCL_MAJOR_VERSION < 8
+#define Tcl_GetStringResult(interp) ((interp)->result)
+#endif
+
+/* Tcl_[GS]etVar2Ex for tcl8.0 */
+#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
+static Tcl_Obj *
+Tcl_GetVar2Ex(interp, name1, name2, flags)
+ Tcl_Interp *interp;
+ CONST char *name1;
+ CONST char *name2;
+ int flags;
+{
+ Tcl_Obj *nameObj1, *nameObj2 = NULL, *retObj;
+
+ nameObj1 = Tcl_NewStringObj((char*)name1, -1);
+ Tcl_IncrRefCount(nameObj1);
+
+ if (name2) {
+ nameObj2 = Tcl_NewStringObj((char*)name2, -1);
+ Tcl_IncrRefCount(nameObj2);
+ }
+
+ retObj = Tcl_ObjGetVar2(interp, nameObj1, nameObj2, flags);
+
+ if (name2) {
+ Tcl_DecrRefCount(nameObj2);
+ }
+
+ Tcl_DecrRefCount(nameObj1);
+
+ return retObj;
+}
+
+static Tcl_Obj *
+Tcl_SetVar2Ex(interp, name1, name2, newValObj, flags)
+ Tcl_Interp *interp;
+ CONST char *name1;
+ CONST char *name2;
+ Tcl_Obj *newValObj;
+ int flags;
+{
+ Tcl_Obj *nameObj1, *nameObj2 = NULL, *retObj;
+
+ nameObj1 = Tcl_NewStringObj((char*)name1, -1);
+ Tcl_IncrRefCount(nameObj1);
+
+ if (name2) {
+ nameObj2 = Tcl_NewStringObj((char*)name2, -1);
+ Tcl_IncrRefCount(nameObj2);
+ }
+
+ retObj = Tcl_ObjSetVar2(interp, nameObj1, nameObj2, newValObj, flags);
+
+ if (name2) {
+ Tcl_DecrRefCount(nameObj2);
+ }
+
+ Tcl_DecrRefCount(nameObj1);
+
+ return retObj;
+}
+#endif
+
+/* from tkAppInit.c */
+
+#if TCL_MAJOR_VERSION < 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 4)
+# if !defined __MINGW32__ && !defined __BORLANDC__
+/*
+ * The following variable is a special hack that is needed in order for
+ * Sun shared libraries to be used for Tcl.
+ */
+
+extern int matherr();
+int *tclDummyMathPtr = (int *) matherr;
+# endif
+#endif
+
+/*---- module TclTkLib ----*/
+
+struct invoke_queue {
+ Tcl_Event ev;
+ int argc;
+#if TCL_MAJOR_VERSION >= 8
+ Tcl_Obj **argv;
+#else /* TCL_MAJOR_VERSION < 8 */
+ char **argv;
+#endif
+ VALUE interp;
+ int *done;
+ int safe_level;
+ VALUE result;
+ VALUE thread;
+};
+
+struct eval_queue {
+ Tcl_Event ev;
+ char *str;
+ int len;
+ VALUE interp;
+ int *done;
+ int safe_level;
+ VALUE result;
+ VALUE thread;
+};
+
+struct call_queue {
+ Tcl_Event ev;
+ VALUE (*func)();
+ int argc;
+ VALUE *argv;
+ VALUE interp;
+ int *done;
+ int safe_level;
+ VALUE result;
+ VALUE thread;
+};
+
+void
+invoke_queue_mark(struct invoke_queue *q)
+{
+ rb_gc_mark(q->interp);
+ rb_gc_mark(q->result);
+ rb_gc_mark(q->thread);
+}
+
+void
+eval_queue_mark(struct eval_queue *q)
+{
+ rb_gc_mark(q->interp);
+ rb_gc_mark(q->result);
+ rb_gc_mark(q->thread);
+}
+
+void
+call_queue_mark(struct call_queue *q)
+{
+ int i;
+
+ for(i = 0; i < q->argc; i++) {
+ rb_gc_mark(q->argv[i]);
+ }
+
+ rb_gc_mark(q->interp);
+ rb_gc_mark(q->result);
+ rb_gc_mark(q->thread);
+}
+
+
+static VALUE eventloop_thread;
+#ifdef RUBY_VM
+Tcl_ThreadId tk_eventloop_thread_id; /* native thread ID of Tcl interpreter */
+#endif
+static VALUE eventloop_stack;
+static int window_event_mode = ( ~ TCL_IDLE_EVENTS | TCL_WINDOW_EVENTS );
+
+static VALUE watchdog_thread;
+
+Tcl_Interp *current_interp;
+
+/* thread control strategy */
+/* multi-tk works with the following settings only ???
+ : CONTROL_BY_STATUS_OF_RB_THREAD_WAITING_FOR_VALUE 1
+ : USE_TOGGLE_WINDOW_MODE_FOR_IDLE 0
+ : DO_THREAD_SCHEDULE_AT_CALLBACK_DONE 0
+*/
+#define CONTROL_BY_STATUS_OF_RB_THREAD_WAITING_FOR_VALUE 1
+#define USE_TOGGLE_WINDOW_MODE_FOR_IDLE 0
+#define DO_THREAD_SCHEDULE_AT_CALLBACK_DONE 0
+
+#if CONTROL_BY_STATUS_OF_RB_THREAD_WAITING_FOR_VALUE
+static int have_rb_thread_waiting_for_value = 0;
+#endif
+
+/*
+ * 'event_loop_max' is a maximum events which the eventloop processes in one
+ * term of thread scheduling. 'no_event_tick' is the count-up value when
+ * there are no event for processing.
+ * 'timer_tick' is a limit of one term of thread scheduling.
+ * If 'timer_tick' == 0, then not use the timer for thread scheduling.
+ */
+#ifdef RUBY_VM
+#define DEFAULT_EVENT_LOOP_MAX 800/*counts*/
+#define DEFAULT_NO_EVENT_TICK 10/*counts*/
+#define DEFAULT_NO_EVENT_WAIT 10/*milliseconds ( 1 -- 999 ) */
+#define WATCHDOG_INTERVAL 10/*milliseconds ( 1 -- 999 ) */
+#define DEFAULT_TIMER_TICK 0/*milliseconds ( 0 -- 999 ) */
+#define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */
+#else /* ! RUBY_VM */
+#define DEFAULT_EVENT_LOOP_MAX 800/*counts*/
+#define DEFAULT_NO_EVENT_TICK 10/*counts*/
+#define DEFAULT_NO_EVENT_WAIT 20/*milliseconds ( 1 -- 999 ) */
+#define WATCHDOG_INTERVAL 10/*milliseconds ( 1 -- 999 ) */
+#define DEFAULT_TIMER_TICK 0/*milliseconds ( 0 -- 999 ) */
+#define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */
+#endif
+
+static int event_loop_max = DEFAULT_EVENT_LOOP_MAX;
+static int no_event_tick = DEFAULT_NO_EVENT_TICK;
+static int no_event_wait = DEFAULT_NO_EVENT_WAIT;
+static int timer_tick = DEFAULT_TIMER_TICK;
+static int req_timer_tick = DEFAULT_TIMER_TICK;
+static int run_timer_flag = 0;
+
+static int event_loop_wait_event = 0;
+static int event_loop_abort_on_exc = 1;
+static int loop_counter = 0;
+
+static int check_rootwidget_flag = 0;
+
+
+/* call ruby interpreter */